Merge "diag: Make fixes in memory device mode"

This commit is contained in:
Linux Build Service Account 2015-07-03 15:53:46 -07:00 committed by Gerrit - the friendly Code Review server
commit 2ead4cc259
5 changed files with 111 additions and 58 deletions

View File

@ -405,6 +405,7 @@ struct diag_md_proc_info {
int pid;
struct task_struct *socket_process;
struct task_struct *callback_process;
struct task_struct *mdlog_process;
};
struct diag_feature_t {
@ -420,13 +421,6 @@ 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 */
@ -538,7 +532,6 @@ 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;

View File

@ -186,7 +186,7 @@ static uint16_t diag_get_next_delayed_rsp_id(void)
return rsp_id;
}
static int diag_switch_logging(int requested_mode);
static int diag_switch_logging(const int requested_mode);
#define COPY_USER_SPACE_OR_EXIT(buf, data, length) \
do { \
@ -371,12 +371,25 @@ static void diag_close_logging_process(int pid)
continue;
}
found = 1;
if (logging_proc->socket_process)
DIAG_LOG(DIAG_DEBUG_USERSPACE, "found entry pid %d\n", pid);
if (logging_proc->socket_process) {
logging_proc->socket_process = NULL;
if (logging_proc->callback_process)
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting socket proc %d to NULL, proc: %d",
driver->md_proc[i].pid, i);
}
if (logging_proc->callback_process) {
logging_proc->callback_process = NULL;
if (driver->md_client_info.client_process)
driver->md_client_info.client_process = NULL;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting callback proc %d to NULL, proc: %d",
driver->md_proc[i].pid, i);
}
if (logging_proc->mdlog_process) {
logging_proc->mdlog_process = NULL;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting mdlog proc %d to NULL, proc: %d",
driver->md_proc[i].pid, i);
}
diag_update_proc_vote(DIAG_PROC_MEMORY_DEVICE, VOTE_DOWN, i);
}
mutex_unlock(&driver->diagchar_mutex);
@ -422,6 +435,8 @@ static void diag_close_logging_process(int pid)
if (logging_proc->pid != pid)
continue;
logging_proc->pid = 0;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting logging proc to 0\n");
}
mutex_unlock(&driver->diagchar_mutex);
}
@ -1101,13 +1116,14 @@ static int mask_request_validate(unsigned char mask_buf[])
return 0;
}
static int diag_switch_logging(int requested_mode)
static int diag_switch_logging(const int requested_mode)
{
int i;
int err = 0;
int mux_mode = DIAG_USB_MODE; /* set the mode from diag_mux.h */
int new_mode = USB_MODE;
int current_mode = driver->logging_mode;
int found = 0;
switch (requested_mode) {
case CALLBACK_MODE:
@ -1127,29 +1143,40 @@ static int diag_switch_logging(int requested_mode)
return -EINVAL;
}
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"current: %d requested: %d translated: %d, pid: %d\n",
current_mode, requested_mode, new_mode, current->tgid);
if (new_mode == current_mode) {
if (requested_mode != MEMORY_DEVICE_MODE ||
driver->real_time_mode) {
pr_info_ratelimited("diag: Already in logging mode change requested, mode: %d\n",
current_mode);
}
DIAG_LOG(DIAG_DEBUG_USERSPACE, "no mode change required\n");
return 0;
}
if (new_mode == SOCKET_MODE &&
driver->md_proc[DIAG_LOCAL_PROC].socket_process) {
err = send_sig(SIGCONT,
driver->md_proc[DIAG_LOCAL_PROC].socket_process,
0);
if (err) {
pr_err("diag: In %s, error notifying socket process %d\n",
__func__, err);
/*
* When any mdlog process exits, or votes for USB mode, check if the
* process is the original requestor for the mode change. Don't allow
* any mdlog process to vote for mode change.
*/
if (current_mode == MEMORY_DEVICE_MODE && new_mode == USB_MODE) {
for (i = 0; i < DIAG_NUM_PROC && !found; i++) {
if (driver->md_proc[i].pid == current->tgid)
found = 1;
}
if (!found) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"switch_logging denied pid: %d saved: %d\n",
current->tgid,
driver->md_proc[DIAG_LOCAL_PROC].pid);
return 0;
}
}
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);
@ -1157,11 +1184,17 @@ static int diag_switch_logging(int requested_mode)
pr_err("diag: In %s, unable to switch mode from %d to %d\n",
__func__, current_mode, requested_mode);
driver->logging_mode = current_mode;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"error changing logging modes\n");
goto fail;
}
driver->logging_mode = new_mode;
pr_info("diag: Logging switched from %d to %d mode\n",
current_mode, new_mode);
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"logging switched from %d to %d mode\n",
current_mode, new_mode);
if (new_mode != MEMORY_DEVICE_MODE) {
diag_update_real_time_vote(DIAG_PROC_MEMORY_DEVICE,
@ -1176,10 +1209,35 @@ static int diag_switch_logging(int requested_mode)
&driver->diag_real_time_work);
}
for (i = 0; i < DIAG_NUM_PROC; i++) {
driver->md_proc[i].pid = current->tgid;
if (requested_mode == SOCKET_MODE)
/*
* Set the pid and context for md_proc. For callback processes, the
* context will be set by DIAG_IOCTL_REGISTER_CALLBACK.
*/
for (i = 0; i < DIAG_NUM_PROC && new_mode == MEMORY_DEVICE_MODE; i++) {
switch (requested_mode) {
case SOCKET_MODE:
driver->md_proc[i].pid = current->tgid;
driver->md_proc[i].socket_process = current;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting socket process to %d, proc: %d",
driver->md_proc[i].pid, i);
break;
case MEMORY_DEVICE_MODE:
driver->md_proc[i].pid = current->tgid;
driver->md_proc[i].mdlog_process = current;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting mdlog process to %d, proc: %d",
driver->md_proc[i].pid, i);
break;
case CALLBACK_MODE:
if (driver->md_proc[i].callback_process == current) {
driver->md_proc[i].pid = current->tgid;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"setting callback process to %d, proc: %d",
driver->md_proc[i].pid, i);
}
break;
}
}
fail:
mutex_unlock(&driver->diagchar_mutex);
@ -1459,10 +1517,12 @@ static int diag_ioctl_register_callback(unsigned long ioarg)
return -EINVAL;
}
/*
* The IOCTL will just send the context for md_proc.
* The pid will be set by diag_switch_logging.
*/
mutex_lock(&driver->diagchar_mutex);
driver->md_proc[reg.proc].pid = current->tgid;
driver->md_proc[reg.proc].callback_process = current;
driver->md_proc[reg.proc].socket_process = NULL;
mutex_unlock(&driver->diagchar_mutex);
return 0;
@ -2842,8 +2902,8 @@ static int __init diagchar_init(void)
driver->md_proc[i].pid = 0;
driver->md_proc[i].callback_process = NULL;
driver->md_proc[i].socket_process = NULL;
driver->md_proc[i].mdlog_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

@ -27,6 +27,7 @@
/* tracks which peripheral is undergoing SSR */
static uint16_t reg_dirty;
static void diag_notify_md_client(uint8_t peripheral, int data);
static void diag_mask_update_work_fn(struct work_struct *work)
{
@ -48,6 +49,7 @@ void diag_cntl_channel_open(struct diagfwd_info *p_info)
return;
driver->mask_update |= PERIPHERAL_MASK(p_info->peripheral);
queue_work(driver->cntl_wq, &driver->mask_update_work);
diag_notify_md_client(p_info->peripheral, DIAG_STATUS_OPEN);
}
void diag_cntl_channel_close(struct diagfwd_info *p_info)
@ -70,6 +72,8 @@ void diag_cntl_channel_close(struct diagfwd_info *p_info)
driver->stm_state[peripheral] = DISABLE_STM;
driver->stm_state_requested[peripheral] = DISABLE_STM;
reg_dirty ^= PERIPHERAL_MASK(peripheral);
diag_notify_md_client(peripheral, DIAG_STATUS_CLOSED);
flush_workqueue(driver->cntl_wq);
}
@ -101,37 +105,42 @@ static void diag_stm_update_work_fn(struct work_struct *work)
}
}
void diag_notify_md_client(uint16_t peripheral_mask, int data)
void diag_notify_md_client(uint8_t peripheral, int data)
{
int stat;
int stat = 0;
struct siginfo info;
if (driver->logging_mode != MEMORY_DEVICE_MODE)
return;
memset(&info, 0, sizeof(struct siginfo));
info.si_code = SI_QUEUE;
info.si_int = (peripheral_mask | data);
info.si_int = (PERIPHERAL_MASK(peripheral) | 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);
if (driver->md_proc[DIAG_LOCAL_PROC].mdlog_process) {
stat = send_sig_info(info.si_signo, &info,
driver->md_proc[DIAG_LOCAL_PROC].mdlog_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;
uint8_t peripheral)
{
struct diag_ctrl_msg_pd_status *pd_msg = NULL;
uint32_t pd;
int status = DIAG_STATUS_CLOSED;
if (!buf || peripheral >= NUM_PERIPHERALS || len == 0)
if (!buf || peripheral >= NUM_PERIPHERALS || len < sizeof(*pd_msg))
return;
pd_msg = (struct diag_ctrl_msg_pd_status *)buf;
pd = pd_msg->pd_id;
status = pd_msg->status;
if (driver->logging_mode == MEMORY_DEVICE_MODE) {
diag_notify_md_client(PERIPHERAL_MASK(peripheral), status);
}
status = (pd_msg->status == 0) ? DIAG_STATUS_OPEN : DIAG_STATUS_CLOSED;
diag_notify_md_client(peripheral, status);
}
static void enable_stm_feature(uint8_t peripheral)

View File

@ -277,5 +277,4 @@ 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,10 +76,6 @@ 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);
}
@ -87,10 +83,6 @@ 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);
}