USB: qdss: Fix NULL pointer deference issue during QDSS transfers
There is a chance that usb_qdss_close() and disconnect race each other and it might result in NULL pointer dereference in set_qdss_data_connection() called from usb_qdss_close(). Fix the issue by passing qdss as argument to set_qdss_data_connection() instead of ep. Also remove restart call, which simulates spoof disconnect and connect, when qdss channel is being closed, which is not required anymore as DBM endpoints can be claimed without full USB block reset now. Change-Id: I00642402dbe2e9595d3b3ce760ba4ed2deb2899f Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
This commit is contained in:
parent
783427f7ad
commit
2fb81fbba6
3 changed files with 20 additions and 26 deletions
|
@ -493,11 +493,7 @@ static void usb_qdss_disconnect_work(struct work_struct *work)
|
||||||
NULL,
|
NULL,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
status = set_qdss_data_connection(
|
status = set_qdss_data_connection(qdss, 0);
|
||||||
qdss->gadget,
|
|
||||||
qdss->port.data,
|
|
||||||
qdss->port.data->address,
|
|
||||||
0);
|
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("qdss_disconnect error");
|
pr_err("qdss_disconnect error");
|
||||||
}
|
}
|
||||||
|
@ -543,11 +539,7 @@ static void usb_qdss_connect_work(struct work_struct *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_debug("usb_qdss_connect_work\n");
|
pr_debug("usb_qdss_connect_work\n");
|
||||||
status = set_qdss_data_connection(
|
status = set_qdss_data_connection(qdss, 1);
|
||||||
qdss->gadget,
|
|
||||||
qdss->port.data,
|
|
||||||
qdss->port.data->address,
|
|
||||||
1);
|
|
||||||
if (status) {
|
if (status) {
|
||||||
pr_err("set_qdss_data_connection error(%d)", status);
|
pr_err("set_qdss_data_connection error(%d)", status);
|
||||||
return;
|
return;
|
||||||
|
@ -868,14 +860,9 @@ void usb_qdss_close(struct usb_qdss_ch *ch)
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("%s: uninit_data error\n", __func__);
|
pr_err("%s: uninit_data error\n", __func__);
|
||||||
|
|
||||||
status = set_qdss_data_connection(
|
status = set_qdss_data_connection(qdss, 0);
|
||||||
gadget,
|
|
||||||
qdss->port.data,
|
|
||||||
qdss->port.data->address,
|
|
||||||
0);
|
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("%s:qdss_disconnect error\n", __func__);
|
pr_err("%s:qdss_disconnect error\n", __func__);
|
||||||
usb_gadget_restart(gadget);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(usb_qdss_close);
|
EXPORT_SYMBOL(usb_qdss_close);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012-2017, 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
|
||||||
|
@ -69,6 +69,5 @@ struct usb_qdss_opts {
|
||||||
};
|
};
|
||||||
|
|
||||||
int uninit_data(struct usb_ep *ep);
|
int uninit_data(struct usb_ep *ep);
|
||||||
int set_qdss_data_connection(struct usb_gadget *gadget,
|
int set_qdss_data_connection(struct f_qdss *qdss, int enable);
|
||||||
struct usb_ep *data_ep, u8 data_addr, int enable);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
|
/* Copyright (c) 2012-2017, 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
|
||||||
|
@ -40,19 +40,25 @@ static int alloc_sps_req(struct usb_ep *data_ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_data(struct usb_ep *ep);
|
static int init_data(struct usb_ep *ep);
|
||||||
int set_qdss_data_connection(struct usb_gadget *gadget,
|
int set_qdss_data_connection(struct f_qdss *qdss, int enable)
|
||||||
struct usb_ep *data_ep, u8 data_addr, int enable)
|
|
||||||
{
|
{
|
||||||
enum usb_ctrl usb_bam_type;
|
enum usb_ctrl usb_bam_type;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
int idx;
|
int idx;
|
||||||
struct f_qdss *qdss = data_ep->driver_data;
|
struct usb_qdss_bam_connect_info bam_info;
|
||||||
struct usb_qdss_bam_connect_info bam_info = qdss->bam_info;
|
struct usb_gadget *gadget;
|
||||||
|
|
||||||
pr_debug("set_qdss_data_connection\n");
|
pr_debug("set_qdss_data_connection\n");
|
||||||
|
|
||||||
|
if (!qdss) {
|
||||||
|
pr_err("%s: qdss ptr is NULL\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gadget = qdss->gadget;
|
||||||
usb_bam_type = usb_bam_get_bam_type(gadget->name);
|
usb_bam_type = usb_bam_get_bam_type(gadget->name);
|
||||||
|
|
||||||
|
bam_info = qdss->bam_info;
|
||||||
/* There is only one qdss pipe, so the pipe number can be set to 0 */
|
/* There is only one qdss pipe, so the pipe number can be set to 0 */
|
||||||
idx = usb_bam_get_connection_idx(usb_bam_type, QDSS_P_BAM,
|
idx = usb_bam_get_connection_idx(usb_bam_type, QDSS_P_BAM,
|
||||||
PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE, 0);
|
PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE, 0);
|
||||||
|
@ -67,14 +73,16 @@ int set_qdss_data_connection(struct usb_gadget *gadget,
|
||||||
kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL);
|
kzalloc(sizeof(struct sps_mem_buffer), GFP_KERNEL);
|
||||||
if (!bam_info.data_fifo) {
|
if (!bam_info.data_fifo) {
|
||||||
pr_err("qdss_data_connection: memory alloc failed\n");
|
pr_err("qdss_data_connection: memory alloc failed\n");
|
||||||
|
usb_bam_free_fifos(usb_bam_type, idx);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
get_bam2bam_connection_info(usb_bam_type, idx,
|
get_bam2bam_connection_info(usb_bam_type, idx,
|
||||||
&bam_info.usb_bam_pipe_idx,
|
&bam_info.usb_bam_pipe_idx,
|
||||||
NULL, bam_info.data_fifo, NULL);
|
NULL, bam_info.data_fifo, NULL);
|
||||||
|
|
||||||
alloc_sps_req(data_ep);
|
alloc_sps_req(qdss->port.data);
|
||||||
msm_data_fifo_config(data_ep, bam_info.data_fifo->phys_base,
|
msm_data_fifo_config(qdss->port.data,
|
||||||
|
bam_info.data_fifo->phys_base,
|
||||||
bam_info.data_fifo->size,
|
bam_info.data_fifo->size,
|
||||||
bam_info.usb_bam_pipe_idx);
|
bam_info.usb_bam_pipe_idx);
|
||||||
init_data(qdss->port.data);
|
init_data(qdss->port.data);
|
||||||
|
|
Loading…
Add table
Reference in a new issue