at v3.16 245 lines 7.6 kB view raw
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] 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 */ 35 36#include "headers.h" 37 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) 42 */ 43int SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket) 44{ 45 struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket; 46 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; 52 } 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; 58 } 59 60 /* Update the netdevice statistics */ 61 /* Dump Packet */ 62 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); 63 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x", PLeader->Vcid); 64 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x", PLeader->PLength); 65 if (Adapter->device_removed) 66 return 0; 67 68 if (netif_msg_pktdata(Adapter)) 69 print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE, 70 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0); 71 72 Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 73 pControlPacket, (PLeader->PLength + LEADER_SIZE)); 74 75 atomic_dec(&Adapter->CurrNumFreeTxDesc); 76 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); 77 return STATUS_SUCCESS; 78} 79 80/** 81 * @ingroup tx_functions 82 * This function despatches the IP packets with the given vcid 83 * to the target via the host h/w interface. 84 * @return zero(success) or -ve value(failure) 85 */ 86int SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid) 87{ 88 int status = 0; 89 bool bHeaderSupressionEnabled = false; 90 B_UINT16 uiClassifierRuleID; 91 u16 QueueIndex = skb_get_queue_mapping(Packet); 92 struct bcm_leader Leader = {0}; 93 94 if (Packet->len > MAX_DEVICE_DESC_SIZE) { 95 status = STATUS_FAILURE; 96 goto errExit; 97 } 98 99 /* Get the Classifier Rule ID */ 100 uiClassifierRuleID = *((UINT32 *) (Packet->cb) + SKB_CB_CLASSIFICATION_OFFSET); 101 102 bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled 103 & Adapter->bPHSEnabled; 104 105 if (Adapter->device_removed) { 106 status = STATUS_FAILURE; 107 goto errExit; 108 } 109 110 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, 111 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); 112 113 if (status != STATUS_SUCCESS) { 114 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, 115 "PHS Transmit failed..\n"); 116 goto errExit; 117 } 118 119 Leader.Vcid = Vcid; 120 121 if (TCP_ACK == *((UINT32 *) (Packet->cb) + SKB_CB_TCPACK_OFFSET)) 122 Leader.Status = LEADER_STATUS_TCP_ACK; 123 else 124 Leader.Status = LEADER_STATUS; 125 126 if (Adapter->PackInfo[QueueIndex].bEthCSSupport) { 127 Leader.PLength = Packet->len; 128 if (skb_headroom(Packet) < LEADER_SIZE) { 129 status = skb_cow(Packet, LEADER_SIZE); 130 if (status) { 131 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit : Failed To Increase headRoom\n"); 132 goto errExit; 133 } 134 } 135 skb_push(Packet, LEADER_SIZE); 136 memcpy(Packet->data, &Leader, LEADER_SIZE); 137 } else { 138 Leader.PLength = Packet->len - ETH_HLEN; 139 memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); 140 } 141 142 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 143 Packet->data, (Leader.PLength + LEADER_SIZE)); 144 if (status) { 145 ++Adapter->dev->stats.tx_errors; 146 if (netif_msg_tx_err(Adapter)) 147 pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name, 148 status); 149 } else { 150 struct net_device_stats *netstats = &Adapter->dev->stats; 151 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; 152 153 netstats->tx_bytes += Leader.PLength; 154 ++netstats->tx_packets; 155 156 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; 157 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); 158 Adapter->PackInfo[QueueIndex].uiSentPackets++; 159 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; 160 161 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); 162 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; 163 } 164 165 atomic_dec(&Adapter->CurrNumFreeTxDesc); 166 167errExit: 168 dev_kfree_skb(Packet); 169 return status; 170} 171 172static int tx_pending(struct bcm_mini_adapter *Adapter) 173{ 174 return (atomic_read(&Adapter->TxPktAvail) 175 && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc)) 176 || Adapter->device_removed || (1 == Adapter->downloadDDR); 177} 178 179/** 180 * @ingroup tx_functions 181 * Transmit thread 182 */ 183int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/) 184{ 185 int status = 0; 186 187 while (!kthread_should_stop()) { 188 /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */ 189 if (Adapter->LinkUpStatus) 190 wait_event_timeout(Adapter->tx_packet_wait_queue, 191 tx_pending(Adapter), msecs_to_jiffies(10)); 192 else 193 wait_event_interruptible(Adapter->tx_packet_wait_queue, 194 tx_pending(Adapter)); 195 196 if (Adapter->device_removed) 197 break; 198 199 if (Adapter->downloadDDR == 1) { 200 Adapter->downloadDDR += 1; 201 status = download_ddr_settings(Adapter); 202 if (status) 203 pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status); 204 continue; 205 } 206 207 /* Check end point for halt/stall. */ 208 if (Adapter->bEndPointHalted == TRUE) { 209 Bcm_clear_halt_of_endpoints(Adapter); 210 Adapter->bEndPointHalted = false; 211 StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter)); 212 } 213 214 if (Adapter->LinkUpStatus && !Adapter->IdleMode) { 215 if (atomic_read(&Adapter->TotalPacketCount)) 216 update_per_sf_desc_cnts(Adapter); 217 } 218 219 if (atomic_read(&Adapter->CurrNumFreeTxDesc) && 220 Adapter->LinkStatus == SYNC_UP_REQUEST && 221 !Adapter->bSyncUpRequestSent) { 222 223 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, 224 DBG_LVL_ALL, "Calling LinkMessage"); 225 LinkMessage(Adapter); 226 } 227 228 if ((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) { 229 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, 230 TX_PACKETS, DBG_LVL_ALL, 231 "Device in Low Power mode...waking up"); 232 Adapter->usIdleModePattern = ABORT_IDLE_MODE; 233 Adapter->bWakeUpDevice = TRUE; 234 wake_up(&Adapter->process_rx_cntrlpkt); 235 } 236 237 transmit_packets(Adapter); 238 atomic_set(&Adapter->TxPktAvail, 0); 239 } 240 241 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, 242 "Exiting the tx thread..\n"); 243 Adapter->transmit_packet_thread = NULL; 244 return 0; 245}