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 ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++;
216 ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+=
218 atomic_dec(&Adapter->CurrNumFreeTxDesc);
219 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
220 return STATUS_SUCCESS;
222 static LEADER Leader={0};
224 @ingroup tx_functions
225 This function despatches the IP packets with the given vcid
226 to the target via the host h/w interface.
227 @return zero(success) or -ve value(failure)
229 INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/
230 struct sk_buff *Packet, /**<data buffer*/
231 USHORT Vcid) /**<VCID for this packet*/
234 BOOLEAN bHeaderSupressionEnabled = FALSE;
235 B_UINT16 uiClassifierRuleID;
236 int QueueIndex = NO_OF_QUEUES + 1;
238 if(!Adapter || !Packet)
240 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet");
243 if(Packet->len > MAX_DEVICE_DESC_SIZE)
245 status = STATUS_FAILURE;
249 /* Get the Classifier Rule ID */
250 uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
251 QueueIndex = SearchVcid( Adapter,Vcid);
252 if(QueueIndex < NO_OF_QUEUES)
254 bHeaderSupressionEnabled =
255 Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
256 bHeaderSupressionEnabled =
257 bHeaderSupressionEnabled & Adapter->bPHSEnabled;
259 if(Adapter->device_removed)
261 status = STATUS_FAILURE;
265 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
266 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
268 if(status != STATUS_SUCCESS)
270 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
276 if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
278 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n");
279 Leader.Status = LEADER_STATUS_TCP_ACK;
283 Leader.Status = LEADER_STATUS;
286 if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
288 Leader.PLength = Packet->len;
289 if(skb_headroom(Packet) < LEADER_SIZE)
291 if((status = skb_cow(Packet,LEADER_SIZE)))
293 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
297 skb_push(Packet, LEADER_SIZE);
298 memcpy(Packet->data, &Leader, LEADER_SIZE);
303 Leader.PLength = Packet->len - ETH_HLEN;
304 memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
307 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len);
308 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid);
310 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
311 Packet->data, (Leader.PLength + LEADER_SIZE));
314 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n");
318 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
319 atomic_add(Leader.PLength, &Adapter->GoodTxByteCount);
320 atomic_inc(&Adapter->TxTotalPacketCount);
323 atomic_dec(&Adapter->CurrNumFreeTxDesc);
327 if(STATUS_SUCCESS == status)
329 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
330 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
331 Adapter->PackInfo[QueueIndex].uiSentPackets++;
332 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
334 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
335 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
339 bcm_kfree_skb(Packet);
344 @ingroup tx_functions
347 int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
352 UINT calltransmit = 1;
353 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);
358 if(Adapter->LinkUpStatus){
359 wait_event_timeout(Adapter->tx_packet_wait_queue,
360 ((atomic_read(&Adapter->TxPktAvail) &&
361 (MINIMUM_PENDING_DESCRIPTORS <
362 atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
363 (Adapter->device_removed == FALSE))) ||
364 (1 == Adapter->downloadDDR) || kthread_should_stop()
365 || (TRUE == Adapter->bEndPointHalted)
366 , msecs_to_jiffies(10));
369 wait_event(Adapter->tx_packet_wait_queue,
370 ((atomic_read(&Adapter->TxPktAvail) &&
371 (MINIMUM_PENDING_DESCRIPTORS <
372 atomic_read(&Adapter->CurrNumFreeTxDesc)) &&
373 (Adapter->device_removed == FALSE))) ||
374 (1 == Adapter->downloadDDR) || kthread_should_stop()
375 || (TRUE == Adapter->bEndPointHalted)
379 if(kthread_should_stop() || Adapter->device_removed)
381 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
382 Adapter->transmit_packet_thread = NULL;
387 if(Adapter->downloadDDR == 1)
389 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n");
390 Adapter->downloadDDR +=1;
391 status = download_ddr_settings(Adapter);
393 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n");
397 //Check end point for halt/stall.
398 if(Adapter->bEndPointHalted == TRUE)
400 Bcm_clear_halt_of_endpoints(Adapter);
401 Adapter->bEndPointHalted = FALSE;
402 StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
405 if(Adapter->LinkUpStatus && !Adapter->IdleMode)
407 if(atomic_read(&Adapter->TotalPacketCount))
409 update_per_sf_desc_cnts(Adapter);
413 if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
414 Adapter->LinkStatus == SYNC_UP_REQUEST &&
415 !Adapter->bSyncUpRequestSent)
417 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
418 LinkMessage(Adapter);
421 if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
423 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
424 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
425 Adapter->bWakeUpDevice = TRUE;
426 wake_up(&Adapter->process_rx_cntrlpkt);
431 transmit_packets(Adapter);
433 atomic_set(&Adapter->TxPktAvail, 0);