]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ath11k: add CE interrupt support for QCN9074
authorKarthikeyan Periyasamy <periyasa@codeaurora.org>
Tue, 16 Feb 2021 07:16:23 +0000 (09:16 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 17 Feb 2021 09:32:58 +0000 (11:32 +0200)
Define host CE configuration for QCN9074 since the max CE count is six.
Available MSI interrupt is five so cannot able to map the ce_id directly
for the msi_data_idx. Added get_ce_msi_idx ops in ath11k_hif_ops to get
the CE MSI idx which is used to initialize the CE ring.

Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.4.0.1.r2-00012-QCAHKSWPL_SILICONZ-1

Signed-off-by: Karthikeyan Periyasamy <periyasa@codeaurora.org>
Signed-off-by: Anilkumar Kolli <akolli@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/1612946530-28504-10-git-send-email-akolli@codeaurora.org
drivers/net/wireless/ath/ath11k/ce.c
drivers/net/wireless/ath/ath11k/ce.h
drivers/net/wireless/ath/ath11k/core.c
drivers/net/wireless/ath/ath11k/core.h
drivers/net/wireless/ath/ath11k/hif.h
drivers/net/wireless/ath/ath11k/hw.c
drivers/net/wireless/ath/ath11k/pci.c

index 987c650102720220034f750a9297e6091348fbe1..de8b632b058ce295a1a5d0d14f6ceddf66db32bc 100644 (file)
@@ -187,6 +187,59 @@ const struct ce_attr ath11k_host_ce_config_qca6390[] = {
 
 };
 
+const struct ce_attr ath11k_host_ce_config_qcn9074[] = {
+       /* CE0: host->target HTC control and raw streams */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 16,
+               .src_sz_max = 2048,
+               .dest_nentries = 0,
+       },
+
+       /* CE1: target->host HTT + HTC control */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 2048,
+               .dest_nentries = 512,
+               .recv_cb = ath11k_htc_rx_completion_handler,
+       },
+
+       /* CE2: target->host WMI */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 2048,
+               .dest_nentries = 32,
+               .recv_cb = ath11k_htc_rx_completion_handler,
+       },
+
+       /* CE3: host->target WMI (mac0) */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 32,
+               .src_sz_max = 2048,
+               .dest_nentries = 0,
+       },
+
+       /* CE4: host->target HTT */
+       {
+               .flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
+               .src_nentries = 2048,
+               .src_sz_max = 256,
+               .dest_nentries = 0,
+       },
+
+       /* CE5: target->host pktlog */
+       {
+               .flags = CE_ATTR_FLAGS,
+               .src_nentries = 0,
+               .src_sz_max = 2048,
+               .dest_nentries = 512,
+               .recv_cb = ath11k_dp_htt_htc_t2h_msg_handler,
+       },
+};
+
 static bool ath11k_ce_need_shadow_fix(int ce_id)
 {
        /* only ce4 needs shadow workaroud*/
@@ -455,7 +508,7 @@ static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_
                                                 struct hal_srng_params *ring_params)
 {
        u32 msi_data_start;
-       u32 msi_data_count;
+       u32 msi_data_count, msi_data_idx;
        u32 msi_irq_start;
        u32 addr_lo;
        u32 addr_hi;
@@ -469,10 +522,11 @@ static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_
                return;
 
        ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
+       ath11k_get_ce_msi_idx(ab, ce_id, &msi_data_idx);
 
        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->msi_data = (msi_data_idx % msi_data_count) + msi_data_start;
        ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
 }
 
index d6eeef919349c0de2c54fdbf4d37eb027030e007..713f766cac223d3c852fbbc48fd150896414b275 100644 (file)
@@ -173,6 +173,7 @@ struct ath11k_ce {
 
 extern const struct ce_attr ath11k_host_ce_config_ipq8074[];
 extern const struct ce_attr ath11k_host_ce_config_qca6390[];
+extern const struct ce_attr ath11k_host_ce_config_qcn9074[];
 
 void ath11k_ce_cleanup_pipes(struct ath11k_base *ab);
 void ath11k_ce_rx_replenish_retry(struct timer_list *t);
index a17812270c073dd42ca30774ca3018e9f33b403e..82b5e8c41f8fae19e2e4482daf54b158e1cf7ec7 100644 (file)
@@ -164,6 +164,12 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
                .hw_ops = &qcn9074_ops,
                .internal_sleep_clock = false,
                .regs = &qcn9074_regs,
+               .host_ce_config = ath11k_host_ce_config_qcn9074,
+               .ce_count = 6,
+               .target_ce_config = ath11k_target_ce_config_wlan_qcn9074,
+               .target_ce_count = 9,
+               .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qcn9074,
+               .svc_to_ce_map_len = 18,
                .rxdma1_enable = true,
                .num_rxmda_per_pdev = 1,
                .rx_mac_buf_ring = false,
index 912294f7657cc59e9c387d277bc37470ab894dc8..9cdc4f0b069090432512ebd373c9c09d84568a75 100644 (file)
@@ -878,6 +878,8 @@ extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018
 extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[];
 extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[];
 
+extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qcn9074[];
+extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qcn9074[];
 int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab);
 int ath11k_core_pre_init(struct ath11k_base *ab);
 int ath11k_core_init(struct ath11k_base *ath11k);
index 6285c52afc443997dfafad625ad01ddf01dc76d7..e9366f786fbb6ab059d910efdf72c63a8b36bbed 100644 (file)
@@ -28,6 +28,7 @@ struct ath11k_hif_ops {
                                u32 *msi_addr_hi);
        void (*ce_irq_enable)(struct ath11k_base *ab);
        void (*ce_irq_disable)(struct ath11k_base *ab);
+       void (*get_ce_msi_idx)(struct ath11k_base *ab, u32 ce_id, u32 *msi_idx);
 };
 
 static inline void ath11k_hif_ce_irq_enable(struct ath11k_base *ab)
@@ -124,4 +125,13 @@ static inline void ath11k_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_
 
        ab->hif.ops->get_msi_address(ab, msi_addr_lo, msi_addr_hi);
 }
+
+static inline void ath11k_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
+                                        u32 *msi_data_idx)
+{
+       if (ab->hif.ops->get_ce_msi_idx)
+               ab->hif.ops->get_ce_msi_idx(ab, ce_id, msi_data_idx);
+       else
+               *msi_data_idx = ce_id;
+}
 #endif /* _HIF_H_ */
index 462d5e81bee8332dcb748ba58bfdcd4e4de282f8..c943e34c3721e12af5e6e0c3e82447e7d39aeb38 100644 (file)
@@ -1241,6 +1241,200 @@ const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[] = {
        },
 };
 
+/* Target firmware's Copy Engine configuration. */
+const struct ce_pipe_config ath11k_target_ce_config_wlan_qcn9074[] = {
+       /* CE0: host->target HTC control and raw streams */
+       {
+               .pipenum = __cpu_to_le32(0),
+               .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE1: target->host HTT + HTC control */
+       {
+               .pipenum = __cpu_to_le32(1),
+               .pipedir = __cpu_to_le32(PIPEDIR_IN),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE2: target->host WMI */
+       {
+               .pipenum = __cpu_to_le32(2),
+               .pipedir = __cpu_to_le32(PIPEDIR_IN),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE3: host->target WMI */
+       {
+               .pipenum = __cpu_to_le32(3),
+               .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE4: host->target HTT */
+       {
+               .pipenum = __cpu_to_le32(4),
+               .pipedir = __cpu_to_le32(PIPEDIR_OUT),
+               .nentries = __cpu_to_le32(256),
+               .nbytes_max = __cpu_to_le32(256),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE5: target->host Pktlog */
+       {
+               .pipenum = __cpu_to_le32(5),
+               .pipedir = __cpu_to_le32(PIPEDIR_IN),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(2048),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE6: Reserved for target autonomous hif_memcpy */
+       {
+               .pipenum = __cpu_to_le32(6),
+               .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(16384),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE7 used only by Host */
+       {
+               .pipenum = __cpu_to_le32(7),
+               .pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
+               .nentries = __cpu_to_le32(0),
+               .nbytes_max = __cpu_to_le32(0),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
+               .reserved = __cpu_to_le32(0),
+       },
+
+       /* CE8 target->host used only by IPA */
+       {
+               .pipenum = __cpu_to_le32(8),
+               .pipedir = __cpu_to_le32(PIPEDIR_INOUT),
+               .nentries = __cpu_to_le32(32),
+               .nbytes_max = __cpu_to_le32(16384),
+               .flags = __cpu_to_le32(CE_ATTR_FLAGS),
+               .reserved = __cpu_to_le32(0),
+       },
+       /* CE 9, 10, 11 are used by MHI driver */
+};
+
+/* Map from service/endpoint to Copy Engine.
+ * This table is derived from the CE_PCI TABLE, above.
+ * It is passed to the Target at startup for use by firmware.
+ */
+const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qcn9074[] = {
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(3),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(2),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(3),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(2),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(3),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(2),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(3),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(2),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(3),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(2),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(0),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(1),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(0),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(1),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
+               __cpu_to_le32(PIPEDIR_OUT),     /* out = UL = host -> target */
+               __cpu_to_le32(4),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(1),
+       },
+       {
+               __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
+               __cpu_to_le32(PIPEDIR_IN),      /* in = DL = target -> host */
+               __cpu_to_le32(5),
+       },
+
+       /* (Additions here) */
+
+       { /* must be last */
+               __cpu_to_le32(0),
+               __cpu_to_le32(0),
+               __cpu_to_le32(0),
+       },
+};
+
 const struct ath11k_hw_regs ipq8074_regs = {
        /* SW2TCL(x) R0 ring configuration address */
        .hal_tcl1_ring_base_lsb = 0x00000510,
index e54f1ef65d7458ecb6e35e07369930ae5b3bd54e..f58ee67626602cbab63983cb5ed0ddec4616aff9 100644 (file)
@@ -482,6 +482,23 @@ int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_nam
        return -EINVAL;
 }
 
+static void ath11k_pci_get_ce_msi_idx(struct ath11k_base *ab, u32 ce_id,
+                                     u32 *msi_idx)
+{
+       u32 i, msi_data_idx;
+
+       for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
+               if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
+                       continue;
+
+               if (ce_id == i)
+                       break;
+
+               msi_data_idx++;
+       }
+       *msi_idx = msi_data_idx;
+}
+
 static int ath11k_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
                                          int *num_vectors, u32 *user_base_data,
                                          u32 *base_vector)
@@ -741,7 +758,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
 {
        struct ath11k_ce_pipe *ce_pipe;
        u32 msi_data_start;
-       u32 msi_data_count;
+       u32 msi_data_count, msi_data_idx;
        u32 msi_irq_start;
        unsigned int msi_data;
        int irq, i, ret, irq_idx;
@@ -753,14 +770,14 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
                return ret;
 
        /* Configure CE irqs */
-       for (i = 0; i < ab->hw_params.ce_count; i++) {
-               msi_data = (i % msi_data_count) + msi_irq_start;
-               irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
-               ce_pipe = &ab->ce.ce_pipe[i];
-
+       for (i = 0, msi_data_idx = 0; i < ab->hw_params.ce_count; i++) {
                if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
                        continue;
 
+               msi_data = (msi_data_idx % msi_data_count) + msi_irq_start;
+               irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
+               ce_pipe = &ab->ce.ce_pipe[i];
+
                irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
 
                tasklet_setup(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet);
@@ -775,6 +792,7 @@ static int ath11k_pci_config_irq(struct ath11k_base *ab)
                }
 
                ab->irq_num[irq_idx] = irq;
+               msi_data_idx++;
 
                ath11k_pci_ce_irq_disable(ab, i);
        }
@@ -1135,6 +1153,7 @@ static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
        .map_service_to_pipe = ath11k_pci_map_service_to_pipe,
        .ce_irq_enable = ath11k_pci_hif_ce_irq_enable,
        .ce_irq_disable = ath11k_pci_hif_ce_irq_disable,
+       .get_ce_msi_idx = ath11k_pci_get_ce_msi_idx,
 };
 
 static int ath11k_pci_probe(struct pci_dev *pdev,