summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CORE/HDD/inc/wlan_hdd_cfg.h29
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg.c9
-rw-r--r--CORE/SERVICES/BMI/ol_fw.c41
-rw-r--r--CORE/SERVICES/BMI/ol_fw.h3
-rw-r--r--CORE/SERVICES/COMMON/ol_if_athvar.h6
-rw-r--r--CORE/SERVICES/HIF/USB/if_usb.c78
-rw-r--r--CORE/VOSS/src/vos_api.c12
-rw-r--r--Kbuild3
8 files changed, 157 insertions, 24 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_cfg.h b/CORE/HDD/inc/wlan_hdd_cfg.h
index c11c47c98e4b..56f631d8515c 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -2973,6 +2973,32 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */
#define CFG_ENABLE_FW_SELF_RECOVERY_ENABLE ( 1 )
#define CFG_ENABLE_FW_SELF_RECOVERY_DEFAULT ( CFG_ENABLE_FW_SELF_RECOVERY_DISABLE )
+/*
+ * Enable/Disable warm reset for USB
+ */
+/*
+ * <ini>
+ * enable_usb_warm_reset - Enable/Disable warm reset for USB
+ * @Min: 0
+ * @Max: 1
+ * @Default: 0
+ *
+ * This ini is used to control warm reset feature for USB solution.
+ * When enabled, dedicated binary will be downloaded to target during
+ * initialization, as well as target be notified when USB disconnected.
+ *
+ * Usage: Internal
+ *
+ * 1: Enable
+ * 0: Disable
+ *
+ * </ini>
+ */
+#define CFG_ENABLE_USB_WARM_RESET_NAME "enable_usb_warm_reset"
+#define CFG_ENABLE_USB_WARM_RESET_DISABLE ( 0 )
+#define CFG_ENABLE_USB_WARM_RESET_ENABLE ( 1 )
+#define CFG_ENABLE_USB_WARM_RESET_DEFAULT ( CFG_ENABLE_USB_WARM_RESET_DISABLE )
+
#ifdef WLAN_FEATURE_11AC
//Macro to handle maximum receive AMPDU size configuration
#define CFG_VHT_AMPDU_LEN_EXPONENT_NAME "gVhtAmpduLenExponent"
@@ -5846,6 +5872,9 @@ struct hdd_config {
v_BOOL_t enablefwprint;
v_BOOL_t enablefwlog;
v_BOOL_t enableFwSelfRecovery;
+#ifdef FEATURE_USB_WARM_RESET
+ v_BOOL_t enable_usb_warm_reset;
+#endif
v_BOOL_t fP2pListenOffload;
#ifdef WLAN_FEATURE_11AC
v_U8_t fVhtAmpduLenExponent;
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index e370dedc19a2..6c3e37ec4fc8 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -2975,6 +2975,15 @@ REG_TABLE_ENTRY g_registry_table[] =
CFG_ENABLE_FW_SELF_RECOVERY_DISABLE,
CFG_ENABLE_FW_SELF_RECOVERY_ENABLE),
+#ifdef FEATURE_USB_WARM_RESET
+ REG_VARIABLE( CFG_ENABLE_USB_WARM_RESET_NAME, WLAN_PARAM_Integer,
+ hdd_config_t, enable_usb_warm_reset,
+ VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT,
+ CFG_ENABLE_USB_WARM_RESET_DEFAULT,
+ CFG_ENABLE_USB_WARM_RESET_DISABLE,
+ CFG_ENABLE_USB_WARM_RESET_ENABLE),
+#endif
+
#ifdef IPA_OFFLOAD
REG_VARIABLE( CFG_IPA_OFFLOAD_CONFIG_NAME, WLAN_PARAM_HexInteger,
hdd_config_t, IpaConfig,
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c
index 37ad17498aee..60d004bddfa9 100644
--- a/CORE/SERVICES/BMI/ol_fw.c
+++ b/CORE/SERVICES/BMI/ol_fw.c
@@ -740,6 +740,9 @@ defined(CONFIG_NON_QC_PLATFORM_PCI)
return -1;
}
break;
+ case ATH_USB_WARM_RESET_FILE:
+ filename = QCA_USB_WARM_RESET_FILE;
+ break;
}
status = request_firmware(&fw_entry, filename, scn->sc_osdev->device);
@@ -2178,6 +2181,41 @@ void ol_transfer_codeswap_struct(struct ol_softc *scn) {
#endif
#endif
+#ifdef FEATURE_USB_WARM_RESET
+static inline int ol_download_usb_warm_reset_firmeware(struct ol_softc *scn)
+{
+ uint32_t warm_reset_load_status = 0;
+ uint32_t address = BMI_SEGMENTED_WRITE_ADDR;
+
+ if (scn->enable_usb_warm_reset) {
+ BMIReadMemory(scn->hif_hdl,
+ host_interest_item_address(scn->target_type,
+ offsetof(struct host_interest_s, hi_minidump)),
+ (uint8_t *)&warm_reset_load_status,
+ sizeof(warm_reset_load_status), scn);
+
+ if (!warm_reset_load_status) {
+ /* first load, download warm_reset.bin */
+ if (ol_transfer_bin_file(scn, ATH_USB_WARM_RESET_FILE,
+ address, TRUE) != EOK)
+ return -1;
+ /*
+ * FW will update the hi_minidump
+ * after recv HIFDiagWriteWARMRESET
+ */
+ /* fall-thru */
+ }
+ }
+
+ return EOK;
+}
+#else
+static inline int ol_download_usb_warm_reset_firmeware(struct ol_softc *scn)
+{
+ return EOK;
+}
+#endif
+
int ol_download_firmware(struct ol_softc *scn)
{
uint32_t param, address = 0;
@@ -2325,6 +2363,9 @@ int ol_download_firmware(struct ol_softc *scn)
}
}
+ if (ol_download_usb_warm_reset_firmeware(scn) != EOK)
+ return -1;
+
/* Download Target firmware - TODO point to target specific files in runtime */
if (ol_transfer_bin_file(scn, ATH_FIRMWARE_FILE, address, TRUE) != EOK) {
return -1;
diff --git a/CORE/SERVICES/BMI/ol_fw.h b/CORE/SERVICES/BMI/ol_fw.h
index aca4961bf50e..0b28b5ddb54f 100644
--- a/CORE/SERVICES/BMI/ol_fw.h
+++ b/CORE/SERVICES/BMI/ol_fw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -54,6 +54,7 @@
#define QCA_BOARD_DATA_FILE "fakeboar.bin"
#define QCA_OTP_FILE "otp.bin"
#define QCA_SETUP_FILE "athsetup.bin"
+#define QCA_USB_WARM_RESET_FILE "warm_reset.bin"
#define AR61X4_SINGLE_FILE "qca61x4.bin"
#define QCA_FIRMWARE_EPPING_FILE "epping.bin"
diff --git a/CORE/SERVICES/COMMON/ol_if_athvar.h b/CORE/SERVICES/COMMON/ol_if_athvar.h
index 03fc4d330b55..52f1fd29c153 100644
--- a/CORE/SERVICES/COMMON/ol_if_athvar.h
+++ b/CORE/SERVICES/COMMON/ol_if_athvar.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -64,6 +64,7 @@ typedef enum _ATH_BIN_FILE {
ATH_BOARD_DATA_FILE,
ATH_FLASH_FILE,
ATH_SETUP_FILE,
+ ATH_USB_WARM_RESET_FILE,
} ATH_BIN_FILE;
typedef enum _ol_target_status {
@@ -248,6 +249,9 @@ struct ol_softc {
bool enablefwlog; /* enable fwlog */
/* enable FW self-recovery for Rome USB */
bool enableFwSelfRecovery;
+#ifdef FEATURE_USB_WARM_RESET
+ bool enable_usb_warm_reset;
+#endif
#ifdef HIF_USB
/* structure to save FW RAM dump (Rome USB) */
struct fw_ramdump *ramdump[FW_RAM_SEG_CNT];
diff --git a/CORE/SERVICES/HIF/USB/if_usb.c b/CORE/SERVICES/HIF/USB/if_usb.c
index b934ac2c2567..2a3ff1083d81 100644
--- a/CORE/SERVICES/HIF/USB/if_usb.c
+++ b/CORE/SERVICES/HIF/USB/if_usb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 2018 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -247,6 +247,44 @@ err_alloc:
return ret;
}
+#ifdef FEATURE_USB_WARM_RESET
+static inline void hif_diag_write_reset_type(struct hif_usb_softc *sc)
+{
+ struct ol_softc *scn = sc->ol_sc;
+
+ if (scn->enable_usb_warm_reset)
+ HIFDiagWriteWARMRESET(sc->interface, 0, 0);
+ else /* do cold reset */
+ HIFDiagWriteCOLDRESET(sc->hif_device);
+}
+
+/*
+ * When unregister USB driver, ol_sc context freed,
+ * and here to save/obtain the warm_reset flag.
+ */
+static inline int hif_usb_warm_reset_flag(struct ol_softc *scn, int set)
+{
+ static int g_warm_reset_flag;
+
+ if (set && scn)
+ g_warm_reset_flag = scn->enable_usb_warm_reset;
+ else
+ return g_warm_reset_flag;
+
+ return 0;
+}
+#else
+static inline void hif_diag_write_reset_type(struct hif_usb_softc *sc)
+{
+ HIFDiagWriteCOLDRESET(sc->hif_device);
+}
+
+static inline int hif_usb_warm_reset_flag(struct ol_softc *scn, int set)
+{
+ return 0;
+}
+#endif
+
static void hif_usb_remove(struct usb_interface *interface)
{
HIF_DEVICE_USB *device = usb_get_intfdata(interface);
@@ -260,6 +298,10 @@ static void hif_usb_remove(struct usb_interface *interface)
if (!sc)
return;
+ scn = sc->ol_sc;
+ if (!scn)
+ return;
+
pr_info("Try to remove hif_usb!\n");
/* wait __hdd_wlan_exit until finished and no more than 4 seconds*/
@@ -283,8 +325,9 @@ static void hif_usb_remove(struct usb_interface *interface)
schedule_timeout(msecs_to_jiffies(DELAY_FOR_TARGET_READY));
set_current_state(TASK_RUNNING);
- /* do cold reset */
- HIFDiagWriteCOLDRESET(sc->hif_device);
+ /* Save to global for later unregister phase */
+ hif_usb_warm_reset_flag(scn, true);
+ hif_diag_write_reset_type(sc);
unregister_reboot_notifier(&sc->reboot_notifier);
usb_put_dev(interface_to_usbdev(interface));
@@ -292,7 +335,6 @@ static void hif_usb_remove(struct usb_interface *interface)
HIF_USB_UNLOAD_STATE_DRV_DEREG)
atomic_set(&hif_usb_unload_state,
HIF_USB_UNLOAD_STATE_TARGET_RESET);
- scn = sc->ol_sc;
/* The logp is set by target failure's ol_ramdump_handler.
* Coldreset occurs and do this disconnect cb, try to issue
@@ -325,11 +367,6 @@ static void hif_usb_remove(struct usb_interface *interface)
pr_info("hif_usb_remove!!!!!!\n");
}
-#ifdef WLAN_LINK_UMAC_SUSPEND_WITH_BUS_SUSPEND
-void hdd_suspend_wlan(void (*callback) (void *callbackContext),
- void *callbackContext);
-#endif
-
static int hif_usb_suspend(struct usb_interface *interface, pm_message_t state)
{
HIF_DEVICE_USB *device = usb_get_intfdata(interface);
@@ -357,10 +394,6 @@ static int hif_usb_suspend(struct usb_interface *interface, pm_message_t state)
return 0;
}
-#ifdef WLAN_LINK_UMAC_SUSPEND_WITH_BUS_SUSPEND
-void hdd_resume_wlan(void);
-#endif
-
static int hif_usb_resume(struct usb_interface *interface)
{
HIF_DEVICE_USB *device = usb_get_intfdata(interface);
@@ -557,15 +590,16 @@ deregister:
if (atomic_read(&hif_usb_unload_state) !=
HIF_USB_UNLOAD_STATE_TARGET_RESET)
goto finish;
- timeleft = wait_event_interruptible_timeout(
- hif_usb_unload_event_wq,
- atomic_read(&hif_usb_unload_state) ==
- HIF_USB_UNLOAD_STATE_DEV_DISCONNECTED,
- HIF_USB_UNLOAD_TIMEOUT);
- if (timeleft <= 0)
- pr_err("Fail to wait from DRV_DEREG to DISCONNECT,"
- "timeleft = %ld \n\r",
- timeleft);
+ if (!hif_usb_warm_reset_flag(NULL, false)) {
+ timeleft = wait_event_interruptible_timeout(
+ hif_usb_unload_event_wq,
+ atomic_read(&hif_usb_unload_state) ==
+ HIF_USB_UNLOAD_STATE_DEV_DISCONNECTED,
+ HIF_USB_UNLOAD_TIMEOUT);
+ if (timeleft <= 0)
+ pr_err("Fail to wait from DRV_DEREG to DISCONNECT, timeleft = %ld \n\r",
+ timeleft);
+ }
finish:
usb_unregister_notify(&hif_usb_dev_nb);
pr_info("hif_unregister_driver!!!!!!\n");
diff --git a/CORE/VOSS/src/vos_api.c b/CORE/VOSS/src/vos_api.c
index 944ba8406925..97bc8a26413d 100644
--- a/CORE/VOSS/src/vos_api.c
+++ b/CORE/VOSS/src/vos_api.c
@@ -238,6 +238,17 @@ static inline void vos_runtime_pm_config(struct ol_softc *scn,
hdd_context_t *pHddCtx) { }
#endif
+#ifdef FEATURE_USB_WARM_RESET
+static inline void vos_usb_warm_reset_config(struct ol_softc *scn,
+ hdd_context_t *pHddCtx)
+{
+ scn->enable_usb_warm_reset = pHddCtx->cfg_ini->enable_usb_warm_reset;
+}
+#else
+static inline void vos_usb_warm_reset_config(struct ol_softc *scn,
+ hdd_context_t *pHddCtx) { }
+#endif
+
#if defined (FEATURE_SECURE_FIRMWARE) && defined (FEATURE_FW_HASH_CHECK)
static inline void vos_fw_hash_check_config(struct ol_softc *scn,
hdd_context_t *pHddCtx)
@@ -541,6 +552,7 @@ VOS_STATUS vos_open( v_CONTEXT_t *pVosContext, v_SIZE_t hddContextSize )
scn->enableRamdumpCollection = pHddCtx->cfg_ini->is_ramdump_enabled;
scn->enable_self_recovery = pHddCtx->cfg_ini->enableSelfRecovery;
+ vos_usb_warm_reset_config(scn, pHddCtx);
vos_fw_hash_check_config(scn, pHddCtx);
vos_runtime_pm_config(scn, pHddCtx);
diff --git a/Kbuild b/Kbuild
index 319ca6a8003e..19cf836a0717 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1379,6 +1379,9 @@ CDEFINES += -DDEBUG_HL_LOGGING
ifeq ($(CONFIG_QOS_FWD_SUPPORT), y)
CDEFINES += -DQOS_FWD_SUPPORT
endif
+ifeq ($(CONFIG_USB_WARM_RESET), y)
+CDEFINES += -DFEATURE_USB_WARM_RESET
+endif
endif
#Enable FW logs through ini