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:
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
......@@ -83,6 +81,28 @@ Each entry consists of:
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.
......
......@@ -316,7 +316,7 @@ static int device_attach(struct device * dev)
* 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;
......
......@@ -92,7 +92,7 @@ void __devinit pci_bus_add_devices(struct pci_bus *bus)
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);
......
......@@ -207,26 +207,6 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
#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)
{
......@@ -275,7 +255,7 @@ void pci_remove_bus_device(struct pci_dev *dev)
pci_proc_detach_device(dev);
#endif
kfree(dev);
pci_put_dev(dev);
}
/**
......@@ -300,7 +280,6 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
}
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_insert_device);
EXPORT_SYMBOL(pci_remove_bus_device);
EXPORT_SYMBOL(pci_remove_behind_bridge);
#endif
This diff is collapsed.
......@@ -462,6 +462,21 @@ int pci_setup_device(struct pci_dev * dev)
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 @@ pci_scan_device(struct pci_bus *bus, int devfn)
kfree(dev);
return NULL;
}
device_initialize(&dev->dev);
dev->dev.release = pci_release_dev;
pci_get_dev(dev);
pci_name_device(dev);
......
......@@ -319,6 +319,7 @@ extern void device_del(struct device * dev);
*/
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 */
......
/*
* 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 {
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;
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 */
......@@ -502,6 +508,7 @@ struct pci_driver {
int (*enable_wake) (struct pci_dev *dev, u32 state, int enable); /* Enable wake event */
struct device_driver driver;
struct pci_dynids dynids;
};
#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);
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 */
......@@ -651,7 +660,6 @@ void pci_enable_bridges(struct pci_bus *bus);
/* 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 *);
......@@ -702,6 +710,12 @@ extern int pci_visit_dev(struct pci_visit *fn,
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 */
......@@ -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 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; }
......
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