diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 22:03:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-08 22:03:25 -0400 |
commit | 857f8640147c9fb43f20e43cbca6452710e1ca5d (patch) | |
tree | 76a92068d703b8001ca790ffa096d435fa24ae81 /drivers/pci/host/pci-hyperv.c | |
parent | 8f3207c7eab9d885cc64c778416537034a7d9c5b (diff) | |
parent | 3146c8f4de9b0858794a902f273aec13f168596e (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.c | 46 |
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 { | |||
421 | struct hv_pci_dev { | 424 | struct 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, | |||
1254 | static void get_pcichild(struct hv_pci_dev *hpdev, | 1263 | static 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 | ||
1260 | static void put_pcichild(struct hv_pci_dev *hpdev, | 1269 | static 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); |