diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 7744afe6b8ef..309fe17ccfc2 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -13477,6 +13477,9 @@ static void hdd_qdf_deinit(void) hdd_qdf_print_deinit(); } +static void hdd_driver_mode_change_register(void); +static void hdd_driver_mode_change_unregister(void); + /** * hdd_driver_load() - Perform the driver-level load operation * @@ -13549,6 +13552,7 @@ static int hdd_driver_load(void) } hdd_driver->state = driver_state_loaded; + hdd_driver_mode_change_register(); dsc_driver_trans_stop(hdd_driver->dsc_driver); /* psoc probe can happen in registration; do after 'load' transition */ @@ -13566,6 +13570,7 @@ pld_deinit: status = dsc_driver_trans_start(hdd_driver->dsc_driver, "unload"); QDF_BUG(QDF_IS_STATUS_SUCCESS(status)); + hdd_driver_mode_change_unregister(); pld_deinit(); param_destroy: @@ -13631,6 +13636,7 @@ static void hdd_driver_unload(void) hdd_warn("External threads are still active attempting " "driver unload anyway"); + hdd_driver_mode_change_unregister(); pld_deinit(); wlan_hdd_state_ctrl_param_destroy(); hdd_set_conparam(0); @@ -13938,49 +13944,45 @@ static void hdd_cleanup_present_mode(struct hdd_context *hdd_ctx, static int hdd_parse_driver_mode(const char *mode_str, enum QDF_GLOBAL_MODE *out_mode) { - int mode; - int errno; + QDF_STATUS status; + uint32_t mode; *out_mode = QDF_GLOBAL_MAX_MODE; - errno = kstrtoint(mode_str, 0, &mode); - if (!errno) - *out_mode = (enum QDF_GLOBAL_MODE)mode; + status = qdf_uint32_parse(mode_str, &mode); + if (QDF_IS_STATUS_ERROR(status)) + return qdf_status_to_os_return(status); - return errno; + if (mode >= QDF_GLOBAL_MAX_MODE) + return -ERANGE; + + *out_mode = (enum QDF_GLOBAL_MODE)mode; + + return 0; } /** - * __con_mode_handler() - Handles module param con_mode change - * @kmessage: con mode name on which driver to be bring up - * @kp: The associated kernel parameter + * __hdd_driver_mode_change() - Handles a driver mode change * @hdd_ctx: Pointer to the global HDD context + * @next_mode: the driver mode to transition to * - * This function is invoked when user updates con mode using sys entry, + * This function is invoked when user updates con_mode using sys entry, * to initialize and bring-up driver in that specific mode. * * Return: Errno */ -static int __con_mode_handler(const char *kmessage, - const struct kernel_param *kp, - struct hdd_context *hdd_ctx) +static int __hdd_driver_mode_change(struct hdd_context *hdd_ctx, + enum QDF_GLOBAL_MODE next_mode) { enum QDF_GLOBAL_MODE curr_mode; - enum QDF_GLOBAL_MODE next_mode; int errno; - hdd_info("Driver mode changing to %s", kmessage); + hdd_info("Driver mode changing to %d", next_mode); errno = wlan_hdd_validate_context(hdd_ctx); if (errno) return errno; - errno = hdd_parse_driver_mode(kmessage, &next_mode); - if (errno) { - hdd_err_rl("Failed to parse driver mode '%s'", kmessage); - return errno; - } - if (!is_con_mode_valid(next_mode)) { hdd_err_rl("Requested driver mode is invalid"); return -EINVAL; @@ -14045,7 +14047,7 @@ static int __con_mode_handler(const char *kmessage, /* con_mode is a global module parameter */ con_mode = next_mode; - hdd_info("Driver mode successfully changed to %s", kmessage); + hdd_info("Driver mode successfully changed to %d", next_mode); errno = 0; @@ -14056,7 +14058,7 @@ unlock: return errno; } -static int con_mode_handler(const char *kmessage, const struct kernel_param *kp) +static int hdd_driver_mode_change(enum QDF_GLOBAL_MODE mode) { struct hdd_driver *hdd_driver = hdd_driver_get(); struct hdd_context *hdd_ctx; @@ -14065,19 +14067,6 @@ static int con_mode_handler(const char *kmessage, const struct kernel_param *kp) hdd_enter(); - /* This handler will be invoked before module init when the wlan driver - * is loaded using 'insmod wlan.ko con_mode=5' for example. Return - * success in this case, as module init will bring up the correct - * con_mode when it runs. - */ - if (hdd_driver->state == driver_state_uninit) - return 0; - - if (hdd_driver->state == driver_state_deinit) { - hdd_err_rl("driver is unloaded so load again"); - return -EAGAIN; - } - status = dsc_driver_trans_start_wait(hdd_driver->dsc_driver, "mode change"); if (QDF_IS_STATUS_ERROR(status)) { @@ -14094,13 +14083,13 @@ static int con_mode_handler(const char *kmessage, const struct kernel_param *kp) goto trans_stop; if (!cds_wait_for_external_threads_completion(__func__)) { - hdd_warn("External threads are still active, can not change mode"); + hdd_warn("External threads still active, cannot change mode"); errno = -EAGAIN; goto trans_stop; } cds_ssr_protect(__func__); - errno = __con_mode_handler(kmessage, kp, hdd_ctx); + errno = __hdd_driver_mode_change(hdd_ctx, mode); cds_ssr_unprotect(__func__); trans_stop: @@ -14112,6 +14101,39 @@ exit: return errno; } +static int hdd_set_con_mode(enum QDF_GLOBAL_MODE mode) +{ + con_mode = mode; + + return 0; +} + +static int (*hdd_set_con_mode_cb)(enum QDF_GLOBAL_MODE mode) = hdd_set_con_mode; + +static void hdd_driver_mode_change_register(void) +{ + hdd_set_con_mode_cb = hdd_driver_mode_change; +} + +static void hdd_driver_mode_change_unregister(void) +{ + hdd_set_con_mode_cb = hdd_set_con_mode; +} + +static int con_mode_handler(const char *kmessage, const struct kernel_param *kp) +{ + enum QDF_GLOBAL_MODE mode; + int errno; + + errno = hdd_parse_driver_mode(kmessage, &mode); + if (errno) { + hdd_err_rl("Failed to parse driver mode '%s'", kmessage); + return errno; + } + + return hdd_set_con_mode_cb(mode); +} + static int con_mode_handler_ftm(const char *kmessage, const struct kernel_param *kp) {