diff options
Diffstat (limited to 'drivers/net/wireless')
33 files changed, 305 insertions, 75 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 2588848f4a8..d066f2516e4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -2982,6 +2982,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,  	case EEP_RX_MASK:  		return pBase->txrxMask & 0xf;  	case EEP_PAPRD: +		if (AR_SREV_9462(ah)) +			return false; +		if (!ah->config.enable_paprd); +			return false;  		return !!(pBase->featureEnable & BIT(5));  	case EEP_CHAIN_MASK_REDUCE:  		return (pBase->miscConfiguration >> 0x3) & 0x1; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 2c9f7d7ed4c..0ed3846f9cb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	};  	int training_power;  	int i, val; +	u32 am2pm_mask = ah->paprd_ratemask;  	if (IS_CHAN_2GHZ(ah->curchan))  		training_power = ar9003_get_training_power_2g(ah); @@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)  	}  	ah->paprd_training_power = training_power; +	if (AR_SREV_9330(ah)) +		am2pm_mask = 0; +  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,  		      ah->paprd_ratemask);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, -		      ah->paprd_ratemask); +		      am2pm_mask);  	REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,  		      ah->paprd_ratemask_ht40); @@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)  }  EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); +static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah, +				       struct ath9k_hw_cal_data *caldata, +				       int chain) +{ +	u32 *pa_in = caldata->pa_table[chain]; +	int capdiv_offset, quick_drop_offset; +	int capdiv2g, quick_drop; +	int count = 0; +	int i; + +	if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah)) +		return false; + +	capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, +				  AR_PHY_65NM_CH0_TXRF3_CAPDIV2G); + +	quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, +				    AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP); + +	if (quick_drop) +		quick_drop -= 0x40; + +	for (i = 0; i < NUM_BIN + 1; i++) { +		if (pa_in[i] == 1400) +			count++; +	} + +	if (AR_SREV_9485(ah)) { +		if (pa_in[23] < 800) { +			capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150); +			capdiv2g += capdiv_offset; +			if (capdiv2g > 7) { +				capdiv2g = 7; +				if (pa_in[23] < 600) { +					quick_drop++; +					if (quick_drop > 0) +						quick_drop = 0; +				} +			} +		} else if (pa_in[23] == 1400) { +			quick_drop_offset = min_t(int, count / 3, 2); +			quick_drop += quick_drop_offset; +			capdiv2g += quick_drop_offset / 2; + +			if (capdiv2g > 7) +				capdiv2g = 7; + +			if (quick_drop > 0) { +				quick_drop = 0; +				capdiv2g -= quick_drop_offset; +				if (capdiv2g < 0) +					capdiv2g = 0; +			} +		} else { +			return false; +		} +	} else if (AR_SREV_9330(ah)) { +		if (pa_in[23] < 1000) { +			capdiv_offset = (1000 - pa_in[23]) / 100; +			capdiv2g += capdiv_offset; +			if (capdiv_offset > 3) { +				capdiv_offset = 1; +				quick_drop--; +			} + +			capdiv2g += capdiv_offset; +			if (capdiv2g > 6) +				capdiv2g = 6; +			if (quick_drop < -4) +				quick_drop = -4; +		} else if (pa_in[23] == 1400) { +			if (count > 3) { +				quick_drop++; +				capdiv2g -= count / 4; +				if (quick_drop > -2) +					quick_drop = -2; +			} else { +				capdiv2g--; +			} + +			if (capdiv2g < 0) +				capdiv2g = 0; +		} else { +			return false; +		} +	} + +	REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3, +		      AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g); +	REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3, +		      AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP, +		      quick_drop); + +	return true; +} +  int ar9003_paprd_create_curve(struct ath_hw *ah,  			      struct ath9k_hw_cal_data *caldata, int chain)  { @@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,  	if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))  		status = -2; +	if (ar9003_paprd_retrain_pa_in(ah, caldata, chain)) +		status = -EINPROGRESS; +  	REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,  		    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 7bfbaf065a4..84d3d495686 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -625,6 +625,10 @@  #define AR_PHY_AIC_CTRL_4_B0	(AR_SM_BASE + 0x4c0)  #define AR_PHY_AIC_STAT_2_B0	(AR_SM_BASE + 0x4cc) +#define AR_PHY_65NM_CH0_TXRF3       0x16048 +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G		0x0000001e +#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S	1 +  #define AR_PHY_65NM_CH0_SYNTH4      0x1608c  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)  #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 68b643c8943..c8ef30127ad 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1577,6 +1577,8 @@ int ath9k_init_debug(struct ath_hw *ah)  			    sc->debug.debugfs_phy, sc, &fops_tx_chainmask);  	debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,  			    sc->debug.debugfs_phy, sc, &fops_disable_ani); +	debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, +			    &sc->sc_ah->config.enable_paprd);  	debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,  			    sc, &fops_regidx);  	debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index bacdb8fb4ef..9f83f71742a 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)  {  	struct ath_btcoex *btcoex = &sc->btcoex; -	ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); +	if (btcoex->hw_timer_enabled) +		ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);  }  u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 60b6a9daff7..4faf0a39587 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)  		ah->config.spurchans[i][1] = AR_NO_SPUR;  	} -	/* PAPRD needs some more work to be enabled */ -	ah->config.paprd_disable = 1; -  	ah->config.rx_intr_mitigation = true;  	ah->config.pcieSerDesWrite = true; @@ -978,9 +975,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,  	else  		imr_reg |= AR_IMR_TXOK; -	if (opmode == NL80211_IFTYPE_AP) -		imr_reg |= AR_IMR_MIB; -  	ENABLE_REGWRITE_BUFFER(ah);  	REG_WRITE(ah, AR_IMR, imr_reg); @@ -1778,6 +1772,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,  		/* Operating channel changed, reset channel calibration data */  		memset(caldata, 0, sizeof(*caldata));  		ath9k_init_nfcal_hist_buffer(ah, chan); +	} else if (caldata) { +		caldata->paprd_packet_sent = false;  	}  	ah->noise = ath9k_hw_getchan_noise(ah, chan); @@ -2501,9 +2497,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)  		pCap->rx_status_len = sizeof(struct ar9003_rxs);  		pCap->tx_desc_len = sizeof(struct ar9003_txc);  		pCap->txs_len = sizeof(struct ar9003_txs); -		if (!ah->config.paprd_disable && -		    ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) -			pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;  	} else {  		pCap->tx_desc_len = sizeof(struct ath_desc);  		if (AR_SREV_9280_20(ah)) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index ce7332c64ef..de6968fc64f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -236,7 +236,6 @@ enum ath9k_hw_caps {  	ATH9K_HW_CAP_LDPC			= BIT(6),  	ATH9K_HW_CAP_FASTCLOCK			= BIT(7),  	ATH9K_HW_CAP_SGI_20			= BIT(8), -	ATH9K_HW_CAP_PAPRD			= BIT(9),  	ATH9K_HW_CAP_ANT_DIV_COMB		= BIT(10),  	ATH9K_HW_CAP_2GHZ			= BIT(11),  	ATH9K_HW_CAP_5GHZ			= BIT(12), @@ -287,12 +286,12 @@ struct ath9k_ops_config {  	u8 pcie_clock_req;  	u32 pcie_waen;  	u8 analog_shiftreg; -	u8 paprd_disable;  	u32 ofdm_trig_low;  	u32 ofdm_trig_high;  	u32 cck_trig_high;  	u32 cck_trig_low;  	u32 enable_ani; +	u32 enable_paprd;  	int serialize_regmode;  	bool rx_intr_mitigation;  	bool tx_intr_mitigation; @@ -405,6 +404,7 @@ struct ath9k_hw_cal_data {  	int8_t iCoff;  	int8_t qCoff;  	bool rtt_done; +	bool paprd_packet_sent;  	bool paprd_done;  	bool nfcal_pending;  	bool nfcal_interference; diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index d4549e9aac5..7b88b9c39cc 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)  	int chain_ok = 0;  	int chain;  	int len = 1800; +	int ret; -	if (!caldata) +	if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)  		return;  	ath9k_ps_wakeup(sc); @@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)  			continue;  		chain_ok = 0; - -		ath_dbg(common, CALIBRATE, -			"Sending PAPRD frame for thermal measurement on chain %d\n", -			chain); -		if (!ath_paprd_send_frame(sc, skb, chain)) -			goto fail_paprd; -  		ar9003_paprd_setup_gain_table(ah, chain);  		ath_dbg(common, CALIBRATE, @@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)  			break;  		} -		if (ar9003_paprd_create_curve(ah, caldata, chain)) { +		ret = ar9003_paprd_create_curve(ah, caldata, chain); +		if (ret == -EINPROGRESS) { +			ath_dbg(common, CALIBRATE, +				"PAPRD curve on chain %d needs to be re-trained\n", +				chain); +			break; +		} else if (ret) {  			ath_dbg(common, CALIBRATE,  				"PAPRD create curve failed on chain %d\n",  				chain); @@ -423,7 +423,7 @@ set_timer:  		cal_interval = min(cal_interval, (u32)short_cal_interval);  	mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); -	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { +	if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {  		if (!ah->caldata->paprd_done)  			ieee80211_queue_work(sc->hw, &sc->paprd_work);  		else if (!ah->paprd_table_write_done) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2c9da6b2ecb..0d4155aec48 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,  	ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); +	if (sc->sc_ah->caldata) +		sc->sc_ah->caldata->paprd_packet_sent = true; +  	if (!(tx_flags & ATH_TX_ERROR))  		/* Frame was ACKed */  		tx_info->flags |= IEEE80211_TX_STAT_ACK; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 49765d34b4e..7c4ee72f9d5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -638,6 +638,8 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)  		oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),  				       GFP_KERNEL); +		if (!oobirq_entry) +			return -ENOMEM;  		oobirq_entry->irq = res->start;  		oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;  		list_add_tail(&oobirq_entry->list, &oobirq_lh); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 2621dd3d7dc..6f70953f0ba 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -764,8 +764,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)  {  	char iovbuf[32];  	int retcode; +	__le32 arp_mode_le; -	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); +	arp_mode_le = cpu_to_le32(arp_mode); +	brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, +			sizeof(iovbuf));  	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,  				   iovbuf, sizeof(iovbuf));  	retcode = retcode >= 0 ? 0 : retcode; @@ -781,8 +784,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)  {  	char iovbuf[32];  	int retcode; +	__le32 arp_enable_le; -	brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, +	arp_enable_le = cpu_to_le32(arp_enable); + +	brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,  			iovbuf, sizeof(iovbuf));  	retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,  				   iovbuf, sizeof(iovbuf)); @@ -800,10 +806,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  	char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];	/*  Room for  				 "event_msgs" + '\0' + bitvec  */  	char buf[128], *ptr; -	u32 roaming = 1; -	uint bcn_timeout = 3; -	int scan_assoc_time = 40; -	int scan_unassoc_time = 40; +	__le32 roaming_le = cpu_to_le32(1); +	__le32 bcn_timeout_le = cpu_to_le32(3); +	__le32 scan_assoc_time_le = cpu_to_le32(40); +	__le32 scan_unassoc_time_le = cpu_to_le32(40);  	int i;  	struct brcmf_bus_dcmd *cmdlst;  	struct list_head *cur, *q; @@ -829,14 +835,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  	/* Setup timeout if Beacons are lost and roam is off to report  		 link down */ -	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, +	brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,  		    sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,  				  sizeof(iovbuf));  	/* Enable/Disable build-in roaming to allowed ext supplicant to take  		 of romaing */ -	brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, +	brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,  		      iovbuf, sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,  				  sizeof(iovbuf)); @@ -848,9 +854,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)  				  sizeof(iovbuf));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, -			 (char *)&scan_assoc_time, sizeof(scan_assoc_time)); +		 (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));  	brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, -			 (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); +		 (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));  	/* Set and enable ARP offload feature */  	brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a299d42da8e..58f89fa9c9f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb)  	else  		devinfo->bus_pub.bus->dstats.tx_errors++; -	dev_kfree_skb(req->skb); +	brcmu_pkt_buf_free_skb(req->skb);  	req->skb = NULL;  	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); @@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)  		devinfo->bus_pub.bus->dstats.rx_packets++;  	} else {  		devinfo->bus_pub.bus->dstats.rx_errors++; -		dev_kfree_skb(skb); +		brcmu_pkt_buf_free_skb(skb);  		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  		return;  	} @@ -550,13 +550,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)  		if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {  			brcmf_dbg(ERROR, "rx protocol error\n");  			brcmu_pkt_buf_free_skb(skb); +			brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  			devinfo->bus_pub.bus->dstats.rx_errors++;  		} else {  			brcmf_rx_packet(devinfo->dev, ifidx, skb);  			brcmf_usb_rx_refill(devinfo, req);  		}  	} else { -		dev_kfree_skb(skb); +		brcmu_pkt_buf_free_skb(skb); +		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  	}  	return; @@ -581,14 +583,13 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,  	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,  			  skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,  			  req); -	req->urb->transfer_flags |= URB_ZERO_PACKET;  	req->devinfo = devinfo; +	brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);  	ret = usb_submit_urb(req->urb, GFP_ATOMIC); -	if (ret == 0) { -		brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); -	} else { -		dev_kfree_skb(req->skb); +	if (ret) { +		brcmf_usb_del_fromq(devinfo, req); +		brcmu_pkt_buf_free_skb(req->skb);  		req->skb = NULL;  		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);  	} @@ -683,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)  	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);  	if (!req) { +		brcmu_pkt_buf_free_skb(skb);  		brcmf_dbg(ERROR, "no req to send\n");  		return -ENOMEM;  	} -	if (!req->urb) { -		brcmf_dbg(ERROR, "no urb for req %p\n", req); -		return -ENOBUFS; -	}  	req->skb = skb;  	req->devinfo = devinfo;  	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,  			  skb->data, skb->len, brcmf_usb_tx_complete, req);  	req->urb->transfer_flags |= URB_ZERO_PACKET; +	brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);  	ret = usb_submit_urb(req->urb, GFP_ATOMIC); -	if (!ret) { -		brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); -	} else { +	if (ret) { +		brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n"); +		brcmf_usb_del_fromq(devinfo, req); +		brcmu_pkt_buf_free_skb(req->skb);  		req->skb = NULL;  		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);  	} diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 28c5fbb4af2..50b5553b696 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -500,8 +500,10 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,  	params_le->active_time = cpu_to_le32(-1);  	params_le->passive_time = cpu_to_le32(-1);  	params_le->home_time = cpu_to_le32(-1); -	if (ssid && ssid->SSID_len) -		memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); +	if (ssid && ssid->SSID_len) { +		params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); +		memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); +	}  }  static s32 @@ -1876,16 +1878,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,  	}  	if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { -		scb_val.val = cpu_to_le32(0); +		memset(&scb_val, 0, sizeof(scb_val));  		err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,  				      sizeof(struct brcmf_scb_val_le)); -		if (err) +		if (err) {  			WL_ERR("Could not get rssi (%d)\n", err); - -		rssi = le32_to_cpu(scb_val.val); -		sinfo->filled |= STATION_INFO_SIGNAL; -		sinfo->signal = rssi; -		WL_CONN("RSSI %d dBm\n", rssi); +		} else { +			rssi = le32_to_cpu(scb_val.val); +			sinfo->filled |= STATION_INFO_SIGNAL; +			sinfo->signal = rssi; +			WL_CONN("RSSI %d dBm\n", rssi); +		}  	}  done: diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 7ed7d757702..64a48f06d68 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c @@ -77,7 +77,7 @@  					 NL80211_RRF_NO_IBSS)  static const struct ieee80211_regdomain brcms_regdom_x2 = { -	.n_reg_rules = 7, +	.n_reg_rules = 6,  	.alpha2 = "X2",  	.reg_rules = {  		BRCM_2GHZ_2412_2462, diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 1e86ea2266d..dbeebef562d 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1442,6 +1442,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)  	return err;  err_free_irq: +	trans_pcie->irq_requested = false;  	free_irq(trans_pcie->irq, trans);  error:  	iwl_free_isr_ict(trans); diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index e970897f6ab..4cb234349fb 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev)  	mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); +	/* If we're powered off anyway, just let the mmc layer remove the +	 * card. */ +	if (!lbs_iface_active(card->priv)) +		return -ENOSYS; +  	dev_info(dev, "%s: suspend: PM flags = 0x%x\n",  		 sdio_func_id(func), flags); diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index c68adec3cc8..565527aee0e 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,  	cmd_code = le16_to_cpu(host_cmd->command);  	cmd_size = le16_to_cpu(host_cmd->size); -	skb_trim(cmd_node->cmd_skb, cmd_size); +	/* Adjust skb length */ +	if (cmd_node->cmd_skb->len > cmd_size) +		/* +		 * cmd_size is less than sizeof(struct host_cmd_ds_command). +		 * Trim off the unused portion. +		 */ +		skb_trim(cmd_node->cmd_skb, cmd_size); +	else if (cmd_node->cmd_skb->len < cmd_size) +		/* +		 * cmd_size is larger than sizeof(struct host_cmd_ds_command) +		 * because we have appended custom IE TLV. Increase skb length +		 * accordingly. +		 */ +		skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);  	do_gettimeofday(&tstamp);  	dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d," diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 8b9dbd76a25..64328af496f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1624,6 +1625,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_BIT8, 1); +	rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2400pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc43..7564ae992b7 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@  #define GPIOCSR_BIT5			FIELD32(0x00000020)  #define GPIOCSR_BIT6			FIELD32(0x00000040)  #define GPIOCSR_BIT7			FIELD32(0x00000080) +#define GPIOCSR_BIT8			FIELD32(0x00000100)  /*   * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d2cf8a4bc8b..3de0406735f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -1942,6 +1943,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); +	rt2x00_set_field32(®, GPIOCSR_DIR0, 1); +	rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3aae36bb0a9..89fee311d8f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)  	u16 reg;  	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); -	return rt2x00_get_field32(reg, MAC_CSR19_BIT7); +	return rt2x00_get_field16(reg, MAC_CSR19_BIT7);  }  #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u16 reg;  	/*  	 * Allocate eeprom data. @@ -1781,6 +1782,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); +	rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); +	rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2500usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7ee..196bd5103e4 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,15 @@   * MAC_CSR19: GPIO control register.   */  #define MAC_CSR19			0x0426 -#define MAC_CSR19_BIT0			FIELD32(0x0001) -#define MAC_CSR19_BIT1			FIELD32(0x0002) -#define MAC_CSR19_BIT2			FIELD32(0x0004) -#define MAC_CSR19_BIT3			FIELD32(0x0008) -#define MAC_CSR19_BIT4			FIELD32(0x0010) -#define MAC_CSR19_BIT5			FIELD32(0x0020) -#define MAC_CSR19_BIT6			FIELD32(0x0040) -#define MAC_CSR19_BIT7			FIELD32(0x0080) +#define MAC_CSR19_BIT0			FIELD16(0x0001) +#define MAC_CSR19_BIT1			FIELD16(0x0002) +#define MAC_CSR19_BIT2			FIELD16(0x0004) +#define MAC_CSR19_BIT3			FIELD16(0x0008) +#define MAC_CSR19_BIT4			FIELD16(0x0010) +#define MAC_CSR19_BIT5			FIELD16(0x0020) +#define MAC_CSR19_BIT6			FIELD16(0x0040) +#define MAC_CSR19_BIT7			FIELD16(0x0080) +#define MAC_CSR19_BIT8			FIELD16(0x0100)  /*   * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index cb8c2aca54e..b93516d832f 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)  		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  		msleep(1);  		rt2800_register_read(rt2x00dev, LDO_CFG0, ®); +		rt2x00_set_field32(®, LDO_CFG0_LDO_CORE_VLEVEL, 0);  		rt2x00_set_field32(®, LDO_CFG0_BGSEL, 1);  		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);  	} diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 98aa426a356..4765bbd654c 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)  static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -996,6 +997,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); +	rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2800_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 6cf336595e2..6b4226b7161 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,  	skb_pull(entry->skb, RXINFO_DESC_SIZE);  	/* -	 * FIXME: we need to check for rx_pkt_len validity +	 * Check for rx_pkt_len validity. Return if invalid, leaving +	 * rxdesc->size zeroed out by the upper level.  	 */ +	if (unlikely(rx_pkt_len == 0 || +			rx_pkt_len > entry->queue->data_size)) { +		ERROR(entry->queue->rt2x00dev, +			"Bad frame size %d, forcing to 0\n", rx_pkt_len); +		return; +	} +  	rxd = (__le32 *)(entry->skb->data + rx_pkt_len);  	/* @@ -736,6 +744,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)  static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -749,6 +758,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); +	rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); +	rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt2800_probe_hw_mode(rt2x00dev); @@ -1157,6 +1174,8 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x1690, 0x0744) },  	{ USB_DEVICE(0x1690, 0x0761) },  	{ USB_DEVICE(0x1690, 0x0764) }, +	/* ASUS */ +	{ USB_DEVICE(0x0b05, 0x179d) },  	/* Cisco */  	{ USB_DEVICE(0x167b, 0x4001) },  	/* EnGenius */ @@ -1222,7 +1241,6 @@ static struct usb_device_id rt2800usb_device_table[] = {  	{ USB_DEVICE(0x0b05, 0x1760) },  	{ USB_DEVICE(0x0b05, 0x1761) },  	{ USB_DEVICE(0x0b05, 0x1790) }, -	{ USB_DEVICE(0x0b05, 0x179d) },  	/* AzureWave */  	{ USB_DEVICE(0x13d3, 0x3262) },  	{ USB_DEVICE(0x13d3, 0x3284) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a6b88bd4a1a..3f07e36f462 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)  	 */  	if (unlikely(rxdesc.size == 0 ||  		     rxdesc.size > entry->queue->data_size)) { -		WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", +		ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",  			rxdesc.size, entry->queue->data_size);  		dev_kfree_skb(entry->skb);  		goto renew_skb; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 3f7bc5cadf9..b8ec9616392 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Disable power saving. @@ -2850,6 +2851,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); +	rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt61pci_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0..8f3da5a5676 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry {  #define MAC_CSR13_BIT10			FIELD32(0x00000400)  #define MAC_CSR13_BIT11			FIELD32(0x00000800)  #define MAC_CSR13_BIT12			FIELD32(0x00001000) +#define MAC_CSR13_BIT13			FIELD32(0x00002000)  /*   * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ba6e434b859..248436c13ce 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)  static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  {  	int retval; +	u32 reg;  	/*  	 * Allocate eeprom data. @@ -2190,6 +2191,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)  		return retval;  	/* +	 * Enable rfkill polling by setting GPIO direction of the +	 * rfkill switch GPIO pin correctly. +	 */ +	rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); +	rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); +	rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + +	/*  	 * Initialize hw specifications.  	 */  	retval = rt73usb_probe_hw_mode(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d..df1cc116b83 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry {  #define MAC_CSR13_BIT10			FIELD32(0x00000400)  #define MAC_CSR13_BIT11			FIELD32(0x00000800)  #define MAC_CSR13_BIT12			FIELD32(0x00001000) +#define MAC_CSR13_BIT13			FIELD32(0x00002000) +#define MAC_CSR13_BIT14			FIELD32(0x00004000) +#define MAC_CSR13_BIT15			FIELD32(0x00008000)  /*   * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 04c3aef8a4f..2925094b2d9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,6 +117,7 @@  #define CHIP_VER_B			BIT(4)  #define CHIP_92C_BITMASK		BIT(0) +#define CHIP_UNKNOWN			BIT(7)  #define CHIP_92C_1T2R			0x03  #define CHIP_92C			0x01  #define CHIP_88C			0x00 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index bd0da7ef290..dd4bb0950a5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -994,8 +994,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)  		version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :  			   VERSION_A_CHIP_88C;  	} else { -		version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : -			   VERSION_B_CHIP_88C; +		version = (enum version_8192c) (CHIP_VER_B | +				((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | +				((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); +		if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & +		     CHIP_VER_RTL_MASK)) { +			version = (enum version_8192c)(version | +				   ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) +				   ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | +				   CHIP_VENDOR_UMC)); +		}  	}  	switch (version) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 3aa927f8b9b..7d8f96405f4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)  	/* request fw */  	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && -	    !IS_92C_SERIAL(rtlhal->version)) +	    !IS_92C_SERIAL(rtlhal->version)) {  		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; -	else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) +	} else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {  		rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; +		pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); +	}  	rtlpriv->max_fw_size = 0x4000;  	pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);  |