Commit ad6ea5a3 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 13c5afb9 b1440482
...@@ -45,8 +45,6 @@ contains: ...@@ -45,8 +45,6 @@ contains:
id_table Pointer to table of device ID's the driver is id_table Pointer to table of device ID's the driver is
interested in. Most drivers should export this interested in. Most drivers should export this
table using MODULE_DEVICE_TABLE(pci,...). 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 probe Pointer to a probing function which gets called (during
execution of pci_register_driver for already existing execution of pci_register_driver for already existing
devices or later if a new device gets inserted) for all devices or later if a new device gets inserted) for all
...@@ -83,6 +81,28 @@ Each entry consists of: ...@@ -83,6 +81,28 @@ Each entry consists of:
class_mask of the class are honored during the comparison. class_mask of the class are honored during the comparison.
driver_data Data private to the driver. 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 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. automatically calls the remove hook for all devices handled by the driver.
......
...@@ -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;
......
...@@ -92,7 +92,7 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus) ...@@ -92,7 +92,7 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
if (!list_empty(&dev->global_list)) if (!list_empty(&dev->global_list))
continue; continue;
device_register(&dev->dev); device_add(&dev->dev);
list_add_tail(&dev->global_list, &pci_devices); list_add_tail(&dev->global_list, &pci_devices);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
pci_proc_attach_device(dev); pci_proc_attach_device(dev);
......
...@@ -207,26 +207,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -207,26 +207,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
#endif /* CONFIG_HOTPLUG */ #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 static void
pci_free_resources(struct pci_dev *dev) pci_free_resources(struct pci_dev *dev)
{ {
...@@ -275,7 +255,7 @@ void pci_remove_bus_device(struct pci_dev *dev) ...@@ -275,7 +255,7 @@ void pci_remove_bus_device(struct pci_dev *dev)
pci_proc_detach_device(dev); pci_proc_detach_device(dev);
#endif #endif
kfree(dev); pci_put_dev(dev);
} }
/** /**
...@@ -300,7 +280,6 @@ void pci_remove_behind_bridge(struct pci_dev *dev) ...@@ -300,7 +280,6 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
} }
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_insert_device);
EXPORT_SYMBOL(pci_remove_bus_device); EXPORT_SYMBOL(pci_remove_bus_device);
EXPORT_SYMBOL(pci_remove_behind_bridge); EXPORT_SYMBOL(pci_remove_behind_bridge);
#endif #endif
This diff is collapsed.
...@@ -462,6 +462,21 @@ int pci_setup_device(struct pci_dev * dev) ...@@ -462,6 +462,21 @@ int pci_setup_device(struct pci_dev * dev)
return 0; 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 * Read the config data for a PCI device, sanity-check it
* and fill in the dev structure... * and fill in the dev structure...
...@@ -506,6 +521,9 @@ pci_scan_device(struct pci_bus *bus, int devfn) ...@@ -506,6 +521,9 @@ pci_scan_device(struct pci_bus *bus, int devfn)
kfree(dev); kfree(dev);
return NULL; return NULL;
} }
device_initialize(&dev->dev);
dev->dev.release = pci_release_dev;
pci_get_dev(dev);
pci_name_device(dev); pci_name_device(dev);
......
...@@ -319,6 +319,7 @@ extern void device_del(struct device * dev); ...@@ -319,6 +319,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 */
......
/*
* 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/list.h>
#include <linux/mod_devicetable.h>
struct dynid {
struct list_head node;
struct pci_device_id id;
};
#endif
...@@ -490,10 +490,16 @@ struct pci_bus_region { ...@@ -490,10 +490,16 @@ struct pci_bus_region {
unsigned long end; 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 pci_driver {
struct list_head node; struct list_head node;
char *name; 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 */ 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) */ 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 */ int (*save_state) (struct pci_dev *dev, u32 state); /* Save Device Context */
...@@ -502,6 +508,7 @@ struct pci_driver { ...@@ -502,6 +508,7 @@ struct pci_driver {
int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */ int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */
struct device_driver driver; struct device_driver driver;
struct pci_dynids dynids;
}; };
#define to_pci_driver(drv) container_of(drv,struct pci_driver, driver) #define to_pci_driver(drv) container_of(drv,struct pci_driver, driver)
...@@ -556,6 +563,8 @@ void pci_read_bridge_bases(struct pci_bus *child); ...@@ -556,6 +563,8 @@ void pci_read_bridge_bases(struct pci_bus *child);
struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res); struct resource *pci_find_parent_resource(const struct pci_dev *dev, struct resource *res);
int pci_setup_device(struct pci_dev *dev); int pci_setup_device(struct pci_dev *dev);
int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge); 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 */ /* Generic PCI functions exported to card drivers */
...@@ -651,7 +660,6 @@ void pci_enable_bridges(struct pci_bus *bus); ...@@ -651,7 +660,6 @@ void pci_enable_bridges(struct pci_bus *bus);
/* New-style probing supporting hot-pluggable devices */ /* New-style probing supporting hot-pluggable devices */
int pci_register_driver(struct pci_driver *); int pci_register_driver(struct pci_driver *);
void pci_unregister_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_bus_device(struct pci_dev *);
void pci_remove_behind_bridge(struct pci_dev *); void pci_remove_behind_bridge(struct pci_dev *);
struct pci_driver *pci_dev_driver(const struct pci_dev *); struct pci_driver *pci_dev_driver(const struct pci_dev *);
...@@ -702,6 +710,12 @@ extern int pci_visit_dev(struct pci_visit *fn, ...@@ -702,6 +710,12 @@ extern int pci_visit_dev(struct pci_visit *fn,
struct pci_bus_wrapped *wrapped_parent); struct pci_bus_wrapped *wrapped_parent);
extern int pci_remove_device_safe(struct pci_dev *dev); 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 */ #endif /* CONFIG_PCI */
/* Include architecture-dependent settings and functions */ /* Include architecture-dependent settings and functions */
...@@ -750,6 +764,7 @@ static inline void pci_unregister_driver(struct pci_driver *drv) { } ...@@ -750,6 +764,7 @@ static inline void pci_unregister_driver(struct pci_driver *drv) { }
static inline int scsi_to_pci_dma_dir(unsigned char scsi_dir) { return scsi_dir; } 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 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 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 */ /* Power management related routines */
static inline int pci_save_state(struct pci_dev *dev, u32 *buffer) { return 0; } static inline int pci_save_state(struct pci_dev *dev, u32 *buffer) { return 0; }
......
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