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

📄 bus.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * bus.c - bus driver management * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs * * This file is released under the GPLv2 * */#include <linux/config.h>#include <linux/device.h>#include <linux/module.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/string.h>#include "base.h"#include "power/power.h"#define to_dev(node) container_of(node, struct device, bus_list)#define to_drv(node) container_of(node, struct device_driver, kobj.entry)#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)/* * sysfs bindings for drivers */#define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)#define to_driver(obj) container_of(obj, struct device_driver, kobj)static ssize_tdrv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf){	struct driver_attribute * drv_attr = to_drv_attr(attr);	struct device_driver * drv = to_driver(kobj);	ssize_t ret = 0;	if (drv_attr->show)		ret = drv_attr->show(drv, buf);	return ret;}static ssize_tdrv_attr_store(struct kobject * kobj, struct attribute * attr,	       const char * buf, size_t count){	struct driver_attribute * drv_attr = to_drv_attr(attr);	struct device_driver * drv = to_driver(kobj);	ssize_t ret = 0;	if (drv_attr->store)		ret = drv_attr->store(drv, buf, count);	return ret;}static struct sysfs_ops driver_sysfs_ops = {	.show	= drv_attr_show,	.store	= drv_attr_store,};static void driver_release(struct kobject * kobj){	struct device_driver * drv = to_driver(kobj);	up(&drv->unload_sem);}static struct kobj_type ktype_driver = {	.sysfs_ops	= &driver_sysfs_ops,	.release	= driver_release,};/* * sysfs bindings for buses */static ssize_tbus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf){	struct bus_attribute * bus_attr = to_bus_attr(attr);	struct bus_type * bus = to_bus(kobj);	ssize_t ret = 0;	if (bus_attr->show)		ret = bus_attr->show(bus, buf);	return ret;}static ssize_tbus_attr_store(struct kobject * kobj, struct attribute * attr,	       const char * buf, size_t count){	struct bus_attribute * bus_attr = to_bus_attr(attr);	struct bus_type * bus = to_bus(kobj);	ssize_t ret = 0;	if (bus_attr->store)		ret = bus_attr->store(bus, buf, count);	return ret;}static struct sysfs_ops bus_sysfs_ops = {	.show	= bus_attr_show,	.store	= bus_attr_store,};int bus_create_file(struct bus_type * bus, struct bus_attribute * attr){	int error;	if (get_bus(bus)) {		error = sysfs_create_file(&bus->subsys.kset.kobj, &attr->attr);		put_bus(bus);	} else		error = -EINVAL;	return error;}void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr){	if (get_bus(bus)) {		sysfs_remove_file(&bus->subsys.kset.kobj, &attr->attr);		put_bus(bus);	}}static struct kobj_type ktype_bus = {	.sysfs_ops	= &bus_sysfs_ops,};decl_subsys(bus, &ktype_bus, NULL);/** *	bus_for_each_dev - device iterator. *	@bus:	bus type. *	@start:	device to start iterating from. *	@data:	data for the callback. *	@fn:	function to be called for each device. * *	Iterate over @bus's list of devices, and call @fn for each, *	passing it @data. If @start is not NULL, we use that device to *	begin iterating from. * *	We check the return of @fn each time. If it returns anything *	other than 0, we break out and return that value. * *	NOTE: The device that returns a non-zero value is not retained *	in any way, nor is its refcount incremented. If the caller needs *	to retain this data, it should do, and increment the reference *	count in the supplied callback. */int bus_for_each_dev(struct bus_type * bus, struct device * start,		     void * data, int (*fn)(struct device *, void *)){	struct device *dev;	struct list_head * head;	int error = 0;	if (!(bus = get_bus(bus)))		return -EINVAL;	head = &bus->devices.list;	dev = list_prepare_entry(start, head, bus_list);	down_read(&bus->subsys.rwsem);	list_for_each_entry_continue(dev, head, bus_list) {		get_device(dev);		error = fn(dev, data);		put_device(dev);		if (error)			break;	}	up_read(&bus->subsys.rwsem);	put_bus(bus);	return error;}/** *	bus_for_each_drv - driver iterator *	@bus:	bus we're dealing with. *	@start:	driver to start iterating on. *	@data:	data to pass to the callback. *	@fn:	function to call for each driver. * *	This is nearly identical to the device iterator above. *	We iterate over each driver that belongs to @bus, and call *	@fn for each. If @fn returns anything but 0, we break out *	and return it. If @start is not NULL, we use it as the head *	of the list. * *	NOTE: we don't return the driver that returns a non-zero *	value, nor do we leave the reference count incremented for that *	driver. If the caller needs to know that info, it must set it *	in the callback. It must also be sure to increment the refcount *	so it doesn't disappear before returning to the caller. */int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,		     void * data, int (*fn)(struct device_driver *, void *)){	struct list_head * head;	struct device_driver *drv;	int error = 0;	if(!(bus = get_bus(bus)))		return -EINVAL;	head = &bus->drivers.list;	drv = list_prepare_entry(start, head, kobj.entry);	down_read(&bus->subsys.rwsem);	list_for_each_entry_continue(drv, head, kobj.entry) {		get_driver(drv);		error = fn(drv, data);		put_driver(drv);		if(error)			break;	}	up_read(&bus->subsys.rwsem);	put_bus(bus);	return error;}/** *	device_bind_driver - bind a driver to one device. *	@dev:	device. * *	Allow manual attachment of a driver to a deivce. *	Caller must have already set @dev->driver. * *	Note that this does not modify the bus reference count *	nor take the bus's rwsem. Please verify those are accounted *	for before calling this. (It is ok to call with no other effort *	from a driver's probe() method.) */void device_bind_driver(struct device * dev){	pr_debug("bound device '%s' to driver '%s'\n",		 dev->bus_id, dev->driver->name);	list_add_tail(&dev->driver_list, &dev->driver->devices);	sysfs_create_link(&dev->driver->kobj, &dev->kobj,			  kobject_name(&dev->kobj));}/** *	bus_match - check compatibility between device & driver. *	@dev:	device. *	@drv:	driver. * *	First, we call the bus's match function, which should compare *	the device IDs the driver supports with the device IDs of the *	device. Note we don't do this ourselves because we don't know *	the format of the ID structures, nor what is to be considered *	a match and what is not. * *	If we find a match, we call @drv->probe(@dev) if it exists, and *	call attach() above. */static int bus_match(struct device * dev, struct device_driver * drv){	int error = -ENODEV;	if (dev->bus->match(dev, drv)) {		dev->driver = drv;		if (drv->probe) {			if ((error = drv->probe(dev))) {				dev->driver = NULL;				return error;			}		}		device_bind_driver(dev);		error = 0;	}	return error;}/** *	device_attach - try to attach device to a driver. *	@dev:	device. * *	Walk the list of drivers that the bus has and call bus_match() *	for each pair. If a compatible pair is found, break out and return. */static int device_attach(struct device * dev){ 	struct bus_type * bus = dev->bus;	struct list_head * entry;	int error;	if (dev->driver) {		device_bind_driver(dev);		return 1;	}	if (bus->match) {		list_for_each(entry, &bus->drivers.list) {			struct device_driver * drv = to_drv(entry);			error = bus_match(dev, drv);			if (!error)				/* success, driver matched */				return 1;			if (error != -ENODEV)				/* driver matched but the probe failed */				printk(KERN_WARNING				    "%s: probe of %s failed with error %d\n",				    drv->name, dev->bus_id, error);		}	}	return 0;}/** *	driver_attach - try to bind driver to devices. *	@drv:	driver. * *	Walk the list of devices that the bus has on it and try to match *	the driver with each one. *	If bus_match() returns 0 and the @dev->driver is set, we've found *	a compatible pair. * *	Note that we ignore the -ENODEV error from bus_match(), since it's *	perfectly valid for a driver not to bind to any devices. */void driver_attach(struct device_driver * drv){	struct bus_type * bus = drv->bus;	struct list_head * entry;	int error;	if (!bus->match)		return;	list_for_each(entry, &bus->devices.list) {		struct device * dev = container_of(entry, struct device, bus_list);		if (!dev->driver) {			error = bus_match(dev, drv);			if (error && (error != -ENODEV))				/* driver matched but the probe failed */				printk(KERN_WARNING				    "%s: probe of %s failed with error %d\n",				    drv->name, dev->bus_id, error);		}	}}/** *	device_release_driver - manually detach device from driver. *	@dev:	device. * *	Manually detach device from driver. *	Note that this is called without incrementing the bus *	reference count nor taking the bus's rwsem. Be sure that *	those are accounted for before calling this function. */void device_release_driver(struct device * dev){	struct device_driver * drv = dev->driver;	if (drv) {		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));		list_del_init(&dev->driver_list);

⌨️ 快捷键说明

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