blob: 972e6ab6fae6cb93b00c68f6e3078c9072e6b070 [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;
Stephen Hemmingercacd9222010-11-01 13:34:35 -040093 u16 QueueIndex = skb_get_queue_mapping(Packet);
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);
Stephen Hemmingercacd9222010-11-01 13:34:35 -0400104
105 bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
106 & Adapter->bPHSEnabled;
107
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700108 if(Adapter->device_removed)
109 {
110 status = STATUS_FAILURE;
111 goto errExit;
112 }
113
114 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
115 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
116
117 if(status != STATUS_SUCCESS)
118 {
119 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
120 goto errExit;
121 }
122
123 Leader.Vcid = Vcid;
124
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400125 if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700126 Leader.Status = LEADER_STATUS_TCP_ACK;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700127 else
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700128 Leader.Status = LEADER_STATUS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700129
130 if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
131 {
132 Leader.PLength = Packet->len;
133 if(skb_headroom(Packet) < LEADER_SIZE)
134 {
135 if((status = skb_cow(Packet,LEADER_SIZE)))
136 {
137 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
138 goto errExit;
139 }
140 }
141 skb_push(Packet, LEADER_SIZE);
142 memcpy(Packet->data, &Leader, LEADER_SIZE);
143 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700144 else
145 {
146 Leader.PLength = Packet->len - ETH_HLEN;
147 memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
148 }
149
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700150 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
151 Packet->data, (Leader.PLength + LEADER_SIZE));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700152 if(status)
153 {
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400154 ++Adapter->dev->stats.tx_errors;
155 if (netif_msg_tx_err(Adapter))
156 pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
157 status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700158 }
159 else
160 {
Stephen Hemmingercacd9222010-11-01 13:34:35 -0400161 struct netdev_queue *txq = netdev_get_tx_queue(Adapter->dev, QueueIndex);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700162 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
Stephen Hemmingercacd9222010-11-01 13:34:35 -0400163
164 txq->tx_bytes += Leader.PLength;
165 ++txq->tx_packets;
166
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700167 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
168 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
169 Adapter->PackInfo[QueueIndex].uiSentPackets++;
170 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
171
172 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700173 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
174 }
175
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400176 atomic_dec(&Adapter->CurrNumFreeTxDesc);
177
178errExit:
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700179
Stephen Hemminger082e8892010-11-01 09:35:21 -0400180 dev_kfree_skb(Packet);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700181 return status;
182}
183
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400184static int tx_pending(PMINI_ADAPTER Adapter)
185{
186 return (atomic_read(&Adapter->TxPktAvail)
187 && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
188 || Adapter->device_removed || (1 == Adapter->downloadDDR);
189}
190
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700191/**
192@ingroup tx_functions
193Transmit thread
194*/
195int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
196 )
197{
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700198 int status = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700199
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400200 while(! kthread_should_stop()) {
201 /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
202 if(Adapter->LinkUpStatus)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700203 wait_event_timeout(Adapter->tx_packet_wait_queue,
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400204 tx_pending(Adapter), msecs_to_jiffies(10));
205 else
206 wait_event_interruptible(Adapter->tx_packet_wait_queue,
207 tx_pending(Adapter));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700208
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400209 if (Adapter->device_removed)
210 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700211
212 if(Adapter->downloadDDR == 1)
213 {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700214 Adapter->downloadDDR +=1;
215 status = download_ddr_settings(Adapter);
216 if(status)
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400217 pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700218 continue;
219 }
220
221 //Check end point for halt/stall.
222 if(Adapter->bEndPointHalted == TRUE)
223 {
224 Bcm_clear_halt_of_endpoints(Adapter);
225 Adapter->bEndPointHalted = FALSE;
226 StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
227 }
228
229 if(Adapter->LinkUpStatus && !Adapter->IdleMode)
230 {
231 if(atomic_read(&Adapter->TotalPacketCount))
232 {
233 update_per_sf_desc_cnts(Adapter);
234 }
235 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700236
237 if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
238 Adapter->LinkStatus == SYNC_UP_REQUEST &&
239 !Adapter->bSyncUpRequestSent)
240 {
241 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
242 LinkMessage(Adapter);
243 }
244
245 if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
246 {
247 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
248 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
249 Adapter->bWakeUpDevice = TRUE;
250 wake_up(&Adapter->process_rx_cntrlpkt);
251 }
252
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400253 transmit_packets(Adapter);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700254
255 atomic_set(&Adapter->TxPktAvail, 0);
256 }
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400257
258 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
259 Adapter->transmit_packet_thread = NULL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700260 return 0;
261}