Staging: csr: update to version 5.1.0 of the driver
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Jun 2012 00:33:16 +0000 (17:33 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Jun 2012 00:34:58 +0000 (17:34 -0700)
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>
56 files changed:
drivers/staging/csr/csr_framework_ext.c
drivers/staging/csr/csr_types.h
drivers/staging/csr/csr_util.c
drivers/staging/csr/csr_util.h
drivers/staging/csr/csr_wifi_common.h
drivers/staging/csr/csr_wifi_hip_card.h
drivers/staging/csr/csr_wifi_hip_card_sdio.c
drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c
drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c
drivers/staging/csr/csr_wifi_hip_download.c
drivers/staging/csr/csr_wifi_hip_dump.c
drivers/staging/csr/csr_wifi_hip_ta_sampling.c
drivers/staging/csr/csr_wifi_hip_unifi.h
drivers/staging/csr/csr_wifi_hip_xbv.c
drivers/staging/csr/csr_wifi_nme_ap_lib.h
drivers/staging/csr/csr_wifi_nme_ap_prim.h
drivers/staging/csr/csr_wifi_router_converter_init.c
drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c
drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c
drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c
drivers/staging/csr/csr_wifi_router_ctrl_lib.h
drivers/staging/csr/csr_wifi_router_ctrl_prim.h
drivers/staging/csr/csr_wifi_router_ctrl_sef.c
drivers/staging/csr/csr_wifi_router_ctrl_sef.h
drivers/staging/csr/csr_wifi_router_ctrl_serialize.c
drivers/staging/csr/csr_wifi_router_ctrl_serialize.h
drivers/staging/csr/csr_wifi_sme_ap_lib.h
drivers/staging/csr/csr_wifi_sme_ap_prim.h
drivers/staging/csr/csr_wifi_sme_converter_init.c
drivers/staging/csr/csr_wifi_sme_converter_init.h
drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c
drivers/staging/csr/csr_wifi_sme_lib.h
drivers/staging/csr/csr_wifi_sme_prim.h
drivers/staging/csr/csr_wifi_sme_serialize.c
drivers/staging/csr/csr_wifi_sme_serialize.h
drivers/staging/csr/drv.c
drivers/staging/csr/firmware.c
drivers/staging/csr/io.c
drivers/staging/csr/netdev.c
drivers/staging/csr/os.c
drivers/staging/csr/putest.c
drivers/staging/csr/sdio_emb.c
drivers/staging/csr/sdio_events.c
drivers/staging/csr/sdio_mmc.c
drivers/staging/csr/sme_blocking.c
drivers/staging/csr/sme_sys.c
drivers/staging/csr/sme_userspace.c
drivers/staging/csr/sme_wext.c
drivers/staging/csr/ul_int.c
drivers/staging/csr/unifi_event.c
drivers/staging/csr/unifi_os.h
drivers/staging/csr/unifi_pdu_processing.c
drivers/staging/csr/unifi_priv.h
drivers/staging/csr/unifi_sme.c
drivers/staging/csr/unifi_sme.h
drivers/staging/csr/unifiio.h

index 0406a4b0f7860afb487ded79dda127bc06d9e96b..1586b235e296fca8526d5d552dfcdf04e49d024d 100644 (file)
@@ -211,3 +211,38 @@ void CsrMemFree(void *pointer)
     kfree(pointer);
 }
 EXPORT_SYMBOL_GPL(CsrMemFree);
+
+/*----------------------------------------------------------------------------*
+ *  NAME
+ *      CsrMemAllocDma
+ *
+ *  DESCRIPTION
+ *      Allocate DMA capable dynamic memory of a given size.
+ *
+ *  RETURNS
+ *      Pointer to allocated memory, or NULL in case of failure.
+ *      Allocated memory is not initialised.
+ *
+ *----------------------------------------------------------------------------*/
+void *CsrMemAllocDma(CsrSize size)
+{
+    return kmalloc(size, GFP_KERNEL | GFP_DMA);
+}
+EXPORT_SYMBOL_GPL(CsrMemAllocDma);
+
+/*----------------------------------------------------------------------------*
+ *  NAME
+ *      CsrMemFreeDma
+ *
+ *  DESCRIPTION
+ *      Free DMA capable dynamic allocated memory.
+ *
+ *  RETURNS
+ *      void
+ *
+ *----------------------------------------------------------------------------*/
+void CsrMemFreeDma(void *pointer)
+{
+    kfree(pointer);
+}
+EXPORT_SYMBOL_GPL(CsrMemFreeDma);
index d7d2c5d061fe22e9966ed101732020f922cb610d..23193ea4429fd0a8df3adf88dfe08e8264142103 100644 (file)
@@ -21,6 +21,7 @@
 #include <stddef.h>
 #include <sys/types.h>
 #include <stdarg.h>
+#include <string.h>
 #endif
 
 #ifdef __cplusplus
index 0ae11531e26ddac86c06c4b67054ff539b09a0a3..939c87c638a199feb5a8450564934fd575377975 100644 (file)
@@ -221,6 +221,7 @@ void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str)
 /*------------------------------------------------------------------*/
 /*  String */
 /*------------------------------------------------------------------*/
+#ifndef CSR_USE_STDC_LIB
 void *CsrMemCpy(void *dest, const void *src, CsrSize count)
 {
     return memcpy(dest, src, count);
@@ -257,7 +258,9 @@ void *CsrMemDup(const void *buf1, CsrSize count)
 
     return buf2;
 }
+#endif
 
+#ifndef CSR_USE_STDC_LIB
 CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src)
 {
     return strcpy(dest, src);
@@ -303,6 +306,7 @@ CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c)
 {
     return strchr(string, c);
 }
+#endif
 
 CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args)
 {
index a19baddc0213782631a3fa950457a25eb44fd03d..ce39c7e8dab7cd1413dda8eb2966ee22893379ee 100644 (file)
@@ -35,26 +35,53 @@ void CsrUInt16ToHex(CsrUint16 number, CsrCharString *str);
 void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str);
 
 /*------------------------------------------------------------------*/
-/*  String */
+/* Standard C Library functions */
 /*------------------------------------------------------------------*/
+#ifdef CSR_USE_STDC_LIB
+#define CsrMemCpy memcpy
+#define CsrMemMove memmove
+#define CsrStrCpy strcpy
+#define CsrStrNCpy strncpy
+#define CsrStrCat strcat
+#define CsrStrNCat strncat
+#define CsrMemCmp(s1, s2, n) ((CsrInt32) memcmp((s1), (s2), (n)))
+#define CsrStrCmp(s1, s2) ((CsrInt32) strcmp((s1), (s2)))
+#define CsrStrNCmp(s1, s2, n) ((CsrInt32) strncmp((s1), (s2), (n)))
+/*#define CsrMemChr memchr*/
+#define CsrStrChr strchr
+/*#define CsrStrCSpn strcspn*/
+/*#define CsrStrPBrk strpbrk*/
+/*#define CsrStrRChr strrchr*/
+/*#define CsrStrSpn strspn*/
+#define CsrStrStr strstr
+/*#define CsrStrTok strtok*/
+#define CsrMemSet memset
+#define CsrStrLen strlen
+/*#define CsrVsnprintf(s, n, format, arg) ((CsrInt32) vsnprintf((s), (n), (format), (arg)))*/
+#else /* !CSR_USE_STDC_LIB */
 void *CsrMemCpy(void *dest, const void *src, CsrSize count);
-void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count);
 void *CsrMemMove(void *dest, const void *src, CsrSize count);
-CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count);
-void *CsrMemDup(const void *buf1, CsrSize count);
 CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src);
 CsrCharString *CsrStrNCpy(CsrCharString *dest, const CsrCharString *src, CsrSize count);
-int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
 CsrCharString *CsrStrCat(CsrCharString *dest, const CsrCharString *src);
 CsrCharString *CsrStrNCat(CsrCharString *dest, const CsrCharString *src, CsrSize count);
-CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2);
-CsrSize CsrStrLen(const CsrCharString *string);
+CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count);
 CsrInt32 CsrStrCmp(const CsrCharString *string1, const CsrCharString *string2);
 CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
-CsrCharString *CsrStrDup(const CsrCharString *string);
 CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c);
-CsrUint32 CsrStrToInt(const CsrCharString *string);
+CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2);
+void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count);
+CsrSize CsrStrLen(const CsrCharString *string);
+#endif /* !CSR_USE_STDC_LIB */
 CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args);
+
+/*------------------------------------------------------------------*/
+/* Non-standard utility functions */
+/*------------------------------------------------------------------*/
+void *CsrMemDup(const void *buf1, CsrSize count);
+int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
+CsrCharString *CsrStrDup(const CsrCharString *string);
+CsrUint32 CsrStrToInt(const CsrCharString *string);
 CsrCharString *CsrStrNCpyZero(CsrCharString *dest, const CsrCharString *src, CsrSize count);
 
 /*------------------------------------------------------------------*/
index 1cdde5c7bd8d4bdbf90616a69f997ff58b9b59c3..442dcc6e4e068be9d621e844cb0aca9d9bb936ce 100644 (file)
@@ -99,7 +99,7 @@ typedef struct
 #define CSR_WIFI_RESULT_INVALID_INTERFACE_TAG     ((CsrResult) 0x000B)
 #define CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT   ((CsrResult) 0x000C)
 
-#define CSR_WIFI_VERSION       "5.0.3.0"
+#define CSR_WIFI_VERSION       "5.1.0.0"
 
 #ifdef __cplusplus
 }
index 8904211d3317c6ff583f9a73e02b6f40dfc469d0..2ab47843bcc6ab80cd84c029ccbf23572d63b5a6 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -81,6 +81,15 @@ CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQue
  */
 void CardClearFromHostDataSlot(card_t *card, const CsrInt16 aSlotNum);
 
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+/*****************************************************************************
+ * CardClearFromHostDataSlotWithoutFreeingBulkData - Clear the data stot
+ * without freeing the bulk data
+ */
+
+void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const CsrInt16 aSlotNum);
+#endif
+
 /*****************************************************************************
  * CardGetFreeFromHostDataSlots -
  */
index 719c608d18b4de6a530e9fb80e321ebfcf5d186c..91976b824a4e19a394572310622b2e38a3db22b2 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -323,7 +323,7 @@ CsrResult unifi_init(card_t *card)
      * have requested a mini-coredump which needs to be captured now the
      * SDIO interface is alive.
      */
-    unifi_coredump_handle_request(card);
+    (void)unifi_coredump_handle_request(card);
 
     /*
      * Probe to see if the UniFi has ROM/flash to boot from. CSR6xxx should do.
@@ -1616,14 +1616,14 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_ptr = 0;
-    CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
-                "fh_cmd_q");
+    (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
+                      "fh_cmd_q");
     for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
     {
         card->fh_traffic_queue[i].q_rd_ptr = 0;
         card->fh_traffic_queue[i].q_wr_ptr = 0;
-        CsrSnprintf(card->fh_traffic_queue[i].name,
-                    UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
+        (void)CsrSnprintf(card->fh_traffic_queue[i].name,
+                          UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
     }
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
@@ -1634,7 +1634,7 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     /*
      * Allocate memory for the from-host and to-host signal buffers.
      */
-    card->fh_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE);
+    card->fh_buffer.buf = CsrMemAllocDma(UNIFI_FH_BUF_SIZE);
     if (card->fh_buffer.buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n");
@@ -1645,7 +1645,7 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     card->fh_buffer.ptr = card->fh_buffer.buf;
     card->fh_buffer.count = 0;
 
-    card->th_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE);
+    card->th_buffer.buf = CsrMemAllocDma(UNIFI_FH_BUF_SIZE);
     if (card->th_buffer.buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n");
@@ -1693,6 +1693,12 @@ static CsrResult card_allocate_memory_resources(card_t *card)
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
 
+    /* Initialise host tag entries for from-host bulk data slots */
+    for (i = 0; i < n; i++)
+    {
+        card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
+    }
+
 
     /* Allocate memory for the array of pointers */
     n = cfg_data->num_tohost_data_slots;
@@ -1811,7 +1817,7 @@ static void card_free_memory_resources(card_t *card)
 
     if (card->fh_buffer.buf)
     {
-        CsrMemFree(card->fh_buffer.buf);
+        CsrMemFreeDma(card->fh_buffer.buf);
     }
     card->fh_buffer.ptr = card->fh_buffer.buf = NULL;
     card->fh_buffer.bufsize = 0;
@@ -1819,7 +1825,7 @@ static void card_free_memory_resources(card_t *card)
 
     if (card->th_buffer.buf)
     {
-        CsrMemFree(card->th_buffer.buf);
+        CsrMemFreeDma(card->th_buffer.buf);
     }
     card->th_buffer.ptr = card->th_buffer.buf = NULL;
     card->th_buffer.bufsize = 0;
@@ -1842,14 +1848,14 @@ static void card_init_soft_queues(card_t *card)
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_ptr = 0;
-    CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
-                "fh_cmd_q");
+    (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
+                      "fh_cmd_q");
     for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
     {
         card->fh_traffic_queue[i].q_rd_ptr = 0;
         card->fh_traffic_queue[i].q_wr_ptr = 0;
-        CsrSnprintf(card->fh_traffic_queue[i].name,
-                    UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
+        (void)CsrSnprintf(card->fh_traffic_queue[i].name,
+                          UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
     }
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
@@ -2399,6 +2405,57 @@ void CardClearFromHostDataSlot(card_t *card, const CsrInt16 slot)
 } /* CardClearFromHostDataSlot() */
 
 
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+/*
+ * ---------------------------------------------------------------------------
+ *  CardClearFromHostDataSlotWithoutFreeingBulkData
+ *
+ *      Clear the given data slot with out freeing the bulk data.
+ *
+ *  Arguments:
+ *      card            Pointer to Card object
+ *      slot            Index of the signal slot to clear.
+ *
+ *  Returns:
+ *      None.
+ * ---------------------------------------------------------------------------
+ */
+void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const CsrInt16 slot)
+{
+    CsrUint8 queue = card->from_host_data[slot].queue;
+
+    /* Initialise the from_host data slot so it can be re-used,
+     * Set length field in from_host_data array to 0.
+     */
+    UNIFI_INIT_BULK_DATA(&card->from_host_data[slot].bd);
+
+    queue = card->from_host_data[slot].queue;
+
+    if (queue < UNIFI_NO_OF_TX_QS)
+    {
+        if (card->dynamic_slot_data.from_host_used_slots[queue] == 0)
+        {
+            unifi_error(card->ospriv, "Goofed up used slots q = %d used slots = %d\n",
+                        queue,
+                        card->dynamic_slot_data.from_host_used_slots[queue]);
+        }
+        else
+        {
+            card->dynamic_slot_data.from_host_used_slots[queue]--;
+        }
+        card->dynamic_slot_data.packets_txed[queue]++;
+        card->dynamic_slot_data.total_packets_txed++;
+        if (card->dynamic_slot_data.total_packets_txed >=
+            card->dynamic_slot_data.packets_interval)
+        {
+            CardReassignDynamicReservation(card);
+        }
+    }
+} /* CardClearFromHostDataSlotWithoutFreeingBulkData() */
+
+
+#endif
+
 CsrUint16 CardGetDataSlotSize(card_t *card)
 {
     return card->config_data.data_slot_size;
index 3d563c13ff5a7435f1acc68150ddda037f3291e8..8fefbdfc715686252df8f8fe345e556dab4c929b 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -148,9 +148,9 @@ void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length)
     CsrCharString s[5];
     CsrUint16 i;
 
-    for (i = 0; i < length; i++)
+    for (i = 0; i < length; i = i + 2)
     {
-        CsrUInt16ToHex(0xff & buff[i], s);
+        CsrUInt16ToHex(*((CsrUint16 *)(buff + i)), s);
         unifi_debug_string_to_buf(s);
     }
 }
@@ -277,7 +277,7 @@ void unifi_sdio_interrupt_handler(card_t *card)
      * Then ask the OS layer to run the unifi_bh to give attention to the UniFi.
      */
     card->bh_reason_unifi = 1;
-    unifi_run_bh(card->ospriv);
+    (void)unifi_run_bh(card->ospriv);
 } /*  sdio_interrupt_handler() */
 
 
@@ -309,7 +309,7 @@ CsrResult unifi_configure_low_power_mode(card_t                       *card,
                 (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled",
                 (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE");
 
-    unifi_run_bh(card->ospriv);
+    (void)unifi_run_bh(card->ospriv);
     return CSR_RESULT_SUCCESS;
 } /* unifi_configure_low_power_mode() */
 
@@ -614,10 +614,10 @@ exit:
                     (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled");
 
         /* Try to capture firmware panic codes */
-        unifi_capture_panic(card);
+        (void)unifi_capture_panic(card);
 
         /* Ask for a mini-coredump when the driver has reset UniFi */
-        unifi_coredump_request_at_next_reset(card, 1);
+        (void)unifi_coredump_request_at_next_reset(card, 1);
     }
 
     return r;
@@ -932,9 +932,13 @@ static CsrResult handle_host_protocol(card_t *card, CsrBool *processed_something
             return r;
         }
     }
+
+#ifdef CSR_WIFI_RX_PATH_SPLIT
 #ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
     unifi_rx_queue_flush(card->ospriv);
 #endif
+#endif
+
     /* See if we can re-enable transmission now */
     restart_packet_flow(card);
 
@@ -1324,7 +1328,6 @@ static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed)
                     if (status && (card->fh_slot_host_tag_record))
                     {
                         CsrUint16 num_fh_slots = card->config_data.num_fromhost_data_slots;
-                        CsrUint16 i = 0;
 
                         /* search through the list of slot records and match with host tag
                          * If a slot is not yet cleared then clear the slot from here
@@ -1333,12 +1336,27 @@ static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed)
                         {
                             if (card->fh_slot_host_tag_record[i] == host_tag)
                             {
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+                                /* Invoke the HAL module function to requeue it back to HAL Queues */
+                                r = unifi_reque_ma_packet_request(card->ospriv, host_tag, status, &card->from_host_data[i].bd);
+                                card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
+                                if (CSR_RESULT_SUCCESS != r)
+                                {
+                                    unifi_trace(card->ospriv, UDBG5, "process_to_host_signals: Failed to requeue Packet(hTag:%x) back to HAL \n", host_tag);
+                                    CardClearFromHostDataSlot(card, i);
+                                }
+                                else
+                                {
+                                    CardClearFromHostDataSlotWithoutFreeingBulkData(card, i);
+                                }
+
+#else
                                 unifi_trace(card->ospriv, UDBG4, "process_to_host_signals Clear slot=%x host tag=%x\n", i, host_tag);
                                 card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
 
                                 /* Set length field in from_host_data array to 0 */
                                 CardClearFromHostDataSlot(card, i);
-
+#endif
                                 break;
                             }
                         }
@@ -1724,7 +1742,7 @@ static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr,
 
     if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3))
     {
-        host_bulk_data_slot = CsrMemAlloc(len);
+        host_bulk_data_slot = CsrMemAllocDma(len);
 
         if (!host_bulk_data_slot)
         {
@@ -1783,7 +1801,7 @@ static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr,
         /* moving this check before we clear host data slot */
         if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3))
         {
-            CsrMemFree(host_bulk_data_slot);
+            CsrMemFreeDma(host_bulk_data_slot);
         }
 #endif
 
index 403641d4df0231fd8e954ab08aa9893087a47690..8bc2d74e8d5e52e5285a135cb9bd5bc31732a20b 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -1565,7 +1565,7 @@ CsrResult unifi_bulk_rw(card_t *card, CsrUint32 handle, void *pdata,
          */
         if (card->chip_id <= SDIO_CARD_ID_UNIFI_2)
         {
-            unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
+            (void)unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
         }
 
         /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted
index fb6f04e1bbf47128bb3136b5b625bf2e36fe0227..47178afe586501e0ea273c906310b358c7d04e67 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -674,7 +674,7 @@ static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
-    buf = CsrMemAlloc(buf_size);
+    buf = CsrMemAllocDma(buf_size);
     if (buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
@@ -720,7 +720,7 @@ static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
         }
     }
 
-    CsrMemFree(buf);
+    CsrMemFreeDma(buf);
 
     if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE)
     {
index c191ea135040310cf929787fc1a498e572b4e6d6..5297f103e9eb80679b98c1a1fffe78c62925a1cd 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -293,7 +293,7 @@ done:
  *  Notes:
  * ---------------------------------------------------------------------------
  */
-static CsrInt32 get_value_from_coredump(const coredump_buffer       *dump,
+static CsrInt32 get_value_from_coredump(const coredump_buffer       *coreDump,
                                         const unifi_coredump_space_t space,
                                         const CsrUint16              offset_in_space)
 {
@@ -316,7 +316,7 @@ static CsrInt32 get_value_from_coredump(const coredump_buffer       *dump,
             {
                 /* Calculate the offset of data within the zone buffer */
                 offset_in_zone = offset_in_space - def->offset;
-                r = (CsrInt32) * (dump->zone[i] + offset_in_zone);
+                r = (CsrInt32) * (coreDump->zone[i] + offset_in_zone);
 
                 unifi_trace(NULL, UDBG6,
                             "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n",
index 4fa8f607f15cdd20090269f8f08d53fc9bfd755b..7afcd3c90fc647d4e34d7ddae408c74a306cdc25 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -69,9 +69,9 @@ enum ta_frame_identity
 #define TA_EAPOL_TYPE_OFFSET        9
 #define TA_EAPOL_TYPE_START         0x01
 
-static const CsrUint8 snap_802_2[3]   = { 0xAA, 0xAA, 0x03 };
-static const CsrUint8 oui_rfc1042[3]  = { 0x00, 0x00, 0x00 };
-static const CsrUint8 oui_8021h[3]    = { 0x00, 0x00, 0xf8 };
+#define snap_802_2                  0xAAAA0300
+#define oui_rfc1042                 0x00000000
+#define oui_8021h                   0x0000f800
 static const CsrUint8 aironet_snap[5] = { 0x00, 0x40, 0x96, 0x00, 0x00 };
 
 
@@ -100,13 +100,17 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
     CsrUint16 proto;
     CsrUint16 source_port, dest_port;
     CsrWifiMacAddress srcAddress;
+    CsrUint32 snap_hdr, oui_hdr;
 
     if (data->data_length < TA_LLC_HEADER_SIZE)
     {
         return TA_FRAME_UNKNOWN;
     }
 
-    if (CsrMemCmp(data->os_data_ptr, snap_802_2, 3))
+    snap_hdr = (((CsrUint32)data->os_data_ptr[0]) << 24) |
+               (((CsrUint32)data->os_data_ptr[1]) << 16) |
+               (((CsrUint32)data->os_data_ptr[2]) << 8);
+    if (snap_hdr != snap_802_2)
     {
         return TA_FRAME_UNKNOWN;
     }
@@ -118,8 +122,10 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
          */
     }
 
-    if (!CsrMemCmp(data->os_data_ptr + 3, oui_rfc1042, 3) ||
-        !CsrMemCmp(data->os_data_ptr + 3, oui_8021h, 3))
+    oui_hdr = (((CsrUint32)data->os_data_ptr[3]) << 24) |
+              (((CsrUint32)data->os_data_ptr[4]) << 16) |
+              (((CsrUint32)data->os_data_ptr[5]) << 8);
+    if ((oui_hdr == oui_rfc1042) || (oui_hdr == oui_8021h))
     {
         proto = (data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET] * 256) +
                 data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET + 1];
@@ -177,7 +183,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
                                 /* The DHCP should have at least a message type (request, ack, nack, etc) */
                                 if (data->data_length > TA_DHCP_MESSAGE_TYPE_OFFSET + 6)
                                 {
-                                    CsrMemCpy(srcAddress.a, saddr, 6);
+                                    UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
 
                                     if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX)
                                     {
@@ -189,7 +195,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
                                     }
 
                                     /* DHCPACK is a special indication */
-                                    if (!CsrMemCmp(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr, 6))
+                                    if (UNIFI_MAC_ADDRESS_CMP(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr) == TRUE)
                                     {
                                         if (data->os_data_ptr[TA_DHCP_MESSAGE_TYPE_OFFSET] == TA_DHCP_MESSAGE_TYPE_ACK)
                                         {
@@ -224,7 +230,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
                 if ((TA_PROTO_TYPE_WAI == proto) || (direction != CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) ||
                     (data->os_data_ptr[TA_EAPOL_TYPE_OFFSET] == TA_EAPOL_TYPE_START))
                 {
-                    CsrMemCpy(srcAddress.a, saddr, 6);
+                    UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
                     unifi_ta_indicate_protocol(card->ospriv,
                                                CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL,
                                                direction, &srcAddress);
@@ -238,7 +244,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
         {
             if (proto == TA_PROTO_TYPE_ARP)
             {
-                CsrMemCpy(srcAddress.a, saddr, 6);
+                UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
                 unifi_ta_indicate_protocol(card->ospriv,
                                            CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP,
                                            direction, &srcAddress);
@@ -253,7 +259,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
         /* detect Aironet frames */
         if (!CsrMemCmp(data->os_data_ptr + 3, aironet_snap, 5))
         {
-            CsrMemCpy(srcAddress.a, saddr, 6);
+            UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
             unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET,
                                        direction, &srcAddress);
         }
index feda2e051c217009bb755d0fe6648d2bd9db4a56..5f1c67b7c6ea1ede31364b6873ee0e674675a6cf 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -103,6 +103,17 @@ extern "C" {
 #include "csr_formatted_io.h"   /* from the synergy gsp folder */
 #include "csr_wifi_result.h"
 
+/* Utility MACROS. Note that UNIFI_MAC_ADDRESS_CMP returns TRUE on success */
+#define UNIFI_MAC_ADDRESS_COPY(dst, src) \
+    do { (dst)[0] = (src)[0]; (dst)[1] = (src)[1]; \
+         (dst)[2] = (src)[2]; (dst)[3] = (src)[3]; \
+         (dst)[4] = (src)[4]; (dst)[5] = (src)[5]; \
+    } while (0)
+
+#define UNIFI_MAC_ADDRESS_CMP(addr1, addr2) \
+    (((addr1)[0] == (addr2)[0]) && ((addr1)[1] == (addr2)[1]) && \
+     ((addr1)[2] == (addr2)[2]) && ((addr1)[3] == (addr2)[3]) && \
+     ((addr1)[4] == (addr2)[4]) && ((addr1)[5] == (addr2)[5]))
 
 /* Traffic queue ordered according to priority
  * EAPOL/Uncontrolled port Queue should be the last
@@ -635,7 +646,24 @@ void unifi_receive_event(void *ospriv,
                          CsrUint8 *sigdata, CsrUint32 siglen,
                          const bulk_data_param_t *bulkdata);
 
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+/**
+ *
+ * Used to reque the failed ma packet request back to hal queues
+ *
+ * @param ospriv the OS layer context.
+ *
+ * @param host_tag host tag for the packet to requeue.
+ *
+ * @param bulkDataDesc pointer to the bulk data.
+ *
+ * @ingroup upperedge
+ */
+CsrResult unifi_reque_ma_packet_request(void *ospriv, CsrUint32 host_tag,
+                                        CsrUint16 status,
+                                        bulk_data_desc_t *bulkDataDesc);
 
+#endif
 typedef struct
 {
     CsrUint16 free_fh_sig_queue_slots[UNIFI_NO_OF_TX_QS];
@@ -836,6 +864,8 @@ const CsrCharString* lookup_bulkcmd_name(CsrUint16 id);
 /* Function to log HIP's global debug buffer */
 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
 void unifi_debug_buf_dump(void);
+void unifi_debug_log_to_buf(const CsrCharString *fmt, ...);
+void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length);
 #endif
 
 /* Mini-coredump utility functions */
index 5d0fdcce1a9774229392253c68f4299ffb98672d..5aaec4da441b0cec65c5546c2f11d75aa33f8706 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -579,8 +579,8 @@ static CsrUint32 write_uint16(void *buf, const CsrUint32 offset, const CsrUint16
 
 static CsrUint32 write_uint32(void *buf, const CsrUint32 offset, const CsrUint32 val)
 {
-    write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff));
-    write_uint16(buf, offset + 2, (CsrUint16)(val >> 16));
+    (void)write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff));
+    (void)write_uint16(buf, offset + 2, (CsrUint16)(val >> 16));
     return sizeof(CsrUint32);
 }
 
@@ -1055,11 +1055,11 @@ void* xbv_to_patch(card_t *card, fwreadfn_t readfn,
     patch_offs += write_reset_ptdl(patch_buf, patch_offs, fwinfo, fw_id);
 
     /* Now the length is known, update the LIST.length */
-    write_uint32(patch_buf, list_len_offs,
-                 (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE);
+    (void)write_uint32(patch_buf, list_len_offs,
+                       (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE);
 
     /* Re write XBV headers just to fill in the correct file size */
-    write_xbv_header(patch_buf, 0, (patch_offs - payload_offs));
+    (void)write_xbv_header(patch_buf, 0, (patch_offs - payload_offs));
 
     unifi_trace(card->ospriv, UDBG1, "XBV:PTCH size %u, fw_id %u\n",
                 patch_offs, fw_id);
index fc5692476ddc0bcf72dde7034fadf83d5a997eb2..aa632d5dd0d4156629d12dc546412bb03259dae0 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -196,7 +196,6 @@ extern const CsrCharString *CsrWifiNmeApDownstreamPrimNames[CSR_WIFI_NME_AP_PRIM
     apCredentials  - Security credential configuration.
     maxConnections - Maximum number of stations/P2P clients allowed
     p2pGoParam     - P2P specific GO parameters.
-                     NOT USED FOR CURRENT RELEASE
     wpsEnabled     - Indicates whether WPS should be enabled or not
 
 *******************************************************************************/
index e3b56b4b44e30a1a2665fd942853c60cf38acc4e..561c2fdc37998649f7e12b19e2d00d5150d188b5 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -248,7 +248,6 @@ typedef struct
     apCredentials  - Security credential configuration.
     maxConnections - Maximum number of stations/P2P clients allowed
     p2pGoParam     - P2P specific GO parameters.
-                     NOT USED FOR CURRENT RELEASE
     wpsEnabled     - Indicates whether WPS should be enabled or not
 
 *******************************************************************************/
index f7ee3f0ec37d62e546a25c88712a182db1be644a..6ff59c01e149169cf8f8a81516b17015825dce1f 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -41,11 +41,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     {
-        CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT;
-        if (index < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) &&
-            csrwifirouter_conv_lut[index].msgType == msgType)
+        CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT;
+        if (idx < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) &&
+            csrwifirouter_conv_lut[idx].msgType == msgType)
         {
-            return &csrwifirouter_conv_lut[index];
+            return &csrwifirouter_conv_lut[idx];
         }
     }
     else
index 36403fcf97e82dc09ddb9f252303c1dd231c8fdc..32d0bb632d99d8a5c1eb63d64cf5a1d3ff36f74f 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -50,9 +50,11 @@ static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = {
     { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, CsrWifiRouterCtrlCapabilitiesReqSizeof, CsrWifiRouterCtrlCapabilitiesReqSer, CsrWifiRouterCtrlCapabilitiesReqDes, CsrWifiRouterCtrlCapabilitiesReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, CsrWifiRouterCtrlBlockAckEnableReqSizeof, CsrWifiRouterCtrlBlockAckEnableReqSer, CsrWifiRouterCtrlBlockAckEnableReqDes, CsrWifiRouterCtrlBlockAckEnableReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, CsrWifiRouterCtrlBlockAckDisableReqSizeof, CsrWifiRouterCtrlBlockAckDisableReqSer, CsrWifiRouterCtrlBlockAckDisableReqDes, CsrWifiRouterCtrlBlockAckDisableReqSerFree },
-    { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, CsrWifiRouterCtrlWapiMulticastReqSizeof, CsrWifiRouterCtrlWapiMulticastReqSer, CsrWifiRouterCtrlWapiMulticastReqDes, CsrWifiRouterCtrlWapiMulticastReqSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, CsrWifiRouterCtrlWapiRxPktReqSizeof, CsrWifiRouterCtrlWapiRxPktReqSer, CsrWifiRouterCtrlWapiRxPktReqDes, CsrWifiRouterCtrlWapiRxPktReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, CsrWifiRouterCtrlWapiMulticastFilterReqSizeof, CsrWifiRouterCtrlWapiMulticastFilterReqSer, CsrWifiRouterCtrlWapiMulticastFilterReqDes, CsrWifiRouterCtrlWapiMulticastFilterReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, CsrWifiRouterCtrlWapiUnicastFilterReqSizeof, CsrWifiRouterCtrlWapiUnicastFilterReqSer, CsrWifiRouterCtrlWapiUnicastFilterReqDes, CsrWifiRouterCtrlWapiUnicastFilterReqSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof, CsrWifiRouterCtrlWapiUnicastTxPktReqSer, CsrWifiRouterCtrlWapiUnicastTxPktReqDes, CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, CsrWifiRouterCtrlWapiFilterReqSizeof, CsrWifiRouterCtrlWapiFilterReqSer, CsrWifiRouterCtrlWapiFilterReqDes, CsrWifiRouterCtrlWapiFilterReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_HIP_IND, CsrWifiRouterCtrlHipIndSizeof, CsrWifiRouterCtrlHipIndSer, CsrWifiRouterCtrlHipIndDes, CsrWifiRouterCtrlHipIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, CsrWifiRouterCtrlPortConfigureCfmSizeof, CsrWifiRouterCtrlPortConfigureCfmSer, CsrWifiRouterCtrlPortConfigureCfmDes, CsrWifiRouterCtrlPortConfigureCfmSerFree },
@@ -81,7 +83,9 @@ static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = {
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, CsrWifiRouterCtrlBlockAckDisableCfmSizeof, CsrWifiRouterCtrlBlockAckDisableCfmSer, CsrWifiRouterCtrlBlockAckDisableCfmDes, CsrWifiRouterCtrlBlockAckDisableCfmSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, CsrWifiRouterCtrlBlockAckErrorIndSizeof, CsrWifiRouterCtrlBlockAckErrorIndSer, CsrWifiRouterCtrlBlockAckErrorIndDes, CsrWifiRouterCtrlBlockAckErrorIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, CsrWifiRouterCtrlStaInactiveIndSizeof, CsrWifiRouterCtrlStaInactiveIndSer, CsrWifiRouterCtrlStaInactiveIndDes, CsrWifiRouterCtrlStaInactiveIndSerFree },
-    { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, CsrWifiRouterCtrlWapiMulticastIndSizeof, CsrWifiRouterCtrlWapiMulticastIndSer, CsrWifiRouterCtrlWapiMulticastIndDes, CsrWifiRouterCtrlWapiMulticastIndSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, CsrWifiRouterCtrlWapiRxMicCheckIndSizeof, CsrWifiRouterCtrlWapiRxMicCheckIndSer, CsrWifiRouterCtrlWapiRxMicCheckIndDes, CsrWifiRouterCtrlWapiRxMicCheckIndSerFree },
+    { CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, CsrWifiRouterCtrlModeSetCfmSizeof, CsrWifiRouterCtrlModeSetCfmSer, CsrWifiRouterCtrlModeSetCfmDes, CsrWifiRouterCtrlModeSetCfmSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer, CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree },
 
     { 0, NULL, NULL, NULL, NULL },
 };
@@ -90,11 +94,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterCtrlConverterLookup(CsrMsgConvMsgEntry *ce, Csr
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     {
-        CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT;
-        if (index < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) &&
-            csrwifirouterctrl_conv_lut[index].msgType == msgType)
+        CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT;
+        if (idx < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) &&
+            csrwifirouterctrl_conv_lut[idx].msgType == msgType)
         {
-            return &csrwifirouterctrl_conv_lut[index];
+            return &csrwifirouterctrl_conv_lut[idx];
         }
     }
     else
index 57aa36739590e4673c01a6f4095ae33355e92151..d161fad8460883387da4d126f0ac06ee5ac2b5a7 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -70,6 +70,13 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *
             p->tclas = NULL;
             break;
         }
+        case CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ:
+        {
+            CsrWifiRouterCtrlWifiOnReq *p = (CsrWifiRouterCtrlWifiOnReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
         case CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES:
         {
             CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message;
@@ -77,15 +84,22 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *
             p->smeVersions.smeBuild = NULL;
             break;
         }
-        case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ:
+        case CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ:
         {
-            CsrWifiRouterCtrlWapiMulticastReq *p = (CsrWifiRouterCtrlWapiMulticastReq *)message;
+            CsrWifiRouterCtrlWapiRxPktReq *p = (CsrWifiRouterCtrlWapiRxPktReq *)message;
             CsrPmemFree(p->signal);
             p->signal = NULL;
             CsrPmemFree(p->data);
             p->data = NULL;
             break;
         }
+        case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ:
+        {
+            CsrWifiRouterCtrlWapiUnicastTxPktReq *p = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
         default:
             break;
index 25e327357a328a80dbe91917faf240518ae5e8c0..b6bf11d566d74d169ca0c6bb8c1359a29a613be7 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -63,15 +63,22 @@ void CsrWifiRouterCtrlFreeUpstreamMessageContents(CsrUint16 eventClass, void *me
             p->versions.routerBuild = NULL;
             break;
         }
-        case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND:
+        case CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND:
         {
-            CsrWifiRouterCtrlWapiMulticastInd *p = (CsrWifiRouterCtrlWapiMulticastInd *)message;
+            CsrWifiRouterCtrlWapiRxMicCheckInd *p = (CsrWifiRouterCtrlWapiRxMicCheckInd *)message;
             CsrPmemFree(p->signal);
             p->signal = NULL;
             CsrPmemFree(p->data);
             p->data = NULL;
             break;
         }
+        case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND:
+        {
+            CsrWifiRouterCtrlWapiUnicastTxEncryptInd *p = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
         default:
             break;
index f0ad836b00c5d9ae7ea49df14419b262144c8e71..6c7e97437570ef4f506ebaf918a6b515fc9feae1 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -658,6 +658,39 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
 #define CsrWifiRouterCtrlModeSetReqSend(src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \
     CsrWifiRouterCtrlModeSetReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlModeSetCfmSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
+    mode         -
+    status       -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__) \
+    msg__ = (CsrWifiRouterCtrlModeSetCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetCfm)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, dst__, src__); \
+    msg__->clientData = (clientData__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->mode = (mode__); \
+    msg__->status = (status__);
+
+#define CsrWifiRouterCtrlModeSetCfmSendTo(dst__, src__, clientData__, interfaceTag__, mode__, status__) \
+    { \
+        CsrWifiRouterCtrlModeSetCfm *msg__; \
+        CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlModeSetCfmSend(dst__, clientData__, interfaceTag__, mode__, status__) \
+    CsrWifiRouterCtrlModeSetCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, mode__, status__)
+
 /*******************************************************************************
 
   NAME
@@ -1594,6 +1627,35 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
 #define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \
     CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiFilterReqSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue           - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag    -
+    isWapiConnected -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__) \
+    msg__ = (CsrWifiRouterCtrlWapiFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiFilterReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->isWapiConnected = (isWapiConnected__);
+
+#define CsrWifiRouterCtrlWapiFilterReqSendTo(dst__, src__, interfaceTag__, isWapiConnected__) \
+    { \
+        CsrWifiRouterCtrlWapiFilterReq *msg__; \
+        CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__); \
+        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlWapiFilterReqSend(src__, interfaceTag__, isWapiConnected__) \
+    CsrWifiRouterCtrlWapiFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, isWapiConnected__)
+
 /*******************************************************************************
 
   NAME
@@ -1602,68 +1664,73 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   DESCRIPTION
 
   PARAMETERS
-    queue  - Message Source Task Queue (Cfm's will be sent to this Queue)
-    status -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \
     msg__ = (CsrWifiRouterCtrlWapiMulticastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastFilterReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->status = (status__);
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \
     { \
         CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \
-        CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__); \
+        CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, status__) \
-    CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__)
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, interfaceTag__, status__) \
+    CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__)
 
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastReqSend
+    CsrWifiRouterCtrlWapiRxMicCheckIndSend
 
   DESCRIPTION
 
   PARAMETERS
-    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
     signalLength -
     signal       -
     dataLength   -
     data         -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__) \
-    msg__ = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq)); \
-    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, dst__, src__); \
+#define CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiRxMicCheckInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, dst__, src__); \
+    msg__->clientData = (clientData__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->signalLength = (signalLength__); \
     msg__->signal = (signal__); \
     msg__->dataLength = (dataLength__); \
     msg__->data = (data__);
 
-#define CsrWifiRouterCtrlWapiMulticastReqSendTo(dst__, src__, signalLength__, signal__, dataLength__, data__) \
+#define CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
     { \
-        CsrWifiRouterCtrlWapiMulticastReq *msg__; \
-        CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__); \
-        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+        CsrWifiRouterCtrlWapiRxMicCheckInd *msg__; \
+        CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiMulticastReqSend(src__, signalLength__, signal__, dataLength__, data__) \
-    CsrWifiRouterCtrlWapiMulticastReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, signalLength__, signal__, dataLength__, data__)
+#define CsrWifiRouterCtrlWapiRxMicCheckIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__)
 
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastIndSend
+    CsrWifiRouterCtrlWapiRxPktReqSend
 
   DESCRIPTION
 
   PARAMETERS
-    queue        - Destination Task Queue
-    clientData   -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
     interfaceTag -
     signalLength -
     signal       -
@@ -1671,25 +1738,24 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
     data         -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
-    msg__ = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd)); \
-    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, dst__, src__); \
-    msg__->clientData = (clientData__); \
+#define CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiRxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, dst__, src__); \
     msg__->interfaceTag = (interfaceTag__); \
     msg__->signalLength = (signalLength__); \
     msg__->signal = (signal__); \
     msg__->dataLength = (dataLength__); \
     msg__->data = (data__);
 
-#define CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+#define CsrWifiRouterCtrlWapiRxPktReqSendTo(dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
     { \
-        CsrWifiRouterCtrlWapiMulticastInd *msg__; \
-        CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \
-        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+        CsrWifiRouterCtrlWapiRxPktReq *msg__; \
+        CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \
+        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiMulticastIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
-    CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__)
+#define CsrWifiRouterCtrlWapiRxPktReqSend(src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiRxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__)
 
 /*******************************************************************************
 
@@ -1699,24 +1765,90 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   DESCRIPTION
 
   PARAMETERS
-    queue  - Message Source Task Queue (Cfm's will be sent to this Queue)
-    status -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \
     msg__ = (CsrWifiRouterCtrlWapiUnicastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastFilterReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->status = (status__);
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \
     { \
         CsrWifiRouterCtrlWapiUnicastFilterReq *msg__; \
-        CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__); \
+        CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \
+        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, interfaceTag__, status__) \
+    CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, dst__, src__); \
+    msg__->clientData = (clientData__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
+
+#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \
+    { \
+        CsrWifiRouterCtrlWapiUnicastTxEncryptInd *msg__; \
+        CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(dst__, clientData__, interfaceTag__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, dataLength__, data__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxPktReqSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
+
+#define CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(dst__, src__, interfaceTag__, dataLength__, data__) \
+    { \
+        CsrWifiRouterCtrlWapiUnicastTxPktReq *msg__; \
+        CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, status__) \
-    CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__)
+#define CsrWifiRouterCtrlWapiUnicastTxPktReqSend(src__, interfaceTag__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, dataLength__, data__)
 
 /*******************************************************************************
 
@@ -1837,22 +1969,26 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   PARAMETERS
     queue      - Message Source Task Queue (Cfm's will be sent to this Queue)
     clientData -
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__) \
+#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__) \
     msg__ = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, dst__, src__); \
-    msg__->clientData = (clientData__);
+    msg__->clientData = (clientData__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
 
-#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__) \
+#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__, dataLength__, data__) \
     { \
         CsrWifiRouterCtrlWifiOnReq *msg__; \
-        CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__); \
+        CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__) \
-    CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__)
+#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__, dataLength__, data__) \
+    CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, dataLength__, data__)
 
 /*******************************************************************************
 
index 954f600b4ff42495f69390178d5828e32c4dd892..810482a8fbabdd10c0aefff9638e4888a9a60f4d 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -616,12 +616,14 @@ typedef struct
 #define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ             ((CsrWifiRouterCtrlPrim) (0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ         ((CsrWifiRouterCtrlPrim) (0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ        ((CsrWifiRouterCtrlPrim) (0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
-#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ           ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ              ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ    ((CsrWifiRouterCtrlPrim) (0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ      ((CsrWifiRouterCtrlPrim) (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ      ((CsrWifiRouterCtrlPrim) (0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ              ((CsrWifiRouterCtrlPrim) (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 
 
-#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST           (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)
+#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST           (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)
 
 /* Upstream */
 #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -654,9 +656,11 @@ typedef struct
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM        ((CsrWifiRouterCtrlPrim)(0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND          ((CsrWifiRouterCtrlPrim)(0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND             ((CsrWifiRouterCtrlPrim)(0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
-#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND           ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND        ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM                 ((CsrWifiRouterCtrlPrim)(0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND  ((CsrWifiRouterCtrlPrim)(0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
 
-#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST             (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)
+#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST             (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)
 
 #define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT             (CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)
 #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT               (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST   + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)
@@ -1032,12 +1036,16 @@ typedef struct
   MEMBERS
     common     - Common header for use with the CsrWifiFsm Module
     clientData -
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
 
 *******************************************************************************/
 typedef struct
 {
     CsrWifiFsmEvent                common;
     CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint32                      dataLength;
+    CsrUint8                      *data;
 } CsrWifiRouterCtrlWifiOnReq;
 
 /*******************************************************************************
@@ -1273,12 +1281,13 @@ typedef struct
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastReq
+    CsrWifiRouterCtrlWapiRxPktReq
 
   DESCRIPTION
 
   MEMBERS
     common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
     signalLength -
     signal       -
     dataLength   -
@@ -1288,11 +1297,12 @@ typedef struct
 typedef struct
 {
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint16       signalLength;
     CsrUint8       *signal;
     CsrUint16       dataLength;
     CsrUint8       *data;
-} CsrWifiRouterCtrlWapiMulticastReq;
+} CsrWifiRouterCtrlWapiRxPktReq;
 
 /*******************************************************************************
 
@@ -1302,13 +1312,15 @@ typedef struct
   DESCRIPTION
 
   MEMBERS
-    common - Common header for use with the CsrWifiFsm Module
-    status -
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
 typedef struct
 {
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint8        status;
 } CsrWifiRouterCtrlWapiMulticastFilterReq;
 
@@ -1320,16 +1332,60 @@ typedef struct
   DESCRIPTION
 
   MEMBERS
-    common - Common header for use with the CsrWifiFsm Module
-    status -
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
 typedef struct
 {
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint8        status;
 } CsrWifiRouterCtrlWapiUnicastFilterReq;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxPktReq
+
+  DESCRIPTION
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
+    CsrUint16       dataLength;
+    CsrUint8       *data;
+} CsrWifiRouterCtrlWapiUnicastTxPktReq;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiFilterReq
+
+  DESCRIPTION
+
+  MEMBERS
+    common          - Common header for use with the CsrWifiFsm Module
+    interfaceTag    -
+    isWapiConnected -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
+    CsrBool         isWapiConnected;
+} CsrWifiRouterCtrlWapiFilterReq;
+
 /*******************************************************************************
 
   NAME
@@ -1984,7 +2040,7 @@ typedef struct
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastInd
+    CsrWifiRouterCtrlWapiRxMicCheckInd
 
   DESCRIPTION
 
@@ -2007,7 +2063,55 @@ typedef struct
     CsrUint8                      *signal;
     CsrUint16                      dataLength;
     CsrUint8                      *data;
-} CsrWifiRouterCtrlWapiMulticastInd;
+} CsrWifiRouterCtrlWapiRxMicCheckInd;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlModeSetCfm
+
+  DESCRIPTION
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    clientData   -
+    interfaceTag -
+    mode         -
+    status       -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent                common;
+    CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint16                      interfaceTag;
+    CsrWifiRouterCtrlMode          mode;
+    CsrResult                      status;
+} CsrWifiRouterCtrlModeSetCfm;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd
+
+  DESCRIPTION
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    clientData   -
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent                common;
+    CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint16                      interfaceTag;
+    CsrUint16                      dataLength;
+    CsrUint8                      *data;
+} CsrWifiRouterCtrlWapiUnicastTxEncryptInd;
 
 
 #ifdef __cplusplus
index b7fa6a1eb521a003c751e79d3ad6fb2c67bbea94..33d92b698c59a686b786b51720639686f30a2441 100644 (file)
@@ -35,9 +35,11 @@ const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers
     /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
     /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
     /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
-    CsrWifiRouterCtrlBlockAckEnableReqHandler,        /* 0x0018 */
-    CsrWifiRouterCtrlBlockAckDisableReqHandler,       /* 0x0019 */
-    CsrWifiRouterCtrlWapiMulticastReqHandler,         /* 0x001A */
-    CsrWifiRouterCtrlWapiMulticastFilterReqHandler,   /* 0x001B */
-    CsrWifiRouterCtrlWapiUnicastFilterReqHandler,     /* 0x001C */
+    /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler,
+    /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler,
+    /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler,
+    /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler,
+    /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler,
+    /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler,
+    /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler,
 };
index 07382ef8cce4224908ef1b123b79d94914e3514f..e0ee5cf45f9eb7add7acb6de1648171028d6164b 100644 (file)
@@ -47,8 +47,10 @@ extern "C" {
     extern void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-    extern void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
 #ifdef __cplusplus
 }
 #endif
index cb1f6dc298883e8ed7e222bf46f2b7987136755d..3239c9bad18dda11866f52c0a0260d9da161fb65 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -656,6 +656,65 @@ void* CsrWifiRouterCtrlTrafficConfigReqDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
+CsrSize CsrWifiRouterCtrlWifiOnReqSizeof(void *msg)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */
+    bufferSize += 2;                     /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */
+    bufferSize += 4;                     /* CsrUint32 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
+    CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlWifiOnReqDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset);
+    CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiRouterCtrlWifiOnReqSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
 CsrSize CsrWifiRouterCtrlWifiOnResSizeof(void *msg)
 {
     CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) msg;
@@ -1055,12 +1114,13 @@ void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg)
+CsrSize CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) msg;
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) msg;
     CsrSize bufferSize = 2;
 
-    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */
+    bufferSize += 2;                       /* CsrUint16 primitive->interfaceTag */
     bufferSize += 2;                       /* CsrUint16 primitive->signalLength */
     bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */
     bufferSize += 2;                       /* CsrUint16 primitive->dataLength */
@@ -1069,11 +1129,12 @@ CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg)
 }
 
 
-CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+CsrUint8* CsrWifiRouterCtrlWapiRxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *)msg;
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *)msg;
     *len = 0;
     CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength);
     if (primitive->signalLength)
     {
@@ -1088,13 +1149,14 @@ CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void
 }
 
 
-void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length)
+void* CsrWifiRouterCtrlWapiRxPktReqDes(CsrUint8 *buffer, CsrSize length)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq));
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq));
     CsrSize offset;
     offset = 0;
 
     CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
     CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset);
     if (primitive->signalLength)
     {
@@ -1120,15 +1182,74 @@ void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *voidPrimitivePointer)
+void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *voidPrimitivePointer)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) voidPrimitivePointer;
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) voidPrimitivePointer;
     CsrPmemFree(primitive->signal);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive);
 }
 
 
+CsrSize CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */
+    bufferSize += 2;                     /* CsrUint16 primitive->interfaceTag */
+    bufferSize += 2;                     /* CsrUint16 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
 CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg)
 {
     CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) msg;
@@ -2287,9 +2408,9 @@ void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg)
+CsrSize CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) msg;
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) msg;
     CsrSize bufferSize = 2;
 
     /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */
@@ -2303,9 +2424,9 @@ CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg)
 }
 
 
-CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+CsrUint8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(CsrUint8 *ptr, CsrSize *len, void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *)msg;
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *)msg;
     *len = 0;
     CsrUint16Ser(ptr, len, primitive->common.type);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
@@ -2324,9 +2445,9 @@ CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void
 }
 
 
-void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length)
+void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(CsrUint8 *buffer, CsrSize length)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd));
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd));
     CsrSize offset;
     offset = 0;
 
@@ -2358,12 +2479,116 @@ void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *voidPrimitivePointer)
+void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *voidPrimitivePointer)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) voidPrimitivePointer;
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) voidPrimitivePointer;
     CsrPmemFree(primitive->signal);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive);
 }
 
 
+CsrSize CsrWifiRouterCtrlModeSetCfmSizeof(void *msg)
+{
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */
+    bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */
+    bufferSize += 2; /* CsrUint16 primitive->interfaceTag */
+    bufferSize += 1; /* CsrWifiRouterCtrlMode primitive->mode */
+    bufferSize += 2; /* CsrResult primitive->status */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlModeSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
+    CsrUint8Ser(ptr, len, (CsrUint8) primitive->mode);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->status);
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlModeSetCfmDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetCfm));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
+    CsrUint8Des((CsrUint8 *) &primitive->mode, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset);
+
+    return primitive;
+}
+
+
+CsrSize CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */
+    bufferSize += 2;                     /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */
+    bufferSize += 2;                     /* CsrUint16 primitive->interfaceTag */
+    bufferSize += 2;                     /* CsrUint16 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
index 5d82f8d0daa6d3f353e015940541bcf92ec601fe..3b7834dad524ece190157c9758d07625bbc74135 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -105,10 +105,10 @@ extern CsrSize CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg);
 #define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiRouterCtrlWifiOffResSerFree CsrWifiRouterCtrlPfree
 
-#define CsrWifiRouterCtrlWifiOnReqSer CsrWifiEventCsrUint16Ser
-#define CsrWifiRouterCtrlWifiOnReqDes CsrWifiEventCsrUint16Des
-#define CsrWifiRouterCtrlWifiOnReqSizeof CsrWifiEventCsrUint16Sizeof
-#define CsrWifiRouterCtrlWifiOnReqSerFree CsrWifiRouterCtrlPfree
+extern CsrUint8* CsrWifiRouterCtrlWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWifiOnReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWifiOnReqSizeof(void *msg);
+extern void CsrWifiRouterCtrlWifiOnReqSerFree(void *msg);
 
 extern CsrUint8* CsrWifiRouterCtrlWifiOnResSer(CsrUint8 *ptr, CsrSize *len, void *msg);
 extern void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize len);
@@ -155,21 +155,31 @@ extern void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize le
 extern CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg);
 #define CsrWifiRouterCtrlBlockAckDisableReqSerFree CsrWifiRouterCtrlPfree
 
-extern CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
-extern void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize len);
-extern CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg);
-extern void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *msg);
+extern CsrUint8* CsrWifiRouterCtrlWapiRxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiRxPktReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *msg);
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint8Ser
-#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint8Des
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
 #define CsrWifiRouterCtrlWapiMulticastFilterReqSerFree CsrWifiRouterCtrlPfree
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint8Ser
-#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint8Des
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
 #define CsrWifiRouterCtrlWapiUnicastFilterReqSerFree CsrWifiRouterCtrlPfree
 
+extern CsrUint8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *msg);
+
+#define CsrWifiRouterCtrlWapiFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiFilterReqSerFree CsrWifiRouterCtrlPfree
+
 extern CsrUint8* CsrWifiRouterCtrlHipIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
 extern void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg);
@@ -310,10 +320,20 @@ extern void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg);
 #define CsrWifiRouterCtrlStaInactiveIndSerFree CsrWifiRouterCtrlPfree
 
-extern CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
-extern void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize len);
-extern CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg);
-extern void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *msg);
+extern CsrUint8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *msg);
+
+extern CsrUint8* CsrWifiRouterCtrlModeSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlModeSetCfmDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlModeSetCfmSizeof(void *msg);
+#define CsrWifiRouterCtrlModeSetCfmSerFree CsrWifiRouterCtrlPfree
+
+extern CsrUint8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *msg);
 
 
 #ifdef __cplusplus
index edef7c8de409bd50b7a7cdcaa059afc1ad6fa7ae..bb9e79f95ec2ab3d869cca761cfe7eabcbfcd264 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -63,6 +63,7 @@ void CsrWifiSmeApFreeDownstreamMessageContents(CsrUint16 eventClass, void *messa
 const CsrCharString* CsrWifiSmeApAccessTypeToString(CsrWifiSmeApAccessType value);
 const CsrCharString* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value);
 const CsrCharString* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value);
+const CsrCharString* CsrWifiSmeApDirectionToString(CsrWifiSmeApDirection value);
 const CsrCharString* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value);
 const CsrCharString* CsrWifiSmeApTypeToString(CsrWifiSmeApType value);
 
@@ -79,6 +80,134 @@ const CsrCharString* CsrWifiSmeApPrimTypeToString(CsrPrim msgType);
 extern const CsrCharString *CsrWifiSmeApUpstreamPrimNames[CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT];
 extern const CsrCharString *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT];
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetReqSend
+
+  DESCRIPTION
+    This primitive used to retrieve information related to the active block
+    ack sessions
+
+  PARAMETERS
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+
+*******************************************************************************/
+#define CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__) \
+    msg__ = (CsrWifiSmeApActiveBaGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApActiveBaGetReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__);
+
+#define CsrWifiSmeApActiveBaGetReqSendTo(dst__, src__, interfaceTag__) \
+    { \
+        CsrWifiSmeApActiveBaGetReq *msg__; \
+        CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__); \
+        CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApActiveBaGetReqSend(src__, interfaceTag__) \
+    CsrWifiSmeApActiveBaGetReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetCfmSend
+
+  DESCRIPTION
+    This primitive carries the information related to the active ba sessions
+
+  PARAMETERS
+    queue            - Destination Task Queue
+    interfaceTag     -
+    status           - Reports the result of the request
+    activeBaCount    - Number of active block ack session
+    activeBaSessions - Points to a buffer containing an array of
+                       CsrWifiSmeApBaSession structures.
+
+*******************************************************************************/
+#define CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \
+    msg__ = (CsrWifiSmeApActiveBaGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApActiveBaGetCfm)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->status = (status__); \
+    msg__->activeBaCount = (activeBaCount__); \
+    msg__->activeBaSessions = (activeBaSessions__);
+
+#define CsrWifiSmeApActiveBaGetCfmSendTo(dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \
+    { \
+        CsrWifiSmeApActiveBaGetCfm *msg__; \
+        CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApActiveBaGetCfmSend(dst__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \
+    CsrWifiSmeApActiveBaGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, activeBaCount__, activeBaSessions__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteReqSend
+
+  DESCRIPTION
+    This primitive is used to delete an active block ack session
+
+  PARAMETERS
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    reason       -
+    baSession    - BA session to be deleted
+
+*******************************************************************************/
+#define CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__) \
+    msg__ = (CsrWifiSmeApBaDeleteReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApBaDeleteReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->reason = (reason__); \
+    msg__->baSession = (baSession__);
+
+#define CsrWifiSmeApBaDeleteReqSendTo(dst__, src__, interfaceTag__, reason__, baSession__) \
+    { \
+        CsrWifiSmeApBaDeleteReq *msg__; \
+        CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__); \
+        CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApBaDeleteReqSend(src__, interfaceTag__, reason__, baSession__) \
+    CsrWifiSmeApBaDeleteReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, reason__, baSession__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteCfmSend
+
+  DESCRIPTION
+    This primitive confirms the BA is deleted
+
+  PARAMETERS
+    queue        - Destination Task Queue
+    interfaceTag -
+    status       - Reports the result of the request
+    baSession    - deleted BA session
+
+*******************************************************************************/
+#define CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__) \
+    msg__ = (CsrWifiSmeApBaDeleteCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApBaDeleteCfm)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_CFM, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->status = (status__); \
+    msg__->baSession = (baSession__);
+
+#define CsrWifiSmeApBaDeleteCfmSendTo(dst__, src__, interfaceTag__, status__, baSession__) \
+    { \
+        CsrWifiSmeApBaDeleteCfm *msg__; \
+        CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApBaDeleteCfmSend(dst__, interfaceTag__, status__, baSession__) \
+    CsrWifiSmeApBaDeleteCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, baSession__)
+
 /*******************************************************************************
 
   NAME
index 3310cd287fdc500a26db954dcfba1ec8c65a6127..41594395c6512cb65703422a622cde1bb56de0b5 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -95,6 +95,23 @@ typedef CsrUint8 CsrWifiSmeApAuthType;
 #define CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL      ((CsrWifiSmeApAuthType) 0x01)
 #define CSR_WIFI_SME_AP_AUTH_TYPE_WEP           ((CsrWifiSmeApAuthType) 0x02)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApDirection
+
+  DESCRIPTION
+    Definition of Direction
+
+ VALUES
+    CSR_WIFI_AP_DIRECTION_RECEIPIENT - Receipient
+    CSR_WIFI_AP_DIRECTION_ORIGINATOR - Originator
+
+*******************************************************************************/
+typedef CsrUint8 CsrWifiSmeApDirection;
+#define CSR_WIFI_AP_DIRECTION_RECEIPIENT   ((CsrWifiSmeApDirection) 0x00)
+#define CSR_WIFI_AP_DIRECTION_ORIGINATOR   ((CsrWifiSmeApDirection) 0x01)
+
 /*******************************************************************************
 
   NAME
@@ -302,6 +319,28 @@ typedef struct
     CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities;
 } CsrWifiSmeApAuthPers;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaSession
+
+  DESCRIPTION
+
+  MEMBERS
+    peerMacAddress - Indicates MAC address of the peer station
+    tid            - Specifies the TID of the MSDUs for which this Block Ack has
+                     been set up. Range: 0-15
+    direction      - Specifies if the AP is the originator or the recipient of
+                     the data stream that uses the Block Ack.
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiMacAddress     peerMacAddress;
+    CsrUint8              tid;
+    CsrWifiSmeApDirection direction;
+} CsrWifiSmeApBaSession;
+
 /*******************************************************************************
 
   NAME
@@ -456,9 +495,11 @@ typedef struct
 #define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ              ((CsrWifiSmeApPrim) (0x0004 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_STA_DISCONNECT_REQ                ((CsrWifiSmeApPrim) (0x0005 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ             ((CsrWifiSmeApPrim) (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ                 ((CsrWifiSmeApPrim) (0x0007 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_BA_DELETE_REQ                     ((CsrWifiSmeApPrim) (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
 
 
-#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST           (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)
+#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST           (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)
 
 /* Upstream */
 #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -473,8 +514,10 @@ typedef struct
 #define CSR_WIFI_SME_AP_STA_DISCONNECT_CFM                ((CsrWifiSmeApPrim)(0x0007 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM             ((CsrWifiSmeApPrim)(0x0008 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_ERROR_IND                         ((CsrWifiSmeApPrim)(0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM                 ((CsrWifiSmeApPrim)(0x000A + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_BA_DELETE_CFM                     ((CsrWifiSmeApPrim)(0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
 
-#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST             (0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)
+#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST             (0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)
 
 #define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT             (CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)
 #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT               (CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST   + 1 - CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)
@@ -655,6 +698,49 @@ typedef struct
     CsrWifiSmeWpsConfig wpsConfig;
 } CsrWifiSmeApWpsConfigurationReq;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetReq
+
+  DESCRIPTION
+    This primitive used to retrieve information related to the active block
+    ack sessions
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
+} CsrWifiSmeApActiveBaGetReq;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteReq
+
+  DESCRIPTION
+    This primitive is used to delete an active block ack session
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    reason       -
+    baSession    - BA session to be deleted
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent           common;
+    CsrUint16                 interfaceTag;
+    CsrWifiSmeIEEE80211Reason reason;
+    CsrWifiSmeApBaSession     baSession;
+} CsrWifiSmeApBaDeleteReq;
+
 /*******************************************************************************
 
   NAME
@@ -895,6 +981,55 @@ typedef struct
     CsrResult        status;
 } CsrWifiSmeApErrorInd;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetCfm
+
+  DESCRIPTION
+    This primitive carries the information related to the active ba sessions
+
+  MEMBERS
+    common           - Common header for use with the CsrWifiFsm Module
+    interfaceTag     -
+    status           - Reports the result of the request
+    activeBaCount    - Number of active block ack session
+    activeBaSessions - Points to a buffer containing an array of
+                       CsrWifiSmeApBaSession structures.
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent        common;
+    CsrUint16              interfaceTag;
+    CsrResult              status;
+    CsrUint16              activeBaCount;
+    CsrWifiSmeApBaSession *activeBaSessions;
+} CsrWifiSmeApActiveBaGetCfm;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteCfm
+
+  DESCRIPTION
+    This primitive confirms the BA is deleted
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       - Reports the result of the request
+    baSession    - deleted BA session
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent       common;
+    CsrUint16             interfaceTag;
+    CsrResult             status;
+    CsrWifiSmeApBaSession baSession;
+} CsrWifiSmeApBaDeleteCfm;
+
 
 #ifdef __cplusplus
 }
index bafd1b411a9051099f0860ddeb056473e172809d..6897a77faf271fdc5ce04ae1c955945b8348f2e3 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -79,6 +79,7 @@ static CsrMsgConvMsgEntry csrwifisme_conv_lut[] = {
     { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, CsrWifiSmeSmeCommonConfigSetReqSizeof, CsrWifiSmeSmeCommonConfigSetReqSer, CsrWifiSmeSmeCommonConfigSetReqDes, CsrWifiSmeSmeCommonConfigSetReqSerFree },
     { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree },
     { CSR_WIFI_SME_WPS_CONFIGURATION_REQ, CsrWifiSmeWpsConfigurationReqSizeof, CsrWifiSmeWpsConfigurationReqSer, CsrWifiSmeWpsConfigurationReqDes, CsrWifiSmeWpsConfigurationReqSerFree },
+    { CSR_WIFI_SME_SET_REQ, CsrWifiSmeSetReqSizeof, CsrWifiSmeSetReqSer, CsrWifiSmeSetReqDes, CsrWifiSmeSetReqSerFree },
     { CSR_WIFI_SME_ACTIVATE_CFM, CsrWifiSmeActivateCfmSizeof, CsrWifiSmeActivateCfmSer, CsrWifiSmeActivateCfmDes, CsrWifiSmeActivateCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, CsrWifiSmeAdhocConfigSetCfmSizeof, CsrWifiSmeAdhocConfigSetCfmSer, CsrWifiSmeAdhocConfigSetCfmDes, CsrWifiSmeAdhocConfigSetCfmSerFree },
@@ -159,11 +160,11 @@ CsrMsgConvMsgEntry* CsrWifiSmeConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint16
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     {
-        CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT;
-        if (index < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) &&
-            csrwifisme_conv_lut[index].msgType == msgType)
+        CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT;
+        if (idx < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) &&
+            csrwifisme_conv_lut[idx].msgType == msgType)
         {
-            return &csrwifisme_conv_lut[index];
+            return &csrwifisme_conv_lut[idx];
         }
     }
     else
index 8637eb7baafe4d0dc7c8cb9512c77feb3cf07556..fb895dec7688efa8824981fbce79d585deb866c4 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
index c8e66be899cd6ff68e2b3c97739fd65ad7e31c74..93e75e5ace18a6ae286ab016ff4fcb6ccb4689ba 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -172,6 +172,13 @@ void CsrWifiSmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message
             p->wpsConfig.secondaryDeviceType = NULL;
             break;
         }
+        case CSR_WIFI_SME_SET_REQ:
+        {
+            CsrWifiSmeSetReq *p = (CsrWifiSmeSetReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
         default:
             break;
index 16053fb6ed436bd2fd9ba9c1b026cbb999f6e222..67dcb48448c32338f646c9b6a416d3ed0c2d549e 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -3442,6 +3442,39 @@ extern const CsrCharString *CsrWifiSmeDownstreamPrimNames[CSR_WIFI_SME_PRIM_DOWN
 #define CsrWifiSmeScanResultsGetCfmSend(dst__, status__, scanResultsCount__, scanResults__) \
     CsrWifiSmeScanResultsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanResultsCount__, scanResults__)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeSetReqSend
+
+  DESCRIPTION
+    Used to pass custom data to the SME. Format is the same as 802.11 Info
+    Elements => | Id | Length | Data
+    1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01
+    (0x00|0x01)"
+
+  PARAMETERS
+    queue      - Message Source Task Queue (Cfm's will be sent to this Queue)
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
+
+*******************************************************************************/
+#define CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__) \
+    msg__ = (CsrWifiSmeSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSetReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SET_REQ, dst__, src__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
+
+#define CsrWifiSmeSetReqSendTo(dst__, src__, dataLength__, data__) \
+    { \
+        CsrWifiSmeSetReq *msg__; \
+        CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__); \
+        CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeSetReqSend(src__, dataLength__, data__) \
+    CsrWifiSmeSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, dataLength__, data__)
+
 /*******************************************************************************
 
   NAME
index 4bc8520dbd0c586c627a0b9ccd194b518217e9df..8ffa50a6c04850b2df1b343affb84e475283462e 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -1434,7 +1434,7 @@ typedef CsrUint8 CsrWifiSmeWepCredentialType;
     CsrWifiSmeWmmMode
 
   DESCRIPTION
-    Defines bits for wmmModeMask: enable/disable WMM features.
+    Defines bits for CsrWifiSmeWmmModeMask: enable/disable WMM features.
 
  VALUES
     CSR_WIFI_SME_WMM_MODE_DISABLED   - Disables the WMM features.
@@ -2410,40 +2410,6 @@ typedef struct
     CsrUint16 maxPassiveChannelTimeTu;
 } CsrWifiSmeScanConfigData;
 
-/*******************************************************************************
-
-  NAME
-    CsrWifiSmeStaConfig
-
-  DESCRIPTION
-    Station configuration options in the SME
-
-  MEMBERS
-    connectionQualityRssiChangeTrigger - Sets the difference of RSSI
-                                         measurements which triggers reports
-                                         from the Firmware
-    connectionQualitySnrChangeTrigger  - Sets the difference of SNR measurements
-                                         which triggers reports from the
-                                         Firmware
-    wmmModeMask                        - Mask containing one or more values from
-                                         CsrWifiSmeWmmMode
-    ifIndex                            - Indicates the band of frequencies used
-    allowUnicastUseGroupCipher         - If TRUE, it allows to use groupwise
-                                         keys if no pairwise key is specified
-    enableOpportunisticKeyCaching      - If TRUE, enables the Opportunistic Key
-                                         Caching feature
-
-*******************************************************************************/
-typedef struct
-{
-    CsrUint8          connectionQualityRssiChangeTrigger;
-    CsrUint8          connectionQualitySnrChangeTrigger;
-    CsrUint8          wmmModeMask;
-    CsrWifiSmeRadioIF ifIndex;
-    CsrBool           allowUnicastUseGroupCipher;
-    CsrBool           enableOpportunisticKeyCaching;
-} CsrWifiSmeStaConfig;
-
 /*******************************************************************************
 
   NAME
@@ -3197,6 +3163,40 @@ typedef struct
     } deviceInfo;
 } CsrWifiSmeScanResult;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeStaConfig
+
+  DESCRIPTION
+    Station configuration options in the SME
+
+  MEMBERS
+    connectionQualityRssiChangeTrigger - Sets the difference of RSSI
+                                         measurements which triggers reports
+                                         from the Firmware
+    connectionQualitySnrChangeTrigger  - Sets the difference of SNR measurements
+                                         which triggers reports from the
+                                         Firmware
+    wmmModeMask                        - Mask containing one or more values from
+                                         CsrWifiSmeWmmMode
+    ifIndex                            - Indicates the band of frequencies used
+    allowUnicastUseGroupCipher         - If TRUE, it allows to use groupwise
+                                         keys if no pairwise key is specified
+    enableOpportunisticKeyCaching      - If TRUE, enables the Opportunistic Key
+                                         Caching feature
+
+*******************************************************************************/
+typedef struct
+{
+    CsrUint8              connectionQualityRssiChangeTrigger;
+    CsrUint8              connectionQualitySnrChangeTrigger;
+    CsrWifiSmeWmmModeMask wmmModeMask;
+    CsrWifiSmeRadioIF     ifIndex;
+    CsrBool               allowUnicastUseGroupCipher;
+    CsrBool               enableOpportunisticKeyCaching;
+} CsrWifiSmeStaConfig;
+
 /*******************************************************************************
 
   NAME
@@ -3393,9 +3393,10 @@ typedef struct
 #define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ            ((CsrWifiSmePrim) (0x0034 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ         ((CsrWifiSmePrim) (0x0035 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_WPS_CONFIGURATION_REQ                ((CsrWifiSmePrim) (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_SME_SET_REQ                              ((CsrWifiSmePrim) (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
 
 
-#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST           (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)
+#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST           (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)
 
 /* Upstream */
 #define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -4809,6 +4810,30 @@ typedef struct
     CsrWifiSmeWpsConfig wpsConfig;
 } CsrWifiSmeWpsConfigurationReq;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeSetReq
+
+  DESCRIPTION
+    Used to pass custom data to the SME. Format is the same as 802.11 Info
+    Elements => | Id | Length | Data
+    1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01
+    (0x00|0x01)"
+
+  MEMBERS
+    common     - Common header for use with the CsrWifiFsm Module
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint32       dataLength;
+    CsrUint8       *data;
+} CsrWifiSmeSetReq;
+
 /*******************************************************************************
 
   NAME
index 489c378186bdd0fab558191961bd87845f960b8f..5c1bc31f2dd687942be14e17e421d900de28336c 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -1356,7 +1356,7 @@ CsrSize CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg)
     bufferSize += 2; /* CsrUint16 primitive->interfaceTag */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */
-    bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */
+    bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */
     bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */
@@ -1898,6 +1898,62 @@ void CsrWifiSmeWpsConfigurationReqSerFree(void *voidPrimitivePointer)
 }
 
 
+CsrSize CsrWifiSmeSetReqSizeof(void *msg)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */
+    bufferSize += 4;                     /* CsrUint32 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiSmeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiSmeSetReqDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSetReq));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiSmeSetReqSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
 CsrSize CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg)
 {
     CsrSize bufferSize = 2;
@@ -5085,7 +5141,7 @@ CsrSize CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg)
     bufferSize += 2; /* CsrResult primitive->status */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */
-    bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */
+    bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */
     bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */
index c2d7fd68c4ae998676abd04276d5a88be11aaf69..0080bf43a6c403633a6f3ca5fecf8f80825fe42a 100644 (file)
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
 
             Refer to LICENSE.txt included with this source for details
@@ -300,6 +300,11 @@ extern void* CsrWifiSmeWpsConfigurationReqDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiSmeWpsConfigurationReqSizeof(void *msg);
 extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg);
 
+extern CsrUint8* CsrWifiSmeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiSmeSetReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiSmeSetReqSizeof(void *msg);
+extern void CsrWifiSmeSetReqSerFree(void *msg);
+
 #define CsrWifiSmeActivateCfmSer CsrWifiEventCsrUint16Ser
 #define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des
 #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof
index 4545fb2b063b14a4b1bd26f8f33f19e3d1008321..fbe86301816cd198c3d2cb7f74f589bb6933811f 100644 (file)
 int buswidth = 0;               /* 0 means use default, values 1,4 */
 int sdio_clock = 50000;         /* kHz */
 int unifi_debug = 0;
-/*
- * fw_init prevents f/w initialisation on error.
- * Unless necessary, avoid usage in the CSR_SME_EMB build because it prevents
- * UniFi initialisation after getting out of suspend and also leaves
- * UniFi powered when the module unloads.
- */
+/* fw_init prevents f/w initialisation on error. */
 int fw_init[MAX_UNIFI_DEVS] = {-1, -1};
 int use_5g = 0;
 int led_mask = 0;               /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */
@@ -67,6 +62,12 @@ int sdio_byte_mode = 0;        /* 0 for block mode + padding, 1 for byte mode */
 int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS;
 int run_bh_once = -1;          /* Set for scheduled interrupt mode, -1 = default */
 int bh_priority = -1;
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+#define UNIFI_LOG_HIP_SIGNALS_FILTER_SIGNAL     (1 << 0)
+#define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA   (1 << 1)
+#define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP  (1 << 2)
+int log_hip_signals = 0;
+#endif
 
 MODULE_DESCRIPTION("CSR UniFi (SDIO)");
 
@@ -87,6 +88,9 @@ module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR);
 module_param(coredump_max, int, S_IRUGO|S_IWUSR);
 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
 module_param(bh_priority, int, S_IRUGO|S_IWUSR);
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+module_param(log_hip_signals, int, S_IRUGO|S_IWUSR);
+#endif
 
 MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode");
 MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)");
@@ -105,6 +109,10 @@ MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO");
 MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate");
 MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts");
 MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority");
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging");
+#endif
+
 
 /* Callback for event logging to UDI clients */
 static void udi_log_event(ul_client_t *client,
@@ -193,6 +201,54 @@ trace_putest_cmdid(unifi_putest_command_t putest_cmd)
     }
  }
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+int uf_register_hip_offline_debug(unifi_priv_t *priv)
+{
+    ul_client_t *udi_cli;
+    int i;
+
+    udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event);
+    if (udi_cli == NULL) {
+        /* Too many clients already using this device */
+        unifi_error(priv, "Too many UDI clients already open\n");
+        return -ENOSPC;
+    }
+    unifi_trace(priv, UDBG1, "Offline HIP client is registered\n");
+
+    down(&priv->udi_logging_mutex);
+    udi_cli->event_hook = udi_log_event;
+    unifi_set_udi_hook(priv->card, logging_handler);
+    /* Log all signals by default */
+    for (i = 0; i < SIG_FILTER_SIZE; i++) {
+        udi_cli->signal_filter[i] = 0xFFFF;
+    }
+    priv->logging_client = udi_cli;
+    up(&priv->udi_logging_mutex);
+
+    return 0;
+}
+
+int uf_unregister_hip_offline_debug(unifi_priv_t *priv)
+{
+    ul_client_t *udi_cli = priv->logging_client;
+    if (udi_cli == NULL)
+    {
+        unifi_error(priv, "Unknown HIP client unregister request\n");
+        return -ERANGE;
+    }
+
+    unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n");
+
+    down(&priv->udi_logging_mutex);
+    priv->logging_client = NULL;
+    udi_cli->event_hook = NULL;
+    up(&priv->udi_logging_mutex);
+
+    ul_deregister_client(udi_cli);
+
+    return 0;
+}
+#endif
 
 
 /*
@@ -312,7 +368,6 @@ unifi_open(struct inode *inode, struct file *file)
 } /* unifi_open() */
 
 
-
 static int
 unifi_release(struct inode *inode, struct file *filp)
 {
@@ -354,6 +409,15 @@ unifi_release(struct inode *inode, struct file *filp)
         }
 
         uf_sme_deinit(priv);
+
+       /* It is possible that a blocking SME request was made from another process
+        * which did not get read by the SME before the WifiOffReq.
+        * So check for a pending request which will go unanswered and cancel
+        * the wait for event. As only one blocking request can be in progress at
+        * a time, up to one event should be completed.
+        */
+       uf_sme_cancel_request(priv, 0);
+
 #endif /* CSR_SME_USERSPACE */
     } else {
 
@@ -979,6 +1043,14 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
             goto out;
         }
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+        if (log_hip_signals) {
+            unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n");
+            r = -EFAULT;
+            goto out;
+        }
+#endif
+
         down(&priv->udi_logging_mutex);
         if (int_param) {
             pcli->event_hook = udi_log_event;
@@ -1264,6 +1336,11 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
             unifi_info(priv, "UniFi ready\n");
 
+#ifdef ANDROID_BUILD
+            /* Release the wakelock */
+            unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n");
+            wake_unlock(&unifi_sdio_wake_lock);
+#endif
 #ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */
             {
                 struct net_device *dev = priv->netdev[interfaceTag];
@@ -1720,6 +1797,40 @@ udi_log_event(ul_client_t *pcli,
         return;
     }
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    /* When HIP offline signal logging is enabled, omnicli cannot run */
+    if (log_hip_signals)
+    {
+        /* Add timestamp */
+        if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP)
+        {
+            int timestamp = jiffies_to_msecs(jiffies);
+            unifi_debug_log_to_buf("T:");
+            unifi_debug_log_to_buf("%04X%04X ", *(((CsrUint16*)&timestamp) + 1),
+                                   *(CsrUint16*)&timestamp);
+        }
+
+        /* Add signal */
+        unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ",
+                               dir ? "T" : "F",
+                               *(CsrUint16*)signal,
+                               *(CsrUint16*)(signal + 2),
+                               *(CsrUint16*)(signal + 4));
+        unifi_debug_hex_to_buf(signal + 6, signal_len - 6);
+
+        /* Add bulk data (assume 1 bulk data per signal) */
+        if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) &&
+            (bulkdata->d[0].data_length > 0))
+        {
+            unifi_debug_log_to_buf("\nD:");
+            unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length);
+        }
+        unifi_debug_log_to_buf("\n");
+
+        return;
+    }
+#endif
+
 #ifdef CSR_NATIVE_LINUX
     uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir);
 #endif
@@ -1950,7 +2061,7 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id)
     priv->unifiudi_cdev.owner = THIS_MODULE;
 
     devno = MKDEV(MAJOR(unifi_first_devno),
-                  MINOR(unifi_first_devno) + (bus_id * MAX_UNIFI_DEVS) + 1);
+                  MINOR(unifi_first_devno) + (bus_id * 2) + 1);
     r = cdev_add(&priv->unifiudi_cdev, devno, 1);
     if (r) {
         device_destroy(unifi_class, priv->unifi_cdev.dev);
@@ -2081,7 +2192,9 @@ unifi_load(void)
 #endif
     printk("CSR native no WEXT support\n");
 #endif
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+    printk("Split patch support\n");
+#endif
     printk("Kernel %d.%d.%d\n",
            ((LINUX_VERSION_CODE) >> 16) & 0xff,
            ((LINUX_VERSION_CODE) >> 8) & 0xff,
index 4ac3c89baa5d8c1c58a4a6dd11ca1c7c4e8d142e..03da0d5c247aaae38f685d9ef53931fe6aac4eca 100644 (file)
@@ -296,7 +296,18 @@ uf_run_unifihelper(unifi_priv_t *priv)
 #endif
 } /* uf_run_unifihelper() */
 
+#ifdef CSR_WIFI_SPLIT_PATCH
+static CsrBool is_ap_mode(unifi_priv_t *priv)
+{
+    if (priv == NULL || priv->interfacePriv[0] == NULL)
+    {
+        return FALSE;
+    }
 
+    /* Test for mode requiring AP patch */
+    return(CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode));
+}
+#endif
 
 /*
  * ---------------------------------------------------------------------------
@@ -334,8 +345,13 @@ int uf_request_firmware_files(unifi_priv_t *priv, int is_fw)
     if (is_fw == UNIFI_FW_STA) {
         /* Free kernel buffer and reload */
         uf_release_firmware(priv, &priv->fw_sta);
+#ifdef CSR_WIFI_SPLIT_PATCH
         scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
-                  postfix, "sta.xbv");
+                  postfix, (is_ap_mode(priv) ? "ap.xbv" : "staonly.xbv") );
+#else
+        scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
+                  postfix, "sta.xbv" );
+#endif
         r = request_firmware(&fw_entry, fw_name, priv->unifi_device);
         if (r == 0) {
             priv->fw_sta.dl_data = fw_entry->data;
index fbf1b2099cc9e120ab12959bf6b24afbb99dc56a..f489ade7f1ba8628255c743c585539b12585101f 100644 (file)
@@ -407,6 +407,13 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
     INIT_WORK(&priv->rx_work_struct, rx_wq_handler);
 #endif
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    if (log_hip_signals)
+    {
+        uf_register_hip_offline_debug(priv);
+    }
+#endif
+
     /* Initialise the SME related threads and parameters */
     r = uf_sme_init(priv);
     if (r) {
@@ -431,6 +438,12 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
     return priv;
 
 failed4:
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+if (log_hip_signals)
+{
+    uf_unregister_hip_offline_debug(priv);
+}
+#endif
 #ifdef CSR_WIFI_RX_PATH_SPLIT
     flush_workqueue(priv->rx_workqueue);
     destroy_workqueue(priv->rx_workqueue);
@@ -547,6 +560,13 @@ cleanup_unifi_sdio(unifi_priv_t *priv)
     priv->smepriv = NULL;
 #endif
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    if (log_hip_signals)
+    {
+        uf_unregister_hip_offline_debug(priv);
+    }
+#endif
+
     /* Free any packets left in the Rx queues */
     for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
     {
index b0335f6fff4e8a0a2262c62fd351ae868ecdcb34..cf19f1116c2e6d0633a4b9af255edc341af41972 100644 (file)
@@ -402,9 +402,14 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
 
     priv->sta_wmm_capabilities = 0;
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_SUPPORT_SME))
     priv->wapi_multicast_filter = 0;
     priv->wapi_unicast_filter = 0;
     priv->wapi_unicast_queued_pkt_filter = 0;
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    priv->isWapiConnection = FALSE;
+#endif
+#endif
 
     /* Enable all queues by default */
     interfacePriv->queueEnabled[0] = 1;
@@ -450,7 +455,15 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
     spin_lock_init(&priv->send_signal_lock);
 
     spin_lock_init(&priv->m4_lock);
-    spin_lock_init(&priv->ba_lock);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+    sema_init(&priv->ba_mutex, 1);
+#else
+    init_MUTEX(&priv->ba_mutex);
+#endif
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    spin_lock_init(&priv->wapi_lock);
+#endif
 
 #ifdef CSR_SUPPORT_SME
     spin_lock_init(&priv->staRecord_lock);
@@ -472,6 +485,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
 
     /* Create m4 buffering work structure */
     INIT_WORK(&interfacePriv->send_m4_ready_task, uf_send_m4_ready_wq);
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Create work structure to buffer the WAPI data packets to be sent to SME for encryption */
+    INIT_WORK(&interfacePriv->send_pkt_to_encrypt, uf_send_pkt_to_encrypt);
+#endif
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
@@ -504,6 +522,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
     }
 #endif /* CSR_SUPPORT_WEXT */
 
+#ifdef CSR_WIFI_SPLIT_PATCH
+    /* set it to some invalid value */
+    priv->pending_mode_set.common.destination = 0xaaaa;
+#endif
+
     return priv;
 } /* uf_alloc_netdevice() */
 
@@ -655,6 +678,19 @@ uf_free_netdevice(unifi_priv_t *priv)
     }
     spin_unlock_irqrestore(&priv->m4_lock, flags);
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Free any bulkdata buffers allocated for M4 caching */
+    spin_lock_irqsave(&priv->wapi_lock, flags);
+    for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
+        netInterface_priv_t *interfacePriv = priv->interfacePriv[i];
+        if (interfacePriv->wapi_unicast_bulk_data.data_length > 0) {
+            unifi_trace(priv, UDBG5, "uf_free_netdevice: free WAPI PKT bulk data %d\n", i);
+            unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
+        }
+    }
+    spin_unlock_irqrestore(&priv->wapi_lock, flags);
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
 #ifdef CONFIG_NET_SCHED
     /* Unregister the qdisc operations */
@@ -1556,7 +1592,7 @@ int prepare_and_add_macheader(unifi_priv_t *priv, struct sk_buff *skb, struct sk
     /* IF Qos Data or Qos Null Data then set QosControl field */
     if ((priority != CSR_CONTENTION) && (macHeaderLengthInBytes >= QOS_CONTROL_HEADER_SIZE)) {
 
-        if (priority >= 7) {
+        if (priority > 7) {
             unifi_trace(priv, UDBG1, "data packets priority is more than 7, priority = %x\n", priority);
             qc |= 7;
         } else {
@@ -1628,6 +1664,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
     CSR_TRANSMISSION_CONTROL transmissionControl = CSR_NO_CONFIRM_REQUIRED;
     CsrInt8 protection;
     netInterface_priv_t *interfacePriv = NULL;
+    CSR_RATE TransmitRate = (CSR_RATE)0;
 
     unifi_trace(priv, UDBG5, "entering send_ma_pkt_request\n");
 
@@ -1780,6 +1817,63 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
             return 0;
         }
 #endif
+    }/*EAPOL or WAI packet*/
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && \
+        (priv->wapi_unicast_filter) && \
+        (proto != ETH_P_PAE) && \
+        (proto != ETH_P_WAI) && \
+        (skb->len > 0))
+    {
+        CSR_SIGNAL signal;
+        CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest;
+        netInterface_priv_t *netpriv = (netInterface_priv_t *)netdev_priv(priv->netdev[interfaceTag]);
+
+        unifi_trace(priv, UDBG4, "send_ma_pkt_request() - WAPI unicast data packet when USKID = 1 \n");
+
+        /* initialize signal to zero */
+        memset(&signal, 0, sizeof(CSR_SIGNAL));
+        /* Frame MA_PACKET request */
+        signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID;
+        signal.SignalPrimitiveHeader.ReceiverProcessId = 0;
+        signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id;
+
+        /* Fill the MA-PACKET.req */
+        req->TransmissionControl = 0;
+        req->Priority = priority;
+        unifi_trace(priv, UDBG3, "Tx Frame with Priority: %x\n", req->Priority);
+        req->TransmitRate = (CSR_RATE) 0; /* rate selected by firmware */
+        req->HostTag = 0xffffffff;        /* Ask for a new HostTag */
+        /* RA address matching with address 1 of Mac header */
+        memcpy(req->Ra.x, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN);
+
+        /* Store the M4-PACKET.req for later */
+        spin_lock(&priv->wapi_lock);
+        interfacePriv->wapi_unicast_ma_pkt_sig = signal;
+        interfacePriv->wapi_unicast_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length;
+        interfacePriv->wapi_unicast_bulk_data.data_length = bulkdata.d[0].data_length;
+        interfacePriv->wapi_unicast_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr;
+        interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr;
+        spin_unlock(&priv->wapi_lock);
+
+        /* Signal the workqueue to call CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend().
+         * It cannot be called directly from the tx path because it
+         * does a non-atomic kmalloc via the framework's CsrPmemAlloc().
+         */
+        queue_work(priv->unifi_workqueue, &netpriv->send_pkt_to_encrypt);
+
+        return 0;
+    }
+#endif
+
+    if(priv->cmanrTestMode)
+    {
+        TransmitRate = priv->cmanrTestModeTransmitRate;
+        unifi_trace(priv, UDBG2, "send_ma_pkt_request: cmanrTestModeTransmitRate = %d TransmitRate=%d\n",
+                    priv->cmanrTestModeTransmitRate,
+                    TransmitRate
+                   );
     }
 
     /* Send UniFi msg */
@@ -1789,7 +1883,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
                                  0xffffffff,  /* Ask for a new HostTag */
                                  interfaceTag,
                                  transmissionControl,
-                                 (CSR_RATE)0,
+                                 TransmitRate,
                                  priority,
                                  priv->netdev_client->sender_id,
                                  &bulkdata);
@@ -1900,8 +1994,22 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif /* CONFIG_NET_SCHED */
 
     if (result == NETDEV_TX_OK) {
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+       /* Don't update the tx stats when the pkt is to be sent for sw encryption*/
+       if (!((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) &&
+              (priv->wapi_unicast_filter == 1)))
+        {
+            dev->trans_start = jiffies;
+            /* Should really count tx stats in the UNITDATA.status signal but
+             * that doesn't have the length.
+             */
+            interfacePriv->stats.tx_packets++;
+            /* count only the packet payload */
+            interfacePriv->stats.tx_bytes += skb->len;
 
-        dev->trans_start = jiffies;
+        }
+#else
+       dev->trans_start = jiffies;
 
         /*
          * Should really count tx stats in the UNITDATA.status signal but
@@ -1910,7 +2018,7 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
         interfacePriv->stats.tx_packets++;
         /* count only the packet payload */
         interfacePriv->stats.tx_bytes += skb->len;
-
+#endif
     } else if (result < 0) {
 
         /* Failed to send: fh queue was full, and the skb was discarded.
@@ -2118,6 +2226,13 @@ indicate_rx_skb(unifi_priv_t *priv, CsrUint16 ifTag, CsrUint8* dst_a, CsrUint8*
     }
 
 
+    if(priv->cmanrTestMode)
+    {
+        const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication;
+        priv->cmanrTestModeTransmitRate = pkt_ind->ReceivedRate;
+        unifi_trace(priv, UDBG2, "indicate_rx_skb: cmanrTestModeTransmitRate=%d\n", priv->cmanrTestModeTransmitRate);
+    }
+
     /* Pass SKB up the stack */
 #ifdef CSR_WIFI_USE_NETIF_RX
         netif_rx(skb);
@@ -2780,36 +2895,17 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
             if((dataFrameType == QOS_DATA) || (dataFrameType == QOS_DATA_NULL)){
 
                 /*
-                  QoS control field is offset from frame control by 2 (frame control)
-                  + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN
-                */
+                 * QoS control field is offset from frame control by 2 (frame control)
+                 * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN
+                 */
                 if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){
                     qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 30);
                 }
                 else{
                     qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 24);
                 }
-
-                if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){
-                    CSR_PRIORITY priority;
-                    unifi_TrafficQueue priority_q;
-                    priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK);
-                    priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority);
-                    if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED)
-                               ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){
-                        unsigned long lock_flags;
-                        spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-                        srcStaInfo->uapsdSuspended = TRUE;
-                        spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
-                        unifi_trace(priv, UDBG3, "%s: qos Trigger Frame received while DTIM Active for staid: 0x%x\n",__FUNCTION__,srcStaInfo->aid);
-                    }
-                }
-                else{
-
-
-                    unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl);
-                    uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag);
-                }
+                unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl);
+                uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag);
             }
         }
     }
@@ -2829,7 +2925,7 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
             ba_addr = bssid;
         }
 
-        spin_lock(&priv->ba_lock);
+        down(&priv->ba_mutex);
         for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
             ba_session = interfacePriv->ba_session_rx[ba_session_idx];
             if (ba_session){
@@ -2842,14 +2938,14 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
                         frame_desc.active = TRUE;
                         unifi_trace(priv, UDBG6, "%s: calling process_ba_frame (session=%d)\n", __FUNCTION__, ba_session_idx);
                         process_ba_frame(priv, interfacePriv, ba_session, &frame_desc);
-                        spin_unlock(&priv->ba_lock);
+                        up(&priv->ba_mutex);
                         process_ba_complete(priv, interfacePriv);
                         break;
                 }
             }
         }
         if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){
-            spin_unlock(&priv->ba_lock);
+            up(&priv->ba_mutex);
             unifi_trace(priv, UDBG6, "%s: calling process_amsdu()", __FUNCTION__);
             process_amsdu(priv, signal, bulkdata);
         }
@@ -2865,7 +2961,7 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
      * And also this code here takes care that timeout check is made for all
      * the receive indications
      */
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){
         ba_session_rx_struct *ba_session;
         ba_session = interfacePriv->ba_session_rx[i];
@@ -2873,8 +2969,8 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
                 check_ba_frame_age_timeout(priv, interfacePriv, ba_session);
             }
     }
+    up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
-    spin_unlock(&priv->ba_lock);
 
     func_exit();
 }
@@ -3879,7 +3975,7 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
     }
     sn = pkt_err_ind->SequenceNumber;
 
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     /* To find the right ba_session loop through the BA sessions, compare MAC address and tID */
     for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
         ba_session = interfacePriv->ba_session_rx[ba_session_idx];
@@ -3894,7 +3990,7 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
         }
     }
 
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
     func_exit();
 }
index 6dfce4226750662ae7d08bcaf5fc934b6a0aa093..f5a9352ce78496b2932f6e4f266dc9d91c9dae60 100644 (file)
@@ -204,12 +204,10 @@ extern int unifi_debug;
             (_s)[DEBUG_BUFFER_SIZE - 1] = 0;            \
         }                                               \
     } while (0)
-#endif /* UNIFI_DEBUG */
 
 void
 unifi_error(void* ospriv, const char *fmt, ...)
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
@@ -230,13 +228,11 @@ unifi_error(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
 
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 
 void
 unifi_warning(void* ospriv, const char *fmt, ...)
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
@@ -259,14 +255,12 @@ unifi_warning(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
 
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 
 
 void
 unifi_notice(void* ospriv, const char *fmt, ...)
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
@@ -289,14 +283,12 @@ unifi_notice(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
 
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 
 
 void
 unifi_info(void* ospriv, const char *fmt, ...)
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
@@ -319,14 +311,12 @@ unifi_info(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
 
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 
 /* debugging */
 void
 unifi_trace(void* ospriv, int level, const char *fmt, ...)
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
@@ -351,9 +341,23 @@ unifi_trace(void* ospriv, int level, const char *fmt, ...)
 
         printk("%s", s);
     }
-#endif /* UNIFI_DEBUG */
 }
 
+#else
+
+void
+unifi_error_nop(void* ospriv, const char *fmt, ...)
+{
+}
+
+void
+unifi_trace_nop(void* ospriv, int level, const char *fmt, ...)
+{
+}
+
+#endif /* UNIFI_DEBUG */
+
+
 /*
  * ---------------------------------------------------------------------------
  *
index 1b2c7c299a6cf38002044a3747d6f8fb05c61f59..22614e7e8f7ebba44c78d9fbf5ba392281891b56 100644 (file)
@@ -180,8 +180,9 @@ int unifi_putest_gp_read16(unifi_priv_t *priv, unsigned char *arg)
                     "unifi_putest_gp_read16: Failed to get the params\n");
         return -EFAULT;
     }
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult);
@@ -240,8 +241,9 @@ int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg)
     }
 
     unifi_trace(priv, UDBG2, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params.addr, gp_w16_params.data);
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult);
@@ -265,7 +267,7 @@ int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg)
     unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed);
 
     CsrSdioClaim(priv->sdio);
-    csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed);
+    csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed * 1000);
     CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
@@ -304,7 +306,9 @@ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg)
 
     /* Application may have stopped the XAPs, but they are needed for reset */
     if (already_in_test) {
+        CsrSdioClaim(priv->sdio);
         csrResult = unifi_start_processors(priv->card);
+        CsrSdioRelease(priv->sdio);
         if (csrResult != CSR_RESULT_SUCCESS) {
             unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
         }
@@ -317,8 +321,9 @@ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg)
             unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult);
         }
     }
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_init(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_start: failed to init UniFi\n");
@@ -335,7 +340,9 @@ int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg)
     CsrResult csrResult;
 
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
     }
@@ -428,7 +435,9 @@ int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg)
     }
 
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
     }
@@ -436,7 +445,9 @@ int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg)
     /* Download the f/w. On UF6xxx this will cause the f/w file to convert
      * into patch format and download via the ROM boot loader
      */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_download(priv->card, 0x0c00);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_dl_fw: failed to download the f/w\n");
@@ -504,7 +515,9 @@ int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg)
     priv->fw_sta.dl_len = fw_length;
 
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
     }
@@ -512,7 +525,9 @@ int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg)
     /* Download the f/w. On UF6xxx this will cause the f/w file to convert
      * into patch format and download via the ROM boot loader
      */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_download(priv->card, 0x0c00);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_dl_fw_buff: failed to download the f/w\n");
@@ -581,7 +596,9 @@ int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg)
             }
 
             /* Card software reset */
+            CsrSdioClaim(priv->sdio);
             r = unifi_card_hard_reset(priv->card);
+            CsrSdioRelease(priv->sdio);
             if (r != CSR_RESULT_SUCCESS) {
                 unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r);
             }
@@ -599,7 +616,9 @@ int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg)
     /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at
      * Raw SDIO deinit, to resume them.
      */
+    CsrSdioClaim(priv->sdio);
     r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH);
+    CsrSdioRelease(priv->sdio);
     if (r != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to stop processors\n");
     }
@@ -646,7 +665,9 @@ int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg)
         return -ENOMEM;
     }
 
+    CsrSdioClaim(priv->sdio);
     r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length);
+    CsrSdioRelease(priv->sdio);
     if (r != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "cmd52r_block: unifi_readn failed\n");
         return -EIO;
index f61fdb130e61c4dc61b818d83aded152f203d87a..b6a7d6f513b0d0d7cf223843b729714ed852d18c 100644 (file)
@@ -17,6 +17,7 @@
  */
 #include <linux/kmod.h>
 #include <linux/init.h>
+#include <linux/suspend.h>
 #include "csr_wifi_hip_unifi.h"
 #include "unifi_priv.h"
 
 /* The function driver context, i.e the UniFi Driver */
 static CsrSdioFunctionDriver *sdio_func_drv;
 
+#ifdef CONFIG_PM
+static int uf_sdio_emb_power_event(struct notifier_block *this, unsigned long event, void *ptr);
+#endif
 
+/* The Android wakelock is here for completeness. Typically the MMC driver is used
+ * instead of sdioemb, but sdioemb may be used for CSPI.
+ */
+#ifdef ANDROID_BUILD
+struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */
+#endif
 
 /* sdioemb driver uses POSIX error codes */
 static CsrResult
@@ -501,6 +511,131 @@ uf_glue_sdio_int_handler(struct sdioemb_dev *fdev)
     }
 }
 
+#ifdef CONFIG_PM
+
+/*
+ * Power Management notifier
+ */
+struct uf_sdio_emb_pm_notifier
+{
+    struct list_head list;
+
+    CsrSdioFunction *sdio_ctx;
+    struct notifier_block pm_notifier;
+};
+
+/* PM notifier list head */
+static struct uf_sdio_emb_pm_notifier uf_sdio_emb_pm_notifiers = {
+    .sdio_ctx = NULL,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_emb_register_pm_notifier
+ * uf_sdio_emb_unregister_pm_notifier
+ *
+ *      Register/unregister for power management events. A list is used to
+ *     allow multiple card instances to be supported.
+ *
+ *  Arguments:
+ *      sdio_ctx - CSR SDIO context to associate PM notifier to
+ *
+ *  Returns:
+ *      Register function returns NULL on error
+ * ---------------------------------------------------------------------------
+ */
+static struct uf_sdio_emb_pm_notifier *
+uf_sdio_emb_register_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    /* Allocate notifier context for this card instance */
+    struct uf_sdio_emb_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_emb_pm_notifier), GFP_KERNEL);
+
+    if (notifier_ctx)
+    {
+        notifier_ctx->sdio_ctx = sdio_ctx;
+        notifier_ctx->pm_notifier.notifier_call = uf_sdio_emb_power_event;
+
+        list_add(&notifier_ctx->list, &uf_sdio_emb_pm_notifiers.list);
+
+        if (register_pm_notifier(&notifier_ctx->pm_notifier)) {
+            printk(KERN_ERR "unifi: register_pm_notifier failed\n");
+        }
+    }
+
+    return notifier_ctx;
+}
+
+static void
+uf_sdio_emb_unregister_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    struct uf_sdio_emb_pm_notifier *notifier_ctx;
+    struct list_head *node, *q;
+
+    list_for_each_safe(node, q, &uf_sdio_emb_pm_notifiers.list) {
+        notifier_ctx = list_entry(node, struct uf_sdio_emb_pm_notifier, list);
+
+        /* If it matches, unregister and free the notifier context */
+        if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx)
+        {
+            if (unregister_pm_notifier(&notifier_ctx->pm_notifier)) {
+                printk(KERN_ERR "unifi: unregister_pm_notifier failed\n");
+            }
+
+            /* Remove from list */
+            notifier_ctx->sdio_ctx = NULL;
+            list_del(node);
+            kfree(notifier_ctx);
+        }
+    }
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_emb_power_event
+ *
+ *      Handler for power management events.
+ *
+ *      We need to handle suspend/resume events while the userspace is unsuspended
+ *      to allow the SME to run its suspend/resume state machines.
+ *
+ *  Arguments:
+ *      event   event ID
+ *
+ *  Returns:
+ *      Status of the event handling
+ * ---------------------------------------------------------------------------
+ */
+static int
+uf_sdio_emb_power_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+    struct uf_sdio_emb_pm_notifier *notifier_ctx = container_of(this,
+                                                                struct uf_sdio_emb_pm_notifier,
+                                                                pm_notifier);
+
+    /* Call the CSR SDIO function driver's suspend/resume method
+     * while the userspace is unsuspended.
+     */
+    switch (event) {
+        case PM_POST_HIBERNATION:
+        case PM_POST_SUSPEND:
+            printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->resume) {
+                sdio_func_drv->resume(notifier_ctx->sdio_ctx);
+            }
+            break;
+
+        case PM_HIBERNATION_PREPARE:
+        case PM_SUSPEND_PREPARE:
+            printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->suspend) {
+                sdio_func_drv->suspend(notifier_ctx->sdio_ctx);
+            }
+            break;
+    }
+    return NOTIFY_DONE;
+}
+
+#endif /* CONFIG_PM */
 
 /*
  * ---------------------------------------------------------------------------
@@ -550,16 +685,30 @@ uf_glue_sdio_probe(struct sdioemb_dev *fdev)
     unifi_trace(NULL, UDBG1, "Setting SDIO bus clock to %d kHz\n", sdio_clock);
     sdioemb_set_max_bus_freq(fdev, 1000 * sdio_clock);
 
+#ifdef CONFIG_PM
+    /* Register to get PM events */
+    if (uf_sdio_emb_register_pm_notifier(sdio_ctx) == NULL) {
+        unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__);
+    }
+#endif
+
     /* Call the main UniFi driver inserted handler */
     if (sdio_func_drv && sdio_func_drv->inserted) {
         uf_add_os_device(fdev->slot_id, fdev->os_device);
         sdio_func_drv->inserted(sdio_ctx);
     }
 
+#ifdef ANDROID_BUILD
+    /* Take the wakelock */
+    unifi_trace(NULL, UDBG1, "emb probe: take wake lock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
+
     return 0;
 } /* uf_glue_sdio_probe() */
 
 
+
 /*
  * ---------------------------------------------------------------------------
  *  uf_sdio_remove
@@ -585,6 +734,11 @@ uf_sdio_remove(struct sdioemb_dev *fdev)
         sdio_func_drv->removed(sdio_ctx);
     }
 
+#ifdef CONFIG_PM
+    /* Unregister for PM events */
+    uf_sdio_emb_unregister_pm_notifier(sdio_ctx);
+#endif
+
     kfree(sdio_ctx);
 
 } /* uf_sdio_remove */
@@ -606,14 +760,7 @@ uf_sdio_remove(struct sdioemb_dev *fdev)
 static void
 uf_glue_sdio_suspend(struct sdioemb_dev *fdev)
 {
-    CsrSdioFunction *sdio_ctx = fdev->drv_data;
-
-    unifi_trace(NULL, UDBG3, "Suspending...\n");
-
-    /* Pass event to UniFi Driver. */
-    if (sdio_func_drv && sdio_func_drv->suspend) {
-        sdio_func_drv->suspend(sdio_ctx);
-    }
+    unifi_info(NULL, "Suspending...\n");
 
 } /* uf_glue_sdio_suspend() */
 
@@ -634,14 +781,13 @@ uf_glue_sdio_suspend(struct sdioemb_dev *fdev)
 static void
 uf_glue_sdio_resume(struct sdioemb_dev *fdev)
 {
-    CsrSdioFunction *sdio_ctx = fdev->drv_data;
+    unifi_info(NULL, "Resuming...\n");
 
-    unifi_trace(NULL, UDBG3, "Resuming...\n");
+#ifdef ANDROID_BUILD
+    unifi_trace(NULL, UDBG1, "emb resume: take wakelock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
 
-    /* Pass event to UniFi Driver. */
-    if (sdio_func_drv && sdio_func_drv->resume) {
-        sdio_func_drv->resume(sdio_ctx);
-    }
 } /* uf_glue_sdio_resume() */
 
 
@@ -708,6 +854,15 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
     /* Save the registered driver description */
     sdio_func_drv = sdio_drv;
 
+#ifdef CONFIG_PM
+    /* Initialise PM notifier list */
+    INIT_LIST_HEAD(&uf_sdio_emb_pm_notifiers.list);
+#endif
+
+#ifdef ANDROID_BUILD
+    wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work");
+#endif
+
     /* Register ourself with sdioemb */
     r = sdioemb_driver_register(&unifi_sdioemb);
     if (r) {
@@ -724,6 +879,10 @@ CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 {
     sdioemb_driver_unregister(&unifi_sdioemb);
 
+#ifdef ANDROID_BUILD
+    wake_lock_destroy(&unifi_sdio_wake_lock);
+#endif
+
     sdio_func_drv = NULL;
 
     CsrPmemFree(unifi_sdioemb.id_table);
index e4f2d0d82fbf99ddc0820cce8648af81fc189c82..6892c2e281bc4873f208c9a7bc82ce16c72f0ad9 100644 (file)
@@ -47,6 +47,12 @@ void unifi_suspend(void *ospriv)
     unifi_priv_t *priv = ospriv;
     int interfaceTag=0;
 
+    /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */
+    priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
+
+    unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d",
+                priv->wol_suspend, enable_wol );
+
     /* Stop network traffic. */
     /* need to stop all the netdevices*/
     for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++)
@@ -54,11 +60,20 @@ void unifi_suspend(void *ospriv)
         netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
         if (interfacePriv->netdev_registered == 1)
         {
-            netif_carrier_off(priv->netdev[interfaceTag]);
+            if( priv->wol_suspend ) {
+                unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off");
+            } else {
+                unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off");
+                netif_carrier_off(priv->netdev[interfaceTag]);
+            }
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]);
         }
     }
+
+    unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME");
+
     sme_sys_suspend(priv);
+
 } /* unifi_suspend() */
 
 
@@ -76,12 +91,44 @@ void unifi_suspend(void *ospriv)
 void unifi_resume(void *ospriv)
 {
     unifi_priv_t *priv = ospriv;
+    int interfaceTag=0;
     int r;
+    int wol = priv->wol_suspend;
+
+    unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol);
 
+    /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */
     r = sme_sys_resume(priv);
     if (r) {
         unifi_error(priv, "Failed to resume UniFi\n");
     }
 
+    /* Resume the network interfaces. For the cold resume case, this will
+     * happen upon reconnection.
+     */
+    if (wol) {
+        unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier");
+
+        /* need to start all the netdevices*/
+        for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) {
+            netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
+
+            unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n",
+                   interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode);
+
+            if (interfacePriv->netdev_registered == 1)
+            {
+                netif_carrier_on(priv->netdev[interfaceTag]);
+                UF_NETIF_TX_START_ALL_QUEUES(priv->netdev[interfaceTag]);
+            }
+        }
+
+        /* Kick the BH thread (with reason=host) to poll for data that may have
+         * arrived during a powered suspend. This caters for the case where the SME
+         * doesn't interact with the chip (e.g install autonomous scans) during resume.
+         */
+        unifi_send_signal(priv->card, NULL, 0, NULL);
+    }
+
 } /* unifi_resume() */
 
index c8508341597addcb470cfdbd056990ec2217a66e..24be0872b0aa68ba36282b4fc334c82d3e7e7e58 100644 (file)
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio.h>
+#include <linux/suspend.h>
 
 #include "unifi_priv.h"
 
+#ifdef ANDROID_BUILD
+struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */
+#endif
 
 static CsrSdioFunctionDriver *sdio_func_drv;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr);
+#endif
+
 /*
  * We need to keep track of the power on/off because we can not call
  * mmc_power_restore_host() when the card is already powered.
  * Even then, we need to patch the MMC driver to add a power_restore handler
- * in the mmc_sdio_ops structure. If the MMC driver is not patched,
- * mmc_power_save_host() and mmc_power_restore_host() are no-ops.
+ * in the mmc_sdio_ops structure. If the MMC driver before 2.6.37 is not patched,
+ * mmc_power_save_host() and mmc_power_restore_host() are no-ops in the kernel,
+ * returning immediately (at least on x86).
  */
 static int card_is_powered = 1;
 #endif /* 2.6.32 */
@@ -312,17 +321,28 @@ csr_sdio_enable_hs(struct mmc_card *card)
     int ret;
     u8 speed;
 
-    if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+    if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) {
+        /* We've asked for HS clock rates, but controller doesn't
+         * claim to support it. We should limit the clock
+         * to 25MHz via module parameter.
+         */
+        printk(KERN_INFO "unifi: request HS but not MMC_CAP_SD_HIGHSPEED");
         return 0;
+    }
 
     if (!card->cccr.high_speed)
         return 0;
 
+#if 1
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     if (ret)
         return ret;
 
     speed |= SDIO_SPEED_EHS;
+#else
+    /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */
+    speed = SDIO_SPEED_EHS | SDIO_SPEED_SHS;
+#endif
 
     ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
     if (ret)
@@ -346,12 +366,16 @@ csr_sdio_disable_hs(struct mmc_card *card)
 
     if (!card->cccr.high_speed)
         return 0;
-
+#if 1
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     if (ret)
         return ret;
 
     speed &= ~SDIO_SPEED_EHS;
+#else
+    /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */
+    speed = SDIO_SPEED_SHS; /* clear SDIO_SPEED_EHS */
+#endif
 
     ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
     if (ret)
@@ -460,6 +484,7 @@ CsrSdioInterruptEnable(CsrSdioFunction *function)
 
     func_exit();
     if (err) {
+        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
     }
 #endif
@@ -486,6 +511,7 @@ CsrSdioInterruptDisable(CsrSdioFunction *function)
 
     func_exit();
     if (err) {
+        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
     }
 #endif
@@ -772,6 +798,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func)
     if (!sdio_ctx) {
         return;
     }
+
 #ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
     /*
      * Normally, we are not allowed to do any SDIO commands here.
@@ -785,7 +812,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func)
     r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL);
 #endif
     if (r) {
-        printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts\n");
+        printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts %d\n", r);
     }
 #endif
 
@@ -824,6 +851,8 @@ csr_sdio_linux_remove_irq(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int r;
 
+    unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n");
+
     sdio_claim_host(func);
     r = sdio_release_irq(func);
     sdio_release_host(func);
@@ -853,6 +882,8 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int r;
 
+    unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n");
+
     /* Register our interrupt handle */
     sdio_claim_host(func);
     r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
@@ -866,7 +897,133 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function)
     return r;
 } /* csr_sdio_linux_install_irq() */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+
+/*
+ * Power Management notifier
+ */
+struct uf_sdio_mmc_pm_notifier
+{
+    struct list_head list;
+
+    CsrSdioFunction *sdio_ctx;
+    struct notifier_block pm_notifier;
+};
+
+/* PM notifier list head */
+static struct uf_sdio_mmc_pm_notifier uf_sdio_mmc_pm_notifiers = {
+    .sdio_ctx = NULL,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_mmc_register_pm_notifier
+ * uf_sdio_mmc_unregister_pm_notifier
+ *
+ *      Register/unregister for power management events. A list is used to
+ *      allow multiple card instances to be supported.
+ *
+ *  Arguments:
+ *      sdio_ctx - CSR SDIO context to associate PM notifier to
+ *
+ *  Returns:
+ *      Register function returns NULL on error
+ * ---------------------------------------------------------------------------
+ */
+static struct uf_sdio_mmc_pm_notifier *
+uf_sdio_mmc_register_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    /* Allocate notifier context for this card instance */
+    struct uf_sdio_mmc_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_mmc_pm_notifier), GFP_KERNEL);
+
+    if (notifier_ctx)
+    {
+        notifier_ctx->sdio_ctx = sdio_ctx;
+        notifier_ctx->pm_notifier.notifier_call = uf_sdio_mmc_power_event;
+
+        list_add(&notifier_ctx->list, &uf_sdio_mmc_pm_notifiers.list);
+
+        if (register_pm_notifier(&notifier_ctx->pm_notifier)) {
+            printk(KERN_ERR "unifi: register_pm_notifier failed\n");
+        }
+    }
+
+    return notifier_ctx;
+}
+
+static void
+uf_sdio_mmc_unregister_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    struct uf_sdio_mmc_pm_notifier *notifier_ctx;
+    struct list_head *node, *q;
+
+    list_for_each_safe(node, q, &uf_sdio_mmc_pm_notifiers.list) {
+        notifier_ctx = list_entry(node, struct uf_sdio_mmc_pm_notifier, list);
+
+        /* If it matches, unregister and free the notifier context */
+        if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx)
+        {
+            if (unregister_pm_notifier(&notifier_ctx->pm_notifier)) {
+                printk(KERN_ERR "unifi: unregister_pm_notifier failed\n");
+            }
+
+            /* Remove from list */
+            notifier_ctx->sdio_ctx = NULL;
+            list_del(node);
+            kfree(notifier_ctx);
+        }
+    }
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_mmc_power_event
+ *
+ *      Handler for power management events.
+ *
+ *      We need to handle suspend/resume events while the userspace is unsuspended
+ *      to allow the SME to run its suspend/resume state machines.
+ *
+ *  Arguments:
+ *      event   event ID
+ *
+ *  Returns:
+ *      Status of the event handling
+ * ---------------------------------------------------------------------------
+ */
+static int
+uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+    struct uf_sdio_mmc_pm_notifier *notifier_ctx = container_of(this,
+                                                                struct uf_sdio_mmc_pm_notifier,
+                                                                pm_notifier);
+
+    /* Call the CSR SDIO function driver's suspend/resume method
+     * while the userspace is unsuspended.
+     */
+    switch (event) {
+        case PM_POST_HIBERNATION:
+        case PM_POST_SUSPEND:
+            printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->resume) {
+                sdio_func_drv->resume(notifier_ctx->sdio_ctx);
+            }
+            break;
+
+        case PM_HIBERNATION_PREPARE:
+        case PM_SUSPEND_PREPARE:
+            printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->suspend) {
+                sdio_func_drv->suspend(notifier_ctx->sdio_ctx);
+            }
+            break;
+    }
+    return NOTIFY_DONE;
+}
 
+#endif /* CONFIG_PM */
+#endif /* 2.6.32 */
 
 /*
  * ---------------------------------------------------------------------------
@@ -925,6 +1082,10 @@ uf_glue_sdio_probe(struct sdio_func *func,
         sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE;
     }
 
+    if (func->card->host->caps & MMC_CAP_SD_HIGHSPEED) {
+        unifi_trace(NULL, UDBG1, "MMC_CAP_SD_HIGHSPEED is available\n");
+    }
+
 #ifdef MMC_QUIRK_LENIENT_FN0
     func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 #endif
@@ -932,6 +1093,15 @@ uf_glue_sdio_probe(struct sdio_func *func,
     /* Pass context to the SDIO driver */
     sdio_set_drvdata(func, sdio_ctx);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+    /* Register to get PM events */
+    if (uf_sdio_mmc_register_pm_notifier(sdio_ctx) == NULL) {
+        unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__);
+    }
+#endif
+#endif
+
     /* Register this device with the SDIO function driver */
     /* Call the main UniFi driver inserted handler */
     if (sdio_func_drv && sdio_func_drv->inserted) {
@@ -942,6 +1112,12 @@ uf_glue_sdio_probe(struct sdio_func *func,
     /* We have finished, so release the SDIO driver */
     sdio_release_host(func);
 
+#ifdef ANDROID_BUILD
+    /* Take the wakelock */
+    unifi_trace(NULL, UDBG1, "probe: take wake lock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
+
     func_exit();
     return 0;
 } /* uf_glue_sdio_probe() */
@@ -980,6 +1156,13 @@ uf_glue_sdio_remove(struct sdio_func *func)
         sdio_func_drv->removed(sdio_ctx);
     }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+    /* Unregister for PM events */
+    uf_sdio_mmc_unregister_pm_notifier(sdio_ctx);
+#endif
+#endif
+
     kfree(sdio_ctx);
 
     func_exit();
@@ -1006,7 +1189,7 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
  * ---------------------------------------------------------------------------
  *  uf_glue_sdio_suspend
  *
- *      Card suspend callback.
+ *      Card suspend callback. The userspace will already be suspended.
  *
  * Arguments:
  *      dev            The struct device owned by the MMC driver
@@ -1018,23 +1201,9 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
 static int
 uf_glue_sdio_suspend(struct device *dev)
 {
-    struct sdio_func *func;
-    CsrSdioFunction *sdio_ctx;
-
     func_enter();
 
-    func = dev_to_sdio_func(dev);
-    WARN_ON(!func);
-
-    sdio_ctx = sdio_get_drvdata(func);
-    WARN_ON(!sdio_ctx);
-
-    unifi_trace(NULL, UDBG1, "System Suspend...\n");
-
-    /* Clean up the SDIO function driver */
-    if (sdio_func_drv && sdio_func_drv->suspend) {
-        sdio_func_drv->suspend(sdio_ctx);
-    }
+    unifi_trace(NULL, UDBG1, "uf_glue_sdio_suspend");
 
     func_exit();
     return 0;
@@ -1045,7 +1214,7 @@ uf_glue_sdio_suspend(struct device *dev)
  * ---------------------------------------------------------------------------
  *  uf_glue_sdio_resume
  *
- *      Card resume callback.
+ *      Card resume callback. The userspace will still be suspended.
  *
  * Arguments:
  *      dev            The struct device owned by the MMC driver
@@ -1057,23 +1226,14 @@ uf_glue_sdio_suspend(struct device *dev)
 static int
 uf_glue_sdio_resume(struct device *dev)
 {
-    struct sdio_func *func;
-    CsrSdioFunction *sdio_ctx;
-
     func_enter();
 
-    func = dev_to_sdio_func(dev);
-    WARN_ON(!func);
-
-    sdio_ctx = sdio_get_drvdata(func);
-    WARN_ON(!sdio_ctx);
+    unifi_trace(NULL, UDBG1, "uf_glue_sdio_resume");
 
-    unifi_trace(NULL, UDBG1, "System Resume...\n");
-
-    /* Clean up the SDIO function driver */
-    if (sdio_func_drv && sdio_func_drv->resume) {
-        sdio_func_drv->resume(sdio_ctx);
-    }
+#ifdef ANDROID_BUILD
+    unifi_trace(NULL, UDBG1, "resume: take wakelock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
 
     func_exit();
     return 0;
@@ -1133,6 +1293,10 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
         return CSR_SDIO_RESULT_INVALID_VALUE;
     }
 
+#ifdef ANDROID_BUILD
+    wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work");
+#endif
+
     /* Save the registered driver description */
     /*
      * FIXME:
@@ -1141,6 +1305,13 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
      */
     sdio_func_drv = sdio_drv;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+    /* Initialise PM notifier list */
+    INIT_LIST_HEAD(&uf_sdio_mmc_pm_notifiers.list);
+#endif
+#endif
+
     /* Register ourself with mmc_core */
     r = sdio_register_driver(&unifi_driver);
     if (r) {
@@ -1157,6 +1328,10 @@ void
 CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 {
     printk(KERN_INFO "UniFi: unregister from MMC sdio\n");
+
+#ifdef ANDROID_BUILD
+    wake_lock_destroy(&unifi_sdio_wake_lock);
+#endif
     sdio_unregister_driver(&unifi_driver);
 
     sdio_func_drv = NULL;
index f30eda950ad6029f92e282569038a2c99a78800f..8461baca2deac48509c9ae77b23a6dcd1987f627 100644 (file)
@@ -92,11 +92,15 @@ sme_init_request(unifi_priv_t *priv)
         return -EIO;
     }
 
+    unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n");
+
     /* Grab the SME semaphore until the reply comes, or timeout */
     if (down_interruptible(&priv->sme_sem)) {
         unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n");
         return -EIO;
     }
+    unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n");
+
     priv->sme_reply.request_status = SME_REQUEST_PENDING;
 
     return 0;
@@ -118,6 +122,10 @@ uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *
                     (func ? func : ""), priv->sme_reply.request_status);
         return;
     }
+    unifi_trace(priv, UDBG5,
+                "sme_complete_request: completed %s (s:%d)\n",
+                (func ? func : ""), priv->sme_reply.request_status);
+
     priv->sme_reply.request_status = SME_REQUEST_RECEIVED;
     priv->sme_reply.reply_status = reply_status;
 
@@ -127,23 +135,66 @@ uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *
 }
 
 
+void
+uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status)
+{
+    /* Check for a blocking SME request in progress, and cancel the wait.
+     * This should be used when the character device is closed.
+     */
+
+    if (priv == NULL) {
+        unifi_error(priv, "sme_cancel_request: Invalid priv\n");
+        return;
+    }
+
+    /* If no request is pending, nothing to wake up */
+    if (priv->sme_reply.request_status != SME_REQUEST_PENDING) {
+        unifi_trace(priv, UDBG5,
+                    "sme_cancel_request: no request was pending (s:%d)\n",
+                    priv->sme_reply.request_status);
+        /* Nothing to do */
+        return;
+    }
+    unifi_trace(priv, UDBG5,
+                "sme_cancel_request: request cancelled (s:%d)\n",
+                priv->sme_reply.request_status);
+
+    /* Wake up the wait with an error status */
+    priv->sme_reply.request_status = SME_REQUEST_CANCELLED;
+    priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */
+
+    wake_up_interruptible(&priv->sme_request_wq);
+
+    return;
+}
+
+
 static int
 _sme_wait_for_reply(unifi_priv_t *priv,
         unsigned long timeout, const char *func)
 {
     long r;
 
-    unifi_trace(priv, UDBG5, "sme_wait_for_reply: sleep\n");
+    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : "");
     r = wait_event_interruptible_timeout(priv->sme_request_wq,
                                          (priv->sme_reply.request_status != SME_REQUEST_PENDING),
                                          msecs_to_jiffies(timeout));
-    unifi_trace(priv, UDBG5, "sme_wait_for_reply: awake\n");
+    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r);
 
     if (r == -ERESTARTSYS) {
         /* The thread was killed */
+        unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n");
         up(&priv->sme_sem);
         return r;
     }
+    if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) {
+        unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n",
+                    (func ? func : ""), priv->sme_reply.request_status, timeout, r);
+
+        /* Release the SME semaphore that was downed in sme_init_request() */
+        up(&priv->sme_sem);
+        return -EIO; /* fail the ioctl */
+    }
     if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) {
         unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n",
                      (func ? func : ""), priv->sme_reply.request_status, timeout);
@@ -156,6 +207,9 @@ _sme_wait_for_reply(unifi_priv_t *priv,
         return -ETIMEDOUT;
     }
 
+    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n",
+                func ? func : "", r);
+
     /* Release the SME semaphore that was downed in sme_init_request() */
     up(&priv->sme_sem);
 
@@ -1289,22 +1343,20 @@ int sme_sys_suspend(unifi_priv_t *priv)
         return -EIO;
     }
 
-    /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */
-    priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
-
-    /* Suspend the SME, which will cause it to power down UniFi */
+    /* Suspend the SME, which MAY cause it to power down UniFi */
     CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
     if (r) {
         /* No reply - forcibly power down in case the request wasn't processed */
         unifi_notice(priv,
                      "suspend: SME did not reply %s, ",
-                     priv->ptest_mode ? "leave powered" : "power off UniFi anyway\n");
+                     (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n");
 
         /* Leave power on for production test, though */
         if (!priv->ptest_mode) {
             /* Put UniFi to deep sleep, in case we can not power it off */
             CsrSdioClaim(priv->sdio);
+            unifi_trace(priv, UDBG1, "Force deep sleep");
             csrResult = unifi_force_low_power_mode(priv->card);
 
             /* For WOL, the UniFi must stay powered */
@@ -1319,13 +1371,40 @@ int sme_sys_suspend(unifi_priv_t *priv)
     if (priv->wol_suspend) {
         unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n");
 
-        /* For PIO WOL, disable SDIO interrupt to enable PIO mode in the f/w */
-        if (enable_wol == UNIFI_WOL_PIO) {
-            unifi_trace(priv, UDBG1, "Remove IRQ to enable PIO WOL\n");
-            if (csr_sdio_linux_remove_irq(priv->sdio)) {
-                unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
+        /* Remove the IRQ, which also disables the card SDIO interrupt.
+         * Disabling the card SDIO interrupt enables the PIO WOL source.
+         * Removal of the of the handler ensures that in both SDIO and PIO cases
+         * the card interrupt only wakes the host. The card will be polled
+         * after resume to handle any pending data.
+         */
+        if (csr_sdio_linux_remove_irq(priv->sdio)) {
+            unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
+        }
+
+        if (enable_wol == UNIFI_WOL_SDIO) {
+            /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt,
+             * it must be left enabled to wake-on-SDIO.
+             */
+            unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n");
+
+            CsrSdioClaim(priv->sdio);
+            csrResult = CsrSdioInterruptEnable(priv->sdio);
+            CsrSdioRelease(priv->sdio);
+
+            if (csrResult != CSR_RESULT_SUCCESS) {
+                unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult);
             }
+        } else {
+            unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n");
         }
+
+        /* Prevent the BH thread from running during the suspend.
+         * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause
+         * the BH thread to be re-enabled and reinstall the ISR.
+         */
+        priv->bh_thread.block_thread = 1;
+
+        unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH");
     }
 
     /* Consider UniFi to be uninitialised */
@@ -1354,22 +1433,10 @@ int sme_sys_resume(unifi_priv_t *priv)
 
     CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend);
 
-    if (priv->ptest_mode == 1) {
-        r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
-        if (r) {
-            /* No reply - forcibly power down in case the request wasn't processed */
-            unifi_notice(priv,
-                    "resume: SME did not reply, return success anyway\n");
-        }
-    } else {
-
-        /*
-         * We are not going to wait for the reply because the SME might be in
-         * the userspace. In this case the event will reach it when the kernel
-         * resumes. So, release now the SME semaphore that was downed in
-         * sme_init_request().
-         */
-        up(&priv->sme_sem);
+    r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
+    if (r) {
+        unifi_notice(priv,
+                "resume: SME did not reply, return success anyway\n");
     }
 
     return 0;
index f5760444bfea779a9268cf1cd511cb5791d25d72..da12807434b45c640594dc77639c5a9cd7c678b7 100644 (file)
@@ -20,6 +20,8 @@
 #ifdef CSR_SUPPORT_WEXT_AP
 #include "sme_csr/csr_wifi_sme_sef.h"
 #endif
+
+
 /*
  * This file implements the SME SYS API and contains the following functions:
  * CsrWifiRouterCtrlMediaStatusReqHandler()
  * CsrWifiRouterCtrlTclasDelReqHandler()
  * CsrWifiRouterCtrlSetModeReqHandler()
  * CsrWifiRouterCtrlWapiMulticastFilterReqHandler()
- * CsrWifiRouterCtrlWapiMulticastReqHandler()
  * CsrWifiRouterCtrlWapiUnicastFilterReqHandler()
+ * CsrWifiRouterCtrlWapiUnicastTxPktReqHandler()
+ * CsrWifiRouterCtrlWapiRxPktReqHandler()
+ * CsrWifiRouterCtrlWapiFilterReqHandler()
  */
 
 #ifdef CSR_SUPPORT_SME
@@ -731,10 +735,31 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     if (priv == NULL) {
         return;
     }
-    for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
-        priv->interfacePriv[i]->interfaceMode = 0;
+    if( priv->wol_suspend ) {
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Don't reset mode\n");
+    } else {
+#ifdef ANDROID_BUILD
+        /* Take the wakelock while Wi-Fi On is in progress */
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: take wake lock\n");
+        wake_lock(&unifi_sdio_wake_lock);
+#endif
+        for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
+            unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Setting interface %d to NONE\n", i );
+
+            priv->interfacePriv[i]->interfaceMode = 0;
+        }
+    }
+    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X) req->dataLength=%d req->data=0x%x\n", msg->source, req->dataLength, req->data);
+
+    if(req->dataLength==3 && req->data && req->data[0]==0 && req->data[1]==1 && req->data[2]==1)
+    {
+        priv->cmanrTestMode = TRUE;
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: cmanrTestMode=%d\n", priv->cmanrTestMode);
+    }
+    else
+    {
+        priv->cmanrTestMode = FALSE;
     }
-    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X)\n", msg->source);
 
     /*
      * The request to initialise UniFi might come while UniFi is running.
@@ -747,11 +772,16 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     /* Update the wifi_on state */
     priv->wifi_on_state = wifi_on_in_progress;
 
-    r = uf_request_firmware_files(priv, UNIFI_FW_STA);
-    if (r) {
-        unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n");
-        CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE);
-        return;
+    /* If UniFi was unpowered, acquire the firmware for download to chip */
+    if (!priv->wol_suspend) {
+        r = uf_request_firmware_files(priv, UNIFI_FW_STA);
+        if (r) {
+            unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n");
+            CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE);
+            return;
+        }
+    } else {
+        unifi_trace(priv, UDBG1, "Don't need firmware\n");
     }
 
     /* Power on UniFi (which may not necessarily have been off) */
@@ -832,6 +862,13 @@ wifi_off(unifi_priv_t *priv)
     int i;
     CsrResult csrResult;
 
+
+    /* Already off? */
+    if (priv->wifi_on_state == wifi_on_unspecified) {
+        unifi_trace(priv, UDBG1, "wifi_off already\n");
+        return;
+    }
+
     unifi_trace(priv, UDBG1, "wifi_off\n");
 
     /* Destroy the Traffic Analysis Module */
@@ -840,6 +877,7 @@ wifi_off(unifi_priv_t *priv)
     cancel_work_sync(&priv->ta_sample_ind_work.task);
 #ifdef CSR_SUPPORT_WEXT
     cancel_work_sync(&priv->sme_config_task);
+    wext_send_disassoc_event(priv);
 #endif
 
     /* Cancel pending M4 stuff */
@@ -908,9 +946,6 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg;
     int i = 0;
-#ifdef CSR_SUPPORT_WEXT_AP
-    CsrWifiSmeWifiOffCfm cfm;
-#endif
 
     if (priv == NULL) {
         return;
@@ -924,6 +959,7 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         if (interfacePriv->netdev_registered == 1) {
             netif_carrier_off(priv->netdev[i]);
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]);
+            interfacePriv->connected = UnifiConnectedUnknown;
         }
         interfacePriv->interfaceMode = 0;
 
@@ -936,15 +972,11 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     wifi_off(priv);
 
     CsrWifiRouterCtrlWifiOffCfmSend(msg->source,req->clientData);
-#ifdef CSR_SUPPORT_WEXT_AP
-    /* Router is turned off when WifiOffCfm is received
-     * hence for wext we don't see WifiOffCfm in the wext
-     * files. So just tell the waiting process that
-     * Wifi off is successful
+
+    /* If this is called in response to closing the character device, the
+     * caller must use uf_sme_cancel_request() to terminate any pending SME
+     * blocking request or there will be a delay while the operation times out.
      */
-    cfm.status =  CSR_RESULT_SUCCESS;
-    CsrWifiSmeWifiOffCfmHandler(priv,(CsrWifiFsmEvent*)(&cfm));
-#endif
 }
 
 
@@ -1065,7 +1097,9 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     {
         int i; /* used as a loop counter */
         CsrUint32 intmode = CSR_WIFI_INTMODE_DEFAULT;
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+        CsrBool switching_ap_fw = FALSE;
+#endif
         /* Register the UniFi device with the OS network manager */
         unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n");
 
@@ -1099,6 +1133,16 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
                     return;
                 }
             }
+#ifdef CSR_WIFI_SPLIT_PATCH
+            else
+            {
+                /* If a netdev is already registered, we have received this WifiOnRes
+                 * in response to switching AP/STA firmware in a ModeSetReq.
+                 * Rememeber this in order to send a ModeSetCfm once
+                 */
+                switching_ap_fw = TRUE;
+            }
+#endif
         }
         priv->totalInterfaceCount = res->numInterfaceAddress;
 
@@ -1117,8 +1161,27 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */
         CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS);
 
+#ifdef CSR_WIFI_SPLIT_PATCH
+        if (switching_ap_fw && (priv->pending_mode_set.common.destination != 0xaaaa)) {
+            unifi_info(priv, "Completed firmware reload with %s patch\n",
+                CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode) ? "AP" : "STA");
+
+            /* Confirm the ModeSetReq that requested the AP/STA patch switch */
+            CsrWifiRouterCtrlModeSetCfmSend(priv->pending_mode_set.common.source,
+                                            priv->pending_mode_set.clientData,
+                                            priv->pending_mode_set.interfaceTag,
+                                            priv->pending_mode_set.mode,
+                                            CSR_RESULT_SUCCESS);
+            priv->pending_mode_set.common.destination = 0xaaaa;
+        }
+#endif
         unifi_info(priv, "UniFi ready\n");
 
+#ifdef ANDROID_BUILD
+        /* Release the wakelock */
+        unifi_trace(priv, UDBG1, "ready: release wake lock\n");
+        wake_unlock(&unifi_sdio_wake_lock);
+#endif
         /* Firmware initialisation is complete, so let the SDIO bus
          * clock be raised when convienent to the core.
          */
@@ -1257,15 +1320,7 @@ void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         return;
     }
 
-    /*
-     * Unless we are in ptest mode, nothing is waiting for the response.
-     * Do not call sme_complete_request(), otherwise the driver
-     * and the SME will be out of step.
-     */
-    if (priv->ptest_mode == 1) {
-        sme_complete_request(priv, res->status);
-    }
-
+    sme_complete_request(priv, res->status);
 }
 
 
@@ -1709,7 +1764,6 @@ void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, CsrUint16 interfaceTag)
                                              &(interfacePriv->genericMulticastOrBroadCastFrames));
 
     uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastFrames));
-    uf_flush_maPktlist(priv,&(interfacePriv->directedMaPktReq));
 
     /*  process the list of frames that requested cfm
     and send cfm to requestor one by one */
@@ -1747,21 +1801,93 @@ void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES)
     {
         netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+        CsrUint8 old_mode = interfacePriv->interfaceMode;
+#endif
         unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n",
                 interfacePriv->interfaceMode);
 
-        /* Cleanup the database first for current existing mode, Then take
-         * care of setting the new mode (Transition seq: AnyMode->NoneMode->newMode)
-         * So for Every mode changes, Database Initialization/cleanup needed
+        interfacePriv->interfaceMode = req->mode;
+
+#ifdef CSR_WIFI_SPLIT_PATCH
+        /* Detect a change in mode that requires a switch to/from the AP firmware patch.
+         * This should only happen when transitioning in/out of AP modes.
          */
-        CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag);
+        if (CSR_WIFI_HIP_IS_AP_FW(req->mode) != CSR_WIFI_HIP_IS_AP_FW(old_mode))
+        {
+            CsrWifiRouterCtrlVersions versions;
+            int r;
+
+#ifdef ANDROID_BUILD
+            /* Take the wakelock while switching patch */
+            unifi_trace(priv, UDBG1, "patch switch: take wake lock\n");
+            wake_lock(&unifi_sdio_wake_lock);
+#endif
+            unifi_info(priv, "Resetting UniFi with %s patch\n", CSR_WIFI_HIP_IS_AP_FW(req->mode) ? "AP" : "STA");
+
+            r = uf_request_firmware_files(priv, UNIFI_FW_STA);
+            if (r) {
+                unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: Failed to get f/w\n");
+                CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag,
+                                                req->mode, CSR_RESULT_FAILURE);
+                return;
+            }
+
+            /* Block the I/O thread */
+            priv->bh_thread.block_thread = 1;
+
+            /* Reset and download the new patch */
+            r = uf_init_hw(priv);
+            if (r) {
+                unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r);
+                CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag,
+                                                req->mode, CSR_RESULT_FAILURE);
+                return;
+            }
+
+            /* Re-enable the I/O thread */
+            priv->bh_thread.block_thread = 0;
+
+            /* Get the version information from the core */
+            unifi_card_info(priv->card, &priv->card_info);
+
+            /* Copy to the unifiio_card_info structure. */
+            versions.chipId = priv->card_info.chip_id;
+            versions.chipVersion = priv->card_info.chip_version;
+            versions.firmwareBuild = priv->card_info.fw_build;
+            versions.firmwareHip = priv->card_info.fw_hip_version;
+            versions.routerBuild = (CsrCharString*)CSR_WIFI_VERSION;
+            versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION;
+
+            /* Now that new firmware is running, send a WifiOnInd to the NME. This will
+             * cause it to retransfer the MIB.
+             */
+            CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions);
+
+            /* Store the request so we know where to send the ModeSetCfm */
+            priv->pending_mode_set = *req;
+        }
+        else
+#endif
+        {
+            /* No patch switch, confirm straightaway */
+            CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag,
+                                            req->mode, CSR_RESULT_SUCCESS);
+        }
 
-        interfacePriv->interfaceMode = req->mode;
         interfacePriv->bssid = req->bssid;
         /* For modes other than AP/P2PGO, set below member FALSE */
         interfacePriv->intraBssEnabled = FALSE;
-
+        /* Initialise the variable bcTimSet with a value
+         * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value
+         */
+        interfacePriv->bcTimSet = 0xFF;
+        interfacePriv->bcTimSetReqPendingFlag = FALSE;
+        /* Initialise the variable bcTimSetReqQueued with a value
+         * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value
+         */
+        interfacePriv->bcTimSetReqQueued =0xFF;
+        CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag);
 
         if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
            req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
@@ -1797,8 +1923,6 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
     unifi_port_config_t *controlledPort;
     unifi_port_config_t *unControlledPort;
     netInterface_priv_t *interfacePriv;
-    maPktReqList_t *maPktreq;
-    struct list_head *listHeadMaPktreq,*placeHolderMaPktreq;
 
     CsrUint8 ba_session_idx = 0;
     ba_session_rx_struct *ba_session_rx = NULL;
@@ -1832,21 +1956,6 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
             uf_flush_list(priv,&(staInfo->dataPdu[j]));
         }
 
-        /* There may be race condition
-           before getting the ma_packet_cfm from f/w, driver may receive peer del from SME
-        */
-        spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-        list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) {
-            maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q);
-            if(maPktreq->staHandler== staInfo->assignedHandle){
-                dev_kfree_skb(maPktreq->skb);
-                list_del(listHeadMaPktreq);
-                kfree(maPktreq);
-            }
-
-        }
-        spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-
         spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
         /* clear the port configure array info, for the corresponding peer entry */
         controlledPort = &interfacePriv->controlled_data_port;
@@ -1885,7 +1994,7 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
         /* Stop BA session if it is active, for this peer address all BA sessions
         (per tID per role) are closed */
 
-        spin_lock(&priv->ba_lock);
+        down(&priv->ba_mutex);
         for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
             ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx];
             if(ba_session_rx) {
@@ -1912,7 +2021,7 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
             }
         }
 
-        spin_unlock(&priv->ba_lock);
+        up(&priv->ba_mutex);
 
 #ifdef CSR_SUPPORT_SME
         unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid);
@@ -2134,8 +2243,16 @@ static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *r
             newRecord->txSuspend = FALSE;
 
             /*U-APSD related data structure*/
+            newRecord->timRequestPendingFlag = FALSE;
+
+            /* Initialise the variable updateTimReqQueued with a value
+             * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value
+             */
+            newRecord->updateTimReqQueued = 0xFF;
+            newRecord->timSet = CSR_WIFI_TIM_RESET;
             newRecord->uapsdActive = FALSE;
             newRecord->noOfSpFramesSent =0;
+            newRecord->triggerFramePriority = CSR_QOS_UP0;
 
             /* The protection bit is updated once the port opens for corresponding peer in
              * routerPortConfigure request */
@@ -2602,13 +2719,13 @@ void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent*
 
     unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__);
 
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     r = blockack_session_stop(priv,
                               req->interfaceTag,
                               req->role,
                               req->trafficStreamID,
                               req->macAddress);
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
 
     CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source,
                                             req->clientData,
@@ -2746,6 +2863,16 @@ CsrBool blockack_session_start(unifi_priv_t *priv,
                             init_timer(&ba_session_rx->timer);
                             mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024)));
                         }
+                        /*
+                         * The starting sequence number shall remain same if the BA
+                         * enable request is issued to update BA parameters only. If
+                         * it is not same, then we scroll our window to the new starting
+                         * sequence number. This could happen if the DELBA frame from
+                         * originator is lost and then we receive ADDBA frame with new SSN.
+                        */
+                        if(ba_session_rx->start_sn != start_sn) {
+                            scroll_ba_window(priv, interfacePriv, ba_session_rx, start_sn);
+                        }
                         return TRUE;
                     }
                 }
@@ -2768,6 +2895,21 @@ CsrBool blockack_session_start(unifi_priv_t *priv,
             return FALSE;
         }
 
+        /* It is observed that with some devices there is a race between
+         * EAPOL exchanges and BA session establishment. This results in
+         * some EAPOL authentication packets getting stuck in BA reorder
+         * buffer and hence the conection cannot be established. To avoid
+         * this we check here if the EAPOL authentication is complete and
+         * if so then only allow the BA session to establish.
+         *
+         * It is verified that the peers normally re-establish
+         * the BA session after the initial rejection.
+         */
+        if (CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN != uf_sme_port_state(priv, macAddress.a, UF_CONTROLLED_PORT_Q, interfacePriv->InterfaceTag))
+        {
+            unifi_warning(priv, "blockack_session_start: Controlled port not opened, Reject BA request\n");
+            return FALSE;
+        }
 
         ba_session_rx = kmalloc(sizeof(ba_session_rx_struct), GFP_KERNEL);
         if (!ba_session_rx) {
@@ -2814,7 +2956,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
 
     unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     r = blockack_session_start(priv,
                                req->interfaceTag,
                                req->trafficStreamID,
@@ -2824,7 +2966,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
                                req->ssn,
                                req->macAddress
                               );
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
 
     CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source,
                                            req->clientData,
@@ -2836,115 +2978,291 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
 
 void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 {
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
 
-    unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status);
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
+
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
+
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status);
+
+        /* status 1 - Filter on
+        * status 0 - Filter off */
+        priv->wapi_multicast_filter = req->status;
+
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
 
-    /* status 1 - Filter on
-     * status 0 - Filter off */
-    priv->wapi_multicast_filter = req->status;
+       unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
 
-    unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    }
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastFilterReqHandler: called when WAPI isn't enabled\n");
+#endif
 }
 
 void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 {
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
 
-    unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status);
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
 
-    if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) {
-        /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */
-               priv->wapi_unicast_queued_pkt_filter = 1;
-       }
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
 
-    /* status 1 - Filter ON
-     * status 0 - Filter OFF */
-    priv->wapi_unicast_filter = req->status;
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status);
 
-    unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
-}
+        if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) {
+            /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */
+            priv->wapi_unicast_queued_pkt_filter = 1;
+        }
 
+        /* status 1 - Filter ON
+         * status 0 - Filter OFF */
+        priv->wapi_unicast_filter = req->status;
 
-void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
-{
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
+
+        unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
+
+    }
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
-    CsrWifiRouterCtrlWapiMulticastReq* req =  (CsrWifiRouterCtrlWapiMulticastReq*)msg;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiUnicastFilterReqHandler: called when WAPI isn't enabled\n");
+#endif
+}
+
+void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
+{
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
 
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    CsrWifiRouterCtrlWapiRxPktReq* req =  (CsrWifiRouterCtrlWapiRxPktReq*)msg;
     int client_id, receiver_id;
     bulk_data_param_t bulkdata;
     CsrResult res;
     ul_client_t *client;
-
     CSR_SIGNAL signal;
     CSR_MA_PACKET_INDICATION *pkt_ind;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
 
-    unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlWapiMulticastReqHandler: \n");
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
 
-    if (priv == NULL) {
-        unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid priv\n",__FUNCTION__);
-        return;
-    }
+       unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
 
-    if (priv->smepriv == NULL) {
-         unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid sme priv\n",__FUNCTION__);
-         return;
-    }
+        if (priv == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid priv\n",__FUNCTION__);
+            return;
+        }
 
-    if (req->dataLength == 0 || req->data == NULL) {
-         unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: invalid request\n",__FUNCTION__);
-         return;
-    }
+        if (priv->smepriv == NULL) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid sme priv\n",__FUNCTION__);
+             return;
+        }
 
-    res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength);
-    if (res != CSR_RESULT_SUCCESS) {
-        unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: Could not allocate net data\n",__FUNCTION__);
-        return;
-    }
+        if (req->dataLength == 0 || req->data == NULL) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: invalid request\n",__FUNCTION__);
+             return;
+        }
 
-    /* This function is expected to be called only when the MIC has been verified by SME to be correct
-     * So reset the reception status to rx_success */
-    res = read_unpack_signal(req->signal, &signal);
-    if (res) {
-           unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Received unknown or corrupted signal.\n");
-           return;
-    }
-    pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication);
-    if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) {
-            unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus);
-            return;
-    }
-    else {
-            unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiMulticastReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__);
-            pkt_ind->ReceptionStatus = CSR_RX_SUCCESS;
-            write_pack(&signal, req->signal, &(req->signalLength));
+        res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength);
+        if (res != CSR_RESULT_SUCCESS) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: Could not allocate net data\n",__FUNCTION__);
+             return;
+        }
+
+        /* This function is expected to be called only when the MIC has been verified by SME to be correct
+         * So reset the reception status to rx_success */
+        res = read_unpack_signal(req->signal, &signal);
+        if (res) {
+                 unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: Received unknown or corrupted signal.\n");
+                 return;
+        }
+        pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication);
+        if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) {
+                 unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus);
+                 return;
+        } else {
+                 unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiRxPktReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__);
+                 pkt_ind->ReceptionStatus = CSR_RX_SUCCESS;
+                 write_pack(&signal, req->signal, &(req->signalLength));
+        }
+
+        memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength);
+
+        receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0;
+        client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
+
+        client = &priv->ul_clients[client_id];
+
+        if (client && client->event_hook) {
+              unifi_trace(priv, UDBG3,
+                          "CsrWifiRouterCtrlWapiRxPktReq: "
+                          "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n",
+                          client->client_id, client->sender_id, receiver_id,
+                          CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal));
+
+              client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST);
+        } else {
+              unifi_trace(priv, UDBG4, "No client to give the packet to\n");
+              unifi_net_data_free(priv, &bulkdata.d[0]);
+        }
+
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
+       unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
     }
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: called when WAPI isn't enabled\n");
+#endif
+}
 
-    memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength);
+void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
+{
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
 
-    receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0;
-    client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
+       unifi_priv_t *priv = (unifi_priv_t*) drvpriv;
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *req  = (CsrWifiRouterCtrlWapiUnicastTxPktReq*) msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
+    bulk_data_param_t bulkdata;
+    CsrUint8 macHeaderLengthInBytes = MAC_HEADER_SIZE;
+    /*KeyID, Reserved, PN, MIC*/
+    CsrUint8 appendedCryptoFields = 1 + 1 + 16 + 16;
+    CsrResult result;
+    /* Retrieve the MA PACKET REQ fields from the Signal retained from send_ma_pkt_request() */
+    CSR_MA_PACKET_REQUEST *storedSignalMAPktReq = &interfacePriv->wapi_unicast_ma_pkt_sig.u.MaPacketRequest;
 
-    client = &priv->ul_clients[client_id];
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
+
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
+
+        if (priv == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid priv\n",__FUNCTION__);
+            return;
+        }
+        if (priv->smepriv == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid sme priv\n",__FUNCTION__);
+            return;
+        }
+        if (req->data == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid request\n",__FUNCTION__);
+            return;
+        } else {
+            /* If it is QoS data (type = data subtype = QoS), frame header contains QoS control field */
+            if ((req->data[0] & 0x88) == 0x88) {
+               macHeaderLengthInBytes  = macHeaderLengthInBytes + QOS_CONTROL_HEADER_SIZE;
+            }
+        }
+        if ( !(req->dataLength>(macHeaderLengthInBytes+appendedCryptoFields)) ) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid dataLength\n",__FUNCTION__);
+            return;
+        }
+
+           /* Encrypted DATA Packet contained in (req->data)
+         * -------------------------------------------------------------------
+         * |MAC Header|  KeyId   | Reserved |    PN    | xxDataxx | xxMICxxx |
+         * -------------------------------------------------------------------
+         *                                             (<-----Encrypted----->)
+         * -------------------------------------------------------------------
+         * |24/26(QoS)|    1     |    1     |    16    |    x     |    16    |
+         * -------------------------------------------------------------------
+         */
+        result = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength);
+        if (result != CSR_RESULT_SUCCESS) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: Could not allocate net data\n",__FUNCTION__);
+             return;
+        }
+        memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength);
+        bulkdata.d[0].data_length = req->dataLength;
+        bulkdata.d[1].os_data_ptr = NULL;
+        bulkdata.d[1].data_length = 0;
+
+        /* Send UniFi msg */
+        /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */
+        result = uf_process_ma_packet_req(priv,
+                                         storedSignalMAPktReq->Ra.x,
+                                          storedSignalMAPktReq->HostTag,/* Ask for a new HostTag */
+                                          req->interfaceTag,
+                                          storedSignalMAPktReq->TransmissionControl,
+                                          storedSignalMAPktReq->TransmitRate,
+                                          storedSignalMAPktReq->Priority, /* Retained value */
+                                          interfacePriv->wapi_unicast_ma_pkt_sig.SignalPrimitiveHeader.SenderProcessId, /*FIXME AP: VALIDATE ???*/
+                                          &bulkdata);
+
+        if (result == NETDEV_TX_OK) {
+             (priv->netdev[req->interfaceTag])->trans_start = jiffies;
+             /* Should really count tx stats in the UNITDATA.status signal but
+              * that doesn't have the length.
+              */
+             interfacePriv->stats.tx_packets++;
+
+             /* count only the packet payload */
+             interfacePriv->stats.tx_bytes += req->dataLength - macHeaderLengthInBytes - appendedCryptoFields;
+             unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Sent), sent count = %x\n", interfacePriv->stats.tx_packets);
+        } else {
+             /* Failed to send: fh queue was full, and the skb was discarded*/
+             unifi_trace(priv, UDBG1, "(HIP validation failure) Result = %d\n", result);
+             unifi_net_data_free(priv, &bulkdata.d[0]);
+
+             interfacePriv->stats.tx_dropped++;
+             unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped);
+        }
 
-    if (client && client->event_hook) {
-         unifi_trace(priv, UDBG3,
-                     "CsrWifiRouterCtrlWapiMulticastReqHandler: "
-                     "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n",
-                     client->client_id, client->sender_id, receiver_id,
-                     CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal));
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+
+    } else {
+
+       unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
 
-         client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST);
     }
-    else {
-         unifi_trace(priv, UDBG4, "No client to give the packet to\n");
-         unifi_net_data_free(priv, &bulkdata.d[0]);
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: called when WAPI SW ENCRYPTION isn't enabled\n");
+#endif
+}
+
+void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
+{
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    CsrWifiRouterCtrlWapiFilterReq* req = (CsrWifiRouterCtrlWapiFilterReq*)msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
+
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
+
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
+
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiFilterReq: req->isWapiConnected [0/1] = %d \n",req->isWapiConnected);
+
+        priv->isWapiConnection = req->isWapiConnected;
+
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
+
+       unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
+
     }
+#endif
 
-    unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiFilterReq: called when WAPI isn't enabled\n");
+#endif
 }
index 38df94b69e9f41849603344b5eda1e7883156a00..d87a6e304ff2c3e7ab4fc8c2e40eefb8d647de36 100644 (file)
@@ -101,7 +101,6 @@ uf_sme_init(unifi_priv_t *priv)
         INIT_LIST_HEAD(&interfacePriv->genericMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames);
-        INIT_LIST_HEAD(&interfacePriv->directedMaPktReq);
 
         for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
             interfacePriv->staInfo[j] = NULL;
@@ -139,7 +138,7 @@ uf_sme_deinit(unifi_priv_t *priv)
 
     /* Remove all the Peer database, before going down */
     for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
-        spin_lock(&priv->ba_lock);
+        down(&priv->ba_mutex);
         for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
             ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx];
             if(ba_session_rx) {
@@ -161,7 +160,7 @@ uf_sme_deinit(unifi_priv_t *priv)
             }
         }
 
-        spin_unlock(&priv->ba_lock);
+        up(&priv->ba_mutex);
         interfacePriv = priv->interfacePriv[i];
         if(interfacePriv){
             for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
index 384ccd46982eed0d967eb9532d063f5eefe2a1fa..3ba7b4cef2ddf6ada55f31214eb6ed3372fdcf0a 100644 (file)
         }                                                   \
     } while (0)
 
-/* Workaround for the wpa_supplicant hanging issue */
+/* Workaround for the wpa_supplicant hanging issue - disabled on Android */
+#ifndef ANDROID_BUILD
 #define CSR_WIFI_WEXT_HANG_WORKAROUND
+#endif
 
 #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND
 # define UF_RTNL_LOCK()    rtnl_lock()
index ae14f2354362ddbb6ae17f79bb2774bc71fefd68..958b8a1a9eb34104198720cb25b118c81acd7433 100644 (file)
@@ -265,7 +265,9 @@ ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len)
         /* wifi_off_ind (error or exit) */
         CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, (CsrWifiRouterCtrlControlIndication)(*conf_param));
     }
-
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    unifi_debug_buf_dump();
+#endif
 #else
     bulk_data_param_t bulkdata;
 
@@ -420,10 +422,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
     CsrResult csrResult;
     unsigned long lock_flags;
     int r;
-#ifdef CSR_SUPPORT_SME
-    netInterface_priv_t *interfacePriv = priv->interfacePriv[0];
-    CsrUint32 alignOffset = 0;
-#endif
 
 
     csrResult = write_pack(sigptr, sigbuf, &packed_siglen);
@@ -431,12 +429,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
         unifi_error(priv, "Malformed HIP signal in ul_send_signal_unpacked()\n");
         return CsrHipResultToStatus(csrResult);
     }
-#ifdef CSR_SUPPORT_SME
-    if (bulkdata != NULL){
-        alignOffset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1);
-
-    }
-#endif
     r = _align_bulk_data_buffers(priv, sigbuf, (bulk_data_param_t*)bulkdata);
     if (r) {
         return r;
@@ -449,17 +441,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
         spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags);
         return CsrHipResultToStatus(csrResult);
     }
-#ifdef CSR_SUPPORT_SME
-    if (sigptr->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) {
-        if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
-           interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
-
-            uf_store_directed_ma_packet_referenece(priv, bulkdata, sigptr,alignOffset);
-
-        }
-    }
-#endif
-
     spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags);
 
     return 0;
index cfc5b32d4a66577cf8b8c447fe695a9b4dc0ff56..8b5d4669e127f25f885d0bd8e20f8391557895dd 100644 (file)
@@ -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
index 579c7e0544a3f9e86754b16fde36a7ab0b0e067f..0a9749450688368bd1d5f8a2008f0dd27a4ae05b 100644 (file)
@@ -97,6 +97,13 @@ void dump16(void *mem, CsrUint16 len);
 void dump_str(void *mem, CsrUint16 len);
 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
 
+void unifi_error(void* ospriv, const char *fmt, ...);
+void unifi_warning(void* ospriv, const char *fmt, ...);
+void unifi_notice(void* ospriv, const char *fmt, ...);
+void unifi_info(void* ospriv, const char *fmt, ...);
+
+void unifi_trace(void* ospriv, int level, const char *fmt, ...);
+
 #else
 
 /* Stubs */
@@ -113,15 +120,16 @@ static inline void dump16(void *mem, CsrUint16 len) {}
 static inline void dump_str(void *mem, CsrUint16 len) {}
 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
 
-#endif /* UNIFI_DEBUG */
+void unifi_error_nop(void* ospriv, const char *fmt, ...);
+void unifi_trace_nop(void* ospriv, int level, const char *fmt, ...);
+#define unifi_error if(1);else unifi_error_nop
+#define unifi_warning if(1);else unifi_error_nop
+#define unifi_notice if(1);else unifi_error_nop
+#define unifi_info if(1);else unifi_error_nop
+#define unifi_trace if(1);else unifi_trace_nop
 
+#endif /* UNIFI_DEBUG */
 
-void unifi_error(void* ospriv, const char *fmt, ...);
-void unifi_warning(void* ospriv, const char *fmt, ...);
-void unifi_notice(void* ospriv, const char *fmt, ...);
-void unifi_info(void* ospriv, const char *fmt, ...);
-
-void unifi_trace(void* ospriv, int level, const char *fmt, ...);
 
 /* Different levels of diagnostic detail... */
 #define UDBG0       0   /* always prints in debug build */
index 36b871e02c98ce0e3b9b4abf56fb6296e1e9bf22..e35747c0831713c621f0b8996e18fbd2b959beb6 100644 (file)
 static void _update_buffered_pkt_params_after_alignment(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
                                                         tx_buffered_packets_t* buffered_pkt)
 {
-
     struct sk_buff *skb ;
     CsrUint32 align_offset;
 
     if (priv == NULL || bulkdata == NULL || buffered_pkt == NULL){
         return;
     }
+
     skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr;
     align_offset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1);
     if(align_offset){
         skb_pull(skb,align_offset);
     }
-    buffered_pkt->bulkdata.os_data_ptr = skb->data;
-    buffered_pkt->bulkdata.data_length = skb->len;
-
 
+    buffered_pkt->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr;
+    buffered_pkt->bulkdata.data_length = bulkdata->d[0].data_length;
+    buffered_pkt->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr;
+    buffered_pkt->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length;
 }
 #endif
 
@@ -122,7 +123,7 @@ unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority,
 #ifdef CSR_SUPPORT_SME
 
 #define TRANSMISSION_CONTROL_TRIGGER_MASK 0x0001
-#define TRANSMISSION_CONTROL_ESOP_MASK 0x0002
+#define TRANSMISSION_CONTROL_EOSP_MASK 0x0002
 
 static
 int frame_and_send_queued_pdu(unifi_priv_t* priv,tx_buffered_packets_t* buffered_pkt,
@@ -167,34 +168,27 @@ int frame_and_send_queued_pdu(unifi_priv_t* priv,tx_buffered_packets_t* buffered
             case IEEE802_11_FC_TYPE_QOS_DATA & IEEE80211_FC_SUBTYPE_MASK:
             case IEEE802_11_FC_TYPE_QOS_NULL & IEEE80211_FC_SUBTYPE_MASK:
                 /* If both are set then the Address4 exists (only for AP) */
-                if (fromDs && toDs)
-                {
+                if (fromDs && toDs) {
                     /* 6 is the size of Address4 field */
                     macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6);
-                }
-                else
-                {
+                } else {
                     macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE;
                 }
 
                 /* If order bit set then HT control field is the part of MAC header */
                 if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) {
                     macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE;
+                    qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-6));
+                } else {
+                    qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-2));
                 }
+                *qc = eosp ? *qc | (1 << 4) : *qc & (~(1 << 4));
                 break;
             default:
                 if (fromDs && toDs)
                     macHeaderLengthInBytes += 6;
-             break;
-        }
-
-        if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) {
-            qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-6));
-        } else {
-            qc = (CsrUint8*)(buffered_pkt->bulkdata.os_data_ptr + (macHeaderLengthInBytes-2));
         }
 
-        *qc = eosp ? *qc | (1 << 4) : *qc & (~(1 << 4));
     }
     result = ul_send_signal_unpacked(priv, &signal, &bulkdata);
     if(result){
@@ -254,7 +248,7 @@ void set_eosp_transmit_ctrl(unifi_priv_t *priv, struct list_head *txList)
     spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
     list_for_each_prev_safe(listHead, placeHolder, txList) {
         tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
-        tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK;
+        tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK;
         tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED));
         unifi_trace(priv, UDBG1,
                 "set_eosp_transmit_ctrl Transmission Control = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag);
@@ -275,6 +269,8 @@ void send_vif_availibility_rsp(unifi_priv_t *priv,CSR_VIF_IDENTIFIER vif,CSR_RES
     bulk_data_param_t *bulkdata = NULL;
     int r;
 
+    unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : invoked with resultCode = %d \n", resultCode);
+
     memset(&signal,0,sizeof(CSR_SIGNAL));
     rsp = &signal.u.MaVifAvailabilityResponse;
     rsp->VirtualInterfaceIdentifier = vif;
@@ -288,6 +284,9 @@ void send_vif_availibility_rsp(unifi_priv_t *priv,CSR_VIF_IDENTIFIER vif,CSR_RES
     if(r) {
         unifi_error(priv,"Availibility response sending failed %x status %d\n",vif,r);
     }
+    else {
+        unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : status = %d \n", r);
+    }
 }
 #endif
 
@@ -354,14 +353,14 @@ void verify_and_accomodate_tx_packet(unifi_priv_t *priv)
         list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) {
             tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
             if(eospFramedeleted){
-                tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK;
+                tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK;
                 tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED));
                 unifi_trace(priv, UDBG1,"updating eosp for next packet hostTag:= 0x%x ",tx_q_item->hostTag);
                 eospFramedeleted =0;
                 break;
             }
 
-            if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK ){
+            if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK ){
                eospFramedeleted = 1;
             }
             unifi_trace(priv,UDBG1, "freeing of multicast packets ToC = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag);
@@ -445,66 +444,162 @@ CsrResult enque_tx_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
     unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n");
     return CSR_RESULT_SUCCESS;
 }
-static
-CsrResult enque_direceted_ma_pkt_cfm_data_pdu(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
-                            struct list_head *list, CSR_SIGNAL *signal,
-                            CsrBool requeueOnSamePos)
+
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+CsrResult unifi_reque_ma_packet_request (void *ospriv, CsrUint32 host_tag,
+                                         CsrUint16 txStatus, bulk_data_desc_t *bulkDataDesc)
 {
+    CsrResult status = CSR_RESULT_SUCCESS;
+    unifi_priv_t *priv = (unifi_priv_t*)ospriv;
+    netInterface_priv_t *interfacePriv;
+    struct list_head *list = NULL;
+    CsrWifiRouterCtrlStaInfo_t *staRecord = NULL;
+    bulk_data_param_t bulkData;
+    CSR_SIGNAL signal;
+    CSR_PRIORITY priority = 0;
+    CsrUint16 interfaceTag = 0;
+    unifi_TrafficQueue priority_q;
+    CsrUint16 frameControl = 0, frameType = 0;
+    unsigned long lock_flags;
 
-    /* queue the tx data packets on to appropriate queue */
-    CSR_MA_PACKET_REQUEST *req = &signal->u.MaPacketRequest;
-    tx_buffered_packets_t *tx_q_item;
+    interfacePriv = priv->interfacePriv[interfaceTag];
+
+    /* If the current mode is not AP or P2PGO then just return failure
+     * to clear the hip slot
+     */
+    if(!((interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP) ||
+        (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO))) {
+        return CSR_RESULT_FAILURE;
+    }
 
+    unifi_trace(priv, UDBG6, "unifi_reque_ma_packet_request: host_tag = 0x%x\n", host_tag);
 
-    unifi_trace(priv, UDBG5, "entering enque_tx_data_pdu\n");
-    if(!list  ) {
-       unifi_error(priv,"List is not specified\n");
-       return CSR_RESULT_FAILURE;
+    staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv,
+                                                                    (((CsrUint8 *) bulkDataDesc->os_data_ptr) + 4),
+                                                                    interfaceTag);
+    if (NULL == staRecord) {
+        unifi_trace(priv, UDBG5, "unifi_reque_ma_packet_request: Invalid STA record \n");
+        return CSR_RESULT_FAILURE;
     }
-    if(!requeueOnSamePos && !list->prev){
-       unifi_error(priv,"List prev is NULL so don't requeu it\n");
-       return CSR_RESULT_FAILURE;
 
+    /* Update TIM if MA-PACKET.cfm fails with status as Tx-retry-limit or No-BSS and then just return failure
+     * to clear the hip slot associated with the Packet
+     */
+    if (CSR_TX_RETRY_LIMIT == txStatus || CSR_TX_NO_BSS == txStatus) {
+        if (staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING)
+        {
+            unifi_trace(priv, UDBG2, "unifi_reque_ma_packet_request: CFM failed with Retry Limit or No BSS-->update TIM\n");
+            if (!staRecord->timRequestPendingFlag) {
+                update_tim(priv, staRecord->aid, 1, interfaceTag, staRecord->assignedHandle);
+            }
+            else {
+                /* Cache the TimSet value so that it will processed immidiatly after
+                 * completing the current setTim Request
+                 */
+                staRecord->updateTimReqQueued = 1;
+                unifi_trace(priv, UDBG6, "unifi_reque_ma_packet_request: One more UpdateTim Request(:%d)Queued for AID %x\n",
+                                         staRecord->updateTimReqQueued, staRecord->aid);
+            }
+        }
+        return CSR_RESULT_FAILURE;
     }
+    else if ((CSR_TX_LIFETIME == txStatus) ||  (CSR_TX_BLOCK_ACK_TIMEOUT == txStatus) ||
+             (CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED == txStatus) ||
+             (CSR_TX_REJECTED_PEER_STATION_SLEEPING == txStatus)    ||
+             (CSR_TX_REJECTED_DTIM_STARTED == txStatus)) {
+        /* Extract the Frame control and the frame type */
+        frameControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr);
+        frameType =  ((frameControl & IEEE80211_FC_TYPE_MASK) >> FRAME_CONTROL_TYPE_FIELD_OFFSET);
 
+        /* Mgmt frames will not be re-queued for Tx
+         * so just return failure to clear the hip slot
+         */
+        if (IEEE802_11_FRAMETYPE_MANAGEMENT == frameType) {
+            return CSR_RESULT_FAILURE;
+        }
+        else if (IEEE802_11_FRAMETYPE_DATA == frameType) {
+            /* QOS NULL and DATA NULL frames will not be re-queued for Tx
+             * so just return failure to clear the hip slot
+             */
+            if ((((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET) == QOS_DATA_NULL) ||
+                (((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> FRAME_CONTROL_SUBTYPE_FIELD_OFFSET)== DATA_NULL )) {
+                return CSR_RESULT_FAILURE;
+            }
+        }
 
+        /* Extract the Packet priority */
+        if (TRUE == staRecord->wmmOrQosEnabled) {
+            CsrUint16 qosControl = 0;
+            CsrUint8  dataFrameType = 0;
 
-    tx_q_item = (tx_buffered_packets_t *)kmalloc(sizeof(tx_buffered_packets_t), GFP_ATOMIC);
-    if (tx_q_item == NULL) {
-        unifi_error(priv,
-                "Failed to allocate %d bytes for tx packet record\n",
-                sizeof(tx_buffered_packets_t));
-        func_exit();
-        return CSR_RESULT_FAILURE;
-    }
-    /* disable the preemption */
-    INIT_LIST_HEAD(&tx_q_item->q);
-    /* fill the tx_q structure members */
-    tx_q_item->bulkdata.os_data_ptr = bulkdata->d[0].os_data_ptr;
-    tx_q_item->bulkdata.data_length = bulkdata->d[0].data_length;
-    tx_q_item->bulkdata.os_net_buf_ptr = bulkdata->d[0].os_net_buf_ptr;
-    tx_q_item->bulkdata.net_buf_length = bulkdata->d[0].net_buf_length;
-    tx_q_item->interfaceTag = req->VirtualInterfaceIdentifier & 0xff;
-    tx_q_item->hostTag = req->HostTag;
-    tx_q_item->leSenderProcessId = signal->SignalPrimitiveHeader.SenderProcessId;
-    tx_q_item->transmissionControl = req->TransmissionControl;
-    tx_q_item->priority = req->Priority;
-    tx_q_item->rate = req->TransmitRate;
-    memcpy(tx_q_item->peerMacAddress.a, req->Ra.x, ETH_ALEN);
+            dataFrameType =((frameControl & IEEE80211_FC_SUBTYPE_MASK) >> 4);
 
+            if (dataFrameType == QOS_DATA) {
+                /* QoS control field is offset from frame control by 2 (frame control)
+                 * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN
+                 */
+                if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)) {
+                    qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr + 30);
+                }
+                else {
+                    qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(bulkDataDesc->os_data_ptr + 24);
+                }
+            }
 
+            priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK);
 
-    if (requeueOnSamePos) {
-        list_add(&tx_q_item->q, list);
-    } else {
-        list_add_tail(&tx_q_item->q, list);
+            if (priority < CSR_QOS_UP0 || priority > CSR_QOS_UP7) {
+                unifi_trace(priv, UDBG5, "unifi_reque_ma_packet_request: Invalid priority:%x \n", priority);
+                return CSR_RESULT_FAILURE;
+            }
+        }
+        else {
+            priority = CSR_CONTENTION;
+        }
+
+        /* Frame Bulk data to requeue it back to HAL Queues */
+        bulkData.d[0].os_data_ptr    = bulkDataDesc->os_data_ptr;
+        bulkData.d[0].data_length    = bulkDataDesc->data_length;
+        bulkData.d[0].os_net_buf_ptr = bulkDataDesc->os_net_buf_ptr;
+        bulkData.d[0].net_buf_length = bulkDataDesc->net_buf_length;
+
+        bulkData.d[1].os_data_ptr    = NULL;
+        bulkData.d[1].os_net_buf_ptr = NULL;
+        bulkData.d[1].data_length    = bulkData.d[1].net_buf_length = 0;
+
+        /* Initialize signal to zero */
+        memset(&signal, 0, sizeof(CSR_SIGNAL));
+
+        /* Frame MA Packet Req */
+        unifi_frame_ma_packet_req(priv, priority, 0, host_tag,
+                              interfaceTag, CSR_NO_CONFIRM_REQUIRED,
+                              priv->netdev_client->sender_id,
+                              staRecord->peerMacAddress.a, &signal);
+
+        /* Find the Q-Priority */
+        priority_q = unifi_frame_priority_to_queue(priority);
+        list = &staRecord->dataPdu[priority_q];
+
+        /* Place the Packet on to HAL Queue */
+        status = enque_tx_data_pdu(priv, &bulkData, list, &signal, TRUE);
+
+        /* Update the Per-station queued packet counter */
+        if (!status) {
+            spin_lock_irqsave(&priv->staRecord_lock, lock_flags);
+            staRecord->noOfPktQueued++;
+            spin_unlock_irqrestore(&priv->staRecord_lock, lock_flags);
+        }
+    }
+    else {
+        /* Packet will not be re-queued for any of the other MA Packet Tx failure
+         * reasons so just return failure to clear the hip slot
+         */
+        return CSR_RESULT_FAILURE;
     }
 
-    /* Count of packet queued in driver */
-    priv->noOfPktQueuedInDriver++;
-    unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n");
-    return CSR_RESULT_SUCCESS;
+    return status;
 }
+#endif
 
 static void is_all_ac_deliver_enabled_and_moredata(CsrWifiRouterCtrlStaInfo_t *staRecord, CsrUint8 *allDeliveryEnabled, CsrUint8 *dataAvailable)
 {
@@ -601,12 +696,53 @@ void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, CsrUin
                     unifi_trace(priv, UDBG3, "receiver processID = %x, success: request & confirm states are not matching in TIM cfm: Debug status = %x, staRecord->timSet = %x, handle = %x\n",
                                  receiverProcessId, timSetStatus, staRecord->timSet, handle);
                 }
+
+                /* Reset TIM pending flag to send next TIM request */
+                staRecord->timRequestPendingFlag = FALSE;
+
+                /* Make sure that one more UpdateTim request is queued, if Queued its value
+                 * should be CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET
+                 */
+                if (0xFF != staRecord->updateTimReqQueued)
+                {
+                    /* Process the UpdateTim Request which is queued while previous UpdateTim was in progress */
+                    if (staRecord->timSet != staRecord->updateTimReqQueued)
+                    {
+                       unifi_trace(priv, UDBG2, "uf_handle_tim_cfm : Processing Queued UpdateTimReq \n");
+
+                       update_tim(priv, staRecord->aid, staRecord->updateTimReqQueued, interfaceTag, handle);
+
+                       staRecord->updateTimReqQueued = 0xFF;
+                    }
+                }
             } else {
+
+                interfacePriv->bcTimSet = timSetValue;
                 /* fh_cmd_q can also be full at some point of time!,
                  * resetting count as queue is cleaned by firmware at this point
                  */
                 retryCount = 0;
                 unifi_trace(priv, UDBG3, "tim (%s) successfully for broadcast frame in firmware\n", (timSetValue)?"SET":"RESET");
+
+                /* Reset DTIM pending flag to send next DTIM request */
+                interfacePriv->bcTimSetReqPendingFlag = FALSE;
+
+                /* Make sure that one more UpdateDTim request is queued, if Queued its value
+                 * should be CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET
+                 */
+                if (0xFF != interfacePriv->bcTimSetReqQueued)
+                {
+                    /* Process the UpdateTim Request which is queued while previous UpdateTim was in progress */
+                    if (interfacePriv->bcTimSet != interfacePriv->bcTimSetReqQueued)
+                    {
+                        unifi_trace(priv, UDBG2, "uf_handle_tim_cfm : Processing Queued UpdateDTimReq \n");
+
+                        update_tim(priv, 0, interfacePriv->bcTimSetReqQueued, interfaceTag, 0xFFFFFFFF);
+
+                        interfacePriv->bcTimSetReqQueued = 0xFF;
+                    }
+                }
+
             }
             break;
         case CSR_RC_INVALID_PARAMETERS:
@@ -684,6 +820,7 @@ void uf_handle_tim_cfm(unifi_priv_t *priv, CSR_MLME_SET_TIM_CONFIRM *cfm, CsrUin
         default:
             unifi_warning(priv, "tim update request failed resultcode = %x\n", cfm->ResultCode);
     }
+
     unifi_trace(priv, UDBG2, "leaving %s\n", __FUNCTION__);
 }
 
@@ -733,8 +870,14 @@ void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 i
 
     unifi_trace(priv, UDBG5, "entering the update_tim routine\n");
 
+
     if (handle == 0xFFFFFFFF) {
         handle &= CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE;
+        if (setTim == interfacePriv->bcTimSet)
+        {
+            unifi_trace(priv, UDBG3, "update_tim, Drop:Hdl=%x, timval=%d, globalTim=%d\n", handle, setTim, interfacePriv->bcTimSet);
+            return;
+        }
     } else if ((handle != 0xFFFFFFFF) && (handle >= UNIFI_MAX_CONNECTIONS)) {
         unifi_warning(priv, "bad station Handle = %x\n", handle);
         return;
@@ -785,6 +928,25 @@ void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 i
         if (staRecord) {
             staRecord->timSet = oldTimSetStatus ;
         }
+        else
+        {
+            /* MLME_SET_TIM.req sending failed here for AID0, so revert back our bcTimSet status */
+            interfacePriv->bcTimSet = !setTim;
+        }
+    }
+    else {
+        /* Update tim request pending flag and ensure no more TIM set requests are send
+           for the same station until TIM confirm is received */
+        if (staRecord) {
+            staRecord->timRequestPendingFlag = TRUE;
+        }
+        else
+        {
+            /* Update tim request (for AID 0) pending flag and ensure no more DTIM set requests are send
+             * for the same station until TIM confirm is received
+             */
+            interfacePriv->bcTimSetReqPendingFlag = TRUE;
+        }
     }
     unifi_trace(priv, UDBG5, "leaving the update_tim routine\n");
 }
@@ -804,12 +966,30 @@ void process_peer_active_transition(unifi_priv_t * priv,
 
     if(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) {
         /* giving more priority to multicast packets so delaying unicast packets*/
-        unifi_trace(priv,UDBG2," multicast transmission is going on so resume unicast transmission after DTIM over\n");
+        unifi_trace(priv,UDBG2, "Multicast transmission is going on so resume unicast transmission after DTIM over\n");
+
+        /* As station is active now, even though AP is not able to send frames to it
+         * because of DTIM, it needs to reset the TIM here
+         */
+        if (!staRecord->timRequestPendingFlag){
+            if((staRecord->timSet == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)){
+                update_tim(priv, staRecord->aid, 0, interfaceTag, staRecord->assignedHandle);
+            }
+        }
+        else
+        {
+            /* Cache the TimSet value so that it will processed immidiatly after
+             * completing the current setTim Request
+             */
+            staRecord->updateTimReqQueued = 0;
+            unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                        staRecord->aid);
+        }
         return;
     }
     while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) {
         buffered_pkt->transmissionControl &=
-                     ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+                     ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK);
         if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) {
             unifi_trace(priv, UDBG2, "p_p_a_t:(ENOSPC) Mgt Frame queueing \n");
             /* Enqueue at the head of the queue */
@@ -828,11 +1008,22 @@ void process_peer_active_transition(unifi_priv_t * priv,
             kfree(buffered_pkt);
         }
     }
-    if (staRecord->txSuspend) {
-        if(staRecord->timSet == CSR_WIFI_TIM_SET) {
-            update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+    if (!staRecord->timRequestPendingFlag) {
+        if (staRecord->txSuspend) {
+            if(staRecord->timSet == CSR_WIFI_TIM_SET) {
+                update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+            }
+            return;
         }
-        return;
+    }
+    else
+    {
+        /* Cache the TimSet value so that it will processed immidiatly after
+         * completing the current setTim Request
+         */
+        staRecord->updateTimReqQueued = 0;
+        unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                    staRecord->aid);
     }
     for(i=3;i>=0;i--) {
         if(!spaceAvail[i])
@@ -840,7 +1031,7 @@ void process_peer_active_transition(unifi_priv_t * priv,
         unifi_trace(priv, UDBG6, "p_p_a_t:data pkt sending for AC %d \n",i);
         while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) {
            buffered_pkt->transmissionControl &=
-                      ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+                      ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK);
            if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) {
                /* Clear the trigger bit transmission control*/
                /* Enqueue at the head of the queue */
@@ -859,9 +1050,20 @@ void process_peer_active_transition(unifi_priv_t * priv,
            }
         }
     }
-    if((staRecord->timSet  == CSR_WIFI_TIM_SET) || (staRecord->timSet == CSR_WIFI_TIM_SETTING)){
-        unifi_trace(priv, UDBG3, "p_p_a_t:resetting tim .....\n");
-        update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+    if (!staRecord->timRequestPendingFlag){
+        if((staRecord->timSet  == CSR_WIFI_TIM_SET) || (staRecord->timSet  == CSR_WIFI_TIM_SETTING)) {
+            unifi_trace(priv, UDBG3, "p_p_a_t:resetting tim .....\n");
+            update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+        }
+    }
+    else
+    {
+        /* Cache the TimSet value so that it will processed immidiatly after
+         * completing the current setTim Request
+         */
+        staRecord->updateTimReqQueued = 0;
+        unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                    staRecord->aid);
     }
     unifi_trace(priv, UDBG5, "leaving process_peer_active_transition\n");
 }
@@ -873,14 +1075,6 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,CsrUint16 interfaceTag, con
     netInterface_priv_t *interfacePriv;
     CsrUint8 i;
     CsrWifiRouterCtrlStaInfo_t *staRecord = NULL;
-    struct list_head *listHeadMaPktreq,*listHeadStaQueue;
-    struct list_head *placeHolderMaPktreq,*placeHolderStaQueue;
-    unsigned long lock_flags;
-    unsigned long lock_flags1;
-    maPktReqList_t *maPktreq = NULL;
-    tx_buffered_packets_t *tx_q_item = NULL;
-    bulk_data_param_t bulkdata;
-    CsrBool entryFound = FALSE;
     interfacePriv = priv->interfacePriv[interfaceTag];
 
 
@@ -892,260 +1086,113 @@ void uf_process_ma_pkt_cfm_for_ap(unifi_priv_t *priv,CsrUint16 interfaceTag, con
          if(list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) &&
               list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) {
             unifi_trace(priv,UDBG1,"Resetting multicastTIM");
-            update_tim(priv,0,0,interfaceTag, 0xFFFFFFFF);
-        }
-        return;
-    }
-
-    /* Check if a copy of the same frame (identified by host tag) is queued in driver */
-    spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-    list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) {
-        maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q);
-        if(maPktreq->hostTag == pkt_cfm->HostTag){
-            entryFound = TRUE;
-            break;
-        }
-    }
-    spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-
-    if(entryFound){
-
-        /* Monitor the time difference between the MA-PACKET.req and MA-PACKET.cfm */
-        unsigned long timeout;
-        timeout = (long)jiffies - (long)maPktreq->jiffeTime;
-
-        /* convert into milliseconds */
-        timeout = jiffies_to_msecs(timeout);
-        unifi_trace(priv, UDBG3, "Jiffies Time: Host Tag(%x) --> Req(%u) Cfm(%u) Diff (in ms): %u\n",maPktreq->hostTag,maPktreq->jiffeTime, jiffies, timeout);
-
-        if( (timeout/1000) > 1)
-        {
-             unifi_trace(priv, UDBG1, "Confirm time > 2 Seconds: time = %u Status = %x\n", (timeout/1000), pkt_cfm->TransmissionStatus);
-        }
-
-       if( CSR_TX_LIFETIME == pkt_cfm->TransmissionStatus  ||
-           CSR_TX_BLOCK_ACK_TIMEOUT== pkt_cfm->TransmissionStatus ||
-           CSR_TX_FAIL_TRANSMISSION_VIF_INTERRUPTED== pkt_cfm->TransmissionStatus ||
-           CSR_TX_REJECTED_PEER_STATION_SLEEPING== pkt_cfm->TransmissionStatus ||
-           CSR_TX_REJECTED_DTIM_STARTED== pkt_cfm->TransmissionStatus ){
-
-         CsrWifiRouterCtrlStaInfo_t *staRecord = interfacePriv->staInfo[maPktreq->staHandler];
-         unifi_TrafficQueue priority_q;
-         struct list_head *list;
-         CsrResult result;
-         CSR_MA_PACKET_REQUEST *req = &maPktreq->signal.u.MaPacketRequest;
-         CsrUint16 ii=0;
-         CsrBool locationFound = FALSE;
-         CsrUint8 *sigbuffer;
-
-         sigbuffer = (CsrUint8*)&maPktreq->signal;
-         if(req->Priority == CSR_MANAGEMENT){
-             list = &staRecord->mgtFrames;
-             unifi_trace(priv,UDBG5,"mgmt list priority %d\n",req->Priority);
-         }
-         else{
-             priority_q= unifi_frame_priority_to_queue(req->Priority);
-             list = &staRecord->dataPdu[priority_q];
-             unifi_trace(priv,UDBG5,"data list priority %d\n",req->Priority);
-         }
-
-         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-         list_for_each_safe(listHeadStaQueue, placeHolderStaQueue, list){
-             tx_q_item = list_entry(listHeadStaQueue, tx_buffered_packets_t, q);
-           COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item->hostTag ,maPktreq->hostTag)
-
-
-         }
-         if(sigbuffer[SIZEOF_SIGNAL_HEADER + 1]){
-            skb_pull(maPktreq->skb,sigbuffer[SIZEOF_SIGNAL_HEADER + 1]);
-         }
-
-         /* enqueue the failed packet sta queue*/
-         bulkdata.d[0].os_net_buf_ptr= (unsigned char*)maPktreq->skb;
-         bulkdata.d[0].os_data_ptr = maPktreq->skb->data;
-         bulkdata.d[0].data_length = bulkdata.d[0].net_buf_length = maPktreq->skb->len;
-         bulkdata.d[1].os_data_ptr = NULL;
-         bulkdata.d[1].os_net_buf_ptr = NULL;
-         bulkdata.d[1].data_length = bulkdata.d[0].net_buf_length = 0;
-         unifi_trace(priv,UDBG4,"Cfm Fail for HosTag = %x with status %d so requeue it\n",maPktreq->hostTag,pkt_cfm->TransmissionStatus );
-         req->TransmissionControl = 0;
-
-         if(!locationFound){
-
-             if(list_empty(list)){
-                result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,1);
-             }
-             else{
-                  unifi_trace(priv,UDBG4,"did not find location so add to end of list \n");
-                  result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,0);
-             }
-
-
-         }
-
-         else {
-            if(ii > 1){
-                 unifi_trace(priv,UDBG4,"find the location in the middle of list \n");
-                 result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, listHeadStaQueue,&maPktreq->signal,0);
-
-            }
-            else{
-                unifi_trace(priv,UDBG4," add at begining of list \n");
-                result = enque_direceted_ma_pkt_cfm_data_pdu(priv, &bulkdata, list,&maPktreq->signal,1);
+            if (!interfacePriv->bcTimSetReqPendingFlag)
+            {
+                update_tim(priv,0,CSR_WIFI_TIM_RESET,interfaceTag, 0xFFFFFFFF);
             }
-         }
-
-         spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-
-         /* Increment the counter */
-         spin_lock_irqsave(&priv->staRecord_lock,lock_flags1);
-         staRecord->noOfPktQueued++;
-         spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags1);
-
-
-
-
-         /* after enqueuing update the TIM */
-         if(CSR_RESULT_SUCCESS == result){
-             if(CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE == staRecord->currentPeerState) {
-                if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) {
-                    if(!staRecord->wmmOrQosEnabled) {
-                        unifi_trace(priv, UDBG3, "uf_process_ma_pkt_cfm_for_ap :tim set due to unicast pkt & peer in powersave\n");
-                        update_tim(priv,staRecord->aid,1,interfaceTag, staRecord->assignedHandle);
-                    }
-                    else {
-                        /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */
-                        CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
-                        /* Check if all AC's are Delivery Enabled */
-                        is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable);
-                        if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)) {
-                            update_tim(priv,staRecord->aid,1,interfaceTag, staRecord->assignedHandle);
-                        }
-                    }
-                }
-             }
-         }
-         else{
-            dev_kfree_skb(maPktreq->skb);
-         }
-       }
-      else
-      {
-        CsrWifiRouterCtrlStaInfo_t *staRecord = interfacePriv->staInfo[maPktreq->staHandler];
-        if (CSR_TX_RETRY_LIMIT == pkt_cfm->TransmissionStatus ||
-            CSR_TX_NO_BSS == pkt_cfm->TransmissionStatus)
-        {
-            if (staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING)
+            else
             {
-                unifi_trace(priv, UDBG2, "CFM failed with Retry Limit or No BSS --> update TIM\n");
-                update_tim(priv, staRecord->aid, 1, interfaceTag, staRecord->assignedHandle);
+                /* Cache the DTimSet value so that it will processed immidiatly after
+                 * completing the current setDTim Request
+                 */
+                 interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET;
+                 unifi_trace(priv, UDBG2, "uf_process_ma_pkt_cfm_for_ap : One more UpdateDTim Request(%d) Queued \n",
+                             interfacePriv->bcTimSetReqQueued);
             }
+
         }
-        else if (CSR_TX_SUCCESSFUL == pkt_cfm->TransmissionStatus)
-        {
-            staRecord->activity_flag = TRUE;
-        }
-        unifi_trace(priv, UDBG5, "CFM for HosTag = %x Status = %d, Free SKB reference\n",
-                    maPktreq->hostTag,
-                    pkt_cfm->TransmissionStatus );
+        return;
+    }
 
-        dev_kfree_skb(maPktreq->skb);
+    /* Check if it is a Confirm for null data frame used
+     * for probing station activity
+     */
+    for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) {
+        staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]);
+        if (staRecord && (staRecord->nullDataHostTag == pkt_cfm->HostTag)) {
+
+            unifi_trace(priv, UDBG1, "CFM for Inactive probe Null frame (tag = %x, status = %d)\n",
+                                    pkt_cfm->HostTag,
+                                    pkt_cfm->TransmissionStatus
+                                    );
+            staRecord->nullDataHostTag = INVALID_HOST_TAG;
+
+            if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){
+                CsrTime now;
+                CsrTime inactive_time;
+
+                unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n");
+                /* Recheck if there is some activity after null data is sent.
+                *
+                * If still there is no activity then send a disconnected indication
+                * to SME to delete the station record.
+                */
+                if (staRecord->activity_flag){
+                    return;
+                }
+                now = CsrTimeGet(NULL);
 
-      }
-      list_del(listHeadMaPktreq);
-      kfree(maPktreq);
+                if (staRecord->lastActivity > now)
+                {
+                    /* simple timer wrap (for 1 wrap) */
+                    inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity),
+                                               now);
+                }
+                else
+                {
+                    inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity);
+                }
 
-    }else{
-        /* Check if it is a Confirm for null data frame used
-         * for probing station activity
-         */
-        for(i =0; i < UNIFI_MAX_CONNECTIONS; i++) {
-            staRecord = (CsrWifiRouterCtrlStaInfo_t *) (interfacePriv->staInfo[i]);
-            if (staRecord && (staRecord->nullDataHostTag == pkt_cfm->HostTag)) {
-
-                unifi_trace(priv, UDBG1, "CFM for Inactive probe Null frame (tag = %x, status = %d)\n",
-                                        pkt_cfm->HostTag,
-                                        pkt_cfm->TransmissionStatus
-                                        );
-                staRecord->nullDataHostTag = INVALID_HOST_TAG;
-
-                if(pkt_cfm->TransmissionStatus == CSR_TX_RETRY_LIMIT){
-                    CsrTime now;
-                    CsrTime inactive_time;
-
-                    unifi_trace(priv, UDBG1, "Nulldata to probe STA ALIVE Failed with retry limit\n");
-                    /* Recheck if there is some activity after null data is sent.
-                    *
-                    * If still there is no activity then send a disconnected indication
-                    * to SME to delete the station record.
-                    */
-                    if (staRecord->activity_flag){
-                        return;
-                    }
-                    now = CsrTimeGet(NULL);
+                if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL)
+                {
+                    struct list_head send_cfm_list;
+                    CsrUint8 j;
+
+                    /* The SME/NME may be waiting for confirmation for requested frames to this station.
+                     * Though this is --VERY UNLIKELY-- in case of station in active mode. But still as a
+                     * a defensive check, it loops through buffered frames for this station and if confirmation
+                     * is requested, send auto confirmation with failure status. Also flush the frames so
+                     * that these are not processed again in PEER_DEL_REQ handler.
+                     */
+                    INIT_LIST_HEAD(&send_cfm_list);
 
-                    if (staRecord->lastActivity > now)
-                    {
-                        /* simple timer wrap (for 1 wrap) */
-                        inactive_time = CsrTimeAdd((CsrTime)CsrTimeSub(CSR_SCHED_TIME_MAX, staRecord->lastActivity),
-                                                   now);
-                    }
-                    else
-                    {
-                        inactive_time = (CsrTime)CsrTimeSub(now, staRecord->lastActivity);
-                    }
+                    uf_prepare_send_cfm_list_for_queued_pkts(priv,
+                                                             &send_cfm_list,
+                                                             &(staRecord->mgtFrames));
 
-                    if (inactive_time >= STA_INACTIVE_TIMEOUT_VAL)
-                    {
-                        struct list_head send_cfm_list;
-                        CsrUint8 j;
-
-                        /* The SME/NME may be waiting for confirmation for requested frames to this station.
-                         * Though this is --VERY UNLIKELY-- in case of station in active mode. But still as a
-                         * a defensive check, it loops through buffered frames for this station and if confirmation
-                         * is requested, send auto confirmation with failure status. Also flush the frames so
-                         * that these are not processed again in PEER_DEL_REQ handler.
-                         */
-                        INIT_LIST_HEAD(&send_cfm_list);
+                    uf_flush_list(priv, &(staRecord->mgtFrames));
 
+                    for(j = 0; j < MAX_ACCESS_CATOGORY; j++){
                         uf_prepare_send_cfm_list_for_queued_pkts(priv,
                                                                  &send_cfm_list,
-                                                                 &(staRecord->mgtFrames));
-
-                        uf_flush_list(priv, &(staRecord->mgtFrames));
+                                                                 &(staRecord->dataPdu[j]));
 
-                        for(j = 0; j < MAX_ACCESS_CATOGORY; j++){
-                            uf_prepare_send_cfm_list_for_queued_pkts(priv,
-                                                                     &send_cfm_list,
-                                                                     &(staRecord->dataPdu[j]));
-
-                            uf_flush_list(priv,&(staRecord->dataPdu[j]));
-                        }
-
-                        send_auto_ma_packet_confirm(priv, staRecord->interfacePriv, &send_cfm_list);
+                        uf_flush_list(priv,&(staRecord->dataPdu[j]));
+                    }
 
+                    send_auto_ma_packet_confirm(priv, staRecord->interfacePriv, &send_cfm_list);
 
 
-                        unifi_warning(priv, "uf_process_ma_pkt_cfm_for_ap: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n",
-                                                 staRecord->peerMacAddress.a[0],
-                                                 staRecord->peerMacAddress.a[1],
-                                                 staRecord->peerMacAddress.a[2],
-                                                 staRecord->peerMacAddress.a[3],
-                                                 staRecord->peerMacAddress.a[4],
-                                                 staRecord->peerMacAddress.a[5]);
 
-                        CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,
-                                                          0,
-                                                          staRecord->interfacePriv->InterfaceTag,
-                                                          staRecord->peerMacAddress,
-                                                          CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED);
-                    }
+                    unifi_warning(priv, "uf_process_ma_pkt_cfm_for_ap: Router Disconnected IND Peer (%x-%x-%x-%x-%x-%x)\n",
+                                             staRecord->peerMacAddress.a[0],
+                                             staRecord->peerMacAddress.a[1],
+                                             staRecord->peerMacAddress.a[2],
+                                             staRecord->peerMacAddress.a[3],
+                                             staRecord->peerMacAddress.a[4],
+                                             staRecord->peerMacAddress.a[5]);
 
+                    CsrWifiRouterCtrlConnectedIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,
+                                                      0,
+                                                      staRecord->interfacePriv->InterfaceTag,
+                                                      staRecord->peerMacAddress,
+                                                      CSR_WIFI_ROUTER_CTRL_PEER_DISCONNECTED);
                 }
-                else if (pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL)
-                {
-                     staRecord->activity_flag = TRUE;
-                }
+
+            }
+            else if (pkt_cfm->TransmissionStatus == CSR_TX_SUCCESSFUL)
+            {
+                 staRecord->activity_flag = TRUE;
             }
         }
     }
@@ -1336,16 +1383,16 @@ static int update_macheader(unifi_priv_t *priv, struct sk_buff *skb,
                 CsrResult csrResult;
                 unifi_trace(priv, UDBG5, "normal Data packet, NO QOS \n");
 
-                *priority = CSR_CONTENTION;
                 if (qosDestination) {
                     CsrUint8 qc = 0;
                     unifi_trace(priv, UDBG3, "destination is QOS station \n");
-                    /* prepare the qos control field */
 
-                    qc |= CSR_QOS_UP0;
+                    /* Set Ma-Packet.req UP to UP0 */
+                    *priority = CSR_QOS_UP0;
 
+                    /* prepare the qos control field */
+                    qc |= CSR_QOS_UP0;
                     /* no Amsdu is in ap buffer so eosp is left 0 */
-
                     if (da[0] & 0x1) {
                         /* multicast/broadcast frames, no acknowledgement needed */
                         qc |= 1 << 5;
@@ -1763,9 +1810,6 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
                      */
 
                     list = &interfacePriv->genericMulticastOrBroadCastMgtFrames;
-                    spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-                    interfacePriv->noOfbroadcastPktQueued++;
-                    spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
                     if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS) &&
                             (list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
                         setBcTim=TRUE;
@@ -1789,11 +1833,9 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
                         /* if multicast traffic is going on, buffet the unicast packets */
                         unifi_trace(priv, UDBG2, "Enqueued to staRecord->dataPdu[%d] queuePacketDozing=%d,\
                                 Buffering enabled = %d \n", priority_q,queuePacketDozing,isRouterBufferEnabled(priv,priority_q));
-                        signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED);
                         list = &staRecord->dataPdu[priority_q];
                     } else {
                         unifi_trace(priv, UDBG5, "staRecord->dataPdu[%d] list is empty uf_process_ma_packet_req \n", priority_q);
-                        signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED);
                         /* Pdu allowed to send to unifi */
                         result = ul_send_signal_unpacked(priv, &signal, bulkdata);
                         if(result == -ENOSPC) {
@@ -1816,9 +1858,6 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
                      * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM
                      */
                     list = &interfacePriv->genericMulticastOrBroadCastFrames;
-                    spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-                    interfacePriv->noOfbroadcastPktQueued++;
-                    spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
                     if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) {
                         setBcTim = TRUE;
                     }
@@ -1838,10 +1877,30 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
             staRecord->noOfPktQueued++;
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
         }
+        else if ((pktType == CSR_WIFI_MULTICAST_PDU) && (!status))
+        {
+            /* If broadcast Tim is set && queuing is successfull, then only update TIM */
+            spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
+            interfacePriv->noOfbroadcastPktQueued++;
+            spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
+        }
     }
-    if(setBcTim) {
+    /* If broadcast Tim is set && queuing is successfull, then only update TIM */
+    if(setBcTim && !status) {
         unifi_trace(priv, UDBG3, "tim set due to broadcast pkt\n");
-        update_tim(priv,0,1,interfaceTag, handle);
+        if (!interfacePriv->bcTimSetReqPendingFlag)
+        {
+            update_tim(priv,0,CSR_WIFI_TIM_SET,interfaceTag, handle);
+        }
+        else
+        {
+            /* Cache the TimSet value so that it will processed immidiatly after
+            * completing the current setTim Request
+            */
+            interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_SET;
+            unifi_trace(priv, UDBG2, "uf_process_ma_packet_req : One more UpdateDTim Request(:%d) Queued \n",
+                        interfacePriv->bcTimSetReqQueued);
+        }
     } else if(staRecord && staRecord->currentPeerState ==
                             CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) {
         if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) {
@@ -1850,15 +1909,38 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
                    !list_empty(&staRecord->dataPdu[3]) ||
                    !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])) {
                     unifi_trace(priv, UDBG3, "tim set due to unicast pkt & peer in powersave\n");
-                    update_tim(priv,staRecord->aid,1,interfaceTag, handle);
-                }
-            } else {
-                /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */
-                CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
+                    if (!staRecord->timRequestPendingFlag){
+                        update_tim(priv,staRecord->aid,1,interfaceTag, handle);
+                    }
+                    else
+                    {
+                        /* Cache the TimSet value so that it will processed immidiatly after
+                         * completing the current setTim Request
+                         */
+                        staRecord->updateTimReqQueued = 1;
+                        unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                                    staRecord->aid);
+                    }
+                }
+            } else {
+                /* Check for non delivery enable(i.e trigger enable), all delivery enable & legacy AC for TIM update in firmware */
+                CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
                 /* Check if all AC's are Delivery Enabled */
                 is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable);
-                if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)) {
-                    update_tim(priv,staRecord->aid,1,interfaceTag, handle);
+                if (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable)
+                    || (!list_empty(&staRecord->mgtFrames))) {
+                    if (!staRecord->timRequestPendingFlag) {
+                        update_tim(priv,staRecord->aid,1,interfaceTag, handle);
+                    }
+                    else
+                    {
+                        /* Cache the TimSet value so that it will processed immidiatly after
+                         * completing the current setTim Request
+                         */
+                        staRecord->updateTimReqQueued = 1;
+                        unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                                    staRecord->aid);
+                    }
                 }
             }
         }
@@ -1945,7 +2027,7 @@ CsrUint8 send_multicast_frames(unifi_priv_t *priv, CsrUint16 interfaceTag)
     if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_VO)) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
             buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK);
-            moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK)?FALSE:TRUE;
+            moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK)?FALSE:TRUE;
 
 
             unifi_trace(priv,UDBG2,"DTIM Occurred for interface:sending Mgt packet %d\n",interfaceTag);
@@ -1986,7 +2068,7 @@ CsrUint8 send_multicast_frames(unifi_priv_t *priv, CsrUint16 interfaceTag)
     if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_CONTENTION)) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastFrames))) {
             buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK;
-            moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK)?FALSE:TRUE;
+            moreData = (buffered_pkt->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK)?FALSE:TRUE;
 
 
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,moreData,FALSE)) == -ENOSPC) {
@@ -2076,7 +2158,19 @@ void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,CsrUint8 *sigdata,
             if(interfacePriv->multicastPduHostTag == 0xffffffff) {
                 unifi_notice(priv,"ma_vif_availibility_ind recevied for multicast but queues are empty%d\n",interfaceTag);
                 /* This may be an extra request in very rare race conditions but it is fine as it would atleast remove the potential lock up */
-                update_tim(priv,0,0,interfaceTag, 0xFFFFFFFF);
+                if (!interfacePriv->bcTimSetReqPendingFlag)
+                {
+                    update_tim(priv,0,CSR_WIFI_TIM_RESET,interfaceTag, 0xFFFFFFFF);
+                }
+                else
+                {
+                    /* Cache the TimSet value so that it will processed immidiatly after
+                     * completing the current setTim Request
+                     */
+                    interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET;
+                    unifi_trace(priv, UDBG2, "uf_process_ma_vif_availibility_ind : One more UpdateDTim Request(%d) Queued \n",
+                                interfacePriv->bcTimSetReqQueued);
+                }
             }
             return;
         }
@@ -2105,59 +2199,62 @@ void uf_process_ma_vif_availibility_ind(unifi_priv_t *priv,CsrUint8 *sigdata,
 
 #define  GET_ACTIVE_INTERFACE_TAG(priv) 0
 
-
-void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo)
+static CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t *staRecord)
 {
-
     CsrInt8 i;
 
-    func_enter();
-
-    if(((staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)||
-         (staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE))
-        &&(!list_empty(&staInfo->mgtFrames))){
-
-        unifi_trace(priv, UDBG5, "uf_continue_uapsd : U-APSD ACTIVE and sending buffered mgt frames\n");
-        uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames);
-
-        /*This may happen because U-APSD was completed
-         with previous AC transfer*/
-
-        if(staInfo->uapsdActive == FALSE) {
-           return;
+    for(i=UNIFI_TRAFFIC_Q_VO; i >= UNIFI_TRAFFIC_Q_BK; i--)
+    {
+        if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)
+             ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))
+             &&(!list_empty(&staRecord->dataPdu[i]))) {
+            unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data Available AC = %d\n", i);
+            return TRUE;
         }
     }
 
-    for(i=3;i>=0;i--) {
+    unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data NOT Available \n");
+    return FALSE;
+}
 
-        if(((staInfo->powersaveMode[i]== CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)
-             ||(staInfo->powersaveMode[i] == CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))
-             &&(!list_empty(&staInfo->dataPdu[i]))) {
-            unifi_trace(priv, UDBG5, "uf_continue_uapsd : U-APSD ACTIVE and sending buffered  data frames\n");
-            uf_send_buffered_data_from_delivery_ac(priv, staInfo, i, &staInfo->dataPdu[i]);
-        }
+static CsrBool uf_is_more_data_for_usp_delivery(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t *staRecord, unifi_TrafficQueue queue)
+{
+    CsrInt8 i;
 
-        /*This may happen because U-APSD was completed
-          with previous AC transfer*/
-        if (staInfo->uapsdActive == FALSE) {
-            return;
+    for(i = queue; i >= UNIFI_TRAFFIC_Q_BK; i--)
+    {
+        if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)
+             ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))
+             &&(!list_empty(&staRecord->dataPdu[i]))) {
+            unifi_trace(priv,UDBG2,"uf_is_more_data_for_usp_delivery: Data Available AC = %d\n", i);
+            return TRUE;
         }
     }
 
-    if (staInfo->uapsdActive && !uf_is_more_data_for_delivery_ac(priv, staInfo, TRUE)) {
-        /* If last packet not able to transfer due to ENOSPC & buffer management algorithm
-         * would have removed last packet. Then we wont update staInfo->UapsdActive = FALSE (suppose
-         * to update as we dont have packet to transfer at this USP) because above if loop fails as list is empty &
-         * update of UAPSD activity done in uf_send_buffered_data_from_delivery_ac().
-         * In this situation we send QOS null & mean time update UapsdActive to FALSE here
-         */
-        staInfo->uapsdActive = FALSE;
-        uf_send_qos_null(priv, GET_ACTIVE_INTERFACE_TAG(priv), staInfo->peerMacAddress.a, CSR_QOS_UP0 , staInfo);
-    }
-    func_exit();
+    unifi_trace(priv,UDBG2,"uf_is_more_data_for_usp_delivery: Data NOT Available \n");
+    return FALSE;
 }
 
-
+/*
+ * ---------------------------------------------------------------------------
+ *  uf_send_buffered_data_from_delivery_ac
+ *
+ *      This function takes care of
+ *      -> Parsing the delivery enabled queue & sending frame down to HIP
+ *      -> Setting EOSP=1 when USP to be terminated
+ *      -> Depending on MAX SP length services the USP
+ *
+ * NOTE:This function always called from uf_handle_uspframes_delivery(), Dont
+ *      call this function from any other location in code
+ *
+ *  Arguments:
+ *      priv        Pointer to device private context struct
+ *      vif         interface specific HIP vif instance
+ *      staInfo     peer for which UAPSD to be scheduled
+ *      queue       AC from which Data to be sent in USP
+ *      txList      access category for processing list
+ * ---------------------------------------------------------------------------
+ */
 void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv,
                                             CsrWifiRouterCtrlStaInfo_t * staInfo,
                                             CsrUint8 queue,
@@ -2170,117 +2267,94 @@ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv,
     CsrBool eosp=FALSE;
     CsrInt8 r =0;
     CsrBool moreData = FALSE;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
 
-    CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
-    netInterface_priv_t *interfacePriv;
-    interfacePriv = priv->interfacePriv[interfaceTag];
-    func_enter();
-
-    /*Check U-APSD conditions if not met return from here*/
-    if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)&&
-        (staInfo->uapsdActive == TRUE)&&
-        (!IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[queue]))){
-
-        unifi_trace(priv,UDBG4,"uf_send_buffered_data_from_queue : U-APSD active. %d :Queue NOT delivery enbaled.return %\n",queue);
+    unifi_trace(priv, UDBG2, "++uf_send_buffered_data_from_delivery_ac, active=%x\n", staInfo->uapsdActive);
 
+    if (queue > UNIFI_TRAFFIC_Q_VO)
+    {
         return;
-     }
+    }
+    while((buffered_pkt=dequeue_tx_data_pdu(priv, txList))) {
+        if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))) {
+            unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: DTIM Active, suspend UAPSD, staId: 0x%x\n",
+                        staInfo->aid);
 
-    while(!isRouterBufferEnabled(priv,queue) &&
-                    ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){
-        if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){
+            /* Once resume called, the U-APSD delivery operation will resume */
             spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-            staInfo->uapsdSuspended = TRUE;
-            staInfo->uapsdActive = FALSE;
+            staInfo->uspSuspend = TRUE;
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
             /* re-queueing the packet as DTIM started */
             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
             list_add(&buffered_pkt->q,txList);
             spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-            unifi_trace(priv, UDBG3, "%s: DTIM Active while UAPSD in progress for staId: 0x%x\n",__FUNCTION__,staInfo->aid);
             break;
         }
 
         buffered_pkt->transmissionControl &=
-                 ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
-
+                 ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
 
-        if((staInfo->wmmOrQosEnabled == TRUE)&&(staInfo->uapsdActive == TRUE)){
 
-            moreData = uf_is_more_data_for_delivery_ac(priv,staInfo,TRUE);
+        if((staInfo->wmmOrQosEnabled == TRUE)&&(staInfo->uapsdActive == TRUE)) {
 
              buffered_pkt->transmissionControl = TRANSMISSION_CONTROL_TRIGGER_MASK;
 
-            if(staInfo->noOfSpFramesSent == (staInfo->maxSpLength-1)){
-                moreData = FALSE;
-            }
-
-            if(moreData == FALSE){
-                 eosp = TRUE;
-                 staInfo->uapsdActive = FALSE;
-                 staInfo->noOfSpFramesSent = FALSE;
-                 buffered_pkt->transmissionControl =
-                          (TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+             /* Check All delivery enables Ac for more data, because caller of this
+              * function not aware about last packet
+              * (First check in moreData fetching helps in draining out Mgt frames Q)
+              */
+              moreData = (!list_empty(txList) || uf_is_more_data_for_usp_delivery(priv, staInfo, queue));
 
-                /* Check if all AC's are Delivery Enabled */
-                is_all_ac_deliver_enabled_and_moredata(staInfo, &allDeliveryEnabled, &dataAvailable);
-                if ((allDeliveryEnabled && !dataAvailable)) {
-                    update_tim(priv,staInfo->aid,0,interfaceTag, staInfo->assignedHandle);
-                }
-                /* check the moer data for non delivery ac and update accordingly */
-                else if(uf_is_more_data_for_non_delivery_ac(staInfo) ) {
-                    update_tim(priv,staInfo->aid,1,interfaceTag, staInfo->assignedHandle);
-                }
-                else if(!uf_is_more_data_for_non_delivery_ac(staInfo) ){
-                     unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_send_buffered_data_from_delivery_ac\n");
-                     update_tim(priv,staInfo->aid,0,interfaceTag, staInfo->assignedHandle);
-                }
+              if(staInfo->noOfSpFramesSent == (staInfo->maxSpLength - 1)) {
+                  moreData = FALSE;
+              }
 
-             }
-        }
-        else
-        {
-          /*Non QoS and non U-APSD.*/
-            eosp = FALSE;
-            moreData = FALSE;
-            unifi_warning(priv,"uf_send_buffered_data_from_delivery_ac :non U-APSD !!! \n");
+              if(moreData == FALSE) {
+                  eosp = TRUE;
+                  buffered_pkt->transmissionControl =
+                      (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
+              }
+        } else {
+            /* Non QoS and non U-APSD */
+            unifi_warning(priv, "uf_send_buffered_data_from_delivery_ac: non U-APSD !!! \n");
         }
 
         unifi_trace(priv,UDBG2,"uf_send_buffered_data_from_delivery_ac : MoreData:%d, EOSP:%d\n",moreData,eosp);
 
         if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,moreData,eosp)) == -ENOSPC) {
-           /* Enqueue at the head of the queue */
-           spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-           list_add(&buffered_pkt->q,txList);
-           spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-           priv->pausedStaHandle[queue]=(CsrUint8)(staInfo->assignedHandle);
-           unifi_notice (priv," U-APSD: PDU sending failed .. no space for queue %d \n",queue);
-           /*Break the loop for this queue.Try for next available Delivery enabled
-           Queue*/
-           break;
+
+            unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: UASPD suspended, ENOSPC in hipQ=%x\n", queue);
+
+            /* Once resume called, the U-APSD delivery operation will resume */
+            spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
+            staInfo->uspSuspend = TRUE;
+            spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
+
+            spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
+            list_add(&buffered_pkt->q,txList);
+            spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
+            priv->pausedStaHandle[queue]=(CsrUint8)(staInfo->assignedHandle);
+            break;
         } else {
             if(r){
                 /* the PDU failed where we can't do any thing so free the storage */
                 unifi_net_data_free(priv, &buffered_pkt->bulkdata);
             }
-
             kfree(buffered_pkt);
-            if(staInfo->uapsdActive == TRUE){
-                    spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-                    staInfo->noOfSpFramesSent = staInfo->noOfSpFramesSent + 1;
-                    if(staInfo->noOfSpFramesSent == staInfo->maxSpLength){
-                        staInfo->uapsdActive = FALSE;
-                        staInfo->noOfSpFramesSent = FALSE;
-                        spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
-                        break;
-                    }
+            spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
+            staInfo->noOfSpFramesSent++;
+            if((!moreData) || (staInfo->noOfSpFramesSent == staInfo->maxSpLength)) {
+                unifi_trace(priv, UDBG2, "uf_send_buffered_data_from_delivery_ac: Terminating USP\n");
+                staInfo->uapsdActive = FALSE;
+                staInfo->uspSuspend = FALSE;
+                staInfo->noOfSpFramesSent = 0;
                 spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
+                break;
             }
+            spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
         }
     }
-
-   func_exit();
-
+    unifi_trace(priv, UDBG2, "--uf_send_buffered_data_from_delivery_ac, active=%x\n", staInfo->uapsdActive);
 }
 
 void uf_send_buffered_data_from_ac(unifi_priv_t *priv,
@@ -2302,7 +2376,7 @@ void uf_send_buffered_data_from_ac(unifi_priv_t *priv,
                     ((buffered_pkt=dequeue_tx_data_pdu(priv, txList))!=NULL)){
 
         buffered_pkt->transmissionControl &=
-                 ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+                 ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK);
 
         unifi_trace(priv,UDBG3,"uf_send_buffered_data_from_ac : MoreData:%d, EOSP:%d\n",moreData,eosp);
 
@@ -2352,7 +2426,19 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
             moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) ||
              !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames));
             if(!moreData) {
-                update_tim(priv,0,0,interfaceTag, 0XFFFFFFFF);
+                if (!interfacePriv->bcTimSetReqPendingFlag)
+                {
+                    update_tim(priv,0,CSR_WIFI_TIM_RESET,interfaceTag, 0XFFFFFFFF);
+                }
+                else
+                {
+                    /* Cache the TimSet value so that it will processed immidiatly after
+                     * completing the current setTim Request
+                     */
+                    interfacePriv->bcTimSetReqQueued = CSR_WIFI_TIM_RESET;
+                    unifi_trace(priv, UDBG2, "uf_send_buffered_frames : One more UpdateDTim Request(%d) Queued \n",
+                                interfacePriv->bcTimSetReqQueued);
+                }
             }
         } else {
             moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) ||
@@ -2391,33 +2477,17 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
                     uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames);
                 }
             }
-            else if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
-                               &&(staInfo->uapsdActive == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]))){
-
-
-                if(!list_empty(&staInfo->mgtFrames)){
-                    /*UNIFI_TRAFFIC_Q_VO is delivery enabled push the managment frames out*/
-                    uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames);
-
-                }
-            }
 
             if(isRouterBufferEnabled(priv,queue)) {
                 unifi_notice(priv,"uf_send_buffered_frames : No space Left for queue = %d\n",queue);
                 break;
             }
         }
-
-
         /*push generic management frames out*/
-
-        if(!list_empty(&interfacePriv->genericMgtFrames)){
-
-        unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying generic mgt from queue=%d\n",queue);
-        uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &interfacePriv->genericMgtFrames);
-
+        if(!list_empty(&interfacePriv->genericMgtFrames)) {
+            unifi_trace(priv,UDBG2,"uf_send_buffered_frames : trying generic mgt from queue=%d\n",queue);
+            uf_send_buffered_data_from_ac(priv,staInfo, UNIFI_TRAFFIC_Q_VO, &interfacePriv->genericMgtFrames);
         }
-
     }
 
 
@@ -2431,14 +2501,14 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
         staInfo =  CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag);
         if(!staInfo) {
             startIndex ++;
-            if(startIndex >= UNIFI_MAX_CONNECTIONS){
+            if(startIndex >= UNIFI_MAX_CONNECTIONS) {
                 startIndex = 0;
             }
             continue;
         } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
-                   &&(staInfo->uapsdActive == FALSE)){
+                   &&(staInfo->uapsdActive == FALSE)) {
             startIndex ++;
-            if(startIndex >= UNIFI_MAX_CONNECTIONS){
+            if(startIndex >= UNIFI_MAX_CONNECTIONS) {
                 startIndex = 0;
             }
             continue;
@@ -2448,23 +2518,15 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
 
 
         if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)
-                           &&(staInfo->uapsdActive == FALSE)){
-
-           if(!list_empty(&staInfo->dataPdu[queue])){
+                           &&(staInfo->uapsdActive == FALSE)) {
+           if(!list_empty(&staInfo->dataPdu[queue])) {
 
-          /*Non-UAPSD case push the AC frames out*/
-            uf_send_buffered_data_from_ac(priv, staInfo, queue, (&staInfo->dataPdu[queue]));
+               /*Non-UAPSD case push the AC frames out*/
+               uf_send_buffered_data_from_ac(priv, staInfo, queue, (&staInfo->dataPdu[queue]));
            }
         }
-        else  if((staInfo != NULL)&&(staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
-                               &&(staInfo->uapsdActive == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staInfo->powersaveMode[queue]))){
-            if(!list_empty(&staInfo->dataPdu[queue])){
-            uf_send_buffered_data_from_delivery_ac(priv, staInfo, queue, &staInfo->dataPdu[queue]);
-            }
-        }
-
         startIndex ++;
-        if(startIndex >= UNIFI_MAX_CONNECTIONS){
+        if(startIndex >= UNIFI_MAX_CONNECTIONS) {
            startIndex = 0;
         }
     }
@@ -2474,47 +2536,14 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
         priv->pausedStaHandle[queue] = 0;
     }
 
-   /*U-APSD might have stopped because of pause.So restart it if U-APSD
-   was active with any of the station*/
-    for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) {
-        staInfo =  CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag);
-        if(!staInfo ) {
-            continue;
-        } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
-                   &&(staInfo->uapsdActive == TRUE)) {
-
-            /*U-APSD Still active, it means trigger frame is received,so continue U-APSD by
-            sending data from remaining delivery enabled queues*/
-            uf_continue_uapsd(priv,staInfo);
-        }
-    }
+    /* U-APSD might have stopped because of ENOSPC in lib_hip (pause activity).
+     * So restart it if U-APSD was active with any of the station
+     */
+    unifi_trace(priv, UDBG4, "csrWifiHipSendBufferedFrames: UAPSD Resume Q=%x\n", queue);
+    resume_suspended_uapsd(priv, interfaceTag);
     func_exit();
 }
 
-CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck)
-{
-    CsrUint8 i;
-
-    for(i=0;i<=3;i++)
-    {
-     if(((staRecord->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)
-            ||(staRecord->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))
-            &&(!list_empty(&staRecord->dataPdu[i]))){
-          unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data Available \n");
-         return TRUE;
-        }
-    }
-    if((mgtCheck == TRUE)&&(IS_DELIVERY_AND_TRIGGER_ENABLED(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO]))
-        &&(!list_empty(&staRecord->mgtFrames))){
-
-        unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Management Data Available \n");
-
-        return TRUE;
-    }
-
-    unifi_trace(priv,UDBG2,"uf_is_more_data_for_delivery_ac: Data NOT Available \n");
-    return FALSE;
-}
 
 CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord)
 {
@@ -2584,101 +2613,148 @@ int uf_process_station_records_for_sending_data(unifi_priv_t *priv,CsrUint16 int
     return 0;
 }
 
-void uf_process_wmm_deliver_ac_uapsd(unifi_priv_t * priv,
-                                     CsrWifiRouterCtrlStaInfo_t * srcStaInfo,
-                                     CsrUint16 qosControl,
-                                     CsrUint16 interfaceTag)
+
+/*
+ * ---------------------------------------------------------------------------
+ *  uf_handle_uspframes_delivery
+ *
+ *      This function takes care of handling USP session for peer, when
+ *      -> trigger frame from peer
+ *      -> suspended USP to be processed (resumed)
+ *
+ *      NOTE: uf_send_buffered_data_from_delivery_ac() always called from this function, Dont
+ *      make a direct call to uf_send_buffered_data_from_delivery_ac() from any other part of
+ *      code
+ *
+ *  Arguments:
+ *      priv            Pointer to device private context struct
+ *      staInfo         peer for which UAPSD to be scheduled
+ *      interfaceTag    virtual interface tag
+ * ---------------------------------------------------------------------------
+ */
+static void uf_handle_uspframes_delivery(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo_t *staInfo, CsrUint16 interfaceTag)
 {
 
-    CSR_PRIORITY priority;
     CsrInt8 i;
-    unifi_TrafficQueue priority_q;
+    CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     unsigned long lock_flags;
 
-    func_enter();
-
-    /* start the U-APSD operation only if it not active*/
-    if(srcStaInfo->uapsdActive == FALSE){
-        /*if recceived Frames trigger Frame and Devlivery enabled AC has data
-         then transmit from High priorty delivery enabled AC*/
+    unifi_trace(priv, UDBG2, " ++ uf_handle_uspframes_delivery, uapsd active=%x, suspended?=%x\n",
+                staInfo->uapsdActive, staInfo->uspSuspend);
 
+    /* Check for Buffered frames according to priority order & deliver it
+     *  1. AC_VO delivery enable & Mgt frames available
+     *  2. Process remaining Ac's from order AC_VO to AC_BK
+     */
 
-        priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK);
-
-        priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority);
-
-      if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED)
-          ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){
+    /* USP initiated by WMMPS enabled peer  & SET the status flag to TRUE */
+    if (!staInfo->uspSuspend && staInfo->uapsdActive)
+    {
+        unifi_notice(priv, "uf_handle_uspframes_delivery: U-APSD already active! STA=%x:%x:%x:%x:%x:%x\n",
+                staInfo->peerMacAddress.a[0], staInfo->peerMacAddress.a[1],
+                staInfo->peerMacAddress.a[2], staInfo->peerMacAddress.a[3],
+                staInfo->peerMacAddress.a[4], staInfo->peerMacAddress.a[5]);
+        return;
+    }
 
-          unifi_trace(priv, UDBG3, "uf_process_wmm_deliver_ac_uapsd starting U-APSD operations\n");
+    spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
+    staInfo->uapsdActive = TRUE;
+    staInfo->uspSuspend = FALSE;
+    spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
 
-          /*Received Frame is trigger frame*/
-        unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : Received Frame is trigger frame %d\n",priority_q);
+    if(((staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)||
+        (staInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE))
+        && (!list_empty(&staInfo->mgtFrames))) {
 
-        if(((srcStaInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)||
-             (srcStaInfo->powersaveMode[UNIFI_TRAFFIC_Q_VO]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE))
-            &&(!list_empty(&srcStaInfo->mgtFrames))){
+         /* Management queue has data &&  UNIFI_TRAFFIC_Q_VO is delivery enable */
+        unifi_trace(priv, UDBG4, "uf_handle_uspframes_delivery: Sending buffered management frames\n");
+        uf_send_buffered_data_from_delivery_ac(priv, staInfo, UNIFI_TRAFFIC_Q_VO, &staInfo->mgtFrames);
+    }
 
-            /*Trigger frame received and Data available in Delivery enabled AC
-            or in Management queue when UNIFI_TRAFFIC_Q_VO is delivery enabled*/
+    if (!uf_is_more_data_for_delivery_ac(priv, staInfo)) {
+        /* All delivery enable AC's are empty, so QNULL to be sent to terminate the USP
+         * NOTE: If we have sent Mgt frame also, we must send QNULL followed to terminate USP
+         */
+        if (!staInfo->uspSuspend) {
             spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-            srcStaInfo->uapsdActive = TRUE;
+            staInfo->uapsdActive = FALSE;
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
 
-            unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : U-APSD ACTIVE and sending buffered mgt frames\n");
-
-           /* uf_send_buffered_frames(priv, priority_q); */
-            uf_send_buffered_data_from_delivery_ac(priv, srcStaInfo, UNIFI_TRAFFIC_Q_VO, &srcStaInfo->mgtFrames);
-
-
-           /*This may happen because U-APSD was completed
-            with previous AC transfer*/
-
-           if(srcStaInfo->uapsdActive == FALSE){
-              return;
-           }
-
-         }
-
-
-        for(i=3;i>=0;i--){
-
-            if(((srcStaInfo->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)
-                ||(srcStaInfo->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))
-                &&(!list_empty(&srcStaInfo->dataPdu[i]))){
-
-
-                 /*Trigger frame received and Data available in Delivery enabled AC
-                 or in Management queue when UNIFI_TRAFFIC_Q_VO is delivery enabled*/
-                 spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-                 srcStaInfo->uapsdActive = TRUE;
-                 spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
-
-                 unifi_trace(priv, UDBG5, "uf_process_wmm_deliver_ac_uapsd : U-APSD ACTIVE and sending buffered  data frames\n");
-
-                 uf_send_buffered_data_from_delivery_ac(priv, srcStaInfo, i, &srcStaInfo->dataPdu[i]);
+            unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: sending QNull for trigger\n");
+            uf_send_qos_null(priv, interfaceTag, staInfo->peerMacAddress.a, (CSR_PRIORITY) staInfo->triggerFramePriority, staInfo);
+            staInfo->triggerFramePriority = CSR_QOS_UP0;
+        } else {
+            unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: MgtQ xfer suspended\n");
+        }
+    } else {
+        for(i = UNIFI_TRAFFIC_Q_VO; i >= UNIFI_TRAFFIC_Q_BK; i--) {
+            if(((staInfo->powersaveMode[i]==CSR_WIFI_AC_DELIVERY_ONLY_ENABLE)
+                ||(staInfo->powersaveMode[i]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED))
+                && (!list_empty(&staInfo->dataPdu[i]))) {
+                /* Deliver Data according to AC priority (from VO to BK) as part of USP */
+                unifi_trace(priv, UDBG4, "uf_handle_uspframes_delivery: Buffered data frames from Queue (%d) for USP\n", i);
+                uf_send_buffered_data_from_delivery_ac(priv, staInfo, i, &staInfo->dataPdu[i]);
+            }
 
-                 /*This may happen because U-APSD was completed
-                  with previous AC transfer*/
+            if ((!staInfo->uapsdActive) ||
+                    (staInfo->uspSuspend && IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))) {
+                /* If DTIM active found on one AC, No need to parse the remaining AC's
+                 * as USP suspended. Break out of loop
+                 */
+                unifi_trace(priv, UDBG2, "uf_handle_uspframes_delivery: suspend=%x,  DTIM=%x, USP terminated=%s\n",
+                           staInfo->uspSuspend, IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag),
+                           staInfo->uapsdActive?"NO":"YES");
+                break;
+            }
+        }
+    }
 
-                 if(srcStaInfo->uapsdActive == FALSE){
-                    return;
-                 }
+    /* Depending on the USP status, update the TIM accordingly for delivery enabled AC only
+     * (since we are not manipulating any Non-delivery list(AC))
+     */
+    is_all_ac_deliver_enabled_and_moredata(staInfo, &allDeliveryEnabled, &dataAvailable);
+    if ((allDeliveryEnabled && !dataAvailable)) {
+        if ((staInfo->timSet != CSR_WIFI_TIM_RESET) || (staInfo->timSet != CSR_WIFI_TIM_RESETTING)) {
+            staInfo->updateTimReqQueued = (CsrUint8) CSR_WIFI_TIM_RESET;
+            unifi_trace(priv, UDBG4, " --uf_handle_uspframes_delivery, UAPSD timset\n");
+            if (!staInfo->timRequestPendingFlag) {
+                update_tim(priv, staInfo->aid, 0, interfaceTag, staInfo->assignedHandle);
             }
+        }
+    }
+    unifi_trace(priv, UDBG2, " --uf_handle_uspframes_delivery, uapsd active=%x, suspend?=%x\n",
+                staInfo->uapsdActive, staInfo->uspSuspend);
+}
 
-         }
-         if(srcStaInfo->uapsdActive == FALSE && !(uf_is_more_data_for_delivery_ac(priv,srcStaInfo,TRUE))){
-             unifi_trace(priv, UDBG3, "uf_process_wmm_deliver_ac_uapsd : No buffer frames so sending QOS Null in response of trigger frame\n");
-             uf_send_qos_null(priv,interfaceTag,srcStaInfo->peerMacAddress.a,priority,srcStaInfo);
-         }
+void uf_process_wmm_deliver_ac_uapsd(unifi_priv_t * priv,
+                                     CsrWifiRouterCtrlStaInfo_t * srcStaInfo,
+                                     CsrUint16 qosControl,
+                                     CsrUint16 interfaceTag)
+{
+    CSR_PRIORITY priority;
+    unifi_TrafficQueue priority_q;
+    unsigned long lock_flags;
 
-      }
+    unifi_trace(priv, UDBG2, "++uf_process_wmm_deliver_ac_uapsd: uapsdactive?=%x\n", srcStaInfo->uapsdActive);
+    /* If recceived Frames trigger Frame and Devlivery enabled AC has data
+     * then transmit from High priorty delivery enabled AC
+     */
+    priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK);
+    priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority);
 
-  }
+    if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED)
+        ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)) {
+        spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
+        srcStaInfo->triggerFramePriority = priority;
+        spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
+        unifi_trace(priv, UDBG2, "uf_process_wmm_deliver_ac_uapsd: trigger frame, Begin U-APSD, triggerQ=%x\n", priority_q);
+        uf_handle_uspframes_delivery(priv, srcStaInfo, interfaceTag);
+    }
+    unifi_trace(priv, UDBG2, "--uf_process_wmm_deliver_ac_uapsd: uapsdactive?=%x\n", srcStaInfo->uapsdActive);
+}
 
-  func_exit();
 
-}
 void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo)
 {
     bulk_data_param_t bulkdata;
@@ -2686,7 +2762,7 @@ void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8
     struct sk_buff *skb, *newSkb = NULL;
     CsrWifiMacAddress peerAddress;
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
-    CSR_TRANSMISSION_CONTROL transmissionControl = (TRANSMISSION_CONTROL_ESOP_MASK | TRANSMISSION_CONTROL_TRIGGER_MASK);
+    CSR_TRANSMISSION_CONTROL transmissionControl = (TRANSMISSION_CONTROL_EOSP_MASK | TRANSMISSION_CONTROL_TRIGGER_MASK);
     int r;
     CSR_SIGNAL signal;
     CsrUint32 priority_q;
@@ -2928,7 +3004,19 @@ CsrBool uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo
                         !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]));
             if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) {
                 unifi_trace(priv, UDBG3, "This condition should not occur\n");
-                update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle);
+                if (!srcStaInfo->timRequestPendingFlag){
+                    update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle);
+                }
+                else
+                {
+                    /* Cache the TimSet value so that it will processed immidiatly after
+                     * completing the current setTim Request
+                     */
+                    srcStaInfo->updateTimReqQueued = 1;
+                    unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", srcStaInfo->updateTimReqQueued,
+                                srcStaInfo->aid);
+                }
+
             }
         } else {
             CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
@@ -2939,7 +3027,18 @@ CsrBool uf_process_pm_bit_for_peer(unifi_priv_t * priv, CsrWifiRouterCtrlStaInfo
             moreData = (uf_is_more_data_for_non_delivery_ac(srcStaInfo) || (allDeliveryEnabled && dataAvailable));
 
             if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) {
-                update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle);
+                if (!srcStaInfo->timRequestPendingFlag){
+                    update_tim(priv,srcStaInfo->aid,1,interfaceTag, srcStaInfo->assignedHandle);
+                }
+                else
+                {
+                    /* Cache the TimSet value so that it will processed immidiatly after
+                     * completing the current setTim Request
+                     */
+                    srcStaInfo->updateTimReqQueued = 1;
+                    unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", srcStaInfo->updateTimReqQueued,
+                                srcStaInfo->aid);
+                }
             }
         }
     }
@@ -2993,10 +3092,10 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
                         !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) ||
                         !list_empty(&staRecord->mgtFrames));
 
-            buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+            buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                 /* Clear the trigger bit transmission control*/
-                buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
                 /* Enqueue at the head of the queue */
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 list_add(&buffered_pkt->q, &staRecord->mgtFrames);
@@ -3016,10 +3115,10 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
             moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) ||
                         !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]));
 
-            buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+            buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                 /* Clear the trigger bit transmission control*/
-                buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
                 /* Enqueue at the head of the queue */
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]);
@@ -3038,10 +3137,10 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
             buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK;
             moreData = !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]);
 
-            buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+            buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                 /* Clear the trigger bit transmission control*/
-                buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
                 /* Enqueue at the head of the queue */
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]);
@@ -3065,7 +3164,18 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
             !list_empty(&staRecord->mgtFrames));
         if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) {
             unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n");
-            update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+            if (!staRecord->timRequestPendingFlag){
+                update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+            }
+            else
+            {
+                /* Cache the TimSet value so that it will processed immidiatly after
+                 * completing the current setTim Request
+                 */
+                staRecord->updateTimReqQueued = 0;
+                unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                            staRecord->aid);
+            }
         }
     } else {
 
@@ -3074,9 +3184,9 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
 
         /*Send Data From Management Frames*/
         /* Priority orders for delivering the buffered packets are
-         * 1. UNIFI_TRAFFIC_Q_VO, if its non delivery enabled
-         * 2. management frames
-         * 3. Other access catagory frames which are non deliver enable
+         * 1. Deliver the Management frames if there
+         * 2. Other access catagory frames which are non deliver enable including UNIFI_TRAFFIC_Q_VO
+         * priority is from VO->BK
          */
 
         /* Check if all AC's are Delivery Enabled */
@@ -3088,42 +3198,18 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
             return;
         }
 
-        if ((!IS_DELIVERY_ENABLED(staRecord->powersaveMode[UNIFI_TRAFFIC_Q_VO])) &&
-                (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]) || !list_empty(&staRecord->mgtFrames))) {
-            /* UNIFI_TRAFFIC_Q_VO is non delivery enabled, & check for packets are there to send from this AC */
-            if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]))) {
-                moreData = uf_is_more_data_for_non_delivery_ac(staRecord);
-                buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
-
-                /* Last parameter is EOSP & its false always for PS-POLL processing */
-                if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
-                    /* Clear the trigger bit transmission control*/
-                    buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
-                    /* Enqueue at the head of the queue */
-                    spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-                    list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]);
-                    spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-                    priv->pausedStaHandle[0]=(CsrUint8)(staRecord->assignedHandle);
-                    unifi_trace(priv, UDBG1, "(ENOSPC) PS-POLL received : PDU sending failed \n");
-                } else {
-                    if(r){
-                        unifi_trace (priv, UDBG1, " HIP validation failure : PDU sending failed \n");
-                        /* the PDU failed where we can't do any thing so free the storage */
-                        unifi_net_data_free(priv, &buffered_pkt->bulkdata);
-                    }
-                    kfree(buffered_pkt);
-                }
-            } else if ((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) {
+        if (!list_empty(&staRecord->mgtFrames)) {
+             if ((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) {
                     /* We dont have packets in non delivery enabled UNIFI_TRAFFIC_Q_VO, So we are looking in management
                      * queue of the station record
                      */
                     moreData = uf_is_more_data_for_non_delivery_ac(staRecord);
-                    buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                    buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
 
                     /* Last parameter is EOSP & its false always for PS-POLL processing */
                     if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                         /* Clear the trigger bit transmission control*/
-                        buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                        buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
                         /* Enqueue at the head of the queue */
                         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                         list_add(&buffered_pkt->q, &staRecord->mgtFrames);
@@ -3138,24 +3224,27 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
                         }
                         kfree(buffered_pkt);
                     }
+                } else {
+                    unifi_error(priv, "uf_process_ps_poll: Mgt frame list empty!! \n");
                 }
+
         } else {
             CsrInt8 i;
-            /* We dont have buffered packet in UNIFI_TRAFFIC_Q_VO & mangement frame queue (1 & 2 failed), So proceed with 3 condition
-             * UNIFI_TRAFFIC_Q_VO is taken care so start with i index = 2
+            /* We dont have buffered packet in mangement frame queue (1 failed), So proceed with condition 2
+             * UNIFI_TRAFFIC_Q_VO -> VI -> BE -> BK
              */
-            for(i= 2; i>=0; i--) {
+            for(i= 3; i>=0; i--) {
                 if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) {
                     /* Send One packet, if queue is NULL then continue */
                     if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) {
                         moreData = uf_is_more_data_for_non_delivery_ac(staRecord);
 
-                        buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                        buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
 
                         /* Last parameter is EOSP & its false always for PS-POLL processing */
                         if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                             /* Clear the trigger bit transmission control*/
-                            buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_ESOP_MASK);
+                            buffered_pkt->transmissionControl &= ~(TRANSMISSION_CONTROL_TRIGGER_MASK | TRANSMISSION_CONTROL_EOSP_MASK);
                             /* Enqueue at the head of the queue */
                             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                             list_add(&buffered_pkt->q, &staRecord->dataPdu[i]);
@@ -3181,7 +3270,19 @@ void uf_process_ps_poll(unifi_priv_t *priv,CsrUint8* sa,CsrUint8* da,CsrUint8 pm
         moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable));
         if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) {
             unifi_trace(priv, UDBG3, "more data = NULL, set tim to 0 in uf_process_ps_poll\n");
-            update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+            if (!staRecord->timRequestPendingFlag){
+                update_tim(priv,staRecord->aid,0,interfaceTag, staRecord->assignedHandle);
+            }
+            else
+            {
+                /* Cache the TimSet value so that it will processed immidiatly after
+                 * completing the current setTim Request
+                 */
+                staRecord->updateTimReqQueued = 0;
+                unifi_trace(priv, UDBG6, "update_tim : One more UpdateTim Request (Tim value:%d) Queued for AID %x\n", staRecord->updateTimReqQueued,
+                            staRecord->aid);
+            }
+
         }
     }
 
@@ -3297,31 +3398,7 @@ void uf_flush_list(unifi_priv_t * priv, struct list_head * list)
     }
     spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
 }
-void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list)
-{
-    struct list_head *listHeadMaPktreq,*placeHolderMaPktreq;
-    maPktReqList_t *maPktreq;
-    unsigned long lock_flags;
 
-    unifi_trace(priv, UDBG5, "entering the uf_flush_maPktlist \n");
-
-    spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-    /* go through list, delete & free memory */
-    list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, list) {
-        maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q);
-
-        if(!maPktreq) {
-            unifi_error(priv, "entry should exists, otherwise crashes (bug)\n");
-        }
-        /* free the allocated memory */
-        dev_kfree_skb(maPktreq->skb);
-        list_del(listHeadMaPktreq);
-        kfree(maPktreq);
-        maPktreq = NULL;
-
-    }
-    spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-}
 tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList)
 {
     /* dequeue the tx data packets from the appropriate queue */
@@ -3521,7 +3598,7 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag)
    while(!isRouterBufferEnabled(priv,3) &&
                             ((buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMgtFrames))!=NULL)) {
         buffered_pkt->transmissionControl &=
-                     ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+                     ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK);
         if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,0,FALSE)) == -ENOSPC) {
             /* Enqueue at the head of the queue */
             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
@@ -3547,7 +3624,7 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag)
         if (staInfo && (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)) {
           while((( TRUE == hipslotFree[3] ) && (buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->mgtFrames)))) {
               buffered_pkt->transmissionControl &=
-                           ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+                           ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK);
               if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) {
                   unifi_trace(priv, UDBG3, "(ENOSPC) in resume_unicast_buffered_frames:: hip slots are full for voice queue\n");
                   /* Enqueue at the head of the queue */
@@ -3573,7 +3650,7 @@ void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag)
 
               while((buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->dataPdu[j]))) {
                  buffered_pkt->transmissionControl &=
-                            ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_ESOP_MASK);
+                            ~(TRANSMISSION_CONTROL_TRIGGER_MASK|TRANSMISSION_CONTROL_EOSP_MASK);
                  if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) {
                      /* Enqueue at the head of the queue */
                      spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
@@ -3615,7 +3692,7 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 int
         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
         list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) {
             tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
-            tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_ESOP_MASK;
+            tx_q_item->transmissionControl |= TRANSMISSION_CONTROL_EOSP_MASK;
             tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED));
             unifi_trace(priv, UDBG1,"updating eosp for list Head hostTag:= 0x%x ",tx_q_item->hostTag);
             break;
@@ -3624,105 +3701,51 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 int
     }
     func_exit();
 }
+
+/*
+ * ---------------------------------------------------------------------------
+ *  resume_suspended_uapsd
+ *
+ *      This function takes care processing packets of Unscheduled Service Period,
+ *      which been suspended earlier due to DTIM/HIP ENOSPC scenarios
+ *
+ *  Arguments:
+ *      priv            Pointer to device private context struct
+ *      interfaceTag    For which resume should happen
+ * ---------------------------------------------------------------------------
+ */
 void resume_suspended_uapsd(unifi_priv_t* priv,CsrUint16 interfaceTag)
 {
 
    CsrUint8 startIndex;
    CsrWifiRouterCtrlStaInfo_t * staInfo = NULL;
-   unsigned long lock_flags;
-   /*U-APSD might have stopped because of multicast. So restart it if U-APSD
-   was active with any of the station*/
+    unsigned long lock_flags;
+
+    unifi_trace(priv, UDBG2, "++resume_suspended_uapsd: \n");
     for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) {
         staInfo =  CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag);
-        if(!staInfo ) {
+
+        if(!staInfo || !staInfo->wmmOrQosEnabled) {
             continue;
         } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
-                   &&(staInfo->uapsdSuspended == TRUE)) {
-
-            /*U-APSD Still active, it means trigger frame is received,so continue U-APSD by
-            sending data from remaining delivery enabled queues*/
-            spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-            staInfo->uapsdActive = TRUE;
-            staInfo->uapsdSuspended = FALSE;
-            spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
-            uf_continue_uapsd(priv,staInfo);
-        }
-    }
-
-}
-void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
-                                            CSR_SIGNAL *sigptr, CsrUint32 alignOffset)
-{
-
-    maPktReqList_t *maPktreq = NULL;
-    CSR_MA_PACKET_REQUEST *req = &sigptr->u.MaPacketRequest;
-    CsrWifiRouterCtrlStaInfo_t *staRecord = NULL;
-    CsrUint16 frmCtrl,interfaceTag = 0;
-    const CsrUint8* macHdrLocation;
-    struct sk_buff *skb ;
-    unsigned long lock_flags;
-    netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
-    CsrUint8 *sigbuffer;
-    CsrUint8 frameType = 0;
-    func_enter();
-
-    if(bulkdata == NULL || (0 == bulkdata->d[0].data_length )){
-      unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece:bulk data NULL \n");
-      func_exit();
-      return;
-    }
-    macHdrLocation = bulkdata->d[0].os_data_ptr;
-    skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr;
-    /* fectch the frame control value from mac header */
-    frmCtrl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(macHdrLocation);
-
-    /* Processing done according to Frame/Packet type */
-    frameType =  ((frmCtrl & 0x000c) >> FRAME_CONTROL_TYPE_FIELD_OFFSET);
-
-    if( (((frmCtrl & 0xff) == IEEE802_11_FC_TYPE_QOS_NULL) ||
-        ((frmCtrl & 0xff) == IEEE802_11_FC_TYPE_NULL ) ) ||
-        ( IEEE802_11_FRAMETYPE_MANAGEMENT== frameType)){
-
-        /* if packet is NULL or Qos Null no need of retransmit so dont queue it*/
-        unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece: NULL data Pkt or mgmt\n");
-        func_exit();
-        return;
-    }
-
-    /* fetch the station record for corresponding peer mac address */
-    if ((staRecord = CsrWifiRouterCtrlGetStationRecordFromPeerMacAddress(priv, req->Ra.x, interfaceTag))) {
-        maPktreq = (maPktReqList_t*)kmalloc(sizeof(maPktReqList_t),GFP_ATOMIC);
-        if(maPktreq == NULL){
-            unifi_error(priv,
-                "uf_store_directed_ma_packet_referenece :: Failed to allocate %d byter for maPktreq\n",
-                sizeof(maPktReqList_t));
-            func_exit();
-            return;
+                   &&staInfo->uapsdActive && staInfo->uspSuspend) {
+            /* U-APSD Still active & previously suspended either ENOSPC of FH queues OR
+             * due to DTIM activity
+             */
+            uf_handle_uspframes_delivery(priv, staInfo, interfaceTag);
+        } else {
+            unifi_trace(priv, UDBG2, "resume_suspended_uapsd: PS state=%x, uapsdActive?=%x, suspend?=%x\n",
+                        staInfo->currentPeerState, staInfo->uapsdActive, staInfo->uspSuspend);
+            if (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)
+            {
+                spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
+                staInfo->uapsdActive = FALSE;
+                staInfo->uspSuspend = FALSE;
+                spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
+            }
         }
     }
-
-    /* staRecord not present that means packet is multicast or generic mgmt so no need to queue it */
-    else{
-        unifi_trace (priv, UDBG3, "uf_store_directed_ma_packet_referenece: multicast pkt \n");
-        func_exit();
-        return ;
-    }
-
-    /* disbale preemption */
-    spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-    INIT_LIST_HEAD(&maPktreq->q);
-    maPktreq->staHandler = staRecord->assignedHandle;
-    memcpy(&maPktreq->signal,sigptr,sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + sizeof(CSR_MA_PACKET_REQUEST));
-    sigbuffer = (CsrUint8*)&maPktreq->signal;
-    sigbuffer[SIZEOF_SIGNAL_HEADER + 1] = alignOffset;
-    maPktreq->skb = skb_get(skb);
-    maPktreq->hostTag = req->HostTag;
-    maPktreq->jiffeTime = jiffies;
-    list_add_tail(&maPktreq->q,&interfacePriv->directedMaPktReq);
-
-    spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-    func_exit();
-
+    unifi_trace(priv, UDBG2, "--resume_suspended_uapsd:\n");
 }
 
 #endif
index f687f270a69942df8faea141050284584c77e30d..b23c84456578f3b0a23796217ed6f56f8660d37a 100644 (file)
 
 #include <linux/fs.h>
 
+#ifdef ANDROID_BUILD
+#include <linux/wakelock.h>
+#endif
+
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifi_udi.h"
 #include "csr_wifi_router_lib.h"
@@ -63,6 +67,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #include "unifi_wext.h"
 #endif
 
+#ifdef ANDROID_BUILD
+extern struct wake_lock unifi_sdio_wake_lock;
+#endif
+
 #include "unifi_clients.h"
 
 
@@ -98,18 +106,14 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #include "unifi_sme.h"
 #endif
 
-#undef  COMPARE_HOST_TAG_TO_ENQUEUE
-#define COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item_hosttag,maPktHostTag)        \
-      if(tx_q_item_hosttag > maPktHostTag){                                \
-        locationFound = TRUE;                                              \
-        ii++;                                                              \
-        break;                                                             \
-    }                                                                      \
-    ii++;                                                                  \
-
-
 /* The device major number to use when registering the udi driver */
 #define UNIFI_NAME      "unifi"
+/*
+ * MAX_UNIFI_DEVS defines the maximum number of UniFi devices that can be present.
+ * This number should be set to the number of SDIO slots supported by the SDIO
+ * host controller on the platform.
+ * Note: If MAX_UNIFI_DEVS value changes, fw_init[] needs to be corrected in drv.c
+ */
 #define MAX_UNIFI_DEVS  2
 
 /* 802.11 Mac header offsets */
@@ -156,6 +160,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #define IEEE802_11_QC_TID_MASK 0x0f
 #define IEEE802_11_QC_A_MSDU_PRESENT 0x80
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND))
+#define IEEE802_11_QC_NON_TID_BITS_MASK 0xFFF0
+#endif
+
 #define CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000
 #define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36
 #define MAX_ACCESS_CATOGORY 4
@@ -185,6 +193,9 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #define     STA_INACTIVE_DETECTION_TIMER_INTERVAL              30               /* in seconds */
 #define     STA_INACTIVE_TIMEOUT_VAL                           120*1000*1000    /* 120 seconds */
 
+/* Test for modes requiring AP firmware patch */
+#define CSR_WIFI_HIP_IS_AP_FW(mode) ((((mode) == CSR_WIFI_ROUTER_CTRL_MODE_AP) || \
+                                      ((mode) == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) ? TRUE : FALSE)
 
 /* Defines used in beacon filtering in case of P2P */
 #define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH        0x7
@@ -220,6 +231,9 @@ extern int sdio_block_size;
 extern int coredump_max;
 extern int run_bh_once;
 extern int bh_priority;
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+extern int log_hip_signals;
+#endif
 
 struct dlpriv {
     const unsigned char *dl_data;
@@ -331,7 +345,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
     CsrTime lastActivity;
 
     /* during m/c transmission sp suspended */
-    CsrBool uapsdSuspended;
+    CsrBool uspSuspend;
+    CSR_PRIORITY triggerFramePriority;
 #endif
     CsrWifiRouterCtrlPeerStatus currentPeerState;
     struct list_head dataPdu[MAX_ACCESS_CATOGORY];
@@ -349,6 +364,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
 #define CSR_WIFI_TIM_RESETTING   2
 #define CSR_WIFI_TIM_SETTING     3
 
+    CsrBool timRequestPendingFlag;
+    CsrUint8 updateTimReqQueued;
     CsrUint16 noOfPktQueued;
 }CsrWifiRouterCtrlStaInfo_t;
 
@@ -609,8 +626,14 @@ struct unifi_priv {
 
     /* Spinlock to protect M4 data */
     spinlock_t m4_lock;
-    /* Spinlock to protect BA RX data */
-    spinlock_t ba_lock;
+    /* Mutex to protect BA RX data */
+    struct semaphore ba_mutex;
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Spinlock to protect the WAPI data */
+    spinlock_t wapi_lock;
+#endif
+
 #ifndef ALLOW_Q_PAUSE
     /* Array to indicate if a particular Tx queue is paused, this may not be
      * required in a multiqueue implementation since we can directly stop kernel
@@ -630,10 +653,24 @@ struct unifi_priv {
     CsrUint32 rxUdpThroughput;
     CsrUint32 txUdpThroughput;
 
-
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+    /*Set if multicast KeyID = 1*/
     CsrUint8 wapi_multicast_filter;
+    /*Set if unicast KeyID = 1*/
     CsrUint8 wapi_unicast_filter;
     CsrUint8 wapi_unicast_queued_pkt_filter;
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    CsrBool  isWapiConnection;
+#endif
+#endif
+
+#ifdef CSR_WIFI_SPLIT_PATCH
+    CsrWifiRouterCtrlModeSetReq pending_mode_set;
+#endif
+
+    CsrBool cmanrTestMode;
+    CSR_RATE cmanrTestModeTransmitRate;
+
 };
 
 typedef struct {
@@ -682,6 +719,9 @@ typedef struct netInterface_priv
     CsrUint8 ba_complete_index;
     CsrUint8 queueEnabled[UNIFI_NO_OF_TX_QS];
     struct work_struct send_m4_ready_task;
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+    struct work_struct send_pkt_to_encrypt;
+#endif
     struct net_device_stats stats;
     CsrUint8 interfaceMode;
     CsrBool protect;
@@ -721,7 +761,6 @@ typedef struct netInterface_priv
     struct list_head genericMgtFrames;
     struct list_head genericMulticastOrBroadCastFrames;
     struct list_head genericMulticastOrBroadCastMgtFrames;
-    struct list_head directedMaPktReq;
 
     /* Timer for detecting station inactivity */
     struct timer_list sta_activity_check_timer;
@@ -740,6 +779,13 @@ typedef struct netInterface_priv
     /* Buffered M4 signal to take care of WPA race condition */
     CSR_SIGNAL m4_signal;
     bulk_data_desc_t m4_bulk_data;
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Buffered WAPI Unicast MA Packet Request for encryption in Sme */
+    CSR_SIGNAL wapi_unicast_ma_pkt_sig;
+    bulk_data_desc_t wapi_unicast_bulk_data;
+#endif
+
     /* This should be removed and m4_hostTag should be used for checking*/
     CsrBool m4_sent;
     CSR_CLIENT_TAG m4_hostTag;
@@ -747,17 +793,11 @@ typedef struct netInterface_priv
     CsrBool intraBssEnabled;
     CsrUint32 multicastPduHostTag; /* Used to set the tim after getting
        a confirm for it */
+    CsrBool bcTimSet;
+    CsrBool bcTimSetReqPendingFlag;
+    CsrBool bcTimSetReqQueued;
 } netInterface_priv_t;
 
-typedef struct maPktReqList{
-    struct list_head q;
-    struct sk_buff *skb;
-    CSR_SIGNAL signal;
-    CSR_CLIENT_TAG hostTag;
-    CsrUint32 staHandler;
-    unsigned long jiffeTime;
-}maPktReqList_t;
-
 #ifndef ALLOW_Q_PAUSE
 #define net_is_tx_q_paused(priv, q)   (priv->tx_q_paused_flag[q])
 #define net_tx_q_unpause(priv, q)   (priv->tx_q_paused_flag[q] = 0)
@@ -925,7 +965,6 @@ int uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb,
                    bulk_data_param_t *bulkdata,
                    CsrUint8 macHeaderLengthInBytes);
 CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord);
-CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck);
 void uf_process_wmm_deliver_ac_uapsd (  unifi_priv_t * priv,
                                         CsrWifiRouterCtrlStaInfo_t * srcStaInfo,
                                         CsrUint16 qosControl,
@@ -937,7 +976,6 @@ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtr
 void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo);
 void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo);
 void uf_send_nulldata(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo);
-void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata,CSR_SIGNAL *sigptr,CsrUint32 alignOffset);
 
 
 
@@ -956,7 +994,6 @@ void send_auto_ma_packet_confirm(unifi_priv_t *priv,
                                  netInterface_priv_t *interfacePriv,
                                  struct list_head *buffered_frames_list);
 void uf_flush_list(unifi_priv_t * priv, struct list_head * list);
-void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list);
 tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList);
 void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag);
 void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 interfaceTag);
@@ -1073,6 +1110,11 @@ void uf_process_rx_pending_queue(unifi_priv_t *priv, int queue,
                                  CsrWifiMacAddress source_address,
                                  int indicate, CsrUint16 interfaceTag);
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+int uf_register_hip_offline_debug(unifi_priv_t *priv);
+int uf_unregister_hip_offline_debug(unifi_priv_t *priv);
+#endif
+
 /*
  *      inet.c
  */
index 4ee663fe4e4afb938000cd973b942c212d32026e..54414ed2ed1ca0a7394027fd3556d91279cffa8f 100644 (file)
@@ -447,6 +447,7 @@ int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
 {
     unifi_cfg_power_t cfg_power;
     int rc;
+    int wol;
 
     if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) {
         unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
@@ -455,16 +456,24 @@ int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
 
     switch (cfg_power) {
         case UNIFI_CFG_POWER_OFF:
+            priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
             rc = sme_sys_suspend(priv);
             if (rc) {
                 return rc;
             }
             break;
         case UNIFI_CFG_POWER_ON:
+            wol = priv->wol_suspend;
             rc = sme_sys_resume(priv);
             if (rc) {
                 return rc;
             }
+            if (wol) {
+                /* Kick the BH to ensure pending transfers are handled when
+                 * a suspend happened with card powered.
+                 */
+                unifi_send_signal(priv->card, NULL, 0, NULL);
+            }
             break;
         default:
             unifi_error(priv, "WIFI POWER: Unknown value.\n");
@@ -921,10 +930,19 @@ int
         supportedRates[i++]=0x8b;
         supportedRates[i++]=0x96;
     } else if(n) {
+        /* For some strange reasons WiFi stack needs both b and g rates*/
         supportedRates[i++]=0x02;
         supportedRates[i++]=0x04;
         supportedRates[i++]=0x0b;
         supportedRates[i++]=0x16;
+        supportedRates[i++]=0x0c;
+        supportedRates[i++]=0x12;
+        supportedRates[i++]=0x18;
+       supportedRates[i++]=0x24;
+        supportedRates[i++]=0x30;
+        supportedRates[i++]=0x48;
+        supportedRates[i++]=0x60;
+        supportedRates[i++]=0x6c;
     }
     if(g) {
         if(!b) {
@@ -1162,3 +1180,65 @@ uf_send_m4_ready_wq(struct work_struct *work)
 
 } /* uf_send_m4_ready_wq() */
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+/*
+ * ---------------------------------------------------------------------------
+ *  uf_send_pkt_to_encrypt
+ *
+ *      Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
+ *      These are done in a deferred work queue for two reasons:
+ *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
+ *       - we want to load the main driver data path as lightly as possible
+ *
+ *  Arguments:
+ *      work    Pointer to work queue item.
+ *
+ *  Returns:
+ *      None.
+ * ---------------------------------------------------------------------------
+ */
+void uf_send_pkt_to_encrypt(struct work_struct *work)
+{
+    netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
+    CsrUint16 interfaceTag = interfacePriv->InterfaceTag;
+    unifi_priv_t *priv = interfacePriv->privPtr;
+
+    CsrUint32 pktBulkDataLength;
+    CsrUint8 *pktBulkData;
+    unsigned long flags;
+
+    if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
+
+        func_enter();
+
+        pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
+
+        if (pktBulkDataLength > 0) {
+                   pktBulkData = (CsrUint8 *)CsrPmemAlloc(pktBulkDataLength);
+                   CsrMemSet(pktBulkData, 0, pktBulkDataLength);
+           } else {
+                   unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
+                   return;
+           }
+
+        spin_lock_irqsave(&priv->wapi_lock, flags);
+        /* Copy over the MA PKT REQ bulk data */
+        CsrMemCpy(pktBulkData, (CsrUint8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
+        /* Free any bulk data buffers allocated for the WAPI Data pkt */
+        unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
+        interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
+        interfacePriv->wapi_unicast_bulk_data.data_length = 0;
+        interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
+        spin_unlock_irqrestore(&priv->wapi_lock, flags);
+
+        CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
+        unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
+
+        CsrPmemFree(pktBulkData); /* Would have been copied over by the SME Handler */
+
+        func_exit();
+    } else {
+           unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
+    }
+}/* uf_send_pkt_to_encrypt() */
+#endif
index 51ca92e890557bbb155303443a5c1daad5f679e1..3cbee81f1b0a5bbb42f2c4b33ed553ebfe6791b4 100644 (file)
@@ -50,6 +50,7 @@ enum sme_request_status {
     SME_REQUEST_PENDING,
     SME_REQUEST_RECEIVED,
     SME_REQUEST_TIMEDOUT,
+    SME_REQUEST_CANCELLED,
 };
 
 /* Structure to hold a UDI logged signal */
@@ -123,6 +124,7 @@ void uf_ta_wq(struct work_struct *work);
 #endif
 
 void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func);
+void uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status);
 
 
 /*
@@ -148,6 +150,13 @@ void uf_sme_config_wq(struct work_struct *work);
  */
 void uf_send_m4_ready_wq(struct work_struct *work);
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+/*
+ * To send data pkt to Sme for encryption
+ */
+void uf_send_pkt_to_encrypt(struct work_struct *work);
+#endif
+
 int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig);
 int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig);
 int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig);
index e707eedef29ddebbced2930d5edcbc9ccbb6c006..4ab050bc71cb0908532af83e27e4b6b9cc89ad47 100644 (file)
@@ -212,20 +212,19 @@ typedef struct {
 
 
 
-typedef enum unifi_putest_command {
-    UNIFI_PUTEST_START,
-    UNIFI_PUTEST_STOP,
-    UNIFI_PUTEST_SET_SDIO_CLOCK,
-    UNIFI_PUTEST_CMD52_READ,
-    UNIFI_PUTEST_CMD52_WRITE,
-    UNIFI_PUTEST_DL_FW,
-    UNIFI_PUTEST_DL_FW_BUFF,
-    UNIFI_PUTEST_CMD52_BLOCK_READ,
-    UNIFI_PUTEST_COREDUMP_PREPARE,
-    UNIFI_PUTEST_GP_READ16,
-    UNIFI_PUTEST_GP_WRITE16
-
-} unifi_putest_command_t;
+typedef CsrUint8 unifi_putest_command_t;
+
+#define UNIFI_PUTEST_START 0
+#define UNIFI_PUTEST_STOP 1
+#define UNIFI_PUTEST_SET_SDIO_CLOCK 2
+#define UNIFI_PUTEST_CMD52_READ 3
+#define UNIFI_PUTEST_CMD52_WRITE 4
+#define UNIFI_PUTEST_DL_FW 5
+#define UNIFI_PUTEST_DL_FW_BUFF 6
+#define UNIFI_PUTEST_CMD52_BLOCK_READ 7
+#define UNIFI_PUTEST_COREDUMP_PREPARE 8
+#define UNIFI_PUTEST_GP_READ16 9
+#define UNIFI_PUTEST_GP_WRITE16 10
 
 
 struct unifi_putest_cmd52 {