mac80211: Re-enable aggregation
Wireless HW without any dedicated queues for aggregation do not need the ampdu_queues mechanism present right now in mac80211. Since mac80211 is still incomplete wrt TX MQ changes, do not allow aggregation sessions for drivers that set ampdu_queues. This is only an interim hack until Intel fixes the requeue issue. Signed-off-by: Sujith <Sujith.Manoharan@atheros.com> Signed-off-by: Luis Rodriguez <Luis.Rodriguez@Atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
4393dce940
commit
8b30b1fe36
|
@ -953,10 +953,7 @@ static int ath_attach(u16 devid,
|
||||||
&sc->sbands[IEEE80211_BAND_5GHZ];
|
&sc->sbands[IEEE80211_BAND_5GHZ];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Have to figure out proper hw init values later */
|
|
||||||
|
|
||||||
hw->queues = 4;
|
hw->queues = 4;
|
||||||
hw->ampdu_queues = 1;
|
|
||||||
|
|
||||||
/* Register rate control */
|
/* Register rate control */
|
||||||
hw->rate_control_algorithm = "ath9k_rate_control";
|
hw->rate_control_algorithm = "ath9k_rate_control";
|
||||||
|
@ -1745,7 +1742,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||||
IEEE80211_HW_SIGNAL_DBM |
|
IEEE80211_HW_SIGNAL_DBM |
|
||||||
IEEE80211_HW_NOISE_DBM;
|
IEEE80211_HW_NOISE_DBM |
|
||||||
|
IEEE80211_HW_AMPDU_AGGREGATION;
|
||||||
|
|
||||||
hw->wiphy->interface_modes =
|
hw->wiphy->interface_modes =
|
||||||
BIT(NL80211_IFTYPE_AP) |
|
BIT(NL80211_IFTYPE_AP) |
|
||||||
|
|
|
@ -871,7 +871,8 @@ int iwl_setup_mac(struct iwl_priv *priv)
|
||||||
|
|
||||||
/* Tell mac80211 our characteristics */
|
/* Tell mac80211 our characteristics */
|
||||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||||
IEEE80211_HW_NOISE_DBM;
|
IEEE80211_HW_NOISE_DBM |
|
||||||
|
IEEE80211_HW_AMPDU_AGGREGATION;
|
||||||
hw->wiphy->interface_modes =
|
hw->wiphy->interface_modes =
|
||||||
BIT(NL80211_IFTYPE_AP) |
|
BIT(NL80211_IFTYPE_AP) |
|
||||||
BIT(NL80211_IFTYPE_STATION) |
|
BIT(NL80211_IFTYPE_STATION) |
|
||||||
|
|
|
@ -250,6 +250,9 @@ typedef unsigned char *sk_buff_data_t;
|
||||||
* @tc_verd: traffic control verdict
|
* @tc_verd: traffic control verdict
|
||||||
* @ndisc_nodetype: router type (from link layer)
|
* @ndisc_nodetype: router type (from link layer)
|
||||||
* @do_not_encrypt: set to prevent encryption of this frame
|
* @do_not_encrypt: set to prevent encryption of this frame
|
||||||
|
* @requeue: set to indicate that the wireless core should attempt
|
||||||
|
* a software retry on this frame if we failed to
|
||||||
|
* receive an ACK for it
|
||||||
* @dma_cookie: a cookie to one of several possible DMA operations
|
* @dma_cookie: a cookie to one of several possible DMA operations
|
||||||
* done by skb DMA functions
|
* done by skb DMA functions
|
||||||
* @secmark: security marking
|
* @secmark: security marking
|
||||||
|
@ -326,6 +329,7 @@ struct sk_buff {
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||||
__u8 do_not_encrypt:1;
|
__u8 do_not_encrypt:1;
|
||||||
|
__u8 requeue:1;
|
||||||
#endif
|
#endif
|
||||||
/* 0/13/14 bit hole */
|
/* 0/13/14 bit hole */
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,6 @@ struct ieee80211_bss_conf {
|
||||||
* @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be
|
* @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be
|
||||||
* set by rate control algorithms to indicate probe rate, will
|
* set by rate control algorithms to indicate probe rate, will
|
||||||
* be cleared for fragmented frames (except on the last fragment)
|
* be cleared for fragmented frames (except on the last fragment)
|
||||||
* @IEEE80211_TX_CTL_REQUEUE: REMOVE THIS
|
|
||||||
*/
|
*/
|
||||||
enum mac80211_tx_control_flags {
|
enum mac80211_tx_control_flags {
|
||||||
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
|
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
|
||||||
|
@ -258,9 +257,6 @@ enum mac80211_tx_control_flags {
|
||||||
IEEE80211_TX_STAT_AMPDU = BIT(10),
|
IEEE80211_TX_STAT_AMPDU = BIT(10),
|
||||||
IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11),
|
IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11),
|
||||||
IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
|
IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12),
|
||||||
|
|
||||||
/* XXX: remove this */
|
|
||||||
IEEE80211_TX_CTL_REQUEUE = BIT(13),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum mac80211_rate_control_flags {
|
enum mac80211_rate_control_flags {
|
||||||
|
@ -847,6 +843,9 @@ enum ieee80211_tkip_key_type {
|
||||||
* @IEEE80211_HW_SPECTRUM_MGMT:
|
* @IEEE80211_HW_SPECTRUM_MGMT:
|
||||||
* Hardware supports spectrum management defined in 802.11h
|
* Hardware supports spectrum management defined in 802.11h
|
||||||
* Measurement, Channel Switch, Quieting, TPC
|
* Measurement, Channel Switch, Quieting, TPC
|
||||||
|
*
|
||||||
|
* @IEEE80211_HW_AMPDU_AGGREGATION:
|
||||||
|
* Hardware supports 11n A-MPDU aggregation.
|
||||||
*/
|
*/
|
||||||
enum ieee80211_hw_flags {
|
enum ieee80211_hw_flags {
|
||||||
IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
|
IEEE80211_HW_RX_INCLUDES_FCS = 1<<1,
|
||||||
|
@ -858,6 +857,7 @@ enum ieee80211_hw_flags {
|
||||||
IEEE80211_HW_SIGNAL_DBM = 1<<7,
|
IEEE80211_HW_SIGNAL_DBM = 1<<7,
|
||||||
IEEE80211_HW_NOISE_DBM = 1<<8,
|
IEEE80211_HW_NOISE_DBM = 1<<8,
|
||||||
IEEE80211_HW_SPECTRUM_MGMT = 1<<9,
|
IEEE80211_HW_SPECTRUM_MGMT = 1<<9,
|
||||||
|
IEEE80211_HW_AMPDU_AGGREGATION = 1<<10,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -544,6 +544,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
|
||||||
C(truesize);
|
C(truesize);
|
||||||
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
#if defined(CONFIG_MAC80211) || defined(CONFIG_MAC80211_MODULE)
|
||||||
C(do_not_encrypt);
|
C(do_not_encrypt);
|
||||||
|
C(requeue);
|
||||||
#endif
|
#endif
|
||||||
atomic_set(&n->users, 1);
|
atomic_set(&n->users, 1);
|
||||||
|
|
||||||
|
|
|
@ -458,7 +458,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||||
u8 *state;
|
u8 *state;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (tid >= STA_TID_NUM)
|
if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
|
@ -515,17 +515,19 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||||
(unsigned long)&sta->timer_to_tid[tid];
|
(unsigned long)&sta->timer_to_tid[tid];
|
||||||
init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
|
init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
|
||||||
|
|
||||||
/* create a new queue for this aggregation */
|
if (hw->ampdu_queues) {
|
||||||
ret = ieee80211_ht_agg_queue_add(local, sta, tid);
|
/* create a new queue for this aggregation */
|
||||||
|
ret = ieee80211_ht_agg_queue_add(local, sta, tid);
|
||||||
|
|
||||||
/* case no queue is available to aggregation
|
/* case no queue is available to aggregation
|
||||||
* don't switch to aggregation */
|
* don't switch to aggregation */
|
||||||
if (ret) {
|
if (ret) {
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
printk(KERN_DEBUG "BA request denied - queue unavailable for"
|
printk(KERN_DEBUG "BA request denied - "
|
||||||
" tid %d\n", tid);
|
"queue unavailable for tid %d\n", tid);
|
||||||
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
||||||
goto err_unlock_queue;
|
goto err_unlock_queue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sdata = sta->sdata;
|
sdata = sta->sdata;
|
||||||
|
|
||||||
|
@ -544,7 +546,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||||
/* No need to requeue the packets in the agg queue, since we
|
/* No need to requeue the packets in the agg queue, since we
|
||||||
* held the tx lock: no packet could be enqueued to the newly
|
* held the tx lock: no packet could be enqueued to the newly
|
||||||
* allocated queue */
|
* allocated queue */
|
||||||
ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
|
if (hw->ampdu_queues)
|
||||||
|
ieee80211_ht_agg_queue_remove(local, sta, tid, 0);
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
printk(KERN_DEBUG "BA request denied - HW unavailable for"
|
printk(KERN_DEBUG "BA request denied - HW unavailable for"
|
||||||
" tid %d\n", tid);
|
" tid %d\n", tid);
|
||||||
|
@ -554,7 +557,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Will put all the packets in the new SW queue */
|
/* Will put all the packets in the new SW queue */
|
||||||
ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
|
if (hw->ampdu_queues)
|
||||||
|
ieee80211_requeue(local, ieee802_1d_to_ac[tid]);
|
||||||
spin_unlock_bh(&sta->lock);
|
spin_unlock_bh(&sta->lock);
|
||||||
|
|
||||||
/* send an addBA request */
|
/* send an addBA request */
|
||||||
|
@ -622,7 +626,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
|
||||||
ra, tid);
|
ra, tid);
|
||||||
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
||||||
|
|
||||||
ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
|
if (hw->ampdu_queues)
|
||||||
|
ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]);
|
||||||
|
|
||||||
*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
|
*state = HT_AGG_STATE_REQ_STOP_BA_MSK |
|
||||||
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
|
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
|
||||||
|
@ -635,7 +640,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
|
||||||
if (ret) {
|
if (ret) {
|
||||||
WARN_ON(ret != -EBUSY);
|
WARN_ON(ret != -EBUSY);
|
||||||
*state = HT_AGG_STATE_OPERATIONAL;
|
*state = HT_AGG_STATE_OPERATIONAL;
|
||||||
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
|
if (hw->ampdu_queues)
|
||||||
|
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
|
||||||
goto stop_BA_exit;
|
goto stop_BA_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,7 +697,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
||||||
#ifdef CONFIG_MAC80211_HT_DEBUG
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
||||||
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
|
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
|
||||||
#endif
|
#endif
|
||||||
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
|
if (hw->ampdu_queues)
|
||||||
|
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&sta->lock);
|
spin_unlock_bh(&sta->lock);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -745,16 +752,18 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
|
||||||
ieee80211_send_delba(sta->sdata, ra, tid,
|
ieee80211_send_delba(sta->sdata, ra, tid,
|
||||||
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
|
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
|
||||||
|
|
||||||
agg_queue = sta->tid_to_tx_q[tid];
|
if (hw->ampdu_queues) {
|
||||||
|
agg_queue = sta->tid_to_tx_q[tid];
|
||||||
|
ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
|
||||||
|
|
||||||
ieee80211_ht_agg_queue_remove(local, sta, tid, 1);
|
/* We just requeued the all the frames that were in the
|
||||||
|
* removed queue, and since we might miss a softirq we do
|
||||||
/* We just requeued the all the frames that were in the
|
* netif_schedule_queue. ieee80211_wake_queue is not used
|
||||||
* removed queue, and since we might miss a softirq we do
|
* here as this queue is not necessarily stopped
|
||||||
* netif_schedule_queue. ieee80211_wake_queue is not used
|
*/
|
||||||
* here as this queue is not necessarily stopped
|
netif_schedule_queue(netdev_get_tx_queue(local->mdev,
|
||||||
*/
|
agg_queue));
|
||||||
netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue));
|
}
|
||||||
spin_lock_bh(&sta->lock);
|
spin_lock_bh(&sta->lock);
|
||||||
*state = HT_AGG_STATE_IDLE;
|
*state = HT_AGG_STATE_IDLE;
|
||||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||||
|
@ -1011,7 +1020,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
|
||||||
*state |= HT_ADDBA_RECEIVED_MSK;
|
*state |= HT_ADDBA_RECEIVED_MSK;
|
||||||
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
sta->ampdu_mlme.addba_req_num[tid] = 0;
|
||||||
|
|
||||||
if (*state == HT_AGG_STATE_OPERATIONAL)
|
if (*state == HT_AGG_STATE_OPERATIONAL &&
|
||||||
|
local->hw.ampdu_queues)
|
||||||
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
|
ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]);
|
||||||
|
|
||||||
spin_unlock_bh(&sta->lock);
|
spin_unlock_bh(&sta->lock);
|
||||||
|
|
|
@ -386,8 +386,6 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||||
struct sta_info *sta,
|
struct sta_info *sta,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
||||||
|
|
||||||
sta->tx_filtered_count++;
|
sta->tx_filtered_count++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -434,10 +432,9 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!test_sta_flags(sta, WLAN_STA_PS) &&
|
if (!test_sta_flags(sta, WLAN_STA_PS) && !skb->requeue) {
|
||||||
!(info->flags & IEEE80211_TX_CTL_REQUEUE)) {
|
|
||||||
/* Software retry the packet once */
|
/* Software retry the packet once */
|
||||||
info->flags |= IEEE80211_TX_CTL_REQUEUE;
|
skb->requeue = 1;
|
||||||
ieee80211_remove_tx_extra(local, sta->key, skb);
|
ieee80211_remove_tx_extra(local, sta->key, skb);
|
||||||
dev_queue_xmit(skb);
|
dev_queue_xmit(skb);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -669,7 +669,6 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
struct ieee80211_tx_info *info;
|
|
||||||
|
|
||||||
atomic_dec(&sdata->bss->num_sta_ps);
|
atomic_dec(&sdata->bss->num_sta_ps);
|
||||||
|
|
||||||
|
@ -685,13 +684,11 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||||
|
|
||||||
/* Send all buffered frames to the station */
|
/* Send all buffered frames to the station */
|
||||||
while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
|
while ((skb = skb_dequeue(&sta->tx_filtered)) != NULL) {
|
||||||
info = IEEE80211_SKB_CB(skb);
|
|
||||||
sent++;
|
sent++;
|
||||||
info->flags |= IEEE80211_TX_CTL_REQUEUE;
|
skb->requeue = 1;
|
||||||
dev_queue_xmit(skb);
|
dev_queue_xmit(skb);
|
||||||
}
|
}
|
||||||
while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
|
while ((skb = skb_dequeue(&sta->ps_tx_buf)) != NULL) {
|
||||||
info = IEEE80211_SKB_CB(skb);
|
|
||||||
local->total_ps_buffered--;
|
local->total_ps_buffered--;
|
||||||
sent++;
|
sent++;
|
||||||
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
|
||||||
|
@ -699,7 +696,7 @@ static int ap_sta_ps_end(struct sta_info *sta)
|
||||||
"since STA not sleeping anymore\n", sdata->dev->name,
|
"since STA not sleeping anymore\n", sdata->dev->name,
|
||||||
sta->sta.addr, sta->sta.aid);
|
sta->sta.addr, sta->sta.aid);
|
||||||
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
|
||||||
info->flags |= IEEE80211_TX_CTL_REQUEUE;
|
skb->requeue = 1;
|
||||||
dev_queue_xmit(skb);
|
dev_queue_xmit(skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -661,6 +661,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
|
||||||
static ieee80211_tx_result debug_noinline
|
static ieee80211_tx_result debug_noinline
|
||||||
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
|
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
|
||||||
{
|
{
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
|
||||||
size_t hdrlen, per_fragm, num_fragm, payload_len, left;
|
size_t hdrlen, per_fragm, num_fragm, payload_len, left;
|
||||||
struct sk_buff **frags, *first, *frag;
|
struct sk_buff **frags, *first, *frag;
|
||||||
|
@ -677,9 +678,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
|
||||||
* This scenario is handled in __ieee80211_tx_prepare but extra
|
* This scenario is handled in __ieee80211_tx_prepare but extra
|
||||||
* caution taken here as fragmented ampdu may cause Tx stop.
|
* caution taken here as fragmented ampdu may cause Tx stop.
|
||||||
*/
|
*/
|
||||||
if (WARN_ON(tx->flags & IEEE80211_TX_CTL_AMPDU ||
|
if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
|
||||||
skb_get_queue_mapping(tx->skb) >=
|
|
||||||
ieee80211_num_regular_queues(&tx->local->hw)))
|
|
||||||
return TX_DROP;
|
return TX_DROP;
|
||||||
|
|
||||||
first = tx->skb;
|
first = tx->skb;
|
||||||
|
@ -951,7 +950,8 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||||
|
|
||||||
int hdrlen;
|
int hdrlen, tid;
|
||||||
|
u8 *qc, *state;
|
||||||
|
|
||||||
memset(tx, 0, sizeof(*tx));
|
memset(tx, 0, sizeof(*tx));
|
||||||
tx->skb = skb;
|
tx->skb = skb;
|
||||||
|
@ -982,6 +982,15 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
||||||
|
|
||||||
tx->sta = sta_info_get(local, hdr->addr1);
|
tx->sta = sta_info_get(local, hdr->addr1);
|
||||||
|
|
||||||
|
if (tx->sta && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||||
|
qc = ieee80211_get_qos_ctl(hdr);
|
||||||
|
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
|
||||||
|
|
||||||
|
state = &tx->sta->ampdu_mlme.tid_state_tx[tid];
|
||||||
|
if (*state == HT_AGG_STATE_OPERATIONAL)
|
||||||
|
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||||
tx->flags &= ~IEEE80211_TX_UNICAST;
|
tx->flags &= ~IEEE80211_TX_UNICAST;
|
||||||
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
info->flags |= IEEE80211_TX_CTL_NO_ACK;
|
||||||
|
@ -1172,7 +1181,7 @@ retry:
|
||||||
* queues, there's no reason for a driver to reject
|
* queues, there's no reason for a driver to reject
|
||||||
* a frame there, warn and drop it.
|
* a frame there, warn and drop it.
|
||||||
*/
|
*/
|
||||||
if (WARN_ON(queue >= ieee80211_num_regular_queues(&local->hw)))
|
if (WARN_ON(info->flags & IEEE80211_TX_CTL_AMPDU))
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
store = &local->pending_packet[queue];
|
store = &local->pending_packet[queue];
|
||||||
|
|
|
@ -114,8 +114,8 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct ieee80211_master_priv *mpriv = netdev_priv(dev);
|
struct ieee80211_master_priv *mpriv = netdev_priv(dev);
|
||||||
struct ieee80211_local *local = mpriv->local;
|
struct ieee80211_local *local = mpriv->local;
|
||||||
|
struct ieee80211_hw *hw = &local->hw;
|
||||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
u16 queue;
|
u16 queue;
|
||||||
u8 tid;
|
u8 tid;
|
||||||
|
@ -124,21 +124,19 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||||
if (unlikely(queue >= local->hw.queues))
|
if (unlikely(queue >= local->hw.queues))
|
||||||
queue = local->hw.queues - 1;
|
queue = local->hw.queues - 1;
|
||||||
|
|
||||||
if (info->flags & IEEE80211_TX_CTL_REQUEUE) {
|
if (skb->requeue) {
|
||||||
|
if (!hw->ampdu_queues)
|
||||||
|
return queue;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
sta = sta_info_get(local, hdr->addr1);
|
sta = sta_info_get(local, hdr->addr1);
|
||||||
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||||
if (sta) {
|
if (sta) {
|
||||||
struct ieee80211_hw *hw = &local->hw;
|
|
||||||
int ampdu_queue = sta->tid_to_tx_q[tid];
|
int ampdu_queue = sta->tid_to_tx_q[tid];
|
||||||
|
|
||||||
if ((ampdu_queue < ieee80211_num_queues(hw)) &&
|
if ((ampdu_queue < ieee80211_num_queues(hw)) &&
|
||||||
test_bit(ampdu_queue, local->queue_pool)) {
|
test_bit(ampdu_queue, local->queue_pool))
|
||||||
queue = ampdu_queue;
|
queue = ampdu_queue;
|
||||||
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
|
||||||
} else {
|
|
||||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
|
@ -159,20 +157,18 @@ u16 ieee80211_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||||
*p++ = ack_policy | tid;
|
*p++ = ack_policy | tid;
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
|
if (!hw->ampdu_queues)
|
||||||
|
return queue;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
|
||||||
sta = sta_info_get(local, hdr->addr1);
|
sta = sta_info_get(local, hdr->addr1);
|
||||||
if (sta) {
|
if (sta) {
|
||||||
int ampdu_queue = sta->tid_to_tx_q[tid];
|
int ampdu_queue = sta->tid_to_tx_q[tid];
|
||||||
struct ieee80211_hw *hw = &local->hw;
|
|
||||||
|
|
||||||
if ((ampdu_queue < ieee80211_num_queues(hw)) &&
|
if ((ampdu_queue < ieee80211_num_queues(hw)) &&
|
||||||
test_bit(ampdu_queue, local->queue_pool)) {
|
test_bit(ampdu_queue, local->queue_pool))
|
||||||
queue = ampdu_queue;
|
queue = ampdu_queue;
|
||||||
info->flags |= IEEE80211_TX_CTL_AMPDU;
|
|
||||||
} else {
|
|
||||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
Loading…
Reference in New Issue