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

Commit 50a808c8 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: fix invalid memory access for rx_buff_mgmt debugfs"

parents 709a12c5 aebf5d13
Loading
Loading
Loading
Loading
+268 −52
Original line number Original line Diff line number Diff line
@@ -393,7 +393,9 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		BIT(IEEE80211_STYPE_PROBE_RESP >> 4) |
		BIT(IEEE80211_STYPE_PROBE_RESP >> 4) |
		BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
		BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) |
		BIT(IEEE80211_STYPE_DISASSOC >> 4),
		BIT(IEEE80211_STYPE_DISASSOC >> 4) |
		BIT(IEEE80211_STYPE_AUTH >> 4) |
		BIT(IEEE80211_STYPE_REASSOC_RESP >> 4),
		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
		BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
		BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
		BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
@@ -1145,6 +1147,26 @@ static void wil_print_crypto(struct wil6210_priv *wil,
		     c->control_port_no_encrypt);
		     c->control_port_no_encrypt);
}
}


static const char *
wil_get_auth_type_name(enum nl80211_auth_type auth_type)
{
	switch (auth_type) {
	case NL80211_AUTHTYPE_OPEN_SYSTEM:
		return "OPEN_SYSTEM";
	case NL80211_AUTHTYPE_SHARED_KEY:
		return "SHARED_KEY";
	case NL80211_AUTHTYPE_FT:
		return "FT";
	case NL80211_AUTHTYPE_NETWORK_EAP:
		return "NETWORK_EAP";
	case NL80211_AUTHTYPE_SAE:
		return "SAE";
	case NL80211_AUTHTYPE_AUTOMATIC:
		return "AUTOMATIC";
	default:
		return "unknown";
	}
}
static void wil_print_connect_params(struct wil6210_priv *wil,
static void wil_print_connect_params(struct wil6210_priv *wil,
				     struct cfg80211_connect_params *sme)
				     struct cfg80211_connect_params *sme)
{
{
@@ -1158,11 +1180,82 @@ static void wil_print_connect_params(struct wil6210_priv *wil,
	if (sme->ssid)
	if (sme->ssid)
		print_hex_dump(KERN_INFO, "  SSID: ", DUMP_PREFIX_OFFSET,
		print_hex_dump(KERN_INFO, "  SSID: ", DUMP_PREFIX_OFFSET,
			       16, 1, sme->ssid, sme->ssid_len, true);
			       16, 1, sme->ssid, sme->ssid_len, true);
	if (sme->prev_bssid)
		wil_info(wil, "  Previous BSSID=%pM\n", sme->prev_bssid);
	wil_info(wil, "  Auth Type: %s\n",
		 wil_get_auth_type_name(sme->auth_type));
	wil_info(wil, "  Privacy: %s\n", sme->privacy ? "secure" : "open");
	wil_info(wil, "  Privacy: %s\n", sme->privacy ? "secure" : "open");
	wil_info(wil, "  PBSS: %d\n", sme->pbss);
	wil_info(wil, "  PBSS: %d\n", sme->pbss);
	wil_print_crypto(wil, &sme->crypto);
	wil_print_crypto(wil, &sme->crypto);
}
}


static int wil_ft_connect(struct wiphy *wiphy,
			  struct net_device *ndev,
			  struct cfg80211_connect_params *sme)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wil6210_vif *vif = ndev_to_vif(ndev);
	struct wmi_ft_auth_cmd auth_cmd;
	int rc;

	if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, wil->fw_capabilities)) {
		wil_err(wil, "FT: FW does not support FT roaming\n");
		return -EOPNOTSUPP;
	}

	if (!sme->prev_bssid) {
		wil_err(wil, "FT: prev_bssid was not set\n");
		return -EINVAL;
	}

	if (ether_addr_equal(sme->prev_bssid, sme->bssid)) {
		wil_err(wil, "FT: can not roam to same AP\n");
		return -EINVAL;
	}

	if (!test_bit(wil_vif_fwconnected, vif->status)) {
		wil_err(wil, "FT: roam while not connected\n");
		return -EINVAL;
	}

	if (vif->privacy != sme->privacy) {
		wil_err(wil, "FT: privacy mismatch, current (%d) roam (%d)\n",
			vif->privacy, sme->privacy);
		return -EINVAL;
	}

	if (sme->pbss) {
		wil_err(wil, "FT: roam is not valid for PBSS\n");
		return -EINVAL;
	}

	memset(&auth_cmd, 0, sizeof(auth_cmd));
	auth_cmd.channel = sme->channel->hw_value - 1;
	ether_addr_copy(auth_cmd.bssid, sme->bssid);

	if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities))
		if (wil->force_edmg_channel) {
			rc = wil_spec2wmi_ch(wil->force_edmg_channel,
					     &auth_cmd.channel);
			if (rc)
				wil_err(wil, "FT: wmi channel for channel %d not found",
					wil->force_edmg_channel);
		}

	wil_info(wil, "FT: roaming\n");

	set_bit(wil_vif_ft_roam, vif->status);
	rc = wmi_send(wil, WMI_FT_AUTH_CMDID, vif->mid,
		      &auth_cmd, sizeof(auth_cmd));
	if (rc == 0)
		mod_timer(&vif->connect_timer,
			  jiffies + msecs_to_jiffies(5000));
	else
		clear_bit(wil_vif_ft_roam, vif->status);

	return rc;
}

static int wil_cfg80211_connect(struct wiphy *wiphy,
static int wil_cfg80211_connect(struct wiphy *wiphy,
				struct net_device *ndev,
				struct net_device *ndev,
				struct cfg80211_connect_params *sme)
				struct cfg80211_connect_params *sme)
@@ -1175,11 +1268,20 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
	const u8 *rsn_eid;
	const u8 *rsn_eid;
	int ch;
	int ch;
	int rc = 0;
	int rc = 0;
	bool is_ft_roam = false;
	u8 network_type;
	enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;
	enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;


	wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid);
	wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid);
	wil_print_connect_params(wil, sme);
	wil_print_connect_params(wil, sme);


	if (sme->auth_type == NL80211_AUTHTYPE_FT)
		is_ft_roam = true;
	if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC &&
	    test_bit(wil_vif_fwconnected, vif->status))
		is_ft_roam = true;

	if (!is_ft_roam)
		if (test_bit(wil_vif_fwconnecting, vif->status) ||
		if (test_bit(wil_vif_fwconnecting, vif->status) ||
		    test_bit(wil_vif_fwconnected, vif->status))
		    test_bit(wil_vif_fwconnected, vif->status))
			return -EALREADY;
			return -EALREADY;
@@ -1192,8 +1294,13 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
	rsn_eid = sme->ie ?
	rsn_eid = sme->ie ?
			cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
			cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
			NULL;
			NULL;
	if (sme->privacy && !rsn_eid)
	if (sme->privacy && !rsn_eid) {
		wil_info(wil, "WSC connection\n");
		wil_info(wil, "WSC connection\n");
		if (is_ft_roam) {
			wil_err(wil, "No WSC with FT roam\n");
			return -EINVAL;
		}
	}


	if (sme->pbss)
	if (sme->pbss)
		bss_type = IEEE80211_BSS_TYPE_PBSS;
		bss_type = IEEE80211_BSS_TYPE_PBSS;
@@ -1215,6 +1322,45 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
	vif->privacy = sme->privacy;
	vif->privacy = sme->privacy;
	vif->pbss = sme->pbss;
	vif->pbss = sme->pbss;


	rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
	if (rc)
		goto out;

	switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
	case WLAN_CAPABILITY_DMG_TYPE_AP:
		network_type = WMI_NETTYPE_INFRA;
		break;
	case WLAN_CAPABILITY_DMG_TYPE_PBSS:
		network_type = WMI_NETTYPE_P2P;
		break;
	default:
		wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
			bss->capability);
		rc = -EINVAL;
		goto out;
	}

	ch = bss->channel->hw_value;
	if (ch == 0) {
		wil_err(wil, "BSS at unknown frequency %dMhz\n",
			bss->channel->center_freq);
		rc = -EOPNOTSUPP;
		goto out;
	}

	if (is_ft_roam) {
		if (network_type != WMI_NETTYPE_INFRA) {
			wil_err(wil, "FT: Unsupported BSS type, capability= 0x%04x\n",
				bss->capability);
			rc = -EINVAL;
			goto out;
		}
		rc = wil_ft_connect(wiphy, ndev, sme);
		if (rc == 0)
			vif->bss = bss;
		goto out;
	}

	if (vif->privacy) {
	if (vif->privacy) {
		/* For secure assoc, remove old keys */
		/* For secure assoc, remove old keys */
		rc = wmi_del_cipher_key(vif, 0, bss->bssid,
		rc = wmi_del_cipher_key(vif, 0, bss->bssid,
@@ -1231,28 +1377,9 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
		}
		}
	}
	}


	/* WMI_SET_APPIE_CMD. ie may contain rsn info as well as other info
	 * elements. Send it also in case it's empty, to erase previously set
	 * ies in FW.
	 */
	rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
	if (rc)
		goto out;

	/* WMI_CONNECT_CMD */
	/* WMI_CONNECT_CMD */
	memset(&conn, 0, sizeof(conn));
	memset(&conn, 0, sizeof(conn));
	switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) {
	conn.network_type = network_type;
	case WLAN_CAPABILITY_DMG_TYPE_AP:
		conn.network_type = WMI_NETTYPE_INFRA;
		break;
	case WLAN_CAPABILITY_DMG_TYPE_PBSS:
		conn.network_type = WMI_NETTYPE_P2P;
		break;
	default:
		wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
			bss->capability);
		goto out;
	}
	if (vif->privacy) {
	if (vif->privacy) {
		if (rsn_eid) { /* regular secure connection */
		if (rsn_eid) { /* regular secure connection */
			conn.dot11_auth_mode = WMI_AUTH11_SHARED;
			conn.dot11_auth_mode = WMI_AUTH11_SHARED;
@@ -1272,14 +1399,6 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,


	conn.ssid_len = min_t(u8, ssid_eid[1], 32);
	conn.ssid_len = min_t(u8, ssid_eid[1], 32);
	memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
	memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);

	ch = bss->channel->hw_value;
	if (ch == 0) {
		wil_err(wil, "BSS at unknown frequency %dMhz\n",
			bss->channel->center_freq);
		rc = -EOPNOTSUPP;
		goto out;
	}
	conn.channel = ch - 1;
	conn.channel = ch - 1;


	if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities))
	if (test_bit(WMI_FW_CAPABILITY_CHANNEL_BONDING, wil->fw_capabilities))
@@ -1485,7 +1604,7 @@ wil_find_sta_by_key_usage(struct wil6210_priv *wil, u8 mid,
	return &wil->sta[cid];
	return &wil->sta[cid];
}
}


static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
		       struct wil_sta_info *cs,
		       struct wil_sta_info *cs,
		       struct key_params *params)
		       struct key_params *params)
{
{
@@ -1570,12 +1689,18 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
		     params->seq_len, params->seq);
		     params->seq_len, params->seq);


	if (IS_ERR(cs)) {
	if (IS_ERR(cs)) {
		/* in FT, sta info may not be available as add_key may be
		 * sent by host before FW sends WMI_CONNECT_EVENT
		 */
		if (!test_bit(wil_vif_ft_roam, vif->status)) {
			wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n",
			wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n",
				mac_addr, key_usage_str[key_usage], key_index,
				mac_addr, key_usage_str[key_usage], key_index,
				params->seq_len, params->seq);
				params->seq_len, params->seq);
			return -EINVAL;
			return -EINVAL;
		}
		}
	}


	if (!IS_ERR(cs))
		wil_del_rx_key(key_index, key_usage, cs);
		wil_del_rx_key(key_index, key_usage, cs);


	if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
	if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
@@ -1589,7 +1714,10 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,


	rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len,
	rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len,
				params->key, key_usage);
				params->key, key_usage);
	if (!rc)
	if (!rc && !IS_ERR(cs))
		/* in FT set crypto will take place upon receiving
		 * WMI_RING_EN_EVENTID event
		 */
		wil_set_crypto_rx(key_index, key_usage, cs, params);
		wil_set_crypto_rx(key_index, key_usage, cs, params);


	return rc;
	return rc;
@@ -1752,21 +1880,36 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
}
}


/* internal functions for device reset and starting AP */
/* internal functions for device reset and starting AP */
static int _wil_cfg80211_set_ies(struct wil6210_vif *vif,
static u8 *
				 struct cfg80211_beacon_data *bcon)
_wil_cfg80211_get_proberesp_ies(const u8 *proberesp, u16 proberesp_len,
				u16 *ies_len)
{
{
	int rc;
	u8 *ies = NULL;
	u16 len = 0, proberesp_len = 0;
	u8 *ies = NULL, *proberesp = NULL;


	if (bcon->probe_resp) {
	if (proberesp) {
		struct ieee80211_mgmt *f =
		struct ieee80211_mgmt *f =
			(struct ieee80211_mgmt *)bcon->probe_resp;
			(struct ieee80211_mgmt *)proberesp;
		size_t hlen = offsetof(struct ieee80211_mgmt,
		size_t hlen = offsetof(struct ieee80211_mgmt,
				       u.probe_resp.variable);
				       u.probe_resp.variable);
		proberesp = f->u.probe_resp.variable;

		proberesp_len = bcon->probe_resp_len - hlen;
		ies = f->u.probe_resp.variable;
		if (ies_len)
			*ies_len = proberesp_len - hlen;
	}

	return ies;
}
}

static int _wil_cfg80211_set_ies(struct wil6210_vif *vif,
				 struct cfg80211_beacon_data *bcon)
{
	int rc;
	u16 len = 0, proberesp_len = 0;
	u8 *ies = NULL, *proberesp;

	proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp,
						    bcon->probe_resp_len,
						    &proberesp_len);
	rc = _wil_cfg80211_merge_extra_ies(proberesp,
	rc = _wil_cfg80211_merge_extra_ies(proberesp,
					   proberesp_len,
					   proberesp_len,
					   bcon->proberesp_ies,
					   bcon->proberesp_ies,
@@ -1810,6 +1953,9 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
	struct wireless_dev *wdev = ndev->ieee80211_ptr;
	struct wireless_dev *wdev = ndev->ieee80211_ptr;
	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
	u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
	u8 is_go = (wdev->iftype == NL80211_IFTYPE_P2P_GO);
	u16 proberesp_len = 0;
	u8 *proberesp;
	bool ft = false;


	if (pbss)
	if (pbss)
		wmi_nettype = WMI_NETTYPE_P2P;
		wmi_nettype = WMI_NETTYPE_P2P;
@@ -1822,6 +1968,25 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,


	wil_set_recovery_state(wil, fw_recovery_idle);
	wil_set_recovery_state(wil, fw_recovery_idle);


	proberesp = _wil_cfg80211_get_proberesp_ies(bcon->probe_resp,
						    bcon->probe_resp_len,
						    &proberesp_len);
	/* check that the probe response IEs has a MDE */
	if ((proberesp && proberesp_len > 0 &&
	     cfg80211_find_ie(WLAN_EID_MOBILITY_DOMAIN,
			      proberesp,
			      proberesp_len)))
		ft = true;

	if (ft) {
		if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING,
			      wil->fw_capabilities)) {
			wil_err(wil, "FW does not support FT roaming\n");
			return -ENOTSUPP;
		}
		set_bit(wil_vif_ft_roam, vif->status);
	}

	mutex_lock(&wil->mutex);
	mutex_lock(&wil->mutex);


	if (!wil_has_other_active_ifaces(wil, ndev, true, false)) {
	if (!wil_has_other_active_ifaces(wil, ndev, true, false)) {
@@ -1983,6 +2148,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
	mutex_lock(&wil->mutex);
	mutex_lock(&wil->mutex);


	wmi_pcp_stop(vif);
	wmi_pcp_stop(vif);
	clear_bit(wil_vif_ft_roam, vif->status);


	if (last)
	if (last)
		__wil_down(wil);
		__wil_down(wil);
@@ -2002,8 +2168,9 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy,
	struct wil6210_vif *vif = ndev_to_vif(dev);
	struct wil6210_vif *vif = ndev_to_vif(dev);
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);


	wil_dbg_misc(wil, "add station %pM aid %d mid %d\n",
	wil_dbg_misc(wil, "add station %pM aid %d mid %d mask 0x%x set 0x%x\n",
		     mac, params->aid, vif->mid);
		     mac, params->aid, vif->mid,
		     params->sta_flags_mask, params->sta_flags_set);


	if (!disable_ap_sme) {
	if (!disable_ap_sme) {
		wil_err(wil, "not supported with AP SME enabled\n");
		wil_err(wil, "not supported with AP SME enabled\n");
@@ -2383,6 +2550,54 @@ static void wil_cfg80211_reg_notify(struct wiphy *wiphy,
	memcpy(wil->regdomain, request->alpha2, 2);
	memcpy(wil->regdomain, request->alpha2, 2);
}
}


static int
wil_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
			   struct cfg80211_update_ft_ies_params *ftie)
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wil6210_vif *vif = ndev_to_vif(dev);
	struct cfg80211_bss *bss;
	struct wmi_ft_reassoc_cmd reassoc;
	int rc = 0;

	wil_dbg_misc(wil, "update ft ies, mid=%d\n", vif->mid);
	wil_hex_dump_misc("FT IE ", DUMP_PREFIX_OFFSET, 16, 1,
			  ftie->ie, ftie->ie_len, true);

	if (!test_bit(WMI_FW_CAPABILITY_FT_ROAMING, wil->fw_capabilities)) {
		wil_err(wil, "FW does not support FT roaming\n");
		return -EOPNOTSUPP;
	}

	rc = wmi_update_ft_ies(vif, ftie->ie_len, ftie->ie);
	if (rc)
		return rc;

	if (!test_bit(wil_vif_ft_roam, vif->status))
		/* vif is not roaming */
		return 0;

	/* wil_vif_ft_roam is set. wil_cfg80211_update_ft_ies is used as
	 * a trigger for reassoc
	 */

	bss = vif->bss;
	if (!bss) {
		wil_err(wil, "FT: bss is NULL\n");
		return -EINVAL;
	}

	memset(&reassoc, 0, sizeof(reassoc));
	ether_addr_copy(reassoc.bssid, bss->bssid);

	rc = wmi_send(wil, WMI_FT_REASSOC_CMDID, vif->mid,
		      &reassoc, sizeof(reassoc));
	if (rc)
		wil_err(wil, "FT: reassoc failed (%d)\n", rc);

	return rc;
}

static const struct cfg80211_ops wil_cfg80211_ops = {
static const struct cfg80211_ops wil_cfg80211_ops = {
	.add_virtual_intf = wil_cfg80211_add_iface,
	.add_virtual_intf = wil_cfg80211_add_iface,
	.del_virtual_intf = wil_cfg80211_del_iface,
	.del_virtual_intf = wil_cfg80211_del_iface,
@@ -2418,6 +2633,7 @@ static const struct cfg80211_ops wil_cfg80211_ops = {
	.resume = wil_cfg80211_resume,
	.resume = wil_cfg80211_resume,
	.sched_scan_start = wil_cfg80211_sched_scan_start,
	.sched_scan_start = wil_cfg80211_sched_scan_start,
	.sched_scan_stop = wil_cfg80211_sched_scan_stop,
	.sched_scan_stop = wil_cfg80211_sched_scan_stop,
	.update_ft_ies = wil_cfg80211_update_ft_ies,
};
};


static void wil_wiphy_init(struct wiphy *wiphy)
static void wil_wiphy_init(struct wiphy *wiphy)
+18 −29
Original line number Original line Diff line number Diff line
@@ -726,32 +726,6 @@ struct dentry *wil_debugfs_create_ioblob(const char *name,
	return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob);
	return debugfs_create_file(name, mode, parent, wil_blob, &fops_ioblob);
}
}


/*---reset---*/
static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
				    size_t len, loff_t *ppos)
{
	struct wil6210_priv *wil = file->private_data;
	struct net_device *ndev = wil->main_ndev;

	/**
	 * BUG:
	 * this code does NOT sync device state with the rest of system
	 * use with care, debug only!!!
	 */
	rtnl_lock();
	dev_close(ndev);
	ndev->flags &= ~IFF_UP;
	rtnl_unlock();
	wil_reset(wil, true);

	return len;
}

static const struct file_operations fops_reset = {
	.write = wil_write_file_reset,
	.open  = simple_open,
};

/*---write channel 1..4 to rxon for it, 0 to rxoff---*/
/*---write channel 1..4 to rxon for it, 0 to rxoff---*/
static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
				   size_t len, loff_t *ppos)
				   size_t len, loff_t *ppos)
@@ -1264,6 +1238,9 @@ static int wil_rx_buff_mgmt_debugfs_show(struct seq_file *s, void *data)
	int num_active;
	int num_active;
	int num_free;
	int num_free;


	if (!rbm->buff_arr)
		return -EINVAL;

	seq_printf(s, "  size = %zu\n", rbm->size);
	seq_printf(s, "  size = %zu\n", rbm->size);
	seq_printf(s, "  free_list_empty_cnt = %lu\n",
	seq_printf(s, "  free_list_empty_cnt = %lu\n",
		   rbm->free_list_empty_cnt);
		   rbm->free_list_empty_cnt);
@@ -1734,6 +1711,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
		char *status = "unknown";
		char *status = "unknown";
		u8 aid = 0;
		u8 aid = 0;
		u8 mid;
		u8 mid;
		bool sta_connected = false;


		switch (p->status) {
		switch (p->status) {
		case wil_sta_unused:
		case wil_sta_unused:
@@ -1748,8 +1726,20 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
			break;
			break;
		}
		}
		mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX;
		mid = (p->status != wil_sta_unused) ? p->mid : U8_MAX;
		seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i, p->addr, status,
		if (mid < wil->max_vifs) {
			   mid, aid);
			struct wil6210_vif *vif = wil->vifs[mid];

			if (vif->wdev.iftype == NL80211_IFTYPE_STATION &&
			    p->status == wil_sta_connected)
				sta_connected = true;
		}
		/* print roam counter only for connected stations */
		if (sta_connected)
			seq_printf(s, "[%d] %pM connected (roam counter %d) MID %d AID %d\n",
				   i, p->addr, p->stats.ft_roams, mid, aid);
		else
			seq_printf(s, "[%d] %pM %s MID %d AID %d\n", i,
				   p->addr, status, mid, aid);


		if (p->status == wil_sta_connected) {
		if (p->status == wil_sta_connected) {
			spin_lock_bh(&p->tid_rx_lock);
			spin_lock_bh(&p->tid_rx_lock);
@@ -2491,7 +2481,6 @@ static const struct {
	{"bf",		0444,		&fops_bf},
	{"bf",		0444,		&fops_bf},
	{"ssid",	0644,		&fops_ssid},
	{"ssid",	0644,		&fops_ssid},
	{"mem_val",	0644,		&fops_memread},
	{"mem_val",	0644,		&fops_memread},
	{"reset",	0244,		&fops_reset},
	{"rxon",	0244,		&fops_rxon},
	{"rxon",	0244,		&fops_rxon},
	{"tx_mgmt",	0244,		&fops_txmgmt},
	{"tx_mgmt",	0244,		&fops_txmgmt},
	{"wmi_send", 0244,		&fops_wmi},
	{"wmi_send", 0244,		&fops_wmi},
+2 −0
Original line number Original line Diff line number Diff line
@@ -362,6 +362,8 @@ static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
			vif->bss = NULL;
			vif->bss = NULL;
		}
		}
		clear_bit(wil_vif_fwconnecting, vif->status);
		clear_bit(wil_vif_fwconnecting, vif->status);
		clear_bit(wil_vif_ft_roam, vif->status);

		break;
		break;
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
	case NL80211_IFTYPE_P2P_GO:
+83 −0
Original line number Original line Diff line number Diff line
@@ -1085,6 +1085,88 @@ static int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
	return rc;
	return rc;
}
}


static int wil_tx_vring_modify(struct wil6210_vif *vif, int ring_id, int cid,
			       int tid)
{
	struct wil6210_priv *wil = vif_to_wil(vif);
	int rc;
	struct wmi_vring_cfg_cmd cmd = {
		.action = cpu_to_le32(WMI_VRING_CMD_MODIFY),
		.vring_cfg = {
			.tx_sw_ring = {
				.max_mpdu_size =
					cpu_to_le16(wil_mtu2macbuf(mtu_max)),
				.ring_size = 0,
			},
			.ringid = ring_id,
			.cidxtid = mk_cidxtid(cid, tid),
			.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
			.mac_ctrl = 0,
			.to_resolution = 0,
			.agg_max_wsize = 0,
			.schd_params = {
				.priority = cpu_to_le16(0),
				.timeslot_us = cpu_to_le16(0xfff),
			},
		},
	};
	struct {
		struct wmi_cmd_hdr wmi;
		struct wmi_vring_cfg_done_event cmd;
	} __packed reply = {
		.cmd = {.status = WMI_FW_STATUS_FAILURE},
	};
	struct wil_ring *vring = &wil->ring_tx[ring_id];
	struct wil_ring_tx_data *txdata = &wil->ring_tx_data[ring_id];

	wil_dbg_misc(wil, "vring_modify: ring %d cid %d tid %d\n", ring_id,
		     cid, tid);
	lockdep_assert_held(&wil->mutex);

	if (!vring->va) {
		wil_err(wil, "Tx ring [%d] not allocated\n", ring_id);
		return -EINVAL;
	}

	if (wil->ring2cid_tid[ring_id][0] != cid ||
	    wil->ring2cid_tid[ring_id][1] != tid) {
		wil_err(wil, "ring info does not match cid=%u tid=%u\n",
			wil->ring2cid_tid[ring_id][0],
			wil->ring2cid_tid[ring_id][1]);
	}

	cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);

	rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
		      WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
	if (rc)
		goto fail;

	if (reply.cmd.status != WMI_FW_STATUS_SUCCESS) {
		wil_err(wil, "Tx modify failed, status 0x%02x\n",
			reply.cmd.status);
		rc = -EINVAL;
		goto fail;
	}

	/* set BA aggregation window size to 0 to force a new BA with the
	 * new AP
	 */
	txdata->agg_wsize = 0;
	if (txdata->dot1x_open && agg_wsize >= 0)
		wil_addba_tx_request(wil, ring_id, agg_wsize);

	return 0;
fail:
	spin_lock_bh(&txdata->lock);
	txdata->dot1x_open = false;
	txdata->enabled = 0;
	spin_unlock_bh(&txdata->lock);
	wil->ring2cid_tid[ring_id][0] = WIL6210_MAX_CID;
	wil->ring2cid_tid[ring_id][1] = 0;
	return rc;
}

int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
{
{
	struct wil6210_priv *wil = vif_to_wil(vif);
	struct wil6210_priv *wil = vif_to_wil(vif);
@@ -2307,6 +2389,7 @@ void wil_init_txrx_ops_legacy_dma(struct wil6210_priv *wil)
	wil->txrx_ops.ring_init_bcast = wil_vring_init_bcast;
	wil->txrx_ops.ring_init_bcast = wil_vring_init_bcast;
	wil->txrx_ops.tx_init = wil_tx_init;
	wil->txrx_ops.tx_init = wil_tx_init;
	wil->txrx_ops.tx_fini = wil_tx_fini;
	wil->txrx_ops.tx_fini = wil_tx_fini;
	wil->txrx_ops.tx_ring_modify = wil_tx_vring_modify;
	/* RX ops */
	/* RX ops */
	wil->txrx_ops.rx_init = wil_rx_init;
	wil->txrx_ops.rx_init = wil_rx_init;
	wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp;
	wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp;
+11 −0
Original line number Original line Diff line number Diff line
@@ -748,6 +748,16 @@ static int wil_ring_init_tx_edma(struct wil6210_vif *vif, int ring_id,
	return rc;
	return rc;
}
}


static int wil_tx_ring_modify_edma(struct wil6210_vif *vif, int ring_id,
				   int cid, int tid)
{
	struct wil6210_priv *wil = vif_to_wil(vif);

	wil_err(wil, "ring modify is not supported for EDMA\n");

	return -EOPNOTSUPP;
}

/* This function is used only for RX SW reorder */
/* This function is used only for RX SW reorder */
static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
static int wil_check_bar(struct wil6210_priv *wil, void *msg, int cid,
			 struct sk_buff *skb, struct wil_net_stats *stats)
			 struct sk_buff *skb, struct wil_net_stats *stats)
@@ -1601,6 +1611,7 @@ void wil_init_txrx_ops_edma(struct wil6210_priv *wil)
	wil->txrx_ops.tx_desc_map = wil_tx_desc_map_edma;
	wil->txrx_ops.tx_desc_map = wil_tx_desc_map_edma;
	wil->txrx_ops.tx_desc_unmap = wil_tx_desc_unmap_edma;
	wil->txrx_ops.tx_desc_unmap = wil_tx_desc_unmap_edma;
	wil->txrx_ops.tx_ring_tso = __wil_tx_ring_tso_edma;
	wil->txrx_ops.tx_ring_tso = __wil_tx_ring_tso_edma;
	wil->txrx_ops.tx_ring_modify = wil_tx_ring_modify_edma;
	/* RX ops */
	/* RX ops */
	wil->txrx_ops.rx_init = wil_rx_init_edma;
	wil->txrx_ops.rx_init = wil_rx_init_edma;
	wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp_edma;
	wil->txrx_ops.wmi_addba_rx_resp = wmi_addba_rx_resp_edma;
Loading