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

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


John Linville says:

====================
Here is another batch of updates intended for 3.6.  This includes a
number of pulls, including ones from the mac80211, iwlwifi, ath6kl, and
wl12xx trees.  I also pulled from the wireless tree to avoid potential
build conflicts.  There are a number of other patches applied directly,
including a number for the Broadcom drivers and the mwifiex driver.

The updates cover the usual variety of new hardware support and feature
enhancements.  It's all good work, but there aren't any big headliners.
This does resolve a net-next/wireless-next merge conflict reported
by Stephen.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ae0eef66 8732baaf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1595,6 +1595,7 @@ M: Arend van Spriel <arend@broadcom.com>
M:	Franky (Zhenhui) Lin <frankyl@broadcom.com>
M:	Kan Yan	<kanyan@broadcom.com>
L:	linux-wireless@vger.kernel.org
L:	brcm80211-dev-list@broadcom.com
S:	Supported
F:	drivers/net/wireless/brcm80211/

+6 −0
Original line number Diff line number Diff line
@@ -28,6 +28,12 @@ static const struct bcma_device_id_name bcma_arm_device_names[] = {

static const struct bcma_device_id_name bcma_bcm_device_names[] = {
	{ BCMA_CORE_OOB_ROUTER, "OOB Router" },
	{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
	{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
	{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
	{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
	{ BCMA_CORE_ALTA, "ALTA (I2S)" },
	{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
	{ BCMA_CORE_INVALID, "Invalid" },
	{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
	{ BCMA_CORE_ILINE20, "ILine 20" },
+174 −34
Original line number Diff line number Diff line
@@ -53,6 +53,11 @@

#define DEFAULT_BG_SCAN_PERIOD 60

struct ath6kl_cfg80211_match_probe_ssid {
	struct cfg80211_ssid ssid;
	u8 flag;
};

static struct ieee80211_rate ath6kl_rates[] = {
	RATETAB_ENT(10, 0x1, 0),
	RATETAB_ENT(20, 0x2, 0),
@@ -576,6 +581,9 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,

	vif->nw_type = vif->next_mode;

	/* enable enhanced bmiss detection if applicable */
	ath6kl_cfg80211_sta_bmiss_enhance(vif, true);

	if (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT)
		nw_subtype = SUBTYPE_P2PCLIENT;

@@ -852,20 +860,6 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
		}
	}

	/*
	 * Send a disconnect command to target when a disconnect event is
	 * received with reason code other than 3 (DISCONNECT_CMD - disconnect
	 * request from host) to make the firmware stop trying to connect even
	 * after giving disconnect event. There will be one more disconnect
	 * event for this disconnect command with reason code DISCONNECT_CMD
	 * which will be notified to cfg80211.
	 */

	if (reason != DISCONNECT_CMD) {
		ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
		return;
	}

	clear_bit(CONNECT_PEND, &vif->flags);

	if (vif->sme_state == SME_CONNECTING) {
@@ -875,32 +869,96 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
					WLAN_STATUS_UNSPECIFIED_FAILURE,
					GFP_KERNEL);
	} else if (vif->sme_state == SME_CONNECTED) {
		cfg80211_disconnected(vif->ndev, reason,
		cfg80211_disconnected(vif->ndev, proto_reason,
				      NULL, 0, GFP_KERNEL);
	}

	vif->sme_state = SME_DISCONNECTED;

	/*
	 * Send a disconnect command to target when a disconnect event is
	 * received with reason code other than 3 (DISCONNECT_CMD - disconnect
	 * request from host) to make the firmware stop trying to connect even
	 * after giving disconnect event. There will be one more disconnect
	 * event for this disconnect command with reason code DISCONNECT_CMD
	 * which won't be notified to cfg80211.
	 */
	if (reason != DISCONNECT_CMD)
		ath6kl_wmi_disconnect_cmd(ar->wmi, vif->fw_vif_idx);
}

static int ath6kl_set_probed_ssids(struct ath6kl *ar,
				   struct ath6kl_vif *vif,
				   struct cfg80211_ssid *ssids, int n_ssids)
				   struct cfg80211_ssid *ssids, int n_ssids,
				   struct cfg80211_match_set *match_set,
				   int n_match_ssid)
{
	u8 i;
	u8 i, j, index_to_add, ssid_found = false;
	struct ath6kl_cfg80211_match_probe_ssid ssid_list[MAX_PROBED_SSIDS];

	if (n_ssids > MAX_PROBED_SSID_INDEX)
	memset(ssid_list, 0, sizeof(ssid_list));

	if (n_ssids > MAX_PROBED_SSIDS ||
	    n_match_ssid > MAX_PROBED_SSIDS)
		return -EINVAL;

	for (i = 0; i < n_ssids; i++) {
		memcpy(ssid_list[i].ssid.ssid,
		       ssids[i].ssid,
		       ssids[i].ssid_len);
		ssid_list[i].ssid.ssid_len = ssids[i].ssid_len;

		if (ssids[i].ssid_len)
			ssid_list[i].flag = SPECIFIC_SSID_FLAG;
		else
			ssid_list[i].flag = ANY_SSID_FLAG;

		if (n_match_ssid == 0)
			ssid_list[i].flag |= MATCH_SSID_FLAG;
	}

	index_to_add = i;

	for (i = 0; i < n_match_ssid; i++) {
		ssid_found = false;

		for (j = 0; j < n_ssids; j++) {
			if ((match_set[i].ssid.ssid_len ==
			     ssid_list[j].ssid.ssid_len) &&
			    (!memcmp(ssid_list[j].ssid.ssid,
				     match_set[i].ssid.ssid,
				     match_set[i].ssid.ssid_len))) {
				ssid_list[j].flag |= MATCH_SSID_FLAG;
				ssid_found = true;
				break;
			}
		}

		if (ssid_found)
			continue;

		if (index_to_add >= MAX_PROBED_SSIDS)
			continue;

		ssid_list[index_to_add].ssid.ssid_len =
			match_set[i].ssid.ssid_len;
		memcpy(ssid_list[index_to_add].ssid.ssid,
		       match_set[i].ssid.ssid,
		       match_set[i].ssid.ssid_len);
		ssid_list[index_to_add].flag |= MATCH_SSID_FLAG;
		index_to_add++;
	}

	for (i = 0; i < index_to_add; i++) {
		ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
					  ssids[i].ssid_len ?
					  SPECIFIC_SSID_FLAG : ANY_SSID_FLAG,
					  ssids[i].ssid_len,
					  ssids[i].ssid);
					  ssid_list[i].flag,
					  ssid_list[i].ssid.ssid_len,
					  ssid_list[i].ssid.ssid);

	}

	/* Make sure no old entries are left behind */
	for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) {
	for (i = index_to_add; i < MAX_PROBED_SSIDS; i++) {
		ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i,
					  DISABLE_SSID_FLAG, 0, NULL);
	}
@@ -934,7 +992,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
	}

	ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
				      request->n_ssids);
				      request->n_ssids, NULL, 0);
	if (ret < 0)
		return ret;

@@ -943,7 +1001,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
				       WMI_FRAME_PROBE_REQ,
				       request->ie, request->ie_len);
	if (ret) {
		ath6kl_err("failed to set Probe Request appie for scan");
		ath6kl_err("failed to set Probe Request appie for scan\n");
		return ret;
	}

@@ -1512,6 +1570,9 @@ static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
		}
	}

	/* need to clean up enhanced bmiss detection fw state */
	ath6kl_cfg80211_sta_bmiss_enhance(vif, false);

set_iface_type:
	switch (type) {
	case NL80211_IFTYPE_STATION:
@@ -2074,7 +2135,9 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)
	if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST))
		return -EINVAL;

	if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) {
	if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags) &&
	    test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
		     ar->fw_capabilities)) {
		ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
						vif->fw_vif_idx, false);
		if (ret)
@@ -2209,7 +2272,9 @@ static int ath6kl_wow_resume(struct ath6kl *ar)

	ar->state = ATH6KL_STATE_ON;

	if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) {
	if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags) &&
	    test_bit(ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,
		     ar->fw_capabilities)) {
		ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi,
					vif->fw_vif_idx, true);
		if (ret)
@@ -2475,7 +2540,7 @@ void ath6kl_check_wow_status(struct ath6kl *ar)
static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,
			    bool ht_enable)
{
	struct ath6kl_htcap *htcap = &vif->htcap;
	struct ath6kl_htcap *htcap = &vif->htcap[band];

	if (htcap->ht_enable == ht_enable)
		return 0;
@@ -2585,6 +2650,30 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif,
	return 0;
}

void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable)
{
	int err;

	if (WARN_ON(!test_bit(WMI_READY, &vif->ar->flag)))
		return;

	if (vif->nw_type != INFRA_NETWORK)
		return;

	if (!test_bit(ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,
		      vif->ar->fw_capabilities))
		return;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s fw bmiss enhance\n",
		   enable ? "enable" : "disable");

	err = ath6kl_wmi_sta_bmiss_enhance_cmd(vif->ar->wmi,
					       vif->fw_vif_idx, enable);
	if (err)
		ath6kl_err("failed to %s enhanced bmiss detection: %d\n",
			   enable ? "enable" : "disable", err);
}

static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
				u8 *rsn_capab)
{
@@ -2665,9 +2754,15 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,

	/* TODO:
	 * info->interval
	 * info->dtim_period
	 */

	ret = ath6kl_wmi_ap_set_dtim_cmd(ar->wmi, vif->fw_vif_idx,
					 info->dtim_period);

	/* ignore error, just print a warning and continue normally */
	if (ret)
		ath6kl_warn("Failed to set dtim_period in beacon: %d\n", ret);

	if (info->beacon.head == NULL)
		return -EINVAL;
	mgmt = (struct ieee80211_mgmt *) info->beacon.head;
@@ -3131,9 +3226,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
	ath6kl_cfg80211_scan_complete_event(vif, true);

	ret = ath6kl_set_probed_ssids(ar, vif, request->ssids,
				      request->n_ssids);
				      request->n_ssids,
				      request->match_sets,
				      request->n_match_sets);
	if (ret < 0)
		return ret;

	if (!request->n_match_sets) {
		ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
					       ALL_BSS_FILTER, 0);
		if (ret < 0)
			return ret;
	} else {
		 ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx,
						MATCHED_SSID_FILTER, 0);
		if (ret < 0)
			return ret;
	}

	/* fw uses seconds, also make sure that it's >0 */
	interval = max_t(u16, 1, request->interval / 1000);
@@ -3156,7 +3265,7 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,
				       WMI_FRAME_PROBE_REQ,
				       request->ie, request->ie_len);
	if (ret) {
		ath6kl_warn("Failed to set probe request IE for scheduled scan: %d",
		ath6kl_warn("Failed to set probe request IE for scheduled scan: %d\n",
			    ret);
		return ret;
	}
@@ -3188,6 +3297,18 @@ static int ath6kl_cfg80211_sscan_stop(struct wiphy *wiphy,
	return 0;
}

static int ath6kl_cfg80211_set_bitrate(struct wiphy *wiphy,
				       struct net_device *dev,
				       const u8 *addr,
				       const struct cfg80211_bitrate_mask *mask)
{
	struct ath6kl *ar = ath6kl_priv(dev);
	struct ath6kl_vif *vif = netdev_priv(dev);

	return ath6kl_wmi_set_bitrate_mask(ar->wmi, vif->fw_vif_idx,
					   mask);
}

static const struct ieee80211_txrx_stypes
ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = {
	[NL80211_IFTYPE_STATION] = {
@@ -3253,6 +3374,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = {
	.mgmt_frame_register = ath6kl_mgmt_frame_register,
	.sched_scan_start = ath6kl_cfg80211_sscan_start,
	.sched_scan_stop = ath6kl_cfg80211_sscan_stop,
	.set_bitrate_mask = ath6kl_cfg80211_set_bitrate,
};

void ath6kl_cfg80211_stop(struct ath6kl_vif *vif)
@@ -3380,7 +3502,8 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
	vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL;
	vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME;
	vif->bg_scan_period = 0;
	vif->htcap.ht_enable = true;
	vif->htcap[IEEE80211_BAND_2GHZ].ht_enable = true;
	vif->htcap[IEEE80211_BAND_5GHZ].ht_enable = true;

	memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
	if (fw_vif_idx != 0)
@@ -3440,7 +3563,13 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
	}

	/* max num of ssids that can be probed during scanning */
	wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
	wiphy->max_scan_ssids = MAX_PROBED_SSIDS;

	/* max num of ssids that can be matched after scan */
	if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,
		     ar->fw_capabilities))
		wiphy->max_match_sets = MAX_PROBED_SSIDS;

	wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */
	switch (ar->hw.cap) {
	case WMI_11AN_CAP:
@@ -3477,6 +3606,17 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
		ath6kl_band_5ghz.ht_cap.cap = 0;
		ath6kl_band_5ghz.ht_cap.ht_supported = false;
	}

	if (ar->hw.flags & ATH6KL_HW_FLAG_64BIT_RATES) {
		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
	} else {
		ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
		ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
	}

	if (band_2gig)
		wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
	if (band_5gig)
@@ -3497,7 +3637,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
	wiphy->wowlan.pattern_min_len = 1;
	wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE;

	wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX;
	wiphy->max_sched_scan_ssids = MAX_PROBED_SSIDS;

	ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
			    WIPHY_FLAG_HAVE_AP_SME |
+2 −0
Original line number Diff line number Diff line
@@ -62,5 +62,7 @@ void ath6kl_cfg80211_cleanup(struct ath6kl *ar);

struct ath6kl *ath6kl_cfg80211_create(void);
void ath6kl_cfg80211_destroy(struct ath6kl *ar);
/* TODO: remove this once ath6kl_vif_cleanup() is moved to cfg80211.c */
void ath6kl_cfg80211_sta_bmiss_enhance(struct ath6kl_vif *vif, bool enable);

#endif /* ATH6KL_CFG80211_H */
+32 −6
Original line number Diff line number Diff line
@@ -100,6 +100,21 @@ enum ath6kl_fw_capability {
	/* Firmware has support to override rsn cap of rsn ie */
	ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,

	/*
	 * Multicast support in WOW and host awake mode.
	 * Allow all multicast in host awake mode.
	 * Apply multicast filter in WOW mode.
	 */
	ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER,

	/* Firmware supports enhanced bmiss detection */
	ATH6KL_FW_CAPABILITY_BMISS_ENHANCE,

	/*
	 * FW supports matching of ssid in schedule scan
	 */
	ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST,

	/* this needs to be last */
	ATH6KL_FW_CAPABILITY_MAX,
};
@@ -112,6 +127,10 @@ struct ath6kl_fw_ie {
	u8 data[0];
};

enum ath6kl_hw_flags {
	ATH6KL_HW_FLAG_64BIT_RATES	= BIT(0),
};

#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"

@@ -196,7 +215,7 @@ struct ath6kl_fw_ie {

#define AGGR_NUM_OF_FREE_NETBUFS    16

#define AGGR_RX_TIMEOUT     400	/* in ms */
#define AGGR_RX_TIMEOUT     100	/* in ms */

#define WMI_TIMEOUT (2 * HZ)

@@ -245,7 +264,6 @@ struct skb_hold_q {

struct rxtid {
	bool aggr;
	bool progress;
	bool timer_mon;
	u16 win_sz;
	u16 seq_next;
@@ -254,9 +272,15 @@ struct rxtid {
	struct sk_buff_head q;

	/*
	 * FIXME: No clue what this should protect. Apparently it should
	 * protect some of the fields above but they are also accessed
	 * without taking the lock.
	 * lock mainly protects seq_next and hold_q. Movement of seq_next
	 * needs to be protected between aggr_timeout() and
	 * aggr_process_recv_frm(). hold_q will be holding the pending
	 * reorder frames and it's access should also be protected.
	 * Some of the other fields like hold_q_sz, win_sz and aggr are
	 * initialized/reset when receiving addba/delba req, also while
	 * deleting aggr state all the pending buffers are flushed before
	 * resetting these fields, so there should not be any race in accessing
	 * these fields.
	 */
	spinlock_t lock;
};
@@ -541,7 +565,7 @@ struct ath6kl_vif {
	struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
	struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
	struct aggr_info *aggr_cntxt;
	struct ath6kl_htcap htcap;
	struct ath6kl_htcap htcap[IEEE80211_NUM_BANDS];

	struct timer_list disconnect_timer;
	struct timer_list sched_scan_timer;
@@ -684,6 +708,8 @@ struct ath6kl {
		u32 testscript_addr;
		enum wmi_phy_cap cap;

		u32 flags;

		struct ath6kl_hw_fw {
			const char *dir;
			const char *otp;
Loading