Commit 346fced8 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6

parents 17af691c 43a6b760
...@@ -190,7 +190,7 @@ static __init struct pci_dev *gx_detect_chipset(void) ...@@ -190,7 +190,7 @@ static __init struct pci_dev *gx_detect_chipset(void)
/* detect which companion chip is used */ /* detect which companion chip is used */
while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) { while ((gx_pci = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, gx_pci)) != NULL) {
if ((pci_match_device (gx_chipset_tbl, gx_pci)) != NULL) { if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) {
return gx_pci; return gx_pci;
} }
} }
......
...@@ -165,6 +165,7 @@ static int __init pcibios_init(void) ...@@ -165,6 +165,7 @@ static int __init pcibios_init(void)
if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
pcibios_sort(); pcibios_sort();
#endif #endif
pci_assign_unassigned_resources();
return 0; return 0;
} }
......
...@@ -106,11 +106,16 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) ...@@ -106,11 +106,16 @@ static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
if ((dev = bus->self)) { if ((dev = bus->self)) {
for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
r = &dev->resource[idx]; r = &dev->resource[idx];
if (!r->start) if (!r->flags)
continue; continue;
pr = pci_find_parent_resource(dev, r); pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) if (!r->start || !pr || request_resource(pr, r) < 0) {
printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev)); printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
/* Something is wrong with the region.
Invalidate the resource to prevent child
resource allocations in this range. */
r->flags = 0;
}
} }
} }
pcibios_allocate_bus_resources(&bus->children); pcibios_allocate_bus_resources(&bus->children);
...@@ -227,7 +232,7 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask) ...@@ -227,7 +232,7 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
pci_read_config_word(dev, PCI_COMMAND, &cmd); pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd; old_cmd = cmd;
for(idx=0; idx<6; idx++) { for(idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
/* Only set up the requested stuff */ /* Only set up the requested stuff */
if (!(mask & (1<<idx))) if (!(mask & (1<<idx)))
continue; continue;
......
...@@ -579,7 +579,7 @@ static int __init rng_init (void) ...@@ -579,7 +579,7 @@ static int __init rng_init (void)
/* Probe for Intel, AMD RNGs */ /* Probe for Intel, AMD RNGs */
for_each_pci_dev(pdev) { for_each_pci_dev(pdev) {
ent = pci_match_device (rng_pci_tbl, pdev); ent = pci_match_id(rng_pci_tbl, pdev);
if (ent) { if (ent) {
rng_ops = &rng_vendor_ops[ent->driver_data]; rng_ops = &rng_vendor_ops[ent->driver_data];
goto match; goto match;
......
...@@ -401,7 +401,7 @@ static unsigned char __init i8xx_tco_getdevice (void) ...@@ -401,7 +401,7 @@ static unsigned char __init i8xx_tco_getdevice (void)
*/ */
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
if (pci_match_device(i8xx_tco_pci_tbl, dev)) { if (pci_match_id(i8xx_tco_pci_tbl, dev)) {
i8xx_tco_pci = dev; i8xx_tco_pci = dev;
break; break;
} }
......
...@@ -847,7 +847,7 @@ static int __init ide_scan_pcidev(struct pci_dev *dev) ...@@ -847,7 +847,7 @@ static int __init ide_scan_pcidev(struct pci_dev *dev)
d = list_entry(l, struct pci_driver, node); d = list_entry(l, struct pci_driver, node);
if(d->id_table) if(d->id_table)
{ {
const struct pci_device_id *id = pci_match_device(d->id_table, dev); const struct pci_device_id *id = pci_match_id(d->id_table, dev);
if(id != NULL) if(id != NULL)
{ {
if(d->probe(dev, id) >= 0) if(d->probe(dev, id) >= 0)
......
...@@ -3008,7 +3008,7 @@ static int __init parport_pc_init_superio (int autoirq, int autodma) ...@@ -3008,7 +3008,7 @@ static int __init parport_pc_init_superio (int autoirq, int autodma)
int ret = 0; int ret = 0;
while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) {
id = pci_match_device (parport_pc_pci_tbl, pdev); id = pci_match_id(parport_pc_pci_tbl, pdev);
if (id == NULL || id->driver_data >= last_sio) if (id == NULL || id->driver_data >= last_sio)
continue; continue;
......
...@@ -19,6 +19,7 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/ ...@@ -19,6 +19,7 @@ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
# #
# Some architectures use the generic PCI setup functions # Some architectures use the generic PCI setup functions
# #
obj-$(CONFIG_X86) += setup-bus.o
obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
obj-$(CONFIG_PARISC) += setup-bus.o obj-$(CONFIG_PARISC) += setup-bus.o
......
...@@ -54,7 +54,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp, ...@@ -54,7 +54,7 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
envp[i++] = scratch; envp[i++] = scratch;
length += scnprintf (scratch, buffer_size - length, length += scnprintf (scratch, buffer_size - length,
"MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n", "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x",
pdev->vendor, pdev->device, pdev->vendor, pdev->device,
pdev->subsystem_vendor, pdev->subsystem_device, pdev->subsystem_vendor, pdev->subsystem_device,
(u8)(pdev->class >> 16), (u8)(pdev->class >> 8), (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pci-dynids.h>
#include "pci.h" #include "pci.h"
/* /*
...@@ -19,35 +18,11 @@ ...@@ -19,35 +18,11 @@
*/ */
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
/**
* pci_device_probe_dynamic()
*
* Walk the dynamic ID list looking for a match.
* returns 0 and sets pci_dev->driver when drv claims pci_dev, else error.
*/
static int
pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
{
int error = -ENODEV;
struct list_head *pos;
struct dynid *dynid;
spin_lock(&drv->dynids.lock); struct pci_dynid {
list_for_each(pos, &drv->dynids.list) { struct list_head node;
dynid = list_entry(pos, struct dynid, node); struct pci_device_id id;
if (pci_match_one_device(&dynid->id, pci_dev)) { };
spin_unlock(&drv->dynids.lock);
error = drv->probe(pci_dev, &dynid->id);
if (error >= 0) {
pci_dev->driver = drv;
return 0;
}
return error;
}
}
spin_unlock(&drv->dynids.lock);
return error;
}
/** /**
* store_new_id * store_new_id
...@@ -58,8 +33,7 @@ pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev) ...@@ -58,8 +33,7 @@ pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
static inline ssize_t 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 pci_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;
...@@ -91,37 +65,22 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count) ...@@ -91,37 +65,22 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)
list_add_tail(&pdrv->dynids.list, &dynid->node); list_add_tail(&pdrv->dynids.list, &dynid->node);
spin_unlock(&pdrv->dynids.lock); spin_unlock(&pdrv->dynids.lock);
bus = get_bus(pdrv->driver.bus);
if (bus) {
if (get_driver(&pdrv->driver)) { if (get_driver(&pdrv->driver)) {
down_write(&bus->subsys.rwsem);
driver_attach(&pdrv->driver); driver_attach(&pdrv->driver);
up_write(&bus->subsys.rwsem);
put_driver(&pdrv->driver); put_driver(&pdrv->driver);
} }
put_bus(bus);
}
return count; return count;
} }
static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id); static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);
static inline void
pci_init_dynids(struct pci_dynids *dynids)
{
spin_lock_init(&dynids->lock);
INIT_LIST_HEAD(&dynids->list);
}
static void static void
pci_free_dynids(struct pci_driver *drv) pci_free_dynids(struct pci_driver *drv)
{ {
struct list_head *pos, *n; struct pci_dynid *dynid, *n;
struct dynid *dynid;
spin_lock(&drv->dynids.lock); spin_lock(&drv->dynids.lock);
list_for_each_safe(pos, n, &drv->dynids.list) { list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
dynid = list_entry(pos, struct dynid, node);
list_del(&dynid->node); list_del(&dynid->node);
kfree(dynid); kfree(dynid);
} }
...@@ -138,83 +97,70 @@ pci_create_newid_file(struct pci_driver *drv) ...@@ -138,83 +97,70 @@ pci_create_newid_file(struct pci_driver *drv)
return error; return error;
} }
static int
pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
{
struct list_head *pos;
struct dynid *dynid;
spin_lock(&pci_drv->dynids.lock);
list_for_each(pos, &pci_drv->dynids.list) {
dynid = list_entry(pos, struct dynid, node);
if (pci_match_one_device(&dynid->id, pci_dev)) {
spin_unlock(&pci_drv->dynids.lock);
return 1;
}
}
spin_unlock(&pci_drv->dynids.lock);
return 0;
}
#else /* !CONFIG_HOTPLUG */ #else /* !CONFIG_HOTPLUG */
static inline int pci_device_probe_dynamic(struct pci_driver *drv, struct pci_dev *pci_dev)
{
return -ENODEV;
}
static inline void pci_init_dynids(struct pci_dynids *dynids) {}
static inline void pci_free_dynids(struct pci_driver *drv) {} static inline void pci_free_dynids(struct pci_driver *drv) {}
static inline int pci_create_newid_file(struct pci_driver *drv) static inline int pci_create_newid_file(struct pci_driver *drv)
{ {
return 0; return 0;
} }
static inline int pci_bus_match_dynids(const struct pci_dev *pci_dev, struct pci_driver *pci_drv)
{
return 0;
}
#endif #endif
/** /**
* pci_match_device - Tell if a PCI device structure has a matching * pci_match_id - See if a pci device matches a given pci_id table
* 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.
* *
* Used by a driver to check whether a PCI device present in the * Used by a driver to check whether a PCI device present in the
* system is in its list of supported devices.Returns the matching * system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match. * pci_device_id structure or %NULL if there is no match.
*
* Depreciated, don't use this as it will not catch any dynamic ids
* that a driver might want to check for.
*/ */
const struct pci_device_id * const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev) struct pci_dev *dev)
{ {
if (ids) {
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;
} }
/** /**
* pci_device_probe_static() * 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
* @dev: the PCI device structure to match against
* @drv: the PCI driver to match against
* *
* returns 0 and sets pci_dev->driver when drv claims pci_dev, else error. * Used by a driver to check whether a PCI device present in the
* system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/ */
static int const struct pci_device_id *pci_match_device(struct pci_driver *drv,
pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev) struct pci_dev *dev)
{ {
int error = -ENODEV;
const struct pci_device_id *id; const struct pci_device_id *id;
struct pci_dynid *dynid;
if (!drv->id_table) id = pci_match_id(drv->id_table, dev);
return error;
id = pci_match_device(drv->id_table, pci_dev);
if (id) if (id)
error = drv->probe(pci_dev, id); return id;
if (error >= 0) {
pci_dev->driver = drv; /* static ids didn't match, lets look at the dynamic ones */
error = 0; spin_lock(&drv->dynids.lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (pci_match_one_device(&dynid->id, dev)) {
spin_unlock(&drv->dynids.lock);
return &dynid->id;
} }
return error; }
spin_unlock(&drv->dynids.lock);
return NULL;
} }
/** /**
...@@ -226,12 +172,19 @@ pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev) ...@@ -226,12 +172,19 @@ pci_device_probe_static(struct pci_driver *drv, struct pci_dev *pci_dev)
static int static int
__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
{ {
const struct pci_device_id *id;
int error = 0; int error = 0;
if (!pci_dev->driver && drv->probe) { if (!pci_dev->driver && drv->probe) {
error = pci_device_probe_static(drv, pci_dev); error = -ENODEV;
if (error == -ENODEV)
error = pci_device_probe_dynamic(drv, pci_dev); id = pci_match_device(drv, pci_dev);
if (id)
error = drv->probe(pci_dev, id);
if (error >= 0) {
pci_dev->driver = drv;
error = 0;
}
} }
return error; return error;
} }
...@@ -371,12 +324,6 @@ static struct kobj_type pci_driver_kobj_type = { ...@@ -371,12 +324,6 @@ static struct kobj_type pci_driver_kobj_type = {
.sysfs_ops = &pci_driver_sysfs_ops, .sysfs_ops = &pci_driver_sysfs_ops,
}; };
static int
pci_populate_driver_dir(struct pci_driver *drv)
{
return pci_create_newid_file(drv);
}
/** /**
* pci_register_driver - register a new pci driver * pci_register_driver - register a new pci driver
* @drv: the driver structure to register * @drv: the driver structure to register
...@@ -401,13 +348,15 @@ int pci_register_driver(struct pci_driver *drv) ...@@ -401,13 +348,15 @@ int pci_register_driver(struct pci_driver *drv)
drv->driver.shutdown = pci_device_shutdown; drv->driver.shutdown = pci_device_shutdown;
drv->driver.owner = drv->owner; drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type; drv->driver.kobj.ktype = &pci_driver_kobj_type;
pci_init_dynids(&drv->dynids);
spin_lock_init(&drv->dynids.lock);
INIT_LIST_HEAD(&drv->dynids.list);
/* register with core */ /* register with core */
error = driver_register(&drv->driver); error = driver_register(&drv->driver);
if (!error) if (!error)
pci_populate_driver_dir(drv); error = pci_create_newid_file(drv);
return error; return error;
} }
...@@ -463,21 +412,17 @@ pci_dev_driver(const struct pci_dev *dev) ...@@ -463,21 +412,17 @@ pci_dev_driver(const struct pci_dev *dev)
* system is in its list of supported devices.Returns the matching * system is in its list of supported devices.Returns the matching
* pci_device_id structure or %NULL if there is no match. * pci_device_id structure or %NULL if there is no match.
*/ */
static int pci_bus_match(struct device * dev, struct device_driver * drv) static int pci_bus_match(struct device *dev, struct device_driver *drv)
{ {
const struct pci_dev * pci_dev = to_pci_dev(dev); struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver * pci_drv = to_pci_driver(drv); struct pci_driver *pci_drv = to_pci_driver(drv);
const struct pci_device_id * ids = pci_drv->id_table;
const struct pci_device_id *found_id; const struct pci_device_id *found_id;
if (!ids) found_id = pci_match_device(pci_drv, pci_dev);
return 0;
found_id = pci_match_device(ids, pci_dev);
if (found_id) if (found_id)
return 1; return 1;
return pci_bus_match_dynids(pci_dev, pci_drv); return 0;
} }
/** /**
...@@ -536,6 +481,7 @@ static int __init pci_driver_init(void) ...@@ -536,6 +481,7 @@ static int __init pci_driver_init(void)
postcore_initcall(pci_driver_init); postcore_initcall(pci_driver_init);
EXPORT_SYMBOL(pci_match_id);
EXPORT_SYMBOL(pci_match_device); EXPORT_SYMBOL(pci_match_device);
EXPORT_SYMBOL(pci_register_driver); EXPORT_SYMBOL(pci_register_driver);
EXPORT_SYMBOL(pci_unregister_driver); EXPORT_SYMBOL(pci_unregister_driver);
......
...@@ -334,10 +334,6 @@ EXPORT_SYMBOL(pci_choose_state); ...@@ -334,10 +334,6 @@ EXPORT_SYMBOL(pci_choose_state);
/** /**
* pci_save_state - save the PCI configuration space of a device before suspending * pci_save_state - save the PCI configuration space of a device before suspending
* @dev: - PCI device that we're dealing with * @dev: - PCI device that we're dealing with
* @buffer: - buffer to hold config space context
*
* @buffer must be large enough to hold the entire PCI 2.2 config space
* (>= 64 bytes).
*/ */
int int
pci_save_state(struct pci_dev *dev) pci_save_state(struct pci_dev *dev)
...@@ -352,8 +348,6 @@ pci_save_state(struct pci_dev *dev) ...@@ -352,8 +348,6 @@ pci_save_state(struct pci_dev *dev)
/** /**
* pci_restore_state - Restore the saved state of a PCI device * pci_restore_state - Restore the saved state of a PCI device
* @dev: - PCI device that we're dealing with * @dev: - PCI device that we're dealing with
* @buffer: - saved PCI config space
*
*/ */
int int
pci_restore_state(struct pci_dev *dev) pci_restore_state(struct pci_dev *dev)
......
...@@ -27,6 +27,11 @@ ...@@ -27,6 +27,11 @@
#define get_descriptor_id(type, service) (((type - 4) << 4) | service) #define get_descriptor_id(type, service) (((type - 4) << 4) | service)
struct pcie_port_device_ext {
int interrupt_mode; /* [0:INTx | 1:MSI | 2:MSI-X] */
unsigned int saved_msi_config_space[5];
};
extern struct bus_type pcie_port_bus_type; extern struct bus_type pcie_port_bus_type;
extern int pcie_port_device_probe(struct pci_dev *dev); extern int pcie_port_device_probe(struct pci_dev *dev);
extern int pcie_port_device_register(struct pci_dev *dev); extern int pcie_port_device_register(struct pci_dev *dev);
......
...@@ -275,10 +275,17 @@ int pcie_port_device_probe(struct pci_dev *dev) ...@@ -275,10 +275,17 @@ int pcie_port_device_probe(struct pci_dev *dev)
int pcie_port_device_register(struct pci_dev *dev) int pcie_port_device_register(struct pci_dev *dev)
{ {
struct pcie_port_device_ext *p_ext;
int status, type, capabilities, irq_mode, i; int status, type, capabilities, irq_mode, i;
int vectors[PCIE_PORT_DEVICE_MAXSERVICES]; int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
u16 reg16; u16 reg16;
/* Allocate port device extension */
if (!(p_ext = kmalloc(sizeof(struct pcie_port_device_ext), GFP_KERNEL)))
return -ENOMEM;
pci_set_drvdata(dev, p_ext);
/* Get port type */ /* Get port type */
pci_read_config_word(dev, pci_read_config_word(dev,
pci_find_capability(dev, PCI_CAP_ID_EXP) + pci_find_capability(dev, PCI_CAP_ID_EXP) +
...@@ -288,6 +295,7 @@ int pcie_port_device_register(struct pci_dev *dev) ...@@ -288,6 +295,7 @@ int pcie_port_device_register(struct pci_dev *dev)
/* Now get port services */ /* Now get port services */
capabilities = get_port_device_capability(dev); capabilities = get_port_device_capability(dev);
irq_mode = assign_interrupt_mode(dev, vectors, capabilities); irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
p_ext->interrupt_mode = irq_mode;
/* Allocate child services if any */ /* Allocate child services if any */
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) { for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
......
...@@ -29,6 +29,78 @@ MODULE_LICENSE("GPL"); ...@@ -29,6 +29,78 @@ MODULE_LICENSE("GPL");
/* global data */ /* global data */
static const char device_name[] = "pcieport-driver"; static const char device_name[] = "pcieport-driver";
static void pci_save_msi_state(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
int i = 0, pos;
u16 control;
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
return;
pci_read_config_dword(dev, pos, &p_ext->saved_msi_config_space[i++]);
control = p_ext->saved_msi_config_space[0] >> 16;
pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
&p_ext->saved_msi_config_space[i++]);
if (control & PCI_MSI_FLAGS_64BIT) {
pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
&p_ext->saved_msi_config_space[i++]);
pci_read_config_dword(dev, pos + PCI_MSI_DATA_64,
&p_ext->saved_msi_config_space[i++]);
} else
pci_read_config_dword(dev, pos + PCI_MSI_DATA_32,
&p_ext->saved_msi_config_space[i++]);
if (control & PCI_MSI_FLAGS_MASKBIT)
pci_read_config_dword(dev, pos + PCI_MSI_MASK_BIT,
&p_ext->saved_msi_config_space[i++]);
}
static void pci_restore_msi_state(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
int i = 0, pos;
u16 control;
if ((pos = pci_find_capability(dev, PCI_CAP_ID_MSI)) <= 0)
return;
control = p_ext->saved_msi_config_space[i++] >> 16;
pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control);
pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO,
p_ext->saved_msi_config_space[i++]);
if (control & PCI_MSI_FLAGS_64BIT) {
pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
p_ext->saved_msi_config_space[i++]);
pci_write_config_dword(dev, pos + PCI_MSI_DATA_64,
p_ext->saved_msi_config_space[i++]);
} else
pci_write_config_dword(dev, pos + PCI_MSI_DATA_32,
p_ext->saved_msi_config_space[i++]);
if (control & PCI_MSI_FLAGS_MASKBIT)
pci_write_config_dword(dev, pos + PCI_MSI_MASK_BIT,
p_ext->saved_msi_config_space[i++]);
}
static void pcie_portdrv_save_config(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
pci_save_state(dev);
if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
pci_save_msi_state(dev);
}
static void pcie_portdrv_restore_config(struct pci_dev *dev)
{
struct pcie_port_device_ext *p_ext = pci_get_drvdata(dev);
pci_restore_state(dev);
if (p_ext->interrupt_mode == PCIE_PORT_MSI_MODE)
pci_restore_msi_state(dev);
pci_enable_device(dev);
pci_set_master(dev);
}
/* /*
* pcie_portdrv_probe - Probe PCI-Express port devices * pcie_portdrv_probe - Probe PCI-Express port devices
* @dev: PCI-Express port device being probed * @dev: PCI-Express port device being probed
...@@ -64,16 +136,21 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, ...@@ -64,16 +136,21 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
static void pcie_portdrv_remove (struct pci_dev *dev) static void pcie_portdrv_remove (struct pci_dev *dev)
{ {
pcie_port_device_remove(dev); pcie_port_device_remove(dev);
kfree(pci_get_drvdata(dev));
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state) static int pcie_portdrv_suspend (struct pci_dev *dev, pm_message_t state)
{ {
return pcie_port_device_suspend(dev, state); int ret = pcie_port_device_suspend(dev, state);
pcie_portdrv_save_config(dev);
return ret;
} }
static int pcie_portdrv_resume (struct pci_dev *dev) static int pcie_portdrv_resume (struct pci_dev *dev)
{ {
pcie_portdrv_restore_config(dev);
return pcie_port_device_resume(dev); return pcie_port_device_resume(dev);
} }
#endif #endif
......
...@@ -239,9 +239,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -239,9 +239,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (dev->transparent) { if (dev->transparent) {
printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev)); printk(KERN_INFO "PCI: Transparent bridge - %s\n", pci_name(dev));
for(i = 0; i < PCI_BUS_NUM_RESOURCES; i++) for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
child->resource[i] = child->parent->resource[i]; child->resource[i] = child->parent->resource[i - 3];
return;
} }
for(i=0; i<3; i++) for(i=0; i<3; i++)
...@@ -398,6 +397,16 @@ static void pci_enable_crs(struct pci_dev *dev) ...@@ -398,6 +397,16 @@ static void pci_enable_crs(struct pci_dev *dev)
pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl); pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
} }
static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
{
struct pci_bus *parent = child->parent;
while (parent->parent && parent->subordinate < max) {
parent->subordinate = max;
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
parent = parent->parent;
}
}
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
/* /*
...@@ -499,7 +508,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max ...@@ -499,7 +508,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
if (!is_cardbus) { if (!is_cardbus) {
child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA; child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA;
/*
* Adjust subordinate busnr in parent buses.
* We do this before scanning for children because
* some devices may not be detected if the bios
* was lazy.
*/
pci_fixup_parent_subordinate_busnr(child, max);
/* Now we can scan all subordinate buses... */ /* Now we can scan all subordinate buses... */
max = pci_scan_child_bus(child); max = pci_scan_child_bus(child);
} else { } else {
...@@ -513,6 +528,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max ...@@ -513,6 +528,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
max+i+1)) max+i+1))
break; break;
max += i; max += i;
pci_fixup_parent_subordinate_busnr(child, max);
} }
/* /*
* Set the subordinate bus number to its real value. * Set the subordinate bus number to its real value.
......
...@@ -767,6 +767,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev) ...@@ -767,6 +767,7 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) { if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB) if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
switch(dev->subsystem_device) { switch(dev->subsystem_device) {
case 0x8025: /* P4B-LX */
case 0x8070: /* P4B */ case 0x8070: /* P4B */
case 0x8088: /* P4B533 */ case 0x8088: /* P4B533 */
case 0x1626: /* L3C notebook */ case 0x1626: /* L3C notebook */
......
...@@ -273,6 +273,8 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type) ...@@ -273,6 +273,8 @@ find_free_bus_resource(struct pci_bus *bus, unsigned long type)
for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) {
r = bus->resource[i]; r = bus->resource[i];
if (r == &ioport_resource || r == &iomem_resource)
continue;
if (r && (r->flags & type_mask) == type && !r->parent) if (r && (r->flags & type_mask) == type && !r->parent)
return r; return r;
} }
......
/*
* PCI defines and function prototypes
* Copyright 2003 Dell Inc.
* 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
...@@ -586,7 +586,7 @@ struct pci_dev { ...@@ -586,7 +586,7 @@ struct pci_dev {
#define PCI_NUM_RESOURCES 11 #define PCI_NUM_RESOURCES 11
#ifndef PCI_BUS_NUM_RESOURCES #ifndef PCI_BUS_NUM_RESOURCES
#define PCI_BUS_NUM_RESOURCES 4 #define PCI_BUS_NUM_RESOURCES 8
#endif #endif
#define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */ #define PCI_REGION_FLAG_MASK 0x0fU /* These bits of resource flags tell us the PCI region flags */
...@@ -860,7 +860,8 @@ int pci_register_driver(struct pci_driver *); ...@@ -860,7 +860,8 @@ int pci_register_driver(struct pci_driver *);
void pci_unregister_driver(struct pci_driver *); void pci_unregister_driver(struct pci_driver *);
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 *);
const struct pci_device_id *pci_match_device(const struct pci_device_id *ids, const struct pci_dev *dev); const struct pci_device_id *pci_match_device(struct pci_driver *drv, struct pci_dev *dev);
const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, struct pci_dev *dev);
int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass); int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass);
/* kmem_cache style wrapper around pci_alloc_consistent() */ /* kmem_cache style wrapper around pci_alloc_consistent() */
......
...@@ -804,7 +804,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci) ...@@ -804,7 +804,7 @@ static int __devinit snd_bt87x_detect_card(struct pci_dev *pci)
int i; int i;
const struct pci_device_id *supported; const struct pci_device_id *supported;
supported = pci_match_device(snd_bt87x_ids, pci); supported = pci_match_device(driver, pci);
if (supported) if (supported)
return supported->driver_data; return supported->driver_data;
......
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