staging: wfx: ensure HIF request has been sent before polling
authorJérôme Pouiller <jerome.pouiller@silabs.com>
Fri, 25 Feb 2022 11:24:04 +0000 (12:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 25 Feb 2022 13:00:29 +0000 (14:00 +0100)
wfx_bh_request_tx() send HIF request asynchronously through bh_work().
Then the caller will run wfx_bh_poll_irq() to poll the answer.

However it useless to burn CPU cycles for the polling while the request
has yet been sent. Worse, wfx_bh_poll_irq() may get the CPU and prevent
wfx_bh_request_tx() to run. This problem has been observed on mono core
architecture.

This first exchange is correct:
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003000
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003000
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003004
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003004
    kworker/0:1H-40    [000] ....    : io_read: QUEUE: 08 00 09 0c 00 00 00 00 3a 7b 00 30 (12 bytes)
    kworker/0:1H-40    [000] ....    : piggyback: CONTROL: 00003000
    kworker/0:1H-40    [000] ....    : hif_recv: 0:2:CNF_CONFIGURATION: 00 00 00 00 (8 bytes)
    kworker/0:1H-40    [000] ....    : io_read32: CONFIG: 03010200
    kworker/0:1H-40    [000] ....    : bh_stats: IND/REQ/CNF:  0/  0/  1, REQ in progress:  0, WUP: release

... while the following is not:
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003000
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003000
    kworker/u2:1-24    [000] ....    : io_read32: CONTROL: 00003000
    [...loop until timeout...]
    wfx-sdio mmc0:0001:1: time out while polling control register

Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
Link: https://lore.kernel.org/r/20220225112405.355599-10-Jerome.Pouiller@silabs.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/wfx/bh.c

index 4c6ba9c342a6cda522828ec8fc92f24878cd7a95..bcea9d5b119c8e03c9109bc6ce4f7bdd47a05af4 100644 (file)
@@ -295,6 +295,7 @@ void wfx_bh_poll_irq(struct wfx_dev *wdev)
        u32 reg;
 
        WARN(!wdev->poll_irq, "unexpected IRQ polling can mask IRQ");
+       flush_workqueue(system_highpri_wq);
        start = ktime_get();
        for (;;) {
                wfx_control_reg_read(wdev, &reg);