summaryrefslogtreecommitdiff
path: root/drivers/staging/csr/unifi_event.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-19 17:33:16 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-19 17:34:58 -0700
commit95edd09ec3b15b165e2c7ba1e54cc508eafb2321 (patch)
tree7fb38c96bdc89f409e0ba5afcf1a703b01c482ca /drivers/staging/csr/unifi_event.c
parent635d2b00e5070378e7bf812acf47fb135c6ab928 (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.c540
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