diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2016-08-01 19:23:44 +0200 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2016-08-01 19:23:44 +0200 |
commit | 3efc7023787f8a6ddc50fa96707614677a568466 (patch) | |
tree | 40014e14e68d3b2d66b030ce1f06914ecd6a814e /drivers/pci/pci.c | |
parent | Merge branches 'pci/aspm', 'pci/dpc', 'pci/hotplug', 'pci/misc', 'pci/msi', '... (diff) | |
parent | unicore32/PCI: Remove pci=firmware command line parameter handling (diff) | |
download | linux-3efc7023787f8a6ddc50fa96707614677a568466.tar.xz linux-3efc7023787f8a6ddc50fa96707614677a568466.zip |
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.c | 66 |
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 */ |