blob: 2ed4836b965410a2ef556fb9d76e06206d6f6781 [file] [log] [blame]
Stephen Hemmingerf8942e02010-09-08 14:46:36 -07001/**
Kevin McKinneyb9e25f82012-09-13 21:11:37 -04002 * @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]
9 *
10 * bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
11 * GetPacketQueueIndex->IpVersion4[label="IPV4"]
12 * GetPacketQueueIndex->IpVersion6[label="IPV6"]
13 * }
14 *
15 * @enddot
16 *
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
34 */
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070035
36#include "headers.h"
37
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070038/**
Kevin McKinneyb9e25f82012-09-13 21:11:37 -040039 * @ingroup ctrl_pkt_functions
40 * This function dispatches control packet to the h/w interface
41 * @return zero(success) or -ve value(failure)
42 */
Kevin McKinneyae1cbea2012-09-13 21:11:38 -040043int SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070044{
Kevin McKinneyff352042012-05-26 12:05:11 -040045 struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070046
Kevin McKinney22976bc2012-09-13 21:11:34 -040047 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
Kevin McKinney97e0a502012-09-13 21:11:35 -040048 if (!pControlPacket || !Adapter) {
Kevin McKinney22976bc2012-09-13 21:11:34 -040049 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070050 return STATUS_FAILURE;
51 }
Kevin McKinney22976bc2012-09-13 21:11:34 -040052 if ((atomic_read(&Adapter->CurrNumFreeTxDesc) <
Kevin McKinney97e0a502012-09-13 21:11:35 -040053 ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) {
Kevin McKinney22976bc2012-09-13 21:11:34 -040054 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
55 return STATUS_FAILURE;
56 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070057
58 /* Update the netdevice statistics */
59 /* Dump Packet */
Kevin McKinney22976bc2012-09-13 21:11:34 -040060 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
61 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x", PLeader->Vcid);
62 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x", PLeader->PLength);
63 if (Adapter->device_removed)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070064 return 0;
Stephen Hemminger349fa792010-11-01 14:09:05 -040065
66 if (netif_msg_pktdata(Adapter))
67 print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
Kevin McKinney22976bc2012-09-13 21:11:34 -040068 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0);
Stephen Hemminger349fa792010-11-01 14:09:05 -040069
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070070 Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
Kevin McKinney22976bc2012-09-13 21:11:34 -040071 pControlPacket, (PLeader->PLength + LEADER_SIZE));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070072
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070073 atomic_dec(&Adapter->CurrNumFreeTxDesc);
Kevin McKinney22976bc2012-09-13 21:11:34 -040074 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070075 return STATUS_SUCCESS;
76}
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -040077
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070078/**
Kevin McKinneyb9e25f82012-09-13 21:11:37 -040079 * @ingroup tx_functions
80 * This function despatches the IP packets with the given vcid
81 * to the target via the host h/w interface.
82 * @return zero(success) or -ve value(failure)
83 */
Kevin McKinneyae1cbea2012-09-13 21:11:38 -040084int SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070085{
Kevin McKinney22976bc2012-09-13 21:11:34 -040086 int status = 0;
Lisa Nguyenf70c8a92013-10-28 01:36:19 -070087 bool bHeaderSupressionEnabled = false;
Kevin McKinney22976bc2012-09-13 21:11:34 -040088 B_UINT16 uiClassifierRuleID;
Stephen Hemmingercacd9222010-11-01 13:34:35 -040089 u16 QueueIndex = skb_get_queue_mapping(Packet);
Kevin McKinney22976bc2012-09-13 21:11:34 -040090 struct bcm_leader Leader = {0};
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070091
Kevin McKinney97e0a502012-09-13 21:11:35 -040092 if (Packet->len > MAX_DEVICE_DESC_SIZE) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -070093 status = STATUS_FAILURE;
94 goto errExit;
95 }
96
97 /* Get the Classifier Rule ID */
Kevin McKinney22976bc2012-09-13 21:11:34 -040098 uiClassifierRuleID = *((UINT32 *) (Packet->cb) + SKB_CB_CLASSIFICATION_OFFSET);
Stephen Hemmingercacd9222010-11-01 13:34:35 -040099
100 bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
101 & Adapter->bPHSEnabled;
102
Kevin McKinney97e0a502012-09-13 21:11:35 -0400103 if (Adapter->device_removed) {
Kevin McKinney22976bc2012-09-13 21:11:34 -0400104 status = STATUS_FAILURE;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700105 goto errExit;
106 }
107
Kevin McKinney22976bc2012-09-13 21:11:34 -0400108 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
109 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700110
Kevin McKinney97e0a502012-09-13 21:11:35 -0400111 if (status != STATUS_SUCCESS) {
Kevin McKinney22976bc2012-09-13 21:11:34 -0400112 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
113 goto errExit;
114 }
115
116 Leader.Vcid = Vcid;
117
118 if (TCP_ACK == *((UINT32 *) (Packet->cb) + SKB_CB_TCPACK_OFFSET))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700119 Leader.Status = LEADER_STATUS_TCP_ACK;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700120 else
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700121 Leader.Status = LEADER_STATUS;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700122
Kevin McKinney97e0a502012-09-13 21:11:35 -0400123 if (Adapter->PackInfo[QueueIndex].bEthCSSupport) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700124 Leader.PLength = Packet->len;
Kevin McKinney97e0a502012-09-13 21:11:35 -0400125 if (skb_headroom(Packet) < LEADER_SIZE) {
Kevin McKinneyd5873d32012-09-13 21:11:36 -0400126 status = skb_cow(Packet, LEADER_SIZE);
127 if (status) {
Kevin McKinney22976bc2012-09-13 21:11:34 -0400128 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit : Failed To Increase headRoom\n");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700129 goto errExit;
130 }
131 }
132 skb_push(Packet, LEADER_SIZE);
133 memcpy(Packet->data, &Leader, LEADER_SIZE);
Kevin McKinney97e0a502012-09-13 21:11:35 -0400134 } else {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700135 Leader.PLength = Packet->len - ETH_HLEN;
Kevin McKinneyff352042012-05-26 12:05:11 -0400136 memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700137 }
138
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700139 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
Kevin McKinney22976bc2012-09-13 21:11:34 -0400140 Packet->data, (Leader.PLength + LEADER_SIZE));
Kevin McKinney97e0a502012-09-13 21:11:35 -0400141 if (status) {
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400142 ++Adapter->dev->stats.tx_errors;
143 if (netif_msg_tx_err(Adapter))
144 pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
145 status);
Kevin McKinney97e0a502012-09-13 21:11:35 -0400146 } else {
Andres Salomone6f597a2011-01-17 16:11:12 -0800147 struct net_device_stats *netstats = &Adapter->dev->stats;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700148 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
Stephen Hemmingercacd9222010-11-01 13:34:35 -0400149
Andres Salomone6f597a2011-01-17 16:11:12 -0800150 netstats->tx_bytes += Leader.PLength;
151 ++netstats->tx_packets;
Stephen Hemmingercacd9222010-11-01 13:34:35 -0400152
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700153 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
154 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
155 Adapter->PackInfo[QueueIndex].uiSentPackets++;
156 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
157
158 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700159 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
160 }
161
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400162 atomic_dec(&Adapter->CurrNumFreeTxDesc);
163
164errExit:
Stephen Hemminger082e8892010-11-01 09:35:21 -0400165 dev_kfree_skb(Packet);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700166 return status;
167}
168
Kevin McKinney29794602012-05-26 12:05:12 -0400169static int tx_pending(struct bcm_mini_adapter *Adapter)
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400170{
171 return (atomic_read(&Adapter->TxPktAvail)
172 && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
173 || Adapter->device_removed || (1 == Adapter->downloadDDR);
174}
175
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700176/**
Kevin McKinneyb9e25f82012-09-13 21:11:37 -0400177 * @ingroup tx_functions
178 * Transmit thread
179 */
Kevin McKinney22976bc2012-09-13 21:11:34 -0400180int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700181{
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700182 int status = 0;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700183
Kevin McKinney22976bc2012-09-13 21:11:34 -0400184 while (!kthread_should_stop()) {
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400185 /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
Kevin McKinney22976bc2012-09-13 21:11:34 -0400186 if (Adapter->LinkUpStatus)
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700187 wait_event_timeout(Adapter->tx_packet_wait_queue,
Kevin McKinney22976bc2012-09-13 21:11:34 -0400188 tx_pending(Adapter), msecs_to_jiffies(10));
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400189 else
190 wait_event_interruptible(Adapter->tx_packet_wait_queue,
Kevin McKinney22976bc2012-09-13 21:11:34 -0400191 tx_pending(Adapter));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700192
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400193 if (Adapter->device_removed)
194 break;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700195
Kevin McKinney97e0a502012-09-13 21:11:35 -0400196 if (Adapter->downloadDDR == 1) {
Kevin McKinney22976bc2012-09-13 21:11:34 -0400197 Adapter->downloadDDR += 1;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700198 status = download_ddr_settings(Adapter);
Kevin McKinney22976bc2012-09-13 21:11:34 -0400199 if (status)
Stephen Hemmingerac1b1ae2010-11-01 12:20:09 -0400200 pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700201 continue;
202 }
203
Kevin McKinneyb9e25f82012-09-13 21:11:37 -0400204 /* Check end point for halt/stall. */
Kevin McKinney97e0a502012-09-13 21:11:35 -0400205 if (Adapter->bEndPointHalted == TRUE) {
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700206 Bcm_clear_halt_of_endpoints(Adapter);
Lisa Nguyenf70c8a92013-10-28 01:36:19 -0700207 Adapter->bEndPointHalted = false;
Kevin McKinneyd6861cf2012-11-01 23:42:21 -0400208 StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter));
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700209 }
210
Kevin McKinney97e0a502012-09-13 21:11:35 -0400211 if (Adapter->LinkUpStatus && !Adapter->IdleMode) {
Kevin McKinney22976bc2012-09-13 21:11:34 -0400212 if (atomic_read(&Adapter->TotalPacketCount))
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700213 update_per_sf_desc_cnts(Adapter);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700214 }
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700215
Kevin McKinney22976bc2012-09-13 21:11:34 -0400216 if (atomic_read(&Adapter->CurrNumFreeTxDesc) &&
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700217 Adapter->LinkStatus == SYNC_UP_REQUEST &&
Kevin McKinney97e0a502012-09-13 21:11:35 -0400218 !Adapter->bSyncUpRequestSent) {
219
Kevin McKinney22976bc2012-09-13 21:11:34 -0400220 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700221 LinkMessage(Adapter);
222 }
223
Kevin McKinney97e0a502012-09-13 21:11:35 -0400224 if ((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) {
Kevin McKinney22976bc2012-09-13 21:11:34 -0400225 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
226 Adapter->usIdleModePattern = ABORT_IDLE_MODE;
227 Adapter->bWakeUpDevice = TRUE;
228 wake_up(&Adapter->process_rx_cntrlpkt);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700229 }
230
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400231 transmit_packets(Adapter);
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700232 atomic_set(&Adapter->TxPktAvail, 0);
233 }
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400234
Kevin McKinney22976bc2012-09-13 21:11:34 -0400235 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
Stephen Hemminger71e253b2010-11-01 09:49:30 -0400236 Adapter->transmit_packet_thread = NULL;
Stephen Hemmingerf8942e02010-09-08 14:46:36 -0700237 return 0;
238}