diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2014-02-07 11:27:30 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-02-07 11:27:30 -0800 |
commit | a3b072cd180c12e8fe0ece9487b9065808327640 (patch) | |
tree | 62b982041be84748852d77cdf6ca5639ef40858f /drivers/net/wireless/ti/wl1251/tx.c | |
parent | x86, microcode, AMD: Unify valid container checks (diff) | |
parent | x86/efi: Allow mapping BGRT on x86-32 (diff) | |
download | linux-dev-a3b072cd180c12e8fe0ece9487b9065808327640.tar.xz linux-dev-a3b072cd180c12e8fe0ece9487b9065808327640.zip |
Merge tag 'efi-urgent' into x86/urgent
* Avoid WARN_ON() when mapping BGRT on Baytrail (EFI 32-bit).
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'drivers/net/wireless/ti/wl1251/tx.c')
-rw-r--r-- | drivers/net/wireless/ti/wl1251/tx.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/drivers/net/wireless/ti/wl1251/tx.c b/drivers/net/wireless/ti/wl1251/tx.c index 28121c590a2b..81de83c6fcf6 100644 --- a/drivers/net/wireless/ti/wl1251/tx.c +++ b/drivers/net/wireless/ti/wl1251/tx.c @@ -28,6 +28,7 @@ #include "tx.h" #include "ps.h" #include "io.h" +#include "event.h" static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) { @@ -89,8 +90,12 @@ static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr, /* 802.11 packets */ tx_hdr->control.packet_type = 0; - if (control->flags & IEEE80211_TX_CTL_NO_ACK) + /* Also disable retry and ACK policy for injected packets */ + if ((control->flags & IEEE80211_TX_CTL_NO_ACK) || + (control->flags & IEEE80211_TX_CTL_INJECTED)) { + tx_hdr->control.rate_policy = 1; tx_hdr->control.ack_policy = 1; + } tx_hdr->control.tx_complete = 1; @@ -277,6 +282,26 @@ static void wl1251_tx_trigger(struct wl1251 *wl) TX_STATUS_DATA_OUT_COUNT_MASK; } +static void enable_tx_for_packet_injection(struct wl1251 *wl) +{ + int ret; + + ret = wl1251_cmd_join(wl, BSS_TYPE_STA_BSS, wl->channel, + wl->beacon_int, wl->dtim_period); + if (ret < 0) { + wl1251_warning("join failed"); + return; + } + + ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100); + if (ret < 0) { + wl1251_warning("join timeout"); + return; + } + + wl->joined = true; +} + /* caller must hold wl->mutex */ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) { @@ -287,6 +312,9 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) info = IEEE80211_SKB_CB(skb); if (info->control.hw_key) { + if (unlikely(wl->monitor_present)) + return -EINVAL; + idx = info->control.hw_key->hw_key_idx; if (unlikely(wl->default_key != idx)) { ret = wl1251_acx_default_key(wl, idx); @@ -295,6 +323,10 @@ static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) } } + /* Enable tx path in monitor mode for packet injection */ + if ((wl->vif == NULL) && !wl->joined) + enable_tx_for_packet_injection(wl); + ret = wl1251_tx_path_status(wl); if (ret < 0) return ret; @@ -394,6 +426,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, info = IEEE80211_SKB_CB(skb); if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && + !(info->flags & IEEE80211_TX_CTL_INJECTED) && (result->status == TX_SUCCESS)) info->flags |= IEEE80211_TX_STAT_ACK; |