diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pci-driver.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index e4115a0d5ba..414c77299c7 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -7,6 +7,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/device.h> +#include <linux/mempolicy.h> #include "pci.h" /* @@ -163,6 +164,34 @@ const struct pci_device_id *pci_match_device(struct pci_driver *drv, return NULL; } +static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, + const struct pci_device_id *id) +{ + int error; +#ifdef CONFIG_NUMA + /* 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. */ + struct mempolicy *oldpol; + cpumask_t oldmask = current->cpus_allowed; + int node = pcibus_to_node(dev->bus); + if (node >= 0 && node_online(node)) + set_cpus_allowed(current, node_to_cpumask(node)); + /* And set default memory allocation policy */ + oldpol = current->mempolicy; + current->mempolicy = &default_policy; + mpol_get(current->mempolicy); +#endif + error = drv->probe(dev, id); +#ifdef CONFIG_NUMA + set_cpus_allowed(current, oldmask); + mpol_free(current->mempolicy); + current->mempolicy = oldpol; +#endif + return error; +} + /** * __pci_device_probe() * @@ -180,7 +209,7 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) id = pci_match_device(drv, pci_dev); if (id) - error = drv->probe(pci_dev, id); + error = pci_call_probe(drv, pci_dev, id); if (error >= 0) { pci_dev->driver = drv; error = 0; |