mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-18 09:51:26 +00:00
This series is based on * 2020-07-10 ipq6018-ilq-11-0_qca_oem-034672b0676c37b1f4519e5720e18e95fe6236ef Add support for * qsdk kernel/v4.4 * qsdk ethernet subsystem * v5.7 ath11k backport + QualComm staging patches (wlan_ap_1.0) * ath11k-firmware * hostapd/iw/... Feature support * full boot, system detection * sysupgrade to nand * HE support via latest hostapd * driver support for usb, crypto, hwmon, cpufreq, ... Missing * NSS/HW flow offloading - FW blob is not redistributable Using the qsdk v4.4 is an intermediate solution while the vanilla is being tested. Vanilla kernel is almost on feature par. Work has already started to upstream the ethernet and switch drivers. Once complete the target will be fully upstream. Signed-off-by: John Crispin <john@phrozen.org>
224 lines
6.0 KiB
Diff
224 lines
6.0 KiB
Diff
From d999e9a699b39f6a91a839ff2250018d0a9bd2db Mon Sep 17 00:00:00 2001
|
|
From: Govind Singh <govinds@codeaurora.org>
|
|
Date: Thu, 12 Dec 2019 13:11:01 +0200
|
|
Subject: [PATCH 163/164] ath11k: setup ce tasklet for control path
|
|
|
|
CE srng is used for control path and CE srng processing
|
|
is done using tasklet bottom half. Setup ce tasklet
|
|
initialization and scheduling for control path.
|
|
|
|
Signed-off-by: Govind Singh <govinds@codeaurora.org>
|
|
Signed-off-by: Anilkumar Kolli <akolli@codeaurora.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/ce.c | 2 +
|
|
drivers/net/wireless/ath/ath11k/ce.h | 2 +
|
|
drivers/net/wireless/ath/ath11k/pci.c | 116 +++++++++++++++++++++++++++++++---
|
|
3 files changed, 112 insertions(+), 8 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath11k/ce.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/ce.c
|
|
@@ -522,6 +522,7 @@ static int ath11k_ce_alloc_pipe(struct a
|
|
|
|
return 0;
|
|
}
|
|
+EXPORT_SYMBOL(ath11k_ce_per_engine_service);
|
|
|
|
void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id)
|
|
{
|
|
@@ -692,6 +693,7 @@ void ath11k_ce_rx_post_buf(struct ath11k
|
|
}
|
|
}
|
|
}
|
|
+EXPORT_SYMBOL(ath11k_ce_rx_post_buf);
|
|
|
|
void ath11k_ce_rx_replenish_retry(struct timer_list *t)
|
|
{
|
|
--- a/drivers/net/wireless/ath/ath11k/ce.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/ce.h
|
|
@@ -182,4 +182,6 @@ int ath11k_ce_alloc_pipes(struct ath11k_
|
|
void ath11k_ce_free_pipes(struct ath11k_base *ab);
|
|
int ath11k_ce_get_attr_flags(int ce_id);
|
|
void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id);
|
|
+int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
|
|
+ u8 *ul_pipe, u8 *dl_pipe);
|
|
#endif
|
|
--- a/drivers/net/wireless/ath/ath11k/pci.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/pci.c
|
|
@@ -341,6 +341,14 @@ static void ath11k_pci_free_irq(struct a
|
|
}
|
|
}
|
|
|
|
+static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
|
+{
|
|
+ u32 irq_idx;
|
|
+
|
|
+ irq_idx = ATH11K_IRQ_CE0_OFFSET + ce_id;
|
|
+ enable_irq(ab->irq_num[irq_idx]);
|
|
+}
|
|
+
|
|
static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
|
|
{
|
|
u32 irq_idx;
|
|
@@ -349,11 +357,46 @@ static void ath11k_pci_ce_irq_disable(st
|
|
disable_irq_nosync(ab->irq_num[irq_idx]);
|
|
}
|
|
|
|
+static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < CE_COUNT; i++) {
|
|
+ if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
|
+ continue;
|
|
+ ath11k_pci_ce_irq_disable(ab, i);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
|
|
+{
|
|
+ int i;
|
|
+ int irq_idx;
|
|
+
|
|
+ for (i = 0; i < CE_COUNT; i++) {
|
|
+ if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
|
+ continue;
|
|
+
|
|
+ irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
|
|
+ synchronize_irq(ab->irq_num[irq_idx]);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void ath11k_pci_ce_tasklet(unsigned long data)
|
|
+{
|
|
+ struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
|
|
+
|
|
+ ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
|
|
+
|
|
+ ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
|
|
+}
|
|
+
|
|
static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
|
|
{
|
|
struct ath11k_ce_pipe *ce_pipe = arg;
|
|
|
|
ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
|
|
+ tasklet_schedule(&ce_pipe->intr_tq);
|
|
|
|
return IRQ_HANDLED;
|
|
}
|
|
@@ -383,6 +426,9 @@ static int ath11k_pci_config_irq(struct
|
|
|
|
irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
|
|
|
|
+ tasklet_init(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet,
|
|
+ (unsigned long)ce_pipe);
|
|
+
|
|
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
|
|
IRQF_SHARED, irq_name[irq_idx],
|
|
ce_pipe);
|
|
@@ -409,14 +455,6 @@ static void ath11k_pci_init_qmi_ce_confi
|
|
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6x90;
|
|
}
|
|
|
|
-static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
|
-{
|
|
- u32 irq_idx;
|
|
-
|
|
- irq_idx = ATH11K_IRQ_CE0_OFFSET + ce_id;
|
|
- enable_irq(ab->irq_num[irq_idx]);
|
|
-}
|
|
-
|
|
static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
|
|
{
|
|
int i;
|
|
@@ -607,8 +645,25 @@ static void ath11k_pci_power_down(struct
|
|
ath11k_pci_qca6x90_powerdown(ar_pci);
|
|
}
|
|
|
|
+static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < CE_COUNT; i++) {
|
|
+ struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
|
|
+
|
|
+ if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
|
+ continue;
|
|
+
|
|
+ tasklet_kill(&ce_pipe->intr_tq);
|
|
+ }
|
|
+}
|
|
+
|
|
static void ath11k_pci_stop(struct ath11k_base *ab)
|
|
{
|
|
+ ath11k_pci_ce_irqs_disable(ab);
|
|
+ ath11k_pci_sync_ce_irqs(ab);
|
|
+ ath11k_pci_kill_tasklets(ab);
|
|
ath11k_ce_cleanup_pipes(ab);
|
|
/* Shutdown other components as appropriate */
|
|
}
|
|
@@ -616,11 +671,55 @@ static void ath11k_pci_stop(struct ath11
|
|
static int ath11k_pci_start(struct ath11k_base *ab)
|
|
{
|
|
ath11k_pci_ce_irqs_enable(ab);
|
|
+ ath11k_ce_rx_post_buf(ab);
|
|
/* Bring up other components as appropriate */
|
|
|
|
return 0;
|
|
}
|
|
|
|
+static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
|
|
+ u8 *ul_pipe, u8 *dl_pipe)
|
|
+{
|
|
+ const struct service_to_pipe *entry;
|
|
+ bool ul_set = false, dl_set = false;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
|
|
+ entry = &target_service_to_ce_map_wlan[i];
|
|
+
|
|
+ if (__le32_to_cpu(entry->service_id) != service_id)
|
|
+ continue;
|
|
+
|
|
+ switch (__le32_to_cpu(entry->pipedir)) {
|
|
+ case PIPEDIR_NONE:
|
|
+ break;
|
|
+ case PIPEDIR_IN:
|
|
+ WARN_ON(dl_set);
|
|
+ *dl_pipe = __le32_to_cpu(entry->pipenum);
|
|
+ dl_set = true;
|
|
+ break;
|
|
+ case PIPEDIR_OUT:
|
|
+ WARN_ON(ul_set);
|
|
+ *ul_pipe = __le32_to_cpu(entry->pipenum);
|
|
+ ul_set = true;
|
|
+ break;
|
|
+ case PIPEDIR_INOUT:
|
|
+ WARN_ON(dl_set);
|
|
+ WARN_ON(ul_set);
|
|
+ *dl_pipe = __le32_to_cpu(entry->pipenum);
|
|
+ *ul_pipe = __le32_to_cpu(entry->pipenum);
|
|
+ dl_set = true;
|
|
+ ul_set = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (WARN_ON(!ul_set || !dl_set))
|
|
+ return -ENOENT;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
|
|
.start = ath11k_pci_start,
|
|
.stop = ath11k_pci_stop,
|
|
@@ -630,6 +729,7 @@ static const struct ath11k_hif_ops ath11
|
|
.power_up = ath11k_pci_power_up,
|
|
.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,
|
|
};
|
|
|
|
static int ath11k_pci_probe(struct pci_dev *pdev,
|