at v3.1 260 lines 7.4 kB view raw
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}