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 if(calltransmit == 1)
150 transmit_packets(Adapter);
153 if(!atomic_read(&Adapter->TxPktAvail))
155 atomic_set(&Adapter->TxPktAvail, 1);
156 wake_up(&Adapter->tx_packet_wait_queue);
159 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<====");
164 return STATUS_SUCCESS;
169 @ingroup ctrl_pkt_functions
170 This function dispatches control packet to the h/w interface
171 @return zero(success) or -ve value(failure)
173 INT SendControlPacket(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
174 char *pControlPacket/**<Control Packet*/
177 PLEADER PLeader = NULL;
179 memset(&tv, 0, sizeof(tv));
183 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "========>");
185 PLeader=(PLEADER)pControlPacket;
186 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
187 if(!pControlPacket || !Adapter)
189 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
190 return STATUS_FAILURE;
192 if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <
193 ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
195 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
196 if(Adapter->bcm_jiffies == 0)
198 Adapter->bcm_jiffies = jiffies;
199 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu",
200 Adapter->bcm_jiffies);
202 return STATUS_FAILURE;
205 /* Update the netdevice statistics */
207 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
208 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
209 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
210 if(Adapter->device_removed)
212 Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
213 pControlPacket, (PLeader->PLength + LEADER_SIZE));
215 atomic_dec(&Adapter->CurrNumFreeTxDesc);
216 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
217 return STATUS_SUCCESS;
219 static LEADER Leader={0};
221 @ingroup tx_functions
222 This function despatches the IP packets with the given vcid
223 to the target via the host h/w interface.
224 @return zero(success) or -ve value(failure)
226 INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
227 struct sk_buff *Packet, /**<data buffer*/
228 USHORT Vcid) /**<VCID for this packet*/
231 BOOLEAN bHeaderSupressionEnabled = FALSE;
232 B_UINT16 uiClassifierRuleID;
233 int QueueIndex = NO_OF_QUEUES + 1;
235 if(!Adapter || !Packet)
237 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet");
240 if(Packet->len > MAX_DEVICE_DESC_SIZE)
242 status = STATUS_FAILURE;
246 /* Get the Classifier Rule ID */
247 uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
248 QueueIndex = SearchVcid( Adapter,Vcid);
249 if(QueueIndex < NO_OF_QUEUES)
251 bHeaderSupressionEnabled =
252 Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
253 bHeaderSupressionEnabled =
254 bHeaderSupressionEnabled & Adapter->bPHSEnabled;
256 if(Adapter->device_removed)
258 status = STATUS_FAILURE;
262 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
263 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
265 if(status != STATUS_SUCCESS)
267 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
273 if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
275 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n");
276 Leader.Status = LEADER_STATUS_TCP_ACK;
280 Leader.Status = LEADER_STATUS;
283 if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
285 Leader.PLength = Packet->len;
286 if(skb_headroom(Packet) < LEADER_SIZE)
288 if((status = skb_cow(Packet,LEADER_SIZE)))
290 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
294 skb_push(Packet, LEADER_SIZE);
295 memcpy(Packet->data, &Leader, LEADER_SIZE);
300 Leader.PLength = Packet->len - ETH_HLEN;
301 memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
304 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len);
305 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid);
307 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
308 Packet->data, (Leader.PLength + LEADER_SIZE));
311 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n");
315 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
316 atomic_add(Leader.PLength, &Adapter->GoodTxByteCount);
317 atomic_inc(&Adapter->TxTotalPacketCount);
320 atomic_dec(&Adapter->CurrNumFreeTxDesc);
324 if(STATUS_SUCCESS == status)
326 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
327 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
328 Adapter->PackInfo[QueueIndex].uiSentPackets++;
329 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
331 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
332 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
336 dev_kfree_skb(Packet);
341 @ingroup tx_functions
344 int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
349 UINT calltransmit = 1;
350 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);
355 if(Adapter->LinkUpStatus){
356 wait_event_timeout(Adapter->tx_packet_wait_queue,
357 ((atomic_read(&Adapter->TxPktAvail) &&
358 (MINIMUM_PENDING_DESCRIPTORS <
359 atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
360 (Adapter->device_removed == FALSE))) ||
361 (1 == Adapter->downloadDDR) || kthread_should_stop()
362 || (TRUE == Adapter->bEndPointHalted)
363 , msecs_to_jiffies(10));
366 wait_event(Adapter->tx_packet_wait_queue,
367 ((atomic_read(&Adapter->TxPktAvail) &&
368 (MINIMUM_PENDING_DESCRIPTORS <
369 atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
370 (Adapter->device_removed == FALSE))) ||
371 (1 == Adapter->downloadDDR) || kthread_should_stop()
372 || (TRUE == Adapter->bEndPointHalted)
376 if(kthread_should_stop() || Adapter->device_removed)
378 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
379 Adapter->transmit_packet_thread = NULL;
384 if(Adapter->downloadDDR == 1)
386 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n");
387 Adapter->downloadDDR +=1;
388 status = download_ddr_settings(Adapter);
390 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n");
394 //Check end point for halt/stall.
395 if(Adapter->bEndPointHalted == TRUE)
397 Bcm_clear_halt_of_endpoints(Adapter);
398 Adapter->bEndPointHalted = FALSE;
399 StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
402 if(Adapter->LinkUpStatus && !Adapter->IdleMode)
404 if(atomic_read(&Adapter->TotalPacketCount))
406 update_per_sf_desc_cnts(Adapter);
410 if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
411 Adapter->LinkStatus == SYNC_UP_REQUEST &&
412 !Adapter->bSyncUpRequestSent)
414 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
415 LinkMessage(Adapter);
418 if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
420 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
421 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
422 Adapter->bWakeUpDevice = TRUE;
423 wake_up(&Adapter->process_rx_cntrlpkt);
428 transmit_packets(Adapter);
430 atomic_set(&Adapter->TxPktAvail, 0);