aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan_p@hotbox.ru <ivan_p@hotbox.ru>2009-03-26 15:03:03 +0300
committerWerner Almesberger <werner@openmoko.org>2009-03-31 00:42:22 -0300
commit645df9d63189968bb3884d46f6558c3e2b0c935a (patch)
tree85ccaba5c015f8c5b7685642fd4452d584d3329c
parent5c7e3aef519168ab5230466f51f28b8553cbd363 (diff)
AR6000 netif_queue_stop non stop, Bug?
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>
-rw-r--r--drivers/ar6000/ar6000/ar6000_drv.c46
-rw-r--r--drivers/ar6000/ar6000/ar6000_drv.h1
-rw-r--r--drivers/ar6000/ar6000/ar6000_raw_if.c1
-rw-r--r--drivers/ar6000/htc/htc.c1
-rw-r--r--drivers/ar6000/htc/htc_send.c70
-rw-r--r--drivers/ar6000/include/htc_api.h3
6 files changed, 60 insertions, 62 deletions
diff --git a/drivers/ar6000/ar6000/ar6000_drv.c b/drivers/ar6000/ar6000/ar6000_drv.c
index 816557641de..cdf05d1b314 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.c
+++ b/drivers/ar6000/ar6000/ar6000_drv.c
@@ -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) &&
diff --git a/drivers/ar6000/ar6000/ar6000_drv.h b/drivers/ar6000/ar6000/ar6000_drv.h
index d5ff7774885..784f158d9c4 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.h
+++ b/drivers/ar6000/ar6000/ar6000_drv.h
@@ -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;
diff --git a/drivers/ar6000/ar6000/ar6000_raw_if.c b/drivers/ar6000/ar6000/ar6000_raw_if.c
index 65402b9c8d5..4443bb26733 100644
--- a/drivers/ar6000/ar6000/ar6000_raw_if.c
+++ b/drivers/ar6000/ar6000/ar6000_raw_if.c
@@ -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
diff --git a/drivers/ar6000/htc/htc.c b/drivers/ar6000/htc/htc.c
index b5e691b962e..63ef90bf916 100644
--- a/drivers/ar6000/htc/htc.c
+++ b/drivers/ar6000/htc/htc.c
@@ -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;
diff --git a/drivers/ar6000/htc/htc_send.c b/drivers/ar6000/htc/htc_send.c
index fd5ef6e2605..62d8bcda5e2 100644
--- a/drivers/ar6000/htc/htc_send.c
+++ b/drivers/ar6000/htc/htc_send.c
@@ -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*/
diff --git a/drivers/ar6000/include/htc_api.h b/drivers/ar6000/include/htc_api.h
index 73b7df60ed0..e75692d7efa 100644
--- a/drivers/ar6000/include/htc_api.h
+++ b/drivers/ar6000/include/htc_api.h
@@ -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 */