aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host/pci-hyperv.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 22:03:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 22:03:25 -0400
commit857f8640147c9fb43f20e43cbca6452710e1ca5d (patch)
tree76a92068d703b8001ca790ffa096d435fa24ae81 /drivers/pci/host/pci-hyperv.c
parent8f3207c7eab9d885cc64c778416537034a7d9c5b (diff)
parent3146c8f4de9b0858794a902f273aec13f168596e (diff)
Merge tag 'pci-v4.12-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas: - add framework for supporting PCIe devices in Endpoint mode (Kishon Vijay Abraham I) - use non-postable PCI config space mappings when possible (Lorenzo Pieralisi) - clean up and unify mmap of PCI BARs (David Woodhouse) - export and unify Function Level Reset support (Christoph Hellwig) - avoid FLR for Intel 82579 NICs (Sasha Neftin) - add pci_request_irq() and pci_free_irq() helpers (Christoph Hellwig) - short-circuit config access failures for disconnected devices (Keith Busch) - remove D3 sleep delay when possible (Adrian Hunter) - freeze PME scan before suspending devices (Lukas Wunner) - stop disabling MSI/MSI-X in pci_device_shutdown() (Prarit Bhargava) - disable boot interrupt quirk for ASUS M2N-LR (Stefan Assmann) - add arch-specific alignment control to improve device passthrough by avoiding multiple BARs in a page (Yongji Xie) - add sysfs sriov_drivers_autoprobe to control VF driver binding (Bodong Wang) - allow slots below PCI-to-PCIe "reverse bridges" (Bjorn Helgaas) - fix crashes when unbinding host controllers that don't support removal (Brian Norris) - add driver for MicroSemi Switchtec management interface (Logan Gunthorpe) - add driver for Faraday Technology FTPCI100 host bridge (Linus Walleij) - add i.MX7D support (Andrey Smirnov) - use generic MSI support for Aardvark (Thomas Petazzoni) - make Rockchip driver modular (Brian Norris) - advertise 128-byte Read Completion Boundary support for Rockchip (Shawn Lin) - advertise PCI_EXP_LNKSTA_SLC for Rockchip root port (Shawn Lin) - convert atomic_t to refcount_t in HV driver (Elena Reshetova) - add CPU IRQ affinity in HV driver (K. Y. Srinivasan) - fix PCI bus removal in HV driver (Long Li) - add support for ThunderX2 DMA alias topology (Jayachandran C) - add ThunderX pass2.x 2nd node MCFG quirk (Tomasz Nowicki) - add ITE 8893 bridge DMA alias quirk (Jarod Wilson) - restrict Cavium ACS quirk only to CN81xx/CN83xx/CN88xx devices (Manish Jaggi) * tag 'pci-v4.12-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (146 commits) PCI: Don't allow unbinding host controllers that aren't prepared ARM: DRA7: clockdomain: Change the CLKTRCTRL of CM_PCIE_CLKSTCTRL to SW_WKUP MAINTAINERS: Add PCI Endpoint maintainer Documentation: PCI: Add userguide for PCI endpoint test function tools: PCI: Add sample test script to invoke pcitest tools: PCI: Add a userspace tool to test PCI endpoint Documentation: misc-devices: Add Documentation for pci-endpoint-test driver misc: Add host side PCI driver for PCI test function device PCI: Add device IDs for DRA74x and DRA72x dt-bindings: PCI: dra7xx: Add DT bindings to enable unaligned access PCI: dwc: dra7xx: Workaround for errata id i870 dt-bindings: PCI: dra7xx: Add DT bindings for PCI dra7xx EP mode PCI: dwc: dra7xx: Add EP mode support PCI: dwc: dra7xx: Facilitate wrapper and MSI interrupts to be enabled independently dt-bindings: PCI: Add DT bindings for PCI designware EP mode PCI: dwc: designware: Add EP mode support Documentation: PCI: Add binding documentation for pci-test endpoint function ixgbe: Use pcie_flr() instead of duplicating it IB/hfi1: Use pcie_flr() instead of duplicating it PCI: imx6: Fix spelling mistake: "contol" -> "control" ...
Diffstat (limited to 'drivers/pci/host/pci-hyperv.c')
-rw-r--r--drivers/pci/host/pci-hyperv.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
index ada98569b78e..84936383e269 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/host/pci-hyperv.c
@@ -56,6 +56,7 @@
56#include <asm/apic.h> 56#include <asm/apic.h>
57#include <linux/msi.h> 57#include <linux/msi.h>
58#include <linux/hyperv.h> 58#include <linux/hyperv.h>
59#include <linux/refcount.h>
59#include <asm/mshyperv.h> 60#include <asm/mshyperv.h>
60 61
61/* 62/*
@@ -72,6 +73,7 @@ enum {
72 PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1 73 PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1
73}; 74};
74 75
76#define CPU_AFFINITY_ALL -1ULL
75#define PCI_CONFIG_MMIO_LENGTH 0x2000 77#define PCI_CONFIG_MMIO_LENGTH 0x2000
76#define CFG_PAGE_OFFSET 0x1000 78#define CFG_PAGE_OFFSET 0x1000
77#define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET) 79#define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET)
@@ -350,6 +352,7 @@ enum hv_pcibus_state {
350 hv_pcibus_init = 0, 352 hv_pcibus_init = 0,
351 hv_pcibus_probed, 353 hv_pcibus_probed,
352 hv_pcibus_installed, 354 hv_pcibus_installed,
355 hv_pcibus_removed,
353 hv_pcibus_maximum 356 hv_pcibus_maximum
354}; 357};
355 358
@@ -421,7 +424,7 @@ enum hv_pcidev_ref_reason {
421struct hv_pci_dev { 424struct hv_pci_dev {
422 /* List protected by pci_rescan_remove_lock */ 425 /* List protected by pci_rescan_remove_lock */
423 struct list_head list_entry; 426 struct list_head list_entry;
424 atomic_t refs; 427 refcount_t refs;
425 enum hv_pcichild_state state; 428 enum hv_pcichild_state state;
426 struct pci_function_description desc; 429 struct pci_function_description desc;
427 bool reported_missing; 430 bool reported_missing;
@@ -876,7 +879,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
876 hv_int_desc_free(hpdev, int_desc); 879 hv_int_desc_free(hpdev, int_desc);
877 } 880 }
878 881
879 int_desc = kzalloc(sizeof(*int_desc), GFP_KERNEL); 882 int_desc = kzalloc(sizeof(*int_desc), GFP_ATOMIC);
880 if (!int_desc) 883 if (!int_desc)
881 goto drop_reference; 884 goto drop_reference;
882 885
@@ -897,9 +900,13 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
897 * processors because Hyper-V only supports 64 in a guest. 900 * processors because Hyper-V only supports 64 in a guest.
898 */ 901 */
899 affinity = irq_data_get_affinity_mask(data); 902 affinity = irq_data_get_affinity_mask(data);
900 for_each_cpu_and(cpu, affinity, cpu_online_mask) { 903 if (cpumask_weight(affinity) >= 32) {
901 int_pkt->int_desc.cpu_mask |= 904 int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL;
902 (1ULL << vmbus_cpu_number_to_vp_number(cpu)); 905 } else {
906 for_each_cpu_and(cpu, affinity, cpu_online_mask) {
907 int_pkt->int_desc.cpu_mask |=
908 (1ULL << vmbus_cpu_number_to_vp_number(cpu));
909 }
903 } 910 }
904 911
905 ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt, 912 ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt,
@@ -1208,9 +1215,11 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
1208 hbus->pci_bus->msi = &hbus->msi_chip; 1215 hbus->pci_bus->msi = &hbus->msi_chip;
1209 hbus->pci_bus->msi->dev = &hbus->hdev->device; 1216 hbus->pci_bus->msi->dev = &hbus->hdev->device;
1210 1217
1218 pci_lock_rescan_remove();
1211 pci_scan_child_bus(hbus->pci_bus); 1219 pci_scan_child_bus(hbus->pci_bus);
1212 pci_bus_assign_resources(hbus->pci_bus); 1220 pci_bus_assign_resources(hbus->pci_bus);
1213 pci_bus_add_devices(hbus->pci_bus); 1221 pci_bus_add_devices(hbus->pci_bus);
1222 pci_unlock_rescan_remove();
1214 hbus->state = hv_pcibus_installed; 1223 hbus->state = hv_pcibus_installed;
1215 return 0; 1224 return 0;
1216} 1225}
@@ -1254,13 +1263,13 @@ static void q_resource_requirements(void *context, struct pci_response *resp,
1254static void get_pcichild(struct hv_pci_dev *hpdev, 1263static void get_pcichild(struct hv_pci_dev *hpdev,
1255 enum hv_pcidev_ref_reason reason) 1264 enum hv_pcidev_ref_reason reason)
1256{ 1265{
1257 atomic_inc(&hpdev->refs); 1266 refcount_inc(&hpdev->refs);
1258} 1267}
1259 1268
1260static void put_pcichild(struct hv_pci_dev *hpdev, 1269static void put_pcichild(struct hv_pci_dev *hpdev,
1261 enum hv_pcidev_ref_reason reason) 1270 enum hv_pcidev_ref_reason reason)
1262{ 1271{
1263 if (atomic_dec_and_test(&hpdev->refs)) 1272 if (refcount_dec_and_test(&hpdev->refs))
1264 kfree(hpdev); 1273 kfree(hpdev);
1265} 1274}
1266 1275
@@ -1314,7 +1323,7 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
1314 wait_for_completion(&comp_pkt.host_event); 1323 wait_for_completion(&comp_pkt.host_event);
1315 1324
1316 hpdev->desc = *desc; 1325 hpdev->desc = *desc;
1317 get_pcichild(hpdev, hv_pcidev_ref_initial); 1326 refcount_set(&hpdev->refs, 1);
1318 get_pcichild(hpdev, hv_pcidev_ref_childlist); 1327 get_pcichild(hpdev, hv_pcidev_ref_childlist);
1319 spin_lock_irqsave(&hbus->device_list_lock, flags); 1328 spin_lock_irqsave(&hbus->device_list_lock, flags);
1320 1329
@@ -1504,13 +1513,24 @@ static void pci_devices_present_work(struct work_struct *work)
1504 put_pcichild(hpdev, hv_pcidev_ref_initial); 1513 put_pcichild(hpdev, hv_pcidev_ref_initial);
1505 } 1514 }
1506 1515
1507 /* Tell the core to rescan bus because there may have been changes. */ 1516 switch(hbus->state) {
1508 if (hbus->state == hv_pcibus_installed) { 1517 case hv_pcibus_installed:
1518 /*
1519 * Tell the core to rescan bus
1520 * because there may have been changes.
1521 */
1509 pci_lock_rescan_remove(); 1522 pci_lock_rescan_remove();
1510 pci_scan_child_bus(hbus->pci_bus); 1523 pci_scan_child_bus(hbus->pci_bus);
1511 pci_unlock_rescan_remove(); 1524 pci_unlock_rescan_remove();
1512 } else { 1525 break;
1526
1527 case hv_pcibus_init:
1528 case hv_pcibus_probed:
1513 survey_child_resources(hbus); 1529 survey_child_resources(hbus);
1530 break;
1531
1532 default:
1533 break;
1514 } 1534 }
1515 1535
1516 up(&hbus->enum_sem); 1536 up(&hbus->enum_sem);
@@ -1600,8 +1620,10 @@ static void hv_eject_device_work(struct work_struct *work)
1600 pdev = pci_get_domain_bus_and_slot(hpdev->hbus->sysdata.domain, 0, 1620 pdev = pci_get_domain_bus_and_slot(hpdev->hbus->sysdata.domain, 0,
1601 wslot); 1621 wslot);
1602 if (pdev) { 1622 if (pdev) {
1623 pci_lock_rescan_remove();
1603 pci_stop_and_remove_bus_device(pdev); 1624 pci_stop_and_remove_bus_device(pdev);
1604 pci_dev_put(pdev); 1625 pci_dev_put(pdev);
1626 pci_unlock_rescan_remove();
1605 } 1627 }
1606 1628
1607 spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags); 1629 spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags);
@@ -2185,6 +2207,7 @@ static int hv_pci_probe(struct hv_device *hdev,
2185 hbus = kzalloc(sizeof(*hbus), GFP_KERNEL); 2207 hbus = kzalloc(sizeof(*hbus), GFP_KERNEL);
2186 if (!hbus) 2208 if (!hbus)
2187 return -ENOMEM; 2209 return -ENOMEM;
2210 hbus->state = hv_pcibus_init;
2188 2211
2189 /* 2212 /*
2190 * The PCI bus "domain" is what is called "segment" in ACPI and 2213 * The PCI bus "domain" is what is called "segment" in ACPI and
@@ -2348,6 +2371,7 @@ static int hv_pci_remove(struct hv_device *hdev)
2348 pci_stop_root_bus(hbus->pci_bus); 2371 pci_stop_root_bus(hbus->pci_bus);
2349 pci_remove_root_bus(hbus->pci_bus); 2372 pci_remove_root_bus(hbus->pci_bus);
2350 pci_unlock_rescan_remove(); 2373 pci_unlock_rescan_remove();
2374 hbus->state = hv_pcibus_removed;
2351 } 2375 }
2352 2376
2353 hv_pci_bus_exit(hdev); 2377 hv_pci_bus_exit(hdev);