From d70357d56942fa587e39505547cb69e10a8d59a0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:06 -0400 Subject: ath9k_hw: start building an abstraction layer for hardware routines ath9k supports the AR5008, AR9001 and AR9002 family of Atheros chipsets, all 802.11n. The new breed of 802.11n chips, the AR9003 family will be supported as well soon. To help with its support we're going to add a few callbacks for hardware routines which differ considerably instead of adding branch checks for the revision at runtime. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/init.c') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 6063f5463708..62682cc2e216 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -566,13 +566,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) { -- cgit v1.2.3 From 8fe6536850ae49609704a263cbc7542133536922 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:38:14 -0400 Subject: ath9k_hw: Move some RF ops to the private callbacks The PHY split is easier done in a few steps. First move the RF ops to the private ops and rename them accordingly. We split PHY stuff up first for the AR5008 and AR9002 families. There are some callbacks that AR9002 share with the AR5008 familiy so we set those first, if AR9002 has some different callbacks it will override them upon hardware init. Signed-off-by: Felix Fietkau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath/ath9k/init.c') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 62682cc2e216..1956c611503e 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -512,7 +512,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) -- cgit v1.2.3 From 4adfcdedd4e0c05c1b659da5f2b8bc4e2d4a86df Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 15 Apr 2010 17:39:33 -0400 Subject: ath9k: Setup appropriate tx desc for regular dma and edma Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/init.c') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 1956c611503e..58a87f7931df 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -233,31 +233,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 @@ -270,7 +276,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); @@ -284,7 +290,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); @@ -298,7 +304,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); @@ -314,7 +320,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); } -- cgit v1.2.3 From b0a3344834fcaf30e472ccc661c8842281453402 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 15 Apr 2010 17:39:39 -0400 Subject: ath9k: add LDPC support LDPC is enabled by the rate control if the its determined that the target peer supports LDPC. We would have already intersected the HT capabilities so if our peer supports LDPC so do we. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k/init.c') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 58a87f7931df..5adc2e335cff 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -189,6 +189,9 @@ 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; -- cgit v1.2.3 From 3bb065a7420c90421d6bbea5f7cffe36bd79a048 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:34 +0200 Subject: ath9k: initialize the number of tx/rx streams correctly AR9300 based hardware can 3x3 MCS rates, this should be set in the HT capabilities. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 39 +++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/ath/ath9k/init.c') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 5adc2e335cff..351538cd8e4c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -173,6 +173,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 */ /**************************/ @@ -180,8 +192,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 | @@ -195,25 +209,28 @@ static void setup_ht_cap(struct ath_softc *sc, 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; + /* 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; } -- cgit v1.2.3 From 074a8c0db255e79960593122b5458c9a9c0551fa Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 19 Apr 2010 19:57:36 +0200 Subject: ath9k: add support for Tx and Rx STBC Supported only for single stream rates by the hardware Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/init.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/net/wireless/ath/ath9k/init.c') diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 351538cd8e4c..70e5aa415c89 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -214,6 +214,12 @@ static void setup_ht_cap(struct ath_softc *sc, 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 = count_streams(common->tx_chainmask, max_streams); -- cgit v1.2.3