aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/bcm/Transmit.c
diff options
context:
space:
mode:
authorStephen Hemminger <stephen.hemminger@vyatta.com>2010-09-08 17:46:36 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-09-09 00:15:06 -0400
commitf8942e07a3db9d82e8fb11d3d494876b8bae9ff9 (patch)
tree2406636a4f9a4ac6b0bfc90e07aefa8b1b18b8ff /drivers/staging/bcm/Transmit.c
parent2d2f03b022186e6d7520a758abdea9c04a2969fe (diff)
staging: Beeceem USB Wimax driver
The Sprint 4G network uses a Wimax dongle with Beecem chipset. The driver is typical of out of tree drivers, but maybe useful for people, and the hardware is readily available. Here is a staging ready version (i.e warts and all) 0. Started with Rel_5.2.7.3P1_USB from Sprint4GDeveloperPack-1.1 1. Consolidated files in staging 2. Remove Dos cr/lf 3. Remove unnecessary ioctl from usbbcm_fops Applied patches that were in the developer pack, surprising there were ones for 2.6.35 already. This is compile tested only, see TODO for what still needs to be done. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/bcm/Transmit.c')
-rw-r--r--drivers/staging/bcm/Transmit.c553
1 files changed, 553 insertions, 0 deletions
diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c
new file mode 100644
index 00000000000..9a076b54324
--- /dev/null
+++ b/drivers/staging/bcm/Transmit.c
@@ -0,0 +1,553 @@
1/**
2@file Transmit.c
3@defgroup tx_functions Transmission
4@section Queueing
5@dot
6digraph transmit1 {
7node[shape=box]
8edge[weight=5;color=red]
9bcm_transmit->reply_to_arp_request[label="ARP"]
10bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
11GetPacketQueueIndex->IpVersion4[label="IPV4"]
12GetPacketQueueIndex->IpVersion6[label="IPV6"]
13}
14
15@enddot
16
17@section De-Queueing
18@dot
19digraph transmit2 {
20node[shape=box]
21edge[weight=5;color=red]
22interrupt_service_thread->transmit_packets
23tx_pkt_hdler->transmit_packets
24transmit_packets->CheckAndSendPacketFromIndex
25transmit_packets->UpdateTokenCount
26CheckAndSendPacketFromIndex->PruneQueue
27CheckAndSendPacketFromIndex->IsPacketAllowedForFlow
28CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"]
29SendControlPacket->bcm_cmd53
30CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"]
31SendPacketFromQueue->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
53INT 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
185This function dispatches control packet to the h/w interface
186@return zero(success) or -ve value(failure)
187*/
188INT 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}
273static LEADER Leader={0};
274/**
275@ingroup tx_functions
276This function despatches the IP packets with the given vcid
277to the target via the host h/w interface.
278@return zero(success) or -ve value(failure)
279*/
280INT 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
384errExit:
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
416Transmit thread
417*/
418int 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
529extern PMINI_ADAPTER psAdaptertest;
530void 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}
546unsigned int total_tx_pkts_pending(void)
547{
548 return atomic_read(&psAdaptertest->TotalPacketCount);
549}
550
551#endif
552
553