Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Transmit.c
Go to the documentation of this file.
1 
36 #include "headers.h"
37 
43 int SendControlPacket(struct bcm_mini_adapter *Adapter, char *pControlPacket)
44 {
45  struct bcm_leader *PLeader = (struct bcm_leader *)pControlPacket;
46 
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 
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 
164 errExit:
165  dev_kfree_skb(Packet);
166  return status;
167 }
168 
169 static int tx_pending(struct bcm_mini_adapter *Adapter)
170 {
171  return (atomic_read(&Adapter->TxPktAvail)
173  || Adapter->device_removed || (1 == Adapter->downloadDDR);
174 }
175 
180 int tx_pkt_handler(struct bcm_mini_adapter *Adapter )
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)
188  tx_pending(Adapter), msecs_to_jiffies(10));
189  else
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) {
207  Adapter->bEndPointHalted = FALSE;
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");
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 }