]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/bcm/Transmit.c
staging: Beeceem USB Wimax driver
[net-next-2.6.git] / drivers / staging / bcm / Transmit.c
1 /**
2 @file Transmit.c
3 @defgroup tx_functions Transmission
4 @section Queueing
5 @dot
6 digraph transmit1 {
7 node[shape=box]
8 edge[weight=5;color=red]
9 bcm_transmit->reply_to_arp_request[label="ARP"]
10 bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
11 GetPacketQueueIndex->IpVersion4[label="IPV4"]
12 GetPacketQueueIndex->IpVersion6[label="IPV6"]
13 }
14
15 @enddot
16
17 @section De-Queueing
18 @dot
19 digraph transmit2 {
20 node[shape=box]
21 edge[weight=5;color=red]
22 interrupt_service_thread->transmit_packets
23 tx_pkt_hdler->transmit_packets
24 transmit_packets->CheckAndSendPacketFromIndex
25 transmit_packets->UpdateTokenCount
26 CheckAndSendPacketFromIndex->PruneQueue
27 CheckAndSendPacketFromIndex->IsPacketAllowedForFlow
28 CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"]
29 SendControlPacket->bcm_cmd53
30 CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"]
31 SendPacketFromQueue->SetupNextSend->bcm_cmd53
32 }
33 @enddot
34 */
35
36 #include "headers.h"
37
38 /*******************************************************************
39 * Function    - bcm_transmit()
40 *
41 * Description - This is the main transmit function for our virtual
42 *                               interface(veth0). It handles the ARP packets. It
43 *                               clones this packet and then Queue it to a suitable
44 *                               Queue. Then calls the transmit_packet().
45 *
46 * Parameter   -  skb - Pointer to the socket buffer structure
47 *                                dev - Pointer to the virtual net device structure
48 *
49 * Returns     -  zero (success) or -ve value (failure)
50 *
51 *********************************************************************/
52
53 INT bcm_transmit(struct sk_buff *skb,           /**< skb */
54                                         struct net_device *dev  /**< net device pointer */
55                                         )
56 {
57         PMINI_ADAPTER           Adapter = NULL;
58         USHORT                          qindex=0;
59         struct timeval tv;
60         UINT            pkt_type = 0;
61         UINT            calltransmit = 0;
62
63         BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__);
64
65         memset(&tv, 0, sizeof(tv));
66         /* Check for valid parameters */
67         if(skb == NULL || dev==NULL)
68         {
69             BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n");
70                 return -EINVAL;
71         }
72
73         Adapter = GET_BCM_ADAPTER(dev);
74         if(!Adapter)
75         {
76                 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n");
77                 return -EINVAL;
78         }
79         if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus)
80         {
81                 if(!netif_queue_stopped(dev)) {
82                                 netif_carrier_off(dev);
83                                 netif_stop_queue(dev);
84                 }
85                 return STATUS_FAILURE;
86         }
87         BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len);
88
89         /*Add Ethernet CS check here*/
90         if(Adapter->TransferMode == IP_PACKET_ONLY_MODE )
91         {
92         pkt_type = ntohs(*(PUSHORT)(skb->data + 12));
93                 /* Get the queue index where the packet is to be queued */
94                 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index.....");
95
96                 qindex = GetPacketQueueIndex(Adapter,skb);
97
98                 if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex)
99                 {
100                         if(pkt_type == ETH_ARP_FRAME)
101                         {
102                                 /*
103                                 Reply directly to ARP request packet
104                                 ARP Spoofing only if NO ETH CS rule matches for it
105                                 */
106                                 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x",
107
108                 (*(PUCHAR)(skb->data + 21)));
109
110                 reply_to_arp_request(skb);
111
112                 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n");
113
114                         }
115                         else
116                         {
117                 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,
118                         "Invalid queue index, dropping pkt\n");
119
120                                 bcm_kfree_skb(skb);
121                         }
122                         return STATUS_SUCCESS;
123         }
124
125                 if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP)
126                 {
127                         atomic_inc(&Adapter->TxDroppedPacketCount);
128                         bcm_kfree_skb(skb);
129                         return STATUS_SUCCESS;
130                 }
131
132                 /* Now Enqueue the packet */
133                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex);
134                 spin_lock(&Adapter->PackInfo[qindex].SFQueueLock);
135                 Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len;
136                 Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++;
137
138                 *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies;
139                 ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue,
140                           Adapter->PackInfo[qindex].LastTxQueue, skb);
141                 atomic_inc(&Adapter->TotalPacketCount);
142                 spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock);
143                 do_gettimeofday(&tv);
144
145                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n");
146                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n",
147                 (skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec);
148
149 #ifdef BCM_SHM_INTERFACE
150                 spin_lock(&Adapter->txtransmitlock);
151                 if(Adapter->txtransmit_running == 0)
152                 {
153                         Adapter->txtransmit_running = 1;
154                         calltransmit = 1;
155                 }
156                 else
157                         calltransmit = 0;
158
159                 spin_unlock(&Adapter->txtransmitlock);
160 #endif
161                 if(calltransmit == 1)
162                         transmit_packets(Adapter);
163                 else
164                 {
165                         if(!atomic_read(&Adapter->TxPktAvail))
166                         {
167                                 atomic_set(&Adapter->TxPktAvail, 1);
168 #ifdef BCM_SHM_INTERFACE
169                                 virtual_mail_box_interrupt();
170 #endif
171                                 wake_up(&Adapter->tx_packet_wait_queue);
172                         }
173                 }
174                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<====");
175         }
176         else
177                 bcm_kfree_skb(skb);
178
179   return STATUS_SUCCESS;
180 }
181
182
183 /**
184 @ingroup ctrl_pkt_functions
185 This function dispatches control packet to the h/w interface
186 @return zero(success) or -ve value(failure)
187 */
188 INT SendControlPacket(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
189                                                         char *pControlPacket/**<Control Packet*/
190                                                         )
191 {
192         PLEADER PLeader = NULL;
193         struct timeval tv;
194         memset(&tv, 0, sizeof(tv));
195
196
197
198         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "========>");
199
200         PLeader=(PLEADER)pControlPacket;
201         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
202         if(!pControlPacket || !Adapter)
203         {
204                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
205                 return STATUS_FAILURE;
206         }
207         if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <
208                 ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
209     {
210         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
211         if(Adapter->bcm_jiffies == 0)
212         {
213                 Adapter->bcm_jiffies = jiffies;
214             BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu",
215                                 Adapter->bcm_jiffies);
216         }
217         return STATUS_FAILURE;
218     }
219
220         /* Update the netdevice statistics */
221         /* Dump Packet  */
222         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
223         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
224         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
225         if(Adapter->device_removed)
226                 return 0;
227 #ifndef BCM_SHM_INTERFACE
228         Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
229                                         pControlPacket, (PLeader->PLength + LEADER_SIZE));
230 #else
231         tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1);
232
233         if(PLeader->Status==IDLE_MESSAGE)
234         {
235                 if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD &&
236                 ((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE)
237                 {
238                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n");
239                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n");
240                         do_gettimeofday(&tv);
241                         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);
242                         if(Adapter->bDoSuspend != TRUE)
243                         {
244                                 Adapter->IdleMode = TRUE;
245                                 Adapter->bPreparingForLowPowerMode = FALSE ;
246                         }
247                 }
248         }
249         if((PLeader->Status == LINK_UP_CONTROL_REQ) &&
250                 ((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK &&
251                 ((PUCHAR)pControlPacket)[sizeof(LEADER)+1] ==
252                                                                 LINK_SHUTDOWN_REQ_FROM_FIRMWARE  &&
253                 ((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER)
254         {
255                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n");
256                 if(Adapter->bDoSuspend != TRUE)
257                 {
258                         Adapter->bShutStatus = TRUE;
259                         Adapter->bPreparingForLowPowerMode = FALSE;
260                         Adapter->bTriedToWakeUpFromlowPowerMode = FALSE;
261                 }
262
263         }
264 #endif
265
266         ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++;
267         ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+=
268                         PLeader->PLength;
269         atomic_dec(&Adapter->CurrNumFreeTxDesc);
270         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
271         return STATUS_SUCCESS;
272 }
273 static  LEADER Leader={0};
274 /**
275 @ingroup tx_functions
276 This function despatches the IP packets with the given vcid
277 to the target via the host h/w interface.
278 @return  zero(success) or -ve value(failure)
279 */
280 INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
281                                         struct sk_buff *Packet, /**<data buffer*/
282                                         USHORT Vcid)                    /**<VCID for this packet*/
283 {
284         int             status=0;
285         int dontfree = 0;
286         BOOLEAN bHeaderSupressionEnabled = FALSE;
287         B_UINT16            uiClassifierRuleID;
288         int QueueIndex = NO_OF_QUEUES + 1;
289
290         if(!Adapter || !Packet)
291         {
292                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet");
293                 return -EINVAL;
294         }
295         if(Packet->len > MAX_DEVICE_DESC_SIZE)
296         {
297                 status = STATUS_FAILURE;
298                 goto errExit;
299         }
300
301         /* Get the Classifier Rule ID */
302         uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
303         QueueIndex = SearchVcid( Adapter,Vcid);
304         if(QueueIndex < NO_OF_QUEUES)
305         {
306                 bHeaderSupressionEnabled =
307                         Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
308                 bHeaderSupressionEnabled =
309                         bHeaderSupressionEnabled & Adapter->bPHSEnabled;
310         }
311         if(Adapter->device_removed)
312                 {
313                 status = STATUS_FAILURE;
314                 goto errExit;
315                 }
316
317         status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
318                                                         (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
319
320         if(status != STATUS_SUCCESS)
321         {
322                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
323                 goto errExit;
324         }
325
326         Leader.Vcid     = Vcid;
327
328     if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
329         {
330         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n");
331                 Leader.Status = LEADER_STATUS_TCP_ACK;
332         }
333         else
334         {
335                 Leader.Status = LEADER_STATUS;
336         }
337
338         if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
339         {
340                 Leader.PLength = Packet->len;
341                 if(skb_headroom(Packet) < LEADER_SIZE)
342         {
343                         if((status = skb_cow(Packet,LEADER_SIZE)))
344                         {
345                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
346                                 goto errExit;
347                         }
348                 }
349                 skb_push(Packet, LEADER_SIZE);
350                 memcpy(Packet->data, &Leader, LEADER_SIZE);
351         }
352
353         else
354         {
355                 Leader.PLength = Packet->len - ETH_HLEN;
356                 memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
357         }
358
359         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len);
360         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid);
361
362 #ifndef BCM_SHM_INTERFACE
363         status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
364                         Packet->data, (Leader.PLength + LEADER_SIZE));
365 #else
366         status = tx_pkts_to_firmware(Packet,Packet->len,0);
367 #endif
368         if(status)
369         {
370                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n");
371         }
372         else
373         {
374                 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
375                 atomic_add(Leader.PLength, &Adapter->GoodTxByteCount);
376                 atomic_inc(&Adapter->TxTotalPacketCount);
377 #ifdef GDMA_INTERFACE
378     dontfree = 1;
379 #endif
380         }
381
382         atomic_dec(&Adapter->CurrNumFreeTxDesc);
383
384 errExit:
385
386         if(STATUS_SUCCESS == status)
387         {
388                 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
389                 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
390                 Adapter->PackInfo[QueueIndex].uiSentPackets++;
391                 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
392
393                 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
394 #ifdef BCM_SHM_INTERFACE
395                 if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0)
396                 {
397                         atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0);
398                 }
399 #endif
400                 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
401         }
402
403
404 #ifdef GDMA_INTERFACE
405   if(!dontfree){
406         bcm_kfree_skb(Packet);
407   }
408 #else
409         bcm_kfree_skb(Packet);
410 #endif
411         return status;
412 }
413
414 /**
415 @ingroup tx_functions
416 Transmit thread
417 */
418 int tx_pkt_handler(PMINI_ADAPTER Adapter  /**< pointer to adapter object*/
419                                 )
420 {
421 #ifndef BCM_SHM_INTERFACE
422         int status = 0;
423 #endif
424
425         UINT calltransmit = 1;
426         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Entring to wait for signal from the interrupt service thread!Adapter = 0x%x",(unsigned int) Adapter);
427
428
429         while(1)
430         {
431                 if(Adapter->LinkUpStatus){
432                         wait_event_timeout(Adapter->tx_packet_wait_queue,
433                                 ((atomic_read(&Adapter->TxPktAvail) &&
434                                 (MINIMUM_PENDING_DESCRIPTORS <
435                                 atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
436                                 (Adapter->device_removed == FALSE))) ||
437                                 (1 == Adapter->downloadDDR) || kthread_should_stop()
438 #ifndef BCM_SHM_INTERFACE
439                                 || (TRUE == Adapter->bEndPointHalted)
440 #endif
441                                 , msecs_to_jiffies(10));
442                 }
443                 else{
444                         wait_event(Adapter->tx_packet_wait_queue,
445                                 ((atomic_read(&Adapter->TxPktAvail) &&
446                                 (MINIMUM_PENDING_DESCRIPTORS <
447                                 atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
448                                 (Adapter->device_removed == FALSE))) ||
449                                 (1 == Adapter->downloadDDR) || kthread_should_stop()
450 #ifndef BCM_SHM_INTERFACE
451                                 || (TRUE == Adapter->bEndPointHalted)
452 #endif
453                                 );
454                 }
455
456                 if(kthread_should_stop() || Adapter->device_removed)
457                 {
458                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
459                         Adapter->transmit_packet_thread = NULL;
460                         return 0;
461                 }
462
463 #ifndef BCM_SHM_INTERFACE
464
465                 if(Adapter->downloadDDR == 1)
466                 {
467                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n");
468                         Adapter->downloadDDR +=1;
469                         status = download_ddr_settings(Adapter);
470                         if(status)
471                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n");
472                         continue;
473                 }
474
475                 //Check end point for halt/stall.
476                 if(Adapter->bEndPointHalted == TRUE)
477                 {
478                         Bcm_clear_halt_of_endpoints(Adapter);
479                         Adapter->bEndPointHalted = FALSE;
480                         StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
481                 }
482
483                 if(Adapter->LinkUpStatus && !Adapter->IdleMode)
484                 {
485                         if(atomic_read(&Adapter->TotalPacketCount))
486                         {
487                                 update_per_sf_desc_cnts(Adapter);
488                         }
489                 }
490 #endif
491
492                 if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
493                         Adapter->LinkStatus == SYNC_UP_REQUEST &&
494                         !Adapter->bSyncUpRequestSent)
495                 {
496                         BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
497                         LinkMessage(Adapter);
498                 }
499
500                 if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
501                 {
502                                 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
503                         Adapter->usIdleModePattern = ABORT_IDLE_MODE;
504                                 Adapter->bWakeUpDevice = TRUE;
505                                 wake_up(&Adapter->process_rx_cntrlpkt);
506                 }
507
508 #ifdef BCM_SHM_INTERFACE
509                 spin_lock_bh(&Adapter->txtransmitlock);
510                 if(Adapter->txtransmit_running == 0)
511                 {
512                         Adapter->txtransmit_running = 1;
513                         calltransmit = 1;
514                 }
515                 else
516                         calltransmit = 0;
517                 spin_unlock_bh(&Adapter->txtransmitlock);
518 #endif
519
520                 if(calltransmit)
521                         transmit_packets(Adapter);
522
523                 atomic_set(&Adapter->TxPktAvail, 0);
524         }
525         return 0;
526 }
527
528 #ifdef BCM_SHM_INTERFACE
529 extern PMINI_ADAPTER psAdaptertest;
530 void  virtual_mail_box_interrupt(void)
531 {
532
533 #ifndef GDMA_INTERFACE
534         PUINT ptr =  (PUINT)CPE_VIRTUAL_MAILBOX_REG;
535         UINT intval = (UINT)((*ptr & 0xFF00) >> 8);
536         if (intval != 0)
537         {
538                 atomic_set(&psAdaptertest->CurrNumFreeTxDesc,   intval);
539                 atomic_set (&psAdaptertest->uiMBupdate, TRUE);
540
541                 //make it to 0
542                 *ptr = *ptr & 0xffff00ff;
543         }
544 #endif
545 }
546 unsigned int total_tx_pkts_pending(void)
547 {
548         return atomic_read(&psAdaptertest->TotalPacketCount);
549 }
550
551 #endif
552
553