Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

Feb 18-20, 2025
Register
Loading...
Note: File does not exist in v4.17.
  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]
  9
 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/**
 40@ingroup ctrl_pkt_functions
 41This function dispatches control packet to the h/w interface
 42@return zero(success) or -ve value(failure)
 43*/
 44INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket)
 45{
 46	PLEADER PLeader = (PLEADER)pControlPacket;
 47
 48	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
 49	if(!pControlPacket || !Adapter)
 50	{
 51		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
 52		return STATUS_FAILURE;
 53	}
 54	if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <
 55		((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
 56    {
 57    	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
 58        return STATUS_FAILURE;
 59    }
 60
 61	/* Update the netdevice statistics */
 62	/* Dump Packet  */
 63	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
 64	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
 65	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
 66	if(Adapter->device_removed)
 67		return 0;
 68
 69	if (netif_msg_pktdata(Adapter))
 70		print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
 71			       16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0);
 72
 73	Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
 74					pControlPacket, (PLeader->PLength + LEADER_SIZE));
 75
 76	atomic_dec(&Adapter->CurrNumFreeTxDesc);
 77	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
 78	return STATUS_SUCCESS;
 79}
 80
 81/**
 82@ingroup tx_functions
 83This function despatches the IP packets with the given vcid
 84to the target via the host h/w interface.
 85@return  zero(success) or -ve value(failure)
 86*/
 87INT SetupNextSend(PMINI_ADAPTER Adapter,  struct sk_buff *Packet, USHORT Vcid)
 88{
 89	int		status=0;
 90	BOOLEAN bHeaderSupressionEnabled = FALSE;
 91	B_UINT16            uiClassifierRuleID;
 92	u16	QueueIndex = skb_get_queue_mapping(Packet);
 93	LEADER Leader={0};
 94
 95	if(Packet->len > MAX_DEVICE_DESC_SIZE)
 96	{
 97		status = STATUS_FAILURE;
 98		goto errExit;
 99	}
100
101	/* Get the Classifier Rule ID */
102	uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
103
104	bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
105		& Adapter->bPHSEnabled;
106
107	if(Adapter->device_removed)
108		{
109		status = STATUS_FAILURE;
110		goto errExit;
111		}
112
113	status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
114							(UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
115
116	if(status != STATUS_SUCCESS)
117	{
118		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
119		goto errExit;
120	}
121
122	Leader.Vcid	= Vcid;
123
124	if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
125		Leader.Status = LEADER_STATUS_TCP_ACK;
126	else
127		Leader.Status = LEADER_STATUS;
128
129	if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
130	{
131		Leader.PLength = Packet->len;
132		if(skb_headroom(Packet) < LEADER_SIZE)
133        {
134			if((status = skb_cow(Packet,LEADER_SIZE)))
135			{
136				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
137				goto errExit;
138			}
139		}
140		skb_push(Packet, LEADER_SIZE);
141		memcpy(Packet->data, &Leader, LEADER_SIZE);
142	}
143	else
144	{
145		Leader.PLength = Packet->len - ETH_HLEN;
146		memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
147	}
148
149	status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
150			Packet->data, (Leader.PLength + LEADER_SIZE));
151	if(status)
152	{
153		++Adapter->dev->stats.tx_errors;
154		if (netif_msg_tx_err(Adapter))
155			pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
156				status);
157	}
158	else
159	{
160		struct net_device_stats *netstats = &Adapter->dev->stats;
161		Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
162
163		netstats->tx_bytes += Leader.PLength;
164		++netstats->tx_packets;
165
166		Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
167		Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
168		Adapter->PackInfo[QueueIndex].uiSentPackets++;
169		Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
170
171		atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
172		Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
173	}
174
175	atomic_dec(&Adapter->CurrNumFreeTxDesc);
176
177errExit:
178
179	dev_kfree_skb(Packet);
180	return status;
181}
182
183static int tx_pending(PMINI_ADAPTER Adapter)
184{
185	return (atomic_read(&Adapter->TxPktAvail)
186		&& MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
187		|| Adapter->device_removed || (1 == Adapter->downloadDDR);
188}
189
190/**
191@ingroup tx_functions
192Transmit thread
193*/
194int tx_pkt_handler(PMINI_ADAPTER Adapter  /**< pointer to adapter object*/
195				)
196{
197	int status = 0;
198
199	while(! kthread_should_stop()) {
200		/* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
201		if(Adapter->LinkUpStatus)
202			wait_event_timeout(Adapter->tx_packet_wait_queue,
203					   tx_pending(Adapter), msecs_to_jiffies(10));
204		else
205			wait_event_interruptible(Adapter->tx_packet_wait_queue,
206						 tx_pending(Adapter));
207
208		if (Adapter->device_removed)
209			break;
210
211		if(Adapter->downloadDDR == 1)
212		{
213			Adapter->downloadDDR +=1;
214			status = download_ddr_settings(Adapter);
215			if(status)
216				pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
217			continue;
218		}
219
220		//Check end point for halt/stall.
221		if(Adapter->bEndPointHalted == TRUE)
222		{
223			Bcm_clear_halt_of_endpoints(Adapter);
224			Adapter->bEndPointHalted = FALSE;
225			StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
226		}
227
228		if(Adapter->LinkUpStatus && !Adapter->IdleMode)
229		{
230			if(atomic_read(&Adapter->TotalPacketCount))
231			{
232				update_per_sf_desc_cnts(Adapter);
233			}
234		}
235
236		if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
237			Adapter->LinkStatus == SYNC_UP_REQUEST &&
238			!Adapter->bSyncUpRequestSent)
239		{
240			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
241			LinkMessage(Adapter);
242		}
243
244		if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
245		{
246				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
247    			Adapter->usIdleModePattern = ABORT_IDLE_MODE;
248				Adapter->bWakeUpDevice = TRUE;
249				wake_up(&Adapter->process_rx_cntrlpkt);
250		}
251
252		transmit_packets(Adapter);
253
254		atomic_set(&Adapter->TxPktAvail, 0);
255	}
256
257	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
258	Adapter->transmit_packet_thread = NULL;
259	return 0;
260}