From: Jack Pham Date: Wed, 7 Jun 2017 05:30:47 +0000 (-0700) Subject: usb: pdphy: Prevent sending when message is just received X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=71c2e3fc4ffa5aa629f3afd9d971b2e1f521255f;p=sagit-ice-cold%2Fkernel_xiaomi_msm8998.git usb: pdphy: Prevent sending when message is just received Prevent pd_phy_write() from sending a TX message if an RX message IRQ is being handled, or if the RX_TOKEN is set (indicating a message has just arrived) by returning -EBUSY to let the upper layer gracefully abort. This helps in cases (such as compliance testing) in which VDM messages are received very quickly after one another and the protocol layer needs to first handle the incoming message. Change-Id: I3e26d7ff062ff7f51b6c66ab8d078b05749f808a Signed-off-by: Jack Pham --- diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c index 588af94db6cd..22c03ace78e7 100644 --- a/drivers/usb/pd/qpnp-pdphy.c +++ b/drivers/usb/pd/qpnp-pdphy.c @@ -108,6 +108,7 @@ struct usb_pdphy { int tx_status; u8 frame_filter_val; bool in_test_data_mode; + bool rx_busy; enum data_role data_role; enum power_role power_role; @@ -492,6 +493,12 @@ int pd_phy_write(u16 hdr, const u8 *data, size_t data_len, return -EINVAL; } + ret = pdphy_reg_read(pdphy, &val, USB_PDPHY_RX_ACKNOWLEDGE, 1); + if (ret || val || pdphy->rx_busy) { + dev_err(pdphy->dev, "%s: RX message pending\n", __func__); + return -EBUSY; + } + pdphy->tx_status = -EINPROGRESS; /* write 2 byte SOP message header */ @@ -664,6 +671,15 @@ static int pd_phy_bist_mode(u8 bist_mode) BIST_MODE_MASK | BIST_ENABLE, bist_mode | BIST_ENABLE); } +static irqreturn_t pdphy_msg_rx_irq(int irq, void *data) +{ + struct usb_pdphy *pdphy = data; + + pdphy->rx_busy = true; + + return IRQ_WAKE_THREAD; +} + static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) { u8 size, rx_status, frame_type; @@ -720,6 +736,7 @@ static irqreturn_t pdphy_msg_rx_irq_thread(int irq, void *data) false); pdphy->rx_bytes += size + 1; done: + pdphy->rx_busy = false; return IRQ_HANDLED; } @@ -805,7 +822,7 @@ static int pdphy_probe(struct platform_device *pdev) return ret; ret = pdphy_request_irq(pdphy, pdev->dev.of_node, - &pdphy->msg_rx_irq, "msg-rx", NULL, + &pdphy->msg_rx_irq, "msg-rx", pdphy_msg_rx_irq, pdphy_msg_rx_irq_thread, (IRQF_TRIGGER_RISING | IRQF_ONESHOT)); if (ret < 0) return ret;