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

Commit 1d2a4456 authored by Vasanthakumar Thiagarajan's avatar Vasanthakumar Thiagarajan Committed by Kalle Valo
Browse files

ath6kl: Fix bug in maintaining aggregation state in AP mode



Currently rx aggregation related states are maintained per
vif, but this will not properly work when operating in AP mode.
Aggregation is completely broken when more than one
11n stations are connected to AP mode vif. Fix this issue
by keeping station specific aggregation state in sta_list.

Signed-off-by: default avatarVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 3fdc0991
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -2871,6 +2871,11 @@ struct ath6kl *ath6kl_cfg80211_create(void)
/* Note: ar variable must not be accessed after calling this! */
void ath6kl_cfg80211_destroy(struct ath6kl *ar)
{
	int i;

	for (i = 0; i < AP_MAX_NUM_STA; i++)
		kfree(ar->sta_list[i].aggr_conn);

	wiphy_free(ar->wiphy);
}
+7 −0
Original line number Diff line number Diff line
@@ -253,6 +253,13 @@ struct ath6kl *ath6kl_core_create(struct device *dev)
		spin_lock_init(&ar->sta_list[ctr].psq_lock);
		skb_queue_head_init(&ar->sta_list[ctr].psq);
		skb_queue_head_init(&ar->sta_list[ctr].apsdq);
		ar->sta_list[ctr].aggr_conn =
			kzalloc(sizeof(struct aggr_info_conn), GFP_KERNEL);
		if (!ar->sta_list[ctr].aggr_conn) {
			ath6kl_err("Failed to allocate memory for sta aggregation information\n");
			ath6kl_core_destroy(ar);
			return NULL;
		}
	}

	skb_queue_head_init(&ar->mcastpsq);
+3 −1
Original line number Diff line number Diff line
@@ -298,6 +298,7 @@ struct ath6kl_sta {
	spinlock_t psq_lock;
	u8 apsd_info;
	struct sk_buff_head apsdq;
	struct aggr_info_conn *aggr_conn;
};

struct ath6kl_version {
@@ -713,6 +714,7 @@ void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev);

struct aggr_info *aggr_init(struct ath6kl_vif *vif);
void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info_conn *aggr_conn);
void ath6kl_rx_refill(struct htc_target *target,
		      enum htc_endpoint_id endpoint);
void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count);
@@ -720,7 +722,7 @@ struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
					    enum htc_endpoint_id endpoint,
					    int len);
void aggr_module_destroy(struct aggr_info *aggr_info);
void aggr_reset_state(struct aggr_info *aggr_info);
void aggr_reset_state(struct aggr_info_conn *aggr_conn);

struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 * node_addr);
struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
+4 −0
Original line number Diff line number Diff line
@@ -1660,6 +1660,7 @@ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
void ath6kl_stop_txrx(struct ath6kl *ar)
{
	struct ath6kl_vif *vif, *tmp_vif;
	int i;

	set_bit(DESTROY_IN_PROGRESS, &ar->flag);

@@ -1668,6 +1669,9 @@ void ath6kl_stop_txrx(struct ath6kl *ar)
		return;
	}

	for (i = 0; i < AP_MAX_NUM_STA; i++)
		aggr_reset_state(ar->sta_list[i].aggr_conn);

	spin_lock_bh(&ar->list_lock);
	list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
		list_del(&vif->list);
+4 −3
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ static void ath6kl_add_new_sta(struct ath6kl_vif *vif, u8 *mac, u16 aid,

	ar->sta_list_index = ar->sta_list_index | (1 << free_slot);
	ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid);
	aggr_conn_init(vif, sta->aggr_conn);
}

static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
@@ -94,7 +95,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
	sta->sta_flags = 0;

	ar->sta_list_index = ar->sta_list_index & ~(1 << i);

	aggr_reset_state(sta->aggr_conn);
}

static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason)
@@ -602,7 +603,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,
	netif_carrier_on(vif->ndev);
	spin_unlock_bh(&vif->if_lock);

	aggr_reset_state(vif->aggr_cntxt);
	aggr_reset_state(vif->aggr_cntxt->aggr_conn);
	vif->reconnect_flag = 0;

	if ((vif->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
@@ -924,7 +925,7 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,
				       assoc_resp_len, assoc_info,
				       prot_reason_status);

	aggr_reset_state(vif->aggr_cntxt);
	aggr_reset_state(vif->aggr_cntxt->aggr_conn);

	del_timer(&vif->disconnect_timer);

Loading