aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen/xen-pciback
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 01:09:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 01:09:10 -0400
commit56d92aa5cf7c96c70f81d0350c94faf46a9fb76d (patch)
tree2fb5d5b891903cada4dff9c581c70d33340a3769 /drivers/xen/xen-pciback
parent33c2a174120b2c1baec9d1dac513f9d4b761b26a (diff)
parentc341ca45ce56143804ef5a8f4db753e554e640b4 (diff)
Merge tag 'stable/for-linus-3.7-x86-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen
Pull Xen update from Konrad Rzeszutek Wilk: "Features: - When hotplugging PCI devices in a PV guest we can allocate Xen-SWIOTLB later. - Cleanup Xen SWIOTLB. - Support pages out grants from HVM domains in the backends. - Support wild cards in xen-pciback.hide=(BDF) arguments. - Update grant status updates with upstream hypervisor. - Boot PV guests with more than 128GB. - Cleanup Xen MMU code/add comments. - Obtain XENVERS using a preferred method. - Lay out generic changes to support Xen ARM. - Allow privcmd ioctl for HVM (used to do only PV). - Do v2 of mmap_batch for privcmd ioctls. - If hypervisor saves the LED keyboard light - we will now instruct the kernel about its state. Fixes: - More fixes to Xen PCI backend for various calls/FLR/etc. - With more than 4GB in a 64-bit PV guest disable native SWIOTLB. - Fix up smatch warnings. - Fix up various return values in privmcmd and mm." * tag 'stable/for-linus-3.7-x86-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/konrad/xen: (48 commits) xen/pciback: Restore the PCI config space after an FLR. xen-pciback: properly clean up after calling pcistub_device_find() xen/vga: add the xen EFI video mode support xen/x86: retrieve keyboard shift status flags from hypervisor. xen/gndev: Xen backend support for paged out grant targets V4. xen-pciback: support wild cards in slot specifications xen/swiotlb: Fix compile warnings when using plain integer instead of NULL pointer. xen/swiotlb: Remove functions not needed anymore. xen/pcifront: Use Xen-SWIOTLB when initting if required. xen/swiotlb: For early initialization, return zero on success. xen/swiotlb: Use the swiotlb_late_init_with_tbl to init Xen-SWIOTLB late when PV PCI is used. xen/swiotlb: Move the error strings to its own function. xen/swiotlb: Move the nr_tbl determination in its own function. xen/arm: compile and run xenbus xen: resynchronise grant table status codes with upstream xen/privcmd: return -EFAULT on error xen/privcmd: Fix mmap batch ioctl error status copy back. xen/privcmd: add PRIVCMD_MMAPBATCH_V2 ioctl xen/mm: return more precise error from xen_remap_domain_range() xen/mmu: If the revector fails, don't attempt to revector anything else. ...
Diffstat (limited to 'drivers/xen/xen-pciback')
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c136
1 files changed, 106 insertions, 30 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 92ff01dbeb10..961d664e2d2f 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -362,6 +362,7 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
362 else { 362 else {
363 dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); 363 dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
364 __pci_reset_function_locked(dev); 364 __pci_reset_function_locked(dev);
365 pci_restore_state(dev);
365 } 366 }
366 /* Now disable the device (this also ensures some private device 367 /* Now disable the device (this also ensures some private device
367 * data is setup before we export) 368 * data is setup before we export)
@@ -681,14 +682,14 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev)
681 dev_err(&dev->dev, DRV_NAME " device is not connected or owned" 682 dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
682 " by HVM, kill it\n"); 683 " by HVM, kill it\n");
683 kill_domain_by_device(psdev); 684 kill_domain_by_device(psdev);
684 goto release; 685 goto end;
685 } 686 }
686 687
687 if (!test_bit(_XEN_PCIB_AERHANDLER, 688 if (!test_bit(_XEN_PCIB_AERHANDLER,
688 (unsigned long *)&psdev->pdev->sh_info->flags)) { 689 (unsigned long *)&psdev->pdev->sh_info->flags)) {
689 dev_err(&dev->dev, 690 dev_err(&dev->dev,
690 "guest with no AER driver should have been killed\n"); 691 "guest with no AER driver should have been killed\n");
691 goto release; 692 goto end;
692 } 693 }
693 result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result); 694 result = common_process(psdev, 1, XEN_PCI_OP_aer_slotreset, result);
694 695
@@ -698,9 +699,9 @@ static pci_ers_result_t xen_pcibk_slot_reset(struct pci_dev *dev)
698 "No AER slot_reset service or disconnected!\n"); 699 "No AER slot_reset service or disconnected!\n");
699 kill_domain_by_device(psdev); 700 kill_domain_by_device(psdev);
700 } 701 }
701release:
702 pcistub_device_put(psdev);
703end: 702end:
703 if (psdev)
704 pcistub_device_put(psdev);
704 up_write(&pcistub_sem); 705 up_write(&pcistub_sem);
705 return result; 706 return result;
706 707
@@ -739,14 +740,14 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev)
739 dev_err(&dev->dev, DRV_NAME " device is not connected or owned" 740 dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
740 " by HVM, kill it\n"); 741 " by HVM, kill it\n");
741 kill_domain_by_device(psdev); 742 kill_domain_by_device(psdev);
742 goto release; 743 goto end;
743 } 744 }
744 745
745 if (!test_bit(_XEN_PCIB_AERHANDLER, 746 if (!test_bit(_XEN_PCIB_AERHANDLER,
746 (unsigned long *)&psdev->pdev->sh_info->flags)) { 747 (unsigned long *)&psdev->pdev->sh_info->flags)) {
747 dev_err(&dev->dev, 748 dev_err(&dev->dev,
748 "guest with no AER driver should have been killed\n"); 749 "guest with no AER driver should have been killed\n");
749 goto release; 750 goto end;
750 } 751 }
751 result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result); 752 result = common_process(psdev, 1, XEN_PCI_OP_aer_mmio, result);
752 753
@@ -756,9 +757,9 @@ static pci_ers_result_t xen_pcibk_mmio_enabled(struct pci_dev *dev)
756 "No AER mmio_enabled service or disconnected!\n"); 757 "No AER mmio_enabled service or disconnected!\n");
757 kill_domain_by_device(psdev); 758 kill_domain_by_device(psdev);
758 } 759 }
759release:
760 pcistub_device_put(psdev);
761end: 760end:
761 if (psdev)
762 pcistub_device_put(psdev);
762 up_write(&pcistub_sem); 763 up_write(&pcistub_sem);
763 return result; 764 return result;
764} 765}
@@ -797,7 +798,7 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev,
797 dev_err(&dev->dev, DRV_NAME " device is not connected or owned" 798 dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
798 " by HVM, kill it\n"); 799 " by HVM, kill it\n");
799 kill_domain_by_device(psdev); 800 kill_domain_by_device(psdev);
800 goto release; 801 goto end;
801 } 802 }
802 803
803 /*Guest owns the device yet no aer handler regiested, kill guest*/ 804 /*Guest owns the device yet no aer handler regiested, kill guest*/
@@ -805,7 +806,7 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev,
805 (unsigned long *)&psdev->pdev->sh_info->flags)) { 806 (unsigned long *)&psdev->pdev->sh_info->flags)) {
806 dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n"); 807 dev_dbg(&dev->dev, "guest may have no aer driver, kill it\n");
807 kill_domain_by_device(psdev); 808 kill_domain_by_device(psdev);
808 goto release; 809 goto end;
809 } 810 }
810 result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result); 811 result = common_process(psdev, error, XEN_PCI_OP_aer_detected, result);
811 812
@@ -815,9 +816,9 @@ static pci_ers_result_t xen_pcibk_error_detected(struct pci_dev *dev,
815 "No AER error_detected service or disconnected!\n"); 816 "No AER error_detected service or disconnected!\n");
816 kill_domain_by_device(psdev); 817 kill_domain_by_device(psdev);
817 } 818 }
818release:
819 pcistub_device_put(psdev);
820end: 819end:
820 if (psdev)
821 pcistub_device_put(psdev);
821 up_write(&pcistub_sem); 822 up_write(&pcistub_sem);
822 return result; 823 return result;
823} 824}
@@ -851,7 +852,7 @@ static void xen_pcibk_error_resume(struct pci_dev *dev)
851 dev_err(&dev->dev, DRV_NAME " device is not connected or owned" 852 dev_err(&dev->dev, DRV_NAME " device is not connected or owned"
852 " by HVM, kill it\n"); 853 " by HVM, kill it\n");
853 kill_domain_by_device(psdev); 854 kill_domain_by_device(psdev);
854 goto release; 855 goto end;
855 } 856 }
856 857
857 if (!test_bit(_XEN_PCIB_AERHANDLER, 858 if (!test_bit(_XEN_PCIB_AERHANDLER,
@@ -859,13 +860,13 @@ static void xen_pcibk_error_resume(struct pci_dev *dev)
859 dev_err(&dev->dev, 860 dev_err(&dev->dev,
860 "guest with no AER driver should have been killed\n"); 861 "guest with no AER driver should have been killed\n");
861 kill_domain_by_device(psdev); 862 kill_domain_by_device(psdev);
862 goto release; 863 goto end;
863 } 864 }
864 common_process(psdev, 1, XEN_PCI_OP_aer_resume, 865 common_process(psdev, 1, XEN_PCI_OP_aer_resume,
865 PCI_ERS_RESULT_RECOVERED); 866 PCI_ERS_RESULT_RECOVERED);
866release:
867 pcistub_device_put(psdev);
868end: 867end:
868 if (psdev)
869 pcistub_device_put(psdev);
869 up_write(&pcistub_sem); 870 up_write(&pcistub_sem);
870 return; 871 return;
871} 872}
@@ -897,17 +898,41 @@ static inline int str_to_slot(const char *buf, int *domain, int *bus,
897 int *slot, int *func) 898 int *slot, int *func)
898{ 899{
899 int err; 900 int err;
901 char wc = '*';
900 902
901 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func); 903 err = sscanf(buf, " %x:%x:%x.%x", domain, bus, slot, func);
902 if (err == 4) 904 switch (err) {
905 case 3:
906 *func = -1;
907 err = sscanf(buf, " %x:%x:%x.%c", domain, bus, slot, &wc);
908 break;
909 case 2:
910 *slot = *func = -1;
911 err = sscanf(buf, " %x:%x:*.%c", domain, bus, &wc);
912 if (err >= 2)
913 ++err;
914 break;
915 }
916 if (err == 4 && wc == '*')
903 return 0; 917 return 0;
904 else if (err < 0) 918 else if (err < 0)
905 return -EINVAL; 919 return -EINVAL;
906 920
907 /* try again without domain */ 921 /* try again without domain */
908 *domain = 0; 922 *domain = 0;
923 wc = '*';
909 err = sscanf(buf, " %x:%x.%x", bus, slot, func); 924 err = sscanf(buf, " %x:%x.%x", bus, slot, func);
910 if (err == 3) 925 switch (err) {
926 case 2:
927 *func = -1;
928 err = sscanf(buf, " %x:%x.%c", bus, slot, &wc);
929 break;
930 case 1:
931 *slot = *func = -1;
932 err = sscanf(buf, " %x:*.%c", bus, &wc) + 1;
933 break;
934 }
935 if (err == 3 && wc == '*')
911 return 0; 936 return 0;
912 937
913 return -EINVAL; 938 return -EINVAL;
@@ -930,6 +955,19 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func)
930{ 955{
931 struct pcistub_device_id *pci_dev_id; 956 struct pcistub_device_id *pci_dev_id;
932 unsigned long flags; 957 unsigned long flags;
958 int rc = 0;
959
960 if (slot < 0) {
961 for (slot = 0; !rc && slot < 32; ++slot)
962 rc = pcistub_device_id_add(domain, bus, slot, func);
963 return rc;
964 }
965
966 if (func < 0) {
967 for (func = 0; !rc && func < 8; ++func)
968 rc = pcistub_device_id_add(domain, bus, slot, func);
969 return rc;
970 }
933 971
934 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL); 972 pci_dev_id = kmalloc(sizeof(*pci_dev_id), GFP_KERNEL);
935 if (!pci_dev_id) 973 if (!pci_dev_id)
@@ -952,15 +990,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) 990static int pcistub_device_id_remove(int domain, int bus, int slot, int func)
953{ 991{
954 struct pcistub_device_id *pci_dev_id, *t; 992 struct pcistub_device_id *pci_dev_id, *t;
955 int devfn = PCI_DEVFN(slot, func);
956 int err = -ENOENT; 993 int err = -ENOENT;
957 unsigned long flags; 994 unsigned long flags;
958 995
959 spin_lock_irqsave(&device_ids_lock, flags); 996 spin_lock_irqsave(&device_ids_lock, flags);
960 list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids, 997 list_for_each_entry_safe(pci_dev_id, t, &pcistub_device_ids,
961 slot_list) { 998 slot_list) {
962 if (pci_dev_id->domain == domain 999 if (pci_dev_id->domain == domain && pci_dev_id->bus == bus
963 && pci_dev_id->bus == bus && pci_dev_id->devfn == devfn) { 1000 && (slot < 0 || PCI_SLOT(pci_dev_id->devfn) == slot)
1001 && (func < 0 || PCI_FUNC(pci_dev_id->devfn) == func)) {
964 /* Don't break; here because it's possible the same 1002 /* Don't break; here because it's possible the same
965 * slot could be in the list more than once 1003 * slot could be in the list more than once
966 */ 1004 */
@@ -987,7 +1025,7 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
987 struct config_field *field; 1025 struct config_field *field;
988 1026
989 psdev = pcistub_device_find(domain, bus, slot, func); 1027 psdev = pcistub_device_find(domain, bus, slot, func);
990 if (!psdev || !psdev->dev) { 1028 if (!psdev) {
991 err = -ENODEV; 1029 err = -ENODEV;
992 goto out; 1030 goto out;
993 } 1031 }
@@ -1011,6 +1049,8 @@ static int pcistub_reg_add(int domain, int bus, int slot, int func, int reg,
1011 if (err) 1049 if (err)
1012 kfree(field); 1050 kfree(field);
1013out: 1051out:
1052 if (psdev)
1053 pcistub_device_put(psdev);
1014 return err; 1054 return err;
1015} 1055}
1016 1056
@@ -1115,10 +1155,9 @@ static ssize_t pcistub_irq_handler_switch(struct device_driver *drv,
1115 1155
1116 err = str_to_slot(buf, &domain, &bus, &slot, &func); 1156 err = str_to_slot(buf, &domain, &bus, &slot, &func);
1117 if (err) 1157 if (err)
1118 goto out; 1158 return err;
1119 1159
1120 psdev = pcistub_device_find(domain, bus, slot, func); 1160 psdev = pcistub_device_find(domain, bus, slot, func);
1121
1122 if (!psdev) 1161 if (!psdev)
1123 goto out; 1162 goto out;
1124 1163
@@ -1134,6 +1173,8 @@ static ssize_t pcistub_irq_handler_switch(struct device_driver *drv,
1134 if (dev_data->isr_on) 1173 if (dev_data->isr_on)
1135 dev_data->ack_intr = 1; 1174 dev_data->ack_intr = 1;
1136out: 1175out:
1176 if (psdev)
1177 pcistub_device_put(psdev);
1137 if (!err) 1178 if (!err)
1138 err = count; 1179 err = count;
1139 return err; 1180 return err;
@@ -1216,15 +1257,16 @@ static ssize_t permissive_add(struct device_driver *drv, const char *buf,
1216 err = str_to_slot(buf, &domain, &bus, &slot, &func); 1257 err = str_to_slot(buf, &domain, &bus, &slot, &func);
1217 if (err) 1258 if (err)
1218 goto out; 1259 goto out;
1260 if (slot < 0 || func < 0) {
1261 err = -EINVAL;
1262 goto out;
1263 }
1219 psdev = pcistub_device_find(domain, bus, slot, func); 1264 psdev = pcistub_device_find(domain, bus, slot, func);
1220 if (!psdev) { 1265 if (!psdev) {
1221 err = -ENODEV; 1266 err = -ENODEV;
1222 goto out; 1267 goto out;
1223 } 1268 }
1224 if (!psdev->dev) { 1269
1225 err = -ENODEV;
1226 goto release;
1227 }
1228 dev_data = pci_get_drvdata(psdev->dev); 1270 dev_data = pci_get_drvdata(psdev->dev);
1229 /* the driver data for a device should never be null at this point */ 1271 /* the driver data for a device should never be null at this point */
1230 if (!dev_data) { 1272 if (!dev_data) {
@@ -1297,17 +1339,51 @@ static int __init pcistub_init(void)
1297 1339
1298 if (pci_devs_to_hide && *pci_devs_to_hide) { 1340 if (pci_devs_to_hide && *pci_devs_to_hide) {
1299 do { 1341 do {
1342 char wc = '*';
1343
1300 parsed = 0; 1344 parsed = 0;
1301 1345
1302 err = sscanf(pci_devs_to_hide + pos, 1346 err = sscanf(pci_devs_to_hide + pos,
1303 " (%x:%x:%x.%x) %n", 1347 " (%x:%x:%x.%x) %n",
1304 &domain, &bus, &slot, &func, &parsed); 1348 &domain, &bus, &slot, &func, &parsed);
1305 if (err != 4) { 1349 switch (err) {
1350 case 3:
1351 func = -1;
1352 err = sscanf(pci_devs_to_hide + pos,
1353 " (%x:%x:%x.%c) %n",
1354 &domain, &bus, &slot, &wc,
1355 &parsed);
1356 break;
1357 case 2:
1358 slot = func = -1;
1359 err = sscanf(pci_devs_to_hide + pos,
1360 " (%x:%x:*.%c) %n",
1361 &domain, &bus, &wc, &parsed) + 1;
1362 break;
1363 }
1364
1365 if (err != 4 || wc != '*') {
1306 domain = 0; 1366 domain = 0;
1367 wc = '*';
1307 err = sscanf(pci_devs_to_hide + pos, 1368 err = sscanf(pci_devs_to_hide + pos,
1308 " (%x:%x.%x) %n", 1369 " (%x:%x.%x) %n",
1309 &bus, &slot, &func, &parsed); 1370 &bus, &slot, &func, &parsed);
1310 if (err != 3) 1371 switch (err) {
1372 case 2:
1373 func = -1;
1374 err = sscanf(pci_devs_to_hide + pos,
1375 " (%x:%x.%c) %n",
1376 &bus, &slot, &wc,
1377 &parsed);
1378 break;
1379 case 1:
1380 slot = func = -1;
1381 err = sscanf(pci_devs_to_hide + pos,
1382 " (%x:*.%c) %n",
1383 &bus, &wc, &parsed) + 1;
1384 break;
1385 }
1386 if (err != 3 || wc != '*')
1311 goto parse_error; 1387 goto parse_error;
1312 } 1388 }
1313 1389