AR6000 netif_queue_stop non stop, Bug?
authorivan_p@hotbox.ru <ivan_p@hotbox.ru>
Thu, 26 Mar 2009 12:03:03 +0000 (15:03 +0300)
committerWerner Almesberger <werner@openmoko.org>
Tue, 31 Mar 2009 03:42:22 +0000 (00:42 -0300)
This patch resolves the following issue:
http://lists.openmoko.org/pipermail/openmoko-kernel/2009-March/009643.html

Changed: prevent rescheduling network queue at interface opened/connected.
Removed: wake network queue at transmit complete.
Added: wake network queue at packet queue limit not reached.

Signed-off-by: Ivan Petrov <ivan_p@hotbox.ru>

drivers/ar6000/ar6000/ar6000_drv.c
drivers/ar6000/ar6000/ar6000_drv.h
drivers/ar6000/ar6000/ar6000_raw_if.c
drivers/ar6000/htc/htc.c
drivers/ar6000/htc/htc_send.c
drivers/ar6000/include/htc_api.h

index 8165576..cdf05d1 100644 (file)
@@ -238,6 +238,8 @@ static void ar6000_tx_complete(void *Context, HTC_PACKET *pPacket);
 
 static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint);
 
+static void ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint);
+
 /*
  * Static variables
  */
@@ -1149,7 +1151,7 @@ static int
 ar6000_open(struct net_device *dev)
 {
     /* Wake up the queues */
-    netif_wake_queue(dev);
+    netif_start_queue(dev);
 
     return 0;
 }
@@ -1278,6 +1280,7 @@ int ar6000_init(struct net_device *dev)
         connect.EpCallbacks.EpRecv = ar6000_rx;
         connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill;
         connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full;
+        connect.EpCallbacks.EpSendAvail = ar6000_tx_queue_avail;
             /* set the max queue depth so that our ar6000_tx_queue_full handler gets called.
              * Linux has the peculiarity of not providing flow control between the
              * NIC and the network stack. There is no API to indicate that a TX packet
@@ -1753,10 +1756,10 @@ applyAPTCHeuristics(AR_SOFTC_T *ar)
 }
 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
 
-static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
+static void
+ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
 {
-    AR_SOFTC_T     *ar = (AR_SOFTC_T *)Context;
-
+    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
 
     if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
         if (!bypasswmi) {
@@ -1771,19 +1774,27 @@ static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
             AR_DEBUG_PRINTF("WMI Control Endpoint is FULL!!! \n");
         }
     } else {
-
-        AR6000_SPIN_LOCK(&ar->arLock, 0);
-        ar->arNetQueueStopped = TRUE;
-        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         /* one of the data endpoints queues is getting full..need to stop network stack
-         * the queue will resume in ar6000_tx_complete() */
+         * the queue will resume after credits received */
         netif_stop_queue(ar->arNetDev);
     }
+}
 
+static void
+ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint)
+{
+    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
 
+    if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
+        /* FIXME: what do for it?  */
+    } else {
+        /* Wake up interface, rescheduling prevented.  */
+        if ((ar->arConnected == TRUE) || (bypasswmi)) {
+            netif_wake_queue(ar->arNetDev);
+        }
+    }
 }
 
-
 static void
 ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
 {
@@ -1877,10 +1888,6 @@ ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
         ar6000_free_cookie(ar, cookie);
     }
 
-    if (ar->arNetQueueStopped) {
-        ar->arNetQueueStopped = FALSE;
-    }
-
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
     /* lock is released, we can freely call other kernel APIs */
@@ -1888,18 +1895,9 @@ ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
         /* this indirectly frees the HTC_PACKET */
     A_NETBUF_FREE(skb);
 
-    if ((ar->arConnected == TRUE) || (bypasswmi)) {
-        if (status != A_ECANCELED) {
-                /* don't wake the queue if we are flushing, other wise it will just
-                 * keep queueing packets, which will keep failing */
-            netif_wake_queue(ar->arNetDev);
-        }
-    }
-
     if (wakeEvent) {
         wake_up(&arEvent);
     }
-
 }
 
 /*
@@ -2317,7 +2315,7 @@ ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
         /* flush data queues */
     ar6000_TxDataCleanup(ar);
 
-    netif_wake_queue(ar->arNetDev);
+    netif_start_queue(ar->arNetDev);
 
     if ((OPEN_AUTH == ar->arDot11AuthMode) &&
         (NONE_AUTH == ar->arAuthMode)      &&
index d5ff777..784f158 100644 (file)
@@ -273,7 +273,6 @@ typedef struct ar6_softc {
     A_BOOL                  write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
     A_BOOL                  read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
 #endif
-    A_BOOL                  arNetQueueStopped;
     A_BOOL                  arRawIfInit;
     int                     arDeviceIndex;
     COMMON_CREDIT_STATE_INFO arCreditStateInfo;
index 65402b9..4443bb2 100644 (file)
@@ -127,6 +127,7 @@ static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T        *ar,
             /* simple interface, we don't need these optional callbacks */
         connect.EpCallbacks.EpRecvRefill = NULL;
         connect.EpCallbacks.EpSendFull = NULL;
+        connect.EpCallbacks.EpSendAvail = NULL;
         connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM;
 
             /* connect to the raw streams service, we may be able to get 1 or more
index b5e691b..63ef90b 100644 (file)
@@ -284,6 +284,7 @@ A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
         connect.EpCallbacks.EpRecv = HTCControlRecv;
         connect.EpCallbacks.EpRecvRefill = NULL;  /* not needed */
         connect.EpCallbacks.EpSendFull = NULL;    /* not nedded */
+        connect.EpCallbacks.EpSendAvail = NULL;   /* not nedded */
         connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS;
         connect.ServiceID = HTC_CTRL_RSVD_SVC;
 
index fd5ef6e..62d8bcd 100644 (file)
@@ -101,23 +101,22 @@ A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 SendFlags
 }
 
 /* try to send the current packet or a packet at the head of the TX queue,
- * if there are no credits, the packet remains in the queue.
- * this function always succeeds and returns a flag if the TX queue for
- * the endpoint has hit the set limit */
-static A_BOOL HTCTrySend(HTC_TARGET   *target,
-                         HTC_ENDPOINT *pEndpoint,
-                         HTC_PACKET   *pPacketToSend)
+ * if there are no credits, the packet remains in the queue. */
+static void HTCTrySend(HTC_TARGET      *target,
+                       HTC_PACKET      *pPacketToSend,
+                       HTC_ENDPOINT_ID ep)
 {
-    HTC_PACKET  *pPacket;
-    int         creditsRequired;
-    int         remainder;
-    A_UINT8     sendFlags;
-    A_BOOL      epFull = FALSE;
-
-    LOCK_HTC_TX(target);
+    HTC_PACKET   *pPacket;
+    HTC_ENDPOINT *pEndpoint;
+    int          creditsRequired;
+    A_UINT8      sendFlags;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (pPkt:0x%X)\n",(A_UINT32)pPacketToSend));
 
+    pEndpoint = &target->EndPoint[ep];
+
+    LOCK_HTC_TX(target);
+
     if (pPacketToSend != NULL) {
         /* caller supplied us a packet to queue to the tail of the HTC TX queue before
          * we check the tx queue */
@@ -143,12 +142,9 @@ static A_BOOL HTCTrySend(HTC_TARGET   *target,
                 (A_UINT32)pPacket, pEndpoint->CurrentTxQueueDepth));
 
             /* figure out how many credits this message requires */
-        creditsRequired = (pPacket->ActualLength + HTC_HDR_LENGTH) / target->TargetCreditSize;
-        remainder = (pPacket->ActualLength + HTC_HDR_LENGTH) % target->TargetCreditSize;
-
-        if (remainder) {
-            creditsRequired++;
-        }
+        creditsRequired  = pPacket->ActualLength + HTC_HDR_LENGTH;
+        creditsRequired += target->TargetCreditSize - 1;
+        creditsRequired /= target->TargetCreditSize;
 
         AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d   Got:%d\n",
                             creditsRequired, pEndpoint->CreditDist.TxCredits));
@@ -212,14 +208,23 @@ static A_BOOL HTCTrySend(HTC_TARGET   *target,
     }
 
     if (pEndpoint->CurrentTxQueueDepth >= pEndpoint->MaxTxQueueDepth) {
-            /* let caller know that this endpoint has reached the maximum depth */
-        epFull = TRUE;
+        AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d, TX queue is full, Depth:%d, Max:%d \n",
+                        ep, pEndpoint->CurrentTxQueueDepth, pEndpoint->MaxTxQueueDepth));
+        UNLOCK_HTC_TX(target);
+            /* queue is now full, let caller know */
+        if (pEndpoint->EpCallBacks.EpSendFull != NULL) {
+            AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Calling driver's send full callback.... \n"));
+            pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext, ep);
+        }
+    } else {
+        UNLOCK_HTC_TX(target);
+            /* queue is now available for new packet, let caller know */
+        if (pEndpoint->EpCallBacks.EpSendAvail) {
+            pEndpoint->EpCallBacks.EpSendAvail(pEndpoint->EpCallBacks.pContext, ep);
+        }
     }
 
-    UNLOCK_HTC_TX(target);
-
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend:  \n"));
-    return epFull;
 }
 
 /* HTC API - HTCSendPkt */
@@ -251,20 +256,12 @@ A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
         pPacket->Completion = HTCSendPktCompletionHandler;
         pPacket->pContext = target;
 
-        if (HTCTrySend(target, pEndpoint, pPacket)) {
-            AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d, TX queue is full, Depth:%d, Max:%d \n",
-                    ep, pEndpoint->CurrentTxQueueDepth, pEndpoint->MaxTxQueueDepth));
-                /* queue is now full, let caller know */
-            if (pEndpoint->EpCallBacks.EpSendFull != NULL) {
-                AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Calling driver's send full callback.... \n"));
-                pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext,
-                                                  ep);
-            }
-        }
+        HTCTrySend(target, pPacket, ep);
 
-        AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPkt \n"));
     } while (FALSE);
 
+    AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPkt \n"));
+
     return status;
 }
 
@@ -292,7 +289,7 @@ static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
                  * Highest priority queue get's processed first, if there are credits available the
                  * highest priority queue will get a chance to reclaim credits from lower priority
                  * ones */
-            HTCTrySend(target, pEndpoint, NULL);
+            HTCTrySend(target, NULL, pDistItem->Endpoint);
         }
 
         pDistItem = pDistItem->pNext;
@@ -480,7 +477,6 @@ void HTCFlushSendPkts(HTC_TARGET *target)
         HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
     }
 
-
 }
 
 /* HTC API to flush an endpoint's TX queue*/
index 73b7df6..e75692d 100644 (file)
@@ -86,6 +86,8 @@ typedef void   (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint);
  * Other OSes require a "per-packet" indication_RAW_STREAM_NUM_MAX for each completed TX packet, this
  * closed loop mechanism will prevent the network stack from overunning the NIC */
 typedef void (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_ENDPOINT_ID Endpoint);
+/* Optional per service connection callback when a send queue is available for receive new packet. */
+typedef void (*HTC_EP_SEND_QUEUE_AVAIL)(void *, HTC_ENDPOINT_ID Endpoint);
 
 typedef struct _HTC_EP_CALLBACKS {
     void                     *pContext;     /* context for each callback */
@@ -93,6 +95,7 @@ typedef struct _HTC_EP_CALLBACKS {
     HTC_EP_RECV_PKT          EpRecv;        /* receive callback for connected endpoint */
     HTC_EP_RECV_REFILL       EpRecvRefill;  /* OPTIONAL receive re-fill callback for connected endpoint */
     HTC_EP_SEND_QUEUE_FULL   EpSendFull;    /* OPTIONAL send full callback */
+    HTC_EP_SEND_QUEUE_AVAIL  EpSendAvail;    /* OPTIONAL send available callback */
 } HTC_EP_CALLBACKS;
 
 /* service connection information */