Transmit.c 7.5 KB

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