Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
unifi_event.c
Go to the documentation of this file.
1 /*
2  * ***************************************************************************
3  * FILE: unifi_event.c
4  *
5  * PURPOSE:
6  * Process the signals received by UniFi.
7  * It is part of the porting exercise.
8  *
9  * Copyright (C) 2009 by Cambridge Silicon Radio Ltd.
10  *
11  * Refer to LICENSE.txt included with this source code for details on
12  * the license terms.
13  *
14  * ***************************************************************************
15  */
16 
17 
18 /*
19  * Porting notes:
20  * The implementation of unifi_receive_event() in Linux is fairly complicated.
21  * The linux driver support multiple userspace applications and several
22  * build configurations, so the received signals are processed by different
23  * processes and multiple times.
24  * In a simple implementation, this function needs to deliver:
25  * - The MLME-UNITDATA.ind signals to the Rx data plane and to the Traffic
26  * Analysis using unifi_ta_sample().
27  * - The MLME-UNITDATA-STATUS.ind signals to the Tx data plane.
28  * - All the other signals to the SME using unifi_sys_hip_ind().
29  */
30 
31 #include "csr_wifi_hip_unifi.h"
33 #include "unifi_priv.h"
34 
35 
36 /*
37  * ---------------------------------------------------------------------------
38  * send_to_client
39  *
40  * Helper for unifi_receive_event.
41  *
42  * This function forwards a signal to one client.
43  *
44  * Arguments:
45  * priv Pointer to driver's private data.
46  * client Pointer to the client structure.
47  * receiver_id The reciever id of the signal.
48  * sigdata Pointer to the packed signal buffer.
49  * siglen Length of the packed signal.
50  * bulkdata Pointer to the signal's bulk data.
51  *
52  * Returns:
53  * None.
54  *
55  * ---------------------------------------------------------------------------
56  */
57 static void send_to_client(unifi_priv_t *priv, ul_client_t *client,
58  int receiver_id,
59  unsigned char *sigdata, int siglen,
60  const bulk_data_param_t *bulkdata)
61 {
62  if (client && client->event_hook) {
63  /*unifi_trace(priv, UDBG3,
64  "Receive: client %d, (s:0x%X, r:0x%X) - Signal 0x%.4X \n",
65  client->client_id, client->sender_id, receiver_id,
66  CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata));*/
67 
68  client->event_hook(client, sigdata, siglen, bulkdata, UDI_TO_HOST);
69  }
70 }
71 
72 /*
73  * ---------------------------------------------------------------------------
74  * process_pkt_data_ind
75  *
76  * Dispatcher for received signals.
77  *
78  * This function receives the 'to host' signals and forwards
79  * them to the unifi linux clients.
80  *
81  * Arguments:
82  * priv Context
83  * sigdata Pointer to the packed signal buffer(Its in form of MA-PACKET.ind).
84  * bulkdata Pointer to signal's bulkdata
85  * freeBulkData Pointer to a flag which gets set if the bulkdata needs to
86  * be freed after calling the logging handlers. If it is not
87  * set the bulkdata must be freed by the MLME handler or
88  * passed to the network stack.
89  * Returns:
90  * TRUE if the packet should be routed to the SME etc.
91  * FALSE if the packet is for the driver or network stack
92  * ---------------------------------------------------------------------------
93  */
94 static u8 check_routing_pkt_data_ind(unifi_priv_t *priv,
95  u8 *sigdata,
96  const bulk_data_param_t* bulkdata,
97  u8 *freeBulkData,
98  netInterface_priv_t *interfacePriv)
99 {
100  u16 frmCtrl, receptionStatus, frmCtrlSubType;
101  u8 *macHdrLocation;
102  u8 interfaceTag;
103  u8 isDataFrame;
104  u8 isProtocolVerInvalid = FALSE;
105  u8 isDataFrameSubTypeNoData = FALSE;
106 
107 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
108  static const u8 wapiProtocolIdSNAPHeader[] = {0x88,0xb4};
109  static const u8 wapiProtocolIdSNAPHeaderOffset = 6;
110  u8 *destAddr;
111  u8 *srcAddr;
112  u8 isWapiUnicastPkt = FALSE;
113 
114 #ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
115  u16 qosControl;
116 #endif
117 
118  u8 llcSnapHeaderOffset = 0;
119 
120  destAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET;
121  srcAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET;
122 
123  /*Individual/Group bit - Bit 0 of first byte*/
124  isWapiUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE;
125 #endif
126 
127 #define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22
128 
129  *freeBulkData = FALSE;
130 
131  /* Fetch the MAC header location from MA_PKT_IND packet */
132  macHdrLocation = (u8 *) bulkdata->d[0].os_data_ptr;
133  /* Fetch the Frame Control value from MAC header */
134  frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation);
135 
136  /* Pull out interface tag from virtual interface identifier */
137  interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff;
138 
139  /* check for MIC failure before processing the signal */
140  receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET);
141 
142  /* To discard any spurious MIC failures that could be reported by the firmware */
143  isDataFrame = ((frmCtrl & IEEE80211_FC_TYPE_MASK) == (IEEE802_11_FC_TYPE_DATA & IEEE80211_FC_TYPE_MASK)) ? TRUE : FALSE;
144  /* 0x00 is the only valid protocol version*/
145  isProtocolVerInvalid = (frmCtrl & IEEE80211_FC_PROTO_VERSION_MASK) ? TRUE : FALSE;
146  frmCtrlSubType = (frmCtrl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET;
147  /*Exclude the no data & reserved sub-types from MIC failure processing*/
148  isDataFrameSubTypeNoData = (((frmCtrlSubType>0x03)&&(frmCtrlSubType<0x08)) || (frmCtrlSubType>0x0B)) ? TRUE : FALSE;
149  if ((receptionStatus == CSR_MICHAEL_MIC_ERROR) &&
150  ((!isDataFrame) || isProtocolVerInvalid || (isDataFrame && isDataFrameSubTypeNoData))) {
151  /* Currently MIC errors are discarded for frames other than data frames. This might need changing when we start
152  * supporting 802.11w (Protected Management frames)
153  */
154  *freeBulkData = TRUE;
155  unifi_trace(priv, UDBG4, "Discarding this frame and ignoring the MIC failure as this is a garbage/non-data/no data frame\n");
156  return FALSE;
157  }
158 
159 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
160 
161  if (receptionStatus == CSR_MICHAEL_MIC_ERROR) {
162 
163  if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
164 
165 #ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
166  if ((isDataFrame) &&
167  ((IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK) == (frmCtrl & IEEE80211_FC_SUBTYPE_MASK)) &&
168  (priv->isWapiConnection))
169  {
170  qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation + (((frmCtrl & IEEE802_11_FC_TO_DS_MASK) && (frmCtrl & IEEE802_11_FC_FROM_DS_MASK)) ? 30 : 24) );
171 
172  unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind() :: Value of the QoS control field - 0x%04x \n", qosControl);
173 
174  if (qosControl & IEEE802_11_QC_NON_TID_BITS_MASK)
175  {
176  unifi_trace(priv, UDBG4, "Ignore the MIC failure and pass the MPDU to the stack when any of bits [4-15] is set in the QoS control field\n");
177 
178  /*Exclude the MIC [16] and the PN [16] that are appended by the firmware*/
179  ((bulk_data_param_t*)bulkdata)->d[0].data_length = bulkdata->d[0].data_length - 32;
180 
181  /*Clear the reception status of the signal (CSR_RX_SUCCESS)*/
183  *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET+1) = 0x00;
184 
185  *freeBulkData = FALSE;
186 
187  return FALSE;
188  }
189  }
190 #endif
191  /* If this MIC ERROR reported by the firmware is either for
192  * [1] a WAPI Multicast MPDU and the Multicast filter has NOT been set (It is set only when group key index (MSKID) = 1 in Group Rekeying) OR
193  * [2] a WAPI Unicast MPDU and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set
194  * then report a MIC FAILURE indication to the SME.
195  */
196 #ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
197  if ((priv->wapi_multicast_filter == 0) || isWapiUnicastPkt) {
198 #else
199  /*When SW encryption is enabled and USKID=1 (wapi_unicast_filter = 1), we are expected
200  *to receive MIC failure INDs for unicast MPDUs*/
201  if ( ((priv->wapi_multicast_filter == 0) && !isWapiUnicastPkt) ||
202  ((priv->wapi_unicast_filter == 0) && isWapiUnicastPkt) ) {
203 #endif
204  /*Discard the frame*/
205  *freeBulkData = TRUE;
206  unifi_trace(priv, UDBG4, "Discarding the contents of the frame with MIC failure \n");
207 
208  if (isWapiUnicastPkt &&
210 #ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
211  (priv->wapi_unicast_filter) ||
212 #endif
213  (priv->wapi_unicast_queued_pkt_filter))) {
214 
215  /* Workaround to handle MIC failures reported by the firmware for encrypted packets from the AP
216  * while we are in the process of re-association induced by unsupported WAPI Unicast key index
217  * - Discard the packets with MIC failures "until" we have
218  * a. negotiated a key,
219  * b. opened the CONTROL PORT and
220  * c. the AP has started using the new key
221  */
222  unifi_trace(priv, UDBG4, "Ignoring the MIC failure as either a. CONTROL PORT isn't OPEN or b. Unicast filter is set or c. WAPI AP using old key for buffered pkts\n");
223 
224  /*Ignore this MIC failure*/
225  return FALSE;
226 
227  }/*WAPI re-key specific workaround*/
228 
229  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n",
230  interfaceTag, srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3], srcAddr[4], srcAddr[5]);
231  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : Dest Addr %x:%x:%x:%x:%x:%x\n",
232  destAddr[0], destAddr[1], destAddr[2], destAddr[3], destAddr[4], destAddr[5]);
233  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind - MIC FAILURE : Control Port State - 0x%.4X \n",
234  uf_sme_port_state(priv,srcAddr,UF_CONTROLLED_PORT_Q,interfaceTag));
235 
236  unifi_error(priv, "MIC failure in %s\n", __FUNCTION__);
237 
238  /*Report the MIC failure to the SME*/
239  return TRUE;
240  }
241  }/* STA mode */
242  else {
243  /* Its AP Mode . Just Return */
244  *freeBulkData = TRUE;
245  unifi_error(priv, "MIC failure in %s\n", __FUNCTION__);
246  return TRUE;
247  } /* AP mode */
248  }/* MIC error */
249 #else
250  if (receptionStatus == CSR_MICHAEL_MIC_ERROR) {
251  *freeBulkData = TRUE;
252  unifi_error(priv, "MIC failure in %s\n", __FUNCTION__);
253  return TRUE;
254  }
255 #endif /*CSR_WIFI_SECURITY_WAPI_ENABLE*/
256 
257  unifi_trace(priv, UDBG4, "frmCtrl = 0x%04x %s\n",
258  frmCtrl,
260  "Mgt" : "Ctrl/Data");
261 
262 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
263  /* To ignore MIC failures reported due to the WAPI AP using the old key for queued packets before
264  * starting to use the new key negotiated as part of unicast re-keying
265  */
266  if ((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA)&&
267  isWapiUnicastPkt &&
268  (receptionStatus == CSR_RX_SUCCESS) &&
269  (priv->wapi_unicast_queued_pkt_filter==1)) {
270 
271  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI unicast pkt received when the (wapi_unicast_queued_pkt_filter) is set\n");
272 
273  if (isDataFrame) {
274  switch(frmCtrl & IEEE80211_FC_SUBTYPE_MASK) {
275  case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK:
276  llcSnapHeaderOffset = MAC_HEADER_SIZE + 2;
277  break;
278  case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK:
279  case IEEE802_11_FC_TYPE_NULL & IEEE80211_FC_SUBTYPE_MASK:
280  break;
281  default:
282  llcSnapHeaderOffset = MAC_HEADER_SIZE;
283  }
284  }
285 
286  if (llcSnapHeaderOffset > 0) {
287  /* QoS data or Data */
288  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): SNAP header found & its offset %d\n",llcSnapHeaderOffset);
289  if (memcmp((u8 *)(bulkdata->d[0].os_data_ptr+llcSnapHeaderOffset+wapiProtocolIdSNAPHeaderOffset),
290  wapiProtocolIdSNAPHeader,sizeof(wapiProtocolIdSNAPHeader))) {
291 
292  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): This is a data & NOT a WAI protocol packet\n");
293  /* On the first unicast data pkt that is decrypted successfully after re-keying, reset the filter */
294  priv->wapi_unicast_queued_pkt_filter = 0;
295  unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind(): WAPI AP has started using the new unicast key, no more MIC failures expected (reset filter)\n");
296  }
297  else {
298  unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI - This is a WAI protocol packet\n");
299  }
300  }
301  }
302 #endif
303 
304 
305  switch ((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) {
307  *freeBulkData = TRUE; /* Free (after SME handler copies it) */
308 
309  /* In P2P device mode, filter the legacy AP beacons here */
310  if((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2P)&&\
312 
313  u8 *pSsid, *pSsidLen;
314  static u8 P2PWildCardSsid[CSR_WIFI_P2P_WILDCARD_SSID_LENGTH] = {'D', 'I', 'R', 'E', 'C', 'T', '-'};
315 
316  pSsidLen = macHdrLocation + MAC_HEADER_SIZE + CSR_WIFI_BEACON_FIXED_LENGTH;
317  pSsid = pSsidLen + 2;
318 
319  if(*(pSsidLen + 1) >= CSR_WIFI_P2P_WILDCARD_SSID_LENGTH){
320  if(memcmp(pSsid, P2PWildCardSsid, CSR_WIFI_P2P_WILDCARD_SSID_LENGTH) == 0){
321  unifi_trace(priv, UDBG6, "Received a P2P Beacon, pass it to SME\n");
322  return TRUE;
323  }
324  }
325  unifi_trace(priv, UDBG6, "Received a Legacy AP beacon in P2P mode, drop it\n");
326  return FALSE;
327  }
328  return TRUE; /* Route to SME */
331  *freeBulkData = FALSE; /* Network stack or MLME handler frees */
332  return FALSE;
333  default:
334  unifi_error(priv, "Unhandled frame type %04x\n", frmCtrl);
335  *freeBulkData = TRUE; /* Not interested, but must free it */
336  return FALSE;
337  }
338 }
339 
340 /*
341  * ---------------------------------------------------------------------------
342  * unifi_process_receive_event
343  *
344  * Dispatcher for received signals.
345  *
346  * This function receives the 'to host' signals and forwards
347  * them to the unifi linux clients.
348  *
349  * Arguments:
350  * ospriv Pointer to driver's private data.
351  * sigdata Pointer to the packed signal buffer.
352  * siglen Length of the packed signal.
353  * bulkdata Pointer to the signal's bulk data.
354  *
355  * Returns:
356  * None.
357  *
358  * Notes:
359  * The signals are received in the format described in the host interface
360  * specification, i.e wire formatted. Certain clients use the same format
361  * to interpret them and other clients use the host formatted structures.
362  * Each client has to call read_unpack_signal() to transform the wire
363  * formatted signal into the host formatted signal, if necessary.
364  * The code is in the core, since the signals are defined therefore
365  * binded to the host interface specification.
366  * ---------------------------------------------------------------------------
367  */
368 static void
369 unifi_process_receive_event(void *ospriv,
370  u8 *sigdata, u32 siglen,
371  const bulk_data_param_t *bulkdata)
372 {
373  unifi_priv_t *priv = (unifi_priv_t*)ospriv;
374  int i, receiver_id;
375  int client_id;
376  s16 signal_id;
377  u8 pktIndToSme = FALSE, freeBulkData = FALSE;
378 
379  func_enter();
380 
381  unifi_trace(priv, UDBG5, "unifi_process_receive_event: "
382  "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n",
383  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF,
384  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*1) & 0xFFFF,
385  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*2) & 0xFFFF,
386  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*3) & 0xFFFF,
387  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*4) & 0xFFFF,
388  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*5) & 0xFFFF,
389  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*6) & 0xFFFF,
390  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*7) & 0xFFFF,
391  siglen);
392 
393  receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)) & 0xFF00;
394  client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
395  signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata);
396 
397 
398 
399  /* check for the type of frame received (checks for 802.11 management frames) */
400  if (signal_id == CSR_MA_PACKET_INDICATION_ID)
401  {
402 #define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET 14
403  u8 interfaceTag;
404  netInterface_priv_t *interfacePriv;
405 
406  /* Pull out interface tag from virtual interface identifier */
407  interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff;
408  interfacePriv = priv->interfacePriv[interfaceTag];
409 
410  /* Update activity for this station in case of IBSS */
411 #ifdef CSR_SUPPORT_SME
412  if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS)
413  {
414  u8 *saddr;
415  /* Fetch the source address from mac header */
416  saddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET;
417  unifi_trace(priv, UDBG5,
418  "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n",
419  interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]);
420 
421  uf_update_sta_activity(priv, interfaceTag, saddr);
422  }
423 #endif
424 
425  pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv);
426 
427  unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO");
428 
429  }
430 
431  if (pktIndToSme)
432  {
433  /* Management MA_PACKET_IND for SME */
434  if(sigdata != NULL && bulkdata != NULL){
435  send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata);
436  }
437  else{
438  unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n");
439  }
440 #ifdef CSR_NATIVE_LINUX
441  send_to_client(priv, priv->wext_client,
442  receiver_id,
443  sigdata, siglen, bulkdata);
444 #endif
445  }
446  else
447  {
448  /* Signals with ReceiverId==0 are also reported to SME / WEXT,
449  * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs
450  */
451  if (!receiver_id) {
452  if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) {
453  uf_process_ma_vif_availibility_ind(priv, sigdata, siglen);
454  }
455  else if (signal_id != CSR_MA_PACKET_INDICATION_ID) {
456  send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata);
457 #ifdef CSR_NATIVE_LINUX
458  send_to_client(priv, priv->wext_client,
459  receiver_id,
460  sigdata, siglen, bulkdata);
461 #endif
462  }
463  else
464  {
465 
466 #if (defined(CSR_SUPPORT_SME) && defined(CSR_WIFI_SECURITY_WAPI_ENABLE))
467  #define CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22
468  netInterface_priv_t *interfacePriv;
469  u8 interfaceTag;
470  u16 receptionStatus = CSR_RX_SUCCESS;
471 
472  /* Pull out interface tag from virtual interface identifier */
473  interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff;
474  interfacePriv = priv->interfacePriv[interfaceTag];
475 
476  /* check for MIC failure */
477  receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET);
478 
479  /* Send a WAPI MPDU to SME for re-check MIC if the respective filter has been set*/
480  if ((!freeBulkData) &&
481  (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) &&
482  (receptionStatus == CSR_MICHAEL_MIC_ERROR) &&
483  ((priv->wapi_multicast_filter == 1)
484 #ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
485  || (priv->wapi_unicast_filter == 1)
486 #endif
487  ))
488  {
489  CSR_SIGNAL signal;
490  u8 *destAddr;
491  CsrResult res;
492  u16 interfaceTag = 0;
493  u8 isMcastPkt = TRUE;
494 
495  unifi_trace(priv, UDBG6, "Received a WAPI data packet when the Unicast/Multicast filter is set\n");
496  res = read_unpack_signal(sigdata, &signal);
497  if (res) {
498  unifi_error(priv, "Received unknown or corrupted signal (0x%x).\n",
500  return;
501  }
502 
503  /* Check if the type of MPDU and the respective filter status*/
504  destAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET;
505  isMcastPkt = (destAddr[0] & 0x01) ? TRUE : FALSE;
506  unifi_trace(priv, UDBG6,
507  "1.MPDU type: (%s), 2.Multicast filter: (%s), 3. Unicast filter: (%s)\n",
508  ((isMcastPkt) ? "Multiast":"Unicast"),
509  ((priv->wapi_multicast_filter) ? "Enabled":"Disabled"),
510  ((priv->wapi_unicast_filter) ? "Enabled":"Disabled"));
511 
512  if (((isMcastPkt) && (priv->wapi_multicast_filter == 1))
513 #ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
514  || ((!isMcastPkt) && (priv->wapi_unicast_filter == 1))
515 #endif
516  )
517  {
518  unifi_trace(priv, UDBG4, "Sending the WAPI MPDU for MIC check\n");
519  CsrWifiRouterCtrlWapiRxMicCheckIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (u8*)bulkdata->d[0].os_data_ptr);
520 
521  for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
522  if (bulkdata->d[i].data_length != 0) {
523  unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
524  }
525  }
526  func_exit();
527  return;
528  }
529  } /* CSR_MA_PACKET_INDICATION_ID */
530 #endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/
531  }
532  }
533 
534  /* calls the registered clients handler callback func.
535  * netdev_mlme_event_handler is one of the registered handler used to route
536  * data packet to network stack or AMP/EAPOL related data to SME
537  *
538  * The freeBulkData check ensures that, it has received a management frame and
539  * the frame needs to be freed here. So not to be passed to netdev handler
540  */
541  if(!freeBulkData){
542  if ((client_id < MAX_UDI_CLIENTS) &&
543  (&priv->ul_clients[client_id] != priv->logging_client)) {
544  unifi_trace(priv, UDBG6, "Call the registered clients handler callback func\n");
545  send_to_client(priv, &priv->ul_clients[client_id],
546  receiver_id,
547  sigdata, siglen, bulkdata);
548  }
549  }
550  }
551 
552  /*
553  * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION
554  */
555  switch (signal_id)
556  {
557 #ifdef UNIFI_SNIFF_ARPHRD
558  case CSR_MA_SNIFFDATA_INDICATION_ID:
559 #endif
560  break;
561 
563  if (!freeBulkData)
564  {
565  break;
566  }
567  /* FALLS THROUGH... */
568  default:
569  for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
570  if (bulkdata->d[i].data_length != 0) {
571  unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
572  }
573  }
574  }
575 
576  func_exit();
577 } /* unifi_process_receive_event() */
578 
579 
580 #ifdef CSR_WIFI_RX_PATH_SPLIT
581 static u8 signal_buffer_is_full(unifi_priv_t* priv)
582 {
583  return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer));
584 }
585 
586 void unifi_rx_queue_flush(void *ospriv)
587 {
588  unifi_priv_t *priv = (unifi_priv_t*)ospriv;
589 
590  func_enter();
591  unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n",
592  priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer);
593  if(priv != NULL) {
594  u8 readPointer = priv->rxSignalBuffer.readPointer;
595  while (readPointer != priv->rxSignalBuffer.writePointer)
596  {
597  rx_buff_struct_t *buf = &priv->rxSignalBuffer.rx_buff[readPointer];
598  unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n",
599  readPointer,priv->rxSignalBuffer.writePointer);
600  unifi_process_receive_event(priv, buf->bufptr, buf->sig_len, &buf->data_ptrs);
601  readPointer ++;
602  if(readPointer >= priv->rxSignalBuffer.size) {
603  readPointer = 0;
604  }
605  }
606  priv->rxSignalBuffer.readPointer = readPointer;
607  }
608  func_exit();
609 }
610 
611 void rx_wq_handler(struct work_struct *work)
612 {
613  unifi_priv_t *priv = container_of(work, unifi_priv_t, rx_work_struct);
614  unifi_rx_queue_flush(priv);
615 }
616 #endif
617 
618 
619 
620 /*
621  * ---------------------------------------------------------------------------
622  * unifi_receive_event
623  *
624  * Dispatcher for received signals.
625  *
626  * This function receives the 'to host' signals and forwards
627  * them to the unifi linux clients.
628  *
629  * Arguments:
630  * ospriv Pointer to driver's private data.
631  * sigdata Pointer to the packed signal buffer.
632  * siglen Length of the packed signal.
633  * bulkdata Pointer to the signal's bulk data.
634  *
635  * Returns:
636  * None.
637  *
638  * Notes:
639  * The signals are received in the format described in the host interface
640  * specification, i.e wire formatted. Certain clients use the same format
641  * to interpret them and other clients use the host formatted structures.
642  * Each client has to call read_unpack_signal() to transform the wire
643  * formatted signal into the host formatted signal, if necessary.
644  * The code is in the core, since the signals are defined therefore
645  * binded to the host interface specification.
646  * ---------------------------------------------------------------------------
647  */
648 void
649 unifi_receive_event(void *ospriv,
650  u8 *sigdata, u32 siglen,
651  const bulk_data_param_t *bulkdata)
652 {
653 #ifdef CSR_WIFI_RX_PATH_SPLIT
654  unifi_priv_t *priv = (unifi_priv_t*)ospriv;
655  u8 writePointer;
656  int i;
657  rx_buff_struct_t * rx_buff;
658  func_enter();
659 
660  unifi_trace(priv, UDBG5, "unifi_receive_event: "
661  "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n",
662  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF,
663  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*1) & 0xFFFF,
664  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*2) & 0xFFFF,
665  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*3) & 0xFFFF,
666  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*4) & 0xFFFF,
667  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*5) & 0xFFFF,
668  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*6) & 0xFFFF,
669  CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*7) & 0xFFFF, siglen);
670  if(signal_buffer_is_full(priv)) {
671  unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n");
672  for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
673  if (bulkdata->d[i].data_length != 0) {
674  unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
675  }
676  }
677  return;
678  }
679  writePointer = priv->rxSignalBuffer.writePointer;
680  rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer];
681  memcpy(rx_buff->bufptr,sigdata,siglen);
682  rx_buff->sig_len = siglen;
683  rx_buff->data_ptrs = *bulkdata;
684  writePointer++;
685  if(writePointer >= priv->rxSignalBuffer.size) {
686  writePointer =0;
687  }
688  unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer);
689  priv->rxSignalBuffer.writePointer = writePointer;
690 
691 #ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
692  queue_work(priv->rx_workqueue, &priv->rx_work_struct);
693 #endif
694 
695 #else
696  unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata);
697 #endif
698  func_exit();
699 } /* unifi_receive_event() */
700