diff options
| author | John W. Linville <linville@tuxdriver.com> | 2012-05-16 10:57:32 -0400 | 
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2012-05-16 10:57:32 -0400 | 
| commit | 12d9568333de3bfc50ff8d3312c097ba7ea7fe3c (patch) | |
| tree | c92a8f034bfc37bc129a26834ef78543d06c8b9d | |
| parent | 5f561f686b90f51d97a1a6985175860200e55a2d (diff) | |
| parent | f3740572512075839e1a7ebde970081106fed3f0 (diff) | |
| download | olio-linux-3.10-12d9568333de3bfc50ff8d3312c097ba7ea7fe3c.tar.xz olio-linux-3.10-12d9568333de3bfc50ff8d3312c097ba7ea7fe3c.zip  | |
Merge branch 'for-linville' of git://github.com/kvalo/ath6kl
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 238 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/core.h | 33 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/debug.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc_mbox.c | 45 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/htc_pipe.c | 11 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/init.c | 29 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/main.c | 104 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/sdio.c | 17 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/txrx.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/usb.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.c | 94 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/wmi.h | 24 | 
13 files changed, 455 insertions, 178 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 28a65d3a03d..b869a358ce4 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -693,8 +693,8 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif,  					  ie, 2 + vif->ssid_len + beacon_ie_len,  					  0, GFP_KERNEL);  		if (bss) -			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to " -				   "cfg80211\n", bssid); +			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +				   "added bss %pM to cfg80211\n", bssid);  		kfree(ie);  	} else  		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); @@ -882,6 +882,32 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,  	vif->sme_state = SME_DISCONNECTED;  } +static int ath6kl_set_probed_ssids(struct ath6kl *ar, +				   struct ath6kl_vif *vif, +				   struct cfg80211_ssid *ssids, int n_ssids) +{ +	u8 i; + +	if (n_ssids > MAX_PROBED_SSID_INDEX) +		return -EINVAL; + +	for (i = 0; i < n_ssids; 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); +	} + +	/* Make sure no old entries are left behind */ +	for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { +		ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, +					  DISABLE_SSID_FLAG, 0, NULL); +	} + +	return 0; +} +  static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,  				struct cfg80211_scan_request *request)  { @@ -899,36 +925,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,  	if (!ar->usr_bss_filter) {  		clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); -		ret = ath6kl_wmi_bssfilter_cmd( -			ar->wmi, vif->fw_vif_idx, -			(test_bit(CONNECTED, &vif->flags) ? -			 ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0); +		ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, +					       ALL_BSS_FILTER, 0);  		if (ret) {  			ath6kl_err("couldn't set bss filtering\n");  			return ret;  		}  	} -	if (request->n_ssids && request->ssids[0].ssid_len) { -		u8 i; - -		if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) -			request->n_ssids = MAX_PROBED_SSID_INDEX - 1; - -		for (i = 0; i < request->n_ssids; i++) -			ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, -						  i + 1, SPECIFIC_SSID_FLAG, -						  request->ssids[i].ssid_len, -						  request->ssids[i].ssid); -	} +	ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, +				      request->n_ssids); +	if (ret < 0) +		return ret;  	/* this also clears IE in fw if it's not set */  	ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx,  				       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");  		return ret;  	} @@ -945,8 +960,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,  		channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);  		if (channels == NULL) { -			ath6kl_warn("failed to set scan channels, " -				    "scan all channels"); +			ath6kl_warn("failed to set scan channels, scan all channels");  			n_channels = 0;  		} @@ -1018,6 +1032,20 @@ out:  	vif->scan_req = NULL;  } +void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, +				      enum wmi_phy_mode mode) +{ +	enum nl80211_channel_type type; + +	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +		   "channel switch notify nw_type %d freq %d mode %d\n", +		   vif->nw_type, freq, mode); + +	type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT; + +	cfg80211_ch_switch_notify(vif->ndev, freq, type); +} +  static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,  				   u8 key_index, bool pairwise,  				   const u8 *mac_addr, @@ -1111,9 +1139,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,  		ar->ap_mode_bkey.key_len = key->key_len;  		memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);  		if (!test_bit(CONNECTED, &vif->flags)) { -			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " -				   "key configuration until AP mode has been " -				   "started\n"); +			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +				   "Delay initial group key configuration until AP mode has been started\n");  			/*  			 * The key will be set in ath6kl_connect_ap_mode() once  			 * the connected event is received from the target. @@ -1129,8 +1156,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,  		 * the AP mode has properly started  		 * (ath6kl_install_statioc_wep_keys).  		 */ -		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration " -			   "until AP mode has been started\n"); +		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +			   "Delay WEP key configuration until AP mode has been started\n");  		vif->wep_key_list[key_index].key_len = key->key_len;  		memcpy(vif->wep_key_list[key_index].key, key->key,  		       key->key_len); @@ -1962,8 +1989,7 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif)  				sizeof(discvr_pattern), discvr_offset,  				discvr_pattern, discvr_mask);  		if (ret) { -			ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR " -				   "pattern\n"); +			ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n");  			return ret;  		}  	} @@ -2031,6 +2057,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)  	u8 index = 0;  	__be32 ips[MAX_IP_ADDRS]; +	/* The FW currently can't support multi-vif WoW properly. */ +	if (ar->num_vif > 1) +		return -EIO; +  	vif = ath6kl_vif_first(ar);  	if (!vif)  		return -EIO; @@ -2044,6 +2074,13 @@ 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)) { +		ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, +						vif->fw_vif_idx, false); +		if (ret) +			return ret; +	} +  	/* Clear existing WOW patterns */  	for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++)  		ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, @@ -2147,8 +2184,8 @@ static int ath6kl_wow_resume(struct ath6kl *ar)  	ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx,  						 ATH6KL_HOST_MODE_AWAKE);  	if (ret) { -		ath6kl_warn("Failed to configure host sleep mode for " -			    "wow resume: %d\n", ret); +		ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n", +			    ret);  		ar->state = ATH6KL_STATE_WOW;  		return ret;  	} @@ -2172,6 +2209,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar)  	ar->state = ATH6KL_STATE_ON; +	if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { +		ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, +					vif->fw_vif_idx, true); +		if (ret) +			return ret; +	} +  	netif_wake_queue(vif->ndev);  	return 0; @@ -2186,8 +2230,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar)  	if (!vif)  		return -EIO; -	if (!ath6kl_cfg80211_ready(vif)) +	if (!test_bit(WMI_READY, &ar->flag)) { +		ath6kl_err("deepsleep failed as wmi is not ready\n");  		return -EIO; +	}  	ath6kl_cfg80211_stop_all(ar); @@ -2447,6 +2493,24 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band,  					band, htcap);  } +static int ath6kl_restore_htcap(struct ath6kl_vif *vif) +{ +	struct wiphy *wiphy = vif->ar->wiphy; +	int band, ret = 0; + +	for (band = 0; band < IEEE80211_NUM_BANDS; band++) { +		if (!wiphy->bands[band]) +			continue; + +		ret = ath6kl_set_htcap(vif, band, +				wiphy->bands[band]->ht_cap.ht_supported); +		if (ret) +			return ret; +	} + +	return ret; +} +  static bool ath6kl_is_p2p_ie(const u8 *pos)  {  	return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && @@ -2568,28 +2632,34 @@ static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,  	/* skip element id and length */  	rsn_ie += 2; -	/* skip version, group cipher */ -	if (rsn_ie_len < 6) +	/* skip version */ +	if (rsn_ie_len < 2)  		return -EINVAL; -	rsn_ie +=  6; -	rsn_ie_len -= 6; +	rsn_ie +=  2; +	rsn_ie_len -= 2; + +	/* skip group cipher suite */ +	if (rsn_ie_len < 4) +		return 0; +	rsn_ie +=  4; +	rsn_ie_len -= 4;  	/* skip pairwise cipher suite */  	if (rsn_ie_len < 2) -		return -EINVAL; -	cnt = *((u16 *) rsn_ie); +		return 0; +	cnt = get_unaligned_le16(rsn_ie);  	rsn_ie += (2 + cnt * 4);  	rsn_ie_len -= (2 + cnt * 4);  	/* skip akm suite */  	if (rsn_ie_len < 2) -		return -EINVAL; -	cnt = *((u16 *) rsn_ie); +		return 0; +	cnt = get_unaligned_le16(rsn_ie);  	rsn_ie += (2 + cnt * 4);  	rsn_ie_len -= (2 + cnt * 4);  	if (rsn_ie_len < 2) -		return -EINVAL; +		return 0;  	memcpy(rsn_capab, rsn_ie, 2); @@ -2766,6 +2836,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,  			return res;  	} +	memcpy(&vif->profile, &p, sizeof(p));  	res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);  	if (res < 0)  		return res; @@ -2801,13 +2872,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)  	clear_bit(CONNECTED, &vif->flags);  	/* Restore ht setting in firmware */ -	if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) -		return -EIO; - -	if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) -		return -EIO; - -	return 0; +	return ath6kl_restore_htcap(vif);  }  static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -3081,7 +3146,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,  	struct ath6kl_vif *vif = netdev_priv(dev);  	u16 interval;  	int ret; -	u8 i;  	if (ar->state != ATH6KL_STATE_ON)  		return -EIO; @@ -3089,29 +3153,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy,  	if (vif->sme_state != SME_DISCONNECTED)  		return -EBUSY; +	/* The FW currently can't support multi-vif WoW properly. */ +	if (ar->num_vif > 1) +		return -EIO; +  	ath6kl_cfg80211_scan_complete_event(vif, true); -	for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { -		ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, -					  i, DISABLE_SSID_FLAG, -					  0, NULL); -	} +	ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, +				      request->n_ssids); +	if (ret < 0) +		return ret;  	/* fw uses seconds, also make sure that it's >0 */  	interval = max_t(u16, 1, request->interval / 1000);  	ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx,  				  interval, interval, -				  10, 0, 0, 0, 3, 0, 0, 0); - -	if (request->n_ssids && request->ssids[0].ssid_len) { -		for (i = 0; i < request->n_ssids; i++) { -			ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, -						  i, SPECIFIC_SSID_FLAG, -						  request->ssids[i].ssid_len, -						  request->ssids[i].ssid); -		} -	} +				  vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0);  	ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx,  					  ATH6KL_WOW_MODE_ENABLE, @@ -3271,8 +3329,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)  		ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode;  		if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) -			ath6kl_warn("ath6kl_deep_sleep_enable: " -				    "wmi_powermode_cmd failed\n"); +			ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n");  		return;  	} @@ -3352,6 +3409,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,  	vif->next_mode = nw_type;  	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;  	memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); @@ -3393,6 +3451,7 @@ err:  int ath6kl_cfg80211_init(struct ath6kl *ar)  {  	struct wiphy *wiphy = ar->wiphy; +	bool band_2gig = false, band_5gig = false, ht = false;  	int ret;  	wiphy->mgmt_stypes = ath6kl_mgmt_stypes; @@ -3413,8 +3472,46 @@ 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_ie_len = 1000; /* FIX: what is correct limit? */ -	wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; -	wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; +	switch (ar->hw.cap) { +	case WMI_11AN_CAP: +		ht = true; +	case WMI_11A_CAP: +		band_5gig = true; +		break; +	case WMI_11GN_CAP: +		ht = true; +	case WMI_11G_CAP: +		band_2gig = true; +		break; +	case WMI_11AGN_CAP: +		ht = true; +	case WMI_11AG_CAP: +		band_2gig = true; +		band_5gig = true; +		break; +	default: +		ath6kl_err("invalid phy capability!\n"); +		return -EINVAL; +	} + +	/* +	 * Even if the fw has HT support, advertise HT cap only when +	 * the firmware has support to override RSN capability, otherwise +	 * 4-way handshake would fail. +	 */ +	if (!(ht && +	      test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, +		       ar->fw_capabilities))) { +		ath6kl_band_2ghz.ht_cap.cap = 0; +		ath6kl_band_2ghz.ht_cap.ht_supported = false; +		ath6kl_band_5ghz.ht_cap.cap = 0; +		ath6kl_band_5ghz.ht_cap.ht_supported = false; +	} +	if (band_2gig) +		wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; +	if (band_5gig) +		wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; +  	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;  	wiphy->cipher_suites = cipher_suites; @@ -3430,7 +3527,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 = 10; +	wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX;  	ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |  			    WIPHY_FLAG_HAVE_AP_SME | @@ -3447,8 +3544,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)  	ar->wiphy->probe_resp_offload =  		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |  		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | -		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | -		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; +		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;  	ret = wiphy_register(wiphy);  	if (ret < 0) { diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index c5def436417..5ea8cbb79f4 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -28,6 +28,8 @@ enum ath6kl_cfg_suspend_mode {  struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,  					enum nl80211_iftype type,  					u8 fw_vif_idx, u8 nw_type); +void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, +				      enum wmi_phy_mode mode);  void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);  void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 9d67964a51d..4d9c6f14269 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -126,9 +126,9 @@ struct ath6kl_fw_ie {  #define AR6003_HW_2_0_FIRMWARE_FILE		"athwlan.bin.z77"  #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE	"athtcmd_ram.bin"  #define AR6003_HW_2_0_PATCH_FILE		"data.patch.bin" -#define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" +#define AR6003_HW_2_0_BOARD_DATA_FILE AR6003_HW_2_0_FW_DIR "/bdata.bin"  #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ -			"ath6k/AR6003/hw2.0/bdata.SD31.bin" +			AR6003_HW_2_0_FW_DIR "/bdata.SD31.bin"  /* AR6003 3.0 definitions */  #define AR6003_HW_2_1_1_VERSION                 0x30000582 @@ -139,25 +139,33 @@ struct ath6kl_fw_ie {  #define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE	"utf.bin"  #define AR6003_HW_2_1_1_TESTSCRIPT_FILE	"nullTestFlow.bin"  #define AR6003_HW_2_1_1_PATCH_FILE		"data.patch.bin" -#define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" +#define AR6003_HW_2_1_1_BOARD_DATA_FILE AR6003_HW_2_1_1_FW_DIR "/bdata.bin"  #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE	\ -			"ath6k/AR6003/hw2.1.1/bdata.SD31.bin" +			AR6003_HW_2_1_1_FW_DIR "/bdata.SD31.bin"  /* AR6004 1.0 definitions */  #define AR6004_HW_1_0_VERSION                 0x30000623  #define AR6004_HW_1_0_FW_DIR			"ath6k/AR6004/hw1.0"  #define AR6004_HW_1_0_FIRMWARE_FILE		"fw.ram.bin" -#define AR6004_HW_1_0_BOARD_DATA_FILE         "ath6k/AR6004/hw1.0/bdata.bin" +#define AR6004_HW_1_0_BOARD_DATA_FILE         AR6004_HW_1_0_FW_DIR "/bdata.bin"  #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ -	"ath6k/AR6004/hw1.0/bdata.DB132.bin" +	AR6004_HW_1_0_FW_DIR "/bdata.DB132.bin"  /* AR6004 1.1 definitions */  #define AR6004_HW_1_1_VERSION                 0x30000001  #define AR6004_HW_1_1_FW_DIR			"ath6k/AR6004/hw1.1"  #define AR6004_HW_1_1_FIRMWARE_FILE		"fw.ram.bin" -#define AR6004_HW_1_1_BOARD_DATA_FILE         "ath6k/AR6004/hw1.1/bdata.bin" +#define AR6004_HW_1_1_BOARD_DATA_FILE         AR6004_HW_1_1_FW_DIR "/bdata.bin"  #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ -	"ath6k/AR6004/hw1.1/bdata.DB132.bin" +	AR6004_HW_1_1_FW_DIR "/bdata.DB132.bin" + +/* AR6004 1.2 definitions */ +#define AR6004_HW_1_2_VERSION                 0x300007e8 +#define AR6004_HW_1_2_FW_DIR			"ath6k/AR6004/hw1.2" +#define AR6004_HW_1_2_FIRMWARE_FILE           "fw.ram.bin" +#define AR6004_HW_1_2_BOARD_DATA_FILE         AR6004_HW_1_2_FW_DIR "/bdata.bin" +#define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \ +	AR6004_HW_1_2_FW_DIR "/bdata.bin"  /* Per STA data, used in AP mode */  #define STA_PS_AWAKE		BIT(0) @@ -502,6 +510,8 @@ enum ath6kl_vif_state {  	WLAN_ENABLED,  	STATS_UPDATE_PEND,  	HOST_SLEEP_MODE_CMD_PROCESSED, +	NETDEV_MCAST_ALL_ON, +	NETDEV_MCAST_ALL_OFF,  };  struct ath6kl_vif { @@ -549,9 +559,11 @@ struct ath6kl_vif {  	u16 assoc_bss_beacon_int;  	u16 listen_intvl_t;  	u16 bmiss_time_t; +	u16 bg_scan_period;  	u8 assoc_bss_dtim_period;  	struct net_device_stats net_stats;  	struct target_stats target_stats; +	struct wmi_connect_cmd profile;  	struct list_head mc_filter;  }; @@ -640,6 +652,7 @@ struct ath6kl {  	u8 sta_list_index;  	struct ath6kl_req_key ap_mode_bkey;  	struct sk_buff_head mcastpsq; +	u32 want_ch_switch;  	/*  	 * FIXME: protects access to mcastpsq but is actually useless as @@ -672,6 +685,7 @@ struct ath6kl {  		u32 refclk_hz;  		u32 uarttx_pin;  		u32 testscript_addr; +		enum wmi_phy_cap cap;  		struct ath6kl_hw_fw {  			const char *dir; @@ -805,7 +819,8 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn);  struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr);  struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); -void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver); +void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, +			enum wmi_phy_cap cap);  int ath6kl_control_tx(void *devt, struct sk_buff *skb,  		      enum htc_endpoint_id eid);  void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 1b76aff7850..15cfe30e54f 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -401,8 +401,10 @@ static ssize_t ath6kl_fwlog_block_read(struct file *file,  		ret = wait_for_completion_interruptible(  			&ar->debug.fwlog_completion); -		if (ret == -ERESTARTSYS) +		if (ret == -ERESTARTSYS) { +			vfree(buf);  			return ret; +		}  		spin_lock(&ar->debug.fwlog_queue.lock);  	} @@ -1570,10 +1572,15 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file,  				size_t count, loff_t *ppos)  {  	struct ath6kl *ar = file->private_data; +	struct ath6kl_vif *vif;  	u16 bgscan_int;  	char buf[32];  	ssize_t len; +	vif = ath6kl_vif_first(ar); +	if (!vif) +		return -EIO; +  	len = min(count, sizeof(buf) - 1);  	if (copy_from_user(buf, user_buf, len))  		return -EFAULT; @@ -1585,6 +1592,8 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file,  	if (bgscan_int == 0)  		bgscan_int = 0xffff; +	vif->bg_scan_period = bgscan_int; +  	ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3,  				  0, 0, 0); @@ -1809,6 +1818,7 @@ int ath6kl_debug_init_fs(struct ath6kl *ar)  void ath6kl_debug_cleanup(struct ath6kl *ar)  {  	skb_queue_purge(&ar->debug.fwlog_queue); +	complete(&ar->debug.fwlog_completion);  	kfree(ar->debug.roam_tbl);  } diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index 065e61516d7..2798624d3a9 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c @@ -83,10 +83,7 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info,  			 * never goes inactive EVER.  			 */  			cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; -		} else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC) -			/* this is the lowest priority data endpoint */ -			/* FIXME: this looks fishy, check */ -			cred_info->lowestpri_ep_dist = cur_ep_dist->list; +		}  		/*  		 * Streams have to be created (explicit | implicit) for all @@ -100,6 +97,13 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info,  		 */  	} +	/* +	 * For ath6kl_credit_seek function, +	 * it use list_for_each_entry_reverse to walk around the whole ep list. +	 * Therefore assign this lowestpri_ep_dist after walk around the ep_list +	 */ +	cred_info->lowestpri_ep_dist = cur_ep_dist->list; +  	WARN_ON(cred_info->cur_free_credits <= 0);  	list_for_each_entry(cur_ep_dist, ep_list, list) { @@ -758,7 +762,7 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,  	u32 txb_mask;  	u8 ac = WMM_NUM_AC; -	if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || +	if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) &&  	    (WMI_CONTROL_SVC != endpoint->svc_id))  		ac = target->dev->ar->ep2ac_map[endpoint->eid]; @@ -793,16 +797,17 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint,  				 * itself  				 */  				txb_mask = ((1 << ac) - 1); -		/* -		 * when the scatter request resources drop below a -		 * certain threshold, disable Tx bundling for all -		 * AC's with priority lower than the current requesting -		 * AC. Otherwise re-enable Tx bundling for them -		 */ -		if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) -			target->tx_bndl_mask &= ~txb_mask; -		else -			target->tx_bndl_mask |= txb_mask; + +			/* +			 * when the scatter request resources drop below a +			 * certain threshold, disable Tx bundling for all +			 * AC's with priority lower than the current requesting +			 * AC. Otherwise re-enable Tx bundling for them +			 */ +			if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) +				target->tx_bndl_mask &= ~txb_mask; +			else +				target->tx_bndl_mask |= txb_mask;  		}  		ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", @@ -849,6 +854,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,  	int bundle_sent;  	int n_pkts_bundle;  	u8 ac = WMM_NUM_AC; +	int status;  	spin_lock_bh(&target->tx_lock); @@ -866,7 +872,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,  	 */  	INIT_LIST_HEAD(&txq); -	if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || +	if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) &&  	    (WMI_CONTROL_SVC != endpoint->svc_id))  		ac = target->dev->ar->ep2ac_map[endpoint->eid]; @@ -910,7 +916,12 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target,  			ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags,  					       0, packet->info.tx.seqno); -			ath6kl_htc_tx_issue(target, packet); +			status = ath6kl_htc_tx_issue(target, packet); + +			if (status) { +				packet->status = status; +				packet->completion(packet->context, packet); +			}  		}  		spin_lock_bh(&target->tx_lock); diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index b277b344688..f9626c72369 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c @@ -108,8 +108,6 @@ static void get_htc_packet_credit_based(struct htc_target *target,  		/* get packet at head, but don't remove it */  		packet = list_first_entry(&ep->txq, struct htc_packet, list); -		if (packet == NULL) -			break;  		ath6kl_dbg(ATH6KL_DBG_HTC,  			   "%s: got head packet:0x%p , queue depth: %d\n", @@ -803,8 +801,6 @@ static int htc_send_packets_multiple(struct htc_target *target,  	/* get first packet to find out which ep the packets will go into */  	packet = list_first_entry(pkt_queue, struct htc_packet, list); -	if (packet == NULL) -		return -EINVAL;  	if (packet->endpoint >= ENDPOINT_MAX) {  		WARN_ON_ONCE(1); @@ -1382,6 +1378,9 @@ static int ath6kl_htc_pipe_conn_service(struct htc_target *target,  	/* copy all the callbacks */  	ep->ep_cb = conn_req->ep_cb; +	/* initialize tx_drop_packet_threshold */ +	ep->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM; +  	status = ath6kl_hif_pipe_map_service(ar, ep->svc_id,  					     &ep->pipe.pipeid_ul,  					     &ep->pipe.pipeid_dl); @@ -1636,10 +1635,6 @@ static int ath6kl_htc_pipe_add_rxbuf_multiple(struct htc_target *target,  		return -EINVAL;  	first = list_first_entry(pkt_queue, struct htc_packet, list); -	if (first == NULL) { -		WARN_ON_ONCE(1); -		return -EINVAL; -	}  	if (first->endpoint >= ENDPOINT_MAX) {  		WARN_ON_ONCE(1); diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 29ef50ea07d..7eb0515f458 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -119,6 +119,24 @@ static const struct ath6kl_hw hw_list[] = {  		.fw_board		= AR6004_HW_1_1_BOARD_DATA_FILE,  		.fw_default_board	= AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE,  	}, +	{ +		.id				= AR6004_HW_1_2_VERSION, +		.name				= "ar6004 hw 1.2", +		.dataset_patch_addr		= 0x436ecc, +		.app_load_addr			= 0x1234, +		.board_ext_data_addr		= 0x437000, +		.reserved_ram_size		= 9216, +		.board_addr			= 0x435c00, +		.refclk_hz			= 40000000, +		.uarttx_pin			= 11, + +		.fw = { +			.dir		= AR6004_HW_1_2_FW_DIR, +			.fw		= AR6004_HW_1_2_FIRMWARE_FILE, +		}, +		.fw_board		= AR6004_HW_1_2_BOARD_DATA_FILE, +		.fw_default_board	= AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE, +	},  };  /* @@ -445,9 +463,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)  					      P2P_FLAG_MACADDR_REQ |  					      P2P_FLAG_HMODEL_REQ);  		if (ret) { -			ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P " -				   "capabilities (%d) - assuming P2P not " -				   "supported\n", ret); +			ath6kl_dbg(ATH6KL_DBG_TRC, +				   "failed to request P2P capabilities (%d) - assuming P2P not supported\n", +				   ret);  			ar->p2p = false;  		}  	} @@ -456,8 +474,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)  		/* Enable Probe Request reporting for P2P */  		ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);  		if (ret) { -			ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe " -				   "Request reporting (%d)\n", ret); +			ath6kl_dbg(ATH6KL_DBG_TRC, +				   "failed to enable Probe Request reporting (%d)\n", +				   ret);  		}  	} diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 4d818f96c41..e5524470529 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -421,8 +421,8 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)  		if (!ik->valid)  			break; -		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " -			   "the initial group key for AP mode\n"); +		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +			   "Delayed addkey for the initial group key for AP mode\n");  		memset(key_rsc, 0, sizeof(key_rsc));  		res = ath6kl_wmi_addkey_cmd(  			ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type, @@ -430,12 +430,19 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)  			ik->key,  			KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);  		if (res) { -			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " -				   "addkey failed: %d\n", res); +			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, +				   "Delayed addkey failed: %d\n", res);  		}  		break;  	} +	if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) { +		ar->want_ch_switch &= ~(1 << vif->fw_vif_idx); +		/* we actually don't know the phymode, default to HT20 */ +		ath6kl_cfg80211_ch_switch_notify(vif, channel, +						 WMI_11G_HT20); +	} +  	ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);  	set_bit(CONNECTED, &vif->flags);  	netif_carrier_on(vif->ndev); @@ -541,7 +548,8 @@ void ath6kl_disconnect(struct ath6kl_vif *vif)  /* WMI Event handlers */ -void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) +void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, +			enum wmi_phy_cap cap)  {  	struct ath6kl *ar = devt; @@ -551,6 +559,7 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)  	ar->version.wlan_ver = sw_ver;  	ar->version.abi_ver = abi_ver; +	ar->hw.cap = cap;  	snprintf(ar->wiphy->fw_version,  		 sizeof(ar->wiphy->fw_version), @@ -584,6 +593,45 @@ void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)  	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status);  } +static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel) +{ + +	struct ath6kl *ar = vif->ar; + +	vif->next_chan = channel; +	vif->profile.ch = cpu_to_le16(channel); + +	switch (vif->nw_type) { +	case AP_NETWORK: +		return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, +						    &vif->profile); +	default: +		ath6kl_err("won't switch channels nw_type=%d\n", vif->nw_type); +		return -ENOTSUPP; +	} +} + +static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel) +{ + +	struct ath6kl_vif *vif; +	int res = 0; + +	if (!ar->want_ch_switch) +		return; + +	spin_lock_bh(&ar->list_lock); +	list_for_each_entry(vif, &ar->vif_list, list) { +		if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) +			res = ath6kl_commit_ch_switch(vif, channel); + +		if (res) +			ath6kl_err("channel switch failed nw_type %d res %d\n", +				   vif->nw_type, res); +	} +	spin_unlock_bh(&ar->list_lock); +} +  void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,  			  u16 listen_int, u16 beacon_int,  			  enum network_type net_type, u8 beacon_ie_len, @@ -601,9 +649,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid,  	memcpy(vif->bssid, bssid, sizeof(vif->bssid));  	vif->bss_ch = channel; -	if ((vif->nw_type == INFRA_NETWORK)) +	if ((vif->nw_type == INFRA_NETWORK)) {  		ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx,  					      vif->listen_intvl_t, 0); +		ath6kl_check_ch_switch(ar, channel); +	}  	netif_wake_queue(vif->ndev); @@ -926,6 +976,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid,  	struct ath6kl *ar = vif->ar;  	if (vif->nw_type == AP_NETWORK) { +		/* disconnect due to other STA vif switching channels */ +		if (reason == BSS_DISCONNECTED && +		    prot_reason_status == WMI_AP_REASON_STA_ROAM) +			ar->want_ch_switch |= 1 << vif->fw_vif_idx; +  		if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))  			return; @@ -1090,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev,  static void ath6kl_set_multicast_list(struct net_device *ndev)  {  	struct ath6kl_vif *vif = netdev_priv(ndev); -	bool mc_all_on = false, mc_all_off = false; +	bool mc_all_on = false;  	int mc_count = netdev_mc_count(ndev);  	struct netdev_hw_addr *ha;  	bool found; @@ -1102,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev)  	    !test_bit(WLAN_ENABLED, &vif->flags))  		return; +	/* Enable multicast-all filter. */  	mc_all_on = !!(ndev->flags & IFF_PROMISC) ||  		    !!(ndev->flags & IFF_ALLMULTI) ||  		    !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); -	mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; +	if (mc_all_on) +		set_bit(NETDEV_MCAST_ALL_ON, &vif->flags); +	else +		clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); + +	mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); -	if (mc_all_on || mc_all_off) { -		/* Enable/disable all multicast */ -		ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", -			   mc_all_on ? "enabling" : "disabling"); -		ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, +	if (!(ndev->flags & IFF_MULTICAST)) { +		mc_all_on = false; +		set_bit(NETDEV_MCAST_ALL_OFF, &vif->flags); +	} else { +		clear_bit(NETDEV_MCAST_ALL_OFF, &vif->flags); +	} + +	/* Enable/disable "multicast-all" filter*/ +	ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast-all filter\n", +		   mc_all_on ? "enabling" : "disabling"); + +	ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx,  						  mc_all_on); -		if (ret) -			ath6kl_warn("Failed to %s multicast receive\n", -				    mc_all_on ? "enable" : "disable"); +	if (ret) { +		ath6kl_warn("Failed to %s multicast-all receive\n", +			    mc_all_on ? "enable" : "disable");  		return;  	} +	if (test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) +		return; + +	/* Keep the driver and firmware mcast list in sync. */  	list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) {  		found = false;  		netdev_for_each_mc_addr(ha, ndev) { diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 44ea7a74210..05b95405f7b 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -552,7 +552,7 @@ static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer,  	bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); -	if (!bus_req) +	if (WARN_ON_ONCE(!bus_req))  		return -ENOMEM;  	bus_req->address = address; @@ -915,6 +915,9 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow)  	}  cut_pwr: +	if (func->card && func->card->host) +		func->card->host->pm_flags &= ~MMC_PM_KEEP_POWER; +  	return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL);  } @@ -985,9 +988,8 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)  	}  	if (status) { -		ath6kl_err("%s: failed to write initial bytes of 0x%x " -			   "to window reg: 0x%X\n", __func__, -			   addr, reg_addr); +		ath6kl_err("%s: failed to write initial bytes of 0x%x to window reg: 0x%X\n", +			   __func__, addr, reg_addr);  		return status;  	} @@ -1076,8 +1078,8 @@ static int ath6kl_sdio_bmi_credits(struct ath6kl *ar)  					 (u8 *)&ar->bmi.cmd_credits, 4,  					 HIF_RD_SYNC_BYTE_INC);  		if (ret) { -			ath6kl_err("Unable to decrement the command credit " -						"count register: %d\n", ret); +			ath6kl_err("Unable to decrement the command credit count register: %d\n", +				   ret);  			return ret;  		} @@ -1457,3 +1459,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);  MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE);  MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);  MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 82f2f5cb475..67206aedea6 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -362,15 +362,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)  		   skb, skb->data, skb->len);  	/* If target is not associated */ -	if (!test_bit(CONNECTED, &vif->flags)) { -		dev_kfree_skb(skb); -		return 0; -	} +	if (!test_bit(CONNECTED, &vif->flags)) +		goto fail_tx; -	if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) { -		dev_kfree_skb(skb); -		return 0; -	} +	if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) +		goto fail_tx;  	if (!test_bit(WMI_READY, &ar->flag))  		goto fail_tx; diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index ec7f1f5fd1c..dfbbe9e7ff7 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -1037,6 +1037,14 @@ static void ath6kl_usb_stop(struct ath6kl *ar)  	hif_stop(ar);  } +static void ath6kl_usb_cleanup_scatter(struct ath6kl *ar) +{ +	/* +	 * USB doesn't support it. Just return. +	 */ +	return; +} +  static const struct ath6kl_hif_ops ath6kl_usb_ops = {  	.diag_read32 = ath6kl_usb_diag_read32,  	.diag_write32 = ath6kl_usb_diag_write32, @@ -1049,6 +1057,7 @@ static const struct ath6kl_hif_ops ath6kl_usb_ops = {  	.pipe_get_default = ath6kl_usb_get_default_pipe,  	.pipe_map_service = ath6kl_usb_map_service_pipe,  	.pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, +	.cleanup_scatter = ath6kl_usb_cleanup_scatter,  };  /* ath6kl usb driver registered functions */ @@ -1207,3 +1216,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE);  MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE);  MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE);  MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 7c8a9977faf..ee8ec2394c2 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -16,6 +16,7 @@   */  #include <linux/ip.h> +#include <linux/in.h>  #include "core.h"  #include "debug.h"  #include "testmode.h" @@ -289,6 +290,13 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx,  					layer2_priority);  		} else  			usr_pri = layer2_priority & 0x7; + +		/* +		 * Queue the EAPOL frames in the same WMM_AC_VO queue +		 * as that of management frames. +		 */ +		if (skb->protocol == cpu_to_be16(ETH_P_PAE)) +			usr_pri = WMI_VOICE_USER_PRIORITY;  	}  	/* @@ -460,8 +468,9 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,  		   freq, dur);  	chan = ieee80211_get_channel(ar->wiphy, freq);  	if (!chan) { -		ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel " -			   "(freq=%u)\n", freq); +		ath6kl_dbg(ATH6KL_DBG_WMI, +			   "remain_on_chnl: Unknown channel (freq=%u)\n", +			   freq);  		return -EINVAL;  	}  	id = vif->last_roc_id; @@ -488,12 +497,14 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,  	ev = (struct wmi_cancel_remain_on_chnl_event *) datap;  	freq = le32_to_cpu(ev->freq);  	dur = le32_to_cpu(ev->duration); -	ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u " -		   "status=%u\n", freq, dur, ev->status); +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "cancel_remain_on_chnl: freq=%u dur=%u status=%u\n", +		   freq, dur, ev->status);  	chan = ieee80211_get_channel(ar->wiphy, freq);  	if (!chan) { -		ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown " -			   "channel (freq=%u)\n", freq); +		ath6kl_dbg(ATH6KL_DBG_WMI, +			   "cancel_remain_on_chnl: Unknown channel (freq=%u)\n", +			   freq);  		return -EINVAL;  	}  	if (vif->last_cancel_roc_id && @@ -548,12 +559,12 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,  	freq = le32_to_cpu(ev->freq);  	dlen = le16_to_cpu(ev->len);  	if (datap + len < ev->data + dlen) { -		ath6kl_err("invalid wmi_p2p_rx_probe_req_event: " -			   "len=%d dlen=%u\n", len, dlen); +		ath6kl_err("invalid wmi_p2p_rx_probe_req_event: len=%d dlen=%u\n", +			   len, dlen);  		return -EINVAL;  	} -	ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u " -		   "probe_req_report=%d\n", +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "rx_probe_req: len=%u freq=%u probe_req_report=%d\n",  		   dlen, freq, vif->probe_req_report);  	if (vif->probe_req_report || vif->nw_type == AP_NETWORK) @@ -592,8 +603,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,  	freq = le32_to_cpu(ev->freq);  	dlen = le16_to_cpu(ev->len);  	if (datap + len < ev->data + dlen) { -		ath6kl_err("invalid wmi_rx_action_event: " -			   "len=%d dlen=%u\n", len, dlen); +		ath6kl_err("invalid wmi_rx_action_event: len=%d dlen=%u\n", +			   len, dlen);  		return -EINVAL;  	}  	ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); @@ -687,7 +698,7 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)  	ath6kl_ready_event(wmi->parent_dev, ev->mac_addr,  			   le32_to_cpu(ev->sw_version), -			   le32_to_cpu(ev->abi_version)); +			   le32_to_cpu(ev->abi_version), ev->phy_cap);  	return 0;  } @@ -777,16 +788,15 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,  		/* AP mode start/STA connected event */  		struct net_device *dev = vif->ndev;  		if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { -			ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM " -				   "(AP started)\n", +			ath6kl_dbg(ATH6KL_DBG_WMI, +				   "%s: freq %d bssid %pM (AP started)\n",  				   __func__, le16_to_cpu(ev->u.ap_bss.ch),  				   ev->u.ap_bss.bssid);  			ath6kl_connect_ap_mode_bss(  				vif, le16_to_cpu(ev->u.ap_bss.ch));  		} else { -			ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM " -				   "auth=%u keymgmt=%u cipher=%u apsd_info=%u " -				   "(STA connected)\n", +			ath6kl_dbg(ATH6KL_DBG_WMI, +				   "%s: aid %u mac_addr %pM auth=%u keymgmt=%u cipher=%u apsd_info=%u (STA connected)\n",  				   __func__, ev->u.ap_sta.aid,  				   ev->u.ap_sta.mac_addr,  				   ev->u.ap_sta.auth, @@ -1229,8 +1239,9 @@ static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap,  	ev = (struct wmi_neighbor_report_event *) datap;  	if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info)  	    > len) { -		ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event " -			   "(num=%d len=%d)\n", ev->num_neighbors, len); +		ath6kl_dbg(ATH6KL_DBG_WMI, +			   "truncated neighbor event (num=%d len=%d)\n", +			   ev->num_neighbors, len);  		return -EINVAL;  	}  	for (i = 0; i < ev->num_neighbors; i++) { @@ -1814,12 +1825,14 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,  			     u32 home_dwell_time, u32 force_scan_interval,  			     s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates)  { +	struct ieee80211_supported_band *sband;  	struct sk_buff *skb;  	struct wmi_begin_scan_cmd *sc; -	s8 size; +	s8 size, *supp_rates;  	int i, band, ret;  	struct ath6kl *ar = wmi->parent_dev;  	int num_rates; +	u32 ratemask;  	size = sizeof(struct wmi_begin_scan_cmd); @@ -1846,10 +1859,13 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx,  	sc->num_ch = num_chan;  	for (band = 0; band < IEEE80211_NUM_BANDS; band++) { -		struct ieee80211_supported_band *sband = -		    ar->wiphy->bands[band]; -		u32 ratemask = rates[band]; -		u8 *supp_rates = sc->supp_rates[band].rates; +		sband = ar->wiphy->bands[band]; + +		if (!sband) +			continue; + +		ratemask = rates[band]; +		supp_rates = sc->supp_rates[band].rates;  		num_rates = 0;  		for (i = 0; i < sband->n_bitrates; i++) { @@ -2129,8 +2145,8 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,  	struct wmi_add_cipher_key_cmd *cmd;  	int ret; -	ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " -		   "key_usage=%d key_len=%d key_op_ctrl=%d\n", +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "addkey cmd: key_index=%u key_type=%d key_usage=%d key_len=%d key_op_ctrl=%d\n",  		   key_index, key_type, key_usage, key_len, key_op_ctrl);  	if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || @@ -3047,8 +3063,8 @@ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx,  	res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID,  				  NO_SYNC_WMIFLAG); -	ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u " -		   "ctrl_flags=0x%x-> res=%d\n", +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "%s: nw_type=%u auth_mode=%u ch=%u ctrl_flags=0x%x-> res=%d\n",  		   __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch),  		   le32_to_cpu(p->ctrl_flags), res);  	return res; @@ -3208,8 +3224,9 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,  	if (!skb)  		return -ENOMEM; -	ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u " -		   "ie_len=%u\n", mgmt_frm_type, ie_len); +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "set_appie_cmd: mgmt_frm_type=%u ie_len=%u\n", +		   mgmt_frm_type, ie_len);  	p = (struct wmi_set_appie_cmd *) skb->data;  	p->mgmt_frm_type = mgmt_frm_type;  	p->ie_len = ie_len; @@ -3310,8 +3327,9 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id,  	wmi->last_mgmt_tx_frame = buf;  	wmi->last_mgmt_tx_frame_len = data_len; -	ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " -		   "len=%u\n", id, freq, wait, data_len); +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "send_action_cmd: id=%u freq=%u wait=%u len=%u\n", +		   id, freq, wait, data_len);  	p = (struct wmi_send_action_cmd *) skb->data;  	p->id = cpu_to_le32(id);  	p->freq = cpu_to_le32(freq); @@ -3348,8 +3366,9 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id,  	wmi->last_mgmt_tx_frame = buf;  	wmi->last_mgmt_tx_frame_len = data_len; -	ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " -		   "len=%u\n", id, freq, wait, data_len); +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "send_action_cmd: id=%u freq=%u wait=%u len=%u\n", +		   id, freq, wait, data_len);  	p = (struct wmi_send_mgmt_cmd *) skb->data;  	p->id = cpu_to_le32(id);  	p->freq = cpu_to_le32(freq); @@ -3402,8 +3421,9 @@ int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq,  	if (!skb)  		return -ENOMEM; -	ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM " -		   "len=%u\n", freq, dst, data_len); +	ath6kl_dbg(ATH6KL_DBG_WMI, +		   "send_probe_response_cmd: freq=%u dst=%pM len=%u\n", +		   freq, dst, data_len);  	p = (struct wmi_p2p_probe_response_cmd *) skb->data;  	p->freq = cpu_to_le32(freq);  	memcpy(p->destination_addr, dst, ETH_ALEN); diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index d3d2ab5c168..9076bec3a2b 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -106,6 +106,8 @@ struct wmi_data_sync_bufs {  #define WMM_AC_VI   2		/* video */  #define WMM_AC_VO   3		/* voice */ +#define WMI_VOICE_USER_PRIORITY		0x7 +  struct wmi {  	u16 stream_exist_for_ac[WMM_NUM_AC];  	u8 fat_pipe_exist; @@ -1151,6 +1153,7 @@ enum wmi_phy_mode {  	WMI_11AG_MODE = 0x3,  	WMI_11B_MODE = 0x4,  	WMI_11GONLY_MODE = 0x5, +	WMI_11G_HT20	= 0x6,  };  #define WMI_MAX_CHANNELS        32 @@ -1416,6 +1419,16 @@ struct wmi_ready_event_2 {  	u8 phy_cap;  } __packed; +/* WMI_PHY_CAPABILITY */ +enum wmi_phy_cap { +	WMI_11A_CAP = 0x01, +	WMI_11G_CAP = 0x02, +	WMI_11AG_CAP = 0x03, +	WMI_11AN_CAP = 0x04, +	WMI_11GN_CAP = 0x05, +	WMI_11AGN_CAP = 0x06, +}; +  /* Connect Event */  struct wmi_connect_event {  	union { @@ -1468,6 +1481,17 @@ enum wmi_disconnect_reason {  	IBSS_MERGE = 0xe,  }; +/* AP mode disconnect proto_reasons */ +enum ap_disconnect_reason { +	WMI_AP_REASON_STA_LEFT		= 101, +	WMI_AP_REASON_FROM_HOST		= 102, +	WMI_AP_REASON_COMM_TIMEOUT	= 103, +	WMI_AP_REASON_MAX_STA		= 104, +	WMI_AP_REASON_ACL		= 105, +	WMI_AP_REASON_STA_ROAM		= 106, +	WMI_AP_REASON_DFS_CHANNEL	= 107, +}; +  #define ATH6KL_COUNTRY_RD_SHIFT        16  struct ath6kl_wmi_regdomain {  |