Transmit.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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. bcm_transmit->GetPacketQueueIndex[label="IP Packet"]
  10. GetPacketQueueIndex->IpVersion4[label="IPV4"]
  11. GetPacketQueueIndex->IpVersion6[label="IPV6"]
  12. }
  13. @enddot
  14. @section De-Queueing
  15. @dot
  16. digraph transmit2 {
  17. node[shape=box]
  18. edge[weight=5;color=red]
  19. interrupt_service_thread->transmit_packets
  20. tx_pkt_hdler->transmit_packets
  21. transmit_packets->CheckAndSendPacketFromIndex
  22. transmit_packets->UpdateTokenCount
  23. CheckAndSendPacketFromIndex->PruneQueue
  24. CheckAndSendPacketFromIndex->IsPacketAllowedForFlow
  25. CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"]
  26. SendControlPacket->bcm_cmd53
  27. CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"]
  28. SendPacketFromQueue->SetupNextSend->bcm_cmd53
  29. }
  30. @enddot
  31. */
  32. #include "headers.h"
  33. /**
  34. @ingroup ctrl_pkt_functions
  35. This function dispatches control packet to the h/w interface
  36. @return zero(success) or -ve value(failure)
  37. */
  38. INT SendControlPacket(PMINI_ADAPTER Adapter, char *pControlPacket)
  39. {
  40. PLEADER PLeader = (PLEADER)pControlPacket;
  41. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx");
  42. if(!pControlPacket || !Adapter)
  43. {
  44. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter");
  45. return STATUS_FAILURE;
  46. }
  47. if((atomic_read( &Adapter->CurrNumFreeTxDesc ) <
  48. ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1))
  49. {
  50. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET");
  51. return STATUS_FAILURE;
  52. }
  53. /* Update the netdevice statistics */
  54. /* Dump Packet */
  55. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status);
  56. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid);
  57. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength);
  58. if(Adapter->device_removed)
  59. return 0;
  60. if (netif_msg_pktdata(Adapter))
  61. print_hex_dump(KERN_DEBUG, PFX "tx control: ", DUMP_PREFIX_NONE,
  62. 16, 1, pControlPacket, PLeader->PLength + LEADER_SIZE, 0);
  63. Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
  64. pControlPacket, (PLeader->PLength + LEADER_SIZE));
  65. atomic_dec(&Adapter->CurrNumFreeTxDesc);
  66. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<=========");
  67. return STATUS_SUCCESS;
  68. }
  69. /**
  70. @ingroup tx_functions
  71. This function despatches the IP packets with the given vcid
  72. to the target via the host h/w interface.
  73. @return zero(success) or -ve value(failure)
  74. */
  75. INT SetupNextSend(PMINI_ADAPTER Adapter, struct sk_buff *Packet, USHORT Vcid)
  76. {
  77. int status=0;
  78. BOOLEAN bHeaderSupressionEnabled = FALSE;
  79. B_UINT16 uiClassifierRuleID;
  80. u16 QueueIndex = skb_get_queue_mapping(Packet);
  81. LEADER Leader={0};
  82. if(Packet->len > MAX_DEVICE_DESC_SIZE)
  83. {
  84. status = STATUS_FAILURE;
  85. goto errExit;
  86. }
  87. /* Get the Classifier Rule ID */
  88. uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET);
  89. bHeaderSupressionEnabled = Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled
  90. & Adapter->bPHSEnabled;
  91. if(Adapter->device_removed)
  92. {
  93. status = STATUS_FAILURE;
  94. goto errExit;
  95. }
  96. status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled,
  97. (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport);
  98. if(status != STATUS_SUCCESS)
  99. {
  100. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n");
  101. goto errExit;
  102. }
  103. Leader.Vcid = Vcid;
  104. if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET ))
  105. Leader.Status = LEADER_STATUS_TCP_ACK;
  106. else
  107. Leader.Status = LEADER_STATUS;
  108. if(Adapter->PackInfo[QueueIndex].bEthCSSupport)
  109. {
  110. Leader.PLength = Packet->len;
  111. if(skb_headroom(Packet) < LEADER_SIZE)
  112. {
  113. if((status = skb_cow(Packet,LEADER_SIZE)))
  114. {
  115. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n");
  116. goto errExit;
  117. }
  118. }
  119. skb_push(Packet, LEADER_SIZE);
  120. memcpy(Packet->data, &Leader, LEADER_SIZE);
  121. }
  122. else
  123. {
  124. Leader.PLength = Packet->len - ETH_HLEN;
  125. memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE);
  126. }
  127. status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter,
  128. Packet->data, (Leader.PLength + LEADER_SIZE));
  129. if(status)
  130. {
  131. ++Adapter->dev->stats.tx_errors;
  132. if (netif_msg_tx_err(Adapter))
  133. pr_info(PFX "%s: transmit error %d\n", Adapter->dev->name,
  134. status);
  135. }
  136. else
  137. {
  138. struct net_device_stats *netstats = &Adapter->dev->stats;
  139. Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength;
  140. netstats->tx_bytes += Leader.PLength;
  141. ++netstats->tx_packets;
  142. Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3;
  143. Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len);
  144. Adapter->PackInfo[QueueIndex].uiSentPackets++;
  145. Adapter->PackInfo[QueueIndex].NumOfPacketsSent++;
  146. atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount);
  147. Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength;
  148. }
  149. atomic_dec(&Adapter->CurrNumFreeTxDesc);
  150. errExit:
  151. dev_kfree_skb(Packet);
  152. return status;
  153. }
  154. static int tx_pending(PMINI_ADAPTER Adapter)
  155. {
  156. return (atomic_read(&Adapter->TxPktAvail)
  157. && MINIMUM_PENDING_DESCRIPTORS < atomic_read(&Adapter->CurrNumFreeTxDesc))
  158. || Adapter->device_removed || (1 == Adapter->downloadDDR);
  159. }
  160. /**
  161. @ingroup tx_functions
  162. Transmit thread
  163. */
  164. int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/
  165. )
  166. {
  167. int status = 0;
  168. while(! kthread_should_stop()) {
  169. /* FIXME - the timeout looks like workaround for racey usage of TxPktAvail */
  170. if(Adapter->LinkUpStatus)
  171. wait_event_timeout(Adapter->tx_packet_wait_queue,
  172. tx_pending(Adapter), msecs_to_jiffies(10));
  173. else
  174. wait_event_interruptible(Adapter->tx_packet_wait_queue,
  175. tx_pending(Adapter));
  176. if (Adapter->device_removed)
  177. break;
  178. if(Adapter->downloadDDR == 1)
  179. {
  180. Adapter->downloadDDR +=1;
  181. status = download_ddr_settings(Adapter);
  182. if(status)
  183. pr_err(PFX "DDR DOWNLOAD FAILED! %d\n", status);
  184. continue;
  185. }
  186. //Check end point for halt/stall.
  187. if(Adapter->bEndPointHalted == TRUE)
  188. {
  189. Bcm_clear_halt_of_endpoints(Adapter);
  190. Adapter->bEndPointHalted = FALSE;
  191. StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter));
  192. }
  193. if(Adapter->LinkUpStatus && !Adapter->IdleMode)
  194. {
  195. if(atomic_read(&Adapter->TotalPacketCount))
  196. {
  197. update_per_sf_desc_cnts(Adapter);
  198. }
  199. }
  200. if( atomic_read(&Adapter->CurrNumFreeTxDesc) &&
  201. Adapter->LinkStatus == SYNC_UP_REQUEST &&
  202. !Adapter->bSyncUpRequestSent)
  203. {
  204. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage");
  205. LinkMessage(Adapter);
  206. }
  207. if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount))
  208. {
  209. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up");
  210. Adapter->usIdleModePattern = ABORT_IDLE_MODE;
  211. Adapter->bWakeUpDevice = TRUE;
  212. wake_up(&Adapter->process_rx_cntrlpkt);
  213. }
  214. transmit_packets(Adapter);
  215. atomic_set(&Adapter->TxPktAvail, 0);
  216. }
  217. BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n");
  218. Adapter->transmit_packet_thread = NULL;
  219. return 0;
  220. }