summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbings <bings@codeaurora.org>2019-01-14 18:21:03 +0800
committerbings <bings@codeaurora.org>2019-01-17 15:28:27 +0800
commitcf86e7b4eceb5f95898d224a8c1cb5bb07eb28bf (patch)
tree418a5fae66de97674fb4adefe61109812a149652
parente4646b07ba96d4110362310266f05f27d42bc360 (diff)
qcacld-2.0: Implement OOB
1.Implement OOB wake up and interrupt api for all interfaces. 2.Implement OOB wake up and interrupt for SDIO interface. OOB wake up and interrupt can be enable/disable independently. Change-Id: Id301966d37c752666f453a16d333c32a32aeb2a2 CRs-Fixed: 2382530
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h48
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c18
-rw-r--r--CORE/SERVICES/COMMON/ol_if_athvar.h6
-rw-r--r--CORE/SERVICES/HIF/hif_oob.c260
-rw-r--r--CORE/SERVICES/HIF/hif_oob.h107
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h6
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c85
-rw-r--r--CORE/SERVICES/HTC/htc.c37
-rw-r--r--CORE/VOSS/inc/i_vos_types.h6
-rw-r--r--CORE/VOSS/src/vos_api.c22
-rw-r--r--Kbuild23
11 files changed, 605 insertions, 13 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index 98f2f2be228a..9abdef519f3f 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -2949,6 +2949,48 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */
#define CFG_P2P_LISTEN_OFFLOAD_ENABLE ( 1 )
#define CFG_P2P_LISTEN_OFFLOAD_DEFAULT ( CFG_P2P_LISTEN_OFFLOAD_DISABLE )
+#ifdef CONFIG_GPIO_OOB
+/*
+ * <ini>
+ * goob_gpio_num - OOB GPIO NUM
+ * @Min: 0
+ * @Max: 255
+ * @Default: 255
+ *
+ * This ini is used to config OOB GPIO NUM
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+
+#define CFG_ENABLE_OOB_GPIO_NUM_NAME "goob_gpio_num"
+#define CFG_ENABLE_OOB_GPIO_NUM_MIN (0)
+#define CFG_ENABLE_OOB_GPIO_NUM_MAX (255)
+#define CFG_ENABLE_OOB_GPIO_NUM_DEFAULT (CFG_ENABLE_OOB_GPIO_NUM_MAX)
+
+/*
+ * <ini>
+ * goob_gpio_flag - OOB GPIO flag
+ * bit 0 - enable OOB wake up
+ * bit 1 - enable OOB interrupt
+ * @Min: 0
+ * @Max: 3
+ * @Default: 0
+ *
+ * This ini is used to enable OOB GPIO feature
+ *
+ * Usage: External
+ *
+ * </ini>
+ */
+
+#define CFG_ENABLE_OOB_GPIO_FLAG_NAME "goob_gpio_flag"
+#define CFG_ENABLE_OOB_GPIO_FLAG_MIN (0)
+#define CFG_ENABLE_OOB_GPIO_FLAG_MAX (3)
+#define CFG_ENABLE_OOB_GPIO_FLAG_DEFAULT (0)
+#endif
+
/*
* Firmware uart print
*/
@@ -5962,6 +6004,10 @@ struct hdd_config {
v_BOOL_t enableTCPChkSumOffld;
v_BOOL_t enableIPChecksumOffload;
v_BOOL_t enablePowersaveOffload;
+#ifdef CONFIG_GPIO_OOB
+ v_U32_t oob_gpio_num;
+ v_U32_t oob_gpio_flag;
+#endif
v_BOOL_t enablefwprint;
v_BOOL_t enablefwlog;
v_BOOL_t fastfwdump;
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 6fc2a9472f0f..f7ffdb69533d 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -2954,6 +2954,22 @@ REG_TABLE_ENTRY g_registry_table[] =
CFG_POWERSAVE_OFFLOAD_MIN,
CFG_POWERSAVE_OFFLOAD_MAX ),
+#ifdef CONFIG_GPIO_OOB
+ REG_VARIABLE(CFG_ENABLE_OOB_GPIO_FLAG_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, oob_gpio_flag,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_ENABLE_OOB_GPIO_FLAG_DEFAULT,
+ CFG_ENABLE_OOB_GPIO_FLAG_MIN,
+ CFG_ENABLE_OOB_GPIO_FLAG_MAX),
+
+ REG_VARIABLE(CFG_ENABLE_OOB_GPIO_NUM_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, oob_gpio_num,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK,
+ CFG_ENABLE_OOB_GPIO_NUM_DEFAULT,
+ CFG_ENABLE_OOB_GPIO_NUM_MIN,
+ CFG_ENABLE_OOB_GPIO_NUM_MAX),
+#endif
+
REG_VARIABLE( CFG_ENABLE_FW_UART_PRINT_NAME, WLAN_PARAM_Integer,
hdd_config_t, enablefwprint,
VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
diff --git a/CORE/SERVICES/COMMON/ol_if_athvar.h b/CORE/SERVICES/COMMON/ol_if_athvar.h
index ee980552f62e..9946586ebbce 100644
--- a/CORE/SERVICES/COMMON/ol_if_athvar.h
+++ b/CORE/SERVICES/COMMON/ol_if_athvar.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -245,6 +245,10 @@ struct ol_softc {
#ifdef PERE_IP_HDR_ALIGNMENT_WAR
bool host_80211_enable; /* Enables native-wifi mode on host */
#endif
+#ifdef CONFIG_GPIO_OOB
+ u_int32_t oob_gpio_num;
+ u_int32_t oob_gpio_flag;
+#endif
bool enableuartprint; /* enable uart/serial prints from target */
bool enablefwlog; /* enable fwlog */
/* enable FW self-recovery for Rome USB */
diff --git a/CORE/SERVICES/HIF/hif_oob.c b/CORE/SERVICES/HIF/hif_oob.c
new file mode 100644
index 000000000000..e50f931f2c73
--- /dev/null
+++ b/CORE/SERVICES/HIF/hif_oob.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/gpio.h>
+#include <hif_oob.h>
+#include <vos_api.h>
+#if defined(HIF_SDIO)
+#include <hif_internal.h>
+#endif
+#define ATH_MODULE_NAME hif
+#include "a_debug.h"
+
+#if defined(HIF_SDIO)
+#define hif_device_oob_ctx(device) (&((device)->hif_oob))
+#define hif_oob_irq_handler_ctx(device) ((device)->func)
+#else
+/*Please add oob context if USB, PCIE supports OOB*/
+#define hif_device_oob_ctx(device) NULL
+#define hif_oob_irq_handler_ctx(device) NULL
+#endif
+
+#define OOB_INVALID_GPIO 255
+/**
+ * hif_oob_irq() - oob irq handler
+ * @irq: irq number
+ * @dev_id: HIF DEVICE
+ *
+ * Return: IRQ_HANDLED
+ */
+static irqreturn_t hif_oob_irq(int irq, void *dev)
+{
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx((HIF_DEVICE *)dev);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return IRQ_HANDLED;
+ }
+
+ if (hif_oob->oob_gpio_flag & GPIO_OOB_INTERRUPT_ENABLE)
+ up(&hif_oob->oob_sem);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * oob_task() - thread to handle all the oob interrupts
+ * @pm_oob: HIF DEVICE
+ *
+ * Return: 0
+ */
+static int oob_task(void *pm_oob)
+{
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx((HIF_DEVICE *)pm_oob);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return A_ERROR;
+ }
+ while (!hif_oob->oob_shutdown) {
+ if (down_interruptible(&hif_oob->oob_sem) != 0)
+ continue;
+ while (!gpio_get_value(hif_oob->oob_gpio_num))
+ hif_oob->oob_irq_handler(
+ hif_oob_irq_handler_ctx((HIF_DEVICE *)pm_oob));
+ }
+
+ complete_and_exit(&hif_oob->oob_completion, 0);
+
+ return 0;
+}
+
+int hif_oob_claim_irq(oob_irq_handler_t handler, HIF_DEVICE *hif_device)
+{
+ struct sched_param param = { .sched_priority = 1 };
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx(hif_device);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return A_ERROR;
+ }
+ if (hif_oob->oob_task) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("oob task already created"));
+ return 0;
+ }
+ sema_init(&hif_oob->oob_sem, 0);
+ hif_oob->oob_task = kthread_create(oob_task, hif_device,
+ "koobirqd");
+ if (IS_ERR(hif_oob->oob_task)) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("fail to create oob task"));
+ hif_oob->oob_task = NULL;
+ return A_ERROR;
+ } else {
+ hif_oob->oob_irq_handler = handler;
+ hif_oob->oob_shutdown = 0;
+ sched_setscheduler(hif_oob->oob_task, SCHED_FIFO,
+ &param);
+ wake_up_process(hif_oob->oob_task);
+ up(&hif_oob->oob_sem);
+ AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("start oob task"));
+ }
+
+ return 0;
+}
+
+int hif_oob_release_irq(HIF_DEVICE *hif_device)
+{
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx(hif_device);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return A_ERROR;
+ }
+ if (!hif_oob->oob_task) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("oob_task is NULL. return"));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("try to kill the oob task"));
+ init_completion(&hif_oob->oob_completion);
+ hif_oob->oob_shutdown = 1;
+ up(&hif_oob->oob_sem);
+ wait_for_completion(&hif_oob->oob_completion);
+ hif_oob->oob_task = NULL;
+ }
+
+ return 0;
+}
+
+void hif_oob_gpio_deinit(HIF_DEVICE *device)
+{
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx(device);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return;
+ }
+
+ if (hif_oob->oob_irq_num >= 0 && hif_oob->oob_gpio_flag) {
+ if (hif_oob->oob_irq_wake_enabled) {
+ if (!disable_irq_wake(hif_oob->oob_irq_num))
+ hif_oob->oob_irq_wake_enabled = false;
+ }
+ disable_irq(hif_oob->oob_irq_num);
+ free_irq(hif_oob->oob_irq_num, device);
+ gpio_free(hif_oob->oob_gpio_num);
+ hif_oob->oob_irq_num = -1;
+ }
+}
+
+int hif_oob_gpio_init(HIF_DEVICE *device, uint32_t oob_gpio,
+ uint32_t oob_gpio_flag)
+{
+ int ret = 0;
+ unsigned long irq_flags = 0;
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx(device);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return A_ERROR;
+ }
+
+ ret = gpio_request(oob_gpio, "oob_irq");
+
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("gpio_request %d ret %d", oob_gpio, ret));
+ goto err_oob_req;
+ }
+
+ ret = gpio_direction_input(oob_gpio);
+
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("gpio_direction_input %d ret %d", oob_gpio, ret));
+ goto err_oob_int;
+ }
+
+ hif_oob->oob_irq_num = gpio_to_irq(oob_gpio);
+ if (hif_oob->oob_irq_num < 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("%s: gpio_to_irq %d ret %d", __func__, oob_gpio, ret));
+ goto err_oob_int;
+ }
+
+ if (oob_gpio_flag & GPIO_OOB_INTERRUPT_ENABLE)
+ irq_flags = IRQF_TRIGGER_FALLING;
+ else
+ irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
+
+ ret = request_irq(hif_oob->oob_irq_num, hif_oob_irq, irq_flags,
+ "oob_irq", device);
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("%s: request_irq %d ret %d", __func__, oob_gpio, ret));
+ goto err_oob_int;
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("%s: gpio %d request oob irq", __func__, oob_gpio));
+ if (oob_gpio_flag & GPIO_OOB_WAKEUP_ENABLE) {
+ ret = enable_irq_wake(hif_oob->oob_irq_num);
+ if (ret) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+ ("enable irq wake failed %d", ret));
+ hif_oob->oob_irq_wake_enabled = false;
+ goto err_oob_wakeup;
+ } else {
+ hif_oob->oob_irq_wake_enabled = true;
+ }
+ }
+ }
+ hif_oob->oob_gpio_num = oob_gpio;
+ hif_oob->oob_gpio_flag = oob_gpio_flag;
+
+ return ret;
+
+err_oob_wakeup:
+ disable_irq(hif_oob->oob_irq_num);
+ free_irq(hif_oob->oob_irq_num, device);
+err_oob_int:
+ gpio_free(oob_gpio);
+err_oob_req:
+ hif_oob->oob_irq_num = -1;
+ hif_oob->oob_gpio_num = OOB_INVALID_GPIO;
+ hif_oob->oob_irq_wake_enabled = false;
+ return ret;
+}
+
+int hif_set_wow_maskint(HIF_DEVICE *device, bool value)
+{
+ struct hif_oob_ctx *hif_oob = hif_device_oob_ctx(device);
+
+ if (!hif_oob) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("NULL hif oob\n"));
+
+ return A_ERROR;
+ }
+
+ hif_oob->wow_maskint = value;
+
+ return A_OK;
+}
diff --git a/CORE/SERVICES/HIF/hif_oob.h b/CORE/SERVICES/HIF/hif_oob.h
new file mode 100644
index 000000000000..0d045e1d510f
--- /dev/null
+++ b/CORE/SERVICES/HIF/hif_oob.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019 The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _HIF_OOB_H_
+#define _HIF_OOB_H_
+
+#include <linux/kthread.h>
+
+#include <hif.h>
+
+#define GPIO_OOB_WAKEUP_ENABLE (1 << 0)
+
+#define GPIO_OOB_INTERRUPT_ENABLE (1 << 1)
+
+#ifdef CONFIG_GPIO_OOB
+typedef void (*oob_irq_handler_t) (void *dev_para);
+
+struct hif_oob_ctx {
+ struct semaphore oob_sem;
+ struct completion oob_completion;
+ struct task_struct *oob_task;
+ int oob_irq_num;
+ uint32_t oob_gpio_num;
+ uint32_t oob_gpio_flag;
+ bool oob_irq_wake_enabled;
+ bool oob_shutdown;
+ oob_irq_handler_t oob_irq_handler;
+ bool wow_maskint;
+};
+
+/**
+ * hif_oob_gpio_init() - initialize gpio oob
+ * @device: HIF handle
+ * @oob_gpio: oob gpio number
+ * @oob_gpio_flag: oob gpio flag
+ *
+ * Return: 0 if succeeds.
+ */
+int hif_oob_gpio_init(HIF_DEVICE *device, uint32_t oob_gpio,
+ uint32_t oob_gpio_flag);
+
+/**
+ * hif_oob_gpio_deinit() - deinitialize gpio oob
+ * @device: HIF handle
+ *
+ * Return: NULL
+ */
+void hif_oob_gpio_deinit(HIF_DEVICE *device);
+
+/**
+ * hif_oob_claim_irq() - create oob task
+ * @handler: oob irq handler
+ * @hif_device: HIF DEVICE
+ *
+ * Return: 0 if succeeds
+ */
+int hif_oob_claim_irq(oob_irq_handler_t handler, HIF_DEVICE *hif_device);
+
+/**
+ * hif_oob_release_irq() - delete oob task
+ * @hif_device: HIF DEVICE
+ *
+ * Return: 0
+ */
+int hif_oob_release_irq(HIF_DEVICE *hif_device);
+
+/**
+ * hif_set_wow_maskint() - configure wow maskint
+ * @hif_device: HIF DEVICE
+ * @value: value to set
+ *
+ * Return: 0 if succeeds
+ */
+int hif_set_wow_maskint(HIF_DEVICE *device, bool value);
+#else
+static inline int hif_oob_gpio_init(HIF_DEVICE *device, uint32_t oob_gpio,
+ uint32_t oob_gpio_flag)
+{
+ return 0;
+}
+
+static inline void hif_oob_gpio_deinit(HIF_DEVICE *device)
+{
+}
+
+static inline int hif_set_wow_maskint(HIF_DEVICE *device, bool value)
+{
+ return 0;
+}
+#endif
+
+#endif
diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h b/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h
index 9d3ae4f07093..947a544e30ca 100644
--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h
+++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/include/hif_internal.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2016-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -36,6 +36,7 @@
#include <adf_os_lock.h>
#include "hif.h"
#include "hif_sdio_common.h"
+#include "hif_oob.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#include <linux/scatterlist.h>
#define HIF_LINUX_MMC_SCATTER_SUPPORT
@@ -135,6 +136,9 @@ struct hif_device {
/* mailbox swapping for control and data svc*/
A_BOOL swap_mailbox;
bool ctrl_response_timeout;
+#ifdef CONFIG_GPIO_OOB
+ struct hif_oob_ctx hif_oob;
+#endif
};
#define HIF_DMA_BUFFER_SIZE (4 * 1024)
diff --git a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
index 894f20b6b44a..8cfcc97b0223 100644
--- a/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
+++ b/CORE/SERVICES/HIF/sdio/linux/native_sdio/src/hif.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -1873,10 +1873,86 @@ HIFAckInterrupt(HIF_DEVICE *device)
/* Acknowledge our function IRQ */
}
+#ifdef CONFIG_GPIO_OOB
void
HIFUnMaskInterrupt(HIF_DEVICE *device)
{
- int ret;;
+ int ret;
+
+ if (!device || !device->func)
+ return;
+
+ ENTER();
+ /*
+ * On HP Elitebook 8460P, interrupt mode is not stable in high
+ * throughput, so polling method should be used instead of
+ * interrupt mode
+ */
+ if (brokenirq) {
+ pr_err("AR6000:Using broken IRQ mode\n");
+ /* disable IRQ support even the capability exists */
+ device->func->card->host->caps &= ~MMC_CAP_SDIO_IRQ;
+ }
+ /* Register the IRQ Handler */
+ sdio_claim_host(device->func);
+ if (device->hif_oob.oob_gpio_flag & GPIO_OOB_INTERRUPT_ENABLE) {
+ ret = hif_oob_claim_irq(hif_oob_irq_handler, device);
+ } else {
+ if (false == vos_oob_enabled())
+ ret = sdio_claim_irq(device->func, hifIRQHandler);
+ else
+ ret = vos_register_oob_irq_handler(hif_oob_irq_handler,
+ device->func);
+ }
+
+ sdio_release_host(device->func);
+ AR_DEBUG_ASSERT(ret == 0);
+ EXIT();
+}
+
+void HIFMaskInterrupt(HIF_DEVICE *device)
+{
+ int ret;
+
+ if (!device || !device->func)
+ return;
+ ENTER();
+
+ /* Mask our function IRQ */
+ sdio_claim_host(device->func);
+ while (atomic_read(&device->irqHandling)) {
+ sdio_release_host(device->func);
+ schedule_timeout_interruptible(HZ / 10);
+ sdio_claim_host(device->func);
+ }
+
+ if (device->hif_oob.oob_gpio_flag & GPIO_OOB_INTERRUPT_ENABLE) {
+ ret = hif_oob_release_irq(device);
+ } else {
+ if (false == vos_oob_enabled())
+ ret = sdio_release_irq(device->func);
+ else
+ ret = vos_unregister_oob_irq_handler(device->func);
+ }
+
+ sdio_release_host(device->func);
+ if (ret) {
+ if (ret == -ETIMEDOUT) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
+ ("AR6000: Timeout mask interrupt. Card rm?"));
+ } else {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
+ ("AR6000: Unable to mask interrupt %d\n", ret));
+ AR_DEBUG_ASSERT(ret == 0);
+ }
+ }
+ EXIT();
+}
+#else
+void
+HIFUnMaskInterrupt(HIF_DEVICE *device)
+{
+ int ret;
if (device == NULL || device->func == NULL)
return;
@@ -1937,6 +2013,7 @@ void HIFMaskInterrupt(HIF_DEVICE *device)
}
EXIT();
}
+#endif
void hif_release_bus_requests(HIF_DEVICE *device)
{
@@ -2397,6 +2474,7 @@ static int hifDeviceSuspend(struct device *dev)
AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: set sdio pm flags MMC_PM_WAKE_SDIO_IRQ failed: %d\n",ret));
return ret;
}
+ hif_set_wow_maskint(device, true);
HIFMaskInterrupt(device);
device->DeviceState = HIF_DEVICE_STATE_WOW;
AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: wow success\n"));
@@ -2414,6 +2492,7 @@ static int hifDeviceSuspend(struct device *dev)
* But before adding finishe callback function to these handler, sleep wait is a simple method.
*/
msleep(100);
+ hif_set_wow_maskint(device, true);
HIFMaskInterrupt(device);
device->DeviceState = HIF_DEVICE_STATE_DEEPSLEEP;
AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("hifDeviceSuspend: deep sleep success\n"));
@@ -2486,6 +2565,7 @@ static int hifDeviceResume(struct device *dev)
}
}
else if(device->DeviceState == HIF_DEVICE_STATE_DEEPSLEEP){
+ hif_set_wow_maskint(device, false);
HIFUnMaskInterrupt(device);
// hifRestartAllVap((struct ol_ath_softc_net80211 *)device->claimedContext);
}
@@ -2501,6 +2581,7 @@ static int hifDeviceResume(struct device *dev)
return status;
}
/*TODO:WOW support*/
+ hif_set_wow_maskint(device, false);
HIFUnMaskInterrupt(device);
}
diff --git a/CORE/SERVICES/HTC/htc.c b/CORE/SERVICES/HTC/htc.c
index 09936a01b5de..0667c6c597f9 100644
--- a/CORE/SERVICES/HTC/htc.c
+++ b/CORE/SERVICES/HTC/htc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -35,6 +35,7 @@
#include <vos_getBin.h>
#include "epping_main.h"
#include "htc_api.h"
+#include <hif_oob.h>
#define MAX_HTC_RX_BUNDLE 2
@@ -309,6 +310,7 @@ void HTCDestroy(HTC_HANDLE HTCHandle)
HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy .. Destroying :0x%pK \n",target));
HIFStop(HTCGetHifDevice(HTCHandle));
+ hif_oob_gpio_deinit(HTCGetHifDevice(HTCHandle));
HTCCleanup(target);
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n"));
}
@@ -528,6 +530,30 @@ A_UINT8 HTCGetCreditAllocation(HTC_TARGET *target, A_UINT16 ServiceID)
return allocation;
}
+/**
+ * get_oob_gpio_config() - get oob gpio config
+ * @HTCHandle - pointer to HTC handle
+ * @gpio_num - pointer to gpio num
+ * @gpio_flag - pointer to gpio flag
+ *
+ * Return NULL
+ */
+#ifdef CONFIG_GPIO_OOB
+static void get_oob_gpio_config(HTC_HANDLE htc_handle, uint32_t *gpio_num,
+ uint32_t *gpio_flag)
+{
+ HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(htc_handle);
+ struct ol_softc *scn = (struct ol_softc *)target->HTCInitInfo.pContext;
+
+ *gpio_num = scn->oob_gpio_num;
+ *gpio_flag = scn->oob_gpio_flag;
+}
+#else
+static void get_oob_gpio_config(HTC_HANDLE htc_handle, uint32_t *gpio_num,
+ uint32_t *gpio_flag)
+{
+}
+#endif
A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
{
@@ -540,12 +566,18 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
A_UINT16 htc_rdy_msg_id;
A_UINT8 i = 0;
HTC_PACKET *pRxBundlePacket, *pTempBundlePacket;
+ uint32_t gpio_num = 0;
+ uint32_t gpio_flag = 0;
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%pK) \n", HTCHandle));
AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n"));
do {
-
+ get_oob_gpio_config(HTCHandle, &gpio_num, &gpio_flag);
+ if (gpio_flag) {
+ if (hif_oob_gpio_init(target->hif_dev, gpio_num, gpio_flag))
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("OOB init failed\n"));
+ }
status = HIFStart(target->hif_dev);
if (A_FAILED(status)) {
AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIFStart failed\n"));
@@ -800,6 +832,7 @@ void HTCStop(HTC_HANDLE HTCHandle)
*/
HIFStop(target->hif_dev);
+ hif_oob_gpio_deinit(target->hif_dev);
#ifdef RX_SG_SUPPORT
LOCK_HTC_RX(target);
diff --git a/CORE/VOSS/inc/i_vos_types.h b/CORE/VOSS/inc/i_vos_types.h
index 756234d33189..d097eee96cc1 100644
--- a/CORE/VOSS/inc/i_vos_types.h
+++ b/CORE/VOSS/inc/i_vos_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -38,6 +38,10 @@
#include <linux/version.h>
#include <asm/div64.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
+#include <uapi/linux/sched/types.h>
+#endif
+
/**=========================================================================
\file i_vos_Types.h
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 825cfd88d815..15f878e0fc4e 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2019 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -413,7 +413,24 @@ static void vos_set_ac_specs_params(tMacOpenParameters *param,
}
}
-
+/**
+ * set_oob_gpio_config() - set oob gpio config
+ * @scn: pointer to scn
+ * @hdd_ctx: pointer to hdd_ctx
+ *
+ * Return NULL
+ */
+#ifdef CONFIG_GPIO_OOB
+static void set_oob_gpio_config(struct ol_softc *scn, hdd_context_t *hdd_ctx)
+{
+ scn->oob_gpio_num = hdd_ctx->cfg_ini->oob_gpio_num;
+ scn->oob_gpio_flag = hdd_ctx->cfg_ini->oob_gpio_flag;
+}
+#else
+static void set_oob_gpio_config(struct ol_softc *scn, hdd_context_t *hdd_ctx)
+{
+}
+#endif
/*---------------------------------------------------------------------------
\brief vos_open() - Open the vOSS Module
@@ -547,6 +564,7 @@ VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize )
scn->enableFwSelfRecovery = pHddCtx->cfg_ini->enableFwSelfRecovery;
scn->fastfwdump_host = pHddCtx->cfg_ini->fastfwdump;
scn->max_no_of_peers = pHddCtx->max_peers;
+ set_oob_gpio_config(scn, pHddCtx);
#ifdef WLAN_FEATURE_LPSS
scn->enablelpasssupport = pHddCtx->cfg_ini->enablelpasssupport;
#endif
diff --git a/Kbuild b/Kbuild
index e919a4d887a7..fd571a0802cf 100644
--- a/Kbuild
+++ b/Kbuild
@@ -396,6 +396,10 @@ HIF_COMMON_DIR := CORE/SERVICES/HIF/common
HIF_COMMON_OBJS := $(HIF_COMMON_DIR)/hif_bmi_reg_access.o \
$(HIF_COMMON_DIR)/hif_diag_reg_access.o
+ifeq ($(CONFIG_GPIO_OOB),y)
+HIF_DIR_OBJS += $(HIF_DIR)/hif_oob.o
+endif
+
HIF_SDIO_DIR := CORE/SERVICES/HIF/sdio
HIF_SDIO_OBJS := $(HIF_SDIO_DIR)/hif_sdio_send.o \
$(HIF_SDIO_DIR)/hif_sdio_dev.o \
@@ -415,6 +419,7 @@ HIF_SDIO_NATIVE_OBJS := $(HIF_SDIO_NATIVE_SRC_DIR)/hif.o \
$(HIF_SDIO_NATIVE_SRC_DIR)/hif_scatter.o
HIF_INC := -I$(WLAN_ROOT)/$(HIF_COMMON_DIR) \
+ -I$(WLAN_ROOT)/$(HIF_DIR) \
-I$(WLAN_ROOT)/$(HIF_SDIO_DIR) \
-I$(WLAN_ROOT)/$(HIF_SDIO_LINUX_DIR) \
-I$(WLAN_ROOT)/$(HIF_SDIO_NATIVE_INC_DIR) \
@@ -869,10 +874,15 @@ HIF_DIR := CORE/SERVICES/HIF
ifeq ($(CONFIG_HIF_PCI), 1)
HIF_PCIE_DIR := $(HIF_DIR)/PCIe
-HIF_INC := -I$(WLAN_ROOT)/$(HIF_PCIE_DIR)
+HIF_INC := -I$(WLAN_ROOT)/$(HIF_PCIE_DIR) \
+ -I$(WLAN_ROOT)/$(HIF_DIR)
HIF_OBJS := $(HIF_DIR)/ath_procfs.o
+ifeq ($(CONFIG_GPIO_OOB),y)
+HIF_OBJS += $(HIF_DIR)/hif_oob.o
+endif
+
HIF_PCIE_OBJS := $(HIF_PCIE_DIR)/copy_engine.o \
$(HIF_PCIE_DIR)/hif_pci.o \
$(HIF_PCIE_DIR)/if_pci.o \
@@ -884,10 +894,15 @@ endif
ifeq ($(CONFIG_HIF_USB), 1)
HIF_USB_DIR := $(HIF_DIR)/USB
-HIF_INC := -I$(WLAN_ROOT)/$(HIF_USB_DIR)
+HIF_INC := -I$(WLAN_ROOT)/$(HIF_USB_DIR) \
+ -I$(WLAN_ROOT)/$(HIF_DIR)
HIF_OBJS := $(HIF_DIR)/ath_procfs.o
+ifeq ($(CONFIG_GPIO_OOB),y)
+HIF_OBJS += $(HIF_DIR)/hif_oob.o
+endif
+
HIF_USB_OBJS := $(HIF_USB_DIR)/usbdrv.o \
$(HIF_USB_DIR)/hif_usb.o \
$(HIF_USB_DIR)/if_usb.o \
@@ -1633,6 +1648,10 @@ CDEFINES += -DCONFIG_NON_QC_PLATFORM
CDEFINES += -DTARGET_DUMP_FOR_NON_QC_PLATFORM
endif
+ifeq ($(CONFIG_GPIO_OOB),y)
+CDEFINES += -DCONFIG_GPIO_OOB
+endif
+
ifeq ($(CONFIG_NON_QC_PLATFORM), y)
ifeq ($(CONFIG_ROME_IF),pci)
CDEFINES += -DCONFIG_NON_QC_PLATFORM_PCI