⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bus.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/** *	bus_attach_device - add device to bus *	@dev:	device tried to attach to a driver * *	- Add device to bus's list of devices. *	- Try to attach to driver. */void bus_attach_device(struct device * dev){	struct bus_type *bus = dev->bus;	int ret = 0;	if (bus) {		dev->is_registered = 1;		if (bus->drivers_autoprobe)			ret = device_attach(dev);		WARN_ON(ret < 0);		if (ret >= 0)			klist_add_tail(&dev->knode_bus, &bus->klist_devices);		else			dev->is_registered = 0;	}}/** *	bus_remove_device - remove device from bus *	@dev:	device to be removed * *	- Remove symlink from bus's directory. *	- Delete device from bus's list. *	- Detach from its driver. *	- Drop reference taken in bus_add_device(). */void bus_remove_device(struct device * dev){	if (dev->bus) {		sysfs_remove_link(&dev->kobj, "subsystem");		remove_deprecated_bus_links(dev);		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);		device_remove_attrs(dev->bus, dev);		if (dev->is_registered) {			dev->is_registered = 0;			klist_del(&dev->knode_bus);		}		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);		device_release_driver(dev);		bus_put(dev->bus);	}}static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv){	int error = 0;	int i;	if (bus->drv_attrs) {		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {			error = driver_create_file(drv, &bus->drv_attrs[i]);			if (error)				goto Err;		}	} Done:	return error; Err:	while (--i >= 0)		driver_remove_file(drv, &bus->drv_attrs[i]);	goto Done;}static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv){	int i;	if (bus->drv_attrs) {		for (i = 0; attr_name(bus->drv_attrs[i]); i++)			driver_remove_file(drv, &bus->drv_attrs[i]);	}}#ifdef CONFIG_HOTPLUG/* * Thanks to drivers making their tables __devinit, we can't allow manual * bind and unbind from userspace unless CONFIG_HOTPLUG is enabled. */static int __must_check add_bind_files(struct device_driver *drv){	int ret;	ret = driver_create_file(drv, &driver_attr_unbind);	if (ret == 0) {		ret = driver_create_file(drv, &driver_attr_bind);		if (ret)			driver_remove_file(drv, &driver_attr_unbind);	}	return ret;}static void remove_bind_files(struct device_driver *drv){	driver_remove_file(drv, &driver_attr_bind);	driver_remove_file(drv, &driver_attr_unbind);}static BUS_ATTR(drivers_probe, S_IWUSR, NULL, store_drivers_probe);static BUS_ATTR(drivers_autoprobe, S_IWUSR | S_IRUGO,		show_drivers_autoprobe, store_drivers_autoprobe);static int add_probe_files(struct bus_type *bus){	int retval;	retval = bus_create_file(bus, &bus_attr_drivers_probe);	if (retval)		goto out;	retval = bus_create_file(bus, &bus_attr_drivers_autoprobe);	if (retval)		bus_remove_file(bus, &bus_attr_drivers_probe);out:	return retval;}static void remove_probe_files(struct bus_type *bus){	bus_remove_file(bus, &bus_attr_drivers_autoprobe);	bus_remove_file(bus, &bus_attr_drivers_probe);}#elsestatic inline int add_bind_files(struct device_driver *drv) { return 0; }static inline void remove_bind_files(struct device_driver *drv) {}static inline int add_probe_files(struct bus_type *bus) { return 0; }static inline void remove_probe_files(struct bus_type *bus) {}#endifstatic ssize_t driver_uevent_store(struct device_driver *drv,				   const char *buf, size_t count){	enum kobject_action action;	if (kobject_action_type(buf, count, &action) == 0)		kobject_uevent(&drv->kobj, action);	return count;}static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);/** *	bus_add_driver - Add a driver to the bus. *	@drv:	driver. * */int bus_add_driver(struct device_driver *drv){	struct bus_type * bus = bus_get(drv->bus);	int error = 0;	if (!bus)		return -EINVAL;	pr_debug("bus %s: add driver %s\n", bus->name, drv->name);	error = kobject_set_name(&drv->kobj, "%s", drv->name);	if (error)		goto out_put_bus;	drv->kobj.kset = &bus->drivers;	error = kobject_register(&drv->kobj);	if (error)		goto out_put_bus;	if (drv->bus->drivers_autoprobe) {		error = driver_attach(drv);		if (error)			goto out_unregister;	}	klist_add_tail(&drv->knode_bus, &bus->klist_drivers);	module_add_driver(drv->owner, drv);	error = driver_create_file(drv, &driver_attr_uevent);	if (error) {		printk(KERN_ERR "%s: uevent attr (%s) failed\n",			__FUNCTION__, drv->name);	}	error = driver_add_attrs(bus, drv);	if (error) {		/* How the hell do we get out of this pickle? Give up */		printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",			__FUNCTION__, drv->name);	}	error = add_bind_files(drv);	if (error) {		/* Ditto */		printk(KERN_ERR "%s: add_bind_files(%s) failed\n",			__FUNCTION__, drv->name);	}	return error;out_unregister:	kobject_unregister(&drv->kobj);out_put_bus:	bus_put(bus);	return error;}/** *	bus_remove_driver - delete driver from bus's knowledge. *	@drv:	driver. * *	Detach the driver from the devices it controls, and remove *	it from its bus's list of drivers. Finally, we drop the reference *	to the bus we took in bus_add_driver(). */void bus_remove_driver(struct device_driver * drv){	if (!drv->bus)		return;	remove_bind_files(drv);	driver_remove_attrs(drv->bus, drv);	driver_remove_file(drv, &driver_attr_uevent);	klist_remove(&drv->knode_bus);	pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);	driver_detach(drv);	module_remove_driver(drv);	kobject_unregister(&drv->kobj);	bus_put(drv->bus);}/* Helper for bus_rescan_devices's iter */static int __must_check bus_rescan_devices_helper(struct device *dev,						void *data){	int ret = 0;	if (!dev->driver) {		if (dev->parent)	/* Needed for USB */			down(&dev->parent->sem);		ret = device_attach(dev);		if (dev->parent)			up(&dev->parent->sem);	}	return ret < 0 ? ret : 0;}/** * bus_rescan_devices - rescan devices on the bus for possible drivers * @bus: the bus to scan. * * This function will look for devices on the bus with no driver * attached and rescan it against existing drivers to see if it matches * any by calling device_attach() for the unbound devices. */int bus_rescan_devices(struct bus_type * bus){	return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);}/** * device_reprobe - remove driver for a device and probe for a new driver * @dev: the device to reprobe * * This function detaches the attached driver (if any) for the given * device and restarts the driver probing process.  It is intended * to use if probing criteria changed during a devices lifetime and * driver attachment should change accordingly. */int device_reprobe(struct device *dev){	if (dev->driver) {		if (dev->parent)        /* Needed for USB */			down(&dev->parent->sem);		device_release_driver(dev);		if (dev->parent)			up(&dev->parent->sem);	}	return bus_rescan_devices_helper(dev, NULL);}EXPORT_SYMBOL_GPL(device_reprobe);/** *	find_bus - locate bus by name. *	@name:	name of bus. * *	Call kset_find_obj() to iterate over list of buses to *	find a bus by name. Return bus if found. * *	Note that kset_find_obj increments bus' reference count. */#if 0struct bus_type * find_bus(char * name){	struct kobject * k = kset_find_obj(&bus_subsys.kset, name);	return k ? to_bus(k) : NULL;}#endif  /*  0  *//** *	bus_add_attrs - Add default attributes for this bus. *	@bus:	Bus that has just been registered. */static int bus_add_attrs(struct bus_type * bus){	int error = 0;	int i;	if (bus->bus_attrs) {		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {			error = bus_create_file(bus,&bus->bus_attrs[i]);			if (error)				goto Err;		}	} Done:	return error; Err:	while (--i >= 0)		bus_remove_file(bus,&bus->bus_attrs[i]);	goto Done;}static void bus_remove_attrs(struct bus_type * bus){	int i;	if (bus->bus_attrs) {		for (i = 0; attr_name(bus->bus_attrs[i]); i++)			bus_remove_file(bus,&bus->bus_attrs[i]);	}}static void klist_devices_get(struct klist_node *n){	struct device *dev = container_of(n, struct device, knode_bus);	get_device(dev);}static void klist_devices_put(struct klist_node *n){	struct device *dev = container_of(n, struct device, knode_bus);	put_device(dev);}static ssize_t bus_uevent_store(struct bus_type *bus,				const char *buf, size_t count){	enum kobject_action action;	if (kobject_action_type(buf, count, &action) == 0)		kobject_uevent(&bus->subsys.kobj, action);	return count;}static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);/** *	bus_register - register a bus with the system. *	@bus:	bus. * *	Once we have that, we registered the bus with the kobject *	infrastructure, then register the children subsystems it has: *	the devices and drivers that belong to the bus. */int bus_register(struct bus_type * bus){	int retval;	BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);	retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);	if (retval)		goto out;	bus->subsys.kobj.kset = &bus_subsys;	retval = subsystem_register(&bus->subsys);	if (retval)		goto out;	retval = bus_create_file(bus, &bus_attr_uevent);	if (retval)		goto bus_uevent_fail;	kobject_set_name(&bus->devices.kobj, "devices");	bus->devices.kobj.parent = &bus->subsys.kobj;	retval = kset_register(&bus->devices);	if (retval)		goto bus_devices_fail;	kobject_set_name(&bus->drivers.kobj, "drivers");	bus->drivers.kobj.parent = &bus->subsys.kobj;	bus->drivers.ktype = &driver_ktype;	retval = kset_register(&bus->drivers);	if (retval)		goto bus_drivers_fail;	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);	klist_init(&bus->klist_drivers, NULL, NULL);	bus->drivers_autoprobe = 1;	retval = add_probe_files(bus);	if (retval)		goto bus_probe_files_fail;	retval = bus_add_attrs(bus);	if (retval)		goto bus_attrs_fail;	pr_debug("bus type '%s' registered\n", bus->name);	return 0;bus_attrs_fail:	remove_probe_files(bus);bus_probe_files_fail:	kset_unregister(&bus->drivers);bus_drivers_fail:	kset_unregister(&bus->devices);bus_devices_fail:	bus_remove_file(bus, &bus_attr_uevent);bus_uevent_fail:	subsystem_unregister(&bus->subsys);out:	return retval;}/** *	bus_unregister - remove a bus from the system *	@bus:	bus. * *	Unregister the child subsystems and the bus itself. *	Finally, we call bus_put() to release the refcount */void bus_unregister(struct bus_type * bus){	pr_debug("bus %s: unregistering\n", bus->name);	bus_remove_attrs(bus);	remove_probe_files(bus);	kset_unregister(&bus->drivers);	kset_unregister(&bus->devices);	bus_remove_file(bus, &bus_attr_uevent);	subsystem_unregister(&bus->subsys);}int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb){	return blocking_notifier_chain_register(&bus->bus_notifier, nb);}EXPORT_SYMBOL_GPL(bus_register_notifier);int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb){	return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);}EXPORT_SYMBOL_GPL(bus_unregister_notifier);int __init buses_init(void){	return subsystem_register(&bus_subsys);}EXPORT_SYMBOL_GPL(bus_for_each_dev);EXPORT_SYMBOL_GPL(bus_find_device);EXPORT_SYMBOL_GPL(bus_for_each_drv);EXPORT_SYMBOL_GPL(bus_register);EXPORT_SYMBOL_GPL(bus_unregister);EXPORT_SYMBOL_GPL(bus_rescan_devices);EXPORT_SYMBOL_GPL(bus_create_file);EXPORT_SYMBOL_GPL(bus_remove_file);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -