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

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

Merge tag 'wireless-drivers-next-for-davem-2017-07-03' of...

Merge tag 'wireless-drivers-next-for-davem-2017-07-03' of https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next



Kalle Valo says:

====================
wireless-drivers-next patches for 4.13

Last minute changes to get new hardware and firmware support for
iwlwifi and few other changes I was able to squeeze in. Also two
patches for ieee80211.h and nl80211 as Johannes is away.

Major changes:

iwlwifi

* some important fixes for 9000 HW

* support for version 30 of the FW API for 8000 and 9000 series

* a few new PCI IDs for 9000 series

* reorganization of common files

brcmfmac

* support 4-way handshake offloading for WPA/WPA2-PSK and 802.1X
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3a3f7d13 17d9aa66
Loading
Loading
Loading
Loading
+137 −13
Original line number Diff line number Diff line
@@ -1357,6 +1357,27 @@ static u16 brcmf_map_fw_linkdown_reason(const struct brcmf_event_msg *e)
	return reason;
}

static int brcmf_set_pmk(struct brcmf_if *ifp, const u8 *pmk_data, u16 pmk_len)
{
	struct brcmf_wsec_pmk_le pmk;
	int i, err;

	/* convert to firmware key format */
	pmk.key_len = cpu_to_le16(pmk_len << 1);
	pmk.flags = cpu_to_le16(BRCMF_WSEC_PASSPHRASE);
	for (i = 0; i < pmk_len; i++)
		snprintf(&pmk.key[2 * i], 3, "%02x", pmk_data[i]);

	/* store psk in firmware */
	err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_WSEC_PMK,
				     &pmk, sizeof(pmk));
	if (err < 0)
		brcmf_err("failed to change PSK in firmware (len=%u)\n",
			  pmk_len);

	return err;
}

static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
{
	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy);
@@ -1379,6 +1400,10 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
	clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
	clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
	brcmf_btcoex_set_mode(vif, BRCMF_BTCOEX_ENABLED, 0);
	if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
		brcmf_set_pmk(vif->ifp, NULL, 0);
		vif->profile.use_fwsup = BRCMF_PROFILE_FWSUP_NONE;
	}
	brcmf_dbg(TRACE, "Exit\n");
}

@@ -1692,6 +1717,7 @@ static s32
brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
{
	struct brcmf_if *ifp = netdev_priv(ndev);
	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
	s32 val;
	s32 err;
	const struct brcmf_tlv *rsn_ie;
@@ -1702,6 +1728,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
	u32 mfp;
	u16 count;

	profile->use_fwsup = BRCMF_PROFILE_FWSUP_NONE;

	if (!sme->crypto.n_akm_suites)
		return 0;

@@ -1714,6 +1742,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
		switch (sme->crypto.akm_suites[0]) {
		case WLAN_AKM_SUITE_8021X:
			val = WPA_AUTH_UNSPECIFIED;
			if (sme->want_1x)
				profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
			break;
		case WLAN_AKM_SUITE_PSK:
			val = WPA_AUTH_PSK;
@@ -1727,9 +1757,13 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
		switch (sme->crypto.akm_suites[0]) {
		case WLAN_AKM_SUITE_8021X:
			val = WPA2_AUTH_UNSPECIFIED;
			if (sme->want_1x)
				profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
			break;
		case WLAN_AKM_SUITE_8021X_SHA256:
			val = WPA2_AUTH_1X_SHA256;
			if (sme->want_1x)
				profile->use_fwsup = BRCMF_PROFILE_FWSUP_1X;
			break;
		case WLAN_AKM_SUITE_PSK_SHA256:
			val = WPA2_AUTH_PSK_SHA256;
@@ -1744,6 +1778,9 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
		}
	}

	if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_1X)
		brcmf_dbg(INFO, "using 1X offload\n");

	if (!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MFP))
		goto skip_mfp_config;
	/* The MFP mode (1 or 2) needs to be determined, parse IEs. The
@@ -1916,6 +1953,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
{
	struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
	struct brcmf_if *ifp = netdev_priv(ndev);
	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
	struct ieee80211_channel *chan = sme->channel;
	struct brcmf_join_params join_params;
	size_t join_params_size;
@@ -2012,6 +2050,31 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
		goto done;
	}

	if (sme->crypto.psk) {
		if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) {
			err = -EINVAL;
			goto done;
		}
		brcmf_dbg(INFO, "using PSK offload\n");
		profile->use_fwsup = BRCMF_PROFILE_FWSUP_PSK;
	}

	if (profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE) {
		/* enable firmware supplicant for this interface */
		err = brcmf_fil_iovar_int_set(ifp, "sup_wpa", 1);
		if (err < 0) {
			brcmf_err("failed to enable fw supplicant\n");
			goto done;
		}
	}

	if (profile->use_fwsup == BRCMF_PROFILE_FWSUP_PSK) {
		err = brcmf_set_pmk(ifp, sme->crypto.psk,
				    BRCMF_WSEC_MAX_PSK_LEN);
		if (err)
			goto done;
	}

	/* Join with specific BSSID and cached SSID
	 * If SSID is zero join based on BSSID only
	 */
@@ -5151,6 +5214,34 @@ brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
}
#endif

static int brcmf_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
				  const struct cfg80211_pmk_conf *conf)
{
	struct brcmf_if *ifp;

	brcmf_dbg(TRACE, "enter\n");

	/* expect using firmware supplicant for 1X */
	ifp = netdev_priv(dev);
	if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
		return -EINVAL;

	return brcmf_set_pmk(ifp, conf->pmk, conf->pmk_len);
}

static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
				  const u8 *aa)
{
	struct brcmf_if *ifp;

	brcmf_dbg(TRACE, "enter\n");
	ifp = netdev_priv(dev);
	if (WARN_ON(ifp->vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_1X))
		return -EINVAL;

	return brcmf_set_pmk(ifp, NULL, 0);
}

static struct cfg80211_ops brcmf_cfg80211_ops = {
	.add_virtual_intf = brcmf_cfg80211_add_iface,
	.del_virtual_intf = brcmf_cfg80211_del_iface,
@@ -5194,6 +5285,8 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
	.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
	.tdls_oper = brcmf_cfg80211_tdls_oper,
	.update_connect_params = brcmf_cfg80211_update_conn_params,
	.set_pmk = brcmf_cfg80211_set_pmk,
	.del_pmk = brcmf_cfg80211_del_pmk,
};

struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
@@ -5247,16 +5340,31 @@ void brcmf_cfg80211_free_netdev(struct net_device *ndev)
		brcmf_free_vif(vif);
}

static bool brcmf_is_linkup(const struct brcmf_event_msg *e)
static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif,
			    const struct brcmf_event_msg *e)
{
	u32 event = e->event_code;
	u32 status = e->status;

	if (vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK &&
	    event == BRCMF_E_PSK_SUP &&
	    status == BRCMF_E_STATUS_FWSUP_COMPLETED)
		set_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
	if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) {
		brcmf_dbg(CONN, "Processing set ssid\n");
		memcpy(vif->profile.bssid, e->addr, ETH_ALEN);
		if (vif->profile.use_fwsup != BRCMF_PROFILE_FWSUP_PSK)
			return true;

		set_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
	}

	if (test_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state) &&
	    test_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state)) {
		clear_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state);
		clear_bit(BRCMF_VIF_STATUS_ASSOC_SUCCESS, &vif->sme_state);
		return true;
	}
	return false;
}

@@ -5291,6 +5399,13 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg,
		return true;
	}

	if (event == BRCMF_E_PSK_SUP &&
	    status != BRCMF_E_STATUS_FWSUP_COMPLETED) {
		brcmf_dbg(CONN, "Processing failed supplicant state: %u\n",
			  status);
		return true;
	}

	return false;
}

@@ -5441,27 +5556,28 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg,
	struct brcmf_if *ifp = netdev_priv(ndev);
	struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
	struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
	struct cfg80211_connect_resp_params conn_params;

	brcmf_dbg(TRACE, "Enter\n");

	if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING,
			       &ifp->vif->sme_state)) {
		memset(&conn_params, 0, sizeof(conn_params));
		if (completed) {
			brcmf_get_assoc_ies(cfg, ifp);
			memcpy(profile->bssid, e->addr, ETH_ALEN);
			brcmf_update_bss_info(cfg, ifp);
			set_bit(BRCMF_VIF_STATUS_CONNECTED,
				&ifp->vif->sme_state);
		}
		cfg80211_connect_result(ndev,
					(u8 *)profile->bssid,
					conn_info->req_ie,
					conn_info->req_ie_len,
					conn_info->resp_ie,
					conn_info->resp_ie_len,
					completed ? WLAN_STATUS_SUCCESS :
						    WLAN_STATUS_AUTH_TIMEOUT,
					GFP_KERNEL);
			conn_params.status = WLAN_STATUS_SUCCESS;
		} else {
			conn_params.status = WLAN_STATUS_AUTH_TIMEOUT;
		}
		conn_params.bssid = profile->bssid;
		conn_params.req_ie = conn_info->req_ie;
		conn_params.req_ie_len = conn_info->req_ie_len;
		conn_params.resp_ie = conn_info->resp_ie;
		conn_params.resp_ie_len = conn_info->resp_ie_len;
		cfg80211_connect_done(ndev, &conn_params, GFP_KERNEL);
		brcmf_dbg(CONN, "Report connect result - connection %s\n",
			  completed ? "succeeded" : "failed");
	}
@@ -5527,7 +5643,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,

	if (brcmf_is_apmode(ifp->vif)) {
		err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
	} else if (brcmf_is_linkup(e)) {
	} else if (brcmf_is_linkup(ifp->vif, e)) {
		brcmf_dbg(CONN, "Linkup\n");
		if (brcmf_is_ibssmode(ifp->vif)) {
			brcmf_inform_ibss(cfg, ndev, e->addr);
@@ -5695,6 +5811,8 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
			    brcmf_p2p_notify_action_tx_complete);
	brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE,
			    brcmf_p2p_notify_action_tx_complete);
	brcmf_fweh_register(cfg->pub, BRCMF_E_PSK_SUP,
			    brcmf_notify_connect_status);
}

static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
@@ -6491,6 +6609,12 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
		wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
	if (!ifp->drvr->settings->roamoff)
		wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_FWSUP)) {
		wiphy_ext_feature_set(wiphy,
				      NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK);
		wiphy_ext_feature_set(wiphy,
				      NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X);
	}
	wiphy->mgmt_stypes = brcmf_txrx_stypes;
	wiphy->max_remain_on_channel_duration = 5000;
	if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
+13 −2
Original line number Diff line number Diff line
@@ -115,6 +115,12 @@ struct brcmf_cfg80211_security {
	u32 cipher_group;
};

enum brcmf_profile_fwsup {
	BRCMF_PROFILE_FWSUP_NONE,
	BRCMF_PROFILE_FWSUP_PSK,
	BRCMF_PROFILE_FWSUP_1X
};

/**
 * struct brcmf_cfg80211_profile - profile information.
 *
@@ -126,6 +132,7 @@ struct brcmf_cfg80211_profile {
	u8 bssid[ETH_ALEN];
	struct brcmf_cfg80211_security sec;
	struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
	enum brcmf_profile_fwsup use_fwsup;
};

/**
@@ -133,16 +140,20 @@ struct brcmf_cfg80211_profile {
 *
 * @BRCMF_VIF_STATUS_READY: ready for operation.
 * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
 * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
 * @BRCMF_VIF_STATUS_CONNECTED: connected/joined successfully.
 * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress.
 * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
 * @BRCMF_VIF_STATUS_EAP_SUCCUSS: EAPOL handshake successful.
 * @BRCMF_VIF_STATUS_ASSOC_SUCCESS: successful SET_SSID received.
 */
enum brcmf_vif_status {
	BRCMF_VIF_STATUS_READY,
	BRCMF_VIF_STATUS_CONNECTING,
	BRCMF_VIF_STATUS_CONNECTED,
	BRCMF_VIF_STATUS_DISCONNECTING,
	BRCMF_VIF_STATUS_AP_CREATED
	BRCMF_VIF_STATUS_AP_CREATED,
	BRCMF_VIF_STATUS_EAP_SUCCESS,
	BRCMF_VIF_STATUS_ASSOC_SUCCESS,
};

/**
+1 −0
Original line number Diff line number Diff line
@@ -195,6 +195,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
			  drvr->settings->feature_disable);
		ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
	}
	brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");

	/* set chip related quirks */
	switch (drvr->bus_if->chip) {
+3 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
 * WOWL_ARP_ND: ARP and Neighbor Discovery offload support during WOWL.
 * MFP: 802.11w Management Frame Protection.
 * GSCAN: enhanced scan offload feature.
 * FWSUP: Firmware supplicant.
 */
#define BRCMF_FEAT_LIST \
	BRCMF_FEAT_DEF(MBSS) \
@@ -46,7 +47,8 @@
	BRCMF_FEAT_DEF(WOWL_GTK) \
	BRCMF_FEAT_DEF(WOWL_ARP_ND) \
	BRCMF_FEAT_DEF(MFP) \
	BRCMF_FEAT_DEF(GSCAN)
	BRCMF_FEAT_DEF(GSCAN) \
	BRCMF_FEAT_DEF(FWSUP)

/*
 * Quirks:
+30 −0
Original line number Diff line number Diff line
@@ -142,6 +142,16 @@ enum brcmf_fweh_event_code {
#define BRCMF_E_STATUS_CS_ABORT			15
#define BRCMF_E_STATUS_ERROR			16

/* status field values for PSK_SUP event */
#define BRCMF_E_STATUS_FWSUP_WAIT_M1		4
#define BRCMF_E_STATUS_FWSUP_PREP_M2		5
#define BRCMF_E_STATUS_FWSUP_COMPLETED		6
#define BRCMF_E_STATUS_FWSUP_TIMEOUT		7
#define BRCMF_E_STATUS_FWSUP_WAIT_M3		8
#define BRCMF_E_STATUS_FWSUP_PREP_M4		9
#define BRCMF_E_STATUS_FWSUP_WAIT_G1		10
#define BRCMF_E_STATUS_FWSUP_PREP_G2		11

/* reason field values in struct brcmf_event_msg */
#define BRCMF_E_REASON_INITIAL_ASSOC		0
#define BRCMF_E_REASON_LOW_RSSI			1
@@ -161,6 +171,26 @@ enum brcmf_fweh_event_code {
#define BRCMF_E_REASON_TDLS_PEER_CONNECTED	1
#define BRCMF_E_REASON_TDLS_PEER_DISCONNECTED	2

/* reason field values for PSK_SUP event */
#define BRCMF_E_REASON_FWSUP_OTHER		0
#define BRCMF_E_REASON_FWSUP_DECRYPT_KEY_DATA	1
#define BRCMF_E_REASON_FWSUP_BAD_UCAST_WEP128	2
#define BRCMF_E_REASON_FWSUP_BAD_UCAST_WEP40	3
#define BRCMF_E_REASON_FWSUP_UNSUP_KEY_LEN	4
#define BRCMF_E_REASON_FWSUP_PW_KEY_CIPHER	5
#define BRCMF_E_REASON_FWSUP_MSG3_TOO_MANY_IE	6
#define BRCMF_E_REASON_FWSUP_MSG3_IE_MISMATCH	7
#define BRCMF_E_REASON_FWSUP_NO_INSTALL_FLAG	8
#define BRCMF_E_REASON_FWSUP_MSG3_NO_GTK	9
#define BRCMF_E_REASON_FWSUP_GRP_KEY_CIPHER	10
#define BRCMF_E_REASON_FWSUP_GRP_MSG1_NO_GTK	11
#define BRCMF_E_REASON_FWSUP_GTK_DECRYPT_FAIL	12
#define BRCMF_E_REASON_FWSUP_SEND_FAIL		13
#define BRCMF_E_REASON_FWSUP_DEAUTH		14
#define BRCMF_E_REASON_FWSUP_WPA_PSK_TMO	15
#define BRCMF_E_REASON_FWSUP_WPA_PSK_M1_TMO	16
#define BRCMF_E_REASON_FWSUP_WPA_PSK_M3_TMO	17

/* action field values for brcmf_ifevent */
#define BRCMF_E_IF_ADD				1
#define BRCMF_E_IF_DEL				2
Loading