aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xen-pciback
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/xen-pciback')
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c118
1 files changed, 64 insertions, 54 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 68dcc59cd287..cd50d251998e 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -142,7 +142,8 @@ static struct pcistub_device *pcistub_device_find(int domain, int bus,
142 if (psdev->dev != NULL 142 if (psdev->dev != NULL
143 && domain == pci_domain_nr(psdev->dev->bus) 143 && domain == pci_domain_nr(psdev->dev->bus)
144 && bus == psdev->dev->bus->number 144 && bus == psdev->dev->bus->number
145 && PCI_DEVFN(slot, func) == psdev->dev->devfn) { 145 && slot == PCI_SLOT(psdev->dev->devfn)
146 && func == PCI_FUNC(psdev->dev->devfn)) {
146 pcistub_device_get(psdev); 147 pcistub_device_get(psdev);
147 goto out; 148 goto out;
148 } 149 }
@@ -191,7 +192,8 @@ struct pci_dev *pcistub_get_pci_dev_by_slot(struct xen_pcibk_device *pdev,
191 if (psdev->dev != NULL 192 if (psdev->dev != NULL
192 && domain == pci_domain_nr(psdev->dev->bus) 193 && domain == pci_domain_nr(psdev->dev->bus)
193 && bus == psdev->dev->bus->number 194 && bus == psdev->dev->bus->number
194 && PCI_DEVFN(slot, func) == psdev->dev->devfn) { 195 && slot == PCI_SLOT(psdev->dev->devfn)
196 && func == PCI_FUNC(psdev->dev->devfn)) {
195 found_dev = pcistub_device_get_pci_dev(pdev, psdev); 197 found_dev = pcistub_device_get_pci_dev(pdev, psdev);
196 break; 198 break;
197 } 199 }
@@ -897,42 +899,35 @@ static struct pci_driver xen_pcibk_pci_driver = {
897static inline int str_to_slot(const char *buf, int *domain, int *bus, 899static inline int str_to_slot(const char *buf, int *domain, int *bus,
898 int *slot, int *func) 900 int *slot, int *func)
899{ 901{
900 int err; 902 int parsed = 0;
901 char wc = '*';
902 903
903 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); 904 switch (sscanf(buf, " %x:%x:%x.%x %n", domain, bus, slot, func,
904 switch (err) { 905 &parsed)) {
905 case 3: 906 case 3:
906 *func = -1; 907 *func = -1;
907 err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc); 908 sscanf(buf, " %x:%x:%x.* %n", domain, bus, slot, &parsed);
908 break; 909 break;
909 case 2: 910 case 2:
910 *slot = *func = -1; 911 *slot = *func = -1;
911 err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc); 912 sscanf(buf, " %x:%x:*.* %n", domain, bus, &parsed);
912 if (err >= 2)
913 ++err;
914 break; 913 break;
915 } 914 }
916 if (err == 4 && wc == '*') 915 if (parsed && !buf[parsed])
917 return 0; 916 return 0;
918 else if (err < 0)
919 return -EINVAL;
920 917
921 /* try again without domain */ 918 /* try again without domain */
922 *domain = 0; 919 *domain = 0;
923 wc = '*'; 920 switch (sscanf(buf, " %x:%x.%x %n", bus, slot, func, &parsed)) {
924 err = sscanf(buf, " %x:%x.%x", bus, slot, func);
925 switch (err) {
926 case 2: 921 case 2:
927 *func = -1; 922 *func = -1;
928 err = sscanf(buf, " %x:%x.%c", bus, slot, &wc); 923 sscanf(buf, " %x:%x.* %n", bus, slot, &parsed);
929 break; 924 break;
930 case 1: 925 case 1:
931 *slot = *func = -1; 926 *slot = *func = -1;
932 err = sscanf(buf, " %x:*.%c", bus, &wc) + 1; 927 sscanf(buf, " %x:*.* %n", bus, &parsed);
933 break; 928 break;
934 } 929 }
935 if (err == 3 && wc == '*') 930 if (parsed && !buf[parsed])
936 return 0; 931 return 0;
937 932
938 return -EINVAL; 933 return -EINVAL;
@@ -941,13 +936,20 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus,
941static inline int str_to_quirk(const char *buf, int *domain, int *bus, int 936static inline int str_to_quirk(const char *buf, int *domain, int *bus, int
942 *slot, int *func, int *reg, int *size, int *mask) 937 *slot, int *func, int *reg, int *size, int *mask)
943{ 938{
944 int err; 939 int parsed = 0;
945 940
946 err = 941 sscanf(buf, " %x:%x:%x.%x-%x:%x:%x %n", domain, bus, slot, func,
947 sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot, 942 reg, size, mask, &parsed);
948 func, reg, size, mask); 943 if (parsed && !buf[parsed])
949 if (err == 7)
950 return 0; 944 return 0;
945
946 /* try again without domain */
947 *domain = 0;
948 sscanf(buf, " %x:%x.%x-%x:%x:%x %n", bus, slot, func, reg, size,
949 mask, &parsed);
950 if (parsed && !buf[parsed])
951 return 0;
952
951 return -EINVAL; 953 return -EINVAL;
952} 954}
953 955
@@ -955,7 +957,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
955{ 957{
956 struct pcistub_device_id *pci_dev_id; 958 struct pcistub_device_id *pci_dev_id;
957 unsigned long flags; 959 unsigned long flags;
958 int rc = 0; 960 int rc = 0, devfn = PCI_DEVFN(slot, func);
959 961
960 if (slot < 0) { 962 if (slot < 0) {
961 for (slot = 0; !rc && slot < 32; ++slot) 963 for (slot = 0; !rc && slot < 32; ++slot)
@@ -969,13 +971,24 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
969 return rc; 971 return rc;
970 } 972 }
971 973
974 if ((
975#if !defined(MODULE) /* pci_domains_supported is not being exported */ \
976 || !defined(CONFIG_PCI_DOMAINS)
977 !pci_domains_supported ? domain :
978#endif
979 domain < 0 || domain > 0xffff)
980 || bus < 0 || bus > 0xff
981 || PCI_SLOT(devfn) != slot
982 || PCI_FUNC(devfn) != func)
983 return -EINVAL;
984
972 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); 985 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
973 if (!pci_dev_id) 986 if (!pci_dev_id)
974 return -ENOMEM; 987 return -ENOMEM;
975 988
976 pci_dev_id->domain = domain; 989 pci_dev_id->domain = domain;
977 pci_dev_id->bus = bus; 990 pci_dev_id->bus = bus;
978 pci_dev_id->devfn = PCI_DEVFN(slot, func); 991 pci_dev_id->devfn = devfn;
979 992
980 pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n", 993 pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n",
981 domain, bus, slot, func); 994 domain, bus, slot, func);
@@ -1016,14 +1029,18 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
1016 return err; 1029 return err;
1017} 1030}
1018 1031
1019static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, 1032static int pcistub_reg_add(int domain, int bus, int slot, int func,
1020 int size, int mask) 1033 unsigned int reg, unsigned int size,
1034 unsigned int mask)
1021{ 1035{
1022 int err = 0; 1036 int err = 0;
1023 struct pcistub_device *psdev; 1037 struct pcistub_device *psdev;
1024 struct pci_dev *dev; 1038 struct pci_dev *dev;
1025 struct config_field *field; 1039 struct config_field *field;
1026 1040
1041 if (reg > 0xfff || (size < 4 && (mask >> (size * 8))))
1042 return -EINVAL;
1043
1027 psdev = pcistub_device_find(domain, bus, slot, func); 1044 psdev = pcistub_device_find(domain, bus, slot, func);
1028 if (!psdev) { 1045 if (!psdev) {
1029 err = -ENODEV; 1046 err = -ENODEV;
@@ -1254,13 +1271,11 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf,
1254 int err; 1271 int err;
1255 struct pcistub_device *psdev; 1272 struct pcistub_device *psdev;
1256 struct xen_pcibk_dev_data *dev_data; 1273 struct xen_pcibk_dev_data *dev_data;
1274
1257 err = str_to_slot(buf, &domain, &bus, &slot, &func); 1275 err = str_to_slot(buf, &domain, &bus, &slot, &func);
1258 if (err) 1276 if (err)
1259 goto out; 1277 goto out;
1260 if (slot < 0 || func < 0) { 1278
1261 err = -EINVAL;
1262 goto out;
1263 }
1264 psdev = pcistub_device_find(domain, bus, slot, func); 1279 psdev = pcistub_device_find(domain, bus, slot, func);
1265 if (!psdev) { 1280 if (!psdev) {
1266 err = -ENODEV; 1281 err = -ENODEV;
@@ -1339,8 +1354,6 @@ static int __init pcistub_init(void)
1339 1354
1340 if (pci_devs_to_hide && *pci_devs_to_hide) { 1355 if (pci_devs_to_hide && *pci_devs_to_hide) {
1341 do { 1356 do {
1342 char wc = '*';
1343
1344 parsed = 0; 1357 parsed = 0;
1345 1358
1346 err = sscanf(pci_devs_to_hide + pos, 1359 err = sscanf(pci_devs_to_hide + pos,
@@ -1349,51 +1362,48 @@ static int __init pcistub_init(void)
1349 switch (err) { 1362 switch (err) {
1350 case 3: 1363 case 3:
1351 func = -1; 1364 func = -1;
1352 err = sscanf(pci_devs_to_hide + pos, 1365 sscanf(pci_devs_to_hide + pos,
1353 " (%x:%x:%x.%c) %n", 1366 " (%x:%x:%x.*) %n",
1354 &domain, &bus, &slot, &wc, 1367 &domain, &bus, &slot, &parsed);
1355 &parsed);
1356 break; 1368 break;
1357 case 2: 1369 case 2:
1358 slot = func = -1; 1370 slot = func = -1;
1359 err = sscanf(pci_devs_to_hide + pos, 1371 sscanf(pci_devs_to_hide + pos,
1360 " (%x:%x:*.%c) %n", 1372 " (%x:%x:*.*) %n",
1361 &domain, &bus, &wc, &parsed) + 1; 1373 &domain, &bus, &parsed);
1362 break; 1374 break;
1363 } 1375 }
1364 1376
1365 if (err != 4 || wc != '*') { 1377 if (!parsed) {
1366 domain = 0; 1378 domain = 0;
1367 wc = '*';
1368 err = sscanf(pci_devs_to_hide + pos, 1379 err = sscanf(pci_devs_to_hide + pos,
1369 " (%x:%x.%x) %n", 1380 " (%x:%x.%x) %n",
1370 &bus, &slot, &func, &parsed); 1381 &bus, &slot, &func, &parsed);
1371 switch (err) { 1382 switch (err) {
1372 case 2: 1383 case 2:
1373 func = -1; 1384 func = -1;
1374 err = sscanf(pci_devs_to_hide + pos, 1385 sscanf(pci_devs_to_hide + pos,
1375 " (%x:%x.%c) %n", 1386 " (%x:%x.*) %n",
1376 &bus, &slot, &wc, 1387 &bus, &slot, &parsed);
1377 &parsed);
1378 break; 1388 break;
1379 case 1: 1389 case 1:
1380 slot = func = -1; 1390 slot = func = -1;
1381 err = sscanf(pci_devs_to_hide + pos, 1391 sscanf(pci_devs_to_hide + pos,
1382 " (%x:*.%c) %n", 1392 " (%x:*.*) %n",
1383 &bus, &wc, &parsed) + 1; 1393 &bus, &parsed);
1384 break; 1394 break;
1385 } 1395 }
1386 if (err != 3 || wc != '*')
1387 goto parse_error;
1388 } 1396 }
1389 1397
1398 if (parsed <= 0)
1399 goto parse_error;
1400
1390 err = pcistub_device_id_add(domain, bus, slot, func); 1401 err = pcistub_device_id_add(domain, bus, slot, func);
1391 if (err) 1402 if (err)
1392 goto out; 1403 goto out;
1393 1404
1394 /* if parsed<=0, we've reached the end of the string */
1395 pos += parsed; 1405 pos += parsed;
1396 } while (parsed > 0 && pci_devs_to_hide[pos]); 1406 } while (pci_devs_to_hide[pos]);
1397 } 1407 }
1398 1408
1399 /* If we're the first PCI Device Driver to register, we're the 1409 /* If we're the first PCI Device Driver to register, we're the