aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host/pci-hyperv.c
diff options
context:
space:
mode:
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);