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.c104
1 files changed, 61 insertions, 43 deletions
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 25d010d449a3..31e99613a12e 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -526,10 +526,37 @@ exit:
526 return count; 526 return count;
527} 527}
528 528
529static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
530 struct device_attribute *attr,
531 char *buf)
532{
533 struct pci_dev *pdev = to_pci_dev(dev);
534
535 return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe);
536}
537
538static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
539 struct device_attribute *attr,
540 const char *buf, size_t count)
541{
542 struct pci_dev *pdev = to_pci_dev(dev);
543 bool drivers_autoprobe;
544
545 if (kstrtobool(buf, &drivers_autoprobe) < 0)
546 return -EINVAL;
547
548 pdev->sriov->drivers_autoprobe = drivers_autoprobe;
549
550 return count;
551}
552
529static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs); 553static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
530static struct device_attribute sriov_numvfs_attr = 554static struct device_attribute sriov_numvfs_attr =
531 __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP), 555 __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
532 sriov_numvfs_show, sriov_numvfs_store); 556 sriov_numvfs_show, sriov_numvfs_store);
557static struct device_attribute sriov_drivers_autoprobe_attr =
558 __ATTR(sriov_drivers_autoprobe, (S_IRUGO|S_IWUSR|S_IWGRP),
559 sriov_drivers_autoprobe_show, sriov_drivers_autoprobe_store);
533#endif /* CONFIG_PCI_IOV */ 560#endif /* CONFIG_PCI_IOV */
534 561
535static ssize_t driver_override_store(struct device *dev, 562static ssize_t driver_override_store(struct device *dev,
@@ -980,20 +1007,24 @@ void pci_remove_legacy_files(struct pci_bus *b)
980} 1007}
981#endif /* HAVE_PCI_LEGACY */ 1008#endif /* HAVE_PCI_LEGACY */
982 1009
983#ifdef HAVE_PCI_MMAP 1010#if defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE)
984 1011
985int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, 1012int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
986 enum pci_mmap_api mmap_api) 1013 enum pci_mmap_api mmap_api)
987{ 1014{
988 unsigned long nr, start, size, pci_start; 1015 unsigned long nr, start, size;
1016 resource_size_t pci_start = 0, pci_end;
989 1017
990 if (pci_resource_len(pdev, resno) == 0) 1018 if (pci_resource_len(pdev, resno) == 0)
991 return 0; 1019 return 0;
992 nr = vma_pages(vma); 1020 nr = vma_pages(vma);
993 start = vma->vm_pgoff; 1021 start = vma->vm_pgoff;
994 size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; 1022 size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
995 pci_start = (mmap_api == PCI_MMAP_PROCFS) ? 1023 if (mmap_api == PCI_MMAP_PROCFS) {
996 pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0; 1024 pci_resource_to_user(pdev, resno, &pdev->resource[resno],
1025 &pci_start, &pci_end);
1026 pci_start >>= PAGE_SHIFT;
1027 }
997 if (start >= pci_start && start < pci_start + size && 1028 if (start >= pci_start && start < pci_start + size &&
998 start + nr <= pci_start + size) 1029 start + nr <= pci_start + size)
999 return 1; 1030 return 1;
@@ -1013,37 +1044,24 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
1013 struct vm_area_struct *vma, int write_combine) 1044 struct vm_area_struct *vma, int write_combine)
1014{ 1045{
1015 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 1046 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
1016 struct resource *res = attr->private; 1047 int bar = (unsigned long)attr->private;
1017 enum pci_mmap_state mmap_type; 1048 enum pci_mmap_state mmap_type;
1018 resource_size_t start, end; 1049 struct resource *res = &pdev->resource[bar];
1019 int i;
1020
1021 for (i = 0; i < PCI_ROM_RESOURCE; i++)
1022 if (res == &pdev->resource[i])
1023 break;
1024 if (i >= PCI_ROM_RESOURCE)
1025 return -ENODEV;
1026 1050
1027 if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start)) 1051 if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
1028 return -EINVAL; 1052 return -EINVAL;
1029 1053
1030 if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) { 1054 if (!pci_mmap_fits(pdev, bar, vma, PCI_MMAP_SYSFS)) {
1031 WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n", 1055 WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
1032 current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff, 1056 current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
1033 pci_name(pdev), i, 1057 pci_name(pdev), bar,
1034 (u64)pci_resource_start(pdev, i), 1058 (u64)pci_resource_start(pdev, bar),
1035 (u64)pci_resource_len(pdev, i)); 1059 (u64)pci_resource_len(pdev, bar));
1036 return -EINVAL; 1060 return -EINVAL;
1037 } 1061 }
1038
1039 /* pci_mmap_page_range() expects the same kind of entry as coming
1040 * from /proc/bus/pci/ which is a "user visible" value. If this is
1041 * different from the resource itself, arch will do necessary fixup.
1042 */
1043 pci_resource_to_user(pdev, i, res, &start, &end);
1044 vma->vm_pgoff += start >> PAGE_SHIFT;
1045 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io; 1062 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
1046 return pci_mmap_page_range(pdev, vma, mmap_type, write_combine); 1063
1064 return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine);
1047} 1065}
1048 1066
1049static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj, 1067static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
@@ -1065,22 +1083,18 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
1065 loff_t off, size_t count, bool write) 1083 loff_t off, size_t count, bool write)
1066{ 1084{
1067 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj)); 1085 struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
1068 struct resource *res = attr->private; 1086 int bar = (unsigned long)attr->private;
1087 struct resource *res;
1069 unsigned long port = off; 1088 unsigned long port = off;
1070 int i;
1071 1089
1072 for (i = 0; i < PCI_ROM_RESOURCE; i++) 1090 res = &pdev->resource[bar];
1073 if (res == &pdev->resource[i])
1074 break;
1075 if (i >= PCI_ROM_RESOURCE)
1076 return -ENODEV;
1077 1091
1078 port += pci_resource_start(pdev, i); 1092 port += pci_resource_start(pdev, bar);
1079 1093
1080 if (port > pci_resource_end(pdev, i)) 1094 if (port > pci_resource_end(pdev, bar))
1081 return 0; 1095 return 0;
1082 1096
1083 if (port + count - 1 > pci_resource_end(pdev, i)) 1097 if (port + count - 1 > pci_resource_end(pdev, bar))
1084 return -EINVAL; 1098 return -EINVAL;
1085 1099
1086 switch (count) { 1100 switch (count) {
@@ -1170,16 +1184,19 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
1170 } else { 1184 } else {
1171 pdev->res_attr[num] = res_attr; 1185 pdev->res_attr[num] = res_attr;
1172 sprintf(res_attr_name, "resource%d", num); 1186 sprintf(res_attr_name, "resource%d", num);
1173 res_attr->mmap = pci_mmap_resource_uc; 1187 if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
1174 } 1188 res_attr->read = pci_read_resource_io;
1175 if (pci_resource_flags(pdev, num) & IORESOURCE_IO) { 1189 res_attr->write = pci_write_resource_io;
1176 res_attr->read = pci_read_resource_io; 1190 if (arch_can_pci_mmap_io())
1177 res_attr->write = pci_write_resource_io; 1191 res_attr->mmap = pci_mmap_resource_uc;
1192 } else {
1193 res_attr->mmap = pci_mmap_resource_uc;
1194 }
1178 } 1195 }
1179 res_attr->attr.name = res_attr_name; 1196 res_attr->attr.name = res_attr_name;
1180 res_attr->attr.mode = S_IRUSR | S_IWUSR; 1197 res_attr->attr.mode = S_IRUSR | S_IWUSR;
1181 res_attr->size = pci_resource_len(pdev, num); 1198 res_attr->size = pci_resource_len(pdev, num);
1182 res_attr->private = &pdev->resource[num]; 1199 res_attr->private = (void *)(unsigned long)num;
1183 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr); 1200 retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
1184 if (retval) 1201 if (retval)
1185 kfree(res_attr); 1202 kfree(res_attr);
@@ -1207,9 +1224,9 @@ static int pci_create_resource_files(struct pci_dev *pdev)
1207 1224
1208 retval = pci_create_attr(pdev, i, 0); 1225 retval = pci_create_attr(pdev, i, 0);
1209 /* for prefetchable resources, create a WC mappable file */ 1226 /* for prefetchable resources, create a WC mappable file */
1210 if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH) 1227 if (!retval && arch_can_pci_mmap_wc() &&
1228 pdev->resource[i].flags & IORESOURCE_PREFETCH)
1211 retval = pci_create_attr(pdev, i, 1); 1229 retval = pci_create_attr(pdev, i, 1);
1212
1213 if (retval) { 1230 if (retval) {
1214 pci_remove_resource_files(pdev); 1231 pci_remove_resource_files(pdev);
1215 return retval; 1232 return retval;
@@ -1549,6 +1566,7 @@ static struct attribute_group pci_dev_hp_attr_group = {
1549static struct attribute *sriov_dev_attrs[] = { 1566static struct attribute *sriov_dev_attrs[] = {
1550 &sriov_totalvfs_attr.attr, 1567 &sriov_totalvfs_attr.attr,
1551 &sriov_numvfs_attr.attr, 1568 &sriov_numvfs_attr.attr,
1569 &sriov_drivers_autoprobe_attr.attr,
1552 NULL, 1570 NULL,
1553}; 1571};
1554 1572