ath11k: configure copy engine msi address in CE srng
authorGovind Singh <govinds@codeaurora.org>
Fri, 14 Aug 2020 07:10:24 +0000 (10:10 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Mon, 17 Aug 2020 10:18:21 +0000 (13:18 +0300)
Fill msi base address and msi data to be programmed in CE srang.
This is used by the srng to generate the msi interrupt.

Needed for PCI support.

Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.1.0.1-01238-QCAHKSWPL_SILICONZ-2

Signed-off-by: Govind Singh <govinds@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1597389030-13887-6-git-send-email-kvalo@codeaurora.org
drivers/net/wireless/ath/ath11k/ce.c
drivers/net/wireless/ath/ath11k/hal.h
drivers/net/wireless/ath/ath11k/hif.h
drivers/net/wireless/ath/ath11k/pci.c

index 2fff171b35f8152b69eeb95099796d678a3657df..a457fe7f7049a436ae02adeae7e8824759e63670 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "dp_rx.h"
 #include "debug.h"
+#include "hif.h"
 
 static const struct ce_attr host_ce_config_wlan[] = {
        /* CE0: host->target HTC control and raw streams */
@@ -352,6 +353,31 @@ static void ath11k_ce_send_done_cb(struct ath11k_ce_pipe *pipe)
        }
 }
 
+static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_id,
+                                                struct hal_srng_params *ring_params)
+{
+       u32 msi_data_start;
+       u32 msi_data_count;
+       u32 msi_irq_start;
+       u32 addr_lo;
+       u32 addr_hi;
+       int ret;
+
+       ret = ath11k_get_user_msi_vector(ab, "CE",
+                                        &msi_data_count, &msi_data_start,
+                                        &msi_irq_start);
+
+       if (ret)
+               return;
+
+       ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
+
+       ring_params->msi_addr = addr_lo;
+       ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
+       ring_params->msi_data = (ce_id % msi_data_count) + msi_data_start;
+       ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
+}
+
 static int ath11k_ce_init_ring(struct ath11k_base *ab,
                               struct ath11k_ce_ring *ce_ring,
                               int ce_id, enum hal_ring_type type)
@@ -395,6 +421,10 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab,
                            ret, ce_id);
                return ret;
        }
+
+       if (!(CE_ATTR_DIS_INTR & host_ce_config_wlan[ce_id].flags))
+               ath11k_ce_srng_msi_ring_params_setup(ab, ce_id, &params);
+
        ce_ring->hal_ring_id = ret;
 
        return 0;
index 780a3e11b6098cf41f218d7fd3eca870d208a630..6d9a6938870c2cc4449b40a2df884414a7f8e903 100644 (file)
@@ -458,6 +458,8 @@ struct hal_srng_params {
        u32 flags;
        u32 max_buffer_len;
        u32 low_threshold;
+       dma_addr_t msi_addr;
+       u32 msi_data;
 
        /* Add more params as needed */
 };
index 48ee55cebc811f37a01ccd8890a66a16368d3273..dbe5568916e87b042cbcc20b0e9ca6db0675303f 100644 (file)
@@ -19,6 +19,11 @@ struct ath11k_hif_ops {
        void (*power_down)(struct ath11k_base *sc);
        int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id,
                                   u8 *ul_pipe, u8 *dl_pipe);
+       int (*get_user_msi_vector)(struct ath11k_base *ab, char *user_name,
+                                  int *num_vectors, u32 *user_base_data,
+                                  u32 *base_vector);
+       void (*get_msi_address)(struct ath11k_base *ab, u32 *msi_addr_lo,
+                               u32 *msi_addr_hi);
 };
 
 static inline int ath11k_hif_start(struct ath11k_base *sc)
@@ -66,4 +71,25 @@ static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 ser
 {
        return sc->hif.ops->map_service_to_pipe(sc, service_id, ul_pipe, dl_pipe);
 }
+
+static inline int ath11k_get_user_msi_vector(struct ath11k_base *ab, char *user_name,
+                                            int *num_vectors, u32 *user_base_data,
+                                            u32 *base_vector)
+{
+       if (!ab->hif.ops->get_user_msi_vector)
+               return -EOPNOTSUPP;
+
+       return ab->hif.ops->get_user_msi_vector(ab, user_name, num_vectors,
+                                               user_base_data,
+                                               base_vector);
+}
+
+static inline void ath11k_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
+                                         u32 *msi_addr_hi)
+{
+       if (!ab->hif.ops->get_msi_address)
+               return;
+
+       ab->hif.ops->get_msi_address(ab, msi_addr_lo, msi_addr_hi);
+}
 #endif /* _HIF_H_ */
index 10c281ece3d43227147dba395645cbdd99e92955..af08f0542867cbe1eb975cd4216f3d55fe53cbc0 100644 (file)
@@ -339,6 +339,18 @@ int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
        return pci_irq_vector(pci_dev, vector);
 }
 
+static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
+                                      u32 *msi_addr_hi)
+{
+       struct pci_dev *pci_dev = to_pci_dev(ab->dev);
+
+       pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
+                             msi_addr_lo);
+
+       pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
+                             msi_addr_hi);
+}
+
 int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
                                       int *num_vectors, u32 *user_base_data,
                                       u32 *base_vector)
@@ -366,6 +378,17 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
        return -EINVAL;
 }
 
+static int ath11k_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
+                                         int *num_vectors, u32 *user_base_data,
+                                         u32 *base_vector)
+{
+       struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
+
+       return ath11k_pci_get_user_msi_assignment(ab_pci, user_name,
+                                                 num_vectors, user_base_data,
+                                                 base_vector);
+}
+
 static void ath11k_pci_free_irq(struct ath11k_base *ab)
 {
        int i, irq_idx;
@@ -634,6 +657,8 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
        .write32 = ath11k_pci_write32,
        .power_down = ath11k_pci_power_down,
        .power_up = ath11k_pci_power_up,
+       .get_msi_address =  ath11k_pci_get_msi_address,
+       .get_user_msi_vector = ath11k_get_user_msi_assignment,
 };
 
 static int ath11k_pci_probe(struct pci_dev *pdev,