diff options
author | Prarit Bhargava <prarit@redhat.com> | 2014-10-23 14:22:12 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2014-11-06 17:10:06 -0500 |
commit | 63692df103e9c76b26c382ce8079283b7df9a99a (patch) | |
tree | 677204f229cd7ad3dcf072d8d7eb44ce01018e9e /drivers/pci/pci-sysfs.c | |
parent | f114040e3ea6e07372334ade75d1ee0775c355e1 (diff) |
PCI: Allow numa_node override via sysfs
NUMA systems with ACPI normally describe the physical topology via _PXM
methods. But many BIOSes don't implement _PXM, which leaves the kernel
with no way to discover the device topology, which reduces performance
because we can't put memory and processes close to the device.
The NUMA node of a PCI device is already exported in the sysfs "numa_node"
file. Make that file writable so users can workaround the lack of _PXM
methods in the BIOS. For example:
echo 3 > /sys/devices/pci0000:ff/0000:03:1f.3/numa_node
sets the node for PCI device 0000:03:1f.3.
Writing the file emits a FW_BUG warning to encourage users to request
firmware updates. It also taints the kernel with TAINT_FIRMWARE_WORKAROUND
because overriding the node incorrectly can cause performance issues.
[bhelgaas: changelog, documentation text]
Signed-off-by: Prarit Bhargava <prarit@redhat.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
CC: Myron Stowe <mstowe@redhat.com>
CC: Alexander Ducyk <alexander.h.duyck@redhat.com>
CC: Jiang Liu <jiang.liu@linux.intel.com>
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
-rw-r--r-- | drivers/pci/pci-sysfs.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 92b6d9ab00e4..91e760f9655b 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c | |||
@@ -221,12 +221,37 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, | |||
221 | static DEVICE_ATTR_RW(enabled); | 221 | static DEVICE_ATTR_RW(enabled); |
222 | 222 | ||
223 | #ifdef CONFIG_NUMA | 223 | #ifdef CONFIG_NUMA |
224 | static ssize_t numa_node_store(struct device *dev, | ||
225 | struct device_attribute *attr, const char *buf, | ||
226 | size_t count) | ||
227 | { | ||
228 | struct pci_dev *pdev = to_pci_dev(dev); | ||
229 | int node, ret; | ||
230 | |||
231 | if (!capable(CAP_SYS_ADMIN)) | ||
232 | return -EPERM; | ||
233 | |||
234 | ret = kstrtoint(buf, 0, &node); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | |||
238 | if (!node_online(node)) | ||
239 | return -EINVAL; | ||
240 | |||
241 | add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); | ||
242 | dev_alert(&pdev->dev, FW_BUG "Overriding NUMA node to %d. Contact your vendor for updates.", | ||
243 | node); | ||
244 | |||
245 | dev->numa_node = node; | ||
246 | return count; | ||
247 | } | ||
248 | |||
224 | static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, | 249 | static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, |
225 | char *buf) | 250 | char *buf) |
226 | { | 251 | { |
227 | return sprintf(buf, "%d\n", dev->numa_node); | 252 | return sprintf(buf, "%d\n", dev->numa_node); |
228 | } | 253 | } |
229 | static DEVICE_ATTR_RO(numa_node); | 254 | static DEVICE_ATTR_RW(numa_node); |
230 | #endif | 255 | #endif |
231 | 256 | ||
232 | static ssize_t dma_mask_bits_show(struct device *dev, | 257 | static ssize_t dma_mask_bits_show(struct device *dev, |