msm: sysmon: Handle races between probe/removal and API calls.
It is possible that clients of the sysmon may call its APIs
before the associated device has probed, after it has been
removed, or while it is in the process of being added or
removed. Handle these scenarios and return -ENODEV when
external APIs are called at illegal times.
Change-Id: I286fcc359bc221f1a501c24ffc525949928366e0
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
diff --git a/arch/arm/mach-msm/sysmon.c b/arch/arm/mach-msm/sysmon.c
index 02ba5ea..112daca 100644
--- a/arch/arm/mach-msm/sysmon.c
+++ b/arch/arm/mach-msm/sysmon.c
@@ -43,6 +43,7 @@
struct completion resp_ready;
char rx_buf[RX_BUF_SIZE];
enum transports transport;
+ struct device *dev;
};
static struct sysmon_subsys subsys[SYSMON_NUM_SS] = {
@@ -138,6 +139,9 @@
char tx_buf[TX_BUF_SIZE];
int ret;
+ if (ss->dev == NULL)
+ return -ENODEV;
+
if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS ||
notif < 0 || notif >= SUBSYS_NOTIF_TYPE_COUNT ||
event_ss == NULL)
@@ -178,6 +182,9 @@
size_t prefix_len = ARRAY_SIZE(expect) - 1;
int ret;
+ if (ss->dev == NULL)
+ return -ENODEV;
+
if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS)
return -EINVAL;
@@ -214,6 +221,9 @@
size_t prefix_len = ARRAY_SIZE(expect) - 1;
int ret;
+ if (ss->dev == NULL)
+ return -ENODEV;
+
if (dest_ss < 0 || dest_ss >= SYSMON_NUM_SS ||
buf == NULL || len == 0)
return -EINVAL;
@@ -293,6 +303,7 @@
default:
return -EINVAL;
}
+ ss->dev = &pdev->dev;
return 0;
}
@@ -301,6 +312,9 @@
{
struct sysmon_subsys *ss = &subsys[pdev->id];
+ ss->dev = NULL;
+
+ mutex_lock(&ss->lock);
switch (ss->transport) {
case TRANSPORT_SMD:
smd_close(ss->chan);
@@ -309,6 +323,7 @@
hsic_sysmon_close(HSIC_SYSMON_DEV_EXT_MODEM);
break;
}
+ mutex_unlock(&ss->lock);
return 0;
}