Merge tag 'rdma-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[firefly-linux-kernel-4.4.55.git] / drivers / staging / csr / unifi_event.c
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"
32 #include "csr_wifi_hip_conversions.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)*/
182                         *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET)     = 0x00;
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 &&
209                     ((uf_sme_port_state(priv,srcAddr,UF_CONTROLLED_PORT_Q,interfaceTag) != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN)||
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,
259                 (((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) == IEEE802_11_FRAMETYPE_MANAGEMENT) ?
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) {
306         case IEEE802_11_FRAMETYPE_MANAGEMENT:
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)&&\
311                ((CSR_WIFI_80211_GET_FRAME_SUBTYPE(macHdrLocation)) == CSR_WIFI_80211_FRAME_SUBTYPE_BEACON)){
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 */
329         case IEEE802_11_FRAMETYPE_DATA:
330         case IEEE802_11_FRAMETYPE_CONTROL:
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     unifi_trace(priv, UDBG5, "unifi_process_receive_event: "
380                 "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n",
381                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF,
382                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*1) & 0xFFFF,
383                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*2) & 0xFFFF,
384                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*3) & 0xFFFF,
385                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*4) & 0xFFFF,
386                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*5) & 0xFFFF,
387                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*6) & 0xFFFF,
388                 CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*7) & 0xFFFF,
389                 siglen);
390
391     receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)) & 0xFF00;
392     client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
393     signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata);
394
395
396
397     /* check for the type of frame received (checks for 802.11 management frames) */
398     if (signal_id == CSR_MA_PACKET_INDICATION_ID)
399     {
400 #define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET    14
401         u8 interfaceTag;
402         netInterface_priv_t *interfacePriv;
403
404         /* Pull out interface tag from virtual interface identifier */
405         interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff;
406         interfacePriv = priv->interfacePriv[interfaceTag];
407
408         /* Update activity for this station in case of IBSS */
409 #ifdef CSR_SUPPORT_SME
410         if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS)
411         {
412             u8 *saddr;
413             /* Fetch the source address from  mac header */
414             saddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET;
415             unifi_trace(priv, UDBG5,
416                                     "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n",
417                                     interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]);
418
419             uf_update_sta_activity(priv, interfaceTag, saddr);
420         }
421 #endif
422
423         pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv);
424
425         unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO");
426
427     }
428
429     if (pktIndToSme)
430     {
431         /* Management MA_PACKET_IND for SME */
432         if(sigdata != NULL && bulkdata != NULL){
433             send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata);
434         }
435         else{
436             unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n");
437         }
438 #ifdef CSR_NATIVE_LINUX
439         send_to_client(priv, priv->wext_client,
440                 receiver_id,
441                 sigdata, siglen, bulkdata);
442 #endif
443     }
444     else
445     {
446         /* Signals with ReceiverId==0 are also reported to SME / WEXT,
447          * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs
448          */
449         if (!receiver_id) {
450                if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) {
451                       uf_process_ma_vif_availibility_ind(priv, sigdata, siglen);
452                }
453                else if (signal_id != CSR_MA_PACKET_INDICATION_ID) {
454                       send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata);
455 #ifdef CSR_NATIVE_LINUX
456                       send_to_client(priv, priv->wext_client,
457                                      receiver_id,
458                                      sigdata, siglen, bulkdata);
459 #endif
460                }
461                else
462                {
463
464 #if (defined(CSR_SUPPORT_SME) && defined(CSR_WIFI_SECURITY_WAPI_ENABLE))
465                    #define CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET    sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22
466                    netInterface_priv_t *interfacePriv;
467                    u8 interfaceTag;
468                    u16 receptionStatus = CSR_RX_SUCCESS;
469
470                    /* Pull out interface tag from virtual interface identifier */
471                    interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff;
472                    interfacePriv = priv->interfacePriv[interfaceTag];
473
474                    /* check for MIC failure */
475                    receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET);
476
477                    /* Send a WAPI MPDU to SME for re-check MIC if the respective filter has been set*/
478                    if ((!freeBulkData) &&
479                        (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) &&
480                        (receptionStatus == CSR_MICHAEL_MIC_ERROR) &&
481                        ((priv->wapi_multicast_filter == 1)
482 #ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
483                          || (priv->wapi_unicast_filter == 1)
484 #endif
485                        ))
486                    {
487                        CSR_SIGNAL signal;
488                        u8 *destAddr;
489                        CsrResult res;
490                        u16 interfaceTag = 0;
491                        u8 isMcastPkt = TRUE;
492
493                        unifi_trace(priv, UDBG6, "Received a WAPI data packet when the Unicast/Multicast filter is set\n");
494                        res = read_unpack_signal(sigdata, &signal);
495                        if (res) {
496                            unifi_error(priv, "Received unknown or corrupted signal (0x%x).\n",
497                                        CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata));
498                            return;
499                        }
500
501                        /* Check if the type of MPDU and the respective filter status*/
502                        destAddr = (u8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET;
503                        isMcastPkt = (destAddr[0] & 0x01) ? TRUE : FALSE;
504                        unifi_trace(priv, UDBG6,
505                                    "1.MPDU type: (%s), 2.Multicast filter: (%s), 3. Unicast filter: (%s)\n",
506                                    ((isMcastPkt) ? "Multiast":"Unicast"),
507                                    ((priv->wapi_multicast_filter) ? "Enabled":"Disabled"),
508                                    ((priv->wapi_unicast_filter)  ? "Enabled":"Disabled"));
509
510                        if (((isMcastPkt) && (priv->wapi_multicast_filter == 1))
511 #ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
512                            || ((!isMcastPkt) && (priv->wapi_unicast_filter == 1))
513 #endif
514                           )
515                         {
516                             unifi_trace(priv, UDBG4, "Sending the WAPI MPDU for MIC check\n");
517                             CsrWifiRouterCtrlWapiRxMicCheckIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (u8*)bulkdata->d[0].os_data_ptr);
518
519                             for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
520                                 if (bulkdata->d[i].data_length != 0) {
521                                     unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
522                                 }
523                            }
524                            return;
525                        }
526                    } /* CSR_MA_PACKET_INDICATION_ID */
527 #endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/
528                }
529         }
530
531         /* calls the registered clients handler callback func.
532          * netdev_mlme_event_handler is one of the registered handler used to route
533          * data packet to network stack or AMP/EAPOL related data to SME
534          *
535          * The freeBulkData check ensures that, it has received a management frame and
536          * the frame needs to be freed here. So not to be passed to netdev handler
537          */
538         if(!freeBulkData){
539             if ((client_id < MAX_UDI_CLIENTS) &&
540                     (&priv->ul_clients[client_id] != priv->logging_client)) {
541                 unifi_trace(priv, UDBG6, "Call the registered clients handler callback func\n");
542                 send_to_client(priv, &priv->ul_clients[client_id],
543                         receiver_id,
544                         sigdata, siglen, bulkdata);
545             }
546         }
547     }
548
549     /*
550      * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION
551      */
552     switch (signal_id)
553     {
554 #ifdef UNIFI_SNIFF_ARPHRD
555         case CSR_MA_SNIFFDATA_INDICATION_ID:
556 #endif
557             break;
558
559         case CSR_MA_PACKET_INDICATION_ID:
560             if (!freeBulkData)
561             {
562                 break;
563             }
564             /* FALLS THROUGH... */
565         default:
566             for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
567                 if (bulkdata->d[i].data_length != 0) {
568                     unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
569                 }
570             }
571     }
572
573 } /* unifi_process_receive_event() */
574
575
576 #ifdef CSR_WIFI_RX_PATH_SPLIT
577 static u8 signal_buffer_is_full(unifi_priv_t* priv)
578 {
579     return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer));
580 }
581
582 void unifi_rx_queue_flush(void *ospriv)
583 {
584     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
585
586     unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr =  %d\n",
587                 priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer);
588     if(priv != NULL) {
589         u8 readPointer = priv->rxSignalBuffer.readPointer;
590         while (readPointer != priv->rxSignalBuffer.writePointer)
591         {
592              rx_buff_struct_t *buf = &priv->rxSignalBuffer.rx_buff[readPointer];
593              unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr =  %d\n",
594                          readPointer,priv->rxSignalBuffer.writePointer);
595              unifi_process_receive_event(priv, buf->bufptr, buf->sig_len, &buf->data_ptrs);
596              readPointer ++;
597              if(readPointer >= priv->rxSignalBuffer.size) {
598                     readPointer = 0;
599              }
600         }
601         priv->rxSignalBuffer.readPointer = readPointer;
602     }
603 }
604
605 void rx_wq_handler(struct work_struct *work)
606 {
607     unifi_priv_t *priv = container_of(work, unifi_priv_t, rx_work_struct);
608     unifi_rx_queue_flush(priv);
609 }
610 #endif
611
612
613
614 /*
615  * ---------------------------------------------------------------------------
616  *  unifi_receive_event
617  *
618  *      Dispatcher for received signals.
619  *
620  *      This function receives the 'to host' signals and forwards
621  *      them to the unifi linux clients.
622  *
623  *  Arguments:
624  *      ospriv      Pointer to driver's private data.
625  *      sigdata     Pointer to the packed signal buffer.
626  *      siglen      Length of the packed signal.
627  *      bulkdata    Pointer to the signal's bulk data.
628  *
629  *  Returns:
630  *      None.
631  *
632  *  Notes:
633  *  The signals are received in the format described in the host interface
634  *  specification, i.e wire formatted. Certain clients use the same format
635  *  to interpret them and other clients use the host formatted structures.
636  *  Each client has to call read_unpack_signal() to transform the wire
637  *  formatted signal into the host formatted signal, if necessary.
638  *  The code is in the core, since the signals are defined therefore
639  *  binded to the host interface specification.
640  * ---------------------------------------------------------------------------
641  */
642 void
643 unifi_receive_event(void *ospriv,
644                     u8 *sigdata, u32 siglen,
645                     const bulk_data_param_t *bulkdata)
646 {
647 #ifdef CSR_WIFI_RX_PATH_SPLIT
648     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
649     u8 writePointer;
650     int i;
651     rx_buff_struct_t * rx_buff;
652
653     unifi_trace(priv, UDBG5, "unifi_receive_event: "
654             "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n",
655             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*0) & 0xFFFF,
656             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*1) & 0xFFFF,
657             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*2) & 0xFFFF,
658             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*3) & 0xFFFF,
659             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*4) & 0xFFFF,
660             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*5) & 0xFFFF,
661             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*6) & 0xFFFF,
662             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(s16)*7) & 0xFFFF, siglen);
663     if(signal_buffer_is_full(priv)) {
664         unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n");
665         for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) {
666             if (bulkdata->d[i].data_length != 0) {
667                 unifi_net_data_free(priv, (void *)&bulkdata->d[i]);
668             }
669         }
670         return;
671     }
672     writePointer = priv->rxSignalBuffer.writePointer;
673     rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer];
674     memcpy(rx_buff->bufptr,sigdata,siglen);
675     rx_buff->sig_len = siglen;
676     rx_buff->data_ptrs = *bulkdata;
677     writePointer++;
678     if(writePointer >= priv->rxSignalBuffer.size) {
679         writePointer =0;
680     }
681     unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer);
682     priv->rxSignalBuffer.writePointer = writePointer;
683
684 #ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
685     queue_work(priv->rx_workqueue, &priv->rx_work_struct);
686 #endif
687
688 #else
689     unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata);
690 #endif
691 } /* unifi_receive_event() */
692