Root/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 */
57static 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 */
94static 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 */
368static void
369unifi_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",
499                                       CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata));
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
562        case CSR_MA_PACKET_INDICATION_ID:
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
581static u8 signal_buffer_is_full(unifi_priv_t* priv)
582{
583    return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer));
584}
585
586void 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
611void 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 */
648void
649unifi_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
701

Archive Download this file



interactive