diag: Fix error response during SSR
This patch addresses the scheduling conflicts of control channel removal work by listening to peripheral events. CRs-Fixed: 1081265 Change-Id: Ib9f2448e564c4800535bd80d13c9bda5cc283c3c Signed-off-by: Manoj Prabhu B <bmanoj@codeaurora.org>
This commit is contained in:
parent
e379f786aa
commit
e145621a4a
5 changed files with 125 additions and 3 deletions
|
@ -473,6 +473,7 @@ struct diagchar_dev {
|
||||||
int ref_count;
|
int ref_count;
|
||||||
int mask_clear;
|
int mask_clear;
|
||||||
struct mutex diag_maskclear_mutex;
|
struct mutex diag_maskclear_mutex;
|
||||||
|
struct mutex diag_notifier_mutex;
|
||||||
struct mutex diagchar_mutex;
|
struct mutex diagchar_mutex;
|
||||||
struct mutex diag_file_mutex;
|
struct mutex diag_file_mutex;
|
||||||
wait_queue_head_t wait_q;
|
wait_queue_head_t wait_q;
|
||||||
|
|
|
@ -3400,6 +3400,7 @@ static int __init diagchar_init(void)
|
||||||
mutex_init(&driver->hdlc_disable_mutex);
|
mutex_init(&driver->hdlc_disable_mutex);
|
||||||
mutex_init(&driver->diagchar_mutex);
|
mutex_init(&driver->diagchar_mutex);
|
||||||
mutex_init(&driver->diag_maskclear_mutex);
|
mutex_init(&driver->diag_maskclear_mutex);
|
||||||
|
mutex_init(&driver->diag_notifier_mutex);
|
||||||
mutex_init(&driver->diag_file_mutex);
|
mutex_init(&driver->diag_file_mutex);
|
||||||
mutex_init(&driver->delayed_rsp_mutex);
|
mutex_init(&driver->delayed_rsp_mutex);
|
||||||
mutex_init(&apps_data_mutex);
|
mutex_init(&apps_data_mutex);
|
||||||
|
|
|
@ -358,6 +358,8 @@ static void process_incoming_feature_mask(uint8_t *buf, uint32_t len,
|
||||||
feature_mask_len = FEATURE_MASK_LEN;
|
feature_mask_len = FEATURE_MASK_LEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diag_cmd_remove_reg_by_proc(peripheral);
|
||||||
|
|
||||||
driver->feature[peripheral].rcvd_feature_mask = 1;
|
driver->feature[peripheral].rcvd_feature_mask = 1;
|
||||||
|
|
||||||
for (i = 0; i < feature_mask_len && read_len < len; i++) {
|
for (i = 0; i < feature_mask_len && read_len < len; i++) {
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
#include "diagfwd_socket.h"
|
#include "diagfwd_socket.h"
|
||||||
#include "diag_ipc_logging.h"
|
#include "diag_ipc_logging.h"
|
||||||
|
|
||||||
|
#include <soc/qcom/subsystem_notif.h>
|
||||||
|
#include <soc/qcom/subsystem_restart.h>
|
||||||
|
|
||||||
#define DIAG_SVC_ID 0x1001
|
#define DIAG_SVC_ID 0x1001
|
||||||
|
|
||||||
#define MODEM_INST_BASE 0
|
#define MODEM_INST_BASE 0
|
||||||
|
@ -50,6 +53,7 @@
|
||||||
#define INST_ID_DCI 4
|
#define INST_ID_DCI 4
|
||||||
|
|
||||||
struct diag_cntl_socket_info *cntl_socket;
|
struct diag_cntl_socket_info *cntl_socket;
|
||||||
|
static uint64_t bootup_req[NUM_SOCKET_SUBSYSTEMS];
|
||||||
|
|
||||||
struct diag_socket_info socket_data[NUM_PERIPHERALS] = {
|
struct diag_socket_info socket_data[NUM_PERIPHERALS] = {
|
||||||
{
|
{
|
||||||
|
@ -416,7 +420,7 @@ static void socket_open_client(struct diag_socket_info *info)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
__socket_open_channel(info);
|
__socket_open_channel(info);
|
||||||
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s exiting\n", info->name);
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s opened client\n", info->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void socket_open_server(struct diag_socket_info *info)
|
static void socket_open_server(struct diag_socket_info *info)
|
||||||
|
@ -492,6 +496,13 @@ static void __socket_close_channel(struct diag_socket_info *info)
|
||||||
if (!atomic_read(&info->opened))
|
if (!atomic_read(&info->opened))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (bootup_req[info->peripheral] == PEPIPHERAL_SSR_UP) {
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: %s is up, stopping cleanup: bootup_req = %d\n",
|
||||||
|
info->name, (int)bootup_req[info->peripheral]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc));
|
memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc));
|
||||||
diagfwd_channel_close(info->fwd_ctxt);
|
diagfwd_channel_close(info->fwd_ctxt);
|
||||||
|
|
||||||
|
@ -610,7 +621,9 @@ static int cntl_socket_process_msg_client(uint32_t cmd, uint32_t node_id,
|
||||||
case CNTL_CMD_REMOVE_CLIENT:
|
case CNTL_CMD_REMOVE_CLIENT:
|
||||||
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s received remove client\n",
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s received remove client\n",
|
||||||
info->name);
|
info->name);
|
||||||
|
mutex_lock(&driver->diag_notifier_mutex);
|
||||||
socket_close_channel(info);
|
socket_close_channel(info);
|
||||||
|
mutex_unlock(&driver->diag_notifier_mutex);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -619,6 +632,25 @@ static int cntl_socket_process_msg_client(uint32_t cmd, uint32_t node_id,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int restart_notifier_cb(struct notifier_block *this,
|
||||||
|
unsigned long code,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
struct restart_notifier_block {
|
||||||
|
unsigned processor;
|
||||||
|
char *name;
|
||||||
|
struct notifier_block nb;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct restart_notifier_block restart_notifiers[] = {
|
||||||
|
{SOCKET_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
|
||||||
|
{SOCKET_ADSP, "adsp", .nb.notifier_call = restart_notifier_cb},
|
||||||
|
{SOCKET_WCNSS, "wcnss", .nb.notifier_call = restart_notifier_cb},
|
||||||
|
{SOCKET_SLPI, "slpi", .nb.notifier_call = restart_notifier_cb},
|
||||||
|
{SOCKET_CDSP, "cdsp", .nb.notifier_call = restart_notifier_cb},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void cntl_socket_read_work_fn(struct work_struct *work)
|
static void cntl_socket_read_work_fn(struct work_struct *work)
|
||||||
{
|
{
|
||||||
union cntl_port_msg msg;
|
union cntl_port_msg msg;
|
||||||
|
@ -626,7 +658,6 @@ static void cntl_socket_read_work_fn(struct work_struct *work)
|
||||||
struct kvec iov = { 0 };
|
struct kvec iov = { 0 };
|
||||||
struct msghdr read_msg = { 0 };
|
struct msghdr read_msg = { 0 };
|
||||||
|
|
||||||
|
|
||||||
if (!cntl_socket)
|
if (!cntl_socket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -845,8 +876,11 @@ static int __diag_cntl_socket_init(void)
|
||||||
int diag_socket_init(void)
|
int diag_socket_init(void)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
int i;
|
||||||
int peripheral = 0;
|
int peripheral = 0;
|
||||||
|
void *handle;
|
||||||
struct diag_socket_info *info = NULL;
|
struct diag_socket_info *info = NULL;
|
||||||
|
struct restart_notifier_block *nb;
|
||||||
|
|
||||||
for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
|
for (peripheral = 0; peripheral < NUM_PERIPHERALS; peripheral++) {
|
||||||
info = &socket_cntl[peripheral];
|
info = &socket_cntl[peripheral];
|
||||||
|
@ -867,6 +901,17 @@ int diag_socket_init(void)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
|
||||||
|
nb = &restart_notifiers[i];
|
||||||
|
if (nb) {
|
||||||
|
handle = subsys_notif_register_notifier(nb->name,
|
||||||
|
&nb->nb);
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"%s: registering notifier for '%s', handle=%p\n",
|
||||||
|
__func__, nb->name, handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
register_ipcrtr_af_init_notifier(&socket_notify);
|
register_ipcrtr_af_init_notifier(&socket_notify);
|
||||||
fail:
|
fail:
|
||||||
return err;
|
return err;
|
||||||
|
@ -902,6 +947,65 @@ static int socket_ready_notify(struct notifier_block *nb,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int restart_notifier_cb(struct notifier_block *this, unsigned long code,
|
||||||
|
void *_cmd)
|
||||||
|
{
|
||||||
|
struct restart_notifier_block *notifier;
|
||||||
|
|
||||||
|
notifier = container_of(this,
|
||||||
|
struct restart_notifier_block, nb);
|
||||||
|
if (!notifier) {
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: %s: invalid notifier block\n", __func__);
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&driver->diag_notifier_mutex);
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"%s: ssr for processor %d ('%s')\n",
|
||||||
|
__func__, notifier->processor, notifier->name);
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
|
||||||
|
case SUBSYS_BEFORE_SHUTDOWN:
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: %s: SUBSYS_BEFORE_SHUTDOWN\n", __func__);
|
||||||
|
bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUBSYS_AFTER_SHUTDOWN:
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: %s: SUBSYS_AFTER_SHUTDOWN\n", __func__);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUBSYS_BEFORE_POWERUP:
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: %s: SUBSYS_BEFORE_POWERUP\n", __func__);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUBSYS_AFTER_POWERUP:
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: %s: SUBSYS_AFTER_POWERUP\n", __func__);
|
||||||
|
if (!bootup_req[notifier->processor]) {
|
||||||
|
bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bootup_req[notifier->processor] = PEPIPHERAL_SSR_UP;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: code: %lu\n", code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mutex_unlock(&driver->diag_notifier_mutex);
|
||||||
|
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
|
||||||
|
"diag: bootup_req[%s] = %d\n",
|
||||||
|
notifier->name, (int)bootup_req[notifier->processor]);
|
||||||
|
|
||||||
|
return NOTIFY_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
int diag_socket_init_peripheral(uint8_t peripheral)
|
int diag_socket_init_peripheral(uint8_t peripheral)
|
||||||
{
|
{
|
||||||
struct diag_socket_info *info = NULL;
|
struct diag_socket_info *info = NULL;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
@ -24,10 +24,24 @@
|
||||||
#define PORT_TYPE_SERVER 0
|
#define PORT_TYPE_SERVER 0
|
||||||
#define PORT_TYPE_CLIENT 1
|
#define PORT_TYPE_CLIENT 1
|
||||||
|
|
||||||
|
#define PEPIPHERAL_AFTER_BOOT 0
|
||||||
|
#define PEPIPHERAL_SSR_DOWN 1
|
||||||
|
#define PEPIPHERAL_SSR_UP 2
|
||||||
|
|
||||||
#define CNTL_CMD_NEW_SERVER 4
|
#define CNTL_CMD_NEW_SERVER 4
|
||||||
#define CNTL_CMD_REMOVE_SERVER 5
|
#define CNTL_CMD_REMOVE_SERVER 5
|
||||||
#define CNTL_CMD_REMOVE_CLIENT 6
|
#define CNTL_CMD_REMOVE_CLIENT 6
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SOCKET_MODEM,
|
||||||
|
SOCKET_ADSP,
|
||||||
|
SOCKET_WCNSS,
|
||||||
|
SOCKET_SLPI,
|
||||||
|
SOCKET_CDSP,
|
||||||
|
SOCKET_APPS,
|
||||||
|
NUM_SOCKET_SUBSYSTEMS,
|
||||||
|
};
|
||||||
|
|
||||||
struct diag_socket_info {
|
struct diag_socket_info {
|
||||||
uint8_t peripheral;
|
uint8_t peripheral;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
Loading…
Add table
Reference in a new issue