aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xen-pciback/pci_stub.c
diff options
context:
space:
mode:
authorJan Beulich <JBeulich@suse.com>2012-09-18 07:29:03 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-09-18 10:44:17 -0400
commitc3cb4709809e655a4ba5a716086c8bc5bbbbccdb (patch)
treebc3d42fb3a4723eb02efb161fd8f2a2bff77e5d6 /drivers/xen/xen-pciback/pci_stub.c
parentecc635f90adfe1b7cd5fd354f49edfbf24aa4e3e (diff)
xen-pciback: support wild cards in slot specifications
Particularly for hiding sets of SR-IOV devices, specifying them all individually is rather cumbersome. Therefore, allow function and slot numbers to be replaced by a wildcard character ('*'). Unfortunately this gets complicated by the in-kernel sscanf() implementation not being really standard conformant - matching of plain text tails cannot be checked by the caller (a patch to overcome this will be sent shortly, and a follow-up patch for simplifying the code is planned to be sent when that fixed went upstream). Signed-off-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/xen/xen-pciback/pci_stub.c')
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c89
1 files changed, 82 insertions, 7 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 03342728bf23..20e1c42c1c48 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -897,17 +897,41 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus,
897 int *slot, int *func) 897 int *slot, int *func)
898{ 898{
899 int err; 899 int err;
900 char wc = '*';
900 901
901 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); 902 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
902 if (err == 4) 903 switch (err) {
904 case 3:
905 *func = -1;
906 err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc);
907 break;
908 case 2:
909 *slot = *func = -1;
910 err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc);
911 if (err >= 2)
912 ++err;
913 break;
914 }
915 if (err == 4 && wc == '*')
903 return 0; 916 return 0;
904 else if (err < 0) 917 else if (err < 0)
905 return -EINVAL; 918 return -EINVAL;
906 919
907 /* try again without domain */ 920 /* try again without domain */
908 *domain = 0; 921 *domain = 0;
922 wc = '*';
909 err = sscanf(buf, " %x:%x.%x", bus, slot, func); 923 err = sscanf(buf, " %x:%x.%x", bus, slot, func);
910 if (err == 3) 924 switch (err) {
925 case 2:
926 *func = -1;
927 err = sscanf(buf, " %x:%x.%c", bus, slot, &wc);
928 break;
929 case 1:
930 *slot = *func = -1;
931 err = sscanf(buf, " %x:*.%c", bus, &wc) + 1;
932 break;
933 }
934 if (err == 3 && wc == '*')
911 return 0; 935 return 0;
912 936
913 return -EINVAL; 937 return -EINVAL;
@@ -930,6 +954,19 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
930{ 954{
931 struct pcistub_device_id *pci_dev_id; 955 struct pcistub_device_id *pci_dev_id;
932 unsigned long flags; 956 unsigned long flags;
957 int rc = 0;
958
959 if (slot < 0) {
960 for (slot = 0; !rc && slot < 32; ++slot)
961 rc = pcistub_device_id_add(domain, bus, slot, func);
962 return rc;
963 }
964
965 if (func < 0) {
966 for (func = 0; !rc && func < 8; ++func)
967 rc = pcistub_device_id_add(domain, bus, slot, func);
968 return rc;
969 }
933 970
934 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); 971 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
935 if (!pci_dev_id) 972 if (!pci_dev_id)
@@ -952,15 +989,15 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
952static int pcistub_device_id_remove(int domain, int bus, int slot, int func) 989static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
953{ 990{
954 struct pcistub_device_id *pci_dev_id, *t; 991 struct pcistub_device_id *pci_dev_id, *t;
955 int devfn = PCI_DEVFN(slot, func);
956 int err = -ENOENT; 992 int err = -ENOENT;
957 unsigned long flags; 993 unsigned long flags;
958 994
959 spin_lock_irqsave(&device_ids_lock, flags); 995 spin_lock_irqsave(&device_ids_lock, flags);
960 list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, 996 list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids,
961 slot_list) { 997 slot_list) {
962 if (pci_dev_id->domain == domain 998 if (pci_dev_id->domain == domain && pci_dev_id->bus == bus
963 && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) { 999 && (slot < 0 || PCI_SLOT(pci_dev_id->devfn) == slot)
1000 && (func < 0 || PCI_FUNC(pci_dev_id->devfn) == func)) {
964 /* Don't break; here because it's possible the same 1001 /* Don't break; here because it's possible the same
965 * slot could be in the list more than once 1002 * slot could be in the list more than once
966 */ 1003 */
@@ -1216,6 +1253,10 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf,
1216 err = str_to_slot(buf, &domain, &bus, &slot, &func); 1253 err = str_to_slot(buf, &domain, &bus, &slot, &func);
1217 if (err) 1254 if (err)
1218 goto out; 1255 goto out;
1256 if (slot < 0 || func < 0) {
1257 err = -EINVAL;
1258 goto out;
1259 }
1219 psdev = pcistub_device_find(domain, bus, slot, func); 1260 psdev = pcistub_device_find(domain, bus, slot, func);
1220 if (!psdev) { 1261 if (!psdev) {
1221 err = -ENODEV; 1262 err = -ENODEV;
@@ -1297,17 +1338,51 @@ static int __init pcistub_init(void)
1297 1338
1298 if (pci_devs_to_hide && *pci_devs_to_hide) { 1339 if (pci_devs_to_hide && *pci_devs_to_hide) {
1299 do { 1340 do {
1341 char wc = '*';
1342
1300 parsed = 0; 1343 parsed = 0;
1301 1344
1302 err = sscanf(pci_devs_to_hide + pos, 1345 err = sscanf(pci_devs_to_hide + pos,
1303 " (%x:%x:%x.%x) %n", 1346 " (%x:%x:%x.%x) %n",
1304 &domain, &bus, &slot, &func, &parsed); 1347 &domain, &bus, &slot, &func, &parsed);
1305 if (err != 4) { 1348 switch (err) {
1349 case 3:
1350 func = -1;
1351 err = sscanf(pci_devs_to_hide + pos,
1352 " (%x:%x:%x.%c) %n",
1353 &domain, &bus, &slot, &wc,
1354 &parsed);
1355 break;
1356 case 2:
1357 slot = func = -1;
1358 err = sscanf(pci_devs_to_hide + pos,
1359 " (%x:%x:*.%c) %n",
1360 &domain, &bus, &wc, &parsed) + 1;
1361 break;
1362 }
1363
1364 if (err != 4 || wc != '*') {
1306 domain = 0; 1365 domain = 0;
1366 wc = '*';
1307 err = sscanf(pci_devs_to_hide + pos, 1367 err = sscanf(pci_devs_to_hide + pos,
1308 " (%x:%x.%x) %n", 1368 " (%x:%x.%x) %n",
1309 &bus, &slot, &func, &parsed); 1369 &bus, &slot, &func, &parsed);
1310 if (err != 3) 1370 switch (err) {
1371 case 2:
1372 func = -1;
1373 err = sscanf(pci_devs_to_hide + pos,
1374 " (%x:%x.%c) %n",
1375 &bus, &slot, &wc,
1376 &parsed);
1377 break;
1378 case 1:
1379 slot = func = -1;
1380 err = sscanf(pci_devs_to_hide + pos,
1381 " (%x:*.%c) %n",
1382 &bus, &wc, &parsed) + 1;
1383 break;
1384 }
1385 if (err != 3 || wc != '*')
1311 goto parse_error; 1386 goto parse_error;
1312 } 1387 }
1313 1388