diag: Add support for multi connection logging

This change adds support to route On-Device logging and
USB logging traffic per peripheral. A peripherals'
traffic can go to either endpoint but not both. The
mux layer has a peripheral state and the mode switching
logic has multi mode support.

CRs-Fixed: 1004236
Change-Id: I54fef744bdf08a346e4aef22c1280e928cdaf5d2
Signed-off-by: Chris Lew <clew@codeaurora.org>
This commit is contained in:
Chris Lew 2016-04-20 08:34:16 -07:00 committed by Kyle Yan
parent 0db49c2550
commit b1e748622f
5 changed files with 314 additions and 190 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2016, 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
@ -23,11 +23,13 @@
#include <linux/spinlock.h>
#include <linux/ratelimit.h>
#include "diagchar.h"
#include "diagfwd.h"
#include "diag_mux.h"
#include "diag_usb.h"
#include "diag_memorydevice.h"
struct diag_logger_t *logger;
struct diag_mux_state_t *diag_mux;
static struct diag_logger_t usb_logger;
static struct diag_logger_t md_logger;
@ -49,11 +51,11 @@ static struct diag_logger_ops md_log_ops = {
int diag_mux_init()
{
logger = kzalloc(NUM_MUX_PROC * sizeof(struct diag_logger_t),
diag_mux = kzalloc(sizeof(struct diag_mux_state_t),
GFP_KERNEL);
if (!logger)
if (!diag_mux)
return -ENOMEM;
kmemleak_not_leak(logger);
kmemleak_not_leak(diag_mux);
usb_logger.mode = DIAG_USB_MODE;
usb_logger.log_ops = &usb_log_ops;
@ -66,13 +68,17 @@ int diag_mux_init()
* Set USB logging as the default logger. This is the mode
* Diag should be in when it initializes.
*/
logger = &usb_logger;
diag_mux->usb_ptr = &usb_logger;
diag_mux->md_ptr = &md_logger;
diag_mux->logger = &usb_logger;
diag_mux->mux_mask = 0;
diag_mux->mode = DIAG_USB_MODE;
return 0;
}
void diag_mux_exit()
{
kfree(logger);
kfree(diag_mux);
}
int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
@ -106,19 +112,43 @@ int diag_mux_register(int proc, int ctx, struct diag_mux_ops *ops)
int diag_mux_queue_read(int proc)
{
struct diag_logger_t *logger = NULL;
if (proc < 0 || proc >= NUM_MUX_PROC)
return -EINVAL;
if (!logger)
if (!diag_mux)
return -EIO;
if (logger->log_ops && logger->log_ops->queue_read)
if (diag_mux->mode == DIAG_MULTI_MODE)
logger = diag_mux->usb_ptr;
else
logger = diag_mux->logger;
if (logger && logger->log_ops && logger->log_ops->queue_read)
return logger->log_ops->queue_read(proc);
return 0;
}
int diag_mux_write(int proc, unsigned char *buf, int len, int ctx)
{
struct diag_logger_t *logger = NULL;
int peripheral;
if (proc < 0 || proc >= NUM_MUX_PROC)
return -EINVAL;
if (!diag_mux)
return -EIO;
peripheral = GET_BUF_PERIPHERAL(ctx);
if (peripheral > NUM_PERIPHERALS)
return -EINVAL;
if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask)
logger = diag_mux->md_ptr;
else
logger = diag_mux->usb_ptr;
if (logger && logger->log_ops && logger->log_ops->write)
return logger->log_ops->write(proc, buf, len, ctx);
return 0;
@ -126,38 +156,86 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx)
int diag_mux_close_peripheral(int proc, uint8_t peripheral)
{
struct diag_logger_t *logger = NULL;
if (proc < 0 || proc >= NUM_MUX_PROC)
return -EINVAL;
/* Peripheral should account for Apps data as well */
if (peripheral > NUM_PERIPHERALS)
return -EINVAL;
if (!diag_mux)
return -EIO;
if (MD_PERIPHERAL_MASK(peripheral) & diag_mux->mux_mask)
logger = diag_mux->md_ptr;
else
logger = diag_mux->logger;
if (logger && logger->log_ops && logger->log_ops->close_peripheral)
return logger->log_ops->close_peripheral(proc, peripheral);
return 0;
}
int diag_mux_switch_logging(int new_mode)
int diag_mux_switch_logging(int *req_mode, int *peripheral_mask)
{
struct diag_logger_t *new_logger = NULL;
unsigned int new_mask = 0;
switch (new_mode) {
case DIAG_USB_MODE:
new_logger = &usb_logger;
break;
case DIAG_MEMORY_DEVICE_MODE:
new_logger = &md_logger;
break;
default:
pr_err("diag: Invalid mode %d in %s\n", new_mode, __func__);
if (!req_mode)
return -EINVAL;
if (*peripheral_mask <= 0 || *peripheral_mask > DIAG_CON_ALL) {
pr_err("diag: mask %d in %s\n", *peripheral_mask, __func__);
return -EINVAL;
}
if (logger) {
logger->log_ops->close();
logger = new_logger;
logger->log_ops->open();
switch (*req_mode) {
case DIAG_USB_MODE:
new_mask = ~(*peripheral_mask) & diag_mux->mux_mask;
if (new_mask != DIAG_CON_NONE)
*req_mode = DIAG_MULTI_MODE;
break;
case DIAG_MEMORY_DEVICE_MODE:
new_mask = (*peripheral_mask) | diag_mux->mux_mask;
if (new_mask != DIAG_CON_ALL)
*req_mode = DIAG_MULTI_MODE;
break;
default:
pr_err("diag: Invalid mode %d in %s\n", *req_mode, __func__);
return -EINVAL;
}
switch (diag_mux->mode) {
case DIAG_USB_MODE:
if (*req_mode == DIAG_MEMORY_DEVICE_MODE) {
diag_mux->usb_ptr->log_ops->close();
diag_mux->logger = diag_mux->md_ptr;
diag_mux->md_ptr->log_ops->open();
} else if (*req_mode == DIAG_MULTI_MODE) {
diag_mux->md_ptr->log_ops->open();
diag_mux->logger = NULL;
}
break;
case DIAG_MEMORY_DEVICE_MODE:
if (*req_mode == DIAG_USB_MODE) {
diag_mux->md_ptr->log_ops->close();
diag_mux->logger = diag_mux->usb_ptr;
diag_mux->usb_ptr->log_ops->open();
} else if (*req_mode == DIAG_MULTI_MODE) {
diag_mux->usb_ptr->log_ops->open();
diag_mux->logger = NULL;
}
break;
case DIAG_MULTI_MODE:
if (*req_mode == DIAG_USB_MODE) {
diag_mux->md_ptr->log_ops->close();
diag_mux->logger = diag_mux->usb_ptr;
} else if (*req_mode == DIAG_MEMORY_DEVICE_MODE) {
diag_mux->usb_ptr->log_ops->close();
diag_mux->logger = diag_mux->md_ptr;
}
break;
}
diag_mux->mode = *req_mode;
diag_mux->mux_mask = new_mask;
*peripheral_mask = new_mask;
return 0;
}

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2014-2016, 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
@ -13,6 +13,14 @@
#define DIAG_MUX_H
#include "diagchar.h"
struct diag_mux_state_t {
struct diag_logger_t *logger;
struct diag_logger_t *usb_ptr;
struct diag_logger_t *md_ptr;
unsigned int mux_mask;
unsigned int mode;
};
struct diag_mux_ops {
int (*open)(int id, int mode);
int (*close)(int id, int mode);
@ -24,6 +32,7 @@ struct diag_mux_ops {
#define DIAG_USB_MODE 0
#define DIAG_MEMORY_DEVICE_MODE 1
#define DIAG_NO_LOGGING_MODE 2
#define DIAG_MULTI_MODE 3
#define DIAG_MUX_LOCAL 0
#define DIAG_MUX_LOCAL_LAST 1
@ -53,7 +62,7 @@ struct diag_logger_t {
struct diag_logger_ops *log_ops;
};
extern struct diag_logger_t *logger;
extern struct diag_mux_state_t *diag_mux;
int diag_mux_init(void);
void diag_mux_exit(void);
@ -63,5 +72,5 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx);
int diag_mux_close_peripheral(int proc, uint8_t peripheral);
int diag_mux_open_all(struct diag_logger_t *logger);
int diag_mux_close_all(void);
int diag_mux_switch_logging(int new_mode);
int diag_mux_switch_logging(int *new_mode, int *peripheral_mask);
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2008-2016, 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
@ -64,6 +64,10 @@
#define DIAG_CON_LPASS (0x0004) /* Bit mask for LPASS */
#define DIAG_CON_WCNSS (0x0008) /* Bit mask for WCNSS */
#define DIAG_CON_SENSORS (0x0010) /* Bit mask for Sensors */
#define DIAG_CON_NONE (0x0000) /* Bit mask for No SS*/
#define DIAG_CON_ALL (DIAG_CON_APSS | DIAG_CON_MPSS \
| DIAG_CON_LPASS | DIAG_CON_WCNSS \
| DIAG_CON_SENSORS)
#define DIAG_STM_MODEM 0x01
#define DIAG_STM_LPASS 0x02
@ -158,8 +162,7 @@
#define FEATURE_MASK_LEN 2
#define DIAG_MD_NONE 0
#define DIAG_MD_NORMAL 1
#define DIAG_MD_PERIPHERAL 2
#define DIAG_MD_PERIPHERAL 1
/*
* The status bit masks when received in a signal handler are to be
@ -561,6 +564,7 @@ struct diagchar_dev {
uint32_t dci_pkt_length;
int in_busy_dcipktdata;
int logging_mode;
int logging_mask;
int mask_check;
uint32_t md_session_mask;
uint8_t md_session_mode;

View file

@ -369,6 +369,24 @@ fail:
return -ENOMEM;
}
static uint32_t diag_translate_kernel_to_user_mask(uint32_t peripheral_mask)
{
uint32_t ret = 0;
if (peripheral_mask & MD_PERIPHERAL_MASK(APPS_DATA))
ret |= DIAG_CON_APSS;
if (peripheral_mask & MD_PERIPHERAL_MASK(PERIPHERAL_MODEM))
ret |= DIAG_CON_MPSS;
if (peripheral_mask & MD_PERIPHERAL_MASK(PERIPHERAL_LPASS))
ret |= DIAG_CON_LPASS;
if (peripheral_mask & MD_PERIPHERAL_MASK(PERIPHERAL_WCNSS))
ret |= DIAG_CON_WCNSS;
if (peripheral_mask & MD_PERIPHERAL_MASK(PERIPHERAL_SENSORS))
ret |= DIAG_CON_SENSORS;
return ret;
}
static void diag_close_logging_process(const int pid)
{
int i;
@ -388,7 +406,8 @@ static void diag_close_logging_process(const int pid)
params.req_mode = USB_MODE;
params.mode_param = 0;
params.peripheral_mask = 0;
params.peripheral_mask =
diag_translate_kernel_to_user_mask(session_peripheral_mask);
mutex_lock(&driver->diagchar_mutex);
diag_switch_logging(&params);
mutex_unlock(&driver->diagchar_mutex);
@ -417,7 +436,8 @@ static int diag_remove_client_entry(struct file *file)
diagpriv_data = file->private_data;
/* clean up any DCI registrations, if this is a DCI client
/*
* 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
*/
@ -1148,19 +1168,10 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
struct diag_md_session_t *new_session = NULL;
/*
* If there is any session running in Normal mode
* we cannot start a new session . If there is a
* session running in Peripheral mode we cannot
* start a new session in NORMAL mode. If a session is
* running with a peripheral mask and a new session
* request comes in with same peripheral mask value
* then return invalid param
* If a session is running with a peripheral mask and a new session
* request comes in with same peripheral mask value then return
* invalid param
*/
if (driver->md_session_mode == DIAG_MD_NORMAL)
return -EINVAL;
if (driver->md_session_mode == DIAG_MD_PERIPHERAL
&& mode == DIAG_MD_NORMAL)
return -EINVAL;
if (driver->md_session_mode == DIAG_MD_PERIPHERAL &&
(driver->md_session_mask & peripheral_mask) != 0)
return -EINVAL;
@ -1176,32 +1187,6 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
new_session->pid = current->tgid;
new_session->task = current;
if (mode == DIAG_MD_NORMAL) {
new_session->log_mask = &log_mask;
new_session->event_mask = &event_mask;
new_session->msg_mask = &msg_mask;
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (driver->md_session_map[i] != NULL) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"another instance present for %d\n",
i);
err = -EEXIST;
goto fail_normal;
}
new_session->peripheral_mask |= MD_PERIPHERAL_MASK(i);
driver->md_session_mask |= MD_PERIPHERAL_MASK(i);
driver->md_session_map[i] = new_session;
}
driver->md_session_mode = DIAG_MD_NORMAL;
setup_timer(&new_session->hdlc_reset_timer,
diag_md_hdlc_reset_timer_func,
new_session->pid);
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"created session in normal mode\n");
mutex_unlock(&driver->md_session_lock);
return 0;
}
new_session->log_mask = kzalloc(sizeof(struct diag_mask_info),
GFP_KERNEL);
if (!new_session->log_mask) {
@ -1251,10 +1236,11 @@ int diag_md_session_create(int mode, int peripheral_mask, int proc)
new_session->peripheral_mask |= MD_PERIPHERAL_MASK(i);
driver->md_session_map[i] = new_session;
driver->md_session_mask |= MD_PERIPHERAL_MASK(i);
}
setup_timer(&new_session->hdlc_reset_timer,
diag_md_hdlc_reset_timer_func,
new_session->pid);
}
driver->md_session_mode = DIAG_MD_PERIPHERAL;
mutex_unlock(&driver->md_session_lock);
DIAG_LOG(DIAG_DEBUG_USERSPACE,
@ -1271,7 +1257,6 @@ fail_peripheral:
diag_msg_mask_free(new_session->msg_mask);
kfree(new_session->msg_mask);
new_session->msg_mask = NULL;
fail_normal:
kfree(new_session);
new_session = NULL;
mutex_unlock(&driver->md_session_lock);
@ -1292,8 +1277,7 @@ static void diag_md_session_close(struct diag_md_session_t *session_info)
continue;
driver->md_session_map[i] = NULL;
driver->md_session_mask &= ~session_info->peripheral_mask;
if (driver->md_session_mode == DIAG_MD_NORMAL)
continue;
}
diag_log_mask_free(session_info->log_mask);
kfree(session_info->log_mask);
session_info->log_mask = NULL;
@ -1304,7 +1288,6 @@ static void diag_md_session_close(struct diag_md_session_t *session_info)
kfree(session_info->event_mask);
session_info->event_mask = NULL;
del_timer(&session_info->hdlc_reset_timer);
}
for (i = 0; i < NUM_MD_SESSIONS && !found; i++) {
if (driver->md_session_map[i] != NULL)
@ -1337,113 +1320,157 @@ struct diag_md_session_t *diag_md_session_get_peripheral(uint8_t peripheral)
return driver->md_session_map[peripheral];
}
static int diag_md_peripheral_switch(struct diag_md_session_t *session_info,
int peripheral_mask, int req_mode) {
int i, bit = 0;
if (!session_info)
return -EINVAL;
if (req_mode != DIAG_USB_MODE || req_mode != DIAG_MEMORY_DEVICE_MODE)
return -EINVAL;
/*
* check that md_session_map for i == session_info,
* if not then race condition occurred and bail
*/
mutex_lock(&driver->md_session_lock);
for (i = 0; i < NUM_MD_SESSIONS; i++) {
bit = MD_PERIPHERAL_MASK(i) & peripheral_mask;
if (!bit)
continue;
if (req_mode == DIAG_USB_MODE) {
if (driver->md_session_map[i] != session_info) {
mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
driver->md_session_map[i] = NULL;
driver->md_session_mask &= ~bit;
session_info->peripheral_mask &= ~bit;
} else {
if (driver->md_session_map[i] != NULL) {
mutex_unlock(&driver->md_session_lock);
return -EINVAL;
}
driver->md_session_map[i] = session_info;
driver->md_session_mask |= bit;
session_info->peripheral_mask |= bit;
}
}
driver->md_session_mode = DIAG_MD_PERIPHERAL;
mutex_unlock(&driver->md_session_lock);
DIAG_LOG(DIAG_DEBUG_USERSPACE, "Changed Peripherals:0x%x to mode:%d\n",
peripheral_mask, req_mode);
}
static int diag_md_session_check(int curr_mode, int req_mode,
const struct diag_logging_mode_param_t *param,
uint8_t *change_mode)
{
int err = 0;
int i, bit = 0, err = 0;
int change_mask = 0;
struct diag_md_session_t *session_info = NULL;
if (!param || !change_mode)
return -EIO;
*change_mode = 1;
*change_mode = 0;
switch (curr_mode) {
case DIAG_USB_MODE:
case DIAG_MEMORY_DEVICE_MODE:
case DIAG_MULTI_MODE:
break;
default:
return -EINVAL;
}
switch (req_mode) {
case DIAG_USB_MODE:
case DIAG_MEMORY_DEVICE_MODE:
break;
default:
if (req_mode != DIAG_USB_MODE && req_mode != DIAG_MEMORY_DEVICE_MODE)
return -EINVAL;
}
if (curr_mode == DIAG_USB_MODE) {
if (req_mode == DIAG_USB_MODE) {
/*
* This case tries to change from USB mode to USB mode.
* There is no change required. Return success.
*/
*change_mode = 0;
if (curr_mode == DIAG_USB_MODE)
return 0;
if (driver->md_session_mode == DIAG_MD_NONE
&& driver->md_session_mask == 0 && driver->logging_mask) {
*change_mode = 1;
return 0;
}
/*
* If there is no other mdlog process, return success.
* Check if the peripheral interested in is active.
* curr_mode is either DIAG_MULTI_MODE or DIAG_MD_MODE
* Check if requested peripherals are already in usb mode
*/
if (param->mode_param == DIAG_MD_NORMAL) {
err = diag_md_session_create(DIAG_MD_NORMAL, 0,
DIAG_LOCAL_PROC);
return err;
} else if (param->mode_param == DIAG_MD_PERIPHERAL &&
(!(driver->md_session_mask &
param->peripheral_mask))) {
err = diag_md_session_create(DIAG_MD_PERIPHERAL,
param->peripheral_mask,
DIAG_LOCAL_PROC);
return err;
for (i = 0; i < NUM_MD_SESSIONS; i++) {
bit = MD_PERIPHERAL_MASK(i) & param->peripheral_mask;
if (!bit)
continue;
if (bit & driver->logging_mask)
change_mask |= bit;
}
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"an instance of mdlog is active\n");
*change_mode = 0;
return -EINVAL;
} else if (curr_mode == DIAG_MEMORY_DEVICE_MODE) {
if (req_mode == DIAG_USB_MODE) {
if (driver->md_session_mask != 0 &&
driver->md_session_mode == DIAG_MD_PERIPHERAL) {
if (!change_mask)
return 0;
/*
* An instance of mdlog is still running, Return
* error.
* Change is needed. Check if this md_session has set all the
* requested peripherals. If another md session set a requested
* peripheral then we cannot switch that peripheral to USB.
* If this session owns all the requested peripherals, then
* call function to switch the modes/masks for the md_session
*/
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"another instance running\n");
*change_mode = 0;
return -EINVAL;
}
session_info = diag_md_session_get_pid(current->tgid);
diag_md_session_close(session_info);
if (!session_info) {
*change_mode = 1;
return 0;
}
if (param->mode_param == DIAG_MD_NORMAL) {
/*
* The new client is asking for MD_NORMAL. We're
* already in memory device mode - this must be
* set by another active process. Return error
* for this new client.
*/
if ((change_mask & session_info->peripheral_mask)
!= change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"unable to switch logging mode\n");
*change_mode = 0;
"Another MD Session owns a requested peripheral\n");
return -EINVAL;
} else if (param->mode_param == DIAG_MD_PERIPHERAL) {
if (driver->md_session_mask & param->peripheral_mask) {
}
*change_mode = 1;
/* If all peripherals are being set to USB Mode, call close */
if (~change_mask & session_info->peripheral_mask) {
err = diag_md_peripheral_switch(session_info,
change_mask, DIAG_USB_MODE);
} else
diag_md_session_close(session_info);
return err;
} else if (req_mode == DIAG_MEMORY_DEVICE_MODE) {
/*
* The new client is asking for a
* specific peripheral. This case checks
* if a client is exercising this
* peripheral already. Return error
* if the peripheral is already in use.
* Get bit mask that represents what peripherals already have
* been set. Check that requested peripherals already set are
* owned by this md session
*/
change_mask = driver->md_session_mask & param->peripheral_mask;
session_info = diag_md_session_get_pid(current->tgid);
if (session_info) {
if ((session_info->peripheral_mask & change_mask)
!= change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"another instance running\n");
*change_mode = 0;
"Another MD Session owns a requested peripheral\n");
return -EINVAL;
}
err = diag_md_peripheral_switch(session_info,
change_mask, DIAG_USB_MODE);
} else {
if (change_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Another MD Session owns a requested peripheral\n");
return -EINVAL;
}
err = diag_md_session_create(DIAG_MD_PERIPHERAL,
param->peripheral_mask,
DIAG_LOCAL_PROC);
*change_mode = 0;
return err;
param->peripheral_mask, DIAG_LOCAL_PROC);
}
*change_mode = 1;
return err;
}
return -EINVAL;
}
@ -1477,17 +1504,14 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
if (!param)
return -EINVAL;
if (param->mode_param == DIAG_MD_PERIPHERAL &&
param->peripheral_mask == 0) {
if (!param->peripheral_mask) {
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"asking for peripehral mode with no mask being set\n");
"asking for mode switch with no peripheral mask set\n");
return -EINVAL;
}
if (param->mode_param == DIAG_MD_PERIPHERAL) {
peripheral_mask = diag_translate_mask(param->peripheral_mask);
param->peripheral_mask = peripheral_mask;
}
switch (param->req_mode) {
case CALLBACK_MODE:
@ -1507,8 +1531,8 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
curr_mode = driver->logging_mode;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"request to switch logging from: %d to %d\n",
curr_mode, new_mode);
"request to switch logging from %d mask:%0x to %d mask:%0x\n",
curr_mode, driver->md_session_mask, new_mode, peripheral_mask);
err = diag_md_session_check(curr_mode, new_mode, param, &do_switch);
if (err) {
@ -1525,7 +1549,7 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
}
diag_ws_reset(DIAG_WS_MUX);
err = diag_mux_switch_logging(new_mode);
err = diag_mux_switch_logging(&new_mode, &peripheral_mask);
if (err) {
pr_err("diag: In %s, unable to switch mode from %d to %d, err: %d\n",
__func__, curr_mode, new_mode, err);
@ -1533,7 +1557,11 @@ static int diag_switch_logging(struct diag_logging_mode_param_t *param)
goto fail;
}
driver->logging_mode = new_mode;
driver->logging_mask = peripheral_mask;
DIAG_LOG(DIAG_DEBUG_USERSPACE,
"Switch logging to %d mask:%0x\n", new_mode, peripheral_mask);
/* Update to take peripheral_mask */
if (new_mode != DIAG_MEMORY_DEVICE_MODE) {
diag_update_real_time_vote(DIAG_PROC_MEMORY_DEVICE,
MODE_REALTIME, ALL_PROC);
@ -1839,10 +1867,8 @@ static int diag_ioctl_register_callback(unsigned long ioarg)
return -EINVAL;
}
if (driver->md_session_mode == DIAG_MD_NORMAL ||
driver->md_session_mode == DIAG_MD_PERIPHERAL) {
if (driver->md_session_mode == DIAG_MD_PERIPHERAL)
return -EIO;
}
return err;
}
@ -2737,7 +2763,8 @@ static ssize_t diagchar_read(struct file *file, char __user *buf, size_t count,
mutex_lock(&driver->diagchar_mutex);
if ((driver->data_ready[index] & USER_SPACE_DATA_TYPE) &&
(driver->logging_mode == DIAG_MEMORY_DEVICE_MODE)) {
(driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
driver->logging_mode == DIAG_MULTI_MODE)) {
pr_debug("diag: process woken up\n");
/*Copy the type of data being passed*/
data_type = driver->data_ready[index] & USER_SPACE_DATA_TYPE;

View file

@ -234,7 +234,7 @@ void chk_logging_wakeup(void)
* index as all the indices point to the same session
* structure.
*/
if (driver->md_session_mode == DIAG_MD_NORMAL && j == 0)
if ((driver->md_session_mask == DIAG_CON_ALL) && (j == 0))
break;
}
}
@ -278,7 +278,8 @@ static void pack_rsp_and_send(unsigned char *buf, int len)
* for responses. Make sure we don't miss previous wakeups for
* draining responses when we are in Memory Device Mode.
*/
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE)
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
driver->logging_mode == DIAG_MULTI_MODE)
chk_logging_wakeup();
}
if (driver->rsp_buf_busy) {
@ -346,7 +347,8 @@ static void encode_rsp_and_send(unsigned char *buf, int len)
* for responses. Make sure we don't miss previous wakeups for
* draining responses when we are in Memory Device Mode.
*/
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE)
if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
driver->logging_mode == DIAG_MULTI_MODE)
chk_logging_wakeup();
}
@ -919,8 +921,13 @@ int diag_process_apps_pkt(unsigned char *buf, int len,
if (MD_PERIPHERAL_MASK(reg_item->proc) &
info->peripheral_mask)
write_len = diag_send_data(reg_item, buf, len);
} else
} else {
if (MD_PERIPHERAL_MASK(reg_item->proc) &
driver->logging_mask)
diag_send_error_rsp(buf, len);
else
write_len = diag_send_data(reg_item, buf, len);
}
mutex_unlock(&driver->cmd_reg_mutex);
return write_len;
}
@ -1228,10 +1235,9 @@ static int diagfwd_mux_close(int id, int mode)
return -EINVAL;
}
if ((mode == DIAG_USB_MODE &&
driver->logging_mode == DIAG_MEMORY_DEVICE_MODE) ||
(mode == DIAG_MEMORY_DEVICE_MODE &&
driver->logging_mode == DIAG_USB_MODE)) {
if ((driver->logging_mode == DIAG_MULTI_MODE &&
driver->md_session_mode == DIAG_MD_NONE) ||
(driver->md_session_mode == DIAG_MD_PERIPHERAL)) {
/*
* In this case the channel must not be closed. This case
* indicates that the USB is removed but there is a client