USB: u_data_ipa: Fix NULL pointer dereference before starting RX/TX
If disconnect happens before connect_work done, there is a chance that port_usb might be NULL before calling ipa_data_start_rx_tx(). This could cause crash if it happens. Fix it by taking to local variable under spin lock protection and check later before calling ipa_data_start_rx_tx() for queuing RX/TX requests to USB HW. Change-Id: I82d74e34bb4d29eac225d31dac67bf5d5bc39a79 Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
This commit is contained in:
parent
3a7e752617
commit
273dcf1abb
1 changed files with 23 additions and 8 deletions
|
@ -95,6 +95,7 @@ static void ipa_data_start_endless_xfer(struct ipa_data_ch_info *port, bool in)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int status;
|
int status;
|
||||||
|
struct usb_ep *ep;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->port_lock, flags);
|
spin_lock_irqsave(&port->port_lock, flags);
|
||||||
if (!port->port_usb || (in && !port->tx_req)
|
if (!port->port_usb || (in && !port->tx_req)
|
||||||
|
@ -103,18 +104,22 @@ static void ipa_data_start_endless_xfer(struct ipa_data_ch_info *port, bool in)
|
||||||
pr_err("%s(): port_usb/req is NULL.\n", __func__);
|
pr_err("%s(): port_usb/req is NULL.\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in)
|
||||||
|
ep = port->port_usb->in;
|
||||||
|
else
|
||||||
|
ep = port->port_usb->out;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
pr_debug("%s: enqueue endless TX_REQ(IN)\n", __func__);
|
pr_debug("%s: enqueue endless TX_REQ(IN)\n", __func__);
|
||||||
status = usb_ep_queue(port->port_usb->in,
|
status = usb_ep_queue(ep, port->tx_req, GFP_ATOMIC);
|
||||||
port->tx_req, GFP_ATOMIC);
|
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("error enqueuing endless TX_REQ, %d\n", status);
|
pr_err("error enqueuing endless TX_REQ, %d\n", status);
|
||||||
} else {
|
} else {
|
||||||
pr_debug("%s: enqueue endless RX_REQ(OUT)\n", __func__);
|
pr_debug("%s: enqueue endless RX_REQ(OUT)\n", __func__);
|
||||||
status = usb_ep_queue(port->port_usb->out,
|
status = usb_ep_queue(ep, port->rx_req, GFP_ATOMIC);
|
||||||
port->rx_req, GFP_ATOMIC);
|
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("error enqueuing endless RX_REQ, %d\n", status);
|
pr_err("error enqueuing endless RX_REQ, %d\n", status);
|
||||||
}
|
}
|
||||||
|
@ -132,6 +137,7 @@ static void ipa_data_stop_endless_xfer(struct ipa_data_ch_info *port, bool in)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int status;
|
int status;
|
||||||
|
struct usb_ep *ep;
|
||||||
|
|
||||||
spin_lock_irqsave(&port->port_lock, flags);
|
spin_lock_irqsave(&port->port_lock, flags);
|
||||||
if (!port->port_usb || (in && !port->tx_req)
|
if (!port->port_usb || (in && !port->tx_req)
|
||||||
|
@ -140,16 +146,22 @@ static void ipa_data_stop_endless_xfer(struct ipa_data_ch_info *port, bool in)
|
||||||
pr_err("%s(): port_usb/req is NULL.\n", __func__);
|
pr_err("%s(): port_usb/req is NULL.\n", __func__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (in)
|
||||||
|
ep = port->port_usb->in;
|
||||||
|
else
|
||||||
|
ep = port->port_usb->out;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||||
|
|
||||||
if (in) {
|
if (in) {
|
||||||
pr_debug("%s: dequeue endless TX_REQ(IN)\n", __func__);
|
pr_debug("%s: dequeue endless TX_REQ(IN)\n", __func__);
|
||||||
status = usb_ep_dequeue(port->port_usb->in, port->tx_req);
|
status = usb_ep_dequeue(ep, port->tx_req);
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("error dequeueing endless TX_REQ, %d\n", status);
|
pr_err("error dequeueing endless TX_REQ, %d\n", status);
|
||||||
} else {
|
} else {
|
||||||
pr_debug("%s: dequeue endless RX_REQ(OUT)\n", __func__);
|
pr_debug("%s: dequeue endless RX_REQ(OUT)\n", __func__);
|
||||||
status = usb_ep_dequeue(port->port_usb->out, port->rx_req);
|
status = usb_ep_dequeue(ep, port->rx_req);
|
||||||
if (status)
|
if (status)
|
||||||
pr_err("error dequeueing endless RX_REQ, %d\n", status);
|
pr_err("error dequeueing endless RX_REQ, %d\n", status);
|
||||||
}
|
}
|
||||||
|
@ -164,6 +176,7 @@ void ipa_data_start_rx_tx(enum ipa_func_type func)
|
||||||
{
|
{
|
||||||
struct ipa_data_ch_info *port;
|
struct ipa_data_ch_info *port;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct usb_ep *epin, *epout;
|
||||||
|
|
||||||
pr_debug("%s: Triggered: starting tx, rx", __func__);
|
pr_debug("%s: Triggered: starting tx, rx", __func__);
|
||||||
/* queue in & out requests */
|
/* queue in & out requests */
|
||||||
|
@ -194,15 +207,17 @@ void ipa_data_start_rx_tx(enum ipa_func_type func)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
epout = port->port_usb->out;
|
||||||
|
epin = port->port_usb->in;
|
||||||
spin_unlock_irqrestore(&port->port_lock, flags);
|
spin_unlock_irqrestore(&port->port_lock, flags);
|
||||||
|
|
||||||
/* queue in & out requests */
|
/* queue in & out requests */
|
||||||
pr_debug("%s: Starting rx", __func__);
|
pr_debug("%s: Starting rx", __func__);
|
||||||
if (port->port_usb->out)
|
if (epout)
|
||||||
ipa_data_start_endless_xfer(port, false);
|
ipa_data_start_endless_xfer(port, false);
|
||||||
|
|
||||||
pr_debug("%s: Starting tx", __func__);
|
pr_debug("%s: Starting tx", __func__);
|
||||||
if (port->port_usb->in)
|
if (epin)
|
||||||
ipa_data_start_endless_xfer(port, true);
|
ipa_data_start_endless_xfer(port, true);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Add table
Reference in a new issue