2 * ***************************************************************************
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
14 * ***************************************************************************
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 * ---------------------------------------------------------------------------
40 * Helper for unifi_receive_event.
42 * This function forwards a signal to one client.
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.
55 * ---------------------------------------------------------------------------
57 static void send_to_client(unifi_priv_t
*priv
, ul_client_t
*client
,
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.
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.
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
,
96 const bulk_data_param_t
* bulkdata
,
98 netInterface_priv_t
*interfacePriv
)
100 u16 frmCtrl
, receptionStatus
, frmCtrlSubType
;
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;
112 u8 isWapiUnicastPkt
= FALSE
;
114 #ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
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
;
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");
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
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
;
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
) {
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
) ) {
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
) ||
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*/
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*/
243 /* Its AP Mode . Just Return */
244 *freeBulkData
= TRUE
;
245 unifi_error(priv
, "MIC failure in %s\n", __FUNCTION__
);
250 if (receptionStatus
== CSR_MICHAEL_MIC_ERROR
) {
251 *freeBulkData
= TRUE
;
252 unifi_error(priv
, "MIC failure in %s\n", __FUNCTION__
);
255 #endif /*CSR_WIFI_SECURITY_WAPI_ENABLE*/
257 unifi_trace(priv
, UDBG4
, "frmCtrl = 0x%04x %s\n",
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
)&&
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");
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;
278 case IEEE802_11_FC_TYPE_QOS_NULL
& IEEE80211_FC_SUBTYPE_MASK
:
279 case IEEE802_11_FC_TYPE_NULL
& IEEE80211_FC_SUBTYPE_MASK
:
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");
298 unifi_trace(priv
, UDBG6
, "check_routing_pkt_data_ind(): WAPI - This is a WAI protocol packet\n");
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");
325 unifi_trace(priv
, UDBG6
, "Received a Legacy AP beacon in P2P mode, drop it\n");
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 */
334 unifi_error(priv
, "Unhandled frame type %04x\n", frmCtrl
);
335 *freeBulkData
= TRUE
; /* Not interested, but must free it */
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.
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.
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 * ---------------------------------------------------------------------------
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
;
377 u8 pktIndToSme
= FALSE
, freeBulkData
= FALSE
;
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,
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
);
397 /* check for the type of frame received (checks for 802.11 management frames) */
398 if (signal_id
== CSR_MA_PACKET_INDICATION_ID
)
400 #define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET 14
402 netInterface_priv_t
*interfacePriv
;
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
];
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
)
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]);
419 uf_update_sta_activity(priv
, interfaceTag
, saddr
);
423 pktIndToSme
= check_routing_pkt_data_ind(priv
, sigdata
, bulkdata
, &freeBulkData
, interfacePriv
);
425 unifi_trace(priv
, UDBG6
, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme
)? "YES":"NO");
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
);
436 unifi_error(priv
, "unifi_receive_event2: sigdata or Bulkdata is NULL \n");
438 #ifdef CSR_NATIVE_LINUX
439 send_to_client(priv
, priv
->wext_client
,
441 sigdata
, siglen
, bulkdata
);
446 /* Signals with ReceiverId==0 are also reported to SME / WEXT,
447 * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs
450 if(signal_id
== CSR_MA_VIF_AVAILABILITY_INDICATION_ID
) {
451 uf_process_ma_vif_availibility_ind(priv
, sigdata
, siglen
);
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
,
458 sigdata
, siglen
, bulkdata
);
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
;
468 u16 receptionStatus
= CSR_RX_SUCCESS
;
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
];
474 /* check for MIC failure */
475 receptionStatus
= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata
+ CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET
);
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)
490 u16 interfaceTag
= 0;
491 u8 isMcastPkt
= TRUE
;
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
);
496 unifi_error(priv
, "Received unknown or corrupted signal (0x%x).\n",
497 CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata
));
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"));
510 if (((isMcastPkt
) && (priv
->wapi_multicast_filter
== 1))
511 #ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION
512 || ((!isMcastPkt
) && (priv
->wapi_unicast_filter
== 1))
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
);
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
]);
526 } /* CSR_MA_PACKET_INDICATION_ID */
527 #endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/
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
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
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
],
544 sigdata
, siglen
, bulkdata
);
550 * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION
554 #ifdef UNIFI_SNIFF_ARPHRD
555 case CSR_MA_SNIFFDATA_INDICATION_ID
:
559 case CSR_MA_PACKET_INDICATION_ID
:
564 /* FALLS THROUGH... */
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
]);
573 } /* unifi_process_receive_event() */
576 #ifdef CSR_WIFI_RX_PATH_SPLIT
577 static u8
signal_buffer_is_full(unifi_priv_t
* priv
)
579 return (((priv
->rxSignalBuffer
.writePointer
+ 1)% priv
->rxSignalBuffer
.size
) == (priv
->rxSignalBuffer
.readPointer
));
582 void unifi_rx_queue_flush(void *ospriv
)
584 unifi_priv_t
*priv
= (unifi_priv_t
*)ospriv
;
586 unifi_trace(priv
, UDBG4
, "rx_wq_handler: RdPtr = %d WritePtr = %d\n",
587 priv
->rxSignalBuffer
.readPointer
,priv
->rxSignalBuffer
.writePointer
);
589 u8 readPointer
= priv
->rxSignalBuffer
.readPointer
;
590 while (readPointer
!= priv
->rxSignalBuffer
.writePointer
)
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
);
597 if(readPointer
>= priv
->rxSignalBuffer
.size
) {
601 priv
->rxSignalBuffer
.readPointer
= readPointer
;
605 void rx_wq_handler(struct work_struct
*work
)
607 unifi_priv_t
*priv
= container_of(work
, unifi_priv_t
, rx_work_struct
);
608 unifi_rx_queue_flush(priv
);
615 * ---------------------------------------------------------------------------
616 * unifi_receive_event
618 * Dispatcher for received signals.
620 * This function receives the 'to host' signals and forwards
621 * them to the unifi linux clients.
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.
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 * ---------------------------------------------------------------------------
643 unifi_receive_event(void *ospriv
,
644 u8
*sigdata
, u32 siglen
,
645 const bulk_data_param_t
*bulkdata
)
647 #ifdef CSR_WIFI_RX_PATH_SPLIT
648 unifi_priv_t
*priv
= (unifi_priv_t
*)ospriv
;
651 rx_buff_struct_t
* rx_buff
;
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
]);
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
;
678 if(writePointer
>= priv
->rxSignalBuffer
.size
) {
681 unifi_trace(priv
, UDBG4
, "unifi_receive_event:writePtr = %d\n",priv
->rxSignalBuffer
.writePointer
);
682 priv
->rxSignalBuffer
.writePointer
= writePointer
;
684 #ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
685 queue_work(priv
->rx_workqueue
, &priv
->rx_work_struct
);
689 unifi_process_receive_event(ospriv
, sigdata
, siglen
, bulkdata
);
691 } /* unifi_receive_event() */