blob: b924a6a4dd78ca4eb68515aa0fa45c267adc60e7 [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001/**
2@file Transmit.c
3@defgroup tx_functions Transmission
4@section Queueing
5@dot
6digraph transmit1 {
7node[shape=box]
8edge[weight=5;color=red]
Stephen Hemminger74416982010-11-01 09:53:58 -04009
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070010bcm_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
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070038
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*/
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -040044INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070045{
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -040046 PLEADER PLeader = (PLEADER)pControlPacket;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070047
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070048 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 if(Adapter->bcm_jiffies == 0)
59 {
60 Adapter->bcm_jiffies = jiffies;
61 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu",
62 Adapter->bcm_jiffies);
63 }
64 return STATUS_FAILURE;
65 }
66
67 /* Update the netdevice statistics */
68 /* Dump Packet */
69 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
70 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
71 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
72 if(Adapter->device_removed)
73 return 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070074 Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
75 pControlPacket, (PLeader->PLength + LEADER_SIZE));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070076
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070077 atomic_dec(&Adapter->CurrNumFreeTxDesc);
78 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
79 return STATUS_SUCCESS;
80}
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -040081
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070082/**
83@ingroup tx_functions
84This function despatches the IP packets with the given vcid
85to the target via the host h/w interface.
86@return zero(success) or -ve value(failure)
87*/
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -040088INT SetupNextSend(PMINI_ADAPTER Adapter, struct sk_buff *Packet, USHORT Vcid)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070089{
90 int status=0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070091 BOOLEAN bHeaderSupressionEnabled = FALSE;
92 B_UINT16 uiClassifierRuleID;
93 int QueueIndex = NO_OF_QUEUES + 1;
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -040094 LEADER Leader={0};
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070095
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070096 if(Packet->len > MAX_DEVICE_DESC_SIZE)
97 {
98 status = STATUS_FAILURE;
99 goto errExit;
100 }
101
102 /* Get the Classifier Rule ID */
103 uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
104 QueueIndex = SearchVcid( Adapter,Vcid);
105 if(QueueIndex < NO_OF_QUEUES)
106 {
107 bHeaderSupressionEnabled =
108 Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled;
109 bHeaderSupressionEnabled =
110 bHeaderSupressionEnabled & Adapter->bPHSEnabled;
111 }
112 if(Adapter->device_removed)
113 {
114 status = STATUS_FAILURE;
115 goto errExit;
116 }
117
118 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
119 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
120
121 if(status != STATUS_SUCCESS)
122 {
123 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
124 goto errExit;
125 }
126
127 Leader.Vcid = Vcid;
128
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400129 if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700130 Leader.Status = LEADER_STATUS_TCP_ACK;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700131 else
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700132 Leader.Status = LEADER_STATUS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700133
134 if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
135 {
136 Leader.PLength = Packet->len;
137 if(skb_headroom(Packet) < LEADER_SIZE)
138 {
139 if((status = skb_cow(Packet,LEADER_SIZE)))
140 {
141 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
142 goto errExit;
143 }
144 }
145 skb_push(Packet, LEADER_SIZE);
146 memcpy(Packet->data, &Leader, LEADER_SIZE);
147 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700148 else
149 {
150 Leader.PLength = Packet->len - ETH_HLEN;
151 memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
152 }
153
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700154 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
155 Packet->data, (Leader.PLength + LEADER_SIZE));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700156 if(status)
157 {
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400158 ++Adapter->dev->stats.tx_errors;
159 if (netif_msg_tx_err(Adapter))
160 pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
161 status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700162 }
163 else
164 {
165 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400166 Adapter->dev->stats.tx_bytes += Leader.PLength;
167 ++Adapter->dev->stats.tx_packets;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700168 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
169 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
170 Adapter->PackInfo[QueueIndex].uiSentPackets++;
171 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
172
173 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700174 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
175 }
176
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400177 atomic_dec(&Adapter->CurrNumFreeTxDesc);
178
179errExit:
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700180
Stephen Hemminger082e8892010-11-01 09:35:21 -0400181 dev_kfree_skb(Packet);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700182 return status;
183}
184
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400185static int tx_pending(PMINI_ADAPTER Adapter)
186{
187 return (atomic_read(&Adapter->TxPktAvail)
188 && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
189 || Adapter->device_removed || (1 == Adapter->downloadDDR);
190}
191
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700192/**
193@ingroup tx_functions
194Transmit thread
195*/
196int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
197 )
198{
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700199 int status = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700200
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400201 while(! kthread_should_stop()) {
202 /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
203 if(Adapter->LinkUpStatus)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700204 wait_event_timeout(Adapter->tx_packet_wait_queue,
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400205 tx_pending(Adapter), msecs_to_jiffies(10));
206 else
207 wait_event_interruptible(Adapter->tx_packet_wait_queue,
208 tx_pending(Adapter));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700209
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400210 if (Adapter->device_removed)
211 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700212
213 if(Adapter->downloadDDR == 1)
214 {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700215 Adapter->downloadDDR +=1;
216 status = download_ddr_settings(Adapter);
217 if(status)
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400218 pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700219 continue;
220 }
221
222 //Check end point for halt/stall.
223 if(Adapter->bEndPointHalted == TRUE)
224 {
225 Bcm_clear_halt_of_endpoints(Adapter);
226 Adapter->bEndPointHalted = FALSE;
227 StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
228 }
229
230 if(Adapter->LinkUpStatus && !Adapter->IdleMode)
231 {
232 if(atomic_read(&Adapter->TotalPacketCount))
233 {
234 update_per_sf_desc_cnts(Adapter);
235 }
236 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700237
238 if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
239 Adapter->LinkStatus == SYNC_UP_REQUEST &&
240 !Adapter->bSyncUpRequestSent)
241 {
242 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
243 LinkMessage(Adapter);
244 }
245
246 if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
247 {
248 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
249 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
250 Adapter->bWakeUpDevice = TRUE;
251 wake_up(&Adapter->process_rx_cntrlpkt);
252 }
253
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400254 transmit_packets(Adapter);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700255
256 atomic_set(&Adapter->TxPktAvail, 0);
257 }
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400258
259 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
260 Adapter->transmit_packet_thread = NULL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700261 return 0;
262}