lkml.org 
[lkml]   [2022]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 6.0 277/862] wifi: mt76: mt7921u: fix race issue between reset and suspend/resume
    Date
    From: Sean Wang <sean.wang@mediatek.com>

    [ Upstream commit 86f15d043ba7f13211d5c3e41961c3381fb12880 ]

    It is unexpected that the reset work is running simultaneously with
    the suspend or resume context and it is possible that reset work is still
    running even after mt7921 is suspended if we don't fix the race issue.

    Thus, the suspend procedure should be waiting until the reset is completed
    at the beginning and ignore the subsequent the reset requests.

    In case there is an error that happens during either suspend or resume
    handler, we will schedule a reset task to recover the error before
    returning the error code to ensure we can immediately fix the error there.

    Fixes: df3e4143ba8a ("mt76: mt7921u: add suspend/resume support")
    Co-developed-by: YN Chen <YN.Chen@mediatek.com>
    Signed-off-by: YN Chen <YN.Chen@mediatek.com>
    Signed-off-by: Sean Wang <sean.wang@mediatek.com>
    Signed-off-by: Felix Fietkau <nbd@nbd.name>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    .../net/wireless/mediatek/mt76/mt7921/usb.c | 28 ++++++++++++++++---
    1 file changed, 24 insertions(+), 4 deletions(-)

    diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
    index dd3b8884e162..613d5cefffc7 100644
    --- a/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
    +++ b/drivers/net/wireless/mediatek/mt76/mt7921/usb.c
    @@ -300,11 +300,15 @@ static void mt7921u_disconnect(struct usb_interface *usb_intf)
    static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
    {
    struct mt7921_dev *dev = usb_get_intfdata(intf);
    + struct mt76_connac_pm *pm = &dev->pm;
    int err;

    + pm->suspended = true;
    + flush_work(&dev->reset_work);
    +
    err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, true);
    if (err)
    - return err;
    + goto failed;

    mt76u_stop_rx(&dev->mt76);
    mt76u_stop_tx(&dev->mt76);
    @@ -312,11 +316,20 @@ static int mt7921u_suspend(struct usb_interface *intf, pm_message_t state)
    set_bit(MT76_STATE_SUSPEND, &dev->mphy.state);

    return 0;
    +
    +failed:
    + pm->suspended = false;
    +
    + if (err < 0)
    + mt7921_reset(&dev->mt76);
    +
    + return err;
    }

    static int mt7921u_resume(struct usb_interface *intf)
    {
    struct mt7921_dev *dev = usb_get_intfdata(intf);
    + struct mt76_connac_pm *pm = &dev->pm;
    bool reinit = true;
    int err, i;

    @@ -338,16 +351,23 @@ static int mt7921u_resume(struct usb_interface *intf)
    if (reinit || mt7921_dma_need_reinit(dev)) {
    err = mt7921u_dma_init(dev, true);
    if (err)
    - return err;
    + goto failed;
    }

    clear_bit(MT76_STATE_SUSPEND, &dev->mphy.state);

    err = mt76u_resume_rx(&dev->mt76);
    if (err < 0)
    - return err;
    + goto failed;
    +
    + err = mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
    +failed:
    + pm->suspended = false;
    +
    + if (err < 0)
    + mt7921_reset(&dev->mt76);

    - return mt76_connac_mcu_set_hif_suspend(&dev->mt76, false);
    + return err;
    }
    #endif /* CONFIG_PM */

    --
    2.35.1


    \
     
     \ /
      Last update: 2022-10-19 15:58    [W:2.926 / U:1.332 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site