You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2021/10/03 20:36:17 UTC

[incubator-nuttx] branch master updated: bcm43xxx: fixed an issue with wrong devif_timer() invocations on bcmf_netdev_notify_tx_done events that provoked massive TCP spurious retransmissions;

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new df40531  bcm43xxx: fixed an issue with wrong devif_timer() invocations on bcmf_netdev_notify_tx_done events that provoked massive TCP spurious retransmissions;
df40531 is described below

commit df40531a070e6048ab749a97755f5187aea7dec7
Author: Alexander Lunev <al...@mail.ru>
AuthorDate: Sat Oct 2 06:26:43 2021 +0300

    bcm43xxx: fixed an issue with wrong devif_timer() invocations
    on bcmf_netdev_notify_tx_done events
    that provoked massive TCP spurious retransmissions;
    
    bcm43xxx: fixed an issue with sporadic stalls of TX poll timer.
---
 drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h |  1 +
 drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c | 71 +++++++++++++++++++----
 2 files changed, 62 insertions(+), 10 deletions(-)

diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
index bb46852..bc465cc 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_driver.h
@@ -66,6 +66,7 @@ struct bcmf_dev_s
   bool bc_bifup;             /* true:ifup false:ifdown */
   struct wdog_s bc_txpoll;   /* TX poll timer */
   struct work_s bc_irqwork;  /* For deferring interrupt work to the work queue */
+  struct work_s bc_rxwork;   /* For deferring rx work to the work queue */
   struct work_s bc_pollwork; /* For deferring poll work to the work queue */
 
   /* This holds the information visible to the NuttX network */
diff --git a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
index 709a138..a6bd1c5 100644
--- a/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
+++ b/drivers/wireless/ieee80211/bcm43xxx/bcmf_netdev.c
@@ -107,7 +107,7 @@ static int  bcmf_transmit(FAR struct bcmf_dev_s *priv,
                           FAR struct bcmf_frame_s *frame);
 static void bcmf_receive(FAR struct bcmf_dev_s *priv);
 static int  bcmf_txpoll(FAR struct net_driver_s *dev);
-static void bcmf_rxpoll(FAR void *arg);
+static void bcmf_rxpoll_work(FAR void *arg);
 
 /* Watchdog timer expirations */
 
@@ -484,7 +484,47 @@ static int bcmf_txpoll(FAR struct net_driver_s *dev)
 }
 
 /****************************************************************************
- * Name: bcmf_rxpoll
+ * Function: bcmf_txdone_poll_work
+ *
+ * Description:
+ *   The function is called in order to perform an out-of-sequence TX poll.
+ *   This is done:
+ *
+ *   1. After completion of a transmission (bcmf_netdev_notify_tx_done), and
+ *   2. When new TX data is available (bcmf_txavail).
+ *
+ * Input Parameters:
+ *   arg - context of device to use
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+static void bcmf_txdone_poll_work(FAR void *arg)
+{
+  FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)arg;
+
+  /* Check if there is room in the hardware to hold another packet. */
+
+  net_lock();
+
+  if (bcmf_netdev_alloc_tx_frame(priv) == OK)
+    {
+      /* If so, then poll the network for new XMIT data */
+
+      priv->bc_dev.d_buf = priv->cur_tx_frame->data;
+      priv->bc_dev.d_len = 0;
+      devif_timer(&priv->bc_dev, 0, bcmf_txpoll);
+    }
+
+  net_unlock();
+}
+
+/****************************************************************************
+ * Name: bcmf_rxpoll_work
  *
  * Description:
  *   Process RX frames
@@ -496,11 +536,10 @@ static int bcmf_txpoll(FAR struct net_driver_s *dev)
  *   OK on success
  *
  * Assumptions:
- *   The network is locked.
  *
  ****************************************************************************/
 
-static void bcmf_rxpoll(FAR void *arg)
+static void bcmf_rxpoll_work(FAR void *arg)
 {
   FAR struct bcmf_dev_s *priv = (FAR struct bcmf_dev_s *)arg;
 
@@ -539,7 +578,11 @@ void bcmf_netdev_notify_tx_done(FAR struct bcmf_dev_s *priv)
 {
   /* Schedule to perform a poll for new Tx data the worker thread. */
 
-  work_queue(BCMFWORK, &priv->bc_pollwork, bcmf_poll_work, priv, 0);
+  if (work_available(&priv->bc_pollwork))
+    {
+      work_queue(BCMFWORK, &priv->bc_pollwork,
+                 bcmf_txdone_poll_work, priv, 0);
+    }
 }
 
 /****************************************************************************
@@ -556,7 +599,7 @@ void bcmf_netdev_notify_rx(FAR struct bcmf_dev_s *priv)
 {
   /* Queue a job to process RX frames */
 
-  work_queue(BCMFWORK, &priv->bc_pollwork, bcmf_rxpoll, priv, 0);
+  work_queue(BCMFWORK, &priv->bc_rxwork, bcmf_rxpoll_work, priv, 0);
 }
 
 /****************************************************************************
@@ -566,13 +609,12 @@ void bcmf_netdev_notify_rx(FAR struct bcmf_dev_s *priv)
  *   Perform periodic polling from the worker thread
  *
  * Input Parameters:
- *   arg - The argument passed when work_queue() as called.
+ *   arg - The argument passed when work_queue() was called.
  *
  * Returned Value:
  *   OK on success
  *
  * Assumptions:
- *   The network is locked.
  *
  ****************************************************************************/
 
@@ -610,9 +652,10 @@ static void bcmf_poll_work(FAR void *arg)
 
   /* Setup the watchdog poll timer again */
 
+exit_unlock:
   wd_start(&priv->bc_txpoll, BCMF_WDDELAY,
            bcmf_poll_expiry, (wdparm_t)priv);
-exit_unlock:
+
   net_unlock();
 }
 
@@ -639,7 +682,15 @@ static void bcmf_poll_expiry(wdparm_t arg)
 
   /* Schedule to perform the interrupt processing on the worker thread. */
 
-  work_queue(BCMFWORK, &priv->bc_pollwork, bcmf_poll_work, priv, 0);
+  if (work_available(&priv->bc_pollwork))
+    {
+      work_queue(BCMFWORK, &priv->bc_pollwork, bcmf_poll_work, priv, 0);
+    }
+  else
+    {
+      wd_start(&priv->bc_txpoll, BCMF_WDDELAY,
+           bcmf_poll_expiry, (wdparm_t)priv);
+    }
 }
 
 /****************************************************************************