summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoehrer Mathias (ETAS/ESW5) <mathias.koehrer@etas.com>2016-06-07 16:24:17 +0200
committerBjorn Helgaas <bhelgaas@google.com>2016-06-22 00:00:34 +0200
commit644a544fd9bcd65f524768b85ab22f62ed08e107 (patch)
tree26ed01e3044c8186b603fd0aae0fbf4d5db03c28
parentsparc/PCI: Implement pci_resource_to_user() with pcibios_resource_to_bus() (diff)
downloadlinux-644a544fd9bcd65f524768b85ab22f62ed08e107.tar.xz
linux-644a544fd9bcd65f524768b85ab22f62ed08e107.zip
PCI: Extending pci=resource_alignment to specify device/vendor IDs
Some uio-based PCI drivers, e.g., uio_cif do not work if the assigned PCI memory resources are not page aligned. By using the kernel option "pci=resource_alignment" it is possible to force single PCI boards to use page alignment for their memory resources. However, this is fairly cumbersome if several of these boards are in use as the specification of the cards has to be done via PCI bus/slot/function number which might change, e.g., by adding another board. Extend the kernel option "pci=resource_alignment" to allow specification of relevant devices via PCI device/vendor (and subdevice/subvendor) IDs. The specification of the devices via device/vendor is indicated by a leading string "pci:" as argument to "pci=resource_alignment". The format of the specification is pci:<vendor>:<device>[:<subvendor>:<subdevice>] Signed-off-by: Mathias Koehrer <mathias.koehrer@etas.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r--Documentation/kernel-parameters.txt2
-rw-r--r--drivers/pci/pci.c66
2 files changed, 49 insertions, 19 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 82b42c958d1c..0618cdd5707e 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2998,6 +2998,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
resource_alignment=
Format:
[<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
+ [<order of align>@]pci:<vendor>:<device>\
+ [:<subvendor>:<subdevice>][; ...]
Specifies alignment and device to reassign
aligned memory resources.
If <order of align> is not specified,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index c8b4dbdd1bdd..78de36f1b012 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4755,6 +4755,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;
@@ -4768,28 +4769,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 */