Commit c951ad35 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

mac80211: convert aggregation to operate on vifs/stas

The entire aggregation code currently operates on the
hw pointer and station addresses, but that needs to
change to make stations purely per-vif; As one step
preparing for that make the aggregation code callable
with the station, or by the combination of virtual
interface and station address.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 3b53fde8
...@@ -2441,6 +2441,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, ...@@ -2441,6 +2441,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
} }
static int ar9170_ampdu_action(struct ieee80211_hw *hw, static int ar9170_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action, enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn) struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{ {
...@@ -2470,7 +2471,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, ...@@ -2470,7 +2471,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw,
tid_info->state = AR9170_TID_STATE_PROGRESS; tid_info->state = AR9170_TID_STATE_PROGRESS;
tid_info->active = false; tid_info->active = false;
spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break; break;
case IEEE80211_AMPDU_TX_STOP: case IEEE80211_AMPDU_TX_STOP:
...@@ -2480,7 +2481,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, ...@@ -2480,7 +2481,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw,
tid_info->active = false; tid_info->active = false;
skb_queue_purge(&tid_info->queue); skb_queue_purge(&tid_info->queue);
spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break; break;
case IEEE80211_AMPDU_TX_OPERATIONAL: case IEEE80211_AMPDU_TX_OPERATIONAL:
......
...@@ -3078,6 +3078,7 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw) ...@@ -3078,6 +3078,7 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw)
} }
static int ath9k_ampdu_action(struct ieee80211_hw *hw, static int ath9k_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action, enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
u16 tid, u16 *ssn) u16 tid, u16 *ssn)
...@@ -3095,11 +3096,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ...@@ -3095,11 +3096,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
break; break;
case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_START:
ath_tx_aggr_start(sc, sta, tid, ssn); ath_tx_aggr_start(sc, sta, tid, ssn);
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break; break;
case IEEE80211_AMPDU_TX_STOP: case IEEE80211_AMPDU_TX_STOP:
ath_tx_aggr_stop(sc, sta, tid); ath_tx_aggr_stop(sc, sta, tid);
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break; break;
case IEEE80211_AMPDU_TX_OPERATIONAL: case IEEE80211_AMPDU_TX_OPERATIONAL:
ath_tx_aggr_resume(sc, sta, tid); ath_tx_aggr_resume(sc, sta, tid);
......
...@@ -1353,7 +1353,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, ...@@ -1353,7 +1353,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
if(ath_tx_aggr_check(sc, an, tid)) if(ath_tx_aggr_check(sc, an, tid))
ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); ieee80211_start_tx_ba_session(sta, tid);
} }
} }
......
...@@ -301,7 +301,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, ...@@ -301,7 +301,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid); sta->addr, tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); ieee80211_start_tx_ba_session(sta, tid);
} }
} }
......
...@@ -2691,6 +2691,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -2691,6 +2691,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
} }
static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action, enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn) struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{ {
......
...@@ -1312,7 +1312,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) ...@@ -1312,7 +1312,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
if (tid_data->tfds_in_queue == 0) { if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(priv, "HW queue is empty\n"); IWL_DEBUG_HT(priv, "HW queue is empty\n");
tid_data->agg.state = IWL_AGG_ON; tid_data->agg.state = IWL_AGG_ON;
ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid);
} else { } else {
IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
tid_data->tfds_in_queue); tid_data->tfds_in_queue);
...@@ -1377,7 +1377,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) ...@@ -1377,7 +1377,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
if (ret) if (ret)
return ret; return ret;
ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
return 0; return 0;
} }
...@@ -1401,7 +1401,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) ...@@ -1401,7 +1401,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, priv->cfg->ops->lib->txq_agg_disable(priv, txq_id,
ssn, tx_fifo); ssn, tx_fifo);
tid_data->agg.state = IWL_AGG_OFF; tid_data->agg.state = IWL_AGG_OFF;
ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid);
} }
break; break;
case IWL_EMPTYING_HW_QUEUE_ADDBA: case IWL_EMPTYING_HW_QUEUE_ADDBA:
...@@ -1409,7 +1409,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) ...@@ -1409,7 +1409,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
if (tid_data->tfds_in_queue == 0) { if (tid_data->tfds_in_queue == 0) {
IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n");
tid_data->agg.state = IWL_AGG_ON; tid_data->agg.state = IWL_AGG_ON;
ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid);
} }
break; break;
} }
......
...@@ -1508,6 +1508,7 @@ struct ieee80211_ops { ...@@ -1508,6 +1508,7 @@ struct ieee80211_ops {
void (*reset_tsf)(struct ieee80211_hw *hw); void (*reset_tsf)(struct ieee80211_hw *hw);
int (*tx_last_beacon)(struct ieee80211_hw *hw); int (*tx_last_beacon)(struct ieee80211_hw *hw);
int (*ampdu_action)(struct ieee80211_hw *hw, int (*ampdu_action)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action, enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn); struct ieee80211_sta *sta, u16 tid, u16 *ssn);
...@@ -2029,8 +2030,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, ...@@ -2029,8 +2030,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
/** /**
* ieee80211_start_tx_ba_session - Start a tx Block Ack session. * ieee80211_start_tx_ba_session - Start a tx Block Ack session.
* @hw: pointer as obtained from ieee80211_alloc_hw(). * @sta: the station for which to start a BA session
* @ra: receiver address of the BA session recipient
* @tid: the TID to BA on. * @tid: the TID to BA on.
* *
* Return: success if addBA request was sent, failure otherwise * Return: success if addBA request was sent, failure otherwise
...@@ -2039,22 +2039,22 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, ...@@ -2039,22 +2039,22 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
* the need to start aggregation on a certain RA/TID, the session level * the need to start aggregation on a certain RA/TID, the session level
* will be managed by the mac80211. * will be managed by the mac80211.
*/ */
int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid); int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid);
/** /**
* ieee80211_start_tx_ba_cb - low level driver ready to aggregate. * ieee80211_start_tx_ba_cb - low level driver ready to aggregate.
* @hw: pointer as obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient. * @ra: receiver address of the BA session recipient.
* @tid: the TID to BA on. * @tid: the TID to BA on.
* *
* This function must be called by low level driver once it has * This function must be called by low level driver once it has
* finished with preparations for the BA session. * finished with preparations for the BA session.
*/ */
void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
/** /**
* ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate.
* @hw: pointer as obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient. * @ra: receiver address of the BA session recipient.
* @tid: the TID to BA on. * @tid: the TID to BA on.
* *
...@@ -2062,13 +2062,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); ...@@ -2062,13 +2062,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid);
* finished with preparations for the BA session. * finished with preparations for the BA session.
* This version of the function is IRQ-safe. * This version of the function is IRQ-safe.
*/ */
void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra,
u16 tid); u16 tid);
/** /**
* ieee80211_stop_tx_ba_session - Stop a Block Ack session. * ieee80211_stop_tx_ba_session - Stop a Block Ack session.
* @hw: pointer as obtained from ieee80211_alloc_hw(). * @sta: the station whose BA session to stop
* @ra: receiver address of the BA session recipient
* @tid: the TID to stop BA. * @tid: the TID to stop BA.
* @initiator: if indicates initiator DELBA frame will be sent. * @initiator: if indicates initiator DELBA frame will be sent.
* *
...@@ -2078,24 +2077,23 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, ...@@ -2078,24 +2077,23 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
* the need to stop aggregation on a certain RA/TID, the session level * the need to stop aggregation on a certain RA/TID, the session level
* will be managed by the mac80211. * will be managed by the mac80211.
*/ */
int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid,
u8 *ra, u16 tid,
enum ieee80211_back_parties initiator); enum ieee80211_back_parties initiator);
/** /**
* ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate.
* @hw: pointer as obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient. * @ra: receiver address of the BA session recipient.
* @tid: the desired TID to BA on. * @tid: the desired TID to BA on.
* *
* This function must be called by low level driver once it has * This function must be called by low level driver once it has
* finished with preparations for the BA session tear down. * finished with preparations for the BA session tear down.
*/ */
void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
/** /**
* ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate.
* @hw: pointer as obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf
* @ra: receiver address of the BA session recipient. * @ra: receiver address of the BA session recipient.
* @tid: the desired TID to BA on. * @tid: the desired TID to BA on.
* *
...@@ -2103,7 +2101,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); ...@@ -2103,7 +2101,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid);
* finished with preparations for the BA session tear down. * finished with preparations for the BA session tear down.
* This version of the function is IRQ-safe. * This version of the function is IRQ-safe.
*/ */
void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra,
u16 tid); u16 tid);
/** /**
......
...@@ -41,7 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, ...@@ -41,7 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
sta->sta.addr, tid); sta->sta.addr, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */ #endif /* CONFIG_MAC80211_HT_DEBUG */
if (drv_ampdu_action(local, IEEE80211_AMPDU_RX_STOP, if (drv_ampdu_action(local, &sta->sdata->vif,
IEEE80211_AMPDU_RX_STOP,
&sta->sta, tid, NULL)) &sta->sta, tid, NULL))
printk(KERN_DEBUG "HW problem - can not stop rx " printk(KERN_DEBUG "HW problem - can not stop rx "
"aggregation for tid %d\n", tid); "aggregation for tid %d\n", tid);
...@@ -284,7 +285,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, ...@@ -284,7 +285,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
goto end; goto end;
} }
ret = drv_ampdu_action(local, IEEE80211_AMPDU_RX_START, ret = drv_ampdu_action(local, &sta->sdata->vif,
IEEE80211_AMPDU_RX_START,
&sta->sta, tid, &start_seq_num); &sta->sta, tid, &start_seq_num);
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret);
......
...@@ -138,7 +138,8 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ...@@ -138,7 +138,8 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 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);
ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_STOP, ret = drv_ampdu_action(local, &sta->sdata->vif,
IEEE80211_AMPDU_TX_STOP,
&sta->sta, tid, NULL); &sta->sta, tid, NULL);
/* HW shall not deny going back to legacy */ /* HW shall not deny going back to legacy */
...@@ -196,11 +197,11 @@ static inline int ieee80211_ac_from_tid(int tid) ...@@ -196,11 +197,11 @@ static inline int ieee80211_ac_from_tid(int tid)
return ieee802_1d_to_ac[tid & 7]; return ieee802_1d_to_ac[tid & 7];
} }
int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
struct sta_info *sta; struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_sub_if_data *sdata; struct ieee80211_local *local = sdata->local;
u8 *state; u8 *state;
int ret = 0; int ret = 0;
u16 start_seq_num; u16 start_seq_num;
...@@ -208,52 +209,37 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -208,52 +209,37 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
if (WARN_ON(!local->ops->ampdu_action)) if (WARN_ON(!local->ops->ampdu_action))
return -EINVAL; return -EINVAL;
if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) if ((tid >= STA_TID_NUM) ||
!(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION))
return -EINVAL; return -EINVAL;
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n",
ra, tid); pubsta->addr, tid);
#endif /* CONFIG_MAC80211_HT_DEBUG */ #endif /* CONFIG_MAC80211_HT_DEBUG */
rcu_read_lock();
sta = sta_info_get(local, ra);
if (!sta) {
#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Could not find the station\n");
#endif
ret = -ENOENT;
goto unlock;
}
/* /*
* The aggregation code is not prepared to handle * The aggregation code is not prepared to handle
* anything but STA/AP due to the BSSID handling. * anything but STA/AP due to the BSSID handling.
* IBSS could work in the code but isn't supported * IBSS could work in the code but isn't supported
* by drivers or the standard. * by drivers or the standard.
*/ */
if (sta->sdata->vif.type != NL80211_IFTYPE_STATION && if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN && sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sta->sdata->vif.type != NL80211_IFTYPE_AP) { sdata->vif.type != NL80211_IFTYPE_AP)
ret = -EINVAL; return -EINVAL;
goto unlock;
}
if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { if (test_sta_flags(sta, WLAN_STA_SUSPEND)) {
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Suspend in progress. " printk(KERN_DEBUG "Suspend in progress. "
"Denying BA session request\n"); "Denying BA session request\n");
#endif #endif
ret = -EINVAL; return -EINVAL;
goto unlock;
} }
spin_lock_bh(&sta->lock); spin_lock_bh(&sta->lock);
spin_lock(&local->ampdu_lock); spin_lock(&local->ampdu_lock);
sdata = sta->sdata;
/* we have tried too many times, receiver does not want A-MPDU */ /* we have tried too many times, receiver does not want A-MPDU */
if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
ret = -EBUSY; ret = -EBUSY;
...@@ -310,8 +296,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -310,8 +296,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
start_seq_num = sta->tid_seq[tid]; start_seq_num = sta->tid_seq[tid];
ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_START, ret = drv_ampdu_action(local, &sdata->vif,
&sta->sta, tid, &start_seq_num); IEEE80211_AMPDU_TX_START,
pubsta, tid, &start_seq_num);
if (ret) { if (ret) {
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
...@@ -336,7 +323,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -336,7 +323,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
sta->ampdu_mlme.dialog_token_allocator; sta->ampdu_mlme.dialog_token_allocator;
sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
ieee80211_send_addba_request(sta->sdata, ra, tid, ieee80211_send_addba_request(sdata, pubsta->addr, tid,
sta->ampdu_mlme.tid_tx[tid]->dialog_token, sta->ampdu_mlme.tid_tx[tid]->dialog_token,
sta->ampdu_mlme.tid_tx[tid]->ssn, sta->ampdu_mlme.tid_tx[tid]->ssn,
0x40, 5000); 0x40, 5000);
...@@ -348,7 +335,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -348,7 +335,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
#ifdef CONFIG_MAC80211_HT_DEBUG #ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
#endif #endif
goto unlock; return 0;
err_free: err_free:
kfree(sta->ampdu_mlme.tid_tx[tid]); kfree(sta->ampdu_mlme.tid_tx[tid]);
...@@ -360,8 +347,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -360,8 +347,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
err_unlock_sta: err_unlock_sta:
spin_unlock(&local->ampdu_lock); spin_unlock(&local->ampdu_lock);
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
unlock:
rcu_read_unlock();
return ret; return ret;
} }
EXPORT_SYMBOL(ieee80211_start_tx_ba_session); EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
...@@ -428,13 +413,15 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, ...@@ -428,13 +413,15 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
ieee80211_agg_splice_finish(local, sta, tid); ieee80211_agg_splice_finish(local, sta, tid);
spin_unlock(&local->ampdu_lock); spin_unlock(&local->ampdu_lock);
drv_ampdu_action(local, IEEE80211_AMPDU_TX_OPERATIONAL, drv_ampdu_action(local, &sta->sdata->vif,
IEEE80211_AMPDU_TX_OPERATIONAL,
&sta->sta, tid, NULL); &sta->sta, tid, NULL);
} }
void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct sta_info *sta; struct sta_info *sta;
u8 *state; u8 *state;
...@@ -483,10 +470,11 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) ...@@ -483,10 +470,11 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
} }
EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
const u8 *ra, u16 tid) const u8 *ra, u16 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_ra_tid *ra_tid; struct ieee80211_ra_tid *ra_tid;
struct sk_buff *skb = dev_alloc_skb(0); struct sk_buff *skb = dev_alloc_skb(0);
...@@ -535,13 +523,12 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, ...@@ -535,13 +523,12 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
return ret; return ret;
} }
int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
u8 *ra, u16 tid,
enum ieee80211_back_parties initiator) enum ieee80211_back_parties initiator)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
struct sta_info *sta; struct ieee80211_sub_if_data *sdata = sta->sdata;
int ret = 0; struct ieee80211_local *local = sdata->local;
if (WARN_ON(!local->ops->ampdu_action)) if (WARN_ON(!local->ops->ampdu_action))
return -EINVAL; return -EINVAL;
...@@ -549,22 +536,14 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, ...@@ -549,22 +536,14 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
if (tid >= STA_TID_NUM) if (tid >= STA_TID_NUM)
return -EINVAL; return -EINVAL;
rcu_read_lock(); return __ieee80211_stop_tx_ba_session(sta, tid, initiator);
sta = sta_info_get(local, ra);
if (!sta) {
rcu_read_unlock();
return -ENOENT;
}
ret = __ieee80211_stop_tx_ba_session(sta, tid, initiator);
rcu_read_unlock();
return ret;
} }
EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct sta_info *sta; struct sta_info *sta;
u8 *state; u8 *state;
...@@ -627,10 +606,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) ...@@ -627,10 +606,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
} }
EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
const u8 *ra, u16 tid) const u8 *ra, u16 tid)
{ {
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_local *local = sdata->local;
struct ieee80211_ra_tid *ra_tid; struct ieee80211_ra_tid *ra_tid;
struct sk_buff *skb = dev_alloc_skb(0); struct sk_buff *skb = dev_alloc_skb(0);
......
...@@ -239,15 +239,16 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) ...@@ -239,15 +239,16 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local)
} }
static inline int drv_ampdu_action(struct ieee80211_local *local, static inline int drv_ampdu_action(struct ieee80211_local *local,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action, enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, struct ieee80211_sta *sta, u16 tid,
u16 *ssn) u16 *ssn)
{ {
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
if (local->ops->ampdu_action) if (local->ops->ampdu_action)
ret = local->ops->ampdu_action(&local->hw, action, ret = local->ops->ampdu_action(&local->hw, vif, action,
sta, tid, ssn); sta, tid, ssn);
trace_drv_ampdu_action(local, action, sta, tid, ssn, ret); trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret);
return ret; return ret;
} }
......
...@@ -634,11 +634,12 @@ TRACE_EVENT(drv_tx_last_beacon, ...@@ -634,11 +634,12 @@ TRACE_EVENT(drv_tx_last_beacon,
TRACE_EVENT(drv_ampdu_action, TRACE_EVENT(drv_ampdu_action,
TP_PROTO(struct ieee80211_local *local, TP_PROTO(struct ieee80211_local *local,
struct ieee80211_vif *vif,
enum ieee80211_ampdu_mlme_action action, enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, struct ieee80211_sta *sta, u16 tid,
u16 *ssn, int ret), u16 *ssn, int ret),
TP_ARGS(local, action, sta, tid, ssn, ret), TP_ARGS(local, vif, action, sta, tid, ssn, ret),
TP_STRUCT__entry( TP_STRUCT__entry(
LOCAL_ENTRY LOCAL_ENTRY
...@@ -647,10 +648,12 @@ TRACE_EVENT(drv_ampdu_action, ...@@ -647,10 +648,12 @@ TRACE_EVENT(drv_ampdu_action,
__field(u16, tid) __field(u16, tid)
__field(u16, ssn) __field(u16, ssn)
__field(int, ret) __field(int, ret)
VIF_ENTRY
), ),
TP_fast_assign( TP_fast_assign(
LOCAL_ASSIGN; LOCAL_ASSIGN;
VIF_ASSIGN;
STA_ASSIGN; STA_ASSIGN;
__entry->ret = ret; __entry->ret = ret;
__entry->action = action; __entry->action = action;
...@@ -659,8 +662,8 @@ TRACE_EVENT(drv_ampdu_action, ...@@ -659,8 +662,8 @@ TRACE_EVENT(drv_ampdu_action,
), ),
TP_printk( TP_printk(
LOCAL_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d", LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d",
LOCAL_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret
) )
); );
#endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
......
...@@ -141,7 +141,6 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, ...@@ -141,7 +141,6 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta, struct sta_info *sta,
struct ieee80211_mgmt *mgmt, size_t len) struct ieee80211_mgmt *mgmt, size_t len)
{ {
struct ieee80211_local *local = sdata->local;
u16 tid, params; u16 tid, params;
u16 initiator; u16 initiator;
...@@ -164,7 +163,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, ...@@ -164,7 +163,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
sta->ampdu_mlme.tid_state_tx[tid] = sta->ampdu_mlme.tid_state_tx[tid] =
HT_AGG_STATE_OPERATIONAL; HT_AGG_STATE_OPERATIONAL;
spin_unlock_bh(&sta->lock); spin_unlock_bh(&sta->lock);
ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid, ieee80211_stop_tx_ba_session(&sta->sta, tid,
WLAN_BACK_RECIPIENT); WLAN_BACK_RECIPIENT);
} }
} }
...@@ -771,8 +771,9 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) ...@@ -771,8 +771,9 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
return netdev_priv(dev); return netdev_priv(dev);
} }
/* this struct represents 802.11n's RA/TID combination */ /* this struct represents 802.11n's RA/TID combination along with our vif */
struct ieee80211_ra_tid { struct ieee80211_ra_tid {
struct ieee80211_vif *vif;
u8 ra[ETH_ALEN]; u8 ra[ETH_ALEN];
u16 tid; u16 tid;
}; };
......
...@@ -296,14 +296,14 @@ static void ieee80211_tasklet_handler(unsigned long data) ...@@ -296,14 +296,14 @@ static void ieee80211_tasklet_handler(unsigned long data)
break; break;
case IEEE80211_DELBA_MSG: case IEEE80211_DELBA_MSG:
ra_tid = (struct ieee80211_ra_tid *) &skb->cb; ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
ieee80211_stop_tx_ba_cb(local_to_hw(local), ieee80211_stop_tx_ba_cb(ra_tid->vif, ra_tid->ra,
ra_tid->ra, ra_tid->tid); ra_tid->tid);
dev_kfree_skb(skb); dev_kfree_skb(skb);
break; break;
case IEEE80211_ADDBA_MSG: case IEEE80211_ADDBA_MSG:
ra_tid = (struct ieee80211_ra_tid *) &skb->cb; ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
ieee80211_start_tx_ba_cb(local_to_hw(local), ieee80211_start_tx_ba_cb(ra_tid->vif, ra_tid->ra,
ra_tid->ra, ra_tid->tid); ra_tid->tid);
dev_kfree_skb(skb); dev_kfree_skb(skb);
break ; break ;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment