diff options
author | Alexander Duyck <alexander.h.duyck@intel.com> | 2013-11-18 12:59:59 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-11-25 16:34:45 -0500 |
commit | 12c3156f10c5d8c5f1fb3f0bbdb8c1ddb1d1f65c (patch) | |
tree | 8436ef47131021f2ac50116d87f7931428e6292c /drivers/pci/pci-driver.c | |
parent | 6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae (diff) |
PCI: Avoid unnecessary CPU switch when calling driver .probe() method
If we are already on a CPU local to the device, call the driver .probe()
method directly without using work_on_cpu().
This is a workaround for a lockdep warning in the following scenario:
pci_call_probe
work_on_cpu(cpu, local_pci_probe, ...)
driver .probe
pci_enable_sriov
...
pci_bus_add_device
...
pci_call_probe
work_on_cpu(cpu, local_pci_probe, ...)
It would be better to fix PCI so we don't call VF driver .probe() methods
from inside a PF driver .probe() method, but that's a bigger project.
[bhelgaas: open bugzilla, rework comments & changelog]
Link: https://bugzilla.kernel.org/show_bug.cgi?id=65071
Link: http://lkml.kernel.org/r/CAE9FiQXYQEAZ=0sG6+2OdffBqfLS9MpoN1xviRR9aDbxPxcKxQ@mail.gmail.com
Link: http://lkml.kernel.org/r/20130624195942.40795.27292.stgit@ahduyck-cp1.jf.intel.com
Tested-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Diffstat (limited to 'drivers/pci/pci-driver.c')
-rw-r--r-- | drivers/pci/pci-driver.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 9042fdbd7244..7edd5c307446 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -288,12 +288,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, | |||
288 | int error, node; | 288 | int error, node; |
289 | struct drv_dev_and_id ddi = { drv, dev, id }; | 289 | struct drv_dev_and_id ddi = { drv, dev, id }; |
290 | 290 | ||
291 | /* Execute driver initialization on node where the device's | 291 | /* |
292 | bus is attached to. This way the driver likely allocates | 292 | * Execute driver initialization on node where the device is |
293 | its local memory on the right node without any need to | 293 | * attached. This way the driver likely allocates its local memory |
294 | change it. */ | 294 | * on the right node. |
295 | */ | ||
295 | node = dev_to_node(&dev->dev); | 296 | node = dev_to_node(&dev->dev); |
296 | if (node >= 0) { | 297 | |
298 | /* | ||
299 | * On NUMA systems, we are likely to call a PF probe function using | ||
300 | * work_on_cpu(). If that probe calls pci_enable_sriov() (which | ||
301 | * adds the VF devices via pci_bus_add_device()), we may re-enter | ||
302 | * this function to call the VF probe function. Calling | ||
303 | * work_on_cpu() again will cause a lockdep warning. Since VFs are | ||
304 | * always on the same node as the PF, we can work around this by | ||
305 | * avoiding work_on_cpu() when we're already on the correct node. | ||
306 | * | ||
307 | * Preemption is enabled, so it's theoretically unsafe to use | ||
308 | * numa_node_id(), but even if we run the probe function on the | ||
309 | * wrong node, it should be functionally correct. | ||
310 | */ | ||
311 | if (node >= 0 && node != numa_node_id()) { | ||
297 | int cpu; | 312 | int cpu; |
298 | 313 | ||
299 | get_online_cpus(); | 314 | get_online_cpus(); |
@@ -305,6 +320,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, | |||
305 | put_online_cpus(); | 320 | put_online_cpus(); |
306 | } else | 321 | } else |
307 | error = local_pci_probe(&ddi); | 322 | error = local_pci_probe(&ddi); |
323 | |||
308 | return error; | 324 | return error; |
309 | } | 325 | } |
310 | 326 | ||