aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-sysfs.c')
-rw-r--r--drivers/pci/pci-sysfs.c94
1 files changed, 84 insertions, 10 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index b5a7d9bfcb24..7bcf12adced7 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -23,6 +23,7 @@
23#include <linux/mm.h> 23#include <linux/mm.h>
24#include <linux/fs.h> 24#include <linux/fs.h>
25#include <linux/capability.h> 25#include <linux/capability.h>
26#include <linux/security.h>
26#include <linux/pci-aspm.h> 27#include <linux/pci-aspm.h>
27#include <linux/slab.h> 28#include <linux/slab.h>
28#include "pci.h" 29#include "pci.h"
@@ -107,6 +108,40 @@ static ssize_t local_cpulist_show(struct device *dev,
107 return len; 108 return len;
108} 109}
109 110
111/*
112 * PCI Bus Class Devices
113 */
114static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
115 int type,
116 struct device_attribute *attr,
117 char *buf)
118{
119 int ret;
120 const struct cpumask *cpumask;
121
122 cpumask = cpumask_of_pcibus(to_pci_bus(dev));
123 ret = type ?
124 cpulist_scnprintf(buf, PAGE_SIZE-2, cpumask) :
125 cpumask_scnprintf(buf, PAGE_SIZE-2, cpumask);
126 buf[ret++] = '\n';
127 buf[ret] = '\0';
128 return ret;
129}
130
131static inline ssize_t pci_bus_show_cpumaskaffinity(struct device *dev,
132 struct device_attribute *attr,
133 char *buf)
134{
135 return pci_bus_show_cpuaffinity(dev, 0, attr, buf);
136}
137
138static inline ssize_t pci_bus_show_cpulistaffinity(struct device *dev,
139 struct device_attribute *attr,
140 char *buf)
141{
142 return pci_bus_show_cpuaffinity(dev, 1, attr, buf);
143}
144
110/* show resources */ 145/* show resources */
111static ssize_t 146static ssize_t
112resource_show(struct device * dev, struct device_attribute *attr, char * buf) 147resource_show(struct device * dev, struct device_attribute *attr, char * buf)
@@ -317,6 +352,25 @@ remove_store(struct device *dev, struct device_attribute *dummy,
317 count = ret; 352 count = ret;
318 return count; 353 return count;
319} 354}
355
356static ssize_t
357dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
358 const char *buf, size_t count)
359{
360 unsigned long val;
361 struct pci_bus *bus = to_pci_bus(dev);
362
363 if (strict_strtoul(buf, 0, &val) < 0)
364 return -EINVAL;
365
366 if (val) {
367 mutex_lock(&pci_remove_rescan_mutex);
368 pci_rescan_bus(bus);
369 mutex_unlock(&pci_remove_rescan_mutex);
370 }
371 return count;
372}
373
320#endif 374#endif
321 375
322struct device_attribute pci_dev_attrs[] = { 376struct device_attribute pci_dev_attrs[] = {
@@ -346,6 +400,15 @@ struct device_attribute pci_dev_attrs[] = {
346 __ATTR_NULL, 400 __ATTR_NULL,
347}; 401};
348 402
403struct device_attribute pcibus_dev_attrs[] = {
404#ifdef CONFIG_HOTPLUG
405 __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_bus_rescan_store),
406#endif
407 __ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpumaskaffinity, NULL),
408 __ATTR(cpulistaffinity, S_IRUGO, pci_bus_show_cpulistaffinity, NULL),
409 __ATTR_NULL,
410};
411
349static ssize_t 412static ssize_t
350boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) 413boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
351{ 414{
@@ -368,7 +431,7 @@ pci_read_config(struct file *filp, struct kobject *kobj,
368 u8 *data = (u8*) buf; 431 u8 *data = (u8*) buf;
369 432
370 /* Several chips lock up trying to read undefined config space */ 433 /* Several chips lock up trying to read undefined config space */
371 if (cap_raised(filp->f_cred->cap_effective, CAP_SYS_ADMIN)) { 434 if (security_capable(&init_user_ns, filp->f_cred, CAP_SYS_ADMIN) == 0) {
372 size = dev->cfg_size; 435 size = dev->cfg_size;
373 } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { 436 } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
374 size = 128; 437 size = 128;
@@ -644,7 +707,7 @@ pci_adjust_legacy_attr(struct pci_bus *b, enum pci_mmap_state mmap_type)
644 * a per-bus basis. This routine creates the files and ties them into 707 * a per-bus basis. This routine creates the files and ties them into
645 * their associated read, write and mmap files from pci-sysfs.c 708 * their associated read, write and mmap files from pci-sysfs.c
646 * 709 *
647 * On error unwind, but don't propogate the error to the caller 710 * On error unwind, but don't propagate the error to the caller
648 * as it is ok to set up the PCI bus without these files. 711 * as it is ok to set up the PCI bus without these files.
649 */ 712 */
650void pci_create_legacy_files(struct pci_bus *b) 713void pci_create_legacy_files(struct pci_bus *b)
@@ -705,17 +768,21 @@ void pci_remove_legacy_files(struct pci_bus *b)
705 768
706#ifdef HAVE_PCI_MMAP 769#ifdef HAVE_PCI_MMAP
707 770
708int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma) 771int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
772 enum pci_mmap_api mmap_api)
709{ 773{
710 unsigned long nr, start, size; 774 unsigned long nr, start, size, pci_start;
711 775
776 if (pci_resource_len(pdev, resno) == 0)
777 return 0;
712 nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; 778 nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
713 start = vma->vm_pgoff; 779 start = vma->vm_pgoff;
714 size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; 780 size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
715 if (start < size && size - start >= nr) 781 pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
782 pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
783 if (start >= pci_start && start < pci_start + size &&
784 start + nr <= pci_start + size)
716 return 1; 785 return 1;
717 WARN(1, "process \"%s\" tried to map 0x%08lx-0x%08lx on %s BAR %d (size 0x%08lx)\n",
718 current->comm, start, start+nr, pci_name(pdev), resno, size);
719 return 0; 786 return 0;
720} 787}
721 788
@@ -745,8 +812,15 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
745 if (i >= PCI_ROM_RESOURCE) 812 if (i >= PCI_ROM_RESOURCE)
746 return -ENODEV; 813 return -ENODEV;
747 814
748 if (!pci_mmap_fits(pdev, i, vma)) 815 if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
816 WARN(1, "process \"%s\" tried to map 0x%08lx bytes "
817 "at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
818 current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
819 pci_name(pdev), i,
820 (u64)pci_resource_start(pdev, i),
821 (u64)pci_resource_len(pdev, i));
749 return -EINVAL; 822 return -EINVAL;
823 }
750 824
751 /* pci_mmap_page_range() expects the same kind of entry as coming 825 /* pci_mmap_page_range() expects the same kind of entry as coming
752 * from /proc/bus/pci/ which is a "user visible" value. If this is 826 * from /proc/bus/pci/ which is a "user visible" value. If this is
@@ -1076,7 +1150,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
1076 attr->write = write_vpd_attr; 1150 attr->write = write_vpd_attr;
1077 retval = sysfs_create_bin_file(&dev->dev.kobj, attr); 1151 retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
1078 if (retval) { 1152 if (retval) {
1079 kfree(dev->vpd->attr); 1153 kfree(attr);
1080 return retval; 1154 return retval;
1081 } 1155 }
1082 dev->vpd->attr = attr; 1156 dev->vpd->attr = attr;
@@ -1138,7 +1212,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
1138 sysfs_bin_attr_init(attr); 1212 sysfs_bin_attr_init(attr);
1139 attr->size = rom_size; 1213 attr->size = rom_size;
1140 attr->attr.name = "rom"; 1214 attr->attr.name = "rom";
1141 attr->attr.mode = S_IRUSR; 1215 attr->attr.mode = S_IRUSR | S_IWUSR;
1142 attr->read = pci_read_rom; 1216 attr->read = pci_read_rom;
1143 attr->write = pci_write_rom; 1217 attr->write = pci_write_rom;
1144 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); 1218 retval = sysfs_create_bin_file(&pdev->dev.kobj, attr);