diff -Nru linux-2.6.27.orig/drivers/pci/pci-driver.c linux-2.6.27/drivers/pci/pci-driver.c --- linux-2.6.27.orig/drivers/pci/pci-driver.c 2008-10-09 18:13:53.000000000 -0400 +++ linux-2.6.27/drivers/pci/pci-driver.c 2008-11-04 08:24:29.000000000 -0500 @@ -118,6 +118,70 @@ static inline void pci_remove_newid_file(struct pci_driver *drv) {} #endif +#define ADD(buf, size, cond, wdata, data, wodata) \ +{ \ + if (cond) { \ + if (snprintf(buf, size, "%s" wdata, buf, data) >= size) \ + return -ENOMEM; \ + } \ + else { \ + if (snprintf(buf, size, "%s" wodata, buf) >= size) \ + return -ENOMEM; \ + } \ +} + +#define PCI_MODALIAS(buf, size, v, d, sv, sd, c, cm) \ +{ \ +ADD(buf, size, 1, "%s", "pci:", "") \ +ADD(buf, size, v != PCI_ANY_ID, "v%08X", v, "v*") \ +ADD(buf, size, d != PCI_ANY_ID, "d%08X", d, "d*") \ +ADD(buf, size, sv != PCI_ANY_ID, "sv%08X", sv, "sv*") \ +ADD(buf, size, sd != PCI_ANY_ID, "sd%08X", sd, "sd*") \ +ADD(buf, size, ((cm >> 16) & 0xFF) == 0xFF, "bc%02X", ((c >> 16) & 0xFF), "bc*") \ +ADD(buf, size, ((cm >> 8) & 0xFF) == 0xFF, "sc%02X", ((c >> 8) & 0xFF), "sc*") \ +ADD(buf, size, ((cm >> 0) & 0xFF) == 0xFF, "i%02X*", ((c >> 0) & 0xFF), "i*") \ +ADD(buf, size, 1, "%s", "\n", "") \ +} + +static ssize_t +show_modaliases(struct device_driver *driver, char *buf) +{ + struct pci_driver *pdrv = to_pci_driver(driver); + struct list_head *pos; + struct pci_dynid *dynid; + int i; + + /* Reset the buffer to be blank */ + buf[0] = '\0'; + + /* List the static ids */ + for (i=0 ; pdrv->id_table[i].vendor != 0 && + pdrv->id_table[i].device != 0; i++) { + PCI_MODALIAS(buf, PAGE_SIZE, + pdrv->id_table[i].vendor, + pdrv->id_table[i].device, + pdrv->id_table[i].subvendor, + pdrv->id_table[i].subdevice, + pdrv->id_table[i].class, + pdrv->id_table[i].class_mask) + } + + /* List the dynamic ids */ + list_for_each(pos, &pdrv->dynids.list) { + dynid = list_entry(pos, struct pci_dynid, node); + PCI_MODALIAS(buf, PAGE_SIZE, + dynid->id.vendor, + dynid->id.device, + dynid->id.subvendor, + dynid->id.subdevice, + dynid->id.class, + dynid->id.class_mask) + } + + return strlen(buf); +} +static DRIVER_ATTR(modaliases, S_IRUGO, show_modaliases, NULL); + /** * pci_match_id - See if a pci device matches a given pci_id table * @ids: array of PCI device id structures to search in @@ -702,9 +766,11 @@ return error; error = pci_create_newid_file(drv); - if (error) - driver_unregister(&drv->driver); + if (!error) + error = driver_create_file(&drv->driver, &driver_attr_modaliases); + if (error) + pci_unregister_driver(drv); return error; } @@ -722,6 +788,7 @@ pci_unregister_driver(struct pci_driver *drv) { pci_remove_newid_file(drv); + driver_remove_file(&drv->driver, &driver_attr_modaliases); driver_unregister(&drv->driver); pci_free_dynids(drv); }