diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index de42c5e8fbbf..806d2c1a0e99 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -2858,14 +2858,15 @@ void hdd_psoc_idle_timer_start(struct hdd_context *hdd_ctx); void hdd_psoc_idle_timer_stop(struct hdd_context *hdd_ctx); /** - * hdd_psoc_idle_restart() - restart a previously shutdown idle psoc, if needed + * hdd_trigger_psoc_idle_restart() - trigger restart of a previously shutdown + * idle psoc, if needed * @hdd_ctx: the hdd context which should be restarted * * This API does nothing if the given psoc is already active. * * Return: Errno */ -int hdd_psoc_idle_restart(struct hdd_context *hdd_ctx); +int hdd_trigger_psoc_idle_restart(struct hdd_context *hdd_ctx); int hdd_start_adapter(struct hdd_adapter *adapter); void hdd_populate_random_mac_addr(struct hdd_context *hdd_ctx, uint32_t num); @@ -3669,4 +3670,21 @@ static inline void hdd_send_update_owe_info_event(struct hdd_adapter *adapter, } #endif +/** + * hdd_psoc_idle_shutdown - perform idle shutdown after interface inactivity + * timeout + * @device: pointer to struct device + * + * Return: 0 for success non-zero error code for failure + */ +int hdd_psoc_idle_shutdown(struct device *dev); + +/** + * hdd_psoc_idle_restart - perform idle restart after idle shutdown + * @device: pointer to struct device + * + * Return: 0 for success non-zero error code for failure + */ +int hdd_psoc_idle_restart(struct device *dev); + #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index eac7b6bbbb8a..b5b9dbed9c95 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -14304,7 +14304,7 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy, qdf_opmode_str(adapter->device_mode), qdf_opmode_str(new_mode)); - errno = hdd_psoc_idle_restart(hdd_ctx); + errno = hdd_trigger_psoc_idle_restart(hdd_ctx); if (errno) { hdd_err("Failed to restart psoc; errno:%d", errno); return -EINVAL; diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c index e68603165869..e86029a20fce 100644 --- a/core/hdd/src/wlan_hdd_driver_ops.c +++ b/core/hdd/src/wlan_hdd_driver_ops.c @@ -1394,6 +1394,33 @@ static void wlan_hdd_pld_remove(struct device *dev, enum pld_bus_type bus_type) hdd_exit(); } +/** + * wlan_hdd_pld_idle_shutdown() - wifi module idle shutdown after interface + * inactivity timeout has trigerred idle shutdown + * @dev: device to remove + * @pld_bus_type: PLD bus type + * + * Return: 0 for success and negative error code for failure + */ +static int wlan_hdd_pld_idle_shutdown(struct device *dev, + enum pld_bus_type bus_type) +{ + return hdd_psoc_idle_shutdown(dev); +} + +/** + * wlan_hdd_pld_idle_restart() - wifi module idle restart after idle shutdown + * @dev: device to remove + * @pld_bus_type: PLD bus type + * + * Return: 0 for success and negative error code for failure + */ +static int wlan_hdd_pld_idle_restart(struct device *dev, + enum pld_bus_type bus_type) +{ + return hdd_psoc_idle_restart(dev); +} + /** * wlan_hdd_pld_shutdown() - shutdown function registered to PLD * @dev: device to shutdown @@ -1689,6 +1716,8 @@ static int wlan_hdd_pld_runtime_resume(struct device *dev, struct pld_driver_ops wlan_drv_ops = { .probe = wlan_hdd_pld_probe, .remove = wlan_hdd_pld_remove, + .idle_shutdown = wlan_hdd_pld_idle_shutdown, + .idle_restart = wlan_hdd_pld_idle_restart, .shutdown = wlan_hdd_pld_shutdown, .reinit = wlan_hdd_pld_reinit, .crash_shutdown = wlan_hdd_pld_crash_shutdown, diff --git a/core/hdd/src/wlan_hdd_hostapd.c b/core/hdd/src/wlan_hdd_hostapd.c index 5ccb73c3c5ac..f474bc49af64 100644 --- a/core/hdd/src/wlan_hdd_hostapd.c +++ b/core/hdd/src/wlan_hdd_hostapd.c @@ -435,7 +435,7 @@ static int __hdd_hostapd_open(struct net_device *dev) return ret; /* ensure the physical soc is up */ - ret = hdd_psoc_idle_restart(hdd_ctx); + ret = hdd_trigger_psoc_idle_restart(hdd_ctx); if (ret) { hdd_err("Failed to start WLAN modules return"); return ret; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index f1177352094a..9273b607879a 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2181,7 +2181,7 @@ static int __hdd_mon_open(struct net_device *dev) hdd_mon_mode_ether_setup(dev); if (con_mode == QDF_GLOBAL_MONITOR_MODE) { - ret = hdd_psoc_idle_restart(hdd_ctx); + ret = hdd_trigger_psoc_idle_restart(hdd_ctx); if (ret) { hdd_err("Failed to start WLAN modules return"); return ret; @@ -3164,7 +3164,7 @@ static int __hdd_open(struct net_device *dev) return -EIO; } - ret = hdd_psoc_idle_restart(hdd_ctx); + ret = hdd_trigger_psoc_idle_restart(hdd_ctx); if (ret) { hdd_err("Failed to start WLAN modules return"); return ret; @@ -9162,7 +9162,7 @@ enum hdd_block_shutdown { }; /** - * hdd_psoc_idle_shutdown() - perform an idle shutdown on the given psoc + * __hdd_psoc_idle_shutdown() - perform an idle shutdown on the given psoc * @hdd_ctx: the hdd context which should be shutdown * * When no interfaces are "up" on a psoc, an idle shutdown timer is started. @@ -9172,7 +9172,7 @@ enum hdd_block_shutdown { * * Return: None */ -static void hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx) +static int __hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx) { struct osif_psoc_sync *psoc_sync; int errno; @@ -9197,13 +9197,41 @@ static void hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx) exit: hdd_exit(); + return errno; } -int hdd_psoc_idle_restart(struct hdd_context *hdd_ctx) +int hdd_psoc_idle_shutdown(struct device *dev) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + + return __hdd_psoc_idle_shutdown(hdd_ctx); +} + +static int __hdd_psoc_idle_restart(struct hdd_context *hdd_ctx) +{ + return hdd_wlan_start_modules(hdd_ctx, false); +} + +int hdd_psoc_idle_restart(struct device *dev) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + + return __hdd_psoc_idle_restart(hdd_ctx); +} + +int hdd_trigger_psoc_idle_restart(struct hdd_context *hdd_ctx) { QDF_BUG(rtnl_is_locked()); - return hdd_wlan_start_modules(hdd_ctx, false); + if (hdd_ctx->driver_status == DRIVER_MODULES_ENABLED) { + hdd_psoc_idle_timer_stop(hdd_ctx); + hdd_info("Driver modules already Enabled"); + return 0; + } + + pld_idle_restart(hdd_ctx->parent_dev, hdd_psoc_idle_restart); + + return 0; } /** @@ -9219,8 +9247,9 @@ static void hdd_psoc_idle_timeout_callback(void *priv) if (wlan_hdd_validate_context(hdd_ctx)) return; - hdd_debug("Psoc idle timeout elapsed; starting psoc shutdown"); - hdd_psoc_idle_shutdown(hdd_ctx); + hdd_info("Psoc idle timeout elapsed; starting psoc shutdown"); + + pld_idle_shutdown(hdd_ctx->parent_dev, hdd_psoc_idle_shutdown); } #ifdef WLAN_LOGGING_SOCK_SVC_ENABLE diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index a623be7e971b..727aee2f7347 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -758,7 +758,7 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy, } /* ensure physcial soc is up */ - ret = hdd_psoc_idle_restart(hdd_ctx); + ret = hdd_trigger_psoc_idle_restart(hdd_ctx); if (ret) { hdd_err("Failed to start the wlan_modules"); goto close_adapter; @@ -876,7 +876,7 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) return errno; /* ensure physical soc is up */ - errno = hdd_psoc_idle_restart(hdd_ctx); + errno = hdd_trigger_psoc_idle_restart(hdd_ctx); if (errno) return errno; diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index 63885a50fd5c..167c4f6e1db4 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -335,9 +335,9 @@ struct pld_driver_ops { void *bdev, void *id); void (*remove)(struct device *dev, enum pld_bus_type bus_type); - void (*idle_shutdown)(struct device *dev, + int (*idle_shutdown)(struct device *dev, enum pld_bus_type bus_type); - void (*idle_restart)(struct device *dev, + int (*idle_restart)(struct device *dev, enum pld_bus_type bus_type); void (*shutdown)(struct device *dev, enum pld_bus_type bus_type); @@ -649,20 +649,20 @@ bool pld_have_platform_driver_support(struct device *dev); * @dev: pointer to struct dev * @shutdown_cb: pointer to hdd psoc idle shutdown callback handler * - * Return: none + * Return: 0 for success and non-zero negative error code for failure */ -void pld_idle_shutdown(struct device *dev, - void (*shutdown_cb)(struct device *dev)); +int pld_idle_shutdown(struct device *dev, + int (*shutdown_cb)(struct device *dev)); /** * pld_idle_restart - request idle restart callback from platform driver * @dev: pointer to struct dev * @restart_cb: pointer to hdd psoc idle restart callback handler * - * Return: none + * Return: 0 for success and non-zero negative error code for failure */ -void pld_idle_restart(struct device *dev, - void (*restart_cb)(struct device *dev)); +int pld_idle_restart(struct device *dev, + int (*restart_cb)(struct device *dev)); #if defined(CONFIG_WCNSS_MEM_PRE_ALLOC) && defined(FEATURE_SKB_PRE_ALLOC) diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index 8eb3cf3e8edf..dc365d9bc291 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -1797,42 +1797,52 @@ void pld_block_shutdown(struct device *dev, bool status) } } -void pld_idle_shutdown(struct device *dev, - void (*shutdown_cb)(struct device *dev)) +int pld_idle_shutdown(struct device *dev, + int (*shutdown_cb)(struct device *dev)) { + int errno = -EINVAL; enum pld_bus_type type; if (!shutdown_cb) - return; + return -EINVAL; type = pld_get_bus_type(dev); switch (type) { + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: case PLD_BUS_TYPE_SNOC: - shutdown_cb(dev); - break; case PLD_BUS_TYPE_PCIE: + errno = shutdown_cb(dev); break; default: + pr_err("Invalid device type %d\n", type); break; } + + return errno; } -void pld_idle_restart(struct device *dev, - void (*restart_cb)(struct device *dev)) +int pld_idle_restart(struct device *dev, + int (*restart_cb)(struct device *dev)) { + int errno = -EINVAL; enum pld_bus_type type; if (!restart_cb) - return; + return -EINVAL; type = pld_get_bus_type(dev); switch (type) { + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: case PLD_BUS_TYPE_SNOC: - restart_cb(dev); - break; case PLD_BUS_TYPE_PCIE: + errno = restart_cb(dev); break; default: + pr_err("Invalid device type %d\n", type); break; } + + return errno; }