Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mwifiex: pcie: implement timeout loop for FW programming doorbell

Marvell Wifi PCIe modules don't always behave nicely for PCIe power
management when their firmware hasn't been loaded, particularly after
suspending the PCIe link one or more times. When this happens, we might
end up spinning forever in this status-polling tight loop. Let's make
this less tight by adding a timeout and by sleeping a bit in between
reads, as we do with the other similar loops.

This prevents us from hogging a CPU even in such pathological cases, and
allows the FW initialization to just fail gracefully instead.

I chose the same polling parameters as the earlier loop in this
function, and empirically, I found that this loop never makes it more
than about 12 cycles in a sane FW init sequence. I had no official
information on the actual intended latency for this portion of the
download.

Signed-off-by: Brian Norris <briannorris@chromium.org>
Acked-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Brian Norris and committed by
Kalle Valo
22dde1ed 4133828c

+13 -3
+13 -3
drivers/net/wireless/marvell/mwifiex/pcie.c
··· 2051 2051 } 2052 2052 2053 2053 /* Wait for the command done interrupt */ 2054 - do { 2054 + for (tries = 0; tries < MAX_POLL_TRIES; tries++) { 2055 2055 if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, 2056 2056 &ireg_intr)) { 2057 2057 mwifiex_dbg(adapter, ERROR, ··· 2063 2063 ret = -1; 2064 2064 goto done; 2065 2065 } 2066 - } while ((ireg_intr & CPU_INTR_DOOR_BELL) == 2067 - CPU_INTR_DOOR_BELL); 2066 + if (!(ireg_intr & CPU_INTR_DOOR_BELL)) 2067 + break; 2068 + usleep_range(10, 20); 2069 + } 2070 + if (ireg_intr & CPU_INTR_DOOR_BELL) { 2071 + mwifiex_dbg(adapter, ERROR, "%s: Card failed to ACK download\n", 2072 + __func__); 2073 + mwifiex_unmap_pci_memory(adapter, skb, 2074 + PCI_DMA_TODEVICE); 2075 + ret = -1; 2076 + goto done; 2077 + } 2068 2078 2069 2079 mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); 2070 2080