diag: Add diag changes to bring diag up to date
diag on the A-Family mainline is out of date. Create a commit
to bring diag up to date.
Change-Id: Ie24780b4b83a3cb378326357d70785a590167447
Signed-off-by: Dixon Peterson <dixonp@codeaurora.org>
diff --git a/arch/arm/mach-msm/include/mach/usbdiag.h b/arch/arm/mach-msm/include/mach/usbdiag.h
index d1e3605..d9320c3 100644
--- a/arch/arm/mach-msm/include/mach/usbdiag.h
+++ b/arch/arm/mach-msm/include/mach/usbdiag.h
@@ -1,6 +1,6 @@
/* include/asm-arm/arch-msm/usbdiag.h
*
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010, 2012, The Linux Foundation. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -21,8 +21,11 @@
#ifndef _DRIVERS_USB_DIAG_H_
#define _DRIVERS_USB_DIAG_H_
+#include <linux/err.h>
+
#define DIAG_LEGACY "diag"
#define DIAG_MDM "diag_mdm"
+#define DIAG_QSC "diag_qsc"
#define USB_DIAG_CONNECT 0
#define USB_DIAG_DISCONNECT 1
@@ -45,6 +48,7 @@
void *priv_usb;
};
+#ifdef CONFIG_USB_G_ANDROID
struct usb_diag_ch *usb_diag_open(const char *name, void *priv,
void (*notify)(void *, unsigned, struct diag_request *));
void usb_diag_close(struct usb_diag_ch *ch);
@@ -52,7 +56,32 @@
void usb_diag_free_req(struct usb_diag_ch *ch);
int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req);
int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req);
-
-int diag_read_from_cb(unsigned char * , int);
-
+#else
+static inline struct usb_diag_ch *usb_diag_open(const char *name, void *priv,
+ void (*notify)(void *, unsigned, struct diag_request *))
+{
+ return ERR_PTR(-ENODEV);
+}
+static inline void usb_diag_close(struct usb_diag_ch *ch)
+{
+}
+static inline
+int usb_diag_alloc_req(struct usb_diag_ch *ch, int n_write, int n_read)
+{
+ return -ENODEV;
+}
+static inline void usb_diag_free_req(struct usb_diag_ch *ch)
+{
+}
+static inline
+int usb_diag_read(struct usb_diag_ch *ch, struct diag_request *d_req)
+{
+ return -ENODEV;
+}
+static inline
+int usb_diag_write(struct usb_diag_ch *ch, struct diag_request *d_req)
+{
+ return -ENODEV;
+}
+#endif /* CONFIG_USB_G_ANDROID */
#endif /* _DRIVERS_USB_DIAG_H_ */
diff --git a/drivers/char/diag/Kconfig b/drivers/char/diag/Kconfig
index 8f8707f..91fcdfc 100644
--- a/drivers/char/diag/Kconfig
+++ b/drivers/char/diag/Kconfig
@@ -30,9 +30,9 @@
SDIO Transport Layer for DIAG Router
endmenu
-menu "HSIC support for DIAG"
+menu "HSIC/SMUX support for DIAG"
-config DIAG_BRIDGE_CODE
+config DIAGFWD_BRIDGE_CODE
depends on USB_QCOM_DIAG_BRIDGE
default y
bool "Enable QSC/9K DIAG traffic over SMUX/HSIC"
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index 6ecc970..c9204ea 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_DIAG_CHAR) := diagchar.o
obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
-obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_hsic.o
-obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_smux.o
+obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_bridge.o
+obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_hsic.o
+obj-$(CONFIG_DIAGFWD_BRIDGE_CODE) += diagfwd_smux.o
diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 24fc99a..d4b1856 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -38,73 +38,48 @@
struct mutex dci_log_mask_mutex;
struct mutex dci_event_mask_mutex;
-smd_channel_t *ch_dci_temp;
-
#define DCI_CHK_CAPACITY(entry, new_data_len) \
((entry->data_len + new_data_len > entry->total_capacity) ? 1 : 0) \
-static void diag_smd_dci_send_req(int proc_num)
+/* Process the data read from the smd dci channel */
+int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf,
+ int recd_bytes)
{
- void *buf = NULL;
- smd_channel_t *smd_ch = NULL;
- int recd_bytes, read_bytes, dci_pkt_len, i;
+ int read_bytes, dci_pkt_len, i;
uint8_t recv_pkt_cmd_code;
- if (driver->in_busy_dci)
- return;
-
- if (proc_num == MODEM_PROC) {
- buf = driver->buf_in_dci;
- smd_ch = driver->ch_dci;
+ /* Each SMD read can have multiple DCI packets */
+ read_bytes = 0;
+ while (read_bytes < recd_bytes) {
+ /* read actual length of dci pkt */
+ dci_pkt_len = *(uint16_t *)(buf+2);
+ /* process one dci packet */
+ pr_debug("diag: bytes read = %d, single dci pkt len = %d\n",
+ read_bytes, dci_pkt_len);
+ /* print_hex_dump(KERN_DEBUG, "Single DCI packet :",
+ DUMP_PREFIX_ADDRESS, 16, 1, buf, 5 + dci_pkt_len, 1);*/
+ recv_pkt_cmd_code = *(uint8_t *)(buf+4);
+ if (recv_pkt_cmd_code == LOG_CMD_CODE)
+ extract_dci_log(buf+4);
+ else if (recv_pkt_cmd_code == EVENT_CMD_CODE)
+ extract_dci_events(buf+4);
+ else
+ extract_dci_pkt_rsp(buf); /* pkt response */
+ read_bytes += 5 + dci_pkt_len;
+ buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
}
-
- if (!smd_ch || !buf)
- return;
-
- recd_bytes = smd_read_avail(smd_ch);
- if (recd_bytes > IN_BUF_SIZE) {
- if (recd_bytes < MAX_IN_BUF_SIZE) {
- pr_err("diag: SMD DCI sending pkt upto %d bytes",
- recd_bytes);
- buf = krealloc(buf, recd_bytes, GFP_KERNEL);
- } else {
- pr_err("diag: DCI pkt > %d bytes", MAX_IN_BUF_SIZE);
- return;
+ /* wake up all sleeping DCI clients which have some data */
+ for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+ if (driver->dci_client_tbl[i].client &&
+ driver->dci_client_tbl[i].data_len) {
+ smd_info->in_busy_1 = 1;
+ diag_update_sleeping_process(
+ driver->dci_client_tbl[i].client->tgid,
+ DCI_DATA_TYPE);
}
}
- if (buf && recd_bytes > 0) {
- smd_read(smd_ch, buf, recd_bytes);
- pr_debug("diag: data received %d bytes\n", recd_bytes);
- /* Each SMD read can have multiple DCI packets */
- read_bytes = 0;
- while (read_bytes < recd_bytes) {
- /* read actual length of dci pkt */
- dci_pkt_len = *(uint16_t *)(buf+2);
- /* process one dci packet */
- pr_debug("diag: bytes read = %d, single dci pkt len = %d\n",
- read_bytes, dci_pkt_len);
- /* print_hex_dump(KERN_DEBUG, "Single DCI packet :",
- DUMP_PREFIX_ADDRESS, 16, 1, buf, 5 + dci_pkt_len, 1);*/
- recv_pkt_cmd_code = *(uint8_t *)(buf+4);
- if (recv_pkt_cmd_code == LOG_CMD_CODE)
- extract_dci_log(buf+4);
- else if (recv_pkt_cmd_code == EVENT_CMD_CODE)
- extract_dci_events(buf+4);
- else
- extract_dci_pkt_rsp(buf); /* pkt response */
- read_bytes += 5 + dci_pkt_len;
- buf += 5 + dci_pkt_len; /* advance to next DCI pkt */
- }
- /* wake up all sleeping DCI clients which have some data */
- for (i = 0; i < MAX_DCI_CLIENTS; i++)
- if (driver->dci_client_tbl[i].client &&
- driver->dci_client_tbl[i].data_len) {
- driver->in_busy_dci = 1;
- diag_update_sleeping_process(
- driver->dci_client_tbl[i].client->tgid,
- DCI_DATA_TYPE);
- }
- }
+
+ return 0;
}
void extract_dci_pkt_rsp(unsigned char *buf)
@@ -163,7 +138,8 @@
buf+4+cmd_code_len, write_len);
entry->data_len += write_len;
/* delete immediate response entry */
- if (driver->buf_in_dci[8+cmd_code_len] != 0x80)
+ if (driver->smd_dci[MODEM_DATA].
+ buf_in_1[8+cmd_code_len] != 0x80)
driver->req_tracking_tbl[index].pid = 0;
break;
}
@@ -303,23 +279,22 @@
}
}
-void diag_read_smd_dci_work_fn(struct work_struct *work)
-{
- diag_smd_dci_send_req(MODEM_PROC);
-}
-
void diag_update_smd_dci_work_fn(struct work_struct *work)
{
+ struct diag_smd_info *smd_info = container_of(work,
+ struct diag_smd_info,
+ diag_notify_update_smd_work);
int i, j;
char dirty_bits[16];
uint8_t *client_log_mask_ptr;
uint8_t *log_mask_ptr;
int ret;
+ int index = smd_info->peripheral;
/* Update the peripheral(s) with the dci log and event masks */
/* If the cntl channel is not up, we can't update logs and events */
- if (!driver->ch_cntl)
+ if (!driver->smd_cntl[index].ch)
return;
memset(dirty_bits, 0, 16 * sizeof(uint8_t));
@@ -352,9 +327,11 @@
}
mutex_unlock(&dci_log_mask_mutex);
- ret = diag_send_dci_log_mask(driver->ch_cntl);
+ ret = diag_send_dci_log_mask(driver->smd_cntl[index].ch);
- ret = diag_send_dci_event_mask(driver->ch_cntl);
+ ret = diag_send_dci_event_mask(driver->smd_cntl[index].ch);
+
+ smd_info->notify_context = 0;
}
void diag_dci_notify_client(int peripheral_mask, int data)
@@ -380,41 +357,23 @@
} /* end of loop for all DCI clients */
}
-static void diag_smd_dci_notify(void *ctxt, unsigned event)
-{
- if (event == SMD_EVENT_CLOSE) {
- driver->ch_dci = 0;
- /* Notify the clients of the close */
- diag_dci_notify_client(DIAG_CON_MPSS, DIAG_STATUS_CLOSED);
- return;
- } else if (event == SMD_EVENT_OPEN) {
-
- if (ch_dci_temp)
- driver->ch_dci = ch_dci_temp;
-
- queue_work(driver->diag_dci_wq,
- &(driver->diag_update_smd_dci_work));
-
- /* Notify the clients of the open */
- diag_dci_notify_client(DIAG_CON_MPSS, DIAG_STATUS_OPEN);
- }
-
- queue_work(driver->diag_dci_wq, &(driver->diag_read_smd_dci_work));
-}
-
static int diag_dci_probe(struct platform_device *pdev)
{
int err = 0;
+ int index;
if (pdev->id == SMD_APPS_MODEM) {
- err = smd_open("DIAG_2", &driver->ch_dci, driver,
- diag_smd_dci_notify);
+ index = MODEM_DATA;
+ err = smd_open("DIAG_2", &driver->smd_dci[index].ch,
+ &driver->smd_dci[index],
+ diag_smd_notify);
+ driver->smd_dci[index].ch_save =
+ driver->smd_dci[index].ch;
if (err)
- pr_err("diag: cannot open DCI port, Id = %d, err ="
- " %d\n", pdev->id, err);
- else
- ch_dci_temp = driver->ch_dci;
+ pr_err("diag: In %s, cannot open DCI port, Id = %d, err: %d\n",
+ __func__, pdev->id, err);
}
+
return err;
}
@@ -422,6 +381,7 @@
int len, int index)
{
int i;
+ int status = 0;
/* remove UID from user space pkt before sending to peripheral */
buf = buf + 4;
@@ -439,15 +399,23 @@
driver->apps_dci_buf[9+len] = CONTROL_CHAR; /* end */
- if (entry.client_id == MODEM_PROC && driver->ch_dci) {
- smd_write(driver->ch_dci, driver->apps_dci_buf, len + 10);
- i = DIAG_DCI_NO_ERROR;
- } else {
+ for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
+ if (entry.client_id == driver->smd_dci[i].peripheral) {
+ if (driver->smd_dci[i].ch) {
+ smd_write(driver->smd_dci[i].ch,
+ driver->apps_dci_buf, len + 10);
+ status = DIAG_DCI_NO_ERROR;
+ }
+ break;
+ }
+ }
+
+ if (status != DIAG_DCI_NO_ERROR) {
pr_alert("diag: check DCI channel\n");
- i = DIAG_DCI_SEND_DATA_FAIL;
+ status = DIAG_DCI_SEND_DATA_FAIL;
}
mutex_unlock(&driver->dci_mutex);
- return i;
+ return status;
}
int diag_register_dci_transaction(int uid)
@@ -487,8 +455,9 @@
uint8_t *event_mask_ptr;
int offset = 0;
- if (!driver->ch_dci) {
- pr_err("diag: ch_dci not valid for dci updates\n");
+ if (!driver->smd_dci[MODEM_DATA].ch) {
+ pr_err("diag: DCI smd channel for peripheral %d not valid for dci updates\n",
+ driver->smd_dci[MODEM_DATA].peripheral);
return DIAG_DCI_SEND_DATA_FAIL;
}
@@ -613,7 +582,7 @@
ret = DIAG_DCI_NO_ERROR;
}
/* send updated mask to peripherals */
- ret = diag_send_dci_log_mask(driver->ch_cntl);
+ ret = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
} else if (*(int *)temp == DCI_EVENT_TYPE) {
/* find client id and table */
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
@@ -659,7 +628,7 @@
ret = DIAG_DCI_NO_ERROR;
}
/* send updated mask to peripherals */
- ret = diag_send_dci_event_mask(driver->ch_cntl);
+ ret = diag_send_dci_event_mask(driver->smd_cntl[MODEM_DATA].ch);
} else {
pr_alert("diag: Incorrect DCI transaction\n");
}
@@ -872,27 +841,19 @@
int diag_dci_init(void)
{
int success = 0;
-
- ch_dci_temp = NULL;
+ int i;
driver->dci_tag = 0;
driver->dci_client_id = 0;
driver->num_dci_client = 0;
- driver->in_busy_dci = 0;
mutex_init(&driver->dci_mutex);
mutex_init(&dci_log_mask_mutex);
mutex_init(&dci_event_mask_mutex);
- if (driver->buf_in_dci == NULL) {
- driver->buf_in_dci = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_dci == NULL)
- goto err;
- }
- if (driver->write_ptr_dci == NULL) {
- driver->write_ptr_dci = kzalloc(
- sizeof(struct diag_write_device), GFP_KERNEL);
- if (driver->write_ptr_dci == NULL)
- goto err;
- }
+ success = diag_smd_constructor(&driver->smd_dci[MODEM_DATA],
+ MODEM_DATA, SMD_DCI_TYPE);
+ if (!success)
+ goto err;
+
if (driver->req_tracking_tbl == NULL) {
driver->req_tracking_tbl = kzalloc(dci_max_reg *
sizeof(struct dci_pkt_req_tracking_tbl), GFP_KERNEL);
@@ -922,8 +883,8 @@
kfree(driver->req_tracking_tbl);
kfree(driver->dci_client_tbl);
kfree(driver->apps_dci_buf);
- kfree(driver->buf_in_dci);
- kfree(driver->write_ptr_dci);
+ for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++)
+ diag_smd_destructor(&driver->smd_dci[i]);
if (driver->diag_dci_wq)
destroy_workqueue(driver->diag_dci_wq);
return DIAG_DCI_NO_REG;
@@ -931,13 +892,14 @@
void diag_dci_exit(void)
{
- smd_close(driver->ch_dci);
- driver->ch_dci = 0;
+ int i;
+
+ for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++)
+ diag_smd_destructor(&driver->smd_dci[i]);
+
platform_driver_unregister(&msm_diag_dci_driver);
kfree(driver->req_tracking_tbl);
kfree(driver->dci_client_tbl);
kfree(driver->apps_dci_buf);
- kfree(driver->buf_in_dci);
- kfree(driver->write_ptr_dci);
destroy_workqueue(driver->diag_dci_wq);
}
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index 3f62e5e..af89ac8 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -78,8 +78,10 @@
int diag_dci_init(void);
void diag_dci_exit(void);
-void diag_read_smd_dci_work_fn(struct work_struct *);
void diag_update_smd_dci_work_fn(struct work_struct *);
+void diag_dci_notify_client(int peripheral_mask, int data);
+int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf,
+ int recd_bytes);
int diag_process_dci_transaction(unsigned char *buf, int len);
int diag_send_dci_pkt(struct diag_master_table entry, unsigned char *buf,
int len, int index);
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 0048007..d852d75 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -16,6 +16,7 @@
#include <linux/debugfs.h>
#include "diagchar.h"
#include "diagfwd.h"
+#include "diagfwd_bridge.h"
#define DEBUG_BUF_SIZE 4096
static struct dentry *diag_dbgfs_dent;
@@ -47,34 +48,34 @@
"Check Polling Response: %d\n"
"polling_reg_flag: %d\n"
"uses device tree: %d\n"
- "in_busy_1: %d\n"
- "in_busy_2: %d\n"
- "in_busy_lpass_1: %d\n"
- "in_busy_lpass_2: %d\n"
- "in_busy_wcnss_1: %d\n"
- "in_busy_wcnss_2: %d\n"
- "in_busy_dci: %d\n"
+ "Modem in_busy_1: %d\n"
+ "Modem in_busy_2: %d\n"
+ "LPASS in_busy_1: %d\n"
+ "LPASS in_busy_2: %d\n"
+ "RIVA in_busy_1: %d\n"
+ "RIVA in_busy_2: %d\n"
+ "DCI Modem in_busy_1: %d\n"
"logging_mode: %d\n",
- (unsigned int)driver->ch,
- (unsigned int)driver->chlpass,
- (unsigned int)driver->ch_wcnss,
- (unsigned int)driver->ch_dci,
- (unsigned int)driver->ch_cntl,
- (unsigned int)driver->chlpass_cntl,
- (unsigned int)driver->ch_wcnss_cntl,
+ (unsigned int)driver->smd_data[MODEM_DATA].ch,
+ (unsigned int)driver->smd_data[LPASS_DATA].ch,
+ (unsigned int)driver->smd_data[WCNSS_DATA].ch,
+ (unsigned int)driver->smd_dci[MODEM_DATA].ch,
+ (unsigned int)driver->smd_cntl[MODEM_DATA].ch,
+ (unsigned int)driver->smd_cntl[LPASS_DATA].ch,
+ (unsigned int)driver->smd_cntl[WCNSS_DATA].ch,
chk_config_get_id(),
chk_apps_only(),
chk_apps_master(),
chk_polling_response(),
driver->polling_reg_flag,
driver->use_device_tree,
- driver->in_busy_1,
- driver->in_busy_2,
- driver->in_busy_lpass_1,
- driver->in_busy_lpass_2,
- driver->in_busy_wcnss_1,
- driver->in_busy_wcnss_2,
- driver->in_busy_dci,
+ driver->smd_data[MODEM_DATA].in_busy_1,
+ driver->smd_data[MODEM_DATA].in_busy_2,
+ driver->smd_data[LPASS_DATA].in_busy_1,
+ driver->smd_data[LPASS_DATA].in_busy_2,
+ driver->smd_data[WCNSS_DATA].in_busy_1,
+ driver->smd_data[WCNSS_DATA].in_busy_2,
+ driver->smd_dci[MODEM_DATA].in_busy_1,
driver->logging_mode);
#ifdef CONFIG_DIAG_OVER_USB
@@ -103,29 +104,49 @@
ret = scnprintf(buf, DEBUG_BUF_SIZE,
"Pending status for work_stucts:\n"
"diag_drain_work: %d\n"
- "diag_read_smd_work: %d\n"
- "diag_read_smd_cntl_work: %d\n"
- "diag_read_smd_lpass_work: %d\n"
- "diag_read_smd_lpass_cntl_work: %d\n"
- "diag_read_smd_wcnss_work: %d\n"
- "diag_read_smd_wcnss_cntl_work: %d\n"
- "diag_modem_mask_update_work: %d\n"
- "diag_lpass_mask_update_work: %d\n"
- "diag_wcnss_mask_update_work: %d\n"
- "diag_read_smd_dci_work: %d\n"
- "diag_update_smd_dci_work: %d\n",
+ "Modem data diag_read_smd_work: %d\n"
+ "LPASS data diag_read_smd_work: %d\n"
+ "RIVA data diag_read_smd_work: %d\n"
+ "Modem cntl diag_read_smd_work: %d\n"
+ "LPASS cntl diag_read_smd_work: %d\n"
+ "RIVA cntl diag_read_smd_work: %d\n"
+ "Modem dci diag_read_smd_work: %d\n"
+ "Modem data diag_notify_update_smd_work: %d\n"
+ "LPASS data diag_notify_update_smd_work: %d\n"
+ "RIVA data diag_notify_update_smd_work: %d\n"
+ "Modem cntl diag_notify_update_smd_work: %d\n"
+ "LPASS cntl diag_notify_update_smd_work: %d\n"
+ "RIVA cntl diag_notify_update_smd_work: %d\n"
+ "Modem dci diag_notify_update_smd_work: %d\n",
work_pending(&(driver->diag_drain_work)),
- work_pending(&(driver->diag_read_smd_work)),
- work_pending(&(driver->diag_read_smd_cntl_work)),
- work_pending(&(driver->diag_read_smd_lpass_work)),
- work_pending(&(driver->diag_read_smd_lpass_cntl_work)),
- work_pending(&(driver->diag_read_smd_wcnss_work)),
- work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
- work_pending(&(driver->diag_modem_mask_update_work)),
- work_pending(&(driver->diag_lpass_mask_update_work)),
- work_pending(&(driver->diag_wcnss_mask_update_work)),
- work_pending(&(driver->diag_read_smd_dci_work)),
- work_pending(&(driver->diag_update_smd_dci_work)));
+ work_pending(&(driver->smd_data[MODEM_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_data[LPASS_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_data[WCNSS_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_cntl[MODEM_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_cntl[LPASS_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_cntl[WCNSS_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_dci[MODEM_DATA].
+ diag_read_smd_work)),
+ work_pending(&(driver->smd_data[MODEM_DATA].
+ diag_notify_update_smd_work)),
+ work_pending(&(driver->smd_data[LPASS_DATA].
+ diag_notify_update_smd_work)),
+ work_pending(&(driver->smd_data[WCNSS_DATA].
+ diag_notify_update_smd_work)),
+ work_pending(&(driver->smd_cntl[MODEM_DATA].
+ diag_notify_update_smd_work)),
+ work_pending(&(driver->smd_cntl[LPASS_DATA].
+ diag_notify_update_smd_work)),
+ work_pending(&(driver->smd_cntl[WCNSS_DATA].
+ diag_notify_update_smd_work)),
+ work_pending(&(driver->smd_dci[MODEM_DATA].
+ diag_notify_update_smd_work)));
#ifdef CONFIG_DIAG_OVER_USB
ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
@@ -164,6 +185,15 @@
}
bytes_remaining = buf_size;
+
+ if (diag_dbgfs_table_index == 0) {
+ bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+ "Client ids: Modem: %d, LPASS: %d, "
+ "WCNSS: %d, APPS: %d\n",
+ MODEM_DATA, LPASS_DATA, WCNSS_DATA, APPS_DATA);
+ bytes_in_buffer += bytes_written;
+ }
+
for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
/* Do not process empty entries in the table */
if (driver->table[i].process_id == 0)
@@ -188,7 +218,7 @@
if (bytes_remaining < bytes_written)
break;
}
- diag_dbgfs_table_index = i;
+ diag_dbgfs_table_index = i+1;
*ppos = 0;
ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
@@ -197,8 +227,8 @@
return ret;
}
-#ifdef CONFIG_DIAG_BRIDGE_CODE
-static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+static ssize_t diag_dbgfs_read_bridge(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
char *buf;
@@ -222,13 +252,17 @@
"count_hsic_write_pool: %d\n"
"diag_hsic_pool: %x\n"
"diag_hsic_write_pool: %x\n"
- "write_len_mdm: %d\n"
+ "HSIC write_len: %d\n"
"num_hsic_buf_tbl_entries: %d\n"
- "usb_mdm_connected: %d\n"
- "diag_read_mdm_work: %d\n"
+ "HSIC usb_connected: %d\n"
+ "HSIC diag_read_work: %d\n"
"diag_read_hsic_work: %d\n"
"diag_disconnect_work: %d\n"
- "diag_usb_read_complete_work: %d\n",
+ "diag_usb_read_complete_work: %d\n"
+ "smux ch: %d\n"
+ "smux enabled %d\n"
+ "smux in busy %d\n"
+ "smux connected %d\n",
driver->hsic_ch,
driver->hsic_inited,
driver->hsic_device_enabled,
@@ -240,13 +274,17 @@
driver->count_hsic_write_pool,
(unsigned int)driver->diag_hsic_pool,
(unsigned int)driver->diag_hsic_write_pool,
- driver->write_len_mdm,
+ diag_bridge[HSIC].write_len,
driver->num_hsic_buf_tbl_entries,
- driver->usb_mdm_connected,
- work_pending(&(driver->diag_read_mdm_work)),
+ diag_bridge[HSIC].usb_connected,
+ work_pending(&(diag_bridge[HSIC].diag_read_work)),
work_pending(&(driver->diag_read_hsic_work)),
work_pending(&(driver->diag_disconnect_work)),
- work_pending(&(driver->diag_usb_read_complete_work)));
+ work_pending(&(diag_bridge[HSIC].usb_read_complete_work)),
+ driver->lcid,
+ driver->diag_smux_enabled,
+ driver->in_busy_smux,
+ driver->smux_connected);
ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
@@ -254,8 +292,8 @@
return ret;
}
-const struct file_operations diag_dbgfs_hsic_ops = {
- .read = diag_dbgfs_read_hsic,
+const struct file_operations diag_dbgfs_bridge_ops = {
+ .read = diag_dbgfs_read_bridge,
};
#endif
@@ -286,9 +324,9 @@
debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
&diag_dbgfs_workpending_ops);
-#ifdef CONFIG_DIAG_BRIDGE_CODE
- debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
- &diag_dbgfs_hsic_ops);
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ debugfs_create_file("bridge", 0444, diag_dbgfs_dent, 0,
+ &diag_dbgfs_bridge_ops);
#endif
diag_dbgfs_table_index = 0;
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 5316548..e8567db 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -26,6 +26,9 @@
#define ALL_SSID -1
#define MAX_SSID_PER_RANGE 100
+#define FEATURE_MASK_LEN_BYTES 1
+#define APPS_RESPOND_LOG_ON_DEMAND 0x04
+
struct mask_info {
int equip_id;
int num_items;
@@ -294,29 +297,24 @@
mutex_unlock(&driver->diagchar_mutex);
}
-void diag_modem_mask_update_fn(struct work_struct *work)
+void diag_mask_update_fn(struct work_struct *work)
{
- diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
- ALL_SSID, MODEM_PROC);
- diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
- diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
-}
+ struct diag_smd_info *smd_info = container_of(work,
+ struct diag_smd_info,
+ diag_notify_update_smd_work);
+ if (!smd_info) {
+ pr_err("diag: In %s, smd info is null, cannot update masks for the peripheral\n",
+ __func__);
+ return;
+ }
-void diag_lpass_mask_update_fn(struct work_struct *work)
-{
- diag_send_msg_mask_update(driver->chlpass_cntl, ALL_SSID,
- ALL_SSID, LPASS_PROC);
- diag_send_log_mask_update(driver->chlpass_cntl, ALL_EQUIP_ID);
- diag_send_event_mask_update(driver->chlpass_cntl, diag_event_num_bytes);
-}
+ diag_send_msg_mask_update(smd_info->ch, ALL_SSID, ALL_SSID,
+ smd_info->peripheral);
+ diag_send_log_mask_update(smd_info->ch, ALL_EQUIP_ID);
+ diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
+ diag_send_feature_mask_update(smd_info->ch, smd_info->peripheral);
-void diag_wcnss_mask_update_fn(struct work_struct *work)
-{
- diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
- ALL_SSID, WCNSS_PROC);
- diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
- diag_send_event_mask_update(driver->ch_wcnss_cntl,
- diag_event_num_bytes);
+ smd_info->notify_context = 0;
}
void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
@@ -467,6 +465,42 @@
mutex_unlock(&driver->diag_cntl_mutex);
}
+void diag_send_feature_mask_update(smd_channel_t *ch, int proc)
+{
+ void *buf = driver->buf_feature_mask_update;
+ int header_size = sizeof(struct diag_ctrl_feature_mask);
+ int wr_size = -ENOMEM, retry_count = 0, timer;
+ uint8_t feature_byte = 0;
+
+ mutex_lock(&driver->diag_cntl_mutex);
+ /* send feature mask update */
+ driver->feature_mask->ctrl_pkt_id = DIAG_CTRL_MSG_FEATURE;
+ driver->feature_mask->ctrl_pkt_data_len = 4 + FEATURE_MASK_LEN_BYTES;
+ driver->feature_mask->feature_mask_len = FEATURE_MASK_LEN_BYTES;
+ memcpy(buf, driver->feature_mask, header_size);
+ feature_byte |= APPS_RESPOND_LOG_ON_DEMAND;
+ memcpy(buf+header_size, &feature_byte, FEATURE_MASK_LEN_BYTES);
+
+ if (ch) {
+ while (retry_count < 3) {
+ wr_size = smd_write(ch, buf, header_size +
+ FEATURE_MASK_LEN_BYTES);
+ if (wr_size == -ENOMEM) {
+ retry_count++;
+ for (timer = 0; timer < 5; timer++)
+ udelay(2000);
+ } else
+ break;
+ }
+ if (wr_size != header_size + FEATURE_MASK_LEN_BYTES)
+ pr_err("diag: proc %d fail feature update %d, tried %d",
+ proc, wr_size, header_size + FEATURE_MASK_LEN_BYTES);
+ } else
+ pr_err("diag: ch invalid, feature update on proc %d\n", proc);
+ mutex_unlock(&driver->diag_cntl_mutex);
+
+}
+
int diag_process_apps_masks(unsigned char *buf, int len)
{
int packet_type = 1;
@@ -493,15 +527,13 @@
payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
for (i = 0; i < payload_length; i++)
*(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
- if (driver->ch_cntl)
- diag_send_log_mask_update(driver->ch_cntl,
- *(int *)buf);
- if (driver->chlpass_cntl)
- diag_send_log_mask_update(driver->chlpass_cntl,
- *(int *)buf);
- if (driver->ch_wcnss_cntl)
- diag_send_log_mask_update(driver->ch_wcnss_cntl,
- *(int *)buf);
+
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
+ if (driver->smd_cntl[i].ch)
+ diag_send_log_mask_update(
+ driver->smd_cntl[i].ch,
+ *(int *)buf);
+ }
encode_rsp_and_send(12 + payload_length - 1);
return 0;
}
@@ -509,7 +541,8 @@
} /* Get log masks */
else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
#if defined(CONFIG_DIAG_OVER_USB)
- if (!(driver->ch) && chk_apps_only()) {
+ if (!(driver->smd_data[MODEM_DATA].ch) &&
+ chk_apps_only()) {
equip_id = *(int *)(buf + 8);
num_items = *(int *)(buf + 12);
driver->apps_rsp_buf[0] = 0x73;
@@ -541,15 +574,13 @@
driver->apps_rsp_buf[3] = 0x0;
*(int *)(driver->apps_rsp_buf + 4) = 0x0;
*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
- if (driver->ch_cntl)
- diag_send_log_mask_update(driver->ch_cntl,
- ALL_EQUIP_ID);
- if (driver->chlpass_cntl)
- diag_send_log_mask_update(driver->chlpass_cntl,
- ALL_EQUIP_ID);
- if (driver->ch_wcnss_cntl)
- diag_send_log_mask_update(driver->ch_wcnss_cntl,
- ALL_EQUIP_ID);
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
+ if (driver->smd_cntl[i].ch)
+ diag_send_log_mask_update(
+ driver->smd_cntl[i].ch,
+ ALL_EQUIP_ID);
+
+ }
encode_rsp_and_send(11);
return 0;
}
@@ -559,7 +590,8 @@
ssid_first = *(uint16_t *)(buf + 2);
ssid_last = *(uint16_t *)(buf + 4);
#if defined(CONFIG_DIAG_OVER_USB)
- if (!(driver->ch) && chk_apps_only()) {
+ if (!(driver->smd_data[MODEM_DATA].ch) &&
+ chk_apps_only()) {
driver->apps_rsp_buf[0] = 0x7d;
driver->apps_rsp_buf[1] = 0x3;
*(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
@@ -599,15 +631,14 @@
for (i = 0; i < 8 + ssid_range; i++)
*(driver->apps_rsp_buf + i) = *(buf+i);
*(driver->apps_rsp_buf + 6) = 0x1;
- if (driver->ch_cntl)
- diag_send_msg_mask_update(driver->ch_cntl,
- ssid_first, ssid_last, MODEM_PROC);
- if (driver->chlpass_cntl)
- diag_send_msg_mask_update(driver->chlpass_cntl,
- ssid_first, ssid_last, LPASS_PROC);
- if (driver->ch_wcnss_cntl)
- diag_send_msg_mask_update(driver->ch_wcnss_cntl,
- ssid_first, ssid_last, WCNSS_PROC);
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
+ if (driver->smd_cntl[i].ch)
+ diag_send_msg_mask_update(
+ driver->smd_cntl[i].ch,
+ ssid_first, ssid_last,
+ driver->smd_cntl[i].peripheral);
+
+ }
encode_rsp_and_send(8 + ssid_range - 1);
return 0;
}
@@ -625,15 +656,14 @@
driver->apps_rsp_buf[3] = 0; /* rsvd */
*(int *)(driver->apps_rsp_buf + 4) = rt_mask;
/* send msg mask update to peripheral */
- if (driver->ch_cntl)
- diag_send_msg_mask_update(driver->ch_cntl,
- ALL_SSID, ALL_SSID, MODEM_PROC);
- if (driver->chlpass_cntl)
- diag_send_msg_mask_update(driver->chlpass_cntl,
- ALL_SSID, ALL_SSID, LPASS_PROC);
- if (driver->ch_wcnss_cntl)
- diag_send_msg_mask_update(driver->ch_wcnss_cntl,
- ALL_SSID, ALL_SSID, WCNSS_PROC);
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
+ if (driver->smd_cntl[i].ch)
+ diag_send_msg_mask_update(
+ driver->smd_cntl[i].ch,
+ ALL_SSID, ALL_SSID,
+ driver->smd_cntl[i].peripheral);
+
+ }
encode_rsp_and_send(7);
return 0;
}
@@ -652,16 +682,12 @@
EVENT_LAST_ID + 1;
memcpy(driver->apps_rsp_buf+6, driver->event_masks,
EVENT_LAST_ID/8+1);
- if (driver->ch_cntl)
- diag_send_event_mask_update(driver->ch_cntl,
- diag_event_num_bytes);
- if (driver->chlpass_cntl)
- diag_send_event_mask_update(
- driver->chlpass_cntl,
- diag_event_num_bytes);
- if (driver->ch_wcnss_cntl)
- diag_send_event_mask_update(
- driver->ch_wcnss_cntl, diag_event_num_bytes);
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
+ if (driver->smd_cntl[i].ch)
+ diag_send_event_mask_update(
+ driver->smd_cntl[i].ch,
+ diag_event_num_bytes);
+ }
encode_rsp_and_send(6 + EVENT_LAST_ID/8);
return 0;
}
@@ -675,20 +701,26 @@
driver->apps_rsp_buf[0] = 0x60;
driver->apps_rsp_buf[1] = 0x0;
driver->apps_rsp_buf[2] = 0x0;
- if (driver->ch_cntl)
- diag_send_event_mask_update(driver->ch_cntl,
- diag_event_num_bytes);
- if (driver->chlpass_cntl)
- diag_send_event_mask_update(
- driver->chlpass_cntl,
- diag_event_num_bytes);
- if (driver->ch_wcnss_cntl)
- diag_send_event_mask_update(
- driver->ch_wcnss_cntl, diag_event_num_bytes);
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
+ if (driver->smd_cntl[i].ch)
+ diag_send_event_mask_update(
+ driver->smd_cntl[i].ch,
+ diag_event_num_bytes);
+ }
encode_rsp_and_send(2);
return 0;
}
#endif
+ } else if (*buf == 0x78) {
+ if (!(driver->smd_cntl[MODEM_DATA].ch) ||
+ (driver->log_on_demand_support)) {
+ driver->apps_rsp_buf[0] = 0x78;
+ /* Copy log code received */
+ *(uint16_t *)(driver->apps_rsp_buf+1) =
+ *(uint16_t *)buf;
+ driver->apps_rsp_buf[3] = 0x1;/* Unknown */
+ encode_rsp_and_send(3);
+ }
}
return packet_type;
@@ -745,6 +777,21 @@
goto err;
kmemleak_not_leak(driver->msg_masks);
}
+ if (driver->buf_feature_mask_update == NULL) {
+ driver->buf_feature_mask_update = kzalloc(sizeof(
+ struct diag_ctrl_feature_mask) +
+ FEATURE_MASK_LEN_BYTES, GFP_KERNEL);
+ if (driver->buf_feature_mask_update == NULL)
+ goto err;
+ kmemleak_not_leak(driver->buf_feature_mask_update);
+ }
+ if (driver->feature_mask == NULL) {
+ driver->feature_mask = kzalloc(sizeof(
+ struct diag_ctrl_feature_mask), GFP_KERNEL);
+ if (driver->feature_mask == NULL)
+ goto err;
+ kmemleak_not_leak(driver->feature_mask);
+ }
diag_create_msg_mask_table();
diag_event_num_bytes = 0;
if (driver->log_masks == NULL) {
@@ -760,14 +807,6 @@
goto err;
kmemleak_not_leak(driver->event_masks);
}
-#ifdef CONFIG_DIAG_OVER_USB
- INIT_WORK(&(driver->diag_modem_mask_update_work),
- diag_modem_mask_update_fn);
- INIT_WORK(&(driver->diag_lpass_mask_update_work),
- diag_lpass_mask_update_fn);
- INIT_WORK(&(driver->diag_wcnss_mask_update_work),
- diag_wcnss_mask_update_fn);
-#endif
return;
err:
pr_err("diag: Could not initialize diag mask buffers");
@@ -777,6 +816,8 @@
kfree(driver->msg_masks);
kfree(driver->log_masks);
kfree(driver->event_masks);
+ kfree(driver->feature_mask);
+ kfree(driver->buf_feature_mask_update);
}
void diag_masks_exit(void)
@@ -787,4 +828,6 @@
kfree(driver->msg_masks);
kfree(driver->log_masks);
kfree(driver->event_masks);
+ kfree(driver->feature_mask);
+ kfree(driver->buf_feature_mask_update);
}
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index bcf5bc2..53f72e8 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -20,6 +20,8 @@
void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
int ssid_last, int proc);
void diag_send_log_mask_update(smd_channel_t *, int);
+void diag_mask_update_fn(struct work_struct *work);
+void diag_send_feature_mask_update(smd_channel_t *ch, int proc);
int diag_process_apps_masks(unsigned char *buf, int len);
void diag_masks_init(void);
void diag_masks_exit(void);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index cb895d8..0d5ad6a 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -23,12 +23,14 @@
#include <mach/msm_smd.h>
#include <asm/atomic.h>
#include <asm/mach-types.h>
+
/* Size of the USB buffers used for read and write*/
#define USB_MAX_OUT_BUF 4096
#define APPS_BUF_SIZE 2000
#define IN_BUF_SIZE 16384
#define MAX_IN_BUF_SIZE 32768
#define MAX_SYNC_OBJ_NAME_SIZE 32
+#define UINT32_MAX UINT_MAX
/* Size of the buffer used for deframing a packet
reveived from the PC tool*/
#define HDLC_MAX 4096
@@ -39,17 +41,14 @@
#define POOL_TYPE_HSIC 8
#define POOL_TYPE_HSIC_WRITE 16
#define POOL_TYPE_ALL 7
-#define MODEM_DATA 1
-#define LPASS_DATA 2
+#define MODEM_DATA 0
+#define LPASS_DATA 1
+#define WCNSS_DATA 2
#define APPS_DATA 3
#define SDIO_DATA 4
-#define WCNSS_DATA 5
-#define HSIC_DATA 6
-#define SMUX_DATA 7
-#define MODEM_PROC 0
+#define HSIC_DATA 5
+#define SMUX_DATA 6
#define APPS_PROC 1
-#define LPASS_PROC 2
-#define WCNSS_PROC 3
#define MSG_MASK_SIZE 10000
#define LOG_MASK_SIZE 8000
#define EVENT_MASK_SIZE 1000
@@ -75,6 +74,14 @@
#define DIAG_STATUS_OPEN (0x00010000) /* DCI channel open status mask */
#define DIAG_STATUS_CLOSED (0x00020000) /* DCI channel closed status mask */
+#define NUM_SMD_DATA_CHANNELS 3
+#define NUM_SMD_CONTROL_CHANNELS 3
+#define NUM_SMD_DCI_CHANNELS 1
+
+#define SMD_DATA_TYPE 0
+#define SMD_CNTL_TYPE 1
+#define SMD_DCI_TYPE 2
+
/* Maximum number of pkt reg supported at initialization*/
extern unsigned int diag_max_reg;
extern unsigned int diag_threshold_reg;
@@ -86,6 +93,12 @@
(diag_debug_buf_idx++) : (diag_debug_buf_idx = 0); \
} while (0)
+/* List of remote processor supported */
+enum remote_procs {
+ MDM = 1,
+ QSC = 2,
+};
+
struct diag_master_table {
uint16_t cmd_code;
uint16_t subsys_id;
@@ -136,6 +149,35 @@
};
#endif
+struct diag_smd_info {
+ int peripheral; /* The peripheral this smd channel communicates with */
+ int type; /* The type of smd channel (data, control, dci) */
+ uint16_t peripheral_mask;
+
+ smd_channel_t *ch;
+ smd_channel_t *ch_save;
+
+ int in_busy_1;
+ int in_busy_2;
+
+ unsigned char *buf_in_1;
+ unsigned char *buf_in_2;
+
+ struct diag_request *write_ptr_1;
+ struct diag_request *write_ptr_2;
+
+ struct work_struct diag_read_smd_work;
+ struct work_struct diag_notify_update_smd_work;
+ int notify_context;
+
+ /*
+ * Function ptr for function to call to process the data that
+ * was just read from the smd channel
+ */
+ int (*process_smd_read_data)(struct diag_smd_info *smd_info,
+ void *buf, int num_bytes);
+};
+
struct diagchar_dev {
/* State for the char driver */
@@ -149,6 +191,7 @@
int ref_count;
struct mutex diagchar_mutex;
wait_queue_head_t wait_q;
+ wait_queue_head_t smd_wait_q;
struct diag_client_map *client_map;
int *data_ready;
int num_clients;
@@ -187,17 +230,11 @@
struct diag_ctrl_event_mask *event_mask;
struct diag_ctrl_log_mask *log_mask;
struct diag_ctrl_msg_mask *msg_mask;
+ struct diag_ctrl_feature_mask *feature_mask;
/* State for diag forwarding */
- unsigned char *buf_in_1;
- unsigned char *buf_in_2;
- unsigned char *buf_in_cntl;
- unsigned char *buf_in_lpass_1;
- unsigned char *buf_in_lpass_2;
- unsigned char *buf_in_lpass_cntl;
- unsigned char *buf_in_wcnss_1;
- unsigned char *buf_in_wcnss_2;
- unsigned char *buf_in_wcnss_cntl;
- unsigned char *buf_in_dci;
+ struct diag_smd_info smd_data[NUM_SMD_DATA_CHANNELS];
+ struct diag_smd_info smd_cntl[NUM_SMD_CONTROL_CHANNELS];
+ struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
unsigned char *usb_buf_out;
unsigned char *apps_rsp_buf;
unsigned char *user_space_data;
@@ -205,20 +242,7 @@
unsigned char *buf_msg_mask_update;
unsigned char *buf_log_mask_update;
unsigned char *buf_event_mask_update;
- smd_channel_t *ch;
- smd_channel_t *ch_cntl;
- smd_channel_t *ch_dci;
- smd_channel_t *chlpass;
- smd_channel_t *chlpass_cntl;
- smd_channel_t *ch_wcnss;
- smd_channel_t *ch_wcnss_cntl;
- int in_busy_1;
- int in_busy_2;
- int in_busy_lpass_1;
- int in_busy_lpass_2;
- int in_busy_wcnss_1;
- int in_busy_wcnss_2;
- int in_busy_dci;
+ unsigned char *buf_feature_mask_update;
int read_len_legacy;
unsigned char *hdlc_buf;
unsigned hdlc_count;
@@ -231,41 +255,22 @@
#endif
struct workqueue_struct *diag_wq;
struct work_struct diag_drain_work;
- struct work_struct diag_read_smd_work;
- struct work_struct diag_read_smd_cntl_work;
- struct work_struct diag_read_smd_lpass_work;
- struct work_struct diag_read_smd_lpass_cntl_work;
- struct work_struct diag_read_smd_wcnss_work;
- struct work_struct diag_read_smd_wcnss_cntl_work;
struct workqueue_struct *diag_cntl_wq;
- struct work_struct diag_modem_mask_update_work;
- struct work_struct diag_lpass_mask_update_work;
- struct work_struct diag_wcnss_mask_update_work;
- struct work_struct diag_read_smd_dci_work;
- struct work_struct diag_update_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;
uint8_t *event_masks;
+ uint8_t log_on_demand_support;
struct diag_master_table *table;
uint8_t *pkt_buf;
int pkt_length;
- struct diag_request *write_ptr_1;
- struct diag_request *write_ptr_2;
struct diag_request *usb_read_ptr;
struct diag_request *write_ptr_svc;
- struct diag_request *write_ptr_lpass_1;
- struct diag_request *write_ptr_lpass_2;
- struct diag_request *write_ptr_wcnss_1;
- struct diag_request *write_ptr_wcnss_2;
- struct diag_write_device *write_ptr_dci;
int logging_mode;
int mask_check;
int logging_process_id;
struct task_struct *socket_process;
+ struct task_struct *callback_process;
#ifdef CONFIG_DIAG_SDIO_PIPE
unsigned char *buf_in_sdio;
unsigned char *usb_buf_mdm_out;
@@ -280,7 +285,9 @@
struct diag_request *usb_read_mdm_ptr;
struct diag_request *write_ptr_mdm;
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ /* common for all bridges */
+ struct work_struct diag_disconnect_work;
/* SGLTE variables */
int lcid;
unsigned char *buf_in_smux;
@@ -297,18 +304,6 @@
int in_busy_hsic_read_on_device;
int in_busy_hsic_write;
struct work_struct diag_read_hsic_work;
- struct mutex bridge_mutex;
- /* USB MDM channel variables */
- int usb_mdm_connected;
- int read_len_mdm;
- int write_len_mdm;
- unsigned char *usb_buf_mdm_out;
- struct usb_diag_ch *mdm_ch;
- struct workqueue_struct *diag_bridge_wq;
- struct work_struct diag_read_mdm_work;
- struct work_struct diag_disconnect_work;
- struct work_struct diag_usb_read_complete_work;
- struct diag_request *usb_read_mdm_ptr;
int count_hsic_pool;
int count_hsic_write_pool;
unsigned int poolsize_hsic;
@@ -323,5 +318,10 @@
#endif
};
+extern struct diag_bridge_dev *diag_bridge;
extern struct diagchar_dev *driver;
+
+extern int wrap_enabled;
+extern uint16_t wrap_count;
+
#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6c9e5ab..d2454f4 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,13 +32,14 @@
#ifdef CONFIG_DIAG_SDIO_PIPE
#include "diagfwd_sdio.h"
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
#include "diagfwd_hsic.h"
#include "diagfwd_smux.h"
#endif
#include <linux/timer.h>
#include "diag_debugfs.h"
#include "diag_masks.h"
+#include "diagfwd_bridge.h"
MODULE_DESCRIPTION("Diag Char Driver");
MODULE_LICENSE("GPL v2");
@@ -78,12 +79,25 @@
/* delayed_rsp_id 0 represents no delay in the response. Any other number
means that the diag packet has a delayed response. */
static uint16_t delayed_rsp_id = 1;
-#define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
-/* This macro gets the next delayed respose id. Once it reaches
- DIAGPKT_MAX_DELAYED_RSP, it stays at DIAGPKT_MAX_DELAYED_RSP */
-#define DIAGPKT_NEXT_DELAYED_RSP_ID(x) \
-((x < DIAGPKT_MAX_DELAYED_RSP) ? x++ : DIAGPKT_MAX_DELAYED_RSP)
+#define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
+
+/* returns the next delayed rsp id - rollsover the id if wrapping is
+ enabled. */
+uint16_t diagpkt_next_delayed_rsp_id(uint16_t rspid)
+{
+ if (rspid < DIAGPKT_MAX_DELAYED_RSP)
+ rspid++;
+ else {
+ if (wrap_enabled) {
+ rspid = 1;
+ wrap_count++;
+ } else
+ rspid = DIAGPKT_MAX_DELAYED_RSP;
+ }
+ delayed_rsp_id = rspid;
+ return delayed_rsp_id;
+}
#define COPY_USER_SPACE_OR_EXIT(buf, data, length) \
do { \
@@ -124,7 +138,7 @@
mutex_unlock(&driver->diagchar_mutex);
}
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
void diag_clear_hsic_tbl(void)
{
int i;
@@ -145,21 +159,6 @@
void diag_clear_hsic_tbl(void) { }
#endif
-void diag_read_smd_work_fn(struct work_struct *work)
-{
- __diag_smd_send_req();
-}
-
-void diag_read_smd_lpass_work_fn(struct work_struct *work)
-{
- __diag_smd_lpass_send_req();
-}
-
-void diag_read_smd_wcnss_work_fn(struct work_struct *work)
-{
- __diag_smd_wcnss_send_req();
-}
-
void diag_add_client(int i, struct file *file)
{
struct diagchar_priv *diagpriv_data;
@@ -248,6 +247,10 @@
pr_alert("diag: Invalid file pointer");
return -ENOMEM;
}
+
+ if (!driver)
+ return -ENOMEM;
+
/* clean up any DCI registrations, if this is a DCI client
* This will specially help in case of ungraceful exit of any DCI client
* This call will remove any pending registrations of such client
@@ -265,13 +268,17 @@
(driver->socket_process->tgid == current->tgid)) {
driver->socket_process = NULL;
}
+ if (driver->callback_process &&
+ (driver->callback_process->tgid == current->tgid)) {
+ driver->callback_process = NULL;
+ }
#ifdef CONFIG_DIAG_OVER_USB
/* If the SD logging process exits, change logging to USB mode */
if (driver->logging_process_id == current->tgid) {
driver->logging_mode = USB_MODE;
diagfwd_connect();
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diag_clear_hsic_tbl();
diagfwd_cancel_hsic();
diagfwd_connect_bridge(0);
@@ -283,26 +290,23 @@
if (driver->table[i].process_id == current->tgid)
driver->table[i].process_id = 0;
- if (driver) {
- mutex_lock(&driver->diagchar_mutex);
- driver->ref_count--;
- /* On Client exit, try to destroy all 3 pools */
- diagmem_exit(driver, POOL_TYPE_COPY);
- diagmem_exit(driver, POOL_TYPE_HDLC);
- diagmem_exit(driver, POOL_TYPE_WRITE_STRUCT);
- for (i = 0; i < driver->num_clients; i++) {
- if (NULL != diagpriv_data && diagpriv_data->pid ==
- driver->client_map[i].pid) {
- driver->client_map[i].pid = 0;
- kfree(diagpriv_data);
- diagpriv_data = NULL;
- break;
- }
+ mutex_lock(&driver->diagchar_mutex);
+ driver->ref_count--;
+ /* On Client exit, try to destroy all 3 pools */
+ diagmem_exit(driver, POOL_TYPE_COPY);
+ diagmem_exit(driver, POOL_TYPE_HDLC);
+ diagmem_exit(driver, POOL_TYPE_WRITE_STRUCT);
+ for (i = 0; i < driver->num_clients; i++) {
+ if (NULL != diagpriv_data && diagpriv_data->pid ==
+ driver->client_map[i].pid) {
+ driver->client_map[i].pid = 0;
+ kfree(diagpriv_data);
+ diagpriv_data = NULL;
+ break;
}
- mutex_unlock(&driver->diagchar_mutex);
- return 0;
}
- return -ENOMEM;
+ mutex_unlock(&driver->diagchar_mutex);
+ return 0;
}
int diag_find_polling_reg(int i)
@@ -328,7 +332,7 @@
return 0;
}
-void diag_clear_reg(int proc_num)
+void diag_clear_reg(int peripheral)
{
int i;
@@ -336,9 +340,8 @@
/* reset polling flag */
driver->polling_reg_flag = 0;
for (i = 0; i < diag_max_reg; i++) {
- if (driver->table[i].client_id == proc_num) {
+ if (driver->table[i].client_id == peripheral)
driver->table[i].process_id = 0;
- }
}
/* re-scan the registration table */
for (i = 0; i < diag_max_reg; i++) {
@@ -351,7 +354,7 @@
}
void diag_add_reg(int j, struct bindpkt_params *params,
- int *success, int *count_entries)
+ int *success, unsigned int *count_entries)
{
*success = 1;
driver->table[j].cmd_code = params->cmd_code;
@@ -365,7 +368,7 @@
driver->polling_reg_flag = 1;
if (params->proc_id == APPS_PROC) {
driver->table[j].process_id = current->tgid;
- driver->table[j].client_id = APPS_PROC;
+ driver->table[j].client_id = APPS_DATA;
} else {
driver->table[j].process_id = NON_APPS_PROC;
driver->table[j].client_id = params->client_id;
@@ -373,82 +376,193 @@
(*count_entries)++;
}
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+uint16_t diag_get_remote_device_mask(void)
+{
+ uint16_t remote_dev = 0;
+
+ /* Check for MDM processor */
+ if (driver->hsic_inited)
+ remote_dev |= 1 << 0;
+
+ /* Check for QSC processor */
+ if (driver->diag_smux_enabled)
+ remote_dev |= 1 << 1;
+
+ return remote_dev;
+}
+#else
+inline uint16_t diag_get_remote_device_mask(void) { return 0; }
+#endif
+
+static int diag_get_remote(int remote_info)
+{
+ int val = (remote_info < 0) ? -remote_info : remote_info;
+ int remote_val;
+
+ switch (val) {
+ case MDM:
+ case QSC:
+ remote_val = -remote_info;
+ break;
+ default:
+ remote_val = 0;
+ break;
+ }
+
+ return remote_val;
+}
+
long diagchar_ioctl(struct file *filp,
unsigned int iocmd, unsigned long ioarg)
{
- int i, j, count_entries = 0, temp;
- int success = -1;
+ int i, j, temp, success = -1, status;
+ unsigned int count_entries = 0, interim_count = 0;
void *temp_buf;
uint16_t support_list = 0;
- struct diag_dci_client_tbl *params =
- kzalloc(sizeof(struct diag_dci_client_tbl), GFP_KERNEL);
+ struct diag_dci_client_tbl *dci_params;
struct diag_dci_health_stats stats;
- int status;
if (iocmd == DIAG_IOCTL_COMMAND_REG) {
- struct bindpkt_params_per_process *pkt_params =
- (struct bindpkt_params_per_process *) ioarg;
+ struct bindpkt_params_per_process pkt_params;
+ struct bindpkt_params *params;
+ struct bindpkt_params *head_params;
+ if (copy_from_user(&pkt_params, (void *)ioarg,
+ sizeof(struct bindpkt_params_per_process))) {
+ return -EFAULT;
+ }
+ if ((UINT32_MAX/sizeof(struct bindpkt_params)) <
+ pkt_params.count) {
+ pr_warning("diag: integer overflow while multiply\n");
+ return -EFAULT;
+ }
+ params = kzalloc(pkt_params.count*sizeof(
+ struct bindpkt_params), GFP_KERNEL);
+ if (!params) {
+ pr_err("diag: unable to alloc memory\n");
+ return -ENOMEM;
+ } else
+ head_params = params;
+
+ if (copy_from_user(params, pkt_params.params,
+ pkt_params.count*sizeof(struct bindpkt_params))) {
+ kfree(head_params);
+ return -EFAULT;
+ }
mutex_lock(&driver->diagchar_mutex);
for (i = 0; i < diag_max_reg; i++) {
if (driver->table[i].process_id == 0) {
- diag_add_reg(i, pkt_params->params,
- &success, &count_entries);
- if (pkt_params->count > count_entries) {
- pkt_params->params++;
+ diag_add_reg(i, params, &success,
+ &count_entries);
+ if (pkt_params.count > count_entries) {
+ params++;
} else {
mutex_unlock(&driver->diagchar_mutex);
+ kfree(head_params);
return success;
}
}
}
if (i < diag_threshold_reg) {
/* Increase table size by amount required */
- diag_max_reg += pkt_params->count -
+ if (pkt_params.count >= count_entries) {
+ interim_count = pkt_params.count -
count_entries;
+ } else {
+ pr_warning("diag: error in params count\n");
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return -EFAULT;
+ }
+ if (UINT32_MAX - diag_max_reg >=
+ interim_count) {
+ diag_max_reg += interim_count;
+ } else {
+ pr_warning("diag: Integer overflow\n");
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return -EFAULT;
+ }
/* Make sure size doesnt go beyond threshold */
if (diag_max_reg > diag_threshold_reg) {
diag_max_reg = diag_threshold_reg;
pr_info("diag: best case memory allocation\n");
}
+ if (UINT32_MAX/sizeof(struct diag_master_table) <
+ diag_max_reg) {
+ pr_warning("diag: integer overflow\n");
+ kfree(head_params);
+ mutex_unlock(&driver->diagchar_mutex);
+ return -EFAULT;
+ }
temp_buf = krealloc(driver->table,
diag_max_reg*sizeof(struct
diag_master_table), GFP_KERNEL);
if (!temp_buf) {
- diag_max_reg -= pkt_params->count -
- count_entries;
- pr_alert("diag: Insufficient memory for reg.");
+ pr_alert("diag: Insufficient memory for reg.\n");
mutex_unlock(&driver->diagchar_mutex);
+
+ if (pkt_params.count >= count_entries) {
+ interim_count = pkt_params.count -
+ count_entries;
+ } else {
+ pr_warning("diag: params count error\n");
+ mutex_unlock(&driver->diagchar_mutex);
+ kfree(head_params);
+ return -EFAULT;
+ }
+ if (diag_max_reg >= interim_count) {
+ diag_max_reg -= interim_count;
+ } else {
+ pr_warning("diag: Integer underflow\n");
+ mutex_unlock(&driver->diagchar_mutex);
+ kfree(head_params);
+ return -EFAULT;
+ }
+ kfree(head_params);
return 0;
} else {
driver->table = temp_buf;
}
for (j = i; j < diag_max_reg; j++) {
- diag_add_reg(j, pkt_params->params,
- &success, &count_entries);
- if (pkt_params->count > count_entries) {
- pkt_params->params++;
+ diag_add_reg(j, params, &success,
+ &count_entries);
+ if (pkt_params.count > count_entries) {
+ params++;
} else {
mutex_unlock(&driver->diagchar_mutex);
+ kfree(head_params);
return success;
}
}
+ kfree(head_params);
mutex_unlock(&driver->diagchar_mutex);
} else {
mutex_unlock(&driver->diagchar_mutex);
+ kfree(head_params);
pr_err("Max size reached, Pkt Registration failed for"
" Process %d", current->tgid);
}
success = 0;
} else if (iocmd == DIAG_IOCTL_GET_DELAYED_RSP_ID) {
- struct diagpkt_delay_params *delay_params =
- (struct diagpkt_delay_params *) ioarg;
-
- if ((delay_params->rsp_ptr) &&
- (delay_params->size == sizeof(delayed_rsp_id)) &&
- (delay_params->num_bytes_ptr)) {
- *((uint16_t *)delay_params->rsp_ptr) =
- DIAGPKT_NEXT_DELAYED_RSP_ID(delayed_rsp_id);
- *(delay_params->num_bytes_ptr) = sizeof(delayed_rsp_id);
+ struct diagpkt_delay_params delay_params;
+ uint16_t interim_rsp_id;
+ int interim_size;
+ if (copy_from_user(&delay_params, (void *)ioarg,
+ sizeof(struct diagpkt_delay_params)))
+ return -EFAULT;
+ if ((delay_params.rsp_ptr) &&
+ (delay_params.size == sizeof(delayed_rsp_id)) &&
+ (delay_params.num_bytes_ptr)) {
+ interim_rsp_id = diagpkt_next_delayed_rsp_id(
+ delayed_rsp_id);
+ if (copy_to_user((void *)delay_params.rsp_ptr,
+ &interim_rsp_id, sizeof(uint16_t)))
+ return -EFAULT;
+ interim_size = sizeof(delayed_rsp_id);
+ if (copy_to_user((void *)delay_params.num_bytes_ptr,
+ &interim_size, sizeof(int)))
+ return -EFAULT;
success = 0;
}
} else if (iocmd == DIAG_IOCTL_DCI_REG) {
@@ -456,22 +570,30 @@
return DIAG_DCI_NO_REG;
if (driver->num_dci_client >= MAX_DCI_CLIENTS)
return DIAG_DCI_NO_REG;
- if (copy_from_user(params, (void *)ioarg,
+ dci_params = kzalloc(sizeof(struct diag_dci_client_tbl),
+ GFP_KERNEL);
+ if (dci_params == NULL) {
+ pr_err("diag: unable to alloc memory\n");
+ return -ENOMEM;
+ }
+ if (copy_from_user(dci_params, (void *)ioarg,
sizeof(struct diag_dci_client_tbl)))
return -EFAULT;
mutex_lock(&driver->dci_mutex);
if (!(driver->num_dci_client))
- driver->in_busy_dci = 0;
+ for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++)
+ driver->smd_dci[i].in_busy_1 = 0;
driver->num_dci_client++;
- pr_debug("diag: id = %d\n", driver->dci_client_id);
+ pr_debug("diag: In %s, id = %d\n",
+ __func__, driver->dci_client_id);
driver->dci_client_id++;
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
if (driver->dci_client_tbl[i].client == NULL) {
driver->dci_client_tbl[i].client = current;
driver->dci_client_tbl[i].list =
- params->list;
+ dci_params->list;
driver->dci_client_tbl[i].signal_type =
- params->signal_type;
+ dci_params->signal_type;
create_dci_log_mask_tbl(driver->
dci_client_tbl[i].dci_log_mask);
create_dci_event_mask_tbl(driver->
@@ -489,6 +611,7 @@
}
}
mutex_unlock(&driver->dci_mutex);
+ kfree(dci_params);
return driver->dci_client_id;
} else if (iocmd == DIAG_IOCTL_DCI_DEINIT) {
success = -1;
@@ -511,27 +634,34 @@
mutex_unlock(&driver->dci_mutex);
return success;
} else if (iocmd == DIAG_IOCTL_DCI_SUPPORT) {
- if (driver->ch_dci)
- support_list = support_list | DIAG_CON_MPSS;
- *(uint16_t *)ioarg = support_list;
+ for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
+ if (driver->smd_dci[i].ch)
+ support_list |=
+ driver->smd_dci[i].peripheral_mask;
+ }
+ if (copy_to_user((void *)ioarg, &support_list,
+ sizeof(uint16_t)))
+ return -EFAULT;
return DIAG_DCI_NO_ERROR;
} else if (iocmd == DIAG_IOCTL_DCI_HEALTH_STATS) {
if (copy_from_user(&stats, (void *)ioarg,
sizeof(struct diag_dci_health_stats)))
return -EFAULT;
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
- params = &(driver->dci_client_tbl[i]);
- if (params->client &&
- params->client->tgid == current->tgid) {
- stats.dropped_logs = params->dropped_logs;
- stats.dropped_events = params->dropped_events;
- stats.received_logs = params->received_logs;
- stats.received_events = params->received_events;
+ dci_params = &(driver->dci_client_tbl[i]);
+ if (dci_params->client &&
+ dci_params->client->tgid == current->tgid) {
+ stats.dropped_logs = dci_params->dropped_logs;
+ stats.dropped_events =
+ dci_params->dropped_events;
+ stats.received_logs = dci_params->received_logs;
+ stats.received_events =
+ dci_params->received_events;
if (stats.reset_status) {
- params->dropped_logs = 0;
- params->dropped_events = 0;
- params->received_logs = 0;
- params->received_events = 0;
+ dci_params->dropped_logs = 0;
+ dci_params->dropped_events = 0;
+ dci_params->received_logs = 0;
+ dci_params->received_events = 0;
}
break;
}
@@ -544,7 +674,7 @@
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid == current->tgid)
break;
- if (i == -1)
+ if (i == driver->num_clients)
return -EINVAL;
driver->data_ready[i] |= DEINIT_TYPE;
wake_up_interruptible(&driver->wait_q);
@@ -553,6 +683,11 @@
mutex_lock(&driver->diagchar_mutex);
temp = driver->logging_mode;
driver->logging_mode = (int)ioarg;
+ if (temp == driver->logging_mode) {
+ mutex_unlock(&driver->diagchar_mutex);
+ pr_alert("diag: forbidden logging change requested\n");
+ return 0;
+ }
if (driver->logging_mode == MEMORY_DEVICE_MODE) {
diag_clear_hsic_tbl();
driver->mask_check = 1;
@@ -571,14 +706,14 @@
}
}
}
- if (driver->logging_mode == UART_MODE) {
- diag_clear_hsic_tbl();
- driver->mask_check = 0;
- driver->logging_mode = MEMORY_DEVICE_MODE;
- }
- if (driver->logging_mode == SOCKET_MODE) {
- diag_clear_hsic_tbl();
+ if (driver->logging_mode == SOCKET_MODE)
driver->socket_process = current;
+ if (driver->logging_mode == CALLBACK_MODE)
+ driver->callback_process = current;
+ if (driver->logging_mode == UART_MODE ||
+ driver->logging_mode == SOCKET_MODE ||
+ driver->logging_mode == CALLBACK_MODE) {
+ diag_clear_hsic_tbl();
driver->mask_check = 0;
driver->logging_mode = MEMORY_DEVICE_MODE;
}
@@ -586,37 +721,28 @@
mutex_unlock(&driver->diagchar_mutex);
if (temp == MEMORY_DEVICE_MODE && driver->logging_mode
== NO_LOGGING_MODE) {
- driver->in_busy_1 = 1;
- driver->in_busy_2 = 1;
- driver->in_busy_lpass_1 = 1;
- driver->in_busy_lpass_2 = 1;
- driver->in_busy_wcnss_1 = 1;
- driver->in_busy_wcnss_2 = 1;
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ }
#ifdef CONFIG_DIAG_SDIO_PIPE
driver->in_busy_sdio = 1;
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diagfwd_disconnect_bridge(0);
diag_clear_hsic_tbl();
#endif
} else if (temp == NO_LOGGING_MODE && driver->logging_mode
== MEMORY_DEVICE_MODE) {
- driver->in_busy_1 = 0;
- driver->in_busy_2 = 0;
- driver->in_busy_lpass_1 = 0;
- driver->in_busy_lpass_2 = 0;
- driver->in_busy_wcnss_1 = 0;
- driver->in_busy_wcnss_2 = 0;
- /* Poll SMD channels to check for data*/
- if (driver->ch)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_work));
- if (driver->chlpass)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_lpass_work));
- if (driver->ch_wcnss)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_work));
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ /* Poll SMD channels to check for data*/
+ if (driver->smd_data[i].ch)
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[i].
+ diag_read_smd_work));
+ }
#ifdef CONFIG_DIAG_SDIO_PIPE
driver->in_busy_sdio = 0;
/* Poll SDIO channel to check for data */
@@ -624,7 +750,7 @@
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diagfwd_connect_bridge(0);
#endif
}
@@ -632,35 +758,27 @@
else if (temp == USB_MODE && driver->logging_mode
== NO_LOGGING_MODE) {
diagfwd_disconnect();
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diagfwd_disconnect_bridge(0);
#endif
} else if (temp == NO_LOGGING_MODE && driver->logging_mode
== USB_MODE) {
diagfwd_connect();
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diagfwd_connect_bridge(0);
#endif
} else if (temp == USB_MODE && driver->logging_mode
== MEMORY_DEVICE_MODE) {
diagfwd_disconnect();
- driver->in_busy_1 = 0;
- driver->in_busy_2 = 0;
- driver->in_busy_lpass_1 = 0;
- driver->in_busy_lpass_2 = 0;
- driver->in_busy_wcnss_1 = 0;
- driver->in_busy_wcnss_2 = 0;
-
- /* Poll SMD channels to check for data*/
- if (driver->ch)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_work));
- if (driver->chlpass)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_lpass_work));
- if (driver->ch_wcnss)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_work));
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ /* Poll SMD channels to check for data*/
+ if (driver->smd_data[i].ch)
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[i].
+ diag_read_smd_work));
+ }
#ifdef CONFIG_DIAG_SDIO_PIPE
driver->in_busy_sdio = 0;
/* Poll SDIO channel to check for data */
@@ -668,14 +786,14 @@
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diagfwd_cancel_hsic();
diagfwd_connect_bridge(0);
#endif
} else if (temp == MEMORY_DEVICE_MODE &&
driver->logging_mode == USB_MODE) {
diagfwd_connect();
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
diag_clear_hsic_tbl();
diagfwd_cancel_hsic();
diagfwd_connect_bridge(0);
@@ -683,6 +801,12 @@
}
#endif /* DIAG over USB */
success = 1;
+ } else if (iocmd == DIAG_IOCTL_REMOTE_DEV) {
+ uint16_t remote_dev = diag_get_remote_device_mask();
+ if (copy_to_user((void *)ioarg, &remote_dev, sizeof(uint16_t)))
+ success = -EFAULT;
+ else
+ success = 1;
}
return success;
@@ -694,6 +818,8 @@
struct diag_dci_client_tbl *entry;
int index = -1, i = 0, ret = 0;
int num_data = 0, data_type;
+ int remote_token;
+
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid == current->tgid)
index = i;
@@ -707,16 +833,16 @@
driver->data_ready[index]);
mutex_lock(&driver->diagchar_mutex);
- if ((driver->data_ready[index] & USER_SPACE_LOG_TYPE) && (driver->
+ if ((driver->data_ready[index] & USER_SPACE_DATA_TYPE) && (driver->
logging_mode == MEMORY_DEVICE_MODE)) {
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
unsigned long spin_lock_flags;
struct diag_write_device hsic_buf_tbl[NUM_HSIC_BUF_TBL_ENTRIES];
#endif
-
+ remote_token = 0;
pr_debug("diag: process woken up\n");
/*Copy the type of data being passed*/
- data_type = driver->data_ready[index] & USER_SPACE_LOG_TYPE;
+ data_type = driver->data_ready[index] & USER_SPACE_DATA_TYPE;
COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
/* place holder for number of data field */
ret += 4;
@@ -761,78 +887,40 @@
}
/* copy modem data */
- if (driver->in_busy_1 == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_1->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- *(driver->buf_in_1),
- driver->write_ptr_1->length);
- driver->in_busy_1 = 0;
- }
- if (driver->in_busy_2 == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_2->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- *(driver->buf_in_2),
- driver->write_ptr_2->length);
- driver->in_busy_2 = 0;
- }
- /* copy lpass data */
- if (driver->in_busy_lpass_1 == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_lpass_1->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
- buf_in_lpass_1),
- driver->write_ptr_lpass_1->length);
- driver->in_busy_lpass_1 = 0;
- }
- if (driver->in_busy_lpass_2 == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_lpass_2->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
- buf_in_lpass_2), driver->
- write_ptr_lpass_2->length);
- driver->in_busy_lpass_2 = 0;
- }
- /* copy wncss data */
- if (driver->in_busy_wcnss_1 == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_wcnss_1->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
- buf_in_wcnss_1),
- driver->write_ptr_wcnss_1->length);
- driver->in_busy_wcnss_1 = 0;
- }
- if (driver->in_busy_wcnss_2 == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_wcnss_2->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret, *(driver->
- buf_in_wcnss_2),
- driver->write_ptr_wcnss_2->length);
- driver->in_busy_wcnss_2 = 0;
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ struct diag_smd_info *data = &driver->smd_data[i];
+ if (data->in_busy_1 == 1) {
+ num_data++;
+ /*Copy the length of data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ (data->write_ptr_1->length), 4);
+ /*Copy the actual data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ *(data->buf_in_1),
+ data->write_ptr_1->length);
+ data->in_busy_1 = 0;
+ }
+ if (data->in_busy_2 == 1) {
+ num_data++;
+ /*Copy the length of data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ (data->write_ptr_2->length), 4);
+ /*Copy the actual data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ *(data->buf_in_2),
+ data->write_ptr_2->length);
+ data->in_busy_2 = 0;
+ }
}
#ifdef CONFIG_DIAG_SDIO_PIPE
/* copy 9K data over SDIO */
if (driver->in_busy_sdio == 1) {
+ remote_token = diag_get_remote(MDM);
num_data++;
+
+ /*Copy the negative token of data being passed*/
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ remote_token, 4);
/*Copy the length of data being passed*/
COPY_USER_SPACE_OR_EXIT(buf+ret,
(driver->write_ptr_mdm->length), 4);
@@ -843,7 +931,7 @@
driver->in_busy_sdio = 0;
}
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
spin_lock_irqsave(&driver->hsic_spinlock, spin_lock_flags);
for (i = 0; i < driver->poolsize_hsic_write; i++) {
hsic_buf_tbl[i].buf = driver->hsic_buf_tbl[i].buf;
@@ -856,12 +944,22 @@
spin_unlock_irqrestore(&driver->hsic_spinlock,
spin_lock_flags);
+ remote_token = diag_get_remote(MDM);
for (i = 0; i < driver->poolsize_hsic_write; i++) {
if (hsic_buf_tbl[i].length > 0) {
pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
i, (unsigned int)hsic_buf_tbl[i].buf,
hsic_buf_tbl[i].length);
num_data++;
+
+ /* Copy the negative token */
+ if (copy_to_user(buf+ret,
+ &remote_token, 4)) {
+ num_data--;
+ goto drop_hsic;
+ }
+ ret += 4;
+
/* Copy the length of data being passed */
if (copy_to_user(buf+ret,
(void *)&(hsic_buf_tbl[i].length),
@@ -890,20 +988,33 @@
diagfwd_write_complete_hsic(NULL);
}
}
+ if (driver->in_busy_smux == 1) {
+ remote_token = diag_get_remote(QSC);
+ num_data++;
+
+ /* Copy the negative token of data being passed */
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ remote_token, 4);
+ /* Copy the length of data being passed */
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ (driver->write_ptr_mdm->length), 4);
+ /* Copy the actual data being passed */
+ COPY_USER_SPACE_OR_EXIT(buf+ret,
+ *(driver->buf_in_smux),
+ driver->write_ptr_mdm->length);
+ pr_debug("diag: SMUX data copied\n");
+ driver->in_busy_smux = 0;
+ }
#endif
/* copy number of data fields */
COPY_USER_SPACE_OR_EXIT(buf+4, num_data, 4);
ret -= 4;
- driver->data_ready[index] ^= USER_SPACE_LOG_TYPE;
- if (driver->ch)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_work));
- if (driver->chlpass)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_lpass_work));
- if (driver->ch_wcnss)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_work));
+ driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ if (driver->smd_data[i].ch)
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[i].diag_read_smd_work));
+ }
#ifdef CONFIG_DIAG_SDIO_PIPE
if (driver->sdio_ch)
queue_work(driver->diag_sdio_wq,
@@ -911,10 +1022,10 @@
#endif
APPEND_DEBUG('n');
goto exit;
- } else if (driver->data_ready[index] & USER_SPACE_LOG_TYPE) {
+ } else if (driver->data_ready[index] & USER_SPACE_DATA_TYPE) {
/* In case, the thread wakes up and the logging mode is
not memory device any more, the condition needs to be cleared */
- driver->data_ready[index] ^= USER_SPACE_LOG_TYPE;
+ driver->data_ready[index] ^= USER_SPACE_DATA_TYPE;
}
if (driver->data_ready[index] & DEINIT_TYPE) {
@@ -971,10 +1082,9 @@
COPY_USER_SPACE_OR_EXIT(buf, data_type, 4);
/* check the current client and copy its data */
for (i = 0; i < MAX_DCI_CLIENTS; i++) {
- if (driver->dci_client_tbl[i].client != NULL) {
- entry = &(driver->dci_client_tbl[i]);
- if (entry && (current->tgid ==
- entry->client->tgid)) {
+ entry = &(driver->dci_client_tbl[i]);
+ if (entry && entry->client) {
+ if (current->tgid == entry->client->tgid) {
COPY_USER_SPACE_OR_EXIT(buf+4,
entry->data_len, 4);
COPY_USER_SPACE_OR_EXIT(buf+8,
@@ -985,10 +1095,12 @@
}
}
driver->data_ready[index] ^= DCI_DATA_TYPE;
- driver->in_busy_dci = 0;
- if (driver->ch_dci)
- queue_work(driver->diag_dci_wq,
- &(driver->diag_read_smd_dci_work));
+ for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) {
+ driver->smd_dci[i].in_busy_1 = 0;
+ if (driver->smd_dci[i].ch)
+ queue_work(driver->diag_dci_wq,
+ &(driver->smd_dci[i].diag_read_smd_work));
+ }
goto exit;
}
exit:
@@ -999,14 +1111,15 @@
static int diagchar_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- int err, ret = 0, pkt_type;
+ int err, ret = 0, pkt_type, token_offset = 0;
+ int remote_proc = 0;
#ifdef DIAG_DEBUG
int length = 0, i;
#endif
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
void *buf_copy = NULL;
- int payload_size;
+ unsigned int payload_size;
#ifdef CONFIG_DIAG_OVER_USB
if (((driver->logging_mode == USB_MODE) && (!driver->usb_connected)) ||
(driver->logging_mode == NO_LOGGING_MODE)) {
@@ -1017,8 +1130,17 @@
/* Get the packet type F3/log/event/Pkt response */
err = copy_from_user((&pkt_type), buf, 4);
/* First 4 bytes indicate the type of payload - ignore these */
+ if (count < 4) {
+ pr_err("diag: Client sending short data\n");
+ return -EBADMSG;
+ }
payload_size = count - 4;
-
+ if (payload_size > USER_SPACE_DATA) {
+ pr_err("diag: Dropping packet, packet payload size crosses 8KB limit. Current payload size %d\n",
+ payload_size);
+ driver->dropped_count++;
+ return -EBADMSG;
+ }
if (pkt_type == DCI_DATA_TYPE) {
err = copy_from_user(driver->user_space_data, buf + 4,
payload_size);
@@ -1030,12 +1152,22 @@
payload_size);
return err;
}
- if (pkt_type == USER_SPACE_LOG_TYPE) {
+ if (pkt_type == USER_SPACE_DATA_TYPE) {
err = copy_from_user(driver->user_space_data, buf + 4,
payload_size);
+ /* Check for proc_type */
+ remote_proc = diag_get_remote(*(int *)driver->user_space_data);
+
+ if (remote_proc) {
+ token_offset = 4;
+ payload_size -= 4;
+ buf += 4;
+ }
+
/* Check masks for On-Device logging */
if (driver->mask_check) {
- if (!mask_request_validate(driver->user_space_data)) {
+ if (!mask_request_validate(driver->user_space_data +
+ token_offset)) {
pr_alert("diag: mask request Invalid\n");
return -EFAULT;
}
@@ -1044,31 +1176,35 @@
#ifdef DIAG_DEBUG
pr_debug("diag: user space data %d\n", payload_size);
for (i = 0; i < payload_size; i++)
- pr_debug("\t %x", *((driver->user_space_data)+i));
+ pr_debug("\t %x", *((driver->user_space_data
+ + token_offset)+i));
#endif
#ifdef CONFIG_DIAG_SDIO_PIPE
/* send masks to 9k too */
- if (driver->sdio_ch) {
+ if (driver->sdio_ch && (remote_proc == MDM)) {
wait_event_interruptible(driver->wait_q,
(sdio_write_avail(driver->sdio_ch) >=
payload_size));
if (driver->sdio_ch && (payload_size > 0)) {
sdio_write(driver->sdio_ch, (void *)
- (driver->user_space_data), payload_size);
+ (driver->user_space_data + token_offset),
+ payload_size);
}
}
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
/* send masks to 9k too */
- if (driver->hsic_ch && (payload_size > 0)) {
+ if (driver->hsic_ch && (payload_size > 0) &&
+ (remote_proc == MDM)) {
/* wait sending mask updates if HSIC ch not ready */
if (driver->in_busy_hsic_write)
wait_event_interruptible(driver->wait_q,
(driver->in_busy_hsic_write != 1));
driver->in_busy_hsic_write = 1;
driver->in_busy_hsic_read_on_device = 0;
- err = diag_bridge_write(driver->user_space_data,
- payload_size);
+ err = diag_bridge_write(
+ driver->user_space_data + token_offset,
+ payload_size);
if (err) {
pr_err("diag: err sending mask to MDM: %d\n",
err);
@@ -1082,10 +1218,25 @@
driver->in_busy_hsic_write = 0;
}
}
+ if (driver->diag_smux_enabled && (remote_proc == QSC)
+ && driver->lcid) {
+ if (payload_size > 0) {
+ err = msm_smux_write(driver->lcid, NULL,
+ driver->user_space_data + token_offset,
+ payload_size);
+ if (err) {
+ pr_err("diag:send mask to MDM err %d",
+ err);
+ return err;
+ }
+ }
+ }
#endif
/* send masks to 8k now */
- diag_process_hdlc((void *)(driver->user_space_data),
- payload_size);
+ if (!remote_proc)
+ diag_process_hdlc((void *)
+ (driver->user_space_data + token_offset),
+ payload_size);
return 0;
}
@@ -1136,13 +1287,21 @@
ret = -ENOMEM;
goto fail_free_hdlc;
}
+ if (HDLC_OUT_BUF_SIZE < (2*payload_size) + 3) {
+ pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
+ ((2*payload_size) + 3));
+ driver->dropped_count++;
+ ret = -EBADMSG;
+ goto fail_free_hdlc;
+ }
if (HDLC_OUT_BUF_SIZE - driver->used <= (2*payload_size) + 3) {
err = diag_device_write(buf_hdlc, APPS_DATA, NULL);
if (err) {
/*Free the buffer right away if write failed */
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
+ if (driver->logging_mode == USB_MODE)
+ diagmem_free(driver, (unsigned char *)driver->
+ write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1169,8 +1328,9 @@
if (err) {
/*Free the buffer right away if write failed */
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
+ if (driver->logging_mode == USB_MODE)
+ diagmem_free(driver, (unsigned char *)driver->
+ write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1194,8 +1354,9 @@
if (err) {
/*Free the buffer right away if write failed */
diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
- diagmem_free(driver, (unsigned char *)driver->
- write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
+ if (driver->logging_mode == USB_MODE)
+ diagmem_free(driver, (unsigned char *)driver->
+ write_ptr_svc, POOL_TYPE_WRITE_STRUCT);
ret = -EIO;
goto fail_free_hdlc;
}
@@ -1203,8 +1364,8 @@
driver->used = 0;
}
- mutex_unlock(&driver->diagchar_mutex);
diagmem_free(driver, buf_copy, POOL_TYPE_COPY);
+ mutex_unlock(&driver->diagchar_mutex);
if (!timer_in_progress) {
timer_in_progress = 1;
ret = mod_timer(&drain_timer, jiffies + msecs_to_jiffies(500));
@@ -1345,6 +1506,13 @@
return 0;
}
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+static void diag_disconnect_work_fn(struct work_struct *w)
+{
+ diagfwd_disconnect_bridge(1);
+}
+#endif
+
#ifdef CONFIG_DIAG_SDIO_PIPE
void diag_sdio_fn(int type)
{
@@ -1359,16 +1527,14 @@
inline void diag_sdio_fn(int type) {}
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
-void diag_bridge_fn(int type)
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+void diagfwd_bridge_fn(int type)
{
- if (type == INIT)
- diagfwd_bridge_init();
- else if (type == EXIT)
+ if (type == EXIT)
diagfwd_bridge_exit();
}
#else
-inline void diag_bridge_fn(int type) {}
+inline void diagfwd_bridge_fn(int type) { }
#endif
static int __init diagchar_init(void)
@@ -1378,6 +1544,12 @@
pr_debug("diagfwd initializing ..\n");
driver = kzalloc(sizeof(struct diagchar_dev) + 5, GFP_KERNEL);
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ diag_bridge = kzalloc(MAX_BRIDGES * sizeof(struct diag_bridge_dev),
+ GFP_KERNEL);
+ if (!diag_bridge)
+ pr_warning("diag: could not allocate memory for bridge\n");
+#endif
if (driver) {
driver->used = 0;
@@ -1394,38 +1566,25 @@
driver->num_clients = max_clients;
driver->logging_mode = USB_MODE;
driver->socket_process = NULL;
+ driver->callback_process = NULL;
driver->mask_check = 0;
mutex_init(&driver->diagchar_mutex);
init_waitqueue_head(&driver->wait_q);
+ init_waitqueue_head(&driver->smd_wait_q);
INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
- INIT_WORK(&(driver->diag_read_smd_work), diag_read_smd_work_fn);
- INIT_WORK(&(driver->diag_read_smd_cntl_work),
- diag_read_smd_cntl_work_fn);
- INIT_WORK(&(driver->diag_read_smd_lpass_work),
- diag_read_smd_lpass_work_fn);
- INIT_WORK(&(driver->diag_read_smd_lpass_cntl_work),
- diag_read_smd_lpass_cntl_work_fn);
- INIT_WORK(&(driver->diag_read_smd_wcnss_work),
- diag_read_smd_wcnss_work_fn);
- INIT_WORK(&(driver->diag_read_smd_wcnss_cntl_work),
- 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_update_smd_dci_work),
- diag_update_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();
diag_masks_init();
+ diagfwd_init();
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ diagfwd_bridge_init(HSIC);
+ diagfwd_bridge_init(SMUX);
+ INIT_WORK(&(driver->diag_disconnect_work),
+ diag_disconnect_work_fn);
+#endif
+ diagfwd_cntl_init();
driver->dci_state = diag_dci_init();
diag_sdio_fn(INIT);
- diag_bridge_fn(INIT);
+
pr_debug("diagchar initializing ..\n");
driver->num = 1;
driver->name = ((void *)driver) + sizeof(struct diagchar_dev);
@@ -1460,7 +1619,7 @@
diagfwd_cntl_exit();
diag_masks_exit();
diag_sdio_fn(EXIT);
- diag_bridge_fn(EXIT);
+ diagfwd_bridge_fn(EXIT);
return -1;
}
@@ -1474,7 +1633,7 @@
diagfwd_cntl_exit();
diag_masks_exit();
diag_sdio_fn(EXIT);
- diag_bridge_fn(EXIT);
+ diagfwd_bridge_fn(EXIT);
diag_debugfs_cleanup();
diagchar_cleanup();
printk(KERN_INFO "done diagchar exit\n");
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 602ca67..0bd26cf 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -40,6 +40,7 @@
#endif
#include "diag_dci.h"
#include "diag_masks.h"
+#include "diagfwd_bridge.h"
#define MODE_CMD 41
#define RESET_ID 2
@@ -48,26 +49,28 @@
unsigned char diag_debug_buf[1024];
static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
struct diag_master_table entry;
-smd_channel_t *ch_temp = NULL, *chlpass_temp = NULL, *ch_wcnss_temp = NULL;
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
+int wrap_enabled;
+uint16_t wrap_count;
void encode_rsp_and_send(int buf_length)
{
+ struct diag_smd_info *data = &(driver->smd_data[MODEM_DATA]);
send.state = DIAG_STATE_START;
send.pkt = driver->apps_rsp_buf;
send.last = (void *)(driver->apps_rsp_buf + buf_length);
send.terminate = 1;
- if (!driver->in_busy_1) {
- enc.dest = driver->buf_in_1;
- enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);
+ if (!data->in_busy_1) {
+ enc.dest = data->buf_in_1;
+ enc.dest_last = (void *)(data->buf_in_1 + APPS_BUF_SIZE - 1);
diag_hdlc_encode(&send, &enc);
- driver->write_ptr_1->buf = driver->buf_in_1;
- driver->write_ptr_1->length = (int)(enc.dest -
- (void *)(driver->buf_in_1));
- driver->in_busy_1 = 1;
- diag_device_write(driver->buf_in_1, MODEM_DATA,
- driver->write_ptr_1);
+ data->write_ptr_1->buf = data->buf_in_1;
+ data->write_ptr_1->length = (int)(enc.dest -
+ (void *)(data->buf_in_1));
+ data->in_busy_1 = 1;
+ diag_device_write(data->buf_in_1, data->peripheral,
+ data->write_ptr_1);
memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE);
}
}
@@ -177,7 +180,8 @@
* has registered to respond for polling
*/
return 1;
- else if (!(driver->ch) && !(chk_apps_master()))
+ else if (!(driver->smd_data[MODEM_DATA].ch) &&
+ !(chk_apps_master()))
/*
* If the apps processor is not the master and the modem
* is not up
@@ -212,69 +216,144 @@
* have their data read/logged. Detect and remedy this
* situation.
*/
- if ((driver->data_ready[i] & USER_SPACE_LOG_TYPE) == 0) {
- driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
+ if ((driver->data_ready[i] & USER_SPACE_DATA_TYPE) == 0) {
+ driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
pr_debug("diag: Force wakeup of logging process\n");
wake_up_interruptible(&driver->wait_q);
}
}
}
-void __diag_smd_send_req(void)
+/* Process the data read from the smd data channel */
+int diag_process_smd_read_data(struct diag_smd_info *smd_info, void *buf,
+ int total_recd)
{
- void *buf = NULL;
- int *in_busy_ptr = NULL;
struct diag_request *write_ptr_modem = NULL;
+ int *in_busy_ptr = 0;
- if (!driver->in_busy_1) {
- buf = driver->buf_in_1;
- write_ptr_modem = driver->write_ptr_1;
- in_busy_ptr = &(driver->in_busy_1);
- } else if (!driver->in_busy_2) {
- buf = driver->buf_in_2;
- write_ptr_modem = driver->write_ptr_2;
- in_busy_ptr = &(driver->in_busy_2);
+ if (smd_info->buf_in_1 == buf) {
+ write_ptr_modem = smd_info->write_ptr_1;
+ in_busy_ptr = &smd_info->in_busy_1;
+ } else if (smd_info->buf_in_2 == buf) {
+ write_ptr_modem = smd_info->write_ptr_2;
+ in_busy_ptr = &smd_info->in_busy_2;
+ } else {
+ pr_err("diag: In %s, no match for in_busy_1\n", __func__);
}
- if (driver->ch && buf) {
- int r = smd_read_avail(driver->ch);
+ if (write_ptr_modem) {
+ write_ptr_modem->length = total_recd;
+ *in_busy_ptr = 1;
+ diag_device_write(buf, smd_info->peripheral, write_ptr_modem);
+ }
- if (r > IN_BUF_SIZE) {
- if (r < MAX_IN_BUF_SIZE) {
- pr_err("diag: SMD sending in "
- "packets upto %d bytes", r);
- buf = krealloc(buf, r, GFP_KERNEL);
- } else {
- pr_err("diag: SMD sending in "
- "packets more than %d bytes", MAX_IN_BUF_SIZE);
+ return 0;
+}
+
+void diag_smd_send_req(struct diag_smd_info *smd_info)
+{
+ void *buf = NULL, *temp_buf = NULL;
+ int total_recd = 0, r = 0, pkt_len;
+ int loop_count = 0;
+ int notify = 0;
+
+ if (!smd_info) {
+ pr_err("diag: In %s, no smd info. Not able to read.\n",
+ __func__);
+ return;
+ }
+
+ if (!smd_info->in_busy_1)
+ buf = smd_info->buf_in_1;
+ else if ((smd_info->type == SMD_DATA_TYPE) && !smd_info->in_busy_2)
+ buf = smd_info->buf_in_2;
+
+ if (smd_info->ch && buf) {
+ temp_buf = buf;
+ pkt_len = smd_cur_packet_size(smd_info->ch);
+
+ while (pkt_len && (pkt_len != total_recd)) {
+ loop_count++;
+ r = smd_read_avail(smd_info->ch);
+ pr_debug("diag: In %s, received pkt %d %d\n",
+ __func__, r, total_recd);
+ if (!r) {
+ /* Nothing to read from SMD */
+ wait_event(driver->smd_wait_q,
+ ((smd_info->ch == 0) ||
+ smd_read_avail(smd_info->ch)));
+ /* If the smd channel is open */
+ if (smd_info->ch) {
+ pr_debug("diag: In %s, return from wait_event\n",
+ __func__);
+ continue;
+ } else {
+ pr_debug("diag: In %s, return from wait_event ch closed\n",
+ __func__);
+ return;
+ }
+ }
+ total_recd += r;
+ if (total_recd > IN_BUF_SIZE) {
+ if (total_recd < MAX_IN_BUF_SIZE) {
+ pr_err("diag: In %s, SMD sending in packets up to %d bytes\n",
+ __func__, total_recd);
+ buf = krealloc(buf, total_recd,
+ GFP_KERNEL);
+ } else {
+ pr_err("diag: In %s, SMD sending in packets more than %d bytes\n",
+ __func__, MAX_IN_BUF_SIZE);
+ return;
+ }
+ }
+ if (pkt_len < r) {
+ pr_err("diag: In %s, SMD sending incorrect pkt\n",
+ __func__);
return;
}
+ if (pkt_len > r) {
+ pr_err("diag: In %s, SMD sending partial pkt %d %d %d %d %d %d\n",
+ __func__, pkt_len, r, total_recd, loop_count,
+ smd_info->peripheral, smd_info->type);
+ }
+
+ /* keep reading for complete packet */
+ smd_read(smd_info->ch, temp_buf, r);
+ temp_buf += r;
}
- if (r > 0) {
- if (!buf)
- pr_info("Out of diagmem for Modem\n");
- else {
- APPEND_DEBUG('i');
- smd_read(driver->ch, buf, r);
- APPEND_DEBUG('j');
- write_ptr_modem->length = r;
- *in_busy_ptr = 1;
- diag_device_write(buf, MODEM_DATA,
- write_ptr_modem);
+
+ if (total_recd > 0) {
+ if (!buf) {
+ pr_err("diag: Out of diagmem for Modem\n");
+ } else if (smd_info->process_smd_read_data) {
+ notify = smd_info->process_smd_read_data(
+ smd_info, buf, total_recd);
+ /* Poll SMD channels to check for data */
+ if (notify)
+ diag_smd_notify(smd_info,
+ SMD_EVENT_DATA);
}
}
- } else if (driver->ch && !buf &&
+ } else if (smd_info->ch && !buf &&
(driver->logging_mode == MEMORY_DEVICE_MODE)) {
- chk_logging_wakeup();
+ chk_logging_wakeup();
}
}
-int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
+void diag_read_smd_work_fn(struct work_struct *work)
+{
+ struct diag_smd_info *smd_info = container_of(work,
+ struct diag_smd_info,
+ diag_read_smd_work);
+ diag_smd_send_req(smd_info);
+}
+
+int diag_device_write(void *buf, int data_type, struct diag_request *write_ptr)
{
int i, err = 0;
if (driver->logging_mode == MEMORY_DEVICE_MODE) {
- if (proc_num == APPS_DATA) {
+ if (data_type == APPS_DATA) {
for (i = 0; i < driver->poolsize_write_struct; i++)
if (driver->buf_tbl[i].length == 0) {
driver->buf_tbl[i].buf = buf;
@@ -290,8 +369,8 @@
}
}
-#ifdef CONFIG_DIAG_BRIDGE_CODE
- else if (proc_num == HSIC_DATA) {
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ else if (data_type == HSIC_DATA) {
unsigned long flags;
int foundIndex = -1;
@@ -300,7 +379,7 @@
if (driver->hsic_buf_tbl[i].length == 0) {
driver->hsic_buf_tbl[i].buf = buf;
driver->hsic_buf_tbl[i].length =
- driver->write_len_mdm;
+ diag_bridge[HSIC].write_len;
driver->num_hsic_buf_tbl_entries++;
foundIndex = i;
break;
@@ -312,7 +391,7 @@
else
pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d\n",
(unsigned int)buf,
- driver->write_len_mdm);
+ diag_bridge[HSIC].write_len);
}
#endif
for (i = 0; i < driver->num_clients; i++)
@@ -320,39 +399,30 @@
driver->logging_process_id)
break;
if (i < driver->num_clients) {
- driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
+ driver->data_ready[i] |= USER_SPACE_DATA_TYPE;
pr_debug("diag: wake up logging process\n");
wake_up_interruptible(&driver->wait_q);
} else
return -EINVAL;
} else if (driver->logging_mode == NO_LOGGING_MODE) {
- if (proc_num == MODEM_DATA) {
- driver->in_busy_1 = 0;
- driver->in_busy_2 = 0;
- queue_work(driver->diag_wq, &(driver->
+ if ((data_type >= 0) && (data_type < NUM_SMD_DATA_CHANNELS)) {
+ driver->smd_data[data_type].in_busy_1 = 0;
+ driver->smd_data[data_type].in_busy_2 = 0;
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[data_type].
diag_read_smd_work));
- } else if (proc_num == LPASS_DATA) {
- driver->in_busy_lpass_1 = 0;
- driver->in_busy_lpass_2 = 0;
- queue_work(driver->diag_wq, &(driver->
- diag_read_smd_lpass_work));
- } else if (proc_num == WCNSS_DATA) {
- driver->in_busy_wcnss_1 = 0;
- driver->in_busy_wcnss_2 = 0;
- queue_work(driver->diag_wq, &(driver->
- diag_read_smd_wcnss_work));
}
#ifdef CONFIG_DIAG_SDIO_PIPE
- else if (proc_num == SDIO_DATA) {
+ else if (data_type == SDIO_DATA) {
driver->in_busy_sdio = 0;
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
}
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
- else if (proc_num == HSIC_DATA) {
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ else if (data_type == HSIC_DATA) {
if (driver->hsic_ch)
- queue_work(driver->diag_bridge_wq,
+ queue_work(diag_bridge[HSIC].wq,
&(driver->diag_read_hsic_work));
}
#endif
@@ -360,7 +430,7 @@
}
#ifdef CONFIG_DIAG_OVER_USB
else if (driver->logging_mode == USB_MODE) {
- if (proc_num == APPS_DATA) {
+ if (data_type == APPS_DATA) {
driver->write_ptr_svc = (struct diag_request *)
(diagmem_alloc(driver, sizeof(struct diag_request),
POOL_TYPE_WRITE_STRUCT));
@@ -371,7 +441,8 @@
driver->write_ptr_svc);
} else
err = -1;
- } else if (proc_num == MODEM_DATA) {
+ } else if ((data_type >= 0) &&
+ (data_type < NUM_SMD_DATA_CHANNELS)) {
write_ptr->buf = buf;
#ifdef DIAG_DEBUG
printk(KERN_INFO "writing data to USB,"
@@ -381,15 +452,9 @@
buf, write_ptr->length, 1);
#endif /* DIAG DEBUG */
err = usb_diag_write(driver->legacy_ch, write_ptr);
- } else if (proc_num == LPASS_DATA) {
- write_ptr->buf = buf;
- err = usb_diag_write(driver->legacy_ch, write_ptr);
- } else if (proc_num == WCNSS_DATA) {
- write_ptr->buf = buf;
- err = usb_diag_write(driver->legacy_ch, write_ptr);
}
#ifdef CONFIG_DIAG_SDIO_PIPE
- else if (proc_num == SDIO_DATA) {
+ else if (data_type == SDIO_DATA) {
if (machine_is_msm8x60_fusion() ||
machine_is_msm8x60_fusn_ffa()) {
write_ptr->buf = buf;
@@ -399,8 +464,8 @@
"while USB write\n");
}
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
- else if (proc_num == HSIC_DATA) {
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ else if (data_type == HSIC_DATA) {
if (driver->hsic_device_enabled) {
struct diag_request *write_ptr_mdm;
write_ptr_mdm = (struct diag_request *)
@@ -410,9 +475,10 @@
if (write_ptr_mdm) {
write_ptr_mdm->buf = buf;
write_ptr_mdm->length =
- driver->write_len_mdm;
- err = usb_diag_write(driver->mdm_ch,
- write_ptr_mdm);
+ diag_bridge[HSIC].write_len;
+ write_ptr_mdm->context = (void *)HSIC;
+ err = usb_diag_write(
+ diag_bridge[HSIC].ch, write_ptr_mdm);
/* Return to the pool immediately */
if (err) {
diagmem_free(driver,
@@ -426,14 +492,16 @@
err = -1;
}
} else {
- pr_err("diag: Incorrect hsic data "
+ pr_err("diag: Incorrect HSIC data "
"while USB write\n");
err = -1;
}
- } else if (proc_num == SMUX_DATA) {
+ } else if (data_type == SMUX_DATA) {
write_ptr->buf = buf;
+ write_ptr->context = (void *)SMUX;
pr_debug("diag: writing SMUX data\n");
- err = usb_diag_write(driver->mdm_ch, write_ptr);
+ err = usb_diag_write(diag_bridge[SMUX].ch,
+ write_ptr);
}
#endif
APPEND_DEBUG('d');
@@ -442,101 +510,6 @@
return err;
}
-void __diag_smd_wcnss_send_req(void)
-{
- void *buf = NULL;
- int *in_busy_wcnss_ptr = NULL;
- struct diag_request *write_ptr_wcnss = NULL;
-
- if (!driver->in_busy_wcnss_1) {
- buf = driver->buf_in_wcnss_1;
- write_ptr_wcnss = driver->write_ptr_wcnss_1;
- in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
- } else if (!driver->in_busy_wcnss_2) {
- buf = driver->buf_in_wcnss_2;
- write_ptr_wcnss = driver->write_ptr_wcnss_2;
- in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
- }
-
- if (driver->ch_wcnss && buf) {
- int r = smd_read_avail(driver->ch_wcnss);
- if (r > IN_BUF_SIZE) {
- if (r < MAX_IN_BUF_SIZE) {
- pr_err("diag: wcnss packets > %d bytes", r);
- buf = krealloc(buf, r, GFP_KERNEL);
- } else {
- pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
- return;
- }
- }
- if (r > 0) {
- if (!buf) {
- pr_err("Out of diagmem for wcnss\n");
- } else {
- APPEND_DEBUG('i');
- smd_read(driver->ch_wcnss, buf, r);
- APPEND_DEBUG('j');
- write_ptr_wcnss->length = r;
- *in_busy_wcnss_ptr = 1;
- diag_device_write(buf, WCNSS_DATA,
- write_ptr_wcnss);
- }
- }
- } else if (driver->ch_wcnss && !buf &&
- (driver->logging_mode == MEMORY_DEVICE_MODE)) {
- chk_logging_wakeup();
- }
-}
-
-void __diag_smd_lpass_send_req(void)
-{
- void *buf = NULL;
- int *in_busy_lpass_ptr = NULL;
- struct diag_request *write_ptr_lpass = NULL;
-
- if (!driver->in_busy_lpass_1) {
- buf = driver->buf_in_lpass_1;
- write_ptr_lpass = driver->write_ptr_lpass_1;
- in_busy_lpass_ptr = &(driver->in_busy_lpass_1);
- } else if (!driver->in_busy_lpass_2) {
- buf = driver->buf_in_lpass_2;
- write_ptr_lpass = driver->write_ptr_lpass_2;
- in_busy_lpass_ptr = &(driver->in_busy_lpass_2);
- }
-
- if (driver->chlpass && buf) {
- int r = smd_read_avail(driver->chlpass);
-
- if (r > IN_BUF_SIZE) {
- if (r < MAX_IN_BUF_SIZE) {
- pr_err("diag: SMD sending in "
- "packets upto %d bytes", r);
- buf = krealloc(buf, r, GFP_KERNEL);
- } else {
- pr_err("diag: SMD sending in "
- "packets more than %d bytes", MAX_IN_BUF_SIZE);
- return;
- }
- }
- if (r > 0) {
- if (!buf)
- printk(KERN_INFO "Out of diagmem for LPASS\n");
- else {
- APPEND_DEBUG('i');
- smd_read(driver->chlpass, buf, r);
- APPEND_DEBUG('j');
- write_ptr_lpass->length = r;
- *in_busy_lpass_ptr = 1;
- diag_device_write(buf, LPASS_DATA,
- write_ptr_lpass);
- }
- }
- } else if (driver->chlpass && !buf &&
- (driver->logging_mode == MEMORY_DEVICE_MODE)) {
- chk_logging_wakeup();
- }
-}
-
static void diag_update_pkt_buffer(unsigned char *buf)
{
unsigned char *ptr = driver->pkt_buf;
@@ -576,6 +549,15 @@
mutex_unlock(&driver->diagchar_mutex);
}
+static int diag_check_mode_reset(unsigned char *buf)
+{
+ int is_mode_reset = 0;
+ if (chk_apps_master() && (int)(*(char *)buf) == MODE_CMD)
+ if ((int)(*(char *)(buf+1)) == RESET_ID)
+ is_mode_reset = 1;
+ return is_mode_reset;
+}
+
void diag_send_data(struct diag_master_table entry, unsigned char *buf,
int len, int type)
{
@@ -585,21 +567,23 @@
diag_update_sleeping_process(entry.process_id, PKT_TYPE);
} else {
if (len > 0) {
- if (entry.client_id == MODEM_PROC && driver->ch) {
- if (chk_apps_master() &&
- (int)(*(char *)buf) == MODE_CMD)
- if ((int)(*(char *)(buf+1)) ==
- RESET_ID)
+ if ((entry.client_id >= 0) &&
+ (entry.client_id < NUM_SMD_DATA_CHANNELS)) {
+ int index = entry.client_id;
+ if (driver->smd_data[index].ch) {
+ if ((index == MODEM_DATA) &&
+ diag_check_mode_reset(buf)) {
return;
- smd_write(driver->ch, buf, len);
- } else if (entry.client_id == LPASS_PROC &&
- driver->chlpass) {
- smd_write(driver->chlpass, buf, len);
- } else if (entry.client_id == WCNSS_PROC &&
- driver->ch_wcnss) {
- smd_write(driver->ch_wcnss, buf, len);
+ }
+ smd_write(driver->smd_data[index].ch,
+ buf, len);
+ } else {
+ pr_err("diag: In %s, smd channel %d not open\n",
+ __func__, index);
+ }
} else {
- pr_alert("diag: incorrect channel");
+ pr_alert("diag: In %s, incorrect channel: %d",
+ __func__, entry.client_id);
}
}
}
@@ -680,7 +664,8 @@
return 0;
}
/* Check for Apps Only & get event mask request */
- else if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
+ else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only() &&
+ *buf == 0x81) {
driver->apps_rsp_buf[0] = 0x81;
driver->apps_rsp_buf[1] = 0x0;
*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
@@ -691,7 +676,7 @@
return 0;
}
/* Get log ID range & Check for Apps Only */
- else if (!(driver->ch) && chk_apps_only()
+ else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
&& (*buf == 0x73) && *(int *)(buf+4) == 1) {
driver->apps_rsp_buf[0] = 0x73;
*(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
@@ -716,7 +701,7 @@
return 0;
}
/* Respond to Get SSID Range request message */
- else if (!(driver->ch) && chk_apps_only()
+ else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
&& (*buf == 0x7d) && (*(buf+1) == 0x1)) {
driver->apps_rsp_buf[0] = 0x7d;
driver->apps_rsp_buf[1] = 0x1;
@@ -774,7 +759,7 @@
return 0;
}
/* Check for Apps Only Respond to Get Subsys Build mask */
- else if (!(driver->ch) && chk_apps_only()
+ else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
&& (*buf == 0x7d) && (*(buf+1) == 0x2)) {
ssid_first = *(uint16_t *)(buf + 2);
ssid_last = *(uint16_t *)(buf + 4);
@@ -913,6 +898,23 @@
return 0;
}
}
+ /* Return the Delayed Response Wrap Status */
+ else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ (*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
+ memcpy(driver->apps_rsp_buf, buf, 4);
+ driver->apps_rsp_buf[4] = wrap_enabled;
+ encode_rsp_and_send(4);
+ return 0;
+ }
+ /* Wrap the Delayed Rsp ID */
+ else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
+ (*(buf+2) == 0x05) && (*(buf+3) == 0x0)) {
+ wrap_enabled = true;
+ memcpy(driver->apps_rsp_buf, buf, 4);
+ driver->apps_rsp_buf[4] = wrap_count;
+ encode_rsp_and_send(5);
+ return 0;
+ }
/* Check for ID for NO MODEM present */
else if (chk_polling_response()) {
/* respond to 0x0 command */
@@ -991,13 +993,14 @@
type = 0;
}
/* implies this packet is NOT meant for apps */
- if (!(driver->ch) && type == 1) {
+ if (!(driver->smd_data[MODEM_DATA].ch) && type == 1) {
if (chk_apps_only()) {
diag_send_error_rsp(hdlc.dest_idx);
} else { /* APQ 8060, Let Q6 respond */
- if (driver->chlpass)
- smd_write(driver->chlpass, driver->hdlc_buf,
- hdlc.dest_idx - 3);
+ if (driver->smd_data[LPASS_DATA].ch)
+ smd_write(driver->smd_data[LPASS_DATA].ch,
+ driver->hdlc_buf,
+ hdlc.dest_idx - 3);
}
type = 0;
}
@@ -1009,9 +1012,11 @@
driver->hdlc_buf)+i));
#endif /* DIAG DEBUG */
/* ignore 2 bytes for CRC, one for 7E and send */
- if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
+ if ((driver->smd_data[MODEM_DATA].ch) && (ret) && (type) &&
+ (hdlc.dest_idx > 3)) {
APPEND_DEBUG('g');
- smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
+ smd_write(driver->smd_data[MODEM_DATA].ch,
+ driver->hdlc_buf, hdlc.dest_idx - 3);
APPEND_DEBUG('h');
#ifdef DIAG_DEBUG
printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
@@ -1029,6 +1034,7 @@
int diagfwd_connect(void)
{
int err;
+ int i;
printk(KERN_DEBUG "diag: USB connected\n");
err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
@@ -1037,21 +1043,16 @@
printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
driver->usb_connected = 1;
- driver->in_busy_1 = 0;
- driver->in_busy_2 = 0;
- driver->in_busy_lpass_1 = 0;
- driver->in_busy_lpass_2 = 0;
- driver->in_busy_wcnss_1 = 0;
- driver->in_busy_wcnss_2 = 0;
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 0;
+ driver->smd_data[i].in_busy_2 = 0;
+ /* Poll SMD data channels to check for data */
+ queue_work(driver->diag_wq,
+ &(driver->smd_data[i].diag_read_smd_work));
+ /* Poll SMD CNTL channels to check for data */
+ diag_smd_notify(&(driver->smd_cntl[i]), SMD_EVENT_DATA);
+ }
- /* Poll SMD channels to check for data*/
- queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
- queue_work(driver->diag_wq, &(driver->diag_read_smd_lpass_work));
- queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
- /* Poll SMD CNTL channels to check for data */
- diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
- diag_smd_lpass_cntl_notify(NULL, SMD_EVENT_DATA);
- diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
/* Poll USB channel to check for data*/
queue_work(driver->diag_wq, &(driver->diag_read_work));
#ifdef CONFIG_DIAG_SDIO_PIPE
@@ -1067,17 +1068,17 @@
int diagfwd_disconnect(void)
{
+ int i;
+
printk(KERN_DEBUG "diag: USB disconnected\n");
driver->usb_connected = 0;
driver->debug_flag = 1;
usb_diag_free_req(driver->legacy_ch);
if (driver->logging_mode == USB_MODE) {
- driver->in_busy_1 = 1;
- driver->in_busy_2 = 1;
- driver->in_busy_lpass_1 = 1;
- driver->in_busy_lpass_2 = 1;
- driver->in_busy_wcnss_1 = 1;
- driver->in_busy_wcnss_2 = 1;
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ driver->smd_data[i].in_busy_1 = 1;
+ driver->smd_data[i].in_busy_2 = 1;
+ }
}
#ifdef CONFIG_DIAG_SDIO_PIPE
if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
@@ -1091,50 +1092,44 @@
int diagfwd_write_complete(struct diag_request *diag_write_ptr)
{
unsigned char *buf = diag_write_ptr->buf;
- /*Determine if the write complete is for data from modem/apps/q6 */
+ int found_it = 0;
+ int i;
+
+ /* Determine if the write complete is for data from modem/apps/q6 */
/* Need a context variable here instead */
- if (buf == (void *)driver->buf_in_1) {
- driver->in_busy_1 = 0;
- APPEND_DEBUG('o');
- queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
- } else if (buf == (void *)driver->buf_in_2) {
- driver->in_busy_2 = 0;
- APPEND_DEBUG('O');
- queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
- } else if (buf == (void *)driver->buf_in_lpass_1) {
- driver->in_busy_lpass_1 = 0;
- APPEND_DEBUG('p');
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_lpass_work));
- } else if (buf == (void *)driver->buf_in_lpass_2) {
- driver->in_busy_lpass_2 = 0;
- APPEND_DEBUG('P');
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_lpass_work));
- } else if (buf == driver->buf_in_wcnss_1) {
- driver->in_busy_wcnss_1 = 0;
- APPEND_DEBUG('r');
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_work));
- } else if (buf == driver->buf_in_wcnss_2) {
- driver->in_busy_wcnss_2 = 0;
- APPEND_DEBUG('R');
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_work));
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++) {
+ struct diag_smd_info *data = &(driver->smd_data[i]);
+ if (buf == (void *)data->buf_in_1) {
+ data->in_busy_1 = 0;
+ queue_work(driver->diag_wq,
+ &(data->diag_read_smd_work));
+ found_it = 1;
+ break;
+ } else if (buf == (void *)data->buf_in_2) {
+ data->in_busy_2 = 0;
+ queue_work(driver->diag_wq,
+ &(data->diag_read_smd_work));
+ found_it = 1;
+ break;
+ }
}
#ifdef CONFIG_DIAG_SDIO_PIPE
- else if (buf == (void *)driver->buf_in_sdio)
- if (machine_is_msm8x60_fusion() ||
- machine_is_msm8x60_fusn_ffa())
- diagfwd_write_complete_sdio();
- else
- pr_err("diag: Incorrect buffer pointer while WRITE");
+ if (!found_it) {
+ if (buf == (void *)driver->buf_in_sdio) {
+ if (machine_is_msm8x60_fusion() ||
+ machine_is_msm8x60_fusn_ffa())
+ diagfwd_write_complete_sdio();
+ else
+ pr_err("diag: Incorrect buffer pointer while WRITE");
+ found_it = 1;
+ }
+ }
#endif
- else {
- diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
+ if (!found_it) {
+ diagmem_free(driver, (unsigned char *)buf,
+ POOL_TYPE_HDLC);
diagmem_free(driver, (unsigned char *)diag_write_ptr,
- POOL_TYPE_WRITE_STRUCT);
- APPEND_DEBUG('q');
+ POOL_TYPE_WRITE_STRUCT);
}
return 0;
}
@@ -1221,70 +1216,87 @@
#endif /* DIAG OVER USB */
-static void diag_smd_notify(void *ctxt, unsigned event)
+void diag_smd_notify(void *ctxt, unsigned event)
{
- if (event == SMD_EVENT_CLOSE) {
- queue_work(driver->diag_cntl_wq,
- &(driver->diag_clean_modem_reg_work));
- driver->ch = 0;
+ struct diag_smd_info *smd_info = (struct diag_smd_info *)ctxt;
+ if (!smd_info)
return;
- } else if (event == SMD_EVENT_OPEN) {
- if (ch_temp)
- driver->ch = ch_temp;
- }
- queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
-}
-#if defined(CONFIG_MSM_N_WAY_SMD)
-static void diag_smd_lpass_notify(void *ctxt, unsigned event)
-{
if (event == SMD_EVENT_CLOSE) {
- queue_work(driver->diag_cntl_wq,
- &(driver->diag_clean_lpass_reg_work));
- driver->chlpass = 0;
+ smd_info->ch = 0;
+ wake_up(&driver->smd_wait_q);
+ if (smd_info->type == SMD_DATA_TYPE) {
+ smd_info->notify_context = event;
+ queue_work(driver->diag_cntl_wq,
+ &(smd_info->diag_notify_update_smd_work));
+ } else if (smd_info->type == SMD_DCI_TYPE) {
+ /* Notify the clients of the close */
+ diag_dci_notify_client(smd_info->peripheral_mask,
+ DIAG_STATUS_CLOSED);
+ }
return;
} else if (event == SMD_EVENT_OPEN) {
- if (chlpass_temp)
- driver->chlpass = chlpass_temp;
- }
- queue_work(driver->diag_wq, &(driver->diag_read_smd_lpass_work));
-}
-#endif
+ if (smd_info->ch_save)
+ smd_info->ch = smd_info->ch_save;
-static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
-{
- if (event == SMD_EVENT_CLOSE) {
- queue_work(driver->diag_cntl_wq,
- &(driver->diag_clean_wcnss_reg_work));
- driver->ch_wcnss = 0;
- return;
- } else if (event == SMD_EVENT_OPEN) {
- if (ch_wcnss_temp)
- driver->ch_wcnss = ch_wcnss_temp;
+ if (smd_info->type == SMD_CNTL_TYPE) {
+ smd_info->notify_context = event;
+ queue_work(driver->diag_cntl_wq,
+ &(smd_info->diag_notify_update_smd_work));
+ } else if (smd_info->type == SMD_DCI_TYPE) {
+ smd_info->notify_context = event;
+ queue_work(driver->diag_dci_wq,
+ &(smd_info->diag_notify_update_smd_work));
+ /* Notify the clients of the open */
+ diag_dci_notify_client(smd_info->peripheral_mask,
+ DIAG_STATUS_OPEN);
+ }
}
- queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
+
+ wake_up(&driver->smd_wait_q);
+
+ if (smd_info->type == SMD_DCI_TYPE)
+ queue_work(driver->diag_dci_wq,
+ &(smd_info->diag_read_smd_work));
+ else
+ queue_work(driver->diag_wq, &(smd_info->diag_read_smd_work));
}
static int diag_smd_probe(struct platform_device *pdev)
{
int r = 0;
+ int index = -1;
if (pdev->id == SMD_APPS_MODEM) {
- r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
- ch_temp = driver->ch;
+ index = MODEM_DATA;
+ r = smd_open("DIAG", &driver->smd_data[index].ch,
+ &driver->smd_data[index],
+ diag_smd_notify);
+ driver->smd_data[index].ch_save =
+ driver->smd_data[index].ch;
}
#if defined(CONFIG_MSM_N_WAY_SMD)
if (pdev->id == SMD_APPS_QDSP) {
+ index = LPASS_DATA;
r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP,
- &driver->chlpass, driver, diag_smd_lpass_notify);
- chlpass_temp = driver->chlpass;
+ &driver->smd_data[index].ch,
+ &driver->smd_data[index],
+ diag_smd_notify);
+ driver->smd_data[index].ch_save =
+ driver->smd_data[index].ch;
}
#endif
if (pdev->id == SMD_APPS_WCNSS) {
- r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
- , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
- ch_wcnss_temp = driver->ch_wcnss;
+ index = WCNSS_DATA;
+ r = smd_named_open_on_edge("APPS_RIVA_DATA",
+ SMD_APPS_WCNSS,
+ &driver->smd_data[index].ch,
+ &driver->smd_data[index],
+ diag_smd_notify);
+ driver->smd_data[index].ch_save =
+ driver->smd_data[index].ch;
}
+
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
@@ -1292,86 +1304,192 @@
return 0;
}
-static int diagfwd_runtime_suspend(struct device *dev)
+static int diag_smd_runtime_suspend(struct device *dev)
{
dev_dbg(dev, "pm_runtime: suspending...\n");
return 0;
}
-static int diagfwd_runtime_resume(struct device *dev)
+static int diag_smd_runtime_resume(struct device *dev)
{
dev_dbg(dev, "pm_runtime: resuming...\n");
return 0;
}
-static const struct dev_pm_ops diagfwd_dev_pm_ops = {
- .runtime_suspend = diagfwd_runtime_suspend,
- .runtime_resume = diagfwd_runtime_resume,
+static const struct dev_pm_ops diag_smd_dev_pm_ops = {
+ .runtime_suspend = diag_smd_runtime_suspend,
+ .runtime_resume = diag_smd_runtime_resume,
};
static struct platform_driver msm_smd_ch1_driver = {
.probe = diag_smd_probe,
.driver = {
- .name = "DIAG",
- .owner = THIS_MODULE,
- .pm = &diagfwd_dev_pm_ops,
- },
+ .name = "DIAG",
+ .owner = THIS_MODULE,
+ .pm = &diag_smd_dev_pm_ops,
+ },
};
static struct platform_driver diag_smd_lite_driver = {
.probe = diag_smd_probe,
.driver = {
- .name = "APPS_RIVA_DATA",
- .owner = THIS_MODULE,
- .pm = &diagfwd_dev_pm_ops,
- },
+ .name = "APPS_RIVA_DATA",
+ .owner = THIS_MODULE,
+ .pm = &diag_smd_dev_pm_ops,
+ },
};
+void diag_smd_destructor(struct diag_smd_info *smd_info)
+{
+ if (smd_info->ch)
+ smd_close(smd_info->ch);
+
+ smd_info->ch = 0;
+ smd_info->ch_save = 0;
+ kfree(smd_info->buf_in_1);
+ kfree(smd_info->buf_in_2);
+ kfree(smd_info->write_ptr_1);
+ kfree(smd_info->write_ptr_2);
+}
+
+int diag_smd_constructor(struct diag_smd_info *smd_info, int peripheral,
+ int type)
+{
+ smd_info->peripheral = peripheral;
+ smd_info->type = type;
+
+ switch (peripheral) {
+ case MODEM_DATA:
+ smd_info->peripheral_mask = DIAG_CON_MPSS;
+ break;
+ case LPASS_DATA:
+ smd_info->peripheral_mask = DIAG_CON_LPASS;
+ break;
+ case WCNSS_DATA:
+ smd_info->peripheral_mask = DIAG_CON_WCNSS;
+ break;
+ default:
+ pr_err("diag: In %s, unknown peripheral, peripheral: %d\n",
+ __func__, peripheral);
+ goto err;
+ }
+
+ smd_info->ch = 0;
+ smd_info->ch_save = 0;
+
+ if (smd_info->buf_in_1 == NULL) {
+ smd_info->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+ if (smd_info->buf_in_1 == NULL)
+ goto err;
+ kmemleak_not_leak(smd_info->buf_in_1);
+ }
+
+ if (smd_info->write_ptr_1 == NULL) {
+ smd_info->write_ptr_1 = kzalloc(sizeof(struct diag_request),
+ GFP_KERNEL);
+ if (smd_info->write_ptr_1 == NULL)
+ goto err;
+ kmemleak_not_leak(smd_info->write_ptr_1);
+ }
+
+ /* The smd data type needs two buffers */
+ if (smd_info->type == SMD_DATA_TYPE) {
+ if (smd_info->buf_in_2 == NULL) {
+ smd_info->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+ if (smd_info->buf_in_2 == NULL)
+ goto err;
+ kmemleak_not_leak(smd_info->buf_in_2);
+ }
+ if (smd_info->write_ptr_2 == NULL) {
+ smd_info->write_ptr_2 =
+ kzalloc(sizeof(struct diag_request),
+ GFP_KERNEL);
+ if (smd_info->write_ptr_2 == NULL)
+ goto err;
+ kmemleak_not_leak(smd_info->write_ptr_2);
+ }
+ }
+
+ INIT_WORK(&(smd_info->diag_read_smd_work), diag_read_smd_work_fn);
+
+ /*
+ * The update function assigned to the diag_notify_update_smd_work
+ * work_struct is meant to be used for updating that is not to
+ * be done in the context of the smd notify function. The
+ * notify_context variable can be used for passing additional
+ * information to the update function.
+ */
+ smd_info->notify_context = 0;
+ if (type == SMD_DATA_TYPE)
+ INIT_WORK(&(smd_info->diag_notify_update_smd_work),
+ diag_clean_reg_fn);
+ else if (type == SMD_CNTL_TYPE)
+ INIT_WORK(&(smd_info->diag_notify_update_smd_work),
+ diag_mask_update_fn);
+ else if (type == SMD_DCI_TYPE)
+ INIT_WORK(&(smd_info->diag_notify_update_smd_work),
+ diag_update_smd_dci_work_fn);
+ else {
+ pr_err("diag: In %s, unknown type, type: %d\n", __func__, type);
+ goto err;
+ }
+
+ /*
+ * Set function ptr for function to call to process the data that
+ * was just read from the smd channel
+ */
+ if (type == SMD_DATA_TYPE)
+ smd_info->process_smd_read_data = diag_process_smd_read_data;
+ else if (type == SMD_CNTL_TYPE)
+ smd_info->process_smd_read_data =
+ diag_process_smd_cntl_read_data;
+ else if (type == SMD_DCI_TYPE)
+ smd_info->process_smd_read_data =
+ diag_process_smd_dci_read_data;
+ else {
+ pr_err("diag: In %s, unknown type, type: %d\n", __func__, type);
+ goto err;
+ }
+
+ return 1;
+err:
+ kfree(smd_info->buf_in_1);
+ kfree(smd_info->buf_in_2);
+ kfree(smd_info->write_ptr_1);
+ kfree(smd_info->write_ptr_2);
+
+ return 0;
+}
+
void diagfwd_init(void)
{
+ int success;
+ int i;
+
+ wrap_enabled = 0;
+ wrap_count = 0;
diag_debug_buf_idx = 0;
driver->read_len_legacy = 0;
driver->use_device_tree = has_device_tree();
mutex_init(&driver->diag_cntl_mutex);
- if (driver->buf_in_1 == NULL) {
- driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_1 == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_1);
- }
- if (driver->buf_in_2 == NULL) {
- driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_2 == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_2);
- }
- if (driver->buf_in_lpass_1 == NULL) {
- driver->buf_in_lpass_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_lpass_1 == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_lpass_1);
- }
- if (driver->buf_in_lpass_2 == NULL) {
- driver->buf_in_lpass_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_lpass_2 == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_lpass_2);
- }
- if (driver->buf_in_wcnss_1 == NULL) {
- driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_wcnss_1 == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_wcnss_1);
- }
- if (driver->buf_in_wcnss_2 == NULL) {
- driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_wcnss_2 == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_wcnss_2);
- }
+ success = diag_smd_constructor(&driver->smd_data[MODEM_DATA],
+ MODEM_DATA, SMD_DATA_TYPE);
+ if (!success)
+ goto err;
+
+ success = diag_smd_constructor(&driver->smd_data[LPASS_DATA],
+ LPASS_DATA, SMD_DATA_TYPE);
+ if (!success)
+ goto err;
+
+ success = diag_smd_constructor(&driver->smd_data[WCNSS_DATA],
+ WCNSS_DATA, SMD_DATA_TYPE);
+ if (!success)
+ goto err;
+
if (driver->usb_buf_out == NULL &&
(driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
GFP_KERNEL)) == NULL)
@@ -1409,48 +1527,6 @@
GFP_KERNEL)) == NULL)
goto err;
kmemleak_not_leak(driver->table);
- if (driver->write_ptr_1 == NULL) {
- driver->write_ptr_1 = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_1 == NULL)
- goto err;
- kmemleak_not_leak(driver->write_ptr_1);
- }
- if (driver->write_ptr_2 == NULL) {
- driver->write_ptr_2 = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_2 == NULL)
- goto err;
- kmemleak_not_leak(driver->write_ptr_2);
- }
- if (driver->write_ptr_lpass_1 == NULL) {
- driver->write_ptr_lpass_1 = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_lpass_1 == NULL)
- goto err;
- kmemleak_not_leak(driver->write_ptr_lpass_1);
- }
- if (driver->write_ptr_lpass_2 == NULL) {
- driver->write_ptr_lpass_2 = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_lpass_2 == NULL)
- goto err;
- kmemleak_not_leak(driver->write_ptr_lpass_2);
- }
- if (driver->write_ptr_wcnss_1 == NULL) {
- driver->write_ptr_wcnss_1 = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_wcnss_1 == NULL)
- goto err;
- kmemleak_not_leak(driver->write_ptr_wcnss_1);
- }
- if (driver->write_ptr_wcnss_2 == NULL) {
- driver->write_ptr_wcnss_2 = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_wcnss_2 == NULL)
- goto err;
- kmemleak_not_leak(driver->write_ptr_wcnss_2);
- }
if (driver->usb_read_ptr == NULL) {
driver->usb_read_ptr = kzalloc(
@@ -1483,16 +1559,13 @@
#endif
platform_driver_register(&msm_smd_ch1_driver);
platform_driver_register(&diag_smd_lite_driver);
-
return;
err:
pr_err("diag: Could not initialize diag buffers");
- kfree(driver->buf_in_1);
- kfree(driver->buf_in_2);
- kfree(driver->buf_in_lpass_1);
- kfree(driver->buf_in_lpass_2);
- kfree(driver->buf_in_wcnss_1);
- kfree(driver->buf_in_wcnss_2);
+
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++)
+ diag_smd_destructor(&driver->smd_data[i]);
+
kfree(driver->buf_msg_mask_update);
kfree(driver->buf_log_mask_update);
kfree(driver->buf_event_mask_update);
@@ -1503,12 +1576,6 @@
kfree(driver->data_ready);
kfree(driver->table);
kfree(driver->pkt_buf);
- kfree(driver->write_ptr_1);
- kfree(driver->write_ptr_2);
- kfree(driver->write_ptr_lpass_1);
- kfree(driver->write_ptr_lpass_2);
- kfree(driver->write_ptr_wcnss_1);
- kfree(driver->write_ptr_wcnss_2);
kfree(driver->usb_read_ptr);
kfree(driver->apps_rsp_buf);
kfree(driver->user_space_data);
@@ -1518,12 +1585,11 @@
void diagfwd_exit(void)
{
- smd_close(driver->ch);
- smd_close(driver->chlpass);
- smd_close(driver->ch_wcnss);
- driver->ch = 0; /* SMD can make this NULL */
- driver->chlpass = 0;
- driver->ch_wcnss = 0;
+ int i;
+
+ for (i = 0; i < NUM_SMD_DATA_CHANNELS; i++)
+ diag_smd_destructor(&driver->smd_data[i]);
+
#ifdef CONFIG_DIAG_OVER_USB
if (driver->usb_connected)
usb_diag_free_req(driver->legacy_ch);
@@ -1532,12 +1598,7 @@
platform_driver_unregister(&msm_smd_ch1_driver);
platform_driver_unregister(&msm_diag_dci_driver);
platform_driver_unregister(&diag_smd_lite_driver);
- kfree(driver->buf_in_1);
- kfree(driver->buf_in_2);
- kfree(driver->buf_in_lpass_1);
- kfree(driver->buf_in_lpass_2);
- kfree(driver->buf_in_wcnss_1);
- kfree(driver->buf_in_wcnss_2);
+
kfree(driver->buf_msg_mask_update);
kfree(driver->buf_log_mask_update);
kfree(driver->buf_event_mask_update);
@@ -1548,12 +1609,6 @@
kfree(driver->data_ready);
kfree(driver->table);
kfree(driver->pkt_buf);
- kfree(driver->write_ptr_1);
- kfree(driver->write_ptr_2);
- kfree(driver->write_ptr_lpass_1);
- kfree(driver->write_ptr_lpass_2);
- kfree(driver->write_ptr_wcnss_1);
- kfree(driver->write_ptr_wcnss_2);
kfree(driver->usb_read_ptr);
kfree(driver->apps_rsp_buf);
kfree(driver->user_space_data);
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index a0631d6..14e2dd5 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -22,9 +22,7 @@
void diagfwd_init(void);
void diagfwd_exit(void);
void diag_process_hdlc(void *data, unsigned len);
-void __diag_smd_send_req(void);
-void __diag_smd_lpass_send_req(void);
-void __diag_smd_wcnss_send_req(void);
+void diag_smd_send_req(struct diag_smd_info *smd_info);
void diag_usb_legacy_notifier(void *, unsigned, struct diag_request *);
long diagchar_ioctl(struct file *, unsigned int, unsigned long);
int diag_device_write(void *, int, struct diag_request *);
@@ -37,6 +35,10 @@
void diag_update_userspace_clients(unsigned int type);
void diag_update_sleeping_process(int process_id, int data_type);
void encode_rsp_and_send(int buf_length);
+void diag_smd_notify(void *ctxt, unsigned event);
+int diag_smd_constructor(struct diag_smd_info *smd_info, int peripheral,
+ int type);
+void diag_smd_destructor(struct diag_smd_info *smd_info);
/* State for diag forwarding */
#ifdef CONFIG_DIAG_OVER_USB
int diagfwd_connect(void);
diff --git a/drivers/char/diag/diagfwd_bridge.c b/drivers/char/diag/diagfwd_bridge.c
new file mode 100644
index 0000000..75fdeb4
--- /dev/null
+++ b/drivers/char/diag/diagfwd_bridge.c
@@ -0,0 +1,355 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/diagchar.h>
+#include <linux/kmemleak.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/ratelimit.h>
+#include <linux/platform_device.h>
+#include <linux/smux.h>
+#ifdef CONFIG_DIAG_OVER_USB
+#include <mach/usbdiag.h>
+#endif
+#include "diagchar.h"
+#include "diagmem.h"
+#include "diagfwd_cntl.h"
+#include "diagfwd_smux.h"
+#include "diagfwd_hsic.h"
+#include "diag_masks.h"
+#include "diagfwd_bridge.h"
+
+struct diag_bridge_dev *diag_bridge;
+
+/* diagfwd_connect_bridge is called when the USB mdm channel is connected */
+int diagfwd_connect_bridge(int process_cable)
+{
+ int i;
+
+ pr_debug("diag: in %s\n", __func__);
+
+ for (i = 0; i < MAX_BRIDGES; i++)
+ if (diag_bridge[i].enabled)
+ connect_bridge(process_cable, i);
+ return 0;
+}
+
+void connect_bridge(int process_cable, int index)
+{
+ int err;
+
+ mutex_lock(&diag_bridge[index].bridge_mutex);
+ /* If the usb cable is being connected */
+ if (process_cable) {
+ err = usb_diag_alloc_req(diag_bridge[index].ch, N_MDM_WRITE,
+ N_MDM_READ);
+ if (err)
+ pr_err("diag: unable to alloc USB req on mdm ch err:%d\n",
+ err);
+
+ diag_bridge[index].usb_connected = 1;
+ }
+
+ if (index == SMUX && driver->diag_smux_enabled) {
+ driver->in_busy_smux = 0;
+ diagfwd_connect_smux();
+ } else if (index == HSIC && driver->hsic_device_enabled) {
+ driver->in_busy_hsic_read_on_device = 0;
+ driver->in_busy_hsic_write = 0;
+ /* If the HSIC (diag_bridge) platform device is not open */
+ if (!driver->hsic_device_opened) {
+ err = diag_bridge_open(&hsic_diag_bridge_ops);
+ if (err) {
+ pr_err("diag: HSIC channel open error: %d\n",
+ err);
+ } else {
+ pr_debug("diag: opened HSIC channel\n");
+ driver->hsic_device_opened = 1;
+ }
+ } else {
+ pr_debug("diag: HSIC channel already open\n");
+ }
+ /*
+ * Turn on communication over usb mdm and HSIC, if the HSIC
+ * device driver is enabled and opened
+ */
+ if (driver->hsic_device_opened) {
+ driver->hsic_ch = 1;
+ /* Poll USB mdm channel to check for data */
+ if (driver->logging_mode == USB_MODE)
+ queue_work(diag_bridge[HSIC].wq,
+ &diag_bridge[HSIC].diag_read_work);
+ /* Poll HSIC channel to check for data */
+ queue_work(diag_bridge[HSIC].wq,
+ &driver->diag_read_hsic_work);
+ }
+ }
+ mutex_unlock(&diag_bridge[index].bridge_mutex);
+}
+
+/*
+ * diagfwd_disconnect_bridge is called when the USB mdm channel
+ * is disconnected. So disconnect should happen for all bridges
+ */
+int diagfwd_disconnect_bridge(int process_cable)
+{
+ int i;
+ pr_debug("diag: In %s, process_cable: %d\n", __func__, process_cable);
+
+ for (i = 0; i < MAX_BRIDGES; i++) {
+ if (diag_bridge[i].enabled) {
+ mutex_lock(&diag_bridge[i].bridge_mutex);
+ /* If the usb cable is being disconnected */
+ if (process_cable) {
+ diag_bridge[i].usb_connected = 0;
+ usb_diag_free_req(diag_bridge[i].ch);
+ }
+
+ if (i == HSIC && driver->hsic_device_enabled &&
+ driver->logging_mode != MEMORY_DEVICE_MODE) {
+ driver->in_busy_hsic_read_on_device = 1;
+ driver->in_busy_hsic_write = 1;
+ /* Turn off communication over usb and HSIC */
+ diag_hsic_close();
+ } else if (i == SMUX && driver->diag_smux_enabled &&
+ driver->logging_mode == USB_MODE) {
+ driver->in_busy_smux = 1;
+ driver->lcid = LCID_INVALID;
+ driver->smux_connected = 0;
+ /* Turn off communication over usb and smux */
+ msm_smux_close(LCID_VALID);
+ }
+ mutex_unlock(&diag_bridge[i].bridge_mutex);
+ }
+ }
+ return 0;
+}
+
+/* Called after the asychronous usb_diag_read() on mdm channel is complete */
+int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
+{
+ int index = (int)(diag_read_ptr->context);
+
+ /* The read of the usb on the mdm (not HSIC/SMUX) has completed */
+ diag_bridge[index].read_len = diag_read_ptr->actual;
+
+ if (index == SMUX) {
+ if (driver->diag_smux_enabled) {
+ diagfwd_read_complete_smux();
+ return 0;
+ } else {
+ pr_warning("diag: incorrect callback for smux\n");
+ }
+ }
+
+ /* If SMUX not enabled, check for HSIC */
+ driver->in_busy_hsic_read_on_device = 0;
+ if (!driver->hsic_ch) {
+ pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+ return 0;
+ }
+
+ /*
+ * The read of the usb driver on the mdm channel has completed.
+ * If there is no write on the HSIC in progress, check if the
+ * read has data to pass on to the HSIC. If so, pass the usb
+ * mdm data on to the HSIC.
+ */
+ if (!driver->in_busy_hsic_write && diag_bridge[HSIC].usb_buf_out &&
+ (diag_bridge[HSIC].read_len > 0)) {
+
+ /*
+ * Initiate the HSIC write. The HSIC write is
+ * asynchronous. When complete the write
+ * complete callback function will be called
+ */
+ int err;
+ driver->in_busy_hsic_write = 1;
+ err = diag_bridge_write(diag_bridge[HSIC].usb_buf_out,
+ diag_bridge[HSIC].read_len);
+ if (err) {
+ pr_err_ratelimited("diag: mdm data on HSIC write err: %d\n",
+ err);
+ /*
+ * If the error is recoverable, then clear
+ * the write flag, so we will resubmit a
+ * write on the next frame. Otherwise, don't
+ * resubmit a write on the next frame.
+ */
+ if ((-ENODEV) != err)
+ driver->in_busy_hsic_write = 0;
+ }
+ }
+
+ /*
+ * If there is no write of the usb mdm data on the
+ * HSIC channel
+ */
+ if (!driver->in_busy_hsic_write)
+ queue_work(diag_bridge[HSIC].wq,
+ &diag_bridge[HSIC].diag_read_work);
+
+ return 0;
+}
+
+static void diagfwd_bridge_notifier(void *priv, unsigned event,
+ struct diag_request *d_req)
+{
+ int index;
+
+ switch (event) {
+ case USB_DIAG_CONNECT:
+ diagfwd_connect_bridge(1);
+ break;
+ case USB_DIAG_DISCONNECT:
+ queue_work(driver->diag_wq,
+ &driver->diag_disconnect_work);
+ break;
+ case USB_DIAG_READ_DONE:
+ index = (int)(d_req->context);
+ queue_work(diag_bridge[index].wq,
+ &diag_bridge[index].usb_read_complete_work);
+ break;
+ case USB_DIAG_WRITE_DONE:
+ index = (int)(d_req->context);
+ if (index == HSIC && driver->hsic_device_enabled)
+ diagfwd_write_complete_hsic(d_req);
+ else if (index == SMUX && driver->diag_smux_enabled)
+ diagfwd_write_complete_smux();
+ break;
+ default:
+ pr_err("diag: in %s: Unknown event from USB diag:%u\n",
+ __func__, event);
+ break;
+ }
+}
+
+void diagfwd_bridge_init(int index)
+{
+ int ret;
+ unsigned char name[20];
+
+ if (index == HSIC)
+ strlcpy(name, "hsic", sizeof(name));
+ else
+ strlcpy(name, "smux", sizeof(name));
+
+ strlcpy(diag_bridge[index].name, name, sizeof(diag_bridge[index].name));
+ strlcat(name, "_diag_wq", sizeof(diag_bridge[index].name));
+ diag_bridge[index].enabled = 1;
+ diag_bridge[index].wq = create_singlethread_workqueue(name);
+ diag_bridge[index].read_len = 0;
+ diag_bridge[index].write_len = 0;
+ if (diag_bridge[index].usb_buf_out == NULL)
+ diag_bridge[index].usb_buf_out =
+ kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
+ if (diag_bridge[index].usb_buf_out == NULL)
+ goto err;
+ if (diag_bridge[index].usb_read_ptr == NULL)
+ diag_bridge[index].usb_read_ptr =
+ kzalloc(sizeof(struct diag_request), GFP_KERNEL);
+ if (diag_bridge[index].usb_read_ptr == NULL)
+ goto err;
+ if (diag_bridge[index].usb_read_ptr->context == NULL)
+ diag_bridge[index].usb_read_ptr->context =
+ kzalloc(sizeof(int), GFP_KERNEL);
+ if (diag_bridge[index].usb_read_ptr->context == NULL)
+ goto err;
+ mutex_init(&diag_bridge[index].bridge_mutex);
+
+ if (index == HSIC) {
+ INIT_WORK(&(diag_bridge[index].usb_read_complete_work),
+ diag_usb_read_complete_hsic_fn);
+#ifdef CONFIG_DIAG_OVER_USB
+ INIT_WORK(&(diag_bridge[index].diag_read_work),
+ diag_read_usb_hsic_work_fn);
+ diag_bridge[index].ch = usb_diag_open(DIAG_MDM, (void *)index,
+ diagfwd_bridge_notifier);
+ if (IS_ERR(diag_bridge[index].ch)) {
+ pr_err("diag: Unable to open USB diag MDM channel\n");
+ goto err;
+ }
+#endif
+ /* register HSIC device */
+ ret = platform_driver_register(&msm_hsic_ch_driver);
+ if (ret)
+ pr_err("diag: could not register HSIC device, ret: %d\n",
+ ret);
+ } else if (index == SMUX) {
+ INIT_WORK(&(diag_bridge[index].usb_read_complete_work),
+ diag_usb_read_complete_smux_fn);
+#ifdef CONFIG_DIAG_OVER_USB
+ INIT_WORK(&(diag_bridge[index].diag_read_work),
+ diag_read_usb_smux_work_fn);
+ diag_bridge[index].ch = usb_diag_open(DIAG_QSC, (void *)index,
+ diagfwd_bridge_notifier);
+ if (IS_ERR(diag_bridge[index].ch)) {
+ pr_err("diag: Unable to open USB diag QSC channel\n");
+ goto err;
+ }
+#endif
+ ret = platform_driver_register(&msm_diagfwd_smux_driver);
+ if (ret)
+ pr_err("diag: could not register SMUX device, ret: %d\n",
+ ret);
+ }
+ return;
+err:
+ pr_err("diag: Could not initialize for bridge forwarding\n");
+ kfree(diag_bridge[index].usb_buf_out);
+ kfree(driver->hsic_buf_tbl);
+ kfree(driver->write_ptr_mdm);
+ kfree(diag_bridge[index].usb_read_ptr);
+ if (diag_bridge[index].wq)
+ destroy_workqueue(diag_bridge[index].wq);
+ return;
+}
+
+void diagfwd_bridge_exit(void)
+{
+ int i;
+ pr_debug("diag: in %s\n", __func__);
+
+ if (driver->hsic_device_enabled) {
+ diag_hsic_close();
+ driver->hsic_device_enabled = 0;
+ diag_bridge[HSIC].enabled = 0;
+ }
+ driver->hsic_inited = 0;
+ diagmem_exit(driver, POOL_TYPE_ALL);
+ if (driver->diag_smux_enabled) {
+ driver->lcid = LCID_INVALID;
+ kfree(driver->buf_in_smux);
+ driver->diag_smux_enabled = 0;
+ diag_bridge[SMUX].enabled = 0;
+ }
+ platform_driver_unregister(&msm_hsic_ch_driver);
+ platform_driver_unregister(&msm_diagfwd_smux_driver);
+ /* destroy USB MDM specific variables */
+ for (i = 0; i < MAX_BRIDGES; i++) {
+ if (diag_bridge[i].enabled) {
+#ifdef CONFIG_DIAG_OVER_USB
+ if (diag_bridge[i].usb_connected)
+ usb_diag_free_req(diag_bridge[i].ch);
+ usb_diag_close(diag_bridge[i].ch);
+#endif
+ kfree(diag_bridge[i].usb_buf_out);
+ kfree(diag_bridge[i].usb_read_ptr);
+ destroy_workqueue(diag_bridge[i].wq);
+ diag_bridge[i].enabled = 0;
+ }
+ }
+ kfree(driver->hsic_buf_tbl);
+ kfree(driver->write_ptr_mdm);
+}
diff --git a/drivers/char/diag/diagfwd_bridge.h b/drivers/char/diag/diagfwd_bridge.h
new file mode 100644
index 0000000..06e6a96
--- /dev/null
+++ b/drivers/char/diag/diagfwd_bridge.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef DIAGFWD_BRIDGE_H
+#define DIAGFWD_BRIDGE_H
+
+#include "diagfwd.h"
+
+#define MAX_BRIDGES 5
+#define HSIC 0
+#define SMUX 1
+
+int diagfwd_connect_bridge(int);
+void connect_bridge(int, int);
+int diagfwd_disconnect_bridge(int);
+void diagfwd_bridge_init(int index);
+void diagfwd_bridge_exit(void);
+int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr);
+
+/* Diag-Bridge structure, n bridges can be used at same time
+ * for instance SMUX, HSIC working at same time
+ */
+struct diag_bridge_dev {
+ char name[20];
+ int enabled;
+ struct mutex bridge_mutex;
+ int usb_connected;
+ int read_len;
+ int write_len;
+ unsigned char *usb_buf_out;
+ struct usb_diag_ch *ch;
+ struct workqueue_struct *wq;
+ struct work_struct diag_read_work;
+ struct diag_request *usb_read_ptr;
+ struct work_struct usb_read_complete_work;
+};
+
+#endif
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 9e5a8d0..acac2fb 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -21,251 +21,151 @@
static uint16_t reg_dirty;
#define HDR_SIZ 8
-void diag_clean_modem_reg_fn(struct work_struct *work)
+void diag_clean_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(LPASS_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;
-
- if (!(driver->ch_cntl))
+ struct diag_smd_info *smd_info = container_of(work,
+ struct diag_smd_info,
+ diag_notify_update_smd_work);
+ if (!smd_info)
return;
- switch (event) {
- case SMD_EVENT_DATA:
- r1 = smd_read_avail(driver->ch_cntl);
- r2 = smd_cur_packet_size(driver->ch_cntl);
- if (r1 > 0 && r1 == r2)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_cntl_work));
- else
- pr_debug("diag: incomplete pkt on Modem CNTL ch\n");
- break;
- case SMD_EVENT_OPEN:
- queue_work(driver->diag_cntl_wq,
- &(driver->diag_modem_mask_update_work));
- break;
- }
+ pr_debug("diag: clean registration for peripheral: %d\n",
+ smd_info->peripheral);
+
+ reg_dirty |= smd_info->peripheral_mask;
+ diag_clear_reg(smd_info->peripheral);
+ reg_dirty ^= smd_info->peripheral_mask;
+
+ smd_info->notify_context = 0;
}
-void diag_smd_lpass_cntl_notify(void *ctxt, unsigned event)
+/* Process the data read from the smd control channel */
+int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
+ int total_recd)
{
- int r1, r2;
-
- if (!(driver->chlpass_cntl))
- return;
-
- switch (event) {
- case SMD_EVENT_DATA:
- r1 = smd_read_avail(driver->chlpass_cntl);
- r2 = smd_cur_packet_size(driver->chlpass_cntl);
- if (r1 > 0 && r1 == r2)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_lpass_cntl_work));
- else
- pr_debug("diag: incomplete pkt on LPASS CNTL ch\n");
- break;
- case SMD_EVENT_OPEN:
- queue_work(driver->diag_cntl_wq,
- &(driver->diag_lpass_mask_update_work));
- break;
- }
-}
-
-void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
-{
- int r1, r2;
-
- if (!(driver->ch_wcnss_cntl))
- return;
-
- switch (event) {
- case SMD_EVENT_DATA:
- r1 = smd_read_avail(driver->ch_wcnss_cntl);
- r2 = smd_cur_packet_size(driver->ch_wcnss_cntl);
- if (r1 > 0 && r1 == r2)
- queue_work(driver->diag_wq,
- &(driver->diag_read_smd_wcnss_cntl_work));
- else
- pr_debug("diag: incomplete pkt on WCNSS CNTL ch\n");
- break;
- case SMD_EVENT_OPEN:
- queue_work(driver->diag_cntl_wq,
- &(driver->diag_wcnss_mask_update_work));
- break;
- }
-}
-
-static void diag_smd_cntl_send_req(int proc_num)
-{
- int data_len = 0, type = -1, count_bytes = 0, j, r, flag = 0;
+ int data_len = 0, type = -1, count_bytes = 0, j, flag = 0;
+ int feature_mask_len;
struct bindpkt_params_per_process *pkt_params =
- kzalloc(sizeof(struct bindpkt_params_per_process), GFP_KERNEL);
+ kzalloc(sizeof(struct bindpkt_params_per_process), GFP_KERNEL);
struct diag_ctrl_msg *msg;
struct cmd_code_range *range;
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");
- return;
+ pr_alert("diag: In %s, Memory allocation failure\n",
+ __func__);
+ return 0;
}
- if (proc_num == MODEM_PROC) {
- buf = driver->buf_in_cntl;
- smd_ch = driver->ch_cntl;
- reg_mask = DIAG_CON_MPSS;
- } else if (proc_num == LPASS_PROC) {
- buf = driver->buf_in_lpass_cntl;
- smd_ch = driver->chlpass_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) {
+ if (!smd_info) {
+ pr_err("diag: In %s, No smd info. Not able to read.\n",
+ __func__);
kfree(pkt_params);
- return;
+ return 0;
}
- r = smd_read_avail(smd_ch);
- if (r > IN_BUF_SIZE) {
- if (r < MAX_IN_BUF_SIZE) {
- pr_err("diag: SMD CNTL sending pkt upto %d bytes", r);
- buf = krealloc(buf, r, GFP_KERNEL);
- } else {
- pr_err("diag: CNTL pkt > %d bytes", MAX_IN_BUF_SIZE);
- kfree(pkt_params);
- return;
+ while (count_bytes + HDR_SIZ <= total_recd) {
+ type = *(uint32_t *)(buf);
+ data_len = *(uint32_t *)(buf + 4);
+ if (type < DIAG_CTRL_MSG_REG ||
+ type > DIAG_CTRL_MSG_F3_MASK_V2) {
+ pr_alert("diag: In %s, Invalid Msg type %d proc %d",
+ __func__, type, smd_info->peripheral);
+ break;
}
- }
- if (buf && r > 0) {
- smd_read(smd_ch, buf, r);
- while (count_bytes + HDR_SIZ <= r) {
- type = *(uint32_t *)(buf);
- data_len = *(uint32_t *)(buf + 4);
- if (type < DIAG_CTRL_MSG_REG ||
- type > DIAG_CTRL_MSG_F3_MASK_V2) {
- pr_alert("diag: Invalid Msg type %d proc %d",
- type, proc_num);
- break;
- }
- if (data_len < 0 || data_len > r) {
- pr_alert("diag: Invalid data len %d proc %d",
- data_len, proc_num);
- break;
- }
- count_bytes = count_bytes+HDR_SIZ+data_len;
- if (type == DIAG_CTRL_MSG_REG && r >= count_bytes) {
- msg = buf+HDR_SIZ;
- range = buf+HDR_SIZ+
- sizeof(struct diag_ctrl_msg);
- pkt_params->count = msg->count_entries;
- temp = kzalloc(pkt_params->count * sizeof(struct
- bindpkt_params), GFP_KERNEL);
- if (temp == NULL) {
- pr_alert("diag: Memory alloc fail\n");
- kfree(pkt_params);
- return;
- }
- for (j = 0; j < pkt_params->count; j++) {
- temp->cmd_code = msg->cmd_code;
- temp->subsys_id = msg->subsysid;
- temp->client_id = proc_num;
- temp->proc_id = proc_num;
- temp->cmd_code_lo = range->cmd_code_lo;
- temp->cmd_code_hi = range->cmd_code_hi;
- range++;
- temp++;
- }
- temp -= pkt_params->count;
- pkt_params->params = temp;
- flag = 1;
- /* 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;
+ if (data_len < 0 || data_len > total_recd) {
+ pr_alert("diag: In %s, Invalid data len %d, total_recd: %d, proc %d",
+ __func__, data_len, total_recd,
+ smd_info->peripheral);
+ break;
}
+ count_bytes = count_bytes+HDR_SIZ+data_len;
+ if (type == DIAG_CTRL_MSG_REG && total_recd >= count_bytes) {
+ msg = buf+HDR_SIZ;
+ range = buf+HDR_SIZ+
+ sizeof(struct diag_ctrl_msg);
+ pkt_params->count = msg->count_entries;
+ temp = kzalloc(pkt_params->count * sizeof(struct
+ bindpkt_params), GFP_KERNEL);
+ if (temp == NULL) {
+ pr_alert("diag: In %s, Memory alloc fail\n",
+ __func__);
+ kfree(pkt_params);
+ return flag;
+ }
+ for (j = 0; j < pkt_params->count; j++) {
+ temp->cmd_code = msg->cmd_code;
+ temp->subsys_id = msg->subsysid;
+ temp->client_id = smd_info->peripheral;
+ temp->proc_id = NON_APPS_PROC;
+ temp->cmd_code_lo = range->cmd_code_lo;
+ temp->cmd_code_hi = range->cmd_code_hi;
+ range++;
+ temp++;
+ }
+ temp -= pkt_params->count;
+ pkt_params->params = temp;
+ flag = 1;
+ /* peripheral undergoing SSR should not
+ * record new registration
+ */
+ if (!(reg_dirty & smd_info->peripheral_mask))
+ diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
+ (unsigned long)pkt_params);
+ else
+ pr_err("diag: drop reg proc %d\n",
+ smd_info->peripheral);
+ kfree(temp);
+ } else if ((type == DIAG_CTRL_MSG_FEATURE) &&
+ (smd_info->peripheral == MODEM_DATA)) {
+ feature_mask_len = *(int *)(buf + 8);
+ driver->log_on_demand_support = (*(uint8_t *)
+ (buf + 12)) & 0x04;
+ } else if (type != DIAG_CTRL_MSG_REG) {
+ flag = 1;
+ }
+ buf = buf + HDR_SIZ + data_len;
}
kfree(pkt_params);
- if (flag) {
- /* Poll SMD CNTL channels to check for data */
- if (proc_num == MODEM_PROC)
- diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
- else if (proc_num == LPASS_PROC)
- diag_smd_lpass_cntl_notify(NULL, SMD_EVENT_DATA);
- else if (proc_num == WCNSS_PROC)
- diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
- }
-}
-void diag_read_smd_cntl_work_fn(struct work_struct *work)
-{
- diag_smd_cntl_send_req(MODEM_PROC);
-}
-
-void diag_read_smd_lpass_cntl_work_fn(struct work_struct *work)
-{
- diag_smd_cntl_send_req(LPASS_PROC);
-}
-
-void diag_read_smd_wcnss_cntl_work_fn(struct work_struct *work)
-{
- diag_smd_cntl_send_req(WCNSS_PROC);
+ return flag;
}
static int diag_smd_cntl_probe(struct platform_device *pdev)
{
int r = 0;
+ int index = -1;
/* open control ports only on 8960 & newer targets */
if (chk_apps_only()) {
- if (pdev->id == SMD_APPS_MODEM)
- r = smd_open("DIAG_CNTL", &driver->ch_cntl, driver,
- diag_smd_cntl_notify);
- if (pdev->id == SMD_APPS_QDSP)
- r = smd_named_open_on_edge("DIAG_CNTL", SMD_APPS_QDSP
- , &driver->chlpass_cntl, driver,
- diag_smd_lpass_cntl_notify);
- if (pdev->id == SMD_APPS_WCNSS)
+ if (pdev->id == SMD_APPS_MODEM) {
+ index = MODEM_DATA;
+ r = smd_open("DIAG_CNTL",
+ &driver->smd_cntl[index].ch,
+ &driver->smd_cntl[index],
+ diag_smd_notify);
+ driver->smd_cntl[index].ch_save =
+ driver->smd_cntl[index].ch;
+ } else if (pdev->id == SMD_APPS_QDSP) {
+ index = LPASS_DATA;
+ r = smd_named_open_on_edge("DIAG_CNTL",
+ SMD_APPS_QDSP,
+ &driver->smd_cntl[index].ch,
+ &driver->smd_cntl[index],
+ diag_smd_notify);
+ driver->smd_cntl[index].ch_save =
+ driver->smd_cntl[index].ch;
+ } else if (pdev->id == SMD_APPS_WCNSS) {
+ index = WCNSS_DATA;
r = smd_named_open_on_edge("APPS_RIVA_CTRL",
- SMD_APPS_WCNSS, &driver->ch_wcnss_cntl,
- driver, diag_smd_wcnss_cntl_notify);
+ SMD_APPS_WCNSS,
+ &driver->smd_cntl[index].ch,
+ &driver->smd_cntl[index],
+ diag_smd_notify);
+ driver->smd_cntl[index].ch_save =
+ driver->smd_cntl[index].ch;
+ }
+
pr_debug("diag: open CNTL port, ID = %d,r = %d\n", pdev->id, r);
}
return 0;
@@ -310,53 +210,52 @@
void diagfwd_cntl_init(void)
{
+ int success;
+ int i;
+
reg_dirty = 0;
driver->polling_reg_flag = 0;
+ driver->log_on_demand_support = 1;
driver->diag_cntl_wq = create_singlethread_workqueue("diag_cntl_wq");
- if (driver->buf_in_cntl == NULL) {
- driver->buf_in_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_cntl == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_cntl);
- }
- if (driver->buf_in_lpass_cntl == NULL) {
- driver->buf_in_lpass_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_lpass_cntl == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_lpass_cntl);
- }
- if (driver->buf_in_wcnss_cntl == NULL) {
- driver->buf_in_wcnss_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_wcnss_cntl == NULL)
- goto err;
- kmemleak_not_leak(driver->buf_in_wcnss_cntl);
- }
+
+ success = diag_smd_constructor(&driver->smd_cntl[MODEM_DATA],
+ MODEM_DATA, SMD_CNTL_TYPE);
+ if (!success)
+ goto err;
+
+ success = diag_smd_constructor(&driver->smd_cntl[LPASS_DATA],
+ LPASS_DATA, SMD_CNTL_TYPE);
+ if (!success)
+ goto err;
+
+ success = diag_smd_constructor(&driver->smd_cntl[WCNSS_DATA],
+ WCNSS_DATA, SMD_CNTL_TYPE);
+ if (!success)
+ goto err;
+
platform_driver_register(&msm_smd_ch1_cntl_driver);
platform_driver_register(&diag_smd_lite_cntl_driver);
return;
err:
- pr_err("diag: Could not initialize diag buffers");
- kfree(driver->buf_in_cntl);
- kfree(driver->buf_in_lpass_cntl);
- kfree(driver->buf_in_wcnss_cntl);
- if (driver->diag_cntl_wq)
- destroy_workqueue(driver->diag_cntl_wq);
+ pr_err("diag: Could not initialize diag buffers");
+
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+ diag_smd_destructor(&driver->smd_cntl[i]);
+
+ if (driver->diag_cntl_wq)
+ destroy_workqueue(driver->diag_cntl_wq);
}
void diagfwd_cntl_exit(void)
{
- smd_close(driver->ch_cntl);
- smd_close(driver->chlpass_cntl);
- smd_close(driver->ch_wcnss_cntl);
- driver->ch_cntl = 0;
- driver->chlpass_cntl = 0;
- driver->ch_wcnss_cntl = 0;
+ int i;
+
+ for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
+ diag_smd_destructor(&driver->smd_cntl[i]);
+
destroy_workqueue(driver->diag_cntl_wq);
+
platform_driver_unregister(&msm_smd_ch1_cntl_driver);
platform_driver_unregister(&diag_smd_lite_cntl_driver);
-
- kfree(driver->buf_in_cntl);
- kfree(driver->buf_in_lpass_cntl);
- kfree(driver->buf_in_wcnss_cntl);
}
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index 8a0ec3f..8d262c4 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -77,16 +77,18 @@
/* Copy msg mask here */
} __packed;
+struct diag_ctrl_feature_mask {
+ uint32_t ctrl_pkt_id;
+ uint32_t ctrl_pkt_data_len;
+ uint32_t feature_mask_len;
+ /* Copy feature mask here */
+} __packed;
+
void diagfwd_cntl_init(void);
void diagfwd_cntl_exit(void);
void diag_read_smd_cntl_work_fn(struct work_struct *);
-void diag_read_smd_lpass_cntl_work_fn(struct work_struct *);
-void diag_read_smd_wcnss_cntl_work_fn(struct work_struct *);
-void diag_smd_cntl_notify(void *ctxt, unsigned event);
-void diag_smd_lpass_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_clean_reg_fn(struct work_struct *work);
+int diag_process_smd_cntl_read_data(struct diag_smd_info *smd_info, void *buf,
+ int total_recd);
#endif
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index 56f2fae..3d5eea5 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -31,6 +31,7 @@
#include "diagfwd.h"
#include "diagfwd_hsic.h"
#include "diagfwd_smux.h"
+#include "diagfwd_bridge.h"
#define READ_HSIC_BUF_SIZE 2048
@@ -72,7 +73,7 @@
write_ptrs_available--;
/*
- * No sense queuing a read if the hsic bridge was
+ * No sense queuing a read if the HSIC bridge was
* closed in another thread
*/
if (!driver->hsic_ch)
@@ -82,7 +83,7 @@
POOL_TYPE_HSIC);
if (buf_in_hsic) {
/*
- * Initiate the read from the hsic. The hsic read is
+ * Initiate the read from the HSIC. The HSIC read is
* asynchronous. Once the read is complete the read
* callback function will be called.
*/
@@ -116,7 +117,7 @@
if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
(num_reads_submitted == 0) && (err != -ENODEV) &&
(driver->hsic_ch != 0))
- queue_work(driver->diag_bridge_wq,
+ queue_work(diag_bridge[HSIC].wq,
&driver->diag_read_hsic_work);
}
@@ -127,7 +128,7 @@
if (!driver->hsic_ch) {
/*
- * The hsic channel is closed. Return the buffer to
+ * The HSIC channel is closed. Return the buffer to
* the pool. Do not send it on.
*/
diagmem_free(driver, buf, POOL_TYPE_HSIC);
@@ -149,7 +150,7 @@
* Send data in buf to be written on the
* appropriate device, e.g. USB MDM channel
*/
- driver->write_len_mdm = actual_size;
+ diag_bridge[HSIC].write_len = actual_size;
err = diag_device_write((void *)buf, HSIC_DATA, NULL);
/* If an error, return buffer to the pool */
if (err) {
@@ -170,13 +171,13 @@
}
/*
- * If for some reason there was no hsic data to write to the
+ * If for some reason there was no HSIC data to write to the
* mdm channel, set up another read
*/
if (err &&
((driver->logging_mode == MEMORY_DEVICE_MODE) ||
- (driver->usb_mdm_connected && !driver->hsic_suspend))) {
- queue_work(driver->diag_bridge_wq,
+ (diag_bridge[HSIC].usb_connected && !driver->hsic_suspend))) {
+ queue_work(diag_bridge[HSIC].wq,
&driver->diag_read_hsic_work);
}
}
@@ -195,8 +196,10 @@
if (actual_size < 0)
pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
- if (driver->usb_mdm_connected)
- queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
+ if (diag_bridge[HSIC].usb_connected &&
+ (driver->logging_mode == USB_MODE))
+ queue_work(diag_bridge[HSIC].wq,
+ &diag_bridge[HSIC].diag_read_work);
}
static int diag_hsic_suspend(void *ctxt)
@@ -223,12 +226,12 @@
if ((driver->count_hsic_pool < driver->poolsize_hsic) &&
((driver->logging_mode == MEMORY_DEVICE_MODE) ||
- (driver->usb_mdm_connected)))
- queue_work(driver->diag_bridge_wq,
+ (diag_bridge[HSIC].usb_connected)))
+ queue_work(diag_bridge[HSIC].wq,
&driver->diag_read_hsic_work);
}
-static struct diag_bridge_ops hsic_diag_bridge_ops = {
+struct diag_bridge_ops hsic_diag_bridge_ops = {
.ctxt = NULL,
.read_complete_cb = diag_hsic_read_complete_callback,
.write_complete_cb = diag_hsic_write_complete_callback,
@@ -236,7 +239,7 @@
.resume = diag_hsic_resume,
};
-static void diag_hsic_close(void)
+void diag_hsic_close(void)
{
if (driver->hsic_device_enabled) {
driver->hsic_ch = 0;
@@ -257,7 +260,7 @@
{
int err;
- mutex_lock(&driver->bridge_mutex);
+ mutex_lock(&diag_bridge[HSIC].bridge_mutex);
if (driver->hsic_device_enabled) {
if (driver->hsic_device_opened) {
driver->hsic_ch = 0;
@@ -274,112 +277,7 @@
}
}
}
-
- mutex_unlock(&driver->bridge_mutex);
- return 0;
-}
-
-/* diagfwd_connect_bridge is called when the USB mdm channel is connected */
-int diagfwd_connect_bridge(int process_cable)
-{
- int err;
-
- pr_debug("diag: in %s\n", __func__);
-
- mutex_lock(&driver->bridge_mutex);
- /* If the usb cable is being connected */
- if (process_cable) {
- err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
- N_MDM_READ);
- if (err)
- pr_err("diag: unable to alloc USB req on mdm"
- " ch err:%d\n", err);
-
- driver->usb_mdm_connected = 1;
- }
-
- if (driver->hsic_device_enabled) {
- driver->in_busy_hsic_read_on_device = 0;
- driver->in_busy_hsic_write = 0;
- } else if (driver->diag_smux_enabled) {
- driver->in_busy_smux = 0;
- diagfwd_connect_smux();
- mutex_unlock(&driver->bridge_mutex);
- return 0;
- }
-
- /* If the hsic (diag_bridge) platform device is not open */
- if (driver->hsic_device_enabled) {
- if (!driver->hsic_device_opened) {
- err = diag_bridge_open(&hsic_diag_bridge_ops);
- if (err) {
- pr_err("diag: HSIC channel open error: %d\n",
- err);
- } else {
- pr_debug("diag: opened HSIC channel\n");
- driver->hsic_device_opened = 1;
- }
- } else {
- pr_debug("diag: HSIC channel already open\n");
- }
-
- /*
- * Turn on communication over usb mdm and hsic, if the hsic
- * device driver is enabled and opened
- */
- if (driver->hsic_device_opened) {
- driver->hsic_ch = 1;
-
- /* Poll USB mdm channel to check for data */
- if (driver->logging_mode == USB_MODE)
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_mdm_work);
-
- /* Poll HSIC channel to check for data */
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_hsic_work);
- }
- } else {
- /* The hsic device driver has not yet been enabled */
- pr_info("diag: HSIC channel not yet enabled\n");
- }
-
- mutex_unlock(&driver->bridge_mutex);
- return 0;
-}
-
-/*
- * diagfwd_disconnect_bridge is called when the USB mdm channel
- * is disconnected
- */
-int diagfwd_disconnect_bridge(int process_cable)
-{
- pr_debug("diag: In %s, process_cable: %d\n", __func__, process_cable);
-
- mutex_lock(&driver->bridge_mutex);
-
- /* If the usb cable is being disconnected */
- if (process_cable) {
- driver->usb_mdm_connected = 0;
- usb_diag_free_req(driver->mdm_ch);
- }
-
- if (driver->hsic_device_enabled &&
- driver->logging_mode != MEMORY_DEVICE_MODE) {
- driver->in_busy_hsic_read_on_device = 1;
- driver->in_busy_hsic_write = 1;
- /* Turn off communication over usb mdm and hsic */
- diag_hsic_close();
- } else if (driver->diag_smux_enabled &&
- driver->logging_mode == USB_MODE) {
- driver->in_busy_smux = 1;
- driver->lcid = LCID_INVALID;
- driver->smux_connected = 0;
- /* Turn off communication over usb mdm and smux */
- msm_smux_close(LCID_VALID);
- }
-
- mutex_unlock(&driver->bridge_mutex);
+ mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
return 0;
}
@@ -403,225 +301,128 @@
return 0;
}
- /* Read data from the hsic */
- queue_work(driver->diag_bridge_wq, &driver->diag_read_hsic_work);
+ /* Read data from the HSIC */
+ queue_work(diag_bridge[HSIC].wq, &driver->diag_read_hsic_work);
return 0;
}
-/* Called after the asychronous usb_diag_read() on mdm channel is complete */
-static int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
+void diag_usb_read_complete_hsic_fn(struct work_struct *w)
{
- /* The read of the usb driver on the mdm (not hsic) has completed */
- driver->in_busy_hsic_read_on_device = 0;
- driver->read_len_mdm = diag_read_ptr->actual;
+ diagfwd_read_complete_bridge(diag_bridge[HSIC].usb_read_ptr);
+}
- if (driver->diag_smux_enabled) {
- diagfwd_read_complete_smux();
- return 0;
- }
- /* If SMUX not enabled, check for HSIC */
+
+void diag_read_usb_hsic_work_fn(struct work_struct *work)
+{
if (!driver->hsic_ch) {
- pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
- return 0;
- }
-
- /*
- * The read of the usb driver on the mdm channel has completed.
- * If there is no write on the hsic in progress, check if the
- * read has data to pass on to the hsic. If so, pass the usb
- * mdm data on to the hsic.
- */
- if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out &&
- (driver->read_len_mdm > 0)) {
-
- /*
- * Initiate the hsic write. The hsic write is
- * asynchronous. When complete the write
- * complete callback function will be called
- */
- int err;
- driver->in_busy_hsic_write = 1;
- err = diag_bridge_write(driver->usb_buf_mdm_out,
- driver->read_len_mdm);
- if (err) {
- pr_err_ratelimited("diag: mdm data on hsic write err: %d\n",
- err);
- /*
- * If the error is recoverable, then clear
- * the write flag, so we will resubmit a
- * write on the next frame. Otherwise, don't
- * resubmit a write on the next frame.
- */
- if ((-ENODEV) != err)
- driver->in_busy_hsic_write = 0;
- }
- }
-
- /*
- * If there is no write of the usb mdm data on the
- * hsic channel
- */
- if (!driver->in_busy_hsic_write)
- queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
-
- return 0;
-}
-
-static void diagfwd_bridge_notifier(void *priv, unsigned event,
- struct diag_request *d_req)
-{
- switch (event) {
- case USB_DIAG_CONNECT:
- diagfwd_connect_bridge(1);
- break;
- case USB_DIAG_DISCONNECT:
- queue_work(driver->diag_bridge_wq,
- &driver->diag_disconnect_work);
- break;
- case USB_DIAG_READ_DONE:
- queue_work(driver->diag_bridge_wq,
- &driver->diag_usb_read_complete_work);
- break;
- case USB_DIAG_WRITE_DONE:
- if (driver->hsic_device_enabled)
- diagfwd_write_complete_hsic(d_req);
- else if (driver->diag_smux_enabled)
- diagfwd_write_complete_smux();
- break;
- default:
- pr_err("diag: in %s: Unknown event from USB diag:%u\n",
- __func__, event);
- break;
- }
-}
-
-static void diag_usb_read_complete_fn(struct work_struct *w)
-{
- diagfwd_read_complete_bridge(driver->usb_read_mdm_ptr);
-}
-
-static void diag_disconnect_work_fn(struct work_struct *w)
-{
- diagfwd_disconnect_bridge(1);
-}
-
-static void diag_read_mdm_work_fn(struct work_struct *work)
-{
- int ret;
- if (driver->diag_smux_enabled) {
- if (driver->lcid && driver->usb_buf_mdm_out &&
- (driver->read_len_mdm > 0) &&
- driver->smux_connected) {
- ret = msm_smux_write(driver->lcid, NULL,
- driver->usb_buf_mdm_out, driver->read_len_mdm);
- if (ret)
- pr_err("diag: writing to SMUX ch, r = %d,"
- "lcid = %d\n", ret, driver->lcid);
- }
- driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
- driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
- usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
+ pr_err("diag: in %s: driver->hsic_ch == 0\n", __func__);
return;
}
-
- /* if SMUX not enabled, check for HSIC */
- if (!driver->hsic_ch) {
- pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
- return;
- }
-
/*
* If there is no data being read from the usb mdm channel
* and there is no mdm channel data currently being written
- * to the hsic
+ * to the HSIC
*/
if (!driver->in_busy_hsic_read_on_device &&
- !driver->in_busy_hsic_write) {
+ !driver->in_busy_hsic_write) {
APPEND_DEBUG('x');
-
/* Setup the next read from usb mdm channel */
driver->in_busy_hsic_read_on_device = 1;
- driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
- driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
- usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
+ diag_bridge[HSIC].usb_read_ptr->buf =
+ diag_bridge[HSIC].usb_buf_out;
+ diag_bridge[HSIC].usb_read_ptr->length = USB_MAX_OUT_BUF;
+ diag_bridge[HSIC].usb_read_ptr->context = (void *)HSIC;
+ usb_diag_read(diag_bridge[HSIC].ch,
+ diag_bridge[HSIC].usb_read_ptr);
APPEND_DEBUG('y');
}
-
- /*
- * If for some reason there was no mdm channel read initiated,
+ /* If for some reason there was no mdm channel read initiated,
* queue up the reading of data from the mdm channel
*/
- if (!driver->in_busy_hsic_read_on_device)
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_mdm_work);
+
+ if (!driver->in_busy_hsic_read_on_device &&
+ (driver->logging_mode == USB_MODE))
+ queue_work(diag_bridge[HSIC].wq,
+ &(diag_bridge[HSIC].diag_read_work));
}
static int diag_hsic_probe(struct platform_device *pdev)
{
int err = 0;
+
pr_debug("diag: in %s\n", __func__);
+ mutex_lock(&diag_bridge[HSIC].bridge_mutex);
if (!driver->hsic_inited) {
+ spin_lock_init(&driver->hsic_spinlock);
+ driver->num_hsic_buf_tbl_entries = 0;
+ if (driver->hsic_buf_tbl == NULL)
+ driver->hsic_buf_tbl = kzalloc(NUM_HSIC_BUF_TBL_ENTRIES
+ * sizeof(struct diag_write_device), GFP_KERNEL);
+ if (driver->hsic_buf_tbl == NULL) {
+ mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
+ return -ENOMEM;
+ }
+ driver->count_hsic_pool = 0;
+ driver->count_hsic_write_pool = 0;
+ driver->itemsize_hsic = READ_HSIC_BUF_SIZE;
+ driver->poolsize_hsic = N_MDM_WRITE;
+ driver->itemsize_hsic_write = sizeof(struct diag_request);
+ driver->poolsize_hsic_write = N_MDM_WRITE;
diagmem_hsic_init(driver);
INIT_WORK(&(driver->diag_read_hsic_work),
- diag_read_hsic_work_fn);
+ diag_read_hsic_work_fn);
driver->hsic_inited = 1;
}
-
- mutex_lock(&driver->bridge_mutex);
-
/*
* The probe function was called after the usb was connected
* on the legacy channel OR ODL is turned on. Communication over usb
- * mdm and hsic needs to be turned on.
+ * mdm and HSIC needs to be turned on.
*/
- if (driver->usb_mdm_connected || (driver->logging_mode ==
- MEMORY_DEVICE_MODE)) {
+ if (diag_bridge[HSIC].usb_connected || (driver->logging_mode ==
+ MEMORY_DEVICE_MODE)) {
if (driver->hsic_device_opened) {
/* should not happen. close it before re-opening */
pr_warn("diag: HSIC channel already opened in probe\n");
diag_bridge_close();
}
-
err = diag_bridge_open(&hsic_diag_bridge_ops);
if (err) {
pr_err("diag: could not open HSIC, err: %d\n", err);
driver->hsic_device_opened = 0;
- mutex_unlock(&driver->bridge_mutex);
+ mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
return err;
}
pr_info("diag: opened HSIC channel\n");
driver->hsic_device_opened = 1;
driver->hsic_ch = 1;
-
driver->in_busy_hsic_read_on_device = 0;
driver->in_busy_hsic_write = 0;
- if (driver->usb_mdm_connected) {
+ if (diag_bridge[HSIC].usb_connected) {
/* Poll USB mdm channel to check for data */
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_mdm_work);
+ queue_work(diag_bridge[HSIC].wq,
+ &diag_bridge[HSIC].diag_read_work);
}
-
/* Poll HSIC channel to check for data */
- queue_work(driver->diag_bridge_wq,
- &driver->diag_read_hsic_work);
+ queue_work(diag_bridge[HSIC].wq,
+ &driver->diag_read_hsic_work);
}
-
- /* The hsic (diag_bridge) platform device driver is enabled */
+ /* The HSIC (diag_bridge) platform device driver is enabled */
driver->hsic_device_enabled = 1;
- mutex_unlock(&driver->bridge_mutex);
+ mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
return err;
}
static int diag_hsic_remove(struct platform_device *pdev)
{
pr_debug("diag: %s called\n", __func__);
- mutex_lock(&driver->bridge_mutex);
+ mutex_lock(&diag_bridge[HSIC].bridge_mutex);
diag_hsic_close();
driver->hsic_device_enabled = 0;
- mutex_unlock(&driver->bridge_mutex);
+ mutex_unlock(&diag_bridge[HSIC].bridge_mutex);
+
return 0;
}
@@ -642,7 +443,7 @@
.runtime_resume = diagfwd_hsic_runtime_resume,
};
-static struct platform_driver msm_hsic_ch_driver = {
+struct platform_driver msm_hsic_ch_driver = {
.probe = diag_hsic_probe,
.remove = diag_hsic_remove,
.driver = {
@@ -651,112 +452,3 @@
.pm = &diagfwd_hsic_dev_pm_ops,
},
};
-
-void diagfwd_bridge_init(void)
-{
- int ret;
-
- pr_debug("diag: in %s\n", __func__);
- driver->diag_bridge_wq = create_singlethread_workqueue(
- "diag_bridge_wq");
- driver->read_len_mdm = 0;
- driver->write_len_mdm = 0;
- driver->num_hsic_buf_tbl_entries = 0;
- spin_lock_init(&driver->hsic_spinlock);
- if (driver->usb_buf_mdm_out == NULL)
- driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
- GFP_KERNEL);
- if (driver->usb_buf_mdm_out == NULL)
- goto err;
- /* Only used by smux move to smux probe function */
- if (driver->write_ptr_mdm == NULL)
- driver->write_ptr_mdm = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_mdm == NULL)
- goto err;
- if (driver->usb_read_mdm_ptr == NULL)
- driver->usb_read_mdm_ptr = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->usb_read_mdm_ptr == NULL)
- goto err;
-
- if (driver->hsic_buf_tbl == NULL)
- driver->hsic_buf_tbl = kzalloc(NUM_HSIC_BUF_TBL_ENTRIES *
- sizeof(struct diag_write_device), GFP_KERNEL);
- if (driver->hsic_buf_tbl == NULL)
- goto err;
-
- driver->count_hsic_pool = 0;
- driver->count_hsic_write_pool = 0;
-
- driver->itemsize_hsic = READ_HSIC_BUF_SIZE;
- driver->poolsize_hsic = N_MDM_WRITE;
- driver->itemsize_hsic_write = sizeof(struct diag_request);
- driver->poolsize_hsic_write = N_MDM_WRITE;
-
- mutex_init(&driver->bridge_mutex);
-#ifdef CONFIG_DIAG_OVER_USB
- INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
-#endif
- INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
- INIT_WORK(&(driver->diag_usb_read_complete_work),
- diag_usb_read_complete_fn);
-#ifdef CONFIG_DIAG_OVER_USB
- driver->mdm_ch = usb_diag_open(DIAG_MDM, driver,
- diagfwd_bridge_notifier);
- if (IS_ERR(driver->mdm_ch)) {
- pr_err("diag: Unable to open USB diag MDM channel\n");
- goto err;
- }
-#endif
- /* register HSIC device */
- ret = platform_driver_register(&msm_hsic_ch_driver);
- if (ret)
- pr_err("diag: could not register HSIC device, ret: %d\n", ret);
- /* register SMUX device */
- ret = platform_driver_register(&msm_diagfwd_smux_driver);
- if (ret)
- pr_err("diag: could not register SMUX device, ret: %d\n", ret);
-
- return;
-err:
- pr_err("diag: Could not initialize for bridge forwarding\n");
- kfree(driver->usb_buf_mdm_out);
- kfree(driver->hsic_buf_tbl);
- kfree(driver->write_ptr_mdm);
- kfree(driver->usb_read_mdm_ptr);
- if (driver->diag_bridge_wq)
- destroy_workqueue(driver->diag_bridge_wq);
-
- return;
-}
-
-void diagfwd_bridge_exit(void)
-{
- pr_debug("diag: in %s\n", __func__);
-
- if (driver->hsic_device_enabled) {
- diag_hsic_close();
- driver->hsic_device_enabled = 0;
- }
- driver->hsic_inited = 0;
- diagmem_exit(driver, POOL_TYPE_ALL);
- if (driver->diag_smux_enabled) {
- driver->lcid = LCID_INVALID;
- kfree(driver->buf_in_smux);
- driver->diag_smux_enabled = 0;
- }
- platform_driver_unregister(&msm_hsic_ch_driver);
- platform_driver_unregister(&msm_diagfwd_smux_driver);
- /* destroy USB MDM specific variables */
-#ifdef CONFIG_DIAG_OVER_USB
- if (driver->usb_mdm_connected)
- usb_diag_free_req(driver->mdm_ch);
- usb_diag_close(driver->mdm_ch);
-#endif
- kfree(driver->usb_buf_mdm_out);
- kfree(driver->hsic_buf_tbl);
- kfree(driver->write_ptr_mdm);
- kfree(driver->usb_read_mdm_ptr);
- destroy_workqueue(driver->diag_bridge_wq);
-}
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index 19ed3c7..2190fff 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -17,14 +17,14 @@
#define N_MDM_WRITE 8
#define N_MDM_READ 1
-
#define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
-int diagfwd_connect_bridge(int);
-int diagfwd_disconnect_bridge(int);
int diagfwd_write_complete_hsic(struct diag_request *);
int diagfwd_cancel_hsic(void);
-void diagfwd_bridge_init(void);
-void diagfwd_bridge_exit(void);
+void diag_read_usb_hsic_work_fn(struct work_struct *work);
+void diag_usb_read_complete_hsic_fn(struct work_struct *w);
+extern struct diag_bridge_ops hsic_diag_bridge_ops;
+extern struct platform_driver msm_hsic_ch_driver;
+void diag_hsic_close(void);
#endif
diff --git a/drivers/char/diag/diagfwd_smux.c b/drivers/char/diag/diagfwd_smux.c
index ae90686..0a97baf 100644
--- a/drivers/char/diag/diagfwd_smux.c
+++ b/drivers/char/diag/diagfwd_smux.c
@@ -18,6 +18,8 @@
#include "diagchar.h"
#include "diagfwd.h"
#include "diagfwd_smux.h"
+#include "diagfwd_hsic.h"
+#include "diagfwd_bridge.h"
void diag_smux_event(void *priv, int event_type, const void *metadata)
{
@@ -30,8 +32,8 @@
driver->smux_connected = 1;
driver->in_busy_smux = 0;
/* read data from USB MDM channel & Initiate first write */
- queue_work(driver->diag_bridge_wq,
- &(driver->diag_read_mdm_work));
+ queue_work(diag_bridge[SMUX].wq,
+ &diag_bridge[SMUX].diag_read_work);
break;
case SMUX_DISCONNECTED:
driver->smux_connected = 0;
@@ -67,7 +69,7 @@
int diagfwd_read_complete_smux(void)
{
- queue_work(driver->diag_bridge_wq, &(driver->diag_read_mdm_work));
+ queue_work(diag_bridge[SMUX].wq, &diag_bridge[SMUX].diag_read_work);
return 0;
}
@@ -85,6 +87,36 @@
return 0;
}
+void diag_usb_read_complete_smux_fn(struct work_struct *w)
+{
+ diagfwd_read_complete_bridge(diag_bridge[SMUX].usb_read_ptr);
+}
+
+void diag_read_usb_smux_work_fn(struct work_struct *work)
+{
+ int ret;
+
+ if (driver->diag_smux_enabled) {
+ if (driver->lcid && diag_bridge[SMUX].usb_buf_out &&
+ (diag_bridge[SMUX].read_len > 0) &&
+ driver->smux_connected) {
+ ret = msm_smux_write(driver->lcid, NULL,
+ diag_bridge[SMUX].usb_buf_out,
+ diag_bridge[SMUX].read_len);
+ if (ret)
+ pr_err("diag: writing to SMUX ch, r = %d, lcid = %d\n",
+ ret, driver->lcid);
+ }
+ diag_bridge[SMUX].usb_read_ptr->buf =
+ diag_bridge[SMUX].usb_buf_out;
+ diag_bridge[SMUX].usb_read_ptr->length = USB_MAX_OUT_BUF;
+ diag_bridge[SMUX].usb_read_ptr->context = (void *)SMUX;
+ usb_diag_read(diag_bridge[SMUX].ch,
+ diag_bridge[SMUX].usb_read_ptr);
+ return;
+ }
+}
+
static int diagfwd_smux_runtime_suspend(struct device *dev)
{
dev_dbg(dev, "pm_runtime: suspending...\n");
@@ -120,7 +152,7 @@
}
}
/* Poll USB channel to check for data*/
- queue_work(driver->diag_bridge_wq, &(driver->diag_read_mdm_work));
+ queue_work(diag_bridge[SMUX].wq, &(diag_bridge[SMUX].diag_read_work));
return ret;
}
@@ -142,6 +174,11 @@
* if (ret)
* pr_err("diag: error setting SMUX ch option, r = %d\n", ret);
*/
+ if (driver->write_ptr_mdm == NULL)
+ driver->write_ptr_mdm = kzalloc(sizeof(struct diag_request),
+ GFP_KERNEL);
+ if (driver->write_ptr_mdm == NULL)
+ goto err;
ret = diagfwd_connect_smux();
return ret;
diff --git a/drivers/char/diag/diagfwd_smux.h b/drivers/char/diag/diagfwd_smux.h
index e78b7ed..b45fd5d 100644
--- a/drivers/char/diag/diagfwd_smux.h
+++ b/drivers/char/diag/diagfwd_smux.h
@@ -20,6 +20,8 @@
int diagfwd_read_complete_smux(void);
int diagfwd_write_complete_smux(void);
int diagfwd_connect_smux(void);
+void diag_usb_read_complete_smux_fn(struct work_struct *w);
+void diag_read_usb_smux_work_fn(struct work_struct *work);
extern struct platform_driver msm_diagfwd_smux_driver;
#endif
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index 1a522d5..ab1aa75 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -51,7 +51,7 @@
driver->diag_write_struct_pool, GFP_ATOMIC);
}
}
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
} else if (pool_type == POOL_TYPE_HSIC) {
if (driver->diag_hsic_pool) {
if (driver->count_hsic_pool < driver->poolsize_hsic) {
@@ -105,7 +105,7 @@
} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
printk(KERN_ALERT "Unable to destroy STRUCT mempool");
}
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
if (driver->diag_hsic_pool && (driver->hsic_inited == 0)) {
if (driver->count_hsic_pool == 0) {
mempool_destroy(driver->diag_hdlc_pool);
@@ -156,7 +156,7 @@
pr_err("diag: Attempt to free up DIAG driver "
"USB structure mempool which is already free %d ",
driver->count_write_struct_pool);
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
} else if (pool_type == POOL_TYPE_HSIC) {
if (driver->diag_hsic_pool != NULL &&
driver->count_hsic_pool > 0) {
@@ -210,7 +210,7 @@
printk(KERN_INFO "Cannot allocate diag USB struct mempool\n");
}
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
void diagmem_hsic_init(struct diagchar_dev *driver)
{
if (driver->count_hsic_pool == 0)
diff --git a/drivers/char/diag/diagmem.h b/drivers/char/diag/diagmem.h
index 8665c75..36def72 100644
--- a/drivers/char/diag/diagmem.h
+++ b/drivers/char/diag/diagmem.h
@@ -18,7 +18,7 @@
void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type);
void diagmem_init(struct diagchar_dev *driver);
void diagmem_exit(struct diagchar_dev *driver, int pool_type);
-#ifdef CONFIG_DIAG_BRIDGE_CODE
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
void diagmem_hsic_init(struct diagchar_dev *driver);
#endif
#endif
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 03c69d0..4bd8885 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,14 +18,14 @@
#define EVENT_MASKS_TYPE 4
#define PKT_TYPE 8
#define DEINIT_TYPE 16
-#define USER_SPACE_LOG_TYPE 32
+#define USER_SPACE_DATA_TYPE 32
#define DCI_DATA_TYPE 64
#define USB_MODE 1
#define MEMORY_DEVICE_MODE 2
#define NO_LOGGING_MODE 3
#define UART_MODE 4
#define SOCKET_MODE 5
-
+#define CALLBACK_MODE 6
/* different values that go in for diag_data_type */
#define DATA_TYPE_EVENT 0
#define DATA_TYPE_F3 1
@@ -43,6 +43,7 @@
#define DIAG_IOCTL_DCI_REG 23
#define DIAG_IOCTL_DCI_STREAM_INIT 24
#define DIAG_IOCTL_DCI_HEALTH_STATS 25
+#define DIAG_IOCTL_REMOTE_DEV 32
/* PC Tools IDs */
#define APQ8060_TOOLS_ID 4062
@@ -111,7 +112,7 @@
/* This needs to be modified manually now, when we add
a new RANGE of SSIDs to the msg_mask_tbl */
#define MSG_MASK_TBL_CNT 24
-#define EVENT_LAST_ID 0x08AD
+#define EVENT_LAST_ID 0x099F
#define MSG_SSID_0 0
#define MSG_SSID_0_LAST 93
@@ -674,24 +675,24 @@
};
static const uint32_t msg_bld_masks_22[] = {
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH,
- MSG_LVL_HIGH
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW,
+ MSG_LVL_LOW
};
/* LOG CODES */
#define LOG_0 0x0
-#define LOG_1 0x15A7
+#define LOG_1 0x1750
#define LOG_2 0x0
#define LOG_3 0x0
#define LOG_4 0x4910