1. 20 1月, 2017 3 次提交
    • B
      mwifiex: pcie: read FROMDEVICE DMA-able memory with READ_ONCE() · fe116788
      Brian Norris 提交于
      In mwifiex_delay_for_sleep_cookie(), we're looping and waiting for the
      PCIe endpoint to write a magic value back to memory, to signal that it
      has finished going to sleep. We're not letting the compiler know that
      this might change underneath our feet though. Let's do that, for good
      hygiene.
      
      I'm not aware of this fixing any concrete problems. I also give no
      guarantee that this loop is actually correct in any other way, but at
      least this looks like an improvement to me.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      fe116788
    • B
      mwifiex: pcie: don't loop/retry interrupt status checks · 5d5ddb5e
      Brian Norris 提交于
      The following sequence occurs when using IEEE power-save on 8997:
      (a) driver sees SLEEP event
      (b) driver issues SLEEP CONFIRM
      (c) driver recevies CMD interrupt; within the interrupt processing loop,
          we do (d) and (e):
      (d) wait for FW sleep cookie (and often time out; it takes a while), FW
          is putting card into low power mode
      (e) re-check PCIE_HOST_INT_STATUS register; quit loop with 0 value
      
      But at (e), no one actually signaled an interrupt (i.e., we didn't check
      adapter->int_status). And what's more, because the card is going to
      sleep, this register read appears to take a very long time in some cases
      -- 3 milliseconds in my case!
      
      Now, I propose that (e) is completely unnecessary. If there were any
      additional interrupts signaled after the start of this loop, then the
      interrupt handler would have set adapter->int_status to non-zero and
      queued more work for the main loop -- and we'd catch it on the next
      iteration of the main loop.
      
      So this patch drops all the looping/re-reading of PCIE_HOST_INT_STATUS,
      which avoids the problematic (and slow) register read in step (e).
      
      Incidentally, this is a very similar issue to the one fixed in commit
      ec815dd2 ("mwifiex: prevent register accesses after host is
      sleeping"), except that the register read is just very slow instead of
      fatal in this case.
      
      Tested on 8997 in both MSI and (though not technically supported at the
      moment) MSI-X mode.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      5d5ddb5e
    • B
      mwifiex: pcie: use posted write to wake up firmware · 062e008a
      Brian Norris 提交于
      Depending on system factors (e.g., the PCIe link PM state), the first
      read to wake up the Wifi firmware can take a long time. There is no
      reason to use a (blocking, non-posted) read at this point, so let's just
      use a write instead. Write vs. read doesn't matter functionality-wise --
      it's just a dummy operation. But let's make sure to re-write with the
      correct "ready" signature, since we check for that in other parts of the
      driver.
      
      This has been shown to decrease the time spent blocking in this function
      on RK3399.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      062e008a
  2. 17 1月, 2017 1 次提交
    • A
      mwifiex: fix uninitialized variable access in pcie_remove · 0e8edb9a
      Arnd Bergmann 提交于
      Checking the firmware status from PCIe register only works
      if the register is available, otherwise we end up with
      random behavior:
      
      drivers/net/wireless/marvell/mwifiex/pcie.c: In function 'mwifiex_pcie_remove':
      drivers/net/wireless/marvell/mwifiex/pcie.c:585:5: error: 'fw_status' may be used uninitialized in this function [-Werror=maybe-uninitialized]
      
      This makes sure we treat the absence of the register as a failure.
      
      Fixes: 045f0c1b ("mwifiex: get rid of global user_rmmod flag")
      Signed-off-by: NArnd Bergmann <arnd@arndb.de>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      0e8edb9a
  3. 12 1月, 2017 8 次提交
  4. 29 11月, 2016 1 次提交
    • B
      mwifiex: pcie: implement timeout loop for FW programming doorbell · 22dde1ed
      Brian Norris 提交于
      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: NBrian Norris <briannorris@chromium.org>
      Acked-by: NAmitkumar Karwar <akarwar@marvell.com>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      22dde1ed
  5. 25 11月, 2016 1 次提交
  6. 19 11月, 2016 11 次提交
  7. 18 11月, 2016 1 次提交
    • B
      mwifiex: don't do unbalanced free()'ing in cleanup_if() · 66b9c182
      Brian Norris 提交于
      The cleanup_if() callback is the inverse of init_if(). We allocate our
      'card' interface structure in the probe() function, but we free it in
      cleanup_if(). That gives a few problems:
      (a) we leak this memory if probe() fails before we reach init_if()
      (b) we can't safely utilize 'card' after cleanup_if() -- namely, in
          remove() or suspend(), both of which might race with the cleanup
          paths in our asynchronous FW initialization path
      
      Solution: just use devm_kzalloc(), which will free this structure
      properly when the device is removed -- and drop the set_drvdata(...,
      NULL), since the driver core does this for us. This also removes the
      temptation to use drvdata == NULL as a hack for checking if the device
      has been "cleaned up."
      
      I *do* leave the set_drvdata(..., NULL) for the hacky SDIO
      mwifiex_recreate_adapter(), since the device core won't be able to clear
      that one for us.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      66b9c182
  8. 09 11月, 2016 2 次提交
    • A
      mwifiex: report error to PCIe for suspend failure · 5190f2e4
      Amitkumar Karwar 提交于
      When host_sleep_config command fails, we should return an error to
      PCIe, instead of continuing (and possibly panicking, when we try to keep
      processing a timed-out ioctl after we return "successfully" from
      suspend).
      Signed-off-by: NAmitkumar Karwar <akarwar@marvell.com>
      Reviewed-by: NBrian Norris <briannorris@chromium.org>
      Tested-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      5190f2e4
    • A
      mwifiex: prevent register accesses after host is sleeping · ec815dd2
      Amitkumar Karwar 提交于
      Following is mwifiex driver-firmware host sleep handshake.
      It involves three threads. suspend handler, interrupt handler, interrupt
      processing in main work queue.
      
      1) Enter suspend handler
      2) Download HS_CFG command
      3) Response from firmware for HS_CFG
      4) Suspend thread waits until handshake completes(i.e hs_activate becomes
         true)
      5) SLEEP from firmware
      6) SLEEP confirm downloaded to firmware.
      7) SLEEP confirm response from firmware
      8) Driver processes SLEEP confirm response and set hs_activate to wake up
      suspend thread
      9) Exit suspend handler
      10) Read sleep cookie in loop and wait until it indicates firmware is
      sleep.
      11) After processing SLEEP confirm response, we are at the end of interrupt
      processing routine. Recheck if there are interrupts received while we were
      processing them.
      
      During suspend-resume stress test, it's been observed that we may end up
      acessing PCIe hardware(in 10 and 11) when PCIe bus is closed which leads
      to a kernel crash.
      
      This patch solves the problem with below changes.
      a) action 10 above can be done before 8
      b) Skip 11 if hs_activated is true. SLEEP confirm response
      is the last interrupt from firmware. No need to recheck for
      pending interrupts.
      c) Add flush_workqueue() in suspend handler.
      Signed-off-by: NAmitkumar Karwar <akarwar@marvell.com>
      Reviewed-by: NBrian Norris <briannorris@chromium.org>
      Tested-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      ec815dd2
  9. 09 9月, 2016 3 次提交
  10. 04 9月, 2016 3 次提交
  11. 19 7月, 2016 3 次提交
  12. 08 7月, 2016 3 次提交