* [BK PATCH] PCI changes for 2.5.69 @ 2003-05-22 22:02 Greg KH 2003-05-22 22:05 ` [PATCH] " Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2003-05-22 22:02 UTC (permalink / raw) To: torvalds; +Cc: linux-kernel Hi, Here's some PCI changesets against the latest 2.5.69 tree. They include Matt Domsch's dynamic PCI id patch for sysfs, which has been gone over a few times on lkml in the recent past, and everyone now agrees with it. It also includes the start of the work to add proper locking to the PCI devices and the PCI device and bus lists. After years of trying to foist that task off on unsuspecting people (who later run screaming from it), it looks like I'm finally going to have to do the work myself :) Please pull from: bk://kernel.bkbits.net/gregkh/linux/pci-2.5 thanks, greg k-h p.s. I'll send these as patches in response to this email to lkml for those who want to see them. drivers/pci/pci-sysfs-dynids.c | 251 ------------- Documentation/pci.txt | 24 + drivers/base/bus.c | 2 drivers/pci/Makefile | 6 drivers/pci/bus.c | 2 drivers/pci/hotplug.c | 23 - drivers/pci/pci-driver.c | 785 +++++++++++++++++++++++++++++++++-------- drivers/pci/pci-sysfs-dynids.c | 251 +++++++++++++ drivers/pci/pci.h | 2 drivers/pci/probe.c | 18 include/linux/device.h | 35 + include/linux/pci-dynids.h | 68 ++- include/linux/pci.h | 47 +- 13 files changed, 1045 insertions(+), 469 deletions(-) ----- Greg Kroah-Hartman <greg@kroah.com>: o PCI: remove pci_insert_device() as no one uses it anymore o PCI: add pci_get_dev() and pci_put_dev() Matt Domsch <matt_domsch@dell.com>: o dynids: call driver_attach() when new IDs are added o pci.h whitespace cleanups o PCI dynids - documentation fixes, id_table NULL check o Shrink dynids feature set o Device Driver Dynamic PCI Device IDs ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH] PCI changes for 2.5.69 2003-05-22 22:02 [BK PATCH] PCI changes for 2.5.69 Greg KH @ 2003-05-22 22:05 ` Greg KH 2003-05-22 22:05 ` Greg KH 2003-05-22 22:36 ` Dave Jones 0 siblings, 2 replies; 12+ messages in thread From: Greg KH @ 2003-05-22 22:05 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1042.9.1, 2003/04/16 16:03:20-05:00, Matt_Domsch@dell.com Device Driver Dynamic PCI Device IDs Provides a mechanism to pass new PCI device IDs to device drivers at runtime, rather than relying only on a static compiled-in list of supported IDs. For each driver which has a pci_driver->probe routine, two things are added: a probe_it file, and a dynamic_id directory. In the dynamic_id directory is a new file, new_id. /sys/bus/pci/drivers/e100 |-- dynamic_id | `-- new_id `-- probe_it One may read the new_id file, which by default returns: $ cat new_id echo vendor device subvendor subdevice class classmask where each field is a 32-bit value in ABCD (hex) format (no leading 0x). Pass only as many fields as you need to override the defaults below. Default vendor, device, subvendor, and subdevice fields are set to FFFFFFFF (PCI_ANY_ID). Default class and classmask fields are set to 0. One may write new PCI device IDs into the new_id file: echo "8086 1229" > new_id which will cause a new device ID (sysfs name 0) to be added to the driver. /sys/bus/pci/drivers/e100 |-- dynamic_id | |-- 0 | `-- new_id `-- probe_it $ cat 0 00008086 00001229 ffffffff ffffffff 00000000 00000000 One can then cause the driver to probe for devices again. echo 1 > probe_it Individual device drivers may override the behavior of the new_id file, for instance, if they need to also pass driver-specific information. Likewise, reading the individual dynamic ID files can be overridden by the driver. This also adds an existance test field to struct driver_attribute, necessary because we only want the probe_it file to appear iff struct pci_driver->probe is non-NULL. The device probing routines in pci-driver.c are enhanced to scan first the static list of IDs, then the dynamic list (if any). drivers/pci/Makefile | 2 drivers/pci/pci-driver.c | 267 +++++++++++++++++++++++++++++++++++++---- drivers/pci/pci-sysfs-dynids.c | 251 ++++++++++++++++++++++++++++++++++++++ drivers/pci/pci.h | 1 include/linux/device.h | 11 + include/linux/pci-dynids.h | 40 ++++++ include/linux/pci.h | 2 7 files changed, 547 insertions(+), 27 deletions(-) diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Thu May 22 14:54:18 2003 +++ b/drivers/pci/Makefile Thu May 22 14:54:18 2003 @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ names.o pci-driver.o search.o hotplug.o \ - pci-sysfs.o + pci-sysfs.o pci-sysfs-dynids.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Thu May 22 14:54:18 2003 +++ b/drivers/pci/pci-driver.c Thu May 22 14:54:18 2003 @@ -13,6 +13,26 @@ */ /** + * pci_match_one_device - Tell if a PCI device structure has a matching PCI device id structure + * @id: single PCI device id structure to match + * @dev: the PCI device structure to match against + * + * Returns the matching pci_device_id structure or %NULL if there is no match. + */ + +static inline const struct pci_device_id * +pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) +{ + if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) && + (id->device == PCI_ANY_ID || id->device == dev->device) && + (id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) && + (id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) && + !((id->class ^ dev->class) & id->class_mask)) + return id; + return NULL; +} + +/** * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure * @ids: array of PCI device id structures to search in * @dev: the PCI device structure to match against @@ -25,17 +45,88 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { while (ids->vendor || ids->subvendor || ids->class_mask) { - if ((ids->vendor == PCI_ANY_ID || ids->vendor == dev->vendor) && - (ids->device == PCI_ANY_ID || ids->device == dev->device) && - (ids->subvendor == PCI_ANY_ID || ids->subvendor == dev->subsystem_vendor) && - (ids->subdevice == PCI_ANY_ID || ids->subdevice == dev->subsystem_device) && - !((ids->class ^ dev->class) & ids->class_mask)) - return ids; + if (pci_match_one_device(ids, dev)) + return ids; ids++; } return NULL; } +/** + * pci_device_probe_static() + * + * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. + */ +static int +pci_device_probe_static(struct pci_driver *drv, + struct pci_dev *pci_dev) +{ + int error = -ENODEV; + const struct pci_device_id *id; + + id = pci_match_device(drv->id_table, pci_dev); + if (id) + error = drv->probe(pci_dev, id); + if (error >= 0) { + pci_dev->driver = drv; + return 0; + } + return error; +} + +/** + * pci_device_probe_dynamic() + * + * Walk the dynamic ID list looking for a match. + * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. + */ +static int +pci_device_probe_dynamic(struct pci_driver *drv, + struct pci_dev *pci_dev) +{ + int error = -ENODEV; + struct list_head *pos; + struct dynid_attribute *dattr; + + spin_lock(&drv->dynids.lock); + list_for_each(pos, &drv->dynids.list) { + dattr = list_entry(pos, struct dynid_attribute, node); + if (pci_match_one_device(dattr->id, pci_dev)) { + spin_unlock(&drv->dynids.lock); + error = drv->probe(pci_dev, dattr->id); + if (error >= 0) { + pci_dev->driver = drv; + return 0; + } + return error; + } + } + spin_unlock(&drv->dynids.lock); + return error; +} + +/** + * __pci_device_probe() + * + * returns 0 on success, else error. + * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. + */ +static int +__pci_device_probe(struct pci_driver *drv, + struct pci_dev *pci_dev) +{ + int error = 0; + + if (!pci_dev->driver && drv->probe) { + error = pci_device_probe_static(drv, pci_dev); + if (error >= 0) + return error; + + error = pci_device_probe_dynamic(drv, pci_dev); + } + return error; +} + static int pci_device_probe(struct device * dev) { int error = 0; @@ -44,17 +135,9 @@ drv = to_pci_driver(dev->driver); pci_dev = to_pci_dev(dev); - - if (!pci_dev->driver && drv->probe) { - const struct pci_device_id *id; - - id = pci_match_device(drv->id_table, pci_dev); - if (id) - error = drv->probe(pci_dev, id); - if (error >= 0) { - pci_dev->driver = drv; - error = 0; - } + if (get_device(dev)) { + error = __pci_device_probe(drv, pci_dev); + put_device(dev); } return error; } @@ -101,6 +184,122 @@ return 0; } +/* + * Attribute to force driver probe for devices + * If __pci_device_probe() returns 0, it matched at least one previously + * unclaimed device. If it returns -ENODEV, it didn't match. Both are + * alright in this case, just keep searching for new devices. + */ + +static int +probe_each_pci_dev(struct pci_driver *drv) +{ + struct pci_dev *pci_dev=NULL; + int error = 0; + pci_for_each_dev(pci_dev) { + if (get_device(&pci_dev->dev)) { + error = __pci_device_probe(drv, pci_dev); + put_device(&pci_dev->dev); + if (error && error != -ENODEV) + return error; + } + } + return error; +} + +static ssize_t +store_probe_it(struct device_driver *driver, const char *buf, size_t count) +{ + int error = 0; + struct pci_driver *drv = to_pci_driver(driver); + int writeone = 0; + if (!((sscanf(buf, "%d", &writeone) == 1) && writeone == 1)) + return -EINVAL; + + if (get_driver(driver)) { + error = probe_each_pci_dev(drv); + put_driver(driver); + } + if (error < 0) + return error; + return count; +} + +static int +probe_it_exists(struct device_driver *driver) +{ + struct pci_driver *pdrv = to_pci_driver(driver); + return pdrv->probe != NULL; +} + +static DRIVER_ATTR_EXISTS(probe_it, S_IWUSR, NULL, store_probe_it, probe_it_exists); + +#define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj) +#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr) + +static ssize_t +pci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf) +{ + struct device_driver *driver = kobj_to_pci_driver(kobj); + struct driver_attribute *dattr = attr_to_driver_attribute(attr); + ssize_t ret = 0; + + if (get_driver(driver)) { + if (dattr->show) + ret = dattr->show(driver, buf); + put_driver(driver); + } + return ret; +} + +static ssize_t +pci_driver_attr_store(struct kobject * kobj, struct attribute *attr, + const char *buf, size_t count) +{ + struct device_driver *driver = kobj_to_pci_driver(kobj); + struct driver_attribute *dattr = attr_to_driver_attribute(attr); + ssize_t ret = 0; + + if (get_driver(driver)) { + if (dattr->store) + ret = dattr->store(driver, buf, count); + put_driver(driver); + } + return ret; +} + +static struct sysfs_ops pci_driver_sysfs_ops = { + .show = pci_driver_attr_show, + .store = pci_driver_attr_store, +}; +static struct kobj_type pci_driver_kobj_type = { + .sysfs_ops = &pci_driver_sysfs_ops, +}; +static struct driver_attribute * driver_attrs[] = { + &driver_attr_probe_it, + NULL, +}; + +static void pci_populate_driver_dir(struct pci_driver * drv) +{ + struct driver_attribute * attr; + int error = 0, i; + + for (i = 0; (attr = driver_attrs[i]) && !error; i++) { + if (!attr->exists || + (attr->exists && attr->exists(&drv->driver))) + error = sysfs_create_file(&drv->driver.kobj,&attr->attr); + } +} + +static inline void +pci_init_dynids(struct pci_dynamic_id_kobj *dynids) +{ + memset(dynids, 0, sizeof(*dynids)); + spin_lock_init(&dynids->lock); + INIT_LIST_HEAD(&dynids->list); +} + /** * pci_register_driver - register a new pci driver * @drv: the driver structure to register @@ -122,9 +321,17 @@ drv->driver.resume = pci_device_resume; drv->driver.suspend = pci_device_suspend; drv->driver.remove = pci_device_remove; + drv->driver.kobj.ktype = &pci_driver_kobj_type; + pci_init_dynids(&drv->dynids); /* register with core */ count = driver_register(&drv->driver); + + if (count >= 0) { + pci_populate_driver_dir(drv); + pci_register_dynids(drv); + } + return count ? count : 1; } @@ -180,22 +387,30 @@ */ static int pci_bus_match(struct device * dev, struct device_driver * drv) { - struct pci_dev * pci_dev = to_pci_dev(dev); + const struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_driver * pci_drv = to_pci_driver(drv); const struct pci_device_id * ids = pci_drv->id_table; + const struct pci_device_id *found_id; + struct list_head *pos; + struct dynid_attribute *dattr; - if (!ids) + if (!ids) return 0; - while (ids->vendor || ids->subvendor || ids->class_mask) { - if ((ids->vendor == PCI_ANY_ID || ids->vendor == pci_dev->vendor) && - (ids->device == PCI_ANY_ID || ids->device == pci_dev->device) && - (ids->subvendor == PCI_ANY_ID || ids->subvendor == pci_dev->subsystem_vendor) && - (ids->subdevice == PCI_ANY_ID || ids->subdevice == pci_dev->subsystem_device) && - !((ids->class ^ pci_dev->class) & ids->class_mask)) + found_id = pci_match_device(ids, pci_dev); + if (found_id) + return 1; + + spin_lock(&pci_drv->dynids.lock); + list_for_each(pos, &pci_drv->dynids.list) { + dattr = list_entry(pos, struct dynid_attribute, node); + if (pci_match_one_device(dattr->id, pci_dev)) { + spin_unlock(&pci_drv->dynids.lock); return 1; - ids++; + } } + spin_unlock(&pci_drv->dynids.lock); + return 0; } diff -Nru a/drivers/pci/pci-sysfs-dynids.c b/drivers/pci/pci-sysfs-dynids.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/pci-sysfs-dynids.c Thu May 22 14:54:18 2003 @@ -0,0 +1,251 @@ +/* + * linux/drivers/pci/pci-sysfs-dynids.c + * Copyright (C) 2003 Dell Computer Corporation + * by Matt Domsch <Matt_Domsch@dell.com> + * + * sysfs interface for exporting dynamic device IDs + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/pci.h> +#include <linux/stat.h> +#include <linux/sysfs.h> +#include <linux/pci-dynids.h> +#include "pci.h" + +/** + * dynid_create_file - create sysfs file for a dynamic ID + * @pdrv: pci_driver + * @dattr: the attribute to create + */ +static int dynid_create_file(struct pci_driver * pdrv, struct dynid_attribute * dattr) +{ + int error; + + if (get_driver(&pdrv->driver)) { + error = sysfs_create_file(&pdrv->dynids.kobj,&dattr->attr); + put_driver(&pdrv->driver); + } else + error = -EINVAL; + return error; +} + +/** + * dynid_remove_file - remove sysfs file for a dynamic ID + * @drv: driver. + * @id: the id to to remove + */ +static void dynid_remove_file(struct pci_driver * pdrv, struct dynid_attribute * dattr) +{ + if (get_driver(&pdrv->driver)) { + sysfs_remove_file(&pdrv->dynids.kobj,&dattr->attr); + put_driver(&pdrv->driver); + } +} + +#define kobj_to_dynids(obj) container_of(obj,struct pci_dynamic_id_kobj,kobj) +#define dynids_to_pci_driver(obj) container_of(obj,struct pci_driver,dynids) +#define attr_to_dattr(_attr) container_of(_attr, struct dynid_attribute, attr) + +static inline ssize_t +default_show_id(const struct pci_device_id * id, char * buf) +{ + return snprintf(buf, PAGE_SIZE, "%08x %08x %08x %08x %08x %08x\n", + id->vendor, + id->device, + id->subvendor, + id->subdevice, + id->class, + id->class_mask); +} + +static ssize_t +dynid_show_id(struct pci_driver * pdrv, struct dynid_attribute *dattr, char *buf) +{ + return pdrv->dynids.show_id ? + pdrv->dynids.show_id(dattr->id, dattr, buf) : + default_show_id(dattr->id, buf); +} + +static ssize_t +default_show_new_id(char * buf) +{ + char *p = buf; + p += sprintf(p, + "echo vendor device subvendor subdevice class classmask\n"); + p += sprintf(p, + "where each field is a 32-bit value in ABCD (hex) format (no leading 0x).\n"); + p += sprintf(p, + "Pass only as many fields as you need to override the defaults below.\n"); + p += sprintf(p, + "Default vendor, device, subvendor, and subdevice fields\n"); + p += sprintf(p, "are set to FFFFFFFF (PCI_ANY_ID).\n"); + p += sprintf(p, + "Default class and classmask fields are set to 0.\n"); + return p - buf; +} + +static inline void +__dattr_init(struct dynid_attribute *dattr) +{ + memset(dattr, 0, sizeof(*dattr)); + INIT_LIST_HEAD(&dattr->node); + dattr->attr.mode = S_IRUGO; + dattr->attr.name = dattr->name; +} + +static inline ssize_t +default_store_new_id(struct pci_driver * pdrv, const char * buf, size_t count) +{ + struct dynid_attribute *dattr; + struct pci_device_id *id; + __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, + subdevice=PCI_ANY_ID, class=0, class_mask=0; + int fields=0, error=0; + + fields = sscanf(buf, "%x %x %x %x %x %x", + &vendor, &device, &subvendor, &subdevice, + &class, &class_mask); + if (fields < 0) return -EINVAL; + + dattr = kmalloc(sizeof(*dattr), GFP_KERNEL); + if (!dattr) return -ENOMEM; + __dattr_init(dattr); + + id = kmalloc(sizeof(*id), GFP_KERNEL); + if (!id) { + kfree(dattr); + return -ENOMEM; + } + dattr->id = id; + dattr->show = dynid_show_id; + + id->vendor = vendor; + id->device = device; + id->subvendor = subvendor; + id->subdevice = subdevice; + id->class = class; + id->class_mask = class_mask; + + spin_lock(&pdrv->dynids.lock); + snprintf(dattr->name, KOBJ_NAME_LEN, "%d", pdrv->dynids.nextname); + pdrv->dynids.nextname++; + spin_unlock(&pdrv->dynids.lock); + + error = dynid_create_file(pdrv,dattr); + if (error) { + kfree(id); + kfree(dattr); + return error; + } + + spin_lock(&pdrv->dynids.lock); + list_add(&pdrv->dynids.list, &dattr->node); + spin_unlock(&pdrv->dynids.lock); + return count; +} + +static ssize_t +dynid_show_new_id(struct pci_driver * pdrv, struct dynid_attribute *unused, char * buf) +{ + return pdrv->dynids.show_new_id ? + pdrv->dynids.show_new_id(pdrv, buf) : + default_show_new_id(buf); +} + +static ssize_t +dynid_store_new_id(struct pci_driver * pdrv, struct dynid_attribute *unused, const char * buf, size_t count) +{ + return pdrv->dynids.store_new_id ? + pdrv->dynids.store_new_id(pdrv, buf, count) : + default_store_new_id(pdrv, buf, count); +} + +#define DYNID_ATTR(_name,_mode,_show,_store) \ +struct dynid_attribute dynid_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .id = NULL, \ + .show = _show, \ + .store = _store, \ +} + +static DYNID_ATTR(new_id,S_IRUSR|S_IWUSR,dynid_show_new_id,dynid_store_new_id); + +static struct attribute * dynids_def_attrs[] = { + &dynid_attr_new_id.attr, + NULL, +}; + +static ssize_t +dynid_show(struct kobject * kobj, struct attribute *attr, char *buf) +{ + struct pci_dynamic_id_kobj *dynid_kobj = kobj_to_dynids(kobj); + struct pci_driver *pdrv = dynids_to_pci_driver(dynid_kobj); + struct dynid_attribute *dattr = attr_to_dattr(attr); + + if (dattr->show) + return dattr->show(pdrv, dattr, buf); + return -ENOSYS; +} + +static ssize_t +dynid_store(struct kobject * kobj, struct attribute *attr, const char *buf, size_t count) +{ + struct pci_dynamic_id_kobj *dynid_kobj = kobj_to_dynids(kobj); + struct pci_driver *pdrv = dynids_to_pci_driver(dynid_kobj); + struct dynid_attribute *dattr = attr_to_dattr(attr); + + if (dattr->store) + return dattr->store(pdrv, dattr, buf, count); + return -ENOSYS; +} + +static void +dynids_release(struct kobject *kobj) +{ + struct pci_dynamic_id_kobj *dynids = kobj_to_dynids(kobj); + struct pci_driver *pdrv = dynids_to_pci_driver(dynids); + struct list_head *pos, *n; + struct dynid_attribute *dattr; + + spin_lock(&dynids->lock); + list_for_each_safe(pos, n, &dynids->list) { + dattr = list_entry(pos, struct dynid_attribute, node); + dynid_remove_file(pdrv, dattr); + list_del(&dattr->node); + if (dattr->id) + kfree(dattr->id); + kfree(dattr); + } + spin_unlock(&dynids->lock); +} + +static struct sysfs_ops dynids_attr_ops = { + .show = dynid_show, + .store = dynid_store, +}; +static struct kobj_type dynids_kobj_type = { + .release = dynids_release, + .sysfs_ops = &dynids_attr_ops, + .default_attrs = dynids_def_attrs, +}; + +/** + * pci_register_dynids - initialize and register driver dynamic_ids kobject + * @driver - the device_driver structure + * @dynids - the dynamic ids structure + */ +int +pci_register_dynids(struct pci_driver *drv) +{ + struct device_driver *driver = &drv->driver; + struct pci_dynamic_id_kobj *dynids = &drv->dynids; + if (drv->probe) { + dynids->kobj.parent = &driver->kobj; + dynids->kobj.ktype = &dynids_kobj_type; + snprintf(dynids->kobj.name, KOBJ_NAME_LEN, "dynamic_id"); + return kobject_register(&dynids->kobj); + } + return -ENODEV; +} + diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h --- a/drivers/pci/pci.h Thu May 22 14:54:18 2003 +++ b/drivers/pci/pci.h Thu May 22 14:54:18 2003 @@ -3,3 +3,4 @@ extern int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); extern void pci_create_sysfs_dev_files(struct pci_dev *pdev); +extern int pci_register_dynids(struct pci_driver *drv); diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Thu May 22 14:54:18 2003 +++ b/include/linux/device.h Thu May 22 14:54:18 2003 @@ -144,6 +144,7 @@ struct attribute attr; ssize_t (*show)(struct device_driver *, char * buf); ssize_t (*store)(struct device_driver *, const char * buf, size_t count); + int (*exists)(struct device_driver *); }; #define DRIVER_ATTR(_name,_mode,_show,_store) \ @@ -151,7 +152,17 @@ .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ + .exists = NULL, \ }; + +#define DRIVER_ATTR_EXISTS(_name,_mode,_show,_store,_exists) \ +struct driver_attribute driver_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ + .exists = _exists, \ +}; + extern int driver_create_file(struct device_driver *, struct driver_attribute *); extern void driver_remove_file(struct device_driver *, struct driver_attribute *); diff -Nru a/include/linux/pci-dynids.h b/include/linux/pci-dynids.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/include/linux/pci-dynids.h Thu May 22 14:54:18 2003 @@ -0,0 +1,40 @@ +/* + * PCI defines and function prototypes + * Copyright 2003 Dell Computer Corporation + * by Matt Domsch <Matt_Domsch@dell.com> + */ + +#ifndef LINUX_PCI_DYNIDS_H +#define LINUX_PCI_DYNIDS_H + +#include <linux/mod_devicetable.h> +#include <linux/types.h> +#include <linux/config.h> +#include <linux/list.h> +#include <linux/device.h> +#include <linux/pci.h> + +struct pci_driver; +struct pci_device_id; + +struct dynid_attribute { + struct attribute attr; + struct list_head node; + struct pci_device_id *id; + ssize_t (*show)(struct pci_driver * pdrv, struct dynid_attribute *dattr, char * buf); + ssize_t (*store)(struct pci_driver * pdrv, struct dynid_attribute *dattr, const char * buf, size_t count); + char name[KOBJ_NAME_LEN]; +}; + +struct pci_dynamic_id_kobj { + ssize_t (*show_new_id)(struct pci_driver * pdrv, char * buf); + ssize_t (*store_new_id)(struct pci_driver * pdrv, const char * buf, size_t count); + ssize_t (*show_id)(struct pci_device_id * id, struct dynid_attribute *dattr, char * buf); + + spinlock_t lock; /* protects list, index */ + struct list_head list; /* for IDs added at runtime */ + struct kobject kobj; /* for displaying the list in sysfs */ + unsigned int nextname; /* name of next dynamic ID twhen created */ +}; + +#endif diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu May 22 14:54:18 2003 +++ b/include/linux/pci.h Thu May 22 14:54:18 2003 @@ -343,6 +343,7 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/device.h> +#include <linux/pci-dynids.h> /* File state for mmap()s on /proc/bus/pci/X/Y */ enum pci_mmap_state { @@ -502,6 +503,7 @@ int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */ struct device_driver driver; + struct pci_dynamic_id_kobj dynids; }; #define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:05 ` [PATCH] " Greg KH @ 2003-05-22 22:05 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-22 22:36 ` Dave Jones 1 sibling, 1 reply; 12+ messages in thread From: Greg KH @ 2003-05-22 22:05 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1042.117.2, 2003/05/05 13:00:19-05:00, Matt_Domsch@dell.com Shrink dynids feature set Per recommendation from GregKH: Remove directory 'dynamic_id' Remove exporting dynamic_id/0 files Remove probe_it driver attribute Move new_id into driver directory as a driver attribute. Make it probe when new IDs are added. Move attribute existance test into pci-driver.c completely. drivers/pci/pci-sysfs-dynids.c | 251 ----------------------------------------- drivers/pci/Makefile | 2 drivers/pci/pci-driver.c | 110 +++++++++++------ drivers/pci/pci.h | 1 include/linux/device.h | 11 - include/linux/pci-dynids.h | 28 ---- include/linux/pci.h | 20 ++- 7 files changed, 91 insertions(+), 332 deletions(-) diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Thu May 22 14:52:46 2003 +++ b/drivers/pci/Makefile Thu May 22 14:52:46 2003 @@ -4,7 +4,7 @@ obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ names.o pci-driver.o search.o hotplug.o \ - pci-sysfs.o pci-sysfs-dynids.o + pci-sysfs.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Thu May 22 14:52:46 2003 +++ b/drivers/pci/pci-driver.c Thu May 22 14:52:46 2003 @@ -6,6 +6,8 @@ #include <linux/pci.h> #include <linux/module.h> #include <linux/init.h> +#include <linux/device.h> +#include <linux/pci-dynids.h> #include "pci.h" /* @@ -86,14 +88,14 @@ { int error = -ENODEV; struct list_head *pos; - struct dynid_attribute *dattr; + struct dynid *dynid; spin_lock(&drv->dynids.lock); list_for_each(pos, &drv->dynids.list) { - dattr = list_entry(pos, struct dynid_attribute, node); - if (pci_match_one_device(dattr->id, pci_dev)) { + dynid = list_entry(pos, struct dynid, node); + if (pci_match_one_device(&dynid->id, pci_dev)) { spin_unlock(&drv->dynids.lock); - error = drv->probe(pci_dev, dattr->id); + error = drv->probe(pci_dev, &dynid->id); if (error >= 0) { pci_dev->driver = drv; return 0; @@ -185,7 +187,6 @@ } /* - * Attribute to force driver probe for devices * If __pci_device_probe() returns 0, it matched at least one previously * unclaimed device. If it returns -ENODEV, it didn't match. Both are * alright in this case, just keep searching for new devices. @@ -207,32 +208,66 @@ return error; } -static ssize_t -store_probe_it(struct device_driver *driver, const char *buf, size_t count) +static inline void +dynid_init(struct dynid *dynid) { - int error = 0; - struct pci_driver *drv = to_pci_driver(driver); - int writeone = 0; - if (!((sscanf(buf, "%d", &writeone) == 1) && writeone == 1)) - return -EINVAL; - - if (get_driver(driver)) { - error = probe_each_pci_dev(drv); - put_driver(driver); - } - if (error < 0) - return error; - return count; + memset(dynid, 0, sizeof(*dynid)); + INIT_LIST_HEAD(&dynid->node); } -static int -probe_it_exists(struct device_driver *driver) +/** + * store_new_id + * @ pdrv + * @ buf + * @ count + * + * Adds a new dynamic pci device ID to this driver, + * and causes the driver to probe for all devices again. + */ +static inline ssize_t +store_new_id(struct device_driver * driver, const char * buf, size_t count) { + struct dynid *dynid; struct pci_driver *pdrv = to_pci_driver(driver); - return pdrv->probe != NULL; + __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, + subdevice=PCI_ANY_ID, class=0, class_mask=0; + unsigned long driver_data=0; + int fields=0, error=0; + + fields = sscanf(buf, "%x %x %x %x %x %x %lux", + &vendor, &device, &subvendor, &subdevice, + &class, &class_mask, &driver_data); + if (fields < 0) return -EINVAL; + + dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); + if (!dynid) return -ENOMEM; + dynid_init(dynid); + + dynid->id.vendor = vendor; + dynid->id.device = device; + dynid->id.subvendor = subvendor; + dynid->id.subdevice = subdevice; + dynid->id.class = class; + dynid->id.class_mask = class_mask; + dynid->id.driver_data = pdrv->dynids.use_driver_data ? driver_data : 0UL; + + spin_lock(&pdrv->dynids.lock); + list_add(&pdrv->dynids.list, &dynid->node); + spin_unlock(&pdrv->dynids.lock); + + if (get_driver(&pdrv->driver)) { + error = probe_each_pci_dev(pdrv); + put_driver(&pdrv->driver); + } + if (error < 0) + return error; + return count; + + + return count; } -static DRIVER_ATTR_EXISTS(probe_it, S_IWUSR, NULL, store_probe_it, probe_it_exists); +static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); #define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj) #define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr) @@ -275,25 +310,19 @@ static struct kobj_type pci_driver_kobj_type = { .sysfs_ops = &pci_driver_sysfs_ops, }; -static struct driver_attribute * driver_attrs[] = { - &driver_attr_probe_it, - NULL, -}; -static void pci_populate_driver_dir(struct pci_driver * drv) +static int +pci_populate_driver_dir(struct pci_driver * drv) { - struct driver_attribute * attr; - int error = 0, i; + int error = 0; - for (i = 0; (attr = driver_attrs[i]) && !error; i++) { - if (!attr->exists || - (attr->exists && attr->exists(&drv->driver))) - error = sysfs_create_file(&drv->driver.kobj,&attr->attr); - } + if (drv->probe != NULL) + error = sysfs_create_file(&drv->driver.kobj,&driver_attr_new_id.attr); + return error; } static inline void -pci_init_dynids(struct pci_dynamic_id_kobj *dynids) +pci_init_dynids(struct pci_dynids *dynids) { memset(dynids, 0, sizeof(*dynids)); spin_lock_init(&dynids->lock); @@ -329,7 +358,6 @@ if (count >= 0) { pci_populate_driver_dir(drv); - pci_register_dynids(drv); } return count ? count : 1; @@ -392,7 +420,7 @@ const struct pci_device_id * ids = pci_drv->id_table; const struct pci_device_id *found_id; struct list_head *pos; - struct dynid_attribute *dattr; + struct dynid *dynid; if (!ids) return 0; @@ -403,8 +431,8 @@ spin_lock(&pci_drv->dynids.lock); list_for_each(pos, &pci_drv->dynids.list) { - dattr = list_entry(pos, struct dynid_attribute, node); - if (pci_match_one_device(dattr->id, pci_dev)) { + dynid = list_entry(pos, struct dynid, node); + if (pci_match_one_device(&dynid->id, pci_dev)) { spin_unlock(&pci_drv->dynids.lock); return 1; } diff -Nru a/drivers/pci/pci-sysfs-dynids.c b/drivers/pci/pci-sysfs-dynids.c --- a/drivers/pci/pci-sysfs-dynids.c Thu May 22 14:52:46 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,251 +0,0 @@ -/* - * linux/drivers/pci/pci-sysfs-dynids.c - * Copyright (C) 2003 Dell Computer Corporation - * by Matt Domsch <Matt_Domsch@dell.com> - * - * sysfs interface for exporting dynamic device IDs - */ -#include <linux/config.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/stat.h> -#include <linux/sysfs.h> -#include <linux/pci-dynids.h> -#include "pci.h" - -/** - * dynid_create_file - create sysfs file for a dynamic ID - * @pdrv: pci_driver - * @dattr: the attribute to create - */ -static int dynid_create_file(struct pci_driver * pdrv, struct dynid_attribute * dattr) -{ - int error; - - if (get_driver(&pdrv->driver)) { - error = sysfs_create_file(&pdrv->dynids.kobj,&dattr->attr); - put_driver(&pdrv->driver); - } else - error = -EINVAL; - return error; -} - -/** - * dynid_remove_file - remove sysfs file for a dynamic ID - * @drv: driver. - * @id: the id to to remove - */ -static void dynid_remove_file(struct pci_driver * pdrv, struct dynid_attribute * dattr) -{ - if (get_driver(&pdrv->driver)) { - sysfs_remove_file(&pdrv->dynids.kobj,&dattr->attr); - put_driver(&pdrv->driver); - } -} - -#define kobj_to_dynids(obj) container_of(obj,struct pci_dynamic_id_kobj,kobj) -#define dynids_to_pci_driver(obj) container_of(obj,struct pci_driver,dynids) -#define attr_to_dattr(_attr) container_of(_attr, struct dynid_attribute, attr) - -static inline ssize_t -default_show_id(const struct pci_device_id * id, char * buf) -{ - return snprintf(buf, PAGE_SIZE, "%08x %08x %08x %08x %08x %08x\n", - id->vendor, - id->device, - id->subvendor, - id->subdevice, - id->class, - id->class_mask); -} - -static ssize_t -dynid_show_id(struct pci_driver * pdrv, struct dynid_attribute *dattr, char *buf) -{ - return pdrv->dynids.show_id ? - pdrv->dynids.show_id(dattr->id, dattr, buf) : - default_show_id(dattr->id, buf); -} - -static ssize_t -default_show_new_id(char * buf) -{ - char *p = buf; - p += sprintf(p, - "echo vendor device subvendor subdevice class classmask\n"); - p += sprintf(p, - "where each field is a 32-bit value in ABCD (hex) format (no leading 0x).\n"); - p += sprintf(p, - "Pass only as many fields as you need to override the defaults below.\n"); - p += sprintf(p, - "Default vendor, device, subvendor, and subdevice fields\n"); - p += sprintf(p, "are set to FFFFFFFF (PCI_ANY_ID).\n"); - p += sprintf(p, - "Default class and classmask fields are set to 0.\n"); - return p - buf; -} - -static inline void -__dattr_init(struct dynid_attribute *dattr) -{ - memset(dattr, 0, sizeof(*dattr)); - INIT_LIST_HEAD(&dattr->node); - dattr->attr.mode = S_IRUGO; - dattr->attr.name = dattr->name; -} - -static inline ssize_t -default_store_new_id(struct pci_driver * pdrv, const char * buf, size_t count) -{ - struct dynid_attribute *dattr; - struct pci_device_id *id; - __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, - subdevice=PCI_ANY_ID, class=0, class_mask=0; - int fields=0, error=0; - - fields = sscanf(buf, "%x %x %x %x %x %x", - &vendor, &device, &subvendor, &subdevice, - &class, &class_mask); - if (fields < 0) return -EINVAL; - - dattr = kmalloc(sizeof(*dattr), GFP_KERNEL); - if (!dattr) return -ENOMEM; - __dattr_init(dattr); - - id = kmalloc(sizeof(*id), GFP_KERNEL); - if (!id) { - kfree(dattr); - return -ENOMEM; - } - dattr->id = id; - dattr->show = dynid_show_id; - - id->vendor = vendor; - id->device = device; - id->subvendor = subvendor; - id->subdevice = subdevice; - id->class = class; - id->class_mask = class_mask; - - spin_lock(&pdrv->dynids.lock); - snprintf(dattr->name, KOBJ_NAME_LEN, "%d", pdrv->dynids.nextname); - pdrv->dynids.nextname++; - spin_unlock(&pdrv->dynids.lock); - - error = dynid_create_file(pdrv,dattr); - if (error) { - kfree(id); - kfree(dattr); - return error; - } - - spin_lock(&pdrv->dynids.lock); - list_add(&pdrv->dynids.list, &dattr->node); - spin_unlock(&pdrv->dynids.lock); - return count; -} - -static ssize_t -dynid_show_new_id(struct pci_driver * pdrv, struct dynid_attribute *unused, char * buf) -{ - return pdrv->dynids.show_new_id ? - pdrv->dynids.show_new_id(pdrv, buf) : - default_show_new_id(buf); -} - -static ssize_t -dynid_store_new_id(struct pci_driver * pdrv, struct dynid_attribute *unused, const char * buf, size_t count) -{ - return pdrv->dynids.store_new_id ? - pdrv->dynids.store_new_id(pdrv, buf, count) : - default_store_new_id(pdrv, buf, count); -} - -#define DYNID_ATTR(_name,_mode,_show,_store) \ -struct dynid_attribute dynid_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .id = NULL, \ - .show = _show, \ - .store = _store, \ -} - -static DYNID_ATTR(new_id,S_IRUSR|S_IWUSR,dynid_show_new_id,dynid_store_new_id); - -static struct attribute * dynids_def_attrs[] = { - &dynid_attr_new_id.attr, - NULL, -}; - -static ssize_t -dynid_show(struct kobject * kobj, struct attribute *attr, char *buf) -{ - struct pci_dynamic_id_kobj *dynid_kobj = kobj_to_dynids(kobj); - struct pci_driver *pdrv = dynids_to_pci_driver(dynid_kobj); - struct dynid_attribute *dattr = attr_to_dattr(attr); - - if (dattr->show) - return dattr->show(pdrv, dattr, buf); - return -ENOSYS; -} - -static ssize_t -dynid_store(struct kobject * kobj, struct attribute *attr, const char *buf, size_t count) -{ - struct pci_dynamic_id_kobj *dynid_kobj = kobj_to_dynids(kobj); - struct pci_driver *pdrv = dynids_to_pci_driver(dynid_kobj); - struct dynid_attribute *dattr = attr_to_dattr(attr); - - if (dattr->store) - return dattr->store(pdrv, dattr, buf, count); - return -ENOSYS; -} - -static void -dynids_release(struct kobject *kobj) -{ - struct pci_dynamic_id_kobj *dynids = kobj_to_dynids(kobj); - struct pci_driver *pdrv = dynids_to_pci_driver(dynids); - struct list_head *pos, *n; - struct dynid_attribute *dattr; - - spin_lock(&dynids->lock); - list_for_each_safe(pos, n, &dynids->list) { - dattr = list_entry(pos, struct dynid_attribute, node); - dynid_remove_file(pdrv, dattr); - list_del(&dattr->node); - if (dattr->id) - kfree(dattr->id); - kfree(dattr); - } - spin_unlock(&dynids->lock); -} - -static struct sysfs_ops dynids_attr_ops = { - .show = dynid_show, - .store = dynid_store, -}; -static struct kobj_type dynids_kobj_type = { - .release = dynids_release, - .sysfs_ops = &dynids_attr_ops, - .default_attrs = dynids_def_attrs, -}; - -/** - * pci_register_dynids - initialize and register driver dynamic_ids kobject - * @driver - the device_driver structure - * @dynids - the dynamic ids structure - */ -int -pci_register_dynids(struct pci_driver *drv) -{ - struct device_driver *driver = &drv->driver; - struct pci_dynamic_id_kobj *dynids = &drv->dynids; - if (drv->probe) { - dynids->kobj.parent = &driver->kobj; - dynids->kobj.ktype = &dynids_kobj_type; - snprintf(dynids->kobj.name, KOBJ_NAME_LEN, "dynamic_id"); - return kobject_register(&dynids->kobj); - } - return -ENODEV; -} - diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h --- a/drivers/pci/pci.h Thu May 22 14:52:46 2003 +++ b/drivers/pci/pci.h Thu May 22 14:52:46 2003 @@ -3,4 +3,3 @@ extern int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); extern void pci_create_sysfs_dev_files(struct pci_dev *pdev); -extern int pci_register_dynids(struct pci_driver *drv); diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Thu May 22 14:52:46 2003 +++ b/include/linux/device.h Thu May 22 14:52:46 2003 @@ -143,7 +143,6 @@ struct attribute attr; ssize_t (*show)(struct device_driver *, char * buf); ssize_t (*store)(struct device_driver *, const char * buf, size_t count); - int (*exists)(struct device_driver *); }; #define DRIVER_ATTR(_name,_mode,_show,_store) \ @@ -151,17 +150,7 @@ .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \ - .exists = NULL, \ }; - -#define DRIVER_ATTR_EXISTS(_name,_mode,_show,_store,_exists) \ -struct driver_attribute driver_attr_##_name = { \ - .attr = {.name = __stringify(_name), .mode = _mode }, \ - .show = _show, \ - .store = _store, \ - .exists = _exists, \ -}; - extern int driver_create_file(struct device_driver *, struct driver_attribute *); extern void driver_remove_file(struct device_driver *, struct driver_attribute *); diff -Nru a/include/linux/pci-dynids.h b/include/linux/pci-dynids.h --- a/include/linux/pci-dynids.h Thu May 22 14:52:46 2003 +++ b/include/linux/pci-dynids.h Thu May 22 14:52:46 2003 @@ -7,34 +7,12 @@ #ifndef LINUX_PCI_DYNIDS_H #define LINUX_PCI_DYNIDS_H -#include <linux/mod_devicetable.h> -#include <linux/types.h> -#include <linux/config.h> #include <linux/list.h> -#include <linux/device.h> -#include <linux/pci.h> - -struct pci_driver; -struct pci_device_id; +#include <linux/mod_devicetable.h> -struct dynid_attribute { - struct attribute attr; +struct dynid { struct list_head node; - struct pci_device_id *id; - ssize_t (*show)(struct pci_driver * pdrv, struct dynid_attribute *dattr, char * buf); - ssize_t (*store)(struct pci_driver * pdrv, struct dynid_attribute *dattr, const char * buf, size_t count); - char name[KOBJ_NAME_LEN]; -}; - -struct pci_dynamic_id_kobj { - ssize_t (*show_new_id)(struct pci_driver * pdrv, char * buf); - ssize_t (*store_new_id)(struct pci_driver * pdrv, const char * buf, size_t count); - ssize_t (*show_id)(struct pci_device_id * id, struct dynid_attribute *dattr, char * buf); - - spinlock_t lock; /* protects list, index */ - struct list_head list; /* for IDs added at runtime */ - struct kobject kobj; /* for displaying the list in sysfs */ - unsigned int nextname; /* name of next dynamic ID twhen created */ + struct pci_device_id id; }; #endif diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu May 22 14:52:46 2003 +++ b/include/linux/pci.h Thu May 22 14:52:46 2003 @@ -343,7 +343,6 @@ #include <linux/list.h> #include <linux/errno.h> #include <linux/device.h> -#include <linux/pci-dynids.h> /* File state for mmap()s on /proc/bus/pci/X/Y */ enum pci_mmap_state { @@ -491,6 +490,12 @@ unsigned long end; }; +struct pci_dynids { + spinlock_t lock; /* protects list, index */ + struct list_head list; /* for IDs added at runtime */ + unsigned int use_driver_data:1; /* pci_driver->driver_data is used */ +}; + struct pci_driver { struct list_head node; char *name; @@ -503,12 +508,14 @@ int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */ struct device_driver driver; - struct pci_dynamic_id_kobj dynids; + struct pci_dynids dynids; }; #define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) + + /* these external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI @@ -704,6 +711,12 @@ struct pci_bus_wrapped *wrapped_parent); extern int pci_remove_device_safe(struct pci_dev *dev); +static inline void +pci_dynids_set_use_driver_data(struct pci_driver *pdrv, int val) +{ + pdrv->dynids.use_driver_data = val; +} + #endif /* CONFIG_PCI */ /* Include architecture-dependent settings and functions */ @@ -752,6 +765,7 @@ static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; } static inline int pci_find_capability (struct pci_dev *dev, int cap) {return 0; } static inline const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) { return NULL; } +static inline void pci_dynids_set_use_driver_data(struct pci_driver *pdrv, int val) { } /* Power management related routines */ static inline int pci_save_state(struct pci_dev *dev, u32 *buffer) { return 0; } @@ -763,6 +777,8 @@ for(dev = NULL; 0; ) #define isa_bridge ((struct pci_dev *)NULL) + + #else ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:05 ` Greg KH @ 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2003-05-22 22:06 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1063.1.2, 2003/05/05 16:40:59-05:00, Matt_Domsch@dell.com PCI dynids - documentation fixes, id_table NULL check Documentation/pci.txt | 24 ++++++++++++++++++++++-- drivers/pci/pci-driver.c | 4 +++- include/linux/pci.h | 2 +- 3 files changed, 26 insertions(+), 4 deletions(-) diff -Nru a/Documentation/pci.txt b/Documentation/pci.txt --- a/Documentation/pci.txt Thu May 22 14:52:14 2003 +++ b/Documentation/pci.txt Thu May 22 14:52:14 2003 @@ -45,8 +45,6 @@ id_table Pointer to table of device ID's the driver is interested in. Most drivers should export this table using MODULE_DEVICE_TABLE(pci,...). - Set to NULL to call probe() function for every - PCI device known to the system. probe Pointer to a probing function which gets called (during execution of pci_register_driver for already existing devices or later if a new device gets inserted) for all @@ -82,6 +80,28 @@ class, Device class to match. The class_mask tells which bits class_mask of the class are honored during the comparison. driver_data Data private to the driver. + +Most drivers don't need to use the driver_data field. Best practice +for use of driver_data is to use it as an index into a static list of +equivalant device types, not to use it as a pointer. + +Have a table entry {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID} +to have probe() called for every PCI device known to the system. + +New PCI IDs may be added to a device driver at runtime by writing +to the file /sys/bus/pci/drivers/{driver}/new_id. When added, the +driver will probe for all devices it can support. + +echo "vendor device subvendor subdevice class class_mask driver_data" > \ + /sys/bus/pci/drivers/{driver}/new_id +where all fields are passed in as hexadecimal values (no leading 0x). +Users need pass only as many fields as necessary; vendor, device, +subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF), +class and classmask fields default to 0, and driver_data defaults to +0UL. Device drivers must call + pci_dynids_set_use_driver_data(pci_driver *, 1) +in order for the driver_data field to get passed to the driver. +Otherwise, only a 0 is passed in that field. When the driver exits, it just calls pci_unregister_driver() and the PCI layer automatically calls the remove hook for all devices handled by the driver. diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Thu May 22 14:52:14 2003 +++ b/drivers/pci/pci-driver.c Thu May 22 14:52:14 2003 @@ -65,7 +65,9 @@ { int error = -ENODEV; const struct pci_device_id *id; - + + if (!drv->id_table) + return error; id = pci_match_device(drv->id_table, pci_dev); if (id) error = drv->probe(pci_dev, id); diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu May 22 14:52:14 2003 +++ b/include/linux/pci.h Thu May 22 14:52:14 2003 @@ -499,7 +499,7 @@ struct pci_driver { struct list_head node; char *name; - const struct pci_device_id *id_table; /* NULL if wants all devices */ + const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:06 ` Greg KH @ 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2003-05-22 22:06 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1063.1.3, 2003/05/05 17:29:47-05:00, Matt_Domsch@dell.com pci.h whitespace cleanups include/linux/pci.h | 4 ---- 1 files changed, 4 deletions(-) diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu May 22 14:51:42 2003 +++ b/include/linux/pci.h Thu May 22 14:51:42 2003 @@ -514,8 +514,6 @@ #define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) - - /* these external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI @@ -777,8 +775,6 @@ for(dev = NULL; 0; ) #define isa_bridge ((struct pci_dev *)NULL) - - #else ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:06 ` Greg KH @ 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 0 siblings, 1 reply; 12+ messages in thread From: Greg KH @ 2003-05-22 22:06 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1063.1.4, 2003/05/06 11:15:45-05:00, Matt_Domsch@dell.com dynids: call driver_attach() when new IDs are added This causes the driver to create proper device symlinks in sysfs when new IDs are added and thus new devices found by the driver. drivers/base/bus.c make driver_attach non-static drivers/pci/pci-driver.c delete probe_each_pci_dev, call driver_attach instead. Whitespace cleanups. include/linux/device.h add declaration of driver_attach. drivers/base/bus.c | 2 - drivers/pci/pci-driver.c | 82 ++++++++++++++++++----------------------------- include/linux/device.h | 1 3 files changed, 35 insertions(+), 50 deletions(-) diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Thu May 22 14:51:15 2003 +++ b/drivers/base/bus.c Thu May 22 14:51:15 2003 @@ -316,7 +316,7 @@ * Note that we ignore the error from bus_match(), since it's perfectly * valid for a driver not to bind to any devices. */ -static void driver_attach(struct device_driver * drv) +void driver_attach(struct device_driver * drv) { struct bus_type * bus = drv->bus; struct list_head * entry; diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Thu May 22 14:51:15 2003 +++ b/drivers/pci/pci-driver.c Thu May 22 14:51:15 2003 @@ -15,7 +15,8 @@ */ /** - * pci_match_one_device - Tell if a PCI device structure has a matching PCI device id structure + * pci_match_one_device - Tell if a PCI device structure has a matching + * PCI device id structure * @id: single PCI device id structure to match * @dev: the PCI device structure to match against * @@ -35,7 +36,8 @@ } /** - * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure + * pci_match_device - Tell if a PCI device structure has a matching + * PCI device id structure * @ids: array of PCI device id structures to search in * @dev: the PCI device structure to match against * @@ -48,7 +50,7 @@ { while (ids->vendor || ids->subvendor || ids->class_mask) { if (pci_match_one_device(ids, dev)) - return ids; + return ids; ids++; } return NULL; @@ -60,8 +62,7 @@ * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. */ static int -pci_device_probe_static(struct pci_driver *drv, - struct pci_dev *pci_dev) +pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev) { int error = -ENODEV; const struct pci_device_id *id; @@ -85,13 +86,12 @@ * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. */ static int -pci_device_probe_dynamic(struct pci_driver *drv, - struct pci_dev *pci_dev) +pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev) { int error = -ENODEV; struct list_head *pos; struct dynid *dynid; - + spin_lock(&drv->dynids.lock); list_for_each(pos, &drv->dynids.list) { dynid = list_entry(pos, struct dynid, node); @@ -116,8 +116,7 @@ * side-effect: pci_dev->driver is set to drv when drv claims pci_dev. */ static int -__pci_device_probe(struct pci_driver *drv, - struct pci_dev *pci_dev) +__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) { int error = 0; @@ -188,28 +187,6 @@ return 0; } -/* - * If __pci_device_probe() returns 0, it matched at least one previously - * unclaimed device. If it returns -ENODEV, it didn't match. Both are - * alright in this case, just keep searching for new devices. - */ - -static int -probe_each_pci_dev(struct pci_driver *drv) -{ - struct pci_dev *pci_dev=NULL; - int error = 0; - pci_for_each_dev(pci_dev) { - if (get_device(&pci_dev->dev)) { - error = __pci_device_probe(drv, pci_dev); - put_device(&pci_dev->dev); - if (error && error != -ENODEV) - return error; - } - } - return error; -} - static inline void dynid_init(struct dynid *dynid) { @@ -230,19 +207,22 @@ store_new_id(struct device_driver * driver, const char * buf, size_t count) { struct dynid *dynid; + struct bus_type * bus; struct pci_driver *pdrv = to_pci_driver(driver); __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, subdevice=PCI_ANY_ID, class=0, class_mask=0; unsigned long driver_data=0; - int fields=0, error=0; + int fields=0; fields = sscanf(buf, "%x %x %x %x %x %x %lux", &vendor, &device, &subvendor, &subdevice, &class, &class_mask, &driver_data); - if (fields < 0) return -EINVAL; + if (fields < 0) + return -EINVAL; dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); - if (!dynid) return -ENOMEM; + if (!dynid) + return -ENOMEM; dynid_init(dynid); dynid->id.vendor = vendor; @@ -251,21 +231,24 @@ dynid->id.subdevice = subdevice; dynid->id.class = class; dynid->id.class_mask = class_mask; - dynid->id.driver_data = pdrv->dynids.use_driver_data ? driver_data : 0UL; + dynid->id.driver_data = pdrv->dynids.use_driver_data ? + driver_data : 0UL; spin_lock(&pdrv->dynids.lock); list_add(&pdrv->dynids.list, &dynid->node); spin_unlock(&pdrv->dynids.lock); - if (get_driver(&pdrv->driver)) { - error = probe_each_pci_dev(pdrv); - put_driver(&pdrv->driver); - } - if (error < 0) - return error; - return count; - - + bus = get_bus(pdrv->driver.bus); + if (bus) { + if (get_driver(&pdrv->driver)) { + down_write(&bus->subsys.rwsem); + driver_attach(&pdrv->driver); + up_write(&bus->subsys.rwsem); + put_driver(&pdrv->driver); + } + put_bus(bus); + } + return count; } @@ -310,7 +293,7 @@ .store = pci_driver_attr_store, }; static struct kobj_type pci_driver_kobj_type = { - .sysfs_ops = &pci_driver_sysfs_ops, + .sysfs_ops = &pci_driver_sysfs_ops, }; static int @@ -319,7 +302,8 @@ int error = 0; if (drv->probe != NULL) - error = sysfs_create_file(&drv->driver.kobj,&driver_attr_new_id.attr); + error = sysfs_create_file(&drv->driver.kobj, + &driver_attr_new_id.attr); return error; } @@ -361,7 +345,7 @@ if (count >= 0) { pci_populate_driver_dir(drv); } - + return count ? count : 1; } @@ -428,7 +412,7 @@ return 0; found_id = pci_match_device(ids, pci_dev); - if (found_id) + if (found_id) return 1; spin_lock(&pci_drv->dynids.lock); diff -Nru a/include/linux/device.h b/include/linux/device.h --- a/include/linux/device.h Thu May 22 14:51:15 2003 +++ b/include/linux/device.h Thu May 22 14:51:15 2003 @@ -318,6 +318,7 @@ */ extern void device_bind_driver(struct device * dev); extern void device_release_driver(struct device * dev); +extern void driver_attach(struct device_driver * drv); /* driverfs interface for exporting device attributes */ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:06 ` Greg KH @ 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-23 6:07 ` Christoph Hellwig 0 siblings, 2 replies; 12+ messages in thread From: Greg KH @ 2003-05-22 22:06 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1210, 2003/05/22 10:30:35-07:00, greg@kroah.com PCI: add pci_get_dev() and pci_put_dev() Move the PCI core to start using these, enabling proper reference counting on struct pci_dev. drivers/pci/bus.c | 2 +- drivers/pci/hotplug.c | 2 +- drivers/pci/pci-driver.c | 41 +++++++++++++++++++++++++++++++++++++++++ drivers/pci/probe.c | 18 ++++++++++++++++++ include/linux/pci.h | 2 ++ 5 files changed, 63 insertions(+), 2 deletions(-) diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c --- a/drivers/pci/bus.c Thu May 22 14:50:44 2003 +++ b/drivers/pci/bus.c Thu May 22 14:50:44 2003 @@ -92,7 +92,7 @@ if (!list_empty(&dev->global_list)) continue; - device_register(&dev->dev); + device_add(&dev->dev); list_add_tail(&dev->global_list, &pci_devices); #ifdef CONFIG_PROC_FS pci_proc_attach_device(dev); diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c --- a/drivers/pci/hotplug.c Thu May 22 14:50:44 2003 +++ b/drivers/pci/hotplug.c Thu May 22 14:50:44 2003 @@ -275,7 +275,7 @@ pci_proc_detach_device(dev); #endif - kfree(dev); + pci_put_dev(dev); } /** diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Thu May 22 14:50:44 2003 +++ b/drivers/pci/pci-driver.c Thu May 22 14:50:44 2003 @@ -199,6 +199,45 @@ return 0; } +/** + * pci_get_dev - increments the reference count of the pci device structure + * @dev: the device being referenced + * + * Each live reference to a device should be refcounted. + * + * Drivers for PCI devices should normally record such references in + * their probe() methods, when they bind to a device, and release + * them by calling pci_put_dev(), in their disconnect() methods. + * + * A pointer to the device with the incremented reference counter is returned. + */ +struct pci_dev *pci_get_dev (struct pci_dev *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + + tmp = get_device(&dev->dev); + if (tmp) + return to_pci_dev(tmp); + else + return NULL; +} + +/** + * pci_put_dev - release a use of the pci device structure + * @dev: device that's been disconnected + * + * Must be called when a user of a device is finished with it. When the last + * user of the device calls this function, the memory of the device is freed. + */ +void pci_put_dev(struct pci_dev *dev) +{ + if (dev) + put_device(&dev->dev); +} + struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, @@ -217,3 +256,5 @@ EXPORT_SYMBOL(pci_unregister_driver); EXPORT_SYMBOL(pci_dev_driver); EXPORT_SYMBOL(pci_bus_type); +EXPORT_SYMBOL(pci_get_dev); +EXPORT_SYMBOL(pci_put_dev); diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Thu May 22 14:50:44 2003 +++ b/drivers/pci/probe.c Thu May 22 14:50:44 2003 @@ -462,6 +462,21 @@ return 0; } +/** + * pci_release_dev - free a pci device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this pci device are + * done. + */ +static void pci_release_dev(struct device *dev) +{ + struct pci_dev *pci_dev; + + pci_dev = to_pci_dev(dev); + kfree(pci_dev); +} + /* * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... @@ -506,6 +521,9 @@ kfree(dev); return NULL; } + device_initialize(&dev->dev); + dev->dev.release = pci_release_dev; + pci_get_dev(dev); pci_name_device(dev); diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu May 22 14:50:44 2003 +++ b/include/linux/pci.h Thu May 22 14:50:44 2003 @@ -556,6 +556,8 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res); int pci_setup_device(struct pci_dev *dev); int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge); +extern struct pci_dev *pci_get_dev(struct pci_dev *dev); +extern void pci_put_dev(struct pci_dev *dev); /* Generic PCI functions exported to card drivers */ ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:06 ` Greg KH @ 2003-05-22 22:06 ` Greg KH 2003-05-23 6:07 ` Christoph Hellwig 1 sibling, 0 replies; 12+ messages in thread From: Greg KH @ 2003-05-22 22:06 UTC (permalink / raw) To: linux-kernel ChangeSet 1.1212, 2003/05/22 14:31:07-07:00, greg@kroah.com [PATCH] PCI: remove pci_insert_device() as no one uses it anymore. drivers/pci/hotplug.c | 21 --------------------- include/linux/pci.h | 1 - 2 files changed, 22 deletions(-) diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c --- a/drivers/pci/hotplug.c Thu May 22 14:49:44 2003 +++ b/drivers/pci/hotplug.c Thu May 22 14:49:44 2003 @@ -207,26 +207,6 @@ #endif /* CONFIG_HOTPLUG */ -/** - * pci_insert_device - insert a pci device - * @dev: the device to insert - * @bus: where to insert it - * - * Link the device to both the global PCI device chain and the - * per-bus list of devices, add the /proc entry. - */ -void -pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) -{ - list_add_tail(&dev->bus_list, &bus->devices); - list_add_tail(&dev->global_list, &pci_devices); -#ifdef CONFIG_PROC_FS - pci_proc_attach_device(dev); -#endif - /* add sysfs device files */ - pci_create_sysfs_dev_files(dev); -} - static void pci_free_resources(struct pci_dev *dev) { @@ -300,7 +280,6 @@ } #ifdef CONFIG_HOTPLUG -EXPORT_SYMBOL(pci_insert_device); EXPORT_SYMBOL(pci_remove_bus_device); EXPORT_SYMBOL(pci_remove_behind_bridge); #endif diff -Nru a/include/linux/pci.h b/include/linux/pci.h --- a/include/linux/pci.h Thu May 22 14:49:44 2003 +++ b/include/linux/pci.h Thu May 22 14:49:44 2003 @@ -660,7 +660,6 @@ /* New-style probing supporting hot-pluggable devices */ int pci_register_driver(struct pci_driver *); void pci_unregister_driver(struct pci_driver *); -void pci_insert_device(struct pci_dev *, struct pci_bus *); void pci_remove_bus_device(struct pci_dev *); void pci_remove_behind_bridge(struct pci_dev *); struct pci_driver *pci_dev_driver(const struct pci_dev *); ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH @ 2003-05-23 6:07 ` Christoph Hellwig 2003-05-23 7:02 ` Greg KH 1 sibling, 1 reply; 12+ messages in thread From: Christoph Hellwig @ 2003-05-23 6:07 UTC (permalink / raw) To: Greg KH; +Cc: linux-kernel On Thu, May 22, 2003 at 03:06:01PM -0700, Greg KH wrote: > ChangeSet 1.1210, 2003/05/22 10:30:35-07:00, greg@kroah.com > > PCI: add pci_get_dev() and pci_put_dev() > > Move the PCI core to start using these, enabling proper reference counting > on struct pci_dev. > > > drivers/pci/bus.c | 2 +- > drivers/pci/hotplug.c | 2 +- > drivers/pci/pci-driver.c | 41 +++++++++++++++++++++++++++++++++++++++++ > drivers/pci/probe.c | 18 ++++++++++++++++++ > include/linux/pci.h | 2 ++ > 5 files changed, 63 insertions(+), 2 deletions(-) > > > diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c > --- a/drivers/pci/bus.c Thu May 22 14:50:44 2003 > +++ b/drivers/pci/bus.c Thu May 22 14:50:44 2003 > @@ -92,7 +92,7 @@ > if (!list_empty(&dev->global_list)) > continue; > > - device_register(&dev->dev); > + device_add(&dev->dev); This doesn't match the patch description.. > +struct pci_dev *pci_get_dev (struct pci_dev *dev) Please fix up to adhere Documentation/CodingStyle (hint: placement of the opening brace is wrong). > +{ > + struct device *tmp; > + > + if (!dev) > + return NULL; Does it make sense to allow NULL argument here? ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-23 6:07 ` Christoph Hellwig @ 2003-05-23 7:02 ` Greg KH 0 siblings, 0 replies; 12+ messages in thread From: Greg KH @ 2003-05-23 7:02 UTC (permalink / raw) To: Christoph Hellwig, linux-kernel On Fri, May 23, 2003 at 07:07:15AM +0100, Christoph Hellwig wrote: > On Thu, May 22, 2003 at 03:06:01PM -0700, Greg KH wrote: > > ChangeSet 1.1210, 2003/05/22 10:30:35-07:00, greg@kroah.com > > > > PCI: add pci_get_dev() and pci_put_dev() > > > > Move the PCI core to start using these, enabling proper reference counting > > on struct pci_dev. > > > > > > drivers/pci/bus.c | 2 +- > > drivers/pci/hotplug.c | 2 +- > > drivers/pci/pci-driver.c | 41 +++++++++++++++++++++++++++++++++++++++++ > > drivers/pci/probe.c | 18 ++++++++++++++++++ > > include/linux/pci.h | 2 ++ > > 5 files changed, 63 insertions(+), 2 deletions(-) > > > > > > diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c > > --- a/drivers/pci/bus.c Thu May 22 14:50:44 2003 > > +++ b/drivers/pci/bus.c Thu May 22 14:50:44 2003 > > @@ -92,7 +92,7 @@ > > if (!list_empty(&dev->global_list)) > > continue; > > > > - device_register(&dev->dev); > > + device_add(&dev->dev); > > This doesn't match the patch description.. Yes it does. "Move the PCI core to start..." describes exactly this portion of the patch. We have to change from device_register() to device_add() if we want to grab a reference count on the pci device before we register it with the driver core. Which we do want to do, because of the two stage process of creating and registering pci devices. > > +struct pci_dev *pci_get_dev (struct pci_dev *dev) > > Please fix up to adhere Documentation/CodingStyle (hint: placement > of the opening brace is wrong). CodingStyle doesn't _explicitly_ say that this is not allowed :) I'll fix it next set of pci patches... > > +{ > > + struct device *tmp; > > + > > + if (!dev) > > + return NULL; > > Does it make sense to allow NULL argument here? Just being safe. We can drop it if it really annoys you, but other subsystems do the same thing. greg k-h ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:05 ` [PATCH] " Greg KH 2003-05-22 22:05 ` Greg KH @ 2003-05-22 22:36 ` Dave Jones 2003-05-22 22:48 ` Greg KH 1 sibling, 1 reply; 12+ messages in thread From: Dave Jones @ 2003-05-22 22:36 UTC (permalink / raw) To: Greg KH; +Cc: linux-kernel On Thu, May 22, 2003 at 03:05:59PM -0700, Greg KH wrote: > One may write new PCI device IDs into the new_id file: > echo "8086 1229" > new_id > > which will cause a new device ID (sysfs name 0) to be added to the driver. Why not call the probe routine at this point ? This would do away with the need for the probe_it file. The only downside I can see is that if we have a script echoing lots of device id updates, we're going to lots of additional (-ENODEV) probes. Dave ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] PCI changes for 2.5.69 2003-05-22 22:36 ` Dave Jones @ 2003-05-22 22:48 ` Greg KH 0 siblings, 0 replies; 12+ messages in thread From: Greg KH @ 2003-05-22 22:48 UTC (permalink / raw) To: Dave Jones, linux-kernel On Thu, May 22, 2003 at 11:36:16PM +0100, Dave Jones wrote: > On Thu, May 22, 2003 at 03:05:59PM -0700, Greg KH wrote: > > > One may write new PCI device IDs into the new_id file: > > echo "8086 1229" > new_id > > > > which will cause a new device ID (sysfs name 0) to be added to the driver. > > Why not call the probe routine at this point ? > This would do away with the need for the probe_it file. > The only downside I can see is that if we have a script > echoing lots of device id updates, we're going to lots of > additional (-ENODEV) probes. Keep reading through the patches :) greg k-h ^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2003-05-23 6:47 UTC | newest] Thread overview: 12+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2003-05-22 22:02 [BK PATCH] PCI changes for 2.5.69 Greg KH 2003-05-22 22:05 ` [PATCH] " Greg KH 2003-05-22 22:05 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-22 22:06 ` Greg KH 2003-05-23 6:07 ` Christoph Hellwig 2003-05-23 7:02 ` Greg KH 2003-05-22 22:36 ` Dave Jones 2003-05-22 22:48 ` Greg KH
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox