summaryrefslogtreecommitdiffstats
path: root/drivers/usb/mtu3
diff options
context:
space:
mode:
authorChunfeng Yun <chunfeng.yun@mediatek.com>2021-12-18 10:57:47 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-12-21 09:05:44 +0100
commita7aae769ca626819a7f9f078ebdc69a8a1b00c81 (patch)
tree602a8f6ab6e97a5192df7f8159ee92d53e4e0f7e /drivers/usb/mtu3
parentusb: mtu3: fix interval value for intr and isoc (diff)
downloadlinux-a7aae769ca626819a7f9f078ebdc69a8a1b00c81.tar.xz
linux-a7aae769ca626819a7f9f078ebdc69a8a1b00c81.zip
usb: mtu3: add memory barrier before set GPD's HWO
There is a seldom issue that the controller access invalid address and trigger devapc or emimpu violation. That is due to memory access is out of order and cause gpd data is not correct. Add mb() to prohibit compiler or cpu from reordering to make sure GPD is fully written before setting its HWO. Fixes: 48e0d3735aa5 ("usb: mtu3: supports new QMU format") Cc: stable@vger.kernel.org Reported-by: Eddie Hung <eddie.hung@mediatek.com> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> Link: https://lore.kernel.org/r/20211218095749.6250-2-chunfeng.yun@mediatek.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/mtu3')
-rw-r--r--drivers/usb/mtu3/mtu3_qmu.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c
index 3f414f91b589..2ea3157ddb6e 100644
--- a/drivers/usb/mtu3/mtu3_qmu.c
+++ b/drivers/usb/mtu3/mtu3_qmu.c
@@ -273,6 +273,8 @@ static int mtu3_prepare_tx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq)
gpd->dw3_info |= cpu_to_le32(GPD_EXT_FLAG_ZLP);
}
+ /* prevent reorder, make sure GPD's HWO is set last */
+ mb();
gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO);
mreq->gpd = gpd;
@@ -306,6 +308,8 @@ static int mtu3_prepare_rx_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq)
gpd->next_gpd = cpu_to_le32(lower_32_bits(enq_dma));
ext_addr |= GPD_EXT_NGP(mtu, upper_32_bits(enq_dma));
gpd->dw3_info = cpu_to_le32(ext_addr);
+ /* prevent reorder, make sure GPD's HWO is set last */
+ mb();
gpd->dw0_info |= cpu_to_le32(GPD_FLAGS_IOC | GPD_FLAGS_HWO);
mreq->gpd = gpd;
@@ -445,7 +449,8 @@ static void qmu_tx_zlp_error_handler(struct mtu3 *mtu, u8 epnum)
return;
}
mtu3_setbits(mbase, MU3D_EP_TXCR0(mep->epnum), TX_TXPKTRDY);
-
+ /* prevent reorder, make sure GPD's HWO is set last */
+ mb();
/* by pass the current GDP */
gpd_current->dw0_info |= cpu_to_le32(GPD_FLAGS_BPS | GPD_FLAGS_HWO);