summaryrefslogtreecommitdiff
path: root/drivers/pci/probe.c
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2008-10-22 23:57:26 -0400
committerLen Brown <len.brown@intel.com>2008-10-23 00:11:07 -0400
commit057316cc6a5b521b332a1d7ccc871cd60c904c74 (patch)
tree4333e608da237c73ff69b10878025cca96dcb4c8 /drivers/pci/probe.c
parent3e2dab9a1c2deb03c311eb3f83466009147ed4d3 (diff)
parent2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (diff)
Merge branch 'linus' into test
Conflicts: MAINTAINERS arch/x86/kernel/acpi/boot.c arch/x86/kernel/acpi/sleep.c drivers/acpi/Kconfig drivers/pnp/Makefile drivers/pnp/quirks.c Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r--drivers/pci/probe.c185
1 files changed, 48 insertions, 137 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 36698e57b97f..aaaf0a1fed22 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -14,8 +14,6 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3
-#define PCI_CFG_SPACE_SIZE 256
-#define PCI_CFG_SPACE_EXP_SIZE 4096
/* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses);
@@ -44,72 +42,6 @@ int no_pci_devices(void)
}
EXPORT_SYMBOL(no_pci_devices);
-#ifdef HAVE_PCI_LEGACY
-/**
- * pci_create_legacy_files - create legacy I/O port and memory files
- * @b: bus to create files under
- *
- * Some platforms allow access to legacy I/O port and ISA memory space on
- * a per-bus basis. This routine creates the files and ties them into
- * their associated read, write and mmap files from pci-sysfs.c
- *
- * On error unwind, but don't propogate the error to the caller
- * as it is ok to set up the PCI bus without these files.
- */
-static void pci_create_legacy_files(struct pci_bus *b)
-{
- int error;
-
- b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
- GFP_ATOMIC);
- if (!b->legacy_io)
- goto kzalloc_err;
-
- b->legacy_io->attr.name = "legacy_io";
- b->legacy_io->size = 0xffff;
- b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
- b->legacy_io->read = pci_read_legacy_io;
- b->legacy_io->write = pci_write_legacy_io;
- error = device_create_bin_file(&b->dev, b->legacy_io);
- if (error)
- goto legacy_io_err;
-
- /* Allocated above after the legacy_io struct */
- b->legacy_mem = b->legacy_io + 1;
- b->legacy_mem->attr.name = "legacy_mem";
- b->legacy_mem->size = 1024*1024;
- b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
- b->legacy_mem->mmap = pci_mmap_legacy_mem;
- error = device_create_bin_file(&b->dev, b->legacy_mem);
- if (error)
- goto legacy_mem_err;
-
- return;
-
-legacy_mem_err:
- device_remove_bin_file(&b->dev, b->legacy_io);
-legacy_io_err:
- kfree(b->legacy_io);
- b->legacy_io = NULL;
-kzalloc_err:
- printk(KERN_WARNING "pci: warning: could not create legacy I/O port "
- "and ISA memory resources to sysfs\n");
- return;
-}
-
-void pci_remove_legacy_files(struct pci_bus *b)
-{
- if (b->legacy_io) {
- device_remove_bin_file(&b->dev, b->legacy_io);
- device_remove_bin_file(&b->dev, b->legacy_mem);
- kfree(b->legacy_io); /* both are allocated here */
- }
-}
-#else /* !HAVE_PCI_LEGACY */
-static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
-void pci_remove_legacy_files(struct pci_bus *bus) { return; }
-#endif /* HAVE_PCI_LEGACY */
-
/*
* PCI Bus Class Devices
*/
@@ -219,7 +151,7 @@ static inline enum pci_bar_type decode_bar(struct resource *res, u32 bar)
res->flags = bar & ~PCI_BASE_ADDRESS_MEM_MASK;
- if (res->flags == PCI_BASE_ADDRESS_MEM_TYPE_64)
+ if (res->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
return pci_bar_mem64;
return pci_bar_mem32;
}
@@ -304,9 +236,8 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
} else {
res->start = l64;
res->end = l64 + sz64;
- printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: [%llx, %llx]\n",
- pci_name(dev), pos, (unsigned long long)res->start,
- (unsigned long long)res->end);
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "reg %x 64bit mmio: %pR\n", pos, res);
}
} else {
sz = pci_size(l, sz, mask);
@@ -316,9 +247,10 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->start = l;
res->end = l + sz;
- printk(KERN_DEBUG "PCI: %s reg %x %s: [%llx, %llx]\n", pci_name(dev),
- pos, (res->flags & IORESOURCE_IO) ? "io port":"32bit mmio",
- (unsigned long long)res->start, (unsigned long long)res->end);
+
+ dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos,
+ (res->flags & IORESOURCE_IO) ? "io port" : "32bit mmio",
+ res);
}
out:
@@ -389,9 +321,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base;
if (!res->end)
res->end = limit + 0xfff;
- printk(KERN_DEBUG "PCI: bridge %s io port: [%llx, %llx]\n",
- pci_name(dev), (unsigned long long) res->start,
- (unsigned long long) res->end);
+ dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res);
}
res = child->resource[1];
@@ -403,9 +333,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base;
res->end = limit + 0xfffff;
- printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: [%llx, %llx]\n",
- pci_name(dev), (unsigned long long) res->start,
- (unsigned long long) res->end);
+ dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n",
+ res);
}
res = child->resource[2];
@@ -441,9 +370,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
res->start = base;
res->end = limit + 0xfffff;
- printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n",
- pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
- (unsigned long long) res->start, (unsigned long long) res->end);
+ dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
+ (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
+ res);
}
}
@@ -764,7 +693,7 @@ static int pci_setup_device(struct pci_dev * dev)
dev->class = class;
class >>= 8;
- dev_dbg(&dev->dev, "found [%04x/%04x] class %06x header type %02x\n",
+ dev_dbg(&dev->dev, "found [%04x:%04x] class %06x header type %02x\n",
dev->vendor, dev->device, class, dev->hdr_type);
/* "Unknown power state" */
@@ -846,6 +775,11 @@ static int pci_setup_device(struct pci_dev * dev)
return 0;
}
+static void pci_release_capabilities(struct pci_dev *dev)
+{
+ pci_vpd_release(dev);
+}
+
/**
* pci_release_dev - free a pci device structure when all users of it are finished.
* @dev: device that's been disconnected
@@ -858,7 +792,7 @@ static void pci_release_dev(struct device *dev)
struct pci_dev *pci_dev;
pci_dev = to_pci_dev(dev);
- pci_vpd_release(pci_dev);
+ pci_release_capabilities(pci_dev);
kfree(pci_dev);
}
@@ -889,8 +823,9 @@ static void set_pcie_port_type(struct pci_dev *pdev)
int pci_cfg_space_size_ext(struct pci_dev *dev)
{
u32 status;
+ int pos = PCI_CFG_SPACE_SIZE;
- if (pci_read_config_dword(dev, 256, &status) != PCIBIOS_SUCCESSFUL)
+ if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
goto fail;
if (status == 0xffffffff)
goto fail;
@@ -938,8 +873,6 @@ struct pci_dev *alloc_pci_dev(void)
INIT_LIST_HEAD(&dev->bus_list);
- pci_msi_init_pci_dev(dev);
-
return dev;
}
EXPORT_SYMBOL(alloc_pci_dev);
@@ -951,6 +884,7 @@ EXPORT_SYMBOL(alloc_pci_dev);
static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{
struct pci_dev *dev;
+ struct pci_slot *slot;
u32 l;
u8 hdr_type;
int delay = 1;
@@ -999,6 +933,10 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
dev->error_state = pci_channel_io_normal;
set_pcie_port_type(dev);
+ list_for_each_entry(slot, &bus->slots, list)
+ if (PCI_SLOT(devfn) == slot->number)
+ dev->slot = slot;
+
/* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer)
set this higher, assuming the system even supports it. */
dev->dma_mask = 0xffffffff;
@@ -1007,9 +945,22 @@ static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
return NULL;
}
+ return dev;
+}
+
+static void pci_init_capabilities(struct pci_dev *dev)
+{
+ /* MSI/MSI-X list */
+ pci_msi_init_pci_dev(dev);
+
+ /* Power Management */
+ pci_pm_init(dev);
+
+ /* Vital Product Data */
pci_vpd_pci22_init(dev);
- return dev;
+ /* Alternative Routing-ID Forwarding */
+ pci_enable_ari(dev);
}
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
@@ -1028,8 +979,8 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
/* Fix up broken headers */
pci_fixup_device(pci_fixup_header, dev);
- /* Initialize power management of the device */
- pci_pm_init(dev);
+ /* Initialize various capabilities */
+ pci_init_capabilities(dev);
/*
* Add the device to our list of discovered devices
@@ -1237,8 +1188,11 @@ EXPORT_SYMBOL(pci_scan_bridge);
EXPORT_SYMBOL_GPL(pci_scan_child_bus);
#endif
-static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev *b)
+static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b)
{
+ const struct pci_dev *a = to_pci_dev(d_a);
+ const struct pci_dev *b = to_pci_dev(d_b);
+
if (pci_domain_nr(a->bus) < pci_domain_nr(b->bus)) return -1;
else if (pci_domain_nr(a->bus) > pci_domain_nr(b->bus)) return 1;
@@ -1251,50 +1205,7 @@ static int __init pci_sort_bf_cmp(const struct pci_dev *a, const struct pci_dev
return 0;
}
-/*
- * Yes, this forcably breaks the klist abstraction temporarily. It
- * just wants to sort the klist, not change reference counts and
- * take/drop locks rapidly in the process. It does all this while
- * holding the lock for the list, so objects can't otherwise be
- * added/removed while we're swizzling.
- */
-static void __init pci_insertion_sort_klist(struct pci_dev *a, struct list_head *list)
-{
- struct list_head *pos;
- struct klist_node *n;
- struct device *dev;
- struct pci_dev *b;
-
- list_for_each(pos, list) {
- n = container_of(pos, struct klist_node, n_node);
- dev = container_of(n, struct device, knode_bus);
- b = to_pci_dev(dev);
- if (pci_sort_bf_cmp(a, b) <= 0) {
- list_move_tail(&a->dev.knode_bus.n_node, &b->dev.knode_bus.n_node);
- return;
- }
- }
- list_move_tail(&a->dev.knode_bus.n_node, list);
-}
-
void __init pci_sort_breadthfirst(void)
{
- LIST_HEAD(sorted_devices);
- struct list_head *pos, *tmp;
- struct klist_node *n;
- struct device *dev;
- struct pci_dev *pdev;
- struct klist *device_klist;
-
- device_klist = bus_get_device_klist(&pci_bus_type);
-
- spin_lock(&device_klist->k_lock);
- list_for_each_safe(pos, tmp, &device_klist->k_list) {
- n = container_of(pos, struct klist_node, n_node);
- dev = container_of(n, struct device, knode_bus);
- pdev = to_pci_dev(dev);
- pci_insertion_sort_klist(pdev, &sorted_devices);
- }
- list_splice(&sorted_devices, &device_klist->k_list);
- spin_unlock(&device_klist->k_lock);
+ bus_sort_breadthfirst(&pci_bus_type, &pci_sort_bf_cmp);
}