ath10k: print errcode when CE ring setup fails
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / ce.c
index 61a8ac7..1a702e1 100644 (file)
@@ -76,36 +76,7 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
                                                      u32 ce_ctrl_addr,
                                                      unsigned int n)
 {
-       struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-       void __iomem *indicator_addr;
-
-       if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) {
-               ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
-               return;
-       }
-
-       /* workaround for QCA988x_1.0 HW CE */
-       indicator_addr = ar_pci->mem + ce_ctrl_addr + DST_WATERMARK_ADDRESS;
-
-       if (ce_ctrl_addr == ath10k_ce_base_address(CDC_WAR_DATA_CE)) {
-               iowrite32((CDC_WAR_MAGIC_STR | n), indicator_addr);
-       } else {
-               unsigned long irq_flags;
-               local_irq_save(irq_flags);
-               iowrite32(1, indicator_addr);
-
-               /*
-                * PCIE write waits for ACK in IPQ8K, there is no
-                * need to read back value.
-                */
-               (void)ioread32(indicator_addr);
-               (void)ioread32(indicator_addr); /* conservative */
-
-               ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
-
-               iowrite32(0, indicator_addr);
-               local_irq_restore(irq_flags);
-       }
+       ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
 }
 
 static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar,
@@ -637,6 +608,7 @@ static int ath10k_ce_completed_send_next_nolock(struct ce_state *ce_state,
                ath10k_pci_wake(ar);
                src_ring->hw_index =
                        ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
+               src_ring->hw_index &= nentries_mask;
                ath10k_pci_sleep(ar);
        }
        read_index = src_ring->hw_index;
@@ -950,10 +922,12 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
 
        ath10k_pci_wake(ar);
        src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
+       src_ring->sw_index &= src_ring->nentries_mask;
        src_ring->hw_index = src_ring->sw_index;
 
        src_ring->write_index =
                ath10k_ce_src_ring_write_index_get(ar, ctrl_addr);
+       src_ring->write_index &= src_ring->nentries_mask;
        ath10k_pci_sleep(ar);
 
        src_ring->per_transfer_context = (void **)ptr;
@@ -967,6 +941,12 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
                                     (nentries * sizeof(struct ce_desc) +
                                      CE_DESC_RING_ALIGN),
                                     &base_addr);
+       if (!src_ring->base_addr_owner_space_unaligned) {
+               kfree(ce_state->src_ring);
+               ce_state->src_ring = NULL;
+               return -ENOMEM;
+       }
+
        src_ring->base_addr_ce_space_unaligned = base_addr;
 
        src_ring->base_addr_owner_space = PTR_ALIGN(
@@ -983,6 +963,16 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
        src_ring->shadow_base_unaligned =
                kmalloc((nentries * sizeof(struct ce_desc) +
                         CE_DESC_RING_ALIGN), GFP_KERNEL);
+       if (!src_ring->shadow_base_unaligned) {
+               pci_free_consistent(ar_pci->pdev,
+                                   (nentries * sizeof(struct ce_desc) +
+                                    CE_DESC_RING_ALIGN),
+                                   src_ring->base_addr_owner_space,
+                                   src_ring->base_addr_ce_space);
+               kfree(ce_state->src_ring);
+               ce_state->src_ring = NULL;
+               return -ENOMEM;
+       }
 
        src_ring->shadow_base = PTR_ALIGN(
                        src_ring->shadow_base_unaligned,
@@ -1035,8 +1025,10 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
 
        ath10k_pci_wake(ar);
        dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
+       dest_ring->sw_index &= dest_ring->nentries_mask;
        dest_ring->write_index =
                ath10k_ce_dest_ring_write_index_get(ar, ctrl_addr);
+       dest_ring->write_index &= dest_ring->nentries_mask;
        ath10k_pci_sleep(ar);
 
        dest_ring->per_transfer_context = (void **)ptr;
@@ -1050,6 +1042,12 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
                                     (nentries * sizeof(struct ce_desc) +
                                      CE_DESC_RING_ALIGN),
                                     &base_addr);
+       if (!dest_ring->base_addr_owner_space_unaligned) {
+               kfree(ce_state->dest_ring);
+               ce_state->dest_ring = NULL;
+               return -ENOMEM;
+       }
+
        dest_ring->base_addr_ce_space_unaligned = base_addr;
 
        /*
@@ -1123,6 +1121,7 @@ struct ce_state *ath10k_ce_init(struct ath10k *ar,
 {
        struct ce_state *ce_state;
        u32 ctrl_addr = ath10k_ce_base_address(ce_id);
+       int ret;
 
        ce_state = ath10k_ce_init_state(ar, ce_id, attr);
        if (!ce_state) {
@@ -1131,18 +1130,20 @@ struct ce_state *ath10k_ce_init(struct ath10k *ar,
        }
 
        if (attr->src_nentries) {
-               if (ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr)) {
-                       ath10k_err("Failed to initialize CE src ring for ID: %d\n",
-                                  ce_id);
+               ret = ath10k_ce_init_src_ring(ar, ce_id, ce_state, attr);
+               if (ret) {
+                       ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n",
+                                  ce_id, ret);
                        ath10k_ce_deinit(ce_state);
                        return NULL;
                }
        }
 
        if (attr->dest_nentries) {
-               if (ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr)) {
-                       ath10k_err("Failed to initialize CE dest ring for ID: %d\n",
-                                  ce_id);
+               ret = ath10k_ce_init_dest_ring(ar, ce_id, ce_state, attr);
+               if (ret) {
+                       ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n",
+                                  ce_id, ret);
                        ath10k_ce_deinit(ce_state);
                        return NULL;
                }