Skip to content

Commit

Permalink
beceem: make transmit thread interruptible
Browse files Browse the repository at this point in the history
Kernel complains loudly if thread does long uninterruptible sleep.
Also, dont wake up every 10ms even if no data present (wastes power).

Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
  • Loading branch information
Stephen Hemminger committed Nov 1, 2010
1 parent de85f98 commit 71e253b
Showing 1 changed file with 61 additions and 134 deletions.
195 changes: 61 additions & 134 deletions drivers/staging/bcm/Transmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53
* Function - bcm_transmit()
*
* Description - This is the main transmit function for our virtual
* interface(veth0). It handles the ARP packets. It
* interface(eth0). It handles the ARP packets. It
* clones this packet and then Queue it to a suitable
* Queue. Then calls the transmit_packet().
*
Expand All @@ -50,118 +50,59 @@ SendPacketFromQueue->SetupNextSend->bcm_cmd53
*
*********************************************************************/

INT bcm_transmit(struct sk_buff *skb, /**< skb */
struct net_device *dev /**< net device pointer */
)
netdev_tx_t bcm_transmit(struct sk_buff *skb, struct net_device *dev)
{
PMINI_ADAPTER Adapter = NULL;
USHORT qindex=0;
struct timeval tv;
UINT pkt_type = 0;
UINT calltransmit = 0;

BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__);
PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
SHORT qindex;

memset(&tv, 0, sizeof(tv));
/* Check for valid parameters */
if(skb == NULL || dev==NULL)
{
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n");
return -EINVAL;
}

Adapter = GET_BCM_ADAPTER(dev);
if(!Adapter)
{
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n");
return -EINVAL;
}
if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus)
{
if(!netif_queue_stopped(dev)) {
netif_carrier_off(dev);
netif_stop_queue(dev);
}
return STATUS_FAILURE;
}
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len);
if (Adapter->device_removed || !Adapter->LinkUpStatus)
goto drop;

/*Add Ethernet CS check here*/
if(Adapter->TransferMode == IP_PACKET_ONLY_MODE )
{
pkt_type = ntohs(*(PUSHORT)(skb->data + 12));
/* Get the queue index where the packet is to be queued */
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index.....");
if (Adapter->TransferMode != IP_PACKET_ONLY_MODE )
goto drop;

qindex = GetPacketQueueIndex(Adapter,skb);
qindex = GetPacketQueueIndex(Adapter, skb);

if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex)
{
if(pkt_type == ETH_ARP_FRAME)
{
/*
Reply directly to ARP request packet
ARP Spoofing only if NO ETH CS rule matches for it
*/
BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x",
if (INVALID_QUEUE_INDEX==qindex) {
if (ntohs(eth_hdr(skb)->h_proto) != ETH_ARP_FRAME)
goto drop;

(*(PUCHAR)(skb->data + 21)));
/*
Reply directly to ARP request packet
ARP Spoofing only if NO ETH CS rule matches for it
*/
reply_to_arp_request(skb);
return NETDEV_TX_OK;
}

reply_to_arp_request(skb);
if (Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
return NETDEV_TX_BUSY;

BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n");
/* Now Enqueue the packet */
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
"bcm_transmit Enqueueing the Packet To Queue %d",qindex);
spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;

}
else
{
BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,
"Invalid queue index, dropping pkt\n");
*((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies;
ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
Adapter->PackInfo[qindex].LastTxQueue, skb);
atomic_inc(&Adapter->TotalPacketCount);
spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);

dev_kfree_skb(skb);
}
return STATUS_SUCCESS;
}
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n");

if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
{
atomic_inc(&Adapter->TxDroppedPacketCount);
dev_kfree_skb(skb);
return STATUS_SUCCESS;
}

/* Now Enqueue the packet */
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex);
spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;

*((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies;
ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
Adapter->PackInfo[qindex].LastTxQueue, skb);
atomic_inc(&Adapter->TotalPacketCount);
spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);
do_gettimeofday(&tv);

BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n");
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n",
(skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec);

if(calltransmit == 1)
transmit_packets(Adapter);
else
{
if(!atomic_read(&Adapter->TxPktAvail))
{
atomic_set(&Adapter->TxPktAvail, 1);
wake_up(&Adapter->tx_packet_wait_queue);
}
}
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<====");
/* FIXME - this is racy and incorrect, replace with work queue */
if (!atomic_read(&Adapter->TxPktAvail)) {
atomic_set(&Adapter->TxPktAvail, 1);
wake_up(&Adapter->tx_packet_wait_queue);
}
else
dev_kfree_skb(skb);
return NETDEV_TX_OK;

return STATUS_SUCCESS;
drop:
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}


Expand Down Expand Up @@ -337,6 +278,13 @@ INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
return status;
}

static int tx_pending(PMINI_ADAPTER Adapter)
{
return (atomic_read(&Adapter->TxPktAvail)
&& MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
|| Adapter->device_removed || (1 == Adapter->downloadDDR);
}

/**
@ingroup tx_functions
Transmit thread
Expand All @@ -346,40 +294,17 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
{
int status = 0;

UINT calltransmit = 1;
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Entring to wait for signal from the interrupt service thread!Adapter = %p",Adapter);


while(1)
{
if(Adapter->LinkUpStatus){
while(! kthread_should_stop()) {
/* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
if(Adapter->LinkUpStatus)
wait_event_timeout(Adapter->tx_packet_wait_queue,
((atomic_read(&Adapter->TxPktAvail) &&
(MINIMUM_PENDING_DESCRIPTORS <
atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
(Adapter->device_removed == FALSE))) ||
(1 == Adapter->downloadDDR) || kthread_should_stop()
|| (TRUE == Adapter->bEndPointHalted)
, msecs_to_jiffies(10));
}
else{
wait_event(Adapter->tx_packet_wait_queue,
((atomic_read(&Adapter->TxPktAvail) &&
(MINIMUM_PENDING_DESCRIPTORS <
atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
(Adapter->device_removed == FALSE))) ||
(1 == Adapter->downloadDDR) || kthread_should_stop()
|| (TRUE == Adapter->bEndPointHalted)
);
}

if(kthread_should_stop() || Adapter->device_removed)
{
BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
Adapter->transmit_packet_thread = NULL;
return 0;
}
tx_pending(Adapter), msecs_to_jiffies(10));
else
wait_event_interruptible(Adapter->tx_packet_wait_queue,
tx_pending(Adapter));

if (Adapter->device_removed)
break;

if(Adapter->downloadDDR == 1)
{
Expand Down Expand Up @@ -424,11 +349,13 @@ int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
}


if(calltransmit)
transmit_packets(Adapter);
transmit_packets(Adapter);

atomic_set(&Adapter->TxPktAvail, 0);
}

BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
Adapter->transmit_packet_thread = NULL;
return 0;
}

Expand Down

0 comments on commit 71e253b

Please sign in to comment.