diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex/sta_ioctl.c')
| -rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 97 | 
1 files changed, 58 insertions, 39 deletions
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 0c9f70b2cbe..9f33c92c90f 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,   */  int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)  { -	bool cancel_flag = false;  	int status;  	struct cmd_ctrl_node *cmd_queued; @@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)  	atomic_inc(&adapter->cmd_pending);  	/* Wait for completion */ -	wait_event_interruptible(adapter->cmd_wait_q.wait, -				 *(cmd_queued->condition)); -	if (!*(cmd_queued->condition)) -		cancel_flag = true; - -	if (cancel_flag) { -		mwifiex_cancel_pending_ioctl(adapter); -		dev_dbg(adapter->dev, "cmd cancel\n"); +	status = wait_event_interruptible(adapter->cmd_wait_q.wait, +					  *(cmd_queued->condition)); +	if (status) { +		dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); +		return status;  	}  	status = adapter->cmd_wait_q.status; @@ -160,10 +156,17 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,  {  	int ret;  	u8 *beacon_ie; +	size_t beacon_ie_len;  	struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; +	const struct cfg80211_bss_ies *ies; + +	rcu_read_lock(); +	ies = rcu_dereference(bss->ies); +	beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); +	beacon_ie_len = ies->len; +	bss_desc->timestamp = ies->tsf; +	rcu_read_unlock(); -	beacon_ie = kmemdup(bss->information_elements, bss->len_beacon_ies, -			    GFP_KERNEL);  	if (!beacon_ie) {  		dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");  		return -ENOMEM; @@ -172,12 +175,11 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,  	memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN);  	bss_desc->rssi = bss->signal;  	bss_desc->beacon_buf = beacon_ie; -	bss_desc->beacon_buf_size = bss->len_beacon_ies; +	bss_desc->beacon_buf_size = beacon_ie_len;  	bss_desc->beacon_period = bss->beacon_interval;  	bss_desc->cap_info_bitmap = bss->capability;  	bss_desc->bss_band = bss_priv->band;  	bss_desc->fw_tsf = bss_priv->fw_tsf; -	bss_desc->timestamp = bss->tsf;  	if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {  		dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");  		bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; @@ -198,18 +200,23 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,  static int mwifiex_process_country_ie(struct mwifiex_private *priv,  				      struct cfg80211_bss *bss)  { -	u8 *country_ie, country_ie_len; +	const u8 *country_ie; +	u8 country_ie_len;  	struct mwifiex_802_11d_domain_reg *domain_info =  					&priv->adapter->domain_reg; -	country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); - -	if (!country_ie) +	rcu_read_lock(); +	country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); +	if (!country_ie) { +		rcu_read_unlock();  		return 0; +	}  	country_ie_len = country_ie[1]; -	if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) +	if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) { +		rcu_read_unlock();  		return 0; +	}  	domain_info->country_code[0] = country_ie[2];  	domain_info->country_code[1] = country_ie[3]; @@ -223,6 +230,8 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,  	memcpy((u8 *)domain_info->triplet,  	       &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); +	rcu_read_unlock(); +  	if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,  				   HostCmd_ACT_GEN_SET, 0, NULL)) {  		wiphy_err(priv->adapter->wiphy, @@ -252,11 +261,9 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		/* Allocate and fill new bss descriptor */  		bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), -				GFP_KERNEL); -		if (!bss_desc) { -			dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); +				   GFP_KERNEL); +		if (!bss_desc)  			return -ENOMEM; -		}  		ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);  		if (ret) @@ -269,6 +276,21 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		if (ret)  			goto done; +		if (bss_desc) { +			u8 config_bands = 0; + +			if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) +			    == HostCmd_SCAN_RADIO_TYPE_BG) +				config_bands = BAND_B | BAND_G | BAND_GN | +					       BAND_GAC; +			else +				config_bands = BAND_A | BAND_AN | BAND_AAC; + +			if (!((config_bands | adapter->fw_bands) & +			      ~adapter->fw_bands)) +				adapter->config_bands = config_bands; +		} +  		ret = mwifiex_check_network_compatibility(priv, bss_desc);  		if (ret)  			goto done; @@ -276,8 +298,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		dev_dbg(adapter->dev, "info: SSID found in scan list ... "  				      "associating...\n"); -		if (!netif_queue_stopped(priv->netdev)) -			mwifiex_stop_net_dev_queue(priv->netdev, adapter); +		mwifiex_stop_net_dev_queue(priv->netdev, adapter);  		if (netif_carrier_ok(priv->netdev))  			netif_carrier_off(priv->netdev); @@ -297,7 +318,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		}  		if (bss) -			cfg80211_put_bss(bss); +			cfg80211_put_bss(priv->adapter->wiphy, bss);  	} else {  		/* Adhoc mode */  		/* If the requested SSID matches current SSID, return */ @@ -318,8 +339,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  		ret = mwifiex_check_network_compatibility(priv, bss_desc); -		if (!netif_queue_stopped(priv->netdev)) -			mwifiex_stop_net_dev_queue(priv->netdev, adapter); +		mwifiex_stop_net_dev_queue(priv->netdev, adapter);  		if (netif_carrier_ok(priv->netdev))  			netif_carrier_off(priv->netdev); @@ -328,7 +348,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,  							" list. Joining...\n");  			ret = mwifiex_adhoc_join(priv, bss_desc);  			if (bss) -				cfg80211_put_bss(bss); +				cfg80211_put_bss(priv->adapter->wiphy, bss);  		} else {  			dev_dbg(adapter->dev, "info: Network not found in "  				"the list, creating adhoc with ssid = %s\n", @@ -463,7 +483,7 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)  	}  	if (adapter->hs_activated) { -		dev_dbg(adapter->dev, "cmd: HS Already actived\n"); +		dev_dbg(adapter->dev, "cmd: HS Already activated\n");  		return true;  	} @@ -480,8 +500,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)  		return false;  	} -	wait_event_interruptible(adapter->hs_activate_wait_q, -				 adapter->hs_activate_wait_q_woken); +	if (wait_event_interruptible(adapter->hs_activate_wait_q, +				     adapter->hs_activate_wait_q_woken)) { +		dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); +		return false; +	}  	return true;  } @@ -607,11 +630,8 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,  		}  	}  	buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL); -	if (!buf) { -		dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", -			__func__); +	if (!buf)  		return -ENOMEM; -	}  	txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf;  	txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); @@ -713,7 +733,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,  		dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",  			priv->wpa_ie_len, priv->wpa_ie[0]); -		if (priv->wpa_ie[0] == WLAN_EID_WPA) { +		if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {  			priv->sec_info.wpa_enabled = true;  		} else if (priv->wpa_ie[0] == WLAN_EID_RSN) {  			priv->sec_info.wpa2_enabled = true; @@ -1046,7 +1066,6 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv)  int  mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,  			   struct ieee80211_channel *chan, -			   enum nl80211_channel_type *ct,  			   unsigned int duration)  {  	struct host_cmd_ds_remain_on_chan roc_cfg; @@ -1056,7 +1075,7 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action,  	roc_cfg.action = cpu_to_le16(action);  	if (action == HostCmd_ACT_GEN_SET) {  		roc_cfg.band_cfg = chan->band; -		sc = mwifiex_chan_type_to_sec_chan_offset(*ct); +		sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT);  		roc_cfg.band_cfg |= (sc << 2);  		roc_cfg.channel = @@ -1253,7 +1272,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,  	}  	pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;  	/* Test to see if it is a WPA IE, if not, then it is a gen IE */ -	if (((pvendor_ie->element_id == WLAN_EID_WPA) && +	if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&  	     (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||  	    (pvendor_ie->element_id == WLAN_EID_RSN)) {  |