From fa855844898339d1c38b8826d5717fa728710256 Mon Sep 17 00:00:00 2001 From: Sarada Prasanna Garnayak Date: Thu, 11 May 2017 20:49:52 +0530 Subject: [PATCH] ath10k: Define structure for copy engine interrupt map for SNOC The WLAN driver request and free the copy engine interrupt according to the WLAN host target communication and protocol in different WLAN context and subsystem state. The ath10k snoc free/request all copy engine interrupt line during wlan subsystem recovery due to firmware crash or hardware interface down etc. To avoid the kernel warning and fault due to redundant copy engine interrupt request/free in different wlan state. Define structure for copy engine to maintain the stat of copy engine interrupt list request/free. Change-Id: I5cf3de4feecfb3a93a930c4939dc0a80bfc14e55 Signed-off-by: Sarada Prasanna Garnayak --- drivers/net/wireless/ath/ath10k/snoc.c | 19 ++++++++++++------- drivers/net/wireless/ath/ath10k/snoc.h | 12 +++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 0cc98e45b65c..9406b6f71a6b 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -969,7 +969,7 @@ int ath10k_snoc_get_ce_id(struct ath10k *ar, int irq) struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); for (i = 0; i < CE_COUNT_MAX; i++) { - if (ar_snoc->ce_irqs[i] == irq) + if (ar_snoc->ce_irqs[i].irq_line == irq) return i; } ath10k_err(ar, "No matching CE id for irq %d\n", irq); @@ -1002,15 +1002,17 @@ static int ath10k_snoc_request_irq(struct ath10k *ar) int irqflags = IRQF_TRIGGER_RISING; for (id = 0; id < CE_COUNT_MAX; id++) { - ret = request_irq(ar_snoc->ce_irqs[id], + ret = request_irq(ar_snoc->ce_irqs[id].irq_line, ath10k_snoc_per_engine_handler, irqflags, ce_name[id], ar); if (ret) { ath10k_err(ar, "%s: cannot register CE %d irq handler, ret = %d", __func__, id, ret); - free_irq(ar_snoc->ce_irqs[id], ar); + atomic_set(&ar_snoc->ce_irqs[id].irq_req_stat, 0); return ret; + } else { + atomic_set(&ar_snoc->ce_irqs[id].irq_req_stat, 1); } } @@ -1022,11 +1024,14 @@ static void ath10k_snoc_free_irq(struct ath10k *ar) int id; struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); - for (id = 0; id < CE_COUNT_MAX; id++) - free_irq(ar_snoc->ce_irqs[id], ar); + for (id = 0; id < CE_COUNT_MAX; id++) { + if (atomic_read(&ar_snoc->ce_irqs[id].irq_req_stat)) { + free_irq(ar_snoc->ce_irqs[id].irq_line, ar); + atomic_set(&ar_snoc->ce_irqs[id].irq_req_stat, 0); + } + } } - static int ath10k_snoc_get_soc_info(struct ath10k *ar) { struct resource *res; @@ -1198,7 +1203,7 @@ static int ath10k_snoc_resource_init(struct ath10k *ar) ret = -ENODEV; goto out; } else { - ar_snoc->ce_irqs[i] = res->start; + ar_snoc->ce_irqs[i].irq_line = res->start; } } diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 99ae157885bb..7a223b1d3ded 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -103,6 +103,15 @@ struct ath10k_service_notifier_context { char name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1]; }; +/* struct ath10k_snoc_ce_irq: copy engine irq struct + * @irq_req_stat: irq request status + * @irq_line: irq line + */ +struct ath10k_snoc_ce_irq { + atomic_t irq_req_stat; + u32 irq_line; +}; + /* struct ath10k_snoc: SNOC info struct * @dev: device structure * @ar:ath10k base structure @@ -111,6 +120,7 @@ struct ath10k_service_notifier_context { * @target_info: snoc target info * @mem_len: mempry map length * @pipe_info: pipe info struct + * @ce_irqs: copy engine irq list * @ce_lock: protect ce structures * @ce_states: maps ce id to ce state * @rx_post_retry: rx buffer post processing timer @@ -134,7 +144,7 @@ struct ath10k_snoc { size_t mem_len; struct ath10k_snoc_pipe pipe_info[CE_COUNT_MAX]; struct timer_list rx_post_retry; - u32 ce_irqs[CE_COUNT_MAX]; + struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX]; u32 *vaddr_rri_on_ddr; bool is_driver_probed; struct notifier_block modem_ssr_nb;