Merge "diag: Move registration cleanup function to work queue" into msm-3.4
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index c0b82df..b70efe3 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -28,11 +28,6 @@
int signal_type;
};
-#define DIAG_CON_APSS (0x0001) /* Bit mask for APSS */
-#define DIAG_CON_MPSS (0x0002) /* Bit mask for MPSS */
-#define DIAG_CON_LPASS (0x0004) /* Bit mask for LPASS */
-#define DIAG_CON_WCNSS (0x0008) /* Bit mask for WCNSS */
-
enum {
DIAG_DCI_NO_ERROR = 1001, /* No error */
DIAG_DCI_NO_REG, /* Could not register */
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 2f356f0..95a85f2 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -58,6 +58,11 @@
#define DIAG_CTRL_MSG_F3_MASK 11
#define CONTROL_CHAR 0x7E
+#define DIAG_CON_APSS (0x0001) /* Bit mask for APSS */
+#define DIAG_CON_MPSS (0x0002) /* Bit mask for MPSS */
+#define DIAG_CON_LPASS (0x0004) /* Bit mask for LPASS */
+#define DIAG_CON_WCNSS (0x0008) /* Bit mask for WCNSS */
+
/* Maximum number of pkt reg supported at initialization*/
extern unsigned int diag_max_reg;
extern unsigned int diag_threshold_reg;
@@ -224,6 +229,9 @@
struct work_struct diag_qdsp_mask_update_work;
struct work_struct diag_wcnss_mask_update_work;
struct work_struct diag_read_smd_dci_work;
+ struct work_struct diag_clean_modem_reg_work;
+ struct work_struct diag_clean_lpass_reg_work;
+ struct work_struct diag_clean_wcnss_reg_work;
uint8_t *msg_masks;
uint8_t *log_masks;
int log_masks_length;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 547f42f..240a514 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1268,6 +1268,12 @@
diag_read_smd_wcnss_cntl_work_fn);
INIT_WORK(&(driver->diag_read_smd_dci_work),
diag_read_smd_dci_work_fn);
+ INIT_WORK(&(driver->diag_clean_modem_reg_work),
+ diag_clean_modem_reg_fn);
+ INIT_WORK(&(driver->diag_clean_lpass_reg_work),
+ diag_clean_lpass_reg_fn);
+ INIT_WORK(&(driver->diag_clean_wcnss_reg_work),
+ diag_clean_wcnss_reg_fn);
diag_debugfs_init();
diagfwd_init();
diagfwd_cntl_init();
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 384c1bf..b228276 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1735,8 +1735,8 @@
static void diag_smd_notify(void *ctxt, unsigned event)
{
if (event == SMD_EVENT_CLOSE) {
- pr_info("diag: clean modem registration\n");
- diag_clear_reg(MODEM_PROC);
+ queue_work(driver->diag_cntl_wq,
+ &(driver->diag_clean_modem_reg_work));
driver->ch = 0;
return;
} else if (event == SMD_EVENT_OPEN) {
@@ -1750,8 +1750,8 @@
static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
{
if (event == SMD_EVENT_CLOSE) {
- pr_info("diag: clean lpass registration\n");
- diag_clear_reg(QDSP_PROC);
+ queue_work(driver->diag_cntl_wq,
+ &(driver->diag_clean_lpass_reg_work));
driver->chqdsp = 0;
return;
} else if (event == SMD_EVENT_OPEN) {
@@ -1765,8 +1765,8 @@
static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
{
if (event == SMD_EVENT_CLOSE) {
- pr_info("diag: clean wcnss registration\n");
- diag_clear_reg(WCNSS_PROC);
+ queue_work(driver->diag_cntl_wq,
+ &(driver->diag_clean_wcnss_reg_work));
driver->ch_wcnss = 0;
return;
} else if (event == SMD_EVENT_OPEN) {
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index de1a5b5..95abd21 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -20,9 +20,34 @@
#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#endif
-
+/* tracks which peripheral is undergoing SSR */
+static uint16_t reg_dirty;
#define HDR_SIZ 8
+void diag_clean_modem_reg_fn(struct work_struct *work)
+{
+ pr_debug("diag: clean modem registration\n");
+ reg_dirty |= DIAG_CON_MPSS;
+ diag_clear_reg(MODEM_PROC);
+ reg_dirty ^= DIAG_CON_MPSS;
+}
+
+void diag_clean_lpass_reg_fn(struct work_struct *work)
+{
+ pr_debug("diag: clean lpass registration\n");
+ reg_dirty |= DIAG_CON_LPASS;
+ diag_clear_reg(QDSP_PROC);
+ reg_dirty ^= DIAG_CON_LPASS;
+}
+
+void diag_clean_wcnss_reg_fn(struct work_struct *work)
+{
+ pr_debug("diag: clean wcnss registration\n");
+ reg_dirty |= DIAG_CON_WCNSS;
+ diag_clear_reg(WCNSS_PROC);
+ reg_dirty ^= DIAG_CON_WCNSS;
+}
+
void diag_smd_cntl_notify(void *ctxt, unsigned event)
{
int r1, r2;
@@ -105,6 +130,8 @@
struct bindpkt_params *temp;
void *buf = NULL;
smd_channel_t *smd_ch = NULL;
+ /* tracks which peripheral is sending registration */
+ uint16_t reg_mask = 0;
if (pkt_params == NULL) {
pr_alert("diag: Memory allocation failure\n");
@@ -114,12 +141,15 @@
if (proc_num == MODEM_PROC) {
buf = driver->buf_in_cntl;
smd_ch = driver->ch_cntl;
+ reg_mask = DIAG_CON_MPSS;
} else if (proc_num == QDSP_PROC) {
buf = driver->buf_in_qdsp_cntl;
smd_ch = driver->chqdsp_cntl;
+ reg_mask = DIAG_CON_LPASS;
} else if (proc_num == WCNSS_PROC) {
buf = driver->buf_in_wcnss_cntl;
smd_ch = driver->ch_wcnss_cntl;
+ reg_mask = DIAG_CON_WCNSS;
}
if (!smd_ch || !buf) {
@@ -180,8 +210,16 @@
temp -= pkt_params->count;
pkt_params->params = temp;
flag = 1;
- diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
- (unsigned long)pkt_params);
+ /* peripheral undergoing SSR should not
+ * record new registration
+ */
+ if (!(reg_dirty & reg_mask))
+ diagchar_ioctl(NULL,
+ DIAG_IOCTL_COMMAND_REG, (unsigned long)
+ pkt_params);
+ else
+ pr_err("diag: drop reg proc %d\n",
+ proc_num);
kfree(temp);
}
buf = buf + HDR_SIZ + data_len;
@@ -275,6 +313,7 @@
void diagfwd_cntl_init(void)
{
+ reg_dirty = 0;
driver->polling_reg_flag = 0;
driver->diag_cntl_wq = create_singlethread_workqueue("diag_cntl_wq");
if (driver->buf_in_cntl == NULL) {
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 743ddc1..59e5e6b 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -85,7 +85,9 @@
void diag_smd_cntl_notify(void *ctxt, unsigned event);
void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event);
void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event);
-
+void diag_clean_modem_reg_fn(struct work_struct *);
+void diag_clean_lpass_reg_fn(struct work_struct *);
+void diag_clean_wcnss_reg_fn(struct work_struct *);
void diag_debugfs_init(void);
void diag_debugfs_cleanup(void);