Commit 8a6a5068 authored by Matt Domsch's avatar Matt Domsch

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.
parent 482ac984
...@@ -316,7 +316,7 @@ static int device_attach(struct device * dev) ...@@ -316,7 +316,7 @@ static int device_attach(struct device * dev)
* Note that we ignore the error from bus_match(), since it's perfectly * Note that we ignore the error from bus_match(), since it's perfectly
* valid for a driver not to bind to any devices. * 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 bus_type * bus = drv->bus;
struct list_head * entry; struct list_head * entry;
......
...@@ -15,7 +15,8 @@ ...@@ -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 * @id: single PCI device id structure to match
* @dev: the PCI device structure to match against * @dev: the PCI device structure to match against
* *
...@@ -35,7 +36,8 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) ...@@ -35,7 +36,8 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
} }
/** /**
* 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 * @ids: array of PCI device id structures to search in
* @dev: the PCI device structure to match against * @dev: the PCI device structure to match against
* *
...@@ -48,7 +50,7 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) ...@@ -48,7 +50,7 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev)
{ {
while (ids->vendor || ids->subvendor || ids->class_mask) { while (ids->vendor || ids->subvendor || ids->class_mask) {
if (pci_match_one_device(ids, dev)) if (pci_match_one_device(ids, dev))
return ids; return ids;
ids++; ids++;
} }
return NULL; return NULL;
...@@ -60,8 +62,7 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) ...@@ -60,8 +62,7 @@ pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev)
* returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
*/ */
static int static int
pci_device_probe_static(struct pci_driver *drv, pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev)
struct pci_dev *pci_dev)
{ {
int error = -ENODEV; int error = -ENODEV;
const struct pci_device_id *id; const struct pci_device_id *id;
...@@ -85,13 +86,12 @@ pci_device_probe_static(struct pci_driver *drv, ...@@ -85,13 +86,12 @@ pci_device_probe_static(struct pci_driver *drv,
* returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. * returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
*/ */
static int static int
pci_device_probe_dynamic(struct pci_driver *drv, pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
struct pci_dev *pci_dev)
{ {
int error = -ENODEV; int error = -ENODEV;
struct list_head *pos; struct list_head *pos;
struct dynid *dynid; struct dynid *dynid;
spin_lock(&drv->dynids.lock); spin_lock(&drv->dynids.lock);
list_for_each(pos, &drv->dynids.list) { list_for_each(pos, &drv->dynids.list) {
dynid = list_entry(pos, struct dynid, node); dynid = list_entry(pos, struct dynid, node);
...@@ -116,8 +116,7 @@ pci_device_probe_dynamic(struct pci_driver *drv, ...@@ -116,8 +116,7 @@ pci_device_probe_dynamic(struct pci_driver *drv,
* side-effect: pci_dev->driver is set to drv when drv claims pci_dev. * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.
*/ */
static int static int
__pci_device_probe(struct pci_driver *drv, __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
struct pci_dev *pci_dev)
{ {
int error = 0; int error = 0;
...@@ -188,28 +187,6 @@ static int pci_device_resume(struct device * dev, u32 level) ...@@ -188,28 +187,6 @@ static int pci_device_resume(struct device * dev, u32 level)
return 0; 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 static inline void
dynid_init(struct dynid *dynid) dynid_init(struct dynid *dynid)
{ {
...@@ -230,19 +207,22 @@ static inline ssize_t ...@@ -230,19 +207,22 @@ static inline ssize_t
store_new_id(struct device_driver * driver, const char * buf, size_t count) store_new_id(struct device_driver * driver, const char * buf, size_t count)
{ {
struct dynid *dynid; struct dynid *dynid;
struct bus_type * bus;
struct pci_driver *pdrv = to_pci_driver(driver); struct pci_driver *pdrv = to_pci_driver(driver);
__u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID, __u32 vendor=PCI_ANY_ID, device=PCI_ANY_ID, subvendor=PCI_ANY_ID,
subdevice=PCI_ANY_ID, class=0, class_mask=0; subdevice=PCI_ANY_ID, class=0, class_mask=0;
unsigned long driver_data=0; unsigned long driver_data=0;
int fields=0, error=0; int fields=0;
fields = sscanf(buf, "%x %x %x %x %x %x %lux", fields = sscanf(buf, "%x %x %x %x %x %x %lux",
&vendor, &device, &subvendor, &subdevice, &vendor, &device, &subvendor, &subdevice,
&class, &class_mask, &driver_data); &class, &class_mask, &driver_data);
if (fields < 0) return -EINVAL; if (fields < 0)
return -EINVAL;
dynid = kmalloc(sizeof(*dynid), GFP_KERNEL); dynid = kmalloc(sizeof(*dynid), GFP_KERNEL);
if (!dynid) return -ENOMEM; if (!dynid)
return -ENOMEM;
dynid_init(dynid); dynid_init(dynid);
dynid->id.vendor = vendor; dynid->id.vendor = vendor;
...@@ -251,21 +231,24 @@ store_new_id(struct device_driver * driver, const char * buf, size_t count) ...@@ -251,21 +231,24 @@ store_new_id(struct device_driver * driver, const char * buf, size_t count)
dynid->id.subdevice = subdevice; dynid->id.subdevice = subdevice;
dynid->id.class = class; dynid->id.class = class;
dynid->id.class_mask = class_mask; 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); spin_lock(&pdrv->dynids.lock);
list_add(&pdrv->dynids.list, &dynid->node); list_add(&pdrv->dynids.list, &dynid->node);
spin_unlock(&pdrv->dynids.lock); spin_unlock(&pdrv->dynids.lock);
if (get_driver(&pdrv->driver)) { bus = get_bus(pdrv->driver.bus);
error = probe_each_pci_dev(pdrv); if (bus) {
put_driver(&pdrv->driver); if (get_driver(&pdrv->driver)) {
} down_write(&bus->subsys.rwsem);
if (error < 0) driver_attach(&pdrv->driver);
return error; up_write(&bus->subsys.rwsem);
return count; put_driver(&pdrv->driver);
}
put_bus(bus);
}
return count; return count;
} }
...@@ -310,7 +293,7 @@ static struct sysfs_ops pci_driver_sysfs_ops = { ...@@ -310,7 +293,7 @@ static struct sysfs_ops pci_driver_sysfs_ops = {
.store = pci_driver_attr_store, .store = pci_driver_attr_store,
}; };
static struct kobj_type pci_driver_kobj_type = { static struct kobj_type pci_driver_kobj_type = {
.sysfs_ops = &pci_driver_sysfs_ops, .sysfs_ops = &pci_driver_sysfs_ops,
}; };
static int static int
...@@ -319,7 +302,8 @@ pci_populate_driver_dir(struct pci_driver * drv) ...@@ -319,7 +302,8 @@ pci_populate_driver_dir(struct pci_driver * drv)
int error = 0; int error = 0;
if (drv->probe != NULL) 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; return error;
} }
...@@ -361,7 +345,7 @@ pci_register_driver(struct pci_driver *drv) ...@@ -361,7 +345,7 @@ pci_register_driver(struct pci_driver *drv)
if (count >= 0) { if (count >= 0) {
pci_populate_driver_dir(drv); pci_populate_driver_dir(drv);
} }
return count ? count : 1; return count ? count : 1;
} }
...@@ -428,7 +412,7 @@ static int pci_bus_match(struct device * dev, struct device_driver * drv) ...@@ -428,7 +412,7 @@ static int pci_bus_match(struct device * dev, struct device_driver * drv)
return 0; return 0;
found_id = pci_match_device(ids, pci_dev); found_id = pci_match_device(ids, pci_dev);
if (found_id) if (found_id)
return 1; return 1;
spin_lock(&pci_drv->dynids.lock); spin_lock(&pci_drv->dynids.lock);
......
...@@ -318,6 +318,7 @@ extern void device_del(struct device * dev); ...@@ -318,6 +318,7 @@ extern void device_del(struct device * dev);
*/ */
extern void device_bind_driver(struct device * dev); extern void device_bind_driver(struct device * dev);
extern void device_release_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 */ /* driverfs interface for exporting device attributes */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment