diag: Enable graceful transfer of transport

Avoid channel close by setting flags if socket
transport close is invoked after rpmsg transport
has been probed.

Change-Id: I5d94894e05bbbe079a566d9356eb08a6aeac7799
Signed-off-by: Vivek Golani <vgolani@codeaurora.org>
This commit is contained in:
Vivek Golani 2021-01-21 11:43:49 +05:30 committed by Manjunatha Madana
parent 97d292264c
commit 71f3e30f8e
5 changed files with 48 additions and 5 deletions

View File

@ -1345,11 +1345,26 @@ int diagfwd_channel_open(struct diagfwd_info *fwd_info)
int diagfwd_channel_close(struct diagfwd_info *fwd_info)
{
struct diag_rpmsg_info *rpmsg_info = NULL;
struct diag_socket_info *socket_info = NULL;
if (!fwd_info)
return -EIO;
mutex_lock(&driver->diagfwd_channel_mutex[fwd_info->peripheral]);
fwd_info->ch_open = 0;
rpmsg_info = diag_get_rpmsg_info_ptr(fwd_info->type,
fwd_info->peripheral);
socket_info = diag_get_socket_info_ptr(fwd_info->type,
fwd_info->peripheral);
if (rpmsg_info && socket_info && rpmsg_info->probed
&& socket_info->reset_flag) {
mutex_unlock(
&driver->diagfwd_channel_mutex[fwd_info->peripheral]);
return 0;
}
if (fwd_info && fwd_info->c_ops && fwd_info->c_ops->close)
fwd_info->c_ops->close(fwd_info);

View File

@ -678,7 +678,7 @@ static void diag_rpmsg_notify_rx_work_fn(struct work_struct *work)
if (!rpmsg_info->buf1 && !rpmsg_info->buf2) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"dropping data for %s len %d\n",
"retry data send for %s len %d\n",
rpmsg_info->name, rx_item->rx_buf_size);
err_flag = 1;
goto err_handling;
@ -738,7 +738,7 @@ end:
return;
}
static struct diag_rpmsg_info *get_info_ptr(int type, int peripheral)
struct diag_rpmsg_info *diag_get_rpmsg_info_ptr(int type, int peripheral)
{
if (type == TYPE_CMD)
return &rpmsg_cmd[peripheral];
@ -771,7 +771,7 @@ void rpmsg_mark_buffers_free(uint8_t peripheral, uint8_t type, int buf_num)
return;
}
rpmsg_info = get_info_ptr(type, peripheral);
rpmsg_info = diag_get_rpmsg_info_ptr(type, peripheral);
if (!rpmsg_info)
return;
@ -849,6 +849,7 @@ static void __diag_rpmsg_init(struct diag_rpmsg_info *rpmsg_info)
mutex_lock(&driver->rpmsginfo_mutex[PERI_RPMSG]);
rpmsg_info->hdl = NULL;
rpmsg_info->fwd_ctxt = NULL;
rpmsg_info->probed = 0;
atomic_set(&rpmsg_info->opened, 0);
atomic_set(&rpmsg_info->diag_state, 0);
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
@ -1046,6 +1047,7 @@ static int diag_rpmsg_probe(struct rpmsg_device *rpdev)
rpmsg_info->hdl = rpdev;
atomic_set(&rpmsg_info->opened, 1);
mutex_unlock(&driver->rpmsginfo_mutex[PERI_RPMSG]);
rpmsg_info->probed = 1;
dev_set_drvdata(&rpdev->dev, rpmsg_info);
diagfwd_channel_read(rpmsg_info->fwd_ctxt);
queue_work(rpmsg_info->wq, &rpmsg_info->open_work);
@ -1075,6 +1077,7 @@ static void diag_rpmsg_remove(struct rpmsg_device *rpdev)
mutex_lock(&driver->rpmsginfo_mutex[PERI_RPMSG]);
atomic_set(&rpmsg_info->opened, 0);
mutex_unlock(&driver->rpmsginfo_mutex[PERI_RPMSG]);
rpmsg_info->probed = 0;
queue_work(rpmsg_info->wq, &rpmsg_info->close_work);
}
}

View File

@ -12,6 +12,7 @@ struct diag_rpmsg_info {
uint8_t peripheral;
uint8_t type;
uint8_t inited;
uint8_t probed;
atomic_t opened;
atomic_t diag_state;
uint32_t fifo_size;
@ -44,5 +45,6 @@ void diag_rpmsg_early_exit(void);
void diag_rpmsg_invalidate(void *ctxt, struct diagfwd_info *fwd_ctxt);
int diag_rpmsg_check_state(void *ctxt);
void rpmsg_mark_buffers_free(uint8_t peripheral, uint8_t type, int buf_num);
struct diag_rpmsg_info *diag_get_rpmsg_info_ptr(int type, int peripheral);
#endif

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/slab.h>
@ -244,6 +244,22 @@ struct diag_socket_info socket_dci_cmd[NUM_PERIPHERALS] = {
}
};
struct diag_socket_info *diag_get_socket_info_ptr(int type, int peripheral)
{
if (type == TYPE_CMD)
return &socket_cmd[peripheral];
else if (type == TYPE_CNTL)
return &socket_cntl[peripheral];
else if (type == TYPE_DATA)
return &socket_data[peripheral];
else if (type == TYPE_DCI_CMD)
return &socket_dci_cmd[peripheral];
else if (type == TYPE_DCI)
return &socket_dci[peripheral];
else
return NULL;
}
struct restart_notifier_block {
unsigned int processor;
char *name;
@ -611,7 +627,9 @@ static void socket_read_work_fn(struct work_struct *work)
err = sock_error(info->hdl->sk);
mutex_unlock(&info->socket_info_mutex);
if (unlikely(err == -ENETRESET)) {
info->reset_flag = 1;
socket_close_channel(info);
info->reset_flag = 0;
if (info->port_type == PORT_TYPE_SERVER)
socket_init_work_fn(&info->init_work);
diag_ws_release();
@ -831,7 +849,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
mutex_lock(channel_mutex);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
mutex_unlock(channel_mutex);
info->reset_flag = 1;
socket_close_channel(info);
info->reset_flag = 0;
if (info->port_type == PORT_TYPE_SERVER)
socket_init_work_fn(&info->init_work);
return read_len;
@ -980,6 +1000,7 @@ static void __diag_socket_init(struct diag_socket_info *info)
info->hdl = NULL;
info->fwd_ctxt = NULL;
info->data_ready = 0;
info->reset_flag = 0;
atomic_set(&info->flow_cnt, 0);
spin_lock_init(&info->lock);
strlcpy(wq_name, info->name, sizeof(wq_name));

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/
#ifndef DIAGFWD_SOCKET_H
@ -33,6 +33,7 @@ struct diag_socket_info {
uint8_t type;
uint8_t port_type;
uint8_t inited;
uint8_t reset_flag;
atomic_t opened;
atomic_t diag_state;
uint32_t pkt_len;
@ -68,4 +69,5 @@ int diag_socket_check_state(void *ctxt);
int diag_socket_init(void);
void diag_socket_exit(void);
int diag_socket_init_peripheral(uint8_t peripheral);
struct diag_socket_info *diag_get_socket_info_ptr(int type, int peripheral);
#endif