diff options
Diffstat (limited to 'drivers/net/wireless/iwlegacy')
| -rw-r--r-- | drivers/net/wireless/iwlegacy/3945-mac.c | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlegacy/3945.c | 18 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlegacy/4965-mac.c | 25 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlegacy/commands.h | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlegacy/common.c | 11 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlegacy/common.h | 41 | 
6 files changed, 91 insertions, 17 deletions
| diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index b37a582ccbe7..9581d07a4242 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3119,7 +3119,7 @@ il3945_store_debug_level(struct device *d, struct device_attribute *attr,  	unsigned long val;  	int ret; -	ret = strict_strtoul(buf, 0, &val); +	ret = kstrtoul(buf, 0, &val);  	if (ret)  		IL_INFO("%s is not in hex or decimal form.\n", buf);  	else @@ -3727,7 +3727,8 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	 * 5. Setup HW Constants  	 * ********************/  	/* Device-specific setup */ -	if (il3945_hw_set_hw_params(il)) { +	err = il3945_hw_set_hw_params(il); +	if (err) {  		IL_ERR("failed to set hw settings\n");  		goto out_eeprom_free;  	} diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index dc1e6da9976a..c092033945cc 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -331,6 +331,19 @@ il3945_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)  		return;  	} +	/* +	 * Firmware will not transmit frame on passive channel, if it not yet +	 * received some valid frame on that channel. When this error happen +	 * we have to wait until firmware will unblock itself i.e. when we +	 * note received beacon or other frame. We unblock queues in +	 * il3945_pass_packet_to_mac80211 or in il_mac_bss_info_changed. +	 */ +	if (unlikely((status & TX_STATUS_MSK) == TX_STATUS_FAIL_PASSIVE_NO_RX) && +	    il->iw_mode == NL80211_IFTYPE_STATION) { +		il_stop_queues_by_reason(il, IL_STOP_REASON_PASSIVE); +		D_INFO("Stopped queues - RX waiting on passive channel\n"); +	} +  	txq->time_stamp = jiffies;  	info = IEEE80211_SKB_CB(txq->skbs[txq->q.read_ptr]);  	ieee80211_tx_info_clear_status(info); @@ -488,6 +501,11 @@ il3945_pass_packet_to_mac80211(struct il_priv *il, struct il_rx_buf *rxb,  		return;  	} +	if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) { +		il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE); +		D_INFO("Woke queues - frame received on passive channel\n"); +	} +  	skb = dev_alloc_skb(128);  	if (!skb) {  		IL_ERR("dev_alloc_skb failed\n"); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 9a95045c97b6..b9b2bb51e605 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -588,6 +588,11 @@ il4965_pass_packet_to_mac80211(struct il_priv *il, struct ieee80211_hdr *hdr,  		return;  	} +	if (unlikely(test_bit(IL_STOP_REASON_PASSIVE, &il->stop_reason))) { +		il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE); +		D_INFO("Woke queues - frame received on passive channel\n"); +	} +  	/* In case of HW accelerated crypto and bad decryption, drop */  	if (!il->cfg->mod_params->sw_crypto &&  	    il_set_decrypted_flag(il, hdr, ampdu_status, stats)) @@ -2806,6 +2811,19 @@ il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb)  		return;  	} +	/* +	 * Firmware will not transmit frame on passive channel, if it not yet +	 * received some valid frame on that channel. When this error happen +	 * we have to wait until firmware will unblock itself i.e. when we +	 * note received beacon or other frame. We unblock queues in +	 * il4965_pass_packet_to_mac80211 or in il_mac_bss_info_changed. +	 */ +	if (unlikely((status & TX_STATUS_MSK) == TX_STATUS_FAIL_PASSIVE_NO_RX) && +	    il->iw_mode == NL80211_IFTYPE_STATION) { +		il_stop_queues_by_reason(il, IL_STOP_REASON_PASSIVE); +		D_INFO("Stopped queues - RX waiting on passive channel\n"); +	} +  	spin_lock_irqsave(&il->sta_lock, flags);  	if (txq->sched_retry) {  		const u32 scd_ssn = il4965_get_scd_ssn(tx_resp); @@ -4567,7 +4585,7 @@ il4965_store_debug_level(struct device *d, struct device_attribute *attr,  	unsigned long val;  	int ret; -	ret = strict_strtoul(buf, 0, &val); +	ret = kstrtoul(buf, 0, &val);  	if (ret)  		IL_ERR("%s is not in hex or decimal form.\n", buf);  	else @@ -4614,7 +4632,7 @@ il4965_store_tx_power(struct device *d, struct device_attribute *attr,  	unsigned long val;  	int ret; -	ret = strict_strtoul(buf, 10, &val); +	ret = kstrtoul(buf, 10, &val);  	if (ret)  		IL_INFO("%s is not in decimal form.\n", buf);  	else { @@ -5741,7 +5759,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)  	hw->flags =  	    IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |  	    IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | -	    IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; +	    IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | +	    IEEE80211_HW_SUPPORTS_DYNAMIC_PS;  	if (il->cfg->sku & IL_SKU_N)  		hw->flags |=  		    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | diff --git a/drivers/net/wireless/iwlegacy/commands.h b/drivers/net/wireless/iwlegacy/commands.h index 3b6c99400892..048421511988 100644 --- a/drivers/net/wireless/iwlegacy/commands.h +++ b/drivers/net/wireless/iwlegacy/commands.h @@ -1348,14 +1348,6 @@ struct il_rx_mpdu_res_start {  #define TX_CMD_SEC_KEY128	0x08  /* - * security overhead sizes - */ -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 -#define CCMP_MIC_LEN 8 -#define TKIP_ICV_LEN 4 - -/*   * C_TX = 0x1c (command)   */ diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index e9a3cbc409ae..3195aad440dd 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -5307,6 +5307,17 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  		D_MAC80211("BSSID %pM\n", bss_conf->bssid);  		/* +		 * On passive channel we wait with blocked queues to see if +		 * there is traffic on that channel. If no frame will be +		 * received (what is very unlikely since scan detects AP on +		 * that channel, but theoretically possible), mac80211 associate +		 * procedure will time out and mac80211 will call us with NULL +		 * bssid. We have to unblock queues on such condition. +		 */ +		if (is_zero_ether_addr(bss_conf->bssid)) +			il_wake_queues_by_reason(il, IL_STOP_REASON_PASSIVE); + +		/*  		 * If there is currently a HW scan going on in the background,  		 * then we need to cancel it, otherwise sometimes we are not  		 * able to authenticate (FIXME: why ?) diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h index 4caaf52986a4..83f8ed8a5528 100644 --- a/drivers/net/wireless/iwlegacy/common.h +++ b/drivers/net/wireless/iwlegacy/common.h @@ -1299,6 +1299,8 @@ struct il_priv {  	/* queue refcounts */  #define IL_MAX_HW_QUEUES	32  	unsigned long queue_stopped[BITS_TO_LONGS(IL_MAX_HW_QUEUES)]; +#define IL_STOP_REASON_PASSIVE	0 +	unsigned long stop_reason;  	/* for each AC */  	atomic_t queue_stop_count[4]; @@ -2257,6 +2259,19 @@ il_set_swq_id(struct il_tx_queue *txq, u8 ac, u8 hwq)  }  static inline void +_il_wake_queue(struct il_priv *il, u8 ac) +{ +	if (atomic_dec_return(&il->queue_stop_count[ac]) <= 0) +		ieee80211_wake_queue(il->hw, ac); +} + +static inline void +_il_stop_queue(struct il_priv *il, u8 ac) +{ +	if (atomic_inc_return(&il->queue_stop_count[ac]) > 0) +		ieee80211_stop_queue(il->hw, ac); +} +static inline void  il_wake_queue(struct il_priv *il, struct il_tx_queue *txq)  {  	u8 queue = txq->swq_id; @@ -2264,8 +2279,7 @@ il_wake_queue(struct il_priv *il, struct il_tx_queue *txq)  	u8 hwq = (queue >> 2) & 0x1f;  	if (test_and_clear_bit(hwq, il->queue_stopped)) -		if (atomic_dec_return(&il->queue_stop_count[ac]) <= 0) -			ieee80211_wake_queue(il->hw, ac); +		_il_wake_queue(il, ac);  }  static inline void @@ -2276,8 +2290,27 @@ il_stop_queue(struct il_priv *il, struct il_tx_queue *txq)  	u8 hwq = (queue >> 2) & 0x1f;  	if (!test_and_set_bit(hwq, il->queue_stopped)) -		if (atomic_inc_return(&il->queue_stop_count[ac]) > 0) -			ieee80211_stop_queue(il->hw, ac); +		_il_stop_queue(il, ac); +} + +static inline void +il_wake_queues_by_reason(struct il_priv *il, int reason) +{ +	u8 ac; + +	if (test_and_clear_bit(reason, &il->stop_reason)) +		for (ac = 0; ac < 4; ac++) +			_il_wake_queue(il, ac); +} + +static inline void +il_stop_queues_by_reason(struct il_priv *il, int reason) +{ +	u8 ac; + +	if (!test_and_set_bit(reason, &il->stop_reason)) +		for (ac = 0; ac < 4; ac++) +			_il_stop_queue(il, ac);  }  #ifdef ieee80211_stop_queue |