memstick: use fully asynchronous request processing

Instead of using a separate thread to pump requests from block layer queue
to memstick, do so inline, utilizing the callback design of the memstick.

[akpm@linux-foundation.org: fix warnings]
Signed-off-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index 1445876..d32d6ad 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -71,6 +71,7 @@
 	struct tifm_dev         *dev;
 	struct timer_list       timer;
 	struct memstick_request *req;
+	struct tasklet_struct   notify;
 	unsigned int            mode_mask;
 	unsigned int            block_pos;
 	unsigned long           timeout_jiffies;
@@ -455,40 +456,45 @@
 	return;
 }
 
-static void tifm_ms_request(struct memstick_host *msh)
+static void tifm_ms_req_tasklet(unsigned long data)
 {
+	struct memstick_host *msh = (struct memstick_host *)data;
 	struct tifm_ms *host = memstick_priv(msh);
 	struct tifm_dev *sock = host->dev;
 	unsigned long flags;
 	int rc;
 
 	spin_lock_irqsave(&sock->lock, flags);
-	if (host->req) {
-		printk(KERN_ERR "%s : unfinished request detected\n",
-		       sock->dev.bus_id);
-		spin_unlock_irqrestore(&sock->lock, flags);
-		tifm_eject(host->dev);
-		return;
-	}
+	if (!host->req) {
+		if (host->eject) {
+			do {
+				rc = memstick_next_req(msh, &host->req);
+				if (!rc)
+					host->req->error = -ETIME;
+			} while (!rc);
+			spin_unlock_irqrestore(&sock->lock, flags);
+			return;
+		}
 
-	if (host->eject) {
 		do {
 			rc = memstick_next_req(msh, &host->req);
-			if (!rc)
-				host->req->error = -ETIME;
-		} while (!rc);
-		spin_unlock_irqrestore(&sock->lock, flags);
-		return;
+		} while (!rc && tifm_ms_issue_cmd(host));
 	}
-
-	do {
-		rc = memstick_next_req(msh, &host->req);
-	} while (!rc && tifm_ms_issue_cmd(host));
-
 	spin_unlock_irqrestore(&sock->lock, flags);
+}
+
+static void tifm_ms_dummy_submit(struct memstick_host *msh)
+{
 	return;
 }
 
+static void tifm_ms_submit_req(struct memstick_host *msh)
+{
+	struct tifm_ms *host = memstick_priv(msh);
+
+	tasklet_schedule(&host->notify);
+}
+
 static int tifm_ms_set_param(struct memstick_host *msh,
 			     enum memstick_param param,
 			     int value)
@@ -569,8 +575,9 @@
 	host->timeout_jiffies = msecs_to_jiffies(1000);
 
 	setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host);
+	tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh);
 
-	msh->request = tifm_ms_request;
+	msh->request = tifm_ms_submit_req;
 	msh->set_param = tifm_ms_set_param;
 	sock->card_event = tifm_ms_card_event;
 	sock->data_event = tifm_ms_data_event;
@@ -592,6 +599,8 @@
 	int rc = 0;
 	unsigned long flags;
 
+	msh->request = tifm_ms_dummy_submit;
+	tasklet_kill(&host->notify);
 	spin_lock_irqsave(&sock->lock, flags);
 	host->eject = 1;
 	if (host->req) {