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 = {