initial commit with v3.6.7
[linux-3.6.7-moxart.git] / drivers / staging / csr / unifi_event.c
blobc27b23daf399d19c9bd72298c01c9bc40ad176b6
1 /*
2 * ***************************************************************************
3 * FILE: unifi_event.c
5 * PURPOSE:
6 * Process the signals received by UniFi.
7 * It is part of the porting exercise.
9 * Copyright (C) 2009 by Cambridge Silicon Radio Ltd.
11 * Refer to LICENSE.txt included with this source code for details on
12 * the license terms.
14 * ***************************************************************************
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().
31 #include "csr_wifi_hip_unifi.h"
32 #include "csr_wifi_hip_conversions.h"
33 #include "unifi_priv.h"
37 * ---------------------------------------------------------------------------
38 * send_to_client
40 * Helper for unifi_receive_event.
42 * This function forwards a signal to one client.
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.
52 * Returns:
53 * None.
55 * ---------------------------------------------------------------------------
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)
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));*/
68 client->event_hook(client, sigdata, siglen, bulkdata, UDI_TO_HOST);
73 * ---------------------------------------------------------------------------
74 * process_pkt_data_ind
76 * Dispatcher for received signals.
78 * This function receives the 'to host' signals and forwards
79 * them to the unifi linux clients.
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 * ---------------------------------------------------------------------------
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)
100 u16 frmCtrl, receptionStatus, frmCtrlSubType;
101 u8 *macHdrLocation;
102 u8 interfaceTag;
103 u8 isDataFrame;
104 u8 isProtocolVerInvalid = FALSE;
105 u8 isDataFrameSubTypeNoData = FALSE;
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;
114 #ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
115 u16 qosControl;
116 #endif
118 u8 llcSnapHeaderOffset = 0;
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;
123 /*Individual/Group bit - Bit 0 of first byte*/
124 isWapiUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE;
125 #endif
127 #define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22
129 *freeBulkData = FALSE;
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);
136 /* Pull out interface tag from virtual interface identifier */
137 interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff;
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);
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)
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;
159 #ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
161 if (receptionStatus == CSR_MICHAEL_MIC_ERROR) {
163 if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
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))
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) );
172 unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind() :: Value of the QoS control field - 0x%04x \n", qosControl);
174 if (qosControl & IEEE802_11_QC_NON_TID_BITS_MASK)
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");
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;
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;
185 *freeBulkData = FALSE;
187 return FALSE;
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.
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");
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))) {
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
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");
224 /*Ignore this MIC failure*/
225 return FALSE;
227 }/*WAPI re-key specific workaround*/
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));
236 unifi_error(priv, "MIC failure in %s\n", __FUNCTION__);
238 /*Report the MIC failure to the SME*/
239 return TRUE;
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;
255 #endif /*CSR_WIFI_SECURITY_WAPI_ENABLE*/
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");
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
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)) {
271 unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI unicast pkt received when the (wapi_unicast_queued_pkt_filter) is set\n");
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;
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))) {
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");
297 else {
298 unifi_trace(priv, UDBG6, "check_routing_pkt_data_ind(): WAPI - This is a WAI protocol packet\n");
302 #endif
305 switch ((frmCtrl & 0x000c)>>FRAME_CONTROL_TYPE_FIELD_OFFSET) {
306 case IEEE802_11_FRAMETYPE_MANAGEMENT:
307 *freeBulkData = TRUE; /* Free (after SME handler copies it) */
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)){
313 u8 *pSsid, *pSsidLen;
314 static u8 P2PWildCardSsid[CSR_WIFI_P2P_WILDCARD_SSID_LENGTH] = {'D', 'I', 'R', 'E', 'C', 'T', '-'};
316 pSsidLen = macHdrLocation + MAC_HEADER_SIZE + CSR_WIFI_BEACON_FIXED_LENGTH;
317 pSsid = pSsidLen + 2;
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;
325 unifi_trace(priv, UDBG6, "Received a Legacy AP beacon in P2P mode, drop it\n");
326 return FALSE;
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;
341 * ---------------------------------------------------------------------------
342 * unifi_process_receive_event
344 * Dispatcher for received signals.
346 * This function receives the 'to host' signals and forwards
347 * them to the unifi linux clients.
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.
355 * Returns:
356 * None.
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 * ---------------------------------------------------------------------------
368 static void
369 unifi_process_receive_event(void *ospriv,
370 u8 *sigdata, u32 siglen,
371 const bulk_data_param_t *bulkdata)
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;
379 func_enter();
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);
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);
399 /* check for the type of frame received (checks for 802.11 management frames) */
400 if (signal_id == CSR_MA_PACKET_INDICATION_ID)
402 #define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET 14
403 u8 interfaceTag;
404 netInterface_priv_t *interfacePriv;
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];
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)
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]);
421 uf_update_sta_activity(priv, interfaceTag, saddr);
423 #endif
425 pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv);
427 unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO");
431 if (pktIndToSme)
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);
437 else{
438 unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n");
440 #ifdef CSR_NATIVE_LINUX
441 send_to_client(priv, priv->wext_client,
442 receiver_id,
443 sigdata, siglen, bulkdata);
444 #endif
446 else
448 /* Signals with ReceiverId==0 are also reported to SME / WEXT,
449 * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs
451 if (!receiver_id) {
452 if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) {
453 uf_process_ma_vif_availibility_ind(priv, sigdata, siglen);
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
463 else
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;
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];
476 /* check for MIC failure */
477 receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET);
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
489 CSR_SIGNAL signal;
490 u8 *destAddr;
491 CsrResult res;
492 u16 interfaceTag = 0;
493 u8 isMcastPkt = TRUE;
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;
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"));
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
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);
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]);
526 func_exit();
527 return;
529 } /* CSR_MA_PACKET_INDICATION_ID */
530 #endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/
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
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
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);
553 * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION
555 switch (signal_id)
557 #ifdef UNIFI_SNIFF_ARPHRD
558 case CSR_MA_SNIFFDATA_INDICATION_ID:
559 #endif
560 break;
562 case CSR_MA_PACKET_INDICATION_ID:
563 if (!freeBulkData)
565 break;
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]);
576 func_exit();
577 } /* unifi_process_receive_event() */
580 #ifdef CSR_WIFI_RX_PATH_SPLIT
581 static u8 signal_buffer_is_full(unifi_priv_t* priv)
583 return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer));
586 void unifi_rx_queue_flush(void *ospriv)
588 unifi_priv_t *priv = (unifi_priv_t*)ospriv;
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)
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;
606 priv->rxSignalBuffer.readPointer = readPointer;
608 func_exit();
611 void rx_wq_handler(struct work_struct *work)
613 unifi_priv_t *priv = container_of(work, unifi_priv_t, rx_work_struct);
614 unifi_rx_queue_flush(priv);
616 #endif
621 * ---------------------------------------------------------------------------
622 * unifi_receive_event
624 * Dispatcher for received signals.
626 * This function receives the 'to host' signals and forwards
627 * them to the unifi linux clients.
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.
635 * Returns:
636 * None.
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 * ---------------------------------------------------------------------------
648 void
649 unifi_receive_event(void *ospriv,
650 u8 *sigdata, u32 siglen,
651 const bulk_data_param_t *bulkdata)
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();
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]);
677 return;
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;
688 unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer);
689 priv->rxSignalBuffer.writePointer = writePointer;
691 #ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
692 queue_work(priv->rx_workqueue, &priv->rx_work_struct);
693 #endif
695 #else
696 unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata);
697 #endif
698 func_exit();
699 } /* unifi_receive_event() */