diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-19 17:33:16 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-06-19 17:34:58 -0700 |
commit | 95edd09ec3b15b165e2c7ba1e54cc508eafb2321 (patch) | |
tree | 7fb38c96bdc89f409e0ba5afcf1a703b01c482ca /drivers/staging/csr/unifi_event.c | |
parent | 635d2b00e5070378e7bf812acf47fb135c6ab928 (diff) |
Staging: csr: update to version 5.1.0 of the driver
This brings the in-kernel driver up to the level of the
csr-linux-wifi-5.1.0-oss.tar.gz tarball.
Cc: Mikko Virkkilä <mikko.virkkila@bluegiga.com>
Cc: Lauri Hintsala <Lauri.Hintsala@bluegiga.com>
Cc: Riku Mettälä <riku.mettala@bluegiga.com>
Cc: Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/csr/unifi_event.c')
-rw-r--r-- | drivers/staging/csr/unifi_event.c | 540 |
1 files changed, 223 insertions, 317 deletions
diff --git a/drivers/staging/csr/unifi_event.c b/drivers/staging/csr/unifi_event.c index cfc5b32d4a66..8b5d4669e127 100644 --- a/drivers/staging/csr/unifi_event.c +++ b/drivers/staging/csr/unifi_event.c @@ -109,7 +109,11 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, static const CsrUint8 wapiProtocolIdSNAPHeaderOffset = 6; CsrUint8 *destAddr; CsrUint8 *srcAddr; - CsrBool isUnicastPkt = FALSE; + CsrBool isWapiUnicastPkt = FALSE; + +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + CsrUint16 qosControl; +#endif CsrUint8 llcSnapHeaderOffset = 0; @@ -117,7 +121,7 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, srcAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; /*Individual/Group bit - Bit 0 of first byte*/ - isUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE; + isWapiUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE; #endif #define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 @@ -158,20 +162,54 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) { +#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND + if ((isDataFrame) && + ((IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK) == (frmCtrl & IEEE80211_FC_SUBTYPE_MASK)) && + (priv->isWapiConnection)) + { + qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation + (((frmCtrl & IEEE802_11_FC_TO_DS_MASK) && (frmCtrl & IEEE802_11_FC_FROM_DS_MASK)) ? 30 : 24) ); + + unifi_trace(priv, UDBG4, "check_routing_pkt_data_ind() :: Value of the QoS control field - 0x%04x \n", qosControl); + + if (qosControl & IEEE802_11_QC_NON_TID_BITS_MASK) + { + 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"); + + /*Exclude the MIC [16] and the PN [16] that are appended by the firmware*/ + ((bulk_data_param_t*)bulkdata)->d[0].data_length = bulkdata->d[0].data_length - 32; + + /*Clear the reception status of the signal (CSR_RX_SUCCESS)*/ + *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET) = 0x00; + *(sigdata + CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET+1) = 0x00; + + *freeBulkData = FALSE; + + return FALSE; + } + } +#endif /* If this MIC ERROR reported by the firmware is either for - * [1] a WAPI Multicast Packet and the Multicast filter has NOT been set (It is set only when group key index (MSKID) = 1 in Group Rekeying) OR - * [2] a WAPI Unicast Packet and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set + * [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 + * [2] a WAPI Unicast MPDU and either the CONTROL PORT is open or the WAPI Unicast filter or filter(s) is NOT set * then report a MIC FAILURE indication to the SME. */ - if ((priv->wapi_multicast_filter == 0) || isUnicastPkt) { - +#ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION + if ((priv->wapi_multicast_filter == 0) || isWapiUnicastPkt) { +#else + /*When SW encryption is enabled and USKID=1 (wapi_unicast_filter = 1), we are expected + *to receive MIC failure INDs for unicast MPDUs*/ + if ( ((priv->wapi_multicast_filter == 0) && !isWapiUnicastPkt) || + ((priv->wapi_unicast_filter == 0) && isWapiUnicastPkt) ) { +#endif /*Discard the frame*/ *freeBulkData = TRUE; unifi_trace(priv, UDBG4, "Discarding the contents of the frame with MIC failure \n"); - if (isUnicastPkt && + if (isWapiUnicastPkt && ((uf_sme_port_state(priv,srcAddr,UF_CONTROLLED_PORT_Q,interfaceTag) != CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN)|| +#ifndef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION (priv->wapi_unicast_filter) || +#endif (priv->wapi_unicast_queued_pkt_filter))) { /* Workaround to handle MIC failures reported by the firmware for encrypted packets from the AP @@ -225,7 +263,8 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, /* To ignore MIC failures reported due to the WAPI AP using the old key for queued packets before * starting to use the new key negotiated as part of unicast re-keying */ - if (isUnicastPkt && + if ((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA)&& + isWapiUnicastPkt && (receptionStatus == CSR_RX_SUCCESS) && (priv->wapi_unicast_queued_pkt_filter==1)) { @@ -297,16 +336,10 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv, return FALSE; } } -#ifdef CSR_WIFI_RX_PATH_SPLIT -static CsrBool signal_buffer_is_full(unifi_priv_t* priv) -{ - return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer)); -} -#endif /* * --------------------------------------------------------------------------- - * unifi_receive_event + * unifi_process_receive_event * * Dispatcher for received signals. * @@ -332,56 +365,11 @@ static CsrBool signal_buffer_is_full(unifi_priv_t* priv) * binded to the host interface specification. * --------------------------------------------------------------------------- */ - - -void -unifi_receive_event(void *ospriv, - CsrUint8 *sigdata, CsrUint32 siglen, - const bulk_data_param_t *bulkdata) +static void +unifi_process_receive_event(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) { -#ifdef CSR_WIFI_RX_PATH_SPLIT - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - CsrUint8 writePointer; - int i; - rx_buff_struct_t * rx_buff; - func_enter(); - - unifi_trace(priv, UDBG5, "unifi_receive_event: " - "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); - if(signal_buffer_is_full(priv)) { - unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n"); - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - return; - } - writePointer = priv->rxSignalBuffer.writePointer; - rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer]; - memcpy(rx_buff->bufptr,sigdata,siglen); - rx_buff->sig_len = siglen; - rx_buff->data_ptrs = *bulkdata; - writePointer++; - if(writePointer >= priv->rxSignalBuffer.size) { - writePointer =0; - } - unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer); - priv->rxSignalBuffer.writePointer = writePointer; - -#ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ - queue_work(priv->rx_workqueue, &priv->rx_work_struct); -#endif - -#else unifi_priv_t *priv = (unifi_priv_t*)ospriv; int i, receiver_id; int client_id; @@ -390,16 +378,17 @@ unifi_receive_event(void *ospriv, func_enter(); - unifi_trace(priv, UDBG5, "unifi_receive_event: " - "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, - CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); + unifi_trace(priv, UDBG5, "unifi_process_receive_event: " + "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*2) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*3) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*4) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, + CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, + siglen); receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00; client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; @@ -410,18 +399,18 @@ unifi_receive_event(void *ospriv, /* check for the type of frame received (checks for 802.11 management frames) */ if (signal_id == CSR_MA_PACKET_INDICATION_ID) { +#define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET 14 CsrUint8 interfaceTag; netInterface_priv_t *interfacePriv; /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff; interfacePriv = priv->interfacePriv[interfaceTag]; /* Update activity for this station in case of IBSS */ #ifdef CSR_SUPPORT_SME - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { - + if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) + { CsrUint8 *saddr; /* Fetch the source address from mac header */ saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; @@ -436,6 +425,7 @@ unifi_receive_event(void *ospriv, pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); + } if (pktIndToSme) @@ -445,7 +435,7 @@ unifi_receive_event(void *ospriv, send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); } else{ - unifi_error(priv, "unifi_receive_event: sigdata or Bulkdata is NULL \n"); + unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n"); } #ifdef CSR_NATIVE_LINUX send_to_client(priv, priv->wext_client, @@ -459,67 +449,99 @@ unifi_receive_event(void *ospriv, * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs */ if (!receiver_id) { - if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) - { - uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); - } - else if (signal_id != CSR_MA_PACKET_INDICATION_ID) - { - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); + if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) { + uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); + } + else if (signal_id != CSR_MA_PACKET_INDICATION_ID) { + send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); #ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); + send_to_client(priv, priv->wext_client, + receiver_id, + sigdata, siglen, bulkdata); #endif - } - }/*if (receiver_id==0) */ - -#ifdef CSR_SUPPORT_SME -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - /* Send a WAPI Multicast Indication to SME if the filter has been set - * and this is a multicast data packet - */ - if ((priv->wapi_multicast_filter == 1) && (signal_id == CSR_MA_PACKET_INDICATION_ID)) { - CSR_SIGNAL signal; - CsrUint8 *destAddr; - CsrResult res; - CsrUint16 interfaceTag = 0; - - /* Check if it is a multicast packet from the destination address in the MAC header */ - res = read_unpack_signal(sigdata, &signal); - destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; - if (res) { - unifi_error(priv, "Received unknown or corrupted signal.\n"); - return; - } - /*Individual/Group bit - Bit 0 of first byte*/ - if (destAddr[0] & 0x01) { - unifi_trace(priv, UDBG4, "Received a WAPI multicast packet ind\n"); - - CsrWifiRouterCtrlWapiMulticastIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); - - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - func_exit(); - return; - } - } + } + else + { + +#if (defined(CSR_SUPPORT_SME) && defined(CSR_WIFI_SECURITY_WAPI_ENABLE)) + #define CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22 + netInterface_priv_t *interfacePriv; + CsrUint8 interfaceTag; + CsrUint16 receptionStatus = CSR_RX_SUCCESS; + + /* Pull out interface tag from virtual interface identifier */ + interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET)) & 0xff; + interfacePriv = priv->interfacePriv[interfaceTag]; + + /* check for MIC failure */ + receptionStatus = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + CSR_MA_PACKET_INDICATION_RECEPTION_STATUS_OFFSET); + + /* Send a WAPI MPDU to SME for re-check MIC if the respective filter has been set*/ + if ((!freeBulkData) && + (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) && + (receptionStatus == CSR_MICHAEL_MIC_ERROR) && + ((priv->wapi_multicast_filter == 1) +#ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION + || (priv->wapi_unicast_filter == 1) #endif + )) + { + CSR_SIGNAL signal; + CsrUint8 *destAddr; + CsrResult res; + CsrUint16 interfaceTag = 0; + CsrBool isMcastPkt = TRUE; + + unifi_trace(priv, UDBG6, "Received a WAPI data packet when the Unicast/Multicast filter is set\n"); + res = read_unpack_signal(sigdata, &signal); + if (res) { + unifi_error(priv, "Received unknown or corrupted signal (0x%x).\n", + CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata)); + return; + } + + /* Check if the type of MPDU and the respective filter status*/ + destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; + isMcastPkt = (destAddr[0] & 0x01) ? TRUE : FALSE; + unifi_trace(priv, UDBG6, + "1.MPDU type: (%s), 2.Multicast filter: (%s), 3. Unicast filter: (%s)\n", + ((isMcastPkt) ? "Multiast":"Unicast"), + ((priv->wapi_multicast_filter) ? "Enabled":"Disabled"), + ((priv->wapi_unicast_filter) ? "Enabled":"Disabled")); + + if (((isMcastPkt) && (priv->wapi_multicast_filter == 1)) +#ifdef CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION + || ((!isMcastPkt) && (priv->wapi_unicast_filter == 1)) #endif + ) + { + unifi_trace(priv, UDBG4, "Sending the WAPI MPDU for MIC check\n"); + CsrWifiRouterCtrlWapiRxMicCheckIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); + + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } + } + func_exit(); + return; + } + } /* CSR_MA_PACKET_INDICATION_ID */ +#endif /*CSR_SUPPORT_SME && CSR_WIFI_SECURITY_WAPI_ENABLE*/ + } + } /* calls the registered clients handler callback func. * netdev_mlme_event_handler is one of the registered handler used to route * data packet to network stack or AMP/EAPOL related data to SME - */ - /* The freeBulkData check ensures that, it has received a management frame and + * + * The freeBulkData check ensures that, it has received a management frame and * the frame needs to be freed here. So not to be passed to netdev handler */ if(!freeBulkData){ if ((client_id < MAX_UDI_CLIENTS) && (&priv->ul_clients[client_id] != priv->logging_client)) { + unifi_trace(priv, UDBG6, "Call the registered clients handler callback func\n"); send_to_client(priv, &priv->ul_clients[client_id], receiver_id, sigdata, siglen, bulkdata); @@ -550,14 +572,54 @@ unifi_receive_event(void *ospriv, } } } -#endif + func_exit(); -} /* unifi_receive_event() */ +} /* unifi_process_receive_event() */ + #ifdef CSR_WIFI_RX_PATH_SPLIT +static CsrBool signal_buffer_is_full(unifi_priv_t* priv) +{ + return (((priv->rxSignalBuffer.writePointer + 1)% priv->rxSignalBuffer.size) == (priv->rxSignalBuffer.readPointer)); +} + +void unifi_rx_queue_flush(void *ospriv) +{ + unifi_priv_t *priv = (unifi_priv_t*)ospriv; + + func_enter(); + unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", + priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer); + if(priv != NULL) { + CsrUint8 readPointer = priv->rxSignalBuffer.readPointer; + while (readPointer != priv->rxSignalBuffer.writePointer) + { + rx_buff_struct_t *buf = &priv->rxSignalBuffer.rx_buff[readPointer]; + unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", + readPointer,priv->rxSignalBuffer.writePointer); + unifi_process_receive_event(priv, buf->bufptr, buf->sig_len, &buf->data_ptrs); + readPointer ++; + if(readPointer >= priv->rxSignalBuffer.size) { + readPointer = 0; + } + } + priv->rxSignalBuffer.readPointer = readPointer; + } + func_exit(); +} + +void rx_wq_handler(struct work_struct *work) +{ + unifi_priv_t *priv = container_of(work, unifi_priv_t, rx_work_struct); + unifi_rx_queue_flush(priv); +} +#endif + + + /* * --------------------------------------------------------------------------- - * unifi_receive_event2 + * unifi_receive_event * * Dispatcher for received signals. * @@ -583,20 +645,19 @@ unifi_receive_event(void *ospriv, * binded to the host interface specification. * --------------------------------------------------------------------------- */ -static void -unifi_receive_event2(void *ospriv, - CsrUint8 *sigdata, CsrUint32 siglen, - const bulk_data_param_t *bulkdata) +void +unifi_receive_event(void *ospriv, + CsrUint8 *sigdata, CsrUint32 siglen, + const bulk_data_param_t *bulkdata) { +#ifdef CSR_WIFI_RX_PATH_SPLIT unifi_priv_t *priv = (unifi_priv_t*)ospriv; - int i, receiver_id; - int client_id; - CsrInt16 signal_id; - CsrBool pktIndToSme = FALSE, freeBulkData = FALSE; - + CsrUint8 writePointer; + int i; + rx_buff_struct_t * rx_buff; func_enter(); - unifi_trace(priv, UDBG5, "unifi_receive_event2: " + unifi_trace(priv, UDBG5, "unifi_receive_event: " "%04x %04x %04x %04x %04x %04x %04x %04x (%d)\n", CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*0) & 0xFFFF, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 0xFFFF, @@ -606,189 +667,34 @@ unifi_receive_event2(void *ospriv, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*5) & 0xFFFF, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF, CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen); - - receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00; - client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT; - signal_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata); - - - - /* check for the type of frame received (checks for 802.11 management frames) */ - if (signal_id == CSR_MA_PACKET_INDICATION_ID) - { - CsrUint8 interfaceTag; - netInterface_priv_t *interfacePriv; - - /* Pull out interface tag from virtual interface identifier */ - interfaceTag = (CSR_GET_UINT16_FROM_LITTLE_ENDIAN(sigdata + 14)) & 0xff; - interfacePriv = priv->interfacePriv[interfaceTag]; - - /* Update activity for this station in case of IBSS */ -#ifdef CSR_SUPPORT_SME - - if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) { - - CsrUint8 *saddr; - /* Fetch the source address from mac header */ - saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET; - unifi_trace(priv, UDBG5, - "Updating sta activity in IBSS interfaceTag %x Src Addr %x:%x:%x:%x:%x:%x\n", - interfaceTag, saddr[0], saddr[1], saddr[2], saddr[3], saddr[4], saddr[5]); - - uf_update_sta_activity(priv, interfaceTag, saddr); + if(signal_buffer_is_full(priv)) { + unifi_error(priv,"TO HOST signal queue FULL dropping the PDU\n"); + for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { + if (bulkdata->d[i].data_length != 0) { + unifi_net_data_free(priv, (void *)&bulkdata->d[i]); + } } -#endif - - pktIndToSme = check_routing_pkt_data_ind(priv, sigdata, bulkdata, &freeBulkData, interfacePriv); - - unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO"); - + return; } - - if (pktIndToSme) - { - /* Management MA_PACKET_IND for SME */ - if(sigdata != NULL && bulkdata != NULL){ - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); - } - else{ - unifi_error(priv, "unifi_receive_event2: sigdata or Bulkdata is NULL \n"); - } -#ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); -#endif + writePointer = priv->rxSignalBuffer.writePointer; + rx_buff = &priv->rxSignalBuffer.rx_buff[writePointer]; + memcpy(rx_buff->bufptr,sigdata,siglen); + rx_buff->sig_len = siglen; + rx_buff->data_ptrs = *bulkdata; + writePointer++; + if(writePointer >= priv->rxSignalBuffer.size) { + writePointer =0; } - else - { - /* Signals with ReceiverId==0 are also reported to SME / WEXT, - * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs - */ - if (!receiver_id) { - if(signal_id == CSR_MA_VIF_AVAILABILITY_INDICATION_ID) - { - uf_process_ma_vif_availibility_ind(priv, sigdata, siglen); - } - else if (signal_id != CSR_MA_PACKET_INDICATION_ID) - { - send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata); -#ifdef CSR_NATIVE_LINUX - send_to_client(priv, priv->wext_client, - receiver_id, - sigdata, siglen, bulkdata); -#endif - } - } - -#ifdef CSR_SUPPORT_SME -#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE - /* Send a WAPI Multicast Indication to SME if the filter has been set - * and this is a multicast data packet - */ - if ((priv->wapi_multicast_filter == 1) && (signal_id == CSR_MA_PACKET_INDICATION_ID)) { - CSR_SIGNAL signal; - CsrUint8 *destAddr; - CsrResult res; - CsrUint16 interfaceTag = 0; - - /* Check if it is a multicast packet from the destination address in the MAC header */ - res = read_unpack_signal(sigdata, &signal); - destAddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR1_OFFSET; - if (res) { - unifi_error(priv, "Received unknown or corrupted signal.\n"); - return; - } - /*Individual/Group bit - Bit 0 of first byte*/ - if (destAddr[0] & 0x01) { - unifi_trace(priv, UDBG4, "Received a WAPI multicast packet ind\n"); - - CsrWifiRouterCtrlWapiMulticastIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, siglen, sigdata, bulkdata->d[0].data_length, (CsrUint8*)bulkdata->d[0].os_data_ptr); + unifi_trace(priv, UDBG4, "unifi_receive_event:writePtr = %d\n",priv->rxSignalBuffer.writePointer); + priv->rxSignalBuffer.writePointer = writePointer; - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - func_exit(); - return; - } - } -#endif +#ifndef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ + queue_work(priv->rx_workqueue, &priv->rx_work_struct); #endif - /* calls the registered clients handler callback func. - * netdev_mlme_event_handler is one of the registered handler used to route - * data packet to network stack or AMP/EAPOL related data to SME - */ - /* The freeBulkData check ensures that, it has received a management frame and - * the frame needs to be freed here. So not to be passed to netdev handler - */ - if(!freeBulkData){ - if ((client_id < MAX_UDI_CLIENTS) && - (&priv->ul_clients[client_id] != priv->logging_client)) { - send_to_client(priv, &priv->ul_clients[client_id], - receiver_id, - sigdata, siglen, bulkdata); - } - } - } - - /* - * Free bulk data buffers here unless it is a CSR_MA_PACKET_INDICATION - */ - switch (signal_id) - { -#ifdef UNIFI_SNIFF_ARPHRD - case CSR_MA_SNIFFDATA_INDICATION_ID: +#else + unifi_process_receive_event(ospriv, sigdata, siglen, bulkdata); #endif - break; - - case CSR_MA_PACKET_INDICATION_ID: - if (!freeBulkData) - { - break; - } - /* FALLS THROUGH... */ - default: - for (i = 0; i < UNIFI_MAX_DATA_REFERENCES; i++) { - if (bulkdata->d[i].data_length != 0) { - unifi_net_data_free(priv, (void *)&bulkdata->d[i]); - } - } - } - func_exit(); -} /* unifi_receive_event2() */ - -void unifi_rx_queue_flush(void *ospriv) -{ - unifi_priv_t *priv = (unifi_priv_t*)ospriv; - - func_enter(); - unifi_trace(priv, UDBG4, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", - priv->rxSignalBuffer.readPointer,priv->rxSignalBuffer.writePointer); - if(priv != NULL) { - CsrUint8 readPointer = priv->rxSignalBuffer.readPointer; - while(readPointer != priv->rxSignalBuffer.writePointer) { - rx_buff_struct_t * buf = &priv->rxSignalBuffer.rx_buff[readPointer]; - unifi_trace(priv, UDBG6, "rx_wq_handler: RdPtr = %d WritePtr = %d\n", - readPointer,priv->rxSignalBuffer.writePointer); - unifi_receive_event2(priv,buf->bufptr,buf->sig_len,&buf->data_ptrs); - readPointer ++; - if(readPointer >= priv->rxSignalBuffer.size) { - readPointer = 0; - } - } - priv->rxSignalBuffer.readPointer = readPointer; - } - func_exit(); -} - -void rx_wq_handler(struct work_struct *work) -{ - unifi_priv_t *priv = container_of(work,unifi_priv_t,rx_work_struct); - unifi_rx_queue_flush(priv); -} +} /* unifi_receive_event() */ -#endif |