diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath11k/pcic.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/pcic.c | 77 |
1 files changed, 61 insertions, 16 deletions
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c index 30d66147223f..fc6e7da05c60 100644 --- a/drivers/net/wireless/ath/ath11k/pcic.c +++ b/drivers/net/wireless/ath/ath11k/pcic.c @@ -1,9 +1,11 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2019-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. */ +#include <linux/export.h> #include "core.h" #include "pcic.h" #include "debug.h" @@ -115,6 +117,28 @@ static const struct ath11k_msi_config ath11k_msi_config[] = { }, .hw_rev = ATH11K_HW_WCN6750_HW10, }, + { + .total_vectors = 32, + .total_users = 4, + .users = (struct ath11k_msi_user[]) { + { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, + { .name = "CE", .num_vectors = 10, .base_vector = 3 }, + { .name = "WAKE", .num_vectors = 1, .base_vector = 13 }, + { .name = "DP", .num_vectors = 18, .base_vector = 14 }, + }, + .hw_rev = ATH11K_HW_QCA2066_HW21, + }, + { + .total_vectors = 32, + .total_users = 4, + .users = (struct ath11k_msi_user[]) { + { .name = "MHI", .num_vectors = 3, .base_vector = 0 }, + { .name = "CE", .num_vectors = 10, .base_vector = 3 }, + { .name = "WAKE", .num_vectors = 1, .base_vector = 13 }, + { .name = "DP", .num_vectors = 18, .base_vector = 14 }, + }, + .hw_rev = ATH11K_HW_QCA6698AQ_HW21, + }, }; int ath11k_pcic_init_msi_config(struct ath11k_base *ab) @@ -263,7 +287,7 @@ int ath11k_pcic_get_user_msi_assignment(struct ath11k_base *ab, char *user_name, *user_base_data = *base_vector + ab->pci.msi.ep_base_data; ath11k_dbg(ab, ATH11K_DBG_PCI, - "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n", + "msi assignment %s num_vectors %d user_base_data %u base_vector %u\n", user_name, *num_vectors, *user_base_data, *base_vector); @@ -305,6 +329,7 @@ static void ath11k_pcic_free_ext_irq(struct ath11k_base *ab) free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp); netif_napi_del(&irq_grp->napi); + free_netdev(irq_grp->napi_ndev); } } @@ -422,14 +447,14 @@ static void ath11k_pcic_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp) disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]); } -static void __ath11k_pcic_ext_irq_disable(struct ath11k_base *sc) +static void __ath11k_pcic_ext_irq_disable(struct ath11k_base *ab) { int i; - clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &sc->dev_flags); + clear_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { - struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i]; + struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; ath11k_pcic_ext_grp_disable(irq_grp); @@ -460,18 +485,17 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab) { int i; - set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); - for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; if (!irq_grp->napi_enabled) { - dev_set_threaded(&irq_grp->napi_ndev, true); napi_enable(&irq_grp->napi); irq_grp->napi_enabled = true; } ath11k_pcic_ext_grp_enable(irq_grp); } + + set_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags); } EXPORT_SYMBOL(ath11k_pcic_ext_irq_enable); @@ -527,7 +551,7 @@ static irqreturn_t ath11k_pcic_ext_interrupt_handler(int irq, void *arg) if (!test_bit(ATH11K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags)) return IRQ_HANDLED; - ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq); + ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq %d\n", irq); /* last interrupt received for this group */ irq_grp->timestamp = jiffies; @@ -548,8 +572,9 @@ ath11k_pcic_get_msi_irq(struct ath11k_base *ab, unsigned int vector) static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab) { - int i, j, ret, num_vectors = 0; + int i, j, n, ret, num_vectors = 0; u32 user_base_data = 0, base_vector = 0; + struct ath11k_ext_irq_grp *irq_grp; unsigned long irq_flags; ret = ath11k_pcic_get_user_msi_assignment(ab, "DP", &num_vectors, @@ -563,13 +588,18 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab) irq_flags |= IRQF_NOBALANCING; for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) { - struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i]; + 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, + irq_grp->napi_ndev = alloc_netdev_dummy(0); + if (!irq_grp->napi_ndev) { + ret = -ENOMEM; + goto fail_allocate; + } + + netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi, ath11k_pcic_ext_grp_napi_poll); if (ab->hw_params.ring_mask->tx[i] || @@ -591,13 +621,15 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab) int vector = (i % num_vectors) + base_vector; int irq = ath11k_pcic_get_msi_irq(ab, vector); - if (irq < 0) - return irq; + if (irq < 0) { + ret = irq; + goto fail_irq; + } ab->irq_num[irq_idx] = irq; ath11k_dbg(ab, ATH11K_DBG_PCI, - "irq:%d group:%d\n", irq, i); + "irq %d group %d\n", irq, i); irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); ret = request_irq(irq, ath11k_pcic_ext_interrupt_handler, @@ -605,6 +637,10 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab) if (ret) { ath11k_err(ab, "failed request irq %d: %d\n", vector, ret); + for (n = 0; n <= i; n++) { + irq_grp = &ab->ext_irq_grp[n]; + free_netdev(irq_grp->napi_ndev); + } return ret; } } @@ -612,6 +648,15 @@ static int ath11k_pcic_ext_irq_config(struct ath11k_base *ab) } return 0; +fail_irq: + /* i ->napi_ndev was properly allocated. Free it also */ + i += 1; +fail_allocate: + for (n = 0; n < i; n++) { + irq_grp = &ab->ext_irq_grp[n]; + free_netdev(irq_grp->napi_ndev); + } + return ret; } int ath11k_pcic_config_irq(struct ath11k_base *ab) |
