This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 5048be1bfe198c5a1cfbcabec60cd86e80f3aa19 Author: chao.an <anc...@xiaomi.com> AuthorDate: Sat Jul 2 12:51:35 2022 +0800 wireless/bcm43xxx: set listen interval on lowpower set listen interval dtim(Delivery Traffic Indication Message) on lowpower mode Signed-off-by: chao.an <anc...@xiaomi.com> --- drivers/wireless/ieee80211/bcm43xxx/Kconfig | 14 +++- drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c | 67 ++++++++++-------- drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h | 11 +-- drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c | 83 ++++++++++++++++------- 4 files changed, 118 insertions(+), 57 deletions(-) diff --git a/drivers/wireless/ieee80211/bcm43xxx/Kconfig b/drivers/wireless/ieee80211/bcm43xxx/Kconfig index 4d5f57c95e..9463b5e9bf 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/Kconfig +++ b/drivers/wireless/ieee80211/bcm43xxx/Kconfig @@ -146,12 +146,24 @@ config IEEE80211_BROADCOM_DEFAULT_COUNTRY if IEEE80211_BROADCOM_LOWPOWER -config IEEE80211_BROADCOM_LOWPOWER_TIMEOUT +config IEEE80211_BROADCOM_LP_DTIM_TIMEOUT int "Broadcom BCMF lower power timeout(second)" default 10 ---help--- This parameter should be enable the bcmf lower power timeout +config IEEE80211_BROADCOM_LP_DTIM_INTERVAL + int "Broadcom BCMF listen interval dtim(millisecond)" + default 500 + ---help--- + This parameter should be set the listen interval dtim in milliseconds + +config IEEE80211_BROADCOM_LP_IFDOWN_TIMEOUT + int "Broadcom BCMF lower power if down timeout(second)" + default 600 + ---help--- + This parameter should be enable the bcmf lower power if down timeout + endif # IEEE80211_BROADCOM_LOWPOWER if IEEE80211_BROADCOM_FULLMAC diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c index cc761c5b9b..40f08a44fd 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.c @@ -426,34 +426,6 @@ int bcmf_driver_download_clm(FAR struct bcmf_dev_s *priv) #endif #endif /* CONFIG_IEEE80211_BROADCOM_HAVE_CLM */ -int bcmf_wl_set_pm(FAR struct bcmf_dev_s *priv, int mode) -{ - int interface = CHIP_STA_INTERFACE; - uint32_t out_len; - uint32_t value; - int ret; - - /* Set default power save mode */ - -#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER - if (priv->lp_mode != mode) -#endif - { - out_len = 4; - value = mode; - ret = bcmf_cdc_ioctl(priv, interface, true, WLC_SET_PM, - (uint8_t *)&value, &out_len); -#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER - if (ret == OK) - { - priv->lp_mode = mode; - } -#endif - } - - return ret; -} - int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active) { int interface = CHIP_STA_INTERFACE; @@ -492,7 +464,10 @@ int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active) /* Set default power save mode */ - ret = bcmf_wl_set_pm(priv, PM_OFF); + out_len = 4; + value = PM_OFF; + ret = bcmf_cdc_ioctl(priv, interface, true, WLC_SET_PM, + (FAR uint8_t *)&value, &out_len); if (ret != OK) { goto errout_in_sdio_active; @@ -1819,3 +1794,37 @@ int bcmf_wl_get_country(FAR struct bcmf_dev_s *priv, FAR struct iwreq *iwr) return ret; } + +#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER + +int bcmf_wl_set_dtim(FAR struct bcmf_dev_s *priv, + uint32_t interval_ms) +{ + uint32_t value = interval_ms / 100; + uint32_t out_len; + int ret; + + out_len = sizeof(interval_ms); + + if (value == 0) + { + return -EINVAL; + } + + if (priv->lp_dtim == interval_ms) + { + return OK; + } + + ret = bcmf_cdc_iovar_request(priv, CHIP_STA_INTERFACE, true, + IOVAR_STR_LISTEN_INTERVAL_DTIM, + (FAR uint8_t *)&value, &out_len); + if (ret == OK) + { + priv->lp_dtim = interval_ms; + } + + return ret; +} + +#endif diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h index 97651d3b2a..5433a0382e 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h @@ -96,9 +96,10 @@ struct bcmf_dev_s int auth_status; /* Authentication status */ #ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER - struct work_s lp_work; /* Low power work to work queue */ - int lp_mode; /* Low power mode */ - sclock_t lp_ticks; /* Ticks of last tx time */ + struct work_s lp_work_ifdown; /* Ifdown work to work queue */ + struct work_s lp_work_dtim; /* Low power work to work queue */ + int lp_dtim; /* Listen interval Delivery Traffic Indication Message */ + sclock_t lp_ticks; /* Ticks of last tx time */ #endif }; @@ -146,7 +147,9 @@ int bcmf_wl_enable(FAR struct bcmf_dev_s *priv, bool enable); int bcmf_wl_active(FAR struct bcmf_dev_s *priv, bool active); -int bcmf_wl_set_pm(FAR struct bcmf_dev_s *priv, int mode); +#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER +int bcmf_wl_set_dtim(FAR struct bcmf_dev_s *priv, uint32_t interval_ms); +#endif int bcmf_wl_set_country_code(FAR struct bcmf_dev_s *priv, int interface, FAR void *code); diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c index 536b5c311f..fd07781b6c 100644 --- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c +++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c @@ -88,6 +88,12 @@ # define CONFIG_IEEE80211_BROADCOM_NINTERFACES 1 #endif +#ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER +# define LP_IFDOWN_TIMEOUT CONFIG_IEEE80211_BROADCOM_LP_IFDOWN_TIMEOUT +# define LP_DTIM_TIMEOUT CONFIG_IEEE80211_BROADCOM_LP_DTIM_TIMEOUT +# define LP_DTIM_INTERVAL CONFIG_IEEE80211_BROADCOM_LP_DTIM_INTERVAL +#endif + /* This is a helper pointer for accessing the contents of Ethernet header */ #define BUF ((FAR struct eth_hdr_s *)priv->bc_dev.d_buf) @@ -762,9 +768,14 @@ static int bcmf_ifdown(FAR struct net_driver_s *dev) priv->bc_bifup = false; #ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER - if (!work_available(&priv->lp_work)) + if (!work_available(&priv->lp_work_dtim)) { - work_cancel(LPWORK, &priv->lp_work); + work_cancel(LPWORK, &priv->lp_work_dtim); + } + + if (!work_available(&priv->lp_work_ifdown)) + { + work_cancel(LPWORK, &priv->lp_work_ifdown); } #endif @@ -789,32 +800,56 @@ static int bcmf_ifdown(FAR struct net_driver_s *dev) ****************************************************************************/ #ifdef CONFIG_IEEE80211_BROADCOM_LOWPOWER -static void bcmf_lowpower_work(FAR void *arg) +static bool bcmf_lowpower_expiration(FAR struct bcmf_dev_s *priv, + FAR struct work_s *work, + worker_t worker, clock_t timeout) { - FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)arg; - irqstate_t flags; clock_t ticks; - clock_t timeout; if (priv->bc_bifup) { /* Disable the hardware interrupt */ - flags = enter_critical_section(); - ticks = clock_systime_ticks() - priv->lp_ticks; - timeout = SEC2TICK(CONFIG_IEEE80211_BROADCOM_LOWPOWER_TIMEOUT); if (ticks >= timeout) { - leave_critical_section(flags); - bcmf_wl_set_pm(priv, PM_MAX); + return true; } else { - work_queue(LPWORK, &priv->lp_work, bcmf_lowpower_work, - priv, timeout - ticks); - leave_critical_section(flags); + work_queue(LPWORK, work, worker, priv, timeout - ticks); + } + } + + return false; +} + +static void bcmf_lowpower_work(FAR void *arg) +{ + FAR struct bcmf_dev_s *priv = arg; + + if (bcmf_lowpower_expiration(arg, &priv->lp_work_dtim, bcmf_lowpower_work, + SEC2TICK(LP_DTIM_TIMEOUT))) + { + if (priv->bc_bifup) + { + bcmf_wl_set_dtim(priv, LP_DTIM_INTERVAL); + } + } +} + +static void bcmf_lowpower_ifdown_work(FAR void *arg) +{ + FAR struct bcmf_dev_s *priv = arg; + + if (bcmf_lowpower_expiration(arg, &priv->lp_work_ifdown, + bcmf_lowpower_ifdown_work, + SEC2TICK(LP_IFDOWN_TIMEOUT))) + { + if (priv->bc_bifup) + { + netdev_ifdown(&priv->bc_dev); } } } @@ -832,24 +867,26 @@ static void bcmf_lowpower_work(FAR void *arg) static void bcmf_lowpower_poll(FAR struct bcmf_dev_s *priv) { - irqstate_t flags; - if (priv->bc_bifup) { - bcmf_wl_set_pm(priv, PM_FAST); + bcmf_wl_set_dtim(priv, 100); /* Listen-iterval to 100 ms */ /* Disable the hardware interrupt */ - flags = enter_critical_section(); - priv->lp_ticks = clock_systime_ticks(); - if (work_available(&priv->lp_work) && priv->lp_mode != PM_MAX) + if (work_available(&priv->lp_work_dtim) && + priv->lp_dtim != LP_DTIM_INTERVAL) { - work_queue(LPWORK, &priv->lp_work, bcmf_lowpower_work, priv, - SEC2TICK(CONFIG_IEEE80211_BROADCOM_LOWPOWER_TIMEOUT)); + work_queue(LPWORK, &priv->lp_work_dtim, bcmf_lowpower_work, priv, + SEC2TICK(LP_DTIM_TIMEOUT)); } - leave_critical_section(flags); + if (work_available(&priv->lp_work_ifdown)) + { + work_queue(LPWORK, &priv->lp_work_ifdown, + bcmf_lowpower_ifdown_work, priv, + SEC2TICK(LP_IFDOWN_TIMEOUT)); + } } }