summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorBjorn Helgaas <bhelgaas@google.com>2016-08-01 12:23:44 -0500
committerBjorn Helgaas <bhelgaas@google.com>2016-08-01 12:23:44 -0500
commit3efc7023787f8a6ddc50fa96707614677a568466 (patch)
tree40014e14e68d3b2d66b030ce1f06914ecd6a814e /drivers/pci/pci.c
parenta00c74c1664e6de4ad671c7c921a06ef164622c0 (diff)
parentab2b750cad0276cebbb9f765ca5652bd35dcb7af (diff)
Merge branch 'pci/resource' into next
* pci/resource: unicore32/PCI: Remove pci=firmware command line parameter handling ARM/PCI: Remove arch-specific pcibios_enable_device() ARM64/PCI: Remove arch-specific pcibios_enable_device() MIPS/PCI: Claim bus resources on PCI_PROBE_ONLY set-ups ARM/PCI: Claim bus resources on PCI_PROBE_ONLY set-ups PCI: generic: Claim bus resources on PCI_PROBE_ONLY set-ups PCI: Add generic pci_bus_claim_resources() alx: Use pci_(request|release)_mem_regions ethernet/intel: Use pci_(request|release)_mem_regions GenWQE: Use pci_(request|release)_mem_regions lpfc: Use pci_(request|release)_mem_regions NVMe: Use pci_(request|release)_mem_regions PCI: Add helpers to request/release memory and I/O regions PCI: Extending pci=resource_alignment to specify device/vendor IDs sparc/PCI: Implement pci_resource_to_user() with pcibios_resource_to_bus() powerpc/pci: Implement pci_resource_to_user() with pcibios_resource_to_bus() microblaze/PCI: Implement pci_resource_to_user() with pcibios_resource_to_bus() PCI: Unify pci_resource_to_user() declarations microblaze/PCI: Remove useless __pci_mmap_set_pgprot() powerpc/pci: Remove __pci_mmap_set_pgprot() PCI: Ignore write combining when mapping I/O port space
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r--drivers/pci/pci.c66
1 files changed, 47 insertions, 19 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 14d24b4fc508..9a6bc77ce3aa 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4953,6 +4953,7 @@ static DEFINE_SPINLOCK(resource_alignment_lock);
static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
{
int seg, bus, slot, func, align_order, count;
+ unsigned short vendor, device, subsystem_vendor, subsystem_device;
resource_size_t align = 0;
char *p;
@@ -4966,28 +4967,55 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
} else {
align_order = -1;
}
- if (sscanf(p, "%x:%x:%x.%x%n",
- &seg, &bus, &slot, &func, &count) != 4) {
- seg = 0;
- if (sscanf(p, "%x:%x.%x%n",
- &bus, &slot, &func, &count) != 3) {
- /* Invalid format */
- printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n",
- p);
+ if (strncmp(p, "pci:", 4) == 0) {
+ /* PCI vendor/device (subvendor/subdevice) ids are specified */
+ p += 4;
+ if (sscanf(p, "%hx:%hx:%hx:%hx%n",
+ &vendor, &device, &subsystem_vendor, &subsystem_device, &count) != 4) {
+ if (sscanf(p, "%hx:%hx%n", &vendor, &device, &count) != 2) {
+ printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: pci:%s\n",
+ p);
+ break;
+ }
+ subsystem_vendor = subsystem_device = 0;
+ }
+ p += count;
+ if ((!vendor || (vendor == dev->vendor)) &&
+ (!device || (device == dev->device)) &&
+ (!subsystem_vendor || (subsystem_vendor == dev->subsystem_vendor)) &&
+ (!subsystem_device || (subsystem_device == dev->subsystem_device))) {
+ if (align_order == -1)
+ align = PAGE_SIZE;
+ else
+ align = 1 << align_order;
+ /* Found */
break;
}
}
- p += count;
- if (seg == pci_domain_nr(dev->bus) &&
- bus == dev->bus->number &&
- slot == PCI_SLOT(dev->devfn) &&
- func == PCI_FUNC(dev->devfn)) {
- if (align_order == -1)
- align = PAGE_SIZE;
- else
- align = 1 << align_order;
- /* Found */
- break;
+ else {
+ if (sscanf(p, "%x:%x:%x.%x%n",
+ &seg, &bus, &slot, &func, &count) != 4) {
+ seg = 0;
+ if (sscanf(p, "%x:%x.%x%n",
+ &bus, &slot, &func, &count) != 3) {
+ /* Invalid format */
+ printk(KERN_ERR "PCI: Can't parse resource_alignment parameter: %s\n",
+ p);
+ break;
+ }
+ }
+ p += count;
+ if (seg == pci_domain_nr(dev->bus) &&
+ bus == dev->bus->number &&
+ slot == PCI_SLOT(dev->devfn) &&
+ func == PCI_FUNC(dev->devfn)) {
+ if (align_order == -1)
+ align = PAGE_SIZE;
+ else
+ align = 1 << align_order;
+ /* Found */
+ break;
+ }
}
if (*p != ';' && *p != ',') {
/* End of param or invalid format */