diff options
Diffstat (limited to 'drivers/net/wireless/ti/wlcore/cmd.c')
| -rw-r--r-- | drivers/net/wireless/ti/wlcore/cmd.c | 92 | 
1 files changed, 56 insertions, 36 deletions
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index c9e060795d1..40dc30f4faa 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -60,7 +60,8 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf,  	u16 status;  	u16 poll_count = 0; -	if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING))) +	if (unlikely(wl->state == WLCORE_STATE_RESTARTING && +		     id != CMD_STOP_FWLOGGER))  		return -EIO;  	cmd = buf; @@ -311,8 +312,8 @@ static int wlcore_get_new_session_id(struct wl1271 *wl, u8 hlid)  int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)  {  	unsigned long flags; -	u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); -	if (link >= WL12XX_MAX_LINKS) +	u8 link = find_first_zero_bit(wl->links_map, wl->num_links); +	if (link >= wl->num_links)  		return -EBUSY;  	wl->session_ids[link] = wlcore_get_new_session_id(wl, link); @@ -323,9 +324,14 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)  	__set_bit(link, wlvif->links_map);  	spin_unlock_irqrestore(&wl->wl_lock, flags); -	/* take the last "freed packets" value from the current FW status */ -	wl->links[link].prev_freed_pkts = -			wl->fw_status_2->counters.tx_lnk_free_pkts[link]; +	/* +	 * take the last "freed packets" value from the current FW status. +	 * on recovery, we might not have fw_status yet, and +	 * tx_lnk_free_pkts will be NULL. check for it. +	 */ +	if (wl->fw_status->counters.tx_lnk_free_pkts) +		wl->links[link].prev_freed_pkts = +			wl->fw_status->counters.tx_lnk_free_pkts[link];  	wl->links[link].wlvif = wlvif;  	/* @@ -845,7 +851,8 @@ EXPORT_SYMBOL_GPL(wl1271_cmd_test);   * @buf: buffer for the response, including all headers, must work with dma   * @len: length of buf   */ -int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) +int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, +			   size_t cmd_len, size_t res_len)  {  	struct acx_header *acx = buf;  	int ret; @@ -854,10 +861,10 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)  	acx->id = cpu_to_le16(id); -	/* payload length, does not include any headers */ -	acx->len = cpu_to_le16(len - sizeof(*acx)); +	/* response payload length, does not include any headers */ +	acx->len = cpu_to_le16(res_len - sizeof(*acx)); -	ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len); +	ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, cmd_len, res_len);  	if (ret < 0)  		wl1271_error("INTERROGATE command failed"); @@ -1126,6 +1133,8 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,  	u16 template_id_2_4 = wl->scan_templ_id_2_4;  	u16 template_id_5 = wl->scan_templ_id_5; +	wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); +  	skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,  				     ie_len);  	if (!skb) { @@ -1135,8 +1144,6 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,  	if (ie_len)  		memcpy(skb_put(skb, ie_len), ie, ie_len); -	wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); -  	if (sched_scan &&  	    (wl->quirks & WLCORE_QUIRK_DUAL_PROBE_TMPL)) {  		template_id_2_4 = wl->sched_scan_templ_id_2_4; @@ -1172,7 +1179,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,  	if (!skb)  		goto out; -	wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); +	wl1271_debug(DEBUG_SCAN, "set ap probe request template");  	rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]);  	if (wlvif->band == IEEE80211_BAND_2GHZ) @@ -1525,6 +1532,7 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,  	cmd->sp_len = sta->max_sp;  	cmd->wmm = sta->wme ? 1 : 0;  	cmd->session_id = wl->session_ids[hlid]; +	cmd->role_id = wlvif->role_id;  	for (i = 0; i < NUM_ACCESS_CATEGORIES_COPY; i++)  		if (sta->wme && (sta->uapsd_queues & BIT(i))) @@ -1561,7 +1569,8 @@ out:  	return ret;  } -int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) +int wl12xx_cmd_remove_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif, +			   u8 hlid)  {  	struct wl12xx_cmd_remove_peer *cmd;  	int ret; @@ -1579,6 +1588,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)  	/* We never send a deauth, mac80211 is in charge of this */  	cmd->reason_opcode = 0;  	cmd->send_deauth_flag = 0; +	cmd->role_id = wlvif->role_id;  	ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0);  	if (ret < 0) { @@ -1607,33 +1617,43 @@ out:  static int wlcore_get_reg_conf_ch_idx(enum ieee80211_band band, u16 ch)  { -	int idx = -1; - +	/* +	 * map the given band/channel to the respective predefined +	 * bit expected by the fw +	 */  	switch (band) { -	case IEEE80211_BAND_5GHZ: -		if (ch >= 8 && ch <= 16) -			idx = ((ch-8)/4 + 18); -		else if (ch >= 34 && ch <= 64) -			idx = ((ch-34)/2 + 3 + 18); -		else if (ch >= 100 && ch <= 140) -			idx = ((ch-100)/4 + 15 + 18); -		else if (ch >= 149 && ch <= 165) -			idx = ((ch-149)/4 + 26 + 18); -		else -			idx = -1; -		break;  	case IEEE80211_BAND_2GHZ: +		/* channels 1..14 are mapped to 0..13 */  		if (ch >= 1 && ch <= 14) -			idx = ch - 1; -		else -			idx = -1; +			return ch - 1; +		break; +	case IEEE80211_BAND_5GHZ: +		switch (ch) { +		case 8 ... 16: +			/* channels 8,12,16 are mapped to 18,19,20 */ +			return 18 + (ch-8)/4; +		case 34 ... 48: +			/* channels 34,36..48 are mapped to 21..28 */ +			return 21 + (ch-34)/2; +		case 52 ... 64: +			/* channels 52,56..64 are mapped to 29..32 */ +			return 29 + (ch-52)/4; +		case 100 ... 140: +			/* channels 100,104..140 are mapped to 33..43 */ +			return 33 + (ch-100)/4; +		case 149 ... 165: +			/* channels 149,153..165 are mapped to 44..48 */ +			return 44 + (ch-149)/4; +		default: +			break; +		}  		break;  	default: -		wl1271_error("get reg conf ch idx - unknown band: %d", -			     (int)band); +		break;  	} -	return idx; +	wl1271_error("%s: unknown band/channel: %d/%d", __func__, band, ch); +	return -1;  }  void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel, @@ -1646,7 +1666,7 @@ void wlcore_set_pending_regdomain_ch(struct wl1271 *wl, u16 channel,  	ch_bit_idx = wlcore_get_reg_conf_ch_idx(band, channel); -	if (ch_bit_idx > 0 && ch_bit_idx <= WL1271_MAX_CHANNELS) +	if (ch_bit_idx >= 0 && ch_bit_idx <= WL1271_MAX_CHANNELS)  		set_bit(ch_bit_idx, (long *)wl->reg_ch_conf_pending);  } @@ -1676,7 +1696,7 @@ int wlcore_cmd_regdomain_config_locked(struct wl1271 *wl)  			if (channel->flags & (IEEE80211_CHAN_DISABLED |  					      IEEE80211_CHAN_RADAR | -					      IEEE80211_CHAN_PASSIVE_SCAN)) +					      IEEE80211_CHAN_NO_IR))  				continue;  			ch_bit_idx = wlcore_get_reg_conf_ch_idx(b, ch);  | 
