Commit 3248044e authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'wireless-drivers-next-2020-05-25' of...

Merge tag 'wireless-drivers-next-2020-05-25' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next



Kalle Valo says:

====================
wireless-drivers-next patches for v5.8

Second set of patches for v5.8. Lots of new features and new supported
hardware for mt76. Also rtw88 got new hardware support.

Major changes:

rtw88

* add support for Realtek 8723DE PCI adapter

* rename rtw88.ko/rtwpci.ko to rtw88_core.ko/rtw88_pci.ko

iwlwifi

* stop supporting swcrypto and bt_coex_active module parameters on
  mvm devices

* enable A-AMSDU in low latency

mt76

* new devices for mt76x0/mt76x2

* support for non-offload firmware on mt7663

* hw/sched scan support for mt7663

* mt7615/mt7663 MSI support

* TDLS support

* mt7603/mt7615 rate control fixes

* new driver for mt7915

* wowlan support for mt7663

* suspend/resume support for mt7663
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 617504c6 472f0a24
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ Optional properties:
- mediatek,mtd-eeprom: Specify a MTD partition + offset containing EEPROM data
- big-endian: if the radio eeprom partition is written in big-endian, specify
  this property
- mediatek,eeprom-merge-otp: Merge EEPROM data with OTP data. Can be used on
  boards where the flash calibration data is generic and specific calibration
  data should be pulled from the OTP ROM

The MAC address can as well be set with corresponding optional properties
defined in net/ethernet.txt.
+227 −38
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "p2p.h"
#include "btcoex.h"
#include "pno.h"
#include "fwsignal.h"
#include "cfg80211.h"
#include "feature.h"
#include "fwil.h"
@@ -1819,6 +1820,10 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
		switch (sme->crypto.akm_suites[0]) {
		case WLAN_AKM_SUITE_SAE:
			val = WPA3_AUTH_SAE_PSK;
			if (sme->crypto.sae_pwd) {
				brcmf_dbg(INFO, "using SAE offload\n");
				profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
			}
			break;
		default:
			bphy_err(drvr, "invalid cipher group (%d)\n",
@@ -2104,11 +2109,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
		goto done;
	}

	if (sme->crypto.sae_pwd) {
		brcmf_dbg(INFO, "using SAE offload\n");
		profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE;
	}

	if (sme->crypto.psk &&
	    profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) {
		if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
@@ -2468,6 +2468,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
	if (!ext_key)
		key->flags = BRCMF_PRIMARY_KEY;

	if (params->seq && params->seq_len == 6) {
		/* rx iv */
		u8 *ivptr;

		ivptr = (u8 *)params->seq;
		key->rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
			(ivptr[3] << 8) | ivptr[2];
		key->rxiv.lo = (ivptr[1] << 8) | ivptr[0];
		key->iv_initialized = true;
	}

	switch (params->cipher) {
	case WLAN_CIPHER_SUITE_WEP40:
		key->algo = CRYPTO_ALGO_WEP1;
@@ -4612,6 +4623,48 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
	return err;
}

static s32
brcmf_parse_configure_security(struct brcmf_if *ifp,
			       struct cfg80211_ap_settings *settings,
			       enum nl80211_iftype dev_role)
{
	const struct brcmf_tlv *rsn_ie;
	const struct brcmf_vs_tlv *wpa_ie;
	s32 err = 0;

	/* find the RSN_IE */
	rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
				  settings->beacon.tail_len, WLAN_EID_RSN);

	/* find the WPA_IE */
	wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
				  settings->beacon.tail_len);

	if (wpa_ie || rsn_ie) {
		brcmf_dbg(TRACE, "WPA(2) IE is found\n");
		if (wpa_ie) {
			/* WPA IE */
			err = brcmf_configure_wpaie(ifp, wpa_ie, false);
			if (err < 0)
				return err;
		} else {
			struct brcmf_vs_tlv *tmp_ie;

			tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;

			/* RSN IE */
			err = brcmf_configure_wpaie(ifp, tmp_ie, true);
			if (err < 0)
				return err;
		}
	} else {
		brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
		brcmf_configure_opensecurity(ifp);
	}

	return err;
}

static s32
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
			struct cfg80211_ap_settings *settings)
@@ -4624,8 +4677,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
	const struct brcmf_tlv *country_ie;
	struct brcmf_ssid_le ssid_le;
	s32 err = -EPERM;
	const struct brcmf_tlv *rsn_ie;
	const struct brcmf_vs_tlv *wpa_ie;
	struct brcmf_join_params join_params;
	enum nl80211_iftype dev_role;
	struct brcmf_fil_bss_enable_le bss_enable;
@@ -4679,36 +4730,6 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
		brcmf_configure_arp_nd_offload(ifp, false);
	}

	/* find the RSN_IE */
	rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
				  settings->beacon.tail_len, WLAN_EID_RSN);

	/* find the WPA_IE */
	wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail,
				  settings->beacon.tail_len);

	if ((wpa_ie != NULL || rsn_ie != NULL)) {
		brcmf_dbg(TRACE, "WPA(2) IE is found\n");
		if (wpa_ie != NULL) {
			/* WPA IE */
			err = brcmf_configure_wpaie(ifp, wpa_ie, false);
			if (err < 0)
				goto exit;
		} else {
			struct brcmf_vs_tlv *tmp_ie;

			tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;

			/* RSN IE */
			err = brcmf_configure_wpaie(ifp, tmp_ie, true);
			if (err < 0)
				goto exit;
		}
	} else {
		brcmf_dbg(TRACE, "No WPA(2) IEs found\n");
		brcmf_configure_opensecurity(ifp);
	}

	/* Parameters shared by all radio interfaces */
	if (!mbss) {
		if ((supports_11d) && (is_11d != ifp->vif->is_11d)) {
@@ -4790,6 +4811,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
			bphy_err(drvr, "BRCMF_C_UP error (%d)\n", err);
			goto exit;
		}

		err = brcmf_parse_configure_security(ifp, settings,
						     NL80211_IFTYPE_AP);
		if (err < 0) {
			bphy_err(drvr, "brcmf_parse_configure_security error\n");
			goto exit;
		}

		/* On DOWN the firmware removes the WEP keys, reconfigure
		 * them if they were set.
		 */
@@ -4822,6 +4851,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
				 chanspec, err);
			goto exit;
		}

		err = brcmf_parse_configure_security(ifp, settings,
						     NL80211_IFTYPE_P2P_GO);
		if (err < 0) {
			brcmf_err("brcmf_parse_configure_security error\n");
			goto exit;
		}

		err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le,
						sizeof(ssid_le));
		if (err < 0) {
@@ -5510,7 +5547,8 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,
	u32 event = e->event_code;
	u32 status = e->status;

	if (vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK &&
	if ((vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK ||
	     vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_SAE) &&
	    event == BRCMF_E_PSK_SUP &&
	    status == BRCMF_E_STATUS_FWSUP_COMPLETED)
		set_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
@@ -5586,12 +5624,151 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg)
	conn_info->resp_ie_len = 0;
}

u8 brcmf_map_prio_to_prec(void *config, u8 prio)
{
	struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)config;

	if (!cfg)
		return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ?
		       (prio ^ 2) : prio;

	/* For those AC(s) with ACM flag set to 1, convert its 4-level priority
	 * to an 8-level precedence which is the same as BE's
	 */
	if (prio > PRIO_8021D_EE &&
	    cfg->ac_priority[prio] == cfg->ac_priority[PRIO_8021D_BE])
		return cfg->ac_priority[prio] * 2;

	/* Conversion of 4-level priority to 8-level precedence */
	if (prio == PRIO_8021D_BE || prio == PRIO_8021D_BK ||
	    prio == PRIO_8021D_CL || prio == PRIO_8021D_VO)
		return cfg->ac_priority[prio] * 2;
	else
		return cfg->ac_priority[prio] * 2 + 1;
}

u8 brcmf_map_prio_to_aci(void *config, u8 prio)
{
	/* Prio here refers to the 802.1d priority in range of 0 to 7.
	 * ACI here refers to the WLAN AC Index in range of 0 to 3.
	 * This function will return ACI corresponding to input prio.
	 */
	struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)config;

	if (cfg)
		return cfg->ac_priority[prio];

	return prio;
}

static void brcmf_init_wmm_prio(u8 *priority)
{
	/* Initialize AC priority array to default
	 * 802.1d priority as per following table:
	 * 802.1d prio 0,3 maps to BE
	 * 802.1d prio 1,2 maps to BK
	 * 802.1d prio 4,5 maps to VI
	 * 802.1d prio 6,7 maps to VO
	 */
	priority[0] = BRCMF_FWS_FIFO_AC_BE;
	priority[3] = BRCMF_FWS_FIFO_AC_BE;
	priority[1] = BRCMF_FWS_FIFO_AC_BK;
	priority[2] = BRCMF_FWS_FIFO_AC_BK;
	priority[4] = BRCMF_FWS_FIFO_AC_VI;
	priority[5] = BRCMF_FWS_FIFO_AC_VI;
	priority[6] = BRCMF_FWS_FIFO_AC_VO;
	priority[7] = BRCMF_FWS_FIFO_AC_VO;
}

static void brcmf_wifi_prioritize_acparams(const
	struct brcmf_cfg80211_edcf_acparam *acp, u8 *priority)
{
	u8 aci;
	u8 aifsn;
	u8 ecwmin;
	u8 ecwmax;
	u8 acm;
	u8 ranking_basis[EDCF_AC_COUNT];
	u8 aci_prio[EDCF_AC_COUNT]; /* AC_BE, AC_BK, AC_VI, AC_VO */
	u8 index;

	for (aci = 0; aci < EDCF_AC_COUNT; aci++, acp++) {
		aifsn  = acp->ACI & EDCF_AIFSN_MASK;
		acm = (acp->ACI & EDCF_ACM_MASK) ? 1 : 0;
		ecwmin = acp->ECW & EDCF_ECWMIN_MASK;
		ecwmax = (acp->ECW & EDCF_ECWMAX_MASK) >> EDCF_ECWMAX_SHIFT;
		brcmf_dbg(CONN, "ACI %d aifsn %d acm %d ecwmin %d ecwmax %d\n",
			  aci, aifsn, acm, ecwmin, ecwmax);
		/* Default AC_VO will be the lowest ranking value */
		ranking_basis[aci] = aifsn + ecwmin + ecwmax;
		/* Initialise priority starting at 0 (AC_BE) */
		aci_prio[aci] = 0;

		/* If ACM is set, STA can't use this AC as per 802.11.
		 * Change the ranking to BE
		 */
		if (aci != AC_BE && aci != AC_BK && acm == 1)
			ranking_basis[aci] = ranking_basis[AC_BE];
	}

	/* Ranking method which works for AC priority
	 * swapping when values for cwmin, cwmax and aifsn are varied
	 * Compare each aci_prio against each other aci_prio
	 */
	for (aci = 0; aci < EDCF_AC_COUNT; aci++) {
		for (index = 0; index < EDCF_AC_COUNT; index++) {
			if (index != aci) {
				/* Smaller ranking value has higher priority,
				 * so increment priority for each ACI which has
				 * a higher ranking value
				 */
				if (ranking_basis[aci] < ranking_basis[index])
					aci_prio[aci]++;
			}
		}
	}

	/* By now, aci_prio[] will be in range of 0 to 3.
	 * Use ACI prio to get the new priority value for
	 * each 802.1d traffic type, in this range.
	 */
	if (!(aci_prio[AC_BE] == aci_prio[AC_BK] &&
	      aci_prio[AC_BK] == aci_prio[AC_VI] &&
	      aci_prio[AC_VI] == aci_prio[AC_VO])) {
		/* 802.1d 0,3 maps to BE */
		priority[0] = aci_prio[AC_BE];
		priority[3] = aci_prio[AC_BE];

		/* 802.1d 1,2 maps to BK */
		priority[1] = aci_prio[AC_BK];
		priority[2] = aci_prio[AC_BK];

		/* 802.1d 4,5 maps to VO */
		priority[4] = aci_prio[AC_VI];
		priority[5] = aci_prio[AC_VI];

		/* 802.1d 6,7 maps to VO */
		priority[6] = aci_prio[AC_VO];
		priority[7] = aci_prio[AC_VO];
	} else {
		/* Initialize to default priority */
		brcmf_init_wmm_prio(priority);
	}

	brcmf_dbg(CONN, "Adj prio BE 0->%d, BK 1->%d, BK 2->%d, BE 3->%d\n",
		  priority[0], priority[1], priority[2], priority[3]);

	brcmf_dbg(CONN, "Adj prio VI 4->%d, VI 5->%d, VO 6->%d, VO 7->%d\n",
		  priority[4], priority[5], priority[6], priority[7]);
}

static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
			       struct brcmf_if *ifp)
{
	struct brcmf_pub *drvr = cfg->pub;
	struct brcmf_cfg80211_assoc_ielen_le *assoc_info;
	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
	struct brcmf_cfg80211_edcf_acparam edcf_acparam_info[EDCF_AC_COUNT];
	u32 req_len;
	u32 resp_len;
	s32 err = 0;
@@ -5640,6 +5817,17 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg,
			    GFP_KERNEL);
		if (!conn_info->resp_ie)
			conn_info->resp_ie_len = 0;

		err = brcmf_fil_iovar_data_get(ifp, "wme_ac_sta",
					       edcf_acparam_info,
					       sizeof(edcf_acparam_info));
		if (err) {
			brcmf_err("could not get wme_ac_sta (%d)\n", err);
			return err;
		}

		brcmf_wifi_prioritize_acparams(edcf_acparam_info,
					       cfg->ac_priority);
	} else {
		conn_info->resp_ie_len = 0;
		conn_info->resp_ie = NULL;
@@ -6056,6 +6244,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg)
	mutex_init(&cfg->usr_sync);
	brcmf_init_escan(cfg);
	brcmf_init_conf(cfg->conf);
	brcmf_init_wmm_prio(cfg->ac_priority);
	init_completion(&cfg->vif_disabled);
	return err;
}
+24 −0
Original line number Diff line number Diff line
@@ -23,6 +23,23 @@
#define WL_ROAM_TRIGGER_LEVEL		-75
#define WL_ROAM_DELTA			20

/* WME Access Category Indices (ACIs) */
#define AC_BE			0	/* Best Effort */
#define AC_BK			1	/* Background */
#define AC_VI			2	/* Video */
#define AC_VO			3	/* Voice */
#define EDCF_AC_COUNT		4
#define MAX_8021D_PRIO		8

#define EDCF_ACI_MASK			0x60
#define EDCF_ACI_SHIFT			5
#define EDCF_ACM_MASK                  0x10
#define EDCF_ECWMIN_MASK		0x0f
#define EDCF_ECWMAX_SHIFT		4
#define EDCF_AIFSN_MASK			0x0f
#define EDCF_AIFSN_MAX			15
#define EDCF_ECWMAX_MASK		0xf0

/* Keep BRCMF_ESCAN_BUF_SIZE below 64K (65536). Allocing over 64K can be
 * problematic on some systems and should be avoided.
 */
@@ -209,6 +226,12 @@ struct brcmf_cfg80211_assoc_ielen_le {
	__le32 resp_len;
};

struct brcmf_cfg80211_edcf_acparam {
	u8 ACI;
	u8 ECW;
	u16 TXOP;        /* stored in network order (ls octet first) */
};

/* dongle escan state */
enum wl_escan_state {
	WL_ESCAN_STATE_IDLE,
@@ -327,6 +350,7 @@ struct brcmf_cfg80211_info {
	struct brcmf_assoclist_le assoclist;
	struct brcmf_cfg80211_wowl wowl;
	struct brcmf_pno_info *pno;
	u8 ac_priority[MAX_8021D_PRIO];
};

/**
+4 −0
Original line number Diff line number Diff line
@@ -72,4 +72,8 @@ static inline void
brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) {}
#endif

u8 brcmf_map_prio_to_prec(void *cfg, u8 prio);

u8 brcmf_map_prio_to_aci(void *cfg, u8 prio);

#endif /* BRCMFMAC_COMMON_H */
+2 −2
Original line number Diff line number Diff line
@@ -26,10 +26,10 @@
#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)

static const u8 brcmf_flowring_prio2fifo[] = {
	1,
	0,
	0,
	1,
	1,
	0,
	2,
	2,
	3,
Loading