wil6210: set dma mask to reflect device capability
authorHamad Kadmany <qca_hkadmany@qca.qualcomm.com>
Wed, 8 Mar 2017 11:52:10 +0000 (13:52 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Thu, 9 Mar 2017 08:04:00 +0000 (10:04 +0200)
device supports 48bit addresses, reflect that by
setting the dma mask accordingly.

Signed-off-by: Hamad Kadmany <qca_hkadmany@qca.qualcomm.com>
Signed-off-by: Maya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/wil6210/pcie_bus.c
drivers/net/wireless/ath/wil6210/pmc.c
drivers/net/wireless/ath/wil6210/txrx.c
drivers/net/wireless/ath/wil6210/wil6210.h

index 874c787727fe5a013acfc558a7804679ee5aa39e..b38515fc7ce7a5eea8387c143e415a8a3f2f06ef 100644 (file)
@@ -211,6 +211,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                dev_err(dev, "wil_if_alloc failed: %d\n", rc);
                return rc;
        }
+
        wil->pdev = pdev;
        pci_set_drvdata(pdev, wil);
        /* rollback to if_free */
@@ -224,6 +225,21 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        }
        /* rollback to err_plat */
 
+       /* device supports 48bit addresses */
+       rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+       if (rc) {
+               dev_err(dev, "dma_set_mask_and_coherent(48) failed: %d\n", rc);
+               rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+               if (rc) {
+                       dev_err(dev,
+                               "dma_set_mask_and_coherent(32) failed: %d\n",
+                               rc);
+                       goto err_plat;
+               }
+       } else {
+               wil->use_extended_dma_addr = 1;
+       }
+
        rc = pci_enable_device(pdev);
        if (rc) {
                wil_err(wil,
index 3ff4f4ce9feffe24c46754c258c3deb811e69056..b067fdf086d41cd44c3e3482b37f7d2b2f21c310 100644 (file)
@@ -107,13 +107,28 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
 
        /* Allocate pring buffer and descriptors.
         * vring->va should be aligned on its size rounded up to power of 2
-        * This is granted by the dma_alloc_coherent
+        * This is granted by the dma_alloc_coherent.
+        *
+        * HW has limitation that all vrings addresses must share the same
+        * upper 16 msb bits part of 48 bits address. To workaround that,
+        * if we are using 48 bit addresses switch to 32 bit allocation
+        * before allocating vring memory.
+        *
+        * There's no check for the return value of dma_set_mask_and_coherent,
+        * since we assume if we were able to set the mask during
+        * initialization in this system it will not fail if we set it again
         */
+       if (wil->use_extended_dma_addr)
+               dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+
        pmc->pring_va = dma_alloc_coherent(dev,
                        sizeof(struct vring_tx_desc) * num_descriptors,
                        &pmc->pring_pa,
                        GFP_KERNEL);
 
+       if (wil->use_extended_dma_addr)
+               dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+
        wil_dbg_misc(wil,
                     "pmc_alloc: allocated pring %p => %pad. %zd x %d = total %zd bytes\n",
                     pmc->pring_va, &pmc->pring_pa,
index 072182e527e69afe888b4ef54789495ba37d4c6a..67f50ae17cd3fdb8d5c5ff816e994e41f846c262 100644 (file)
@@ -123,15 +123,32 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
                vring->va = NULL;
                return -ENOMEM;
        }
+
        /* vring->va should be aligned on its size rounded up to power of 2
-        * This is granted by the dma_alloc_coherent
+        * This is granted by the dma_alloc_coherent.
+        *
+        * HW has limitation that all vrings addresses must share the same
+        * upper 16 msb bits part of 48 bits address. To workaround that,
+        * if we are using 48 bit addresses switch to 32 bit allocation
+        * before allocating vring memory.
+        *
+        * There's no check for the return value of dma_set_mask_and_coherent,
+        * since we assume if we were able to set the mask during
+        * initialization in this system it will not fail if we set it again
         */
+       if (wil->use_extended_dma_addr)
+               dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+
        vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL);
        if (!vring->va) {
                kfree(vring->ctx);
                vring->ctx = NULL;
                return -ENOMEM;
        }
+
+       if (wil->use_extended_dma_addr)
+               dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+
        /* initially, all descriptors are SW owned
         * For Tx and Rx, ownership bit is at the same location, thus
         * we can use any
index 085a2dbfa21d615887c458e6385ac06cae8dcca3..ea1e5b34e011fb03c5a8287d2df57fda193a8e2c 100644 (file)
@@ -657,6 +657,7 @@ struct wil6210_priv {
        u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
        struct wil_sta_info sta[WIL6210_MAX_CID];
        int bcast_vring;
+       bool use_extended_dma_addr; /* indicates whether we are using 48 bits */
        /* scan */
        struct cfg80211_scan_request *scan_request;