aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/Transmit.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/bcm/Transmit.c')
-rw-r--r--drivers/staging/bcm/Transmit.c555
1 files changed, 555 insertions, 0 deletions
diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c
new file mode 100644
index 000000000000..12f9e13457db
--- /dev/null
+++ b/drivers/staging/bcm/Transmit.c
@@ -0,0 +1,555 @@
+/**
+@file Transmit.c
+@defgroup tx_functions Transmission
+@section Queueing
+@dot
+digraph transmit1 {
+node[shape=box]
+edge[weight=5;color=red]
+bcm_transmit->reply_to_arp_request[label="ARP"]
+bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
+GetPacketQueueIndex->IpVersion4[label="IPV4"]
+GetPacketQueueIndex->IpVersion6[label="IPV6"]
+}
+
+@enddot
+
+@section De-Queueing
+@dot
+digraph transmit2 {
+node[shape=box]
+edge[weight=5;color=red]
+interrupt_service_thread->transmit_packets
+tx_pkt_hdler->transmit_packets
+transmit_packets->CheckAndSendPacketFromIndex
+transmit_packets->UpdateTokenCount
+CheckAndSendPacketFromIndex->PruneQueue
+CheckAndSendPacketFromIndex->IsPacketAllowedForFlow
+CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"]
+SendControlPacket->bcm_cmd53
+CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"]
+SendPacketFromQueue->SetupNextSend->bcm_cmd53
+}
+@enddot
+*/
+
+#include "headers.h"
+
+/*******************************************************************
+* Function - bcm_transmit()
+*
+* Description - This is the main transmit function for our virtual
+* interface(veth0). It handles the ARP packets. It
+* clones this packet and then Queue it to a suitable
+* Queue. Then calls the transmit_packet().
+*
+* Parameter - skb - Pointer to the socket buffer structure
+* dev - Pointer to the virtual net device structure
+*
+* Returns - zero (success) or -ve value (failure)
+*
+*********************************************************************/
+
+INT bcm_transmit(struct sk_buff *skb, /**< skb */
+ struct net_device *dev /**< net device pointer */
+ )
+{
+ 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__);
+
+ 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);
+
+ /*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.....");
+
+ 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",
+
+ (*(PUCHAR)(skb->data + 21)));
+
+ reply_to_arp_request(skb);
+
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n");
+
+ }
+ else
+ {
+ BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,
+ "Invalid queue index, dropping pkt\n");
+
+ bcm_kfree_skb(skb);
+ }
+ return STATUS_SUCCESS;
+ }
+
+ if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
+ {
+ atomic_inc(&Adapter->TxDroppedPacketCount);
+ bcm_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);
+
+#ifdef BCM_SHM_INTERFACE
+ spin_lock(&Adapter->txtransmitlock);
+ if(Adapter->txtransmit_running == 0)
+ {
+ Adapter->txtransmit_running = 1;
+ calltransmit = 1;
+ }
+ else
+ calltransmit = 0;
+
+ spin_unlock(&Adapter->txtransmitlock);
+#endif
+ if(calltransmit == 1)
+ transmit_packets(Adapter);
+ else
+ {
+ if(!atomic_read(&Adapter->TxPktAvail))
+ {
+ atomic_set(&Adapter->TxPktAvail, 1);
+#ifdef BCM_SHM_INTERFACE
+ virtual_mail_box_interrupt();
+#endif
+ wake_up(&Adapter->tx_packet_wait_queue);
+ }
+ }
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<====");
+ }
+ else
+ bcm_kfree_skb(skb);
+
+ return STATUS_SUCCESS;
+}
+
+
+/**
+@ingroup ctrl_pkt_functions
+This function dispatches control packet to the h/w interface
+@return zero(success) or -ve value(failure)
+*/
+INT SendControlPacket(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
+ char *pControlPacket/**<Control Packet*/
+ )
+{
+ PLEADER PLeader = NULL;
+ struct timeval tv;
+ memset(&tv, 0, sizeof(tv));
+
+
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "========>");
+
+ PLeader=(PLEADER)pControlPacket;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
+ if(!pControlPacket || !Adapter)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
+ return STATUS_FAILURE;
+ }
+ if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <
+ ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
+ if(Adapter->bcm_jiffies == 0)
+ {
+ Adapter->bcm_jiffies = jiffies;
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu",
+ Adapter->bcm_jiffies);
+ }
+ return STATUS_FAILURE;
+ }
+
+ /* Update the netdevice statistics */
+ /* Dump Packet */
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
+ if(Adapter->device_removed)
+ return 0;
+#ifndef BCM_SHM_INTERFACE
+ Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
+ pControlPacket, (PLeader->PLength + LEADER_SIZE));
+#else
+ tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1);
+
+ if(PLeader->Status==IDLE_MESSAGE)
+ {
+ if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD &&
+ ((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n");
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n");
+ do_gettimeofday(&tv);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "IdleMode Msg sent to f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000);
+ if(Adapter->bDoSuspend != TRUE)
+ {
+ Adapter->IdleMode = TRUE;
+ Adapter->bPreparingForLowPowerMode = FALSE ;
+ }
+ }
+ }
+ if((PLeader->Status == LINK_UP_CONTROL_REQ) &&
+ ((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK &&
+ ((PUCHAR)pControlPacket)[sizeof(LEADER)+1] ==
+ LINK_SHUTDOWN_REQ_FROM_FIRMWARE &&
+ ((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n");
+ if(Adapter->bDoSuspend != TRUE)
+ {
+ Adapter->bShutStatus = TRUE;
+ Adapter->bPreparingForLowPowerMode = FALSE;
+ Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
+ }
+
+ }
+#endif
+
+ ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++;
+ ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+=
+ PLeader->PLength;
+ atomic_dec(&Adapter->CurrNumFreeTxDesc);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
+ return STATUS_SUCCESS;
+}
+static LEADER Leader={0};
+/**
+@ingroup tx_functions
+This function despatches the IP packets with the given vcid
+to the target via the host h/w interface.
+@return zero(success) or -ve value(failure)
+*/
+INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
+ struct sk_buff *Packet, /**<data buffer*/
+ USHORT Vcid) /**<VCID for this packet*/
+{
+ int status=0;
+#ifdef GDMA_INTERFACE
+ int dontfree = 0;
+#endif
+ BOOLEAN bHeaderSupressionEnabled = FALSE;
+ B_UINT16 uiClassifierRuleID;
+ int QueueIndex = NO_OF_QUEUES + 1;
+
+ if(!Adapter || !Packet)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet");
+ return -EINVAL;
+ }
+ if(Packet->len > MAX_DEVICE_DESC_SIZE)
+ {
+ status = STATUS_FAILURE;
+ goto errExit;
+ }
+
+ /* Get the Classifier Rule ID */
+ uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
+ QueueIndex = SearchVcid( Adapter,Vcid);
+ if(QueueIndex < NO_OF_QUEUES)
+ {
+ bHeaderSupressionEnabled =
+ Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
+ bHeaderSupressionEnabled =
+ bHeaderSupressionEnabled & Adapter->bPHSEnabled;
+ }
+ if(Adapter->device_removed)
+ {
+ status = STATUS_FAILURE;
+ goto errExit;
+ }
+
+ status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
+ (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
+
+ if(status != STATUS_SUCCESS)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
+ goto errExit;
+ }
+
+ Leader.Vcid = Vcid;
+
+ if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n");
+ Leader.Status = LEADER_STATUS_TCP_ACK;
+ }
+ else
+ {
+ Leader.Status = LEADER_STATUS;
+ }
+
+ if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
+ {
+ Leader.PLength = Packet->len;
+ if(skb_headroom(Packet) < LEADER_SIZE)
+ {
+ if((status = skb_cow(Packet,LEADER_SIZE)))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
+ goto errExit;
+ }
+ }
+ skb_push(Packet, LEADER_SIZE);
+ memcpy(Packet->data, &Leader, LEADER_SIZE);
+ }
+
+ else
+ {
+ Leader.PLength = Packet->len - ETH_HLEN;
+ memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
+ }
+
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len);
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid);
+
+#ifndef BCM_SHM_INTERFACE
+ status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
+ Packet->data, (Leader.PLength + LEADER_SIZE));
+#else
+ status = tx_pkts_to_firmware(Packet,Packet->len,0);
+#endif
+ if(status)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n");
+ }
+ else
+ {
+ Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
+ atomic_add(Leader.PLength, &Adapter->GoodTxByteCount);
+ atomic_inc(&Adapter->TxTotalPacketCount);
+#ifdef GDMA_INTERFACE
+ dontfree = 1;
+#endif
+ }
+
+ atomic_dec(&Adapter->CurrNumFreeTxDesc);
+
+errExit:
+
+ if(STATUS_SUCCESS == status)
+ {
+ Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
+ Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
+ Adapter->PackInfo[QueueIndex].uiSentPackets++;
+ Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
+
+ atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
+#ifdef BCM_SHM_INTERFACE
+ if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0)
+ {
+ atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0);
+ }
+#endif
+ Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
+ }
+
+
+#ifdef GDMA_INTERFACE
+ if(!dontfree){
+ bcm_kfree_skb(Packet);
+ }
+#else
+ bcm_kfree_skb(Packet);
+#endif
+ return status;
+}
+
+/**
+@ingroup tx_functions
+Transmit thread
+*/
+int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
+ )
+{
+#ifndef BCM_SHM_INTERFACE
+ int status = 0;
+#endif
+
+ 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){
+ 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()
+#ifndef BCM_SHM_INTERFACE
+ || (TRUE == Adapter->bEndPointHalted)
+#endif
+ , 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()
+#ifndef BCM_SHM_INTERFACE
+ || (TRUE == Adapter->bEndPointHalted)
+#endif
+ );
+ }
+
+ 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;
+ }
+
+#ifndef BCM_SHM_INTERFACE
+
+ if(Adapter->downloadDDR == 1)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n");
+ Adapter->downloadDDR +=1;
+ status = download_ddr_settings(Adapter);
+ if(status)
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n");
+ continue;
+ }
+
+ //Check end point for halt/stall.
+ if(Adapter->bEndPointHalted == TRUE)
+ {
+ Bcm_clear_halt_of_endpoints(Adapter);
+ Adapter->bEndPointHalted = FALSE;
+ StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
+ }
+
+ if(Adapter->LinkUpStatus && !Adapter->IdleMode)
+ {
+ if(atomic_read(&Adapter->TotalPacketCount))
+ {
+ update_per_sf_desc_cnts(Adapter);
+ }
+ }
+#endif
+
+ if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
+ Adapter->LinkStatus == SYNC_UP_REQUEST &&
+ !Adapter->bSyncUpRequestSent)
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
+ LinkMessage(Adapter);
+ }
+
+ if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
+ {
+ BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
+ Adapter->usIdleModePattern = ABORT_IDLE_MODE;
+ Adapter->bWakeUpDevice = TRUE;
+ wake_up(&Adapter->process_rx_cntrlpkt);
+ }
+
+#ifdef BCM_SHM_INTERFACE
+ spin_lock_bh(&Adapter->txtransmitlock);
+ if(Adapter->txtransmit_running == 0)
+ {
+ Adapter->txtransmit_running = 1;
+ calltransmit = 1;
+ }
+ else
+ calltransmit = 0;
+ spin_unlock_bh(&Adapter->txtransmitlock);
+#endif
+
+ if(calltransmit)
+ transmit_packets(Adapter);
+
+ atomic_set(&Adapter->TxPktAvail, 0);
+ }
+ return 0;
+}
+
+#ifdef BCM_SHM_INTERFACE
+extern PMINI_ADAPTER psAdaptertest;
+void virtual_mail_box_interrupt(void)
+{
+
+#ifndef GDMA_INTERFACE
+ PUINT ptr = (PUINT)CPE_VIRTUAL_MAILBOX_REG;
+ UINT intval = (UINT)((*ptr & 0xFF00) >> 8);
+ if (intval != 0)
+ {
+ atomic_set(&psAdaptertest->CurrNumFreeTxDesc, intval);
+ atomic_set (&psAdaptertest->uiMBupdate, TRUE);
+
+ //make it to 0
+ *ptr = *ptr & 0xffff00ff;
+ }
+#endif
+}
+unsigned int total_tx_pkts_pending(void)
+{
+ return atomic_read(&psAdaptertest->TotalPacketCount);
+}
+
+#endif
+
+