Skip to content

Commit

Permalink
PCI: Avoid unnecessary CPU switch when calling driver .probe() method
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexander Duyck authored and Bjorn Helgaas committed Nov 25, 2013
1 parent 6ce4eac commit 12c3156
Showing 1 changed file with 21 additions and 5 deletions.
26 changes: 21 additions & 5 deletions drivers/pci/pci-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
int error, node;
struct drv_dev_and_id ddi = { drv, dev, id };

/* Execute driver initialization on node where the device's
bus is attached to. This way the driver likely allocates
its local memory on the right node without any need to
change it. */
/*
* Execute driver initialization on node where the device is
* attached. This way the driver likely allocates its local memory
* on the right node.
*/
node = dev_to_node(&dev->dev);
if (node >= 0) {

/*
* On NUMA systems, we are likely to call a PF probe function using
* work_on_cpu(). If that probe calls pci_enable_sriov() (which
* adds the VF devices via pci_bus_add_device()), we may re-enter
* this function to call the VF probe function. Calling
* work_on_cpu() again will cause a lockdep warning. Since VFs are
* always on the same node as the PF, we can work around this by
* avoiding work_on_cpu() when we're already on the correct node.
*
* Preemption is enabled, so it's theoretically unsafe to use
* numa_node_id(), but even if we run the probe function on the
* wrong node, it should be functionally correct.
*/
if (node >= 0 && node != numa_node_id()) {
int cpu;

get_online_cpus();
Expand All @@ -305,6 +320,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
put_online_cpus();
} else
error = local_pci_probe(&ddi);

return error;
}

Expand Down

0 comments on commit 12c3156

Please sign in to comment.