ptp: fix missing break in switch
[linux/fpc-iii.git] / drivers / staging / bcm / Transmit.c
blob622a482e9826442d26bca842b0200e84d12fdca8
1 /**
2 * @file Transmit.c
3 * @defgroup tx_functions Transmission
4 * @section Queueing
5 * @dot
6 * digraph transmit1 {
7 * node[shape=box]
8 * edge[weight=5;color=red]
10 * bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
11 * GetPacketQueueIndex->IpVersion4[label="IPV4"]
12 * GetPacketQueueIndex->IpVersion6[label="IPV6"]
13 * }
15 * @enddot
17 * @section De-Queueing
18 * @dot
19 * digraph transmit2 {
20 * node[shape=box]
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
32 * }
33 * @enddot
36 #include "headers.h"
38 /**
39 * @ingroup ctrl_pkt_functions
40 * This function dispatches control packet to the h/w interface
41 * @return zero(success) or -ve value(failure)
43 int SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket)
45 struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket;
47 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
48 if (!pControlPacket || !Adapter) {
49 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
50 "Got NULL Control Packet or Adapter");
51 return STATUS_FAILURE;
53 if ((atomic_read(&Adapter->CurrNumFreeTxDesc) <
54 ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) {
55 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
56 "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
57 return STATUS_FAILURE;
60 /* Update the netdevice statistics */
61 /* Dump Packet */
62 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
63 "Leader Status: %x", PLeader->Status);
64 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
65 "Leader VCID: %x", PLeader->Vcid);
66 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
67 "Leader Length: %x", PLeader->PLength);
68 if (Adapter->device_removed)
69 return 0;
71 if (netif_msg_pktdata(Adapter))
72 print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
73 16, 1, pControlPacket,
74 PLeader->PLength + LEADER_SIZE, 0);
76 Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
77 pControlPacket,
78 (PLeader->PLength + LEADER_SIZE));
80 atomic_dec(&Adapter->CurrNumFreeTxDesc);
81 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL,
82 "<=========");
83 return STATUS_SUCCESS;
86 /**
87 * @ingroup tx_functions
88 * This function despatches the IP packets with the given vcid
89 * to the target via the host h/w interface.
90 * @return zero(success) or -ve value(failure)
92 int SetupNextSend(struct bcm_mini_adapter *Adapter,
93 struct sk_buff *Packet, USHORT Vcid)
95 int status = 0;
96 bool bHeaderSupressionEnabled = false;
97 B_UINT16 uiClassifierRuleID;
98 u16 QueueIndex = skb_get_queue_mapping(Packet);
99 struct bcm_packet_info *curr_packet_info =
100 &Adapter->PackInfo[QueueIndex];
101 struct bcm_leader Leader = {0};
103 if (Packet->len > MAX_DEVICE_DESC_SIZE) {
104 status = STATUS_FAILURE;
105 goto errExit;
108 /* Get the Classifier Rule ID */
109 uiClassifierRuleID = *((UINT32 *) (Packet->cb) +
110 SKB_CB_CLASSIFICATION_OFFSET);
112 bHeaderSupressionEnabled = curr_packet_info->bHeaderSuppressionEnabled &
113 Adapter->bPHSEnabled;
115 if (Adapter->device_removed) {
116 status = STATUS_FAILURE;
117 goto errExit;
120 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID,
121 bHeaderSupressionEnabled,
122 (UINT *)&Packet->len,
123 curr_packet_info->bEthCSSupport);
125 if (status != STATUS_SUCCESS) {
126 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,
127 "PHS Transmit failed..\n");
128 goto errExit;
131 Leader.Vcid = Vcid;
133 if (TCP_ACK == *((UINT32 *) (Packet->cb) + SKB_CB_TCPACK_OFFSET))
134 Leader.Status = LEADER_STATUS_TCP_ACK;
135 else
136 Leader.Status = LEADER_STATUS;
138 if (curr_packet_info->bEthCSSupport) {
139 Leader.PLength = Packet->len;
140 if (skb_headroom(Packet) < LEADER_SIZE) {
141 status = skb_cow(Packet, LEADER_SIZE);
142 if (status) {
143 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND,
144 DBG_LVL_ALL,
145 "bcm_transmit : Failed To Increase headRoom\n");
146 goto errExit;
149 skb_push(Packet, LEADER_SIZE);
150 memcpy(Packet->data, &Leader, LEADER_SIZE);
151 } else {
152 Leader.PLength = Packet->len - ETH_HLEN;
153 memcpy((struct bcm_leader *)skb_pull(Packet,
154 (ETH_HLEN - LEADER_SIZE)),
155 &Leader,
156 LEADER_SIZE);
159 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
160 Packet->data,
161 (Leader.PLength + LEADER_SIZE));
162 if (status) {
163 ++Adapter->dev->stats.tx_errors;
164 if (netif_msg_tx_err(Adapter))
165 pr_info(PFX "%s: transmit error %d\n",
166 Adapter->dev->name,
167 status);
168 } else {
169 struct net_device_stats *netstats = &Adapter->dev->stats;
171 curr_packet_info->uiTotalTxBytes += Leader.PLength;
173 netstats->tx_bytes += Leader.PLength;
174 ++netstats->tx_packets;
176 curr_packet_info->uiCurrentTokenCount -= Leader.PLength << 3;
177 curr_packet_info->uiSentBytes += (Packet->len);
178 curr_packet_info->uiSentPackets++;
179 curr_packet_info->NumOfPacketsSent++;
181 atomic_dec(&curr_packet_info->uiPerSFTxResourceCount);
182 curr_packet_info->uiThisPeriodSentBytes += Leader.PLength;
185 atomic_dec(&Adapter->CurrNumFreeTxDesc);
187 errExit:
188 dev_kfree_skb(Packet);
189 return status;
192 static int tx_pending(struct bcm_mini_adapter *Adapter)
194 return (atomic_read(&Adapter->TxPktAvail)
195 && MINIMUM_PENDING_DESCRIPTORS <
196 atomic_read(&Adapter->CurrNumFreeTxDesc))
197 || Adapter->device_removed || (1 == Adapter->downloadDDR);
201 * @ingroup tx_functions
202 * Transmit thread
204 int tx_pkt_handler(struct bcm_mini_adapter *Adapter)
206 int status = 0;
208 while (!kthread_should_stop()) {
209 /* FIXME - the timeout looks like workaround
210 * for racey usage of TxPktAvail
212 if (Adapter->LinkUpStatus)
213 wait_event_timeout(Adapter->tx_packet_wait_queue,
214 tx_pending(Adapter),
215 msecs_to_jiffies(10));
216 else
217 wait_event_interruptible(Adapter->tx_packet_wait_queue,
218 tx_pending(Adapter));
220 if (Adapter->device_removed)
221 break;
223 if (Adapter->downloadDDR == 1) {
224 Adapter->downloadDDR += 1;
225 status = download_ddr_settings(Adapter);
226 if (status)
227 pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
228 continue;
231 /* Check end point for halt/stall. */
232 if (Adapter->bEndPointHalted == TRUE) {
233 Bcm_clear_halt_of_endpoints(Adapter);
234 Adapter->bEndPointHalted = false;
235 StartInterruptUrb((struct bcm_interface_adapter *)
236 (Adapter->pvInterfaceAdapter));
239 if (Adapter->LinkUpStatus && !Adapter->IdleMode) {
240 if (atomic_read(&Adapter->TotalPacketCount))
241 update_per_sf_desc_cnts(Adapter);
244 if (atomic_read(&Adapter->CurrNumFreeTxDesc) &&
245 Adapter->LinkStatus == SYNC_UP_REQUEST &&
246 !Adapter->bSyncUpRequestSent) {
248 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS,
249 DBG_LVL_ALL, "Calling LinkMessage");
250 LinkMessage(Adapter);
253 if ((Adapter->IdleMode || Adapter->bShutStatus) &&
254 atomic_read(&Adapter->TotalPacketCount)) {
255 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX,
256 TX_PACKETS, DBG_LVL_ALL,
257 "Device in Low Power mode...waking up");
258 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
259 Adapter->bWakeUpDevice = TRUE;
260 wake_up(&Adapter->process_rx_cntrlpkt);
263 transmit_packets(Adapter);
264 atomic_set(&Adapter->TxPktAvail, 0);
267 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL,
268 "Exiting the tx thread..\n");
269 Adapter->transmit_packet_thread = NULL;
270 return 0;