msm: sdio: add support to sdio_close on SDIO_SMEM channel

Signed-off-by: Maya Erez <merez@codeaurora.org>
diff --git a/arch/arm/mach-msm/sdio_smem.c b/arch/arm/mach-msm/sdio_smem.c
index 4da8199..adc360e 100644
--- a/arch/arm/mach-msm/sdio_smem.c
+++ b/arch/arm/mach-msm/sdio_smem.c
@@ -25,6 +25,7 @@
 static DECLARE_WORK(work_read, sdio_smem_read);
 static DECLARE_WAIT_QUEUE_HEAD(waitq);
 static int bytes_avail;
+static int sdio_ch_opened;
 
 static void sdio_smem_release(struct device *dev)
 {
@@ -39,22 +40,26 @@
 	int read_avail;
 	char *data = client.buf;
 
+	if (!sdio_ch_opened)
+		return;
+
 	read_avail = sdio_read_avail(channel);
 	if (read_avail > bytes_avail ||
 		read_avail < 0) {
 		pr_err("Error: read_avail=%d bytes_avail=%d\n",
 			read_avail, bytes_avail);
-		client.cb_func(SDIO_SMEM_EVENT_READ_ERR);
-		return;
+		goto read_err;
 	}
 
+	if (read_avail == 0)
+		return;
+
 	err = sdio_read(channel,
 			&data[client.size - bytes_avail],
 			read_avail);
-	if (err < 0) {
+	if (err) {
 		pr_err("sdio_read error (%d)", err);
-		client.cb_func(SDIO_SMEM_EVENT_READ_ERR);
-		return;
+		goto read_err;
 	}
 
 	bytes_avail -= read_avail;
@@ -67,6 +72,13 @@
 	}
 	if (err)
 		pr_err("error (%d) on callback\n", err);
+
+	return;
+
+read_err:
+	if (sdio_ch_opened)
+		client.cb_func(SDIO_SMEM_EVENT_READ_ERR);
+	return;
 }
 
 static void sdio_smem_notify(void *priv, unsigned event)
@@ -93,8 +105,10 @@
 	if (!workq)
 		return -ENOMEM;
 
+	sdio_ch_opened = 1;
 	err = sdio_open("SDIO_SMEM", &channel, NULL, sdio_smem_notify);
-	if (err < 0) {
+	if (err) {
+		sdio_ch_opened = 0;
 		pr_err("sdio_open error (%d)\n", err);
 		destroy_workqueue(workq);
 		return err;
@@ -105,12 +119,22 @@
 
 int sdio_smem_unregister_client(void)
 {
+	int err = 0;
+
+	sdio_ch_opened = 0;
+	err = sdio_close(channel);
+	if (err) {
+		pr_err("sdio_close error (%d)\n", err);
+		return err;
+	}
+	pr_debug("SDIO SMEM channel closed\n");
+	flush_workqueue(workq);
 	destroy_workqueue(workq);
 	bytes_avail = 0;
 	client.buf = NULL;
 	client.cb_func = NULL;
 	client.size = 0;
-	pr_debug("SDIO SMEM channel closed\n");
+
 	return 0;
 }
 
@@ -127,6 +151,7 @@
 {
 	platform_device_unregister(&client.plat_dev);
 	memset(&client, 0, sizeof(client));
+	sdio_ch_opened = 0;
 	return 0;
 }
 static struct platform_driver sdio_smem_drv = {