Skip to content

Commit

Permalink
Merge tag 'pci-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/helgaas/pci

Pull PCI changes from Bjorn Helgaas:
 - Host bridge cleanups from Yinghai
 - Disable Bus Master bit on PCI device shutdown (kexec-related)
 - Stratus ftServer fix
 - pci_dev_reset() locking fix
 - IvyBridge graphics erratum workaround

* tag 'pci-for-3.5' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (21 commits)
  microblaze/PCI: fix "io_offset undeclared" error
  x86/PCI: only check for spinlock being held in SMP kernels
  resources: add resource_overlaps()
  PCI: fix uninitialized variable 'cap_mask'
  MAINTAINERS: update PCI git tree and patchwork
  PCI: disable Bus Master on PCI device shutdown
  PCI: work around IvyBridge internal graphics FLR erratum
  x86/PCI: fix unused variable warning in amd_bus.c
  PCI: move mutex locking out of pci_dev_reset function
  PCI: work around Stratus ftServer broken PCIe hierarchy
  x86/PCI: merge pcibios_scan_root() and pci_scan_bus_on_node()
  x86/PCI: dynamically allocate pci_root_info for native host bridge drivers
  x86/PCI: embed pci_sysdata into pci_root_info on ACPI path
  x86/PCI: embed name into pci_root_info struct
  x86/PCI: add host bridge resource release for _CRS path
  x86/PCI: refactor get_current_resources()
  PCI: add host bridge release support
  PCI: add generic device into pci_host_bridge struct
  PCI: rename pci_host_bridge() to find_pci_root_bridge()
  x86/PCI: fix memleak with get_current_resources()
  ...
  • Loading branch information
torvalds committed May 21, 2012
2 parents 6326c71 + 5420e46 commit 3bb07f1
Show file tree
Hide file tree
Showing 20 changed files with 442 additions and 305 deletions.
3 changes: 3 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2161,6 +2161,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
on: Turn realloc on
realloc same as realloc=on
noari do not use PCIe ARI.
pcie_scan_all Scan all possible PCIe devices. Otherwise we
only look for one device below a PCIe downstream
port.

pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management.
Expand Down
10 changes: 2 additions & 8 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5128,19 +5128,13 @@ F: Documentation/powerpc/eeh-pci-error-recovery.txt
PCI SUBSYSTEM
M: Bjorn Helgaas <[email protected]>
L: [email protected]
Q: http://patchwork.kernel.org/project/linux-pci/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci.git
Q: http://patchwork.ozlabs.org/project/linux-pci/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/linux.git
S: Supported
F: Documentation/PCI/
F: drivers/pci/
F: include/linux/pci*

PCI HOTPLUG
M: Bjorn Helgaas <[email protected]>
L: [email protected]
S: Supported
F: drivers/pci/hotplug

PCMCIA SUBSYSTEM
P: Linux PCMCIA Team
L: [email protected]
Expand Down
1 change: 1 addition & 0 deletions arch/microblaze/pci/pci-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1422,6 +1422,7 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)

static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
{
unsigned long io_offset;
struct resource *res;
int i;

Expand Down
128 changes: 72 additions & 56 deletions arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

struct pci_root_info {
struct acpi_device *bridge;
char *name;
char name[16];
unsigned int res_num;
struct resource *res;
struct list_head *resources;
int busnum;
struct pci_sysdata sd;
};

static bool pci_use_crs = true;
Expand Down Expand Up @@ -245,13 +245,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK;
}

static bool resource_contains(struct resource *res, resource_size_t point)
{
if (res->start <= point && point <= res->end)
return true;
return false;
}

static void coalesce_windows(struct pci_root_info *info, unsigned long type)
{
int i, j;
Expand All @@ -272,10 +265,7 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
* our resources no longer match the ACPI _CRS, but
* the kernel resource tree doesn't allow overlaps.
*/
if (resource_contains(res1, res2->start) ||
resource_contains(res1, res2->end) ||
resource_contains(res2, res1->start) ||
resource_contains(res2, res1->end)) {
if (resource_overlaps(res1, res2)) {
res1->start = min(res1->start, res2->start);
res1->end = max(res1->end, res2->end);
dev_info(&info->bridge->dev,
Expand All @@ -287,7 +277,8 @@ static void coalesce_windows(struct pci_root_info *info, unsigned long type)
}
}

static void add_resources(struct pci_root_info *info)
static void add_resources(struct pci_root_info *info,
struct list_head *resources)
{
int i;
struct resource *res, *root, *conflict;
Expand All @@ -311,53 +302,74 @@ static void add_resources(struct pci_root_info *info)
"ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict);
else
pci_add_resource(info->resources, res);
pci_add_resource(resources, res);
}
}

static void free_pci_root_info_res(struct pci_root_info *info)
{
kfree(info->res);
info->res = NULL;
info->res_num = 0;
}

static void __release_pci_root_info(struct pci_root_info *info)
{
int i;
struct resource *res;

for (i = 0; i < info->res_num; i++) {
res = &info->res[i];

if (!res->parent)
continue;

if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
continue;

release_resource(res);
}

free_pci_root_info_res(info);

kfree(info);
}
static void release_pci_root_info(struct pci_host_bridge *bridge)
{
struct pci_root_info *info = bridge->release_data;

__release_pci_root_info(info);
}

static void
get_current_resources(struct acpi_device *device, int busnum,
int domain, struct list_head *resources)
probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
int busnum, int domain)
{
struct pci_root_info info;
size_t size;

info.bridge = device;
info.res_num = 0;
info.resources = resources;
info->bridge = device;
info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
&info);
if (!info.res_num)
info);
if (!info->res_num)
return;

size = sizeof(*info.res) * info.res_num;
info.res = kmalloc(size, GFP_KERNEL);
if (!info.res)
size = sizeof(*info->res) * info->res_num;
info->res_num = 0;
info->res = kmalloc(size, GFP_KERNEL);
if (!info->res)
return;

info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
if (!info.name)
goto name_alloc_fail;
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);

info.res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
&info);

if (pci_use_crs) {
add_resources(&info);

return;
}

kfree(info.name);

name_alloc_fail:
kfree(info.res);
info);
}

struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
{
struct acpi_device *device = root->device;
struct pci_root_info *info = NULL;
int domain = root->segment;
int busnum = root->secondary.start;
LIST_HEAD(resources);
Expand Down Expand Up @@ -389,17 +401,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
if (node != -1 && !node_online(node))
node = -1;

/* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care.
*/
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
if (!sd) {
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
printk(KERN_WARNING "pci_bus %04x:%02x: "
"ignored (out of memory)\n", domain, busnum);
return NULL;
}

sd = &info->sd;
sd->domain = domain;
sd->node = node;
/*
Expand All @@ -413,22 +422,32 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
* be replaced by sd.
*/
memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd);
kfree(info);
} else {
get_current_resources(device, busnum, domain, &resources);
probe_pci_root_info(info, device, busnum, domain);

/*
* _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS.
*/
if (!pci_use_crs)
if (pci_use_crs)
add_resources(info, &resources);
else {
free_pci_root_info_res(info);
x86_pci_root_bus_resources(busnum, &resources);
}

bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus)
if (bus) {
bus->subordinate = pci_scan_child_bus(bus);
else
pci_set_host_bridge_release(
to_pci_host_bridge(bus->bridge),
release_pci_root_info, info);
} else {
pci_free_resource_list(&resources);
__release_pci_root_info(info);
}
}

/* After the PCI-E bus has been walked and all devices discovered,
Expand All @@ -445,9 +464,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
}
}

if (!bus)
kfree(sd);

if (bus && node != -1) {
#ifdef CONFIG_ACPI_NUMA
if (pxm >= 0)
Expand Down
Loading

0 comments on commit 3bb07f1

Please sign in to comment.