You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/07/02 18:28:57 UTC

[incubator-nuttx] 01/02: wireless/bcm43xxx: set listen interval on lowpower

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 <an...@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 <an...@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));
+        }
     }
 }