diff options
Diffstat (limited to 'drivers/xen/xen-pciback')
-rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 118 |
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 = { | |||
897 | static inline int str_to_slot(const char *buf, int *domain, int *bus, | 899 | static 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, | |||
941 | static inline int str_to_quirk(const char *buf, int *domain, int *bus, int | 936 | static 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 | ||
1019 | static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg, | 1032 | static 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 |