From c62991534012b71651ccc909090d97c06e6a3c8d Mon Sep 17 00:00:00 2001 From: Anilkumar Kolli Date: Tue, 24 Mar 2020 23:21:23 +0530 Subject: [PATCH 1179/1179] ath11k abstract ext interrupts --- drivers/net/wireless/ath/ath11k/ahb.c | 54 +++++++++ drivers/net/wireless/ath/ath11k/core.h | 8 ++ drivers/net/wireless/ath/ath11k/dp.c | 141 ++++++++++++++++++++-- drivers/net/wireless/ath/ath11k/dp_tx.c | 6 +- drivers/net/wireless/ath/ath11k/hif.h | 45 ------- drivers/net/wireless/ath/ath11k/pci.c | 202 +++++++++++++++++++++++++++++++- 6 files changed, 396 insertions(+), 60 deletions(-) --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -13,6 +13,51 @@ #include "hif.h" #include +static const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_TX_RING_MASK_0, + ATH11K_TX_RING_MASK_1, + ATH11K_TX_RING_MASK_2, +}; + +static const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + 0, 0, 0, 0, + ATH11K_RX_MON_STATUS_RING_MASK_0, + ATH11K_RX_MON_STATUS_RING_MASK_1, + ATH11K_RX_MON_STATUS_RING_MASK_2, +}; + +static const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + 0, 0, 0, 0, 0, 0, 0, + ATH11K_RX_RING_MASK_0, + ATH11K_RX_RING_MASK_1, + ATH11K_RX_RING_MASK_2, + ATH11K_RX_RING_MASK_3, +}; + +static const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_RX_ERR_RING_MASK_0, +}; + +static const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_RX_WBM_REL_RING_MASK_0, +}; + +static const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_REO_STATUS_RING_MASK_0, +}; + +static const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_RXDMA2HOST_RING_MASK_0, + ATH11K_RXDMA2HOST_RING_MASK_1, + ATH11K_RXDMA2HOST_RING_MASK_2, +}; + +static const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_HOST2RXDMA_RING_MASK_0, + ATH11K_HOST2RXDMA_RING_MASK_1, + ATH11K_HOST2RXDMA_RING_MASK_2, +}; + static const struct of_device_id ath11k_ahb_of_match[] = { /* TODO: Should we change the compatible string to something similar * to one that ath10k uses? @@ -637,6 +682,15 @@ static int ath11k_ahb_ext_irq_config(str int irq; int ret; + ab->tx_ring_mask = ath11k_tx_ring_mask; + ab->rx_mon_status_ring_mask = rx_mon_status_ring_mask; + ab->rx_ring_mask = ath11k_rx_ring_mask; + ab->rx_err_ring_mask = ath11k_rx_err_ring_mask; + ab->rx_wbm_rel_ring_mask = ath11k_rx_wbm_rel_ring_mask; + ab->reo_status_ring_mask = ath11k_reo_status_ring_mask; + ab->rxdma2host_ring_mask = ath11k_rxdma2host_ring_mask; + ab->host2rxdma_ring_mask = ath11k_host2rxdma_ring_mask; + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; u32 num_irq = 0; --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -750,6 +750,14 @@ struct ath11k_base { u32 wlan_init_status; int irq_num[ATH11K_IRQ_NUM_MAX]; struct ath11k_ext_irq_grp ext_irq_grp[ATH11K_EXT_IRQ_GRP_NUM_MAX]; + const u8 *tx_ring_mask; + const u8 *rx_mon_status_ring_mask; + const u8 *rx_ring_mask; + const u8 *rx_err_ring_mask; + const u8 *rx_wbm_rel_ring_mask; + const u8 *reo_status_ring_mask; + const u8 *rxdma2host_ring_mask; + const u8 *host2rxdma_ring_mask; struct napi_struct *napi; struct ath11k_targ_cap target_caps; u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE]; --- a/drivers/net/wireless/ath/ath11k/dp.c +++ b/drivers/net/wireless/ath/ath11k/dp.c @@ -107,6 +107,124 @@ void ath11k_dp_srng_cleanup(struct ath11 ring->vaddr_unaligned = NULL; } +static +int ath11k_dp_srng_find_ring_in_mask(int ring_num, const u8 *grp_mask, u32 *grp_num) +{ + int ext_group_num; + u8 mask = 1 << ring_num; + + for (ext_group_num = 0; ext_group_num < ATH11K_EXT_IRQ_GRP_NUM_MAX; + ext_group_num++) { + if (mask & grp_mask[ext_group_num]) { + *grp_num = ext_group_num; + + return 0; + } + } + + return -ENOENT; +} + +static +int ath11k_dp_srng_calculate_msi_group(struct ath11k_base *ab, enum hal_ring_type type, + int ring_num, u32 *msi_grp_num) +{ + const u8 *grp_mask; + + switch (type) { + case HAL_WBM2SW_RELEASE: + if (ring_num < 3) { + grp_mask = ab->tx_ring_mask; + } else if (ring_num == 3) { + /* sw treats this as a separate ring type */ + grp_mask = ab->rx_wbm_rel_ring_mask; + ring_num = 0; + } else { + return -ENOENT; + } + break; + case HAL_REO_EXCEPTION: + grp_mask = ab->rx_err_ring_mask; + break; + case HAL_REO_DST: + grp_mask = ab->rx_ring_mask; + break; + case HAL_REO_STATUS: + grp_mask = ab->reo_status_ring_mask; + break; + case HAL_RXDMA_MONITOR_STATUS: + case HAL_RXDMA_MONITOR_DST: + grp_mask = ab->rx_mon_status_ring_mask; + break; + case HAL_RXDMA_DST: + grp_mask = ab->rxdma2host_ring_mask; + break; + case HAL_RXDMA_BUF: + grp_mask = ab->host2rxdma_ring_mask; + break; + case HAL_RXDMA_MONITOR_BUF: + /* TODO: support low_thresh interrupt */ + return -ENOENT; + break; + case HAL_TCL_DATA: + case HAL_TCL_CMD: + case HAL_REO_CMD: + case HAL_SW2WBM_RELEASE: + case HAL_WBM_IDLE_LINK: + case HAL_TCL_STATUS: + case HAL_REO_REINJECT: + case HAL_CE_SRC: + case HAL_CE_DST: + case HAL_CE_DST_STATUS: + default: + return -ENOENT; + break; + } + + return ath11k_dp_srng_find_ring_in_mask(ring_num, grp_mask, msi_grp_num); +} + +static +void ath11k_dp_srng_msi_setup(struct ath11k_base *ab, struct hal_srng_params *ring_params, + enum hal_ring_type type, int ring_num) +{ + u32 msi_data_start, msi_data_count, msi_irq_start, msi_grp_num; + u32 addr_lo, addr_hi; + int ret; + + ret = ath11k_get_user_msi_vector(ab, "DP", + &msi_data_count, &msi_data_start, + &msi_irq_start); + if (ret) + return; + + ret = ath11k_dp_srng_calculate_msi_group(ab, type, ring_num, &msi_grp_num); + if (ret) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "dp ring type %d num %d not part of the ext grp\n", + type, ring_num); + + ring_params->msi_addr = 0; + ring_params->msi_data = 0; + + return; + } + + if (msi_grp_num > msi_data_count) { + ath11k_warn(ab, "2 msi_groups will share an msi; msi_grp_num %d\n", + msi_grp_num); + + 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 = (msi_grp_num % msi_data_count) + msi_data_start; + ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR; +} + int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring, enum hal_ring_type type, int ring_num, int mac_id, int num_entries) @@ -137,6 +255,8 @@ int ath11k_dp_srng_setup(struct ath11k_b params.ring_base_paddr = ring->paddr; params.num_entries = num_entries; + ath11k_dp_srng_msi_setup(ab, ¶ms, type, ring_num); + switch (type) { case HAL_REO_DST: params.intr_batch_cntr_thres_entries = @@ -626,13 +746,13 @@ int ath11k_dp_service_srng(struct ath11k int i = 0; int tot_work_done = 0; - while (ath11k_tx_ring_mask[grp_id] >> i) { - if (ath11k_tx_ring_mask[grp_id] & BIT(i)) + while (ab->tx_ring_mask[grp_id] >> i) { + if (ab->tx_ring_mask[grp_id] & BIT(i)) ath11k_dp_tx_completion_handler(ab, i); i++; } - if (ath11k_rx_err_ring_mask[grp_id]) { + if (ab->rx_err_ring_mask[grp_id]) { work_done = ath11k_dp_process_rx_err(ab, napi, budget); budget -= work_done; tot_work_done += work_done; @@ -640,7 +760,7 @@ int ath11k_dp_service_srng(struct ath11k goto done; } - if (ath11k_rx_wbm_rel_ring_mask[grp_id]) { + if (ab->rx_wbm_rel_ring_mask[grp_id]) { work_done = ath11k_dp_rx_process_wbm_err(ab, napi, budget); @@ -651,8 +771,8 @@ int ath11k_dp_service_srng(struct ath11k goto done; } - if (ath11k_rx_ring_mask[grp_id]) { - i = fls(ath11k_rx_ring_mask[grp_id]) - 1; + if (ab->rx_ring_mask[grp_id]) { + i = fls(ab->rx_ring_mask[grp_id]) - 1; work_done = ath11k_dp_process_rx(ab, i, napi, budget); budget -= work_done; @@ -661,9 +781,9 @@ int ath11k_dp_service_srng(struct ath11k goto done; } - if (rx_mon_status_ring_mask[grp_id]) { + if (ab->rx_mon_status_ring_mask[grp_id]) { for (i = 0; i < ab->num_radios; i++) { - if (rx_mon_status_ring_mask[grp_id] & BIT(i)) { + if (ab->rx_mon_status_ring_mask[grp_id] & BIT(i)) { work_done = ath11k_dp_rx_process_mon_rings(ab, i, napi, @@ -676,11 +796,11 @@ int ath11k_dp_service_srng(struct ath11k } } - if (ath11k_reo_status_ring_mask[grp_id]) + if (ab->reo_status_ring_mask[grp_id]) ath11k_dp_process_reo_status(ab); for (i = 0; i < ab->num_radios; i++) { - if (ath11k_rxdma2host_ring_mask[grp_id] & BIT(i)) { + if (ab->rxdma2host_ring_mask[grp_id] & BIT(i)) { work_done = ath11k_dp_process_rxdma_err(ab, i, budget); budget -= work_done; tot_work_done += work_done; @@ -689,7 +809,7 @@ int ath11k_dp_service_srng(struct ath11k if (budget <= 0) goto done; - if (ath11k_host2rxdma_ring_mask[grp_id] & BIT(i)) { + if (ab->host2rxdma_ring_mask[grp_id] & BIT(i)) { struct ath11k_pdev_dp *dp = &ab->pdevs[i].ar->dp; struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; --- a/drivers/net/wireless/ath/ath11k/dp_tx.c +++ b/drivers/net/wireless/ath/ath11k/dp_tx.c @@ -796,9 +796,9 @@ int ath11k_dp_tx_htt_srng_setup(struct a cmd->ring_tail_off32_remote_addr_hi = (u64)tp_addr >> HAL_ADDR_MSB_REG_SHIFT; - cmd->ring_msi_addr_lo = 0; - cmd->ring_msi_addr_hi = 0; - cmd->msi_data = 0; + cmd->ring_msi_addr_lo = lower_32_bits(params.msi_addr); + cmd->ring_msi_addr_hi = upper_32_bits(params.msi_addr); + cmd->msi_data = params.msi_data; cmd->intr_info = FIELD_PREP( HTT_SRNG_SETUP_CMD_INTR_INFO_BATCH_COUNTER_THRESH, --- a/drivers/net/wireless/ath/ath11k/hif.h +++ b/drivers/net/wireless/ath/ath11k/hif.h @@ -33,51 +33,6 @@ #define ATH11K_RX_MON_STATUS_RING_MASK_1 0x2 #define ATH11K_RX_MON_STATUS_RING_MASK_2 0x4 -static const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - ATH11K_TX_RING_MASK_0, - ATH11K_TX_RING_MASK_1, - ATH11K_TX_RING_MASK_2, -}; - -static const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - 0, 0, 0, 0, - ATH11K_RX_MON_STATUS_RING_MASK_0, - ATH11K_RX_MON_STATUS_RING_MASK_1, - ATH11K_RX_MON_STATUS_RING_MASK_2, -}; - -static const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - 0, 0, 0, 0, 0, 0, 0, - ATH11K_RX_RING_MASK_0, - ATH11K_RX_RING_MASK_1, - ATH11K_RX_RING_MASK_2, - ATH11K_RX_RING_MASK_3, -}; - -static const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - ATH11K_RX_ERR_RING_MASK_0, -}; - -static const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - ATH11K_RX_WBM_REL_RING_MASK_0, -}; - -static const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - ATH11K_REO_STATUS_RING_MASK_0, -}; - -static const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - ATH11K_RXDMA2HOST_RING_MASK_0, - ATH11K_RXDMA2HOST_RING_MASK_1, - ATH11K_RXDMA2HOST_RING_MASK_2, -}; - -static const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { - ATH11K_HOST2RXDMA_RING_MASK_0, - ATH11K_HOST2RXDMA_RING_MASK_1, - ATH11K_HOST2RXDMA_RING_MASK_2, -}; - struct ath11k_hif_ops { u32 (*read32)(struct ath11k_base *sc, u32 address); void (*write32)(struct ath11k_base *sc, u32 address, u32 data); --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -13,6 +13,43 @@ #include "pci.h" #include "debug.h" +static const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_TX_RING_MASK_0, + ATH11K_TX_RING_MASK_1, + ATH11K_TX_RING_MASK_2, +}; + +static const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + 0, +}; + +static const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_RX_RING_MASK_0, + ATH11K_RX_RING_MASK_1, + ATH11K_RX_RING_MASK_2, + ATH11K_RX_RING_MASK_3, +}; + +static const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_RX_ERR_RING_MASK_0, +}; + +static const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_RX_WBM_REL_RING_MASK_0, +}; + +static const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + ATH11K_REO_STATUS_RING_MASK_0, +}; + +static const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + 0, +}; + +static const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = { + 0, +}; + const char *irq_name[ATH11K_IRQ_NUM_MAX] = { "bhi", "mhi-er0", @@ -488,6 +525,18 @@ int ath11k_get_user_msi_assignment(struc base_vector); } +static void ath11k_pci_free_ext_irq(struct ath11k_base *ab) +{ + int i, j; + + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + + for (j = 0; j < irq_grp->num_irq; j++) + free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); + } +} + static void ath11k_pci_free_irq(struct ath11k_base *ab) { int irq_idx; @@ -499,6 +548,8 @@ static void ath11k_pci_free_irq(struct a irq_idx = ATH11K_IRQ_CE0_OFFSET + i; free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); } + + ath11k_pci_free_ext_irq(ab); } static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id) @@ -555,12 +606,176 @@ static irqreturn_t ath11k_pci_ce_interru { struct ath11k_ce_pipe *ce_pipe = arg; + /* last interrupt received for this CE */ + ce_pipe->timestamp = jiffies; + ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num); tasklet_schedule(&ce_pipe->intr_tq); return IRQ_HANDLED; } +static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp) +{ + int i; + + for (i = 0; i < irq_grp->num_irq; i++) + disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); +} + +static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc) +{ + struct sk_buff *skb; + int i; + + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i]; + + ath11k_pci_ext_grp_disable(irq_grp); + + napi_synchronize(&irq_grp->napi); + napi_disable(&irq_grp->napi); + } +} + +static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp) +{ + int i; + + for (i = 0; i < irq_grp->num_irq; i++) + enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]); +} + +static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab) +{ + int i; + + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + + napi_enable(&irq_grp->napi); + ath11k_pci_ext_grp_enable(irq_grp); + } +} + +static void ath11k_pci_sync_ext_irqs(struct ath11k_base *ab) +{ + int i, j; + int irq_idx; + + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + + for (j = 0; j < irq_grp->num_irq; j++) { + irq_idx = irq_grp->irqs[j]; + synchronize_irq(ab->irq_num[irq_idx]); + } + } +} + +static void ath11k_pci_ext_irq_disable(struct ath11k_base *ab) +{ + __ath11k_pci_ext_irq_disable(ab); + ath11k_pci_sync_ext_irqs(ab); +} + +static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget) +{ + struct ath11k_ext_irq_grp *irq_grp = container_of(napi, + struct ath11k_ext_irq_grp, + napi); + struct ath11k_base *ab = irq_grp->ab; + int work_done; + + work_done = ath11k_dp_service_srng(ab, irq_grp, budget); + if (work_done < budget) { + napi_complete_done(napi, work_done); + ath11k_pci_ext_grp_enable(irq_grp); + } + + if (work_done > budget) + work_done = budget; + + return work_done; +} + +static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg) +{ + struct ath11k_ext_irq_grp *irq_grp = arg; + + /* last interrupt received for this group */ + irq_grp->timestamp = jiffies; + + ath11k_pci_ext_grp_disable(irq_grp); + + napi_schedule(&irq_grp->napi); + + return IRQ_HANDLED; +} + +static int ath11k_pci_ext_irq_config(struct ath11k_base *ab) +{ + int i, j; + int ret; + int num_vectors = 0; + u32 user_base_data = 0, base_vector = 0, base_idx; + + ab->tx_ring_mask = ath11k_tx_ring_mask; + ab->rx_mon_status_ring_mask = rx_mon_status_ring_mask; + ab->rx_ring_mask = ath11k_rx_ring_mask; + ab->rx_err_ring_mask = ath11k_rx_err_ring_mask; + ab->rx_wbm_rel_ring_mask = ath11k_rx_wbm_rel_ring_mask; + ab->reo_status_ring_mask = ath11k_reo_status_ring_mask; + ab->rxdma2host_ring_mask = ath11k_rxdma2host_ring_mask; + ab->host2rxdma_ring_mask = ath11k_host2rxdma_ring_mask; + + base_idx = ATH11K_IRQ_CE0_OFFSET + MAX_CE_COUNT; + + ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP", + &num_vectors, &user_base_data, + &base_vector); + + for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + u32 num_irq = 0; + + irq_grp->ab = ab; + irq_grp->grp_id = i; + init_dummy_netdev(&irq_grp->napi_ndev); + netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi, + ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT); + + if (ath11k_tx_ring_mask[i] || ath11k_rx_ring_mask[i] || + ath11k_rx_err_ring_mask[i] || ath11k_rx_wbm_rel_ring_mask[i] || + ath11k_reo_status_ring_mask[i] || ath11k_rxdma2host_ring_mask[i] || + ath11k_host2rxdma_ring_mask[i] || rx_mon_status_ring_mask[i]) { + num_irq = 1; + } + + irq_grp->num_irq = num_irq; + irq_grp->irqs[0] = base_idx + i; + + for (j = 0; j < irq_grp->num_irq; j++) { + int irq_idx = irq_grp->irqs[j]; + int vector = (i % num_vectors) + base_vector; + int irq = ath11k_pci_get_msi_irq(ab->dev, vector); + + ab->irq_num[irq_idx] = irq; + + irq_set_status_flags(irq, IRQ_NOAUTOEN); + ret = request_irq(irq, ath11k_pci_ext_interrupt_handler, + IRQF_SHARED | IRQF_NO_SUSPEND, + "DP_EXT_IRQ", irq_grp); + if (ret) { + ath11k_err(ab, "failed request_irq for %d\n", + vector); + } + } + } + + return 0; +} + static int ath11k_pci_config_irq(struct ath11k_base *ab) { struct ath11k_ce_pipe *ce_pipe; @@ -600,7 +815,7 @@ static int ath11k_pci_config_irq(struct msi_data_idx++; } - /* To Do Configure external interrupts */ + ath11k_pci_ext_irq_config(ab); return ret; } @@ -904,6 +1119,8 @@ static const struct ath11k_hif_ops ath11 .write32 = ath11k_pci_write32, .power_down = ath11k_pci_power_down, .power_up = ath11k_pci_power_up, + .irq_enable = ath11k_pci_ext_irq_enable, + .irq_disable = ath11k_pci_ext_irq_disable, .get_msi_address = ath11k_pci_get_msi_address, .get_user_msi_vector = ath11k_get_user_msi_assignment, .map_service_to_pipe = ath11k_pci_map_service_to_pipe,