diff mbox series

[3/7] usb: mtu3: fix KE at qmu transfer done irq handler

Message ID 20230403025230.25035-3-chunfeng.yun@mediatek.com (mailing list archive)
State Superseded
Headers show
Series [1/7] usb: mtu3: give back request when rx error happens | expand

Commit Message

Chunfeng Yun April 3, 2023, 2:52 a.m. UTC
When handle qmu transfer irq, it will unlock @mtu->lock before give back
request, if another thread hanlde disconnect event at the same time, and
try to disable ep, it may lock @mtu->lock and free qmu ring, then qmu
irq hanlder may get a NULL gpd, avoid the KE by checking gpd's value before
handling it.

e.g.
qmu done irq on cpu0                 thread running on cpu1

qmu_done_tx()
  handle gpd [0]
    mtu3_requ_complete()        mtu3_gadget_ep_disable()
      unlock @mtu->lock
        give back request         lock @mtu->lock
                                    mtu3_ep_disable()
                                      mtu3_gpd_ring_free()
                                   unlock @mtu->lock
      lock @mtu->lock
    get next gpd [1]

[1]: goto [0] to handle next gpd, and next gpd may be NULL.

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
 drivers/usb/mtu3/mtu3_qmu.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

AngeloGioacchino Del Regno April 3, 2023, 12:31 p.m. UTC | #1
Il 03/04/23 04:52, Chunfeng Yun ha scritto:
> When handle qmu transfer irq, it will unlock @mtu->lock before give back
> request, if another thread hanlde disconnect event at the same time, and
> try to disable ep, it may lock @mtu->lock and free qmu ring, then qmu
> irq hanlder may get a NULL gpd, avoid the KE by checking gpd's value before

KE == Kernel Error? I think you wanted to say KP == Kernel Panic instead.

Also, s/hanlder/handler/g.

> handling it.
> 
> e.g.
> qmu done irq on cpu0                 thread running on cpu1
> 
> qmu_done_tx()
>    handle gpd [0]
>      mtu3_requ_complete()        mtu3_gadget_ep_disable()
>        unlock @mtu->lock
>          give back request         lock @mtu->lock
>                                      mtu3_ep_disable()
>                                        mtu3_gpd_ring_free()
>                                     unlock @mtu->lock
>        lock @mtu->lock
>      get next gpd [1]
> 
> [1]: goto [0] to handle next gpd, and next gpd may be NULL.
 >
 > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>

This is a fix and needs a Fixes tag.

Regards,
Angelo
Chunfeng Yun April 7, 2023, 7:59 a.m. UTC | #2
On Mon, 2023-04-03 at 14:31 +0200, AngeloGioacchino Del Regno wrote:
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
> 
> 
> Il 03/04/23 04:52, Chunfeng Yun ha scritto:
> > When handle qmu transfer irq, it will unlock @mtu->lock before give
> > back
> > request, if another thread hanlde disconnect event at the same
> > time, and
> > try to disable ep, it may lock @mtu->lock and free qmu ring, then
> > qmu
> > irq hanlder may get a NULL gpd, avoid the KE by checking gpd's
> > value before
> 
> KE == Kernel Error? I think you wanted to say KP == Kernel Panic
> instead.
> 
> Also, s/hanlder/handler/g.
Ok, will modify it
> 
> > handling it.
> > 
> > e.g.
> > qmu done irq on cpu0                 thread running on cpu1
> > 
> > qmu_done_tx()
> >    handle gpd [0]
> >      mtu3_requ_complete()        mtu3_gadget_ep_disable()
> >        unlock @mtu->lock
> >          give back request         lock @mtu->lock
> >                                      mtu3_ep_disable()
> >                                        mtu3_gpd_ring_free()
> >                                     unlock @mtu->lock
> >        lock @mtu->lock
> >      get next gpd [1]
> > 
> > [1]: goto [0] to handle next gpd, and next gpd may be NULL.
> 
>  >
>  > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> 
> This is a fix and needs a Fixes tag.
I usually add Fixes tag when the issue introduced by a patch except the
original one when the driver applied.

Thanks a lot

> 
> Regards,
> Angelo
> 
>
AngeloGioacchino Del Regno April 7, 2023, 9:08 a.m. UTC | #3
Il 07/04/23 09:59, Chunfeng Yun (云春峰) ha scritto:
> On Mon, 2023-04-03 at 14:31 +0200, AngeloGioacchino Del Regno wrote:
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>
>>
>> Il 03/04/23 04:52, Chunfeng Yun ha scritto:
>>> When handle qmu transfer irq, it will unlock @mtu->lock before give
>>> back
>>> request, if another thread hanlde disconnect event at the same
>>> time, and
>>> try to disable ep, it may lock @mtu->lock and free qmu ring, then
>>> qmu
>>> irq hanlder may get a NULL gpd, avoid the KE by checking gpd's
>>> value before
>>
>> KE == Kernel Error? I think you wanted to say KP == Kernel Panic
>> instead.
>>
>> Also, s/hanlder/handler/g.
> Ok, will modify it
>>
>>> handling it.
>>>
>>> e.g.
>>> qmu done irq on cpu0                 thread running on cpu1
>>>
>>> qmu_done_tx()
>>>     handle gpd [0]
>>>       mtu3_requ_complete()        mtu3_gadget_ep_disable()
>>>         unlock @mtu->lock
>>>           give back request         lock @mtu->lock
>>>                                       mtu3_ep_disable()
>>>                                         mtu3_gpd_ring_free()
>>>                                      unlock @mtu->lock
>>>         lock @mtu->lock
>>>       get next gpd [1]
>>>
>>> [1]: goto [0] to handle next gpd, and next gpd may be NULL.
>>
>>   >
>>   > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
>>
>> This is a fix and needs a Fixes tag.
> I usually add Fixes tag when the issue introduced by a patch except the
> original one when the driver applied.
> 

If this patch is a fix for the "original driver", you shall still add a
Fixes tag which advertises that this fixes the first commit, so the driver
was broken from the very beginning.

Thanks,
Angelo.
diff mbox series

Patch

diff --git a/drivers/usb/mtu3/mtu3_qmu.c b/drivers/usb/mtu3/mtu3_qmu.c
index 66639f602a9d..3146a112141f 100644
--- a/drivers/usb/mtu3/mtu3_qmu.c
+++ b/drivers/usb/mtu3/mtu3_qmu.c
@@ -210,6 +210,7 @@  static struct qmu_gpd *advance_enq_gpd(struct mtu3_gpd_ring *ring)
 	return ring->enqueue;
 }
 
+/* @dequeue may be NULL if ring is unallocated or freed */
 static struct qmu_gpd *advance_deq_gpd(struct mtu3_gpd_ring *ring)
 {
 	if (ring->dequeue < ring->end)
@@ -524,7 +525,7 @@  static void qmu_done_tx(struct mtu3 *mtu, u8 epnum)
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
 
-	while (gpd != gpd_current && !GET_GPD_HWO(gpd)) {
+	while (gpd && gpd != gpd_current && !GET_GPD_HWO(gpd)) {
 
 		mreq = next_request(mep);
 
@@ -563,7 +564,7 @@  static void qmu_done_rx(struct mtu3 *mtu, u8 epnum)
 	dev_dbg(mtu->dev, "%s EP%d, last=%p, current=%p, enq=%p\n",
 		__func__, epnum, gpd, gpd_current, ring->enqueue);
 
-	while (gpd != gpd_current && !GET_GPD_HWO(gpd)) {
+	while (gpd && gpd != gpd_current && !GET_GPD_HWO(gpd)) {
 
 		mreq = next_request(mep);