Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts: net/mac80211/sta_info.c net/wireless/core.h
This commit is contained in:
		
						commit
						9a574cd67a
					
				| @ -5043,9 +5043,8 @@ S:	Maintained | ||||
| F:	drivers/net/ethernet/marvell/sk* | ||||
| 
 | ||||
| MARVELL LIBERTAS WIRELESS DRIVER | ||||
| M:	Dan Williams <dcbw@redhat.com> | ||||
| L:	libertas-dev@lists.infradead.org | ||||
| S:	Maintained | ||||
| S:	Orphan | ||||
| F:	drivers/net/wireless/libertas/ | ||||
| 
 | ||||
| MARVELL MV643XX ETHERNET DRIVER | ||||
|  | ||||
| @ -73,9 +73,11 @@ static struct usb_device_id ath3k_table[] = { | ||||
| 	{ USB_DEVICE(0x03F0, 0x311D) }, | ||||
| 
 | ||||
| 	/* Atheros AR3012 with sflash firmware*/ | ||||
| 	{ USB_DEVICE(0x0CF3, 0x0036) }, | ||||
| 	{ USB_DEVICE(0x0CF3, 0x3004) }, | ||||
| 	{ USB_DEVICE(0x0CF3, 0x3008) }, | ||||
| 	{ USB_DEVICE(0x0CF3, 0x311D) }, | ||||
| 	{ USB_DEVICE(0x0CF3, 0x817a) }, | ||||
| 	{ USB_DEVICE(0x13d3, 0x3375) }, | ||||
| 	{ USB_DEVICE(0x04CA, 0x3004) }, | ||||
| 	{ USB_DEVICE(0x04CA, 0x3005) }, | ||||
| @ -107,9 +109,11 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); | ||||
| static struct usb_device_id ath3k_blist_tbl[] = { | ||||
| 
 | ||||
| 	/* Atheros AR3012 with sflash firmware*/ | ||||
| 	{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | ||||
|  | ||||
| @ -131,9 +131,11 @@ static struct usb_device_id blacklist_table[] = { | ||||
| 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, | ||||
| 
 | ||||
| 	/* Atheros 3012 with sflash firmware */ | ||||
| 	{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||||
| 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | ||||
|  | ||||
| @ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | ||||
| 					  AR_PHY_AGC_CONTROL_FLTR_CAL   | | ||||
| 					  AR_PHY_AGC_CONTROL_PKDET_CAL; | ||||
| 
 | ||||
| 	/* Use chip chainmask only for calibration */ | ||||
| 	ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); | ||||
| 
 | ||||
| 	if (rtt) { | ||||
| @ -1151,6 +1152,9 @@ skip_tx_iqcal: | ||||
| 		ar9003_hw_rtt_disable(ah); | ||||
| 	} | ||||
| 
 | ||||
| 	/* Revert chainmask to runtime parameters */ | ||||
| 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | ||||
| 
 | ||||
| 	/* Initialize list pointers */ | ||||
| 	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | ||||
| 
 | ||||
|  | ||||
| @ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct work_struct *work) | ||||
| 	int i; | ||||
| 	bool needreset = false; | ||||
| 
 | ||||
| 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | ||||
| 		if (ATH_TXQ_SETUP(sc, i)) { | ||||
| 			txq = &sc->tx.txq[i]; | ||||
| 			ath_txq_lock(sc, txq); | ||||
| 			if (txq->axq_depth) { | ||||
| 				if (txq->axq_tx_inprogress) { | ||||
| 					needreset = true; | ||||
| 					ath_txq_unlock(sc, txq); | ||||
| 					break; | ||||
| 				} else { | ||||
| 					txq->axq_tx_inprogress = true; | ||||
| 				} | ||||
| 	for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||||
| 		txq = sc->tx.txq_map[i]; | ||||
| 
 | ||||
| 		ath_txq_lock(sc, txq); | ||||
| 		if (txq->axq_depth) { | ||||
| 			if (txq->axq_tx_inprogress) { | ||||
| 				needreset = true; | ||||
| 				ath_txq_unlock(sc, txq); | ||||
| 				break; | ||||
| 			} else { | ||||
| 				txq->axq_tx_inprogress = true; | ||||
| 			} | ||||
| 			ath_txq_unlock_complete(sc, txq); | ||||
| 		} | ||||
| 		ath_txq_unlock_complete(sc, txq); | ||||
| 	} | ||||
| 
 | ||||
| 	if (needreset) { | ||||
| 		ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | ||||
| @ -170,7 +170,8 @@ void ath_rx_poll(unsigned long data) | ||||
| { | ||||
| 	struct ath_softc *sc = (struct ath_softc *)data; | ||||
| 
 | ||||
| 	ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||||
| 	if (!test_bit(SC_OP_INVALID, &sc->sc_flags)) | ||||
| 		ieee80211_queue_work(sc->hw, &sc->hw_check_work); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | ||||
| 	const struct b43_dma_ops *ops; | ||||
| 	struct b43_dmaring *ring; | ||||
| 	struct b43_dmadesc_meta *meta; | ||||
| 	static const struct b43_txstatus fake; /* filled with 0 */ | ||||
| 	const struct b43_txstatus *txstat; | ||||
| 	int slot, firstused; | ||||
| 	bool frame_succeed; | ||||
| 	int skip; | ||||
| 	static u8 err_out1, err_out2; | ||||
| 
 | ||||
| 	ring = parse_cookie(dev, status->cookie, &slot); | ||||
| 	if (unlikely(!ring)) | ||||
| @ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | ||||
| 	firstused = ring->current_slot - ring->used_slots + 1; | ||||
| 	if (firstused < 0) | ||||
| 		firstused = ring->nr_slots + firstused; | ||||
| 
 | ||||
| 	skip = 0; | ||||
| 	if (unlikely(slot != firstused)) { | ||||
| 		/* This possibly is a firmware bug and will result in
 | ||||
| 		 * malfunction, memory leaks and/or stall of DMA functionality. */ | ||||
| 		b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. " | ||||
| 		       "Expected %d, but got %d\n", | ||||
| 		       ring->index, firstused, slot); | ||||
| 		return; | ||||
| 		 * malfunction, memory leaks and/or stall of DMA functionality. | ||||
| 		 */ | ||||
| 		if (slot == next_slot(ring, next_slot(ring, firstused))) { | ||||
| 			/* If a single header/data pair was missed, skip over
 | ||||
| 			 * the first two slots in an attempt to recover. | ||||
| 			 */ | ||||
| 			slot = firstused; | ||||
| 			skip = 2; | ||||
| 			if (!err_out1) { | ||||
| 				/* Report the error once. */ | ||||
| 				b43dbg(dev->wl, | ||||
| 				       "Skip on DMA ring %d slot %d.\n", | ||||
| 				       ring->index, slot); | ||||
| 				err_out1 = 1; | ||||
| 			} | ||||
| 		} else { | ||||
| 			/* More than a single header/data pair were missed.
 | ||||
| 			 * Report this error once. | ||||
| 			 */ | ||||
| 			if (!err_out2) | ||||
| 				b43dbg(dev->wl, | ||||
| 				       "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n", | ||||
| 				       ring->index, firstused, slot); | ||||
| 			err_out2 = 1; | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	ops = ring->ops; | ||||
| @ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | ||||
| 			       slot, firstused, ring->index); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (meta->skb) { | ||||
| 			struct b43_private_tx_info *priv_info = | ||||
| 				b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); | ||||
| 			     b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); | ||||
| 
 | ||||
| 			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); | ||||
| 			unmap_descbuffer(ring, meta->dmaaddr, | ||||
| 					 meta->skb->len, 1); | ||||
| 			kfree(priv_info->bouncebuffer); | ||||
| 			priv_info->bouncebuffer = NULL; | ||||
| 		} else { | ||||
| @ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | ||||
| 			struct ieee80211_tx_info *info; | ||||
| 
 | ||||
| 			if (unlikely(!meta->skb)) { | ||||
| 				/* This is a scatter-gather fragment of a frame, so
 | ||||
| 				 * the skb pointer must not be NULL. */ | ||||
| 				/* This is a scatter-gather fragment of a frame,
 | ||||
| 				 * so the skb pointer must not be NULL. | ||||
| 				 */ | ||||
| 				b43dbg(dev->wl, "TX status unexpected NULL skb " | ||||
| 				       "at slot %d (first=%d) on ring %d\n", | ||||
| 				       slot, firstused, ring->index); | ||||
| @ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * Call back to inform the ieee80211 subsystem about | ||||
| 			 * the status of the transmission. | ||||
| 			 * the status of the transmission. When skipping over | ||||
| 			 * a missed TX status report, use a status structure | ||||
| 			 * filled with zeros to indicate that the frame was not | ||||
| 			 * sent (frame_count 0) and not acknowledged | ||||
| 			 */ | ||||
| 			frame_succeed = b43_fill_txstatus_report(dev, info, status); | ||||
| 			if (unlikely(skip)) | ||||
| 				txstat = &fake; | ||||
| 			else | ||||
| 				txstat = status; | ||||
| 
 | ||||
| 			frame_succeed = b43_fill_txstatus_report(dev, info, | ||||
| 								 txstat); | ||||
| #ifdef CONFIG_B43_DEBUG | ||||
| 			if (frame_succeed) | ||||
| 				ring->nr_succeed_tx_packets++; | ||||
| @ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | ||||
| 		/* Everything unmapped and free'd. So it's not used anymore. */ | ||||
| 		ring->used_slots--; | ||||
| 
 | ||||
| 		if (meta->is_last_fragment) { | ||||
| 		if (meta->is_last_fragment && !skip) { | ||||
| 			/* This is the last scatter-gather
 | ||||
| 			 * fragment of the frame. We are done. */ | ||||
| 			break; | ||||
| 		} | ||||
| 		slot = next_slot(ring, slot); | ||||
| 		if (skip > 0) | ||||
| 			--skip; | ||||
| 	} | ||||
| 	if (ring->stopped) { | ||||
| 		B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); | ||||
|  | ||||
| @ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||||
| 	u16 clip_off[2] = { 0xFFFF, 0xFFFF }; | ||||
| 
 | ||||
| 	u8 vcm_final = 0; | ||||
| 	s8 offset[4]; | ||||
| 	s32 offset[4]; | ||||
| 	s32 results[8][4] = { }; | ||||
| 	s32 results_min[4] = { }; | ||||
| 	s32 poll_results[4] = { }; | ||||
| @ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) | ||||
| 		} | ||||
| 		for (i = 0; i < 4; i += 2) { | ||||
| 			s32 curr; | ||||
| 			s32 mind = 40; | ||||
| 			s32 mind = 0x100000; | ||||
| 			s32 minpoll = 249; | ||||
| 			u8 minvcm = 0; | ||||
| 			if (2 * core != i) | ||||
| @ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | ||||
| 	u8 regs_save_radio[2]; | ||||
| 	u16 regs_save_phy[2]; | ||||
| 
 | ||||
| 	s8 offset[4]; | ||||
| 	s32 offset[4]; | ||||
| 	u8 core; | ||||
| 	u8 rail; | ||||
| 
 | ||||
| @ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) | ||||
| 	} | ||||
| 
 | ||||
| 	for (i = 0; i < 4; i++) { | ||||
| 		s32 mind = 40; | ||||
| 		s32 mind = 0x100000; | ||||
| 		u8 minvcm = 0; | ||||
| 		s32 minpoll = 249; | ||||
| 		s32 curr; | ||||
|  | ||||
| @ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, | ||||
| 	gain0_15 = ((biq1 & 0xf) << 12) | | ||||
| 		   ((tia & 0xf) << 8) | | ||||
| 		   ((lna2 & 0x3) << 6) | | ||||
| 		   ((lna2 & 0x3) << 4) | | ||||
| 		   ((lna1 & 0x3) << 2) | | ||||
| 		   ((lna1 & 0x3) << 0); | ||||
| 		   ((lna2 & | ||||
| 		     0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0); | ||||
| 	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0); | ||||
| @ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi, | ||||
| 	} | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0); | ||||
| 	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11); | ||||
| 	mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| @ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples) | ||||
| 	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples; | ||||
| } | ||||
| 
 | ||||
| static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, | ||||
| 				      u16 tia_gain, u16 lna2_gain) | ||||
| { | ||||
| 	u32 i_thresh_l, q_thresh_l; | ||||
| 	u32 i_thresh_h, q_thresh_h; | ||||
| 	struct lcnphy_iq_est iq_est_h, iq_est_l; | ||||
| 
 | ||||
| 	wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain, | ||||
| 					       lna2_gain, 0); | ||||
| 
 | ||||
| 	wlc_lcnphy_rx_gain_override_enable(pi, true); | ||||
| 	wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); | ||||
| 	udelay(500); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG112, 0); | ||||
| 	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); | ||||
| 	udelay(500); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG112, 0); | ||||
| 	if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	i_thresh_l = (iq_est_l.i_pwr << 1); | ||||
| 	i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr; | ||||
| 
 | ||||
| 	q_thresh_l = (iq_est_l.q_pwr << 1); | ||||
| 	q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr; | ||||
| 	if ((iq_est_h.i_pwr > i_thresh_l) && | ||||
| 	    (iq_est_h.i_pwr < i_thresh_h) && | ||||
| 	    (iq_est_h.q_pwr > q_thresh_l) && | ||||
| 	    (iq_est_h.q_pwr < q_thresh_h)) | ||||
| 		return true; | ||||
| 
 | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static bool | ||||
| wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | ||||
| 		     const struct lcnphy_rx_iqcomp *iqcomp, | ||||
| @ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | ||||
| 	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old, | ||||
| 	    rfoverride3_old, rfoverride3val_old, rfoverride4_old, | ||||
| 	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old; | ||||
| 	int tia_gain, lna2_gain, biq1_gain; | ||||
| 	bool set_gain; | ||||
| 	int tia_gain; | ||||
| 	u32 received_power, rx_pwr_threshold; | ||||
| 	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl; | ||||
| 	u16 values_to_save[11]; | ||||
| 	s16 *ptr; | ||||
| @ -1408,135 +1368,127 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi, | ||||
| 		goto cal_done; | ||||
| 	} | ||||
| 
 | ||||
| 	WARN_ON(module != 1); | ||||
| 	tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); | ||||
| 	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); | ||||
| 	if (module == 1) { | ||||
| 
 | ||||
| 	for (i = 0; i < 11; i++) | ||||
| 		values_to_save[i] = | ||||
| 			read_radio_reg(pi, rxiq_cal_rf_reg[i]); | ||||
| 	Core1TxControl_old = read_phy_reg(pi, 0x631); | ||||
| 		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi); | ||||
| 		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); | ||||
| 
 | ||||
| 	or_phy_reg(pi, 0x631, 0x0015); | ||||
| 		for (i = 0; i < 11; i++) | ||||
| 			values_to_save[i] = | ||||
| 				read_radio_reg(pi, rxiq_cal_rf_reg[i]); | ||||
| 		Core1TxControl_old = read_phy_reg(pi, 0x631); | ||||
| 
 | ||||
| 	RFOverride0_old = read_phy_reg(pi, 0x44c); | ||||
| 	RFOverrideVal0_old = read_phy_reg(pi, 0x44d); | ||||
| 	rfoverride2_old = read_phy_reg(pi, 0x4b0); | ||||
| 	rfoverride2val_old = read_phy_reg(pi, 0x4b1); | ||||
| 	rfoverride3_old = read_phy_reg(pi, 0x4f9); | ||||
| 	rfoverride3val_old = read_phy_reg(pi, 0x4fa); | ||||
| 	rfoverride4_old = read_phy_reg(pi, 0x938); | ||||
| 	rfoverride4val_old = read_phy_reg(pi, 0x939); | ||||
| 	afectrlovr_old = read_phy_reg(pi, 0x43b); | ||||
| 	afectrlovrval_old = read_phy_reg(pi, 0x43c); | ||||
| 	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | ||||
| 	old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); | ||||
| 		or_phy_reg(pi, 0x631, 0x0015); | ||||
| 
 | ||||
| 	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); | ||||
| 	if (tx_gain_override_old) { | ||||
| 		wlc_lcnphy_get_tx_gain(pi, &old_gains); | ||||
| 		tx_gain_index_old = pi_lcn->lcnphy_current_index; | ||||
| 	} | ||||
| 		RFOverride0_old = read_phy_reg(pi, 0x44c); | ||||
| 		RFOverrideVal0_old = read_phy_reg(pi, 0x44d); | ||||
| 		rfoverride2_old = read_phy_reg(pi, 0x4b0); | ||||
| 		rfoverride2val_old = read_phy_reg(pi, 0x4b1); | ||||
| 		rfoverride3_old = read_phy_reg(pi, 0x4f9); | ||||
| 		rfoverride3val_old = read_phy_reg(pi, 0x4fa); | ||||
| 		rfoverride4_old = read_phy_reg(pi, 0x938); | ||||
| 		rfoverride4val_old = read_phy_reg(pi, 0x939); | ||||
| 		afectrlovr_old = read_phy_reg(pi, 0x43b); | ||||
| 		afectrlovrval_old = read_phy_reg(pi, 0x43c); | ||||
| 		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da); | ||||
| 		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db); | ||||
| 
 | ||||
| 	wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); | ||||
| 	mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); | ||||
| 	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); | ||||
| 
 | ||||
| 	write_radio_reg(pi, RADIO_2064_REG116, 0x06); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG12C, 0x07); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG098, 0x03); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG00B, 0x7); | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG01D, 0x01); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG114, 0x01); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG02E, 0x10); | ||||
| 	write_radio_reg(pi, RADIO_2064_REG12A, 0x08); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); | ||||
| 	mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); | ||||
| 	mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); | ||||
| 	mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); | ||||
| 	mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); | ||||
| 	mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); | ||||
| 	mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); | ||||
| 	mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); | ||||
| 	mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); | ||||
| 	mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); | ||||
| 	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); | ||||
| 
 | ||||
| 	write_phy_reg(pi, 0x6da, 0xffff); | ||||
| 	or_phy_reg(pi, 0x6db, 0x3); | ||||
| 
 | ||||
| 	wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); | ||||
| 	set_gain = false; | ||||
| 
 | ||||
| 	lna2_gain = 3; | ||||
| 	while ((lna2_gain >= 0) && !set_gain) { | ||||
| 		tia_gain = 4; | ||||
| 
 | ||||
| 		while ((tia_gain >= 0) && !set_gain) { | ||||
| 			biq1_gain = 6; | ||||
| 
 | ||||
| 			while ((biq1_gain >= 0) && !set_gain) { | ||||
| 				set_gain = wlc_lcnphy_rx_iq_cal_gain(pi, | ||||
| 								     (u16) | ||||
| 								     biq1_gain, | ||||
| 								     (u16) | ||||
| 								     tia_gain, | ||||
| 								     (u16) | ||||
| 								     lna2_gain); | ||||
| 				biq1_gain -= 1; | ||||
| 			} | ||||
| 			tia_gain -= 1; | ||||
| 		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi); | ||||
| 		if (tx_gain_override_old) { | ||||
| 			wlc_lcnphy_get_tx_gain(pi, &old_gains); | ||||
| 			tx_gain_index_old = pi_lcn->lcnphy_current_index; | ||||
| 		} | ||||
| 		lna2_gain -= 1; | ||||
| 
 | ||||
| 		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx); | ||||
| 
 | ||||
| 		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0); | ||||
| 		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0); | ||||
| 
 | ||||
| 		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1); | ||||
| 		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1); | ||||
| 
 | ||||
| 		write_radio_reg(pi, RADIO_2064_REG116, 0x06); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG12C, 0x07); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG098, 0x03); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG00B, 0x7); | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG01D, 0x01); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG114, 0x01); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG02E, 0x10); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG12A, 0x08); | ||||
| 
 | ||||
| 		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0); | ||||
| 		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0); | ||||
| 		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1); | ||||
| 		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1); | ||||
| 		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2); | ||||
| 		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2); | ||||
| 		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3); | ||||
| 		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3); | ||||
| 		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5); | ||||
| 		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5); | ||||
| 
 | ||||
| 		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0); | ||||
| 		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0); | ||||
| 
 | ||||
| 		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0); | ||||
| 		write_phy_reg(pi, 0x6da, 0xffff); | ||||
| 		or_phy_reg(pi, 0x6db, 0x3); | ||||
| 		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch); | ||||
| 		wlc_lcnphy_rx_gain_override_enable(pi, true); | ||||
| 
 | ||||
| 		tia_gain = 8; | ||||
| 		rx_pwr_threshold = 950; | ||||
| 		while (tia_gain > 0) { | ||||
| 			tia_gain -= 1; | ||||
| 			wlc_lcnphy_set_rx_gain_by_distribution(pi, | ||||
| 							       0, 0, 2, 2, | ||||
| 							       (u16) | ||||
| 							       tia_gain, 1, 0); | ||||
| 			udelay(500); | ||||
| 
 | ||||
| 			received_power = | ||||
| 				wlc_lcnphy_measure_digital_power(pi, 2000); | ||||
| 			if (received_power < rx_pwr_threshold) | ||||
| 				break; | ||||
| 		} | ||||
| 		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff); | ||||
| 
 | ||||
| 		wlc_lcnphy_stop_tx_tone(pi); | ||||
| 
 | ||||
| 		write_phy_reg(pi, 0x631, Core1TxControl_old); | ||||
| 
 | ||||
| 		write_phy_reg(pi, 0x44c, RFOverrideVal0_old); | ||||
| 		write_phy_reg(pi, 0x44d, RFOverrideVal0_old); | ||||
| 		write_phy_reg(pi, 0x4b0, rfoverride2_old); | ||||
| 		write_phy_reg(pi, 0x4b1, rfoverride2val_old); | ||||
| 		write_phy_reg(pi, 0x4f9, rfoverride3_old); | ||||
| 		write_phy_reg(pi, 0x4fa, rfoverride3val_old); | ||||
| 		write_phy_reg(pi, 0x938, rfoverride4_old); | ||||
| 		write_phy_reg(pi, 0x939, rfoverride4val_old); | ||||
| 		write_phy_reg(pi, 0x43b, afectrlovr_old); | ||||
| 		write_phy_reg(pi, 0x43c, afectrlovrval_old); | ||||
| 		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); | ||||
| 		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); | ||||
| 
 | ||||
| 		wlc_lcnphy_clear_trsw_override(pi); | ||||
| 
 | ||||
| 		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); | ||||
| 
 | ||||
| 		for (i = 0; i < 11; i++) | ||||
| 			write_radio_reg(pi, rxiq_cal_rf_reg[i], | ||||
| 					values_to_save[i]); | ||||
| 
 | ||||
| 		if (tx_gain_override_old) | ||||
| 			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); | ||||
| 		else | ||||
| 			wlc_lcnphy_disable_tx_gain_override(pi); | ||||
| 
 | ||||
| 		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); | ||||
| 		wlc_lcnphy_rx_gain_override_enable(pi, false); | ||||
| 	} | ||||
| 
 | ||||
| 	if (set_gain) | ||||
| 		result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024); | ||||
| 	else | ||||
| 		result = false; | ||||
| 
 | ||||
| 	wlc_lcnphy_stop_tx_tone(pi); | ||||
| 
 | ||||
| 	write_phy_reg(pi, 0x631, Core1TxControl_old); | ||||
| 
 | ||||
| 	write_phy_reg(pi, 0x44c, RFOverrideVal0_old); | ||||
| 	write_phy_reg(pi, 0x44d, RFOverrideVal0_old); | ||||
| 	write_phy_reg(pi, 0x4b0, rfoverride2_old); | ||||
| 	write_phy_reg(pi, 0x4b1, rfoverride2val_old); | ||||
| 	write_phy_reg(pi, 0x4f9, rfoverride3_old); | ||||
| 	write_phy_reg(pi, 0x4fa, rfoverride3val_old); | ||||
| 	write_phy_reg(pi, 0x938, rfoverride4_old); | ||||
| 	write_phy_reg(pi, 0x939, rfoverride4val_old); | ||||
| 	write_phy_reg(pi, 0x43b, afectrlovr_old); | ||||
| 	write_phy_reg(pi, 0x43c, afectrlovrval_old); | ||||
| 	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl); | ||||
| 	write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl); | ||||
| 
 | ||||
| 	wlc_lcnphy_clear_trsw_override(pi); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2); | ||||
| 
 | ||||
| 	for (i = 0; i < 11; i++) | ||||
| 		write_radio_reg(pi, rxiq_cal_rf_reg[i], | ||||
| 				values_to_save[i]); | ||||
| 
 | ||||
| 	if (tx_gain_override_old) | ||||
| 		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old); | ||||
| 	else | ||||
| 		wlc_lcnphy_disable_tx_gain_override(pi); | ||||
| 
 | ||||
| 	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl); | ||||
| 	wlc_lcnphy_rx_gain_override_enable(pi, false); | ||||
| 
 | ||||
| cal_done: | ||||
| 	kfree(ptr); | ||||
| 	return result; | ||||
| @ -1837,17 +1789,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel) | ||||
| 		write_radio_reg(pi, RADIO_2064_REG038, 3); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG091, 7); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!(pi->sh->boardflags & BFL_FEM)) { | ||||
| 		u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc, | ||||
| 			0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0}; | ||||
| 
 | ||||
| 		write_radio_reg(pi, RADIO_2064_REG02A, 0xf); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG091, 0x3); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG038, 0x3); | ||||
| 
 | ||||
| 		write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| @ -2042,16 +1983,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos) | ||||
| 		} else { | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1); | ||||
| 			mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4); | ||||
| 		} | ||||
| 	} else { | ||||
| 		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2); | ||||
| @ -2138,14 +2069,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi) | ||||
| 		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12)); | ||||
| 
 | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5)); | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0)); | ||||
| } | ||||
| 
 | ||||
| static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | ||||
| { | ||||
| 	struct phytbl_info tab; | ||||
| 	u32 rfseq, ind; | ||||
| 	u8 tssi_sel; | ||||
| 
 | ||||
| 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; | ||||
| 	tab.tbl_width = 32; | ||||
| @ -2167,13 +2096,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4); | ||||
| 
 | ||||
| 	if (pi->sh->boardflags & BFL_FEM) { | ||||
| 		tssi_sel = 0x1; | ||||
| 		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); | ||||
| 	} else { | ||||
| 		tssi_sel = 0xe; | ||||
| 		wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA); | ||||
| 	} | ||||
| 	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT); | ||||
| 	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15); | ||||
| @ -2209,10 +2132,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | ||||
| 	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0); | ||||
| 
 | ||||
| 	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) { | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel); | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe); | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4); | ||||
| 	} else { | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1); | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1); | ||||
| 		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3); | ||||
| 	} | ||||
| @ -2259,10 +2181,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi) | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8); | ||||
| 
 | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0); | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0); | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8); | ||||
| 
 | ||||
| 	wlc_lcnphy_pwrctrl_rssiparams(pi); | ||||
| } | ||||
| 
 | ||||
| @ -2881,8 +2799,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | ||||
| 		read_radio_reg(pi, RADIO_2064_REG007) & 1; | ||||
| 	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10; | ||||
| 	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4; | ||||
| 	u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi); | ||||
| 
 | ||||
| 	idleTssi = read_phy_reg(pi, 0x4ab); | ||||
| 	suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) & | ||||
| 			 MCTL_EN_MAC)); | ||||
| @ -2900,12 +2816,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4); | ||||
| 	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2); | ||||
| 	wlc_lcnphy_tssi_setup(pi); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0)); | ||||
| 	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6)); | ||||
| 
 | ||||
| 	wlc_lcnphy_set_bbmult(pi, 0x0); | ||||
| 
 | ||||
| 	wlc_phy_do_dummy_tx(pi, true, OFF); | ||||
| 	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0)) | ||||
| 		    >> 0); | ||||
| @ -2927,7 +2837,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi) | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12); | ||||
| 
 | ||||
| 	wlc_lcnphy_set_bbmult(pi, SAVE_bbmult); | ||||
| 	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old); | ||||
| 	wlc_lcnphy_set_tx_gain(pi, &old_gains); | ||||
| 	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl); | ||||
| @ -3141,11 +3050,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi) | ||||
| 			wlc_lcnphy_write_table(pi, &tab); | ||||
| 			tab.tbl_offset++; | ||||
| 		} | ||||
| 		mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0); | ||||
| 		mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0); | ||||
| 		mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8); | ||||
| 		mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4); | ||||
| 		mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2); | ||||
| 
 | ||||
| 		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7); | ||||
| 
 | ||||
| @ -3947,6 +3851,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) | ||||
| 	target_gains.pad_gain = 21; | ||||
| 	target_gains.dac_gain = 0; | ||||
| 	wlc_lcnphy_set_tx_gain(pi, &target_gains); | ||||
| 	wlc_lcnphy_set_tx_pwr_by_index(pi, 16); | ||||
| 
 | ||||
| 	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) { | ||||
| 
 | ||||
| @ -3957,7 +3862,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi) | ||||
| 					lcnphy_recal ? LCNPHY_CAL_RECAL : | ||||
| 					LCNPHY_CAL_FULL), false); | ||||
| 	} else { | ||||
| 		wlc_lcnphy_set_tx_pwr_by_index(pi, 16); | ||||
| 		wlc_lcnphy_tx_iqlo_soft_cal_full(pi); | ||||
| 	} | ||||
| 
 | ||||
| @ -4382,22 +4286,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi, | ||||
| 	if (CHSPEC_IS5G(pi->radio_chanspec)) | ||||
| 		pa_gain = 0x70; | ||||
| 	else | ||||
| 		pa_gain = 0x60; | ||||
| 		pa_gain = 0x70; | ||||
| 
 | ||||
| 	if (pi->sh->boardflags & BFL_FEM) | ||||
| 		pa_gain = 0x10; | ||||
| 
 | ||||
| 	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL; | ||||
| 	tab.tbl_width = 32; | ||||
| 	tab.tbl_len = 1; | ||||
| 	tab.tbl_ptr = &val; | ||||
| 
 | ||||
| 	for (j = 0; j < 128; j++) { | ||||
| 		if (pi->sh->boardflags & BFL_FEM) | ||||
| 			gm_gain = gain_table[j].gm; | ||||
| 		else | ||||
| 			gm_gain = 15; | ||||
| 
 | ||||
| 		gm_gain = gain_table[j].gm; | ||||
| 		val = (((u32) pa_gain << 24) | | ||||
| 		       (gain_table[j].pad << 16) | | ||||
| 		       (gain_table[j].pga << 8) | gm_gain); | ||||
| @ -4608,10 +4507,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) | ||||
| 
 | ||||
| 	write_phy_reg(pi, 0x4ea, 0x4688); | ||||
| 
 | ||||
| 	if (pi->sh->boardflags & BFL_FEM) | ||||
| 		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); | ||||
| 	else | ||||
| 		mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0); | ||||
| 	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6); | ||||
| 
 | ||||
| @ -4622,13 +4518,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi) | ||||
| 	wlc_lcnphy_rcal(pi); | ||||
| 
 | ||||
| 	wlc_lcnphy_rc_cal(pi); | ||||
| 
 | ||||
| 	if (!(pi->sh->boardflags & BFL_FEM)) { | ||||
| 		write_radio_reg(pi, RADIO_2064_REG032, 0x6f); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG033, 0x19); | ||||
| 		write_radio_reg(pi, RADIO_2064_REG039, 0xe); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void wlc_lcnphy_radio_init(struct brcms_phy *pi) | ||||
| @ -4658,20 +4547,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi) | ||||
| 		wlc_lcnphy_write_table(pi, &tab); | ||||
| 	} | ||||
| 
 | ||||
| 	if (!(pi->sh->boardflags & BFL_FEM)) { | ||||
| 		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; | ||||
| 		tab.tbl_width = 16; | ||||
| 		tab.tbl_ptr = &val; | ||||
| 		tab.tbl_len = 1; | ||||
| 	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ; | ||||
| 	tab.tbl_width = 16; | ||||
| 	tab.tbl_ptr = &val; | ||||
| 	tab.tbl_len = 1; | ||||
| 
 | ||||
| 		val = 150; | ||||
| 		tab.tbl_offset = 0; | ||||
| 		wlc_lcnphy_write_table(pi, &tab); | ||||
| 	val = 114; | ||||
| 	tab.tbl_offset = 0; | ||||
| 	wlc_lcnphy_write_table(pi, &tab); | ||||
| 
 | ||||
| 		val = 220; | ||||
| 		tab.tbl_offset = 1; | ||||
| 		wlc_lcnphy_write_table(pi, &tab); | ||||
| 	} | ||||
| 	val = 130; | ||||
| 	tab.tbl_offset = 1; | ||||
| 	wlc_lcnphy_write_table(pi, &tab); | ||||
| 
 | ||||
| 	val = 6; | ||||
| 	tab.tbl_offset = 8; | ||||
| 	wlc_lcnphy_write_table(pi, &tab); | ||||
| 
 | ||||
| 	if (CHSPEC_IS2G(pi->radio_chanspec)) { | ||||
| 		if (pi->sh->boardflags & BFL_FEM) | ||||
| @ -5064,7 +4955,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec) | ||||
| 		wlc_lcnphy_load_tx_iir_filter(pi, true, 3); | ||||
| 
 | ||||
| 	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3); | ||||
| 	wlc_lcnphy_tssi_setup(pi); | ||||
| } | ||||
| 
 | ||||
| void wlc_phy_detach_lcnphy(struct brcms_phy *pi) | ||||
| @ -5103,7 +4993,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi) | ||||
| 	if (!wlc_phy_txpwr_srom_read_lcnphy(pi)) | ||||
| 		return false; | ||||
| 
 | ||||
| 	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) { | ||||
| 	if ((pi->sh->boardflags & BFL_FEM) && | ||||
| 	    (LCNREV_IS(pi->pubpi.phy_rev, 1))) { | ||||
| 		if (pi_lcn->lcnphy_tempsense_option == 3) { | ||||
| 			pi->hwpwrctrl = true; | ||||
| 			pi->hwpwrctrl_capable = true; | ||||
|  | ||||
| @ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = { | ||||
| }; | ||||
| 
 | ||||
| static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = { | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x000a, | ||||
| 	0x0005, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| 	0x000a, | ||||
| 	0x0009, | ||||
| 	0x0006, | ||||
| 	0x0005, | ||||
| }; | ||||
| 
 | ||||
| static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = { | ||||
|  | ||||
| @ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il, | ||||
| 	dma_addr_t txcmd_phys; | ||||
| 	int txq_id = skb_get_queue_mapping(skb); | ||||
| 	u16 len, idx, hdr_len; | ||||
| 	u16 firstlen, secondlen; | ||||
| 	u8 id; | ||||
| 	u8 unicast; | ||||
| 	u8 sta_id; | ||||
| @ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il, | ||||
| 	len = | ||||
| 	    sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) + | ||||
| 	    hdr_len; | ||||
| 	len = (len + 3) & ~3; | ||||
| 	firstlen = (len + 3) & ~3; | ||||
| 
 | ||||
| 	/* Physical address of this Tx command's header (not MAC header!),
 | ||||
| 	 * within command buffer array. */ | ||||
| 	txcmd_phys = | ||||
| 	    pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE); | ||||
| 	    pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen, | ||||
| 			   PCI_DMA_TODEVICE); | ||||
| 	if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) | ||||
| 		goto drop_unlock; | ||||
| 
 | ||||
| 	/* Set up TFD's 2nd entry to point directly to remainder of skb,
 | ||||
| 	 * if any (802.11 null frames have no payload). */ | ||||
| 	len = skb->len - hdr_len; | ||||
| 	if (len) { | ||||
| 	secondlen = skb->len - hdr_len; | ||||
| 	if (secondlen > 0) { | ||||
| 		phys_addr = | ||||
| 		    pci_map_single(il->pci_dev, skb->data + hdr_len, len, | ||||
| 		    pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, | ||||
| 				   PCI_DMA_TODEVICE); | ||||
| 		if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) | ||||
| 			goto drop_unlock; | ||||
| @ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il, | ||||
| 
 | ||||
| 	/* Add buffer containing Tx command and MAC(!) header to TFD's
 | ||||
| 	 * first entry */ | ||||
| 	il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); | ||||
| 	il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); | ||||
| 	dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||||
| 	dma_unmap_len_set(out_meta, len, len); | ||||
| 	if (len) | ||||
| 		il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, | ||||
| 					       U32_PAD(len)); | ||||
| 	dma_unmap_len_set(out_meta, len, firstlen); | ||||
| 	if (secondlen > 0) | ||||
| 		il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, 0, | ||||
| 					       U32_PAD(secondlen)); | ||||
| 
 | ||||
| 	if (!ieee80211_has_morefrags(hdr->frame_control)) { | ||||
| 		txq->need_update = 1; | ||||
|  | ||||
| @ -2152,7 +2152,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, | ||||
| 	int rate_idx; | ||||
| 	int i; | ||||
| 	u32 rate; | ||||
| 	u8 use_green = il4965_rs_use_green(il, sta); | ||||
| 	u8 use_green; | ||||
| 	u8 active_tbl = 0; | ||||
| 	u8 valid_tx_ant; | ||||
| 	struct il_station_priv *sta_priv; | ||||
| @ -2160,6 +2160,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf, | ||||
| 	if (!sta || !lq_sta) | ||||
| 		return; | ||||
| 
 | ||||
| 	use_green = il4965_rs_use_green(il, sta); | ||||
| 	sta_priv = (void *)sta->drv_priv; | ||||
| 
 | ||||
| 	i = lq_sta->last_txrate_idx; | ||||
|  | ||||
| @ -1261,6 +1261,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | ||||
| 		return -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag | ||||
| 	 * in iwl_down but cancel the workers only later. | ||||
| 	 */ | ||||
| 	if (!priv->ucode_loaded) { | ||||
| 		IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id); | ||||
| 		return -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Synchronous commands from this op-mode must hold | ||||
| 	 * the mutex, this ensures we don't try to send two | ||||
|  | ||||
| @ -367,6 +367,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | ||||
| 		return -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	priv->ucode_loaded = true; | ||||
| 
 | ||||
| 	if (ucode_type != IWL_UCODE_WOWLAN) { | ||||
| 		/* delay a bit to give rfkill time to run */ | ||||
| 		msleep(5); | ||||
| @ -380,8 +382,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv, | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	priv->ucode_loaded = true; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -475,6 +475,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | ||||
| 
 | ||||
| 	/* If platform's RF_KILL switch is NOT set to KILL */ | ||||
| 	hw_rfkill = iwl_is_rfkill_set(trans); | ||||
| 	if (hw_rfkill) | ||||
| 		set_bit(STATUS_RFKILL, &trans_pcie->status); | ||||
| 	else | ||||
| 		clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||||
| 	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | ||||
| 	if (hw_rfkill && !run_in_rfkill) | ||||
| 		return -ERFKILL; | ||||
| @ -641,6 +645,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | ||||
| 
 | ||||
| static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | ||||
| { | ||||
| 	struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||||
| 	bool hw_rfkill; | ||||
| 	int err; | ||||
| 
 | ||||
| @ -656,6 +661,10 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) | ||||
| 	iwl_enable_rfkill_int(trans); | ||||
| 
 | ||||
| 	hw_rfkill = iwl_is_rfkill_set(trans); | ||||
| 	if (hw_rfkill) | ||||
| 		set_bit(STATUS_RFKILL, &trans_pcie->status); | ||||
| 	else | ||||
| 		clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||||
| 	iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | ||||
| 
 | ||||
| 	return 0; | ||||
| @ -694,6 +703,10 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans, | ||||
| 		 * op_mode. | ||||
| 		 */ | ||||
| 		hw_rfkill = iwl_is_rfkill_set(trans); | ||||
| 		if (hw_rfkill) | ||||
| 			set_bit(STATUS_RFKILL, &trans_pcie->status); | ||||
| 		else | ||||
| 			clear_bit(STATUS_RFKILL, &trans_pcie->status); | ||||
| 		iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -1264,7 +1264,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | ||||
| 	for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { | ||||
| 		int copy = 0; | ||||
| 
 | ||||
| 		if (!cmd->len) | ||||
| 		if (!cmd->len[i]) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ | ||||
|  | ||||
| @ -157,6 +157,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	cmd_code = le16_to_cpu(host_cmd->command); | ||||
| 	cmd_size = le16_to_cpu(host_cmd->size); | ||||
| 
 | ||||
| 	if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET && | ||||
| 	    cmd_code != HostCmd_CMD_FUNC_SHUTDOWN && | ||||
| 	    cmd_code != HostCmd_CMD_FUNC_INIT) { | ||||
| 		dev_err(adapter->dev, | ||||
| 			"DNLD_CMD: FW in reset state, ignore cmd %#x\n", | ||||
| 			cmd_code); | ||||
| 		mwifiex_complete_cmd(adapter, cmd_node); | ||||
| 		mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set command sequence number */ | ||||
| 	adapter->seq_num++; | ||||
| 	host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO | ||||
| @ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | ||||
| 	adapter->curr_cmd = cmd_node; | ||||
| 	spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | ||||
| 
 | ||||
| 	cmd_code = le16_to_cpu(host_cmd->command); | ||||
| 	cmd_size = le16_to_cpu(host_cmd->size); | ||||
| 
 | ||||
| 	/* Adjust skb length */ | ||||
| 	if (cmd_node->cmd_skb->len > cmd_size) | ||||
| 		/*
 | ||||
| @ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | ||||
| 
 | ||||
| 	ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, | ||||
| 				     data_buf); | ||||
| 	if (!ret) | ||||
| 		ret = mwifiex_wait_queue_complete(adapter); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| @ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | ||||
| 	if (cmd_no == HostCmd_CMD_802_11_SCAN) { | ||||
| 		mwifiex_queue_scan_cmd(priv, cmd_node); | ||||
| 	} else { | ||||
| 		adapter->cmd_queued = cmd_node; | ||||
| 		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | ||||
| 		queue_work(adapter->workqueue, &adapter->main_work); | ||||
| 		if (cmd_node->wait_q_enabled) | ||||
| 			ret = mwifiex_wait_queue_complete(adapter, cmd_node); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
|  | ||||
| @ -709,6 +709,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* cancel current command */ | ||||
| 	if (adapter->curr_cmd) { | ||||
| 		dev_warn(adapter->dev, "curr_cmd is still in processing\n"); | ||||
| 		del_timer(&adapter->cmd_timer); | ||||
| 		mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | ||||
| 		adapter->curr_cmd = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	/* shut down mwifiex */ | ||||
| 	dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); | ||||
| 
 | ||||
|  | ||||
| @ -728,7 +728,6 @@ struct mwifiex_adapter { | ||||
| 	u16 cmd_wait_q_required; | ||||
| 	struct mwifiex_wait_queue cmd_wait_q; | ||||
| 	u8 scan_wait_q_woken; | ||||
| 	struct cmd_ctrl_node *cmd_queued; | ||||
| 	spinlock_t queue_lock;		/* lock for tx queues */ | ||||
| 	struct completion fw_load; | ||||
| 	u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | ||||
| @ -1029,7 +1028,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | ||||
| 			struct mwifiex_multicast_list *mcast_list); | ||||
| int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | ||||
| 			    struct net_device *dev); | ||||
| int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); | ||||
| int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, | ||||
| 				struct cmd_ctrl_node *cmd_queued); | ||||
| int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | ||||
| 		      struct cfg80211_ssid *req_ssid); | ||||
| int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); | ||||
|  | ||||
| @ -1519,6 +1519,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) | ||||
| 		} | ||||
| 		memcpy(adapter->upld_buf, skb->data, | ||||
| 		       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); | ||||
| 		skb_push(skb, INTF_HEADER_LEN); | ||||
| 		if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, | ||||
| 					   PCI_DMA_FROMDEVICE)) | ||||
| 			return -1; | ||||
|  | ||||
| @ -1388,10 +1388,13 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | ||||
| 			list_del(&cmd_node->list); | ||||
| 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||||
| 					       flags); | ||||
| 			adapter->cmd_queued = cmd_node; | ||||
| 			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | ||||
| 							true); | ||||
| 			queue_work(adapter->workqueue, &adapter->main_work); | ||||
| 
 | ||||
| 			/* Perform internal scan synchronously */ | ||||
| 			if (!priv->scan_request) | ||||
| 				mwifiex_wait_queue_complete(adapter, cmd_node); | ||||
| 		} else { | ||||
| 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||||
| 					       flags); | ||||
| @ -1946,9 +1949,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv, | ||||
| 		/* Normal scan */ | ||||
| 		ret = mwifiex_scan_networks(priv, NULL); | ||||
| 
 | ||||
| 	if (!ret) | ||||
| 		ret = mwifiex_wait_queue_complete(priv->adapter); | ||||
| 
 | ||||
| 	up(&priv->async_sem); | ||||
| 
 | ||||
| 	return ret; | ||||
|  | ||||
| @ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | ||||
|  * This function waits on a cmd wait queue. It also cancels the pending | ||||
|  * request after waking up, in case of errors. | ||||
|  */ | ||||
| int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | ||||
| int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, | ||||
| 				struct cmd_ctrl_node *cmd_queued) | ||||
| { | ||||
| 	int status; | ||||
| 	struct cmd_ctrl_node *cmd_queued; | ||||
| 
 | ||||
| 	if (!adapter->cmd_queued) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	cmd_queued = adapter->cmd_queued; | ||||
| 	adapter->cmd_queued = NULL; | ||||
| 
 | ||||
| 	dev_dbg(adapter->dev, "cmd pending\n"); | ||||
| 	atomic_inc(&adapter->cmd_pending); | ||||
|  | ||||
| @ -932,6 +932,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, | ||||
| 	if (unlikely(!_urb)) { | ||||
| 		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||||
| 			 "Can't allocate urb. Drop skb!\n"); | ||||
| 		kfree_skb(skb); | ||||
| 		return; | ||||
| 	} | ||||
| 	_rtl_submit_tx_urb(hw, _urb); | ||||
|  | ||||
| @ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk) | ||||
| 			sco_chan_del(sk, ECONNRESET); | ||||
| 		break; | ||||
| 
 | ||||
| 	case BT_CONNECT2: | ||||
| 	case BT_CONNECT: | ||||
| 	case BT_DISCONN: | ||||
| 		sco_chan_del(sk, ECONNRESET); | ||||
|  | ||||
| @ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) | ||||
| static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | ||||
| { | ||||
| 	struct ieee80211_sub_if_data *sdata; | ||||
| 	int ret = 0; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	mutex_lock(&local->iflist_mtx); | ||||
| 	ASSERT_RTNL(); | ||||
| 
 | ||||
| 	if (local->monitor_sdata) | ||||
| 		goto out_unlock; | ||||
| 		return 0; | ||||
| 
 | ||||
| 	sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); | ||||
| 	if (!sdata) { | ||||
| 		ret = -ENOMEM; | ||||
| 		goto out_unlock; | ||||
| 	} | ||||
| 	if (!sdata) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	/* set up data */ | ||||
| 	sdata->local = local; | ||||
| @ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | ||||
| 	if (WARN_ON(ret)) { | ||||
| 		/* ok .. stupid driver, it asked for this! */ | ||||
| 		kfree(sdata); | ||||
| 		goto out_unlock; | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = ieee80211_check_queues(sdata); | ||||
| 	if (ret) { | ||||
| 		kfree(sdata); | ||||
| 		goto out_unlock; | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, | ||||
| @ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | ||||
| 	if (ret) { | ||||
| 		drv_remove_interface(local, sdata); | ||||
| 		kfree(sdata); | ||||
| 		goto out_unlock; | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_lock(&local->iflist_mtx); | ||||
| 	rcu_assign_pointer(local->monitor_sdata, sdata); | ||||
|  out_unlock: | ||||
| 	mutex_unlock(&local->iflist_mtx); | ||||
| 	return ret; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | ||||
| @ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | ||||
| 	if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) | ||||
| 		return; | ||||
| 
 | ||||
| 	ASSERT_RTNL(); | ||||
| 
 | ||||
| 	mutex_lock(&local->iflist_mtx); | ||||
| 
 | ||||
| 	sdata = rcu_dereference_protected(local->monitor_sdata, | ||||
| 					  lockdep_is_held(&local->iflist_mtx)); | ||||
| 	if (!sdata) | ||||
| 		goto out_unlock; | ||||
| 	if (!sdata) { | ||||
| 		mutex_unlock(&local->iflist_mtx); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	rcu_assign_pointer(local->monitor_sdata, NULL); | ||||
| 	mutex_unlock(&local->iflist_mtx); | ||||
| 
 | ||||
| 	synchronize_net(); | ||||
| 
 | ||||
| 	ieee80211_vif_release_channel(sdata); | ||||
| @ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | ||||
| 	drv_remove_interface(local, sdata); | ||||
| 
 | ||||
| 	kfree(sdata); | ||||
|  out_unlock: | ||||
| 	mutex_unlock(&local->iflist_mtx); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | ||||
| @ -1004,7 +1004,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||||
| 		if (ieee80211_vif_is_mesh(&sdata->vif)) | ||||
| 		if (ieee80211_vif_is_mesh(&sdata->vif) && | ||||
| 		    ieee80211_sdata_running(sdata)) | ||||
| 			ieee80211_queue_work(&local->hw, &sdata->work); | ||||
| 	rcu_read_unlock(); | ||||
| } | ||||
|  | ||||
| @ -3531,8 +3531,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | ||||
| 
 | ||||
| 	/* Restart STA timers */ | ||||
| 	rcu_read_lock(); | ||||
| 	list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||||
| 		ieee80211_restart_sta_timer(sdata); | ||||
| 	list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||||
| 		if (ieee80211_sdata_running(sdata)) | ||||
| 			ieee80211_restart_sta_timer(sdata); | ||||
| 	} | ||||
| 	rcu_read_unlock(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -2666,7 +2666,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) | ||||
| 
 | ||||
| 		memset(nskb->cb, 0, sizeof(nskb->cb)); | ||||
| 
 | ||||
| 		ieee80211_tx_skb(rx->sdata, nskb); | ||||
| 		if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||||
| 			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb); | ||||
| 
 | ||||
| 			info->flags = IEEE80211_TX_CTL_TX_OFFCHAN | | ||||
| 				      IEEE80211_TX_INTFL_OFFCHAN_TX_OK | | ||||
| 				      IEEE80211_TX_CTL_NO_CCK_RATE; | ||||
| 			if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) | ||||
| 				info->hw_queue = | ||||
| 					local->hw.offchannel_tx_hw_queue; | ||||
| 		} | ||||
| 
 | ||||
| 		__ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7, | ||||
| 					    status->band); | ||||
| 	} | ||||
| 	dev_kfree_skb(rx->skb); | ||||
| 	return RX_QUEUED; | ||||
|  | ||||
| @ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) | ||||
| 	rdev_rfkill_poll(rdev); | ||||
| } | ||||
| 
 | ||||
| void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||||
| 			      struct wireless_dev *wdev) | ||||
| { | ||||
| 	lockdep_assert_held(&rdev->devlist_mtx); | ||||
| 	lockdep_assert_held(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (!wdev->p2p_started) | ||||
| 		return; | ||||
| 
 | ||||
| 	rdev_stop_p2p_device(rdev, wdev); | ||||
| 	wdev->p2p_started = false; | ||||
| 
 | ||||
| 	rdev->opencount--; | ||||
| 
 | ||||
| 	if (rdev->scan_req && rdev->scan_req->wdev == wdev) { | ||||
| 		bool busy = work_busy(&rdev->scan_done_wk); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * If the work isn't pending or running (in which case it would | ||||
| 		 * be waiting for the lock we hold) the driver didn't properly | ||||
| 		 * cancel the scan when the interface was removed. In this case | ||||
| 		 * warn and leak the scan request object to not crash later. | ||||
| 		 */ | ||||
| 		WARN_ON(!busy); | ||||
| 
 | ||||
| 		rdev->scan_req->aborted = true; | ||||
| 		___cfg80211_scan_done(rdev, !busy); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int cfg80211_rfkill_set_block(void *data, bool blocked) | ||||
| { | ||||
| 	struct cfg80211_registered_device *rdev = data; | ||||
| @ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	rtnl_lock(); | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 
 | ||||
| 	/* read-only iteration need not hold the devlist_mtx */ | ||||
| 
 | ||||
| 	list_for_each_entry(wdev, &rdev->wdev_list, list) { | ||||
| 		if (wdev->netdev) { | ||||
| @ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | ||||
| 		/* otherwise, check iftype */ | ||||
| 		switch (wdev->iftype) { | ||||
| 		case NL80211_IFTYPE_P2P_DEVICE: | ||||
| 			if (!wdev->p2p_started) | ||||
| 				break; | ||||
| 			rdev_stop_p2p_device(rdev, wdev); | ||||
| 			wdev->p2p_started = false; | ||||
| 			rdev->opencount--; | ||||
| 			/* but this requires it */ | ||||
| 			mutex_lock(&rdev->devlist_mtx); | ||||
| 			mutex_lock(&rdev->sched_scan_mtx); | ||||
| 			cfg80211_stop_p2p_device(rdev, wdev); | ||||
| 			mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 			mutex_unlock(&rdev->devlist_mtx); | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| 	rtnl_unlock(); | ||||
| 
 | ||||
| 	return 0; | ||||
| @ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work) | ||||
| 	wdev = container_of(work, struct wireless_dev, cleanup_work); | ||||
| 	rdev = wiphy_to_dev(wdev->wiphy); | ||||
| 
 | ||||
| 	cfg80211_lock_rdev(rdev); | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||||
| 		rdev->scan_req->aborted = true; | ||||
| 		___cfg80211_scan_done(rdev, true); | ||||
| 	} | ||||
| 
 | ||||
| 	cfg80211_unlock_rdev(rdev); | ||||
| 
 | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	if (WARN_ON(rdev->sched_scan_req && | ||||
| 		    rdev->sched_scan_req->dev == wdev->netdev)) { | ||||
| 		__cfg80211_stop_sched_scan(rdev, false); | ||||
| @ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | ||||
| 		return; | ||||
| 
 | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	list_del_rcu(&wdev->list); | ||||
| 	rdev->devlist_generation++; | ||||
| 
 | ||||
| 	switch (wdev->iftype) { | ||||
| 	case NL80211_IFTYPE_P2P_DEVICE: | ||||
| 		if (!wdev->p2p_started) | ||||
| 			break; | ||||
| 		rdev_stop_p2p_device(rdev, wdev); | ||||
| 		wdev->p2p_started = false; | ||||
| 		rdev->opencount--; | ||||
| 		cfg80211_stop_p2p_device(rdev, wdev); | ||||
| 		break; | ||||
| 	default: | ||||
| 		WARN_ON_ONCE(1); | ||||
| 		break; | ||||
| 	} | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| } | ||||
| EXPORT_SYMBOL(cfg80211_unregister_wdev); | ||||
| @ -945,6 +973,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | ||||
| 		cfg80211_update_iface_num(rdev, wdev->iftype, 1); | ||||
| 		cfg80211_lock_rdev(rdev); | ||||
| 		mutex_lock(&rdev->devlist_mtx); | ||||
| 		mutex_lock(&rdev->sched_scan_mtx); | ||||
| 		wdev_lock(wdev); | ||||
| 		switch (wdev->iftype) { | ||||
| #ifdef CONFIG_CFG80211_WEXT | ||||
| @ -976,6 +1005,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | ||||
| 			break; | ||||
| 		} | ||||
| 		wdev_unlock(wdev); | ||||
| 		mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 		rdev->opencount++; | ||||
| 		mutex_unlock(&rdev->devlist_mtx); | ||||
| 		cfg80211_unlock_rdev(rdev); | ||||
|  | ||||
| @ -503,6 +503,9 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, | ||||
| void cfg80211_leave(struct cfg80211_registered_device *rdev, | ||||
| 		    struct wireless_dev *wdev); | ||||
| 
 | ||||
| void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | ||||
| 			      struct wireless_dev *wdev); | ||||
| 
 | ||||
| #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10 | ||||
| 
 | ||||
| #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | ||||
|  | ||||
| @ -5048,14 +5048,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | ||||
| 	if (!rdev->ops->scan) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (rdev->scan_req) | ||||
| 		return -EBUSY; | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	if (rdev->scan_req) { | ||||
| 		err = -EBUSY; | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | ||||
| 		n_channels = validate_scan_freqs( | ||||
| 				info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | ||||
| 		if (!n_channels) | ||||
| 			return -EINVAL; | ||||
| 		if (!n_channels) { | ||||
| 			err = -EINVAL; | ||||
| 			goto unlock; | ||||
| 		} | ||||
| 	} else { | ||||
| 		enum ieee80211_band band; | ||||
| 		n_channels = 0; | ||||
| @ -5069,23 +5074,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | ||||
| 		nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) | ||||
| 			n_ssids++; | ||||
| 
 | ||||
| 	if (n_ssids > wiphy->max_scan_ssids) | ||||
| 		return -EINVAL; | ||||
| 	if (n_ssids > wiphy->max_scan_ssids) { | ||||
| 		err = -EINVAL; | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	if (info->attrs[NL80211_ATTR_IE]) | ||||
| 		ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||||
| 	else | ||||
| 		ie_len = 0; | ||||
| 
 | ||||
| 	if (ie_len > wiphy->max_scan_ie_len) | ||||
| 		return -EINVAL; | ||||
| 	if (ie_len > wiphy->max_scan_ie_len) { | ||||
| 		err = -EINVAL; | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	request = kzalloc(sizeof(*request) | ||||
| 			+ sizeof(*request->ssids) * n_ssids | ||||
| 			+ sizeof(*request->channels) * n_channels | ||||
| 			+ ie_len, GFP_KERNEL); | ||||
| 	if (!request) | ||||
| 		return -ENOMEM; | ||||
| 	if (!request) { | ||||
| 		err = -ENOMEM; | ||||
| 		goto unlock; | ||||
| 	} | ||||
| 
 | ||||
| 	if (n_ssids) | ||||
| 		request->ssids = (void *)&request->channels[n_channels]; | ||||
| @ -5222,6 +5233,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | ||||
| 		kfree(request); | ||||
| 	} | ||||
| 
 | ||||
|  unlock: | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	return err; | ||||
| } | ||||
| 
 | ||||
| @ -8130,20 +8143,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | ||||
| 	if (!rdev->ops->stop_p2p_device) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	if (!wdev->p2p_started) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	rdev_stop_p2p_device(rdev, wdev); | ||||
| 	wdev->p2p_started = false; | ||||
| 
 | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 	rdev->opencount--; | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| 
 | ||||
| 	if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||||
| 		rdev->scan_req->aborted = true; | ||||
| 		___cfg80211_scan_done(rdev, true); | ||||
| 	} | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	cfg80211_stop_p2p_device(rdev, wdev); | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| @ -8929,7 +8931,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg, | ||||
| 	struct nlattr *nest; | ||||
| 	int i; | ||||
| 
 | ||||
| 	ASSERT_RDEV_LOCK(rdev); | ||||
| 	lockdep_assert_held(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	if (WARN_ON(!req)) | ||||
| 		return 0; | ||||
|  | ||||
| @ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) | ||||
| 	union iwreq_data wrqu; | ||||
| #endif | ||||
| 
 | ||||
| 	ASSERT_RDEV_LOCK(rdev); | ||||
| 	lockdep_assert_held(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	request = rdev->scan_req; | ||||
| 
 | ||||
| @ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk) | ||||
| 	rdev = container_of(wk, struct cfg80211_registered_device, | ||||
| 			    scan_done_wk); | ||||
| 
 | ||||
| 	cfg80211_lock_rdev(rdev); | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	___cfg80211_scan_done(rdev, false); | ||||
| 	cfg80211_unlock_rdev(rdev); | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| } | ||||
| 
 | ||||
| void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | ||||
| @ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | ||||
| 	found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); | ||||
| 
 | ||||
| 	if (found) { | ||||
| 		found->pub.beacon_interval = tmp->pub.beacon_interval; | ||||
| 		found->pub.signal = tmp->pub.signal; | ||||
| 		found->pub.capability = tmp->pub.capability; | ||||
| 		found->ts = tmp->ts; | ||||
| 
 | ||||
| 		/* Update IEs */ | ||||
| 		if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | ||||
| 			const struct cfg80211_bss_ies *old; | ||||
| @ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | ||||
| 
 | ||||
| 			if (found->pub.hidden_beacon_bss && | ||||
| 			    !list_empty(&found->hidden_list)) { | ||||
| 				const struct cfg80211_bss_ies *f; | ||||
| 
 | ||||
| 				/*
 | ||||
| 				 * The found BSS struct is one of the probe | ||||
| 				 * response members of a group, but we're | ||||
| @ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | ||||
| 				 * SSID to showing it, which is confusing so | ||||
| 				 * drop this information. | ||||
| 				 */ | ||||
| 
 | ||||
| 				f = rcu_access_pointer(tmp->pub.beacon_ies); | ||||
| 				kfree_rcu((struct cfg80211_bss_ies *)f, | ||||
| 					  rcu_head); | ||||
| 				goto drop; | ||||
| 			} | ||||
| 
 | ||||
| @ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | ||||
| 				kfree_rcu((struct cfg80211_bss_ies *)old, | ||||
| 					  rcu_head); | ||||
| 		} | ||||
| 
 | ||||
| 		found->pub.beacon_interval = tmp->pub.beacon_interval; | ||||
| 		found->pub.signal = tmp->pub.signal; | ||||
| 		found->pub.capability = tmp->pub.capability; | ||||
| 		found->ts = tmp->ts; | ||||
| 	} else { | ||||
| 		struct cfg80211_internal_bss *new; | ||||
| 		struct cfg80211_internal_bss *hidden; | ||||
| @ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | ||||
| 	if (IS_ERR(rdev)) | ||||
| 		return PTR_ERR(rdev); | ||||
| 
 | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	if (rdev->scan_req) { | ||||
| 		err = -EBUSY; | ||||
| 		goto out; | ||||
| @ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | ||||
| 		dev_hold(dev); | ||||
| 	} | ||||
|  out: | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	kfree(creq); | ||||
| 	cfg80211_unlock_rdev(rdev); | ||||
| 	return err; | ||||
|  | ||||
| @ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | ||||
| 	ASSERT_RTNL(); | ||||
| 	ASSERT_RDEV_LOCK(rdev); | ||||
| 	ASSERT_WDEV_LOCK(wdev); | ||||
| 	lockdep_assert_held(&rdev->sched_scan_mtx); | ||||
| 
 | ||||
| 	if (rdev->scan_req) | ||||
| 		return -EBUSY; | ||||
| @ -324,11 +325,9 @@ void cfg80211_sme_scan_done(struct net_device *dev) | ||||
| { | ||||
| 	struct wireless_dev *wdev = dev->ieee80211_ptr; | ||||
| 
 | ||||
| 	mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||||
| 	wdev_lock(wdev); | ||||
| 	__cfg80211_sme_scan_done(dev); | ||||
| 	wdev_unlock(wdev); | ||||
| 	mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx); | ||||
| } | ||||
| 
 | ||||
| void cfg80211_sme_rx_auth(struct net_device *dev, | ||||
| @ -928,9 +927,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, | ||||
| 	int err; | ||||
| 
 | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 	/* might request scan - scan_mtx -> wdev_mtx dependency */ | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	wdev_lock(dev->ieee80211_ptr); | ||||
| 	err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL); | ||||
| 	wdev_unlock(dev->ieee80211_ptr); | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| 
 | ||||
| 	return err; | ||||
|  | ||||
| @ -27,7 +27,8 @@ | ||||
| #define WIPHY_PR_ARG	__entry->wiphy_name | ||||
| 
 | ||||
| #define WDEV_ENTRY	__field(u32, id) | ||||
| #define WDEV_ASSIGN	(__entry->id) = (wdev ? wdev->identifier : 0) | ||||
| #define WDEV_ASSIGN	(__entry->id) = (!IS_ERR_OR_NULL(wdev)	\ | ||||
| 					 ? wdev->identifier : 0) | ||||
| #define WDEV_PR_FMT	"wdev(%u)" | ||||
| #define WDEV_PR_ARG	(__entry->id) | ||||
| 
 | ||||
| @ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl, | ||||
| 	), | ||||
| 	TP_fast_assign( | ||||
| 		WIPHY_ASSIGN; | ||||
| 		WIPHY_ASSIGN; | ||||
| 		NETDEV_ASSIGN; | ||||
| 		__entry->acl_policy = params->acl_policy; | ||||
| 	), | ||||
| 	TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d", | ||||
|  | ||||
| @ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | ||||
| 
 | ||||
| 	cfg80211_lock_rdev(rdev); | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	wdev_lock(wdev); | ||||
| 
 | ||||
| 	if (wdev->sme_state != CFG80211_SME_IDLE) { | ||||
| @ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, | ||||
| 	err = cfg80211_mgd_wext_connect(rdev, wdev); | ||||
|  out: | ||||
| 	wdev_unlock(wdev); | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| 	cfg80211_unlock_rdev(rdev); | ||||
| 	return err; | ||||
| @ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | ||||
| 
 | ||||
| 	cfg80211_lock_rdev(rdev); | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	wdev_lock(wdev); | ||||
| 
 | ||||
| 	err = 0; | ||||
| @ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, | ||||
| 	err = cfg80211_mgd_wext_connect(rdev, wdev); | ||||
|  out: | ||||
| 	wdev_unlock(wdev); | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| 	cfg80211_unlock_rdev(rdev); | ||||
| 	return err; | ||||
| @ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | ||||
| 
 | ||||
| 	cfg80211_lock_rdev(rdev); | ||||
| 	mutex_lock(&rdev->devlist_mtx); | ||||
| 	mutex_lock(&rdev->sched_scan_mtx); | ||||
| 	wdev_lock(wdev); | ||||
| 
 | ||||
| 	if (wdev->sme_state != CFG80211_SME_IDLE) { | ||||
| @ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, | ||||
| 	err = cfg80211_mgd_wext_connect(rdev, wdev); | ||||
|  out: | ||||
| 	wdev_unlock(wdev); | ||||
| 	mutex_unlock(&rdev->sched_scan_mtx); | ||||
| 	mutex_unlock(&rdev->devlist_mtx); | ||||
| 	cfg80211_unlock_rdev(rdev); | ||||
| 	return err; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user