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

Commit 85a8eefd authored by John W. Linville's avatar John W. Linville
Browse files

Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx

parents bb8f2cb2 6b661895
Loading
Loading
Loading
Loading
+25 −18
Original line number Diff line number Diff line
@@ -661,12 +661,9 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)

	wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id);

	/*
	 * We currently do not support hidden SSID. The real SSID
	 * should be fetched from mac80211 first.
	 */
	if (wl->ssid_len == 0) {
		wl1271_warning("Hidden SSID currently not supported for AP");
	/* trying to use hidden SSID with an old hostapd version */
	if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) {
		wl1271_error("got a null SSID from beacon/bss");
		ret = -EINVAL;
		goto out;
	}
@@ -695,9 +692,18 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
	cmd->ap.dtim_interval = bss_conf->dtim_period;
	cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
	cmd->channel = wl->channel;
	cmd->ap.ssid_len = wl->ssid_len;

	if (!bss_conf->hidden_ssid) {
		/* take the SSID from the beacon for backward compatibility */
		cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
		cmd->ap.ssid_len = wl->ssid_len;
		memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
	} else {
		cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN;
		cmd->ap.ssid_len = bss_conf->ssid_len;
		memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len);
	}

	cmd->ap.local_rates = cpu_to_le32(0xffffffff);

	switch (wl->band) {
@@ -1106,6 +1112,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
{
	struct sk_buff *skb;
	int ret;
	u32 rate;

	skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
				     ie, ie_len);
@@ -1116,14 +1123,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,

	wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);

	rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
	if (band == IEEE80211_BAND_2GHZ)
		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
					      skb->data, skb->len, 0,
					      wl->conf.tx.basic_rate);
					      skb->data, skb->len, 0, rate);
	else
		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
					      skb->data, skb->len, 0,
					      wl->conf.tx.basic_rate_5);
					      skb->data, skb->len, 0, rate);

out:
	dev_kfree_skb(skb);
@@ -1134,6 +1140,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
					      struct sk_buff *skb)
{
	int ret;
	u32 rate;

	if (!skb)
		skb = ieee80211_ap_probereq_get(wl->hw, wl->vif);
@@ -1142,14 +1149,13 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,

	wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);

	rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]);
	if (wl->band == IEEE80211_BAND_2GHZ)
		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
					      skb->data, skb->len, 0,
					      wl->conf.tx.basic_rate);
					      skb->data, skb->len, 0, rate);
	else
		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
					      skb->data, skb->len, 0,
					      wl->conf.tx.basic_rate_5);
					      skb->data, skb->len, 0, rate);

	if (ret < 0)
		wl1271_error("Unable to set ap probe request template.");
@@ -1442,7 +1448,8 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
		sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;

	cmd->supported_rates =
		cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates));
		cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
							wl->band));

	wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
		     cmd->supported_rates, sta->uapsd_queues);
+2 −4
Original line number Diff line number Diff line
@@ -454,12 +454,10 @@ struct conf_rx_settings {
#define CONF_TX_AP_DEFAULT_MGMT_RATES  (CONF_HW_BIT_RATE_1MBPS | \
	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)

/*
 * Default rates for working as IBSS. use 11b rates
 */
/* default rates for working as IBSS (11b and OFDM) */
#define CONF_TX_IBSS_DEFAULT_RATES  (CONF_HW_BIT_RATE_1MBPS |       \
		CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
		CONF_HW_BIT_RATE_11MBPS);
		CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES);

struct conf_tx_rate_class {

+1 −1
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl)
	} else {
		int i;
		struct wl1271_link *lnk;
		for (i = WL1271_AP_STA_HLID_START; i < WL12XX_MAX_LINKS; i++) {
		for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) {
			lnk = &wl->links[i];
			if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
				continue;
+10 −7
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
{
	struct wl12xx_disconn_template *tmpl;
	int ret;
	u32 rate;

	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
	if (!tmpl) {
@@ -113,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
	tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					     IEEE80211_STYPE_DEAUTH);

	rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
				      tmpl, sizeof(*tmpl), 0,
				      wl1271_tx_min_rate_get(wl));
				      tmpl, sizeof(*tmpl), 0, rate);

out:
	kfree(tmpl);
@@ -126,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
{
	struct ieee80211_hdr_3addr *nullfunc;
	int ret;
	u32 rate;

	nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
	if (!nullfunc) {
@@ -142,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
	memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
	memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);

	rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
				      sizeof(*nullfunc), 0,
				      wl1271_tx_min_rate_get(wl));
				      sizeof(*nullfunc), 0, rate);

out:
	kfree(nullfunc);
@@ -155,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
{
	struct ieee80211_qos_hdr *qosnull;
	int ret;
	u32 rate;

	qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
	if (!qosnull) {
@@ -171,9 +174,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
	memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
	memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);

	rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
				      sizeof(*qosnull), 0,
				      wl1271_tx_min_rate_get(wl));
				      sizeof(*qosnull), 0, rate);

out:
	kfree(qosnull);
@@ -498,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
		return ret;

	/* use the min basic rate for AP broadcast/multicast */
	rc.enabled_rates = wl1271_tx_min_rate_get(wl);
	rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
	rc.short_retry_limit = 10;
	rc.long_retry_limit = 10;
	rc.aflags = 0;
+171 −30
Original line number Diff line number Diff line
@@ -2099,6 +2099,8 @@ deinit:
	wl->time_offset = 0;
	wl->session_counter = 0;
	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
	wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
	wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
	wl->vif = NULL;
	wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
	wl1271_free_ap_keys(wl);
@@ -2237,14 +2239,8 @@ out:

static void wl1271_set_band_rate(struct wl1271 *wl)
{
	if (wl->band == IEEE80211_BAND_2GHZ) {
		wl->basic_rate_set = wl->conf.tx.basic_rate;
		wl->rate_set = wl->conf.tx.basic_rate;
	} else {
		wl->basic_rate_set = wl->conf.tx.basic_rate_5;
		wl->rate_set = wl->conf.tx.basic_rate_5;
	}

	wl->basic_rate_set = wl->bitrate_masks[wl->band];
	wl->rate_set = wl->basic_rate_set;
}

static bool wl12xx_is_roc(struct wl1271 *wl)
@@ -2273,7 +2269,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
			if (ret < 0)
				goto out;
		}
		wl->rate_set = wl1271_tx_min_rate_get(wl);
		wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
		ret = wl1271_acx_sta_rate_policies(wl);
		if (ret < 0)
			goto out;
@@ -2355,6 +2351,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
	if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
	    ((wl->band != conf->channel->band) ||
	     (wl->channel != channel))) {
		/* send all pending packets */
		wl1271_tx_work_locked(wl);
		wl->band = conf->channel->band;
		wl->channel = channel;

@@ -2368,7 +2366,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
			if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
				wl1271_set_band_rate(wl);

			wl->basic_rate = wl1271_tx_min_rate_get(wl);
			wl->basic_rate =
				wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
			ret = wl1271_acx_sta_rate_policies(wl);
			if (ret < 0)
				wl1271_warning("rate policy for channel "
@@ -3069,6 +3068,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
	return 0;
}

static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset)
{
	int len;
	const u8 *next, *end = skb->data + skb->len;
	u8 *ie = (u8 *)cfg80211_find_ie(eid, skb->data + ieoffset,
					skb->len - ieoffset);
	if (!ie)
		return;
	len = ie[1] + 2;
	next = ie + len;
	memmove(ie, next, end - next);
	skb_trim(skb, skb->len - len);
}

static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
					    unsigned int oui, u8 oui_type,
					    int ieoffset)
{
	int len;
	const u8 *next, *end = skb->data + skb->len;
	u8 *ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
					       skb->data + ieoffset,
					       skb->len - ieoffset);
	if (!ie)
		return;
	len = ie[1] + 2;
	next = ie + len;
	memmove(ie, next, end - next);
	skb_trim(skb, skb->len - len);
}

static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
					 u8 *probe_rsp_data,
					 size_t probe_rsp_len,
					 u32 rates)
{
	struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
	u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE];
	int ssid_ie_offset, ie_offset, templ_len;
	const u8 *ptr;

	/* no need to change probe response if the SSID is set correctly */
	if (wl->ssid_len > 0)
		return wl1271_cmd_template_set(wl,
					       CMD_TEMPL_AP_PROBE_RESPONSE,
					       probe_rsp_data,
					       probe_rsp_len, 0,
					       rates);

	if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) {
		wl1271_error("probe_rsp template too big");
		return -EINVAL;
	}

	/* start searching from IE offset */
	ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);

	ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset,
			       probe_rsp_len - ie_offset);
	if (!ptr) {
		wl1271_error("No SSID in beacon!");
		return -EINVAL;
	}

	ssid_ie_offset = ptr - probe_rsp_data;
	ptr += (ptr[1] + 2);

	memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset);

	/* insert SSID from bss_conf */
	probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID;
	probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len;
	memcpy(probe_rsp_templ + ssid_ie_offset + 2,
	       bss_conf->ssid, bss_conf->ssid_len);
	templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len;

	memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len,
	       ptr, probe_rsp_len - (ptr - probe_rsp_data));
	templ_len += probe_rsp_len - (ptr - probe_rsp_data);

	return wl1271_cmd_template_set(wl,
				       CMD_TEMPL_AP_PROBE_RESPONSE,
				       probe_rsp_templ,
				       templ_len, 0,
				       rates);
}

static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
				       struct ieee80211_bss_conf *bss_conf,
				       u32 changed)
@@ -3125,6 +3211,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,

	if ((changed & BSS_CHANGED_BEACON)) {
		struct ieee80211_hdr *hdr;
		u32 min_rate;
		int ieoffset = offsetof(struct ieee80211_mgmt,
					u.beacon.variable);
		struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
@@ -3140,28 +3227,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
			dev_kfree_skb(beacon);
			goto out;
		}
		min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
		tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
				  CMD_TEMPL_BEACON;
		ret = wl1271_cmd_template_set(wl, tmpl_id,
					      beacon->data,
					      beacon->len, 0,
					      wl1271_tx_min_rate_get(wl));
					      min_rate);
		if (ret < 0) {
			dev_kfree_skb(beacon);
			goto out;
		}

		/* remove TIM ie from probe response */
		wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);

		/*
		 * remove p2p ie from probe response.
		 * the fw reponds to probe requests that don't include
		 * the p2p ie. probe requests with p2p ie will be passed,
		 * and will be responded by the supplicant (the spec
		 * forbids including the p2p ie when responding to probe
		 * requests that didn't include it).
		 */
		wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA,
					WLAN_OUI_TYPE_WFA_P2P, ieoffset);

		hdr = (struct ieee80211_hdr *) beacon->data;
		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						 IEEE80211_STYPE_PROBE_RESP);

		tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
				  CMD_TEMPL_PROBE_RESPONSE;
		if (is_ap)
			ret = wl1271_ap_set_probe_resp_tmpl(wl,
						beacon->data,
						beacon->len,
						min_rate);
		else
			ret = wl1271_cmd_template_set(wl,
					      tmpl_id,
						CMD_TEMPL_PROBE_RESPONSE,
						beacon->data,
						beacon->len, 0,
					      wl1271_tx_min_rate_get(wl));
						min_rate);
		dev_kfree_skb(beacon);
		if (ret < 0)
			goto out;
@@ -3182,8 +3287,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
	if ((changed & BSS_CHANGED_BASIC_RATES)) {
		u32 rates = bss_conf->basic_rates;

		wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
		wl->basic_rate = wl1271_tx_min_rate_get(wl);
		wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates,
								 wl->band);
		wl->basic_rate = wl1271_tx_min_rate_get(wl,
							wl->basic_rate_set);

		ret = wl1271_init_ap_rates(wl);
		if (ret < 0) {
@@ -3365,12 +3472,15 @@ sta_not_found:
			 * to use with control frames.
			 */
			rates = bss_conf->basic_rates;
			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
									 rates);
			wl->basic_rate = wl1271_tx_min_rate_get(wl);
			wl->basic_rate_set =
				wl1271_tx_enabled_rates_get(wl, rates,
							    wl->band);
			wl->basic_rate =
				wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
			if (sta_rate_set)
				wl->rate_set = wl1271_tx_enabled_rates_get(wl,
								sta_rate_set);
								sta_rate_set,
								wl->band);
			ret = wl1271_acx_sta_rate_policies(wl);
			if (ret < 0)
				goto out;
@@ -3417,7 +3527,8 @@ sta_not_found:

			/* revert back to minimum rates for the current band */
			wl1271_set_band_rate(wl);
			wl->basic_rate = wl1271_tx_min_rate_get(wl);
			wl->basic_rate =
				wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
			ret = wl1271_acx_sta_rate_policies(wl);
			if (ret < 0)
				goto out;
@@ -3468,11 +3579,13 @@ sta_not_found:

		if (bss_conf->ibss_joined) {
			u32 rates = bss_conf->basic_rates;
			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
									 rates);
			wl->basic_rate = wl1271_tx_min_rate_get(wl);
			wl->basic_rate_set =
				wl1271_tx_enabled_rates_get(wl, rates,
							    wl->band);
			wl->basic_rate =
				wl1271_tx_min_rate_get(wl, wl->basic_rate_set);

			/* by default, use 11b rates */
			/* by default, use 11b + OFDM rates */
			wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
			ret = wl1271_acx_sta_rate_policies(wl);
			if (ret < 0)
@@ -3992,6 +4105,29 @@ out:
	return ret;
}

static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
				   struct ieee80211_vif *vif,
				   const struct cfg80211_bitrate_mask *mask)
{
	struct wl1271 *wl = hw->priv;
	int i;

	wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x",
		mask->control[NL80211_BAND_2GHZ].legacy,
		mask->control[NL80211_BAND_5GHZ].legacy);

	mutex_lock(&wl->mutex);

	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
		wl->bitrate_masks[i] =
			wl1271_tx_enabled_rates_get(wl,
						    mask->control[i].legacy,
						    i);
	mutex_unlock(&wl->mutex);

	return 0;
}

static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
	struct wl1271 *wl = hw->priv;
@@ -4267,6 +4403,7 @@ static const struct ieee80211_ops wl1271_ops = {
	.sta_remove = wl1271_op_sta_remove,
	.ampdu_action = wl1271_op_ampdu_action,
	.tx_frames_pending = wl1271_tx_frames_pending,
	.set_bitrate_mask = wl12xx_set_bitrate_mask,
	CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};

@@ -4585,6 +4722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
	int i, j, ret;
	unsigned int order;

	BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS);

	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
	if (!hw) {
		wl1271_error("could not alloc ieee80211_hw");
@@ -4687,6 +4826,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)

	/* Apply default driver configuration. */
	wl1271_conf_init(wl);
	wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
	wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;

	order = get_order(WL1271_AGGR_BUFFER_SIZE);
	wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
Loading