* Registration of PCI drivers and handling of hot-pluggable devices.
*/
-LIST_HEAD(pci_drivers);
-
/**
* 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
return ret;
}
+
+static int pci_device_probe(struct device * dev)
+{
+ int error = 0;
+
+ struct pci_driver * drv = list_entry(dev->driver,struct pci_driver,driver);
+ struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+
+ if (drv->probe)
+ error = drv->probe(pci_dev,NULL);
+ printk("%s: returning %d\n",__FUNCTION__,error);
+ return error > 0 ? 0 : -ENODEV;
+}
+
+static int pci_device_remove(struct device * dev, u32 flags)
+{
+ struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+
+ if (dev->driver) {
+ struct pci_driver * drv = list_entry(dev->driver,struct pci_driver,driver);
+ if (drv->remove)
+ drv->remove(pci_dev);
+ }
+ return 0;
+}
+
+static int pci_device_suspend(struct device * dev, u32 state, u32 level)
+{
+ struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
+ int error = 0;
+
+ if (pci_dev->driver) {
+ if (level == SUSPEND_SAVE_STATE && pci_dev->driver->save_state)
+ error = pci_dev->driver->save_state(pci_dev,state);
+ else if (level == SUSPEND_POWER_DOWN && pci_dev->driver->suspend)
+ error = pci_dev->driver->suspend(pci_dev,state);
+ }
+ return error;
+}
+
+static int pci_device_resume(struct device * dev, u32 level)
+{
+ struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
+
+ if (pci_dev->driver) {
+ if (level == RESUME_POWER_ON && pci_dev->driver->resume)
+ pci_dev->driver->resume(pci_dev);
+ }
+ return 0;
+}
+
/**
* pci_register_driver - register a new pci driver
* @drv: the driver structure to register
int
pci_register_driver(struct pci_driver *drv)
{
- struct pci_dev *dev;
int count = 0;
+ struct pci_dev * dev;
+
+ /* initialize common driver fields */
+ drv->driver.name = drv->name;
+ drv->driver.bus = &pci_bus_type;
+ drv->driver.probe = pci_device_probe;
+ drv->driver.resume = pci_device_resume;
+ drv->driver.suspend = pci_device_suspend;
+ drv->driver.remove = pci_device_remove;
+
+ /* register with core */
+ count = driver_register(&drv->driver);
- list_add_tail(&drv->node, &pci_drivers);
pci_for_each_dev(dev) {
if (!pci_dev_driver(dev))
- count += pci_announce_device(drv, dev);
+ pci_announce_device(drv, dev);
}
- return count;
+ return count ? count : 1;
}
/**
void
pci_unregister_driver(struct pci_driver *drv)
{
- struct pci_dev *dev;
-
- list_del(&drv->node);
- pci_for_each_dev(dev) {
- if (dev->driver == drv) {
- if (drv->remove)
- drv->remove(dev);
- dev->driver = NULL;
- }
+ list_t * node;
+
+ node = drv->driver.devices.next;
+
+ while (node != &drv->driver.devices) {
+ struct device * dev = list_entry(node,struct device,driver_list);
+ struct pci_dev * pci_dev = list_entry(dev,struct pci_dev,dev);
+
+ if (drv->remove)
+ drv->remove(pci_dev);
+ pci_dev->driver = NULL;
+ dev->driver = NULL;
+ list_del_init(&dev->driver_list);
}
+ put_driver(&drv->driver);
}
static struct pci_driver pci_compat_driver = {
return NULL;
}
-static int pci_device_suspend(struct device * dev, u32 state, u32 level)
-{
- struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
- int error = 0;
-
- if (pci_dev->driver) {
- if (level == SUSPEND_SAVE_STATE && pci_dev->driver->save_state)
- error = pci_dev->driver->save_state(pci_dev,state);
- else if (level == SUSPEND_POWER_DOWN && pci_dev->driver->suspend)
- error = pci_dev->driver->suspend(pci_dev,state);
- }
- return error;
-}
-
-static int pci_device_resume(struct device * dev, u32 level)
-{
- struct pci_dev * pci_dev = (struct pci_dev *)list_entry(dev,struct pci_dev,dev);
-
- if (pci_dev->driver) {
- if (level == RESUME_POWER_ON && pci_dev->driver->resume)
- pci_dev->driver->resume(pci_dev);
- }
- return 0;
-}
-
-struct device_driver pci_device_driver = {
- suspend: pci_device_suspend,
- resume: pci_device_resume,
-};
-
struct bus_type pci_bus_type = {
name: "pci",
};