Pārlūkot izejas kodu

Staging: csr: update to version 5.1.0 of the driver

This brings the in-kernel driver up to the level of the
csr-linux-wifi-5.1.0-oss.tar.gz tarball.

Cc: Mikko Virkkilä <mikko.virkkila@bluegiga.com>
Cc: Lauri Hintsala <Lauri.Hintsala@bluegiga.com>
Cc: Riku Mettälä <riku.mettala@bluegiga.com>
Cc: Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Greg Kroah-Hartman 13 gadi atpakaļ
vecāks
revīzija
95edd09ec3
56 mainītis faili ar 3845 papildinājumiem un 1670 dzēšanām
  1. 35 0
      drivers/staging/csr/csr_framework_ext.c
  2. 1 0
      drivers/staging/csr/csr_types.h
  3. 4 0
      drivers/staging/csr/csr_util.c
  4. 36 9
      drivers/staging/csr/csr_util.h
  5. 1 1
      drivers/staging/csr/csr_wifi_common.h
  6. 10 1
      drivers/staging/csr/csr_wifi_hip_card.h
  7. 71 14
      drivers/staging/csr/csr_wifi_hip_card_sdio.c
  8. 29 11
      drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c
  9. 2 2
      drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c
  10. 3 3
      drivers/staging/csr/csr_wifi_hip_download.c
  11. 3 3
      drivers/staging/csr/csr_wifi_hip_dump.c
  12. 18 12
      drivers/staging/csr/csr_wifi_hip_ta_sampling.c
  13. 31 1
      drivers/staging/csr/csr_wifi_hip_unifi.h
  14. 6 6
      drivers/staging/csr/csr_wifi_hip_xbv.c
  15. 1 2
      drivers/staging/csr/csr_wifi_nme_ap_lib.h
  16. 1 2
      drivers/staging/csr/csr_wifi_nme_ap_prim.h
  17. 5 5
      drivers/staging/csr/csr_wifi_router_converter_init.c
  18. 11 7
      drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c
  19. 17 3
      drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c
  20. 10 3
      drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c
  21. 181 45
      drivers/staging/csr/csr_wifi_router_ctrl_lib.h
  22. 117 13
      drivers/staging/csr/csr_wifi_router_ctrl_prim.h
  23. 7 5
      drivers/staging/csr/csr_wifi_router_ctrl_sef.c
  24. 3 1
      drivers/staging/csr/csr_wifi_router_ctrl_sef.h
  25. 243 18
      drivers/staging/csr/csr_wifi_router_ctrl_serialize.c
  26. 39 19
      drivers/staging/csr/csr_wifi_router_ctrl_serialize.h
  27. 130 1
      drivers/staging/csr/csr_wifi_sme_ap_lib.h
  28. 138 3
      drivers/staging/csr/csr_wifi_sme_ap_prim.h
  29. 6 5
      drivers/staging/csr/csr_wifi_sme_converter_init.c
  30. 1 1
      drivers/staging/csr/csr_wifi_sme_converter_init.h
  31. 8 1
      drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c
  32. 34 1
      drivers/staging/csr/csr_wifi_sme_lib.h
  33. 62 37
      drivers/staging/csr/csr_wifi_sme_prim.h
  34. 59 3
      drivers/staging/csr/csr_wifi_sme_serialize.c
  35. 6 1
      drivers/staging/csr/csr_wifi_sme_serialize.h
  36. 122 9
      drivers/staging/csr/drv.c
  37. 17 1
      drivers/staging/csr/firmware.c
  38. 20 0
      drivers/staging/csr/io.c
  39. 132 36
      drivers/staging/csr/netdev.c
  40. 15 11
      drivers/staging/csr/os.c
  41. 25 4
      drivers/staging/csr/putest.c
  42. 173 14
      drivers/staging/csr/sdio_emb.c
  43. 48 1
      drivers/staging/csr/sdio_events.c
  44. 211 36
      drivers/staging/csr/sdio_mmc.c
  45. 95 28
      drivers/staging/csr/sme_blocking.c
  46. 450 132
      drivers/staging/csr/sme_sys.c
  47. 2 3
      drivers/staging/csr/sme_userspace.c
  48. 3 1
      drivers/staging/csr/sme_wext.c
  49. 3 22
      drivers/staging/csr/ul_int.c
  50. 223 317
      drivers/staging/csr/unifi_event.c
  51. 15 7
      drivers/staging/csr/unifi_os.h
  52. 791 768
      drivers/staging/csr/unifi_pdu_processing.c
  53. 69 27
      drivers/staging/csr/unifi_priv.h
  54. 80 0
      drivers/staging/csr/unifi_sme.c
  55. 9 0
      drivers/staging/csr/unifi_sme.h
  56. 13 14
      drivers/staging/csr/unifiio.h

+ 35 - 0
drivers/staging/csr/csr_framework_ext.c

@@ -211,3 +211,38 @@ void CsrMemFree(void *pointer)
     kfree(pointer);
     kfree(pointer);
 }
 }
 EXPORT_SYMBOL_GPL(CsrMemFree);
 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);

+ 1 - 0
drivers/staging/csr/csr_types.h

@@ -21,6 +21,7 @@
 #include <stddef.h>
 #include <stddef.h>
 #include <sys/types.h>
 #include <sys/types.h>
 #include <stdarg.h>
 #include <stdarg.h>
+#include <string.h>
 #endif
 #endif
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 4 - 0
drivers/staging/csr/csr_util.c

@@ -221,6 +221,7 @@ void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str)
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
 /*  String */
 /*  String */
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
+#ifndef CSR_USE_STDC_LIB
 void *CsrMemCpy(void *dest, const void *src, CsrSize count)
 void *CsrMemCpy(void *dest, const void *src, CsrSize count)
 {
 {
     return memcpy(dest, src, count);
     return memcpy(dest, src, count);
@@ -257,7 +258,9 @@ void *CsrMemDup(const void *buf1, CsrSize count)
 
 
     return buf2;
     return buf2;
 }
 }
+#endif
 
 
+#ifndef CSR_USE_STDC_LIB
 CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src)
 CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src)
 {
 {
     return strcpy(dest, src);
     return strcpy(dest, src);
@@ -303,6 +306,7 @@ CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c)
 {
 {
     return strchr(string, c);
     return strchr(string, c);
 }
 }
+#endif
 
 
 CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args)
 CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args)
 {
 {

+ 36 - 9
drivers/staging/csr/csr_util.h

@@ -35,26 +35,53 @@ void CsrUInt16ToHex(CsrUint16 number, CsrCharString *str);
 void CsrUInt32ToHex(CsrUint32 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 *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);
 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 *CsrStrCpy(CsrCharString *dest, const CsrCharString *src);
 CsrCharString *CsrStrNCpy(CsrCharString *dest, const CsrCharString *src, CsrSize count);
 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 *CsrStrCat(CsrCharString *dest, const CsrCharString *src);
 CsrCharString *CsrStrNCat(CsrCharString *dest, const CsrCharString *src, CsrSize count);
 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 CsrStrCmp(const CsrCharString *string1, const CsrCharString *string2);
 CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
 CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
-CsrCharString *CsrStrDup(const CsrCharString *string);
 CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c);
 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);
 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);
 CsrCharString *CsrStrNCpyZero(CsrCharString *dest, const CsrCharString *src, CsrSize count);
 
 
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/

+ 1 - 1
drivers/staging/csr/csr_wifi_common.h

@@ -99,7 +99,7 @@ typedef struct
 #define CSR_WIFI_RESULT_INVALID_INTERFACE_TAG     ((CsrResult) 0x000B)
 #define CSR_WIFI_RESULT_INVALID_INTERFACE_TAG     ((CsrResult) 0x000B)
 #define CSR_WIFI_RESULT_P2P_NOA_CONFIG_CONFLICT   ((CsrResult) 0x000C)
 #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
 #ifdef __cplusplus
 }
 }

+ 10 - 1
drivers/staging/csr/csr_wifi_hip_card.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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);
 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 -
  * CardGetFreeFromHostDataSlots -
  */
  */

+ 71 - 14
drivers/staging/csr/csr_wifi_hip_card_sdio.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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
      * have requested a mini-coredump which needs to be captured now the
      * SDIO interface is alive.
      * 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.
      * 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 */
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_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++)
     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_rd_ptr = 0;
         card->fh_traffic_queue[i].q_wr_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
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
     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.
      * 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)
     if (card->fh_buffer.buf == NULL)
     {
     {
         unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n");
         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.ptr = card->fh_buffer.buf;
     card->fh_buffer.count = 0;
     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)
     if (card->th_buffer.buf == NULL)
     {
     {
         unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n");
         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;
         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 */
     /* Allocate memory for the array of pointers */
     n = cfg_data->num_tohost_data_slots;
     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)
     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.ptr = card->fh_buffer.buf = NULL;
     card->fh_buffer.bufsize = 0;
     card->fh_buffer.bufsize = 0;
@@ -1819,7 +1825,7 @@ static void card_free_memory_resources(card_t *card)
 
 
     if (card->th_buffer.buf)
     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.ptr = card->th_buffer.buf = NULL;
     card->th_buffer.bufsize = 0;
     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 */
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_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++)
     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_rd_ptr = 0;
         card->fh_traffic_queue[i].q_wr_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
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
     unifi_ta_sampling_init(card);
@@ -2399,6 +2405,57 @@ void CardClearFromHostDataSlot(card_t *card, const CsrInt16 slot)
 } /* CardClearFromHostDataSlot() */
 } /* 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)
 CsrUint16 CardGetDataSlotSize(card_t *card)
 {
 {
     return card->config_data.data_slot_size;
     return card->config_data.data_slot_size;

+ 29 - 11
drivers/staging/csr/csr_wifi_hip_card_sdio_intr.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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];
     CsrCharString s[5];
     CsrUint16 i;
     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);
         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.
      * Then ask the OS layer to run the unifi_bh to give attention to the UniFi.
      */
      */
     card->bh_reason_unifi = 1;
     card->bh_reason_unifi = 1;
-    unifi_run_bh(card->ospriv);
+    (void)unifi_run_bh(card->ospriv);
 } /*  sdio_interrupt_handler() */
 } /*  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",
                 (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled",
                 (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE");
                 (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;
     return CSR_RESULT_SUCCESS;
 } /* unifi_configure_low_power_mode() */
 } /* unifi_configure_low_power_mode() */
 
 
@@ -614,10 +614,10 @@ exit:
                     (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled");
                     (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled");
 
 
         /* Try to capture firmware panic codes */
         /* 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 */
         /* 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;
     return r;
@@ -932,9 +932,13 @@ static CsrResult handle_host_protocol(card_t *card, CsrBool *processed_something
             return r;
             return r;
         }
         }
     }
     }
+
+#ifdef CSR_WIFI_RX_PATH_SPLIT
 #ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
 #ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
     unifi_rx_queue_flush(card->ospriv);
     unifi_rx_queue_flush(card->ospriv);
 #endif
 #endif
+#endif
+
     /* See if we can re-enable transmission now */
     /* See if we can re-enable transmission now */
     restart_packet_flow(card);
     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))
                     if (status && (card->fh_slot_host_tag_record))
                     {
                     {
                         CsrUint16 num_fh_slots = card->config_data.num_fromhost_data_slots;
                         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
                         /* 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
                          * 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)
                             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);
                                 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;
                                 card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
 
 
                                 /* Set length field in from_host_data array to 0 */
                                 /* Set length field in from_host_data array to 0 */
                                 CardClearFromHostDataSlot(card, i);
                                 CardClearFromHostDataSlot(card, i);
-
+#endif
                                 break;
                                 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))
     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)
         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 */
         /* moving this check before we clear host data slot */
         if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3))
         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
 #endif
 
 

+ 2 - 2
drivers/staging/csr/csr_wifi_hip_card_sdio_mem.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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)
         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
         /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted

+ 3 - 3
drivers/staging/csr/csr_wifi_hip_download.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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;
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
     }
 
 
-    buf = CsrMemAlloc(buf_size);
+    buf = CsrMemAllocDma(buf_size);
     if (buf == NULL)
     if (buf == NULL)
     {
     {
         unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
         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)
     if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE)
     {
     {

+ 3 - 3
drivers/staging/csr/csr_wifi_hip_dump.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -293,7 +293,7 @@ done:
  *  Notes:
  *  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 unifi_coredump_space_t space,
                                         const CsrUint16              offset_in_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 */
                 /* Calculate the offset of data within the zone buffer */
                 offset_in_zone = offset_in_space - def->offset;
                 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,
                 unifi_trace(NULL, UDBG6,
                             "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n",
                             "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n",

+ 18 - 12
drivers/staging/csr/csr_wifi_hip_ta_sampling.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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_OFFSET        9
 #define TA_EAPOL_TYPE_START         0x01
 #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 };
 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 proto;
     CsrUint16 source_port, dest_port;
     CsrUint16 source_port, dest_port;
     CsrWifiMacAddress srcAddress;
     CsrWifiMacAddress srcAddress;
+    CsrUint32 snap_hdr, oui_hdr;
 
 
     if (data->data_length < TA_LLC_HEADER_SIZE)
     if (data->data_length < TA_LLC_HEADER_SIZE)
     {
     {
         return TA_FRAME_UNKNOWN;
         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;
         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) +
         proto = (data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET] * 256) +
                 data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET + 1];
                 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) */
                                 /* The DHCP should have at least a message type (request, ack, nack, etc) */
                                 if (data->data_length > TA_DHCP_MESSAGE_TYPE_OFFSET + 6)
                                 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)
                                     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 */
                                     /* 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)
                                         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) ||
                 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))
                     (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,
                     unifi_ta_indicate_protocol(card->ospriv,
                                                CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL,
                                                CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL,
                                                direction, &srcAddress);
                                                direction, &srcAddress);
@@ -238,7 +244,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
         {
         {
             if (proto == TA_PROTO_TYPE_ARP)
             if (proto == TA_PROTO_TYPE_ARP)
             {
             {
-                CsrMemCpy(srcAddress.a, saddr, 6);
+                UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
                 unifi_ta_indicate_protocol(card->ospriv,
                 unifi_ta_indicate_protocol(card->ospriv,
                                            CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP,
                                            CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP,
                                            direction, &srcAddress);
                                            direction, &srcAddress);
@@ -253,7 +259,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
         /* detect Aironet frames */
         /* detect Aironet frames */
         if (!CsrMemCmp(data->os_data_ptr + 3, aironet_snap, 5))
         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,
             unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET,
                                        direction, &srcAddress);
                                        direction, &srcAddress);
         }
         }

+ 31 - 1
drivers/staging/csr/csr_wifi_hip_unifi.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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_formatted_io.h"   /* from the synergy gsp folder */
 #include "csr_wifi_result.h"
 #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
 /* Traffic queue ordered according to priority
  * EAPOL/Uncontrolled port Queue should be the last
  * EAPOL/Uncontrolled port Queue should be the last
@@ -635,7 +646,24 @@ void unifi_receive_event(void *ospriv,
                          CsrUint8 *sigdata, CsrUint32 siglen,
                          CsrUint8 *sigdata, CsrUint32 siglen,
                          const bulk_data_param_t *bulkdata);
                          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
 typedef struct
 {
 {
     CsrUint16 free_fh_sig_queue_slots[UNIFI_NO_OF_TX_QS];
     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 */
 /* Function to log HIP's global debug buffer */
 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
 void unifi_debug_buf_dump(void);
 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
 #endif
 
 
 /* Mini-coredump utility functions */
 /* Mini-coredump utility functions */

+ 6 - 6
drivers/staging/csr/csr_wifi_hip_xbv.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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)
 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);
     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);
     patch_offs += write_reset_ptdl(patch_buf, patch_offs, fwinfo, fw_id);
 
 
     /* Now the length is known, update the LIST.length */
     /* 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 */
     /* 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",
     unifi_trace(card->ospriv, UDBG1, "XBV:PTCH size %u, fw_id %u\n",
                 patch_offs, fw_id);
                 patch_offs, fw_id);

+ 1 - 2
drivers/staging/csr/csr_wifi_nme_ap_lib.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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.
     apCredentials  - Security credential configuration.
     maxConnections - Maximum number of stations/P2P clients allowed
     maxConnections - Maximum number of stations/P2P clients allowed
     p2pGoParam     - P2P specific GO parameters.
     p2pGoParam     - P2P specific GO parameters.
-                     NOT USED FOR CURRENT RELEASE
     wpsEnabled     - Indicates whether WPS should be enabled or not
     wpsEnabled     - Indicates whether WPS should be enabled or not
 
 
 *******************************************************************************/
 *******************************************************************************/

+ 1 - 2
drivers/staging/csr/csr_wifi_nme_ap_prim.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -248,7 +248,6 @@ typedef struct
     apCredentials  - Security credential configuration.
     apCredentials  - Security credential configuration.
     maxConnections - Maximum number of stations/P2P clients allowed
     maxConnections - Maximum number of stations/P2P clients allowed
     p2pGoParam     - P2P specific GO parameters.
     p2pGoParam     - P2P specific GO parameters.
-                     NOT USED FOR CURRENT RELEASE
     wpsEnabled     - Indicates whether WPS should be enabled or not
     wpsEnabled     - Indicates whether WPS should be enabled or not
 
 
 *******************************************************************************/
 *******************************************************************************/

+ 5 - 5
drivers/staging/csr/csr_wifi_router_converter_init.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -41,11 +41,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint
 {
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     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
     else

+ 11 - 7
drivers/staging/csr/csr_wifi_router_ctrl_converter_init.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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_CAPABILITIES_REQ, CsrWifiRouterCtrlCapabilitiesReqSizeof, CsrWifiRouterCtrlCapabilitiesReqSer, CsrWifiRouterCtrlCapabilitiesReqDes, CsrWifiRouterCtrlCapabilitiesReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, CsrWifiRouterCtrlBlockAckEnableReqSizeof, CsrWifiRouterCtrlBlockAckEnableReqSer, CsrWifiRouterCtrlBlockAckEnableReqDes, CsrWifiRouterCtrlBlockAckEnableReqSerFree },
     { 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_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_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_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_HIP_IND, CsrWifiRouterCtrlHipIndSizeof, CsrWifiRouterCtrlHipIndSer, CsrWifiRouterCtrlHipIndDes, CsrWifiRouterCtrlHipIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, CsrWifiRouterCtrlPortConfigureCfmSizeof, CsrWifiRouterCtrlPortConfigureCfmSer, CsrWifiRouterCtrlPortConfigureCfmDes, CsrWifiRouterCtrlPortConfigureCfmSerFree },
     { 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_DISABLE_CFM, CsrWifiRouterCtrlBlockAckDisableCfmSizeof, CsrWifiRouterCtrlBlockAckDisableCfmSer, CsrWifiRouterCtrlBlockAckDisableCfmDes, CsrWifiRouterCtrlBlockAckDisableCfmSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, CsrWifiRouterCtrlBlockAckErrorIndSizeof, CsrWifiRouterCtrlBlockAckErrorIndSer, CsrWifiRouterCtrlBlockAckErrorIndDes, CsrWifiRouterCtrlBlockAckErrorIndSerFree },
     { 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_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 },
     { 0, NULL, NULL, NULL, NULL },
 };
 };
@@ -90,11 +94,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterCtrlConverterLookup(CsrMsgConvMsgEntry *ce, Csr
 {
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     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
     else

+ 17 - 3
drivers/staging/csr/csr_wifi_router_ctrl_free_downstream_contents.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -70,6 +70,13 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *
             p->tclas = NULL;
             p->tclas = NULL;
             break;
             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:
         case CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES:
         {
         {
             CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message;
             CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message;
@@ -77,15 +84,22 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *
             p->smeVersions.smeBuild = NULL;
             p->smeVersions.smeBuild = NULL;
             break;
             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);
             CsrPmemFree(p->signal);
             p->signal = NULL;
             p->signal = NULL;
             CsrPmemFree(p->data);
             CsrPmemFree(p->data);
             p->data = NULL;
             p->data = NULL;
             break;
             break;
         }
         }
+        case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ:
+        {
+            CsrWifiRouterCtrlWapiUnicastTxPktReq *p = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
 
         default:
         default:
             break;
             break;

+ 10 - 3
drivers/staging/csr/csr_wifi_router_ctrl_free_upstream_contents.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -63,15 +63,22 @@ void CsrWifiRouterCtrlFreeUpstreamMessageContents(CsrUint16 eventClass, void *me
             p->versions.routerBuild = NULL;
             p->versions.routerBuild = NULL;
             break;
             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);
             CsrPmemFree(p->signal);
             p->signal = NULL;
             p->signal = NULL;
             CsrPmemFree(p->data);
             CsrPmemFree(p->data);
             p->data = NULL;
             p->data = NULL;
             break;
             break;
         }
         }
+        case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND:
+        {
+            CsrWifiRouterCtrlWapiUnicastTxEncryptInd *p = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
 
         default:
         default:
             break;
             break;

+ 181 - 45
drivers/staging/csr/csr_wifi_router_ctrl_lib.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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__) \
 #define CsrWifiRouterCtrlModeSetReqSend(src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \
     CsrWifiRouterCtrlModeSetReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, 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
   NAME
@@ -1594,6 +1627,35 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
 #define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \
 #define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \
     CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, 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
   NAME
@@ -1602,68 +1664,73 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   DESCRIPTION
   DESCRIPTION
 
 
   PARAMETERS
   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)); \
     msg__ = (CsrWifiRouterCtrlWapiMulticastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastFilterReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->status = (status__);
     msg__->status = (status__);
 
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \
     { \
     { \
         CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \
         CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \
-        CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__); \
+        CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
         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
   NAME
-    CsrWifiRouterCtrlWapiMulticastReqSend
+    CsrWifiRouterCtrlWapiRxMicCheckIndSend
 
 
   DESCRIPTION
   DESCRIPTION
 
 
   PARAMETERS
   PARAMETERS
-    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
     signalLength -
     signalLength -
     signal       -
     signal       -
     dataLength   -
     dataLength   -
     data         -
     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__->signalLength = (signalLength__); \
     msg__->signal = (signal__); \
     msg__->signal = (signal__); \
     msg__->dataLength = (dataLength__); \
     msg__->dataLength = (dataLength__); \
     msg__->data = (data__);
     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
   NAME
-    CsrWifiRouterCtrlWapiMulticastIndSend
+    CsrWifiRouterCtrlWapiRxPktReqSend
 
 
   DESCRIPTION
   DESCRIPTION
 
 
   PARAMETERS
   PARAMETERS
-    queue        - Destination Task Queue
-    clientData   -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
     interfaceTag -
     interfaceTag -
     signalLength -
     signalLength -
     signal       -
     signal       -
@@ -1671,25 +1738,24 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
     data         -
     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__->interfaceTag = (interfaceTag__); \
     msg__->signalLength = (signalLength__); \
     msg__->signalLength = (signalLength__); \
     msg__->signal = (signal__); \
     msg__->signal = (signal__); \
     msg__->dataLength = (dataLength__); \
     msg__->dataLength = (dataLength__); \
     msg__->data = (data__);
     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
   DESCRIPTION
 
 
   PARAMETERS
   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)); \
     msg__ = (CsrWifiRouterCtrlWapiUnicastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastFilterReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->status = (status__);
     msg__->status = (status__);
 
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \
     { \
     { \
         CsrWifiRouterCtrlWapiUnicastFilterReq *msg__; \
         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__); \
         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
   PARAMETERS
     queue      - Message Source Task Queue (Cfm's will be sent to this Queue)
     queue      - Message Source Task Queue (Cfm's will be sent to this Queue)
     clientData -
     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)); \
     msg__ = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, dst__, src__); \
     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__; \
         CsrWifiRouterCtrlWifiOnReq *msg__; \
-        CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__); \
+        CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
         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__)
 
 
 /*******************************************************************************
 /*******************************************************************************
 
 

+ 117 - 13
drivers/staging/csr/csr_wifi_router_ctrl_prim.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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_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_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_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_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_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 */
 /* Upstream */
 #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_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_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_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_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_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)
 #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
   MEMBERS
     common     - Common header for use with the CsrWifiFsm Module
     common     - Common header for use with the CsrWifiFsm Module
     clientData -
     clientData -
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
 
 
 *******************************************************************************/
 *******************************************************************************/
 typedef struct
 typedef struct
 {
 {
     CsrWifiFsmEvent                common;
     CsrWifiFsmEvent                common;
     CsrWifiRouterCtrlRequestorInfo clientData;
     CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint32                      dataLength;
+    CsrUint8                      *data;
 } CsrWifiRouterCtrlWifiOnReq;
 } CsrWifiRouterCtrlWifiOnReq;
 
 
 /*******************************************************************************
 /*******************************************************************************
@@ -1273,12 +1281,13 @@ typedef struct
 /*******************************************************************************
 /*******************************************************************************
 
 
   NAME
   NAME
-    CsrWifiRouterCtrlWapiMulticastReq
+    CsrWifiRouterCtrlWapiRxPktReq
 
 
   DESCRIPTION
   DESCRIPTION
 
 
   MEMBERS
   MEMBERS
     common       - Common header for use with the CsrWifiFsm Module
     common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
     signalLength -
     signalLength -
     signal       -
     signal       -
     dataLength   -
     dataLength   -
@@ -1288,11 +1297,12 @@ typedef struct
 typedef struct
 typedef struct
 {
 {
     CsrWifiFsmEvent common;
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint16       signalLength;
     CsrUint16       signalLength;
     CsrUint8       *signal;
     CsrUint8       *signal;
     CsrUint16       dataLength;
     CsrUint16       dataLength;
     CsrUint8       *data;
     CsrUint8       *data;
-} CsrWifiRouterCtrlWapiMulticastReq;
+} CsrWifiRouterCtrlWapiRxPktReq;
 
 
 /*******************************************************************************
 /*******************************************************************************
 
 
@@ -1302,13 +1312,15 @@ typedef struct
   DESCRIPTION
   DESCRIPTION
 
 
   MEMBERS
   MEMBERS
-    common - Common header for use with the CsrWifiFsm Module
-    status -
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       -
 
 
 *******************************************************************************/
 *******************************************************************************/
 typedef struct
 typedef struct
 {
 {
     CsrWifiFsmEvent common;
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint8        status;
     CsrUint8        status;
 } CsrWifiRouterCtrlWapiMulticastFilterReq;
 } CsrWifiRouterCtrlWapiMulticastFilterReq;
 
 
@@ -1320,16 +1332,60 @@ typedef struct
   DESCRIPTION
   DESCRIPTION
 
 
   MEMBERS
   MEMBERS
-    common - Common header for use with the CsrWifiFsm Module
-    status -
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       -
 
 
 *******************************************************************************/
 *******************************************************************************/
 typedef struct
 typedef struct
 {
 {
     CsrWifiFsmEvent common;
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint8        status;
     CsrUint8        status;
 } CsrWifiRouterCtrlWapiUnicastFilterReq;
 } 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
   NAME
@@ -1984,7 +2040,7 @@ typedef struct
 /*******************************************************************************
 /*******************************************************************************
 
 
   NAME
   NAME
-    CsrWifiRouterCtrlWapiMulticastInd
+    CsrWifiRouterCtrlWapiRxMicCheckInd
 
 
   DESCRIPTION
   DESCRIPTION
 
 
@@ -2007,7 +2063,55 @@ typedef struct
     CsrUint8                      *signal;
     CsrUint8                      *signal;
     CsrUint16                      dataLength;
     CsrUint16                      dataLength;
     CsrUint8                      *data;
     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
 #ifdef __cplusplus

+ 7 - 5
drivers/staging/csr/csr_wifi_router_ctrl_sef.c

@@ -35,9 +35,11 @@ const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers
     /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
     /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
     /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
     /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
     /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
     /* 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,
 };
 };

+ 3 - 1
drivers/staging/csr/csr_wifi_router_ctrl_sef.h

@@ -47,8 +47,10 @@ extern "C" {
     extern void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(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 CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 243 - 18
drivers/staging/csr/csr_wifi_router_ctrl_serialize.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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)
 CsrSize CsrWifiRouterCtrlWifiOnResSizeof(void *msg)
 {
 {
     CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) 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;
     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 += 2;                       /* CsrUint16 primitive->signalLength */
     bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */
     bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */
     bufferSize += 2;                       /* CsrUint16 primitive->dataLength */
     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;
     *len = 0;
     CsrUint16Ser(ptr, len, primitive->common.type);
     CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength);
     if (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;
     CsrSize offset;
     offset = 0;
     offset = 0;
 
 
     CsrUint16Des(&primitive->common.type, buffer, &offset);
     CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
     CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset);
     CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset);
     if (primitive->signalLength)
     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->signal);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive);
     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)
 CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg)
 {
 {
     CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) 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;
     CsrSize bufferSize = 2;
 
 
     /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */
     /* 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;
     *len = 0;
     CsrUint16Ser(ptr, len, primitive->common.type);
     CsrUint16Ser(ptr, len, primitive->common.type);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
     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;
     CsrSize offset;
     offset = 0;
     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->signal);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive);
     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);
+}
+
+

+ 39 - 19
drivers/staging/csr/csr_wifi_router_ctrl_serialize.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -105,10 +105,10 @@ extern CsrSize CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg);
 #define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiRouterCtrlWifiOffResSerFree CsrWifiRouterCtrlPfree
 #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 CsrUint8* CsrWifiRouterCtrlWifiOnResSer(CsrUint8 *ptr, CsrSize *len, void *msg);
 extern void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize len);
 extern void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize len);
@@ -155,21 +155,31 @@ extern void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize le
 extern CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg);
 extern CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg);
 #define CsrWifiRouterCtrlBlockAckDisableReqSerFree CsrWifiRouterCtrlPfree
 #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 CsrWifiRouterCtrlWapiMulticastFilterReqSerFree CsrWifiRouterCtrlPfree
 
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint8Ser
-#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint8Des
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
 #define CsrWifiRouterCtrlWapiUnicastFilterReqSerFree CsrWifiRouterCtrlPfree
 #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 CsrUint8* CsrWifiRouterCtrlHipIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
 extern void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize len);
 extern void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg);
 extern CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg);
@@ -310,10 +320,20 @@ extern void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg);
 extern CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg);
 #define CsrWifiRouterCtrlStaInactiveIndSerFree CsrWifiRouterCtrlPfree
 #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
 #ifdef __cplusplus

+ 130 - 1
drivers/staging/csr/csr_wifi_sme_ap_lib.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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* CsrWifiSmeApAccessTypeToString(CsrWifiSmeApAccessType value);
 const CsrCharString* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value);
 const CsrCharString* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value);
 const CsrCharString* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value);
 const CsrCharString* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value);
+const CsrCharString* CsrWifiSmeApDirectionToString(CsrWifiSmeApDirection value);
 const CsrCharString* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value);
 const CsrCharString* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value);
 const CsrCharString* CsrWifiSmeApTypeToString(CsrWifiSmeApType 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 *CsrWifiSmeApUpstreamPrimNames[CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT];
 extern const CsrCharString *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_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
   NAME

+ 138 - 3
drivers/staging/csr/csr_wifi_sme_ap_prim.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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_PERSONAL      ((CsrWifiSmeApAuthType) 0x01)
 #define CSR_WIFI_SME_AP_AUTH_TYPE_WEP           ((CsrWifiSmeApAuthType) 0x02)
 #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
   NAME
@@ -302,6 +319,28 @@ typedef struct
     CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities;
     CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities;
 } CsrWifiSmeApAuthPers;
 } 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
   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_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_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_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 */
 /* Upstream */
 #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_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_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_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_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_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)
 #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;
     CsrWifiSmeWpsConfig wpsConfig;
 } CsrWifiSmeApWpsConfigurationReq;
 } 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
   NAME
@@ -895,6 +981,55 @@ typedef struct
     CsrResult        status;
     CsrResult        status;
 } CsrWifiSmeApErrorInd;
 } 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
 #ifdef __cplusplus
 }
 }

+ 6 - 5
drivers/staging/csr/csr_wifi_sme_converter_init.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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_SME_COMMON_CONFIG_SET_REQ, CsrWifiSmeSmeCommonConfigSetReqSizeof, CsrWifiSmeSmeCommonConfigSetReqSer, CsrWifiSmeSmeCommonConfigSetReqDes, CsrWifiSmeSmeCommonConfigSetReqSerFree },
     { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree },
     { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree },
     { CSR_WIFI_SME_WPS_CONFIGURATION_REQ, CsrWifiSmeWpsConfigurationReqSizeof, CsrWifiSmeWpsConfigurationReqSer, CsrWifiSmeWpsConfigurationReqDes, CsrWifiSmeWpsConfigurationReqSerFree },
     { 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_ACTIVATE_CFM, CsrWifiSmeActivateCfmSizeof, CsrWifiSmeActivateCfmSer, CsrWifiSmeActivateCfmDes, CsrWifiSmeActivateCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, CsrWifiSmeAdhocConfigSetCfmSizeof, CsrWifiSmeAdhocConfigSetCfmSer, CsrWifiSmeAdhocConfigSetCfmDes, CsrWifiSmeAdhocConfigSetCfmSerFree },
     { 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)
     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
     else

+ 1 - 1
drivers/staging/csr/csr_wifi_sme_converter_init.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details

+ 8 - 1
drivers/staging/csr/csr_wifi_sme_free_downstream_contents.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -172,6 +172,13 @@ void CsrWifiSmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message
             p->wpsConfig.secondaryDeviceType = NULL;
             p->wpsConfig.secondaryDeviceType = NULL;
             break;
             break;
         }
         }
+        case CSR_WIFI_SME_SET_REQ:
+        {
+            CsrWifiSmeSetReq *p = (CsrWifiSmeSetReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
 
         default:
         default:
             break;
             break;

+ 34 - 1
drivers/staging/csr/csr_wifi_sme_lib.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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__) \
 #define CsrWifiSmeScanResultsGetCfmSend(dst__, status__, scanResultsCount__, scanResults__) \
     CsrWifiSmeScanResultsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, 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
   NAME

+ 62 - 37
drivers/staging/csr/csr_wifi_sme_prim.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -1434,7 +1434,7 @@ typedef CsrUint8 CsrWifiSmeWepCredentialType;
     CsrWifiSmeWmmMode
     CsrWifiSmeWmmMode
 
 
   DESCRIPTION
   DESCRIPTION
-    Defines bits for wmmModeMask: enable/disable WMM features.
+    Defines bits for CsrWifiSmeWmmModeMask: enable/disable WMM features.
 
 
  VALUES
  VALUES
     CSR_WIFI_SME_WMM_MODE_DISABLED   - Disables the WMM features.
     CSR_WIFI_SME_WMM_MODE_DISABLED   - Disables the WMM features.
@@ -2410,40 +2410,6 @@ typedef struct
     CsrUint16 maxPassiveChannelTimeTu;
     CsrUint16 maxPassiveChannelTimeTu;
 } CsrWifiSmeScanConfigData;
 } 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
   NAME
@@ -3197,6 +3163,40 @@ typedef struct
     } deviceInfo;
     } deviceInfo;
 } CsrWifiSmeScanResult;
 } 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
   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_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_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_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 */
 /* Upstream */
 #define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
 #define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -4809,6 +4810,30 @@ typedef struct
     CsrWifiSmeWpsConfig wpsConfig;
     CsrWifiSmeWpsConfig wpsConfig;
 } CsrWifiSmeWpsConfigurationReq;
 } 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
   NAME

+ 59 - 3
drivers/staging/csr/csr_wifi_sme_serialize.c

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             Refer to LICENSE.txt included with this source for details
@@ -1356,7 +1356,7 @@ CsrSize CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg)
     bufferSize += 2; /* CsrUint16 primitive->interfaceTag */
     bufferSize += 2; /* CsrUint16 primitive->interfaceTag */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */
     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; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */
     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 CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg)
 {
 {
     CsrSize bufferSize = 2;
     CsrSize bufferSize = 2;
@@ -5085,7 +5141,7 @@ CsrSize CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg)
     bufferSize += 2; /* CsrResult primitive->status */
     bufferSize += 2; /* CsrResult primitive->status */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */
     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; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */

+ 6 - 1
drivers/staging/csr/csr_wifi_sme_serialize.h

@@ -1,6 +1,6 @@
 /*****************************************************************************
 /*****************************************************************************
 
 
-            (c) Cambridge Silicon Radio Limited 2011
+            (c) Cambridge Silicon Radio Limited 2012
             All rights reserved and confidential information of CSR
             All rights reserved and confidential information of CSR
 
 
             Refer to LICENSE.txt included with this source for details
             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 CsrSize CsrWifiSmeWpsConfigurationReqSizeof(void *msg);
 extern void CsrWifiSmeWpsConfigurationReqSerFree(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 CsrWifiSmeActivateCfmSer CsrWifiEventCsrUint16Ser
 #define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des
 #define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des
 #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof

+ 122 - 9
drivers/staging/csr/drv.c

@@ -47,12 +47,7 @@
 int buswidth = 0;               /* 0 means use default, values 1,4 */
 int buswidth = 0;               /* 0 means use default, values 1,4 */
 int sdio_clock = 50000;         /* kHz */
 int sdio_clock = 50000;         /* kHz */
 int unifi_debug = 0;
 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 fw_init[MAX_UNIFI_DEVS] = {-1, -1};
 int use_5g = 0;
 int use_5g = 0;
 int led_mask = 0;               /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */
 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 coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS;
 int run_bh_once = -1;          /* Set for scheduled interrupt mode, -1 = default */
 int run_bh_once = -1;          /* Set for scheduled interrupt mode, -1 = default */
 int bh_priority = -1;
 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)");
 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(coredump_max, int, S_IRUGO|S_IWUSR);
 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
 module_param(bh_priority, 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(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)");
 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(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(run_bh_once, "Run BH only when firmware interrupts");
 MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority");
 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 */
 /* Callback for event logging to UDI clients */
 static void udi_log_event(ul_client_t *client,
 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() */
 } /* unifi_open() */
 
 
 
 
-
 static int
 static int
 unifi_release(struct inode *inode, struct file *filp)
 unifi_release(struct inode *inode, struct file *filp)
 {
 {
@@ -354,6 +409,15 @@ unifi_release(struct inode *inode, struct file *filp)
         }
         }
 
 
         uf_sme_deinit(priv);
         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 */
 #endif /* CSR_SME_USERSPACE */
     } else {
     } else {
 
 
@@ -979,6 +1043,14 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
             goto out;
             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);
         down(&priv->udi_logging_mutex);
         if (int_param) {
         if (int_param) {
             pcli->event_hook = udi_log_event;
             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");
             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 */
 #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];
                 struct net_device *dev = priv->netdev[interfaceTag];
@@ -1720,6 +1797,40 @@ udi_log_event(ul_client_t *pcli,
         return;
         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
 #ifdef CSR_NATIVE_LINUX
     uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir);
     uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir);
 #endif
 #endif
@@ -1950,7 +2061,7 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id)
     priv->unifiudi_cdev.owner = THIS_MODULE;
     priv->unifiudi_cdev.owner = THIS_MODULE;
 
 
     devno = MKDEV(MAJOR(unifi_first_devno),
     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);
     r = cdev_add(&priv->unifiudi_cdev, devno, 1);
     if (r) {
     if (r) {
         device_destroy(unifi_class, priv->unifi_cdev.dev);
         device_destroy(unifi_class, priv->unifi_cdev.dev);
@@ -2081,7 +2192,9 @@ unifi_load(void)
 #endif
 #endif
     printk("CSR native no WEXT support\n");
     printk("CSR native no WEXT support\n");
 #endif
 #endif
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+    printk("Split patch support\n");
+#endif
     printk("Kernel %d.%d.%d\n",
     printk("Kernel %d.%d.%d\n",
            ((LINUX_VERSION_CODE) >> 16) & 0xff,
            ((LINUX_VERSION_CODE) >> 16) & 0xff,
            ((LINUX_VERSION_CODE) >> 8) & 0xff,
            ((LINUX_VERSION_CODE) >> 8) & 0xff,

+ 17 - 1
drivers/staging/csr/firmware.c

@@ -296,7 +296,18 @@ uf_run_unifihelper(unifi_priv_t *priv)
 #endif
 #endif
 } /* uf_run_unifihelper() */
 } /* 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) {
     if (is_fw == UNIFI_FW_STA) {
         /* Free kernel buffer and reload */
         /* Free kernel buffer and reload */
         uf_release_firmware(priv, &priv->fw_sta);
         uf_release_firmware(priv, &priv->fw_sta);
+#ifdef CSR_WIFI_SPLIT_PATCH
         scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
         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);
         r = request_firmware(&fw_entry, fw_name, priv->unifi_device);
         if (r == 0) {
         if (r == 0) {
             priv->fw_sta.dl_data = fw_entry->data;
             priv->fw_sta.dl_data = fw_entry->data;

+ 20 - 0
drivers/staging/csr/io.c

@@ -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);
     INIT_WORK(&priv->rx_work_struct, rx_wq_handler);
 #endif
 #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 */
     /* Initialise the SME related threads and parameters */
     r = uf_sme_init(priv);
     r = uf_sme_init(priv);
     if (r) {
     if (r) {
@@ -431,6 +438,12 @@ register_unifi_sdio(CsrSdioFunction *sdio_dev, int bus_id, struct device *dev)
     return priv;
     return priv;
 
 
 failed4:
 failed4:
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+if (log_hip_signals)
+{
+    uf_unregister_hip_offline_debug(priv);
+}
+#endif
 #ifdef CSR_WIFI_RX_PATH_SPLIT
 #ifdef CSR_WIFI_RX_PATH_SPLIT
     flush_workqueue(priv->rx_workqueue);
     flush_workqueue(priv->rx_workqueue);
     destroy_workqueue(priv->rx_workqueue);
     destroy_workqueue(priv->rx_workqueue);
@@ -547,6 +560,13 @@ cleanup_unifi_sdio(unifi_priv_t *priv)
     priv->smepriv = NULL;
     priv->smepriv = NULL;
 #endif
 #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 */
     /* Free any packets left in the Rx queues */
     for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
     for(i=0;i<CSR_WIFI_NUM_INTERFACES;i++)
     {
     {

+ 132 - 36
drivers/staging/csr/netdev.c

@@ -402,9 +402,14 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
 
 
     priv->sta_wmm_capabilities = 0;
     priv->sta_wmm_capabilities = 0;
 
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_SUPPORT_SME))
     priv->wapi_multicast_filter = 0;
     priv->wapi_multicast_filter = 0;
     priv->wapi_unicast_filter = 0;
     priv->wapi_unicast_filter = 0;
     priv->wapi_unicast_queued_pkt_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 */
     /* Enable all queues by default */
     interfacePriv->queueEnabled[0] = 1;
     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->send_signal_lock);
 
 
     spin_lock_init(&priv->m4_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
 #ifdef CSR_SUPPORT_SME
     spin_lock_init(&priv->staRecord_lock);
     spin_lock_init(&priv->staRecord_lock);
@@ -472,6 +485,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
 
 
     /* Create m4 buffering work structure */
     /* Create m4 buffering work structure */
     INIT_WORK(&interfacePriv->send_m4_ready_task, uf_send_m4_ready_wq);
     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
 #endif
 
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
 #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 */
 #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;
     return priv;
 } /* uf_alloc_netdevice() */
 } /* uf_alloc_netdevice() */
 
 
@@ -655,6 +678,19 @@ uf_free_netdevice(unifi_priv_t *priv)
     }
     }
     spin_unlock_irqrestore(&priv->m4_lock, flags);
     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)
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
 #ifdef CONFIG_NET_SCHED
 #ifdef CONFIG_NET_SCHED
     /* Unregister the qdisc operations */
     /* 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 Qos Data or Qos Null Data then set QosControl field */
     if ((priority != CSR_CONTENTION) && (macHeaderLengthInBytes >= QOS_CONTROL_HEADER_SIZE)) {
     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);
             unifi_trace(priv, UDBG1, "data packets priority is more than 7, priority = %x\n", priority);
             qc |= 7;
             qc |= 7;
         } else {
         } 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;
     CSR_TRANSMISSION_CONTROL transmissionControl = CSR_NO_CONFIRM_REQUIRED;
     CsrInt8 protection;
     CsrInt8 protection;
     netInterface_priv_t *interfacePriv = NULL;
     netInterface_priv_t *interfacePriv = NULL;
+    CSR_RATE TransmitRate = (CSR_RATE)0;
 
 
     unifi_trace(priv, UDBG5, "entering send_ma_pkt_request\n");
     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;
             return 0;
         }
         }
 #endif
 #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 */
     /* 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 */
                                  0xffffffff,  /* Ask for a new HostTag */
                                  interfaceTag,
                                  interfaceTag,
                                  transmissionControl,
                                  transmissionControl,
-                                 (CSR_RATE)0,
+                                 TransmitRate,
                                  priority,
                                  priority,
                                  priv->netdev_client->sender_id,
                                  priv->netdev_client->sender_id,
                                  &bulkdata);
                                  &bulkdata);
@@ -1900,8 +1994,22 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif /* CONFIG_NET_SCHED */
 #endif /* CONFIG_NET_SCHED */
 
 
     if (result == NETDEV_TX_OK) {
     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
          * 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++;
         interfacePriv->stats.tx_packets++;
         /* count only the packet payload */
         /* count only the packet payload */
         interfacePriv->stats.tx_bytes += skb->len;
         interfacePriv->stats.tx_bytes += skb->len;
-
+#endif
     } else if (result < 0) {
     } else if (result < 0) {
 
 
         /* Failed to send: fh queue was full, and the skb was discarded.
         /* 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 */
     /* Pass SKB up the stack */
 #ifdef CSR_WIFI_USE_NETIF_RX
 #ifdef CSR_WIFI_USE_NETIF_RX
         netif_rx(skb);
         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)){
             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)){
                 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);
                     qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 30);
                 }
                 }
                 else{
                 else{
                     qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 24);
                     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;
             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++){
         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];
             ba_session = interfacePriv->ba_session_rx[ba_session_idx];
             if (ba_session){
             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;
                         frame_desc.active = TRUE;
                         unifi_trace(priv, UDBG6, "%s: calling process_ba_frame (session=%d)\n", __FUNCTION__, ba_session_idx);
                         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);
                         process_ba_frame(priv, interfacePriv, ba_session, &frame_desc);
-                        spin_unlock(&priv->ba_lock);
+                        up(&priv->ba_mutex);
                         process_ba_complete(priv, interfacePriv);
                         process_ba_complete(priv, interfacePriv);
                         break;
                         break;
                 }
                 }
             }
             }
         }
         }
         if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){
         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__);
             unifi_trace(priv, UDBG6, "%s: calling process_amsdu()", __FUNCTION__);
             process_amsdu(priv, signal, bulkdata);
             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
      * And also this code here takes care that timeout check is made for all
      * the receive indications
      * the receive indications
      */
      */
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){
     for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){
         ba_session_rx_struct *ba_session;
         ba_session_rx_struct *ba_session;
         ba_session = interfacePriv->ba_session_rx[i];
         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);
                 check_ba_frame_age_timeout(priv, interfacePriv, ba_session);
             }
             }
     }
     }
+    up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
     process_ba_complete(priv, interfacePriv);
-    spin_unlock(&priv->ba_lock);
 
 
     func_exit();
     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;
     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 */
     /* 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++){
     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];
         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);
     process_ba_complete(priv, interfacePriv);
     func_exit();
     func_exit();
 }
 }

+ 15 - 11
drivers/staging/csr/os.c

@@ -204,12 +204,10 @@ extern int unifi_debug;
             (_s)[DEBUG_BUFFER_SIZE - 1] = 0;            \
             (_s)[DEBUG_BUFFER_SIZE - 1] = 0;            \
         }                                               \
         }                                               \
     } while (0)
     } while (0)
-#endif /* UNIFI_DEBUG */
 
 
 void
 void
 unifi_error(void* ospriv, const char *fmt, ...)
 unifi_error(void* ospriv, const char *fmt, ...)
 {
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
     va_list args;
@@ -230,13 +228,11 @@ unifi_error(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
     FORMAT_TRACE(s, len, args, fmt);
 
 
     printk("%s", s);
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 }
 
 
 void
 void
 unifi_warning(void* ospriv, const char *fmt, ...)
 unifi_warning(void* ospriv, const char *fmt, ...)
 {
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
     va_list args;
@@ -259,14 +255,12 @@ unifi_warning(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
     FORMAT_TRACE(s, len, args, fmt);
 
 
     printk("%s", s);
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 }
 
 
 
 
 void
 void
 unifi_notice(void* ospriv, const char *fmt, ...)
 unifi_notice(void* ospriv, const char *fmt, ...)
 {
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
     va_list args;
@@ -289,14 +283,12 @@ unifi_notice(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
     FORMAT_TRACE(s, len, args, fmt);
 
 
     printk("%s", s);
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 }
 
 
 
 
 void
 void
 unifi_info(void* ospriv, const char *fmt, ...)
 unifi_info(void* ospriv, const char *fmt, ...)
 {
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
     va_list args;
@@ -319,14 +311,12 @@ unifi_info(void* ospriv, const char *fmt, ...)
     FORMAT_TRACE(s, len, args, fmt);
     FORMAT_TRACE(s, len, args, fmt);
 
 
     printk("%s", s);
     printk("%s", s);
-#endif /* UNIFI_DEBUG */
 }
 }
 
 
 /* debugging */
 /* debugging */
 void
 void
 unifi_trace(void* ospriv, int level, const char *fmt, ...)
 unifi_trace(void* ospriv, int level, const char *fmt, ...)
 {
 {
-#ifdef UNIFI_DEBUG
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     unifi_priv_t *priv = (unifi_priv_t*) ospriv;
     char s[DEBUG_BUFFER_SIZE];
     char s[DEBUG_BUFFER_SIZE];
     va_list args;
     va_list args;
@@ -351,9 +341,23 @@ unifi_trace(void* ospriv, int level, const char *fmt, ...)
 
 
         printk("%s", s);
         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 */
+
+
 /*
 /*
  * ---------------------------------------------------------------------------
  * ---------------------------------------------------------------------------
  *
  *

+ 25 - 4
drivers/staging/csr/putest.c

@@ -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");
                     "unifi_putest_gp_read16: Failed to get the params\n");
         return -EFAULT;
         return -EFAULT;
     }
     }
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data);
     csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
         unifi_error(priv,
                     "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult);
                     "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);
     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);
     csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
         unifi_error(priv,
                     "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult);
                     "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);
     unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed);
 
 
     CsrSdioClaim(priv->sdio);
     CsrSdioClaim(priv->sdio);
-    csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed);
+    csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed * 1000);
     CsrSdioRelease(priv->sdio);
     CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
         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 */
     /* Application may have stopped the XAPs, but they are needed for reset */
     if (already_in_test) {
     if (already_in_test) {
+        CsrSdioClaim(priv->sdio);
         csrResult = unifi_start_processors(priv->card);
         csrResult = unifi_start_processors(priv->card);
+        CsrSdioRelease(priv->sdio);
         if (csrResult != CSR_RESULT_SUCCESS) {
         if (csrResult != CSR_RESULT_SUCCESS) {
             unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
             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);
             unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult);
         }
         }
     }
     }
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_init(priv->card);
     csrResult = unifi_init(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
         unifi_error(priv,
                     "unifi_putest_start: failed to init UniFi\n");
                     "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;
     CsrResult csrResult;
 
 
     /* Application may have stopped the XAPs, but they are needed for reset */
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
         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 */
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
         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
     /* 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
      * into patch format and download via the ROM boot loader
      */
      */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_download(priv->card, 0x0c00);
     csrResult = unifi_download(priv->card, 0x0c00);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
         unifi_error(priv,
                     "unifi_putest_dl_fw: failed to download the f/w\n");
                     "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;
     priv->fw_sta.dl_len = fw_length;
 
 
     /* Application may have stopped the XAPs, but they are needed for reset */
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
         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
     /* 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
      * into patch format and download via the ROM boot loader
      */
      */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_download(priv->card, 0x0c00);
     csrResult = unifi_download(priv->card, 0x0c00);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
         unifi_error(priv,
                     "unifi_putest_dl_fw_buff: failed to download the f/w\n");
                     "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 */
             /* Card software reset */
+            CsrSdioClaim(priv->sdio);
             r = unifi_card_hard_reset(priv->card);
             r = unifi_card_hard_reset(priv->card);
+            CsrSdioRelease(priv->sdio);
             if (r != CSR_RESULT_SUCCESS) {
             if (r != CSR_RESULT_SUCCESS) {
                 unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r);
                 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
     /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at
      * Raw SDIO deinit, to resume them.
      * Raw SDIO deinit, to resume them.
      */
      */
+    CsrSdioClaim(priv->sdio);
     r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH);
     r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH);
+    CsrSdioRelease(priv->sdio);
     if (r != CSR_RESULT_SUCCESS) {
     if (r != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to stop processors\n");
         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;
         return -ENOMEM;
     }
     }
 
 
+    CsrSdioClaim(priv->sdio);
     r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length);
     r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length);
+    CsrSdioRelease(priv->sdio);
     if (r != CSR_RESULT_SUCCESS) {
     if (r != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "cmd52r_block: unifi_readn failed\n");
         unifi_error(priv, "cmd52r_block: unifi_readn failed\n");
         return -EIO;
         return -EIO;

+ 173 - 14
drivers/staging/csr/sdio_emb.c

@@ -17,6 +17,7 @@
  */
  */
 #include <linux/kmod.h>
 #include <linux/kmod.h>
 #include <linux/init.h>
 #include <linux/init.h>
+#include <linux/suspend.h>
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifi.h"
 #include "unifi_priv.h"
 #include "unifi_priv.h"
 
 
@@ -25,7 +26,16 @@
 /* The function driver context, i.e the UniFi Driver */
 /* The function driver context, i.e the UniFi Driver */
 static CsrSdioFunctionDriver *sdio_func_drv;
 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 */
 /* sdioemb driver uses POSIX error codes */
 static CsrResult
 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);
     unifi_trace(NULL, UDBG1, "Setting SDIO bus clock to %d kHz\n", sdio_clock);
     sdioemb_set_max_bus_freq(fdev, 1000 * 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 */
     /* Call the main UniFi driver inserted handler */
     if (sdio_func_drv && sdio_func_drv->inserted) {
     if (sdio_func_drv && sdio_func_drv->inserted) {
         uf_add_os_device(fdev->slot_id, fdev->os_device);
         uf_add_os_device(fdev->slot_id, fdev->os_device);
         sdio_func_drv->inserted(sdio_ctx);
         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;
     return 0;
 } /* uf_glue_sdio_probe() */
 } /* uf_glue_sdio_probe() */
 
 
 
 
+
 /*
 /*
  * ---------------------------------------------------------------------------
  * ---------------------------------------------------------------------------
  *  uf_sdio_remove
  *  uf_sdio_remove
@@ -585,6 +734,11 @@ uf_sdio_remove(struct sdioemb_dev *fdev)
         sdio_func_drv->removed(sdio_ctx);
         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);
     kfree(sdio_ctx);
 
 
 } /* uf_sdio_remove */
 } /* uf_sdio_remove */
@@ -606,14 +760,7 @@ uf_sdio_remove(struct sdioemb_dev *fdev)
 static void
 static void
 uf_glue_sdio_suspend(struct sdioemb_dev *fdev)
 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() */
 } /* uf_glue_sdio_suspend() */
 
 
@@ -634,14 +781,13 @@ uf_glue_sdio_suspend(struct sdioemb_dev *fdev)
 static void
 static void
 uf_glue_sdio_resume(struct sdioemb_dev *fdev)
 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() */
 } /* uf_glue_sdio_resume() */
 
 
 
 
@@ -708,6 +854,15 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
     /* Save the registered driver description */
     /* Save the registered driver description */
     sdio_func_drv = sdio_drv;
     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 */
     /* Register ourself with sdioemb */
     r = sdioemb_driver_register(&unifi_sdioemb);
     r = sdioemb_driver_register(&unifi_sdioemb);
     if (r) {
     if (r) {
@@ -724,6 +879,10 @@ CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 {
 {
     sdioemb_driver_unregister(&unifi_sdioemb);
     sdioemb_driver_unregister(&unifi_sdioemb);
 
 
+#ifdef ANDROID_BUILD
+    wake_lock_destroy(&unifi_sdio_wake_lock);
+#endif
+
     sdio_func_drv = NULL;
     sdio_func_drv = NULL;
 
 
     CsrPmemFree(unifi_sdioemb.id_table);
     CsrPmemFree(unifi_sdioemb.id_table);

+ 48 - 1
drivers/staging/csr/sdio_events.c

@@ -47,6 +47,12 @@ void unifi_suspend(void *ospriv)
     unifi_priv_t *priv = ospriv;
     unifi_priv_t *priv = ospriv;
     int interfaceTag=0;
     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. */
     /* Stop network traffic. */
     /* need to stop all the netdevices*/
     /* need to stop all the netdevices*/
     for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++)
     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];
         netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
         if (interfacePriv->netdev_registered == 1)
         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]);
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]);
         }
         }
     }
     }
+
+    unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME");
+
     sme_sys_suspend(priv);
     sme_sys_suspend(priv);
+
 } /* unifi_suspend() */
 } /* unifi_suspend() */
 
 
 
 
@@ -76,12 +91,44 @@ void unifi_suspend(void *ospriv)
 void unifi_resume(void *ospriv)
 void unifi_resume(void *ospriv)
 {
 {
     unifi_priv_t *priv = ospriv;
     unifi_priv_t *priv = ospriv;
+    int interfaceTag=0;
     int r;
     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);
     r = sme_sys_resume(priv);
     if (r) {
     if (r) {
         unifi_error(priv, "Failed to resume UniFi\n");
         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() */
 } /* unifi_resume() */
 
 

+ 211 - 36
drivers/staging/csr/sdio_mmc.c

@@ -21,19 +21,28 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sdio.h>
+#include <linux/suspend.h>
 
 
 #include "unifi_priv.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;
 static CsrSdioFunctionDriver *sdio_func_drv;
 
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
 #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
  * 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.
  * 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
  * 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;
 static int card_is_powered = 1;
 #endif /* 2.6.32 */
 #endif /* 2.6.32 */
@@ -312,17 +321,28 @@ csr_sdio_enable_hs(struct mmc_card *card)
     int ret;
     int ret;
     u8 speed;
     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;
         return 0;
+    }
 
 
     if (!card->cccr.high_speed)
     if (!card->cccr.high_speed)
         return 0;
         return 0;
 
 
+#if 1
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     if (ret)
     if (ret)
         return ret;
         return ret;
 
 
     speed |= SDIO_SPEED_EHS;
     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);
     ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
     if (ret)
     if (ret)
@@ -346,12 +366,16 @@ csr_sdio_disable_hs(struct mmc_card *card)
 
 
     if (!card->cccr.high_speed)
     if (!card->cccr.high_speed)
         return 0;
         return 0;
-
+#if 1
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     if (ret)
     if (ret)
         return ret;
         return ret;
 
 
     speed &= ~SDIO_SPEED_EHS;
     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);
     ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
     if (ret)
     if (ret)
@@ -460,6 +484,7 @@ CsrSdioInterruptEnable(CsrSdioFunction *function)
 
 
     func_exit();
     func_exit();
     if (err) {
     if (err) {
+        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
         return ConvertSdioToCsrSdioResult(err);
     }
     }
 #endif
 #endif
@@ -486,6 +511,7 @@ CsrSdioInterruptDisable(CsrSdioFunction *function)
 
 
     func_exit();
     func_exit();
     if (err) {
     if (err) {
+        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
         return ConvertSdioToCsrSdioResult(err);
     }
     }
 #endif
 #endif
@@ -772,6 +798,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func)
     if (!sdio_ctx) {
     if (!sdio_ctx) {
         return;
         return;
     }
     }
+
 #ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
 #ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
     /*
     /*
      * Normally, we are not allowed to do any SDIO commands here.
      * 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);
     r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL);
 #endif
 #endif
     if (r) {
     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
 #endif
 
 
@@ -824,6 +851,8 @@ csr_sdio_linux_remove_irq(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int r;
     int r;
 
 
+    unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n");
+
     sdio_claim_host(func);
     sdio_claim_host(func);
     r = sdio_release_irq(func);
     r = sdio_release_irq(func);
     sdio_release_host(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;
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int r;
     int r;
 
 
+    unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n");
+
     /* Register our interrupt handle */
     /* Register our interrupt handle */
     sdio_claim_host(func);
     sdio_claim_host(func);
     r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
     r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
@@ -866,7 +897,133 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function)
     return r;
     return r;
 } /* csr_sdio_linux_install_irq() */
 } /* 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;
         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
 #ifdef MMC_QUIRK_LENIENT_FN0
     func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
     func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 #endif
 #endif
@@ -932,6 +1093,15 @@ uf_glue_sdio_probe(struct sdio_func *func,
     /* Pass context to the SDIO driver */
     /* Pass context to the SDIO driver */
     sdio_set_drvdata(func, sdio_ctx);
     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 */
     /* Register this device with the SDIO function driver */
     /* Call the main UniFi driver inserted handler */
     /* Call the main UniFi driver inserted handler */
     if (sdio_func_drv && sdio_func_drv->inserted) {
     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 */
     /* We have finished, so release the SDIO driver */
     sdio_release_host(func);
     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();
     func_exit();
     return 0;
     return 0;
 } /* uf_glue_sdio_probe() */
 } /* uf_glue_sdio_probe() */
@@ -980,6 +1156,13 @@ uf_glue_sdio_remove(struct sdio_func *func)
         sdio_func_drv->removed(sdio_ctx);
         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);
     kfree(sdio_ctx);
 
 
     func_exit();
     func_exit();
@@ -1006,7 +1189,7 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
  * ---------------------------------------------------------------------------
  * ---------------------------------------------------------------------------
  *  uf_glue_sdio_suspend
  *  uf_glue_sdio_suspend
  *
  *
- *      Card suspend callback.
+ *      Card suspend callback. The userspace will already be suspended.
  *
  *
  * Arguments:
  * Arguments:
  *      dev            The struct device owned by the MMC driver
  *      dev            The struct device owned by the MMC driver
@@ -1018,23 +1201,9 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
 static int
 static int
 uf_glue_sdio_suspend(struct device *dev)
 uf_glue_sdio_suspend(struct device *dev)
 {
 {
-    struct sdio_func *func;
-    CsrSdioFunction *sdio_ctx;
-
     func_enter();
     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();
     func_exit();
     return 0;
     return 0;
@@ -1045,7 +1214,7 @@ uf_glue_sdio_suspend(struct device *dev)
  * ---------------------------------------------------------------------------
  * ---------------------------------------------------------------------------
  *  uf_glue_sdio_resume
  *  uf_glue_sdio_resume
  *
  *
- *      Card resume callback.
+ *      Card resume callback. The userspace will still be suspended.
  *
  *
  * Arguments:
  * Arguments:
  *      dev            The struct device owned by the MMC driver
  *      dev            The struct device owned by the MMC driver
@@ -1057,23 +1226,14 @@ uf_glue_sdio_suspend(struct device *dev)
 static int
 static int
 uf_glue_sdio_resume(struct device *dev)
 uf_glue_sdio_resume(struct device *dev)
 {
 {
-    struct sdio_func *func;
-    CsrSdioFunction *sdio_ctx;
-
     func_enter();
     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();
     func_exit();
     return 0;
     return 0;
@@ -1133,6 +1293,10 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
         return CSR_SDIO_RESULT_INVALID_VALUE;
         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 */
     /* Save the registered driver description */
     /*
     /*
      * FIXME:
      * FIXME:
@@ -1141,6 +1305,13 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
      */
      */
     sdio_func_drv = 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 */
     /* Register ourself with mmc_core */
     r = sdio_register_driver(&unifi_driver);
     r = sdio_register_driver(&unifi_driver);
     if (r) {
     if (r) {
@@ -1157,6 +1328,10 @@ void
 CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 {
 {
     printk(KERN_INFO "UniFi: unregister from MMC sdio\n");
     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_unregister_driver(&unifi_driver);
 
 
     sdio_func_drv = NULL;
     sdio_func_drv = NULL;

+ 95 - 28
drivers/staging/csr/sme_blocking.c

@@ -92,11 +92,15 @@ sme_init_request(unifi_priv_t *priv)
         return -EIO;
         return -EIO;
     }
     }
 
 
+    unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n");
+
     /* Grab the SME semaphore until the reply comes, or timeout */
     /* Grab the SME semaphore until the reply comes, or timeout */
     if (down_interruptible(&priv->sme_sem)) {
     if (down_interruptible(&priv->sme_sem)) {
         unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n");
         unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n");
         return -EIO;
         return -EIO;
     }
     }
+    unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n");
+
     priv->sme_reply.request_status = SME_REQUEST_PENDING;
     priv->sme_reply.request_status = SME_REQUEST_PENDING;
 
 
     return 0;
     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);
                     (func ? func : ""), priv->sme_reply.request_status);
         return;
         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.request_status = SME_REQUEST_RECEIVED;
     priv->sme_reply.reply_status = reply_status;
     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
 static int
 _sme_wait_for_reply(unifi_priv_t *priv,
 _sme_wait_for_reply(unifi_priv_t *priv,
         unsigned long timeout, const char *func)
         unsigned long timeout, const char *func)
 {
 {
     long r;
     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,
     r = wait_event_interruptible_timeout(priv->sme_request_wq,
                                          (priv->sme_reply.request_status != SME_REQUEST_PENDING),
                                          (priv->sme_reply.request_status != SME_REQUEST_PENDING),
                                          msecs_to_jiffies(timeout));
                                          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) {
     if (r == -ERESTARTSYS) {
         /* The thread was killed */
         /* The thread was killed */
+        unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n");
         up(&priv->sme_sem);
         up(&priv->sme_sem);
         return r;
         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)) {
     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",
         unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n",
                      (func ? func : ""), priv->sme_reply.request_status, timeout);
                      (func ? func : ""), priv->sme_reply.request_status, timeout);
@@ -156,6 +207,9 @@ _sme_wait_for_reply(unifi_priv_t *priv,
         return -ETIMEDOUT;
         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() */
     /* Release the SME semaphore that was downed in sme_init_request() */
     up(&priv->sme_sem);
     up(&priv->sme_sem);
 
 
@@ -1289,22 +1343,20 @@ int sme_sys_suspend(unifi_priv_t *priv)
         return -EIO;
         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);
     CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
     if (r) {
     if (r) {
         /* No reply - forcibly power down in case the request wasn't processed */
         /* No reply - forcibly power down in case the request wasn't processed */
         unifi_notice(priv,
         unifi_notice(priv,
                      "suspend: SME did not reply %s, ",
                      "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 */
         /* Leave power on for production test, though */
         if (!priv->ptest_mode) {
         if (!priv->ptest_mode) {
             /* Put UniFi to deep sleep, in case we can not power it off */
             /* Put UniFi to deep sleep, in case we can not power it off */
             CsrSdioClaim(priv->sdio);
             CsrSdioClaim(priv->sdio);
+            unifi_trace(priv, UDBG1, "Force deep sleep");
             csrResult = unifi_force_low_power_mode(priv->card);
             csrResult = unifi_force_low_power_mode(priv->card);
 
 
             /* For WOL, the UniFi must stay powered */
             /* For WOL, the UniFi must stay powered */
@@ -1319,13 +1371,40 @@ int sme_sys_suspend(unifi_priv_t *priv)
     if (priv->wol_suspend) {
     if (priv->wol_suspend) {
         unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n");
         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 */
     /* 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);
     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;
     return 0;

+ 450 - 132
drivers/staging/csr/sme_sys.c

@@ -20,6 +20,8 @@
 #ifdef CSR_SUPPORT_WEXT_AP
 #ifdef CSR_SUPPORT_WEXT_AP
 #include "sme_csr/csr_wifi_sme_sef.h"
 #include "sme_csr/csr_wifi_sme_sef.h"
 #endif
 #endif
+
+
 /*
 /*
  * This file implements the SME SYS API and contains the following functions:
  * This file implements the SME SYS API and contains the following functions:
  * CsrWifiRouterCtrlMediaStatusReqHandler()
  * CsrWifiRouterCtrlMediaStatusReqHandler()
@@ -40,8 +42,10 @@
  * CsrWifiRouterCtrlTclasDelReqHandler()
  * CsrWifiRouterCtrlTclasDelReqHandler()
  * CsrWifiRouterCtrlSetModeReqHandler()
  * CsrWifiRouterCtrlSetModeReqHandler()
  * CsrWifiRouterCtrlWapiMulticastFilterReqHandler()
  * CsrWifiRouterCtrlWapiMulticastFilterReqHandler()
- * CsrWifiRouterCtrlWapiMulticastReqHandler()
  * CsrWifiRouterCtrlWapiUnicastFilterReqHandler()
  * CsrWifiRouterCtrlWapiUnicastFilterReqHandler()
+ * CsrWifiRouterCtrlWapiUnicastTxPktReqHandler()
+ * CsrWifiRouterCtrlWapiRxPktReqHandler()
+ * CsrWifiRouterCtrlWapiFilterReqHandler()
  */
  */
 
 
 #ifdef CSR_SUPPORT_SME
 #ifdef CSR_SUPPORT_SME
@@ -731,10 +735,31 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     if (priv == NULL) {
     if (priv == NULL) {
         return;
         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.
      * 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 */
     /* Update the wifi_on state */
     priv->wifi_on_state = wifi_on_in_progress;
     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) */
     /* Power on UniFi (which may not necessarily have been off) */
@@ -832,6 +862,13 @@ wifi_off(unifi_priv_t *priv)
     int i;
     int i;
     CsrResult csrResult;
     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");
     unifi_trace(priv, UDBG1, "wifi_off\n");
 
 
     /* Destroy the Traffic Analysis Module */
     /* Destroy the Traffic Analysis Module */
@@ -840,6 +877,7 @@ wifi_off(unifi_priv_t *priv)
     cancel_work_sync(&priv->ta_sample_ind_work.task);
     cancel_work_sync(&priv->ta_sample_ind_work.task);
 #ifdef CSR_SUPPORT_WEXT
 #ifdef CSR_SUPPORT_WEXT
     cancel_work_sync(&priv->sme_config_task);
     cancel_work_sync(&priv->sme_config_task);
+    wext_send_disassoc_event(priv);
 #endif
 #endif
 
 
     /* Cancel pending M4 stuff */
     /* Cancel pending M4 stuff */
@@ -908,9 +946,6 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg;
     CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg;
     int i = 0;
     int i = 0;
-#ifdef CSR_SUPPORT_WEXT_AP
-    CsrWifiSmeWifiOffCfm cfm;
-#endif
 
 
     if (priv == NULL) {
     if (priv == NULL) {
         return;
         return;
@@ -924,6 +959,7 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         if (interfacePriv->netdev_registered == 1) {
         if (interfacePriv->netdev_registered == 1) {
             netif_carrier_off(priv->netdev[i]);
             netif_carrier_off(priv->netdev[i]);
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]);
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]);
+            interfacePriv->connected = UnifiConnectedUnknown;
         }
         }
         interfacePriv->interfaceMode = 0;
         interfacePriv->interfaceMode = 0;
 
 
@@ -936,15 +972,11 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     wifi_off(priv);
     wifi_off(priv);
 
 
     CsrWifiRouterCtrlWifiOffCfmSend(msg->source,req->clientData);
     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 */
         int i; /* used as a loop counter */
         CsrUint32 intmode = CSR_WIFI_INTMODE_DEFAULT;
         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 */
         /* Register the UniFi device with the OS network manager */
         unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n");
         unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n");
 
 
@@ -1099,6 +1133,16 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
                     return;
                     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;
         priv->totalInterfaceCount = res->numInterfaceAddress;
 
 
@@ -1117,8 +1161,27 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */
         /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */
         CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS);
         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");
         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
         /* Firmware initialisation is complete, so let the SDIO bus
          * clock be raised when convienent to the core.
          * clock be raised when convienent to the core.
          */
          */
@@ -1257,15 +1320,7 @@ void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         return;
         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));
                                              &(interfacePriv->genericMulticastOrBroadCastFrames));
 
 
     uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastFrames));
     uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastFrames));
-    uf_flush_maPktlist(priv,&(interfacePriv->directedMaPktReq));
 
 
     /*  process the list of frames that requested cfm
     /*  process the list of frames that requested cfm
     and send cfm to requestor one by one */
     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)
     if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES)
     {
     {
         netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
         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",
         unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n",
                 interfacePriv->interfaceMode);
                 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;
         interfacePriv->bssid = req->bssid;
         /* For modes other than AP/P2PGO, set below member FALSE */
         /* For modes other than AP/P2PGO, set below member FALSE */
         interfacePriv->intraBssEnabled = 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 ||
         if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
            req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
            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 *controlledPort;
     unifi_port_config_t *unControlledPort;
     unifi_port_config_t *unControlledPort;
     netInterface_priv_t *interfacePriv;
     netInterface_priv_t *interfacePriv;
-    maPktReqList_t *maPktreq;
-    struct list_head *listHeadMaPktreq,*placeHolderMaPktreq;
 
 
     CsrUint8 ba_session_idx = 0;
     CsrUint8 ba_session_idx = 0;
     ba_session_rx_struct *ba_session_rx = NULL;
     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]));
             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);
         spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
         /* clear the port configure array info, for the corresponding peer entry */
         /* clear the port configure array info, for the corresponding peer entry */
         controlledPort = &interfacePriv->controlled_data_port;
         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
         /* Stop BA session if it is active, for this peer address all BA sessions
         (per tID per role) are closed */
         (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++){
         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];
             ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx];
             if(ba_session_rx) {
             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
 #ifdef CSR_SUPPORT_SME
         unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid);
         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;
             newRecord->txSuspend = FALSE;
 
 
             /*U-APSD related data structure*/
             /*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->uapsdActive = FALSE;
             newRecord->noOfSpFramesSent =0;
             newRecord->noOfSpFramesSent =0;
+            newRecord->triggerFramePriority = CSR_QOS_UP0;
 
 
             /* The protection bit is updated once the port opens for corresponding peer in
             /* The protection bit is updated once the port opens for corresponding peer in
              * routerPortConfigure request */
              * routerPortConfigure request */
@@ -2602,13 +2719,13 @@ void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent*
 
 
     unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__);
     unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__);
 
 
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     r = blockack_session_stop(priv,
     r = blockack_session_stop(priv,
                               req->interfaceTag,
                               req->interfaceTag,
                               req->role,
                               req->role,
                               req->trafficStreamID,
                               req->trafficStreamID,
                               req->macAddress);
                               req->macAddress);
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
 
 
     CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source,
     CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source,
                                             req->clientData,
                                             req->clientData,
@@ -2746,6 +2863,16 @@ CsrBool blockack_session_start(unifi_priv_t *priv,
                             init_timer(&ba_session_rx->timer);
                             init_timer(&ba_session_rx->timer);
                             mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024)));
                             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;
                         return TRUE;
                     }
                     }
                 }
                 }
@@ -2768,6 +2895,21 @@ CsrBool blockack_session_start(unifi_priv_t *priv,
             return FALSE;
             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);
         ba_session_rx = kmalloc(sizeof(ba_session_rx_struct), GFP_KERNEL);
         if (!ba_session_rx) {
         if (!ba_session_rx) {
@@ -2814,7 +2956,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
 
 
     unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
     unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     r = blockack_session_start(priv,
     r = blockack_session_start(priv,
                                req->interfaceTag,
                                req->interfaceTag,
                                req->trafficStreamID,
                                req->trafficStreamID,
@@ -2824,7 +2966,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
                                req->ssn,
                                req->ssn,
                                req->macAddress
                                req->macAddress
                               );
                               );
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
 
 
     CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source,
     CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source,
                                            req->clientData,
                                            req->clientData,
@@ -2836,115 +2978,291 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
 
 
 void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 {
 {
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg;
     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)
 void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 {
 {
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg;
     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;
     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;
     int client_id, receiver_id;
     bulk_data_param_t bulkdata;
     bulk_data_param_t bulkdata;
     CsrResult res;
     CsrResult res;
     ul_client_t *client;
     ul_client_t *client;
-
     CSR_SIGNAL signal;
     CSR_SIGNAL signal;
     CSR_MA_PACKET_INDICATION *pkt_ind;
     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
 }
 }

+ 2 - 3
drivers/staging/csr/sme_userspace.c

@@ -101,7 +101,6 @@ uf_sme_init(unifi_priv_t *priv)
         INIT_LIST_HEAD(&interfacePriv->genericMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames);
-        INIT_LIST_HEAD(&interfacePriv->directedMaPktReq);
 
 
         for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
         for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
             interfacePriv->staInfo[j] = NULL;
             interfacePriv->staInfo[j] = NULL;
@@ -139,7 +138,7 @@ uf_sme_deinit(unifi_priv_t *priv)
 
 
     /* Remove all the Peer database, before going down */
     /* Remove all the Peer database, before going down */
     for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
     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++){
         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];
             ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx];
             if(ba_session_rx) {
             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];
         interfacePriv = priv->interfacePriv[i];
         if(interfacePriv){
         if(interfacePriv){
             for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
             for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {

+ 3 - 1
drivers/staging/csr/sme_wext.c

@@ -29,8 +29,10 @@
         }                                                   \
         }                                                   \
     } while (0)
     } 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
 #define CSR_WIFI_WEXT_HANG_WORKAROUND
+#endif
 
 
 #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND
 #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND
 # define UF_RTNL_LOCK()    rtnl_lock()
 # define UF_RTNL_LOCK()    rtnl_lock()

+ 3 - 22
drivers/staging/csr/ul_int.c

@@ -265,7 +265,9 @@ ul_log_config_ind(unifi_priv_t *priv, u8 *conf_param, int len)
         /* wifi_off_ind (error or exit) */
         /* wifi_off_ind (error or exit) */
         CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, (CsrWifiRouterCtrlControlIndication)(*conf_param));
         CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, (CsrWifiRouterCtrlControlIndication)(*conf_param));
     }
     }
-
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    unifi_debug_buf_dump();
+#endif
 #else
 #else
     bulk_data_param_t bulkdata;
     bulk_data_param_t bulkdata;
 
 
@@ -420,10 +422,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
     CsrResult csrResult;
     CsrResult csrResult;
     unsigned long lock_flags;
     unsigned long lock_flags;
     int r;
     int r;
-#ifdef CSR_SUPPORT_SME
-    netInterface_priv_t *interfacePriv = priv->interfacePriv[0];
-    CsrUint32 alignOffset = 0;
-#endif
 
 
 
 
     csrResult = write_pack(sigptr, sigbuf, &packed_siglen);
     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");
         unifi_error(priv, "Malformed HIP signal in ul_send_signal_unpacked()\n");
         return CsrHipResultToStatus(csrResult);
         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);
     r = _align_bulk_data_buffers(priv, sigbuf, (bulk_data_param_t*)bulkdata);
     if (r) {
     if (r) {
         return 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);
         spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags);
         return CsrHipResultToStatus(csrResult);
         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);
     spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags);
 
 
     return 0;
     return 0;

+ 223 - 317
drivers/staging/csr/unifi_event.c

@@ -109,7 +109,11 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv,
     static const CsrUint8 wapiProtocolIdSNAPHeaderOffset = 6;
     static const CsrUint8 wapiProtocolIdSNAPHeaderOffset = 6;
     CsrUint8 *destAddr;
     CsrUint8 *destAddr;
     CsrUint8 *srcAddr;
     CsrUint8 *srcAddr;
-    CsrBool isUnicastPkt = FALSE;
+    CsrBool isWapiUnicastPkt = FALSE;
+
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    CsrUint16 qosControl;
+#endif
 
 
     CsrUint8 llcSnapHeaderOffset = 0;
     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;
     srcAddr  = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET;
 
 
     /*Individual/Group bit - Bit 0 of first byte*/
     /*Individual/Group bit - Bit 0 of first byte*/
-    isUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE;
+    isWapiUnicastPkt = (!(destAddr[0] & 0x01)) ? TRUE : FALSE;
 #endif
 #endif
 
 
 #define CSR_WIFI_MA_PKT_IND_RECEPTION_STATUS_OFFSET    sizeof(CSR_SIGNAL_PRIMITIVE_HEADER) + 22
 #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) {
         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
             /* 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.
              * 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*/
                 /*Discard the frame*/
                 *freeBulkData = TRUE;
                 *freeBulkData = TRUE;
                 unifi_trace(priv, UDBG4, "Discarding the contents of the frame with MIC failure \n");
                 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)||
                     ((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) ||
                     (priv->wapi_unicast_filter) ||
+#endif
                     (priv->wapi_unicast_queued_pkt_filter))) {
                     (priv->wapi_unicast_queued_pkt_filter))) {
 
 
                     /* Workaround to handle MIC failures reported by the firmware for encrypted packets from the AP
                     /* 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
     /* 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
      * 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) &&
         (receptionStatus == CSR_RX_SUCCESS) &&
         (priv->wapi_unicast_queued_pkt_filter==1)) {
         (priv->wapi_unicast_queued_pkt_filter==1)) {
 
 
@@ -297,16 +336,10 @@ static CsrBool check_routing_pkt_data_ind(unifi_priv_t *priv,
             return FALSE;
             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.
  *      Dispatcher for received signals.
  *
  *
@@ -332,56 +365,11 @@ static CsrBool signal_buffer_is_full(unifi_priv_t* priv)
  *  binded to the host interface specification.
  *  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;
     unifi_priv_t *priv = (unifi_priv_t*)ospriv;
     int i, receiver_id;
     int i, receiver_id;
     int client_id;
     int client_id;
@@ -390,16 +378,17 @@ unifi_receive_event(void *ospriv,
 
 
     func_enter();
     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;
     receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)) & 0xFF00;
     client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
     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) */
     /* check for the type of frame received (checks for 802.11 management frames) */
     if (signal_id == CSR_MA_PACKET_INDICATION_ID)
     if (signal_id == CSR_MA_PACKET_INDICATION_ID)
     {
     {
+#define CSR_MA_PACKET_INDICATION_INTERFACETAG_OFFSET    14
         CsrUint8 interfaceTag;
         CsrUint8 interfaceTag;
         netInterface_priv_t *interfacePriv;
         netInterface_priv_t *interfacePriv;
 
 
         /* Pull out interface tag from virtual interface identifier */
         /* 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];
         interfacePriv = priv->interfacePriv[interfaceTag];
 
 
         /* Update activity for this station in case of IBSS */
         /* Update activity for this station in case of IBSS */
 #ifdef CSR_SUPPORT_SME
 #ifdef CSR_SUPPORT_SME
-
-        if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS) {
-
+        if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_IBSS)
+        {
             CsrUint8 *saddr;
             CsrUint8 *saddr;
             /* Fetch the source address from  mac header */
             /* Fetch the source address from  mac header */
             saddr = (CsrUint8 *) bulkdata->d[0].os_data_ptr + MAC_HEADER_ADDR2_OFFSET;
             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);
         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");
         unifi_trace(priv, UDBG6, "RX: packet entry point to driver from HIP,pkt to SME ?(%s) \n", (pktIndToSme)? "YES":"NO");
+
     }
     }
 
 
     if (pktIndToSme)
     if (pktIndToSme)
@@ -445,7 +435,7 @@ unifi_receive_event(void *ospriv,
             send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata);
             send_to_client(priv, priv->sme_cli, receiver_id, sigdata, siglen, bulkdata);
         }
         }
         else{
         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
 #ifdef CSR_NATIVE_LINUX
         send_to_client(priv, priv->wext_client,
         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
          * unless they are data/control MA_PACKET_INDs or VIF_AVAILABILITY_INDs
          */
          */
         if (!receiver_id) {
         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
 #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
 #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
 #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
 #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.
         /* calls the registered clients handler callback func.
          * netdev_mlme_event_handler is one of the registered handler used to route
          * 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
          * 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
          * the frame needs to be freed here. So not to be passed to netdev handler
          */
          */
         if(!freeBulkData){
         if(!freeBulkData){
             if ((client_id < MAX_UDI_CLIENTS) &&
             if ((client_id < MAX_UDI_CLIENTS) &&
                     (&priv->ul_clients[client_id] != priv->logging_client)) {
                     (&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],
                 send_to_client(priv, &priv->ul_clients[client_id],
                         receiver_id,
                         receiver_id,
                         sigdata, siglen, bulkdata);
                         sigdata, siglen, bulkdata);
@@ -550,14 +572,54 @@ unifi_receive_event(void *ospriv,
                 }
                 }
             }
             }
     }
     }
-#endif
+
     func_exit();
     func_exit();
-} /* unifi_receive_event() */
+} /* unifi_process_receive_event() */
+
 
 
 #ifdef CSR_WIFI_RX_PATH_SPLIT
 #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.
  *      Dispatcher for received signals.
  *
  *
@@ -583,20 +645,19 @@ unifi_receive_event(void *ospriv,
  *  binded to the host interface specification.
  *  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;
     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();
     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",
             "%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)*0) & 0xFFFF,
             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*1) & 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)*5) & 0xFFFF,
             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF,
             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*6) & 0xFFFF,
             CSR_GET_UINT16_FROM_LITTLE_ENDIAN((sigdata) + sizeof(CsrInt16)*7) & 0xFFFF, siglen);
             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
 #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
 #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();
     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

+ 15 - 7
drivers/staging/csr/unifi_os.h

@@ -97,6 +97,13 @@ void dump16(void *mem, CsrUint16 len);
 void dump_str(void *mem, CsrUint16 len);
 void dump_str(void *mem, CsrUint16 len);
 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
 #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
 #else
 
 
 /* Stubs */
 /* Stubs */
@@ -113,15 +120,16 @@ static inline void dump16(void *mem, CsrUint16 len) {}
 static inline void dump_str(void *mem, CsrUint16 len) {}
 static inline void dump_str(void *mem, CsrUint16 len) {}
 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
 #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... */
 /* Different levels of diagnostic detail... */
 #define UDBG0       0   /* always prints in debug build */
 #define UDBG0       0   /* always prints in debug build */

+ 791 - 768
drivers/staging/csr/unifi_pdu_processing.c

@@ -32,22 +32,23 @@
 static void _update_buffered_pkt_params_after_alignment(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
 static void _update_buffered_pkt_params_after_alignment(unifi_priv_t *priv, bulk_data_param_t *bulkdata,
                                                         tx_buffered_packets_t* buffered_pkt)
                                                         tx_buffered_packets_t* buffered_pkt)
 {
 {
-
     struct sk_buff *skb ;
     struct sk_buff *skb ;
     CsrUint32 align_offset;
     CsrUint32 align_offset;
 
 
     if (priv == NULL || bulkdata == NULL || buffered_pkt == NULL){
     if (priv == NULL || bulkdata == NULL || buffered_pkt == NULL){
         return;
         return;
     }
     }
+
     skb = (struct sk_buff*)bulkdata->d[0].os_net_buf_ptr;
     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);
     align_offset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1);
     if(align_offset){
     if(align_offset){
         skb_pull(skb,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
 #endif
 
 
@@ -122,7 +123,7 @@ unifi_frame_ma_packet_req(unifi_priv_t *priv, CSR_PRIORITY priority,
 #ifdef CSR_SUPPORT_SME
 #ifdef CSR_SUPPORT_SME
 
 
 #define TRANSMISSION_CONTROL_TRIGGER_MASK 0x0001
 #define TRANSMISSION_CONTROL_TRIGGER_MASK 0x0001
-#define TRANSMISSION_CONTROL_ESOP_MASK 0x0002
+#define TRANSMISSION_CONTROL_EOSP_MASK 0x0002
 
 
 static
 static
 int frame_and_send_queued_pdu(unifi_priv_t* priv,tx_buffered_packets_t* buffered_pkt,
 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_DATA & IEEE80211_FC_SUBTYPE_MASK:
             case IEEE802_11_FC_TYPE_QOS_NULL & 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 both are set then the Address4 exists (only for AP) */
-                if (fromDs && toDs)
-                {
+                if (fromDs && toDs) {
                     /* 6 is the size of Address4 field */
                     /* 6 is the size of Address4 field */
                     macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6);
                     macHeaderLengthInBytes += (QOS_CONTROL_HEADER_SIZE + 6);
-                }
-                else
-                {
+                } else {
                     macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE;
                     macHeaderLengthInBytes += QOS_CONTROL_HEADER_SIZE;
                 }
                 }
 
 
                 /* If order bit set then HT control field is the part of MAC header */
                 /* If order bit set then HT control field is the part of MAC header */
                 if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) {
                 if (*fc & cpu_to_le16(IEEE80211_FC_ORDER_MASK)) {
                     macHeaderLengthInBytes += HT_CONTROL_HEADER_SIZE;
                     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;
                 break;
             default:
             default:
                 if (fromDs && toDs)
                 if (fromDs && toDs)
                     macHeaderLengthInBytes += 6;
                     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);
     result = ul_send_signal_unpacked(priv, &signal, &bulkdata);
     if(result){
     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);
     spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
     list_for_each_prev_safe(listHead, placeHolder, txList) {
     list_for_each_prev_safe(listHead, placeHolder, txList) {
         tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
         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));
         tx_q_item->transmissionControl = (tx_q_item->transmissionControl & ~(CSR_NO_CONFIRM_REQUIRED));
         unifi_trace(priv, UDBG1,
         unifi_trace(priv, UDBG1,
                 "set_eosp_transmit_ctrl Transmission Control = 0x%x hostTag = 0x%x \n",tx_q_item->transmissionControl,tx_q_item->hostTag);
                 "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;
     bulk_data_param_t *bulkdata = NULL;
     int r;
     int r;
 
 
+    unifi_trace(priv, UDBG3, "send_vif_availibility_rsp : invoked with resultCode = %d \n", resultCode);
+
     memset(&signal,0,sizeof(CSR_SIGNAL));
     memset(&signal,0,sizeof(CSR_SIGNAL));
     rsp = &signal.u.MaVifAvailabilityResponse;
     rsp = &signal.u.MaVifAvailabilityResponse;
     rsp->VirtualInterfaceIdentifier = vif;
     rsp->VirtualInterfaceIdentifier = vif;
@@ -288,6 +284,9 @@ void send_vif_availibility_rsp(unifi_priv_t *priv,CSR_VIF_IDENTIFIER vif,CSR_RES
     if(r) {
     if(r) {
         unifi_error(priv,"Availibility response sending failed %x status %d\n",vif,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
 #endif
 
 
@@ -354,14 +353,14 @@ void verify_and_accomodate_tx_packet(unifi_priv_t *priv)
         list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) {
         list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) {
             tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
             tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
             if(eospFramedeleted){
             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));
                 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);
                 unifi_trace(priv, UDBG1,"updating eosp for next packet hostTag:= 0x%x ",tx_q_item->hostTag);
                 eospFramedeleted =0;
                 eospFramedeleted =0;
                 break;
                 break;
             }
             }
 
 
-            if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_ESOP_MASK ){
+            if(tx_q_item->transmissionControl & TRANSMISSION_CONTROL_EOSP_MASK ){
                eospFramedeleted = 1;
                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);
             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");
     unifi_trace(priv, UDBG5, "leaving enque_tx_data_pdu\n");
     return CSR_RESULT_SUCCESS;
     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)
 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",
                     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);
                                  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 {
             } else {
+
+                interfacePriv->bcTimSet = timSetValue;
                 /* fh_cmd_q can also be full at some point of time!,
                 /* fh_cmd_q can also be full at some point of time!,
                  * resetting count as queue is cleaned by firmware at this point
                  * resetting count as queue is cleaned by firmware at this point
                  */
                  */
                 retryCount = 0;
                 retryCount = 0;
                 unifi_trace(priv, UDBG3, "tim (%s) successfully for broadcast frame in firmware\n", (timSetValue)?"SET":"RESET");
                 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;
             break;
         case CSR_RC_INVALID_PARAMETERS:
         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:
         default:
             unifi_warning(priv, "tim update request failed resultcode = %x\n", cfm->ResultCode);
             unifi_warning(priv, "tim update request failed resultcode = %x\n", cfm->ResultCode);
     }
     }
+
     unifi_trace(priv, UDBG2, "leaving %s\n", __FUNCTION__);
     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");
     unifi_trace(priv, UDBG5, "entering the update_tim routine\n");
 
 
+
     if (handle == 0xFFFFFFFF) {
     if (handle == 0xFFFFFFFF) {
         handle &= CSR_WIFI_BROADCAST_OR_MULTICAST_HANDLE;
         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)) {
     } else if ((handle != 0xFFFFFFFF) && (handle >= UNIFI_MAX_CONNECTIONS)) {
         unifi_warning(priv, "bad station Handle = %x\n", handle);
         unifi_warning(priv, "bad station Handle = %x\n", handle);
         return;
         return;
@@ -785,6 +928,25 @@ void update_tim(unifi_priv_t * priv, CsrUint16 aid, CsrUint8 setTim, CsrUint16 i
         if (staRecord) {
         if (staRecord) {
             staRecord->timSet = oldTimSetStatus ;
             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");
     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)) {
     if(IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag)) {
         /* giving more priority to multicast packets so delaying unicast packets*/
         /* 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;
         return;
     }
     }
     while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) {
     while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->mgtFrames))) {
         buffered_pkt->transmissionControl &=
         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) {
         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");
             unifi_trace(priv, UDBG2, "p_p_a_t:(ENOSPC) Mgt Frame queueing \n");
             /* Enqueue at the head of the queue */
             /* Enqueue at the head of the queue */
@@ -828,11 +1008,22 @@ void process_peer_active_transition(unifi_priv_t * priv,
             kfree(buffered_pkt);
             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--) {
     for(i=3;i>=0;i--) {
         if(!spaceAvail[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);
         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]))) {
         while((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) {
            buffered_pkt->transmissionControl &=
            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) {
            if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,0,FALSE)) == -ENOSPC) {
                /* Clear the trigger bit transmission control*/
                /* Clear the trigger bit transmission control*/
                /* Enqueue at the head of the queue */
                /* 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");
     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;
     netInterface_priv_t *interfacePriv;
     CsrUint8 i;
     CsrUint8 i;
     CsrWifiRouterCtrlStaInfo_t *staRecord = NULL;
     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];
     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) &&
          if(list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) &&
               list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) {
               list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) {
             unifi_trace(priv,UDBG1,"Resetting multicastTIM");
             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,
                         uf_prepare_send_cfm_list_for_queued_pkts(priv,
                                                                  &send_cfm_list,
                                                                  &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;
                 CsrResult csrResult;
                 unifi_trace(priv, UDBG5, "normal Data packet, NO QOS \n");
                 unifi_trace(priv, UDBG5, "normal Data packet, NO QOS \n");
 
 
-                *priority = CSR_CONTENTION;
                 if (qosDestination) {
                 if (qosDestination) {
                     CsrUint8 qc = 0;
                     CsrUint8 qc = 0;
                     unifi_trace(priv, UDBG3, "destination is QOS station \n");
                     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 */
                     /* no Amsdu is in ap buffer so eosp is left 0 */
-
                     if (da[0] & 0x1) {
                     if (da[0] & 0x1) {
                         /* multicast/broadcast frames, no acknowledgement needed */
                         /* multicast/broadcast frames, no acknowledgement needed */
                         qc |= 1 << 5;
                         qc |= 1 << 5;
@@ -1763,9 +1810,6 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
                      */
                      */
 
 
                     list = &interfacePriv->genericMulticastOrBroadCastMgtFrames;
                     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) &&
                     if((interfacePriv->interfaceMode != CSR_WIFI_ROUTER_CTRL_MODE_IBSS) &&
                             (list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
                             (list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
                         setBcTim=TRUE;
                         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 */
                         /* if multicast traffic is going on, buffet the unicast packets */
                         unifi_trace(priv, UDBG2, "Enqueued to staRecord->dataPdu[%d] queuePacketDozing=%d,\
                         unifi_trace(priv, UDBG2, "Enqueued to staRecord->dataPdu[%d] queuePacketDozing=%d,\
                                 Buffering enabled = %d \n", priority_q,queuePacketDozing,isRouterBufferEnabled(priv,priority_q));
                                 Buffering enabled = %d \n", priority_q,queuePacketDozing,isRouterBufferEnabled(priv,priority_q));
-                        signal.u.MaPacketRequest.TransmissionControl &= ~(CSR_NO_CONFIRM_REQUIRED);
                         list = &staRecord->dataPdu[priority_q];
                         list = &staRecord->dataPdu[priority_q];
                     } else {
                     } else {
                         unifi_trace(priv, UDBG5, "staRecord->dataPdu[%d] list is empty uf_process_ma_packet_req \n", priority_q);
                         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 */
                         /* Pdu allowed to send to unifi */
                         result = ul_send_signal_unpacked(priv, &signal, bulkdata);
                         result = ul_send_signal_unpacked(priv, &signal, bulkdata);
                         if(result == -ENOSPC) {
                         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
                      * will be sent when we receive VIF AVAILABILITY from firmware as part of DTIM
                      */
                      */
                     list = &interfacePriv->genericMulticastOrBroadCastFrames;
                     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)) {
                     if(list_empty(&interfacePriv->genericMulticastOrBroadCastFrames)) {
                         setBcTim = TRUE;
                         setBcTim = TRUE;
                     }
                     }
@@ -1838,10 +1877,30 @@ CsrResult uf_process_ma_packet_req(unifi_priv_t *priv,
             staRecord->noOfPktQueued++;
             staRecord->noOfPktQueued++;
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
             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");
         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 ==
     } else if(staRecord && staRecord->currentPeerState ==
                             CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) {
                             CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE) {
         if(staRecord->timSet == CSR_WIFI_TIM_RESET || staRecord->timSet == CSR_WIFI_TIM_RESETTING) {
         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[3]) ||
                    !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])) {
                    !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION])) {
                     unifi_trace(priv, UDBG3, "tim set due to unicast pkt & peer in powersave\n");
                     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 */
                 /* Check if all AC's are Delivery Enabled */
                 is_all_ac_deliver_enabled_and_moredata(staRecord, &allDeliveryEnabled, &dataAvailable);
                 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)) {
     if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_VO)) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastMgtFrames))) {
             buffered_pkt->transmissionControl |= (TRANSMISSION_CONTROL_TRIGGER_MASK);
             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);
             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)) {
     if(!isRouterBufferEnabled(priv,UNIFI_TRAFFIC_Q_CONTENTION)) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastFrames))) {
         while((interfacePriv->dtimActive)&& (buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMulticastOrBroadCastFrames))) {
             buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK;
             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) {
             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) {
             if(interfacePriv->multicastPduHostTag == 0xffffffff) {
                 unifi_notice(priv,"ma_vif_availibility_ind recevied for multicast but queues are empty%d\n",interfaceTag);
                 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 */
                 /* 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;
             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
 #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;
     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,
 void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv,
                                             CsrWifiRouterCtrlStaInfo_t * staInfo,
                                             CsrWifiRouterCtrlStaInfo_t * staInfo,
                                             CsrUint8 queue,
                                             CsrUint8 queue,
@@ -2170,117 +2267,94 @@ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv,
     CsrBool eosp=FALSE;
     CsrBool eosp=FALSE;
     CsrInt8 r =0;
     CsrInt8 r =0;
     CsrBool moreData = FALSE;
     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;
         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);
             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);
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
             /* re-queueing the packet as DTIM started */
             /* re-queueing the packet as DTIM started */
             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
             list_add(&buffered_pkt->q,txList);
             list_add(&buffered_pkt->q,txList);
             spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
             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;
             break;
         }
         }
 
 
         buffered_pkt->transmissionControl &=
         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;
              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);
         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) {
         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 {
         } else {
             if(r){
             if(r){
                 /* the PDU failed where we can't do any thing so free the storage */
                 /* the PDU failed where we can't do any thing so free the storage */
                 unifi_net_data_free(priv, &buffered_pkt->bulkdata);
                 unifi_net_data_free(priv, &buffered_pkt->bulkdata);
             }
             }
-
             kfree(buffered_pkt);
             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);
                 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,
 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=dequeue_tx_data_pdu(priv, txList))!=NULL)){
 
 
         buffered_pkt->transmissionControl &=
         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);
         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) ||
             moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) ||
              !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames));
              !list_empty(&interfacePriv->genericMulticastOrBroadCastFrames));
             if(!moreData) {
             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 {
         } else {
             moreData = (!list_empty(&interfacePriv->genericMulticastOrBroadCastMgtFrames) ||
             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);
                     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)) {
             if(isRouterBufferEnabled(priv,queue)) {
                 unifi_notice(priv,"uf_send_buffered_frames : No space Left for queue = %d\n",queue);
                 unifi_notice(priv,"uf_send_buffered_frames : No space Left for queue = %d\n",queue);
                 break;
                 break;
             }
             }
         }
         }
-
-
         /*push generic management frames out*/
         /*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);
         staInfo =  CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag);
         if(!staInfo) {
         if(!staInfo) {
             startIndex ++;
             startIndex ++;
-            if(startIndex >= UNIFI_MAX_CONNECTIONS){
+            if(startIndex >= UNIFI_MAX_CONNECTIONS) {
                 startIndex = 0;
                 startIndex = 0;
             }
             }
             continue;
             continue;
         } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
         } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
-                   &&(staInfo->uapsdActive == FALSE)){
+                   &&(staInfo->uapsdActive == FALSE)) {
             startIndex ++;
             startIndex ++;
-            if(startIndex >= UNIFI_MAX_CONNECTIONS){
+            if(startIndex >= UNIFI_MAX_CONNECTIONS) {
                 startIndex = 0;
                 startIndex = 0;
             }
             }
             continue;
             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)
         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 ++;
         startIndex ++;
-        if(startIndex >= UNIFI_MAX_CONNECTIONS){
+        if(startIndex >= UNIFI_MAX_CONNECTIONS) {
            startIndex = 0;
            startIndex = 0;
         }
         }
     }
     }
@@ -2474,47 +2536,14 @@ void uf_send_buffered_frames(unifi_priv_t *priv,unifi_TrafficQueue q)
         priv->pausedStaHandle[queue] = 0;
         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();
     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)
 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;
     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;
     CsrInt8 i;
-    unifi_TrafficQueue priority_q;
+    CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     unsigned long lock_flags;
     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);
             spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-            srcStaInfo->uapsdActive = TRUE;
+            staInfo->uapsdActive = FALSE;
             spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
             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)
 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;
     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;
     struct sk_buff *skb, *newSkb = NULL;
     CsrWifiMacAddress peerAddress;
     CsrWifiMacAddress peerAddress;
     netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
     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;
     int r;
     CSR_SIGNAL signal;
     CSR_SIGNAL signal;
     CsrUint32 priority_q;
     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]));
                         !list_empty(&srcStaInfo->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]));
             if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) {
             if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) {
                 unifi_trace(priv, UDBG3, "This condition should not occur\n");
                 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 {
         } else {
             CsrUint8 allDeliveryEnabled = 0, dataAvailable = 0;
             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));
             moreData = (uf_is_more_data_for_non_delivery_ac(srcStaInfo) || (allDeliveryEnabled && dataAvailable));
 
 
             if(moreData && (srcStaInfo->timSet == CSR_WIFI_TIM_RESET)) {
             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->dataPdu[UNIFI_TRAFFIC_Q_VO]) ||
                         !list_empty(&staRecord->mgtFrames));
                         !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) {
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                 /* Clear the trigger bit transmission control*/
                 /* 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 */
                 /* Enqueue at the head of the queue */
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 list_add(&buffered_pkt->q, &staRecord->mgtFrames);
                 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]) ||
             moreData = (!list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]) ||
                         !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]));
                         !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) {
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                 /* Clear the trigger bit transmission control*/
                 /* 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 */
                 /* Enqueue at the head of the queue */
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_VO]);
                 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;
             buffered_pkt->transmissionControl |= TRANSMISSION_CONTROL_TRIGGER_MASK;
             moreData = !list_empty(&staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]);
             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) {
             if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                 /* Clear the trigger bit transmission control*/
                 /* 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 */
                 /* Enqueue at the head of the queue */
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                 list_add(&buffered_pkt->q, &staRecord->dataPdu[UNIFI_TRAFFIC_Q_CONTENTION]);
                 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));
             !list_empty(&staRecord->mgtFrames));
         if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) {
         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");
             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 {
     } 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*/
         /*Send Data From Management Frames*/
         /* Priority orders for delivering the buffered packets are
         /* 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 */
         /* 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;
             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
                     /* We dont have packets in non delivery enabled UNIFI_TRAFFIC_Q_VO, So we are looking in management
                      * queue of the station record
                      * queue of the station record
                      */
                      */
                     moreData = uf_is_more_data_for_non_delivery_ac(staRecord);
                     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 */
                     /* 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) {
                     if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                         /* Clear the trigger bit transmission control*/
                         /* 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 */
                         /* Enqueue at the head of the queue */
                         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                         list_add(&buffered_pkt->q, &staRecord->mgtFrames);
                         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);
                         kfree(buffered_pkt);
                     }
                     }
+                } else {
+                    unifi_error(priv, "uf_process_ps_poll: Mgt frame list empty!! \n");
                 }
                 }
+
         } else {
         } else {
             CsrInt8 i;
             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])) {
                 if (!IS_DELIVERY_ENABLED(staRecord->powersaveMode[i])) {
                     /* Send One packet, if queue is NULL then continue */
                     /* Send One packet, if queue is NULL then continue */
                     if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) {
                     if((buffered_pkt=dequeue_tx_data_pdu(priv, &staRecord->dataPdu[i]))) {
                         moreData = uf_is_more_data_for_non_delivery_ac(staRecord);
                         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 */
                         /* 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) {
                         if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staRecord,moreData,FALSE)) == -ENOSPC) {
                             /* Clear the trigger bit transmission control*/
                             /* 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 */
                             /* Enqueue at the head of the queue */
                             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                             list_add(&buffered_pkt->q, &staRecord->dataPdu[i]);
                             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));
         moreData = (uf_is_more_data_for_non_delivery_ac(staRecord) || (allDeliveryEnabled && dataAvailable));
         if(!moreData && (staRecord->timSet == CSR_WIFI_TIM_SET)) {
         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");
             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);
     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)
 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 */
     /* 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) &&
    while(!isRouterBufferEnabled(priv,3) &&
                             ((buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMgtFrames))!=NULL)) {
                             ((buffered_pkt=dequeue_tx_data_pdu(priv,&interfacePriv->genericMgtFrames))!=NULL)) {
         buffered_pkt->transmissionControl &=
         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) {
         if((r=frame_and_send_queued_pdu(priv,buffered_pkt,NULL,0,FALSE)) == -ENOSPC) {
             /* Enqueue at the head of the queue */
             /* Enqueue at the head of the queue */
             spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
             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)) {
         if (staInfo && (staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_ACTIVE)) {
           while((( TRUE == hipslotFree[3] ) && (buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->mgtFrames)))) {
           while((( TRUE == hipslotFree[3] ) && (buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->mgtFrames)))) {
               buffered_pkt->transmissionControl &=
               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) {
               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");
                   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 */
                   /* 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]))) {
               while((buffered_pkt=dequeue_tx_data_pdu(priv, &staInfo->dataPdu[j]))) {
                  buffered_pkt->transmissionControl &=
                  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) {
                  if((r=frame_and_send_queued_pdu(priv,buffered_pkt,staInfo,0,FALSE)) == -ENOSPC) {
                      /* Enqueue at the head of the queue */
                      /* Enqueue at the head of the queue */
                      spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
                      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);
         spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
         list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) {
         list_for_each_safe(listHead, placeHolder, &interfacePriv->genericMulticastOrBroadCastFrames) {
             tx_q_item = list_entry(listHead, tx_buffered_packets_t, q);
             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));
             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);
             unifi_trace(priv, UDBG1,"updating eosp for list Head hostTag:= 0x%x ",tx_q_item->hostTag);
             break;
             break;
@@ -3624,105 +3701,51 @@ void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 int
     }
     }
     func_exit();
     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)
 void resume_suspended_uapsd(unifi_priv_t* priv,CsrUint16 interfaceTag)
 {
 {
 
 
    CsrUint8 startIndex;
    CsrUint8 startIndex;
    CsrWifiRouterCtrlStaInfo_t * staInfo = NULL;
    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++) {
     for(startIndex= 0; startIndex < UNIFI_MAX_CONNECTIONS;startIndex++) {
         staInfo =  CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag);
         staInfo =  CsrWifiRouterCtrlGetStationRecordFromHandle(priv,startIndex,interfaceTag);
-        if(!staInfo ) {
+
+        if(!staInfo || !staInfo->wmmOrQosEnabled) {
             continue;
             continue;
         } else if((staInfo->currentPeerState == CSR_WIFI_ROUTER_CTRL_PEER_CONNECTED_POWER_SAVE)
         } 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
 #endif

+ 69 - 27
drivers/staging/csr/unifi_priv.h

@@ -44,6 +44,10 @@
 
 
 #include <linux/fs.h>
 #include <linux/fs.h>
 
 
+#ifdef ANDROID_BUILD
+#include <linux/wakelock.h>
+#endif
+
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifi_udi.h"
 #include "csr_wifi_hip_unifi_udi.h"
 #include "csr_wifi_router_lib.h"
 #include "csr_wifi_router_lib.h"
@@ -63,6 +67,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #include "unifi_wext.h"
 #include "unifi_wext.h"
 #endif
 #endif
 
 
+#ifdef ANDROID_BUILD
+extern struct wake_lock unifi_sdio_wake_lock;
+#endif
+
 #include "unifi_clients.h"
 #include "unifi_clients.h"
 
 
 
 
@@ -98,18 +106,14 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #include "unifi_sme.h"
 #include "unifi_sme.h"
 #endif
 #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 */
 /* The device major number to use when registering the udi driver */
 #define UNIFI_NAME      "unifi"
 #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
 #define MAX_UNIFI_DEVS  2
 
 
 /* 802.11 Mac header offsets */
 /* 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_TID_MASK 0x0f
 #define IEEE802_11_QC_A_MSDU_PRESENT 0x80
 #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 CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000
 #define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36
 #define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36
 #define MAX_ACCESS_CATOGORY 4
 #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_DETECTION_TIMER_INTERVAL              30               /* in seconds */
 #define     STA_INACTIVE_TIMEOUT_VAL                           120*1000*1000    /* 120 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 */
 /* Defines used in beacon filtering in case of P2P */
 #define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH        0x7
 #define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH        0x7
@@ -220,6 +231,9 @@ extern int sdio_block_size;
 extern int coredump_max;
 extern int coredump_max;
 extern int run_bh_once;
 extern int run_bh_once;
 extern int bh_priority;
 extern int bh_priority;
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+extern int log_hip_signals;
+#endif
 
 
 struct dlpriv {
 struct dlpriv {
     const unsigned char *dl_data;
     const unsigned char *dl_data;
@@ -331,7 +345,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
     CsrTime lastActivity;
     CsrTime lastActivity;
 
 
     /* during m/c transmission sp suspended */
     /* during m/c transmission sp suspended */
-    CsrBool uapsdSuspended;
+    CsrBool uspSuspend;
+    CSR_PRIORITY triggerFramePriority;
 #endif
 #endif
     CsrWifiRouterCtrlPeerStatus currentPeerState;
     CsrWifiRouterCtrlPeerStatus currentPeerState;
     struct list_head dataPdu[MAX_ACCESS_CATOGORY];
     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_RESETTING   2
 #define CSR_WIFI_TIM_SETTING     3
 #define CSR_WIFI_TIM_SETTING     3
 
 
+    CsrBool timRequestPendingFlag;
+    CsrUint8 updateTimReqQueued;
     CsrUint16 noOfPktQueued;
     CsrUint16 noOfPktQueued;
 }CsrWifiRouterCtrlStaInfo_t;
 }CsrWifiRouterCtrlStaInfo_t;
 
 
@@ -609,8 +626,14 @@ struct unifi_priv {
 
 
     /* Spinlock to protect M4 data */
     /* Spinlock to protect M4 data */
     spinlock_t m4_lock;
     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
 #ifndef ALLOW_Q_PAUSE
     /* Array to indicate if a particular Tx queue is paused, this may not be
     /* 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
      * required in a multiqueue implementation since we can directly stop kernel
@@ -630,10 +653,24 @@ struct unifi_priv {
     CsrUint32 rxUdpThroughput;
     CsrUint32 rxUdpThroughput;
     CsrUint32 txUdpThroughput;
     CsrUint32 txUdpThroughput;
 
 
-
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+    /*Set if multicast KeyID = 1*/
     CsrUint8 wapi_multicast_filter;
     CsrUint8 wapi_multicast_filter;
+    /*Set if unicast KeyID = 1*/
     CsrUint8 wapi_unicast_filter;
     CsrUint8 wapi_unicast_filter;
     CsrUint8 wapi_unicast_queued_pkt_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 {
 typedef struct {
@@ -682,6 +719,9 @@ typedef struct netInterface_priv
     CsrUint8 ba_complete_index;
     CsrUint8 ba_complete_index;
     CsrUint8 queueEnabled[UNIFI_NO_OF_TX_QS];
     CsrUint8 queueEnabled[UNIFI_NO_OF_TX_QS];
     struct work_struct send_m4_ready_task;
     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;
     struct net_device_stats stats;
     CsrUint8 interfaceMode;
     CsrUint8 interfaceMode;
     CsrBool protect;
     CsrBool protect;
@@ -721,7 +761,6 @@ typedef struct netInterface_priv
     struct list_head genericMgtFrames;
     struct list_head genericMgtFrames;
     struct list_head genericMulticastOrBroadCastFrames;
     struct list_head genericMulticastOrBroadCastFrames;
     struct list_head genericMulticastOrBroadCastMgtFrames;
     struct list_head genericMulticastOrBroadCastMgtFrames;
-    struct list_head directedMaPktReq;
 
 
     /* Timer for detecting station inactivity */
     /* Timer for detecting station inactivity */
     struct timer_list sta_activity_check_timer;
     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 */
     /* Buffered M4 signal to take care of WPA race condition */
     CSR_SIGNAL m4_signal;
     CSR_SIGNAL m4_signal;
     bulk_data_desc_t m4_bulk_data;
     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*/
     /* This should be removed and m4_hostTag should be used for checking*/
     CsrBool m4_sent;
     CsrBool m4_sent;
     CSR_CLIENT_TAG m4_hostTag;
     CSR_CLIENT_TAG m4_hostTag;
@@ -747,17 +793,11 @@ typedef struct netInterface_priv
     CsrBool intraBssEnabled;
     CsrBool intraBssEnabled;
     CsrUint32 multicastPduHostTag; /* Used to set the tim after getting
     CsrUint32 multicastPduHostTag; /* Used to set the tim after getting
        a confirm for it */
        a confirm for it */
+    CsrBool bcTimSet;
+    CsrBool bcTimSetReqPendingFlag;
+    CsrBool bcTimSetReqQueued;
 } netInterface_priv_t;
 } 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
 #ifndef ALLOW_Q_PAUSE
 #define net_is_tx_q_paused(priv, q)   (priv->tx_q_paused_flag[q])
 #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)
 #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,
                    bulk_data_param_t *bulkdata,
                    CsrUint8 macHeaderLengthInBytes);
                    CsrUint8 macHeaderLengthInBytes);
 CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord);
 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,
 void uf_process_wmm_deliver_ac_uapsd (  unifi_priv_t * priv,
                                         CsrWifiRouterCtrlStaInfo_t * srcStaInfo,
                                         CsrWifiRouterCtrlStaInfo_t * srcStaInfo,
                                         CsrUint16 qosControl,
                                         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_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_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_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,
                                  netInterface_priv_t *interfacePriv,
                                  struct list_head *buffered_frames_list);
                                  struct list_head *buffered_frames_list);
 void uf_flush_list(unifi_priv_t * priv, struct list_head * 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);
 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 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);
 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,
                                  CsrWifiMacAddress source_address,
                                  int indicate, CsrUint16 interfaceTag);
                                  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
  *      inet.c
  */
  */

+ 80 - 0
drivers/staging/csr/unifi_sme.c

@@ -447,6 +447,7 @@ int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
 {
 {
     unifi_cfg_power_t cfg_power;
     unifi_cfg_power_t cfg_power;
     int rc;
     int rc;
+    int wol;
 
 
     if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) {
     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");
         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) {
     switch (cfg_power) {
         case UNIFI_CFG_POWER_OFF:
         case UNIFI_CFG_POWER_OFF:
+            priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
             rc = sme_sys_suspend(priv);
             rc = sme_sys_suspend(priv);
             if (rc) {
             if (rc) {
                 return rc;
                 return rc;
             }
             }
             break;
             break;
         case UNIFI_CFG_POWER_ON:
         case UNIFI_CFG_POWER_ON:
+            wol = priv->wol_suspend;
             rc = sme_sys_resume(priv);
             rc = sme_sys_resume(priv);
             if (rc) {
             if (rc) {
                 return 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;
             break;
         default:
         default:
             unifi_error(priv, "WIFI POWER: Unknown value.\n");
             unifi_error(priv, "WIFI POWER: Unknown value.\n");
@@ -921,10 +930,19 @@ int
         supportedRates[i++]=0x8b;
         supportedRates[i++]=0x8b;
         supportedRates[i++]=0x96;
         supportedRates[i++]=0x96;
     } else if(n) {
     } else if(n) {
+        /* For some strange reasons WiFi stack needs both b and g rates*/
         supportedRates[i++]=0x02;
         supportedRates[i++]=0x02;
         supportedRates[i++]=0x04;
         supportedRates[i++]=0x04;
         supportedRates[i++]=0x0b;
         supportedRates[i++]=0x0b;
         supportedRates[i++]=0x16;
         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(g) {
         if(!b) {
         if(!b) {
@@ -1162,3 +1180,65 @@ uf_send_m4_ready_wq(struct work_struct *work)
 
 
 } /* uf_send_m4_ready_wq() */
 } /* 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

+ 9 - 0
drivers/staging/csr/unifi_sme.h

@@ -50,6 +50,7 @@ enum sme_request_status {
     SME_REQUEST_PENDING,
     SME_REQUEST_PENDING,
     SME_REQUEST_RECEIVED,
     SME_REQUEST_RECEIVED,
     SME_REQUEST_TIMEDOUT,
     SME_REQUEST_TIMEDOUT,
+    SME_REQUEST_CANCELLED,
 };
 };
 
 
 /* Structure to hold a UDI logged signal */
 /* Structure to hold a UDI logged signal */
@@ -123,6 +124,7 @@ void uf_ta_wq(struct work_struct *work);
 #endif
 #endif
 
 
 void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func);
 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);
 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_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig);
 int sme_mgt_power_config_get(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);
 int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig);

+ 13 - 14
drivers/staging/csr/unifiio.h

@@ -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 {
 struct unifi_putest_cmd52 {