PATCH: platforms: avoid queuing work if possible

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



we noticed a change in module loading behavior and tracked it
backwards to a small change in behavior due to
774a1221e862b343388347bac9b318767336b20b. this tries to avoid queuing
if possible, but if we do queue then copy the relevant task flag on
the target cpu.

\p
From 9e77188d8a8e74b7b4e3f3e7c6bb0deb8fdf7eb4 Mon Sep 17 00:00:00 2001
From: peter chang <dpf@xxxxxxxxxx>
Date: Mon, 27 Jan 2014 16:24:53 -0800
Subject: [PATCH] platforms: avoid queuing work if possible

774a1221e862b343388347bac9b318767336b20b tries to avoid an expensive sync
by marking the current task iff it uses the async_schedule() machinery.
however, if the part of the driver's probe is called through a worker
thread the bookeeping fails to mark the correct task as having used the
async machinery.

this is a workaround for the common case that we're already running
on the correct cpu. however, it seems sort of reasonable to not use
the worker thread if we don't have to.

Tested:
- checked on vebmy2 (ibis + satasquatch) which is where the original issue
  was discovered.
- checked on fdha347 (ikaria + loggerhead + satasquatch) to show that
  nothing changed.

Change-Id: Ibe8996cf652735c74a9e06ba9fd03118078395bd
Google-Bug-Id: 12632867
Signed-off-by: peter chang <dpf@xxxxxxxxxx>
---
 drivers/pci/pci-driver.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index e6515e2..9f7e1e9 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -243,6 +243,7 @@ struct drv_dev_and_id {
 	struct pci_driver *drv;
 	struct pci_dev *dev;
 	const struct pci_device_id *id;
+	unsigned int task_flags;
 };
 
 static long local_pci_probe(void *_ddi)
@@ -267,7 +268,8 @@ static long local_pci_probe(void *_ddi)
 	if (rc) {
 		pci_dev->driver = NULL;
 		pm_runtime_put_sync(dev);
-	}
+	} else if (current)
+		ddi->task_flags = current->flags;
 	return rc;
 }
 
@@ -275,7 +277,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
 			  const struct pci_device_id *id)
 {
 	int error, node;
-	struct drv_dev_and_id ddi = { drv, dev, id };
+	struct drv_dev_and_id ddi = { drv, dev, id, 0 };
 
 	/* Execute driver initialization on node where the device's
 	   bus is attached to.  This way the driver likely allocates
@@ -287,9 +289,16 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
 
 		get_online_cpus();
 		cpu = cpumask_any_and(cpumask_of_node(node), cpu_online_mask);
-		if (cpu < nr_cpu_ids)
+		/* try not to queue work if we're already on the target cpu */
+		if (cpu < nr_cpu_ids && cpu != get_cpu()) {
 			error = work_on_cpu(cpu, local_pci_probe, &ddi);
-		else
+			/* copy out some task flags for the module loading
+			 * case.
+			 */
+			if (!error && current)
+				current->flags |= (ddi.task_flags &
+						   PF_USED_ASYNC);
+		} else
 			error = local_pci_probe(&ddi);
 		put_online_cpus();
 	} else
-- 
1.8.5.3


[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux