3 @defgroup tx_functions Transmission
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"]
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
38 /*******************************************************************
39 * Function - bcm_transmit()
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().
46 * Parameter - skb - Pointer to the socket buffer structure
47 * dev - Pointer to the virtual net device structure
49 * Returns - zero (success) or -ve value (failure)
51 *********************************************************************/
53 INT
bcm_transmit(struct sk_buff
*skb
, /**< skb */
54 struct net_device
*dev
/**< net device pointer */
57 PMINI_ADAPTER Adapter
= NULL
;
61 UINT calltransmit
= 0;
63 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
, TX_OSAL_DBG
, DBG_LVL_ALL
, "\n%s====>\n",__FUNCTION__
);
65 memset(&tv
, 0, sizeof(tv
));
66 /* Check for valid parameters */
67 if(skb
== NULL
|| dev
==NULL
)
69 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
,TX_OSAL_DBG
, DBG_LVL_ALL
, "Got NULL skb or dev\n");
73 Adapter
= GET_BCM_ADAPTER(dev
);
76 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
, TX_OSAL_DBG
, DBG_LVL_ALL
, "Got Invalid Adapter\n");
79 if(Adapter
->device_removed
== TRUE
|| !Adapter
->LinkUpStatus
)
81 if(!netif_queue_stopped(dev
)) {
82 netif_carrier_off(dev
);
83 netif_stop_queue(dev
);
85 return STATUS_FAILURE
;
87 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
, TX_OSAL_DBG
, DBG_LVL_ALL
, "Packet size : %d\n", skb
->len
);
89 /*Add Ethernet CS check here*/
90 if(Adapter
->TransferMode
== IP_PACKET_ONLY_MODE
)
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.....");
96 qindex
= GetPacketQueueIndex(Adapter
,skb
);
98 if((SHORT
)INVALID_QUEUE_INDEX
==(SHORT
)qindex
)
100 if(pkt_type
== ETH_ARP_FRAME
)
103 Reply directly to ARP request packet
104 ARP Spoofing only if NO ETH CS rule matches for it
106 BCM_DEBUG_PRINT (Adapter
,DBG_TYPE_TX
, TX_OSAL_DBG
, DBG_LVL_ALL
,"ARP OPCODE = %02x",
108 (*(PUCHAR
)(skb
->data
+ 21)));
110 reply_to_arp_request(skb
);
112 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
,TX_OSAL_DBG
, DBG_LVL_ALL
,"After reply_to_arp_request \n");
117 BCM_DEBUG_PRINT (Adapter
, DBG_TYPE_TX
, TX_OSAL_DBG
, DBG_LVL_ALL
,
118 "Invalid queue index, dropping pkt\n");
122 return STATUS_SUCCESS
;
125 if(Adapter
->PackInfo
[qindex
].uiCurrentPacketsOnHost
>= SF_MAX_ALLOWED_PACKETS_TO_BACKUP
)
127 atomic_inc(&Adapter
->TxDroppedPacketCount
);
129 return STATUS_SUCCESS
;
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
++;
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
);
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
);
149 #ifdef BCM_SHM_INTERFACE
150 spin_lock(&Adapter
->txtransmitlock
);
151 if(Adapter
->txtransmit_running
== 0)
153 Adapter
->txtransmit_running
= 1;
159 spin_unlock(&Adapter
->txtransmitlock
);
161 if(calltransmit
== 1)
162 transmit_packets(Adapter
);
165 if(!atomic_read(&Adapter
->TxPktAvail
))
167 atomic_set(&Adapter
->TxPktAvail
, 1);
168 #ifdef BCM_SHM_INTERFACE
169 virtual_mail_box_interrupt();
171 wake_up(&Adapter
->tx_packet_wait_queue
);
174 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_OSAL_DBG
, DBG_LVL_ALL
, "<====");
179 return STATUS_SUCCESS
;
184 @ingroup ctrl_pkt_functions
185 This function dispatches control packet to the h/w interface
186 @return zero(success) or -ve value(failure)
188 INT
SendControlPacket(PMINI_ADAPTER Adapter
, /**<Logical Adapter*/
189 char *pControlPacket
/**<Control Packet*/
192 PLEADER PLeader
= NULL
;
194 memset(&tv
, 0, sizeof(tv
));
198 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "========>");
200 PLeader
=(PLEADER
)pControlPacket
;
201 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Tx");
202 if(!pControlPacket
|| !Adapter
)
204 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "Got NULL Control Packet or Adapter");
205 return STATUS_FAILURE
;
207 if((atomic_read( &Adapter
->CurrNumFreeTxDesc
) <
208 ((PLeader
->PLength
-1)/MAX_DEVICE_DESC_SIZE
)+1))
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)
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
);
217 return STATUS_FAILURE
;
220 /* Update the netdevice statistics */
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
)
227 #ifndef BCM_SHM_INTERFACE
228 Adapter
->interface_transmit(Adapter
->pvInterfaceAdapter
,
229 pControlPacket
, (PLeader
->PLength
+ LEADER_SIZE
));
231 tx_pkts_to_firmware(pControlPacket
,(PLeader
->PLength
+ LEADER_SIZE
),1);
233 if(PLeader
->Status
==IDLE_MESSAGE
)
235 if(((CONTROL_MESSAGE
*)PLeader
)->szData
[0] == GO_TO_IDLE_MODE_PAYLOAD
&&
236 ((CONTROL_MESSAGE
*)PLeader
)->szData
[1] == TARGET_CAN_GO_TO_IDLE_MODE
)
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
)
244 Adapter
->IdleMode
= TRUE
;
245 Adapter
->bPreparingForLowPowerMode
= FALSE
;
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
)
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
)
258 Adapter
->bShutStatus
= TRUE
;
259 Adapter
->bPreparingForLowPowerMode
= FALSE
;
260 Adapter
->bTriedToWakeUpFromlowPowerMode
= FALSE
;
266 ((PLINUX_DEP_DATA
)Adapter
->pvOsDepData
)->netstats
.tx_packets
++;
267 ((PLINUX_DEP_DATA
)Adapter
->pvOsDepData
)->netstats
.tx_bytes
+=
269 atomic_dec(&Adapter
->CurrNumFreeTxDesc
);
270 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_CONTROL
, DBG_LVL_ALL
, "<=========");
271 return STATUS_SUCCESS
;
273 static LEADER Leader
={0};
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)
280 INT
SetupNextSend(PMINI_ADAPTER Adapter
, /**<Logical Adapter*/
281 struct sk_buff
*Packet
, /**<data buffer*/
282 USHORT Vcid
) /**<VCID for this packet*/
285 #ifdef GDMA_INTERFACE
288 BOOLEAN bHeaderSupressionEnabled
= FALSE
;
289 B_UINT16 uiClassifierRuleID
;
290 int QueueIndex
= NO_OF_QUEUES
+ 1;
292 if(!Adapter
|| !Packet
)
294 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "Got NULL Adapter or Packet");
297 if(Packet
->len
> MAX_DEVICE_DESC_SIZE
)
299 status
= STATUS_FAILURE
;
303 /* Get the Classifier Rule ID */
304 uiClassifierRuleID
= *((UINT32
*) (Packet
->cb
)+SKB_CB_CLASSIFICATION_OFFSET
);
305 QueueIndex
= SearchVcid( Adapter
,Vcid
);
306 if(QueueIndex
< NO_OF_QUEUES
)
308 bHeaderSupressionEnabled
=
309 Adapter
->PackInfo
[QueueIndex
].bHeaderSuppressionEnabled
;
310 bHeaderSupressionEnabled
=
311 bHeaderSupressionEnabled
& Adapter
->bPHSEnabled
;
313 if(Adapter
->device_removed
)
315 status
= STATUS_FAILURE
;
319 status
= PHSTransmit(Adapter
, &Packet
, Vcid
, uiClassifierRuleID
, bHeaderSupressionEnabled
,
320 (UINT
*)&Packet
->len
, Adapter
->PackInfo
[QueueIndex
].bEthCSSupport
);
322 if(status
!= STATUS_SUCCESS
)
324 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "PHS Transmit failed..\n");
330 if(TCP_ACK
== *((UINT32
*) (Packet
->cb
) + SKB_CB_TCPACK_OFFSET
))
332 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "Sending TCP ACK\n");
333 Leader
.Status
= LEADER_STATUS_TCP_ACK
;
337 Leader
.Status
= LEADER_STATUS
;
340 if(Adapter
->PackInfo
[QueueIndex
].bEthCSSupport
)
342 Leader
.PLength
= Packet
->len
;
343 if(skb_headroom(Packet
) < LEADER_SIZE
)
345 if((status
= skb_cow(Packet
,LEADER_SIZE
)))
347 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
,"bcm_transmit : Failed To Increase headRoom\n");
351 skb_push(Packet
, LEADER_SIZE
);
352 memcpy(Packet
->data
, &Leader
, LEADER_SIZE
);
357 Leader
.PLength
= Packet
->len
- ETH_HLEN
;
358 memcpy((LEADER
*)skb_pull(Packet
, (ETH_HLEN
- LEADER_SIZE
)), &Leader
, LEADER_SIZE
);
361 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "Packet->len = %d", Packet
->len
);
362 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "Vcid = %d", Vcid
);
364 #ifndef BCM_SHM_INTERFACE
365 status
= Adapter
->interface_transmit(Adapter
->pvInterfaceAdapter
,
366 Packet
->data
, (Leader
.PLength
+ LEADER_SIZE
));
368 status
= tx_pkts_to_firmware(Packet
,Packet
->len
,0);
372 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, NEXT_SEND
, DBG_LVL_ALL
, "Tx Failed..\n");
376 Adapter
->PackInfo
[QueueIndex
].uiTotalTxBytes
+= Leader
.PLength
;
377 atomic_add(Leader
.PLength
, &Adapter
->GoodTxByteCount
);
378 atomic_inc(&Adapter
->TxTotalPacketCount
);
379 #ifdef GDMA_INTERFACE
384 atomic_dec(&Adapter
->CurrNumFreeTxDesc
);
388 if(STATUS_SUCCESS
== status
)
390 Adapter
->PackInfo
[QueueIndex
].uiCurrentTokenCount
-= Leader
.PLength
<< 3;
391 Adapter
->PackInfo
[QueueIndex
].uiSentBytes
+= (Packet
->len
);
392 Adapter
->PackInfo
[QueueIndex
].uiSentPackets
++;
393 Adapter
->PackInfo
[QueueIndex
].NumOfPacketsSent
++;
395 atomic_dec(&Adapter
->PackInfo
[QueueIndex
].uiPerSFTxResourceCount
);
396 #ifdef BCM_SHM_INTERFACE
397 if(atomic_read(&Adapter
->PackInfo
[QueueIndex
].uiPerSFTxResourceCount
) < 0)
399 atomic_set(&Adapter
->PackInfo
[QueueIndex
].uiPerSFTxResourceCount
, 0);
402 Adapter
->PackInfo
[QueueIndex
].uiThisPeriodSentBytes
+= Leader
.PLength
;
406 #ifdef GDMA_INTERFACE
408 bcm_kfree_skb(Packet
);
411 bcm_kfree_skb(Packet
);
417 @ingroup tx_functions
420 int tx_pkt_handler(PMINI_ADAPTER Adapter
/**< pointer to adapter object*/
423 #ifndef BCM_SHM_INTERFACE
427 UINT calltransmit
= 1;
428 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
);
433 if(Adapter
->LinkUpStatus
){
434 wait_event_timeout(Adapter
->tx_packet_wait_queue
,
435 ((atomic_read(&Adapter
->TxPktAvail
) &&
436 (MINIMUM_PENDING_DESCRIPTORS
<
437 atomic_read(&Adapter
->CurrNumFreeTxDesc
)) &&
438 (Adapter
->device_removed
== FALSE
))) ||
439 (1 == Adapter
->downloadDDR
) || kthread_should_stop()
440 #ifndef BCM_SHM_INTERFACE
441 || (TRUE
== Adapter
->bEndPointHalted
)
443 , msecs_to_jiffies(10));
446 wait_event(Adapter
->tx_packet_wait_queue
,
447 ((atomic_read(&Adapter
->TxPktAvail
) &&
448 (MINIMUM_PENDING_DESCRIPTORS
<
449 atomic_read(&Adapter
->CurrNumFreeTxDesc
)) &&
450 (Adapter
->device_removed
== FALSE
))) ||
451 (1 == Adapter
->downloadDDR
) || kthread_should_stop()
452 #ifndef BCM_SHM_INTERFACE
453 || (TRUE
== Adapter
->bEndPointHalted
)
458 if(kthread_should_stop() || Adapter
->device_removed
)
460 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Exiting the tx thread..\n");
461 Adapter
->transmit_packet_thread
= NULL
;
465 #ifndef BCM_SHM_INTERFACE
467 if(Adapter
->downloadDDR
== 1)
469 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Downloading DDR Settings\n");
470 Adapter
->downloadDDR
+=1;
471 status
= download_ddr_settings(Adapter
);
473 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "DDR DOWNLOAD FAILED!\n");
477 //Check end point for halt/stall.
478 if(Adapter
->bEndPointHalted
== TRUE
)
480 Bcm_clear_halt_of_endpoints(Adapter
);
481 Adapter
->bEndPointHalted
= FALSE
;
482 StartInterruptUrb((PS_INTERFACE_ADAPTER
)(Adapter
->pvInterfaceAdapter
));
485 if(Adapter
->LinkUpStatus
&& !Adapter
->IdleMode
)
487 if(atomic_read(&Adapter
->TotalPacketCount
))
489 update_per_sf_desc_cnts(Adapter
);
494 if( atomic_read(&Adapter
->CurrNumFreeTxDesc
) &&
495 Adapter
->LinkStatus
== SYNC_UP_REQUEST
&&
496 !Adapter
->bSyncUpRequestSent
)
498 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Calling LinkMessage");
499 LinkMessage(Adapter
);
502 if((Adapter
->IdleMode
|| Adapter
->bShutStatus
) && atomic_read(&Adapter
->TotalPacketCount
))
504 BCM_DEBUG_PRINT(Adapter
,DBG_TYPE_TX
, TX_PACKETS
, DBG_LVL_ALL
, "Device in Low Power mode...waking up");
505 Adapter
->usIdleModePattern
= ABORT_IDLE_MODE
;
506 Adapter
->bWakeUpDevice
= TRUE
;
507 wake_up(&Adapter
->process_rx_cntrlpkt
);
510 #ifdef BCM_SHM_INTERFACE
511 spin_lock_bh(&Adapter
->txtransmitlock
);
512 if(Adapter
->txtransmit_running
== 0)
514 Adapter
->txtransmit_running
= 1;
519 spin_unlock_bh(&Adapter
->txtransmitlock
);
523 transmit_packets(Adapter
);
525 atomic_set(&Adapter
->TxPktAvail
, 0);
530 #ifdef BCM_SHM_INTERFACE
531 extern PMINI_ADAPTER psAdaptertest
;
532 void virtual_mail_box_interrupt(void)
535 #ifndef GDMA_INTERFACE
536 PUINT ptr
= (PUINT
)CPE_VIRTUAL_MAILBOX_REG
;
537 UINT intval
= (UINT
)((*ptr
& 0xFF00) >> 8);
540 atomic_set(&psAdaptertest
->CurrNumFreeTxDesc
, intval
);
541 atomic_set (&psAdaptertest
->uiMBupdate
, TRUE
);
544 *ptr
= *ptr
& 0xffff00ff;
548 unsigned int total_tx_pkts_pending(void)
550 return atomic_read(&psAdaptertest
->TotalPacketCount
);