Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
@@ -552,7 +552,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
|
||||
new->vlan_tci = old->vlan_tci;
|
||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||
new->do_not_encrypt = old->do_not_encrypt;
|
||||
new->requeue = old->requeue;
|
||||
#endif
|
||||
|
||||
skb_copy_secmark(new, old);
|
||||
|
@@ -132,6 +132,9 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
|
||||
|
||||
state = &sta->ampdu_mlme.tid_state_tx[tid];
|
||||
|
||||
if (*state == HT_AGG_STATE_OPERATIONAL)
|
||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||
|
||||
*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
|
||||
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
|
||||
|
||||
@@ -337,6 +340,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||
sta->ampdu_mlme.tid_tx[tid]->dialog_token,
|
||||
sta->ampdu_mlme.tid_tx[tid]->ssn,
|
||||
0x40, 5000);
|
||||
sta->ampdu_mlme.addba_req_num[tid]++;
|
||||
/* activate the timer for the recipient's addBA response */
|
||||
sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
|
||||
jiffies + ADDBA_RESP_INTERVAL;
|
||||
@@ -606,7 +610,6 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
|
||||
|
||||
*state = HT_AGG_STATE_IDLE;
|
||||
/* from now on packets are no longer put onto sta->pending */
|
||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||
kfree(sta->ampdu_mlme.tid_tx[tid]);
|
||||
sta->ampdu_mlme.tid_tx[tid] = NULL;
|
||||
|
||||
@@ -689,7 +692,6 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
|
||||
|
||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||
} else {
|
||||
sta->ampdu_mlme.addba_req_num[tid]++;
|
||||
___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
|
||||
}
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
@@ -1122,8 +1122,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
|
||||
p.txop = params->txop;
|
||||
if (drv_conf_tx(local, params->queue, &p)) {
|
||||
printk(KERN_DEBUG "%s: failed to set TX queue "
|
||||
"parameters for queue %d\n", local->mdev->name,
|
||||
params->queue);
|
||||
"parameters for queue %d\n",
|
||||
wiphy_name(local->hw.wiphy), params->queue);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@@ -589,6 +589,7 @@ enum queue_stop_reason {
|
||||
IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
|
||||
IEEE80211_QUEUE_STOP_REASON_PENDING,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
|
||||
};
|
||||
|
||||
struct ieee80211_master_priv {
|
||||
@@ -1121,6 +1122,10 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
|
||||
enum queue_stop_reason reason);
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb);
|
||||
int ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs);
|
||||
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg,
|
||||
|
@@ -369,60 +369,12 @@ static void ieee80211_tasklet_handler(unsigned long data)
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove added headers (e.g., QoS control), encryption header/MIC, etc. to
|
||||
* make a prepared TX frame (one that has been given to hw) to look like brand
|
||||
* new IEEE 802.11 frame that is ready to go through TX processing again.
|
||||
*/
|
||||
static void ieee80211_remove_tx_extra(struct ieee80211_local *local,
|
||||
struct ieee80211_key *key,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
unsigned int hdrlen, iv_len, mic_len;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
hdrlen = ieee80211_hdrlen(hdr->frame_control);
|
||||
|
||||
if (!key)
|
||||
goto no_key;
|
||||
|
||||
switch (key->conf.alg) {
|
||||
case ALG_WEP:
|
||||
iv_len = WEP_IV_LEN;
|
||||
mic_len = WEP_ICV_LEN;
|
||||
break;
|
||||
case ALG_TKIP:
|
||||
iv_len = TKIP_IV_LEN;
|
||||
mic_len = TKIP_ICV_LEN;
|
||||
break;
|
||||
case ALG_CCMP:
|
||||
iv_len = CCMP_HDR_LEN;
|
||||
mic_len = CCMP_MIC_LEN;
|
||||
break;
|
||||
default:
|
||||
goto no_key;
|
||||
}
|
||||
|
||||
if (skb->len >= hdrlen + mic_len &&
|
||||
!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
|
||||
skb_trim(skb, skb->len - mic_len);
|
||||
if (skb->len >= hdrlen + iv_len) {
|
||||
memmove(skb->data + iv_len, skb->data, hdrlen);
|
||||
hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len);
|
||||
}
|
||||
|
||||
no_key:
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
|
||||
memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data,
|
||||
hdrlen - IEEE80211_QOS_CTL_LEN);
|
||||
skb_pull(skb, IEEE80211_QOS_CTL_LEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
struct sta_info *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
sta->tx_filtered_count++;
|
||||
|
||||
/*
|
||||
@@ -464,16 +416,15 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||
*/
|
||||
if (test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||
skb_queue_tail(&sta->tx_filtered, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) {
|
||||
if (!test_sta_flags(sta, WLAN_STA_PS) &&
|
||||
!(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
|
||||
/* Software retry the packet once */
|
||||
skb->requeue = 1;
|
||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||
dev_queue_xmit(skb);
|
||||
info->flags |= IEEE80211_TX_INTFL_RETRIED;
|
||||
ieee80211_add_pending_skb(local, skb);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -621,9 +621,6 @@ static void ieee80211_change_ps(struct ieee80211_local *local)
|
||||
struct ieee80211_conf *conf = &local->hw.conf;
|
||||
|
||||
if (local->ps_sdata) {
|
||||
if (!(local->ps_sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED))
|
||||
return;
|
||||
|
||||
ieee80211_enable_ps(local, local->ps_sdata);
|
||||
} else if (conf->flags & IEEE80211_CONF_PS) {
|
||||
conf->flags &= ~IEEE80211_CONF_PS;
|
||||
@@ -653,7 +650,9 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
|
||||
count++;
|
||||
}
|
||||
|
||||
if (count == 1 && found->u.mgd.powersave) {
|
||||
if (count == 1 && found->u.mgd.powersave &&
|
||||
(found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) &&
|
||||
!(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
|
||||
s32 beaconint_us;
|
||||
|
||||
if (latency < 0)
|
||||
@@ -793,13 +792,13 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
|
||||
printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
|
||||
"cWmin=%d cWmax=%d txop=%d\n",
|
||||
local->mdev->name, queue, aci, acm, params.aifs, params.cw_min,
|
||||
params.cw_max, params.txop);
|
||||
wiphy_name(local->hw.wiphy), queue, aci, acm,
|
||||
params.aifs, params.cw_min, params.cw_max, params.txop);
|
||||
#endif
|
||||
if (drv_conf_tx(local, queue, ¶ms) && local->ops->conf_tx)
|
||||
printk(KERN_DEBUG "%s: failed to set TX queue "
|
||||
"parameters for queue %d\n", local->mdev->name,
|
||||
queue);
|
||||
"parameters for queue %d\n",
|
||||
wiphy_name(local->hw.wiphy), queue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1322,6 +1321,11 @@ void ieee80211_beacon_loss_work(struct work_struct *work)
|
||||
#endif
|
||||
|
||||
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
||||
|
||||
mutex_lock(&sdata->local->iflist_mtx);
|
||||
ieee80211_recalc_ps(sdata->local, -1);
|
||||
mutex_unlock(&sdata->local->iflist_mtx);
|
||||
|
||||
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
||||
ifmgd->ssid_len, NULL, 0);
|
||||
|
||||
@@ -1342,6 +1346,7 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
unsigned long last_rx;
|
||||
bool disassoc = false;
|
||||
|
||||
/* TODO: start monitoring current AP signal quality and number of
|
||||
@@ -1358,17 +1363,21 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
||||
printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n",
|
||||
sdata->dev->name, ifmgd->bssid);
|
||||
disassoc = true;
|
||||
goto unlock;
|
||||
rcu_read_unlock();
|
||||
goto out;
|
||||
}
|
||||
|
||||
last_rx = sta->last_rx;
|
||||
rcu_read_unlock();
|
||||
|
||||
if ((ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) &&
|
||||
time_after(jiffies, sta->last_rx + IEEE80211_PROBE_WAIT)) {
|
||||
time_after(jiffies, last_rx + IEEE80211_PROBE_WAIT)) {
|
||||
printk(KERN_DEBUG "%s: no probe response from AP %pM "
|
||||
"- disassociating\n",
|
||||
sdata->dev->name, ifmgd->bssid);
|
||||
disassoc = true;
|
||||
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1387,26 +1396,29 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
|
||||
}
|
||||
#endif
|
||||
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
||||
ifmgd->ssid_len, NULL, 0);
|
||||
mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
|
||||
goto unlock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
|
||||
if (time_after(jiffies, last_rx + IEEE80211_PROBE_IDLE_TIME)) {
|
||||
ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
|
||||
ifmgd->ssid_len, NULL, 0);
|
||||
}
|
||||
|
||||
out:
|
||||
if (!disassoc)
|
||||
mod_timer(&ifmgd->timer,
|
||||
jiffies + IEEE80211_MONITORING_INTERVAL);
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
|
||||
if (disassoc)
|
||||
else
|
||||
ieee80211_set_disassoc(sdata, true, true,
|
||||
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
||||
}
|
||||
@@ -1889,8 +1901,12 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_authenticate(sdata);
|
||||
}
|
||||
|
||||
if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
|
||||
if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
|
||||
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&sdata->local->iflist_mtx);
|
||||
ieee80211_recalc_ps(sdata->local, -1);
|
||||
mutex_unlock(&sdata->local->iflist_mtx);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1948,6 +1964,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
#endif
|
||||
ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
|
||||
mutex_lock(&local->iflist_mtx);
|
||||
ieee80211_recalc_ps(local, -1);
|
||||
mutex_unlock(&local->iflist_mtx);
|
||||
}
|
||||
|
||||
ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
|
||||
|
@@ -215,7 +215,7 @@ minstrel_get_next_sample(struct minstrel_sta_info *mi)
|
||||
unsigned int sample_ndx;
|
||||
sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column);
|
||||
mi->sample_idx++;
|
||||
if (mi->sample_idx > (mi->n_rates - 2)) {
|
||||
if ((int) mi->sample_idx > (mi->n_rates - 2)) {
|
||||
mi->sample_idx = 0;
|
||||
mi->sample_column++;
|
||||
if (mi->sample_column >= SAMPLE_COLUMNS)
|
||||
|
@@ -797,8 +797,7 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
int sent = 0;
|
||||
int sent, buffered;
|
||||
|
||||
atomic_dec(&sdata->bss->num_sta_ps);
|
||||
|
||||
@@ -814,22 +813,16 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
|
||||
/* Send all buffered frames to the station */
|
||||
while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
|
||||
sent++;
|
||||
skb->requeue = 1;
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
|
||||
local->total_ps_buffered--;
|
||||
sent++;
|
||||
sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
|
||||
buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
|
||||
sent += buffered;
|
||||
local->total_ps_buffered -= buffered;
|
||||
|
||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||
printk(KERN_DEBUG "%s: STA %pM aid %d send PS frame "
|
||||
"since STA not sleeping anymore\n", sdata->dev->name,
|
||||
sta->sta.addr, sta->sta.aid);
|
||||
printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
|
||||
"since STA not sleeping anymore\n", sdata->dev->name,
|
||||
sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
|
||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||
skb->requeue = 1;
|
||||
dev_queue_xmit(skb);
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
@@ -1335,7 +1328,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
||||
* mac80211. That also explains the __skb_push()
|
||||
* below.
|
||||
*/
|
||||
align = (unsigned long)skb->data & 3;
|
||||
align = ((unsigned long)(skb->data + sizeof(struct ethhdr))) & 3;
|
||||
if (align) {
|
||||
if (WARN_ON(skb_headroom(skb) < 3)) {
|
||||
dev_kfree_skb(skb);
|
||||
|
@@ -400,6 +400,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
sta_info_set_tim_bit(sta);
|
||||
|
||||
info->control.jiffies = jiffies;
|
||||
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
|
||||
skb_queue_tail(&sta->ps_tx_buf, tx->skb);
|
||||
return TX_QUEUED;
|
||||
}
|
||||
@@ -420,7 +421,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
|
||||
* frame filtering and keeps a station blacklist on its own
|
||||
* (e.g: p54), so that frames can be delivered unimpeded.
|
||||
*
|
||||
* Note: It should be save to disable the filter now.
|
||||
* Note: It should be safe to disable the filter now.
|
||||
* As, it is really unlikely that we still have any pending
|
||||
* frame for this station in the hw's buffers/fifos left,
|
||||
* that is not rejected with a unsuccessful tx_status yet.
|
||||
@@ -907,9 +908,8 @@ ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
|
||||
* deal with packet injection down monitor interface
|
||||
* with Radiotap Header -- only called for monitor mode interface
|
||||
*/
|
||||
static ieee80211_tx_result
|
||||
__ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb)
|
||||
static bool __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
/*
|
||||
* this is the moment to interpret and discard the radiotap header that
|
||||
@@ -960,7 +960,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
* on transmission
|
||||
*/
|
||||
if (skb->len < (iterator.max_length + FCS_LEN))
|
||||
return TX_DROP;
|
||||
return false;
|
||||
|
||||
skb_trim(skb, skb->len - FCS_LEN);
|
||||
}
|
||||
@@ -982,7 +982,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
}
|
||||
|
||||
if (ret != -ENOENT) /* ie, if we didn't simply run out of fields */
|
||||
return TX_DROP;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* remove the radiotap header
|
||||
@@ -991,7 +991,7 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx,
|
||||
*/
|
||||
skb_pull(skb, iterator.max_length);
|
||||
|
||||
return TX_CONTINUE;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1025,7 +1025,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||
/* process and remove the injection radiotap header */
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) {
|
||||
if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP)
|
||||
if (!__ieee80211_parse_tx_radiotap(tx, skb))
|
||||
return TX_DROP;
|
||||
|
||||
/*
|
||||
@@ -1415,7 +1415,8 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
}
|
||||
|
||||
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
|
||||
local->hw.conf.dynamic_ps_timeout > 0) {
|
||||
local->hw.conf.dynamic_ps_timeout > 0 &&
|
||||
!local->sw_scanning && !local->hw_scanning && local->ps_sdata) {
|
||||
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
|
||||
ieee80211_stop_queues_by_reason(&local->hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_PS);
|
||||
|
@@ -341,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_stop_queue);
|
||||
|
||||
void ieee80211_add_pending_skb(struct ieee80211_local *local,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
unsigned long flags;
|
||||
int queue = skb_get_queue_mapping(skb);
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
__ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING);
|
||||
skb_queue_tail(&local->pending[queue], skb);
|
||||
__ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
}
|
||||
|
||||
int ieee80211_add_pending_skbs(struct ieee80211_local *local,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
struct ieee80211_hw *hw = &local->hw;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int queue, ret = 0, i;
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
for (i = 0; i < hw->queues; i++)
|
||||
__ieee80211_stop_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
|
||||
while ((skb = skb_dequeue(skbs))) {
|
||||
ret++;
|
||||
queue = skb_get_queue_mapping(skb);
|
||||
skb_queue_tail(&local->pending[queue], skb);
|
||||
}
|
||||
|
||||
for (i = 0; i < hw->queues; i++) {
|
||||
if (ret)
|
||||
__ieee80211_stop_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_PENDING);
|
||||
__ieee80211_wake_queue(hw, i,
|
||||
IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
|
||||
}
|
||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
|
||||
enum queue_stop_reason reason)
|
||||
{
|
||||
|
@@ -101,7 +101,7 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||
* Now we know the 1d priority, fill in the QoS header if
|
||||
* there is one (and we haven't done this before).
|
||||
*/
|
||||
if (!skb->requeue && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
if (ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
u8 *p = ieee80211_get_qos_ctl(hdr);
|
||||
u8 ack_policy = 0;
|
||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
|
@@ -18,7 +18,7 @@ config RFKILL_LEDS
|
||||
default y
|
||||
|
||||
config RFKILL_INPUT
|
||||
bool "RF switch input support"
|
||||
bool "RF switch input support" if EMBEDDED
|
||||
depends on RFKILL
|
||||
depends on INPUT = y || RFKILL = INPUT
|
||||
default y if !EMBEDDED
|
||||
|
@@ -57,6 +57,7 @@ struct rfkill {
|
||||
|
||||
bool registered;
|
||||
bool suspended;
|
||||
bool persistent;
|
||||
|
||||
const struct rfkill_ops *ops;
|
||||
void *data;
|
||||
@@ -116,11 +117,9 @@ MODULE_PARM_DESC(default_state,
|
||||
"Default initial state for all radio types, 0 = radio off");
|
||||
|
||||
static struct {
|
||||
bool cur, def;
|
||||
bool cur, sav;
|
||||
} rfkill_global_states[NUM_RFKILL_TYPES];
|
||||
|
||||
static unsigned long rfkill_states_default_locked;
|
||||
|
||||
static bool rfkill_epo_lock_active;
|
||||
|
||||
|
||||
@@ -392,7 +391,7 @@ void rfkill_epo(void)
|
||||
rfkill_set_block(rfkill, true);
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++) {
|
||||
rfkill_global_states[i].def = rfkill_global_states[i].cur;
|
||||
rfkill_global_states[i].sav = rfkill_global_states[i].cur;
|
||||
rfkill_global_states[i].cur = true;
|
||||
}
|
||||
|
||||
@@ -417,7 +416,7 @@ void rfkill_restore_states(void)
|
||||
|
||||
rfkill_epo_lock_active = false;
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
__rfkill_switch_all(i, rfkill_global_states[i].def);
|
||||
__rfkill_switch_all(i, rfkill_global_states[i].sav);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
|
||||
@@ -464,29 +463,6 @@ bool rfkill_get_global_sw_state(const enum rfkill_type type)
|
||||
}
|
||||
#endif
|
||||
|
||||
void rfkill_set_global_sw_state(const enum rfkill_type type, bool blocked)
|
||||
{
|
||||
BUG_ON(type == RFKILL_TYPE_ALL);
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
|
||||
/* don't allow unblock when epo */
|
||||
if (rfkill_epo_lock_active && !blocked)
|
||||
goto out;
|
||||
|
||||
/* too late */
|
||||
if (rfkill_states_default_locked & BIT(type))
|
||||
goto out;
|
||||
|
||||
rfkill_states_default_locked |= BIT(type);
|
||||
|
||||
rfkill_global_states[type].cur = blocked;
|
||||
rfkill_global_states[type].def = blocked;
|
||||
out:
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_global_sw_state);
|
||||
|
||||
|
||||
bool rfkill_set_hw_state(struct rfkill *rfkill, bool blocked)
|
||||
{
|
||||
@@ -532,13 +508,14 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
|
||||
blocked = blocked || hwblock;
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
if (!rfkill->registered)
|
||||
return blocked;
|
||||
if (!rfkill->registered) {
|
||||
rfkill->persistent = true;
|
||||
} else {
|
||||
if (prev != blocked && !hwblock)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
if (prev != blocked && !hwblock)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
}
|
||||
|
||||
return blocked;
|
||||
}
|
||||
@@ -563,13 +540,14 @@ void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
|
||||
|
||||
spin_unlock_irqrestore(&rfkill->lock, flags);
|
||||
|
||||
if (!rfkill->registered)
|
||||
return;
|
||||
if (!rfkill->registered) {
|
||||
rfkill->persistent = true;
|
||||
} else {
|
||||
if (swprev != sw || hwprev != hw)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
if (swprev != sw || hwprev != hw)
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
rfkill_led_trigger_event(rfkill);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(rfkill_set_states);
|
||||
|
||||
@@ -750,15 +728,11 @@ static int rfkill_resume(struct device *dev)
|
||||
struct rfkill *rfkill = to_rfkill(dev);
|
||||
bool cur;
|
||||
|
||||
mutex_lock(&rfkill_global_mutex);
|
||||
cur = rfkill_global_states[rfkill->type].cur;
|
||||
cur = !!(rfkill->state & RFKILL_BLOCK_SW);
|
||||
rfkill_set_block(rfkill, cur);
|
||||
mutex_unlock(&rfkill_global_mutex);
|
||||
|
||||
rfkill->suspended = false;
|
||||
|
||||
schedule_work(&rfkill->uevent_work);
|
||||
|
||||
rfkill_resume_polling(rfkill);
|
||||
|
||||
return 0;
|
||||
@@ -888,15 +862,6 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
dev_set_name(dev, "rfkill%lu", rfkill_no);
|
||||
rfkill_no++;
|
||||
|
||||
if (!(rfkill_states_default_locked & BIT(rfkill->type))) {
|
||||
/* first of its kind */
|
||||
BUILD_BUG_ON(NUM_RFKILL_TYPES >
|
||||
sizeof(rfkill_states_default_locked) * 8);
|
||||
rfkill_states_default_locked |= BIT(rfkill->type);
|
||||
rfkill_global_states[rfkill->type].cur =
|
||||
rfkill_global_states[rfkill->type].def;
|
||||
}
|
||||
|
||||
list_add_tail(&rfkill->node, &rfkill_list);
|
||||
|
||||
error = device_add(dev);
|
||||
@@ -916,7 +881,17 @@ int __must_check rfkill_register(struct rfkill *rfkill)
|
||||
if (rfkill->ops->poll)
|
||||
schedule_delayed_work(&rfkill->poll_work,
|
||||
round_jiffies_relative(POLL_INTERVAL));
|
||||
schedule_work(&rfkill->sync_work);
|
||||
|
||||
if (!rfkill->persistent || rfkill_epo_lock_active) {
|
||||
schedule_work(&rfkill->sync_work);
|
||||
} else {
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
bool soft_blocked = !!(rfkill->state & RFKILL_BLOCK_SW);
|
||||
|
||||
if (!atomic_read(&rfkill_input_disabled))
|
||||
__rfkill_switch_all(rfkill->type, soft_blocked);
|
||||
#endif
|
||||
}
|
||||
|
||||
rfkill_send_events(rfkill, RFKILL_OP_ADD);
|
||||
|
||||
@@ -1134,7 +1109,8 @@ static int rfkill_fop_release(struct inode *inode, struct file *file)
|
||||
|
||||
#ifdef CONFIG_RFKILL_INPUT
|
||||
if (data->input_handler)
|
||||
atomic_dec(&rfkill_input_disabled);
|
||||
if (atomic_dec_return(&rfkill_input_disabled) == 0)
|
||||
printk(KERN_DEBUG "rfkill: input handler enabled\n");
|
||||
#endif
|
||||
|
||||
kfree(data);
|
||||
@@ -1157,7 +1133,8 @@ static long rfkill_fop_ioctl(struct file *file, unsigned int cmd,
|
||||
mutex_lock(&data->mtx);
|
||||
|
||||
if (!data->input_handler) {
|
||||
atomic_inc(&rfkill_input_disabled);
|
||||
if (atomic_inc_return(&rfkill_input_disabled) == 1)
|
||||
printk(KERN_DEBUG "rfkill: input handler disabled\n");
|
||||
data->input_handler = true;
|
||||
}
|
||||
|
||||
@@ -1191,7 +1168,7 @@ static int __init rfkill_init(void)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_RFKILL_TYPES; i++)
|
||||
rfkill_global_states[i].def = !rfkill_default_state;
|
||||
rfkill_global_states[i].cur = !rfkill_default_state;
|
||||
|
||||
error = class_register(&rfkill_class);
|
||||
if (error)
|
||||
|
@@ -395,21 +395,23 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
/* check and set up bitrates */
|
||||
ieee80211_set_bitrate_flags(wiphy);
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/* set up regulatory info */
|
||||
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
|
||||
|
||||
res = device_add(&drv->wiphy.dev);
|
||||
if (res)
|
||||
goto out_unlock;
|
||||
return res;
|
||||
|
||||
res = rfkill_register(drv->rfkill);
|
||||
if (res)
|
||||
goto out_rm_dev;
|
||||
|
||||
mutex_lock(&cfg80211_mutex);
|
||||
|
||||
/* set up regulatory info */
|
||||
wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
|
||||
|
||||
list_add(&drv->list, &cfg80211_drv_list);
|
||||
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
|
||||
/* add to debugfs */
|
||||
drv->wiphy.debugfsdir =
|
||||
debugfs_create_dir(wiphy_name(&drv->wiphy),
|
||||
@@ -430,13 +432,10 @@ int wiphy_register(struct wiphy *wiphy)
|
||||
|
||||
cfg80211_debugfs_drv_add(drv);
|
||||
|
||||
res = 0;
|
||||
goto out_unlock;
|
||||
return 0;
|
||||
|
||||
out_rm_dev:
|
||||
device_del(&drv->wiphy.dev);
|
||||
out_unlock:
|
||||
mutex_unlock(&cfg80211_mutex);
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(wiphy_register);
|
||||
|
@@ -2129,7 +2129,12 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
|
||||
* driver wanted to the wiphy to deal with conflicts
|
||||
*/
|
||||
|
||||
BUG_ON(request_wiphy->regd);
|
||||
/*
|
||||
* Userspace could have sent two replies with only
|
||||
* one kernel request.
|
||||
*/
|
||||
if (request_wiphy->regd)
|
||||
return -EALREADY;
|
||||
|
||||
r = reg_copy_regd(&request_wiphy->regd, rd);
|
||||
if (r)
|
||||
|
Reference in New Issue
Block a user