Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a006827a authored by John W. Linville's avatar John W. Linville
Browse files
parents 1d9e954e 08cf42e8
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -1001,6 +1001,26 @@ struct ieee80211_vendor_ie {
	u8 oui_type;
} __packed;

struct ieee80211_wmm_ac_param {
	u8 aci_aifsn; /* AIFSN, ACM, ACI */
	u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */
	__le16 txop_limit;
} __packed;

struct ieee80211_wmm_param_ie {
	u8 element_id; /* Element ID: 221 (0xdd); */
	u8 len; /* Length: 24 */
	/* required fields for WMM version 1 */
	u8 oui[3]; /* 00:50:f2 */
	u8 oui_type; /* 2 */
	u8 oui_subtype; /* 1 */
	u8 version; /* 1 for WMM version 1.0 */
	u8 qos_info; /* AP/STA specific QoS info */
	u8 reserved; /* 0 */
	/* AC_BE, AC_BK, AC_VI, AC_VO */
	struct ieee80211_wmm_ac_param ac[4];
} __packed;

/* Control frames */
struct ieee80211_rts {
	__le16 frame_control;
+34 −0
Original line number Diff line number Diff line
@@ -4552,6 +4552,40 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
 */
void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);

/**
 * ieee80211_start_rx_ba_session_offl - start a Rx BA session
 *
 * Some device drivers may offload part of the Rx aggregation flow including
 * AddBa/DelBa negotiation but may otherwise be incapable of full Rx
 * reordering.
 *
 * Create structures responsible for reordering so device drivers may call here
 * when they complete AddBa negotiation.
 *
 * @vif: &struct ieee80211_vif pointer from the add_interface callback
 * @addr: station mac address
 * @tid: the rx tid
 */
void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
					const u8 *addr, u16 tid);

/**
 * ieee80211_stop_rx_ba_session_offl - stop a Rx BA session
 *
 * Some device drivers may offload part of the Rx aggregation flow including
 * AddBa/DelBa negotiation but may otherwise be incapable of full Rx
 * reordering.
 *
 * Destroy structures responsible for reordering so device drivers may call here
 * when they complete DelBa negotiation.
 *
 * @vif: &struct ieee80211_vif pointer from the add_interface callback
 * @addr: station mac address
 * @tid: the rx tid
 */
void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
				       const u8 *addr, u16 tid);

/* Rate control API */

/**
+84 −26
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
	del_timer_sync(&tid_rx->reorder_timer);

	for (i = 0; i < tid_rx->buf_size; i++)
		dev_kfree_skb(tid_rx->reorder_buf[i]);
		__skb_queue_purge(&tid_rx->reorder_buf[i]);
	kfree(tid_rx->reorder_buf);
	kfree(tid_rx->reorder_time);
	kfree(tid_rx);
@@ -224,28 +224,15 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
	ieee80211_tx_skb(sdata, skb);
}

void ieee80211_process_addba_request(struct ieee80211_local *local,
				     struct sta_info *sta,
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
void __ieee80211_start_rx_ba_session(struct sta_info *sta,
				     u8 dialog_token, u16 timeout,
				     u16 start_seq_num, u16 ba_policy, u16 tid,
				     u16 buf_size, bool tx)
{
	struct ieee80211_local *local = sta->sdata->local;
	struct tid_ampdu_rx *tid_agg_rx;
	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status;
	u8 dialog_token;
	int ret = -EOPNOTSUPP;

	/* extract session parameters from addba request frame */
	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
	start_seq_num =
		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;

	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;

	status = WLAN_STATUS_REQUEST_DECLINED;
	int i, ret = -EOPNOTSUPP;
	u16 status = WLAN_STATUS_REQUEST_DECLINED;

	if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
		ht_dbg(sta->sdata,
@@ -264,7 +251,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
		status = WLAN_STATUS_INVALID_QOS_PARAM;
		ht_dbg_ratelimited(sta->sdata,
				   "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n",
				   mgmt->sa, tid, ba_policy, buf_size);
				   sta->sta.addr, tid, ba_policy, buf_size);
		goto end_no_lock;
	}
	/* determine default buffer size */
@@ -281,7 +268,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
	if (sta->ampdu_mlme.tid_rx[tid]) {
		ht_dbg_ratelimited(sta->sdata,
				   "unexpected AddBA Req from %pM on tid %u\n",
				   mgmt->sa, tid);
				   sta->sta.addr, tid);

		/* delete existing Rx BA session on the same tid */
		___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
@@ -308,7 +295,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,

	/* prepare reordering buffer */
	tid_agg_rx->reorder_buf =
		kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL);
		kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL);
	tid_agg_rx->reorder_time =
		kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
	if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
@@ -318,6 +305,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
		goto end;
	}

	for (i = 0; i < buf_size; i++)
		__skb_queue_head_init(&tid_agg_rx->reorder_buf[i]);

	ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START,
			       &sta->sta, tid, &start_seq_num, 0);
	ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
@@ -350,6 +340,74 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
	mutex_unlock(&sta->ampdu_mlme.mtx);

end_no_lock:
	if (tx)
		ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid,
				  dialog_token, status, 1, buf_size, timeout);
					  dialog_token, status, 1, buf_size,
					  timeout);
}

void ieee80211_process_addba_request(struct ieee80211_local *local,
				     struct sta_info *sta,
				     struct ieee80211_mgmt *mgmt,
				     size_t len)
{
	u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num;
	u8 dialog_token;

	/* extract session parameters from addba request frame */
	dialog_token = mgmt->u.action.u.addba_req.dialog_token;
	timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout);
	start_seq_num =
		le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4;

	capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
	ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1;
	tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
	buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6;

	__ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
					start_seq_num, ba_policy, tid,
					buf_size, true);
}

void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
					const u8 *addr, u16 tid)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_rx_agg *rx_agg;
	struct sk_buff *skb = dev_alloc_skb(0);

	if (unlikely(!skb))
		return;

	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
	memcpy(&rx_agg->addr, addr, ETH_ALEN);
	rx_agg->tid = tid;

	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
	skb_queue_tail(&sdata->skb_queue, skb);
	ieee80211_queue_work(&local->hw, &sdata->work);
}
EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);

void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
				       const u8 *addr, u16 tid)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_rx_agg *rx_agg;
	struct sk_buff *skb = dev_alloc_skb(0);

	if (unlikely(!skb))
		return;

	rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
	memcpy(&rx_agg->addr, addr, ETH_ALEN);
	rx_agg->tid = tid;

	skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
	skb_queue_tail(&sdata->skb_queue, skb);
	ieee80211_queue_work(&local->hw, &sdata->work);
}
EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local)
static struct ieee80211_chanctx *
ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_local *local __maybe_unused = sdata->local;
	struct ieee80211_chanctx_conf *conf;

	conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
+6 −4
Original line number Diff line number Diff line
@@ -150,13 +150,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,

	/*
	 * If user has specified capability over-rides, take care
	 * of that if the station we're setting up is the AP that
	 * of that if the station we're setting up is the AP or TDLS peer that
	 * we advertised a restricted capability set to. Override
	 * our own capabilities and then use those below.
	 */
	if ((sdata->vif.type == NL80211_IFTYPE_STATION ||
	     sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
	    !test_sta_flag(sta, WLAN_STA_TDLS_PEER))
	if (sdata->vif.type == NL80211_IFTYPE_STATION ||
	    sdata->vif.type == NL80211_IFTYPE_ADHOC)
		ieee80211_apply_htcap_overrides(sdata, &own_cap);

	/*
@@ -228,6 +227,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata,
	if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1)
		ht_cap.mcs.rx_mask[32/8] |= 1;

	/* set Rx highest rate */
	ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest;

 apply:
	changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap));

Loading