]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/ath/ath9k/init.c
Merge branch 'master' into for-davem
[mv-sheeva.git] / drivers / net / wireless / ath / ath9k / init.c
index b78308c3c4d4ccdc29bcd0b73c03a06c95e3cff7..8c795488ebc307076f62ad4b47472aee4a4c2de8 100644 (file)
@@ -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) {