Skip to content
  • Johannes Berg's avatar
    mac80211: fix aggregation state with current drivers · 8147dc7f
    Johannes Berg authored
    
    
    For drivers that don't actually flush their queues when
    aggregation stop with the IEEE80211_AMPDU_TX_STOP_FLUSH
    or IEEE80211_AMPDU_TX_STOP_FLUSH_CONT reasons is done,
    like iwlwifi or iwlegacy, mac80211 can then transmit on
    a TID that the driver still considers busy. This happens
    in the following way:
    
     - IEEE80211_AMPDU_TX_STOP_FLUSH requested
     - driver marks TID as emptying
     - mac80211 removes tid_tx data, this can copy packets
       to the TX pending queues and also let new packets
       through to the driver
     - driver gets unexpected TX as it wasn't completely
       converted to the new API
    
    In iwlwifi, this lead to the following warning:
    
    WARNING: at drivers/net/wireless/iwlwifi/dvm/tx.c:442 iwlagn_tx_skb+0xc47/0xce0
    Tx while agg.state = 4
    Modules linked in: [...]
    Pid: 0, comm: kworker/0:0 Tainted: G        W   3.1.0 #1
    Call Trace:
     [<c1046e42>] warn_slowpath_common+0x72/0xa0
     [<c1046f13>] warn_slowpath_fmt+0x33/0x40
     [<fddffa17>] iwlagn_tx_skb+0xc47/0xce0 [iwldvm]
     [<fddfcaa3>] iwlagn_mac_tx+0x23/0x40 [iwldvm]
     [<fd8c98b6>] __ieee80211_tx+0xf6/0x3c0 [mac80211]
     [<fd8cbe00>] ieee80211_tx+0xd0/0x100 [mac80211]
     [<fd8cc176>] ieee80211_xmit+0x96/0xe0 [mac80211]
     [<fd8cc578>] ieee80211_subif_start_xmit+0x348/0xc80 [mac80211]
     [<c1445207>] dev_hard_start_xmit+0x337/0x6d0
     [<c145eee9>] sch_direct_xmit+0xa9/0x210
     [<c14462c0>] dev_queue_xmit+0x1b0/0x8e0
    
    Fortunately, solving this problem is easy as the station
    is being destroyed, so such transmit packets can only
    happen due to races. Instead of trying to close the race
    just let the race not reach the drivers by making two
    changes:
     1) remove the explicit aggregation session teardown in
        the managed mode code, the same thing will be done
        when the station is removed, in __sta_info_destroy.
     2) When aggregation stop with AGG_STOP_DESTROY_STA is
        requested, leave the tid_tx data around as stopped.
        It will be cleared and freed in cleanup_single_sta
        later, but until then any racy packets will be put
        onto the tid_tx pending queue instead of transmitted
        which is fine since the station is being removed.
    
    Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
    8147dc7f