• Emmanuel Grumbach's avatar
    mac80211: fix deauth TX when we disconnect · f6c7f03f
    Emmanuel Grumbach authored
    The iTXQs stop/wake queue mechanism involves a whole bunch
    of locks and this is probably why the call to
    ieee80211_wake_txqs is deferred to a tasklet when called from
    __ieee80211_wake_queue.
    
    Another advantage of that is that ieee80211_wake_txqs might
    call the wake_tx_queue() callback and then the driver may
    call mac80211 which will call it back in the same context.
    
    The bug I saw is that when we send a deauth frame as a
    station we do:
    
    flush(drop=1)
    tx deauth
    flush(drop=0)
    
    While we flush we stop the queues and wake them up
    immediately after we finished flushing. The problem here is
    that the tasklet that de-facto enables the queue may not have
    run until we send the deauth. Then the deauth frame is sent
    to the driver (which is surprising by itself), but the driver
    won't get anything useful from ieee80211_tx_dequeue because
    the queue is stopped (or more precisely because
    vif->txqs_stopped[0] is true).
    Then the deauth is not sent. Later on, the tasklet will run,
    but that'll be too late. We'll already have removed all the
    vif etc...
    
    Fix this by calling ieee80211_wake_txqs synchronously if we
    are not waking up the queues from the driver (we check the
    reason to determine that). This makes the code really
    convoluted because we may call ieee80211_wake_txqs from
    __ieee80211_wake_queue. The latter assumes that
    queue_stop_reason_lock has been taken by the caller and
    ieee80211_wake_txqs may release the lock to send the frames.
    Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
    Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
    f6c7f03f
util.c 98 KB