Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2010-02-04 08:58:14 -08:00
commit 10be7eb36b
125 changed files with 3770 additions and 2018 deletions

View file

@ -120,36 +120,38 @@ STA_OPS(last_seq_ctrl);
static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
char buf[30 + STA_TID_NUM * 70], *p = buf;
char buf[64 + STA_TID_NUM * 40], *p = buf;
int i;
struct sta_info *sta = file->private_data;
spin_lock_bh(&sta->lock);
p += scnprintf(p, sizeof(buf)+buf-p, "next dialog_token is %#02x\n",
p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
sta->ampdu_mlme.dialog_token_allocator + 1);
p += scnprintf(p, sizeof(buf) + buf - p,
"TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tSSN\tpending\n");
for (i = 0; i < STA_TID_NUM; i++) {
p += scnprintf(p, sizeof(buf)+buf-p, "TID %02d:", i);
p += scnprintf(p, sizeof(buf)+buf-p, " RX=%x",
p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
sta->ampdu_mlme.tid_state_rx[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x",
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
sta->ampdu_mlme.tid_state_rx[i] ?
sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x",
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
sta->ampdu_mlme.tid_state_rx[i] ?
sta->ampdu_mlme.tid_rx[i]->ssn : 0);
p += scnprintf(p, sizeof(buf)+buf-p, " TX=%x",
p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x",
sta->ampdu_mlme.tid_state_tx[i]);
p += scnprintf(p, sizeof(buf)+buf-p, "/DTKN=%#.2x",
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
sta->ampdu_mlme.tid_state_tx[i] ?
sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "/SSN=%#.3x",
p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
sta->ampdu_mlme.tid_state_tx[i] ?
sta->ampdu_mlme.tid_tx[i]->ssn : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "/pending=%03d",
p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
sta->ampdu_mlme.tid_state_tx[i] ?
skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0);
p += scnprintf(p, sizeof(buf)+buf-p, "\n");
p += scnprintf(p, sizeof(buf) + buf - p, "\n");
}
spin_unlock_bh(&sta->lock);
@ -165,7 +167,7 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
if (_cond) \
p += scnprintf(p, sizeof(buf)+buf-p, "\t" _str "\n"); \
} while (0)
char buf[1024], *p = buf;
char buf[512], *p = buf;
int i;
struct sta_info *sta = file->private_data;
struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap;

View file

@ -137,16 +137,20 @@ static inline int drv_set_key(struct ieee80211_local *local,
}
static inline void drv_update_tkip_key(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_key_conf *conf,
const u8 *address, u32 iv32,
struct sta_info *sta, u32 iv32,
u16 *phase1key)
{
might_sleep();
struct ieee80211_sta *ista = NULL;
if (sta)
ista = &sta->sta;
if (local->ops->update_tkip_key)
local->ops->update_tkip_key(&local->hw, conf, address,
iv32, phase1key);
trace_drv_update_tkip_key(local, conf, address, iv32);
local->ops->update_tkip_key(&local->hw, &sdata->vif, conf,
ista, iv32, phase1key);
trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
}
static inline int drv_hw_scan(struct ieee80211_local *local,

View file

@ -331,26 +331,29 @@ TRACE_EVENT(drv_set_key,
TRACE_EVENT(drv_update_tkip_key,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_key_conf *conf,
const u8 *address, u32 iv32),
struct ieee80211_sta *sta, u32 iv32),
TP_ARGS(local, conf, address, iv32),
TP_ARGS(local, sdata, conf, sta, iv32),
TP_STRUCT__entry(
LOCAL_ENTRY
__array(u8, addr, 6)
VIF_ENTRY
STA_ENTRY
__field(u32, iv32)
),
TP_fast_assign(
LOCAL_ASSIGN;
memcpy(__entry->addr, address, 6);
VIF_ASSIGN;
STA_ASSIGN;
__entry->iv32 = iv32;
),
TP_printk(
LOCAL_PR_FMT " addr:%pM iv32:%#x",
LOCAL_PR_ARG, __entry->addr, __entry->iv32
LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " iv32:%#x",
LOCAL_PR_ARG,VIF_PR_ARG,STA_PR_ARG, __entry->iv32
)
);

View file

@ -293,12 +293,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
/* check if we need to merge IBSS */
/* merge only on beacons (???) */
if (!beacon)
goto put_bss;
/* we use a fixed BSSID */
if (sdata->u.ibss.bssid)
if (sdata->u.ibss.fixed_bssid)
goto put_bss;
/* not an IBSS */
@ -454,6 +450,9 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
return active;
}
/*
* This function is called with state == IEEE80211_IBSS_MLME_JOINED
*/
static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
@ -519,6 +518,10 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
capability, 0);
}
/*
* This function is called with state == IEEE80211_IBSS_MLME_SEARCH
*/
static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
@ -575,18 +578,14 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
/* Selected IBSS not found in current scan results - try to scan */
if (ifibss->state == IEEE80211_IBSS_MLME_JOINED &&
!ieee80211_sta_active_ibss(sdata)) {
mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
} else if (time_after(jiffies, ifibss->last_scan_completed +
if (time_after(jiffies, ifibss->last_scan_completed +
IEEE80211_SCAN_INTERVAL)) {
printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to "
"join\n", sdata->name);
ieee80211_request_internal_scan(sdata, ifibss->ssid,
ifibss->ssid_len);
} else if (ifibss->state != IEEE80211_IBSS_MLME_JOINED) {
} else {
int interval = IEEE80211_SCAN_INTERVAL;
if (time_after(jiffies, ifibss->ibss_join_req +
@ -604,7 +603,6 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
interval = IEEE80211_SCAN_INTERVAL_SLOW;
}
ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
mod_timer(&ifibss->timer,
round_jiffies(jiffies + interval));
}

View file

@ -299,7 +299,6 @@ struct ieee80211_work {
} assoc;
struct {
u32 duration;
bool started;
} remain;
};

View file

@ -695,10 +695,14 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,
hdr = (void *)((u8 *)skb->data + le16_to_cpu(rtap->it_len));
if (!ieee80211_is_data_qos(hdr->frame_control)) {
if (!ieee80211_is_data(hdr->frame_control)) {
skb->priority = 7;
return ieee802_1d_to_ac[skb->priority];
}
if (!ieee80211_is_data_qos(hdr->frame_control)) {
skb->priority = 0;
return ieee802_1d_to_ac[skb->priority];
}
p = ieee80211_get_qos_ctl(hdr);
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;

View file

@ -484,6 +484,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
if (count == 1 && found->u.mgd.powersave &&
found->u.mgd.associated &&
found->u.mgd.associated->beacon_ies &&
!(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL))) {
s32 beaconint_us;
@ -497,14 +498,22 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
if (beaconint_us > latency) {
local->ps_sdata = NULL;
} else {
u8 dtimper = found->vif.bss_conf.dtim_period;
struct ieee80211_bss *bss;
int maxslp = 1;
u8 dtimper;
if (dtimper > 1)
bss = (void *)found->u.mgd.associated->priv;
dtimper = bss->dtim_period;
/* If the TIM IE is invalid, pretend the value is 1 */
if (!dtimper)
dtimper = 1;
else if (dtimper > 1)
maxslp = min_t(int, dtimper,
latency / beaconint_us);
local->hw.conf.max_sleep_period = maxslp;
local->hw.conf.ps_dtim_period = dtimper;
local->ps_sdata = found;
}
} else {
@ -702,7 +711,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
/* set timing information */
sdata->vif.bss_conf.beacon_int = cbss->beacon_interval;
sdata->vif.bss_conf.timestamp = cbss->tsf;
sdata->vif.bss_conf.dtim_period = bss->dtim_period;
bss_info_changed |= BSS_CHANGED_BEACON_INT;
bss_info_changed |= ieee80211_handle_bss_capability(sdata,
@ -1168,6 +1176,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
int freq;
struct ieee80211_bss *bss;
struct ieee80211_channel *channel;
bool need_ps = false;
if (sdata->u.mgd.associated) {
bss = (void *)sdata->u.mgd.associated->priv;
/* not previously set so we may need to recalc */
need_ps = !bss->dtim_period;
}
if (elems->ds_params && elems->ds_params_len == 1)
freq = ieee80211_channel_to_frequency(elems->ds_params[0]);
@ -1187,6 +1202,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
if (!sdata->u.mgd.associated)
return;
if (need_ps) {
mutex_lock(&local->iflist_mtx);
ieee80211_recalc_ps(local, -1);
mutex_unlock(&local->iflist_mtx);
}
if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) &&
(memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid,
ETH_ALEN) == 0)) {

View file

@ -44,6 +44,10 @@ static inline void rate_control_tx_status(struct ieee80211_local *local,
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
if (!ref)
return;
ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
}

View file

@ -157,9 +157,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
/* In case nothing happened during the previous control interval, turn
* the sharpening factor on. */
period = (HZ * pinfo->sampling_period + 500) / 1000;
if (!period)
period = 1;
period = msecs_to_jiffies(pinfo->sampling_period);
if (jiffies - spinfo->last_sample > 2 * period)
spinfo->sharp_cnt = pinfo->sharpen_duration;
@ -252,9 +250,7 @@ static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_ba
}
/* Update PID controller state. */
period = (HZ * pinfo->sampling_period + 500) / 1000;
if (!period)
period = 1;
period = msecs_to_jiffies(pinfo->sampling_period);
if (time_after(jiffies, spinfo->last_sample + period))
rate_control_pid_sample(pinfo, sband, sta, spinfo);
}

View file

@ -2348,22 +2348,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
continue;
rx.sta = sta_info_get(sdata, hdr->addr2);
rx.flags |= IEEE80211_RX_RA_MATCH;
prepares = prepare_for_handlers(sdata, &rx, hdr);
if (!prepares)
continue;
if (status->flag & RX_FLAG_MMIC_ERROR) {
rx.sdata = sdata;
if (rx.flags & IEEE80211_RX_RA_MATCH)
ieee80211_rx_michael_mic_report(hdr,
&rx);
continue;
}
/*
* frame is destined for this interface, but if it's
* not also for the previous one we handle that after
@ -2375,6 +2359,22 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
continue;
}
rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.flags |= IEEE80211_RX_RA_MATCH;
prepares = prepare_for_handlers(prev, &rx, hdr);
if (!prepares)
goto next;
if (status->flag & RX_FLAG_MMIC_ERROR) {
rx.sdata = prev;
if (rx.flags & IEEE80211_RX_RA_MATCH)
ieee80211_rx_michael_mic_report(hdr,
&rx);
goto next;
}
/*
* frame was destined for the previous interface
* so invoke RX handlers for it
@ -2387,11 +2387,22 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
"multicast frame for %s\n",
wiphy_name(local->hw.wiphy),
prev->name);
continue;
goto next;
}
ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate);
next:
prev = sdata;
}
if (prev) {
rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.flags |= IEEE80211_RX_RA_MATCH;
prepares = prepare_for_handlers(prev, &rx, hdr);
if (!prepares)
prev = NULL;
}
}
if (prev)
ieee80211_invoke_rx_handlers(prev, &rx, skb, rate);

View file

@ -111,10 +111,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
bss->dtim_period = tim_ie->dtim_period;
}
/* set default value for buggy AP/no TIM element */
if (bss->dtim_period == 0)
bss->dtim_period = 1;
bss->supp_rates_len = 0;
if (elems->supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;

View file

@ -45,29 +45,19 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
/*
* XXX: This is temporary!
*
* The problem here is that when we get here, the driver will
* quite likely have pretty much overwritten info->control by
* using info->driver_data or info->rate_driver_data. Thus,
* when passing out the frame to the driver again, we would be
* passing completely bogus data since the driver would then
* expect a properly filled info->control. In mac80211 itself
* the same problem occurs, since we need info->control.vif
* internally.
*
* To fix this, we should send the frame through TX processing
* again. However, it's not that simple, since the frame will
* have been software-encrypted (if applicable) already, and
* encrypting it again doesn't do much good. So to properly do
* that, we not only have to skip the actual 'raw' encryption
* (key selection etc. still has to be done!) but also the
* sequence number assignment since that impacts the crypto
* encapsulation, of course.
*
* Hence, for now, fix the bug by just dropping the frame.
* This skb 'survived' a round-trip through the driver, and
* hopefully the driver didn't mangle it too badly. However,
* we can definitely not rely on the the control information
* being correct. Clear it so we don't get junk there, and
* indicate that it needs new processing, but must not be
* modified/encrypted again.
*/
goto drop;
memset(&info->control, 0, sizeof(info->control));
info->control.jiffies = jiffies;
info->control.vif = &sta->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING |
IEEE80211_TX_INTFL_RETRANSMISSION;
sta->tx_filtered_count++;
@ -122,7 +112,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
return;
}
drop:
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
if (net_ratelimit())
printk(KERN_DEBUG "%s: dropped TX filtered frame, "

View file

@ -195,11 +195,13 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf,
}
EXPORT_SYMBOL(ieee80211_get_tkip_key);
/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
/*
* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
* beginning of the buffer containing payload. This payload must include
* headroom of eight octets for IV and Ext. IV and taildroom of four octets
* for ICV. @payload_len is the length of payload (_not_ including extra
* headroom and tailroom). @ta is the transmitter addresses. */
* the IV/Ext.IV and space for (taildroom) four octets for ICV.
* @payload_len is the length of payload (_not_ including IV/ICV length).
* @ta is the transmitter addresses.
*/
void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
struct ieee80211_key *key,
u8 *pos, size_t payload_len, u8 *ta)
@ -214,7 +216,6 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm,
tkip_mixing_phase2(tk, ctx, ctx->iv16, rc4key);
pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
ieee80211_wep_encrypt_data(tfm, rc4key, 16, pos, payload_len);
}
@ -303,14 +304,12 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm,
if (key->local->ops->update_tkip_key &&
key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
key->u.tkip.rx[queue].state != TKIP_STATE_PHASE1_HW_UPLOADED) {
static const u8 bcast[ETH_ALEN] =
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const u8 *sta_addr = key->sta->sta.addr;
struct ieee80211_sub_if_data *sdata = key->sdata;
if (is_multicast_ether_addr(ra))
sta_addr = bcast;
drv_update_tkip_key(key->local, &key->conf, sta_addr,
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(key->sdata->bss,
struct ieee80211_sub_if_data, u.ap);
drv_update_tkip_key(key->local, sdata, &key->conf, key->sta,
iv32, key->u.tkip.rx[queue].p1k);
key->u.tkip.rx[queue].state = TKIP_STATE_PHASE1_HW_UPLOADED;
}

View file

@ -529,6 +529,8 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
tx->key = NULL;
if (tx->key) {
bool skip_hw = false;
tx->key->tx_rx_count++;
/* TODO: add threshold stuff again */
@ -545,16 +547,32 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
!ieee80211_use_mfp(hdr->frame_control, tx->sta,
tx->skb))
tx->key = NULL;
else
skip_hw = (tx->key->conf.flags &
IEEE80211_KEY_FLAG_SW_MGMT) &&
ieee80211_is_mgmt(hdr->frame_control);
break;
case ALG_AES_CMAC:
if (!ieee80211_is_mgmt(hdr->frame_control))
tx->key = NULL;
break;
}
if (!skip_hw && tx->key &&
tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
info->control.hw_key = &tx->key->conf;
}
if (!tx->key || !(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sta(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
if (tx->sta)
info->control.sta = &tx->sta->sta;
return TX_CONTINUE;
}
@ -733,17 +751,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
if (tx->sta)
info->control.sta = &tx->sta->sta;
return TX_CONTINUE;
}
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{
@ -1101,7 +1108,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->flags |= IEEE80211_TX_FRAGMENTED;
/* process and remove the injection radiotap header */
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
if (unlikely(info->flags & IEEE80211_TX_INTFL_HAS_RADIOTAP)) {
if (!__ieee80211_parse_tx_radiotap(tx, skb))
return TX_DROP;
@ -1110,6 +1117,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
* the radiotap header that was present and pre-filled
* 'tx' with tx control information.
*/
info->flags &= ~IEEE80211_TX_INTFL_HAS_RADIOTAP;
}
/*
@ -1125,6 +1133,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
return TX_DROP;
} else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
if (!tx->sta)
tx->sta = sta_info_get(sdata, hdr->addr1);
@ -1279,6 +1289,7 @@ static int __ieee80211_tx(struct ieee80211_local *local,
static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
{
struct sk_buff *skb = tx->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ieee80211_tx_result res = TX_DROP;
#define CALL_TXH(txh) \
@ -1292,10 +1303,14 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
CALL_TXH(ieee80211_tx_h_check_assoc);
CALL_TXH(ieee80211_tx_h_ps_buf);
CALL_TXH(ieee80211_tx_h_select_key);
CALL_TXH(ieee80211_tx_h_michael_mic_add);
CALL_TXH(ieee80211_tx_h_sta);
if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL))
CALL_TXH(ieee80211_tx_h_rate_ctrl);
CALL_TXH(ieee80211_tx_h_misc);
if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION))
goto txh_done;
CALL_TXH(ieee80211_tx_h_michael_mic_add);
CALL_TXH(ieee80211_tx_h_sequence);
CALL_TXH(ieee80211_tx_h_fragment);
/* handlers after fragment must be aware of tx info fragmentation! */
@ -1487,7 +1502,8 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
int hdrlen;
u16 len_rthdr;
info->flags |= IEEE80211_TX_CTL_INJECTED;
info->flags |= IEEE80211_TX_CTL_INJECTED |
IEEE80211_TX_INTFL_HAS_RADIOTAP;
len_rthdr = ieee80211_get_radiotap_len(skb->data);
hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);

View file

@ -305,20 +305,19 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
if (!info->control.hw_key) {
if (ieee80211_wep_encrypt(tx->local, skb, tx->key->conf.key,
tx->key->conf.keylen,
tx->key->conf.keyidx))
return -1;
} else {
info->control.hw_key = &tx->key->conf;
if (tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) {
if (!ieee80211_wep_add_iv(tx->local, skb,
tx->key->conf.keylen,
tx->key->conf.keyidx))
return -1;
}
} else if (info->control.hw_key->flags &
IEEE80211_KEY_FLAG_GENERATE_IV) {
if (!ieee80211_wep_add_iv(tx->local, skb,
tx->key->conf.keylen,
tx->key->conf.keyidx))
return -1;
}
return 0;
}

View file

@ -535,8 +535,7 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk)
* First time we run, do nothing -- the generic code will
* have switched to the right channel etc.
*/
if (!wk->remain.started) {
wk->remain.started = true;
if (!wk->started) {
wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration);
cfg80211_ready_on_channel(wk->sdata->dev, (unsigned long) wk,
@ -821,15 +820,17 @@ static void ieee80211_work_work(struct work_struct *work)
mutex_lock(&local->work_mtx);
list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
bool started = wk->started;
/* mark work as started if it's on the current off-channel */
if (!wk->started && local->tmp_channel &&
if (!started && local->tmp_channel &&
wk->chan == local->tmp_channel &&
wk->chan_type == local->tmp_channel_type) {
wk->started = true;
started = true;
wk->timeout = jiffies;
}
if (!wk->started && !local->tmp_channel) {
if (!started && !local->tmp_channel) {
/*
* TODO: could optimize this by leaving the
* station vifs in awake mode if they
@ -842,12 +843,12 @@ static void ieee80211_work_work(struct work_struct *work)
local->tmp_channel = wk->chan;
local->tmp_channel_type = wk->chan_type;
ieee80211_hw_config(local, 0);
wk->started = true;
started = true;
wk->timeout = jiffies;
}
/* don't try to work with items that aren't started */
if (!wk->started)
if (!started)
continue;
if (time_is_after_jiffies(wk->timeout)) {
@ -882,6 +883,8 @@ static void ieee80211_work_work(struct work_struct *work)
break;
}
wk->started = started;
switch (rma) {
case WORK_ACT_NONE:
/* might have changed the timeout */
@ -1022,8 +1025,6 @@ ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
case IEEE80211_STYPE_PROBE_RESP:
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
case IEEE80211_STYPE_DEAUTH:
case IEEE80211_STYPE_DISASSOC:
skb_queue_tail(&local->work_skb_queue, skb);
ieee80211_queue_work(&local->hw, &local->work_work);
return RX_QUEUED;

View file

@ -31,8 +31,8 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
unsigned int hdrlen;
struct ieee80211_hdr *hdr;
struct sk_buff *skb = tx->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int authenticator;
int wpa_test = 0;
int tail;
hdr = (struct ieee80211_hdr *)skb->data;
@ -47,16 +47,15 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
data = skb->data + hdrlen;
data_len = skb->len - hdrlen;
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
if (info->control.hw_key &&
!(tx->flags & IEEE80211_TX_FRAGMENTED) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) &&
!wpa_test) {
/* hwaccel - with no need for preallocated room for MMIC */
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) {
/* hwaccel - with no need for SW-generated MMIC */
return TX_CONTINUE;
}
tail = MICHAEL_MIC_LEN;
if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
if (!info->control.hw_key)
tail += TKIP_ICV_LEN;
if (WARN_ON(skb_tailroom(skb) < tail ||
@ -147,17 +146,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
int len, tail;
u8 *pos;
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
/* hwaccel - with no need for preallocated room for IV/ICV */
info->control.hw_key = &tx->key->conf;
if (info->control.hw_key &&
!(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
/* hwaccel - with no need for software-generated IV */
return 0;
}
hdrlen = ieee80211_hdrlen(hdr->frame_control);
len = skb->len - hdrlen;
if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
if (info->control.hw_key)
tail = 0;
else
tail = TKIP_ICV_LEN;
@ -175,13 +173,11 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
if (key->u.tkip.tx.iv16 == 0)
key->u.tkip.tx.iv32++;
if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
/* hwaccel - with preallocated room for IV */
ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
pos = ieee80211_tkip_add_iv(pos, key, key->u.tkip.tx.iv16);
info->control.hw_key = &tx->key->conf;
/* hwaccel - with software IV */
if (info->control.hw_key)
return 0;
}
/* Add room for ICV */
skb_put(skb, TKIP_ICV_LEN);
@ -363,24 +359,20 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
int hdrlen, len, tail;
u8 *pos, *pn;
int i;
bool skip_hw;
skip_hw = (tx->key->conf.flags & IEEE80211_KEY_FLAG_SW_MGMT) &&
ieee80211_is_mgmt(hdr->frame_control);
if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
!(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
!skip_hw) {
/* hwaccel - with no need for preallocated room for CCMP
* header or MIC fields */
info->control.hw_key = &tx->key->conf;
if (info->control.hw_key &&
!(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
/*
* hwaccel has no need for preallocated room for CCMP
* header or MIC fields
*/
return 0;
}
hdrlen = ieee80211_hdrlen(hdr->frame_control);
len = skb->len - hdrlen;
if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
if (info->control.hw_key)
tail = 0;
else
tail = CCMP_MIC_LEN;
@ -405,11 +397,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
ccmp_pn2hdr(pos, pn, key->conf.keyidx);
if ((key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !skip_hw) {
/* hwaccel - with preallocated room for CCMP header */
info->control.hw_key = &tx->key->conf;
/* hwaccel - with software CCMP header */
if (info->control.hw_key)
return 0;
}
pos += CCMP_HDR_LEN;
ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0);
@ -525,11 +515,8 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
u8 *pn, aad[20];
int i;
if (tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
/* hwaccel */
info->control.hw_key = &tx->key->conf;
if (info->control.hw_key)
return 0;
}
if (WARN_ON(skb_tailroom(skb) < sizeof(*mmie)))
return TX_DROP;