diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/init.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/init.c | 83 | 
1 files changed, 56 insertions, 27 deletions
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index b78308c3c4d..8c795488ebc 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -175,6 +175,18 @@ static const struct ath_ops ath9k_common_ops = {  	.write = ath9k_iowrite32,  }; +static int count_streams(unsigned int chainmask, int max) +{ +	int streams = 0; + +	do { +		if (++streams == max) +			break; +	} while ((chainmask = chainmask & (chainmask - 1))); + +	return streams; +} +  /**************************/  /*     Initialization     */  /**************************/ @@ -182,8 +194,10 @@ static const struct ath_ops ath9k_common_ops = {  static void setup_ht_cap(struct ath_softc *sc,  			 struct ieee80211_sta_ht_cap *ht_info)  { -	struct ath_common *common = ath9k_hw_common(sc->sc_ah); +	struct ath_hw *ah = sc->sc_ah; +	struct ath_common *common = ath9k_hw_common(ah);  	u8 tx_streams, rx_streams; +	int i, max_streams;  	ht_info->ht_supported = true;  	ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | @@ -191,28 +205,40 @@ static void setup_ht_cap(struct ath_softc *sc,  		       IEEE80211_HT_CAP_SGI_40 |  		       IEEE80211_HT_CAP_DSSSCCK40; +	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC) +		ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; +  	ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;  	ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; +	if (AR_SREV_9300_20_OR_LATER(ah)) +		max_streams = 3; +	else +		max_streams = 2; + +	if (AR_SREV_9280_10_OR_LATER(ah)) { +		if (max_streams >= 2) +			ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; +		ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); +	} +  	/* set up supported mcs set */  	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); -	tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ? -		     1 : 2; -	rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ? -		     1 : 2; +	tx_streams = count_streams(common->tx_chainmask, max_streams); +	rx_streams = count_streams(common->rx_chainmask, max_streams); + +	ath_print(common, ATH_DBG_CONFIG, +		  "TX streams %d, RX streams: %d\n", +		  tx_streams, rx_streams);  	if (tx_streams != rx_streams) { -		ath_print(common, ATH_DBG_CONFIG, -			  "TX streams %d, RX streams: %d\n", -			  tx_streams, rx_streams);  		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;  		ht_info->mcs.tx_params |= ((tx_streams - 1) <<  				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);  	} -	ht_info->mcs.rx_mask[0] = 0xff; -	if (rx_streams >= 2) -		ht_info->mcs.rx_mask[1] = 0xff; +	for (i = 0; i < rx_streams; i++) +		ht_info->mcs.rx_mask[i] = 0xff;  	ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;  } @@ -235,31 +261,37 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,  */  int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		      struct list_head *head, const char *name, -		      int nbuf, int ndesc) +		      int nbuf, int ndesc, bool is_tx)  {  #define	DS2PHYS(_dd, _ds)						\  	((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))  #define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)  #define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)  	struct ath_common *common = ath9k_hw_common(sc->sc_ah); -	struct ath_desc *ds; +	u8 *ds;  	struct ath_buf *bf; -	int i, bsize, error; +	int i, bsize, error, desc_len;  	ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",  		  name, nbuf, ndesc);  	INIT_LIST_HEAD(head); + +	if (is_tx) +		desc_len = sc->sc_ah->caps.tx_desc_len; +	else +		desc_len = sizeof(struct ath_desc); +  	/* ath_desc must be a multiple of DWORDs */ -	if ((sizeof(struct ath_desc) % 4) != 0) { +	if ((desc_len % 4) != 0) {  		ath_print(common, ATH_DBG_FATAL,  			  "ath_desc not DWORD aligned\n"); -		BUG_ON((sizeof(struct ath_desc) % 4) != 0); +		BUG_ON((desc_len % 4) != 0);  		error = -ENOMEM;  		goto fail;  	} -	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; +	dd->dd_desc_len = desc_len * nbuf * ndesc;  	/*  	 * Need additional DMA memory because we can't use @@ -272,7 +304,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		u32 dma_len;  		while (ndesc_skipped) { -			dma_len = ndesc_skipped * sizeof(struct ath_desc); +			dma_len = ndesc_skipped * desc_len;  			dd->dd_desc_len += dma_len;  			ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); @@ -286,7 +318,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  		error = -ENOMEM;  		goto fail;  	} -	ds = dd->dd_desc; +	ds = (u8 *) dd->dd_desc;  	ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",  		  name, ds, (u32) dd->dd_desc_len,  		  ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); @@ -300,7 +332,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  	}  	dd->dd_bufptr = bf; -	for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { +	for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {  		bf->bf_desc = ds;  		bf->bf_daddr = DS2PHYS(dd, ds); @@ -316,7 +348,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,  				       ((caddr_t) dd->dd_desc +  					dd->dd_desc_len)); -				ds += ndesc; +				ds += (desc_len * ndesc);  				bf->bf_desc = ds;  				bf->bf_daddr = DS2PHYS(dd, ds);  			} @@ -514,7 +546,7 @@ static void ath9k_init_misc(struct ath_softc *sc)  	common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;  	common->rx_chainmask = sc->sc_ah->caps.rx_chainmask; -	ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); +	ath9k_hw_set_diversity(sc->sc_ah, true);  	sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);  	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) @@ -568,13 +600,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,  	ath_read_cachesize(common, &csz);  	common->cachelsz = csz << 2; /* convert to bytes */ +	/* Initializes the hardware for all supported chipsets */  	ret = ath9k_hw_init(ah); -	if (ret) { -		ath_print(common, ATH_DBG_FATAL, -			  "Unable to initialize hardware; " -			  "initialization status: %d\n", ret); +	if (ret)  		goto err_hw; -	}  	ret = ath9k_init_debug(ah);  	if (ret) {  |