diff options
author | Yuji Shimada <shimada-yxb@necst.nec.co.jp> | 2009-03-16 04:13:39 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-03-20 13:48:15 -0400 |
commit | 32a9a682bef2f6fce7026bd94d1ce20028b0e52d (patch) | |
tree | a93225b3039585e8364ae3d411b22f63eebc8d70 /drivers/pci/quirks.c | |
parent | 1c8d7b0a562da06d3ebe83f01b1ed553205d1ae4 (diff) |
PCI: allow assignment of memory resources with a specified alignment
This patch allows memory resources to be assigned with a specified
alignment at boot-time or run-time. The patch is useful when we use PCI
pass-through, because page-aligned memory resources are required to
securely share PCI resources with guest drivers.
If you want to assign the resource at boot time, please set
"pci=resource_alignment=" boot parameter.
This is format of "pci=resource_alignment=" boot parameter:
[<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
Specifies alignment and device to reassign
aligned memory resources.
If <order of align> is not specified, PAGE_SIZE is
used as alignment.
PCI-PCI bridge can be specified, if resource
windows need to be expanded.
This is example:
pci=resource_alignment=20@07:00.0;18@0f:00.0;00:1d.7
If you want to assign the resource at run-time, please set
"/sys/bus/pci/resource_alignment" file, and hot-remove the device and
hot-add the device. For this purpose, fakephp or PCI hotplug interfaces
can be used.
The format of "/sys/bus/pci/resource_alignment" file is the same with
boot parameter. You can use "," instead of ";".
For example:
# cd /sys/bus/pci
# echo -n 20@12:00.0 > resource_alignment
# echo 1 > devices/0000:12:00.0/remove
# echo 1 > rescan
Reviewed-by: Alex Chiang <achiang@hp.com>
Reviewed-by: Yu Zhao <yu.zhao@intel.com>
Signed-off-by: Yuji Shimada <shimada-yxb@necst.nec.co.jp>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/quirks.c')
-rw-r--r-- | drivers/pci/quirks.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 5aa2afb23ef9..50233818a763 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/kallsyms.h> | 24 | #include <linux/kallsyms.h> |
25 | #include <linux/dmi.h> | 25 | #include <linux/dmi.h> |
26 | #include <linux/pci-aspm.h> | 26 | #include <linux/pci-aspm.h> |
27 | #include <linux/ioport.h> | ||
27 | #include "pci.h" | 28 | #include "pci.h" |
28 | 29 | ||
29 | int isa_dma_bridge_buggy; | 30 | int isa_dma_bridge_buggy; |
@@ -34,6 +35,65 @@ int pcie_mch_quirk; | |||
34 | EXPORT_SYMBOL(pcie_mch_quirk); | 35 | EXPORT_SYMBOL(pcie_mch_quirk); |
35 | 36 | ||
36 | #ifdef CONFIG_PCI_QUIRKS | 37 | #ifdef CONFIG_PCI_QUIRKS |
38 | /* | ||
39 | * This quirk function disables the device and releases resources | ||
40 | * which is specified by kernel's boot parameter 'pci=resource_alignment='. | ||
41 | * It also rounds up size to specified alignment. | ||
42 | * Later on, the kernel will assign page-aligned memory resource back | ||
43 | * to that device. | ||
44 | */ | ||
45 | static void __devinit quirk_resource_alignment(struct pci_dev *dev) | ||
46 | { | ||
47 | int i; | ||
48 | struct resource *r; | ||
49 | resource_size_t align, size; | ||
50 | |||
51 | if (!pci_is_reassigndev(dev)) | ||
52 | return; | ||
53 | |||
54 | if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL && | ||
55 | (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) { | ||
56 | dev_warn(&dev->dev, | ||
57 | "Can't reassign resources to host bridge.\n"); | ||
58 | return; | ||
59 | } | ||
60 | |||
61 | dev_info(&dev->dev, "Disabling device and release resources.\n"); | ||
62 | pci_disable_device(dev); | ||
63 | |||
64 | align = pci_specified_resource_alignment(dev); | ||
65 | for (i=0; i < PCI_BRIDGE_RESOURCES; i++) { | ||
66 | r = &dev->resource[i]; | ||
67 | if (!(r->flags & IORESOURCE_MEM)) | ||
68 | continue; | ||
69 | size = resource_size(r); | ||
70 | if (size < align) { | ||
71 | size = align; | ||
72 | dev_info(&dev->dev, | ||
73 | "Rounding up size of resource #%d to %#llx.\n", | ||
74 | i, (unsigned long long)size); | ||
75 | } | ||
76 | r->end = size - 1; | ||
77 | r->start = 0; | ||
78 | } | ||
79 | /* Need to disable bridge's resource window, | ||
80 | * to enable the kernel to reassign new resource | ||
81 | * window later on. | ||
82 | */ | ||
83 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && | ||
84 | (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { | ||
85 | for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) { | ||
86 | r = &dev->resource[i]; | ||
87 | if (!(r->flags & IORESOURCE_MEM)) | ||
88 | continue; | ||
89 | r->end = resource_size(r) - 1; | ||
90 | r->start = 0; | ||
91 | } | ||
92 | pci_disable_bridge_window(dev); | ||
93 | } | ||
94 | } | ||
95 | DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment); | ||
96 | |||
37 | /* The Mellanox Tavor device gives false positive parity errors | 97 | /* The Mellanox Tavor device gives false positive parity errors |
38 | * Mark this device with a broken_parity_status, to allow | 98 | * Mark this device with a broken_parity_status, to allow |
39 | * PCI scanning code to "skip" this now blacklisted device. | 99 | * PCI scanning code to "skip" this now blacklisted device. |