All of lore.kernel.org
 help / color / mirror / Atom feed
From: Carlos Aguiar <carlos.aguiar@indt.org.br>
To: ext Pierre Ossman <drzeus-list@drzeus.cx>
Cc: Tony Lindgren <tony@atomide.com>, linux-kernel@vger.kernel.org
Subject: [PATCH 14/18] MMC: OMAP: Use tasklet instead of workqueue for cover switch notification
Date: Wed, 26 Mar 2008 16:09:42 -0400	[thread overview]
Message-ID: <47EAAD86.2060904@indt.org.br> (raw)
In-Reply-To: <20080324132631.1e0d2125@mjolnir.drzeus.cx>

From: Jarkko Lavinen <jarkko.lavinen@nokia.com>

The cover waitqueue is occasionally scheduled twice from timer
and the interrupt and oops follows. It would have been possible
to fix this problem with spinlocks but using tasklet was a dropin
solution with no need for locking.

This path also adds some cleanups.

Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
---
 drivers/mmc/host/omap.c |   67 ++++++++++++++++++++++++++++-------------------
 1 files changed, 40 insertions(+), 27 deletions(-)

diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 0e7ceb0..f97f390 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -94,7 +94,7 @@
 
 /* Specifies how often in millisecs to poll for card status changes
  * when the cover switch is open */
-#define OMAP_MMC_SWITCH_POLL_DELAY	500
+#define OMAP_MMC_COVER_POLL_DELAY	500
 
 struct mmc_omap_host;
 
@@ -106,8 +106,8 @@ struct mmc_omap_slot {
 	unsigned int		fclk_freq;
 	unsigned		powered:1;
 
-	struct work_struct      switch_work;
-	struct timer_list       switch_timer;
+	struct tasklet_struct	cover_tasklet;
+	struct timer_list       cover_timer;
 	unsigned		cover_open;
 
 	struct mmc_request      *mrq;
@@ -740,40 +740,51 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-void omap_mmc_notify_cover_event(struct device *dev, int slot, int is_closed)
+void omap_mmc_notify_cover_event(struct device *dev, int num, int is_closed)
 {
+	int cover_open;
 	struct mmc_omap_host *host = dev_get_drvdata(dev);
+	struct mmc_omap_slot *slot = host->slots[num];
 
-	BUG_ON(slot >= host->nr_slots);
+	BUG_ON(num >= host->nr_slots);
 
 	/* Other subsystems can call in here before we're initialised. */
-	if (host->nr_slots == 0 || !host->slots[slot])
+	if (host->nr_slots == 0 || !host->slots[num])
 		return;
 
-	schedule_work(&host->slots[slot]->switch_work);
+	cover_open = mmc_omap_cover_is_open(slot);
+	if (cover_open != slot->cover_open) {
+		slot->cover_open = cover_open;
+		sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
+	}
+
+	tasklet_hi_schedule(&slot->cover_tasklet);
 }
 
-static void mmc_omap_switch_timer(unsigned long arg)
+static void mmc_omap_cover_timer(unsigned long arg)
 {
 	struct mmc_omap_slot *slot = (struct mmc_omap_slot *) arg;
-
-	schedule_work(&slot->switch_work);
+	tasklet_schedule(&slot->cover_tasklet);
 }
 
-static void mmc_omap_cover_handler(struct work_struct *work)
+static void mmc_omap_cover_handler(unsigned long param)
 {
-	struct mmc_omap_slot *slot = container_of(work, struct mmc_omap_slot,
-						  switch_work);
-	int cover_open;
+	struct mmc_omap_slot *slot = (struct mmc_omap_slot *)param;
+	int cover_open = mmc_omap_cover_is_open(slot);
 
-	cover_open = mmc_omap_cover_is_open(slot);
-	if (cover_open != slot->cover_open) {
-		sysfs_notify(&slot->mmc->class_dev.kobj, NULL, "cover_switch");
-		slot->cover_open = cover_open;
-		dev_info(mmc_dev(slot->mmc), "cover is now %s\n",
-			 cover_open ? "open" : "closed");
-	}
-	mmc_detect_change(slot->mmc, slot->id);
+	mmc_detect_change(slot->mmc, 0);
+	if (!cover_open)
+		return;
+
+	/*
+	 * If no card is inserted, we postpone polling until
+	 * the cover has been closed.
+	 */
+	if (slot->mmc->card == NULL || !mmc_card_present(slot->mmc->card))
+		return;
+
+	mod_timer(&slot->cover_timer,
+		  jiffies + msecs_to_jiffies(OMAP_MMC_COVER_POLL_DELAY));
 }
 
 /* Prepare to transfer the next segment of a scatterlist */
@@ -1237,10 +1248,11 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id)
 		if (r < 0)
 			goto err_remove_slot_name;
 
-		INIT_WORK(&slot->switch_work, mmc_omap_cover_handler);
-		setup_timer(&slot->switch_timer, mmc_omap_switch_timer,
-			    (unsigned long) slot);
-		schedule_work(&slot->switch_work);
+		setup_timer(&slot->cover_timer, mmc_omap_cover_timer,
+			    (unsigned long)slot);
+		tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler,
+			     (unsigned long)slot);
+		tasklet_schedule(&slot->cover_tasklet);
 	}
 
 	return 0;
@@ -1263,7 +1275,8 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
 	if (slot->pdata->get_cover_state != NULL)
 		device_remove_file(&mmc->class_dev, &dev_attr_cover_switch);
 
-	del_timer_sync(&slot->switch_timer);
+	tasklet_kill(&slot->cover_tasklet);
+	del_timer_sync(&slot->cover_timer);
 	flush_scheduled_work();
 
 	mmc_remove_host(mmc);
-- 1.5.3.GIT


  parent reply	other threads:[~2008-03-26 20:17 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-14 19:35 [PATCH 00/18] MMC: OMAP: Sync MMC OMAP driver with mainline tree Carlos Aguiar
2008-03-24 12:26 ` Pierre Ossman
2008-03-26 20:08   ` Carlos Aguiar
2008-03-30 16:10     ` Pierre Ossman
2008-03-26 20:08   ` [PATCH 01/18] MMC: OMAP: Remove some opcodes from host driver Carlos Aguiar
2008-03-26 20:08   ` [PATCH 02/18] MMC: OMAP: Remove extra divisor increase Carlos Aguiar
2008-03-26 20:08   ` [PATCH 03/18] MMC: OMAP: Fix the BYTEBLOCK capability removal Carlos Aguiar
2008-03-26 20:08   ` [PATCH 04/18] MMC: OMAP: Remove cover switch handling to allow adding multislot support Carlos Aguiar
2008-03-26 20:08   ` [PATCH 05/18] MMC: OMAP: Introduce new multislot structure and change driver to use it Carlos Aguiar
2008-03-26 20:09   ` [PATCH 06/18] MMC: OMAP: Add back cover switch support Carlos Aguiar
2008-03-26 20:09   ` [PATCH 07/18] MMC: OMAP: New release dma and abort xfer functions Carlos Aguiar
2008-03-26 20:09   ` [PATCH 08/18] MMC: OMAP: Fix timeout calculation for MMC multislot support Carlos Aguiar
2008-03-26 20:09   ` [PATCH 09/18] MMC: OMAP: Power functions modified to " Carlos Aguiar
2008-03-26 20:09   ` [PATCH 10/18] MMC: OMAP: General cleanup for " Carlos Aguiar
2008-03-26 20:09   ` [PATCH 11/18] MMC: OMAP: Abort stuck commands Carlos Aguiar
2008-03-26 20:09   ` [PATCH 12/18] MMC: OMAP: Using setup_timer instead of init_timer Carlos Aguiar
2008-03-26 20:09   ` [PATCH 13/18] MMC: OMAP: Check the get_cover_state function pointer if not set Carlos Aguiar
2008-03-26 20:09   ` Carlos Aguiar [this message]
2008-03-26 20:09   ` [PATCH 15/18] MMC: OMAP: Move failing command abortion to workqueue Carlos Aguiar
2008-03-26 20:09   ` [PATCH 16/18] MMC: OMAP: Lazy clock shutdown Carlos Aguiar
2008-03-26 20:09   ` [PATCH 17/18] MMC: OMAP: Start new commands from work queue instead of irq Carlos Aguiar
2008-03-26 20:10   ` [PATCH 18/18] MMC: OMAP: Do not busy wait for end of command for ever Carlos Aguiar
  -- strict thread matches above, loose matches on Subject: below --
2008-03-14 19:36 [PATCH 14/18] MMC: OMAP: Use tasklet instead of workqueue for cover switch notification Carlos Aguiar
2008-01-28 19:08 Carlos Aguiar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=47EAAD86.2060904@indt.org.br \
    --to=carlos.aguiar@indt.org.br \
    --cc=drzeus-list@drzeus.cx \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tony@atomide.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.