diag: Add control packet support to indicate pd status

Add control packet support to signal MEMORY_DEVICE application
when a pd comes up.

Change-Id: I7182dfbe60ee07d0ab2f7c87eb981816ba764e25
Signed-off-by: Sreelakshmi Gownipalli <sgownipa@codeaurora.org>
This commit is contained in:
Sreelakshmi Gownipalli 2015-05-19 13:06:28 -07:00 committed by Gerrit - the friendly Code Review server
parent c85774e5d1
commit f207dbeaba
10 changed files with 170 additions and 119 deletions

View file

@ -158,7 +158,7 @@ static void diag_send_log_mask_update(uint8_t peripheral, int equip_id)
mutex_unlock(&mask->lock);
err = diagfwd_write(peripheral, TYPE_CNTL,
buf, header_len + mask_size);
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: Unable to send log masks to peripheral %d, equip_id: %d, err: %d\n",
peripheral, i, err);
}
@ -236,7 +236,7 @@ static void diag_send_event_mask_update(uint8_t peripheral)
write_len += sizeof(header);
err = diagfwd_write(peripheral, TYPE_CNTL, buf, write_len);
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: Unable to send event masks to peripheral %d\n",
peripheral);
}
@ -327,7 +327,7 @@ proceed:
err = diagfwd_write(peripheral, TYPE_CNTL, buf,
header_len + mask_size);
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: Unable to send msg masks to peripheral %d\n",
peripheral);
}
@ -382,7 +382,7 @@ static void diag_send_feature_mask_update(uint8_t peripheral)
total_len = header_size + FEATURE_MASK_LEN;
err = diagfwd_write(peripheral, TYPE_CNTL, buf, total_len);
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: In %s, unable to write to peripheral: %d, type: %d, len: %d, err: %d\n",
__func__, peripheral, TYPE_CNTL,
total_len, err);

View file

@ -98,9 +98,15 @@
#define DIAG_CMD_QUERY_TMC 0x02
#define DIAG_SS_TDSCDMA 0x57
#define DIAG_CMD_TDSCDMA_STATUS 0x0E
#define DIAG_CMD_DIAG_SUBSYS_DELAY 0x80
#define DIAG_SS_DIAG 0x12
#define DIAG_SS_PARAMS 0x32
#define DIAG_SS_FILE_READ_MODEM 0x0816
#define DIAG_SS_FILE_READ_ADSP 0x0E10
#define DIAG_SS_FILE_READ_WCNSS 0x141F
#define DIAG_SS_FILE_READ_SLPI 0x01A18
#define DIAG_SS_FILE_READ_APPS 0x020F
#define DIAG_DIAG_MAX_PKT_SZ 0x55
#define DIAG_DIAG_STM 0x214
@ -381,6 +387,13 @@ struct diag_feature_t {
uint8_t sent_feature_mask;
};
struct diag_mdlog_client_info {
struct task_struct *client_process;
int client_id;
uint16_t notification_list;
int signal_type;
};
struct diagchar_dev {
/* State for the char driver */
@ -492,6 +505,7 @@ struct diagchar_dev {
int logging_mode;
int mask_check;
struct diag_md_proc_info md_proc[DIAG_NUM_PROC];
struct diag_mdlog_client_info md_client_info;
/* Power related variables */
struct diag_ws_ref_t dci_ws;
struct diag_ws_ref_t md_ws;
@ -510,8 +524,8 @@ struct diagchar_dev {
uint32_t max_ssid_count[NUM_PERIPHERALS];
#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
/* For sending command requests in callback mode */
unsigned char *cb_buf;
int cb_buf_len;
unsigned char *hdlc_encode_buf;
int hdlc_encode_buf_len;
#endif
};

View file

@ -59,8 +59,8 @@ struct diagchar_priv {
int pid;
};
#define CALLBACK_NON_HDLC_DATA 0
#define CALLBACK_HDLC_DATA 1
#define USER_SPACE_RAW_DATA 0
#define USER_SPACE_HDLC_DATA 1
/* Memory pool variables */
/* Used for copying any incoming packet from user space clients. */
@ -376,6 +376,8 @@ static void diag_close_logging_process(int pid)
if (logging_proc->callback_process)
logging_proc->callback_process = NULL;
logging_proc->pid = 0;
if (driver->md_client_info.client_process)
driver->md_client_info.client_process = NULL;
diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_DOWN, i);
}
mutex_unlock(&driver->diagchar_mutex);
@ -839,19 +841,19 @@ static int diag_remote_init(void)
poolsize_mdm_dci_write);
diagmem_setsize(POOL_TYPE_QSC_MUX, itemsize_qsc_usb,
poolsize_qsc_usb);
driver->cb_buf = kzalloc(DIAG_MAX_HDLC_BUF_SIZE, GFP_KERNEL);
if (!driver->cb_buf)
driver->hdlc_encode_buf = kzalloc(DIAG_MAX_HDLC_BUF_SIZE, GFP_KERNEL);
if (!driver->hdlc_encode_buf)
return -ENOMEM;
driver->cb_buf_len = 0;
driver->hdlc_encode_buf_len = 0;
return 0;
}
static void diag_remote_exit(void)
{
kfree(driver->cb_buf);
kfree(driver->hdlc_encode_buf);
}
static int diag_cb_send_data_remote(int proc, void *buf, int len,
static int diag_send_raw_data_remote(int proc, void *buf, int len,
uint8_t hdlc_flag)
{
int err = 0;
@ -861,6 +863,7 @@ static int diag_cb_send_data_remote(int proc, void *buf, int len,
uint16_t payload = 0;
struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
int bridge_index = proc - 1;
if (!buf)
return -EINVAL;
@ -870,24 +873,30 @@ static int diag_cb_send_data_remote(int proc, void *buf, int len,
return -EBADMSG;
}
if (bridge_index < 0 || bridge_index > NUM_REMOTE_DEV) {
pr_err("diag: In %s, invalid bridge index: %d\n", __func__,
bridge_index);
return -EINVAL;
}
do {
if (driver->cb_buf_len == 0)
if (driver->hdlc_encode_buf_len == 0)
break;
usleep_range(10000, 10100);
retry_count++;
} while (retry_count < max_retries);
if (driver->cb_buf_len != 0)
if (driver->hdlc_encode_buf_len != 0)
return -EAGAIN;
if (driver->hdlc_disabled) {
payload = *(uint16_t *)(buf + 2);
driver->cb_buf_len = payload;
driver->hdlc_encode_buf_len = payload;
/*
* Adding 4 bytes for start (1 byte), version (1 byte) and
* payload (2 bytes)
*/
memcpy(driver->cb_buf, buf + 4, payload);
memcpy(driver->hdlc_encode_buf, buf + 4, payload);
goto send_data;
}
@ -897,8 +906,8 @@ static int diag_cb_send_data_remote(int proc, void *buf, int len,
len);
return -EBADMSG;
}
driver->cb_buf_len = len;
memcpy(driver->cb_buf, buf, len);
driver->hdlc_encode_buf_len = len;
memcpy(driver->hdlc_encode_buf, buf, len);
goto send_data;
}
@ -919,18 +928,19 @@ static int diag_cb_send_data_remote(int proc, void *buf, int len,
send.last = (void *)(buf + len - 1);
send.terminate = 1;
enc.dest = driver->cb_buf;
enc.dest_last = (void *)(driver->cb_buf + max_len - 1);
enc.dest = driver->hdlc_encode_buf;
enc.dest_last = (void *)(driver->hdlc_encode_buf + max_len - 1);
diag_hdlc_encode(&send, &enc);
driver->cb_buf_len = (int)(enc.dest - (void *)driver->cb_buf);
driver->hdlc_encode_buf_len = (int)(enc.dest -
(void *)driver->hdlc_encode_buf);
send_data:
err = diagfwd_bridge_write(proc, driver->cb_buf,
driver->cb_buf_len);
err = diagfwd_bridge_write(proc, driver->hdlc_encode_buf,
driver->hdlc_encode_buf_len);
if (err) {
pr_err("diag: Error writing Callback packet to proc: %d, err: %d\n",
proc, err);
driver->cb_buf_len = 0;
driver->hdlc_encode_buf_len = 0;
}
return err;
@ -981,7 +991,7 @@ uint16_t diag_get_remote_device_mask(void)
return 0;
}
static int diag_cb_send_data_remote(int proc, void *buf, int len,
static int diag_send_raw_data_remote(int proc, void *buf, int len,
uint8_t hdlc_flag)
{
return -EINVAL;
@ -1001,7 +1011,22 @@ static int mask_request_validate(unsigned char mask_buf[])
packet_id = mask_buf[0];
if (packet_id == 0x4B) {
if (packet_id == DIAG_CMD_DIAG_SUBSYS_DELAY) {
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
switch (subsys_id) {
case DIAG_SS_DIAG:
if ((ss_cmd == DIAG_SS_FILE_READ_MODEM) ||
(ss_cmd == DIAG_SS_FILE_READ_ADSP) ||
(ss_cmd == DIAG_SS_FILE_READ_WCNSS) ||
(ss_cmd == DIAG_SS_FILE_READ_SLPI) ||
(ss_cmd == DIAG_SS_FILE_READ_APPS))
return 1;
break;
default:
return 0;
}
} else if (packet_id == 0x4B) {
subsys_id = mask_buf[1];
ss_cmd = *(uint16_t *)(mask_buf + 2);
/* Packets with SSID which are allowed */
@ -1106,6 +1131,9 @@ static int diag_switch_logging(int requested_mode)
}
}
if (new_mode == MEMORY_DEVICE_MODE)
driver->md_client_info.client_process = current;
mutex_lock(&driver->diagchar_mutex);
diag_ws_reset(DIAG_WS_MUX);
err = diag_mux_switch_logging(mux_mode);
@ -1968,7 +1996,7 @@ fail:
return err;
}
static int diag_user_process_callback_data(const char __user *buf, int len)
static int diag_user_process_raw_data(const char __user *buf, int len)
{
int err = 0;
int ret = 0;
@ -1995,82 +2023,41 @@ static int diag_user_process_callback_data(const char __user *buf, int len)
/* Check for proc_type */
remote_proc = diag_get_remote(*(int *)user_space_data);
if (!remote_proc) {
if (remote_proc) {
token_offset = sizeof(int);
if (len <= MIN_SIZ_ALLOW) {
pr_err("diag: In %s, possible integer underflow, payload size: %d\n",
__func__, len);
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
return -EBADMSG;
}
len -= sizeof(int);
}
if (driver->mask_check) {
if (!mask_request_validate(user_space_data +
token_offset)) {
pr_alert("diag: mask request Invalid\n");
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
return -EFAULT;
}
}
if (remote_proc) {
ret = diag_send_raw_data_remote(remote_proc - 1,
(void *)(user_space_data + token_offset),
len, USER_SPACE_RAW_DATA);
if (ret) {
pr_err("diag: Error sending data to remote proc %d, err: %d\n",
remote_proc, ret);
}
} else {
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
ret = diag_process_apps_pkt(user_space_data, len);
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
return ret;
if (ret == 1)
diag_send_error_rsp((void *)(user_space_data), len);
}
token_offset = sizeof(int);
if (len <= MIN_SIZ_ALLOW) {
pr_err("diag: In %s, possible integer underflow, payload size: %d\n",
__func__, len);
return -EBADMSG;
}
len -= sizeof(int);
ret = diag_cb_send_data_remote(remote_proc - 1,
(void *)(user_space_data + token_offset),
len, CALLBACK_NON_HDLC_DATA);
fail:
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
return ret;
}
static int diag_user_process_callback_hdlc_data(const char __user *buf, int len)
{
int err = 0;
int ret = 0;
int token_offset = 0;
int remote_proc = 0;
const int mempool = POOL_TYPE_COPY;
unsigned char *user_space_data = NULL;
if (!buf || len <= 0 || len > CALLBACK_BUF_SIZE) {
pr_err_ratelimited("diag: In %s, invalid buf %p len: %d\n",
__func__, buf, len);
return -EBADMSG;
}
user_space_data = diagmem_alloc(driver, len, mempool);
if (!user_space_data)
return -ENOMEM;
err = copy_from_user(user_space_data, buf, len);
if (err) {
pr_err("diag: copy failed for user space data\n");
goto fail;
}
/* Check for proc_type */
remote_proc = diag_get_remote(*(int *)user_space_data);
if (!remote_proc) {
wait_event_interruptible(driver->wait_q,
(driver->in_busy_pktdata == 0));
if (driver->hdlc_disabled)
diag_process_non_hdlc_pkt(user_space_data, len);
else
diag_process_hdlc_pkt((void *)user_space_data, len);
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
return 0;
}
token_offset = sizeof(int);
if (len <= MIN_SIZ_ALLOW) {
pr_err("diag: In %s, possible integer underflow, payload size: %d\n",
__func__, len);
return -EBADMSG;
}
len -= sizeof(int);
ret = diag_cb_send_data_remote(remote_proc - 1,
(void *)(user_space_data + token_offset),
len, CALLBACK_HDLC_DATA);
fail:
diagmem_free(driver, user_space_data, mempool);
user_space_data = NULL;
@ -2471,11 +2458,8 @@ static ssize_t diagchar_write(struct file *file, const char __user *buf,
pkt_type);
else if (pkt_type == DCI_DATA_TYPE)
return diag_user_process_dci_data(payload_buf, payload_len);
else if (pkt_type == CALLBACK_DATA_TYPE)
return diag_user_process_callback_data(payload_buf,
payload_len);
else if (pkt_type == CALLBACK_HDLC_DATA_TYPE)
return diag_user_process_callback_hdlc_data(payload_buf,
else if (pkt_type == USER_SPACE_RAW_DATA_TYPE)
return diag_user_process_raw_data(payload_buf,
payload_len);
else if (pkt_type == USER_SPACE_DATA_TYPE)
return diag_user_process_userspace_data(payload_buf,
@ -2838,6 +2822,7 @@ static int __init diagchar_init(void)
driver->md_proc[i].callback_process = NULL;
driver->md_proc[i].socket_process = NULL;
}
driver->md_client_info.client_process = NULL;
driver->mask_check = 0;
driver->in_busy_pktdata = 0;
driver->in_busy_dcipktdata = 0;

View file

@ -719,7 +719,7 @@ static int diag_cmd_disable_hdlc(unsigned char *src_buf, int src_len,
return write_len;
}
static void diag_send_error_rsp(unsigned char *buf, int len)
void diag_send_error_rsp(unsigned char *buf, int len)
{
/* -1 to accomodate the first byte 0x13 */
if (len > (DIAG_MAX_RSP_SIZE - 1)) {

View file

@ -42,6 +42,7 @@ int diag_check_common_cmd(struct diag_pkt_header_t *header);
void diag_update_userspace_clients(unsigned int type);
void diag_update_sleeping_process(int process_id, int data_type);
int diag_process_apps_pkt(unsigned char *buf, int len);
void diag_send_error_rsp(unsigned char *buf, int len);
void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type);
int diag_process_stm_cmd(unsigned char *buf, unsigned char *dest_buf);
#endif

View file

@ -233,8 +233,8 @@ int diag_remote_dev_write_done(int id, unsigned char *buf, int len, int ctxt)
return -EINVAL;
if (bridge_info[id].type == DIAG_DATA_TYPE) {
if (buf == driver->cb_buf)
driver->cb_buf_len = 0;
if (buf == driver->hdlc_encode_buf)
driver->hdlc_encode_buf_len = 0;
/*
* For remote processor, the token offset is stripped from the
* buffer. Account for the token offset while checking against

View file

@ -100,6 +100,39 @@ static void diag_stm_update_work_fn(struct work_struct *work)
}
}
void diag_notify_md_client(uint16_t peripheral_mask, int data)
{
int stat;
struct siginfo info;
memset(&info, 0, sizeof(struct siginfo));
info.si_code = SI_QUEUE;
info.si_int = (peripheral_mask | data);
info.si_signo = SIGCONT;
stat = send_sig_info(info.si_signo,
&info, driver->md_client_info.client_process);
if (stat)
pr_err("diag: Err sending signal to memory device client, signal data: 0x%x, stat: %d\n",
info.si_int, stat);
}
static void process_pd_status(uint8_t *buf, uint32_t len,
uint8_t peripheral) {
struct diag_ctrl_msg_pd_status *pd_msg =
(struct diag_ctrl_msg_pd_status *)buf;
uint16_t pd;
uint8_t status;
if (!buf || peripheral >= NUM_PERIPHERALS || len == 0)
return;
pd = pd_msg->pd_id;
status = pd_msg->status;
if (driver->logging_mode == MEMORY_DEVICE_MODE) {
diag_notify_md_client(PERIPHERAL_MASK(peripheral), status);
}
}
static void enable_stm_feature(uint8_t peripheral)
{
if (peripheral >= NUM_PERIPHERALS)
@ -657,6 +690,10 @@ void diag_cntl_process_read_data(struct diagfwd_info *p_info, void *buf,
process_build_mask_report(ptr, ctrl_pkt->len,
p_info->peripheral);
break;
case DIAG_CTRL_MSG_PD_STATUS:
process_pd_status(ptr, ctrl_pkt->len,
p_info->peripheral);
break;
default:
pr_debug("diag: Control packet %d not supported\n",
ctrl_pkt->pkt_id);
@ -948,7 +985,7 @@ int diag_send_real_time_update(uint8_t peripheral, int real_time)
mutex_lock(&driver->diag_cntl_mutex);
err = diagfwd_write(peripheral, TYPE_CNTL, buf, msg_size);
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: In %s, unable to write to smd, peripheral: %d, type: %d, len: %d, err: %d\n",
__func__, peripheral, TYPE_CNTL,
msg_size, err);
@ -1064,7 +1101,7 @@ int diag_send_stm_state(uint8_t peripheral, uint8_t stm_control_data)
stm_msg.version = 1;
stm_msg.control_data = stm_control_data;
err = diagfwd_write(peripheral, TYPE_CNTL, &stm_msg, msg_size);
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: In %s, unable to write to smd, peripheral: %d, type: %d, len: %d, err: %d\n",
__func__, peripheral, TYPE_CNTL,
msg_size, err);
@ -1098,7 +1135,7 @@ int diag_send_peripheral_drain_immediate(uint8_t peripheral)
ctrl_pkt.stream_id = 1;
err = diagfwd_write(peripheral, TYPE_CNTL, &ctrl_pkt, sizeof(ctrl_pkt));
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: Unable to send drain immediate ctrl packet to peripheral %d, err: %d\n",
peripheral, err);
}
@ -1143,7 +1180,7 @@ int diag_send_buffering_tx_mode_pkt(uint8_t peripheral,
ctrl_pkt.tx_mode = params->mode;
err = diagfwd_write(peripheral, TYPE_CNTL, &ctrl_pkt, sizeof(ctrl_pkt));
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: Unable to send tx_mode ctrl packet to peripheral %d, err: %d\n",
peripheral, err);
goto fail;
@ -1203,7 +1240,7 @@ int diag_send_buffering_wm_values(uint8_t peripheral,
err = diagfwd_write(peripheral, TYPE_CNTL, &ctrl_pkt,
sizeof(ctrl_pkt));
if (err) {
if (err && err != -ENODEV) {
pr_err("diag: Unable to send watermark values to peripheral %d, err: %d\n",
peripheral, err);
}

View file

@ -44,6 +44,7 @@
#define DIAG_CTRL_MSG_BUILD_MASK_REPORT 25
#define DIAG_CTRL_MSG_DEREG 27
#define DIAG_CTRL_MSG_DCI_HANDSHAKE_PKT 29
#define DIAG_CTRL_MSG_PD_STATUS 30
/*
* Feature Mask Definitions: Feature mask is used to sepcify Diag features
@ -185,6 +186,14 @@ struct diag_ctrl_dci_handshake_pkt {
uint32_t magic;
} __packed;
struct diag_ctrl_msg_pd_status {
uint32_t ctrl_pkt_id;
uint32_t ctrl_pkt_data_len;
uint32_t version;
uint32_t pd_id;
uint8_t status;
} __packed;
struct diag_ctrl_last_event_report {
uint32_t pkt_id;
uint32_t len;
@ -260,5 +269,5 @@ int diag_send_buffering_tx_mode_pkt(uint8_t peripheral,
struct diag_buffering_mode_t *params);
int diag_send_buffering_wm_values(uint8_t peripheral,
struct diag_buffering_mode_t *params);
void diag_notify_md_client(uint16_t peripheral_mask, int data);
#endif

View file

@ -76,7 +76,10 @@ static void diagfwd_cntl_open(struct diagfwd_info *fwd_info)
{
if (!fwd_info)
return;
if (driver->logging_mode == MEMORY_DEVICE_MODE) {
diag_notify_md_client(PERIPHERAL_MASK(fwd_info->peripheral),
DIAG_STATUS_OPEN);
}
diag_cntl_channel_open(fwd_info);
}
@ -84,7 +87,10 @@ static void diagfwd_cntl_close(struct diagfwd_info *fwd_info)
{
if (!fwd_info)
return;
if (driver->logging_mode == MEMORY_DEVICE_MODE) {
diag_notify_md_client(PERIPHERAL_MASK(fwd_info->peripheral),
DIAG_STATUS_CLOSED);
}
diag_cntl_channel_close(fwd_info);
}
@ -304,7 +310,7 @@ static void diagfwd_data_read_done(struct diagfwd_info *fwd_info,
err = diag_mux_write(DIAG_LOCAL_PROC, write_buf, write_len,
temp_buf->ctxt);
if (err) {
pr_err_ratelimited("diag: In %s, diag_device_write error: %d\n",
pr_err_ratelimited("diag: In %s, unable to write to mux error: %d\n",
__func__, err);
goto end;
}

View file

@ -20,11 +20,10 @@
#define DEINIT_TYPE 0x00000010
#define USER_SPACE_DATA_TYPE 0x00000020
#define DCI_DATA_TYPE 0x00000040
#define CALLBACK_DATA_TYPE 0x00000080
#define USER_SPACE_RAW_DATA_TYPE 0x00000080
#define DCI_LOG_MASKS_TYPE 0x00000100
#define DCI_EVENT_MASKS_TYPE 0x00000200
#define DCI_PKT_TYPE 0x00000400
#define CALLBACK_HDLC_DATA_TYPE 0x00000800
#define HDLC_SUPPORT_TYPE 0x00001000
#define USB_MODE 1