1. 19 5月, 2017 12 次提交
    • B
      mwifiex: pcie: stop setting/clearing 'surprise_removed' · 68efd038
      Brian Norris 提交于
      These are already handled by mwifiex_shutdown_sw() and
      mwifiex_reinit_sw(). Ideally, we'll kill the flag entirely eventually,
      as I suspect it breeds race conditions.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      68efd038
    • B
      mwifiex: pcie: remove useless pdev check · fa4651e1
      Brian Norris 提交于
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      fa4651e1
    • B
      mwifiex: 11h: drop unnecessary check for '!priv' · 7ade530e
      Brian Norris 提交于
      These pointers are retrieved via container_of(). There's no way they are
      NULL.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      7ade530e
    • B
      mwifiex: remove redundant 'adapter' check in mwifiex_adapter_cleanup · 71708627
      Brian Norris 提交于
      We're using 'adapter' right before calling this. Stop being
      unnecessarily paranoid.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      71708627
    • B
      mwifiex: remove useless 'mwifiex_lock' · bc69ca39
      Brian Norris 提交于
      If mwifiex_shutdown_drv() is racing with another mwifiex_shutdown_drv(),
      we *really* have problems. Kill the lock.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      bc69ca39
    • B
      mwifiex: don't leak stashed beacon buffer on reset · 6eb2d002
      Brian Norris 提交于
      When removing or resetting an mwifiex device, we don't remember to free
      the saved beacon buffer. Use the (somewhat misleadingly-named)
      mwifiex_free_priv() helper to handle this.
      
      Noticed by kmemleak during tests:
      
      echo 1 > /sys/bus/pci/devices/.../reset
      
      unreferenced object 0xffffffc09d034a00 (size 256):
      ...
        backtrace:
          [<ffffffc0003cdce4>] create_object+0x228/0x3c4
          [<ffffffc000c0b9d8>] kmemleak_alloc+0x54/0x88
          [<ffffffc0003c0848>] __kmalloc+0x1cc/0x2dc
          [<ffffffbffc1500c4>] mwifiex_save_curr_bcn+0x80/0x308 [mwifiex]
          [<ffffffbffc1516b8>] mwifiex_ret_802_11_associate+0x4ec/0x5fc [mwifiex]
          [<ffffffbffc15da90>] mwifiex_process_sta_cmdresp+0xaf8/0x1fa4 [mwifiex]
          [<ffffffbffc1411e0>] mwifiex_process_cmdresp+0x40c/0x510 [mwifiex]
          [<ffffffbffc13b8f4>] mwifiex_main_process+0x4a4/0xb00 [mwifiex]
          [<ffffffbffc13bf84>] mwifiex_main_work_queue+0x34/0x40 [mwifiex]
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      6eb2d002
    • B
      mwifiex: don't drop lock between list-retrieval / list-deletion · 0f13acf0
      Brian Norris 提交于
      mwifiex_exec_next_cmd() seems to have a classic TOCTOU race, where we
      drop the list lock in between retrieving the next command and deleting
      it from the list. This potentially leaves room for someone else to also
      retrieve / steal this node from the list (e.g.,
      mwifiex_cancel_all_pending_cmd()).
      
      Let's keep holding the lock while we do our 'ps_state' sanity checks.
      There should be no harm in continuing to hold this lock for a bit more.
      
      Noticed only by code inspection.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      0f13acf0
    • D
      mwifiex: Add locking to mwifiex_11n_delba · 09bdb650
      Douglas Anderson 提交于
      The mwifiex_11n_delba() function walked the rx_reorder_tbl_ptr without
      holding the lock, which was an obvious violation.
      
      Grab the lock.
      
      NOTE: we hold the lock while calling mwifiex_send_delba().  There's also
      several callers in 11n_rxreorder.c that hold the lock and the comments
      in the struct sound just like very other list/lock pair -- as if the
      lock should definitely be help for all operations like this.
      Signed-off-by: NDouglas Anderson <dianders@chromium.org>
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      09bdb650
    • D
      mwifiex: Don't release cmd_pending_q_lock while iterating · 90ad0be8
      Douglas Anderson 提交于
      Just like in the previous patch ("mwifiex: Don't release
      tx_ba_stream_tbl_lock while iterating"), in
      mwifiex_cancel_all_pending_cmd() we were itearting over a list protected
      by a spinlock.  Again, it is not safe to release the spinlock while
      iterating.  Don't do it.
      
      Luckily in this case there should be no need to release the spinlock.
      This is evidenced by:
      
      1. The only function called while the spinlock was released was
         mwifiex_recycle_cmd_node()
      2. Aside from atomic functions (which are safe to call), the only
         function called by mwifiex_recycle_cmd_node() was
         mwifiex_insert_cmd_to_free_q().
      3. It can be seen in mwifiex_cancel_pending_scan_cmd() that it's OK to
         call mwifiex_insert_cmd_to_free_q() while holding a different
         spinlock (scan_pending_q_lock), so in general holding a spinlock
         should be OK.
      4. It doesn't appear that mwifiex_insert_cmd_to_free_q() has any
         interaction with the cmd_pending_q_lock
      
      No known bugs are fixed with this change, but as with other similar
      changes this could fix random list corruption.
      Signed-off-by: NDouglas Anderson <dianders@chromium.org>
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      90ad0be8
    • D
      mwifiex: Don't release tx_ba_stream_tbl_lock while iterating · e0b636e5
      Douglas Anderson 提交于
      Despite the macro list_for_each_entry_safe() having the word "safe" in
      the name, it's still not actually safe to release the list spinlock
      while iterating over the list.  The "safe" in the macro name actually
      only means that it's safe to delete the current entry while iterating
      over the list.
      
      Releasing the spinlock while iterating over the list means that someone
      else could come in and adjust the list while we don't have the
      spinlock.  If they do that it can totally mix up our iteration and fully
      corrupt the list.  Later iterating over a corrupted list while holding a
      spinlock and having IRQs off can cause all sorts of hard to debug
      problems.
      
      As evidenced by the other call to
      mwifiex_11n_delete_tx_ba_stream_tbl_entry() in
      mwifiex_11n_delete_all_tx_ba_stream_tbl(), it's actually safe to skip
      the spinlock release.  Let's do that.
      
      No known problems are fixed by this patch, but it could fix all sorts of
      weird problems and it should be very safe.
      Signed-off-by: NDouglas Anderson <dianders@chromium.org>
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      e0b636e5
    • B
      mwifiex: fixup error cases in mwifiex_add_virtual_intf() · 8535107a
      Brian Norris 提交于
      If we fail to add an interface in mwifiex_add_virtual_intf(), we might
      hit a BUG_ON() in the networking code, because we didn't tear things
      down properly. Among the problems:
      
       (a) when failing to allocate workqueues, we fail to unregister the
           netdev before calling free_netdev()
       (b) even if we do try to unregister the netdev, we're still holding the
           rtnl lock, so the device never properly unregistered; we'll be at
           state NETREG_UNREGISTERING, and then hit free_netdev()'s:
      	BUG_ON(dev->reg_state != NETREG_UNREGISTERED);
       (c) we're allocating some dependent resources (e.g., DFS workqueues)
           after we've registered the interface; this may or may not cause
           problems, but it's good practice to allocate these before registering
       (d) we're not even trying to unwind anything when mwifiex_send_cmd() or
           mwifiex_sta_init_cmd() fail
      
      To fix these issues, let's:
      
       * add a stacked set of error handling labels, to keep error handling
         consistent and properly ordered (resolving (a) and (d))
       * move the workqueue allocations before the registration (to resolve
         (c); also resolves (b) by avoiding error cases where we have to
         unregister)
      
      [Incidentally, it's pretty easy to interrupt the alloc_workqueue() in,
      e.g., the following:
      
        iw phy phy0 interface add mlan0 type station
      
      by sending it SIGTERM.]
      
      This bugfix covers commits like commit 7d652034 ("mwifiex: channel
      switch support for mwifiex"), but parts of this bug exist all the way
      back to the introduction of dynamic interface handling in commit
      93a1df48 ("mwifiex: add cfg80211 handlers add/del_virtual_intf").
      
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      8535107a
    • B
      mwifiex: pcie: de-duplicate buffer allocation code · d41bf5c1
      Brian Norris 提交于
      This code was duplicated as part of the PCIe FLR code added to this
      driver. Let's de-duplicate it to:
      
       * make things easier to read (mwifiex_pcie_free_buffers() now has a
         corresponding mwifiex_pcie_alloc_buffers())
       * reduce likelihood of bugs
       * make error logging equally verbose
       * save lines of code!
      
      Also drop some of the commentary that isn't really needed.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      d41bf5c1
  2. 18 5月, 2017 3 次提交
  3. 28 4月, 2017 3 次提交
    • A
      cfg80211: add request id to cfg80211_sched_scan_*() api · b34939b9
      Arend Van Spriel 提交于
      Have proper request id filled in the SCHED_SCAN_RESULTS and
      SCHED_SCAN_STOPPED notifications toward user-space by having the
      driver provide it through the api.
      Reviewed-by: NHante Meuleman <hante.meuleman@broadcom.com>
      Reviewed-by: NPieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
      Reviewed-by: NFranky Lin <franky.lin@broadcom.com>
      Signed-off-by: NArend van Spriel <arend.vanspriel@broadcom.com>
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      b34939b9
    • J
      mac80211: separate encoding/bandwidth from flags · da6a4352
      Johannes Berg 提交于
      We currently use a lot of flags that are mutually incompatible,
      separate this out into actual encoding and bandwidth enum values.
      
      Much of this again done with spatch, with manual post-editing,
      mostly to add the switch statements and get rid of the conversions.
      
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_80MHZ
      +status->bw = RATE_INFO_BW_80
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_40MHZ
      +status->bw = RATE_INFO_BW_40
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_20MHZ
      +status->bw = RATE_INFO_BW_20
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_160MHZ
      +status->bw = RATE_INFO_BW_160
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_5MHZ
      +status->bw = RATE_INFO_BW_5
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_10MHZ
      +status->bw = RATE_INFO_BW_10
      
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_VHT
      +status->encoding = RX_ENC_VHT
      @@
      expression status;
      @@
      -status->enc_flags |= RX_ENC_FLAG_HT
      +status->encoding = RX_ENC_HT
      @@
      expression status;
      @@
      -status.enc_flags |= RX_ENC_FLAG_VHT
      +status.encoding = RX_ENC_VHT
      @@
      expression status;
      @@
      -status.enc_flags |= RX_ENC_FLAG_HT
      +status.encoding = RX_ENC_HT
      
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_HT)
      +(status->encoding == RX_ENC_HT)
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_VHT)
      +(status->encoding == RX_ENC_VHT)
      
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_5MHZ)
      +(status->bw == RATE_INFO_BW_5)
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_10MHZ)
      +(status->bw == RATE_INFO_BW_10)
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_40MHZ)
      +(status->bw == RATE_INFO_BW_40)
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_80MHZ)
      +(status->bw == RATE_INFO_BW_80)
      @@
      expression status;
      @@
      -(status->enc_flags & RX_ENC_FLAG_160MHZ)
      +(status->bw == RATE_INFO_BW_160)
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      da6a4352
    • J
      mac80211: clean up rate encoding bits in RX status · 7fdd69c5
      Johannes Berg 提交于
      In preparation for adding support for HE rates, clean up
      the driver report encoding for rate/bandwidth reporting
      on RX frames.
      
      Much of this patch was done with the following spatch:
      
      @@
      expression status;
      @@
      -status->flag & (RX_FLAG_HT | RX_FLAG_VHT)
      +status->enc_flags & (RX_ENC_FLAG_HT | RX_ENC_FLAG_VHT)
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_SHORTPRE
      +status->enc_flags op RX_ENC_FLAG_SHORTPRE
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_SHORTPRE
      +status->enc_flags & RX_ENC_FLAG_SHORTPRE
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_HT
      +status->enc_flags op RX_ENC_FLAG_HT
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_HT
      +status->enc_flags & RX_ENC_FLAG_HT
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_40MHZ
      +status->enc_flags op RX_ENC_FLAG_40MHZ
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_40MHZ
      +status->enc_flags & RX_ENC_FLAG_40MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_SHORT_GI
      +status->enc_flags op RX_ENC_FLAG_SHORT_GI
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_SHORT_GI
      +status->enc_flags & RX_ENC_FLAG_SHORT_GI
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_HT_GF
      +status->enc_flags op RX_ENC_FLAG_HT_GF
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_HT_GF
      +status->enc_flags & RX_ENC_FLAG_HT_GF
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_VHT
      +status->enc_flags op RX_ENC_FLAG_VHT
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_VHT
      +status->enc_flags & RX_ENC_FLAG_VHT
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_STBC_MASK
      +status->enc_flags op RX_ENC_FLAG_STBC_MASK
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_STBC_MASK
      +status->enc_flags & RX_ENC_FLAG_STBC_MASK
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_LDPC
      +status->enc_flags op RX_ENC_FLAG_LDPC
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_LDPC
      +status->enc_flags & RX_ENC_FLAG_LDPC
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_10MHZ
      +status->enc_flags op RX_ENC_FLAG_10MHZ
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_10MHZ
      +status->enc_flags & RX_ENC_FLAG_10MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->flag op RX_FLAG_5MHZ
      +status->enc_flags op RX_ENC_FLAG_5MHZ
      @@
      expression status;
      @@
      -status->flag & RX_FLAG_5MHZ
      +status->enc_flags & RX_ENC_FLAG_5MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->vht_flag op RX_VHT_FLAG_80MHZ
      +status->enc_flags op RX_ENC_FLAG_80MHZ
      @@
      expression status;
      @@
      -status->vht_flag & RX_VHT_FLAG_80MHZ
      +status->enc_flags & RX_ENC_FLAG_80MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->vht_flag op RX_VHT_FLAG_160MHZ
      +status->enc_flags op RX_ENC_FLAG_160MHZ
      @@
      expression status;
      @@
      -status->vht_flag & RX_VHT_FLAG_160MHZ
      +status->enc_flags & RX_ENC_FLAG_160MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status->vht_flag op RX_VHT_FLAG_BF
      +status->enc_flags op RX_ENC_FLAG_BF
      @@
      expression status;
      @@
      -status->vht_flag & RX_VHT_FLAG_BF
      +status->enc_flags & RX_ENC_FLAG_BF
      
      @@
      assignment operator op;
      expression status, STBC;
      @@
      -status->flag op STBC << RX_FLAG_STBC_SHIFT
      +status->enc_flags op STBC << RX_ENC_FLAG_STBC_SHIFT
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_SHORTPRE
      +status.enc_flags op RX_ENC_FLAG_SHORTPRE
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_SHORTPRE
      +status.enc_flags & RX_ENC_FLAG_SHORTPRE
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_HT
      +status.enc_flags op RX_ENC_FLAG_HT
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_HT
      +status.enc_flags & RX_ENC_FLAG_HT
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_40MHZ
      +status.enc_flags op RX_ENC_FLAG_40MHZ
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_40MHZ
      +status.enc_flags & RX_ENC_FLAG_40MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_SHORT_GI
      +status.enc_flags op RX_ENC_FLAG_SHORT_GI
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_SHORT_GI
      +status.enc_flags & RX_ENC_FLAG_SHORT_GI
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_HT_GF
      +status.enc_flags op RX_ENC_FLAG_HT_GF
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_HT_GF
      +status.enc_flags & RX_ENC_FLAG_HT_GF
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_VHT
      +status.enc_flags op RX_ENC_FLAG_VHT
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_VHT
      +status.enc_flags & RX_ENC_FLAG_VHT
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_STBC_MASK
      +status.enc_flags op RX_ENC_FLAG_STBC_MASK
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_STBC_MASK
      +status.enc_flags & RX_ENC_FLAG_STBC_MASK
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_LDPC
      +status.enc_flags op RX_ENC_FLAG_LDPC
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_LDPC
      +status.enc_flags & RX_ENC_FLAG_LDPC
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_10MHZ
      +status.enc_flags op RX_ENC_FLAG_10MHZ
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_10MHZ
      +status.enc_flags & RX_ENC_FLAG_10MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.flag op RX_FLAG_5MHZ
      +status.enc_flags op RX_ENC_FLAG_5MHZ
      @@
      expression status;
      @@
      -status.flag & RX_FLAG_5MHZ
      +status.enc_flags & RX_ENC_FLAG_5MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.vht_flag op RX_VHT_FLAG_80MHZ
      +status.enc_flags op RX_ENC_FLAG_80MHZ
      @@
      expression status;
      @@
      -status.vht_flag & RX_VHT_FLAG_80MHZ
      +status.enc_flags & RX_ENC_FLAG_80MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.vht_flag op RX_VHT_FLAG_160MHZ
      +status.enc_flags op RX_ENC_FLAG_160MHZ
      @@
      expression status;
      @@
      -status.vht_flag & RX_VHT_FLAG_160MHZ
      +status.enc_flags & RX_ENC_FLAG_160MHZ
      
      @@
      assignment operator op;
      expression status;
      @@
      -status.vht_flag op RX_VHT_FLAG_BF
      +status.enc_flags op RX_ENC_FLAG_BF
      @@
      expression status;
      @@
      -status.vht_flag & RX_VHT_FLAG_BF
      +status.enc_flags & RX_ENC_FLAG_BF
      
      @@
      assignment operator op;
      expression status, STBC;
      @@
      -status.flag op STBC << RX_FLAG_STBC_SHIFT
      +status.enc_flags op STBC << RX_ENC_FLAG_STBC_SHIFT
      
      @@
      @@
      -RX_FLAG_STBC_SHIFT
      +RX_ENC_FLAG_STBC_SHIFT
      Signed-off-by: NJohannes Berg <johannes.berg@intel.com>
      7fdd69c5
  4. 27 4月, 2017 2 次提交
  5. 26 4月, 2017 1 次提交
  6. 20 4月, 2017 9 次提交
    • B
      mwifiex: don't leak 'chan_stats' on reset · fb9e67be
      Brian Norris 提交于
      'chan_stats' is (re)allocated in _mwifiex_fw_dpc() ->
      mwifiex_init_channel_scan_gap(), which is called whenever the device is
      initialized -- at probe or at reset.
      
      But we only free it in we completely unregister the adapter, meaning we
      leak a copy of it during every reset.
      
      Let's free it in the shutdown / removal paths instead (and in the
      error-handling path), to avoid the leak.
      
      Ideally, we can eventually unify much of mwifiex_shutdown_sw() and
      mwifiex_remove_card() (way too much copy-and-paste) to reduce the burden
      on bugfixes like this. But that's work for tomorrow.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      fb9e67be
    • B
      mwifiex: pcie: clear outstanding work when resetting · 35e67d3d
      Brian Norris 提交于
      When we shut down the device (i.e., during 'reset'), we cancel any
      outstanding work, but we don't clear any work-related flags. This can
      cause problems if, e.g., we begin to queue a new firmware dump or card
      reset while the other one is in progress. That might leave work_flags
      with a stale value, and we might begin one of these *after* we've
      completely reset the device. That doesn't make sense, because all
      firmware context will have been lost by then.
      
      This fixes some forms of cascading failures, where I:
      
      (a) force a firmware dump (cat /sys/kernel/debug/mwifiex/mlan0/device_dump)
      (b) run a Wifi scan in parallel (iw mlan0 scan)
      (c) the scan times out due to (a) hogging the interface
      (d) the command timeout triggers another firmware dump and a reset [*]
      (e) the 2nd firmware dump flag persists across the reset
      (f) as soon as the interface comes back up, we trigger the pending
          firmware dump
      (g) subsequent commands time out again, while we are processing the
          firmware dump; return to (d)
      
      [*] Note that automatic card_reset() support is not yet implemented for
      the mwifiex PCIe driver, so we won't hit *exactly* this behavior yet.
      But we can see similarly-confusing behaviors today.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      35e67d3d
    • B
      mwifiex: reset timeout flag when resetting device · 9ae3fbd1
      Brian Norris 提交于
      If we reset because of a command timeout, we should reset this flag.
      Otherwise, we might erroneously think the next command after reset is
      timing out, and trigger another reset.
      
      The above behavior effectively neuters the automatic card_reset()
      behavior, as it means we will never recover from a command timeout
      properly (and in fact, we might enter an infinite loop:
      
        timeout -> reset -> (fake) timeout -> reset -> ...
      
      This fixes a bug introduced with introduction of PCIe function level
      reset support, but it was carried into the SDIO driver when it was
      converted to use the same codepaths. And this is currently mostly a
      problem only in the SDIO driver, because it's the only one with
      automatic card_reset() support (e.g., on command timeout). But it will
      be a problem for PCIe too, as I'm working on supporting automatic
      card_reset() for PCIe.
      
      Fixes: c742e623 ("mwifiex: sdio card reset enhancement")
      Fixes: 4c5dae59 ("mwifiex: add PCIe function level reset support")
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      9ae3fbd1
    • B
      mwifiex: pcie: fix cmd_buf use-after-free in remove/reset · 3c8cb9ad
      Brian Norris 提交于
      Command buffers (skb's) are allocated by the main driver, and freed upon
      the last use. That last use is often in mwifiex_free_cmd_buffer(). In
      the meantime, if the command buffer gets used by the PCI driver, we map
      it as DMA-able, and store the mapping information in the 'cb' memory.
      
      However, if a command was in-flight when resetting the device (and
      therefore was still mapped), we don't get a chance to unmap this memory
      until after the core has cleaned up its command handling.
      
      Let's keep a refcount within the PCI driver, so we ensure the memory
      only gets freed after we've finished unmapping it.
      
      Noticed by KASAN when forcing a reset via:
      
        echo 1 > /sys/bus/pci/.../reset
      
      The same code path can presumably be exercised in remove() and
      shutdown().
      
      [  205.390377] mwifiex_pcie 0000:01:00.0: info: shutdown mwifiex...
      [  205.400393] ==================================================================
      [  205.407719] BUG: KASAN: use-after-free in mwifiex_unmap_pci_memory.isra.14+0x4c/0x100 [mwifiex_pcie] at addr ffffffc0ad471b28
      [  205.419040] Read of size 16 by task bash/1913
      [  205.423421] =============================================================================
      [  205.431625] BUG skbuff_head_cache (Tainted: G    B          ): kasan: bad access detected
      [  205.439815] -----------------------------------------------------------------------------
      [  205.439815]
      [  205.449534] INFO: Allocated in __build_skb+0x48/0x114 age=1311 cpu=4 pid=1913
      [  205.456709] 	alloc_debug_processing+0x124/0x178
      [  205.461282] 	___slab_alloc.constprop.58+0x528/0x608
      [  205.466196] 	__slab_alloc.isra.54.constprop.57+0x44/0x54
      [  205.471542] 	kmem_cache_alloc+0xcc/0x278
      [  205.475497] 	__build_skb+0x48/0x114
      [  205.479019] 	__netdev_alloc_skb+0xe0/0x170
      [  205.483244] 	mwifiex_alloc_cmd_buffer+0x68/0xdc [mwifiex]
      [  205.488759] 	mwifiex_init_fw+0x40/0x6cc [mwifiex]
      [  205.493584] 	_mwifiex_fw_dpc+0x158/0x520 [mwifiex]
      [  205.498491] 	mwifiex_reinit_sw+0x2c4/0x398 [mwifiex]
      [  205.503510] 	mwifiex_pcie_reset_notify+0x114/0x15c [mwifiex_pcie]
      [  205.509643] 	pci_reset_notify+0x5c/0x6c
      [  205.513519] 	pci_reset_function+0x6c/0x7c
      [  205.517567] 	reset_store+0x68/0x98
      [  205.521003] 	dev_attr_store+0x54/0x60
      [  205.524705] 	sysfs_kf_write+0x9c/0xb0
      [  205.528413] INFO: Freed in __kfree_skb+0xb0/0xbc age=131 cpu=4 pid=1913
      [  205.535064] 	free_debug_processing+0x264/0x370
      [  205.539550] 	__slab_free+0x84/0x40c
      [  205.543075] 	kmem_cache_free+0x1c8/0x2a0
      [  205.547030] 	__kfree_skb+0xb0/0xbc
      [  205.550465] 	consume_skb+0x164/0x178
      [  205.554079] 	__dev_kfree_skb_any+0x58/0x64
      [  205.558304] 	mwifiex_free_cmd_buffer+0xa0/0x158 [mwifiex]
      [  205.563817] 	mwifiex_shutdown_drv+0x578/0x5c4 [mwifiex]
      [  205.569164] 	mwifiex_shutdown_sw+0x178/0x310 [mwifiex]
      [  205.574353] 	mwifiex_pcie_reset_notify+0xd4/0x15c [mwifiex_pcie]
      [  205.580398] 	pci_reset_notify+0x5c/0x6c
      [  205.584274] 	pci_dev_save_and_disable+0x24/0x6c
      [  205.588837] 	pci_reset_function+0x30/0x7c
      [  205.592885] 	reset_store+0x68/0x98
      [  205.596324] 	dev_attr_store+0x54/0x60
      [  205.600017] 	sysfs_kf_write+0x9c/0xb0
      ...
      [  205.800488] Call trace:
      [  205.802980] [<ffffffc00020a69c>] dump_backtrace+0x0/0x190
      [  205.808415] [<ffffffc00020a96c>] show_stack+0x20/0x28
      [  205.813506] [<ffffffc0005d020c>] dump_stack+0xa4/0xcc
      [  205.818598] [<ffffffc0003be44c>] print_trailer+0x158/0x168
      [  205.824120] [<ffffffc0003be5f0>] object_err+0x4c/0x5c
      [  205.829210] [<ffffffc0003c45bc>] kasan_report+0x334/0x500
      [  205.834641] [<ffffffc0003c3994>] check_memory_region+0x20/0x14c
      [  205.840593] [<ffffffc0003c3b14>] __asan_loadN+0x14/0x1c
      [  205.845879] [<ffffffbffc46171c>] mwifiex_unmap_pci_memory.isra.14+0x4c/0x100 [mwifiex_pcie]
      [  205.854282] [<ffffffbffc461864>] mwifiex_pcie_delete_cmdrsp_buf+0x94/0xa8 [mwifiex_pcie]
      [  205.862421] [<ffffffbffc462028>] mwifiex_pcie_free_buffers+0x11c/0x158 [mwifiex_pcie]
      [  205.870302] [<ffffffbffc4620d4>] mwifiex_pcie_down_dev+0x70/0x80 [mwifiex_pcie]
      [  205.877736] [<ffffffbffc1397a8>] mwifiex_shutdown_sw+0x190/0x310 [mwifiex]
      [  205.884658] [<ffffffbffc4606b4>] mwifiex_pcie_reset_notify+0xd4/0x15c [mwifiex_pcie]
      [  205.892446] [<ffffffc000635f54>] pci_reset_notify+0x5c/0x6c
      [  205.898048] [<ffffffc00063a044>] pci_dev_save_and_disable+0x24/0x6c
      [  205.904350] [<ffffffc00063cf0c>] pci_reset_function+0x30/0x7c
      [  205.910134] [<ffffffc000641118>] reset_store+0x68/0x98
      [  205.915312] [<ffffffc000771588>] dev_attr_store+0x54/0x60
      [  205.920750] [<ffffffc00046f53c>] sysfs_kf_write+0x9c/0xb0
      [  205.926182] [<ffffffc00046dfb0>] kernfs_fop_write+0x184/0x1f8
      [  205.931963] [<ffffffc0003d64f4>] __vfs_write+0x6c/0x17c
      [  205.937221] [<ffffffc0003d7164>] vfs_write+0xf0/0x1c4
      [  205.942310] [<ffffffc0003d7da0>] SyS_write+0x78/0xd8
      [  205.947312] [<ffffffc000204634>] el0_svc_naked+0x24/0x28
      ...
      [  205.998268] ==================================================================
      
      This bug has been around in different forms for a while. It was sort of
      noticed in commit 955ab095 ("mwifiex: Do not kfree cmd buf while
      unregistering PCIe"), but it just fixed the double-free, without
      acknowledging the potential for use-after-free.
      
      Fixes: fc331460 ("mwifiex: use pci_alloc/free_consistent APIs for PCIe")
      Cc: <stable@vger.kernel.org>
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      3c8cb9ad
    • X
      mwifiex: pcie: extract wifi part from combo firmware during function level reset · efde6648
      Xinming Hu 提交于
      A separate wifi-only firmware was download during pcie function level
      reset. It is in fact the tail part of wifi/bt combo firmware. Per
      Brian's and Dmitry's suggestion, this patch extract the wifi part from
      combo firmware.
      
      After that, the mrvl/pcie8997_wlan_v4.bin image in linux-firmware repo
      is redundant (though I guess we keep it around to support older
      kernels).
      Signed-off-by: NXinming Hu <huxm@marvell.com>
      Signed-off-by: NGanapathi Bhat <gbhat@marvell.com>
      Signed-off-by: NCathy Luo <cluo@marvell.com>
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      efde6648
    • X
      mwifiex: pcie: correct scratch register name · 127ee1db
      Xinming Hu 提交于
      This patch correct pcie scratch register name, to keep the same with
      chipset side definition.
      Signed-off-by: NXinming Hu <huxm@marvell.com>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      127ee1db
    • X
      mwifiex: fall back mwifiex_dbg to pr_info when adapter->dev not set · ef6c7d3c
      Xinming Hu 提交于
      mwifiex_dbg will do nothing before adapter->dev get assigned. several logs
      lost in this case. it can be avoided by fall back to pr_info.
      Signed-off-by: NXinming Hu <huxm@marvell.com>
      Reviewed-by: NBrian Norris <briannorris@chromium.org>
      Reviewed-by: NDmitry Torokhov <dtor@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      ef6c7d3c
    • X
      mwifiex: remove unnecessary wakeup interrupt number sanity check · 625b4dba
      Xinming Hu 提交于
      If wakeup interrupt handler is called, we know that the wakeup
      interrupt number is valid, there is no need to check it.
      Signed-off-by: NXinming Hu <huxm@marvell.com>
      Signed-off-by: NCathy Luo <cluo@marvell.com>
      Reviewed-by: NDmitry Torokhov <dtor@chromium.org>
      Reviewed-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      625b4dba
    • B
      mwifiex: MAC randomization should not be persistent · 7e2f18f0
      Brian Norris 提交于
      nl80211 provides the NL80211_SCAN_FLAG_RANDOM_ADDR for every scan
      request that should be randomized; the absence of such a flag means we
      should not randomize. However, mwifiex was stashing the latest
      randomization request and *always* using it for future scans, even those
      that didn't set the flag.
      
      Let's zero out the randomization info whenever we get a scan request
      without NL80211_SCAN_FLAG_RANDOM_ADDR. I'd prefer to remove
      priv->random_mac entirely (and plumb the randomization MAC properly
      through the call sequence), but the spaghetti is a little difficult to
      unravel here for me.
      
      Fixes: c2a8f0ff ("mwifiex: support random MAC address for scanning")
      Cc: <stable@vger.kernel.org> # 4.9+
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      7e2f18f0
  7. 14 4月, 2017 1 次提交
  8. 13 4月, 2017 2 次提交
  9. 05 4月, 2017 6 次提交
  10. 21 3月, 2017 1 次提交
    • B
      mwifiex: fix kernel crash after shutdown command timeout · 5caa7f38
      Brian Norris 提交于
      We observed a SHUTDOWN command timeout during reboot stress test due to
      a corner case firmware bug. It can lead to either a use-after-free +
      OOPS (on either the adapter structure, or the 'card' structure) or an
      abort (where, e.g., the PCI device is "disabled" before we're done
      dumping the FW).
      
      We can avoid this by canceling/flushing the FW dump work:
      
      (a) after we've terminated all other work queues (e.g., for processing
          commands which could time out)
      (b) after we've disabled all interrupts (which could also queue more
          work for us)
      (c) after we've unregistered the netdev and wiphy structures (and
          implicitly, and debugfs entries which could manually trigger FW dumps)
      (d) before we've actually disabled the device (e.g.,
          pci_device_disable())
      
      Altogether, this means no card->work will be scheduled if we sync at
      a point that satisfies the above. This can be done at the beginning of
      the .cleanup_if() callback.
      Signed-off-by: NBrian Norris <briannorris@chromium.org>
      Signed-off-by: NKalle Valo <kvalo@codeaurora.org>
      5caa7f38