|
@@ -458,7 +458,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|
|
u8 *state;
|
|
|
int ret;
|
|
|
|
|
|
- if (tid >= STA_TID_NUM)
|
|
|
+ if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
|
|
|
return -EINVAL;
|
|
|
|
|
|
#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];
|
|
|
init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
|
|
|
|
|
|
- /* create a new queue for this aggregation */
|
|
|
- ret = ieee80211_ht_agg_queue_add(local, sta, tid);
|
|
|
+ if (hw->ampdu_queues) {
|
|
|
+ /* create a new queue for this aggregation */
|
|
|
+ ret = ieee80211_ht_agg_queue_add(local, sta, tid);
|
|
|
|
|
|
- /* case no queue is available to aggregation
|
|
|
- * don't switch to aggregation */
|
|
|
- if (ret) {
|
|
|
+ /* case no queue is available to aggregation
|
|
|
+ * don't switch to aggregation */
|
|
|
+ if (ret) {
|
|
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
|
|
- printk(KERN_DEBUG "BA request denied - queue unavailable for"
|
|
|
- " tid %d\n", tid);
|
|
|
+ printk(KERN_DEBUG "BA request denied - "
|
|
|
+ "queue unavailable for tid %d\n", tid);
|
|
|
#endif /* CONFIG_MAC80211_HT_DEBUG */
|
|
|
- goto err_unlock_queue;
|
|
|
+ goto err_unlock_queue;
|
|
|
+ }
|
|
|
}
|
|
|
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
|
|
|
* held the tx lock: no packet could be enqueued to the newly
|
|
|
* 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
|
|
|
printk(KERN_DEBUG "BA request denied - HW unavailable for"
|
|
|
" 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 */
|
|
|
- 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);
|
|
|
|
|
|
/* send an addBA request */
|
|
@@ -622,7 +626,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
|
|
|
ra, tid);
|
|
|
#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 |
|
|
|
(initiator << HT_AGG_STATE_INITIATOR_SHIFT);
|
|
@@ -635,7 +640,8 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
|
|
|
if (ret) {
|
|
|
WARN_ON(ret != -EBUSY);
|
|
|
*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;
|
|
|
}
|
|
|
|
|
@@ -691,7 +697,8 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
|
|
|
#ifdef CONFIG_MAC80211_HT_DEBUG
|
|
|
printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
|
|
|
#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);
|
|
|
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,
|
|
|
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
|
|
|
|
|
|
- agg_queue = sta->tid_to_tx_q[tid];
|
|
|
-
|
|
|
- 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
|
|
|
- * 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));
|
|
|
+ if (hw->ampdu_queues) {
|
|
|
+ agg_queue = sta->tid_to_tx_q[tid];
|
|
|
+ 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
|
|
|
+ * 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));
|
|
|
+ }
|
|
|
spin_lock_bh(&sta->lock);
|
|
|
*state = HT_AGG_STATE_IDLE;
|
|
|
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;
|
|
|
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]);
|
|
|
|
|
|
spin_unlock_bh(&sta->lock);
|