at v3.9 238 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, "Got NULL Control Packet or Adapter"); 50 return STATUS_FAILURE; 51 } 52 if ((atomic_read(&Adapter->CurrNumFreeTxDesc) < 53 ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) { 54 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); 55 return STATUS_FAILURE; 56 } 57 58 /* Update the netdevice statistics */ 59 /* Dump Packet */ 60 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) 64 return 0; 65 66 if (netif_msg_pktdata(Adapter)) 67 print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE, 68 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0); 69 70 Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 71 pControlPacket, (PLeader->PLength + LEADER_SIZE)); 72 73 atomic_dec(&Adapter->CurrNumFreeTxDesc); 74 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); 75 return STATUS_SUCCESS; 76} 77 78/** 79 * @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 */ 84int SetupNextSend(struct bcm_mini_adapter *Adapter, struct sk_buff *Packet, USHORT Vcid) 85{ 86 int status = 0; 87 BOOLEAN bHeaderSupressionEnabled = FALSE; 88 B_UINT16 uiClassifierRuleID; 89 u16 QueueIndex = skb_get_queue_mapping(Packet); 90 struct bcm_leader Leader = {0}; 91 92 if (Packet->len > MAX_DEVICE_DESC_SIZE) { 93 status = STATUS_FAILURE; 94 goto errExit; 95 } 96 97 /* Get the Classifier Rule ID */ 98 uiClassifierRuleID = *((UINT32 *) (Packet->cb) + SKB_CB_CLASSIFICATION_OFFSET); 99 100 bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled 101 & Adapter->bPHSEnabled; 102 103 if (Adapter->device_removed) { 104 status = STATUS_FAILURE; 105 goto errExit; 106 } 107 108 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, 109 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); 110 111 if (status != STATUS_SUCCESS) { 112 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)) 119 Leader.Status = LEADER_STATUS_TCP_ACK; 120 else 121 Leader.Status = LEADER_STATUS; 122 123 if (Adapter->PackInfo[QueueIndex].bEthCSSupport) { 124 Leader.PLength = Packet->len; 125 if (skb_headroom(Packet) < LEADER_SIZE) { 126 status = skb_cow(Packet, LEADER_SIZE); 127 if (status) { 128 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit : Failed To Increase headRoom\n"); 129 goto errExit; 130 } 131 } 132 skb_push(Packet, LEADER_SIZE); 133 memcpy(Packet->data, &Leader, LEADER_SIZE); 134 } else { 135 Leader.PLength = Packet->len - ETH_HLEN; 136 memcpy((struct bcm_leader *)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); 137 } 138 139 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 140 Packet->data, (Leader.PLength + LEADER_SIZE)); 141 if (status) { 142 ++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); 146 } else { 147 struct net_device_stats *netstats = &Adapter->dev->stats; 148 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; 149 150 netstats->tx_bytes += Leader.PLength; 151 ++netstats->tx_packets; 152 153 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); 159 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; 160 } 161 162 atomic_dec(&Adapter->CurrNumFreeTxDesc); 163 164errExit: 165 dev_kfree_skb(Packet); 166 return status; 167} 168 169static int tx_pending(struct bcm_mini_adapter *Adapter) 170{ 171 return (atomic_read(&Adapter->TxPktAvail) 172 && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc)) 173 || Adapter->device_removed || (1 == Adapter->downloadDDR); 174} 175 176/** 177 * @ingroup tx_functions 178 * Transmit thread 179 */ 180int tx_pkt_handler(struct bcm_mini_adapter *Adapter /**< pointer to adapter object*/) 181{ 182 int status = 0; 183 184 while (!kthread_should_stop()) { 185 /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */ 186 if (Adapter->LinkUpStatus) 187 wait_event_timeout(Adapter->tx_packet_wait_queue, 188 tx_pending(Adapter), msecs_to_jiffies(10)); 189 else 190 wait_event_interruptible(Adapter->tx_packet_wait_queue, 191 tx_pending(Adapter)); 192 193 if (Adapter->device_removed) 194 break; 195 196 if (Adapter->downloadDDR == 1) { 197 Adapter->downloadDDR += 1; 198 status = download_ddr_settings(Adapter); 199 if (status) 200 pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status); 201 continue; 202 } 203 204 /* Check end point for halt/stall. */ 205 if (Adapter->bEndPointHalted == TRUE) { 206 Bcm_clear_halt_of_endpoints(Adapter); 207 Adapter->bEndPointHalted = FALSE; 208 StartInterruptUrb((struct bcm_interface_adapter *)(Adapter->pvInterfaceAdapter)); 209 } 210 211 if (Adapter->LinkUpStatus && !Adapter->IdleMode) { 212 if (atomic_read(&Adapter->TotalPacketCount)) 213 update_per_sf_desc_cnts(Adapter); 214 } 215 216 if (atomic_read(&Adapter->CurrNumFreeTxDesc) && 217 Adapter->LinkStatus == SYNC_UP_REQUEST && 218 !Adapter->bSyncUpRequestSent) { 219 220 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage"); 221 LinkMessage(Adapter); 222 } 223 224 if ((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) { 225 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); 229 } 230 231 transmit_packets(Adapter); 232 atomic_set(&Adapter->TxPktAvail, 0); 233 } 234 235 BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); 236 Adapter->transmit_packet_thread = NULL; 237 return 0; 238}