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

Commit 41bd3d58 authored by Toke Høiland-Jørgensen's avatar Toke Høiland-Jørgensen Committed by Kalle Valo
Browse files

wireless-drivers: Dynamically allocate struct station_info



Since the addition of the TXQ stats to cfg80211, the station_info struct
has grown to be quite large, which results in warnings when allocated on
the stack. Fix the affected places to do dynamic allocations instead.

Fixes: 52539ca8 ("cfg80211: Expose TXQ stats and parameters to userspace")
Reviewed-by: default avatarSergey Matyukevich <sergey.matyukevich.os@quantenna.com>
Signed-off-by: default avatarToke Høiland-Jørgensen <toke@toke.dk>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent 4f9fb990
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -426,7 +426,7 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
{
	u8 *ies = NULL, *wpa_ie = NULL, *pos;
	size_t ies_len = 0;
	struct station_info sinfo;
	struct station_info *sinfo;

	ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);

@@ -482,16 +482,20 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
			   keymgmt, ucipher, auth, apsd_info);

	/* send event to application */
	memset(&sinfo, 0, sizeof(sinfo));
	sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
	if (!sinfo)
		return;

	/* TODO: sinfo.generation */

	sinfo.assoc_req_ies = ies;
	sinfo.assoc_req_ies_len = ies_len;
	sinfo->assoc_req_ies = ies;
	sinfo->assoc_req_ies_len = ies_len;

	cfg80211_new_sta(vif->ndev, mac_addr, &sinfo, GFP_KERNEL);
	cfg80211_new_sta(vif->ndev, mac_addr, sinfo, GFP_KERNEL);

	netif_wake_queue(vif->ndev);

	kfree(sinfo);
}

void disconnect_timer_handler(struct timer_list *t)
+14 −8
Original line number Diff line number Diff line
@@ -1200,8 +1200,12 @@ static const struct file_operations fops_freq = {
static int wil_link_debugfs_show(struct seq_file *s, void *data)
{
	struct wil6210_priv *wil = s->private;
	struct station_info sinfo;
	int i, rc;
	struct station_info *sinfo;
	int i, rc = 0;

	sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
	if (!sinfo)
		return -ENOMEM;

	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
		struct wil_sta_info *p = &wil->sta[i];
@@ -1229,19 +1233,21 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data)

		vif = (mid < wil->max_vifs) ? wil->vifs[mid] : NULL;
		if (vif) {
			rc = wil_cid_fill_sinfo(vif, i, &sinfo);
			rc = wil_cid_fill_sinfo(vif, i, sinfo);
			if (rc)
				return rc;
				goto out;

			seq_printf(s, "  Tx_mcs = %d\n", sinfo.txrate.mcs);
			seq_printf(s, "  Rx_mcs = %d\n", sinfo.rxrate.mcs);
			seq_printf(s, "  SQ     = %d\n", sinfo.signal);
			seq_printf(s, "  Tx_mcs = %d\n", sinfo->txrate.mcs);
			seq_printf(s, "  Rx_mcs = %d\n", sinfo->rxrate.mcs);
			seq_printf(s, "  SQ     = %d\n", sinfo->signal);
		} else {
			seq_puts(s, "  INVALID MID\n");
		}
	}

	return 0;
out:
	kfree(sinfo);
	return rc;
}

static int wil_link_seq_open(struct inode *inode, struct file *file)
+13 −6
Original line number Diff line number Diff line
@@ -824,7 +824,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
	struct wireless_dev *wdev = vif_to_wdev(vif);
	struct wmi_connect_event *evt = d;
	int ch; /* channel number */
	struct station_info sinfo;
	struct station_info *sinfo;
	u8 *assoc_req_ie, *assoc_resp_ie;
	size_t assoc_req_ielen, assoc_resp_ielen;
	/* capinfo(u16) + listen_interval(u16) + IEs */
@@ -940,6 +940,7 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
		vif->bss = NULL;
	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {

		if (rc) {
			if (disable_ap_sme)
				/* notify new_sta has failed */
@@ -947,16 +948,22 @@ static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
			goto out;
		}

		memset(&sinfo, 0, sizeof(sinfo));
		sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
		if (!sinfo) {
			rc = -ENOMEM;
			goto out;
		}

		sinfo.generation = wil->sinfo_gen++;
		sinfo->generation = wil->sinfo_gen++;

		if (assoc_req_ie) {
			sinfo.assoc_req_ies = assoc_req_ie;
			sinfo.assoc_req_ies_len = assoc_req_ielen;
			sinfo->assoc_req_ies = assoc_req_ie;
			sinfo->assoc_req_ies_len = assoc_req_ielen;
		}

		cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
		cfg80211_new_sta(ndev, evt->bssid, sinfo, GFP_KERNEL);

		kfree(sinfo);
	} else {
		wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype,
			evt->cid);
+12 −6
Original line number Diff line number Diff line
@@ -5498,7 +5498,7 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,
	static int generation;
	u32 event = e->event_code;
	u32 reason = e->reason;
	struct station_info sinfo;
	struct station_info *sinfo;

	brcmf_dbg(CONN, "event %s (%u), reason %d\n",
		  brcmf_fweh_event_name(event), event, reason);
@@ -5511,16 +5511,22 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg,

	if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
	    (reason == BRCMF_E_STATUS_SUCCESS)) {
		memset(&sinfo, 0, sizeof(sinfo));
		if (!data) {
			brcmf_err("No IEs present in ASSOC/REASSOC_IND");
			return -EINVAL;
		}
		sinfo.assoc_req_ies = data;
		sinfo.assoc_req_ies_len = e->datalen;

		sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
		if (!sinfo)
			return -ENOMEM;

		sinfo->assoc_req_ies = data;
		sinfo->assoc_req_ies_len = e->datalen;
		generation++;
		sinfo.generation = generation;
		cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_KERNEL);
		sinfo->generation = generation;
		cfg80211_new_sta(ndev, e->addr, sinfo, GFP_KERNEL);

		kfree(sinfo);
	} else if ((event == BRCMF_E_DISASSOC_IND) ||
		   (event == BRCMF_E_DEAUTH_IND) ||
		   (event == BRCMF_E_DEAUTH)) {
+16 −9
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
	struct mwifiex_adapter *adapter = priv->adapter;
	int len, i;
	u32 eventcause = adapter->event_cause;
	struct station_info sinfo;
	struct station_info *sinfo;
	struct mwifiex_assoc_event *event;
	struct mwifiex_sta_node *node;
	u8 *deauth_mac;
@@ -117,7 +117,10 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)

	switch (eventcause) {
	case EVENT_UAP_STA_ASSOC:
		memset(&sinfo, 0, sizeof(sinfo));
		sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
		if (!sinfo)
			return -ENOMEM;

		event = (struct mwifiex_assoc_event *)
			(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
		if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
@@ -132,28 +135,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
				len = ETH_ALEN;

			if (len != -1) {
				sinfo.assoc_req_ies = &event->data[len];
				len = (u8 *)sinfo.assoc_req_ies -
				sinfo->assoc_req_ies = &event->data[len];
				len = (u8 *)sinfo->assoc_req_ies -
				      (u8 *)&event->frame_control;
				sinfo.assoc_req_ies_len =
				sinfo->assoc_req_ies_len =
					le16_to_cpu(event->len) - (u16)len;
			}
		}
		cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
		cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo,
				 GFP_KERNEL);

		node = mwifiex_add_sta_entry(priv, event->sta_addr);
		if (!node) {
			mwifiex_dbg(adapter, ERROR,
				    "could not create station entry!\n");
			kfree(sinfo);
			return -1;
		}

		if (!priv->ap_11n_enabled)
		if (!priv->ap_11n_enabled) {
			kfree(sinfo);
			break;
		}

		mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
				       sinfo.assoc_req_ies_len, node);
		mwifiex_set_sta_ht_cap(priv, sinfo->assoc_req_ies,
				       sinfo->assoc_req_ies_len, node);

		for (i = 0; i < MAX_NUM_TID; i++) {
			if (node->is_11n_enabled)
@@ -163,6 +169,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
				node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
		}
		memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
		kfree(sinfo);
		break;
	case EVENT_UAP_STA_DEAUTH:
		deauth_mac = adapter->event_body +
Loading