diff options
| author | John W. Linville <linville@tuxdriver.com> | 2011-08-29 14:52:20 -0400 | 
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-08-29 14:52:20 -0400 | 
| commit | ba6e5eb107b4b26444cb67ce6fb8eb0973a97964 (patch) | |
| tree | 9377baf652e0cd8360372020b0386e238d07a30d | |
| parent | f3116f62cb56ef5efd172371fab688bb27529f69 (diff) | |
| parent | a508a6ea234571e0e7d1e9f2455fc1eca54d1fef (diff) | |
| download | olio-linux-3.10-ba6e5eb107b4b26444cb67ce6fb8eb0973a97964.tar.xz olio-linux-3.10-ba6e5eb107b4b26444cb67ce6fb8eb0973a97964.zip  | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
121 files changed, 5609 insertions, 1486 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 194095ac07e..579713ef7cf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1230,7 +1230,7 @@ F:	Documentation/aoe/  F:	drivers/block/aoe/  ATHEROS ATH GENERIC UTILITIES -M:	"Luis R. Rodriguez" <lrodriguez@atheros.com> +M:	"Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>  L:	linux-wireless@vger.kernel.org  S:	Supported  F:	drivers/net/wireless/ath/* @@ -1238,7 +1238,7 @@ F:	drivers/net/wireless/ath/*  ATHEROS ATH5K WIRELESS DRIVER  M:	Jiri Slaby <jirislaby@gmail.com>  M:	Nick Kossifidis <mickflemm@gmail.com> -M:	"Luis R. Rodriguez" <lrodriguez@atheros.com> +M:	"Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>  M:	Bob Copeland <me@bobcopeland.com>  L:	linux-wireless@vger.kernel.org  L:	ath5k-devel@lists.ath5k.org @@ -1247,10 +1247,10 @@ S:	Maintained  F:	drivers/net/wireless/ath/ath5k/  ATHEROS ATH9K WIRELESS DRIVER -M:	"Luis R. Rodriguez" <lrodriguez@atheros.com> -M:	Jouni Malinen <jmalinen@atheros.com> -M:	Vasanthakumar Thiagarajan <vasanth@atheros.com> -M:	Senthil Balasubramanian <senthilkumar@atheros.com> +M:	"Luis R. Rodriguez" <mcgrof@qca.qualcomm.com> +M:	Jouni Malinen <jouni@qca.qualcomm.com> +M:	Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> +M:	Senthil Balasubramanian <senthilb@qca.qualcomm.com>  L:	linux-wireless@vger.kernel.org  L:	ath9k-devel@lists.ath9k.org  W:	http://wireless.kernel.org/en/users/Drivers/ath9k @@ -1278,7 +1278,7 @@ F:	drivers/input/misc/ati_remote2.c  ATLX ETHERNET DRIVERS  M:	Jay Cliburn <jcliburn@gmail.com>  M:	Chris Snook <chris.snook@gmail.com> -M:	Jie Yang <jie.yang@atheros.com> +M:	Jie Yang <yangjie@qca.qualcomm.com>  L:	netdev@vger.kernel.org  W:	http://sourceforge.net/projects/atl1  W:	http://atl1.sourceforge.net @@ -4503,6 +4503,17 @@ W:	http://www.qlogic.com  S:	Supported  F:	drivers/net/ethernet/qlogic/netxen/ +NFC SUBSYSTEM +M:	Lauro Ramos Venancio <lauro.venancio@openbossa.org> +M:	Aloisio Almeida Jr <aloisio.almeida@openbossa.org> +M:	Samuel Ortiz <sameo@linux.intel.com> +L:	linux-wireless@vger.kernel.org +S:	Maintained +F:	net/nfc/ +F:	include/linux/nfc.h +F:	include/net/nfc.h +F:	drivers/nfc/ +  NFS, SUNRPC, AND LOCKD CLIENTS  M:	Trond Myklebust <Trond.Myklebust@netapp.com>  L:	linux-nfs@vger.kernel.org diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 5940c81e7e1..4bc10aa57bd 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -90,6 +90,24 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)  	}  } +/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */ +void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable) +{ +	struct bcma_bus *bus = cc->core->bus; +	u32 val; + +	val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL); +	if (enable) { +		val |= BCMA_CHIPCTL_4331_EXTPA_EN; +		if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11) +			val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; +	} else { +		val &= ~BCMA_CHIPCTL_4331_EXTPA_EN; +		val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5; +	} +	bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val); +} +  void bcma_pmu_workarounds(struct bcma_drv_cc *cc)  {  	struct bcma_bus *bus = cc->core->bus; @@ -99,7 +117,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)  		bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);  		break;  	case 0x4331: -		pr_err("Enabling Ext PA lines not implemented\n"); +		/* BCM4331 workaround is SPROM-related, we put it in sprom.c */  		break;  	case 43224:  		if (bus->chipinfo.rev == 0) { diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 0ea390f9aa9..cad99485768 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -281,7 +281,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,  	/* get & parse master ports */  	for (i = 0; i < ports[0]; i++) { -		u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr); +		s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);  		if (mst_port_d < 0)  			return -EILSEQ;  	} diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 8b5b7856abe..166ed13ec06 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -152,6 +152,9 @@ int bcma_sprom_get(struct bcma_bus *bus)  	if (!sprom)  		return -ENOMEM; +	if (bus->chipinfo.id == 0x4331) +		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); +  	/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).  	 * According to brcm80211 this applies to cards with PCIe rev >= 6  	 * TODO: understand this condition and use it */ @@ -159,6 +162,9 @@ int bcma_sprom_get(struct bcma_bus *bus)  		BCMA_CC_SPROM_PCIE6;  	bcma_sprom_read(bus, offset, sprom); +	if (bus->chipinfo.id == 0x4331) +		bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); +  	err = bcma_sprom_valid(sprom);  	if (err)  		goto out; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 44d9d8d5649..b54ab78fb09 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -303,17 +303,13 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)   * register as the other analog registers.  Hence the 9 writes.   */  static void ar9002_hw_configpcipowersave(struct ath_hw *ah, -					 int restore, -					 int power_off) +					 bool power_off)  {  	u8 i;  	u32 val; -	if (ah->is_pciexpress != true || ah->aspm_enabled != true) -		return; -  	/* Nothing to do on restore for 11N */ -	if (!restore) { +	if (!power_off /* !restore */) {  		if (AR_SREV_9280_20_OR_LATER(ah)) {  			/*  			 * AR9280 2.0 or later chips use SerDes values from the diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index a0aadaddd07..f2c6f2316a3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -636,7 +636,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {  	{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},  	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},  	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, -	{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, +	{0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},  	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},  	{0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},  	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index f48051c5009..fa35a0235f4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -839,20 +839,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,  			       struct ath9k_channel *chan)  {  	struct ath_common *common = ath9k_hw_common(ah); -	struct ath9k_hw_capabilities *pCap = &ah->caps; -	int val;  	bool txiqcal_done = false; -	val = REG_READ(ah, AR_ENT_OTP); -	ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); - -	/* Configure rx/tx chains before running AGC/TxiQ cals */ -	if (val & AR_ENT_OTP_CHAIN2_DISABLE) -		ar9003_hw_set_chain_masks(ah, 0x3, 0x3); -	else -		ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask, -					  pCap->tx_chainmask); -  	/* Do Tx IQ Calibration */  	REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,  		      AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, @@ -887,9 +875,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,  	if (txiqcal_done)  		ar9003_hw_tx_iq_cal_post_proc(ah); -	/* Revert chainmasks to their original values before NF cal */ -	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); -  	ath9k_hw_start_nfcal(ah, true);  	/* Initialize list pointers */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index ad2bb2bf4e8..b6839e69527 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -21,6 +21,7 @@  #include "ar9340_initvals.h"  #include "ar9330_1p1_initvals.h"  #include "ar9330_1p2_initvals.h" +#include "ar9580_1p0_initvals.h"  /* General hardware code for the AR9003 hadware family */ @@ -253,6 +254,56 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)  				ar9485_1_1_pcie_phy_clkreq_disable_L1,  				ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),  				2); +	} else if (AR_SREV_9580(ah)) { +		/* mac */ +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], +				ar9580_1p0_mac_core, +				ARRAY_SIZE(ar9580_1p0_mac_core), 2); +		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], +				ar9580_1p0_mac_postamble, +				ARRAY_SIZE(ar9580_1p0_mac_postamble), 5); + +		/* bb */ +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], +				ar9580_1p0_baseband_core, +				ARRAY_SIZE(ar9580_1p0_baseband_core), 2); +		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], +				ar9580_1p0_baseband_postamble, +				ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5); + +		/* radio */ +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], +				ar9580_1p0_radio_core, +				ARRAY_SIZE(ar9580_1p0_radio_core), 2); +		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], +				ar9580_1p0_radio_postamble, +				ARRAY_SIZE(ar9580_1p0_radio_postamble), 5); + +		/* soc */ +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], +				ar9580_1p0_soc_preamble, +				ARRAY_SIZE(ar9580_1p0_soc_preamble), 2); +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); +		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], +				ar9580_1p0_soc_postamble, +				ARRAY_SIZE(ar9580_1p0_soc_postamble), 5); + +		/* rx/tx gain */ +		INIT_INI_ARRAY(&ah->iniModesRxGain, +				ar9580_1p0_rx_gain_table, +				ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2); +		INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9580_1p0_low_ob_db_tx_gain_table, +				ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), +				5); + +		INIT_INI_ARRAY(&ah->iniModesAdditional, +				ar9580_1p0_modes_fast_clock, +				ARRAY_SIZE(ar9580_1p0_modes_fast_clock), +				3);  	} else {  		/* mac */  		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -348,6 +399,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       ar9485_modes_lowest_ob_db_tx_gain_1_1,  				       ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),  				       5); +		else if (AR_SREV_9580(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +			      ar9580_1p0_lowest_ob_db_tx_gain_table, +			      ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table), +			      5);  		else  			INIT_INI_ARRAY(&ah->iniModesTxGain,  				       ar9300Modes_lowest_ob_db_tx_gain_table_2p2, @@ -375,6 +431,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       ar9485Modes_high_ob_db_tx_gain_1_1,  				       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),  				       5); +		else if (AR_SREV_9580(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9580_1p0_high_ob_db_tx_gain_table, +				ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table), +				       5);  		else  			INIT_INI_ARRAY(&ah->iniModesTxGain,  				       ar9300Modes_high_ob_db_tx_gain_table_2p2, @@ -402,6 +463,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       ar9485Modes_low_ob_db_tx_gain_1_1,  				       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),  				       5); +		else if (AR_SREV_9580(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				 ar9580_1p0_low_ob_db_tx_gain_table, +				 ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), +				 5);  		else  			INIT_INI_ARRAY(&ah->iniModesTxGain,  				       ar9300Modes_low_ob_db_tx_gain_table_2p2, @@ -429,6 +495,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)  				       ar9485Modes_high_power_tx_gain_1_1,  				       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),  				       5); +		else if (AR_SREV_9580(ah)) +			INIT_INI_ARRAY(&ah->iniModesTxGain, +				ar9580_1p0_high_power_tx_gain_table, +				ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table), +				5);  		else  			INIT_INI_ARRAY(&ah->iniModesTxGain,  				       ar9300Modes_high_power_tx_gain_table_2p2, @@ -463,6 +534,11 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)  				       ar9485Common_wo_xlna_rx_gain_1_1,  				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),  				       2); +		else if (AR_SREV_9580(ah)) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +				       ar9580_1p0_rx_gain_table, +				       ARRAY_SIZE(ar9580_1p0_rx_gain_table), +				       2);  		else  			INIT_INI_ARRAY(&ah->iniModesRxGain,  				       ar9300Common_rx_gain_table_2p2, @@ -490,6 +566,11 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)  				       ar9485Common_wo_xlna_rx_gain_1_1,  				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),  				       2); +		else if (AR_SREV_9580(ah)) +			INIT_INI_ARRAY(&ah->iniModesRxGain, +				   ar9580_1p0_wo_xlna_rx_gain_table, +				   ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table), +				   2);  		else  			INIT_INI_ARRAY(&ah->iniModesRxGain,  				       ar9300Common_wo_xlna_rx_gain_table_2p2, @@ -516,14 +597,10 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)   * register as the other analog registers.  Hence the 9 writes.   */  static void ar9003_hw_configpcipowersave(struct ath_hw *ah, -					 int restore, -					 int power_off) +					 bool power_off)  { -	if (ah->is_pciexpress != true || ah->aspm_enabled != true) -		return; -  	/* Nothing to do on restore for 11N */ -	if (!restore) { +	if (!power_off /* !restore */) {  		/* set bit 19 to allow forcing of pcie core into L1 state */  		REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 1aadc4757e6..8ace36e7739 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -253,8 +253,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,  		return -EIO;  	} -	if (status & AR_TxOpExceeded) -		ts->ts_status |= ATH9K_TXERR_XTXOP;  	ts->ts_rateindex = MS(status, AR_FinalTxIdx);  	ts->ts_seqnum = MS(status, AR_SeqNum);  	ts->tid = MS(status, AR_TxTid); @@ -264,6 +262,8 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,  	ts->ts_status = 0;  	ts->ts_flags  = 0; +	if (status & AR_TxOpExceeded) +		ts->ts_status |= ATH9K_TXERR_XTXOP;  	status = ACCESS_ONCE(ads->status2);  	ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);  	ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); @@ -415,36 +415,12 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,  static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,  					u32 aggrLen)  { -#define FIRST_DESC_NDELIMS 60  	struct ar9003_txc *ads = (struct ar9003_txc *) ds;  	ads->ctl12 |= (AR_IsAggr | AR_MoreAggr); -	if (ah->ent_mode & AR_ENT_OTP_MPSD) { -		u32 ctl17, ndelim; -		/* -		 * Add delimiter when using RTS/CTS with aggregation -		 * and non enterprise AR9003 card -		 */ -		ctl17 = ads->ctl17; -		ndelim = MS(ctl17, AR_PadDelim); - -		if (ndelim < FIRST_DESC_NDELIMS) { -			aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4; -			ndelim = FIRST_DESC_NDELIMS; -		} - -		ctl17 &= ~AR_AggrLen; -		ctl17 |= SM(aggrLen, AR_AggrLen); - -		ctl17 &= ~AR_PadDelim; -		ctl17 |= SM(ndelim, AR_PadDelim); - -		ads->ctl17 = ctl17; -	} else { -		ads->ctl17 &= ~AR_AggrLen; -		ads->ctl17 |= SM(aggrLen, AR_AggrLen); -	} +	ads->ctl17 &= ~AR_AggrLen; +	ads->ctl17 |= SM(aggrLen, AR_AggrLen);  }  static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index a0aaa685548..33edb5653ca 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -482,7 +482,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah,  		(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);  	/* Enable 11n HT, 20 MHz */ -	phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH | +	phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |  		  AR_PHY_GC_SHORT_GI_40 | enableDacFifo;  	/* Configure baseband for dynamic 20/40 operation */ @@ -540,7 +540,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,  	udelay(synthDelay + BASE_ACTIVATE_DELAY);  } -void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)  {  	switch (rx) {  	case 0x5: diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 5c590429f12..80397de11e0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h @@ -1124,6 +1124,4 @@  #define AR_PHY_CL_TAB_CL_GAIN_MOD		0x1f  #define AR_PHY_CL_TAB_CL_GAIN_MOD_S		0 -void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); -  #endif  /* AR9003_PHY_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h new file mode 100644 index 00000000000..06b3f0df9fa --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -0,0 +1,1673 @@ +/* + * Copyright (c) 2010 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef INITVALS_9580_1P0_H +#define INITVALS_9580_1P0_H + +/* AR9580 1.0 */ + +static const u32 ar9580_1p0_modes_fast_clock[][3] = { +	/* Addr      5G_HT20     5G_HT40   */ +	{0x00001030, 0x00000268, 0x000004d0}, +	{0x00001070, 0x0000018c, 0x00000318}, +	{0x000010b0, 0x00000fd0, 0x00001fa0}, +	{0x00008014, 0x044c044c, 0x08980898}, +	{0x0000801c, 0x148ec02b, 0x148ec057}, +	{0x00008318, 0x000044c0, 0x00008980}, +	{0x00009e00, 0x0372131c, 0x0372131c}, +	{0x0000a230, 0x0000000b, 0x00000016}, +	{0x0000a254, 0x00000898, 0x00001130}, +}; + +static const u32 ar9580_1p0_radio_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, +	{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, +	{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, +	{0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +	{0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +	{0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, +}; + +static const u32 ar9580_1p0_baseband_core[][2] = { +	/* Addr      allmodes  */ +	{0x00009800, 0xafe68e30}, +	{0x00009804, 0xfd14e000}, +	{0x00009808, 0x9c0a9f6b}, +	{0x0000980c, 0x04900000}, +	{0x00009814, 0x3280c00a}, +	{0x00009818, 0x00000000}, +	{0x0000981c, 0x00020028}, +	{0x00009834, 0x6400a290}, +	{0x00009838, 0x0108ecff}, +	{0x0000983c, 0x0d000600}, +	{0x00009880, 0x201fff00}, +	{0x00009884, 0x00001042}, +	{0x000098a4, 0x00200400}, +	{0x000098b0, 0x32840bbe}, +	{0x000098d0, 0x004b6a8e}, +	{0x000098d4, 0x00000820}, +	{0x000098dc, 0x00000000}, +	{0x000098f0, 0x00000000}, +	{0x000098f4, 0x00000000}, +	{0x00009c04, 0xff55ff55}, +	{0x00009c08, 0x0320ff55}, +	{0x00009c0c, 0x00000000}, +	{0x00009c10, 0x00000000}, +	{0x00009c14, 0x00046384}, +	{0x00009c18, 0x05b6b440}, +	{0x00009c1c, 0x00b6b440}, +	{0x00009d00, 0xc080a333}, +	{0x00009d04, 0x40206c10}, +	{0x00009d08, 0x009c4060}, +	{0x00009d0c, 0x9883800a}, +	{0x00009d10, 0x01834061}, +	{0x00009d14, 0x00c0040b}, +	{0x00009d18, 0x00000000}, +	{0x00009e08, 0x0038230c}, +	{0x00009e24, 0x990bb515}, +	{0x00009e28, 0x0c6f0000}, +	{0x00009e30, 0x06336f77}, +	{0x00009e34, 0x6af6532f}, +	{0x00009e38, 0x0cc80c00}, +	{0x00009e40, 0x0d261820}, +	{0x00009e4c, 0x00001004}, +	{0x00009e50, 0x00ff03f1}, +	{0x00009e54, 0x00000000}, +	{0x00009fc0, 0x803e4788}, +	{0x00009fc4, 0x0001efb5}, +	{0x00009fcc, 0x40000014}, +	{0x00009fd0, 0x01193b93}, +	{0x0000a20c, 0x00000000}, +	{0x0000a220, 0x00000000}, +	{0x0000a224, 0x00000000}, +	{0x0000a228, 0x10002310}, +	{0x0000a23c, 0x00000000}, +	{0x0000a244, 0x0c000000}, +	{0x0000a2a0, 0x00000001}, +	{0x0000a2c0, 0x00000001}, +	{0x0000a2c8, 0x00000000}, +	{0x0000a2cc, 0x18c43433}, +	{0x0000a2d4, 0x00000000}, +	{0x0000a2ec, 0x00000000}, +	{0x0000a2f0, 0x00000000}, +	{0x0000a2f4, 0x00000000}, +	{0x0000a2f8, 0x00000000}, +	{0x0000a344, 0x00000000}, +	{0x0000a34c, 0x00000000}, +	{0x0000a350, 0x0000a000}, +	{0x0000a364, 0x00000000}, +	{0x0000a370, 0x00000000}, +	{0x0000a390, 0x00000001}, +	{0x0000a394, 0x00000444}, +	{0x0000a398, 0x001f0e0f}, +	{0x0000a39c, 0x0075393f}, +	{0x0000a3a0, 0xb79f6427}, +	{0x0000a3a4, 0x00000000}, +	{0x0000a3a8, 0xaaaaaaaa}, +	{0x0000a3ac, 0x3c466478}, +	{0x0000a3c0, 0x20202020}, +	{0x0000a3c4, 0x22222220}, +	{0x0000a3c8, 0x20200020}, +	{0x0000a3cc, 0x20202020}, +	{0x0000a3d0, 0x20202020}, +	{0x0000a3d4, 0x20202020}, +	{0x0000a3d8, 0x20202020}, +	{0x0000a3dc, 0x20202020}, +	{0x0000a3e0, 0x20202020}, +	{0x0000a3e4, 0x20202020}, +	{0x0000a3e8, 0x20202020}, +	{0x0000a3ec, 0x20202020}, +	{0x0000a3f0, 0x00000000}, +	{0x0000a3f4, 0x00000000}, +	{0x0000a3f8, 0x0c9bd380}, +	{0x0000a3fc, 0x000f0f01}, +	{0x0000a400, 0x8fa91f01}, +	{0x0000a404, 0x00000000}, +	{0x0000a408, 0x0e79e5c6}, +	{0x0000a40c, 0x00820820}, +	{0x0000a414, 0x1ce739ce}, +	{0x0000a418, 0x2d001dce}, +	{0x0000a41c, 0x1ce739ce}, +	{0x0000a420, 0x000001ce}, +	{0x0000a424, 0x1ce739ce}, +	{0x0000a428, 0x000001ce}, +	{0x0000a42c, 0x1ce739ce}, +	{0x0000a430, 0x1ce739ce}, +	{0x0000a434, 0x00000000}, +	{0x0000a438, 0x00001801}, +	{0x0000a43c, 0x00100000}, +	{0x0000a440, 0x00000000}, +	{0x0000a444, 0x00000000}, +	{0x0000a448, 0x05000080}, +	{0x0000a44c, 0x00000001}, +	{0x0000a450, 0x00010000}, +	{0x0000a458, 0x00000000}, +	{0x0000a640, 0x00000000}, +	{0x0000a644, 0x3fad9d74}, +	{0x0000a648, 0x0048060a}, +	{0x0000a64c, 0x00003c37}, +	{0x0000a670, 0x03020100}, +	{0x0000a674, 0x09080504}, +	{0x0000a678, 0x0d0c0b0a}, +	{0x0000a67c, 0x13121110}, +	{0x0000a680, 0x31301514}, +	{0x0000a684, 0x35343332}, +	{0x0000a688, 0x00000036}, +	{0x0000a690, 0x00000838}, +	{0x0000a7c0, 0x00000000}, +	{0x0000a7c4, 0xfffffffc}, +	{0x0000a7c8, 0x00000000}, +	{0x0000a7cc, 0x00000000}, +	{0x0000a7d0, 0x00000000}, +	{0x0000a7d4, 0x00000004}, +	{0x0000a7dc, 0x00000000}, +	{0x0000a8d0, 0x004b6a8e}, +	{0x0000a8d4, 0x00000820}, +	{0x0000a8dc, 0x00000000}, +	{0x0000a8f0, 0x00000000}, +	{0x0000a8f4, 0x00000000}, +	{0x0000b2d0, 0x00000080}, +	{0x0000b2d4, 0x00000000}, +	{0x0000b2ec, 0x00000000}, +	{0x0000b2f0, 0x00000000}, +	{0x0000b2f4, 0x00000000}, +	{0x0000b2f8, 0x00000000}, +	{0x0000b408, 0x0e79e5c0}, +	{0x0000b40c, 0x00820820}, +	{0x0000b420, 0x00000000}, +	{0x0000b8d0, 0x004b6a8e}, +	{0x0000b8d4, 0x00000820}, +	{0x0000b8dc, 0x00000000}, +	{0x0000b8f0, 0x00000000}, +	{0x0000b8f4, 0x00000000}, +	{0x0000c2d0, 0x00000080}, +	{0x0000c2d4, 0x00000000}, +	{0x0000c2ec, 0x00000000}, +	{0x0000c2f0, 0x00000000}, +	{0x0000c2f4, 0x00000000}, +	{0x0000c2f8, 0x00000000}, +	{0x0000c408, 0x0e79e5c0}, +	{0x0000c40c, 0x00820820}, +	{0x0000c420, 0x00000000}, +}; + +static const u32 ar9580_1p0_mac_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, +	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, +	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, +	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, +	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, +	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, +	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, +	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, +}; + +static const u32 ar9580_1p0_low_ob_db_tx_gain_table[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +	{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, +	{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +	{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, +	{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, +	{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, +	{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_high_power_tx_gain_table[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +	{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, +	{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +	{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, +	{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, +	{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, +	{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_lowest_ob_db_tx_gain_table[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, +	{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, +	{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, +	{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, +	{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, +	{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83}, +	{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84}, +	{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3}, +	{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5}, +	{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9}, +	{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb}, +	{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec}, +	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, +	{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, +	{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, +	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, +	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, +	{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83}, +	{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84}, +	{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3}, +	{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5}, +	{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9}, +	{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb}, +	{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, +	{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, +	{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, +	{0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_baseband_core_txfir_coeff_japan_2484[][2] = { +	/* Addr      allmodes  */ +	{0x0000a398, 0x00000000}, +	{0x0000a39c, 0x6f7f0301}, +	{0x0000a3a0, 0xca9228ee}, +}; + +static const u32 ar9580_1p0_mac_core[][2] = { +	/* Addr      allmodes  */ +	{0x00000008, 0x00000000}, +	{0x00000030, 0x00020085}, +	{0x00000034, 0x00000005}, +	{0x00000040, 0x00000000}, +	{0x00000044, 0x00000000}, +	{0x00000048, 0x00000008}, +	{0x0000004c, 0x00000010}, +	{0x00000050, 0x00000000}, +	{0x00001040, 0x002ffc0f}, +	{0x00001044, 0x002ffc0f}, +	{0x00001048, 0x002ffc0f}, +	{0x0000104c, 0x002ffc0f}, +	{0x00001050, 0x002ffc0f}, +	{0x00001054, 0x002ffc0f}, +	{0x00001058, 0x002ffc0f}, +	{0x0000105c, 0x002ffc0f}, +	{0x00001060, 0x002ffc0f}, +	{0x00001064, 0x002ffc0f}, +	{0x000010f0, 0x00000100}, +	{0x00001270, 0x00000000}, +	{0x000012b0, 0x00000000}, +	{0x000012f0, 0x00000000}, +	{0x0000143c, 0x00000000}, +	{0x0000147c, 0x00000000}, +	{0x00008000, 0x00000000}, +	{0x00008004, 0x00000000}, +	{0x00008008, 0x00000000}, +	{0x0000800c, 0x00000000}, +	{0x00008018, 0x00000000}, +	{0x00008020, 0x00000000}, +	{0x00008038, 0x00000000}, +	{0x0000803c, 0x00000000}, +	{0x00008040, 0x00000000}, +	{0x00008044, 0x00000000}, +	{0x00008048, 0x00000000}, +	{0x0000804c, 0xffffffff}, +	{0x00008054, 0x00000000}, +	{0x00008058, 0x00000000}, +	{0x0000805c, 0x000fc78f}, +	{0x00008060, 0x0000000f}, +	{0x00008064, 0x00000000}, +	{0x00008070, 0x00000310}, +	{0x00008074, 0x00000020}, +	{0x00008078, 0x00000000}, +	{0x0000809c, 0x0000000f}, +	{0x000080a0, 0x00000000}, +	{0x000080a4, 0x02ff0000}, +	{0x000080a8, 0x0e070605}, +	{0x000080ac, 0x0000000d}, +	{0x000080b0, 0x00000000}, +	{0x000080b4, 0x00000000}, +	{0x000080b8, 0x00000000}, +	{0x000080bc, 0x00000000}, +	{0x000080c0, 0x2a800000}, +	{0x000080c4, 0x06900168}, +	{0x000080c8, 0x13881c22}, +	{0x000080cc, 0x01f40000}, +	{0x000080d0, 0x00252500}, +	{0x000080d4, 0x00a00000}, +	{0x000080d8, 0x00400000}, +	{0x000080dc, 0x00000000}, +	{0x000080e0, 0xffffffff}, +	{0x000080e4, 0x0000ffff}, +	{0x000080e8, 0x3f3f3f3f}, +	{0x000080ec, 0x00000000}, +	{0x000080f0, 0x00000000}, +	{0x000080f4, 0x00000000}, +	{0x000080fc, 0x00020000}, +	{0x00008100, 0x00000000}, +	{0x00008108, 0x00000052}, +	{0x0000810c, 0x00000000}, +	{0x00008110, 0x00000000}, +	{0x00008114, 0x000007ff}, +	{0x00008118, 0x000000aa}, +	{0x0000811c, 0x00003210}, +	{0x00008124, 0x00000000}, +	{0x00008128, 0x00000000}, +	{0x0000812c, 0x00000000}, +	{0x00008130, 0x00000000}, +	{0x00008134, 0x00000000}, +	{0x00008138, 0x00000000}, +	{0x0000813c, 0x0000ffff}, +	{0x00008144, 0xffffffff}, +	{0x00008168, 0x00000000}, +	{0x0000816c, 0x00000000}, +	{0x000081c0, 0x00000000}, +	{0x000081c4, 0x33332210}, +	{0x000081ec, 0x00000000}, +	{0x000081f0, 0x00000000}, +	{0x000081f4, 0x00000000}, +	{0x000081f8, 0x00000000}, +	{0x000081fc, 0x00000000}, +	{0x00008240, 0x00100000}, +	{0x00008244, 0x0010f400}, +	{0x00008248, 0x00000800}, +	{0x0000824c, 0x0001e800}, +	{0x00008250, 0x00000000}, +	{0x00008254, 0x00000000}, +	{0x00008258, 0x00000000}, +	{0x0000825c, 0x40000000}, +	{0x00008260, 0x00080922}, +	{0x00008264, 0x9bc00010}, +	{0x00008268, 0xffffffff}, +	{0x0000826c, 0x0000ffff}, +	{0x00008270, 0x00000000}, +	{0x00008274, 0x40000000}, +	{0x00008278, 0x003e4180}, +	{0x0000827c, 0x00000004}, +	{0x00008284, 0x0000002c}, +	{0x00008288, 0x0000002c}, +	{0x0000828c, 0x000000ff}, +	{0x00008294, 0x00000000}, +	{0x00008298, 0x00000000}, +	{0x0000829c, 0x00000000}, +	{0x00008300, 0x00000140}, +	{0x00008314, 0x00000000}, +	{0x0000831c, 0x0000010d}, +	{0x00008328, 0x00000000}, +	{0x0000832c, 0x00000007}, +	{0x00008330, 0x00000302}, +	{0x00008334, 0x00000700}, +	{0x00008338, 0x00ff0000}, +	{0x0000833c, 0x02400000}, +	{0x00008340, 0x000107ff}, +	{0x00008344, 0xaa48105b}, +	{0x00008348, 0x008f0000}, +	{0x0000835c, 0x00000000}, +	{0x00008360, 0xffffffff}, +	{0x00008364, 0xffffffff}, +	{0x00008368, 0x00000000}, +	{0x00008370, 0x00000000}, +	{0x00008374, 0x000000ff}, +	{0x00008378, 0x00000000}, +	{0x0000837c, 0x00000000}, +	{0x00008380, 0xffffffff}, +	{0x00008384, 0xffffffff}, +	{0x00008390, 0xffffffff}, +	{0x00008394, 0xffffffff}, +	{0x00008398, 0x00000000}, +	{0x0000839c, 0x00000000}, +	{0x000083a0, 0x00000000}, +	{0x000083a4, 0x0000fa14}, +	{0x000083a8, 0x000f0c00}, +	{0x000083ac, 0x33332210}, +	{0x000083b0, 0x33332210}, +	{0x000083b4, 0x33332210}, +	{0x000083b8, 0x33332210}, +	{0x000083bc, 0x00000000}, +	{0x000083c0, 0x00000000}, +	{0x000083c4, 0x00000000}, +	{0x000083c8, 0x00000000}, +	{0x000083cc, 0x00000200}, +	{0x000083d0, 0x000301ff}, +}; + +static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, +	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400}, +	{0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402}, +	{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, +	{0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603}, +	{0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02}, +	{0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04}, +	{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20}, +	{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20}, +	{0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22}, +	{0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24}, +	{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640}, +	{0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660}, +	{0x0000a544, 0x5302266c, 0x5302266c, 0x3b001861, 0x3b001861}, +	{0x0000a548, 0x5702286c, 0x5702286c, 0x3e001a81, 0x3e001a81}, +	{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42001a83, 0x42001a83}, +	{0x0000a550, 0x61024a6c, 0x61024a6c, 0x44001c84, 0x44001c84}, +	{0x0000a554, 0x66026a6c, 0x66026a6c, 0x48001ce3, 0x48001ce3}, +	{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a55c, 0x7002708c, 0x7002708c, 0x50001ce9, 0x50001ce9}, +	{0x0000a560, 0x7302b08a, 0x7302b08a, 0x54001ceb, 0x54001ceb}, +	{0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001eec, 0x56001eec}, +	{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, +	{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, +	{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400}, +	{0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402}, +	{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603}, +	{0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02}, +	{0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04}, +	{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20}, +	{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20}, +	{0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22}, +	{0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24}, +	{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640}, +	{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660}, +	{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b801861, 0x3b801861}, +	{0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e801a81, 0x3e801a81}, +	{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x42801a83, 0x42801a83}, +	{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x44801c84, 0x44801c84}, +	{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x48801ce3, 0x48801ce3}, +	{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x4c801ce5, 0x4c801ce5}, +	{0x0000a5dc, 0x7082708c, 0x7082708c, 0x50801ce9, 0x50801ce9}, +	{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x54801ceb, 0x54801ceb}, +	{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x56801eec, 0x56801eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000}, +	{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501}, +	{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005}, +	{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, +	{0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, +	{0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4}, +	{0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_wo_xlna_rx_gain_table[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00010000}, +	{0x0000a004, 0x00030002}, +	{0x0000a008, 0x00050004}, +	{0x0000a00c, 0x00810080}, +	{0x0000a010, 0x00830082}, +	{0x0000a014, 0x01810180}, +	{0x0000a018, 0x01830182}, +	{0x0000a01c, 0x01850184}, +	{0x0000a020, 0x01890188}, +	{0x0000a024, 0x018b018a}, +	{0x0000a028, 0x018d018c}, +	{0x0000a02c, 0x03820190}, +	{0x0000a030, 0x03840383}, +	{0x0000a034, 0x03880385}, +	{0x0000a038, 0x038a0389}, +	{0x0000a03c, 0x038c038b}, +	{0x0000a040, 0x0390038d}, +	{0x0000a044, 0x03920391}, +	{0x0000a048, 0x03940393}, +	{0x0000a04c, 0x03960395}, +	{0x0000a050, 0x00000000}, +	{0x0000a054, 0x00000000}, +	{0x0000a058, 0x00000000}, +	{0x0000a05c, 0x00000000}, +	{0x0000a060, 0x00000000}, +	{0x0000a064, 0x00000000}, +	{0x0000a068, 0x00000000}, +	{0x0000a06c, 0x00000000}, +	{0x0000a070, 0x00000000}, +	{0x0000a074, 0x00000000}, +	{0x0000a078, 0x00000000}, +	{0x0000a07c, 0x00000000}, +	{0x0000a080, 0x29292929}, +	{0x0000a084, 0x29292929}, +	{0x0000a088, 0x29292929}, +	{0x0000a08c, 0x29292929}, +	{0x0000a090, 0x22292929}, +	{0x0000a094, 0x1d1d2222}, +	{0x0000a098, 0x0c111117}, +	{0x0000a09c, 0x00030303}, +	{0x0000a0a0, 0x00000000}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x001f0000}, +	{0x0000a0c4, 0x01000101}, +	{0x0000a0c8, 0x011e011f}, +	{0x0000a0cc, 0x011c011d}, +	{0x0000a0d0, 0x02030204}, +	{0x0000a0d4, 0x02010202}, +	{0x0000a0d8, 0x021f0200}, +	{0x0000a0dc, 0x0302021e}, +	{0x0000a0e0, 0x03000301}, +	{0x0000a0e4, 0x031e031f}, +	{0x0000a0e8, 0x0402031d}, +	{0x0000a0ec, 0x04000401}, +	{0x0000a0f0, 0x041e041f}, +	{0x0000a0f4, 0x0502041d}, +	{0x0000a0f8, 0x05000501}, +	{0x0000a0fc, 0x051e051f}, +	{0x0000a100, 0x06010602}, +	{0x0000a104, 0x061f0600}, +	{0x0000a108, 0x061d061e}, +	{0x0000a10c, 0x07020703}, +	{0x0000a110, 0x07000701}, +	{0x0000a114, 0x00000000}, +	{0x0000a118, 0x00000000}, +	{0x0000a11c, 0x00000000}, +	{0x0000a120, 0x00000000}, +	{0x0000a124, 0x00000000}, +	{0x0000a128, 0x00000000}, +	{0x0000a12c, 0x00000000}, +	{0x0000a130, 0x00000000}, +	{0x0000a134, 0x00000000}, +	{0x0000a138, 0x00000000}, +	{0x0000a13c, 0x00000000}, +	{0x0000a140, 0x001f0000}, +	{0x0000a144, 0x01000101}, +	{0x0000a148, 0x011e011f}, +	{0x0000a14c, 0x011c011d}, +	{0x0000a150, 0x02030204}, +	{0x0000a154, 0x02010202}, +	{0x0000a158, 0x021f0200}, +	{0x0000a15c, 0x0302021e}, +	{0x0000a160, 0x03000301}, +	{0x0000a164, 0x031e031f}, +	{0x0000a168, 0x0402031d}, +	{0x0000a16c, 0x04000401}, +	{0x0000a170, 0x041e041f}, +	{0x0000a174, 0x0502041d}, +	{0x0000a178, 0x05000501}, +	{0x0000a17c, 0x051e051f}, +	{0x0000a180, 0x06010602}, +	{0x0000a184, 0x061f0600}, +	{0x0000a188, 0x061d061e}, +	{0x0000a18c, 0x07020703}, +	{0x0000a190, 0x07000701}, +	{0x0000a194, 0x00000000}, +	{0x0000a198, 0x00000000}, +	{0x0000a19c, 0x00000000}, +	{0x0000a1a0, 0x00000000}, +	{0x0000a1a4, 0x00000000}, +	{0x0000a1a8, 0x00000000}, +	{0x0000a1ac, 0x00000000}, +	{0x0000a1b0, 0x00000000}, +	{0x0000a1b4, 0x00000000}, +	{0x0000a1b8, 0x00000000}, +	{0x0000a1bc, 0x00000000}, +	{0x0000a1c0, 0x00000000}, +	{0x0000a1c4, 0x00000000}, +	{0x0000a1c8, 0x00000000}, +	{0x0000a1cc, 0x00000000}, +	{0x0000a1d0, 0x00000000}, +	{0x0000a1d4, 0x00000000}, +	{0x0000a1d8, 0x00000000}, +	{0x0000a1dc, 0x00000000}, +	{0x0000a1e0, 0x00000000}, +	{0x0000a1e4, 0x00000000}, +	{0x0000a1e8, 0x00000000}, +	{0x0000a1ec, 0x00000000}, +	{0x0000a1f0, 0x00000396}, +	{0x0000a1f4, 0x00000396}, +	{0x0000a1f8, 0x00000396}, +	{0x0000a1fc, 0x00000196}, +	{0x0000b000, 0x00010000}, +	{0x0000b004, 0x00030002}, +	{0x0000b008, 0x00050004}, +	{0x0000b00c, 0x00810080}, +	{0x0000b010, 0x00830082}, +	{0x0000b014, 0x01810180}, +	{0x0000b018, 0x01830182}, +	{0x0000b01c, 0x01850184}, +	{0x0000b020, 0x02810280}, +	{0x0000b024, 0x02830282}, +	{0x0000b028, 0x02850284}, +	{0x0000b02c, 0x02890288}, +	{0x0000b030, 0x028b028a}, +	{0x0000b034, 0x0388028c}, +	{0x0000b038, 0x038a0389}, +	{0x0000b03c, 0x038c038b}, +	{0x0000b040, 0x0390038d}, +	{0x0000b044, 0x03920391}, +	{0x0000b048, 0x03940393}, +	{0x0000b04c, 0x03960395}, +	{0x0000b050, 0x00000000}, +	{0x0000b054, 0x00000000}, +	{0x0000b058, 0x00000000}, +	{0x0000b05c, 0x00000000}, +	{0x0000b060, 0x00000000}, +	{0x0000b064, 0x00000000}, +	{0x0000b068, 0x00000000}, +	{0x0000b06c, 0x00000000}, +	{0x0000b070, 0x00000000}, +	{0x0000b074, 0x00000000}, +	{0x0000b078, 0x00000000}, +	{0x0000b07c, 0x00000000}, +	{0x0000b080, 0x32323232}, +	{0x0000b084, 0x2f2f3232}, +	{0x0000b088, 0x23282a2d}, +	{0x0000b08c, 0x1c1e2123}, +	{0x0000b090, 0x14171919}, +	{0x0000b094, 0x0e0e1214}, +	{0x0000b098, 0x03050707}, +	{0x0000b09c, 0x00030303}, +	{0x0000b0a0, 0x00000000}, +	{0x0000b0a4, 0x00000000}, +	{0x0000b0a8, 0x00000000}, +	{0x0000b0ac, 0x00000000}, +	{0x0000b0b0, 0x00000000}, +	{0x0000b0b4, 0x00000000}, +	{0x0000b0b8, 0x00000000}, +	{0x0000b0bc, 0x00000000}, +	{0x0000b0c0, 0x003f0020}, +	{0x0000b0c4, 0x00400041}, +	{0x0000b0c8, 0x0140005f}, +	{0x0000b0cc, 0x0160015f}, +	{0x0000b0d0, 0x017e017f}, +	{0x0000b0d4, 0x02410242}, +	{0x0000b0d8, 0x025f0240}, +	{0x0000b0dc, 0x027f0260}, +	{0x0000b0e0, 0x0341027e}, +	{0x0000b0e4, 0x035f0340}, +	{0x0000b0e8, 0x037f0360}, +	{0x0000b0ec, 0x04400441}, +	{0x0000b0f0, 0x0460045f}, +	{0x0000b0f4, 0x0541047f}, +	{0x0000b0f8, 0x055f0540}, +	{0x0000b0fc, 0x057f0560}, +	{0x0000b100, 0x06400641}, +	{0x0000b104, 0x0660065f}, +	{0x0000b108, 0x067e067f}, +	{0x0000b10c, 0x07410742}, +	{0x0000b110, 0x075f0740}, +	{0x0000b114, 0x077f0760}, +	{0x0000b118, 0x07800781}, +	{0x0000b11c, 0x07a0079f}, +	{0x0000b120, 0x07c107bf}, +	{0x0000b124, 0x000007c0}, +	{0x0000b128, 0x00000000}, +	{0x0000b12c, 0x00000000}, +	{0x0000b130, 0x00000000}, +	{0x0000b134, 0x00000000}, +	{0x0000b138, 0x00000000}, +	{0x0000b13c, 0x00000000}, +	{0x0000b140, 0x003f0020}, +	{0x0000b144, 0x00400041}, +	{0x0000b148, 0x0140005f}, +	{0x0000b14c, 0x0160015f}, +	{0x0000b150, 0x017e017f}, +	{0x0000b154, 0x02410242}, +	{0x0000b158, 0x025f0240}, +	{0x0000b15c, 0x027f0260}, +	{0x0000b160, 0x0341027e}, +	{0x0000b164, 0x035f0340}, +	{0x0000b168, 0x037f0360}, +	{0x0000b16c, 0x04400441}, +	{0x0000b170, 0x0460045f}, +	{0x0000b174, 0x0541047f}, +	{0x0000b178, 0x055f0540}, +	{0x0000b17c, 0x057f0560}, +	{0x0000b180, 0x06400641}, +	{0x0000b184, 0x0660065f}, +	{0x0000b188, 0x067e067f}, +	{0x0000b18c, 0x07410742}, +	{0x0000b190, 0x075f0740}, +	{0x0000b194, 0x077f0760}, +	{0x0000b198, 0x07800781}, +	{0x0000b19c, 0x07a0079f}, +	{0x0000b1a0, 0x07c107bf}, +	{0x0000b1a4, 0x000007c0}, +	{0x0000b1a8, 0x00000000}, +	{0x0000b1ac, 0x00000000}, +	{0x0000b1b0, 0x00000000}, +	{0x0000b1b4, 0x00000000}, +	{0x0000b1b8, 0x00000000}, +	{0x0000b1bc, 0x00000000}, +	{0x0000b1c0, 0x00000000}, +	{0x0000b1c4, 0x00000000}, +	{0x0000b1c8, 0x00000000}, +	{0x0000b1cc, 0x00000000}, +	{0x0000b1d0, 0x00000000}, +	{0x0000b1d4, 0x00000000}, +	{0x0000b1d8, 0x00000000}, +	{0x0000b1dc, 0x00000000}, +	{0x0000b1e0, 0x00000000}, +	{0x0000b1e4, 0x00000000}, +	{0x0000b1e8, 0x00000000}, +	{0x0000b1ec, 0x00000000}, +	{0x0000b1f0, 0x00000396}, +	{0x0000b1f4, 0x00000396}, +	{0x0000b1f8, 0x00000396}, +	{0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9580_1p0_soc_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, +}; + +static const u32 ar9580_1p0_high_ob_db_tx_gain_table[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x0000a2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, +	{0x0000a2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, +	{0x0000a2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, +	{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, +	{0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, +	{0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, +	{0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, +	{0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, +	{0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, +	{0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, +	{0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, +	{0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, +	{0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, +	{0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, +	{0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, +	{0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, +	{0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, +	{0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, +	{0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, +	{0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, +	{0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, +	{0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, +	{0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, +	{0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, +	{0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, +	{0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, +	{0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, +	{0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, +	{0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, +	{0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, +	{0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, +	{0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, +	{0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, +	{0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, +	{0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, +	{0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, +	{0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, +	{0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, +	{0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, +	{0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, +	{0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, +	{0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, +	{0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, +	{0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, +	{0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, +	{0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, +	{0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, +	{0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, +	{0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, +	{0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, +	{0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, +	{0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, +	{0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, +	{0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, +	{0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, +	{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, +	{0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, +	{0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, +	{0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, +	{0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, +	{0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, +	{0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, +	{0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, +	{0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, +	{0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, +	{0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, +	{0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, +	{0x0000b2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, +	{0x0000b2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, +	{0x0000b2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x0000c2dc, 0x01feee00, 0x01feee00, 0x03aaa352, 0x03aaa352}, +	{0x0000c2e0, 0x0000f000, 0x0000f000, 0x03ccc584, 0x03ccc584}, +	{0x0000c2e4, 0x01ff0000, 0x01ff0000, 0x03f0f800, 0x03f0f800}, +	{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, +	{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, +	{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, +	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, +	{0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, +	{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +	{0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, +	{0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, +	{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, +}; + +static const u32 ar9580_1p0_soc_preamble[][2] = { +	/* Addr      allmodes  */ +	{0x000040a4, 0x00a0c1c9}, +	{0x00007008, 0x00000000}, +	{0x00007020, 0x00000000}, +	{0x00007034, 0x00000002}, +	{0x00007038, 0x000004c2}, +	{0x00007048, 0x00000008}, +}; + +static const u32 ar9580_1p0_rx_gain_table[][2] = { +	/* Addr      allmodes  */ +	{0x0000a000, 0x00010000}, +	{0x0000a004, 0x00030002}, +	{0x0000a008, 0x00050004}, +	{0x0000a00c, 0x00810080}, +	{0x0000a010, 0x00830082}, +	{0x0000a014, 0x01810180}, +	{0x0000a018, 0x01830182}, +	{0x0000a01c, 0x01850184}, +	{0x0000a020, 0x01890188}, +	{0x0000a024, 0x018b018a}, +	{0x0000a028, 0x018d018c}, +	{0x0000a02c, 0x01910190}, +	{0x0000a030, 0x01930192}, +	{0x0000a034, 0x01950194}, +	{0x0000a038, 0x038a0196}, +	{0x0000a03c, 0x038c038b}, +	{0x0000a040, 0x0390038d}, +	{0x0000a044, 0x03920391}, +	{0x0000a048, 0x03940393}, +	{0x0000a04c, 0x03960395}, +	{0x0000a050, 0x00000000}, +	{0x0000a054, 0x00000000}, +	{0x0000a058, 0x00000000}, +	{0x0000a05c, 0x00000000}, +	{0x0000a060, 0x00000000}, +	{0x0000a064, 0x00000000}, +	{0x0000a068, 0x00000000}, +	{0x0000a06c, 0x00000000}, +	{0x0000a070, 0x00000000}, +	{0x0000a074, 0x00000000}, +	{0x0000a078, 0x00000000}, +	{0x0000a07c, 0x00000000}, +	{0x0000a080, 0x22222229}, +	{0x0000a084, 0x1d1d1d1d}, +	{0x0000a088, 0x1d1d1d1d}, +	{0x0000a08c, 0x1d1d1d1d}, +	{0x0000a090, 0x171d1d1d}, +	{0x0000a094, 0x11111717}, +	{0x0000a098, 0x00030311}, +	{0x0000a09c, 0x00000000}, +	{0x0000a0a0, 0x00000000}, +	{0x0000a0a4, 0x00000000}, +	{0x0000a0a8, 0x00000000}, +	{0x0000a0ac, 0x00000000}, +	{0x0000a0b0, 0x00000000}, +	{0x0000a0b4, 0x00000000}, +	{0x0000a0b8, 0x00000000}, +	{0x0000a0bc, 0x00000000}, +	{0x0000a0c0, 0x001f0000}, +	{0x0000a0c4, 0x01000101}, +	{0x0000a0c8, 0x011e011f}, +	{0x0000a0cc, 0x011c011d}, +	{0x0000a0d0, 0x02030204}, +	{0x0000a0d4, 0x02010202}, +	{0x0000a0d8, 0x021f0200}, +	{0x0000a0dc, 0x0302021e}, +	{0x0000a0e0, 0x03000301}, +	{0x0000a0e4, 0x031e031f}, +	{0x0000a0e8, 0x0402031d}, +	{0x0000a0ec, 0x04000401}, +	{0x0000a0f0, 0x041e041f}, +	{0x0000a0f4, 0x0502041d}, +	{0x0000a0f8, 0x05000501}, +	{0x0000a0fc, 0x051e051f}, +	{0x0000a100, 0x06010602}, +	{0x0000a104, 0x061f0600}, +	{0x0000a108, 0x061d061e}, +	{0x0000a10c, 0x07020703}, +	{0x0000a110, 0x07000701}, +	{0x0000a114, 0x00000000}, +	{0x0000a118, 0x00000000}, +	{0x0000a11c, 0x00000000}, +	{0x0000a120, 0x00000000}, +	{0x0000a124, 0x00000000}, +	{0x0000a128, 0x00000000}, +	{0x0000a12c, 0x00000000}, +	{0x0000a130, 0x00000000}, +	{0x0000a134, 0x00000000}, +	{0x0000a138, 0x00000000}, +	{0x0000a13c, 0x00000000}, +	{0x0000a140, 0x001f0000}, +	{0x0000a144, 0x01000101}, +	{0x0000a148, 0x011e011f}, +	{0x0000a14c, 0x011c011d}, +	{0x0000a150, 0x02030204}, +	{0x0000a154, 0x02010202}, +	{0x0000a158, 0x021f0200}, +	{0x0000a15c, 0x0302021e}, +	{0x0000a160, 0x03000301}, +	{0x0000a164, 0x031e031f}, +	{0x0000a168, 0x0402031d}, +	{0x0000a16c, 0x04000401}, +	{0x0000a170, 0x041e041f}, +	{0x0000a174, 0x0502041d}, +	{0x0000a178, 0x05000501}, +	{0x0000a17c, 0x051e051f}, +	{0x0000a180, 0x06010602}, +	{0x0000a184, 0x061f0600}, +	{0x0000a188, 0x061d061e}, +	{0x0000a18c, 0x07020703}, +	{0x0000a190, 0x07000701}, +	{0x0000a194, 0x00000000}, +	{0x0000a198, 0x00000000}, +	{0x0000a19c, 0x00000000}, +	{0x0000a1a0, 0x00000000}, +	{0x0000a1a4, 0x00000000}, +	{0x0000a1a8, 0x00000000}, +	{0x0000a1ac, 0x00000000}, +	{0x0000a1b0, 0x00000000}, +	{0x0000a1b4, 0x00000000}, +	{0x0000a1b8, 0x00000000}, +	{0x0000a1bc, 0x00000000}, +	{0x0000a1c0, 0x00000000}, +	{0x0000a1c4, 0x00000000}, +	{0x0000a1c8, 0x00000000}, +	{0x0000a1cc, 0x00000000}, +	{0x0000a1d0, 0x00000000}, +	{0x0000a1d4, 0x00000000}, +	{0x0000a1d8, 0x00000000}, +	{0x0000a1dc, 0x00000000}, +	{0x0000a1e0, 0x00000000}, +	{0x0000a1e4, 0x00000000}, +	{0x0000a1e8, 0x00000000}, +	{0x0000a1ec, 0x00000000}, +	{0x0000a1f0, 0x00000396}, +	{0x0000a1f4, 0x00000396}, +	{0x0000a1f8, 0x00000396}, +	{0x0000a1fc, 0x00000196}, +	{0x0000b000, 0x00010000}, +	{0x0000b004, 0x00030002}, +	{0x0000b008, 0x00050004}, +	{0x0000b00c, 0x00810080}, +	{0x0000b010, 0x00830082}, +	{0x0000b014, 0x01810180}, +	{0x0000b018, 0x01830182}, +	{0x0000b01c, 0x01850184}, +	{0x0000b020, 0x02810280}, +	{0x0000b024, 0x02830282}, +	{0x0000b028, 0x02850284}, +	{0x0000b02c, 0x02890288}, +	{0x0000b030, 0x028b028a}, +	{0x0000b034, 0x0388028c}, +	{0x0000b038, 0x038a0389}, +	{0x0000b03c, 0x038c038b}, +	{0x0000b040, 0x0390038d}, +	{0x0000b044, 0x03920391}, +	{0x0000b048, 0x03940393}, +	{0x0000b04c, 0x03960395}, +	{0x0000b050, 0x00000000}, +	{0x0000b054, 0x00000000}, +	{0x0000b058, 0x00000000}, +	{0x0000b05c, 0x00000000}, +	{0x0000b060, 0x00000000}, +	{0x0000b064, 0x00000000}, +	{0x0000b068, 0x00000000}, +	{0x0000b06c, 0x00000000}, +	{0x0000b070, 0x00000000}, +	{0x0000b074, 0x00000000}, +	{0x0000b078, 0x00000000}, +	{0x0000b07c, 0x00000000}, +	{0x0000b080, 0x2a2d2f32}, +	{0x0000b084, 0x21232328}, +	{0x0000b088, 0x19191c1e}, +	{0x0000b08c, 0x12141417}, +	{0x0000b090, 0x07070e0e}, +	{0x0000b094, 0x03030305}, +	{0x0000b098, 0x00000003}, +	{0x0000b09c, 0x00000000}, +	{0x0000b0a0, 0x00000000}, +	{0x0000b0a4, 0x00000000}, +	{0x0000b0a8, 0x00000000}, +	{0x0000b0ac, 0x00000000}, +	{0x0000b0b0, 0x00000000}, +	{0x0000b0b4, 0x00000000}, +	{0x0000b0b8, 0x00000000}, +	{0x0000b0bc, 0x00000000}, +	{0x0000b0c0, 0x003f0020}, +	{0x0000b0c4, 0x00400041}, +	{0x0000b0c8, 0x0140005f}, +	{0x0000b0cc, 0x0160015f}, +	{0x0000b0d0, 0x017e017f}, +	{0x0000b0d4, 0x02410242}, +	{0x0000b0d8, 0x025f0240}, +	{0x0000b0dc, 0x027f0260}, +	{0x0000b0e0, 0x0341027e}, +	{0x0000b0e4, 0x035f0340}, +	{0x0000b0e8, 0x037f0360}, +	{0x0000b0ec, 0x04400441}, +	{0x0000b0f0, 0x0460045f}, +	{0x0000b0f4, 0x0541047f}, +	{0x0000b0f8, 0x055f0540}, +	{0x0000b0fc, 0x057f0560}, +	{0x0000b100, 0x06400641}, +	{0x0000b104, 0x0660065f}, +	{0x0000b108, 0x067e067f}, +	{0x0000b10c, 0x07410742}, +	{0x0000b110, 0x075f0740}, +	{0x0000b114, 0x077f0760}, +	{0x0000b118, 0x07800781}, +	{0x0000b11c, 0x07a0079f}, +	{0x0000b120, 0x07c107bf}, +	{0x0000b124, 0x000007c0}, +	{0x0000b128, 0x00000000}, +	{0x0000b12c, 0x00000000}, +	{0x0000b130, 0x00000000}, +	{0x0000b134, 0x00000000}, +	{0x0000b138, 0x00000000}, +	{0x0000b13c, 0x00000000}, +	{0x0000b140, 0x003f0020}, +	{0x0000b144, 0x00400041}, +	{0x0000b148, 0x0140005f}, +	{0x0000b14c, 0x0160015f}, +	{0x0000b150, 0x017e017f}, +	{0x0000b154, 0x02410242}, +	{0x0000b158, 0x025f0240}, +	{0x0000b15c, 0x027f0260}, +	{0x0000b160, 0x0341027e}, +	{0x0000b164, 0x035f0340}, +	{0x0000b168, 0x037f0360}, +	{0x0000b16c, 0x04400441}, +	{0x0000b170, 0x0460045f}, +	{0x0000b174, 0x0541047f}, +	{0x0000b178, 0x055f0540}, +	{0x0000b17c, 0x057f0560}, +	{0x0000b180, 0x06400641}, +	{0x0000b184, 0x0660065f}, +	{0x0000b188, 0x067e067f}, +	{0x0000b18c, 0x07410742}, +	{0x0000b190, 0x075f0740}, +	{0x0000b194, 0x077f0760}, +	{0x0000b198, 0x07800781}, +	{0x0000b19c, 0x07a0079f}, +	{0x0000b1a0, 0x07c107bf}, +	{0x0000b1a4, 0x000007c0}, +	{0x0000b1a8, 0x00000000}, +	{0x0000b1ac, 0x00000000}, +	{0x0000b1b0, 0x00000000}, +	{0x0000b1b4, 0x00000000}, +	{0x0000b1b8, 0x00000000}, +	{0x0000b1bc, 0x00000000}, +	{0x0000b1c0, 0x00000000}, +	{0x0000b1c4, 0x00000000}, +	{0x0000b1c8, 0x00000000}, +	{0x0000b1cc, 0x00000000}, +	{0x0000b1d0, 0x00000000}, +	{0x0000b1d4, 0x00000000}, +	{0x0000b1d8, 0x00000000}, +	{0x0000b1dc, 0x00000000}, +	{0x0000b1e0, 0x00000000}, +	{0x0000b1e4, 0x00000000}, +	{0x0000b1e8, 0x00000000}, +	{0x0000b1ec, 0x00000000}, +	{0x0000b1f0, 0x00000396}, +	{0x0000b1f4, 0x00000396}, +	{0x0000b1f8, 0x00000396}, +	{0x0000b1fc, 0x00000196}, +}; + +static const u32 ar9580_1p0_radio_core[][2] = { +	/* Addr      allmodes  */ +	{0x00016000, 0x36db6db6}, +	{0x00016004, 0x6db6db40}, +	{0x00016008, 0x73f00000}, +	{0x0001600c, 0x00000000}, +	{0x00016040, 0x7f80fff8}, +	{0x0001604c, 0x76d005b5}, +	{0x00016050, 0x556cf031}, +	{0x00016054, 0x13449440}, +	{0x00016058, 0x0c51c92c}, +	{0x0001605c, 0x3db7fffc}, +	{0x00016060, 0xfffffffc}, +	{0x00016064, 0x000f0278}, +	{0x0001606c, 0x6db60000}, +	{0x00016080, 0x00000000}, +	{0x00016084, 0x0e48048c}, +	{0x00016088, 0x54214514}, +	{0x0001608c, 0x119f481e}, +	{0x00016090, 0x24926490}, +	{0x00016098, 0xd2888888}, +	{0x000160a0, 0x0a108ffe}, +	{0x000160a4, 0x812fc370}, +	{0x000160a8, 0x423c8000}, +	{0x000160b4, 0x92480080}, +	{0x000160c0, 0x00adb6d0}, +	{0x000160c4, 0x6db6db60}, +	{0x000160c8, 0x6db6db6c}, +	{0x000160cc, 0x01e6c000}, +	{0x00016100, 0x3fffbe01}, +	{0x00016104, 0xfff80000}, +	{0x00016108, 0x00080010}, +	{0x00016144, 0x02084080}, +	{0x00016148, 0x00000000}, +	{0x00016280, 0x058a0001}, +	{0x00016284, 0x3d840208}, +	{0x00016288, 0x05a20408}, +	{0x0001628c, 0x00038c07}, +	{0x00016290, 0x00000004}, +	{0x00016294, 0x458aa14f}, +	{0x00016380, 0x00000000}, +	{0x00016384, 0x00000000}, +	{0x00016388, 0x00800700}, +	{0x0001638c, 0x00800700}, +	{0x00016390, 0x00800700}, +	{0x00016394, 0x00000000}, +	{0x00016398, 0x00000000}, +	{0x0001639c, 0x00000000}, +	{0x000163a0, 0x00000001}, +	{0x000163a4, 0x00000001}, +	{0x000163a8, 0x00000000}, +	{0x000163ac, 0x00000000}, +	{0x000163b0, 0x00000000}, +	{0x000163b4, 0x00000000}, +	{0x000163b8, 0x00000000}, +	{0x000163bc, 0x00000000}, +	{0x000163c0, 0x000000a0}, +	{0x000163c4, 0x000c0000}, +	{0x000163c8, 0x14021402}, +	{0x000163cc, 0x00001402}, +	{0x000163d0, 0x00000000}, +	{0x000163d4, 0x00000000}, +	{0x00016400, 0x36db6db6}, +	{0x00016404, 0x6db6db40}, +	{0x00016408, 0x73f00000}, +	{0x0001640c, 0x00000000}, +	{0x00016440, 0x7f80fff8}, +	{0x0001644c, 0x76d005b5}, +	{0x00016450, 0x556cf031}, +	{0x00016454, 0x13449440}, +	{0x00016458, 0x0c51c92c}, +	{0x0001645c, 0x3db7fffc}, +	{0x00016460, 0xfffffffc}, +	{0x00016464, 0x000f0278}, +	{0x0001646c, 0x6db60000}, +	{0x00016500, 0x3fffbe01}, +	{0x00016504, 0xfff80000}, +	{0x00016508, 0x00080010}, +	{0x00016544, 0x02084080}, +	{0x00016548, 0x00000000}, +	{0x00016780, 0x00000000}, +	{0x00016784, 0x00000000}, +	{0x00016788, 0x00800700}, +	{0x0001678c, 0x00800700}, +	{0x00016790, 0x00800700}, +	{0x00016794, 0x00000000}, +	{0x00016798, 0x00000000}, +	{0x0001679c, 0x00000000}, +	{0x000167a0, 0x00000001}, +	{0x000167a4, 0x00000001}, +	{0x000167a8, 0x00000000}, +	{0x000167ac, 0x00000000}, +	{0x000167b0, 0x00000000}, +	{0x000167b4, 0x00000000}, +	{0x000167b8, 0x00000000}, +	{0x000167bc, 0x00000000}, +	{0x000167c0, 0x000000a0}, +	{0x000167c4, 0x000c0000}, +	{0x000167c8, 0x14021402}, +	{0x000167cc, 0x00001402}, +	{0x000167d0, 0x00000000}, +	{0x000167d4, 0x00000000}, +	{0x00016800, 0x36db6db6}, +	{0x00016804, 0x6db6db40}, +	{0x00016808, 0x73f00000}, +	{0x0001680c, 0x00000000}, +	{0x00016840, 0x7f80fff8}, +	{0x0001684c, 0x76d005b5}, +	{0x00016850, 0x556cf031}, +	{0x00016854, 0x13449440}, +	{0x00016858, 0x0c51c92c}, +	{0x0001685c, 0x3db7fffc}, +	{0x00016860, 0xfffffffc}, +	{0x00016864, 0x000f0278}, +	{0x0001686c, 0x6db60000}, +	{0x00016900, 0x3fffbe01}, +	{0x00016904, 0xfff80000}, +	{0x00016908, 0x00080010}, +	{0x00016944, 0x02084080}, +	{0x00016948, 0x00000000}, +	{0x00016b80, 0x00000000}, +	{0x00016b84, 0x00000000}, +	{0x00016b88, 0x00800700}, +	{0x00016b8c, 0x00800700}, +	{0x00016b90, 0x00800700}, +	{0x00016b94, 0x00000000}, +	{0x00016b98, 0x00000000}, +	{0x00016b9c, 0x00000000}, +	{0x00016ba0, 0x00000001}, +	{0x00016ba4, 0x00000001}, +	{0x00016ba8, 0x00000000}, +	{0x00016bac, 0x00000000}, +	{0x00016bb0, 0x00000000}, +	{0x00016bb4, 0x00000000}, +	{0x00016bb8, 0x00000000}, +	{0x00016bbc, 0x00000000}, +	{0x00016bc0, 0x000000a0}, +	{0x00016bc4, 0x000c0000}, +	{0x00016bc8, 0x14021402}, +	{0x00016bcc, 0x00001402}, +	{0x00016bd0, 0x00000000}, +	{0x00016bd4, 0x00000000}, +}; + +static const u32 ar9580_1p0_baseband_postamble[][5] = { +	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */ +	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, +	{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, +	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, +	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, +	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, +	{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, +	{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4}, +	{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0}, +	{0x00009e04, 0x001c2020, 0x001c2020, 0x001c2020, 0x001c2020}, +	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, +	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, +	{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e}, +	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, +	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, +	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, +	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, +	{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, +	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, +	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, +	{0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0}, +	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, +	{0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f}, +	{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, +	{0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff}, +	{0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018}, +	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, +	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, +	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, +	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, +	{0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, +	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, +	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, +	{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +	{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, +	{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, +	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, +	{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, +	{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, +	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000ae04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, +	{0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, +	{0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +	{0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000be04, 0x001c0000, 0x001c0000, 0x001c0000, 0x001c0000}, +	{0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, +	{0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, +	{0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, +	{0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, +}; + +static const u32 ar9580_1p0_pcie_phy_clkreq_enable_L1[][2] = { +	/* Addr      allmodes  */ +	{0x00004040, 0x0835365e}, +	{0x00004040, 0x0008003b}, +	{0x00004044, 0x00000000}, +}; + +static const u32 ar9580_1p0_pcie_phy_clkreq_disable_L1[][2] = { +	/* Addr      allmodes  */ +	{0x00004040, 0x0831365e}, +	{0x00004040, 0x0008003b}, +	{0x00004044, 0x00000000}, +}; + +static const u32 ar9580_1p0_pcie_phy_pll_on_clkreq[][2] = { +	/* Addr      allmodes  */ +	{0x00004040, 0x0831265e}, +	{0x00004040, 0x0008003b}, +	{0x00004044, 0x00000000}, +}; + +#endif /* INITVALS_9580_1P0_H */ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index c03949eb37c..3a893e19d6c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -558,8 +558,7 @@ struct ath_ant_comb {  #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)  #define SC_OP_BT_SCAN		     BIT(13)  #define SC_OP_ANI_RUN		     BIT(14) -#define SC_OP_ENABLE_APM	     BIT(15) -#define SC_OP_PRIM_STA_VIF	     BIT(16) +#define SC_OP_PRIM_STA_VIF	     BIT(15)  /* Powersave flags */  #define PS_WAIT_FOR_BEACON        BIT(0) @@ -664,7 +663,6 @@ extern int led_blink;  extern bool is_ath9k_unloaded;  irqreturn_t ath_isr(int irq, void *dev); -void ath9k_init_crypto(struct ath_softc *sc);  int ath9k_init_device(u16 devid, struct ath_softc *sc,  		    const struct ath_bus_ops *bus_ops);  void ath9k_deinit_device(struct ath_softc *sc); diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index ac2da3cce78..ebaf304f464 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -82,7 +82,6 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,  					      int16_t *nfarray)  {  	struct ath_common *common = ath9k_hw_common(ah); -	struct ieee80211_conf *conf = &common->hw->conf;  	struct ath_nf_limits *limit;  	struct ath9k_nfcal_hist *h;  	bool high_nf_mid = false; @@ -94,7 +93,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,  	for (i = 0; i < NUM_NF_READINGS; i++) {  		if (!(chainmask & (1 << i)) || -		    ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) +		    ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))  			continue;  		h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index fa6bd2d189e..dc705a22495 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c @@ -169,6 +169,32 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,  }  EXPORT_SYMBOL(ath9k_cmn_update_txpow); +void ath9k_cmn_init_crypto(struct ath_hw *ah) +{ +	struct ath_common *common = ath9k_hw_common(ah); +	int i = 0; + +	/* Get the hardware key cache size. */ +	common->keymax = AR_KEYTABLE_SIZE; + +	/* +	 * Check whether the separate key cache entries +	 * are required to handle both tx+rx MIC keys. +	 * With split mic keys the number of stations is limited +	 * to 27 otherwise 59. +	 */ +	if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) +		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; + +	/* +	 * Reset the key cache since some parts do not +	 * reset the contents on initial power up. +	 */ +	for (i = 0; i < common->keymax; i++) +		ath_hw_keyreset(common, (u16) i); +} +EXPORT_SYMBOL(ath9k_cmn_init_crypto); +  static int __init ath9k_cmn_init(void)  {  	return 0; diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 77ec288b5a7..ad14fecc76c 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -62,3 +62,4 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,  				  enum ath_stomp_type stomp_type);  void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,  			    u16 new_txpow, u16 *txpower); +void ath9k_cmn_init_crypto(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 9bec3b89fb6..da45f325be7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -1163,6 +1163,59 @@ static const struct file_operations fops_regdump = {  	.llseek = default_llseek,/* read accesses f_pos */  }; +static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf, +				    size_t count, loff_t *ppos) +{ +	struct ath_softc *sc = file->private_data; +	struct ath_hw *ah = sc->sc_ah; +	struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist; +	struct ath_common *common = ath9k_hw_common(ah); +	struct ieee80211_conf *conf = &common->hw->conf; +	u32 len = 0, size = 1500; +	u32 i, j; +	ssize_t retval = 0; +	char *buf; +	u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; +	u8 nread; + +	buf = kzalloc(size, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	len += snprintf(buf + len, size - len, +			"Channel Noise Floor : %d\n", ah->noise); +	len += snprintf(buf + len, size - len, +			"Chain | privNF | # Readings | NF Readings\n"); +	for (i = 0; i < NUM_NF_READINGS; i++) { +		if (!(chainmask & (1 << i)) || +		    ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) +			continue; + +		nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount; +		len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t", +				i, h[i].privNF, nread); +		for (j = 0; j < nread; j++) +			len += snprintf(buf + len, size - len, +					" %d", h[i].nfCalBuffer[j]); +		len += snprintf(buf + len, size - len, "\n"); +	} + +	if (len > size) +		len = size; + +	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); +	kfree(buf); + +	return retval; +} + +static const struct file_operations fops_dump_nfcal = { +	.read = read_file_dump_nfcal, +	.open = ath9k_debugfs_open, +	.owner = THIS_MODULE, +	.llseek = default_llseek, +}; +  static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,  				     size_t count, loff_t *ppos)  { @@ -1262,6 +1315,8 @@ int ath9k_init_debug(struct ath_hw *ah)  			    &ah->config.cwm_ignore_extcca);  	debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,  			    &fops_regdump); +	debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc, +			    &fops_dump_nfcal);  	debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,  			    &fops_base_eeprom);  	debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 19aa5b72488..9cf42f6973a 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -572,25 +572,6 @@ err:  	return -EINVAL;  } -static void ath9k_init_crypto(struct ath9k_htc_priv *priv) -{ -	struct ath_common *common = ath9k_hw_common(priv->ah); -	int i = 0; - -	/* Get the hardware key cache size. */ -	common->keymax = AR_KEYTABLE_SIZE; - -	if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) -		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; - -	/* -	 * Reset the key cache since some parts do not -	 * reset the contents on initial power up. -	 */ -	for (i = 0; i < common->keymax; i++) -		ath_hw_keyreset(common, (u16) i); -} -  static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)  {  	if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { @@ -720,7 +701,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,  	for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)  		priv->cur_beacon_conf.bslot[i] = NULL; -	ath9k_init_crypto(priv); +	ath9k_cmn_init_crypto(ah);  	ath9k_init_channels_rates(priv);  	ath9k_init_misc(priv); diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7212acb2bd6..0248024da56 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1736,6 +1736,22 @@ out:  	return ret;  } + +static int ath9k_htc_get_stats(struct ieee80211_hw *hw, +			       struct ieee80211_low_level_stats *stats) +{ +	struct ath9k_htc_priv *priv = hw->priv; +	struct ath_hw *ah = priv->ah; +	struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; + +	stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; +	stats->dot11RTSFailureCount = mib_stats->rts_bad; +	stats->dot11FCSErrorCount = mib_stats->fcs_bad; +	stats->dot11RTSSuccessCount = mib_stats->rts_good; + +	return 0; +} +  struct ieee80211_ops ath9k_htc_ops = {  	.tx                 = ath9k_htc_tx,  	.start              = ath9k_htc_start, @@ -1759,4 +1775,5 @@ struct ieee80211_ops ath9k_htc_ops = {  	.rfkill_poll        = ath9k_htc_rfkill_poll_state,  	.set_coverage_class = ath9k_htc_set_coverage_class,  	.set_bitrate_mask   = ath9k_htc_set_bitrate_mask, +	.get_stats	    = ath9k_htc_get_stats,  }; diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index cb29e887538..dd9003ee123 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h @@ -22,10 +22,12 @@  /* Hardware core and driver accessible callbacks */  static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, -					       int restore, -					       int power_off) +					       bool power_off)  { -	ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off); +	if (ah->aspm_enabled != true) +		return; + +	ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off);  }  static inline void ath9k_hw_rxena(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index db44e5b0c98..a0d1147844f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -603,10 +603,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)  	ath9k_hw_init_mode_regs(ah); - -	if (ah->is_pciexpress) -		ath9k_hw_aspm_init(ah); -	else +	if (!ah->is_pciexpress)  		ath9k_hw_disablepcie(ah);  	if (!AR_SREV_9300_20_OR_LATER(ah)) @@ -621,6 +618,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)  	if (r)  		return r; +	if (ah->is_pciexpress) +		ath9k_hw_aspm_init(ah); +  	r = ath9k_hw_init_macaddr(ah);  	if (r) {  		ath_err(common, "Failed to initialize MAC address\n"); @@ -663,6 +663,7 @@ int ath9k_hw_init(struct ath_hw *ah)  	case AR9300_DEVID_AR9485_PCIE:  	case AR9300_DEVID_AR9330:  	case AR9300_DEVID_AR9340: +	case AR9300_DEVID_AR9580:  		break;  	default:  		if (common->bus_ops->ath_bus_type == ATH_USB) @@ -996,7 +997,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)  		slottime = 21;  		sifstime = 64;  	} else { -		eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS); +		eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate;  		reg = REG_READ(ah, AR_USEC);  		rx_lat = MS(reg, AR_USEC_RX_LAT);  		tx_lat = MS(reg, AR_USEC_TX_LAT); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 4fbcced2828..3aa3fb19177 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -45,6 +45,7 @@  #define AR9300_DEVID_PCIE	0x0030  #define AR9300_DEVID_AR9340	0x0031  #define AR9300_DEVID_AR9485_PCIE 0x0032 +#define AR9300_DEVID_AR9580	0x0033  #define AR9300_DEVID_AR9330	0x0035  #define AR5416_AR9100_DEVID	0x000b @@ -606,8 +607,7 @@ struct ath_hw_private_ops {   */  struct ath_hw_ops {  	void (*config_pci_powersave)(struct ath_hw *ah, -				     int restore, -				     int power_off); +				     bool power_off);  	void (*rx_enable)(struct ath_hw *ah);  	void (*set_desc_link)(void *ds, u32 link);  	bool (*calibrate)(struct ath_hw *ah, @@ -1037,10 +1037,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);  void ath9k_hw_proc_mib_event(struct ath_hw *ah);  void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan); -#define ATH_PCIE_CAP_LINK_CTRL	0x70 -#define ATH_PCIE_CAP_LINK_L0S	1 -#define ATH_PCIE_CAP_LINK_L1	2 -  #define ATH9K_CLOCK_RATE_CCK		22  #define ATH9K_CLOCK_RATE_5GHZ_OFDM	40  #define ATH9K_CLOCK_RATE_2GHZ_OFDM	44 diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index db38a58e752..d7761d1fc5b 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -404,31 +404,6 @@ fail:  	return error;  } -void ath9k_init_crypto(struct ath_softc *sc) -{ -	struct ath_common *common = ath9k_hw_common(sc->sc_ah); -	int i = 0; - -	/* Get the hardware key cache size. */ -	common->keymax = AR_KEYTABLE_SIZE; - -	/* -	 * Reset the key cache since some parts do not -	 * reset the contents on initial power up. -	 */ -	for (i = 0; i < common->keymax; i++) -		ath_hw_keyreset(common, (u16) i); - -	/* -	 * Check whether the separate key cache entries -	 * are required to handle both tx+rx MIC keys. -	 * With split mic keys the number of stations is limited -	 * to 27 otherwise 59. -	 */ -	if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) -		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; -} -  static int ath9k_init_btcoex(struct ath_softc *sc)  {  	struct ath_txq *txq; @@ -630,7 +605,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,  	if (ret)  		goto err_btcoex; -	ath9k_init_crypto(sc); +	ath9k_cmn_init_crypto(sc->sc_ah);  	ath9k_init_misc(sc);  	return 0; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 0f90e1521ff..7ce9b320f0d 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -345,21 +345,8 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,  	}  	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));  	qi->tqi_type = type; -	if (qinfo == NULL) { -		qi->tqi_qflags = -			TXQ_FLAG_TXOKINT_ENABLE -			| TXQ_FLAG_TXERRINT_ENABLE -			| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; -		qi->tqi_aifs = INIT_AIFS; -		qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; -		qi->tqi_cwmax = INIT_CWMAX; -		qi->tqi_shretry = INIT_SH_RETRY; -		qi->tqi_lgretry = INIT_LG_RETRY; -		qi->tqi_physCompBuf = 0; -	} else { -		qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; -		(void) ath9k_hw_set_txq_props(ah, q, qinfo); -	} +	qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; +	(void) ath9k_hw_set_txq_props(ah, q, qinfo);  	return q;  } @@ -564,7 +551,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)  EXPORT_SYMBOL(ath9k_hw_resettxqueue);  int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, -			struct ath_rx_status *rs, u64 tsf) +			struct ath_rx_status *rs)  {  	struct ar5416_desc ads;  	struct ar5416_desc *adsp = AR5416DESC(ds); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 8e848c4d16b..153859ccc2a 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -687,7 +687,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,  bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);  bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);  int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, -			struct ath_rx_status *rs, u64 tsf); +			struct ath_rx_status *rs);  void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,  			  u32 size, u32 flags);  bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1e7fe8c0e11..5ac4f3f2ad6 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -565,7 +565,6 @@ set_timer:  static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)  {  	struct ath_node *an; -	struct ath_hw *ah = sc->sc_ah;  	an = (struct ath_node *)sta->drv_priv;  #ifdef CONFIG_ATH9K_DEBUGFS @@ -574,9 +573,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)  	spin_unlock(&sc->nodes_lock);  	an->sta = sta;  #endif -	if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM) -		sc->sc_flags |= SC_OP_ENABLE_APM; -  	if (sc->sc_flags & SC_OP_TXAGGR) {  		ath_tx_node_init(sc, an);  		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + @@ -826,11 +822,9 @@ irqreturn_t ath_isr(int irq, void *dev)  	if (status & ATH9K_INT_TXURN)  		ath9k_hw_updatetxtriglevel(ah, true); -	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { -		if (status & ATH9K_INT_RXEOL) { -			ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); -			ath9k_hw_set_interrupts(ah, ah->imask); -		} +	if (status & ATH9K_INT_RXEOL) { +		ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN); +		ath9k_hw_set_interrupts(ah, ah->imask);  	}  	if (status & ATH9K_INT_MIB) { @@ -888,7 +882,7 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)  	spin_lock_bh(&sc->sc_pcu_lock);  	atomic_set(&ah->intr_ref_cnt, -1); -	ath9k_hw_configpcipowersave(ah, 0, 0); +	ath9k_hw_configpcipowersave(ah, false);  	if (!ah->curchan)  		ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah); @@ -969,7 +963,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)  	ath9k_hw_phy_disable(ah); -	ath9k_hw_configpcipowersave(ah, 1, 1); +	ath9k_hw_configpcipowersave(ah, true);  	spin_unlock_bh(&sc->sc_pcu_lock);  	ath9k_ps_restore(sc); @@ -1069,7 +1063,7 @@ static int ath9k_start(struct ieee80211_hw *hw)  	init_channel = ath9k_cmn_get_curchannel(hw, ah);  	/* Reset SERDES registers */ -	ath9k_hw_configpcipowersave(ah, 0, 0); +	ath9k_hw_configpcipowersave(ah, false);  	/*  	 * The basic interface to setting the hardware in a good @@ -1145,8 +1139,6 @@ static int ath9k_start(struct ieee80211_hw *hw)  					   AR_STOMP_LOW_WLAN_WGHT);  		ath9k_hw_btcoex_enable(ah); -		if (common->bus_ops->bt_coex_prep) -			common->bus_ops->bt_coex_prep(common);  		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)  			ath9k_btcoex_timer_resume(sc);  	} @@ -1680,6 +1672,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)  	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {  		struct ieee80211_channel *curchan = hw->conf.channel; +		struct ath9k_channel old_chan;  		int pos = curchan->hw_value;  		int old_pos = -1;  		unsigned long flags; @@ -1696,15 +1689,25 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)  			"Set channel: %d MHz type: %d\n",  			curchan->center_freq, conf->channel_type); -		ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], -					  curchan, conf->channel_type); -  		/* update survey stats for the old channel before switching */  		spin_lock_irqsave(&common->cc_lock, flags);  		ath_update_survey_stats(sc);  		spin_unlock_irqrestore(&common->cc_lock, flags);  		/* +		 * Preserve the current channel values, before updating +		 * the same channel +		 */ +		if (old_pos == pos) { +			memcpy(&old_chan, &sc->sc_ah->channels[pos], +				sizeof(struct ath9k_channel)); +			ah->curchan = &old_chan; +		} + +		ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], +					  curchan, conf->channel_type); + +		/*  		 * If the operating channel changes, change the survey in-use flags  		 * along with it.  		 * Reset the survey data for the new channel, unless we're switching @@ -2400,6 +2403,20 @@ skip:  	return sc->beacon.tx_last;  } +static int ath9k_get_stats(struct ieee80211_hw *hw, +			   struct ieee80211_low_level_stats *stats) +{ +	struct ath_softc *sc = hw->priv; +	struct ath_hw *ah = sc->sc_ah; +	struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats; + +	stats->dot11ACKFailureCount = mib_stats->ackrcv_bad; +	stats->dot11RTSFailureCount = mib_stats->rts_bad; +	stats->dot11FCSErrorCount = mib_stats->fcs_bad; +	stats->dot11RTSSuccessCount = mib_stats->rts_good; +	return 0; +} +  struct ieee80211_ops ath9k_ops = {  	.tx 		    = ath9k_tx,  	.start 		    = ath9k_start, @@ -2424,5 +2441,6 @@ struct ieee80211_ops ath9k_ops = {  	.set_coverage_class = ath9k_set_coverage_class,  	.flush		    = ath9k_flush,  	.tx_frames_pending  = ath9k_tx_frames_pending, -	.tx_last_beacon = ath9k_tx_last_beacon, +	.tx_last_beacon     = ath9k_tx_last_beacon, +	.get_stats	    = ath9k_get_stats,  }; diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 5685cf11cfe..891661a6151 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -32,9 +32,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {  	{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */  	{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E  AR9300 */  	{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E  AR9485 */ +	{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E  AR9580 */  	{ 0 }  }; +  /* return bus cachesize in 4B word units */  static void ath_pci_read_cachesize(struct ath_common *common, int *csz)  { @@ -88,23 +90,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)  	return true;  } -/* - * Bluetooth coexistance requires disabling ASPM. - */ -static void ath_pci_bt_coex_prep(struct ath_common *common) -{ -	struct ath_softc *sc = (struct ath_softc *) common->priv; -	struct pci_dev *pdev = to_pci_dev(sc->dev); -	u8 aspm; - -	if (!pci_is_pcie(pdev)) -		return; - -	pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); -	aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); -	pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); -} -  static void ath_pci_extn_synch_enable(struct ath_common *common)  {  	struct ath_softc *sc = (struct ath_softc *) common->priv; @@ -116,6 +101,7 @@ static void ath_pci_extn_synch_enable(struct ath_common *common)  	pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);  } +/* Need to be called after we discover btcoex capabilities */  static void ath_pci_aspm_init(struct ath_common *common)  {  	struct ath_softc *sc = (struct ath_softc *) common->priv; @@ -125,19 +111,38 @@ static void ath_pci_aspm_init(struct ath_common *common)  	int pos;  	u8 aspm; -	if (!pci_is_pcie(pdev)) +	pos = pci_pcie_cap(pdev); +	if (!pos)  		return;  	parent = pdev->bus->self; -	if (WARN_ON(!parent)) +	if (!parent)  		return; +	if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) { +		/* Bluetooth coexistance requires disabling ASPM. */ +		pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); +		aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); +		pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); + +		/* +		 * Both upstream and downstream PCIe components should +		 * have the same ASPM settings. +		 */ +		pos = pci_pcie_cap(parent); +		pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm); +		aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); +		pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm); + +		return; +	} +  	pos = pci_pcie_cap(parent);  	pci_read_config_byte(parent, pos +  PCI_EXP_LNKCTL, &aspm);  	if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {  		ah->aspm_enabled = true;  		/* Initialize PCIe PM and SERDES registers. */ -		ath9k_hw_configpcipowersave(ah, 0, 0); +		ath9k_hw_configpcipowersave(ah, false);  	}  } @@ -145,7 +150,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {  	.ath_bus_type = ATH_PCI,  	.read_cachesize = ath_pci_read_cachesize,  	.eeprom_read = ath_pci_eeprom_read, -	.bt_coex_prep = ath_pci_bt_coex_prep,  	.extn_synch_en = ath_pci_extn_synch_enable,  	.aspm_init = ath_pci_aspm_init,  }; @@ -338,7 +342,7 @@ static int ath_pci_resume(struct device *device)  	   * semi-random values after suspend/resume.  	   */  	ath9k_ps_wakeup(sc); -	ath9k_init_crypto(sc); +	ath9k_cmn_init_crypto(sc->sc_ah);  	ath9k_ps_restore(sc);  	sc->ps_idle = true; diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 9e3649a3d5c..4f130188113 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -603,7 +603,8 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,  static u8 ath_rc_get_highest_rix(struct ath_softc *sc,  			         struct ath_rate_priv *ath_rc_priv,  				 const struct ath_rate_table *rate_table, -				 int *is_probing) +				 int *is_probing, +				 bool legacy)  {  	u32 best_thruput, this_thruput, now_msec;  	u8 rate, next_rate, best_rate, maxindex, minindex; @@ -624,6 +625,8 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,  		u8 per_thres;  		rate = ath_rc_priv->valid_rate_index[index]; +		if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY)) +			continue;  		if (rate > ath_rc_priv->rate_max_phy)  			continue; @@ -767,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,  	struct ieee80211_tx_rate *rates = tx_info->control.rates;  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;  	__le16 fc = hdr->frame_control; -	u8 try_per_rate, i = 0, rix; +	u8 try_per_rate, i = 0, rix, high_rix;  	int is_probe = 0;  	if (rate_control_send_low(sta, priv_sta, txrc)) @@ -786,7 +789,9 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,  	try_per_rate = 4;  	rate_table = ath_rc_priv->rate_table; -	rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); +	rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, +				     &is_probe, false); +	high_rix = rix;  	/*  	 * If we're in HT mode and both us and our peer supports LDPC. @@ -822,10 +827,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,  	}  	/* Fill in the other rates for multirate retry */ -	for ( ; i < 4; i++) { -		/* Use twice the number of tries for the last MRR segment. */ -		if (i + 1 == 4) -			try_per_rate = 8; +	for ( ; i < 3; i++) {  		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);  		/* All other rates in the series have RTS enabled */ @@ -833,6 +835,24 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,  				       try_per_rate, rix, 1);  	} +	/* Use twice the number of tries for the last MRR segment. */ +	try_per_rate = 8; + +	/* +	 * Use a legacy rate as last retry to ensure that the frame +	 * is tried in both MCS and legacy rates. +	 */ +	if ((rates[2].flags & IEEE80211_TX_RC_MCS) && +	    (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) || +	    (ath_rc_priv->per[high_rix] > 45))) +		rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, +				&is_probe, true); +	else +		ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); + +	/* All other rates in the series have RTS enabled */ +	ath_rc_rate_set_series(rate_table, &rates[i], txrc, +			       try_per_rate, rix, 1);  	/*  	 * NB:Change rate series to enable aggregation when operating  	 * at lower MCS rates. When first rate in series is MCS2 diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 74094022b65..ad5f9bd2f0b 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -761,7 +761,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  	 * on.  All this is necessary because of our use of  	 * a self-linked list to avoid rx overruns.  	 */ -	ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0); +	ret = ath9k_hw_rxprocdesc(ah, ds, rs);  	if (ret == -EINPROGRESS) {  		struct ath_rx_status trs;  		struct ath_buf *tbf; @@ -787,7 +787,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,  		 */  		tds = tbf->bf_desc; -		ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0); +		ret = ath9k_hw_rxprocdesc(ah, tds, &trs);  		if (ret == -EINPROGRESS)  			return NULL;  	} @@ -824,7 +824,8 @@ static bool ath9k_rx_accept(struct ath_common *common,  	is_mc = !!is_multicast_ether_addr(hdr->addr1);  	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&  		test_bit(rx_stats->rs_keyix, common->tkip_keymap); -	strip_mic = is_valid_tkip && !(rx_stats->rs_status & +	strip_mic = is_valid_tkip && ieee80211_is_data(fc) && +		!(rx_stats->rs_status &  		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));  	if (!rx_stats->rs_datalen) @@ -1978,5 +1979,10 @@ requeue:  	spin_unlock_bh(&sc->rx.rxbuflock); +	if (!(ah->imask & ATH9K_INT_RXEOL)) { +		ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); +		ath9k_hw_set_interrupts(ah, ah->imask); +	} +  	return 0;  } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index fa4c0bbce6b..a3b8bbc6c06 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -793,6 +793,8 @@  #define AR_SREV_REVISION_9485_10	0  #define AR_SREV_REVISION_9485_11        1  #define AR_SREV_VERSION_9340		0x300 +#define AR_SREV_VERSION_9580		0x1C0 +#define AR_SREV_REVISION_9580_10	4 /* AR9580 1.0 */  #define AR_SREV_5416(_ah) \  	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ @@ -893,6 +895,18 @@      (AR_SREV_9285_12_OR_LATER(_ah) && \       ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) +#define AR_SREV_9580(_ah) \ +	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ +	((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10)) + +#define AR_SREV_9580_10(_ah) \ +	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \ +	((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10)) + +/* NOTE: When adding chips newer than Peacock, add chip check here */ +#define AR_SREV_9580_10_OR_LATER(_ah) \ +	(AR_SREV_9580(_ah)) +  enum ath_usb_dev {  	AR9280_USB = 1, /* AR7010 + AR9280, UB94 */  	AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index e1d1e903229..5e2982938ff 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -571,6 +571,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  		ath_reset(sc, false);  } +static bool ath_lookup_legacy(struct ath_buf *bf) +{ +	struct sk_buff *skb; +	struct ieee80211_tx_info *tx_info; +	struct ieee80211_tx_rate *rates; +	int i; + +	skb = bf->bf_mpdu; +	tx_info = IEEE80211_SKB_CB(skb); +	rates = tx_info->control.rates; + +	for (i = 3; i >= 0; i--) { +		if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) +			return true; +	} + +	return false; +} +  static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,  			   struct ath_atx_tid *tid)  { @@ -644,8 +663,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,   * meet the minimum required mpdudensity.   */  static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, -				  struct ath_buf *bf, u16 frmlen) +				  struct ath_buf *bf, u16 frmlen, +				  bool first_subfrm)  { +#define FIRST_DESC_NDELIMS 60  	struct sk_buff *skb = bf->bf_mpdu;  	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);  	u32 nsymbits, nsymbols; @@ -668,6 +689,13 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,  		ndelim += ATH_AGGR_ENCRYPTDELIM;  	/* +	 * Add delimiter when using RTS/CTS with aggregation +	 * and non enterprise AR9003 card +	 */ +	if (first_subfrm) +		ndelim = max(ndelim, FIRST_DESC_NDELIMS); + +	/*  	 * Convert desired mpdu density from microeconds to bytes based  	 * on highest rate in rate series (i.e. first rate) to determine  	 * required minimum length for subframe. Take into account @@ -741,7 +769,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,  		al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;  		if (nframes && -		    (aggr_limit < (al + bpad + al_delta + prev_al))) { +		    ((aggr_limit < (al + bpad + al_delta + prev_al)) || +		     ath_lookup_legacy(bf))) {  			status = ATH_AGGR_LIMITED;  			break;  		} @@ -756,7 +785,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,  			status = ATH_AGGR_LIMITED;  			break;  		} -		nframes++;  		/* add padding for previous frame to aggregation length */  		al += bpad + al_delta; @@ -765,9 +793,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,  		 * Get the delimiters needed to meet the MPDU  		 * density for this node.  		 */ -		ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen); +		ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen, +						!nframes);  		bpad = PADBYTES(al_delta) + (ndelim << 2); +		nframes++;  		bf->bf_next = NULL;  		ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0); @@ -1574,9 +1604,9 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)  {  	struct ath_hw *ah = sc->sc_ah;  	struct ath9k_channel *curchan = ah->curchan; -	if ((sc->sc_flags & SC_OP_ENABLE_APM) && -			(curchan->channelFlags & CHANNEL_5GHZ) && -			(chainmask == 0x7) && (rate < 0x90)) +	if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && +	    (curchan->channelFlags & CHANNEL_5GHZ) && +	    (chainmask == 0x7) && (rate < 0x90))  		return 0x3;  	else  		return chainmask; diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig index 2d1b821b440..267d5dcf82d 100644 --- a/drivers/net/wireless/ath/carl9170/Kconfig +++ b/drivers/net/wireless/ath/carl9170/Kconfig @@ -39,3 +39,17 @@ config CARL9170_WPC  	bool  	depends on CARL9170 && (INPUT = y || INPUT = CARL9170)  	default y + +config CARL9170_HWRNG +        bool "Random number generator" +        depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170) +        default n +	help +	  Provides a hardware random number generator to the kernel. + +	  SECURITY WARNING: It's relatively easy to eavesdrop all +	  generated random numbers from the transport stream with +	  usbmon [software] or special usb sniffer hardware. + +	  Say N, unless your setup[i.e.: embedded system] has no +	  other rng source and you can afford to take the risk. diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index c5427a72a1e..6cfbb419e2f 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -43,6 +43,7 @@  #include <linux/firmware.h>  #include <linux/completion.h>  #include <linux/spinlock.h> +#include <linux/hw_random.h>  #include <net/cfg80211.h>  #include <net/mac80211.h>  #include <linux/usb.h> @@ -151,6 +152,7 @@ struct carl9170_sta_tid {  #define CARL9170_TX_TIMEOUT		2500  #define CARL9170_JANITOR_DELAY		128  #define CARL9170_QUEUE_STUCK_TIMEOUT	5500 +#define CARL9170_STAT_WORK		30000  #define CARL9170_NUM_TX_AGG_MAX		30 @@ -282,6 +284,7 @@ struct ar9170 {  		bool rx_stream;  		bool tx_stream;  		bool rx_filter; +		bool hw_counters;  		unsigned int mem_blocks;  		unsigned int mem_block_size;  		unsigned int rx_size; @@ -331,11 +334,21 @@ struct ar9170 {  	/* PHY */  	struct ieee80211_channel *channel; +	unsigned int num_channels;  	int noise[4];  	unsigned int chan_fail;  	unsigned int total_chan_fail;  	u8 heavy_clip;  	u8 ht_settings; +	struct { +		u64 active;	/* usec */ +		u64 cca;	/* usec */ +		u64 tx_time;	/* usec */ +		u64 rx_total; +		u64 rx_overrun; +	} tally; +	struct delayed_work stat_work; +	struct survey_info *survey;  	/* power calibration data */  	u8 power_5G_leg[4]; @@ -437,6 +450,17 @@ struct ar9170 {  		unsigned int off_override;  		bool state;  	} ps; + +#ifdef CONFIG_CARL9170_HWRNG +# define CARL9170_HWRNG_CACHE_SIZE	CARL9170_MAX_CMD_PAYLOAD_LEN +	struct { +		struct hwrng rng; +		bool initialized; +		char name[30 + 1]; +		u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)]; +		unsigned int cache_idx; +	} rng; +#endif /* CONFIG_CARL9170_HWRNG */  };  enum carl9170_ps_off_override_reasons { diff --git a/drivers/net/wireless/ath/carl9170/cmd.c b/drivers/net/wireless/ath/carl9170/cmd.c index cdfc94c371b..195dc653811 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.c +++ b/drivers/net/wireless/ath/carl9170/cmd.c @@ -36,6 +36,7 @@   *    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ +#include <asm/div64.h>  #include "carl9170.h"  #include "cmd.h" @@ -165,6 +166,39 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,  	return __carl9170_exec_cmd(ar, cmd, true);  } +int carl9170_collect_tally(struct ar9170 *ar) +{ +	struct carl9170_tally_rsp tally; +	struct survey_info *info; +	unsigned int tick; +	int err; + +	err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL, +				sizeof(tally), (u8 *)&tally); +	if (err) +		return err; + +	tick = le32_to_cpu(tally.tick); +	if (tick) { +		ar->tally.active += le32_to_cpu(tally.active) / tick; +		ar->tally.cca += le32_to_cpu(tally.cca) / tick; +		ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick; +		ar->tally.rx_total += le32_to_cpu(tally.rx_total); +		ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun); + +		if (ar->channel) { +			info = &ar->survey[ar->channel->hw_value]; +			info->channel_time = ar->tally.active; +			info->channel_time_busy = ar->tally.cca; +			info->channel_time_tx = ar->tally.tx_time; +			do_div(info->channel_time, 1000); +			do_div(info->channel_time_busy, 1000); +			do_div(info->channel_time_tx, 1000); +		} +	} +	return 0; +} +  int carl9170_powersave(struct ar9170 *ar, const bool ps)  {  	struct carl9170_cmd *cmd; diff --git a/drivers/net/wireless/ath/carl9170/cmd.h b/drivers/net/wireless/ath/carl9170/cmd.h index d5f95bdc75c..885c42778b8 100644 --- a/drivers/net/wireless/ath/carl9170/cmd.h +++ b/drivers/net/wireless/ath/carl9170/cmd.h @@ -50,6 +50,7 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v);  int carl9170_reboot(struct ar9170 *ar);  int carl9170_mac_reset(struct ar9170 *ar);  int carl9170_powersave(struct ar9170 *ar, const bool power_on); +int carl9170_collect_tally(struct ar9170 *ar);  int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,  		       const u32 mode, const u32 addr, const u32 len); diff --git a/drivers/net/wireless/ath/carl9170/fw.c b/drivers/net/wireless/ath/carl9170/fw.c index 39ddea5794f..f4cae1cccbf 100644 --- a/drivers/net/wireless/ath/carl9170/fw.c +++ b/drivers/net/wireless/ath/carl9170/fw.c @@ -266,6 +266,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)  			FIF_PROMISC_IN_BSS;  	} +	if (SUPP(CARL9170FW_HW_COUNTERS)) +		ar->fw.hw_counters = true; +  	if (SUPP(CARL9170FW_WOL))  		device_set_wakeup_enable(&ar->udev->dev, true); diff --git a/drivers/net/wireless/ath/carl9170/fwcmd.h b/drivers/net/wireless/ath/carl9170/fwcmd.h index 0a6dec529b5..9443c802b25 100644 --- a/drivers/net/wireless/ath/carl9170/fwcmd.h +++ b/drivers/net/wireless/ath/carl9170/fwcmd.h @@ -55,6 +55,7 @@ enum carl9170_cmd_oids {  	CARL9170_CMD_READ_TSF		= 0x06,  	CARL9170_CMD_RX_FILTER		= 0x07,  	CARL9170_CMD_WOL		= 0x08, +	CARL9170_CMD_TALLY		= 0x09,  	/* CAM */  	CARL9170_CMD_EKEY		= 0x10, @@ -286,6 +287,15 @@ struct carl9170_tsf_rsp {  } __packed;  #define CARL9170_TSF_RSP_SIZE		8 +struct carl9170_tally_rsp { +	__le32 active; +	__le32 cca; +	__le32 tx_time; +	__le32 rx_total; +	__le32 rx_overrun; +	__le32 tick; +} __packed; +  struct carl9170_rsp {  	struct carl9170_cmd_head hdr; @@ -300,6 +310,7 @@ struct carl9170_rsp {  		struct carl9170_gpio		gpio;  		struct carl9170_tsf_rsp		tsf;  		struct carl9170_psm		psm; +		struct carl9170_tally_rsp	tally;  		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];  	} __packed;  } __packed __aligned(4); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 0122930b14c..782b8f3ae58 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -413,6 +413,9 @@ static int carl9170_op_start(struct ieee80211_hw *hw)  	carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED); +	ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, +		round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK))); +  	ieee80211_wake_queues(ar->hw);  	err = 0; @@ -423,6 +426,7 @@ out:  static void carl9170_cancel_worker(struct ar9170 *ar)  { +	cancel_delayed_work_sync(&ar->stat_work);  	cancel_delayed_work_sync(&ar->tx_janitor);  #ifdef CONFIG_CARL9170_LEDS  	cancel_delayed_work_sync(&ar->led_work); @@ -794,6 +798,43 @@ static void carl9170_ps_work(struct work_struct *work)  	mutex_unlock(&ar->mutex);  } +static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise) +{ +	int err; + +	if (noise) { +		err = carl9170_get_noisefloor(ar); +		if (err) +			return err; +	} + +	if (ar->fw.hw_counters) { +		err = carl9170_collect_tally(ar); +		if (err) +			return err; +	} + +	if (flush) +		memset(&ar->tally, 0, sizeof(ar->tally)); + +	return 0; +} + +static void carl9170_stat_work(struct work_struct *work) +{ +	struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work); +	int err; + +	mutex_lock(&ar->mutex); +	err = carl9170_update_survey(ar, false, true); +	mutex_unlock(&ar->mutex); + +	if (err) +		return; + +	ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, +		round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK))); +}  static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)  { @@ -828,11 +869,19 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)  		if (err)  			goto out; +		err = carl9170_update_survey(ar, true, false); +		if (err) +			goto out; +  		err = carl9170_set_channel(ar, hw->conf.channel,  			hw->conf.channel_type, CARL9170_RFI_NONE);  		if (err)  			goto out; +		err = carl9170_update_survey(ar, false, true); +		if (err) +			goto out; +  		err = carl9170_set_dyn_sifs_ack(ar);  		if (err)  			goto out; @@ -1419,24 +1468,159 @@ static int carl9170_register_wps_button(struct ar9170 *ar)  }  #endif /* CONFIG_CARL9170_WPC */ -static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, -				struct survey_info *survey) +#ifdef CONFIG_CARL9170_HWRNG +static int carl9170_rng_get(struct ar9170 *ar)  { -	struct ar9170 *ar = hw->priv; + +#define RW	(CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32)) +#define RB	(CARL9170_MAX_CMD_PAYLOAD_LEN) + +	static const __le32 rng_load[RW] = { +		[0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)}; + +	u32 buf[RW]; + +	unsigned int i, off = 0, transfer, count;  	int err; -	if (idx != 0) -		return -ENOENT; +	BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN); + +	if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized) +		return -EAGAIN; + +	count = ARRAY_SIZE(ar->rng.cache); +	while (count) { +		err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG, +					RB, (u8 *) rng_load, +					RB, (u8 *) buf); +		if (err) +			return err; + +		transfer = min_t(unsigned int, count, RW); +		for (i = 0; i < transfer; i++) +			ar->rng.cache[off + i] = buf[i]; + +		off += transfer; +		count -= transfer; +	} + +	ar->rng.cache_idx = 0; + +#undef RW +#undef RB +	return 0; +} + +static int carl9170_rng_read(struct hwrng *rng, u32 *data) +{ +	struct ar9170 *ar = (struct ar9170 *)rng->priv; +	int ret = -EIO;  	mutex_lock(&ar->mutex); -	err = carl9170_get_noisefloor(ar); +	if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) { +		ret = carl9170_rng_get(ar); +		if (ret) { +			mutex_unlock(&ar->mutex); +			return ret; +		} +	} + +	*data = ar->rng.cache[ar->rng.cache_idx++];  	mutex_unlock(&ar->mutex); -	if (err) + +	return sizeof(u16); +} + +static void carl9170_unregister_hwrng(struct ar9170 *ar) +{ +	if (ar->rng.initialized) { +		hwrng_unregister(&ar->rng.rng); +		ar->rng.initialized = false; +	} +} + +static int carl9170_register_hwrng(struct ar9170 *ar) +{ +	int err; + +	snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name), +		 "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy)); +	ar->rng.rng.name = ar->rng.name; +	ar->rng.rng.data_read = carl9170_rng_read; +	ar->rng.rng.priv = (unsigned long)ar; + +	if (WARN_ON(ar->rng.initialized)) +		return -EALREADY; + +	err = hwrng_register(&ar->rng.rng); +	if (err) { +		dev_err(&ar->udev->dev, "Failed to register the random " +			"number generator (%d)\n", err);  		return err; +	} + +	ar->rng.initialized = true; + +	err = carl9170_rng_get(ar); +	if (err) { +		carl9170_unregister_hwrng(ar); +		return err; +	} + +	return 0; +} +#endif /* CONFIG_CARL9170_HWRNG */ + +static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx, +				struct survey_info *survey) +{ +	struct ar9170 *ar = hw->priv; +	struct ieee80211_channel *chan; +	struct ieee80211_supported_band *band; +	int err, b, i; + +	chan = ar->channel; +	if (!chan) +		return -ENODEV; + +	if (idx == chan->hw_value) { +		mutex_lock(&ar->mutex); +		err = carl9170_update_survey(ar, false, true); +		mutex_unlock(&ar->mutex); +		if (err) +			return err; +	} + +	for (b = 0; b < IEEE80211_NUM_BANDS; b++) { +		band = ar->hw->wiphy->bands[b]; + +		if (!band) +			continue; + +		for (i = 0; i < band->n_channels; i++) { +			if (band->channels[i].hw_value == idx) { +				chan = &band->channels[i]; +				goto found; +			} +		} +	} +	return -ENOENT; + +found: +	memcpy(survey, &ar->survey[idx], sizeof(*survey)); -	survey->channel = ar->channel; +	survey->channel = chan;  	survey->filled = SURVEY_INFO_NOISE_DBM; -	survey->noise = ar->noise[0]; + +	if (ar->channel == chan) +		survey->filled |= SURVEY_INFO_IN_USE; + +	if (ar->fw.hw_counters) { +		survey->filled |= SURVEY_INFO_CHANNEL_TIME | +				  SURVEY_INFO_CHANNEL_TIME_BUSY | +				  SURVEY_INFO_CHANNEL_TIME_TX; +	} +  	return 0;  } @@ -1569,6 +1753,7 @@ void *carl9170_alloc(size_t priv_size)  	INIT_WORK(&ar->ping_work, carl9170_ping_work);  	INIT_WORK(&ar->restart_work, carl9170_restart_work);  	INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); +	INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work);  	INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);  	INIT_LIST_HEAD(&ar->tx_ampdu_list);  	rcu_assign_pointer(ar->tx_ampdu_iter, @@ -1652,6 +1837,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)  	struct ath_regulatory *regulatory = &ar->common.regulatory;  	unsigned int rx_streams, tx_streams, tx_params = 0;  	int bands = 0; +	int chans = 0;  	if (ar->eeprom.length == cpu_to_le16(0xffff))  		return -ENODATA; @@ -1675,14 +1861,24 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)  	if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {  		ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =  			&carl9170_band_2GHz; +		chans += carl9170_band_2GHz.n_channels;  		bands++;  	}  	if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {  		ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =  			&carl9170_band_5GHz; +		chans += carl9170_band_5GHz.n_channels;  		bands++;  	} +	if (!bands) +		return -EINVAL; + +	ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL); +	if (!ar->survey) +		return -ENOMEM; +	ar->num_channels = chans; +  	/*  	 * I measured this, a bandswitch takes roughly  	 * 135 ms and a frequency switch about 80. @@ -1701,7 +1897,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)  	/* second part of wiphy init */  	SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address); -	return bands ? 0 : -EINVAL; +	return 0;  }  static int carl9170_reg_notifier(struct wiphy *wiphy, @@ -1785,6 +1981,12 @@ int carl9170_register(struct ar9170 *ar)  		goto err_unreg;  #endif /* CONFIG_CARL9170_WPC */ +#ifdef CONFIG_CARL9170_HWRNG +	err = carl9170_register_hwrng(ar); +	if (err) +		goto err_unreg; +#endif /* CONFIG_CARL9170_HWRNG */ +  	dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",  		 wiphy_name(ar->hw->wiphy)); @@ -1817,6 +2019,10 @@ void carl9170_unregister(struct ar9170 *ar)  	}  #endif /* CONFIG_CARL9170_WPC */ +#ifdef CONFIG_CARL9170_HWRNG +	carl9170_unregister_hwrng(ar); +#endif /* CONFIG_CARL9170_HWRNG */ +  	carl9170_cancel_worker(ar);  	cancel_work_sync(&ar->restart_work); @@ -1834,6 +2040,9 @@ void carl9170_free(struct ar9170 *ar)  	kfree(ar->mem_bitmap);  	ar->mem_bitmap = NULL; +	kfree(ar->survey); +	ar->survey = NULL; +  	mutex_destroy(&ar->mutex);  	ieee80211_free_hw(ar->hw); diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index aa147a9120b..472efc7e340 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c @@ -578,11 +578,10 @@ static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)  	if (err)  		return err; -	/* XXX: remove magic! */ -	if (is_2ghz) -		err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163); -	else -		err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143); +	if (!ar->fw.hw_counters) { +		err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, +					 is_2ghz ? 0x5163 : 0x5143); +	}  	return err;  } @@ -1574,6 +1573,9 @@ int carl9170_get_noisefloor(struct ar9170 *ar)  			AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);  	} +	if (ar->channel) +		ar->survey[ar->channel->hw_value].noise = ar->noise[0]; +  	return 0;  } @@ -1766,10 +1768,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,  		ar->chan_fail = 0;  	} -	err = carl9170_get_noisefloor(ar); -	if (err) -		return err; -  	if (ar->heavy_clip) {  		err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,  					 0x200 | ar->heavy_clip); diff --git a/drivers/net/wireless/ath/carl9170/version.h b/drivers/net/wireless/ath/carl9170/version.h index 64703778cfe..e651db85634 100644 --- a/drivers/net/wireless/ath/carl9170/version.h +++ b/drivers/net/wireless/ath/carl9170/version.h @@ -1,7 +1,7 @@  #ifndef __CARL9170_SHARED_VERSION_H  #define __CARL9170_SHARED_VERSION_H  #define CARL9170FW_VERSION_YEAR 11 -#define CARL9170FW_VERSION_MONTH 6 -#define CARL9170FW_VERSION_DAY 30 +#define CARL9170FW_VERSION_MONTH 8 +#define CARL9170FW_VERSION_DAY 15  #define CARL9170FW_VERSION_GIT "1.9.4"  #endif /* __CARL9170_SHARED_VERSION_H */ diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index b81a2a1c261..df2b7c0856e 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -169,13 +169,3 @@ config B43_DEBUG  	  Say N, if you are a distributor or user building a release kernel  	  for production use.  	  Only say Y, if you are debugging a problem in the b43 driver sourcecode. - -config B43_FORCE_PIO -	bool "Force usage of PIO instead of DMA" -	depends on B43 && B43_DEBUG -	---help--- -	  This will disable DMA and always enable PIO instead. - -	  Say N! -	  This is only for debugging the PIO engine code. You do -	  _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index c818b0bc88e..8ff706289b5 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -17,11 +17,6 @@  #include "phy_common.h" -/* The unique identifier of the firmware that's officially supported by - * this driver version. */ -#define B43_SUPPORTED_FIRMWARE_ID	"FW13" - -  #ifdef CONFIG_B43_DEBUG  # define B43_DEBUG	1  #else @@ -594,6 +589,7 @@ struct b43_dma {  	struct b43_dmaring *rx_ring;  	u32 translation; /* Routing bits */ +	bool translation_in_low; /* Should translation bit go into low addr? */  	bool parity; /* Check for parity */  }; @@ -694,6 +690,12 @@ struct b43_firmware_file {  	enum b43_firmware_file_type type;  }; +enum b43_firmware_hdr_format { +	B43_FW_HDR_598, +	B43_FW_HDR_410, +	B43_FW_HDR_351, +}; +  /* Pointers to the firmware data and meta information about it. */  struct b43_firmware {  	/* Microcode */ @@ -710,6 +712,9 @@ struct b43_firmware {  	/* Firmware patchlevel */  	u16 patch; +	/* Format of header used by firmware */ +	enum b43_firmware_hdr_format hdr_format; +  	/* Set to true, if we are using an opensource firmware.  	 * Use this to check for proprietary vs opensource. */  	bool opensource; @@ -875,7 +880,7 @@ struct b43_wl {  	struct b43_leds leds;  	/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ -	u8 pio_scratchspace[110] __attribute__((__aligned__(8))); +	u8 pio_scratchspace[118] __attribute__((__aligned__(8)));  	u8 pio_tailspace[4] __attribute__((__aligned__(8)));  }; @@ -965,12 +970,6 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev)  	return dev->__using_pio_transfers;  } -#ifdef CONFIG_B43_FORCE_PIO -# define B43_PIO_DEFAULT 1 -#else -# define B43_PIO_DEFAULT 0 -#endif -  /* Message printing */  void b43info(struct b43_wl *wl, const char *fmt, ...)      __attribute__ ((format(printf, 2, 3))); diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 481e534534e..c5d890e74a1 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -47,6 +47,38 @@   * into separate slots. */  #define TX_SLOTS_PER_FRAME	2 +static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr, +			   enum b43_addrtype addrtype) +{ +	u32 uninitialized_var(addr); + +	switch (addrtype) { +	case B43_DMA_ADDR_LOW: +		addr = lower_32_bits(dmaaddr); +		if (dma->translation_in_low) { +			addr &= ~SSB_DMA_TRANSLATION_MASK; +			addr |= dma->translation; +		} +		break; +	case B43_DMA_ADDR_HIGH: +		addr = upper_32_bits(dmaaddr); +		if (!dma->translation_in_low) { +			addr &= ~SSB_DMA_TRANSLATION_MASK; +			addr |= dma->translation; +		} +		break; +	case B43_DMA_ADDR_EXT: +		if (dma->translation_in_low) +			addr = lower_32_bits(dmaaddr); +		else +			addr = upper_32_bits(dmaaddr); +		addr &= SSB_DMA_TRANSLATION_MASK; +		addr >>= SSB_DMA_TRANSLATION_SHIFT; +		break; +	} + +	return addr; +}  /* 32bit DMA ops. */  static @@ -77,10 +109,9 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,  	slot = (int)(&(desc->dma32) - descbase);  	B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); -	addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); -	addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) -	    >> SSB_DMA_TRANSLATION_SHIFT; -	addr |= ring->dev->dma.translation; +	addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW); +	addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT); +  	ctl = bufsize & B43_DMA32_DCTL_BYTECNT;  	if (slot == ring->nr_slots - 1)  		ctl |= B43_DMA32_DCTL_DTABLEEND; @@ -170,11 +201,10 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,  	slot = (int)(&(desc->dma64) - descbase);  	B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); -	addrlo = (u32) (dmaaddr & 0xFFFFFFFF); -	addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); -	addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) -	    >> SSB_DMA_TRANSLATION_SHIFT; -	addrhi |= ring->dev->dma.translation; +	addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW); +	addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH); +	addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT); +  	if (slot == ring->nr_slots - 1)  		ctl0 |= B43_DMA64_DCTL0_DTABLEEND;  	if (start) @@ -658,41 +688,37 @@ static int dmacontroller_setup(struct b43_dmaring *ring)  	int err = 0;  	u32 value;  	u32 addrext; -	u32 trans = ring->dev->dma.translation;  	bool parity = ring->dev->dma.parity; +	u32 addrlo; +	u32 addrhi;  	if (ring->tx) {  		if (ring->type == B43_DMA_64BIT) {  			u64 ringbase = (u64) (ring->dmabase); +			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); +			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); +			addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH); -			addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) -			    >> SSB_DMA_TRANSLATION_SHIFT;  			value = B43_DMA64_TXENABLE;  			value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)  			    & B43_DMA64_TXADDREXT_MASK;  			if (!parity)  				value |= B43_DMA64_TXPARITYDISABLE;  			b43_dma_write(ring, B43_DMA64_TXCTL, value); -			b43_dma_write(ring, B43_DMA64_TXRINGLO, -				      (ringbase & 0xFFFFFFFF)); -			b43_dma_write(ring, B43_DMA64_TXRINGHI, -				      ((ringbase >> 32) & -				       ~SSB_DMA_TRANSLATION_MASK) -				      | trans); +			b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo); +			b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi);  		} else {  			u32 ringbase = (u32) (ring->dmabase); +			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); +			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); -			addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) -			    >> SSB_DMA_TRANSLATION_SHIFT;  			value = B43_DMA32_TXENABLE;  			value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)  			    & B43_DMA32_TXADDREXT_MASK;  			if (!parity)  				value |= B43_DMA32_TXPARITYDISABLE;  			b43_dma_write(ring, B43_DMA32_TXCTL, value); -			b43_dma_write(ring, B43_DMA32_TXRING, -				      (ringbase & ~SSB_DMA_TRANSLATION_MASK) -				      | trans); +			b43_dma_write(ring, B43_DMA32_TXRING, addrlo);  		}  	} else {  		err = alloc_initial_descbuffers(ring); @@ -700,9 +726,10 @@ static int dmacontroller_setup(struct b43_dmaring *ring)  			goto out;  		if (ring->type == B43_DMA_64BIT) {  			u64 ringbase = (u64) (ring->dmabase); +			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); +			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); +			addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH); -			addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) -			    >> SSB_DMA_TRANSLATION_SHIFT;  			value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);  			value |= B43_DMA64_RXENABLE;  			value |= (addrext << B43_DMA64_RXADDREXT_SHIFT) @@ -710,19 +737,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)  			if (!parity)  				value |= B43_DMA64_RXPARITYDISABLE;  			b43_dma_write(ring, B43_DMA64_RXCTL, value); -			b43_dma_write(ring, B43_DMA64_RXRINGLO, -				      (ringbase & 0xFFFFFFFF)); -			b43_dma_write(ring, B43_DMA64_RXRINGHI, -				      ((ringbase >> 32) & -				       ~SSB_DMA_TRANSLATION_MASK) -				      | trans); +			b43_dma_write(ring, B43_DMA64_RXRINGLO, addrlo); +			b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi);  			b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *  				      sizeof(struct b43_dmadesc64));  		} else {  			u32 ringbase = (u32) (ring->dmabase); +			addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT); +			addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW); -			addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) -			    >> SSB_DMA_TRANSLATION_SHIFT;  			value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT);  			value |= B43_DMA32_RXENABLE;  			value |= (addrext << B43_DMA32_RXADDREXT_SHIFT) @@ -730,9 +753,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)  			if (!parity)  				value |= B43_DMA32_RXPARITYDISABLE;  			b43_dma_write(ring, B43_DMA32_RXCTL, value); -			b43_dma_write(ring, B43_DMA32_RXRING, -				      (ringbase & ~SSB_DMA_TRANSLATION_MASK) -				      | trans); +			b43_dma_write(ring, B43_DMA32_RXRING, addrlo);  			b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *  				      sizeof(struct b43_dmadesc32));  		} @@ -872,8 +893,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,  		ring->current_slot = -1;  	} else {  		if (ring->index == 0) { -			ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; -			ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; +			switch (dev->fw.hdr_format) { +			case B43_FW_HDR_598: +				ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE; +				ring->frameoffset = B43_DMA0_RX_FW598_FO; +				break; +			case B43_FW_HDR_410: +			case B43_FW_HDR_351: +				ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE; +				ring->frameoffset = B43_DMA0_RX_FW351_FO; +				break; +			}  		} else  			B43_WARN_ON(1);  	} @@ -1066,6 +1096,25 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)  	return 0;  } +/* Some hardware with 64-bit DMA seems to be bugged and looks for translation + * bit in low address word instead of high one. + */ +static bool b43_dma_translation_in_low_word(struct b43_wldev *dev, +					    enum b43_dmatype type) +{ +	if (type != B43_DMA_64BIT) +		return 1; + +#ifdef CONFIG_B43_SSB +	if (dev->dev->bus_type == B43_BUS_SSB && +	    dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && +	    !(dev->dev->sdev->bus->host_pci->is_pcie && +	      ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) +			return 1; +#endif +	return 0; +} +  int b43_dma_init(struct b43_wldev *dev)  {  	struct b43_dma *dma = &dev->dma; @@ -1091,6 +1140,7 @@ int b43_dma_init(struct b43_wldev *dev)  		break;  #endif  	} +	dma->translation_in_low = b43_dma_translation_in_low_word(dev, type);  	dma->parity = true;  #ifdef CONFIG_B43_BCMA diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index cdf87094efe..7e20b04fa51 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -162,12 +162,15 @@ struct b43_dmadesc_generic {  /* Misc DMA constants */  #define B43_DMA_RINGMEMSIZE		PAGE_SIZE -#define B43_DMA0_RX_FRAMEOFFSET		30 +/* Offset of frame with actual data */ +#define B43_DMA0_RX_FW598_FO		38 +#define B43_DMA0_RX_FW351_FO		30  /* DMA engine tuning knobs */  #define B43_TXRING_SLOTS		256  #define B43_RXRING_SLOTS		64 -#define B43_DMA0_RX_BUFFERSIZE		(B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_FW598_BUFSIZE	(B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) +#define B43_DMA0_RX_FW351_BUFSIZE	(B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)  /* Pointer poison */  #define B43_DMA_PTR_POISON		((void *)ERR_PTR(-ENOMEM)) @@ -212,6 +215,12 @@ enum b43_dmatype {  	B43_DMA_64BIT	= 64,  }; +enum b43_addrtype { +	B43_DMA_ADDR_LOW, +	B43_DMA_ADDR_HIGH, +	B43_DMA_ADDR_EXT, +}; +  struct b43_dmaring {  	/* Lowlevel DMA ops. */  	const struct b43_dma_ops *ops; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index d2661aaff50..d2b1d1fe202 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -66,7 +66,6 @@ MODULE_AUTHOR("Michael Buesch");  MODULE_AUTHOR("Gábor Stefanik");  MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);  MODULE_FIRMWARE("b43/ucode11.fw");  MODULE_FIRMWARE("b43/ucode13.fw");  MODULE_FIRMWARE("b43/ucode14.fw"); @@ -108,7 +107,7 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;  module_param_named(verbose, b43_modparam_verbose, int, 0644);  MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); -static int b43_modparam_pio = B43_PIO_DEFAULT; +static int b43_modparam_pio = 0;  module_param_named(pio, b43_modparam_pio, int, 0644);  MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); @@ -320,6 +319,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev);  static int b43_wireless_core_init(struct b43_wldev *dev);  static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);  static int b43_wireless_core_start(struct b43_wldev *dev); +static void b43_op_bss_info_changed(struct ieee80211_hw *hw, +				    struct ieee80211_vif *vif, +				    struct ieee80211_bss_conf *conf, +				    u32 changed);  static int b43_ratelimit(struct b43_wl *wl)  { @@ -2510,6 +2513,12 @@ static int b43_upload_microcode(struct b43_wldev *dev)  	}  	dev->fw.rev = fwrev;  	dev->fw.patch = fwpatch; +	if (dev->fw.rev >= 598) +		dev->fw.hdr_format = B43_FW_HDR_598; +	else if (dev->fw.rev >= 410) +		dev->fw.hdr_format = B43_FW_HDR_410; +	else +		dev->fw.hdr_format = B43_FW_HDR_351;  	dev->fw.opensource = (fwdate == 0xFFFF);  	/* Default to use-all-queues. */ @@ -2557,7 +2566,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)  			dev->fw.rev, dev->fw.patch);  	wiphy->hw_version = dev->dev->core_id; -	if (b43_is_old_txhdr_format(dev)) { +	if (dev->fw.hdr_format == B43_FW_HDR_351) {  		/* We're over the deadline, but we keep support for old fw  		 * until it turns out to be in major conflict with something new. */  		b43warn(dev->wl, "You are using an old firmware image. " @@ -2943,6 +2952,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)  	case B43_PHYTYPE_G:  	case B43_PHYTYPE_N:  	case B43_PHYTYPE_LP: +	case B43_PHYTYPE_HT:  		b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);  		b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);  		b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); @@ -3778,14 +3788,24 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)  	struct ieee80211_conf *conf = &hw->conf;  	int antenna;  	int err = 0; +	bool reload_bss = false;  	mutex_lock(&wl->mutex); +	dev = wl->current_dev; +  	/* Switch the band (if necessary). This might change the active core. */  	err = b43_switch_band(wl, conf->channel);  	if (err)  		goto out_unlock_mutex; -	dev = wl->current_dev; + +	/* Need to reload all settings if the core changed */ +	if (dev != wl->current_dev) { +		dev = wl->current_dev; +		changed = ~0; +		reload_bss = true; +	} +  	phy = &dev->phy;  	if (conf_is_ht(conf)) @@ -3846,6 +3866,9 @@ out_mac_enable:  out_unlock_mutex:  	mutex_unlock(&wl->mutex); +	if (wl->vif && reload_bss) +		b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0); +  	return err;  } @@ -3934,7 +3957,8 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,  	if (changed & BSS_CHANGED_BEACON_INT &&  	    (b43_is_mode(wl, NL80211_IFTYPE_AP) ||  	     b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || -	     b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) +	     b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) && +	    conf->beacon_int)  		b43_set_beacon_int(dev, conf->beacon_int);  	if (changed & BSS_CHANGED_BASIC_RATES) @@ -4629,8 +4653,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)  	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);  	if (b43_bus_host_is_pcmcia(dev->dev) || -	    b43_bus_host_is_sdio(dev->dev) || -	    dev->use_pio) { +	    b43_bus_host_is_sdio(dev->dev)) { +		dev->__using_pio_transfers = 1; +		err = b43_pio_init(dev); +	} else if (dev->use_pio) { +		b43warn(dev->wl, "Forced PIO by use_pio module parameter. " +			"This should not be needed and will result in lower " +			"performance.\n");  		dev->__using_pio_transfers = 1;  		err = b43_pio_init(dev);  	} else { @@ -4702,6 +4731,9 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,   out_mutex_unlock:  	mutex_unlock(&wl->mutex); +	if (err == 0) +		b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0); +  	return err;  } @@ -4772,6 +4804,9 @@ static int b43_op_start(struct ieee80211_hw *hw)   out_mutex_unlock:  	mutex_unlock(&wl->mutex); +	/* reload configuration */ +	b43_op_config(hw, ~0); +  	return err;  } @@ -4928,10 +4963,18 @@ out:  	if (err)  		wl->current_dev = NULL; /* Failed to init the dev. */  	mutex_unlock(&wl->mutex); -	if (err) + +	if (err) {  		b43err(wl, "Controller restart FAILED\n"); -	else -		b43info(wl, "Controller restarted\n"); +		return; +	} + +	/* reload configuration */ +	b43_op_config(wl->hw, ~0); +	if (wl->vif) +		b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0); + +	b43info(wl, "Controller restarted\n");  }  static int b43_setup_bands(struct b43_wldev *dev, @@ -5416,8 +5459,7 @@ static void b43_print_driverinfo(void)  	feat_sdio = "S";  #endif  	printk(KERN_INFO "Broadcom 43xx driver loaded " -	       "[ Features: %s%s%s%s%s, Firmware-ID: " -	       B43_SUPPORTED_FIRMWARE_ID " ]\n", +	       "[ Features: %s%s%s%s%s ]\n",  	       feat_pci, feat_pcmcia, feat_nphy,  	       feat_leds, feat_sdio);  } diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 07f009ff5ee..3ea44bb0368 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c @@ -448,6 +448,38 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)  		channel_type == NL80211_CHAN_HT40PLUS);  } +/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ +void b43_phy_force_clock(struct b43_wldev *dev, bool force) +{ +	u32 tmp; + +	WARN_ON(dev->phy.type != B43_PHYTYPE_N && +		dev->phy.type != B43_PHYTYPE_HT); + +	switch (dev->dev->bus_type) { +#ifdef CONFIG_B43_BCMA +	case B43_BUS_BCMA: +		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); +		if (force) +			tmp |= BCMA_IOCTL_FGC; +		else +			tmp &= ~BCMA_IOCTL_FGC; +		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); +		break; +#endif +#ifdef CONFIG_B43_SSB +	case B43_BUS_SSB: +		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); +		if (force) +			tmp |= SSB_TMSLOW_FGC; +		else +			tmp &= ~SSB_TMSLOW_FGC; +		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); +		break; +#endif +	} +} +  /* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */  struct b43_c32 b43_cordic(int theta)  { diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index aa77ba612a9..9233b13fc16 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -444,6 +444,8 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);  bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type); +void b43_phy_force_clock(struct b43_wldev *dev, bool force); +  struct b43_c32 b43_cordic(int theta);  #endif /* LINUX_B43_PHY_COMMON_H_ */ diff --git a/drivers/net/wireless/b43/phy_ht.c b/drivers/net/wireless/b43/phy_ht.c index 7c40919651a..4d6345e8ee6 100644 --- a/drivers/net/wireless/b43/phy_ht.c +++ b/drivers/net/wireless/b43/phy_ht.c @@ -152,6 +152,92 @@ static void b43_radio_2059_init(struct b43_wldev *dev)  }  /************************************************** + * Various PHY ops + **************************************************/ + +static void b43_phy_ht_zero_extg(struct b43_wldev *dev) +{ +	u8 i, j; +	u16 base[] = { 0x40, 0x60, 0x80 }; + +	for (i = 0; i < ARRAY_SIZE(base); i++) { +		for (j = 0; j < 4; j++) +			b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0); +	} + +	for (i = 0; i < ARRAY_SIZE(base); i++) +		b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0); +} + +/* Some unknown AFE (Analog Frondned) op */ +static void b43_phy_ht_afe_unk1(struct b43_wldev *dev) +{ +	u8 i; + +	const u16 ctl_regs[3][2] = { +		{ B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 }, +		{ B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 }, +		{ B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6}, +	}; + +	for (i = 0; i < 3; i++) { +		/* TODO: verify masks&sets */ +		b43_phy_set(dev, ctl_regs[i][1], 0x4); +		b43_phy_set(dev, ctl_regs[i][0], 0x4); +		b43_phy_mask(dev, ctl_regs[i][1], ~0x1); +		b43_phy_set(dev, ctl_regs[i][0], 0x1); +		b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0); +		b43_phy_mask(dev, ctl_regs[i][0], ~0x4); +	} +} + +static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq) +{ +	u8 i; + +	u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE); +	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3); + +	b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq); +	for (i = 0; i < 200; i++) { +		if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) { +			i = 0; +			break; +		} +		msleep(1); +	} +	if (i) +		b43err(dev->wl, "Forcing RF sequence timeout\n"); + +	b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode); +} + +static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st) +{ +	clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES); +	clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES); +	clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES); +} + +static void b43_phy_ht_bphy_init(struct b43_wldev *dev) +{ +	unsigned int i; +	u16 val; + +	val = 0x1E1F; +	for (i = 0; i < 16; i++) { +		b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); +		val -= 0x202; +	} +	val = 0x3E3F; +	for (i = 0; i < 16; i++) { +		b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val); +		val -= 0x202; +	} +	b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); +} + +/**************************************************   * Channel switching ops.   **************************************************/ @@ -255,8 +341,125 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)  static int b43_phy_ht_op_init(struct b43_wldev *dev)  { +	u16 tmp; +	u16 clip_state[3]; +  	b43_phy_ht_tables_init(dev); +	b43_phy_mask(dev, 0x0be, ~0x2); +	b43_phy_set(dev, 0x23f, 0x7ff); +	b43_phy_set(dev, 0x240, 0x7ff); +	b43_phy_set(dev, 0x241, 0x7ff); + +	b43_phy_ht_zero_extg(dev); + +	b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3); + +	b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0); +	b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0); +	b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0); + +	b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20); +	b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20); +	b43_phy_write(dev, 0x20d, 0xb8); +	b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8); +	b43_phy_write(dev, 0x70, 0x50); +	b43_phy_write(dev, 0x1ff, 0x30); + +	if (0) /* TODO: condition */ +		; /* TODO: PHY op on reg 0x217 */ + +	b43_phy_read(dev, 0xb0); /* TODO: what for? */ +	b43_phy_set(dev, 0xb0, 0x1); + +	b43_phy_set(dev, 0xb1, 0x91); +	b43_phy_write(dev, 0x32f, 0x0003); +	b43_phy_write(dev, 0x077, 0x0010); +	b43_phy_write(dev, 0x0b4, 0x0258); +	b43_phy_mask(dev, 0x17e, ~0x4000); + +	b43_phy_write(dev, 0x0b9, 0x0072); + +	b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f); +	b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f); +	b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f); + +	b43_phy_ht_afe_unk1(dev); + +	b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111, +			    0x777, 0x111, 0x111, 0x777, 0x111, 0x111); + +	b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777); +	b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777); + +	b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02); +	b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02); +	b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02); + +	b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4, +			    0x8e, 0x96, 0x96, 0x96); +	b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4, +			    0x8f, 0x9f, 0x9f, 0x9f); +	b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4, +			    0x8f, 0x9f, 0x9f, 0x9f); + +	b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2); +	b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2); +	b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2); + +	b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e); +	b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e); +	b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46); +	b43_phy_maskset(dev, 0x0283, 0xff00, 0x40); + +	b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4, +			    0x09, 0x0e, 0x13, 0x18); +	b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4, +			    0x09, 0x0e, 0x13, 0x18); +	/* TODO: Did wl mean 2 instead of 40? */ +	b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4, +			    0x09, 0x0e, 0x13, 0x18); + +	b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd); +	b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd); +	b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd); + +	b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1); +	b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1); +	b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1); +	b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1); + +	/* Copy some tables entries */ +	tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144)); +	b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp); +	tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154)); +	b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp); +	tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164)); +	b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp); + +	/* Reset CCA */ +	b43_phy_force_clock(dev, true); +	tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG); +	b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA); +	b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA); +	b43_phy_force_clock(dev, false); + +	b43_mac_phy_clock_set(dev, true); + +	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX); +	b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX); + +	/* TODO: PHY op on reg 0xb0 */ + +	/* TODO: Should we restore it? Or store it in global PHY info? */ +	b43_phy_ht_read_clip_detection(dev, clip_state); + +	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) +		b43_phy_ht_bphy_init(dev); + +	b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0), +			B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late); +  	return 0;  } diff --git a/drivers/net/wireless/b43/phy_ht.h b/drivers/net/wireless/b43/phy_ht.h index 7ad7affc8df..6544c4293b3 100644 --- a/drivers/net/wireless/b43/phy_ht.h +++ b/drivers/net/wireless/b43/phy_ht.h @@ -4,7 +4,11 @@  #include "phy_common.h" +#define B43_PHY_HT_BBCFG			0x001 /* BB config */ +#define  B43_PHY_HT_BBCFG_RSTCCA		0x4000 /* Reset CCA */ +#define  B43_PHY_HT_BBCFG_RSTRX			0x8000 /* Reset RX */  #define B43_PHY_HT_BANDCTL			0x009 /* Band control */ +#define  B43_PHY_HT_BANDCTL_5GHZ		0x0001 /* Use the 5GHz band */  #define B43_PHY_HT_TABLE_ADDR			0x072 /* Table address */  #define B43_PHY_HT_TABLE_DATALO			0x073 /* Table data low */  #define B43_PHY_HT_TABLE_DATAHI			0x074 /* Table data high */ @@ -15,6 +19,21 @@  #define B43_PHY_HT_BW5				0x1D2  #define B43_PHY_HT_BW6				0x1D3 +#define B43_PHY_HT_C1_CLIP1THRES		B43_PHY_OFDM(0x00E) +#define B43_PHY_HT_C2_CLIP1THRES		B43_PHY_OFDM(0x04E) +#define B43_PHY_HT_C3_CLIP1THRES		B43_PHY_OFDM(0x08E) + +#define B43_PHY_HT_RF_SEQ_MODE			B43_PHY_EXTG(0x000) +#define B43_PHY_HT_RF_SEQ_TRIG			B43_PHY_EXTG(0x003) +#define  B43_PHY_HT_RF_SEQ_TRIG_RX2TX		0x0001 /* RX2TX */ +#define  B43_PHY_HT_RF_SEQ_TRIG_TX2RX		0x0002 /* TX2RX */ +#define  B43_PHY_HT_RF_SEQ_TRIG_UPGH		0x0004 /* Update gain H */ +#define  B43_PHY_HT_RF_SEQ_TRIG_UPGL		0x0008 /* Update gain L */ +#define  B43_PHY_HT_RF_SEQ_TRIG_UPGU		0x0010 /* Update gain U */ +#define  B43_PHY_HT_RF_SEQ_TRIG_RST2RX		0x0020 /* Reset to RX */ +#define B43_PHY_HT_RF_SEQ_STATUS		B43_PHY_EXTG(0x004) +/* Values for the status are the same as for the trigger */ +  #define B43_PHY_HT_RF_CTL1			B43_PHY_EXTG(0x010)  #define B43_PHY_HT_AFE_CTL1			B43_PHY_EXTG(0x110) diff --git a/drivers/net/wireless/b43/phy_lcn.c b/drivers/net/wireless/b43/phy_lcn.c index 9f7dbbd5ced..4b2cd6d24ce 100644 --- a/drivers/net/wireless/b43/phy_lcn.c +++ b/drivers/net/wireless/b43/phy_lcn.c @@ -28,25 +28,232 @@  #include "main.h"  /************************************************** + * Radio 2064. + **************************************************/ + +static void b43_radio_2064_init(struct b43_wldev *dev) +{ +	b43_radio_write(dev, 0x09c, 0x0020); +	b43_radio_write(dev, 0x105, 0x0008); +	b43_radio_write(dev, 0x032, 0x0062); +	b43_radio_write(dev, 0x033, 0x0019); +	b43_radio_write(dev, 0x090, 0x0010); +	b43_radio_write(dev, 0x010, 0x0000); +	b43_radio_write(dev, 0x060, 0x007f); +	b43_radio_write(dev, 0x061, 0x0072); +	b43_radio_write(dev, 0x062, 0x007f); +	b43_radio_write(dev, 0x01d, 0x0002); +	b43_radio_write(dev, 0x01e, 0x0006); + +	b43_phy_write(dev, 0x4ea, 0x4688); +	b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2); +	b43_phy_mask(dev, 0x4eb, ~0x01c0); +	b43_phy_maskset(dev, 0x4eb, 0xff00, 0x19); + +	b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0); + +	b43_radio_mask(dev, 0x05b, (u16) ~0xff02); +	b43_radio_set(dev, 0x004, 0x40); +	b43_radio_set(dev, 0x120, 0x10); +	b43_radio_set(dev, 0x078, 0x80); +	b43_radio_set(dev, 0x129, 0x2); +	b43_radio_set(dev, 0x057, 0x1); +	b43_radio_set(dev, 0x05b, 0x2); + +	/* TODO: wait for some bit to be set */ +	b43_radio_read(dev, 0x05c); + +	b43_radio_mask(dev, 0x05b, (u16) ~0xff02); +	b43_radio_mask(dev, 0x057, (u16) ~0xff01); + +	b43_phy_write(dev, 0x933, 0x2d6b); +	b43_phy_write(dev, 0x934, 0x2d6b); +	b43_phy_write(dev, 0x935, 0x2d6b); +	b43_phy_write(dev, 0x936, 0x2d6b); +	b43_phy_write(dev, 0x937, 0x016b); + +	b43_radio_mask(dev, 0x057, (u16) ~0xff02); +	b43_radio_write(dev, 0x0c2, 0x006f); +} + +/************************************************** + * Various PHY ops + **************************************************/ + +static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev) +{ +	u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2); +	u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1); + +	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1); +	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1); + +	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1); +	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1); + +	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2); +	b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1); +} + +static void b43_phy_lcn_clean_0x18_table(struct b43_wldev *dev) +{ +	u8 i; + +	for (i = 0; i < 0x80; i++) +		b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000); +} + +static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev) +{ +	u8 i; + +	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340); +	for (i = 0; i < 30; i++) { +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0); +	} + +	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80); +	for (i = 0; i < 64; i++) { +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0); +	} +} + +/************************************************** + * Basic PHY ops. + **************************************************/ + +static int b43_phy_lcn_op_allocate(struct b43_wldev *dev) +{ +	struct b43_phy_lcn *phy_lcn; + +	phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL); +	if (!phy_lcn) +		return -ENOMEM; +	dev->phy.lcn = phy_lcn; + +	return 0; +} + +static void b43_phy_lcn_op_free(struct b43_wldev *dev) +{ +	struct b43_phy *phy = &dev->phy; +	struct b43_phy_lcn *phy_lcn = phy->lcn; + +	kfree(phy_lcn); +	phy->lcn = NULL; +} + +static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev) +{ +	struct b43_phy *phy = &dev->phy; +	struct b43_phy_lcn *phy_lcn = phy->lcn; + +	memset(phy_lcn, 0, sizeof(*phy_lcn)); +} + +static int b43_phy_lcn_op_init(struct b43_wldev *dev) +{ +	b43_phy_set(dev, 0x44a, 0x80); +	b43_phy_mask(dev, 0x44a, 0x7f); +	b43_phy_set(dev, 0x6d1, 0x80); +	b43_phy_write(dev, 0x6d0, 0x7); + +	b43_phy_lcn_afe_set_unset(dev); + +	b43_phy_write(dev, 0x60a, 0xa0); +	b43_phy_write(dev, 0x46a, 0x19); +	b43_phy_maskset(dev, 0x663, 0xFF00, 0x64); + +	b43_phy_lcn_tables_init(dev); +	/* TODO: various tables ops here */ +	b43_phy_lcn_clean_0x18_table(dev); + +	/* TODO: some ops here */ + +	b43_phy_lcn_clear_0x07_table(dev); + +	if (dev->phy.radio_ver == 0x2064) +		b43_radio_2064_init(dev); +	else +		B43_WARN_ON(1); + +	return 0; +} + +static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev, +					bool blocked) +{ +	if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED) +		b43err(dev->wl, "MAC not suspended\n"); + +	if (blocked) { +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00); +		b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00); + +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00); +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2); +		b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808); + +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8); +		b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8); +	} else { +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00); +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808); +		b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8); +	} +} + +static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on) +{ +	if (on) { +		b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7); +	} else { +		b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7); +		b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7); +	} +} + +static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev) +{ +	if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) +		return 1; +	return 36; +} + +static enum b43_txpwr_result +b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi) +{ +	return B43_TXPWR_RES_DONE; +} + +static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev) +{ +} + +/**************************************************   * PHY ops struct.   **************************************************/  const struct b43_phy_operations b43_phyops_lcn = { -	/*  	.allocate		= b43_phy_lcn_op_allocate,  	.free			= b43_phy_lcn_op_free,  	.prepare_structs	= b43_phy_lcn_op_prepare_structs,  	.init			= b43_phy_lcn_op_init, +	/*  	.phy_read		= b43_phy_lcn_op_read,  	.phy_write		= b43_phy_lcn_op_write,  	.phy_maskset		= b43_phy_lcn_op_maskset,  	.radio_read		= b43_phy_lcn_op_radio_read,  	.radio_write		= b43_phy_lcn_op_radio_write, +	*/  	.software_rfkill	= b43_phy_lcn_op_software_rfkill,  	.switch_analog		= b43_phy_lcn_op_switch_analog, +	/*  	.switch_channel		= b43_phy_lcn_op_switch_channel, +	*/  	.get_default_chan	= b43_phy_lcn_op_get_default_chan,  	.recalc_txpower		= b43_phy_lcn_op_recalc_txpower,  	.adjust_txpower		= b43_phy_lcn_op_adjust_txpower, -	*/  }; diff --git a/drivers/net/wireless/b43/phy_lcn.h b/drivers/net/wireless/b43/phy_lcn.h index c046c2a6cab..25f06e8d453 100644 --- a/drivers/net/wireless/b43/phy_lcn.h +++ b/drivers/net/wireless/b43/phy_lcn.h @@ -4,6 +4,20 @@  #include "phy_common.h" +#define B43_PHY_LCN_AFE_CTL1			B43_PHY_OFDM(0x03B) +#define B43_PHY_LCN_AFE_CTL2			B43_PHY_OFDM(0x03C) +#define B43_PHY_LCN_RF_CTL1			B43_PHY_OFDM(0x04C) +#define B43_PHY_LCN_RF_CTL2			B43_PHY_OFDM(0x04D) +#define B43_PHY_LCN_TABLE_ADDR			B43_PHY_OFDM(0x055) /* Table address */ +#define B43_PHY_LCN_TABLE_DATALO		B43_PHY_OFDM(0x056) /* Table data low */ +#define B43_PHY_LCN_TABLE_DATAHI		B43_PHY_OFDM(0x057) /* Table data high */ +#define B43_PHY_LCN_RF_CTL3			B43_PHY_OFDM(0x0B0) +#define B43_PHY_LCN_RF_CTL4			B43_PHY_OFDM(0x0B1) +#define B43_PHY_LCN_RF_CTL5			B43_PHY_OFDM(0x0B7) +#define B43_PHY_LCN_RF_CTL6			B43_PHY_OFDM(0x0F9) +#define B43_PHY_LCN_RF_CTL7			B43_PHY_OFDM(0x0FA) + +  struct b43_phy_lcn {  }; @@ -11,4 +25,4 @@ struct b43_phy_lcn {  struct b43_phy_operations;  extern const struct b43_phy_operations b43_phyops_lcn; -#endif /* B43_PHY_LCN_H_ */
\ No newline at end of file +#endif /* B43_PHY_LCN_H_ */ diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3b46360da99..2eadadf5f4f 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -600,49 +600,17 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)  	}  } -/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ -static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force) -{ -	u32 tmp; - -	if (dev->phy.type != B43_PHYTYPE_N) -		return; - -	switch (dev->dev->bus_type) { -#ifdef CONFIG_B43_BCMA -	case B43_BUS_BCMA: -		tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); -		if (force) -			tmp |= BCMA_IOCTL_FGC; -		else -			tmp &= ~BCMA_IOCTL_FGC; -		bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); -		break; -#endif -#ifdef CONFIG_B43_SSB -	case B43_BUS_SSB: -		tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); -		if (force) -			tmp |= SSB_TMSLOW_FGC; -		else -			tmp &= ~SSB_TMSLOW_FGC; -		ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); -		break; -#endif -	} -} -  /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */  static void b43_nphy_reset_cca(struct b43_wldev *dev)  {  	u16 bbcfg; -	b43_nphy_bmac_clock_fgc(dev, 1); +	b43_phy_force_clock(dev, 1);  	bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);  	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);  	udelay(1);  	b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA); -	b43_nphy_bmac_clock_fgc(dev, 0); +	b43_phy_force_clock(dev, 0);  	b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);  } @@ -3715,11 +3683,11 @@ int b43_phy_initn(struct b43_wldev *dev)  	b43_nphy_workarounds(dev);  	/* Reset CCA, in init code it differs a little from standard way */ -	b43_nphy_bmac_clock_fgc(dev, 1); +	b43_phy_force_clock(dev, 1);  	tmp = b43_phy_read(dev, B43_NPHY_BBCFG);  	b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);  	b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); -	b43_nphy_bmac_clock_fgc(dev, 0); +	b43_phy_force_clock(dev, 0);  	b43_mac_phy_clock_set(dev, true); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 6e4228c3ed1..fcff923b3c1 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -611,7 +611,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)  	struct b43_wldev *dev = q->dev;  	struct b43_wl *wl = dev->wl;  	u16 len; -	u32 macstat; +	u32 macstat = 0;  	unsigned int i, padding;  	struct sk_buff *skb;  	const char *err_msg = NULL; @@ -676,7 +676,15 @@ data_ready:  		goto rx_error;  	} -	macstat = le32_to_cpu(rxhdr->mac_status); +	switch (dev->fw.hdr_format) { +	case B43_FW_HDR_598: +		macstat = le32_to_cpu(rxhdr->format_598.mac_status); +		break; +	case B43_FW_HDR_410: +	case B43_FW_HDR_351: +		macstat = le32_to_cpu(rxhdr->format_351.mac_status); +		break; +	}  	if (macstat & B43_RX_MAC_FCSERR) {  		if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {  			/* Drop frames with failed FCS. */ diff --git a/drivers/net/wireless/b43/tables_phy_ht.c b/drivers/net/wireless/b43/tables_phy_ht.c index 603938657b1..677d217b5fb 100644 --- a/drivers/net/wireless/b43/tables_phy_ht.c +++ b/drivers/net/wireless/b43/tables_phy_ht.c @@ -574,6 +574,42 @@ static const u32 b43_httab_0x24[] = {  	0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,  }; +/* Some late-init table */ +const u32 b43_httab_0x1a_0xc0_late[] = { +	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d, +	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b, +	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039, +	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d, +	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b, +	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b, +	0x10390038, 0x10390035, 0x1031003a, 0x10310036, +	0x10310033, 0x1029003a, 0x10290037, 0x10290034, +	0x10290031, 0x10210039, 0x10210036, 0x10210033, +	0x10210030, 0x1019003c, 0x10190039, 0x10190036, +	0x10190033, 0x10190030, 0x1019002d, 0x1019002b, +	0x10190028, 0x1011003a, 0x10110036, 0x10110033, +	0x10110030, 0x1011002e, 0x1011002b, 0x10110029, +	0x10110027, 0x10110024, 0x10110022, 0x10110020, +	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037, +	0x10090034, 0x10090031, 0x1009002e, 0x1009002c, +	0x10090029, 0x10090027, 0x10090025, 0x10090023, +	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b, +	0x1009001a, 0x10090018, 0x10090017, 0x10090016, +	0x10090015, 0x10090013, 0x10090012, 0x10090011, +	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e, +	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b, +	0x1009000a, 0x1009000a, 0x10090009, 0x10090009, +	0x10090008, 0x10090008, 0x10090007, 0x10090007, +	0x10090007, 0x10090006, 0x10090006, 0x10090005, +	0x10090005, 0x10090005, 0x10090005, 0x10090004, +	0x10090004, 0x10090004, 0x10090004, 0x10090003, +	0x10090003, 0x10090003, 0x10090003, 0x10090003, +	0x10090003, 0x10090002, 0x10090002, 0x10090002, +	0x10090002, 0x10090002, 0x10090002, 0x10090002, +	0x10090002, 0x10090002, 0x10090001, 0x10090001, +	0x10090001, 0x10090001, 0x10090001, 0x10090001, +}; +  /**************************************************   * R/W ops.   **************************************************/ @@ -674,6 +710,51 @@ void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)  	return;  } +void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...) +{ +	va_list args; +	u32 type, value; +	unsigned int i; + +	type = offset & B43_HTTAB_TYPEMASK; +	offset &= 0xFFFF; + +	va_start(args, num); +	switch (type) { +	case B43_HTTAB_8BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		for (i = 0; i < num; i++) { +			value = va_arg(args, int); +			B43_WARN_ON(value & ~0xFF); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); +		} +		break; +	case B43_HTTAB_16BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		for (i = 0; i < num; i++) { +			value = va_arg(args, int); +			B43_WARN_ON(value & ~0xFFFF); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value); +		} +		break; +	case B43_HTTAB_32BIT: +		b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset); +		for (i = 0; i < num; i++) { +			value = va_arg(args, int); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, +				      value >> 16); +			b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, +				      value & 0xFFFF); +		} +		break; +	default: +		B43_WARN_ON(1); +	} +	va_end(args); + +	return; +} +  void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,  			  unsigned int nr_elements, const void *_data)  { @@ -723,6 +804,9 @@ void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,  	} while (0)  void b43_phy_ht_tables_init(struct b43_wldev *dev)  { +	BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) != +			B43_HTTAB_1A_C0_LATE_SIZE); +  	httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);  	httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);  	httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26); diff --git a/drivers/net/wireless/b43/tables_phy_ht.h b/drivers/net/wireless/b43/tables_phy_ht.h index ea3be382c89..1b5ef2bc770 100644 --- a/drivers/net/wireless/b43/tables_phy_ht.h +++ b/drivers/net/wireless/b43/tables_phy_ht.h @@ -14,9 +14,13 @@ u32 b43_httab_read(struct b43_wldev *dev, u32 offset);  void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,  			 unsigned int nr_elements, void *_data);  void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...);  void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,  			  unsigned int nr_elements, const void *_data);  void b43_phy_ht_tables_init(struct b43_wldev *dev); +#define B43_HTTAB_1A_C0_LATE_SIZE		128 +extern const u32 b43_httab_0x1a_0xc0_late[]; +  #endif /* B43_TABLES_PHY_HT_H_ */ diff --git a/drivers/net/wireless/b43/tables_phy_lcn.c b/drivers/net/wireless/b43/tables_phy_lcn.c index 40c1d0915dd..0a5842808a7 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.c +++ b/drivers/net/wireless/b43/tables_phy_lcn.c @@ -25,10 +25,442 @@  #include "phy_common.h"  #include "phy_lcn.h" +static const u16 b43_lcntab_0x02[] = { +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, 0x014d, 0x014d, +	0x014d, 0x014d, 0x014d, 0x014d, +}; + +static const u16 b43_lcntab_0x01[] = { +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, +}; + +static const u32 b43_lcntab_0x0b[] = { +	0x000141f8, 0x000021f8, 0x000021fb, 0x000041fb, +	0x0001fedb, 0x0000217b, 0x00002133, 0x000040eb, +	0x0001fea3, 0x0000024b, +}; + +static const u32 b43_lcntab_0x0c[] = { +	0x00100001, 0x00200010, 0x00300001, 0x00400010, +	0x00500022, 0x00600122, 0x00700222, 0x00800322, +	0x00900422, 0x00a00522, 0x00b00622, 0x00c00722, +	0x00d00822, 0x00f00922, 0x00100a22, 0x00200b22, +	0x00300c22, 0x00400d22, 0x00500e22, 0x00600f22, +}; + +static const u32 b43_lcntab_0x0d[] = { +	0x00000000, 0x00000000, 0x10000000, 0x00000000, +	0x20000000, 0x00000000, 0x30000000, 0x00000000, +	0x40000000, 0x00000000, 0x50000000, 0x00000000, +	0x60000000, 0x00000000, 0x70000000, 0x00000000, +	0x80000000, 0x00000000, 0x90000000, 0x00000008, +	0xa0000000, 0x00000008, 0xb0000000, 0x00000008, +	0xc0000000, 0x00000008, 0xd0000000, 0x00000008, +	0xe0000000, 0x00000008, 0xf0000000, 0x00000008, +	0x00000000, 0x00000009, 0x10000000, 0x00000009, +	0x20000000, 0x00000019, 0x30000000, 0x00000019, +	0x40000000, 0x00000019, 0x50000000, 0x00000019, +	0x60000000, 0x00000019, 0x70000000, 0x00000019, +	0x80000000, 0x00000019, 0x90000000, 0x00000019, +	0xa0000000, 0x00000019, 0xb0000000, 0x00000019, +	0xc0000000, 0x00000019, 0xd0000000, 0x00000019, +	0xe0000000, 0x00000019, 0xf0000000, 0x00000019, +	0x00000000, 0x0000001a, 0x10000000, 0x0000001a, +	0x20000000, 0x0000001a, 0x30000000, 0x0000001a, +	0x40000000, 0x0000001a, 0x50000000, 0x00000002, +	0x60000000, 0x00000002, 0x70000000, 0x00000002, +	0x80000000, 0x00000002, 0x90000000, 0x00000002, +	0xa0000000, 0x00000002, 0xb0000000, 0x00000002, +	0xc0000000, 0x0000000a, 0xd0000000, 0x0000000a, +	0xe0000000, 0x0000000a, 0xf0000000, 0x0000000a, +	0x00000000, 0x0000000b, 0x10000000, 0x0000000b, +	0x20000000, 0x0000000b, 0x30000000, 0x0000000b, +	0x40000000, 0x0000000b, 0x50000000, 0x0000001b, +	0x60000000, 0x0000001b, 0x70000000, 0x0000001b, +	0x80000000, 0x0000001b, 0x90000000, 0x0000001b, +	0xa0000000, 0x0000001b, 0xb0000000, 0x0000001b, +	0xc0000000, 0x0000001b, 0xd0000000, 0x0000001b, +	0xe0000000, 0x0000001b, 0xf0000000, 0x0000001b, +	0x00000000, 0x0000001c, 0x10000000, 0x0000001c, +	0x20000000, 0x0000001c, 0x30000000, 0x0000001c, +	0x40000000, 0x0000001c, 0x50000000, 0x0000001c, +	0x60000000, 0x0000001c, 0x70000000, 0x0000001c, +	0x80000000, 0x0000001c, 0x90000000, 0x0000001c, +}; + +static const u16 b43_lcntab_0x0e[] = { +	0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, +	0x0407, 0x0408, 0x0409, 0x040a, 0x058b, 0x058c, +	0x058d, 0x058e, 0x058f, 0x0090, 0x0091, 0x0092, +	0x0193, 0x0194, 0x0195, 0x0196, 0x0197, 0x0198, +	0x0199, 0x019a, 0x019b, 0x019c, 0x019d, 0x019e, +	0x019f, 0x01a0, 0x01a1, 0x01a2, 0x01a3, 0x01a4, +	0x01a5, 0x0000, +}; + +static const u16 b43_lcntab_0x0f[] = { +	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, +	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, +	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, +	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, +	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, +	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, +	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, +	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, +	0x000a, 0x0009, 0x0006, 0x0005, 0x000a, 0x0009, +	0x0006, 0x0005, 0x000a, 0x0009, 0x0006, 0x0005, +	0x000a, 0x0009, 0x0006, 0x0005, +}; + +static const u16 b43_lcntab_0x10[] = { +	0x005f, 0x0036, 0x0029, 0x001f, 0x005f, 0x0036, +	0x0029, 0x001f, 0x005f, 0x0036, 0x0029, 0x001f, +	0x005f, 0x0036, 0x0029, 0x001f, +}; + +static const u16 b43_lcntab_0x11[] = { +	0x0009, 0x000f, 0x0014, 0x0018, 0x00fe, 0x0007, +	0x000b, 0x000f, 0x00fb, 0x00fe, 0x0001, 0x0005, +	0x0008, 0x000b, 0x000e, 0x0011, 0x0014, 0x0017, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, +	0x0012, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0003, +	0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, +	0x0018, 0x001b, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0003, 0x00eb, 0x0000, 0x0000, +}; + +static const u32 b43_lcntab_0x12[] = { +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000004, 0x00000000, 0x00000004, 0x00000008, +	0x00000001, 0x00000005, 0x00000009, 0x0000000d, +	0x0000004d, 0x0000008d, 0x0000000d, 0x0000004d, +	0x0000008d, 0x000000cd, 0x0000004f, 0x0000008f, +	0x000000cf, 0x000000d3, 0x00000113, 0x00000513, +	0x00000913, 0x00000953, 0x00000d53, 0x00001153, +	0x00001193, 0x00005193, 0x00009193, 0x0000d193, +	0x00011193, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000004, +	0x00000000, 0x00000004, 0x00000008, 0x00000001, +	0x00000005, 0x00000009, 0x0000000d, 0x0000004d, +	0x0000008d, 0x0000000d, 0x0000004d, 0x0000008d, +	0x000000cd, 0x0000004f, 0x0000008f, 0x000000cf, +	0x000000d3, 0x00000113, 0x00000513, 0x00000913, +	0x00000953, 0x00000d53, 0x00001153, 0x00005153, +	0x00009153, 0x0000d153, 0x00011153, 0x00015153, +	0x00019153, 0x0001d153, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +	0x00000000, 0x00000000, 0x00000000, 0x00000000, +}; + +static const u16 b43_lcntab_0x14[] = { +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0002, 0x0003, 0x0001, 0x0003, 0x0002, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0002, 0x0003, +	0x0001, 0x0003, 0x0002, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, +	0x0001, 0x0001, +}; + +static const u16 b43_lcntab_0x17[] = { +	0x001a, 0x0034, 0x004e, 0x0068, 0x009c, 0x00d0, +	0x00ea, 0x0104, 0x0034, 0x0068, 0x009c, 0x00d0, +	0x0138, 0x01a0, 0x01d4, 0x0208, 0x004e, 0x009c, +	0x00ea, 0x0138, 0x01d4, 0x0270, 0x02be, 0x030c, +	0x0068, 0x00d0, 0x0138, 0x01a0, 0x0270, 0x0340, +	0x03a8, 0x0410, 0x0018, 0x009c, 0x00d0, 0x0104, +	0x00ea, 0x0138, 0x0186, 0x00d0, 0x0104, 0x0104, +	0x0138, 0x016c, 0x016c, 0x01a0, 0x0138, 0x0186, +	0x0186, 0x01d4, 0x0222, 0x0222, 0x0270, 0x0104, +	0x0138, 0x016c, 0x0138, 0x016c, 0x01a0, 0x01d4, +	0x01a0, 0x01d4, 0x0208, 0x0208, 0x023c, 0x0186, +	0x01d4, 0x0222, 0x01d4, 0x0222, 0x0270, 0x02be, +	0x0270, 0x02be, 0x030c, 0x030c, 0x035a, 0x0036, +	0x006c, 0x00a2, 0x00d8, 0x0144, 0x01b0, 0x01e6, +	0x021c, 0x006c, 0x00d8, 0x0144, 0x01b0, 0x0288, +	0x0360, 0x03cc, 0x0438, 0x00a2, 0x0144, 0x01e6, +	0x0288, 0x03cc, 0x0510, 0x05b2, 0x0654, 0x00d8, +	0x01b0, 0x0288, 0x0360, 0x0510, 0x06c0, 0x0798, +	0x0870, 0x0018, 0x0144, 0x01b0, 0x021c, 0x01e6, +	0x0288, 0x032a, 0x01b0, 0x021c, 0x021c, 0x0288, +	0x02f4, 0x02f4, 0x0360, 0x0288, 0x032a, 0x032a, +	0x03cc, 0x046e, 0x046e, 0x0510, 0x021c, 0x0288, +	0x02f4, 0x0288, 0x02f4, 0x0360, 0x03cc, 0x0360, +	0x03cc, 0x0438, 0x0438, 0x04a4, 0x032a, 0x03cc, +	0x046e, 0x03cc, 0x046e, 0x0510, 0x05b2, 0x0510, +	0x05b2, 0x0654, 0x0654, 0x06f6, +}; + +static const u16 b43_lcntab_0x00[] = { +	0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, +	0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, +	0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600, +	0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, +	0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, +	0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +static const u32 b43_lcntab_0x18[] = { +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +	0x00080000, 0x00080000, 0x00080000, 0x00080000, +}; + +/************************************************** + * R/W ops. + **************************************************/ + +u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset) +{ +	u32 type, value; + +	type = offset & B43_LCNTAB_TYPEMASK; +	offset &= ~B43_LCNTAB_TYPEMASK; +	B43_WARN_ON(offset > 0xFFFF); + +	switch (type) { +	case B43_LCNTAB_8BIT: +		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); +		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO) & 0xFF; +		break; +	case B43_LCNTAB_16BIT: +		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); +		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO); +		break; +	case B43_LCNTAB_32BIT: +		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); +		value = b43_phy_read(dev, B43_PHY_LCN_TABLE_DATAHI); +		value <<= 16; +		value |= b43_phy_read(dev, B43_PHY_LCN_TABLE_DATALO); +		break; +	default: +		B43_WARN_ON(1); +		value = 0; +	} + +	return value; +} + +void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, +			  unsigned int nr_elements, void *_data) +{ +	u32 type; +	u8 *data = _data; +	unsigned int i; + +	type = offset & B43_LCNTAB_TYPEMASK; +	offset &= ~B43_LCNTAB_TYPEMASK; +	B43_WARN_ON(offset > 0xFFFF); + +	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + +	for (i = 0; i < nr_elements; i++) { +		switch (type) { +		case B43_LCNTAB_8BIT: +			*data = b43_phy_read(dev, +					     B43_PHY_LCN_TABLE_DATALO) & 0xFF; +			data++; +			break; +		case B43_LCNTAB_16BIT: +			*((u16 *)data) = b43_phy_read(dev, +						      B43_PHY_LCN_TABLE_DATALO); +			data += 2; +			break; +		case B43_LCNTAB_32BIT: +			*((u32 *)data) = b43_phy_read(dev, +						      B43_PHY_LCN_TABLE_DATAHI); +			*((u32 *)data) <<= 16; +			*((u32 *)data) |= b43_phy_read(dev, +						B43_PHY_LCN_TABLE_DATALO); +			data += 4; +			break; +		default: +			B43_WARN_ON(1); +		} +	} +} + +void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value) +{ +	u32 type; + +	type = offset & B43_LCNTAB_TYPEMASK; +	offset &= 0xFFFF; + +	switch (type) { +	case B43_LCNTAB_8BIT: +		B43_WARN_ON(value & ~0xFF); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); +		break; +	case B43_LCNTAB_16BIT: +		B43_WARN_ON(value & ~0xFFFF); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); +		break; +	case B43_LCNTAB_32BIT: +		b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, value >> 16); +		b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value & 0xFFFF); +		break; +	default: +		B43_WARN_ON(1); +	} + +	return; +} + +void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset, +			   unsigned int nr_elements, const void *_data) +{ +	u32 type, value; +	const u8 *data = _data; +	unsigned int i; + +	type = offset & B43_LCNTAB_TYPEMASK; +	offset &= ~B43_LCNTAB_TYPEMASK; +	B43_WARN_ON(offset > 0xFFFF); + +	b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, offset); + +	for (i = 0; i < nr_elements; i++) { +		switch (type) { +		case B43_LCNTAB_8BIT: +			value = *data; +			data++; +			B43_WARN_ON(value & ~0xFF); +			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); +			break; +		case B43_LCNTAB_16BIT: +			value = *((u16 *)data); +			data += 2; +			B43_WARN_ON(value & ~0xFFFF); +			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, value); +			break; +		case B43_LCNTAB_32BIT: +			value = *((u32 *)data); +			data += 4; +			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, +				      value >> 16); +			b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, +				      value & 0xFFFF); +			break; +		default: +			B43_WARN_ON(1); +		} +	} +} +  /**************************************************   * Tables ops.   **************************************************/ +#define lcntab_upload(dev, offset, data) do { \ +		b43_lcntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \ +	} while (0)  void b43_phy_lcn_tables_init(struct b43_wldev *dev)  { +	lcntab_upload(dev, B43_LCNTAB16(0x02, 0), b43_lcntab_0x02); +	lcntab_upload(dev, B43_LCNTAB16(0x01, 0), b43_lcntab_0x01); +	lcntab_upload(dev, B43_LCNTAB32(0x0b, 0), b43_lcntab_0x0b); +	lcntab_upload(dev, B43_LCNTAB32(0x0c, 0), b43_lcntab_0x0c); +	lcntab_upload(dev, B43_LCNTAB32(0x0d, 0), b43_lcntab_0x0d); +	lcntab_upload(dev, B43_LCNTAB16(0x0e, 0), b43_lcntab_0x0e); +	lcntab_upload(dev, B43_LCNTAB16(0x0f, 0), b43_lcntab_0x0f); +	lcntab_upload(dev, B43_LCNTAB16(0x10, 0), b43_lcntab_0x10); +	lcntab_upload(dev, B43_LCNTAB16(0x11, 0), b43_lcntab_0x11); +	lcntab_upload(dev, B43_LCNTAB32(0x12, 0), b43_lcntab_0x12); +	lcntab_upload(dev, B43_LCNTAB16(0x14, 0), b43_lcntab_0x14); +	lcntab_upload(dev, B43_LCNTAB16(0x17, 0), b43_lcntab_0x17); +	lcntab_upload(dev, B43_LCNTAB16(0x00, 0), b43_lcntab_0x00); +	lcntab_upload(dev, B43_LCNTAB32(0x18, 0), b43_lcntab_0x18);  } diff --git a/drivers/net/wireless/b43/tables_phy_lcn.h b/drivers/net/wireless/b43/tables_phy_lcn.h index 5e31b15b81e..b6471e89c36 100644 --- a/drivers/net/wireless/b43/tables_phy_lcn.h +++ b/drivers/net/wireless/b43/tables_phy_lcn.h @@ -1,6 +1,22 @@  #ifndef B43_TABLES_PHY_LCN_H_  #define B43_TABLES_PHY_LCN_H_ +/* The LCN-PHY tables. */ +#define B43_LCNTAB_TYPEMASK		0xF0000000 +#define B43_LCNTAB_8BIT			0x10000000 +#define B43_LCNTAB_16BIT		0x20000000 +#define B43_LCNTAB_32BIT		0x30000000 +#define B43_LCNTAB8(table, offset)	(((table) << 10) | (offset) | B43_LCNTAB_8BIT) +#define B43_LCNTAB16(table, offset)	(((table) << 10) | (offset) | B43_LCNTAB_16BIT) +#define B43_LCNTAB32(table, offset)	(((table) << 10) | (offset) | B43_LCNTAB_32BIT) + +u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset); +void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset, +			  unsigned int nr_elements, void *_data); +void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value); +void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset, +			   unsigned int nr_elements, const void *_data); +  void b43_phy_lcn_tables_init(struct b43_wldev *dev);  #endif /* B43_TABLES_PHY_LCN_H_ */ diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index b74f25ec1ab..b8de62c2247 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -337,12 +337,19 @@ int b43_generate_txhdr(struct b43_wldev *dev,  			memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);  		}  	} -	if (b43_is_old_txhdr_format(dev)) { -		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), +	switch (dev->fw.hdr_format) { +	case B43_FW_HDR_598: +		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),  				      plcp_fragment_len, rate); -	} else { -		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), +		break; +	case B43_FW_HDR_351: +		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp), +				      plcp_fragment_len, rate); +		break; +	case B43_FW_HDR_410: +		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),  				      plcp_fragment_len, rate); +		break;  	}  	b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),  			      plcp_fragment_len, rate_fb); @@ -415,10 +422,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,  	if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||  	    (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {  		unsigned int len; -		struct ieee80211_hdr *hdr; +		struct ieee80211_hdr *uninitialized_var(hdr);  		int rts_rate, rts_rate_fb;  		int rts_rate_ofdm, rts_rate_fb_ofdm; -		struct b43_plcp_hdr6 *plcp; +		struct b43_plcp_hdr6 *uninitialized_var(plcp);  		struct ieee80211_rate *rts_cts_rate;  		rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); @@ -429,14 +436,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,  		rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);  		if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { -			struct ieee80211_cts *cts; +			struct ieee80211_cts *uninitialized_var(cts); -			if (b43_is_old_txhdr_format(dev)) { +			switch (dev->fw.hdr_format) { +			case B43_FW_HDR_598:  				cts = (struct ieee80211_cts *) -					(txhdr->old_format.rts_frame); -			} else { +					(txhdr->format_598.rts_frame); +				break; +			case B43_FW_HDR_351:  				cts = (struct ieee80211_cts *) -					(txhdr->new_format.rts_frame); +					(txhdr->format_351.rts_frame); +				break; +			case B43_FW_HDR_410: +				cts = (struct ieee80211_cts *) +					(txhdr->format_410.rts_frame); +				break;  			}  			ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,  						fragment_data, fragment_len, @@ -444,14 +458,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,  			mac_ctl |= B43_TXH_MAC_SENDCTS;  			len = sizeof(struct ieee80211_cts);  		} else { -			struct ieee80211_rts *rts; +			struct ieee80211_rts *uninitialized_var(rts); -			if (b43_is_old_txhdr_format(dev)) { +			switch (dev->fw.hdr_format) { +			case B43_FW_HDR_598:  				rts = (struct ieee80211_rts *) -					(txhdr->old_format.rts_frame); -			} else { +					(txhdr->format_598.rts_frame); +				break; +			case B43_FW_HDR_351: +				rts = (struct ieee80211_rts *) +					(txhdr->format_351.rts_frame); +				break; +			case B43_FW_HDR_410:  				rts = (struct ieee80211_rts *) -					(txhdr->new_format.rts_frame); +					(txhdr->format_410.rts_frame); +				break;  			}  			ieee80211_rts_get(dev->wl->hw, info->control.vif,  					  fragment_data, fragment_len, @@ -462,22 +483,36 @@ int b43_generate_txhdr(struct b43_wldev *dev,  		len += FCS_LEN;  		/* Generate the PLCP headers for the RTS/CTS frame */ -		if (b43_is_old_txhdr_format(dev)) -			plcp = &txhdr->old_format.rts_plcp; -		else -			plcp = &txhdr->new_format.rts_plcp; +		switch (dev->fw.hdr_format) { +		case B43_FW_HDR_598: +			plcp = &txhdr->format_598.rts_plcp; +			break; +		case B43_FW_HDR_351: +			plcp = &txhdr->format_351.rts_plcp; +			break; +		case B43_FW_HDR_410: +			plcp = &txhdr->format_410.rts_plcp; +			break; +		}  		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,  				      len, rts_rate);  		plcp = &txhdr->rts_plcp_fb;  		b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,  				      len, rts_rate_fb); -		if (b43_is_old_txhdr_format(dev)) { +		switch (dev->fw.hdr_format) { +		case B43_FW_HDR_598:  			hdr = (struct ieee80211_hdr *) -				(&txhdr->old_format.rts_frame); -		} else { +				(&txhdr->format_598.rts_frame); +			break; +		case B43_FW_HDR_351: +			hdr = (struct ieee80211_hdr *) +				(&txhdr->format_351.rts_frame); +			break; +		case B43_FW_HDR_410:  			hdr = (struct ieee80211_hdr *) -				(&txhdr->new_format.rts_frame); +				(&txhdr->format_410.rts_frame); +			break;  		}  		txhdr->rts_dur_fb = hdr->duration_id; @@ -505,10 +540,17 @@ int b43_generate_txhdr(struct b43_wldev *dev,  	}  	/* Magic cookie */ -	if (b43_is_old_txhdr_format(dev)) -		txhdr->old_format.cookie = cpu_to_le16(cookie); -	else -		txhdr->new_format.cookie = cpu_to_le16(cookie); +	switch (dev->fw.hdr_format) { +	case B43_FW_HDR_598: +		txhdr->format_598.cookie = cpu_to_le16(cookie); +		break; +	case B43_FW_HDR_351: +		txhdr->format_351.cookie = cpu_to_le16(cookie); +		break; +	case B43_FW_HDR_410: +		txhdr->format_410.cookie = cpu_to_le16(cookie); +		break; +	}  	if (phy->type == B43_PHYTYPE_N) {  		txhdr->phy_ctl1 = @@ -611,8 +653,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)  	struct ieee80211_hdr *wlhdr;  	const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;  	__le16 fctl; -	u16 phystat0, phystat3, chanstat, mactime; -	u32 macstat; +	u16 phystat0, phystat3; +	u16 uninitialized_var(chanstat), uninitialized_var(mactime); +	u32 uninitialized_var(macstat);  	u16 chanid;  	u16 phytype;  	int padding; @@ -622,9 +665,19 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)  	/* Get metadata about the frame from the header. */  	phystat0 = le16_to_cpu(rxhdr->phy_status0);  	phystat3 = le16_to_cpu(rxhdr->phy_status3); -	macstat = le32_to_cpu(rxhdr->mac_status); -	mactime = le16_to_cpu(rxhdr->mac_time); -	chanstat = le16_to_cpu(rxhdr->channel); +	switch (dev->fw.hdr_format) { +	case B43_FW_HDR_598: +		macstat = le32_to_cpu(rxhdr->format_598.mac_status); +		mactime = le16_to_cpu(rxhdr->format_598.mac_time); +		chanstat = le16_to_cpu(rxhdr->format_598.channel); +		break; +	case B43_FW_HDR_410: +	case B43_FW_HDR_351: +		macstat = le32_to_cpu(rxhdr->format_351.mac_status); +		mactime = le16_to_cpu(rxhdr->format_351.mac_time); +		chanstat = le16_to_cpu(rxhdr->format_351.channel); +		break; +	}  	phytype = chanstat & B43_RX_CHAN_PHYTYPE;  	if (unlikely(macstat & B43_RX_MAC_FCSERR)) { @@ -744,6 +797,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)  		break;  	case B43_PHYTYPE_N:  	case B43_PHYTYPE_LP: +	case B43_PHYTYPE_HT:  		/* chanid is the SHM channel cookie. Which is the plain  		 * channel number in b43. */  		if (chanstat & B43_RX_CHAN_5GHZ) { diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 42debb5cd6f..f6e8bc436d5 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -46,7 +46,24 @@ struct b43_txhdr {  	__le32 timeout;			/* Timeout */  	union { -		/* The new r410 format. */ +		/* Tested with 598.314, 644.1001 and 666.2 */ +		struct { +			__le16 mimo_antenna;            /* MIMO antenna select */ +			__le16 preload_size;            /* Preload size */ +			PAD_BYTES(2); +			__le16 cookie;                  /* TX frame cookie */ +			__le16 tx_status;               /* TX status */ +			__le16 max_n_mpdus; +			__le16 max_a_bytes_mrt; +			__le16 max_a_bytes_fbr; +			__le16 min_m_bytes; +			struct b43_plcp_hdr6 rts_plcp;  /* RTS PLCP header */ +			__u8 rts_frame[16];             /* The RTS frame (if used) */ +			PAD_BYTES(2); +			struct b43_plcp_hdr6 plcp;      /* Main PLCP header */ +		} format_598 __packed; + +		/* Tested with 410.2160, 478.104 and 508.* */  		struct {  			__le16 mimo_antenna;		/* MIMO antenna select */  			__le16 preload_size;		/* Preload size */ @@ -57,9 +74,9 @@ struct b43_txhdr {  			__u8 rts_frame[16];		/* The RTS frame (if used) */  			PAD_BYTES(2);  			struct b43_plcp_hdr6 plcp;	/* Main PLCP header */ -		} new_format __packed; +		} format_410 __packed; -		/* The old r351 format. */ +		/* Tested with 351.126 */  		struct {  			PAD_BYTES(2);  			__le16 cookie;			/* TX frame cookie */ @@ -68,7 +85,7 @@ struct b43_txhdr {  			__u8 rts_frame[16];		/* The RTS frame (if used) */  			PAD_BYTES(2);  			struct b43_plcp_hdr6 plcp;	/* Main PLCP header */ -		} old_format __packed; +		} format_351 __packed;  	} __packed;  } __packed; @@ -166,19 +183,18 @@ struct b43_tx_legacy_rate_phy_ctl_entry {  #define  B43_TXH_PHY1_MODUL_QAM256	0x2000 /* QAM256 */ -/* r351 firmware compatibility stuff. */ -static inline -bool b43_is_old_txhdr_format(struct b43_wldev *dev) -{ -	return (dev->fw.rev <= 351); -} -  static inline  size_t b43_txhdr_size(struct b43_wldev *dev)  { -	if (b43_is_old_txhdr_format(dev)) +	switch (dev->fw.hdr_format) { +	case B43_FW_HDR_598: +		return 112 + sizeof(struct b43_plcp_hdr6); +	case B43_FW_HDR_410: +		return 104 + sizeof(struct b43_plcp_hdr6); +	case B43_FW_HDR_351:  		return 100 + sizeof(struct b43_plcp_hdr6); -	return 104 + sizeof(struct b43_plcp_hdr6); +	} +	return 0;  } @@ -234,9 +250,23 @@ struct b43_rxhdr_fw4 {  	} __packed;  	__le16 phy_status2;	/* PHY RX Status 2 */  	__le16 phy_status3;	/* PHY RX Status 3 */ -	__le32 mac_status;	/* MAC RX status */ -	__le16 mac_time; -	__le16 channel; +	union { +		/* Tested with 598.314, 644.1001 and 666.2 */ +		struct { +			__le16 phy_status4;	/* PHY RX Status 4 */ +			__le16 phy_status5;	/* PHY RX Status 5 */ +			__le32 mac_status;	/* MAC RX status */ +			__le16 mac_time; +			__le16 channel; +		} format_598 __packed; + +		/* Tested with 351.126, 410.2160, 478.104 and 508.* */ +		struct { +			__le32 mac_status;	/* MAC RX status */ +			__le16 mac_time; +			__le16 channel; +		} format_351 __packed; +	} __packed;  } __packed;  /* PHY RX Status 0 */ diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index ad4e743e476..12b51825158 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -22,10 +22,6 @@  #include "phy.h" -/* The unique identifier of the firmware that's officially supported by this - * driver version. */ -#define B43legacy_SUPPORTED_FIRMWARE_ID	"FW10" -  #define B43legacy_IRQWAIT_MAX_RETRIES	20  /* MMIO offsets */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index aae8dfcb852..468d1836548 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -60,7 +60,6 @@ MODULE_AUTHOR("Stefano Brivio");  MODULE_AUTHOR("Michael Buesch");  MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);  MODULE_FIRMWARE("b43legacy/ucode2.fw");  MODULE_FIRMWARE("b43legacy/ucode4.fw"); @@ -3947,8 +3946,7 @@ static void b43legacy_print_driverinfo(void)  	feat_dma = "D";  #endif  	printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " -	       "[ Features: %s%s%s%s, Firmware-ID: " -	       B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", +	       "[ Features: %s%s%s%s ]\n",  	       feat_pci, feat_leds, feat_pio, feat_dma);  } diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README index 1453eec82a9..91f2ca90c70 100644 --- a/drivers/net/wireless/libertas/README +++ b/drivers/net/wireless/libertas/README @@ -238,28 +238,3 @@ hostsleep  		echo "1" > hostsleep : enable host sleep.  		echo "0" > hostsleep : disable host sleep -======================== -IWCONFIG COMMANDS -======================== -power period - -	This command is used to configure the station in deep sleep mode / -	auto deep sleep mode. - -	The timer is implemented to monitor the activities (command, event, -	etc.). When an activity is detected station will exit from deep -	sleep mode automatically and restart the timer. At timer expiry -	(no activity for defined time period) the deep sleep mode is entered -	automatically. - -	Note: this command is for SDIO interface only. - -	Usage: -	To enable deep sleep mode do: -		iwconfig wlan0 power period 0 -	To enable auto deep sleep mode with idle time period 5 seconds do: -		iwconfig wlan0 power period 5 -	To disable deep sleep/auto deep sleep mode do: -		iwconfig wlan0 power period -1 - -============================================================================== diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 814838916b8..b9ff0dc53e8 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -190,8 +190,8 @@ static inline int lbs_iface_active(struct lbs_private *priv)  	int r;  	r = netif_running(priv->dev); -	if (priv->mesh_dev); -		r |= netif_running(priv->dev); +	if (priv->mesh_dev) +		r |= netif_running(priv->mesh_dev);  	return r;  } diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index b28241c6e73..37ca2f90ad6 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -1480,8 +1480,8 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv,  		return -ENOMEM;  	}  	beacon_ie = kzalloc(ie_len, GFP_KERNEL); -	if (!bss_desc) { -		dev_err(priv->adapter->dev, " failed to alloc bss_desc\n"); +	if (!beacon_ie) { +		dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");  		return -ENOMEM;  	}  	memcpy(beacon_ie, ie_buf, ie_len); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index da36dbf8d87..771280a47ea 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c @@ -4097,9 +4097,6 @@ static int mwl8k_set_key(struct ieee80211_hw *hw,  		if (rc)  			goto out; - -		mwl8k_vif->is_hw_crypto_enabled = false; -  	}  out:  	return rc; diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 54cc0bba66b..8b6f363b3f7 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -145,6 +145,7 @@ static int p54_fill_band_bitrates(struct ieee80211_hw *dev,  static int p54_generate_band(struct ieee80211_hw *dev,  			     struct p54_channel_list *list, +			     unsigned int *chan_num,  			     enum ieee80211_band band)  {  	struct p54_common *priv = dev->priv; @@ -190,7 +191,14 @@ static int p54_generate_band(struct ieee80211_hw *dev,  		tmp->channels[j].band = chan->band;  		tmp->channels[j].center_freq = chan->freq; +		priv->survey[*chan_num].channel = &tmp->channels[j]; +		priv->survey[*chan_num].filled = SURVEY_INFO_NOISE_DBM | +			SURVEY_INFO_CHANNEL_TIME | +			SURVEY_INFO_CHANNEL_TIME_BUSY | +			SURVEY_INFO_CHANNEL_TIME_TX; +		tmp->channels[j].hw_value = (*chan_num);  		j++; +		(*chan_num)++;  	}  	if (j == 0) { @@ -263,7 +271,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)  {  	struct p54_common *priv = dev->priv;  	struct p54_channel_list *list; -	unsigned int i, j, max_channel_num; +	unsigned int i, j, k, max_channel_num;  	int ret = 0;  	u16 freq; @@ -283,6 +291,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)  		ret = -ENOMEM;  		goto free;  	} +	priv->chan_num = max_channel_num; +	priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num, +			       GFP_KERNEL); +	if (!priv->survey) { +		ret = -ENOMEM; +		goto free; +	}  	list->max_entries = max_channel_num;  	list->channels = kzalloc(sizeof(struct p54_channel_entry) * @@ -321,8 +336,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)  	sort(list->channels, list->entries, sizeof(struct p54_channel_entry),  	     p54_compare_channels, NULL); +	k = 0;  	for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { -		if (p54_generate_band(dev, list, i) == 0) +		if (p54_generate_band(dev, list, &k, i) == 0)  			j++;  	}  	if (j == 0) { @@ -335,6 +351,10 @@ free:  		kfree(list->channels);  		kfree(list);  	} +	if (ret) { +		kfree(priv->survey); +		priv->survey = NULL; +	}  	return ret;  } @@ -853,10 +873,12 @@ err:  	kfree(priv->output_limit);  	kfree(priv->curve_data);  	kfree(priv->rssi_db); +	kfree(priv->survey);  	priv->iq_autocal = NULL;  	priv->output_limit = NULL;  	priv->curve_data = NULL;  	priv->rssi_db = NULL; +	priv->survey = NULL;  	wiphy_err(dev->wiphy, "eeprom parse failed!\n");  	return err; diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index b6a061cbbde..53a3408931b 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -385,6 +385,7 @@ int p54_setup_mac(struct p54_common *priv)  		setup->v2.osc_start_delay = cpu_to_le16(65535);  	}  	p54_tx(priv, skb); +	priv->phy_idle = mode == P54_FILTER_TYPE_HIBERNATE;  	return 0;  } @@ -626,6 +627,7 @@ int p54_set_ps(struct p54_common *priv)  	psm->exclude[0] = WLAN_EID_TIM;  	p54_tx(priv, skb); +	priv->phy_ps = mode != P54_PSM_CAM;  	return 0;  } diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index a5a6d9e647b..726a9343f51 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c @@ -204,13 +204,11 @@ static void p54_stop(struct ieee80211_hw *dev)  	struct p54_common *priv = dev->priv;  	int i; -	mutex_lock(&priv->conf_mutex);  	priv->mode = NL80211_IFTYPE_UNSPECIFIED;  	priv->softled_state = 0; -	p54_set_leds(priv); -  	cancel_delayed_work_sync(&priv->work); - +	mutex_lock(&priv->conf_mutex); +	p54_set_leds(priv);  	priv->stop(dev);  	skb_queue_purge(&priv->tx_pending);  	skb_queue_purge(&priv->tx_queue); @@ -278,6 +276,42 @@ static void p54_remove_interface(struct ieee80211_hw *dev,  	mutex_unlock(&priv->conf_mutex);  } +static int p54_wait_for_stats(struct ieee80211_hw *dev) +{ +	struct p54_common *priv = dev->priv; +	int ret; + +	priv->update_stats = true; +	ret = p54_fetch_statistics(priv); +	if (ret) +		return ret; + +	ret = wait_for_completion_interruptible_timeout(&priv->stat_comp, HZ); +	if (ret == 0) +		return -ETIMEDOUT; + +	return 0; +} + +static void p54_reset_stats(struct p54_common *priv) +{ +	struct ieee80211_channel *chan = priv->curchan; + +	if (chan) { +		struct survey_info *info = &priv->survey[chan->hw_value]; + +		/* only reset channel statistics, don't touch .filled, etc. */ +		info->channel_time = 0; +		info->channel_time_busy = 0; +		info->channel_time_tx = 0; +	} + +	priv->update_stats = true; +	priv->survey_raw.active = 0; +	priv->survey_raw.cca = 0; +	priv->survey_raw.tx = 0; +} +  static int p54_config(struct ieee80211_hw *dev, u32 changed)  {  	int ret = 0; @@ -288,19 +322,36 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)  	if (changed & IEEE80211_CONF_CHANGE_POWER)  		priv->output_power = conf->power_level << 2;  	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { +		struct ieee80211_channel *oldchan; +		WARN_ON(p54_wait_for_stats(dev)); +		oldchan = priv->curchan; +		priv->curchan = NULL;  		ret = p54_scan(priv, P54_SCAN_EXIT, 0); -		if (ret) +		if (ret) { +			priv->curchan = oldchan;  			goto out; +		} +		/* +		 * TODO: Use the LM_SCAN_TRAP to determine the current +		 * operating channel. +		 */ +		priv->curchan = priv->hw->conf.channel; +		p54_reset_stats(priv); +		WARN_ON(p54_fetch_statistics(priv));  	}  	if (changed & IEEE80211_CONF_CHANGE_PS) { +		WARN_ON(p54_wait_for_stats(dev));  		ret = p54_set_ps(priv);  		if (ret)  			goto out; +		WARN_ON(p54_wait_for_stats(dev));  	}  	if (changed & IEEE80211_CONF_CHANGE_IDLE) { +		WARN_ON(p54_wait_for_stats(dev));  		ret = p54_setup_mac(priv);  		if (ret)  			goto out; +		WARN_ON(p54_wait_for_stats(dev));  	}  out: @@ -384,7 +435,9 @@ static void p54_work(struct work_struct *work)  	 *      2. cancel stuck frames / reset the device if necessary.  	 */ -	p54_fetch_statistics(priv); +	mutex_lock(&priv->conf_mutex); +	WARN_ON_ONCE(p54_fetch_statistics(priv)); +	mutex_unlock(&priv->conf_mutex);  }  static int p54_get_stats(struct ieee80211_hw *dev, @@ -541,16 +594,47 @@ static int p54_get_survey(struct ieee80211_hw *dev, int idx,  				struct survey_info *survey)  {  	struct p54_common *priv = dev->priv; -	struct ieee80211_conf *conf = &dev->conf; +	struct ieee80211_channel *chan; +	int err, tries; +	bool in_use = false; -	if (idx != 0) +	if (idx >= priv->chan_num)  		return -ENOENT; -	survey->channel = conf->channel; -	survey->filled = SURVEY_INFO_NOISE_DBM; -	survey->noise = clamp_t(s8, priv->noise, -128, 127); +#define MAX_TRIES 1 +	for (tries = 0; tries < MAX_TRIES; tries++) { +		chan = priv->curchan; +		if (chan && chan->hw_value == idx) { +			mutex_lock(&priv->conf_mutex); +			err = p54_wait_for_stats(dev); +			mutex_unlock(&priv->conf_mutex); +			if (err) +				return err; -	return 0; +			in_use = true; +		} + +		memcpy(survey, &priv->survey[idx], sizeof(*survey)); + +		if (in_use) { +			/* test if the reported statistics are valid. */ +			if  (survey->channel_time != 0) { +				survey->filled |= SURVEY_INFO_IN_USE; +			} else { +				/* +				 * hw/fw has not accumulated enough sample sets. +				 * Wait for 100ms, this ought to be enough to +				 * to get at least one non-null set of channel +				 * usage statistics. +				 */ +				msleep(100); +				continue; +			} +		} +		return 0; +	} +	return -ETIMEDOUT; +#undef MAX_TRIES  }  static unsigned int p54_flush_count(struct p54_common *priv) @@ -686,11 +770,14 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)  	mutex_init(&priv->conf_mutex);  	mutex_init(&priv->eeprom_mutex); +	init_completion(&priv->stat_comp);  	init_completion(&priv->eeprom_comp);  	init_completion(&priv->beacon_comp);  	INIT_DELAYED_WORK(&priv->work, p54_work);  	memset(&priv->mc_maclist[0], ~0, ETH_ALEN); +	priv->curchan = NULL; +	p54_reset_stats(priv);  	return dev;  }  EXPORT_SYMBOL_GPL(p54_init_common); @@ -730,11 +817,13 @@ void p54_free_common(struct ieee80211_hw *dev)  	kfree(priv->curve_data);  	kfree(priv->rssi_db);  	kfree(priv->used_rxkeys); +	kfree(priv->survey);  	priv->iq_autocal = NULL;  	priv->output_limit = NULL;  	priv->curve_data = NULL;  	priv->rssi_db = NULL;  	priv->used_rxkeys = NULL; +	priv->survey = NULL;  	ieee80211_free_hw(dev);  }  EXPORT_SYMBOL_GPL(p54_free_common); diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index 799d05e1259..452fa3a64aa 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -199,6 +199,22 @@ struct p54_common {  	u8 tx_diversity_mask;  	unsigned int output_power;  	struct p54_rssi_db_entry *cur_rssi; +	struct ieee80211_channel *curchan; +	struct survey_info *survey; +	unsigned int chan_num; +	struct completion stat_comp; +	bool update_stats; +	struct { +		unsigned int timestamp; +		unsigned int cached_cca; +		unsigned int cached_tx; +		unsigned int cached_rssi; +		u64 active; +		u64 cca; +		u64 tx; +		u64 rssi; +	} survey_raw; +  	int noise;  	/* calibration, output power limit and rssi<->dBm conversation data */  	struct pda_iq_autocal_entry *iq_autocal; @@ -220,6 +236,8 @@ struct p54_common {  	u32 basic_rate_mask;  	u16 aid;  	u8 coverage_class; +	bool phy_idle; +	bool phy_ps;  	bool powersave_override;  	__le32 beacon_req_id;  	struct completion beacon_comp; diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 042842e704d..44a3bd4b0f4 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c @@ -507,6 +507,8 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)  	struct p54_hdr *hdr = (struct p54_hdr *) skb->data;  	struct p54_statistics *stats = (struct p54_statistics *) hdr->data;  	struct sk_buff *tmp; +	struct ieee80211_channel *chan; +	unsigned int i, rssi, tx, cca, dtime, dtotal, dcca, dtx, drssi, unit;  	u32 tsf32;  	if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) @@ -523,8 +525,72 @@ static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb)  	priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise)); +	/* +	 * STSW450X LMAC API page 26 - 3.8 Statistics +	 * "The exact measurement period can be derived from the +	 * timestamp member". +	 */ +	dtime = tsf32 - priv->survey_raw.timestamp; + +	/* +	 * STSW450X LMAC API page 26 - 3.8.1 Noise histogram +	 * The LMAC samples RSSI, CCA and transmit state at regular +	 * periods (typically 8 times per 1k [as in 1024] usec). +	 */ +	cca = le32_to_cpu(stats->sample_cca); +	tx = le32_to_cpu(stats->sample_tx); +	rssi = 0; +	for (i = 0; i < ARRAY_SIZE(stats->sample_noise); i++) +		rssi += le32_to_cpu(stats->sample_noise[i]); + +	dcca = cca - priv->survey_raw.cached_cca; +	drssi = rssi - priv->survey_raw.cached_rssi; +	dtx = tx - priv->survey_raw.cached_tx; +	dtotal = dcca + drssi + dtx; + +	/* +	 * update statistics when more than a second is over since the +	 * last call, or when a update is badly needed. +	 */ +	if (dtotal && (priv->update_stats || dtime >= USEC_PER_SEC) && +	    dtime >= dtotal) { +		priv->survey_raw.timestamp = tsf32; +		priv->update_stats = false; +		unit = dtime / dtotal; + +		if (dcca) { +			priv->survey_raw.cca += dcca * unit; +			priv->survey_raw.cached_cca = cca; +		} +		if (dtx) { +			priv->survey_raw.tx += dtx * unit; +			priv->survey_raw.cached_tx = tx; +		} +		if (drssi) { +			priv->survey_raw.rssi += drssi * unit; +			priv->survey_raw.cached_rssi = rssi; +		} + +		/* 1024 usec / 8 times = 128 usec / time */ +		if (!(priv->phy_ps || priv->phy_idle)) +			priv->survey_raw.active += dtotal * unit; +		else +			priv->survey_raw.active += (dcca + dtx) * unit; +	} + +	chan = priv->curchan; +	if (chan) { +		struct survey_info *survey = &priv->survey[chan->hw_value]; +		survey->noise = clamp_t(s8, priv->noise, -128, 127); +		survey->channel_time = priv->survey_raw.active / 1024; +		survey->channel_time_tx = priv->survey_raw.tx / 1024; +		survey->channel_time_busy = priv->survey_raw.cca / 1024 + +			survey->channel_time_tx; +	} +  	tmp = p54_find_and_unlink_skb(priv, hdr->req_id);  	dev_kfree_skb_any(tmp); +	complete(&priv->stat_comp);  }  static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 0b598db38da..098fc557a88 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -664,6 +664,167 @@ static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw)  	return hw_rate;  } +/* mac80211's rate_idx is like this: + * + * 2.4G band:rx_status->band == IEEE80211_BAND_2GHZ + * + * B/G rate: + * (rx_status->flag & RX_FLAG_HT) = 0, + * DESC92_RATE1M-->DESC92_RATE54M ==> idx is 0-->11, + * + * N rate: + * (rx_status->flag & RX_FLAG_HT) = 1, + * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15 + * + * 5G band:rx_status->band == IEEE80211_BAND_5GHZ + * A rate: + * (rx_status->flag & RX_FLAG_HT) = 0, + * DESC92_RATE6M-->DESC92_RATE54M ==> idx is 0-->7, + * + * N rate: + * (rx_status->flag & RX_FLAG_HT) = 1, + * DESC92_RATEMCS0-->DESC92_RATEMCS15 ==> idx is 0-->15 + */ +int rtlwifi_rate_mapping(struct ieee80211_hw *hw, +			 bool isht, u8 desc_rate, bool first_ampdu) +{ +	int rate_idx; + +	if (false == isht) { +		if (IEEE80211_BAND_2GHZ == hw->conf.channel->band) { +			switch (desc_rate) { +			case DESC92_RATE1M: +				rate_idx = 0; +				break; +			case DESC92_RATE2M: +				rate_idx = 1; +				break; +			case DESC92_RATE5_5M: +				rate_idx = 2; +				break; +			case DESC92_RATE11M: +				rate_idx = 3; +				break; +			case DESC92_RATE6M: +				rate_idx = 4; +				break; +			case DESC92_RATE9M: +				rate_idx = 5; +				break; +			case DESC92_RATE12M: +				rate_idx = 6; +				break; +			case DESC92_RATE18M: +				rate_idx = 7; +				break; +			case DESC92_RATE24M: +				rate_idx = 8; +				break; +			case DESC92_RATE36M: +				rate_idx = 9; +				break; +			case DESC92_RATE48M: +				rate_idx = 10; +				break; +			case DESC92_RATE54M: +				rate_idx = 11; +				break; +			default: +				rate_idx = 0; +				break; +			} +		} else { +			switch (desc_rate) { +			case DESC92_RATE6M: +				rate_idx = 0; +				break; +			case DESC92_RATE9M: +				rate_idx = 1; +				break; +			case DESC92_RATE12M: +				rate_idx = 2; +				break; +			case DESC92_RATE18M: +				rate_idx = 3; +				break; +			case DESC92_RATE24M: +				rate_idx = 4; +				break; +			case DESC92_RATE36M: +				rate_idx = 5; +				break; +			case DESC92_RATE48M: +				rate_idx = 6; +				break; +			case DESC92_RATE54M: +				rate_idx = 7; +				break; +			default: +				rate_idx = 0; +				break; +			} +		} + +	} else { + +		switch (desc_rate) { +		case DESC92_RATEMCS0: +			rate_idx = 0; +			break; +		case DESC92_RATEMCS1: +			rate_idx = 1; +			break; +		case DESC92_RATEMCS2: +			rate_idx = 2; +			break; +		case DESC92_RATEMCS3: +			rate_idx = 3; +			break; +		case DESC92_RATEMCS4: +			rate_idx = 4; +			break; +		case DESC92_RATEMCS5: +			rate_idx = 5; +			break; +		case DESC92_RATEMCS6: +			rate_idx = 6; +			break; +		case DESC92_RATEMCS7: +			rate_idx = 7; +			break; +		case DESC92_RATEMCS8: +			rate_idx = 8; +			break; +		case DESC92_RATEMCS9: +			rate_idx = 9; +			break; +		case DESC92_RATEMCS10: +			rate_idx = 10; +			break; +		case DESC92_RATEMCS11: +			rate_idx = 11; +			break; +		case DESC92_RATEMCS12: +			rate_idx = 12; +			break; +		case DESC92_RATEMCS13: +			rate_idx = 13; +			break; +		case DESC92_RATEMCS14: +			rate_idx = 14; +			break; +		case DESC92_RATEMCS15: +			rate_idx = 15; +			break; +		default: +			rate_idx = 0; +			break; +		} +	} +	return rate_idx; +} +EXPORT_SYMBOL(rtlwifi_rate_mapping); +  void rtl_get_tcb_desc(struct ieee80211_hw *hw,  		      struct ieee80211_tx_info *info,  		      struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/rtlwifi/base.h b/drivers/net/wireless/rtlwifi/base.h index a91f3eee59c..4ae905983d0 100644 --- a/drivers/net/wireless/rtlwifi/base.h +++ b/drivers/net/wireless/rtlwifi/base.h @@ -140,4 +140,6 @@ u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);  void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);  u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid);  extern struct attribute_group rtl_attribute_group; +int rtlwifi_rate_mapping(struct ieee80211_hw *hw, +			 bool isht, u8 desc_rate, bool first_ampdu);  #endif diff --git a/drivers/net/wireless/rtlwifi/debug.c b/drivers/net/wireless/rtlwifi/debug.c index 5fa73852cb6..b2f897acb23 100644 --- a/drivers/net/wireless/rtlwifi/debug.c +++ b/drivers/net/wireless/rtlwifi/debug.c @@ -28,12 +28,16 @@  #include "wifi.h" +static unsigned int debug = DBG_EMERG; +module_param(debug, uint, 0); +MODULE_PARM_DESC(debug, "Set global debug level for rtlwifi (0,2-5)"); +  void rtl_dbgp_flag_init(struct ieee80211_hw *hw)  {  	struct rtl_priv *rtlpriv = rtl_priv(hw);  	u8 i; -	rtlpriv->dbg.global_debuglevel = DBG_EMERG; +	rtlpriv->dbg.global_debuglevel = debug;  	rtlpriv->dbg.global_debugcomponents =  	    COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND | diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 35ff7df41a1..11f43196e61 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -220,41 +220,6 @@ enum rtl_desc_qsel {  	QSLT_CMD = 0x13,  }; -enum rtl_desc92c_rate { -	DESC92C_RATE1M = 0x00, -	DESC92C_RATE2M = 0x01, -	DESC92C_RATE5_5M = 0x02, -	DESC92C_RATE11M = 0x03, - -	DESC92C_RATE6M = 0x04, -	DESC92C_RATE9M = 0x05, -	DESC92C_RATE12M = 0x06, -	DESC92C_RATE18M = 0x07, -	DESC92C_RATE24M = 0x08, -	DESC92C_RATE36M = 0x09, -	DESC92C_RATE48M = 0x0a, -	DESC92C_RATE54M = 0x0b, - -	DESC92C_RATEMCS0 = 0x0c, -	DESC92C_RATEMCS1 = 0x0d, -	DESC92C_RATEMCS2 = 0x0e, -	DESC92C_RATEMCS3 = 0x0f, -	DESC92C_RATEMCS4 = 0x10, -	DESC92C_RATEMCS5 = 0x11, -	DESC92C_RATEMCS6 = 0x12, -	DESC92C_RATEMCS7 = 0x13, -	DESC92C_RATEMCS8 = 0x14, -	DESC92C_RATEMCS9 = 0x15, -	DESC92C_RATEMCS10 = 0x16, -	DESC92C_RATEMCS11 = 0x17, -	DESC92C_RATEMCS12 = 0x18, -	DESC92C_RATEMCS13 = 0x19, -	DESC92C_RATEMCS14 = 0x1a, -	DESC92C_RATEMCS15 = 0x1b, -	DESC92C_RATEMCS15_SG = 0x1c, -	DESC92C_RATEMCS32 = 0x20, -}; -  struct phy_sts_cck_8192s_t {  	u8 adc_pwdb_X[4];  	u8 sq_rpt; @@ -267,108 +232,4 @@ struct h2c_cmd_8192c {  	u8 *p_cmdbuffer;  }; -/* NOTE: reference to rtl8192c_rates struct */ -static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT, -				       u8 desc_rate, bool first_ampdu) -{ -	struct rtl_priv *rtlpriv = rtl_priv(hw); -	int rate_idx = 0; - -	if (first_ampdu) { -		if (false == isHT) { -			switch (desc_rate) { -			case DESC92C_RATE1M: -				rate_idx = 0; -				break; -			case DESC92C_RATE2M: -				rate_idx = 1; -				break; -			case DESC92C_RATE5_5M: -				rate_idx = 2; -				break; -			case DESC92C_RATE11M: -				rate_idx = 3; -				break; -			case DESC92C_RATE6M: -				rate_idx = 4; -				break; -			case DESC92C_RATE9M: -				rate_idx = 5; -				break; -			case DESC92C_RATE12M: -				rate_idx = 6; -				break; -			case DESC92C_RATE18M: -				rate_idx = 7; -				break; -			case DESC92C_RATE24M: -				rate_idx = 8; -				break; -			case DESC92C_RATE36M: -				rate_idx = 9; -				break; -			case DESC92C_RATE48M: -				rate_idx = 10; -				break; -			case DESC92C_RATE54M: -				rate_idx = 11; -				break; -			default: -				RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, -					 ("Rate %d is not support, set to " -					"1M rate.\n", desc_rate)); -				rate_idx = 0; -				break; -			} -		} else { -			rate_idx = 11; -		} -		return rate_idx; -	} -	switch (desc_rate) { -	case DESC92C_RATE1M: -		rate_idx = 0; -		break; -	case DESC92C_RATE2M: -		rate_idx = 1; -		break; -	case DESC92C_RATE5_5M: -		rate_idx = 2; -		break; -	case DESC92C_RATE11M: -		rate_idx = 3; -		break; -	case DESC92C_RATE6M: -		rate_idx = 4; -		break; -	case DESC92C_RATE9M: -		rate_idx = 5; -		break; -	case DESC92C_RATE12M: -		rate_idx = 6; -		break; -	case DESC92C_RATE18M: -		rate_idx = 7; -		break; -	case DESC92C_RATE24M: -		rate_idx = 8; -		break; -	case DESC92C_RATE36M: -		rate_idx = 9; -		break; -	case DESC92C_RATE48M: -		rate_idx = 10; -		break; -	case DESC92C_RATE54M: -		rate_idx = 11; -		break; -	/* TODO: How to mapping MCS rate? */ -	/*  NOTE: referenc to __ieee80211_rx */ -	default: -		rate_idx = 11; -		break; -	} -	return rate_idx; -} -  #endif diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 373dc78af1d..4c34c4c1ae5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -318,21 +318,21 @@ static struct rtl_hal_cfg rtl92ce_hal_cfg = {  	.maps[RTL_IMR_ROK] = IMR_ROK,  	.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), -	.maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, -	.maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, -	.maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, -	.maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, -	.maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, -	.maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, -	.maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, -	.maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, -	.maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, -	.maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, -	.maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, -	.maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, +	.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, +	.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, +	.maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, +	.maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, +	.maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, +	.maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, +	.maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, +	.maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, +	.maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, +	.maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, +	.maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, +	.maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, -	.maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, -	.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +	.maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, +	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,  };  DEFINE_PCI_DEVICE_TABLE(rtl92ce_pci_ids) = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 230bbe900d8..4fb5ae24dee 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -48,104 +48,6 @@ static u8 _rtl92ce_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)  	return skb->priority;  } -static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -{ -	int rate_idx; - -	if (first_ampdu) { -		if (false == isht) { -			switch (desc_rate) { -			case DESC92C_RATE1M: -				rate_idx = 0; -				break; -			case DESC92C_RATE2M: -				rate_idx = 1; -				break; -			case DESC92C_RATE5_5M: -				rate_idx = 2; -				break; -			case DESC92C_RATE11M: -				rate_idx = 3; -				break; -			case DESC92C_RATE6M: -				rate_idx = 4; -				break; -			case DESC92C_RATE9M: -				rate_idx = 5; -				break; -			case DESC92C_RATE12M: -				rate_idx = 6; -				break; -			case DESC92C_RATE18M: -				rate_idx = 7; -				break; -			case DESC92C_RATE24M: -				rate_idx = 8; -				break; -			case DESC92C_RATE36M: -				rate_idx = 9; -				break; -			case DESC92C_RATE48M: -				rate_idx = 10; -				break; -			case DESC92C_RATE54M: -				rate_idx = 11; -				break; -			default: -				rate_idx = 0; -				break; -			} -		} else { -			rate_idx = 11; -		} - -		return rate_idx; -	} - -	switch (desc_rate) { -	case DESC92C_RATE1M: -		rate_idx = 0; -		break; -	case DESC92C_RATE2M: -		rate_idx = 1; -		break; -	case DESC92C_RATE5_5M: -		rate_idx = 2; -		break; -	case DESC92C_RATE11M: -		rate_idx = 3; -		break; -	case DESC92C_RATE6M: -		rate_idx = 4; -		break; -	case DESC92C_RATE9M: -		rate_idx = 5; -		break; -	case DESC92C_RATE12M: -		rate_idx = 6; -		break; -	case DESC92C_RATE18M: -		rate_idx = 7; -		break; -	case DESC92C_RATE24M: -		rate_idx = 8; -		break; -	case DESC92C_RATE36M: -		rate_idx = 9; -		break; -	case DESC92C_RATE48M: -		rate_idx = 10; -		break; -	case DESC92C_RATE54M: -		rate_idx = 11; -		break; -	default: -		rate_idx = 11; -		break; -	} -	return rate_idx; -} -  static u8 _rtl92c_query_rxpwrpercentage(char antpower)  {  	if ((antpower <= -100) || (antpower >= 20)) @@ -336,8 +238,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,  		pstats->rxpower = rx_pwr_all;  		pstats->recvsignalpower = rx_pwr_all; -		if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 && -		    pdesc->rxmcs <= DESC92C_RATEMCS15) +		if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && +		    pdesc->rxmcs <= DESC92_RATEMCS15)  			max_spatial_stream = 2;  		else  			max_spatial_stream = 1; @@ -670,12 +572,10 @@ bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,  	if (stats->decrypted)  		rx_status->flag |= RX_FLAG_DECRYPTED; -	rx_status->rate_idx = _rtl92ce_rate_mapping((bool) -						    GET_RX_DESC_RXHT(pdesc), -						    (u8) -						    GET_RX_DESC_RXMCS(pdesc), -						    (bool) -						    GET_RX_DESC_PAGGR(pdesc)); +	rx_status->rate_idx = rtlwifi_rate_mapping(hw, +				(bool)GET_RX_DESC_RXHT(pdesc), +				(u8)GET_RX_DESC_RXMCS(pdesc), +				(bool)GET_RX_DESC_PAGGR(pdesc));  	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);  	if (phystatus) { @@ -768,7 +668,7 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,  		SET_TX_DESC_RTS_BW(pdesc, 0);  		SET_TX_DESC_RTS_SC(pdesc, tcb_desc->rts_sc);  		SET_TX_DESC_RTS_SHORT(pdesc, -				      ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? +				      ((tcb_desc->rts_rate <= DESC92_RATE54M) ?  				       (tcb_desc->rts_use_shortpreamble ? 1 : 0)  				       : (tcb_desc->rts_use_shortgi ? 1 : 0))); @@ -886,7 +786,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,  	if (firstseg)  		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); -	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); +	SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);  	SET_TX_DESC_SEQ(pdesc, 0); diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h index 0f117713750..81ae64234f8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h @@ -538,10 +538,10 @@ do {							\  } while (0);  #define RX_HAL_IS_CCK_RATE(_pdesc)\ -	(_pdesc->rxmcs == DESC92C_RATE1M ||		\ -	 _pdesc->rxmcs == DESC92C_RATE2M ||		\ -	 _pdesc->rxmcs == DESC92C_RATE5_5M ||		\ -	 _pdesc->rxmcs == DESC92C_RATE11M) +	(_pdesc->rxmcs == DESC92_RATE1M ||		\ +	 _pdesc->rxmcs == DESC92_RATE2M ||		\ +	 _pdesc->rxmcs == DESC92_RATE5_5M ||		\ +	 _pdesc->rxmcs == DESC92_RATE11M)  struct rx_fwinfo_92c {  	u8 gain_trsw[4]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index 194fc693c1f..060a06f4a88 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -892,8 +892,8 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,  		pstats->rxpower = rx_pwr_all;  		pstats->recvsignalpower = rx_pwr_all;  		if (GET_RX_DESC_RX_MCS(pdesc) && -		    GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 && -		    GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15) +		    GET_RX_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 && +		    GET_RX_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)  			max_spatial_stream = 2;  		else  			max_spatial_stream = 1; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h index 298fdb724aa..35529f701fc 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h @@ -88,10 +88,10 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);  u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);  #define RX_HAL_IS_CCK_RATE(_pdesc)\ -	(GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\ -	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\ -	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\ -	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M) +	(GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||\ +	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||\ +	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ +	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)  struct rx_fwinfo_92c {  	u8 gain_trsw[4]; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 17a8e962851..1e851aae58d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,  			tx_agc[RF90_PATH_A] = 0x10101010;  			tx_agc[RF90_PATH_B] = 0x10101010;  		} else if (rtlpriv->dm.dynamic_txhighpower_lvl == -			   TXHIGHPWRLEVEL_LEVEL2) { +			   TXHIGHPWRLEVEL_LEVEL1) {  			tx_agc[RF90_PATH_A] = 0x00000000;  			tx_agc[RF90_PATH_B] = 0x00000000;  		} else{ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index ef63c0df006..424b8a0323e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -241,20 +241,20 @@ static struct rtl_hal_cfg rtl92cu_hal_cfg = {  	.maps[RTL_IMR_ROK] = IMR_ROK,  	.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), -	.maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M, -	.maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M, -	.maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M, -	.maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M, -	.maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M, -	.maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M, -	.maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M, -	.maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M, -	.maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M, -	.maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M, -	.maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M, -	.maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M, -	.maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7, -	.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15, +	.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, +	.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, +	.maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, +	.maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, +	.maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, +	.maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, +	.maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, +	.maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, +	.maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, +	.maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, +	.maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, +	.maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, +	.maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, +	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,  };  #define USB_VENDER_ID_REALTEK		0x0bda diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 906e7aa55bc..c4161148e0d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -337,10 +337,10 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,  	rx_status->flag |= RX_FLAG_MACTIME_MPDU;  	if (stats->decrypted)  		rx_status->flag |= RX_FLAG_DECRYPTED; -	rx_status->rate_idx = _rtl92c_rate_mapping(hw, -						(bool)GET_RX_DESC_RX_HT(pdesc), -						(u8)GET_RX_DESC_RX_MCS(pdesc), -						(bool)GET_RX_DESC_PAGGR(pdesc)); +	rx_status->rate_idx = rtlwifi_rate_mapping(hw, +					(bool)GET_RX_DESC_RX_HT(pdesc), +					(u8)GET_RX_DESC_RX_MCS(pdesc), +					(bool)GET_RX_DESC_PAGGR(pdesc));  	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);  	if (phystatus) {  		p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); @@ -406,11 +406,10 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)  	if (GET_RX_DESC_RX_HT(rxdesc))  		rx_status->flag |= RX_FLAG_HT;  	/* Data rate */ -	rx_status->rate_idx = _rtl92c_rate_mapping(hw, -						(bool)GET_RX_DESC_RX_HT(rxdesc), -						(u8)GET_RX_DESC_RX_MCS(rxdesc), -						(bool)GET_RX_DESC_PAGGR(rxdesc) -						); +	rx_status->rate_idx = rtlwifi_rate_mapping(hw, +					(bool)GET_RX_DESC_RX_HT(rxdesc), +					(u8)GET_RX_DESC_RX_MCS(rxdesc), +					(bool)GET_RX_DESC_PAGGR(rxdesc));  	/*  There is a phy status after this rx descriptor. */  	if (GET_RX_DESC_PHY_STATUS(rxdesc)) {  		p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE); @@ -545,7 +544,7 @@ void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,  	SET_TX_DESC_RTS_BW(txdesc, 0);  	SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc);  	SET_TX_DESC_RTS_SHORT(txdesc, -			      ((tcb_desc->rts_rate <= DESC92C_RATE54M) ? +			      ((tcb_desc->rts_rate <= DESC92_RATE54M) ?  			       (tcb_desc->rts_use_shortpreamble ? 1 : 0)  			       : (tcb_desc->rts_use_shortgi ? 1 : 0)));  	if (mac->bw_40) { @@ -643,7 +642,7 @@ void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,  	}  	SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */  	SET_TX_DESC_OWN(pDesc, 1); -	SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M); +	SET_TX_DESC_TX_RATE(pDesc, DESC92_RATE1M);  	_rtl_tx_desc_checksum(pDesc);  } @@ -659,7 +658,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,  	memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);  	if (firstseg)  		SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); -	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M); +	SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);  	SET_TX_DESC_SEQ(pdesc, 0);  	SET_TX_DESC_LINIP(pdesc, 0);  	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/def.h b/drivers/net/wireless/rtlwifi/rtl8192de/def.h index f0f5f9bfbb7..aff7e19714f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/def.h @@ -193,41 +193,6 @@ enum rtl_desc_qsel {  	QSLT_CMD = 0x13,  }; -enum rtl_desc92d_rate { -	DESC92D_RATE1M = 0x00, -	DESC92D_RATE2M = 0x01, -	DESC92D_RATE5_5M = 0x02, -	DESC92D_RATE11M = 0x03, - -	DESC92D_RATE6M = 0x04, -	DESC92D_RATE9M = 0x05, -	DESC92D_RATE12M = 0x06, -	DESC92D_RATE18M = 0x07, -	DESC92D_RATE24M = 0x08, -	DESC92D_RATE36M = 0x09, -	DESC92D_RATE48M = 0x0a, -	DESC92D_RATE54M = 0x0b, - -	DESC92D_RATEMCS0 = 0x0c, -	DESC92D_RATEMCS1 = 0x0d, -	DESC92D_RATEMCS2 = 0x0e, -	DESC92D_RATEMCS3 = 0x0f, -	DESC92D_RATEMCS4 = 0x10, -	DESC92D_RATEMCS5 = 0x11, -	DESC92D_RATEMCS6 = 0x12, -	DESC92D_RATEMCS7 = 0x13, -	DESC92D_RATEMCS8 = 0x14, -	DESC92D_RATEMCS9 = 0x15, -	DESC92D_RATEMCS10 = 0x16, -	DESC92D_RATEMCS11 = 0x17, -	DESC92D_RATEMCS12 = 0x18, -	DESC92D_RATEMCS13 = 0x19, -	DESC92D_RATEMCS14 = 0x1a, -	DESC92D_RATEMCS15 = 0x1b, -	DESC92D_RATEMCS15_SG = 0x1c, -	DESC92D_RATEMCS32 = 0x20, -}; -  enum channel_plan {  	CHPL_FCC	= 0,  	CHPL_IC		= 1, diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index 351765df517..f6419b7ed2f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c @@ -340,21 +340,21 @@ static struct rtl_hal_cfg rtl92de_hal_cfg = {  	.maps[RTL_IMR_ROK] = IMR_ROK,  	.maps[RTL_IBSS_INT_MASKS] = (IMR_BcnInt | IMR_TBDOK | IMR_TBDER), -	.maps[RTL_RC_CCK_RATE1M] = DESC92D_RATE1M, -	.maps[RTL_RC_CCK_RATE2M] = DESC92D_RATE2M, -	.maps[RTL_RC_CCK_RATE5_5M] = DESC92D_RATE5_5M, -	.maps[RTL_RC_CCK_RATE11M] = DESC92D_RATE11M, -	.maps[RTL_RC_OFDM_RATE6M] = DESC92D_RATE6M, -	.maps[RTL_RC_OFDM_RATE9M] = DESC92D_RATE9M, -	.maps[RTL_RC_OFDM_RATE12M] = DESC92D_RATE12M, -	.maps[RTL_RC_OFDM_RATE18M] = DESC92D_RATE18M, -	.maps[RTL_RC_OFDM_RATE24M] = DESC92D_RATE24M, -	.maps[RTL_RC_OFDM_RATE36M] = DESC92D_RATE36M, -	.maps[RTL_RC_OFDM_RATE48M] = DESC92D_RATE48M, -	.maps[RTL_RC_OFDM_RATE54M] = DESC92D_RATE54M, +	.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, +	.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, +	.maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, +	.maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, +	.maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, +	.maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, +	.maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, +	.maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, +	.maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, +	.maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, +	.maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, +	.maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, -	.maps[RTL_RC_HT_RATEMCS7] = DESC92D_RATEMCS7, -	.maps[RTL_RC_HT_RATEMCS15] = DESC92D_RATEMCS15, +	.maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, +	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,  };  static struct pci_device_id rtl92de_pci_ids[] __devinitdata = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index dc86fcb0b3a..3637c0c3352 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -48,99 +48,6 @@ static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)  	return skb->priority;  } -static int _rtl92de_rate_mapping(bool isht, u8 desc_rate) -{ -	int rate_idx; - -	if (false == isht) { -		switch (desc_rate) { -		case DESC92D_RATE1M: -			rate_idx = 0; -			break; -		case DESC92D_RATE2M: -			rate_idx = 1; -			break; -		case DESC92D_RATE5_5M: -			rate_idx = 2; -			break; -		case DESC92D_RATE11M: -			rate_idx = 3; -			break; -		case DESC92D_RATE6M: -			rate_idx = 4; -			break; -		case DESC92D_RATE9M: -			rate_idx = 5; -			break; -		case DESC92D_RATE12M: -			rate_idx = 6; -			break; -		case DESC92D_RATE18M: -			rate_idx = 7; -			break; -		case DESC92D_RATE24M: -			rate_idx = 8; -			break; -		case DESC92D_RATE36M: -			rate_idx = 9; -			break; -		case DESC92D_RATE48M: -			rate_idx = 10; -			break; -		case DESC92D_RATE54M: -			rate_idx = 11; -			break; -		default: -			rate_idx = 0; -			break; -		} -		return rate_idx; -	} else { -		switch (desc_rate) { -		case DESC92D_RATE1M: -			rate_idx = 0; -			break; -		case DESC92D_RATE2M: -			rate_idx = 1; -			break; -		case DESC92D_RATE5_5M: -			rate_idx = 2; -			break; -		case DESC92D_RATE11M: -			rate_idx = 3; -			break; -		case DESC92D_RATE6M: -			rate_idx = 4; -			break; -		case DESC92D_RATE9M: -			rate_idx = 5; -			break; -		case DESC92D_RATE12M: -			rate_idx = 6; -			break; -		case DESC92D_RATE18M: -			rate_idx = 7; -			break; -		case DESC92D_RATE24M: -			rate_idx = 8; -			break; -		case DESC92D_RATE36M: -			rate_idx = 9; -			break; -		case DESC92D_RATE48M: -			rate_idx = 10; -			break; -		case DESC92D_RATE54M: -			rate_idx = 11; -			break; -		default: -			rate_idx = 11; -			break; -		} -		return rate_idx; -	} -} -  static u8 _rtl92d_query_rxpwrpercentage(char antpower)  {  	if ((antpower <= -100) || (antpower >= 20)) @@ -328,8 +235,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,  		pstats->rx_pwdb_all = pwdb_all;  		pstats->rxpower = rx_pwr_all;  		pstats->recvsignalpower = rx_pwr_all; -		if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 && -		    pdesc->rxmcs <= DESC92D_RATEMCS15) +		if (pdesc->rxht && pdesc->rxmcs >= DESC92_RATEMCS8 && +		    pdesc->rxmcs <= DESC92_RATEMCS15)  			max_spatial_stream = 2;  		else  			max_spatial_stream = 1; @@ -609,10 +516,10 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,	struct rtl_stats *stats,  	rx_status->flag |= RX_FLAG_MACTIME_MPDU;  	if (stats->decrypted)  		rx_status->flag |= RX_FLAG_DECRYPTED; -	rx_status->rate_idx = _rtl92de_rate_mapping((bool) -						    GET_RX_DESC_RXHT(pdesc), -						    (u8) -						    GET_RX_DESC_RXMCS(pdesc)); +	rx_status->rate_idx = rtlwifi_rate_mapping(hw, +					(bool)GET_RX_DESC_RXHT(pdesc), +					(u8)GET_RX_DESC_RXMCS(pdesc), +					(bool)GET_RX_DESC_PAGGR(pdesc));  	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);  	if (phystatus) {  		p_drvinfo = (struct rx_fwinfo_92d *)(skb->data + @@ -705,14 +612,14 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,  		}  		/* 5G have no CCK rate */  		if (rtlhal->current_bandtype == BAND_ON_5G) -			if (ptcb_desc->hw_rate < DESC92D_RATE6M) -				ptcb_desc->hw_rate = DESC92D_RATE6M; +			if (ptcb_desc->hw_rate < DESC92_RATE6M) +				ptcb_desc->hw_rate = DESC92_RATE6M;  		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);  		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)  			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);  		if (rtlhal->macphymode == DUALMAC_DUALPHY && -			ptcb_desc->hw_rate == DESC92D_RATEMCS7) +			ptcb_desc->hw_rate == DESC92_RATEMCS7)  			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);  		if (info->flags & IEEE80211_TX_CTL_AMPDU) { @@ -728,13 +635,13 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,  		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));  		/* 5G have no CCK rate */  		if (rtlhal->current_bandtype == BAND_ON_5G) -			if (ptcb_desc->rts_rate < DESC92D_RATE6M) -				ptcb_desc->rts_rate = DESC92D_RATE6M; +			if (ptcb_desc->rts_rate < DESC92_RATE6M) +				ptcb_desc->rts_rate = DESC92_RATE6M;  		SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);  		SET_TX_DESC_RTS_BW(pdesc, 0);  		SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);  		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= -			DESC92D_RATE54M) ? +			DESC92_RATE54M) ?  			(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :  			(ptcb_desc->rts_use_shortgi ? 1 : 0)));  		if (bw_40) { @@ -844,9 +751,9 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,  	 * The braces are needed no matter what checkpatch says  	 */  	if (rtlhal->current_bandtype == BAND_ON_5G) { -		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M); +		SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE6M);  	} else { -		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M); +		SET_TX_DESC_TX_RATE(pdesc, DESC92_RATE1M);  	}  	SET_TX_DESC_SEQ(pdesc, 0);  	SET_TX_DESC_LINIP(pdesc, 0); diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h index 992d6766e66..6c2236868c9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.h @@ -538,10 +538,10 @@ do {							\  } while (0);  #define RX_HAL_IS_CCK_RATE(_pdesc)\ -	(_pdesc->rxmcs == DESC92D_RATE1M ||		\ -	 _pdesc->rxmcs == DESC92D_RATE2M ||		\ -	 _pdesc->rxmcs == DESC92D_RATE5_5M ||		\ -	 _pdesc->rxmcs == DESC92D_RATE11M) +	(_pdesc->rxmcs == DESC92_RATE1M ||		\ +	 _pdesc->rxmcs == DESC92_RATE2M ||		\ +	 _pdesc->rxmcs == DESC92_RATE5_5M ||		\ +	 _pdesc->rxmcs == DESC92_RATE11M)  /* For 92D early mode */  #define SET_EARLYMODE_PKTNUM(__paddr, __value)		\ diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 69828f2b3fa..68204ea175d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h @@ -33,37 +33,6 @@  #define RX_CMD_QUEUE				1  #define RX_MAX_QUEUE				2 -#define DESC92S_RATE1M				0x00 -#define DESC92S_RATE2M				0x01 -#define DESC92S_RATE5_5M			0x02 -#define DESC92S_RATE11M				0x03 -#define DESC92S_RATE6M				0x04 -#define DESC92S_RATE9M				0x05 -#define DESC92S_RATE12M				0x06 -#define DESC92S_RATE18M				0x07 -#define DESC92S_RATE24M				0x08 -#define DESC92S_RATE36M				0x09 -#define DESC92S_RATE48M				0x0a -#define DESC92S_RATE54M				0x0b -#define DESC92S_RATEMCS0			0x0c -#define DESC92S_RATEMCS1			0x0d -#define DESC92S_RATEMCS2			0x0e -#define DESC92S_RATEMCS3			0x0f -#define DESC92S_RATEMCS4			0x10 -#define DESC92S_RATEMCS5			0x11 -#define DESC92S_RATEMCS6			0x12 -#define DESC92S_RATEMCS7			0x13 -#define DESC92S_RATEMCS8			0x14 -#define DESC92S_RATEMCS9			0x15 -#define DESC92S_RATEMCS10			0x16 -#define DESC92S_RATEMCS11			0x17 -#define DESC92S_RATEMCS12			0x18 -#define DESC92S_RATEMCS13			0x19 -#define DESC92S_RATEMCS14			0x1a -#define DESC92S_RATEMCS15			0x1b -#define DESC92S_RATEMCS15_SG			0x1c -#define DESC92S_RATEMCS32			0x20 -  #define SHORT_SLOT_TIME				9  #define NON_SHORT_SLOT_TIME			20 @@ -491,10 +460,10 @@ do {								\  	SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)  #define RX_HAL_IS_CCK_RATE(_pdesc)\ -	(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M ||	\ -	 GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M ||	\ -	 GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\ -	 GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M) +	(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||	\ +	 GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||	\ +	 GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\ +	 GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)  enum rf_optype {  	RF_OP_BY_SW_3WIRE = 0, diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 3876078a63d..0055a1c845a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -348,21 +348,21 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = {  	.maps[RTL_IMR_ROK] = IMR_ROK,  	.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), -	.maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M, -	.maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M, -	.maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M, -	.maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M, -	.maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M, -	.maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M, -	.maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M, -	.maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M, -	.maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M, -	.maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M, -	.maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M, -	.maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M, +	.maps[RTL_RC_CCK_RATE1M] = DESC92_RATE1M, +	.maps[RTL_RC_CCK_RATE2M] = DESC92_RATE2M, +	.maps[RTL_RC_CCK_RATE5_5M] = DESC92_RATE5_5M, +	.maps[RTL_RC_CCK_RATE11M] = DESC92_RATE11M, +	.maps[RTL_RC_OFDM_RATE6M] = DESC92_RATE6M, +	.maps[RTL_RC_OFDM_RATE9M] = DESC92_RATE9M, +	.maps[RTL_RC_OFDM_RATE12M] = DESC92_RATE12M, +	.maps[RTL_RC_OFDM_RATE18M] = DESC92_RATE18M, +	.maps[RTL_RC_OFDM_RATE24M] = DESC92_RATE24M, +	.maps[RTL_RC_OFDM_RATE36M] = DESC92_RATE36M, +	.maps[RTL_RC_OFDM_RATE48M] = DESC92_RATE48M, +	.maps[RTL_RC_OFDM_RATE54M] = DESC92_RATE54M, -	.maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7, -	.maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15, +	.maps[RTL_RC_HT_RATEMCS7] = DESC92_RATEMCS7, +	.maps[RTL_RC_HT_RATEMCS15] = DESC92_RATEMCS15,  };  static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index cffe30851f7..d9aeae7f8bd 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -51,104 +51,6 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)  	return skb->priority;  } -static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) -{ -	int rate_idx = 0; - -	if (first_ampdu) { -		if (false == isht) { -			switch (desc_rate) { -			case DESC92S_RATE1M: -				rate_idx = 0; -				break; -			case DESC92S_RATE2M: -				rate_idx = 1; -				break; -			case DESC92S_RATE5_5M: -				rate_idx = 2; -				break; -			case DESC92S_RATE11M: -				rate_idx = 3; -				break; -			case DESC92S_RATE6M: -				rate_idx = 4; -				break; -			case DESC92S_RATE9M: -				rate_idx = 5; -				break; -			case DESC92S_RATE12M: -				rate_idx = 6; -				break; -			case DESC92S_RATE18M: -				rate_idx = 7; -				break; -			case DESC92S_RATE24M: -				rate_idx = 8; -				break; -			case DESC92S_RATE36M: -				rate_idx = 9; -				break; -			case DESC92S_RATE48M: -				rate_idx = 10; -				break; -			case DESC92S_RATE54M: -				rate_idx = 11; -				break; -			default: -				rate_idx = 0; -				break; -			} -		} else { -			rate_idx = 11; -		} - -		return rate_idx; -	} - -	switch (desc_rate) { -	case DESC92S_RATE1M: -		rate_idx = 0; -		break; -	case DESC92S_RATE2M: -		rate_idx = 1; -		break; -	case DESC92S_RATE5_5M: -		rate_idx = 2; -		break; -	case DESC92S_RATE11M: -		rate_idx = 3; -		break; -	case DESC92S_RATE6M: -		rate_idx = 4; -		break; -	case DESC92S_RATE9M: -		rate_idx = 5; -		break; -	case DESC92S_RATE12M: -		rate_idx = 6; -		break; -	case DESC92S_RATE18M: -		rate_idx = 7; -		break; -	case DESC92S_RATE24M: -		rate_idx = 8; -		break; -	case DESC92S_RATE36M: -		rate_idx = 9; -		break; -	case DESC92S_RATE48M: -		rate_idx = 10; -		break; -	case DESC92S_RATE54M: -		rate_idx = 11; -		break; -	default: -		rate_idx = 11; -		break; -	} -	return rate_idx; -} -  static u8 _rtl92s_query_rxpwrpercentage(char antpower)  {  	if ((antpower <= -100) || (antpower >= 20)) @@ -345,8 +247,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,  		pstats->recvsignalpower = rx_pwr_all;  		if (GET_RX_STATUS_DESC_RX_HT(pdesc) && -			GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 && -		    GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15) +			GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92_RATEMCS8 && +		    GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92_RATEMCS15)  			max_spatial_stream = 2;  		else  			max_spatial_stream = 1; @@ -654,10 +556,10 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,  	if (stats->decrypted)  		rx_status->flag |= RX_FLAG_DECRYPTED; -	rx_status->rate_idx = _rtl92se_rate_mapping((bool) -			GET_RX_STATUS_DESC_RX_HT(pdesc), -			(u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), -			(bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); +	rx_status->rate_idx = rtlwifi_rate_mapping(hw, +				(bool)GET_RX_STATUS_DESC_RX_HT(pdesc), +				(u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), +				(bool)GET_RX_STATUS_DESC_PAGGR(pdesc));  	rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); @@ -723,14 +625,14 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,  		SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid);  		SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= -				 DESC92S_RATEMCS0) ? 1 : 0)); +				 DESC92_RATEMCS0) ? 1 : 0));  		if (rtlhal->version == VERSION_8192S_ACUT) { -			if (ptcb_desc->hw_rate == DESC92S_RATE1M || -				ptcb_desc->hw_rate  == DESC92S_RATE2M || -				ptcb_desc->hw_rate == DESC92S_RATE5_5M || -				ptcb_desc->hw_rate == DESC92S_RATE11M) { -				ptcb_desc->hw_rate = DESC92S_RATE12M; +			if (ptcb_desc->hw_rate == DESC92_RATE1M || +				ptcb_desc->hw_rate  == DESC92_RATE2M || +				ptcb_desc->hw_rate == DESC92_RATE5_5M || +				ptcb_desc->hw_rate == DESC92_RATE11M) { +				ptcb_desc->hw_rate = DESC92_RATE12M;  			}  		} @@ -759,7 +661,7 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,  		SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0);  		SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc);  		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= -		       DESC92S_RATE54M) ? +		       DESC92_RATE54M) ?  		       (ptcb_desc->rts_use_shortpreamble ? 1 : 0)  		       : (ptcb_desc->rts_use_shortgi ? 1 : 0))); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index d3c3ffd3898..8a9091968f3 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -386,6 +386,41 @@ enum rtl_hal_state {  	_HAL_STATE_START = 1,  }; +enum rtl_desc92_rate { +	DESC92_RATE1M = 0x00, +	DESC92_RATE2M = 0x01, +	DESC92_RATE5_5M = 0x02, +	DESC92_RATE11M = 0x03, + +	DESC92_RATE6M = 0x04, +	DESC92_RATE9M = 0x05, +	DESC92_RATE12M = 0x06, +	DESC92_RATE18M = 0x07, +	DESC92_RATE24M = 0x08, +	DESC92_RATE36M = 0x09, +	DESC92_RATE48M = 0x0a, +	DESC92_RATE54M = 0x0b, + +	DESC92_RATEMCS0 = 0x0c, +	DESC92_RATEMCS1 = 0x0d, +	DESC92_RATEMCS2 = 0x0e, +	DESC92_RATEMCS3 = 0x0f, +	DESC92_RATEMCS4 = 0x10, +	DESC92_RATEMCS5 = 0x11, +	DESC92_RATEMCS6 = 0x12, +	DESC92_RATEMCS7 = 0x13, +	DESC92_RATEMCS8 = 0x14, +	DESC92_RATEMCS9 = 0x15, +	DESC92_RATEMCS10 = 0x16, +	DESC92_RATEMCS11 = 0x17, +	DESC92_RATEMCS12 = 0x18, +	DESC92_RATEMCS13 = 0x19, +	DESC92_RATEMCS14 = 0x1a, +	DESC92_RATEMCS15 = 0x1b, +	DESC92_RATEMCS15_SG = 0x1c, +	DESC92_RATEMCS32 = 0x20, +}; +  enum rtl_var_map {  	/*reg map */  	SYS_ISO_CTRL = 0, diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index c77e0543e50..f81a93e5b59 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1246,7 +1246,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)  {  	int payload_len = skb->len;  	struct pn533_frame *out_frame; -	struct sk_buff *discarded;  	u8 tg;  	nfc_dev_dbg(&dev->interface->dev, "%s - Sending %d bytes", __func__, @@ -1260,18 +1259,6 @@ static int pn533_data_exchange_tx_frame(struct pn533 *dev, struct sk_buff *skb)  		return -ENOSYS;  	} -	/* Reserving header space */ -	if (skb_cow_head(skb, PN533_CMD_DATAEXCH_HEAD_LEN)) { -		nfc_dev_err(&dev->interface->dev, "Error to add header data"); -		return -ENOMEM; -	} - -	/* Reserving tail space, see pn533_tx_frame_finish */ -	if (skb_cow_data(skb, PN533_FRAME_TAIL_SIZE, &discarded) < 0) { -		nfc_dev_err(&dev->interface->dev, "Error to add tail data"); -		return -ENOMEM; -	} -  	skb_push(skb, PN533_CMD_DATAEXCH_HEAD_LEN);  	out_frame = (struct pn533_frame *) skb->data; @@ -1536,7 +1523,9 @@ static int pn533_probe(struct usb_interface *interface,  			| NFC_PROTO_ISO14443_MASK  			| NFC_PROTO_NFC_DEP_MASK; -	dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols); +	dev->nfc_dev = nfc_allocate_device(&pn533_nfc_ops, protocols, +					   PN533_CMD_DATAEXCH_HEAD_LEN, +					   PN533_FRAME_TAIL_SIZE);  	if (!dev->nfc_dev)  		goto kill_tasklet; diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 29c7d4f9d1a..d0cbdb0cf9d 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1260,16 +1260,34 @@ void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)  }  EXPORT_SYMBOL(ssb_device_disable); +/* Some chipsets need routing known for PCIe and 64-bit DMA */ +static bool ssb_dma_translation_special_bit(struct ssb_device *dev) +{ +	u16 chip_id = dev->bus->chip_id; + +	if (dev->id.coreid == SSB_DEV_80211) { +		return (chip_id == 0x4322 || chip_id == 43221 || +			chip_id == 43231 || chip_id == 43222); +	} + +	return 0; +} +  u32 ssb_dma_translation(struct ssb_device *dev)  {  	switch (dev->bus->bustype) {  	case SSB_BUSTYPE_SSB:  		return 0;  	case SSB_BUSTYPE_PCI: -		if (ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) +		if (pci_is_pcie(dev->bus->host_pci) && +		    ssb_read32(dev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64) {  			return SSB_PCIE_DMA_H32; -		else -			return SSB_PCI_DMA; +		} else { +			if (ssb_dma_translation_special_bit(dev)) +				return SSB_PCIE_DMA_H32; +			else +				return SSB_PCI_DMA; +		}  	default:  		__ssb_dma_not_implemented(dev);  	} diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 6083725dd22..a7ae33d06f2 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h @@ -283,6 +283,22 @@  #define BCMA_CC_PPL_PCHI_OFF		5  #define BCMA_CC_PPL_PCHI_MASK		0x0000003f +/* BCM4331 ChipControl numbers. */ +#define BCMA_CHIPCTL_4331_BT_COEXIST		BIT(0)	/* 0 disable */ +#define BCMA_CHIPCTL_4331_SECI			BIT(1)	/* 0 SECI is disabled (JATG functional) */ +#define BCMA_CHIPCTL_4331_EXT_LNA		BIT(2)	/* 0 disable */ +#define BCMA_CHIPCTL_4331_SPROM_GPIO13_15	BIT(3)	/* sprom/gpio13-15 mux */ +#define BCMA_CHIPCTL_4331_EXTPA_EN		BIT(4)	/* 0 ext pa disable, 1 ext pa enabled */ +#define BCMA_CHIPCTL_4331_GPIOCLK_ON_SPROMCS	BIT(5)	/* set drive out GPIO_CLK on sprom_cs pin */ +#define BCMA_CHIPCTL_4331_PCIE_MDIO_ON_SPROMCS	BIT(6)	/* use sprom_cs pin as PCIE mdio interface */ +#define BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5	BIT(7)	/* aband extpa will be at gpio2/5 and sprom_dout */ +#define BCMA_CHIPCTL_4331_OVR_PIPEAUXCLKEN	BIT(8)	/* override core control on pipe_AuxClkEnable */ +#define BCMA_CHIPCTL_4331_OVR_PIPEAUXPWRDOWN	BIT(9)	/* override core control on pipe_AuxPowerDown */ +#define BCMA_CHIPCTL_4331_PCIE_AUXCLKEN		BIT(10)	/* pcie_auxclkenable */ +#define BCMA_CHIPCTL_4331_PCIE_PIPE_PLLDOWN	BIT(11)	/* pcie_pipe_pllpowerdown */ +#define BCMA_CHIPCTL_4331_BT_SHD0_ON_GPIO4	BIT(16)	/* enable bt_shd0 at gpio4 */ +#define BCMA_CHIPCTL_4331_BT_SHD1_ON_GPIO5	BIT(17)	/* enable bt_shd1 at gpio5 */ +  /* Data for the PMU, if available.   * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU)   */ @@ -342,6 +358,8 @@ extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);  extern void bcma_chipco_suspend(struct bcma_drv_cc *cc);  extern void bcma_chipco_resume(struct bcma_drv_cc *cc); +void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable); +  extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc,  					  u32 ticks); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 54c87896087..37f95f2e10f 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -629,9 +629,14 @@ struct ieee80211_rann_ie {  	u8 rann_ttl;  	u8 rann_addr[6];  	u32 rann_seq; +	u32 rann_interval;  	u32 rann_metric;  } __attribute__ ((packed)); +enum ieee80211_rann_flags { +	RANN_FLAG_IS_GATE = 1 << 0, +}; +  #define WLAN_SA_QUERY_TR_ID_LEN 2  struct ieee80211_mgmt { @@ -736,19 +741,10 @@ struct ieee80211_mgmt {  					__le16 params;  					__le16 reason_code;  				} __attribute__((packed)) delba; -				struct{ +				struct {  					u8 action_code; -					/* capab_info for open and confirm, -					 * reason for close -					 */ -					__le16 aux; -					/* Followed in plink_confirm by status -					 * code, AID and supported rates, -					 * and directly by supported rates in -					 * plink_open and plink_close -					 */  					u8 variable[0]; -				} __attribute__((packed)) plink_action; +				} __attribute__((packed)) self_prot;  				struct{  					u8 action_code;  					u8 variable[0]; @@ -816,9 +812,11 @@ struct ieee80211_bar {  } __attribute__((packed));  /* 802.11 BAR control masks */ -#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL     0x0000 -#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA  0x0004 - +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL	0x0000 +#define IEEE80211_BAR_CTRL_MULTI_TID		0x0002 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA	0x0004 +#define IEEE80211_BAR_CTRL_TID_INFO_MASK	0xf000 +#define IEEE80211_BAR_CTRL_TID_INFO_SHIFT	12  #define IEEE80211_HT_MCS_MASK_LEN		10 @@ -1194,11 +1192,6 @@ enum ieee80211_eid {  	WLAN_EID_MESH_ID = 114,  	WLAN_EID_LINK_METRIC_REPORT = 115,  	WLAN_EID_CONGESTION_NOTIFICATION = 116, -	/* Note that the Peer Link IE has been replaced with the similar -	 * Peer Management IE.  We will keep the former definition until mesh -	 * code is changed to comply with latest 802.11s drafts. -	 */ -	WLAN_EID_PEER_LINK = 55,  /* no longer in 802.11s drafts */  	WLAN_EID_PEER_MGMT = 117,  	WLAN_EID_CHAN_SWITCH_PARAM = 118,  	WLAN_EID_MESH_AWAKE_WINDOW = 119, @@ -1281,9 +1274,6 @@ enum ieee80211_category {  	WLAN_CATEGORY_MULTIHOP_ACTION = 14,  	WLAN_CATEGORY_SELF_PROTECTED = 15,  	WLAN_CATEGORY_WMM = 17, -	/* TODO: remove MESH_PATH_SEL after mesh is updated -	 * to current 802.11s draft  */ -	WLAN_CATEGORY_MESH_PATH_SEL = 32,  	WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,  	WLAN_CATEGORY_VENDOR_SPECIFIC = 127,  }; @@ -1309,6 +1299,31 @@ enum ieee80211_ht_actioncode {  	WLAN_HT_ACTION_ASEL_IDX_FEEDBACK = 7,  }; +/* Self Protected Action codes */ +enum ieee80211_self_protected_actioncode { +	WLAN_SP_RESERVED = 0, +	WLAN_SP_MESH_PEERING_OPEN = 1, +	WLAN_SP_MESH_PEERING_CONFIRM = 2, +	WLAN_SP_MESH_PEERING_CLOSE = 3, +	WLAN_SP_MGK_INFORM = 4, +	WLAN_SP_MGK_ACK = 5, +}; + +/* Mesh action codes */ +enum ieee80211_mesh_actioncode { +	WLAN_MESH_ACTION_LINK_METRIC_REPORT, +	WLAN_MESH_ACTION_HWMP_PATH_SELECTION, +	WLAN_MESH_ACTION_GATE_ANNOUNCEMENT, +	WLAN_MESH_ACTION_CONGESTION_CONTROL_NOTIFICATION, +	WLAN_MESH_ACTION_MCCA_SETUP_REQUEST, +	WLAN_MESH_ACTION_MCCA_SETUP_REPLY, +	WLAN_MESH_ACTION_MCCA_ADVERTISEMENT_REQUEST, +	WLAN_MESH_ACTION_MCCA_ADVERTISEMENT, +	WLAN_MESH_ACTION_MCCA_TEARDOWN, +	WLAN_MESH_ACTION_TBTT_ADJUSTMENT_REQUEST, +	WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE, +}; +  /* Security key length */  enum ieee80211_key_len {  	WLAN_KEY_LEN_WEP40 = 5, diff --git a/include/linux/nfc.h b/include/linux/nfc.h index 330a4c5db58..c525e0b5876 100644 --- a/include/linux/nfc.h +++ b/include/linux/nfc.h @@ -123,4 +123,6 @@ struct sockaddr_nfc {  #define NFC_SOCKPROTO_RAW	0  #define NFC_SOCKPROTO_MAX	1 +#define NFC_HEADER_SIZE 1 +  #endif /*__LINUX_NFC_H */ diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 89dec16b469..0343504082a 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1042,6 +1042,9 @@ enum nl80211_commands {   *	(Re)Association Response frames when the driver (or firmware) replies to   *	(Re)Association Request frames.   * + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + *	of the station, see &enum nl80211_sta_wme_attr. + *   * @NL80211_ATTR_MAX: highest attribute number currently defined   * @__NL80211_ATTR_AFTER_LAST: internal use   */ @@ -1252,6 +1255,8 @@ enum nl80211_attrs {  	NL80211_ATTR_IE_PROBE_RESP,  	NL80211_ATTR_IE_ASSOC_RESP, +	NL80211_ATTR_STA_WME, +  	/* add attributes here, update the policy in nl80211.c */  	__NL80211_ATTR_AFTER_LAST, @@ -1861,6 +1866,13 @@ enum nl80211_mntr_flags {   * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a   * source mesh point for path selection elements.   * + * @NL80211_MESHCONF_HWMP_RANN_INTERVAL:  The interval of time (in TUs) between + * root announcements are transmitted. + * + * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has + * access to a broader network beyond the MBSS.  This is done via Root + * Announcement frames. + *   * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute   *   * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -1882,6 +1894,8 @@ enum nl80211_meshconf_params {  	NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,  	NL80211_MESHCONF_HWMP_ROOTMODE,  	NL80211_MESHCONF_ELEMENT_TTL, +	NL80211_MESHCONF_HWMP_RANN_INTERVAL, +	NL80211_MESHCONF_GATE_ANNOUNCEMENTS,  	/* keep last */  	__NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -2473,4 +2487,22 @@ enum nl80211_hidden_ssid {  	NL80211_HIDDEN_SSID_ZERO_CONTENTS  }; +/** + * enum nl80211_sta_wme_attr - station WME attributes + * @__NL80211_STA_WME_INVALID: invalid number for nested attribute + * @NL80211_STA_WME_QUEUES: bitmap of uapsd queues. + * @NL80211_STA_WME_MAX_SP: max service period. + * @__NL80211_STA_WME_AFTER_LAST: internal + * @NL80211_STA_WME_MAX: highest station WME attribute + */ +enum nl80211_sta_wme_attr { +	__NL80211_STA_WME_INVALID, +	NL80211_STA_WME_UAPSD_QUEUES, +	NL80211_STA_WME_MAX_SP, + +	/* keep last */ +	__NL80211_STA_WME_AFTER_LAST, +	NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 +}; +  #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d86a15d87e5..88112ca59c8 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -452,6 +452,8 @@ struct station_parameters {  	u8 plink_action;  	u8 plink_state;  	struct ieee80211_ht_cap *ht_capa; +	u8 uapsd_queues; +	u8 max_sp;  };  /** @@ -755,6 +757,12 @@ struct mesh_config {  	u16 dot11MeshHWMPpreqMinInterval;  	u16 dot11MeshHWMPnetDiameterTraversalTime;  	u8  dot11MeshHWMPRootMode; +	u16 dot11MeshHWMPRannInterval; +	/* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol +	 * set to true only means that the station will announce others it's a +	 * mesh gate, but not necessarily using the gate announcement protocol. +	 * Still keeping the same nomenclature to be in sync with the spec. */ +	bool  dot11MeshGateAnnouncementProtocol;  };  /** @@ -2291,7 +2299,7 @@ struct ieee802_11_elems {  	struct ieee80211_ht_info *ht_info_elem;  	struct ieee80211_meshconf_ie *mesh_config;  	u8 *mesh_id; -	u8 *peer_link; +	u8 *peering;  	u8 *preq;  	u8 *prep;  	u8 *perr; @@ -2318,7 +2326,7 @@ struct ieee802_11_elems {  	u8 wmm_info_len;  	u8 wmm_param_len;  	u8 mesh_id_len; -	u8 peer_link_len; +	u8 peering_len;  	u8 preq_len;  	u8 prep_len;  	u8 perr_len; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2f01d84ca52..2e752df5751 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -954,6 +954,8 @@ struct ieee80211_sta {  	u16 aid;  	struct ieee80211_sta_ht_cap ht_cap;  	bool wme; +	u8 uapsd_queues; +	u8 max_sp;  	/* must be last */  	u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); diff --git a/include/net/nfc.h b/include/net/nfc.h index cc0130312f7..87b51fe15b7 100644 --- a/include/net/nfc.h +++ b/include/net/nfc.h @@ -82,6 +82,9 @@ struct nfc_dev {  	struct nfc_genl_data genl_data;  	u32 supported_protocols; +	int tx_headroom; +	int tx_tailroom; +  	struct nfc_ops *ops;  };  #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) @@ -89,7 +92,9 @@ struct nfc_dev {  extern struct class nfc_class;  struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, -					u32 supported_protocols); +					u32 supported_protocols, +					int tx_headroom, +					int tx_tailroom);  /**   * nfc_free_device - free nfc device diff --git a/include/net/regulatory.h b/include/net/regulatory.h index 356d6e3dc20..eb7d3c2d427 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -3,11 +3,19 @@  /*   * regulatory support structures   * - * Copyright 2008-2009	Luis R. Rodriguez <lrodriguez@atheros.com> + * Copyright 2008-2009	Luis R. Rodriguez <mcgrof@qca.qualcomm.com>   * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.   */ diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index f5fdfcbf552..d1886b59bec 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -199,6 +199,19 @@ config MAC80211_VERBOSE_MPL_DEBUG  	  Do not select this option. +config MAC80211_VERBOSE_MPATH_DEBUG +	bool "Verbose mesh path debugging" +	depends on MAC80211_DEBUG_MENU +	depends on MAC80211_MESH +	---help--- +	  Selecting this option causes mac80211 to print out very +	  verbose mesh path selection debugging messages (when mac80211 +	  is taking part in a mesh network). +	  It should not be selected on production systems as those +	  messages are remotely triggerable. + +	  Do not select this option. +  config MAC80211_VERBOSE_MHWMP_DEBUG  	bool "Verbose mesh HWMP routing debugging"  	depends on MAC80211_DEBUG_MENU diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index b7075f33dc0..018108d1a2f 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -128,7 +128,7 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1  	memcpy(bar->ta, sdata->vif.addr, ETH_ALEN);  	bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;  	bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; -	bar_control |= (u16)(tid << 12); +	bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT);  	bar->control = cpu_to_le16(bar_control);  	bar->start_seq_num = cpu_to_le16(ssn); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index a589addf6ce..4baa03b1c25 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -697,6 +697,9 @@ static void sta_apply_parameters(struct ieee80211_local *local,  	}  	spin_unlock_irqrestore(&sta->flaglock, flags); +	sta->sta.uapsd_queues = params->uapsd_queues; +	sta->sta.max_sp = params->max_sp; +  	/*  	 * cfg80211 validates this (1-2007) and allows setting the AID  	 * only when creating a new station entry @@ -1137,6 +1140,22 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,  		conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;  		ieee80211_mesh_root_setup(ifmsh);  	} +	if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) { +		/* our current gate announcement implementation rides on root +		 * announcements, so require this ifmsh to also be a root node +		 * */ +		if (nconf->dot11MeshGateAnnouncementProtocol && +		    !conf->dot11MeshHWMPRootMode) { +			conf->dot11MeshHWMPRootMode = 1; +			ieee80211_mesh_root_setup(ifmsh); +		} +		conf->dot11MeshGateAnnouncementProtocol = +			nconf->dot11MeshGateAnnouncementProtocol; +	} +	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask)) { +		conf->dot11MeshHWMPRannInterval = +			nconf->dot11MeshHWMPRannInterval; +	}  	return 0;  } diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 9ea7c0d0103..6e8eab7919e 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c @@ -372,6 +372,10 @@ IEEE80211_IF_FILE(min_discovery_timeout,  		u.mesh.mshcfg.min_discovery_timeout, DEC);  IEEE80211_IF_FILE(dot11MeshHWMPRootMode,  		u.mesh.mshcfg.dot11MeshHWMPRootMode, DEC); +IEEE80211_IF_FILE(dot11MeshGateAnnouncementProtocol, +		u.mesh.mshcfg.dot11MeshGateAnnouncementProtocol, DEC); +IEEE80211_IF_FILE(dot11MeshHWMPRannInterval, +		u.mesh.mshcfg.dot11MeshHWMPRannInterval, DEC);  #endif @@ -485,7 +489,9 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)  	MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);  	MESHPARAMS_ADD(path_refresh_time);  	MESHPARAMS_ADD(min_discovery_timeout); - +	MESHPARAMS_ADD(dot11MeshHWMPRootMode); +	MESHPARAMS_ADD(dot11MeshHWMPRannInterval); +	MESHPARAMS_ADD(dot11MeshGateAnnouncementProtocol);  #undef MESHPARAMS_ADD  }  #endif diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ea741905084..c204cee1189 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -514,6 +514,7 @@ struct ieee80211_if_mesh {  	struct mesh_config mshcfg;  	u32 mesh_seqnum;  	bool accepting_plinks; +	int num_gates;  	const u8 *ie;  	u8 ie_len;  	enum { diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 29e9980c8e6..28ab510e621 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -13,10 +13,6 @@  #include "ieee80211_i.h"  #include "mesh.h" -#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) -#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) -#define IEEE80211_MESH_RANN_INTERVAL	     (1 * HZ) -  #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01  #define MESHCONF_CAPAB_FORWARDING    0x08 @@ -27,6 +23,17 @@  int mesh_allocated;  static struct kmem_cache *rm_cache; +#ifdef CONFIG_MAC80211_MESH +bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) +{ +	return (mgmt->u.action.u.mesh_action.action_code == +			WLAN_MESH_ACTION_HWMP_PATH_SELECTION); +} +#else +bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt) +{ return false; } +#endif +  void ieee80211s_init(void)  {  	mesh_pathtbl_init(); @@ -204,36 +211,185 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,  	return 0;  } -void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +int +mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ +	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +	u8 *pos, neighbors; +	u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie); + +	if (skb_tailroom(skb) < 2 + meshconf_len) +		return -ENOMEM; + +	pos = skb_put(skb, 2 + meshconf_len); +	*pos++ = WLAN_EID_MESH_CONFIG; +	*pos++ = meshconf_len; + +	/* Active path selection protocol ID */ +	*pos++ = ifmsh->mesh_pp_id; +	/* Active path selection metric ID   */ +	*pos++ = ifmsh->mesh_pm_id; +	/* Congestion control mode identifier */ +	*pos++ = ifmsh->mesh_cc_id; +	/* Synchronization protocol identifier */ +	*pos++ = ifmsh->mesh_sp_id; +	/* Authentication Protocol identifier */ +	*pos++ = ifmsh->mesh_auth_id; +	/* Mesh Formation Info - number of neighbors */ +	neighbors = atomic_read(&ifmsh->mshstats.estab_plinks); +	/* Number of neighbor mesh STAs or 15 whichever is smaller */ +	neighbors = (neighbors > 15) ? 15 : neighbors; +	*pos++ = neighbors << 1; +	/* Mesh capability */ +	ifmsh->accepting_plinks = mesh_plink_availables(sdata); +	*pos = MESHCONF_CAPAB_FORWARDING; +	*pos++ |= ifmsh->accepting_plinks ? +	    MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; +	*pos++ = 0x00; + +	return 0; +} + +int +mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ +	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +	u8 *pos; + +	if (skb_tailroom(skb) < 2 + ifmsh->mesh_id_len) +		return -ENOMEM; + +	pos = skb_put(skb, 2 + ifmsh->mesh_id_len); +	*pos++ = WLAN_EID_MESH_ID; +	*pos++ = ifmsh->mesh_id_len; +	if (ifmsh->mesh_id_len) +		memcpy(pos, ifmsh->mesh_id, ifmsh->mesh_id_len); + +	return 0; +} + +int +mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ +	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +	u8 offset, len; +	const u8 *data; + +	if (!ifmsh->ie || !ifmsh->ie_len) +		return 0; + +	/* fast-forward to vendor IEs */ +	offset = ieee80211_ie_split_vendor(ifmsh->ie, ifmsh->ie_len, 0); + +	if (offset) { +		len = ifmsh->ie_len - offset; +		data = ifmsh->ie + offset; +		if (skb_tailroom(skb) < len) +			return -ENOMEM; +		memcpy(skb_put(skb, len), data, len); +	} + +	return 0; +} + +int +mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) +{ +	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +	u8 len = 0; +	const u8 *data; + +	if (!ifmsh->ie || !ifmsh->ie_len) +		return 0; + +	/* find RSN IE */ +	data = ifmsh->ie; +	while (data < ifmsh->ie + ifmsh->ie_len) { +		if (*data == WLAN_EID_RSN) { +			len = data[1] + 2; +			break; +		} +		data++; +	} + +	if (len) { +		if (skb_tailroom(skb) < len) +			return -ENOMEM; +		memcpy(skb_put(skb, len), data, len); +	} + +	return 0; +} + +int +mesh_add_srates_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)  {  	struct ieee80211_local *local = sdata->local;  	struct ieee80211_supported_band *sband; -	u8 *pos; -	int len, i, rate; -	u8 neighbors; +	int rate; +	u8 i, rates, *pos;  	sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; -	len = sband->n_bitrates; -	if (len > 8) -		len = 8; -	pos = skb_put(skb, len + 2); +	rates = sband->n_bitrates; +	if (rates > 8) +		rates = 8; + +	if (skb_tailroom(skb) < rates + 2) +		return -ENOMEM; + +	pos = skb_put(skb, rates + 2);  	*pos++ = WLAN_EID_SUPP_RATES; -	*pos++ = len; -	for (i = 0; i < len; i++) { +	*pos++ = rates; +	for (i = 0; i < rates; i++) {  		rate = sband->bitrates[i].bitrate;  		*pos++ = (u8) (rate / 5);  	} -	if (sband->n_bitrates > len) { -		pos = skb_put(skb, sband->n_bitrates - len + 2); +	return 0; +} + +int +mesh_add_ext_srates_ie(struct sk_buff *skb, +		       struct ieee80211_sub_if_data *sdata) +{ +	struct ieee80211_local *local = sdata->local; +	struct ieee80211_supported_band *sband; +	int rate; +	u8 i, exrates, *pos; + +	sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; +	exrates = sband->n_bitrates; +	if (exrates > 8) +		exrates -= 8; +	else +		exrates = 0; + +	if (skb_tailroom(skb) < exrates + 2) +		return -ENOMEM; + +	if (exrates) { +		pos = skb_put(skb, exrates + 2);  		*pos++ = WLAN_EID_EXT_SUPP_RATES; -		*pos++ = sband->n_bitrates - len; -		for (i = len; i < sband->n_bitrates; i++) { +		*pos++ = exrates; +		for (i = 8; i < sband->n_bitrates; i++) {  			rate = sband->bitrates[i].bitrate;  			*pos++ = (u8) (rate / 5);  		}  	} +	return 0; +} +int mesh_add_ds_params_ie(struct sk_buff *skb, +			  struct ieee80211_sub_if_data *sdata) +{ +	struct ieee80211_local *local = sdata->local; +	struct ieee80211_supported_band *sband; +	u8 *pos; + +	if (skb_tailroom(skb) < 3) +		return -ENOMEM; + +	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];  	if (sband->band == IEEE80211_BAND_2GHZ) {  		pos = skb_put(skb, 2 + 1);  		*pos++ = WLAN_EID_DS_PARAMS; @@ -241,53 +397,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)  		*pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq);  	} -	pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); -	*pos++ = WLAN_EID_MESH_ID; -	*pos++ = sdata->u.mesh.mesh_id_len; -	if (sdata->u.mesh.mesh_id_len) -		memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); - -	pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); -	*pos++ = WLAN_EID_MESH_CONFIG; -	*pos++ = sizeof(struct ieee80211_meshconf_ie); - -	/* Active path selection protocol ID */ -	*pos++ = sdata->u.mesh.mesh_pp_id; - -	/* Active path selection metric ID   */ -	*pos++ = sdata->u.mesh.mesh_pm_id; - -	/* Congestion control mode identifier */ -	*pos++ = sdata->u.mesh.mesh_cc_id; - -	/* Synchronization protocol identifier */ -	*pos++ = sdata->u.mesh.mesh_sp_id; - -	/* Authentication Protocol identifier */ -	*pos++ = sdata->u.mesh.mesh_auth_id; - -	/* Mesh Formation Info - number of neighbors */ -	neighbors = atomic_read(&sdata->u.mesh.mshstats.estab_plinks); -	/* Number of neighbor mesh STAs or 15 whichever is smaller */ -	neighbors = (neighbors > 15) ? 15 : neighbors; -	*pos++ = neighbors << 1; - -	/* Mesh capability */ -	sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); -	*pos = MESHCONF_CAPAB_FORWARDING; -	*pos++ |= sdata->u.mesh.accepting_plinks ? -	    MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; -	*pos++ = 0x00; - -	if (sdata->u.mesh.ie) { -		int len = sdata->u.mesh.ie_len; -		const u8 *data = sdata->u.mesh.ie; -		if (skb_tailroom(skb) > len) -			memcpy(skb_put(skb, len), data, len); -	} +	return 0;  } -  static void ieee80211_mesh_path_timer(unsigned long data)  {  	struct ieee80211_sub_if_data *sdata = @@ -425,7 +537,8 @@ static void ieee80211_mesh_rootpath(struct ieee80211_sub_if_data *sdata)  	mesh_path_tx_root_frame(sdata);  	mod_timer(&ifmsh->mesh_path_root_timer, -		  round_jiffies(jiffies + IEEE80211_MESH_RANN_INTERVAL)); +		  round_jiffies(TU_TO_EXP_TIME( +				  ifmsh->mshcfg.dot11MeshHWMPRannInterval)));  }  #ifdef CONFIG_PM @@ -433,7 +546,7 @@ void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)  {  	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; -	/* use atomic bitops in case both timers fire at the same time */ +	/* use atomic bitops in case all timers fire at the same time */  	if (del_timer_sync(&ifmsh->housekeeping_timer))  		set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); @@ -557,11 +670,18 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,  					  struct ieee80211_rx_status *rx_status)  {  	switch (mgmt->u.action.category) { -	case WLAN_CATEGORY_MESH_ACTION: -		mesh_rx_plink_frame(sdata, mgmt, len, rx_status); +	case WLAN_CATEGORY_SELF_PROTECTED: +		switch (mgmt->u.action.u.self_prot.action_code) { +		case WLAN_SP_MESH_PEERING_OPEN: +		case WLAN_SP_MESH_PEERING_CLOSE: +		case WLAN_SP_MESH_PEERING_CONFIRM: +			mesh_rx_plink_frame(sdata, mgmt, len, rx_status); +			break; +		}  		break; -	case WLAN_CATEGORY_MESH_PATH_SEL: -		mesh_rx_path_sel_frame(sdata, mgmt, len); +	case WLAN_CATEGORY_MESH_ACTION: +		if (mesh_action_is_path_sel(mgmt)) +			mesh_rx_path_sel_frame(sdata, mgmt, len);  		break;  	}  } @@ -633,6 +753,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)  	ifmsh->accepting_plinks = true;  	ifmsh->preq_id = 0;  	ifmsh->sn = 0; +	ifmsh->num_gates = 0;  	atomic_set(&ifmsh->mpaths, 0);  	mesh_rmc_init(sdata);  	ifmsh->last_preq = jiffies; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 249e733362e..20272072171 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -81,6 +81,7 @@ enum mesh_deferred_task_flags {   * @discovery_retries: number of discovery retries   * @flags: mesh path flags, as specified on &enum mesh_path_flags   * @state_lock: mesh path state lock + * @is_gate: the destination station of this path is a mesh gate   *   *   * The combination of dst and sdata is unique in the mesh path table. Since the @@ -104,6 +105,7 @@ struct mesh_path {  	u8 discovery_retries;  	enum mesh_path_flags flags;  	spinlock_t state_lock; +	bool is_gate;  };  /** @@ -120,6 +122,9 @@ struct mesh_path {   *	buckets   * @mean_chain_len: maximum average length for the hash buckets' list, if it is   *	reached, the table will grow + * @known_gates: list of known mesh gates and their mpaths by the station. The + * gate's mpath may or may not be resolved and active. + *   * rcu_head: RCU head to free the table   */  struct mesh_table { @@ -133,6 +138,8 @@ struct mesh_table {  	int (*copy_node) (struct hlist_node *p, struct mesh_table *newtbl);  	int size_order;  	int mean_chain_len; +	struct hlist_head *known_gates; +	spinlock_t gates_lock;  	struct rcu_head rcu_head;  }; @@ -166,6 +173,8 @@ struct mesh_rmc {  	u32 idx_mask;  }; +#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) +#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)  #define MESH_DEFAULT_BEACON_INTERVAL		1000 	/* in 1024 us units */ @@ -177,14 +186,6 @@ struct mesh_rmc {  /* Maximum number of paths per interface */  #define MESH_MAX_MPATHS		1024 -/* Pending ANA approval */ -#define MESH_PATH_SEL_ACTION	0 - -/* PERR reason codes */ -#define PEER_RCODE_UNSPECIFIED  11 -#define PERR_RCODE_NO_ROUTE     12 -#define PERR_RCODE_DEST_UNREACH 13 -  /* Public interfaces */  /* Various */  int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, @@ -199,6 +200,20 @@ bool mesh_matches_local(struct ieee802_11_elems *ie,  void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);  void mesh_mgmt_ies_add(struct sk_buff *skb,  		struct ieee80211_sub_if_data *sdata); +int mesh_add_meshconf_ie(struct sk_buff *skb, +			 struct ieee80211_sub_if_data *sdata); +int mesh_add_meshid_ie(struct sk_buff *skb, +		       struct ieee80211_sub_if_data *sdata); +int mesh_add_rsn_ie(struct sk_buff *skb, +		    struct ieee80211_sub_if_data *sdata); +int mesh_add_vendor_ies(struct sk_buff *skb, +			struct ieee80211_sub_if_data *sdata); +int mesh_add_srates_ie(struct sk_buff *skb, +		       struct ieee80211_sub_if_data *sdata); +int mesh_add_ext_srates_ie(struct sk_buff *skb, +			   struct ieee80211_sub_if_data *sdata); +int mesh_add_ds_params_ie(struct sk_buff *skb, +			  struct ieee80211_sub_if_data *sdata);  void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);  int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);  void ieee80211s_init(void); @@ -227,6 +242,10 @@ void mesh_path_flush(struct ieee80211_sub_if_data *sdata);  void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,  		struct ieee80211_mgmt *mgmt, size_t len);  int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); + +int mesh_path_add_gate(struct mesh_path *mpath); +int mesh_path_send_to_gates(struct mesh_path *mpath); +int mesh_gate_num(struct ieee80211_sub_if_data *sdata);  /* Mesh plinks */  void mesh_neighbour_update(u8 *hw_addr, u32 rates,  		struct ieee80211_sub_if_data *sdata, @@ -262,6 +281,7 @@ void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);  void mesh_path_restart(struct ieee80211_sub_if_data *sdata);  void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); +bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);  extern int mesh_paths_generation;  #ifdef CONFIG_MAC80211_MESH diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 3d8e55ae6ab..fd4f76a3e13 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -11,7 +11,8 @@  #include "mesh.h"  #ifdef CONFIG_MAC80211_VERBOSE_MHWMP_DEBUG -#define mhwmp_dbg(fmt, args...)   printk(KERN_DEBUG "Mesh HWMP: " fmt, ##args) +#define mhwmp_dbg(fmt, args...) \ +	printk(KERN_DEBUG "Mesh HWMP (%s): " fmt "\n", sdata->name, ##args)  #else  #define mhwmp_dbg(fmt, args...)   do { (void)(0); } while (0)  #endif @@ -68,12 +69,12 @@ static inline u32 u16_field_get(u8 *preq_elem, int offset, bool ae)  #define PREP_IE_FLAGS(x)	PREQ_IE_FLAGS(x)  #define PREP_IE_HOPCOUNT(x)	PREQ_IE_HOPCOUNT(x)  #define PREP_IE_TTL(x)		PREQ_IE_TTL(x) -#define PREP_IE_ORIG_ADDR(x)	(x + 3) -#define PREP_IE_ORIG_SN(x)	u32_field_get(x, 9, 0) +#define PREP_IE_ORIG_ADDR(x)	(AE_F_SET(x) ? x + 27 : x + 21) +#define PREP_IE_ORIG_SN(x)	u32_field_get(x, 27, AE_F_SET(x))  #define PREP_IE_LIFETIME(x)	u32_field_get(x, 13, AE_F_SET(x))  #define PREP_IE_METRIC(x)	u32_field_get(x, 17, AE_F_SET(x)) -#define PREP_IE_TARGET_ADDR(x)	(AE_F_SET(x) ? x + 27 : x + 21) -#define PREP_IE_TARGET_SN(x)	u32_field_get(x, 27, AE_F_SET(x)) +#define PREP_IE_TARGET_ADDR(x)	(x + 3) +#define PREP_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)  #define PERR_IE_TTL(x)		(*(x))  #define PERR_IE_TARGET_FLAGS(x)	(*(x + 2)) @@ -132,24 +133,25 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,  	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);  	/* BSSID == SA */  	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); -	mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; -	mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; +	mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; +	mgmt->u.action.u.mesh_action.action_code = +					WLAN_MESH_ACTION_HWMP_PATH_SELECTION;  	switch (action) {  	case MPATH_PREQ: -		mhwmp_dbg("sending PREQ to %pM\n", target); +		mhwmp_dbg("sending PREQ to %pM", target);  		ie_len = 37;  		pos = skb_put(skb, 2 + ie_len);  		*pos++ = WLAN_EID_PREQ;  		break;  	case MPATH_PREP: -		mhwmp_dbg("sending PREP to %pM\n", target); +		mhwmp_dbg("sending PREP to %pM", target);  		ie_len = 31;  		pos = skb_put(skb, 2 + ie_len);  		*pos++ = WLAN_EID_PREP;  		break;  	case MPATH_RANN: -		mhwmp_dbg("sending RANN from %pM\n", orig_addr); +		mhwmp_dbg("sending RANN from %pM", orig_addr);  		ie_len = sizeof(struct ieee80211_rann_ie);  		pos = skb_put(skb, 2 + ie_len);  		*pos++ = WLAN_EID_RANN; @@ -163,29 +165,37 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags,  	*pos++ = flags;  	*pos++ = hop_count;  	*pos++ = ttl; -	if (action == MPATH_PREQ) { -		memcpy(pos, &preq_id, 4); +	if (action == MPATH_PREP) { +		memcpy(pos, target, ETH_ALEN); +		pos += ETH_ALEN; +		memcpy(pos, &target_sn, 4);  		pos += 4; -	} -	memcpy(pos, orig_addr, ETH_ALEN); -	pos += ETH_ALEN; -	memcpy(pos, &orig_sn, 4); -	pos += 4; -	if (action != MPATH_RANN) { -		memcpy(pos, &lifetime, 4); +	} else { +		if (action == MPATH_PREQ) { +			memcpy(pos, &preq_id, 4); +			pos += 4; +		} +		memcpy(pos, orig_addr, ETH_ALEN); +		pos += ETH_ALEN; +		memcpy(pos, &orig_sn, 4);  		pos += 4;  	} +	memcpy(pos, &lifetime, 4);	/* interval for RANN */ +	pos += 4;  	memcpy(pos, &metric, 4);  	pos += 4;  	if (action == MPATH_PREQ) { -		/* destination count */ -		*pos++ = 1; +		*pos++ = 1; /* destination count */  		*pos++ = target_flags; -	} -	if (action != MPATH_RANN) {  		memcpy(pos, target, ETH_ALEN);  		pos += ETH_ALEN;  		memcpy(pos, &target_sn, 4); +		pos += 4; +	} else if (action == MPATH_PREP) { +		memcpy(pos, orig_addr, ETH_ALEN); +		pos += ETH_ALEN; +		memcpy(pos, &orig_sn, 4); +		pos += 4;  	}  	ieee80211_tx_skb(sdata, skb); @@ -224,9 +234,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn,  	memcpy(mgmt->da, ra, ETH_ALEN);  	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); -	/* BSSID is left zeroed, wildcard value */ -	mgmt->u.action.category = WLAN_CATEGORY_MESH_PATH_SEL; -	mgmt->u.action.u.mesh_action.action_code = MESH_PATH_SEL_ACTION; +	/* BSSID == SA */ +	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); +	mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; +	mgmt->u.action.u.mesh_action.action_code = +					WLAN_MESH_ACTION_HWMP_PATH_SELECTION;  	ie_len = 15;  	pos = skb_put(skb, 2 + ie_len);  	*pos++ = WLAN_EID_PERR; @@ -483,10 +495,10 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,  	orig_sn = PREQ_IE_ORIG_SN(preq_elem);  	target_flags = PREQ_IE_TARGET_F(preq_elem); -	mhwmp_dbg("received PREQ from %pM\n", orig_addr); +	mhwmp_dbg("received PREQ from %pM", orig_addr);  	if (memcmp(target_addr, sdata->vif.addr, ETH_ALEN) == 0) { -		mhwmp_dbg("PREQ is for us\n"); +		mhwmp_dbg("PREQ is for us");  		forward = false;  		reply = true;  		metric = 0; @@ -522,7 +534,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,  		lifetime = PREQ_IE_LIFETIME(preq_elem);  		ttl = ifmsh->mshcfg.element_ttl;  		if (ttl != 0) { -			mhwmp_dbg("replying to the PREQ\n"); +			mhwmp_dbg("replying to the PREQ");  			mesh_path_sel_frame_tx(MPATH_PREP, 0, target_addr,  				cpu_to_le32(target_sn), 0, orig_addr,  				cpu_to_le32(orig_sn), mgmt->sa, 0, ttl, @@ -542,7 +554,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,  			ifmsh->mshstats.dropped_frames_ttl++;  			return;  		} -		mhwmp_dbg("forwarding the PREQ from %pM\n", orig_addr); +		mhwmp_dbg("forwarding the PREQ from %pM", orig_addr);  		--ttl;  		flags = PREQ_IE_FLAGS(preq_elem);  		preq_id = PREQ_IE_PREQ_ID(preq_elem); @@ -577,7 +589,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,  	u8 next_hop[ETH_ALEN];  	u32 target_sn, orig_sn, lifetime; -	mhwmp_dbg("received PREP from %pM\n", PREP_IE_ORIG_ADDR(prep_elem)); +	mhwmp_dbg("received PREP from %pM", PREP_IE_ORIG_ADDR(prep_elem));  	/* Note that we divert from the draft nomenclature and denominate  	 * destination to what the draft refers to as origininator. So in this @@ -683,6 +695,8 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,  	u8 ttl, flags, hopcount;  	u8 *orig_addr;  	u32 orig_sn, metric; +	u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; +	bool root_is_gate;  	ttl = rann->rann_ttl;  	if (ttl <= 1) { @@ -691,12 +705,19 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,  	}  	ttl--;  	flags = rann->rann_flags; +	root_is_gate = !!(flags & RANN_FLAG_IS_GATE);  	orig_addr = rann->rann_addr;  	orig_sn = rann->rann_seq;  	hopcount = rann->rann_hopcount;  	hopcount++;  	metric = rann->rann_metric; -	mhwmp_dbg("received RANN from %pM\n", orig_addr); + +	/*  Ignore our own RANNs */ +	if (memcmp(orig_addr, sdata->vif.addr, ETH_ALEN) == 0) +		return; + +	mhwmp_dbg("received RANN from %pM (is_gate=%d)", orig_addr, +			root_is_gate);  	rcu_read_lock();  	mpath = mesh_path_lookup(orig_addr, sdata); @@ -708,18 +729,28 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,  			sdata->u.mesh.mshstats.dropped_frames_no_route++;  			return;  		} -		mesh_queue_preq(mpath, -				PREQ_Q_F_START | PREQ_Q_F_REFRESH);  	} + +	if ((!(mpath->flags & (MESH_PATH_ACTIVE | MESH_PATH_RESOLVING)) || +	     time_after(jiffies, mpath->exp_time - 1*HZ)) && +	     !(mpath->flags & MESH_PATH_FIXED)) { +		mhwmp_dbg("%s time to refresh root mpath %pM", sdata->name, +							       orig_addr); +		mesh_queue_preq(mpath, PREQ_Q_F_START | PREQ_Q_F_REFRESH); +	} +  	if (mpath->sn < orig_sn) {  		mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr,  				       cpu_to_le32(orig_sn),  				       0, NULL, 0, broadcast_addr, -				       hopcount, ttl, 0, +				       hopcount, ttl, cpu_to_le32(interval),  				       cpu_to_le32(metric + mpath->metric),  				       0, sdata);  		mpath->sn = orig_sn;  	} +	if (root_is_gate) +		mesh_path_add_gate(mpath); +  	rcu_read_unlock();  } @@ -787,7 +818,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)  	preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_ATOMIC);  	if (!preq_node) { -		mhwmp_dbg("could not allocate PREQ node\n"); +		mhwmp_dbg("could not allocate PREQ node");  		return;  	} @@ -796,7 +827,7 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)  		spin_unlock_bh(&ifmsh->mesh_preq_queue_lock);  		kfree(preq_node);  		if (printk_ratelimit()) -			mhwmp_dbg("PREQ node queue full\n"); +			mhwmp_dbg("PREQ node queue full");  		return;  	} @@ -981,35 +1012,46 @@ void mesh_path_timer(unsigned long data)  {  	struct mesh_path *mpath = (void *) data;  	struct ieee80211_sub_if_data *sdata = mpath->sdata; +	int ret;  	if (sdata->local->quiescing)  		return;  	spin_lock_bh(&mpath->state_lock);  	if (mpath->flags & MESH_PATH_RESOLVED || -			(!(mpath->flags & MESH_PATH_RESOLVING))) +			(!(mpath->flags & MESH_PATH_RESOLVING))) {  		mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); -	else if (mpath->discovery_retries < max_preq_retries(sdata)) { +		spin_unlock_bh(&mpath->state_lock); +	} else if (mpath->discovery_retries < max_preq_retries(sdata)) {  		++mpath->discovery_retries;  		mpath->discovery_timeout *= 2; +		spin_unlock_bh(&mpath->state_lock);  		mesh_queue_preq(mpath, 0);  	} else {  		mpath->flags = 0;  		mpath->exp_time = jiffies; -		mesh_path_flush_pending(mpath); +		spin_unlock_bh(&mpath->state_lock); +		if (!mpath->is_gate && mesh_gate_num(sdata) > 0) { +			ret = mesh_path_send_to_gates(mpath); +			if (ret) +				mhwmp_dbg("no gate was reachable"); +		} else +			mesh_path_flush_pending(mpath);  	} - -	spin_unlock_bh(&mpath->state_lock);  }  void  mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata)  {  	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +	u32 interval = ifmsh->mshcfg.dot11MeshHWMPRannInterval; +	u8 flags; -	mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->vif.addr, +	flags = (ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol) +			? RANN_FLAG_IS_GATE : 0; +	mesh_path_sel_frame_tx(MPATH_RANN, flags, sdata->vif.addr,  			       cpu_to_le32(++ifmsh->sn),  			       0, NULL, 0, broadcast_addr,  			       0, sdata->u.mesh.mshcfg.element_ttl, -			       0, 0, 0, sdata); +			       cpu_to_le32(interval), 0, 0, sdata);  } diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index dc7ae8d31aa..7fde32159fd 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -17,6 +17,12 @@  #include "ieee80211_i.h"  #include "mesh.h" +#ifdef CONFIG_MAC80211_VERBOSE_MPATH_DEBUG +#define mpath_dbg(fmt, args...)	printk(KERN_DEBUG fmt, ##args) +#else +#define mpath_dbg(fmt, args...)	do { (void)(0); } while (0) +#endif +  /* There will be initially 2^INIT_PATHS_SIZE_ORDER buckets */  #define INIT_PATHS_SIZE_ORDER	2 @@ -60,6 +66,8 @@ static inline struct mesh_table *resize_dereference_mpp_paths(void)  		lockdep_is_held(&pathtbl_resize_lock));  } +static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath); +  /*   * CAREFUL -- "tbl" must not be an expression,   * in particular not an rcu_dereference(), since @@ -103,6 +111,7 @@ static struct mesh_table *mesh_table_alloc(int size_order)  			sizeof(newtbl->hash_rnd));  	for (i = 0; i <= newtbl->hash_mask; i++)  		spin_lock_init(&newtbl->hashwlock[i]); +	spin_lock_init(&newtbl->gates_lock);  	return newtbl;  } @@ -118,6 +127,7 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)  {  	struct hlist_head *mesh_hash;  	struct hlist_node *p, *q; +	struct mpath_node *gate;  	int i;  	mesh_hash = tbl->hash_buckets; @@ -129,6 +139,17 @@ static void mesh_table_free(struct mesh_table *tbl, bool free_leafs)  		}  		spin_unlock_bh(&tbl->hashwlock[i]);  	} +	if (free_leafs) { +		spin_lock_bh(&tbl->gates_lock); +		hlist_for_each_entry_safe(gate, p, q, +					 tbl->known_gates, list) { +			hlist_del(&gate->list); +			kfree(gate); +		} +		kfree(tbl->known_gates); +		spin_unlock_bh(&tbl->gates_lock); +	} +  	__mesh_table_free(tbl);  } @@ -146,6 +167,7 @@ static int mesh_table_grow(struct mesh_table *oldtbl,  	newtbl->free_node = oldtbl->free_node;  	newtbl->mean_chain_len = oldtbl->mean_chain_len;  	newtbl->copy_node = oldtbl->copy_node; +	newtbl->known_gates = oldtbl->known_gates;  	atomic_set(&newtbl->entries, atomic_read(&oldtbl->entries));  	oldhash = oldtbl->hash_buckets; @@ -205,6 +227,111 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta)  	spin_unlock_irqrestore(&mpath->frame_queue.lock, flags);  } +static void prepare_for_gate(struct sk_buff *skb, char *dst_addr, +			     struct mesh_path *gate_mpath) +{ +	struct ieee80211_hdr *hdr; +	struct ieee80211s_hdr *mshdr; +	int mesh_hdrlen, hdrlen; +	char *next_hop; + +	hdr = (struct ieee80211_hdr *) skb->data; +	hdrlen = ieee80211_hdrlen(hdr->frame_control); +	mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + +	if (!(mshdr->flags & MESH_FLAGS_AE)) { +		/* size of the fixed part of the mesh header */ +		mesh_hdrlen = 6; + +		/* make room for the two extended addresses */ +		skb_push(skb, 2 * ETH_ALEN); +		memmove(skb->data, hdr, hdrlen + mesh_hdrlen); + +		hdr = (struct ieee80211_hdr *) skb->data; + +		/* we preserve the previous mesh header and only add +		 * the new addreses */ +		mshdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); +		mshdr->flags = MESH_FLAGS_AE_A5_A6; +		memcpy(mshdr->eaddr1, hdr->addr3, ETH_ALEN); +		memcpy(mshdr->eaddr2, hdr->addr4, ETH_ALEN); +	} + +	/* update next hop */ +	hdr = (struct ieee80211_hdr *) skb->data; +	rcu_read_lock(); +	next_hop = rcu_dereference(gate_mpath->next_hop)->sta.addr; +	memcpy(hdr->addr1, next_hop, ETH_ALEN); +	rcu_read_unlock(); +	memcpy(hdr->addr3, dst_addr, ETH_ALEN); +} + +/** + * + * mesh_path_move_to_queue - Move or copy frames from one mpath queue to another + * + * This function is used to transfer or copy frames from an unresolved mpath to + * a gate mpath.  The function also adds the Address Extension field and + * updates the next hop. + * + * If a frame already has an Address Extension field, only the next hop and + * destination addresses are updated. + * + * The gate mpath must be an active mpath with a valid mpath->next_hop. + * + * @mpath: An active mpath the frames will be sent to (i.e. the gate) + * @from_mpath: The failed mpath + * @copy: When true, copy all the frames to the new mpath queue.  When false, + * move them. + */ +static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, +				    struct mesh_path *from_mpath, +				    bool copy) +{ +	struct sk_buff *skb, *cp_skb = NULL; +	struct sk_buff_head gateq, failq; +	unsigned long flags; +	int num_skbs; + +	BUG_ON(gate_mpath == from_mpath); +	BUG_ON(!gate_mpath->next_hop); + +	__skb_queue_head_init(&gateq); +	__skb_queue_head_init(&failq); + +	spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); +	skb_queue_splice_init(&from_mpath->frame_queue, &failq); +	spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); + +	num_skbs = skb_queue_len(&failq); + +	while (num_skbs--) { +		skb = __skb_dequeue(&failq); +		if (copy) +			cp_skb = skb_copy(skb, GFP_ATOMIC); + +		prepare_for_gate(skb, gate_mpath->dst, gate_mpath); +		__skb_queue_tail(&gateq, skb); + +		if (copy && cp_skb) +			__skb_queue_tail(&failq, cp_skb); +	} + +	spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); +	skb_queue_splice(&gateq, &gate_mpath->frame_queue); +	mpath_dbg("Mpath queue for gate %pM has %d frames\n", +			gate_mpath->dst, +			skb_queue_len(&gate_mpath->frame_queue)); +	spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); + +	if (!copy) +		return; + +	spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); +	skb_queue_splice(&failq, &from_mpath->frame_queue); +	spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); +} +  /**   * mesh_path_lookup - look up a path in the mesh path table @@ -304,6 +431,109 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data  	return NULL;  } +static void mesh_gate_node_reclaim(struct rcu_head *rp) +{ +	struct mpath_node *node = container_of(rp, struct mpath_node, rcu); +	kfree(node); +} + +/** + * mesh_gate_add - mark mpath as path to a mesh gate and add to known_gates + * @mesh_tbl: table which contains known_gates list + * @mpath: mpath to known mesh gate + * + * Returns: 0 on success + * + */ +static int mesh_gate_add(struct mesh_table *tbl, struct mesh_path *mpath) +{ +	struct mpath_node *gate, *new_gate; +	struct hlist_node *n; +	int err; + +	rcu_read_lock(); +	tbl = rcu_dereference(tbl); + +	hlist_for_each_entry_rcu(gate, n, tbl->known_gates, list) +		if (gate->mpath == mpath) { +			err = -EEXIST; +			goto err_rcu; +		} + +	new_gate = kzalloc(sizeof(struct mpath_node), GFP_ATOMIC); +	if (!new_gate) { +		err = -ENOMEM; +		goto err_rcu; +	} + +	mpath->is_gate = true; +	mpath->sdata->u.mesh.num_gates++; +	new_gate->mpath = mpath; +	spin_lock_bh(&tbl->gates_lock); +	hlist_add_head_rcu(&new_gate->list, tbl->known_gates); +	spin_unlock_bh(&tbl->gates_lock); +	rcu_read_unlock(); +	mpath_dbg("Mesh path (%s): Recorded new gate: %pM. %d known gates\n", +		  mpath->sdata->name, mpath->dst, +		  mpath->sdata->u.mesh.num_gates); +	return 0; +err_rcu: +	rcu_read_unlock(); +	return err; +} + +/** + * mesh_gate_del - remove a mesh gate from the list of known gates + * @tbl: table which holds our list of known gates + * @mpath: gate mpath + * + * Returns: 0 on success + * + * Locking: must be called inside rcu_read_lock() section + */ +static int mesh_gate_del(struct mesh_table *tbl, struct mesh_path *mpath) +{ +	struct mpath_node *gate; +	struct hlist_node *p, *q; + +	tbl = rcu_dereference(tbl); + +	hlist_for_each_entry_safe(gate, p, q, tbl->known_gates, list) +		if (gate->mpath == mpath) { +			spin_lock_bh(&tbl->gates_lock); +			hlist_del_rcu(&gate->list); +			call_rcu(&gate->rcu, mesh_gate_node_reclaim); +			spin_unlock_bh(&tbl->gates_lock); +			mpath->sdata->u.mesh.num_gates--; +			mpath->is_gate = false; +			mpath_dbg("Mesh path (%s): Deleted gate: %pM. " +				  "%d known gates\n", mpath->sdata->name, +				  mpath->dst, mpath->sdata->u.mesh.num_gates); +			break; +		} + +	return 0; +} + +/** + * + * mesh_path_add_gate - add the given mpath to a mesh gate to our path table + * @mpath: gate path to add to table + */ +int mesh_path_add_gate(struct mesh_path *mpath) +{ +	return mesh_gate_add(mesh_paths, mpath); +} + +/** + * mesh_gate_num - number of gates known to this interface + * @sdata: subif data + */ +int mesh_gate_num(struct ieee80211_sub_if_data *sdata) +{ +	return sdata->u.mesh.num_gates; +} +  /**   * mesh_path_add - allocate and add a new path to the mesh path table   * @addr: destination address of the path (ETH_ALEN length) @@ -481,6 +711,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)  	new_mpath->flags = 0;  	skb_queue_head_init(&new_mpath->frame_queue);  	new_node->mpath = new_mpath; +	init_timer(&new_mpath->timer);  	new_mpath->exp_time = jiffies;  	spin_lock_init(&new_mpath->state_lock); @@ -539,6 +770,7 @@ void mesh_plink_broken(struct sta_info *sta)  	struct hlist_node *p;  	struct ieee80211_sub_if_data *sdata = sta->sdata;  	int i; +	__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_DEST_UNREACHABLE);  	rcu_read_lock();  	tbl = rcu_dereference(mesh_paths); @@ -553,8 +785,7 @@ void mesh_plink_broken(struct sta_info *sta)  			spin_unlock_bh(&mpath->state_lock);  			mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl,  					mpath->dst, cpu_to_le32(mpath->sn), -					cpu_to_le16(PERR_RCODE_DEST_UNREACH), -					bcast, sdata); +					reason, bcast, sdata);  		} else  		spin_unlock_bh(&mpath->state_lock);  	} @@ -647,12 +878,14 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)  		mpath = node->mpath;  		if (mpath->sdata == sdata &&  		    memcmp(addr, mpath->dst, ETH_ALEN) == 0) { -			spin_lock(&mpath->state_lock); +			spin_lock_bh(&mpath->state_lock); +			if (mpath->is_gate) +				mesh_gate_del(tbl, mpath);  			mpath->flags |= MESH_PATH_RESOLVING;  			hlist_del_rcu(&node->list);  			call_rcu(&node->rcu, mesh_path_node_reclaim);  			atomic_dec(&tbl->entries); -			spin_unlock(&mpath->state_lock); +			spin_unlock_bh(&mpath->state_lock);  			goto enddel;  		}  	} @@ -681,6 +914,58 @@ void mesh_path_tx_pending(struct mesh_path *mpath)  }  /** + * mesh_path_send_to_gates - sends pending frames to all known mesh gates + * + * @mpath: mesh path whose queue will be emptied + * + * If there is only one gate, the frames are transferred from the failed mpath + * queue to that gate's queue.  If there are more than one gates, the frames + * are copied from each gate to the next.  After frames are copied, the + * mpath queues are emptied onto the transmission queue. + */ +int mesh_path_send_to_gates(struct mesh_path *mpath) +{ +	struct ieee80211_sub_if_data *sdata = mpath->sdata; +	struct hlist_node *n; +	struct mesh_table *tbl; +	struct mesh_path *from_mpath = mpath; +	struct mpath_node *gate = NULL; +	bool copy = false; +	struct hlist_head *known_gates; + +	rcu_read_lock(); +	tbl = rcu_dereference(mesh_paths); +	known_gates = tbl->known_gates; +	rcu_read_unlock(); + +	if (!known_gates) +		return -EHOSTUNREACH; + +	hlist_for_each_entry_rcu(gate, n, known_gates, list) { +		if (gate->mpath->sdata != sdata) +			continue; + +		if (gate->mpath->flags & MESH_PATH_ACTIVE) { +			mpath_dbg("Forwarding to %pM\n", gate->mpath->dst); +			mesh_path_move_to_queue(gate->mpath, from_mpath, copy); +			from_mpath = gate->mpath; +			copy = true; +		} else { +			mpath_dbg("Not forwarding %p\n", gate->mpath); +			mpath_dbg("flags %x\n", gate->mpath->flags); +		} +	} + +	hlist_for_each_entry_rcu(gate, n, known_gates, list) +		if (gate->mpath->sdata == sdata) { +			mpath_dbg("Sending to %pM\n", gate->mpath->dst); +			mesh_path_tx_pending(gate->mpath); +		} + +	return (from_mpath == mpath) ? -EHOSTUNREACH : 0; +} + +/**   * mesh_path_discard_frame - discard a frame whose path could not be resolved   *   * @skb: frame to discard @@ -699,6 +984,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,  	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;  	struct mesh_path *mpath;  	u32 sn = 0; +	__le16 reason = cpu_to_le16(WLAN_REASON_MESH_PATH_NOFORWARD);  	if (memcmp(hdr->addr4, sdata->vif.addr, ETH_ALEN) != 0) {  		u8 *ra, *da; @@ -709,8 +995,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,  		if (mpath)  			sn = ++mpath->sn;  		mesh_path_error_tx(sdata->u.mesh.mshcfg.element_ttl, skb->data, -				   cpu_to_le32(sn), -				   cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); +				   cpu_to_le32(sn), reason, ra, sdata);  	}  	kfree_skb(skb); @@ -728,8 +1013,7 @@ void mesh_path_flush_pending(struct mesh_path *mpath)  {  	struct sk_buff *skb; -	while ((skb = skb_dequeue(&mpath->frame_queue)) && -			(mpath->flags & MESH_PATH_ACTIVE)) +	while ((skb = skb_dequeue(&mpath->frame_queue)) != NULL)  		mesh_path_discard_frame(skb, mpath->sdata);  } @@ -797,6 +1081,9 @@ int mesh_pathtbl_init(void)  	tbl_path->free_node = &mesh_path_node_free;  	tbl_path->copy_node = &mesh_path_node_copy;  	tbl_path->mean_chain_len = MEAN_CHAIN_LEN; +	tbl_path->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); +	INIT_HLIST_HEAD(tbl_path->known_gates); +  	tbl_mpp = mesh_table_alloc(INIT_PATHS_SIZE_ORDER);  	if (!tbl_mpp) { @@ -806,6 +1093,8 @@ int mesh_pathtbl_init(void)  	tbl_mpp->free_node = &mesh_path_node_free;  	tbl_mpp->copy_node = &mesh_path_node_copy;  	tbl_mpp->mean_chain_len = MEAN_CHAIN_LEN; +	tbl_mpp->known_gates = kzalloc(sizeof(struct hlist_head), GFP_ATOMIC); +	INIT_HLIST_HEAD(tbl_mpp->known_gates);  	/* Need no locking since this is during init */  	RCU_INIT_POINTER(mesh_paths, tbl_path); diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f4adc091788..1a00d0f701c 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -19,35 +19,18 @@  #define mpl_dbg(fmt, args...)	do { (void)(0); } while (0)  #endif -#define PLINK_GET_LLID(p) (p + 4) -#define PLINK_GET_PLID(p) (p + 6) +#define PLINK_GET_LLID(p) (p + 2) +#define PLINK_GET_PLID(p) (p + 4)  #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \  				jiffies + HZ * t / 1000)) -/* Peer link cancel reasons, all subject to ANA approval */ -#define MESH_LINK_CANCELLED			2 -#define MESH_MAX_NEIGHBORS			3 -#define MESH_CAPABILITY_POLICY_VIOLATION	4 -#define MESH_CLOSE_RCVD				5 -#define MESH_MAX_RETRIES			6 -#define MESH_CONFIRM_TIMEOUT			7 -#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS	8 -#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE	9 -#define MESH_SECURITY_FAILED_VERIFICATION	10 -  #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)  #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)  #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)  #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)  #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) -enum plink_frame_type { -	PLINK_OPEN = 1, -	PLINK_CONFIRM, -	PLINK_CLOSE -}; -  enum plink_event {  	PLINK_UNDEFINED,  	OPN_ACPT, @@ -157,16 +140,16 @@ void mesh_plink_deactivate(struct sta_info *sta)  }  static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, -		enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, -		__le16 reason) { +		enum ieee80211_self_protected_actioncode action, +		u8 *da, __le16 llid, __le16 plid, __le16 reason) {  	struct ieee80211_local *local = sdata->local;  	struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +  			sdata->u.mesh.ie_len);  	struct ieee80211_mgmt *mgmt;  	bool include_plid = false; -	static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; +	int ie_len = 4; +	u16 peering_proto = 0;  	u8 *pos; -	int ie_len;  	if (!skb)  		return -1; @@ -175,63 +158,75 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,  	 * common action part (1)  	 */  	mgmt = (struct ieee80211_mgmt *) -		skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); -	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); +		skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot)); +	memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot));  	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |  					  IEEE80211_STYPE_ACTION);  	memcpy(mgmt->da, da, ETH_ALEN);  	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);  	memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); -	mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; -	mgmt->u.action.u.plink_action.action_code = action; +	mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED; +	mgmt->u.action.u.self_prot.action_code = action; -	if (action == PLINK_CLOSE) -		mgmt->u.action.u.plink_action.aux = reason; -	else { -		mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0); -		if (action == PLINK_CONFIRM) { -			pos = skb_put(skb, 4); -			/* two-byte status code followed by two-byte AID */ -			memset(pos, 0, 2); +	if (action != WLAN_SP_MESH_PEERING_CLOSE) { +		/* capability info */ +		pos = skb_put(skb, 2); +		memset(pos, 0, 2); +		if (action == WLAN_SP_MESH_PEERING_CONFIRM) { +			/* AID */ +			pos = skb_put(skb, 2);  			memcpy(pos + 2, &plid, 2);  		} -		mesh_mgmt_ies_add(skb, sdata); +		if (mesh_add_srates_ie(skb, sdata) || +		    mesh_add_ext_srates_ie(skb, sdata) || +		    mesh_add_rsn_ie(skb, sdata) || +		    mesh_add_meshid_ie(skb, sdata) || +		    mesh_add_meshconf_ie(skb, sdata)) +			return -1; +	} else {	/* WLAN_SP_MESH_PEERING_CLOSE */ +		if (mesh_add_meshid_ie(skb, sdata)) +			return -1;  	} -	/* Add Peer Link Management element */ +	/* Add Mesh Peering Management element */  	switch (action) { -	case PLINK_OPEN: -		ie_len = 6; +	case WLAN_SP_MESH_PEERING_OPEN:  		break; -	case PLINK_CONFIRM: -		ie_len = 8; +	case WLAN_SP_MESH_PEERING_CONFIRM: +		ie_len += 2;  		include_plid = true;  		break; -	case PLINK_CLOSE: -	default: -		if (!plid) -			ie_len = 8; -		else { -			ie_len = 10; +	case WLAN_SP_MESH_PEERING_CLOSE: +		if (plid) { +			ie_len += 2;  			include_plid = true;  		} +		ie_len += 2;	/* reason code */  		break; +	default: +		return -EINVAL;  	} +	if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) +		return -ENOMEM; +  	pos = skb_put(skb, 2 + ie_len); -	*pos++ = WLAN_EID_PEER_LINK; +	*pos++ = WLAN_EID_PEER_MGMT;  	*pos++ = ie_len; -	memcpy(pos, meshpeeringproto, sizeof(meshpeeringproto)); -	pos += 4; +	memcpy(pos, &peering_proto, 2); +	pos += 2;  	memcpy(pos, &llid, 2); +	pos += 2;  	if (include_plid) { -		pos += 2;  		memcpy(pos, &plid, 2); -	} -	if (action == PLINK_CLOSE) {  		pos += 2; +	} +	if (action == WLAN_SP_MESH_PEERING_CLOSE) {  		memcpy(pos, &reason, 2); +		pos += 2;  	} +	if (mesh_add_vendor_ies(skb, sdata)) +		return -1;  	ieee80211_tx_skb(sdata, skb);  	return 0; @@ -322,21 +317,21 @@ static void mesh_plink_timer(unsigned long data)  			++sta->plink_retries;  			mod_plink_timer(sta, sta->plink_timeout);  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, -					    0, 0); +			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, +					    sta->sta.addr, llid, 0, 0);  			break;  		} -		reason = cpu_to_le16(MESH_MAX_RETRIES); +		reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);  		/* fall through on else */  	case NL80211_PLINK_CNF_RCVD:  		/* confirm timer */  		if (!reason) -			reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); +			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);  		sta->plink_state = NL80211_PLINK_HOLDING;  		mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));  		spin_unlock_bh(&sta->lock); -		mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, -				    reason); +		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, +				    sta->sta.addr, llid, plid, reason);  		break;  	case NL80211_PLINK_HOLDING:  		/* holding timer */ @@ -396,7 +391,7 @@ int mesh_plink_open(struct sta_info *sta)  	mpl_dbg("Mesh plink: starting establishment with %pM\n",  		sta->sta.addr); -	return mesh_plink_frame_tx(sdata, PLINK_OPEN, +	return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,  				   sta->sta.addr, llid, 0, 0);  } @@ -422,7 +417,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  	struct ieee802_11_elems elems;  	struct sta_info *sta;  	enum plink_event event; -	enum plink_frame_type ftype; +	enum ieee80211_self_protected_actioncode ftype;  	size_t baselen;  	bool deactivated, matches_local = true;  	u8 ie_len; @@ -449,14 +444,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		return;  	} -	baseaddr = mgmt->u.action.u.plink_action.variable; -	baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; -	if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { +	baseaddr = mgmt->u.action.u.self_prot.variable; +	baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt; +	if (mgmt->u.action.u.self_prot.action_code == +						WLAN_SP_MESH_PEERING_CONFIRM) {  		baseaddr += 4;  		baselen += 4;  	}  	ieee802_11_parse_elems(baseaddr, len - baselen, &elems); -	if (!elems.peer_link) { +	if (!elems.peering) {  		mpl_dbg("Mesh plink: missing necessary peer link ie\n");  		return;  	} @@ -466,31 +462,34 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		return;  	} -	ftype = mgmt->u.action.u.plink_action.action_code; -	ie_len = elems.peer_link_len; -	if ((ftype == PLINK_OPEN && ie_len != 6) || -	    (ftype == PLINK_CONFIRM && ie_len != 8) || -	    (ftype == PLINK_CLOSE && ie_len != 8 && ie_len != 10)) { +	ftype = mgmt->u.action.u.self_prot.action_code; +	ie_len = elems.peering_len; +	if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) || +	    (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) || +	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6 +							&& ie_len != 8)) {  		mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",  		    ftype, ie_len);  		return;  	} -	if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) { +	if (ftype != WLAN_SP_MESH_PEERING_CLOSE && +				(!elems.mesh_id || !elems.mesh_config)) {  		mpl_dbg("Mesh plink: missing necessary ie\n");  		return;  	}  	/* Note the lines below are correct, the llid in the frame is the plid  	 * from the point of view of this host.  	 */ -	memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); -	if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 10)) -		memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); +	memcpy(&plid, PLINK_GET_LLID(elems.peering), 2); +	if (ftype == WLAN_SP_MESH_PEERING_CONFIRM || +	    (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) +		memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);  	rcu_read_lock();  	sta = sta_info_get(sdata, mgmt->sa); -	if (!sta && ftype != PLINK_OPEN) { +	if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {  		mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");  		rcu_read_unlock();  		return; @@ -509,30 +508,30 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  	/* Now we will figure out the appropriate event... */  	event = PLINK_UNDEFINED; -	if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { +	if (ftype != WLAN_SP_MESH_PEERING_CLOSE && +	    (!mesh_matches_local(&elems, sdata))) {  		matches_local = false;  		switch (ftype) { -		case PLINK_OPEN: +		case WLAN_SP_MESH_PEERING_OPEN:  			event = OPN_RJCT;  			break; -		case PLINK_CONFIRM: +		case WLAN_SP_MESH_PEERING_CONFIRM:  			event = CNF_RJCT;  			break; -		case PLINK_CLOSE: -			/* avoid warning */ +		default:  			break;  		}  	}  	if (!sta && !matches_local) {  		rcu_read_unlock(); -		reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); +		reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);  		llid = 0; -		mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, -				    plid, reason); +		mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, +				    mgmt->sa, llid, plid, reason);  		return;  	} else if (!sta) { -		/* ftype == PLINK_OPEN */ +		/* ftype == WLAN_SP_MESH_PEERING_OPEN */  		u32 rates;  		rcu_read_unlock(); @@ -557,21 +556,21 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  	} else if (matches_local) {  		spin_lock_bh(&sta->lock);  		switch (ftype) { -		case PLINK_OPEN: +		case WLAN_SP_MESH_PEERING_OPEN:  			if (!mesh_plink_free_count(sdata) ||  			    (sta->plid && sta->plid != plid))  				event = OPN_IGNR;  			else  				event = OPN_ACPT;  			break; -		case PLINK_CONFIRM: +		case WLAN_SP_MESH_PEERING_CONFIRM:  			if (!mesh_plink_free_count(sdata) ||  			    (sta->llid != llid || sta->plid != plid))  				event = CNF_IGNR;  			else  				event = CNF_ACPT;  			break; -		case PLINK_CLOSE: +		case WLAN_SP_MESH_PEERING_CLOSE:  			if (sta->plink_state == NL80211_PLINK_ESTAB)  				/* Do not check for llid or plid. This does not  				 * follow the standard but since multiple plinks @@ -620,10 +619,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			sta->llid = llid;  			mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, -					    0, 0); -			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, -					    llid, plid, 0); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_OPEN, +					    sta->sta.addr, llid, 0, 0); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CONFIRM, +					    sta->sta.addr, llid, plid, 0);  			break;  		default:  			spin_unlock_bh(&sta->lock); @@ -635,10 +636,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		switch (event) {  		case OPN_RJCT:  		case CNF_RJCT: -			reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); +			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);  		case CLS_ACPT:  			if (!reason) -				reason = cpu_to_le16(MESH_CLOSE_RCVD); +				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);  			sta->reason = reason;  			sta->plink_state = NL80211_PLINK_HOLDING;  			if (!mod_plink_timer(sta, @@ -647,8 +648,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			llid = sta->llid;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, -					    plid, reason); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CLOSE, +					    sta->sta.addr, llid, plid, reason);  			break;  		case OPN_ACPT:  			/* retry timer is left untouched */ @@ -656,8 +658,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			sta->plid = plid;  			llid = sta->llid;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, -					    plid, 0); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CONFIRM, +					    sta->sta.addr, llid, plid, 0);  			break;  		case CNF_ACPT:  			sta->plink_state = NL80211_PLINK_CNF_RCVD; @@ -677,10 +680,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		switch (event) {  		case OPN_RJCT:  		case CNF_RJCT: -			reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); +			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);  		case CLS_ACPT:  			if (!reason) -				reason = cpu_to_le16(MESH_CLOSE_RCVD); +				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);  			sta->reason = reason;  			sta->plink_state = NL80211_PLINK_HOLDING;  			if (!mod_plink_timer(sta, @@ -689,14 +692,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			llid = sta->llid;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, -					    plid, reason); +			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, +					    sta->sta.addr, llid, plid, reason);  			break;  		case OPN_ACPT:  			llid = sta->llid;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, -					    plid, 0); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CONFIRM, +					    sta->sta.addr, llid, plid, 0);  			break;  		case CNF_ACPT:  			del_timer(&sta->plink_timer); @@ -717,10 +721,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  		switch (event) {  		case OPN_RJCT:  		case CNF_RJCT: -			reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); +			reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);  		case CLS_ACPT:  			if (!reason) -				reason = cpu_to_le16(MESH_CLOSE_RCVD); +				reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);  			sta->reason = reason;  			sta->plink_state = NL80211_PLINK_HOLDING;  			if (!mod_plink_timer(sta, @@ -729,8 +733,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			llid = sta->llid;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, -					    plid, reason); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CLOSE, +					    sta->sta.addr, llid, plid, reason);  			break;  		case OPN_ACPT:  			del_timer(&sta->plink_timer); @@ -740,8 +745,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);  			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",  				sta->sta.addr); -			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, -					    plid, 0); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CONFIRM, +					    sta->sta.addr, llid, plid, 0);  			break;  		default:  			spin_unlock_bh(&sta->lock); @@ -752,7 +758,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  	case NL80211_PLINK_ESTAB:  		switch (event) {  		case CLS_ACPT: -			reason = cpu_to_le16(MESH_CLOSE_RCVD); +			reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);  			sta->reason = reason;  			deactivated = __mesh_plink_deactivate(sta);  			sta->plink_state = NL80211_PLINK_HOLDING; @@ -761,14 +767,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			spin_unlock_bh(&sta->lock);  			if (deactivated)  				ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); -			mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, -					    plid, reason); +			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, +					    sta->sta.addr, llid, plid, reason);  			break;  		case OPN_ACPT:  			llid = sta->llid;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, -					    plid, 0); +			mesh_plink_frame_tx(sdata, +					    WLAN_SP_MESH_PEERING_CONFIRM, +					    sta->sta.addr, llid, plid, 0);  			break;  		default:  			spin_unlock_bh(&sta->lock); @@ -790,8 +797,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m  			llid = sta->llid;  			reason = sta->reason;  			spin_unlock_bh(&sta->lock); -			mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, -					    llid, plid, reason); +			mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, +					    sta->sta.addr, llid, plid, reason);  			break;  		default:  			spin_unlock_bh(&sta->lock); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index d6470c7fd6c..60a6f273cd3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1482,10 +1482,14 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,  	ifmgd->aid = aid; -	sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); -	if (!sta) { -		printk(KERN_DEBUG "%s: failed to alloc STA entry for" -		       " the AP\n", sdata->name); +	mutex_lock(&sdata->local->sta_mtx); +	/* +	 * station info was already allocated and inserted before +	 * the association and should be available to us +	 */ +	sta = sta_info_get_rx(sdata, cbss->bssid); +	if (WARN_ON(!sta)) { +		mutex_unlock(&sdata->local->sta_mtx);  		return false;  	} @@ -1556,7 +1560,8 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,  	if (elems.wmm_param)  		set_sta_flags(sta, WLAN_STA_WME); -	err = sta_info_insert(sta); +	/* sta_info_reinsert will also unlock the mutex lock */ +	err = sta_info_reinsert(sta);  	sta = NULL;  	if (err) {  		printk(KERN_DEBUG "%s: failed to insert STA entry for" @@ -2429,6 +2434,32 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,  	return 0;  } +/* create and insert a dummy station entry */ +static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata, +				u8 *bssid) { +	struct sta_info *sta; +	int err; + +	sta = sta_info_alloc(sdata, bssid, GFP_KERNEL); +	if (!sta) { +		printk(KERN_DEBUG "%s: failed to alloc STA entry for" +			   " the AP\n", sdata->name); +		return -ENOMEM; +	} + +	sta->dummy = true; + +	err = sta_info_insert(sta); +	sta = NULL; +	if (err) { +		printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for" +		       " the AP (error %d)\n", sdata->name, err); +		return err; +	} + +	return 0; +} +  static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,  						  struct sk_buff *skb)  { @@ -2436,9 +2467,11 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,  	struct ieee80211_mgmt *mgmt;  	struct ieee80211_rx_status *rx_status;  	struct ieee802_11_elems elems; +	struct cfg80211_bss *cbss = wk->assoc.bss;  	u16 status;  	if (!skb) { +		sta_info_destroy_addr(wk->sdata, cbss->bssid);  		cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta);  		goto destroy;  	} @@ -2468,12 +2501,16 @@ static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk,  		if (!ieee80211_assoc_success(wk, mgmt, skb->len)) {  			mutex_unlock(&wk->sdata->u.mgd.mtx);  			/* oops -- internal error -- send timeout for now */ +			sta_info_destroy_addr(wk->sdata, cbss->bssid);  			cfg80211_send_assoc_timeout(wk->sdata->dev,  						    wk->filter_ta);  			return WORK_DONE_DESTROY;  		}  		mutex_unlock(&wk->sdata->u.mgd.mtx); +	} else { +		/* assoc failed - destroy the dummy station entry */ +		sta_info_destroy_addr(wk->sdata, cbss->bssid);  	}  	cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); @@ -2492,7 +2529,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,  	struct ieee80211_bss *bss = (void *)req->bss->priv;  	struct ieee80211_work *wk;  	const u8 *ssid; -	int i; +	int i, err;  	mutex_lock(&ifmgd->mtx);  	if (ifmgd->associated) { @@ -2517,6 +2554,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,  	if (!wk)  		return -ENOMEM; +	/* +	 * create a dummy station info entry in order +	 * to start accepting incoming EAPOL packets from the station +	 */ +	err = ieee80211_pre_assoc(sdata, req->bss->bssid); +	if (err) { +		kfree(wk); +		return err; +	} +  	ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N;  	ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index fe2c2a71779..f45fd2fedc2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -850,8 +850,21 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)  		      ieee80211_is_pspoll(hdr->frame_control)) &&  		     rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&  		     rx->sdata->vif.type != NL80211_IFTYPE_WDS && -		     (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) +		     (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { +		if (rx->sta && rx->sta->dummy && +		    ieee80211_is_data_present(hdr->frame_control)) { +			u16 ethertype; +			u8 *payload; + +			payload = rx->skb->data + +				ieee80211_hdrlen(hdr->frame_control); +			ethertype = (payload[6] << 8) | payload[7]; +			if (cpu_to_be16(ethertype) == +			    rx->sdata->control_port_protocol) +				return RX_CONTINUE; +		}  		return RX_DROP_MONITOR; +	}  	return RX_CONTINUE;  } @@ -2220,12 +2233,29 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  			goto handled;  		}  		break; +	case WLAN_CATEGORY_SELF_PROTECTED: +		switch (mgmt->u.action.u.self_prot.action_code) { +		case WLAN_SP_MESH_PEERING_OPEN: +		case WLAN_SP_MESH_PEERING_CLOSE: +		case WLAN_SP_MESH_PEERING_CONFIRM: +			if (!ieee80211_vif_is_mesh(&sdata->vif)) +				goto invalid; +			if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) +				/* userspace handles this frame */ +				break; +			goto queue; +		case WLAN_SP_MGK_INFORM: +		case WLAN_SP_MGK_ACK: +			if (!ieee80211_vif_is_mesh(&sdata->vif)) +				goto invalid; +			break; +		} +		break;  	case WLAN_CATEGORY_MESH_ACTION:  		if (!ieee80211_vif_is_mesh(&sdata->vif))  			break; -		goto queue; -	case WLAN_CATEGORY_MESH_PATH_SEL: -		if (!mesh_path_sel_is_hwmp(sdata)) +		if (mesh_action_is_path_sel(mgmt) && +		  (!mesh_path_sel_is_hwmp(sdata)))  			break;  		goto queue;  	} @@ -2686,7 +2716,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,  		} else if (!ieee80211_bssid_match(bssid,  					sdata->vif.addr)) {  			if (!(status->rx_flags & IEEE80211_RX_IN_SCAN) && -			    !ieee80211_is_beacon(hdr->frame_control)) +			    !ieee80211_is_beacon(hdr->frame_control) && +			    !(ieee80211_is_action(hdr->frame_control) && +			      sdata->vif.p2p))  				return 0;  			status->rx_flags &= ~IEEE80211_RX_RA_MATCH;  		} @@ -2791,7 +2823,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,  	if (ieee80211_is_data(fc)) {  		prev_sta = NULL; -		for_each_sta_info(local, hdr->addr2, sta, tmp) { +		for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {  			if (!prev_sta) {  				prev_sta = sta;  				continue; @@ -2835,7 +2867,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,  			continue;  		} -		rx.sta = sta_info_get_bss(prev, hdr->addr2); +		rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);  		rx.sdata = prev;  		ieee80211_prepare_and_rx_handle(&rx, skb, false); @@ -2843,7 +2875,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,  	}  	if (prev) { -		rx.sta = sta_info_get_bss(prev, hdr->addr2); +		rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);  		rx.sdata = prev;  		if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 0bdbf3b8f28..6bc17fb80ee 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -100,6 +100,27 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,  				    lockdep_is_held(&local->sta_lock) ||  				    lockdep_is_held(&local->sta_mtx));  	while (sta) { +		if (sta->sdata == sdata && !sta->dummy && +		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) +			break; +		sta = rcu_dereference_check(sta->hnext, +					    lockdep_is_held(&local->sta_lock) || +					    lockdep_is_held(&local->sta_mtx)); +	} +	return sta; +} + +/* get a station info entry even if it is a dummy station*/ +struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, +			      const u8 *addr) +{ +	struct ieee80211_local *local = sdata->local; +	struct sta_info *sta; + +	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], +				    lockdep_is_held(&local->sta_lock) || +				    lockdep_is_held(&local->sta_mtx)); +	while (sta) {  		if (sta->sdata == sdata &&  		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)  			break; @@ -126,6 +147,32 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,  	while (sta) {  		if ((sta->sdata == sdata ||  		     (sta->sdata->bss && sta->sdata->bss == sdata->bss)) && +		    !sta->dummy && +		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0) +			break; +		sta = rcu_dereference_check(sta->hnext, +					    lockdep_is_held(&local->sta_lock) || +					    lockdep_is_held(&local->sta_mtx)); +	} +	return sta; +} + +/* + * Get sta info either from the specified interface + * or from one of its vlans (including dummy stations) + */ +struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, +				  const u8 *addr) +{ +	struct ieee80211_local *local = sdata->local; +	struct sta_info *sta; + +	sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)], +				    lockdep_is_held(&local->sta_lock) || +				    lockdep_is_held(&local->sta_mtx)); +	while (sta) { +		if ((sta->sdata == sdata || +		     (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&  		    memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)  			break;  		sta = rcu_dereference_check(sta->hnext, @@ -280,7 +327,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,  	return sta;  } -static int sta_info_finish_insert(struct sta_info *sta, bool async) +static int sta_info_finish_insert(struct sta_info *sta, +				bool async, bool dummy_reinsert)  {  	struct ieee80211_local *local = sta->local;  	struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -290,51 +338,58 @@ static int sta_info_finish_insert(struct sta_info *sta, bool async)  	lockdep_assert_held(&local->sta_mtx); -	/* notify driver */ -	if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) -		sdata = container_of(sdata->bss, -				     struct ieee80211_sub_if_data, -				     u.ap); -	err = drv_sta_add(local, sdata, &sta->sta); -	if (err) { -		if (!async) -			return err; -		printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to driver (%d)" -				  " - keeping it anyway.\n", -		       sdata->name, sta->sta.addr, err); -	} else { -		sta->uploaded = true; +	if (!sta->dummy || dummy_reinsert) { +		/* notify driver */ +		if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) +			sdata = container_of(sdata->bss, +					     struct ieee80211_sub_if_data, +					     u.ap); +		err = drv_sta_add(local, sdata, &sta->sta); +		if (err) { +			if (!async) +				return err; +			printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to " +					  "driver (%d) - keeping it anyway.\n", +			       sdata->name, sta->sta.addr, err); +		} else { +			sta->uploaded = true;  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG -		if (async) -			wiphy_debug(local->hw.wiphy, -				    "Finished adding IBSS STA %pM\n", -				    sta->sta.addr); +			if (async) +				wiphy_debug(local->hw.wiphy, +					    "Finished adding IBSS STA %pM\n", +					    sta->sta.addr);  #endif +		} + +		sdata = sta->sdata;  	} -	sdata = sta->sdata; +	if (!dummy_reinsert) { +		if (!async) { +			local->num_sta++; +			local->sta_generation++; +			smp_mb(); -	if (!async) { -		local->num_sta++; -		local->sta_generation++; -		smp_mb(); +			/* make the station visible */ +			spin_lock_irqsave(&local->sta_lock, flags); +			sta_info_hash_add(local, sta); +			spin_unlock_irqrestore(&local->sta_lock, flags); +		} -		/* make the station visible */ -		spin_lock_irqsave(&local->sta_lock, flags); -		sta_info_hash_add(local, sta); -		spin_unlock_irqrestore(&local->sta_lock, flags); +		list_add(&sta->list, &local->sta_list); +	} else { +		sta->dummy = false;  	} -	list_add(&sta->list, &local->sta_list); - -	ieee80211_sta_debugfs_add(sta); -	rate_control_add_sta_debugfs(sta); - -	memset(&sinfo, 0, sizeof(sinfo)); -	sinfo.filled = 0; -	sinfo.generation = local->sta_generation; -	cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); +	if (!sta->dummy) { +		ieee80211_sta_debugfs_add(sta); +		rate_control_add_sta_debugfs(sta); +		memset(&sinfo, 0, sizeof(sinfo)); +		sinfo.filled = 0; +		sinfo.generation = local->sta_generation; +		cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL); +	}  	return 0;  } @@ -351,7 +406,7 @@ static void sta_info_finish_pending(struct ieee80211_local *local)  		list_del(&sta->list);  		spin_unlock_irqrestore(&local->sta_lock, flags); -		sta_info_finish_insert(sta, true); +		sta_info_finish_insert(sta, true, false);  		spin_lock_irqsave(&local->sta_lock, flags);  	} @@ -368,106 +423,117 @@ static void sta_info_finish_work(struct work_struct *work)  	mutex_unlock(&local->sta_mtx);  } -int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +static int sta_info_insert_check(struct sta_info *sta)  { -	struct ieee80211_local *local = sta->local;  	struct ieee80211_sub_if_data *sdata = sta->sdata; -	unsigned long flags; -	int err = 0;  	/*  	 * Can't be a WARN_ON because it can be triggered through a race:  	 * something inserts a STA (on one CPU) without holding the RTNL  	 * and another CPU turns off the net device.  	 */ -	if (unlikely(!ieee80211_sdata_running(sdata))) { -		err = -ENETDOWN; -		rcu_read_lock(); -		goto out_free; -	} +	if (unlikely(!ieee80211_sdata_running(sdata))) +		return -ENETDOWN;  	if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->vif.addr) == 0 || -		    is_multicast_ether_addr(sta->sta.addr))) { -		err = -EINVAL; +		    is_multicast_ether_addr(sta->sta.addr))) +		return -EINVAL; + +	return 0; +} + +static int sta_info_insert_ibss(struct sta_info *sta) __acquires(RCU) +{ +	struct ieee80211_local *local = sta->local; +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	unsigned long flags; + +	spin_lock_irqsave(&local->sta_lock, flags); +	/* check if STA exists already */ +	if (sta_info_get_bss_rx(sdata, sta->sta.addr)) { +		spin_unlock_irqrestore(&local->sta_lock, flags);  		rcu_read_lock(); -		goto out_free; +		return -EEXIST;  	} -	/* -	 * In ad-hoc mode, we sometimes need to insert stations -	 * from tasklet context from the RX path. To avoid races, -	 * always do so in that case -- see the comment below. -	 */ -	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { -		spin_lock_irqsave(&local->sta_lock, flags); -		/* check if STA exists already */ -		if (sta_info_get_bss(sdata, sta->sta.addr)) { -			spin_unlock_irqrestore(&local->sta_lock, flags); -			rcu_read_lock(); -			err = -EEXIST; -			goto out_free; -		} - -		local->num_sta++; -		local->sta_generation++; -		smp_mb(); -		sta_info_hash_add(local, sta); +	local->num_sta++; +	local->sta_generation++; +	smp_mb(); +	sta_info_hash_add(local, sta); -		list_add_tail(&sta->list, &local->sta_pending_list); +	list_add_tail(&sta->list, &local->sta_pending_list); -		rcu_read_lock(); -		spin_unlock_irqrestore(&local->sta_lock, flags); +	rcu_read_lock(); +	spin_unlock_irqrestore(&local->sta_lock, flags);  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG -		wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", -			    sta->sta.addr); +	wiphy_debug(local->hw.wiphy, "Added IBSS STA %pM\n", +			sta->sta.addr);  #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ -		ieee80211_queue_work(&local->hw, &local->sta_finish_work); +	ieee80211_queue_work(&local->hw, &local->sta_finish_work); -		return 0; -	} +	return 0; +} + +/* + * should be called with sta_mtx locked + * this function replaces the mutex lock + * with a RCU lock + */ +static int sta_info_insert_non_ibss(struct sta_info *sta) __acquires(RCU) +{ +	struct ieee80211_local *local = sta->local; +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	unsigned long flags; +	struct sta_info *exist_sta; +	bool dummy_reinsert = false; +	int err = 0; + +	lockdep_assert_held(&local->sta_mtx);  	/*  	 * On first glance, this will look racy, because the code -	 * below this point, which inserts a station with sleeping, +	 * in this function, which inserts a station with sleeping,  	 * unlocks the sta_lock between checking existence in the  	 * hash table and inserting into it.  	 *  	 * However, it is not racy against itself because it keeps -	 * the mutex locked. It still seems to race against the -	 * above code that atomically inserts the station... That, -	 * however, is not true because the above code can only -	 * be invoked for IBSS interfaces, and the below code will -	 * not be -- and the two do not race against each other as -	 * the hash table also keys off the interface. +	 * the mutex locked.  	 */ -	might_sleep(); - -	mutex_lock(&local->sta_mtx); -  	spin_lock_irqsave(&local->sta_lock, flags); -	/* check if STA exists already */ -	if (sta_info_get_bss(sdata, sta->sta.addr)) { -		spin_unlock_irqrestore(&local->sta_lock, flags); -		mutex_unlock(&local->sta_mtx); -		rcu_read_lock(); -		err = -EEXIST; -		goto out_free; +	/* +	 * check if STA exists already. +	 * only accept a scenario of a second call to sta_info_insert_non_ibss +	 * with a dummy station entry that was inserted earlier +	 * in that case - assume that the dummy station flag should +	 * be removed. +	 */ +	exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr); +	if (exist_sta) { +		if (exist_sta == sta && sta->dummy) { +			dummy_reinsert = true; +		} else { +			spin_unlock_irqrestore(&local->sta_lock, flags); +			mutex_unlock(&local->sta_mtx); +			rcu_read_lock(); +			return -EEXIST; +		}  	}  	spin_unlock_irqrestore(&local->sta_lock, flags); -	err = sta_info_finish_insert(sta, false); +	err = sta_info_finish_insert(sta, false, dummy_reinsert);  	if (err) {  		mutex_unlock(&local->sta_mtx);  		rcu_read_lock(); -		goto out_free; +		return err;  	}  #ifdef CONFIG_MAC80211_VERBOSE_DEBUG -	wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr); +	wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n", +			sta->dummy ? "dummy " : "", sta->sta.addr);  #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */  	/* move reference to rcu-protected */ @@ -478,6 +544,51 @@ int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)  		mesh_accept_plinks_update(sdata);  	return 0; +} + +int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU) +{ +	struct ieee80211_local *local = sta->local; +	struct ieee80211_sub_if_data *sdata = sta->sdata; +	int err = 0; + +	err = sta_info_insert_check(sta); +	if (err) { +		rcu_read_lock(); +		goto out_free; +	} + +	/* +	 * In ad-hoc mode, we sometimes need to insert stations +	 * from tasklet context from the RX path. To avoid races, +	 * always do so in that case -- see the comment below. +	 */ +	if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { +		err = sta_info_insert_ibss(sta); +		if (err) +			goto out_free; + +		return 0; +	} + +	/* +	 * It might seem that the function called below is in race against +	 * the function call above that atomically inserts the station... That, +	 * however, is not true because the above code can only +	 * be invoked for IBSS interfaces, and the below code will +	 * not be -- and the two do not race against each other as +	 * the hash table also keys off the interface. +	 */ + +	might_sleep(); + +	mutex_lock(&local->sta_mtx); + +	err = sta_info_insert_non_ibss(sta); +	if (err) +		goto out_free; + +	return 0;   out_free:  	BUG_ON(!err);  	__sta_info_free(local, sta); @@ -493,6 +604,25 @@ int sta_info_insert(struct sta_info *sta)  	return err;  } +/* Caller must hold sta->local->sta_mtx */ +int sta_info_reinsert(struct sta_info *sta) +{ +	struct ieee80211_local *local = sta->local; +	int err = 0; + +	err = sta_info_insert_check(sta); +	if (err) { +		mutex_unlock(&local->sta_mtx); +		return err; +	} + +	might_sleep(); + +	err = sta_info_insert_non_ibss(sta); +	rcu_read_unlock(); +	return err; +} +  static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)  {  	/* @@ -733,7 +863,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)  	int ret;  	mutex_lock(&sdata->local->sta_mtx); -	sta = sta_info_get(sdata, addr); +	sta = sta_info_get_rx(sdata, addr);  	ret = __sta_info_destroy(sta);  	mutex_unlock(&sdata->local->sta_mtx); @@ -747,7 +877,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,  	int ret;  	mutex_lock(&sdata->local->sta_mtx); -	sta = sta_info_get_bss(sdata, addr); +	sta = sta_info_get_bss_rx(sdata, addr);  	ret = __sta_info_destroy(sta);  	mutex_unlock(&sdata->local->sta_mtx); diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 28beb78e601..e9eb565506d 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -238,10 +238,12 @@ struct sta_ampdu_mlme {   * @plink_timer: peer link watch timer   * @plink_timer_was_running: used by suspend/resume to restore timers   * @debugfs: debug filesystem info - * @sta: station information we share with the driver   * @dead: set to true when sta is unlinked   * @uploaded: set to true when sta is uploaded to the driver   * @lost_packets: number of consecutive lost packets + * @dummy: indicate a dummy station created for receiving + *	EAP frames before association + * @sta: station information we share with the driver   */  struct sta_info {  	/* General information, mostly static */ @@ -336,6 +338,9 @@ struct sta_info {  	unsigned int lost_packets; +	/* should be right in front of sta to be in the same cache line */ +	bool dummy; +  	/* keep last! */  	struct ieee80211_sta sta;  }; @@ -436,9 +441,15 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)  struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,  			      const u8 *addr); +struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata, +			      const u8 *addr); +  struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,  				  const u8 *addr); +struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata, +				  const u8 *addr); +  static inline  void for_each_sta_info_type_check(struct ieee80211_local *local,  				  const u8 *addr, @@ -459,6 +470,22 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,  		_sta = nxt,						\  		nxt = _sta ? rcu_dereference(_sta->hnext) : NULL	\  	     )								\ +	/* run code only if address matches and it's not a dummy sta */	\ +	if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 &&		\ +		!_sta->dummy) + +#define for_each_sta_info_rx(local, _addr, _sta, nxt)			\ +	for (	/* initialise loop */					\ +		_sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\ +		nxt = _sta ? rcu_dereference(_sta->hnext) : NULL;	\ +		/* typecheck */						\ +		for_each_sta_info_type_check(local, (_addr), _sta, nxt),\ +		/* continue condition */				\ +		_sta;							\ +		/* advance loop */					\ +		_sta = nxt,						\ +		nxt = _sta ? rcu_dereference(_sta->hnext) : NULL	\ +	     )								\  	/* compare address and run code only if it matches */		\  	if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0) @@ -484,6 +511,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,  int sta_info_insert(struct sta_info *sta);  int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);  int sta_info_insert_atomic(struct sta_info *sta); +int sta_info_reinsert(struct sta_info *sta);  int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,  			  const u8 *addr); diff --git a/net/mac80211/status.c b/net/mac80211/status.c index a89cca3491b..e51bd2a1a07 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -187,6 +187,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)  	int rates_idx = -1;  	bool send_to_cooked;  	bool acked; +	struct ieee80211_bar *bar; +	u16 tid;  	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {  		if (info->status.rates[i].idx < 0) { @@ -243,6 +245,22 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)  					   tid, ssn);  		} +		if (!acked && ieee80211_is_back_req(fc)) { +			/* +			 * BAR failed, let's tear down the BA session as a +			 * last resort as some STAs (Intel 5100 on Windows) +			 * can get stuck when the BA window isn't flushed +			 * correctly. +			 */ +			bar = (struct ieee80211_bar *) skb->data; +			if (!(bar->control & IEEE80211_BAR_CTRL_MULTI_TID)) { +				tid = (bar->control & +				       IEEE80211_BAR_CTRL_TID_INFO_MASK) >> +				      IEEE80211_BAR_CTRL_TID_INFO_SHIFT; +				ieee80211_stop_tx_ba_session(&sta->sta, tid); +			} +		} +  		if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) {  			ieee80211_handle_filtered_frame(local, sta, skb);  			rcu_read_unlock(); diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 69fd494f32f..01072639666 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -2295,13 +2295,23 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,  		memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);  		mgmt->u.beacon.beacon_int =  			cpu_to_le16(sdata->vif.bss_conf.beacon_int); -		mgmt->u.beacon.capab_info = 0x0; /* 0x0 for MPs */ +		mgmt->u.beacon.capab_info |= cpu_to_le16( +			sdata->u.mesh.security ? WLAN_CAPABILITY_PRIVACY : 0);  		pos = skb_put(skb, 2);  		*pos++ = WLAN_EID_SSID;  		*pos++ = 0x0; -		mesh_mgmt_ies_add(skb, sdata); +		if (mesh_add_srates_ie(skb, sdata) || +		    mesh_add_ds_params_ie(skb, sdata) || +		    mesh_add_ext_srates_ie(skb, sdata) || +		    mesh_add_rsn_ie(skb, sdata) || +		    mesh_add_meshid_ie(skb, sdata) || +		    mesh_add_meshconf_ie(skb, sdata) || +		    mesh_add_vendor_ies(skb, sdata)) { +			pr_err("o11s: couldn't add ies!\n"); +			goto out; +		}  	} else {  		WARN_ON(1);  		goto out; diff --git a/net/nfc/core.c b/net/nfc/core.c index b6fd4e1f205..284e2f6a14f 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c @@ -322,7 +322,9 @@ struct nfc_dev *nfc_get_device(unsigned idx)   * @supported_protocols: NFC protocols supported by the device   */  struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, -					u32 supported_protocols) +					u32 supported_protocols, +					int tx_headroom, +					int tx_tailroom)  {  	static atomic_t dev_no = ATOMIC_INIT(0);  	struct nfc_dev *dev; @@ -345,6 +347,8 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,  	dev->ops = ops;  	dev->supported_protocols = supported_protocols; +	dev->tx_headroom = tx_headroom; +	dev->tx_tailroom = tx_tailroom;  	spin_lock_init(&dev->targets_lock);  	nfc_genl_data_init(&dev->genl_data); diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 52de84a5511..9fd652a5142 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -123,11 +123,7 @@ error:  static int rawsock_add_header(struct sk_buff *skb)  { - -	if (skb_cow_head(skb, 1)) -		return -ENOMEM; - -	*skb_push(skb, 1) = 0; +	*skb_push(skb, NFC_HEADER_SIZE) = 0;  	return 0;  } @@ -197,6 +193,7 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,  					struct msghdr *msg, size_t len)  {  	struct sock *sk = sock->sk; +	struct nfc_dev *dev = nfc_rawsock(sk)->dev;  	struct sk_buff *skb;  	int rc; @@ -208,11 +205,13 @@ static int rawsock_sendmsg(struct kiocb *iocb, struct socket *sock,  	if (sock->state != SS_CONNECTED)  		return -ENOTCONN; -	skb = sock_alloc_send_skb(sk, len, msg->msg_flags & MSG_DONTWAIT, -									&rc); +	skb = sock_alloc_send_skb(sk, len + dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE, +					msg->msg_flags & MSG_DONTWAIT, &rc);  	if (!skb)  		return rc; +	skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); +  	rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);  	if (rc < 0) {  		kfree_skb(skb); diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 5c116083eec..4423e64c7d9 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c @@ -12,6 +12,7 @@  #define MESH_HOLD_T 		100  #define MESH_PATH_TIMEOUT	5000 +#define MESH_RANN_INTERVAL      5000  /*   * Minimum interval between two consecutive PREQs originated by the same @@ -49,6 +50,8 @@ const struct mesh_config default_mesh_config = {  	.dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,  	.path_refresh_time = MESH_PATH_REFRESH_TIME,  	.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT, +	.dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL, +	.dot11MeshGateAnnouncementProtocol = false,  };  const struct mesh_setup default_mesh_setup = { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2aa6a218984..bddb5595c65 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2545,6 +2545,12 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)  	return err;  } +static struct nla_policy +nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { +	[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, +	[NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, +}; +  static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)  {  	struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2590,6 +2596,27 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)  	if (parse_station_flags(info, ¶ms))  		return -EINVAL; +	/* parse WME attributes if sta is WME capable */ +	if ((params.sta_flags_set & NL80211_STA_FLAG_WME) && +	    info->attrs[NL80211_ATTR_STA_WME]) { +		struct nlattr *tb[NL80211_STA_WME_MAX + 1]; +		struct nlattr *nla; + +		nla = info->attrs[NL80211_ATTR_STA_WME]; +		err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, +				       nl80211_sta_wme_policy); +		if (err) +			return err; + +		if (tb[NL80211_STA_WME_UAPSD_QUEUES]) +			params.uapsd_queues = +			     nla_get_u8(tb[NL80211_STA_WME_UAPSD_QUEUES]); + +		if (tb[NL80211_STA_WME_MAX_SP]) +			params.max_sp = +			     nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); +	} +  	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&  	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&  	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT && @@ -3035,6 +3062,10 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,  			cur_params.dot11MeshHWMPnetDiameterTraversalTime);  	NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,  			cur_params.dot11MeshHWMPRootMode); +	NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_RANN_INTERVAL, +			cur_params.dot11MeshHWMPRannInterval); +	NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, +			cur_params.dot11MeshGateAnnouncementProtocol);  	nla_nest_end(msg, pinfoattr);  	genlmsg_end(msg, hdr);  	return genlmsg_reply(msg, info); @@ -3062,6 +3093,9 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A  	[NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT] = { .type = NLA_U32 },  	[NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL] = { .type = NLA_U16 },  	[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 }, +	[NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 }, +	[NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 }, +	[NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },  };  static const struct nla_policy @@ -3140,6 +3174,14 @@ do {\  			dot11MeshHWMPRootMode, mask,  			NL80211_MESHCONF_HWMP_ROOTMODE,  			nla_get_u8); +	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, +			dot11MeshHWMPRannInterval, mask, +			NL80211_MESHCONF_HWMP_RANN_INTERVAL, +			nla_get_u16); +	FILL_IN_MESH_PARAM_IF_SET(tb, cfg, +			dot11MeshGateAnnouncementProtocol, mask, +			NL80211_MESHCONF_GATE_ANNOUNCEMENTS, +			nla_get_u8);  	if (mask_out)  		*mask_out = mask; diff --git a/net/wireless/util.c b/net/wireless/util.c index 844ddb0aa65..eef82f79554 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1158,9 +1158,9 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,  			if (elen >= sizeof(struct ieee80211_meshconf_ie))  				elems->mesh_config = (void *)pos;  			break; -		case WLAN_EID_PEER_LINK: -			elems->peer_link = pos; -			elems->peer_link_len = elen; +		case WLAN_EID_PEER_MGMT: +			elems->peering = pos; +			elems->peering_len = elen;  			break;  		case WLAN_EID_PREQ:  			elems->preq = pos;  |