diff options
| -rw-r--r-- | CORE/HDD/inc/wlan_hdd_cfg.h | 29 | ||||
| -rw-r--r-- | CORE/HDD/src/wlan_hdd_cfg.c | 9 | ||||
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.c | 41 | ||||
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/ol_if_athvar.h | 6 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/USB/if_usb.c | 78 | ||||
| -rw-r--r-- | CORE/VOSS/src/vos_api.c | 12 | ||||
| -rw-r--r-- | Kbuild | 3 |
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); @@ -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 |
