Browse Source

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 years ago
parent
commit
95edd09ec3
56 changed files with 3475 additions and 1241 deletions
  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. 421 339
      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);
 }
 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 <sys/types.h>
 #include <stdarg.h>
+#include <string.h>
 #endif
 
 #ifdef __cplusplus

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

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

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

@@ -35,26 +35,53 @@ void CsrUInt16ToHex(CsrUint16 number, CsrCharString *str);
 void CsrUInt32ToHex(CsrUint32 number, CsrCharString *str);
 
 /*------------------------------------------------------------------*/
-/*  String */
+/* Standard C Library functions */
 /*------------------------------------------------------------------*/
+#ifdef CSR_USE_STDC_LIB
+#define CsrMemCpy memcpy
+#define CsrMemMove memmove
+#define CsrStrCpy strcpy
+#define CsrStrNCpy strncpy
+#define CsrStrCat strcat
+#define CsrStrNCat strncat
+#define CsrMemCmp(s1, s2, n) ((CsrInt32) memcmp((s1), (s2), (n)))
+#define CsrStrCmp(s1, s2) ((CsrInt32) strcmp((s1), (s2)))
+#define CsrStrNCmp(s1, s2, n) ((CsrInt32) strncmp((s1), (s2), (n)))
+/*#define CsrMemChr memchr*/
+#define CsrStrChr strchr
+/*#define CsrStrCSpn strcspn*/
+/*#define CsrStrPBrk strpbrk*/
+/*#define CsrStrRChr strrchr*/
+/*#define CsrStrSpn strspn*/
+#define CsrStrStr strstr
+/*#define CsrStrTok strtok*/
+#define CsrMemSet memset
+#define CsrStrLen strlen
+/*#define CsrVsnprintf(s, n, format, arg) ((CsrInt32) vsnprintf((s), (n), (format), (arg)))*/
+#else /* !CSR_USE_STDC_LIB */
 void *CsrMemCpy(void *dest, const void *src, CsrSize count);
-void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count);
 void *CsrMemMove(void *dest, const void *src, CsrSize count);
-CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count);
-void *CsrMemDup(const void *buf1, CsrSize count);
 CsrCharString *CsrStrCpy(CsrCharString *dest, const CsrCharString *src);
 CsrCharString *CsrStrNCpy(CsrCharString *dest, const CsrCharString *src, CsrSize count);
-int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
 CsrCharString *CsrStrCat(CsrCharString *dest, const CsrCharString *src);
 CsrCharString *CsrStrNCat(CsrCharString *dest, const CsrCharString *src, CsrSize count);
-CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2);
-CsrSize CsrStrLen(const CsrCharString *string);
+CsrInt32 CsrMemCmp(const void *buf1, const void *buf2, CsrSize count);
 CsrInt32 CsrStrCmp(const CsrCharString *string1, const CsrCharString *string2);
 CsrInt32 CsrStrNCmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
-CsrCharString *CsrStrDup(const CsrCharString *string);
 CsrCharString *CsrStrChr(const CsrCharString *string, CsrCharString c);
-CsrUint32 CsrStrToInt(const CsrCharString *string);
+CsrCharString *CsrStrStr(const CsrCharString *string1, const CsrCharString *string2);
+void *CsrMemSet(void *dest, CsrUint8 c, CsrSize count);
+CsrSize CsrStrLen(const CsrCharString *string);
+#endif /* !CSR_USE_STDC_LIB */
 CsrInt32 CsrVsnprintf(CsrCharString *string, CsrSize count, const CsrCharString *format, va_list args);
+
+/*------------------------------------------------------------------*/
+/* Non-standard utility functions */
+/*------------------------------------------------------------------*/
+void *CsrMemDup(const void *buf1, CsrSize count);
+int CsrStrNICmp(const CsrCharString *string1, const CsrCharString *string2, CsrSize count);
+CsrCharString *CsrStrDup(const CsrCharString *string);
+CsrUint32 CsrStrToInt(const CsrCharString *string);
 CsrCharString *CsrStrNCpyZero(CsrCharString *dest, const CsrCharString *src, CsrSize count);
 
 /*------------------------------------------------------------------*/

+ 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_P2P_NOA_CONFIG_CONFLICT   ((CsrResult) 0x000C)
 
-#define CSR_WIFI_VERSION	"5.0.3.0"
+#define CSR_WIFI_VERSION	"5.1.0.0"
 
 #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
 
             Refer to LICENSE.txt included with this source for details
@@ -81,6 +81,15 @@ CsrResult CardWriteBulkData(card_t *card, card_signal_t *csptr, unifi_TrafficQue
  */
 void CardClearFromHostDataSlot(card_t *card, const CsrInt16 aSlotNum);
 
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+/*****************************************************************************
+ * CardClearFromHostDataSlotWithoutFreeingBulkData - Clear the data stot
+ * without freeing the bulk data
+ */
+
+void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const CsrInt16 aSlotNum);
+#endif
+
 /*****************************************************************************
  * CardGetFreeFromHostDataSlots -
  */

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -323,7 +323,7 @@ CsrResult unifi_init(card_t *card)
      * have requested a mini-coredump which needs to be captured now the
      * SDIO interface is alive.
      */
-    unifi_coredump_handle_request(card);
+    (void)unifi_coredump_handle_request(card);
 
     /*
      * Probe to see if the UniFi has ROM/flash to boot from. CSR6xxx should do.
@@ -1616,14 +1616,14 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_ptr = 0;
-    CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
-                "fh_cmd_q");
+    (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
+                      "fh_cmd_q");
     for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
     {
         card->fh_traffic_queue[i].q_rd_ptr = 0;
         card->fh_traffic_queue[i].q_wr_ptr = 0;
-        CsrSnprintf(card->fh_traffic_queue[i].name,
-                    UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
+        (void)CsrSnprintf(card->fh_traffic_queue[i].name,
+                          UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
     }
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
@@ -1634,7 +1634,7 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     /*
      * Allocate memory for the from-host and to-host signal buffers.
      */
-    card->fh_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE);
+    card->fh_buffer.buf = CsrMemAllocDma(UNIFI_FH_BUF_SIZE);
     if (card->fh_buffer.buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for F-H signals\n");
@@ -1645,7 +1645,7 @@ static CsrResult card_allocate_memory_resources(card_t *card)
     card->fh_buffer.ptr = card->fh_buffer.buf;
     card->fh_buffer.count = 0;
 
-    card->th_buffer.buf = CsrMemAlloc(UNIFI_FH_BUF_SIZE);
+    card->th_buffer.buf = CsrMemAllocDma(UNIFI_FH_BUF_SIZE);
     if (card->th_buffer.buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate memory for T-H signals\n");
@@ -1693,6 +1693,12 @@ static CsrResult card_allocate_memory_resources(card_t *card)
         return CSR_WIFI_HIP_RESULT_NO_MEMORY;
     }
 
+    /* Initialise host tag entries for from-host bulk data slots */
+    for (i = 0; i < n; i++)
+    {
+        card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
+    }
+
 
     /* Allocate memory for the array of pointers */
     n = cfg_data->num_tohost_data_slots;
@@ -1811,7 +1817,7 @@ static void card_free_memory_resources(card_t *card)
 
     if (card->fh_buffer.buf)
     {
-        CsrMemFree(card->fh_buffer.buf);
+        CsrMemFreeDma(card->fh_buffer.buf);
     }
     card->fh_buffer.ptr = card->fh_buffer.buf = NULL;
     card->fh_buffer.bufsize = 0;
@@ -1819,7 +1825,7 @@ static void card_free_memory_resources(card_t *card)
 
     if (card->th_buffer.buf)
     {
-        CsrMemFree(card->th_buffer.buf);
+        CsrMemFreeDma(card->th_buffer.buf);
     }
     card->th_buffer.ptr = card->th_buffer.buf = NULL;
     card->th_buffer.bufsize = 0;
@@ -1842,14 +1848,14 @@ static void card_init_soft_queues(card_t *card)
     /* Reset any state carried forward from a previous life */
     card->fh_command_queue.q_rd_ptr = 0;
     card->fh_command_queue.q_wr_ptr = 0;
-    CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
-                "fh_cmd_q");
+    (void)CsrSnprintf(card->fh_command_queue.name, UNIFI_QUEUE_NAME_MAX_LENGTH,
+                      "fh_cmd_q");
     for (i = 0; i < UNIFI_NO_OF_TX_QS; i++)
     {
         card->fh_traffic_queue[i].q_rd_ptr = 0;
         card->fh_traffic_queue[i].q_wr_ptr = 0;
-        CsrSnprintf(card->fh_traffic_queue[i].name,
-                    UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
+        (void)CsrSnprintf(card->fh_traffic_queue[i].name,
+                          UNIFI_QUEUE_NAME_MAX_LENGTH, "fh_data_q%d", i);
     }
 #ifndef CSR_WIFI_HIP_TA_DISABLE
     unifi_ta_sampling_init(card);
@@ -2399,6 +2405,57 @@ void CardClearFromHostDataSlot(card_t *card, const CsrInt16 slot)
 } /* CardClearFromHostDataSlot() */
 
 
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+/*
+ * ---------------------------------------------------------------------------
+ *  CardClearFromHostDataSlotWithoutFreeingBulkData
+ *
+ *      Clear the given data slot with out freeing the bulk data.
+ *
+ *  Arguments:
+ *      card            Pointer to Card object
+ *      slot            Index of the signal slot to clear.
+ *
+ *  Returns:
+ *      None.
+ * ---------------------------------------------------------------------------
+ */
+void CardClearFromHostDataSlotWithoutFreeingBulkData(card_t *card, const CsrInt16 slot)
+{
+    CsrUint8 queue = card->from_host_data[slot].queue;
+
+    /* Initialise the from_host data slot so it can be re-used,
+     * Set length field in from_host_data array to 0.
+     */
+    UNIFI_INIT_BULK_DATA(&card->from_host_data[slot].bd);
+
+    queue = card->from_host_data[slot].queue;
+
+    if (queue < UNIFI_NO_OF_TX_QS)
+    {
+        if (card->dynamic_slot_data.from_host_used_slots[queue] == 0)
+        {
+            unifi_error(card->ospriv, "Goofed up used slots q = %d used slots = %d\n",
+                        queue,
+                        card->dynamic_slot_data.from_host_used_slots[queue]);
+        }
+        else
+        {
+            card->dynamic_slot_data.from_host_used_slots[queue]--;
+        }
+        card->dynamic_slot_data.packets_txed[queue]++;
+        card->dynamic_slot_data.total_packets_txed++;
+        if (card->dynamic_slot_data.total_packets_txed >=
+            card->dynamic_slot_data.packets_interval)
+        {
+            CardReassignDynamicReservation(card);
+        }
+    }
+} /* CardClearFromHostDataSlotWithoutFreeingBulkData() */
+
+
+#endif
+
 CsrUint16 CardGetDataSlotSize(card_t *card)
 {
     return card->config_data.data_slot_size;

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -148,9 +148,9 @@ void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length)
     CsrCharString s[5];
     CsrUint16 i;
 
-    for (i = 0; i < length; i++)
+    for (i = 0; i < length; i = i + 2)
     {
-        CsrUInt16ToHex(0xff & buff[i], s);
+        CsrUInt16ToHex(*((CsrUint16 *)(buff + i)), s);
         unifi_debug_string_to_buf(s);
     }
 }
@@ -277,7 +277,7 @@ void unifi_sdio_interrupt_handler(card_t *card)
      * Then ask the OS layer to run the unifi_bh to give attention to the UniFi.
      */
     card->bh_reason_unifi = 1;
-    unifi_run_bh(card->ospriv);
+    (void)unifi_run_bh(card->ospriv);
 } /*  sdio_interrupt_handler() */
 
 
@@ -309,7 +309,7 @@ CsrResult unifi_configure_low_power_mode(card_t                       *card,
                 (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled",
                 (periodic_wake_mode == UNIFI_PERIODIC_WAKE_HOST_DISABLED)?"FALSE" : "TRUE");
 
-    unifi_run_bh(card->ospriv);
+    (void)unifi_run_bh(card->ospriv);
     return CSR_RESULT_SUCCESS;
 } /* unifi_configure_low_power_mode() */
 
@@ -614,10 +614,10 @@ exit:
                     (low_power_mode == UNIFI_LOW_POWER_DISABLED)?"disabled" : "enabled");
 
         /* Try to capture firmware panic codes */
-        unifi_capture_panic(card);
+        (void)unifi_capture_panic(card);
 
         /* Ask for a mini-coredump when the driver has reset UniFi */
-        unifi_coredump_request_at_next_reset(card, 1);
+        (void)unifi_coredump_request_at_next_reset(card, 1);
     }
 
     return r;
@@ -932,9 +932,13 @@ static CsrResult handle_host_protocol(card_t *card, CsrBool *processed_something
             return r;
         }
     }
+
+#ifdef CSR_WIFI_RX_PATH_SPLIT
 #ifdef CSR_WIFI_RX_PATH_SPLIT_DONT_USE_WQ
     unifi_rx_queue_flush(card->ospriv);
 #endif
+#endif
+
     /* See if we can re-enable transmission now */
     restart_packet_flow(card);
 
@@ -1324,7 +1328,6 @@ static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed)
                     if (status && (card->fh_slot_host_tag_record))
                     {
                         CsrUint16 num_fh_slots = card->config_data.num_fromhost_data_slots;
-                        CsrUint16 i = 0;
 
                         /* search through the list of slot records and match with host tag
                          * If a slot is not yet cleared then clear the slot from here
@@ -1333,12 +1336,27 @@ static CsrResult process_to_host_signals(card_t *card, CsrInt32 *processed)
                         {
                             if (card->fh_slot_host_tag_record[i] == host_tag)
                             {
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+                                /* Invoke the HAL module function to requeue it back to HAL Queues */
+                                r = unifi_reque_ma_packet_request(card->ospriv, host_tag, status, &card->from_host_data[i].bd);
+                                card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
+                                if (CSR_RESULT_SUCCESS != r)
+                                {
+                                    unifi_trace(card->ospriv, UDBG5, "process_to_host_signals: Failed to requeue Packet(hTag:%x) back to HAL \n", host_tag);
+                                    CardClearFromHostDataSlot(card, i);
+                                }
+                                else
+                                {
+                                    CardClearFromHostDataSlotWithoutFreeingBulkData(card, i);
+                                }
+
+#else
                                 unifi_trace(card->ospriv, UDBG4, "process_to_host_signals Clear slot=%x host tag=%x\n", i, host_tag);
                                 card->fh_slot_host_tag_record[i] = CSR_WIFI_HIP_RESERVED_HOST_TAG;
 
                                 /* Set length field in from_host_data array to 0 */
                                 CardClearFromHostDataSlot(card, i);
-
+#endif
                                 break;
                             }
                         }
@@ -1724,7 +1742,7 @@ static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr,
 
     if (len != 0 && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3))
     {
-        host_bulk_data_slot = CsrMemAlloc(len);
+        host_bulk_data_slot = CsrMemAllocDma(len);
 
         if (!host_bulk_data_slot)
         {
@@ -1783,7 +1801,7 @@ static CsrResult process_bulk_data_command(card_t *card, const CsrUint8 *cmdptr,
         /* moving this check before we clear host data slot */
         if ((len != 0) && (dir == UNIFI_SDIO_WRITE) && (((CsrIntptr)bdslot->os_data_ptr + offset) & 3))
         {
-            CsrMemFree(host_bulk_data_slot);
+            CsrMemFreeDma(host_bulk_data_slot);
         }
 #endif
 

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -1565,7 +1565,7 @@ CsrResult unifi_bulk_rw(card_t *card, CsrUint32 handle, void *pdata,
          */
         if (card->chip_id <= SDIO_CARD_ID_UNIFI_2)
         {
-            unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
+            (void)unifi_set_host_state(card, UNIFI_HOST_STATE_AWAKE);
         }
 
         /* If csr_sdio_block_rw() failed in a non-retryable way, or retries exhausted

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -674,7 +674,7 @@ static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
         return CSR_WIFI_HIP_RESULT_INVALID_VALUE;
     }
 
-    buf = CsrMemAlloc(buf_size);
+    buf = CsrMemAllocDma(buf_size);
     if (buf == NULL)
     {
         unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
@@ -720,7 +720,7 @@ static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
         }
     }
 
-    CsrMemFree(buf);
+    CsrMemFreeDma(buf);
 
     if (r != CSR_RESULT_SUCCESS && r != CSR_WIFI_HIP_RESULT_NO_DEVICE)
     {

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -293,7 +293,7 @@ done:
  *  Notes:
  * ---------------------------------------------------------------------------
  */
-static CsrInt32 get_value_from_coredump(const coredump_buffer       *dump,
+static CsrInt32 get_value_from_coredump(const coredump_buffer       *coreDump,
                                         const unifi_coredump_space_t space,
                                         const CsrUint16              offset_in_space)
 {
@@ -316,7 +316,7 @@ static CsrInt32 get_value_from_coredump(const coredump_buffer       *dump,
             {
                 /* Calculate the offset of data within the zone buffer */
                 offset_in_zone = offset_in_space - def->offset;
-                r = (CsrInt32) * (dump->zone[i] + offset_in_zone);
+                r = (CsrInt32) * (coreDump->zone[i] + offset_in_zone);
 
                 unifi_trace(NULL, UDBG6,
                             "sp %d, offs 0x%04x = 0x%04x (in z%d 0x%04x->0x%04x)\n",

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -69,9 +69,9 @@ enum ta_frame_identity
 #define TA_EAPOL_TYPE_OFFSET        9
 #define TA_EAPOL_TYPE_START         0x01
 
-static const CsrUint8 snap_802_2[3]   = { 0xAA, 0xAA, 0x03 };
-static const CsrUint8 oui_rfc1042[3]  = { 0x00, 0x00, 0x00 };
-static const CsrUint8 oui_8021h[3]    = { 0x00, 0x00, 0xf8 };
+#define snap_802_2                  0xAAAA0300
+#define oui_rfc1042                 0x00000000
+#define oui_8021h                   0x0000f800
 static const CsrUint8 aironet_snap[5] = { 0x00, 0x40, 0x96, 0x00, 0x00 };
 
 
@@ -100,13 +100,17 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
     CsrUint16 proto;
     CsrUint16 source_port, dest_port;
     CsrWifiMacAddress srcAddress;
+    CsrUint32 snap_hdr, oui_hdr;
 
     if (data->data_length < TA_LLC_HEADER_SIZE)
     {
         return TA_FRAME_UNKNOWN;
     }
 
-    if (CsrMemCmp(data->os_data_ptr, snap_802_2, 3))
+    snap_hdr = (((CsrUint32)data->os_data_ptr[0]) << 24) |
+               (((CsrUint32)data->os_data_ptr[1]) << 16) |
+               (((CsrUint32)data->os_data_ptr[2]) << 8);
+    if (snap_hdr != snap_802_2)
     {
         return TA_FRAME_UNKNOWN;
     }
@@ -118,8 +122,10 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
          */
     }
 
-    if (!CsrMemCmp(data->os_data_ptr + 3, oui_rfc1042, 3) ||
-        !CsrMemCmp(data->os_data_ptr + 3, oui_8021h, 3))
+    oui_hdr = (((CsrUint32)data->os_data_ptr[3]) << 24) |
+              (((CsrUint32)data->os_data_ptr[4]) << 16) |
+              (((CsrUint32)data->os_data_ptr[5]) << 8);
+    if ((oui_hdr == oui_rfc1042) || (oui_hdr == oui_8021h))
     {
         proto = (data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET] * 256) +
                 data->os_data_ptr[TA_ETHERNET_TYPE_OFFSET + 1];
@@ -177,7 +183,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
                                 /* The DHCP should have at least a message type (request, ack, nack, etc) */
                                 if (data->data_length > TA_DHCP_MESSAGE_TYPE_OFFSET + 6)
                                 {
-                                    CsrMemCpy(srcAddress.a, saddr, 6);
+                                    UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
 
                                     if (direction == CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX)
                                     {
@@ -189,7 +195,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
                                     }
 
                                     /* DHCPACK is a special indication */
-                                    if (!CsrMemCmp(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr, 6))
+                                    if (UNIFI_MAC_ADDRESS_CMP(data->os_data_ptr + TA_BOOTP_CLIENT_MAC_ADDR_OFFSET, sta_macaddr) == TRUE)
                                     {
                                         if (data->os_data_ptr[TA_DHCP_MESSAGE_TYPE_OFFSET] == TA_DHCP_MESSAGE_TYPE_ACK)
                                         {
@@ -224,7 +230,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
                 if ((TA_PROTO_TYPE_WAI == proto) || (direction != CSR_WIFI_ROUTER_CTRL_PROTOCOL_DIRECTION_TX) ||
                     (data->os_data_ptr[TA_EAPOL_TYPE_OFFSET] == TA_EAPOL_TYPE_START))
                 {
-                    CsrMemCpy(srcAddress.a, saddr, 6);
+                    UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
                     unifi_ta_indicate_protocol(card->ospriv,
                                                CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_EAPOL,
                                                direction, &srcAddress);
@@ -238,7 +244,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
         {
             if (proto == TA_PROTO_TYPE_ARP)
             {
-                CsrMemCpy(srcAddress.a, saddr, 6);
+                UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
                 unifi_ta_indicate_protocol(card->ospriv,
                                            CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_ARP,
                                            direction, &srcAddress);
@@ -253,7 +259,7 @@ static enum ta_frame_identity ta_detect_protocol(card_t *card, CsrWifiRouterCtrl
         /* detect Aironet frames */
         if (!CsrMemCmp(data->os_data_ptr + 3, aironet_snap, 5))
         {
-            CsrMemCpy(srcAddress.a, saddr, 6);
+            UNIFI_MAC_ADDRESS_COPY(srcAddress.a, saddr);
             unifi_ta_indicate_protocol(card->ospriv, CSR_WIFI_ROUTER_CTRL_TRAFFIC_PACKET_TYPE_AIRONET,
                                        direction, &srcAddress);
         }

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -103,6 +103,17 @@ extern "C" {
 #include "csr_formatted_io.h"   /* from the synergy gsp folder */
 #include "csr_wifi_result.h"
 
+/* Utility MACROS. Note that UNIFI_MAC_ADDRESS_CMP returns TRUE on success */
+#define UNIFI_MAC_ADDRESS_COPY(dst, src) \
+    do { (dst)[0] = (src)[0]; (dst)[1] = (src)[1]; \
+         (dst)[2] = (src)[2]; (dst)[3] = (src)[3]; \
+         (dst)[4] = (src)[4]; (dst)[5] = (src)[5]; \
+    } while (0)
+
+#define UNIFI_MAC_ADDRESS_CMP(addr1, addr2) \
+    (((addr1)[0] == (addr2)[0]) && ((addr1)[1] == (addr2)[1]) && \
+     ((addr1)[2] == (addr2)[2]) && ((addr1)[3] == (addr2)[3]) && \
+     ((addr1)[4] == (addr2)[4]) && ((addr1)[5] == (addr2)[5]))
 
 /* Traffic queue ordered according to priority
  * EAPOL/Uncontrolled port Queue should be the last
@@ -635,7 +646,24 @@ void unifi_receive_event(void *ospriv,
                          CsrUint8 *sigdata, CsrUint32 siglen,
                          const bulk_data_param_t *bulkdata);
 
+#ifdef CSR_WIFI_REQUEUE_PACKET_TO_HAL
+/**
+ *
+ * Used to reque the failed ma packet request back to hal queues
+ *
+ * @param ospriv the OS layer context.
+ *
+ * @param host_tag host tag for the packet to requeue.
+ *
+ * @param bulkDataDesc pointer to the bulk data.
+ *
+ * @ingroup upperedge
+ */
+CsrResult unifi_reque_ma_packet_request(void *ospriv, CsrUint32 host_tag,
+                                        CsrUint16 status,
+                                        bulk_data_desc_t *bulkDataDesc);
 
+#endif
 typedef struct
 {
     CsrUint16 free_fh_sig_queue_slots[UNIFI_NO_OF_TX_QS];
@@ -836,6 +864,8 @@ const CsrCharString* lookup_bulkcmd_name(CsrUint16 id);
 /* Function to log HIP's global debug buffer */
 #ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
 void unifi_debug_buf_dump(void);
+void unifi_debug_log_to_buf(const CsrCharString *fmt, ...);
+void unifi_debug_hex_to_buf(const CsrCharString *buff, CsrUint16 length);
 #endif
 
 /* Mini-coredump utility functions */

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -579,8 +579,8 @@ static CsrUint32 write_uint16(void *buf, const CsrUint32 offset, const CsrUint16
 
 static CsrUint32 write_uint32(void *buf, const CsrUint32 offset, const CsrUint32 val)
 {
-    write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff));
-    write_uint16(buf, offset + 2, (CsrUint16)(val >> 16));
+    (void)write_uint16(buf, offset + 0, (CsrUint16)(val & 0xffff));
+    (void)write_uint16(buf, offset + 2, (CsrUint16)(val >> 16));
     return sizeof(CsrUint32);
 }
 
@@ -1055,11 +1055,11 @@ void* xbv_to_patch(card_t *card, fwreadfn_t readfn,
     patch_offs += write_reset_ptdl(patch_buf, patch_offs, fwinfo, fw_id);
 
     /* Now the length is known, update the LIST.length */
-    write_uint32(patch_buf, list_len_offs,
-                 (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE);
+    (void)write_uint32(patch_buf, list_len_offs,
+                       (patch_offs - ptdl_start_offs) + PTCH_LIST_SIZE);
 
     /* Re write XBV headers just to fill in the correct file size */
-    write_xbv_header(patch_buf, 0, (patch_offs - payload_offs));
+    (void)write_xbv_header(patch_buf, 0, (patch_offs - payload_offs));
 
     unifi_trace(card->ospriv, UDBG1, "XBV:PTCH size %u, fw_id %u\n",
                 patch_offs, fw_id);

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -196,7 +196,6 @@ extern const CsrCharString *CsrWifiNmeApDownstreamPrimNames[CSR_WIFI_NME_AP_PRIM
     apCredentials  - Security credential configuration.
     maxConnections - Maximum number of stations/P2P clients allowed
     p2pGoParam     - P2P specific GO parameters.
-                     NOT USED FOR CURRENT RELEASE
     wpsEnabled     - Indicates whether WPS should be enabled or not
 
 *******************************************************************************/

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -248,7 +248,6 @@ typedef struct
     apCredentials  - Security credential configuration.
     maxConnections - Maximum number of stations/P2P clients allowed
     p2pGoParam     - P2P specific GO parameters.
-                     NOT USED FOR CURRENT RELEASE
     wpsEnabled     - Indicates whether WPS should be enabled or not
 
 *******************************************************************************/

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -41,11 +41,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     {
-        CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT;
-        if (index < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) &&
-            csrwifirouter_conv_lut[index].msgType == msgType)
+        CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT;
+        if (idx < (CSR_WIFI_ROUTER_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_PRIM_DOWNSTREAM_COUNT) &&
+            csrwifirouter_conv_lut[idx].msgType == msgType)
         {
-            return &csrwifirouter_conv_lut[index];
+            return &csrwifirouter_conv_lut[idx];
         }
     }
     else

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -50,9 +50,11 @@ static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = {
     { CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ, CsrWifiRouterCtrlCapabilitiesReqSizeof, CsrWifiRouterCtrlCapabilitiesReqSer, CsrWifiRouterCtrlCapabilitiesReqDes, CsrWifiRouterCtrlCapabilitiesReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ, CsrWifiRouterCtrlBlockAckEnableReqSizeof, CsrWifiRouterCtrlBlockAckEnableReqSer, CsrWifiRouterCtrlBlockAckEnableReqDes, CsrWifiRouterCtrlBlockAckEnableReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ, CsrWifiRouterCtrlBlockAckDisableReqSizeof, CsrWifiRouterCtrlBlockAckDisableReqSer, CsrWifiRouterCtrlBlockAckDisableReqDes, CsrWifiRouterCtrlBlockAckDisableReqSerFree },
-    { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, CsrWifiRouterCtrlWapiMulticastReqSizeof, CsrWifiRouterCtrlWapiMulticastReqSer, CsrWifiRouterCtrlWapiMulticastReqDes, CsrWifiRouterCtrlWapiMulticastReqSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, CsrWifiRouterCtrlWapiRxPktReqSizeof, CsrWifiRouterCtrlWapiRxPktReqSer, CsrWifiRouterCtrlWapiRxPktReqDes, CsrWifiRouterCtrlWapiRxPktReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, CsrWifiRouterCtrlWapiMulticastFilterReqSizeof, CsrWifiRouterCtrlWapiMulticastFilterReqSer, CsrWifiRouterCtrlWapiMulticastFilterReqDes, CsrWifiRouterCtrlWapiMulticastFilterReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, CsrWifiRouterCtrlWapiUnicastFilterReqSizeof, CsrWifiRouterCtrlWapiUnicastFilterReqSer, CsrWifiRouterCtrlWapiUnicastFilterReqDes, CsrWifiRouterCtrlWapiUnicastFilterReqSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof, CsrWifiRouterCtrlWapiUnicastTxPktReqSer, CsrWifiRouterCtrlWapiUnicastTxPktReqDes, CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, CsrWifiRouterCtrlWapiFilterReqSizeof, CsrWifiRouterCtrlWapiFilterReqSer, CsrWifiRouterCtrlWapiFilterReqDes, CsrWifiRouterCtrlWapiFilterReqSerFree },
     { CSR_WIFI_ROUTER_CTRL_HIP_IND, CsrWifiRouterCtrlHipIndSizeof, CsrWifiRouterCtrlHipIndSer, CsrWifiRouterCtrlHipIndDes, CsrWifiRouterCtrlHipIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_MULTICAST_ADDRESS_IND, CsrWifiRouterCtrlMulticastAddressIndSizeof, CsrWifiRouterCtrlMulticastAddressIndSer, CsrWifiRouterCtrlMulticastAddressIndDes, CsrWifiRouterCtrlMulticastAddressIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_PORT_CONFIGURE_CFM, CsrWifiRouterCtrlPortConfigureCfmSizeof, CsrWifiRouterCtrlPortConfigureCfmSer, CsrWifiRouterCtrlPortConfigureCfmDes, CsrWifiRouterCtrlPortConfigureCfmSerFree },
@@ -81,7 +83,9 @@ static CsrMsgConvMsgEntry csrwifirouterctrl_conv_lut[] = {
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM, CsrWifiRouterCtrlBlockAckDisableCfmSizeof, CsrWifiRouterCtrlBlockAckDisableCfmSer, CsrWifiRouterCtrlBlockAckDisableCfmDes, CsrWifiRouterCtrlBlockAckDisableCfmSerFree },
     { CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND, CsrWifiRouterCtrlBlockAckErrorIndSizeof, CsrWifiRouterCtrlBlockAckErrorIndSer, CsrWifiRouterCtrlBlockAckErrorIndDes, CsrWifiRouterCtrlBlockAckErrorIndSerFree },
     { CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND, CsrWifiRouterCtrlStaInactiveIndSizeof, CsrWifiRouterCtrlStaInactiveIndSer, CsrWifiRouterCtrlStaInactiveIndDes, CsrWifiRouterCtrlStaInactiveIndSerFree },
-    { CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, CsrWifiRouterCtrlWapiMulticastIndSizeof, CsrWifiRouterCtrlWapiMulticastIndSer, CsrWifiRouterCtrlWapiMulticastIndDes, CsrWifiRouterCtrlWapiMulticastIndSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, CsrWifiRouterCtrlWapiRxMicCheckIndSizeof, CsrWifiRouterCtrlWapiRxMicCheckIndSer, CsrWifiRouterCtrlWapiRxMicCheckIndDes, CsrWifiRouterCtrlWapiRxMicCheckIndSerFree },
+    { CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, CsrWifiRouterCtrlModeSetCfmSizeof, CsrWifiRouterCtrlModeSetCfmSer, CsrWifiRouterCtrlModeSetCfmDes, CsrWifiRouterCtrlModeSetCfmSerFree },
+    { CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer, CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes, CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree },
 
     { 0, NULL, NULL, NULL, NULL },
 };
@@ -90,11 +94,11 @@ CsrMsgConvMsgEntry* CsrWifiRouterCtrlConverterLookup(CsrMsgConvMsgEntry *ce, Csr
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     {
-        CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT;
-        if (index < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) &&
-            csrwifirouterctrl_conv_lut[index].msgType == msgType)
+        CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT;
+        if (idx < (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT) &&
+            csrwifirouterctrl_conv_lut[idx].msgType == msgType)
         {
-            return &csrwifirouterctrl_conv_lut[index];
+            return &csrwifirouterctrl_conv_lut[idx];
         }
     }
     else

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -70,6 +70,13 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *
             p->tclas = NULL;
             break;
         }
+        case CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ:
+        {
+            CsrWifiRouterCtrlWifiOnReq *p = (CsrWifiRouterCtrlWifiOnReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
         case CSR_WIFI_ROUTER_CTRL_WIFI_ON_RES:
         {
             CsrWifiRouterCtrlWifiOnRes *p = (CsrWifiRouterCtrlWifiOnRes *)message;
@@ -77,15 +84,22 @@ void CsrWifiRouterCtrlFreeDownstreamMessageContents(CsrUint16 eventClass, void *
             p->smeVersions.smeBuild = NULL;
             break;
         }
-        case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ:
+        case CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ:
         {
-            CsrWifiRouterCtrlWapiMulticastReq *p = (CsrWifiRouterCtrlWapiMulticastReq *)message;
+            CsrWifiRouterCtrlWapiRxPktReq *p = (CsrWifiRouterCtrlWapiRxPktReq *)message;
             CsrPmemFree(p->signal);
             p->signal = NULL;
             CsrPmemFree(p->data);
             p->data = NULL;
             break;
         }
+        case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ:
+        {
+            CsrWifiRouterCtrlWapiUnicastTxPktReq *p = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
         default:
             break;

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -63,15 +63,22 @@ void CsrWifiRouterCtrlFreeUpstreamMessageContents(CsrUint16 eventClass, void *me
             p->versions.routerBuild = NULL;
             break;
         }
-        case CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND:
+        case CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND:
         {
-            CsrWifiRouterCtrlWapiMulticastInd *p = (CsrWifiRouterCtrlWapiMulticastInd *)message;
+            CsrWifiRouterCtrlWapiRxMicCheckInd *p = (CsrWifiRouterCtrlWapiRxMicCheckInd *)message;
             CsrPmemFree(p->signal);
             p->signal = NULL;
             CsrPmemFree(p->data);
             p->data = NULL;
             break;
         }
+        case CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND:
+        {
+            CsrWifiRouterCtrlWapiUnicastTxEncryptInd *p = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
         default:
             break;

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -658,6 +658,39 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
 #define CsrWifiRouterCtrlModeSetReqSend(src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__) \
     CsrWifiRouterCtrlModeSetReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, clientData__, mode__, bssid__, protection__, intraBssDistEnabled__)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlModeSetCfmSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
+    mode         -
+    status       -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__) \
+    msg__ = (CsrWifiRouterCtrlModeSetCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetCfm)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM, dst__, src__); \
+    msg__->clientData = (clientData__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->mode = (mode__); \
+    msg__->status = (status__);
+
+#define CsrWifiRouterCtrlModeSetCfmSendTo(dst__, src__, clientData__, interfaceTag__, mode__, status__) \
+    { \
+        CsrWifiRouterCtrlModeSetCfm *msg__; \
+        CsrWifiRouterCtrlModeSetCfmCreate(msg__, dst__, src__, clientData__, interfaceTag__, mode__, status__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlModeSetCfmSend(dst__, clientData__, interfaceTag__, mode__, status__) \
+    CsrWifiRouterCtrlModeSetCfmSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, mode__, status__)
+
 /*******************************************************************************
 
   NAME
@@ -1594,6 +1627,35 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
 #define CsrWifiRouterCtrlUnexpectedFrameIndSend(dst__, clientData__, interfaceTag__, peerMacAddress__) \
     CsrWifiRouterCtrlUnexpectedFrameIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, peerMacAddress__)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiFilterReqSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue           - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag    -
+    isWapiConnected -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__) \
+    msg__ = (CsrWifiRouterCtrlWapiFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiFilterReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->isWapiConnected = (isWapiConnected__);
+
+#define CsrWifiRouterCtrlWapiFilterReqSendTo(dst__, src__, interfaceTag__, isWapiConnected__) \
+    { \
+        CsrWifiRouterCtrlWapiFilterReq *msg__; \
+        CsrWifiRouterCtrlWapiFilterReqCreate(msg__, dst__, src__, interfaceTag__, isWapiConnected__); \
+        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlWapiFilterReqSend(src__, interfaceTag__, isWapiConnected__) \
+    CsrWifiRouterCtrlWapiFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, isWapiConnected__)
+
 /*******************************************************************************
 
   NAME
@@ -1602,68 +1664,73 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   DESCRIPTION
 
   PARAMETERS
-    queue  - Message Source Task Queue (Cfm's will be sent to this Queue)
-    status -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \
     msg__ = (CsrWifiRouterCtrlWapiMulticastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastFilterReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->status = (status__);
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \
     { \
         CsrWifiRouterCtrlWapiMulticastFilterReq *msg__; \
-        CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, status__); \
+        CsrWifiRouterCtrlWapiMulticastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, status__) \
-    CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__)
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSend(src__, interfaceTag__, status__) \
+    CsrWifiRouterCtrlWapiMulticastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__)
 
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastReqSend
+    CsrWifiRouterCtrlWapiRxMicCheckIndSend
 
   DESCRIPTION
 
   PARAMETERS
-    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
     signalLength -
     signal       -
     dataLength   -
     data         -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__) \
-    msg__ = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq)); \
-    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ, dst__, src__); \
+#define CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiRxMicCheckInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND, dst__, src__); \
+    msg__->clientData = (clientData__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->signalLength = (signalLength__); \
     msg__->signal = (signal__); \
     msg__->dataLength = (dataLength__); \
     msg__->data = (data__);
 
-#define CsrWifiRouterCtrlWapiMulticastReqSendTo(dst__, src__, signalLength__, signal__, dataLength__, data__) \
+#define CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
     { \
-        CsrWifiRouterCtrlWapiMulticastReq *msg__; \
-        CsrWifiRouterCtrlWapiMulticastReqCreate(msg__, dst__, src__, signalLength__, signal__, dataLength__, data__); \
-        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+        CsrWifiRouterCtrlWapiRxMicCheckInd *msg__; \
+        CsrWifiRouterCtrlWapiRxMicCheckIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiMulticastReqSend(src__, signalLength__, signal__, dataLength__, data__) \
-    CsrWifiRouterCtrlWapiMulticastReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, signalLength__, signal__, dataLength__, data__)
+#define CsrWifiRouterCtrlWapiRxMicCheckIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiRxMicCheckIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__)
 
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastIndSend
+    CsrWifiRouterCtrlWapiRxPktReqSend
 
   DESCRIPTION
 
   PARAMETERS
-    queue        - Destination Task Queue
-    clientData   -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
     interfaceTag -
     signalLength -
     signal       -
@@ -1671,25 +1738,24 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
     data         -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
-    msg__ = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd)); \
-    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND, dst__, src__); \
-    msg__->clientData = (clientData__); \
+#define CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiRxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ, dst__, src__); \
     msg__->interfaceTag = (interfaceTag__); \
     msg__->signalLength = (signalLength__); \
     msg__->signal = (signal__); \
     msg__->dataLength = (dataLength__); \
     msg__->data = (data__);
 
-#define CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+#define CsrWifiRouterCtrlWapiRxPktReqSendTo(dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
     { \
-        CsrWifiRouterCtrlWapiMulticastInd *msg__; \
-        CsrWifiRouterCtrlWapiMulticastIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \
-        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+        CsrWifiRouterCtrlWapiRxPktReq *msg__; \
+        CsrWifiRouterCtrlWapiRxPktReqCreate(msg__, dst__, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__); \
+        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiMulticastIndSend(dst__, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
-    CsrWifiRouterCtrlWapiMulticastIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, signalLength__, signal__, dataLength__, data__)
+#define CsrWifiRouterCtrlWapiRxPktReqSend(src__, interfaceTag__, signalLength__, signal__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiRxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, signalLength__, signal__, dataLength__, data__)
 
 /*******************************************************************************
 
@@ -1699,24 +1765,90 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   DESCRIPTION
 
   PARAMETERS
-    queue  - Message Source Task Queue (Cfm's will be sent to this Queue)
-    status -
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__) \
     msg__ = (CsrWifiRouterCtrlWapiUnicastFilterReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastFilterReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
     msg__->status = (status__);
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, status__) \
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(dst__, src__, interfaceTag__, status__) \
     { \
         CsrWifiRouterCtrlWapiUnicastFilterReq *msg__; \
-        CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, status__); \
+        CsrWifiRouterCtrlWapiUnicastFilterReqCreate(msg__, dst__, src__, interfaceTag__, status__); \
+        CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, interfaceTag__, status__) \
+    CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, status__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue        - Destination Task Queue
+    clientData   -
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND, dst__, src__); \
+    msg__->clientData = (clientData__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
+
+#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, src__, clientData__, interfaceTag__, dataLength__, data__) \
+    { \
+        CsrWifiRouterCtrlWapiUnicastTxEncryptInd *msg__; \
+        CsrWifiRouterCtrlWapiUnicastTxEncryptIndCreate(msg__, dst__, src__, clientData__, interfaceTag__, dataLength__, data__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
+    }
+
+#define CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(dst__, clientData__, interfaceTag__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiUnicastTxEncryptIndSendTo(dst__, CSR_WIFI_ROUTER_IFACEQUEUE, clientData__, interfaceTag__, dataLength__, data__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxPktReqSend
+
+  DESCRIPTION
+
+  PARAMETERS
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+#define CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__) \
+    msg__ = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
+
+#define CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(dst__, src__, interfaceTag__, dataLength__, data__) \
+    { \
+        CsrWifiRouterCtrlWapiUnicastTxPktReq *msg__; \
+        CsrWifiRouterCtrlWapiUnicastTxPktReqCreate(msg__, dst__, src__, interfaceTag__, dataLength__, data__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSend(src__, status__) \
-    CsrWifiRouterCtrlWapiUnicastFilterReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, status__)
+#define CsrWifiRouterCtrlWapiUnicastTxPktReqSend(src__, interfaceTag__, dataLength__, data__) \
+    CsrWifiRouterCtrlWapiUnicastTxPktReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, interfaceTag__, dataLength__, data__)
 
 /*******************************************************************************
 
@@ -1837,22 +1969,26 @@ extern const CsrCharString *CsrWifiRouterCtrlDownstreamPrimNames[CSR_WIFI_ROUTER
   PARAMETERS
     queue      - Message Source Task Queue (Cfm's will be sent to this Queue)
     clientData -
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
 
 *******************************************************************************/
-#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__) \
+#define CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__) \
     msg__ = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq)); \
     CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_ROUTER_CTRL_PRIM, CSR_WIFI_ROUTER_CTRL_WIFI_ON_REQ, dst__, src__); \
-    msg__->clientData = (clientData__);
+    msg__->clientData = (clientData__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
 
-#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__) \
+#define CsrWifiRouterCtrlWifiOnReqSendTo(dst__, src__, clientData__, dataLength__, data__) \
     { \
         CsrWifiRouterCtrlWifiOnReq *msg__; \
-        CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__); \
+        CsrWifiRouterCtrlWifiOnReqCreate(msg__, dst__, src__, clientData__, dataLength__, data__); \
         CsrMsgTransport(dst__, CSR_WIFI_ROUTER_CTRL_PRIM, msg__); \
     }
 
-#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__) \
-    CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__)
+#define CsrWifiRouterCtrlWifiOnReqSend(src__, clientData__, dataLength__, data__) \
+    CsrWifiRouterCtrlWifiOnReqSendTo(CSR_WIFI_ROUTER_IFACEQUEUE, src__, clientData__, dataLength__, data__)
 
 /*******************************************************************************
 

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -616,12 +616,14 @@ typedef struct
 #define CSR_WIFI_ROUTER_CTRL_CAPABILITIES_REQ             ((CsrWifiRouterCtrlPrim) (0x0017 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ENABLE_REQ         ((CsrWifiRouterCtrlPrim) (0x0018 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_REQ        ((CsrWifiRouterCtrlPrim) (0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
-#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_REQ           ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_PKT_REQ              ((CsrWifiRouterCtrlPrim) (0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_FILTER_REQ    ((CsrWifiRouterCtrlPrim) (0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_FILTER_REQ      ((CsrWifiRouterCtrlPrim) (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_PKT_REQ      ((CsrWifiRouterCtrlPrim) (0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_FILTER_REQ              ((CsrWifiRouterCtrlPrim) (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST))
 
 
-#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST           (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)
+#define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST           (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)
 
 /* Upstream */
 #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -654,9 +656,11 @@ typedef struct
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_DISABLE_CFM        ((CsrWifiRouterCtrlPrim)(0x0019 + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_BLOCK_ACK_ERROR_IND          ((CsrWifiRouterCtrlPrim)(0x001A + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_ROUTER_CTRL_STA_INACTIVE_IND             ((CsrWifiRouterCtrlPrim)(0x001B + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
-#define CSR_WIFI_ROUTER_CTRL_WAPI_MULTICAST_IND           ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_RX_MIC_CHECK_IND        ((CsrWifiRouterCtrlPrim)(0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_MODE_SET_CFM                 ((CsrWifiRouterCtrlPrim)(0x001D + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_ROUTER_CTRL_WAPI_UNICAST_TX_ENCRYPT_IND  ((CsrWifiRouterCtrlPrim)(0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST))
 
-#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST             (0x001C + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)
+#define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST             (0x001E + CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)
 
 #define CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_COUNT             (CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_DOWNSTREAM_LOWEST)
 #define CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_COUNT               (CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_HIGHEST   + 1 - CSR_WIFI_ROUTER_CTRL_PRIM_UPSTREAM_LOWEST)
@@ -1032,12 +1036,16 @@ typedef struct
   MEMBERS
     common     - Common header for use with the CsrWifiFsm Module
     clientData -
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
 
 *******************************************************************************/
 typedef struct
 {
     CsrWifiFsmEvent                common;
     CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint32                      dataLength;
+    CsrUint8                      *data;
 } CsrWifiRouterCtrlWifiOnReq;
 
 /*******************************************************************************
@@ -1273,12 +1281,13 @@ typedef struct
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastReq
+    CsrWifiRouterCtrlWapiRxPktReq
 
   DESCRIPTION
 
   MEMBERS
     common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
     signalLength -
     signal       -
     dataLength   -
@@ -1288,11 +1297,12 @@ typedef struct
 typedef struct
 {
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint16       signalLength;
     CsrUint8       *signal;
     CsrUint16       dataLength;
     CsrUint8       *data;
-} CsrWifiRouterCtrlWapiMulticastReq;
+} CsrWifiRouterCtrlWapiRxPktReq;
 
 /*******************************************************************************
 
@@ -1302,13 +1312,15 @@ typedef struct
   DESCRIPTION
 
   MEMBERS
-    common - Common header for use with the CsrWifiFsm Module
-    status -
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
 typedef struct
 {
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint8        status;
 } CsrWifiRouterCtrlWapiMulticastFilterReq;
 
@@ -1320,16 +1332,60 @@ typedef struct
   DESCRIPTION
 
   MEMBERS
-    common - Common header for use with the CsrWifiFsm Module
-    status -
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       -
 
 *******************************************************************************/
 typedef struct
 {
     CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
     CsrUint8        status;
 } CsrWifiRouterCtrlWapiUnicastFilterReq;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxPktReq
+
+  DESCRIPTION
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
+    CsrUint16       dataLength;
+    CsrUint8       *data;
+} CsrWifiRouterCtrlWapiUnicastTxPktReq;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiFilterReq
+
+  DESCRIPTION
+
+  MEMBERS
+    common          - Common header for use with the CsrWifiFsm Module
+    interfaceTag    -
+    isWapiConnected -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
+    CsrBool         isWapiConnected;
+} CsrWifiRouterCtrlWapiFilterReq;
+
 /*******************************************************************************
 
   NAME
@@ -1984,7 +2040,7 @@ typedef struct
 /*******************************************************************************
 
   NAME
-    CsrWifiRouterCtrlWapiMulticastInd
+    CsrWifiRouterCtrlWapiRxMicCheckInd
 
   DESCRIPTION
 
@@ -2007,7 +2063,55 @@ typedef struct
     CsrUint8                      *signal;
     CsrUint16                      dataLength;
     CsrUint8                      *data;
-} CsrWifiRouterCtrlWapiMulticastInd;
+} CsrWifiRouterCtrlWapiRxMicCheckInd;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlModeSetCfm
+
+  DESCRIPTION
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    clientData   -
+    interfaceTag -
+    mode         -
+    status       -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent                common;
+    CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint16                      interfaceTag;
+    CsrWifiRouterCtrlMode          mode;
+    CsrResult                      status;
+} CsrWifiRouterCtrlModeSetCfm;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd
+
+  DESCRIPTION
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    clientData   -
+    interfaceTag -
+    dataLength   -
+    data         -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent                common;
+    CsrWifiRouterCtrlRequestorInfo clientData;
+    CsrUint16                      interfaceTag;
+    CsrUint16                      dataLength;
+    CsrUint8                      *data;
+} CsrWifiRouterCtrlWapiUnicastTxEncryptInd;
 
 
 #ifdef __cplusplus

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

@@ -35,9 +35,11 @@ const CsrWifiRouterCtrlStateHandlerType CsrWifiRouterCtrlDownstreamStateHandlers
     /* 0x0015 */ CsrWifiRouterCtrlPeerDelReqHandler,
     /* 0x0016 */ CsrWifiRouterCtrlPeerUpdateReqHandler,
     /* 0x0017 */ CsrWifiRouterCtrlCapabilitiesReqHandler,
-    CsrWifiRouterCtrlBlockAckEnableReqHandler,        /* 0x0018 */
-    CsrWifiRouterCtrlBlockAckDisableReqHandler,       /* 0x0019 */
-    CsrWifiRouterCtrlWapiMulticastReqHandler,         /* 0x001A */
-    CsrWifiRouterCtrlWapiMulticastFilterReqHandler,   /* 0x001B */
-    CsrWifiRouterCtrlWapiUnicastFilterReqHandler,     /* 0x001C */
+    /* 0x0018 */ CsrWifiRouterCtrlBlockAckEnableReqHandler,
+    /* 0x0019 */ CsrWifiRouterCtrlBlockAckDisableReqHandler,
+    /* 0x001A */ CsrWifiRouterCtrlWapiRxPktReqHandler,
+    /* 0x001B */ CsrWifiRouterCtrlWapiMulticastFilterReqHandler,
+    /* 0x001C */ CsrWifiRouterCtrlWapiUnicastFilterReqHandler,
+    /* 0x001D */ CsrWifiRouterCtrlWapiUnicastTxPktReqHandler,
+    /* 0x001E */ CsrWifiRouterCtrlWapiFilterReqHandler,
 };

+ 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 CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
-    extern void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
     extern void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
+    extern void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg);
 #ifdef __cplusplus
 }
 #endif

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -656,6 +656,65 @@ void* CsrWifiRouterCtrlTrafficConfigReqDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
+CsrSize CsrWifiRouterCtrlWifiOnReqSizeof(void *msg)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */
+    bufferSize += 2;                     /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */
+    bufferSize += 4;                     /* CsrUint32 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
+    CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlWifiOnReqDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWifiOnReq));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset);
+    CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiRouterCtrlWifiOnReqSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiRouterCtrlWifiOnReq *primitive = (CsrWifiRouterCtrlWifiOnReq *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
 CsrSize CsrWifiRouterCtrlWifiOnResSizeof(void *msg)
 {
     CsrWifiRouterCtrlWifiOnRes *primitive = (CsrWifiRouterCtrlWifiOnRes *) msg;
@@ -1055,12 +1114,13 @@ void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg)
+CsrSize CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) msg;
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) msg;
     CsrSize bufferSize = 2;
 
-    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 9) */
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 11) */
+    bufferSize += 2;                       /* CsrUint16 primitive->interfaceTag */
     bufferSize += 2;                       /* CsrUint16 primitive->signalLength */
     bufferSize += primitive->signalLength; /* CsrUint8 primitive->signal */
     bufferSize += 2;                       /* CsrUint16 primitive->dataLength */
@@ -1069,11 +1129,12 @@ CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg)
 }
 
 
-CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+CsrUint8* CsrWifiRouterCtrlWapiRxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *)msg;
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *)msg;
     *len = 0;
     CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->signalLength);
     if (primitive->signalLength)
     {
@@ -1088,13 +1149,14 @@ CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void
 }
 
 
-void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length)
+void* CsrWifiRouterCtrlWapiRxPktReqDes(CsrUint8 *buffer, CsrSize length)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastReq));
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxPktReq));
     CsrSize offset;
     offset = 0;
 
     CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
     CsrUint16Des((CsrUint16 *) &primitive->signalLength, buffer, &offset);
     if (primitive->signalLength)
     {
@@ -1120,15 +1182,74 @@ void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *voidPrimitivePointer)
+void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *voidPrimitivePointer)
 {
-    CsrWifiRouterCtrlWapiMulticastReq *primitive = (CsrWifiRouterCtrlWapiMulticastReq *) voidPrimitivePointer;
+    CsrWifiRouterCtrlWapiRxPktReq *primitive = (CsrWifiRouterCtrlWapiRxPktReq *) voidPrimitivePointer;
     CsrPmemFree(primitive->signal);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive);
 }
 
 
+CsrSize CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */
+    bufferSize += 2;                     /* CsrUint16 primitive->interfaceTag */
+    bufferSize += 2;                     /* CsrUint16 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxPktReq));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *primitive = (CsrWifiRouterCtrlWapiUnicastTxPktReq *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
 CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg)
 {
     CsrWifiRouterCtrlHipInd *primitive = (CsrWifiRouterCtrlHipInd *) msg;
@@ -2287,9 +2408,9 @@ void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg)
+CsrSize CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) msg;
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) msg;
     CsrSize bufferSize = 2;
 
     /* Calculate the Size of the Serialised Data. Could be more efficient (Try 13) */
@@ -2303,9 +2424,9 @@ CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg)
 }
 
 
-CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+CsrUint8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(CsrUint8 *ptr, CsrSize *len, void *msg)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *)msg;
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *)msg;
     *len = 0;
     CsrUint16Ser(ptr, len, primitive->common.type);
     CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
@@ -2324,9 +2445,9 @@ CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void
 }
 
 
-void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length)
+void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(CsrUint8 *buffer, CsrSize length)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiMulticastInd));
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiRxMicCheckInd));
     CsrSize offset;
     offset = 0;
 
@@ -2358,12 +2479,116 @@ void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize length)
 }
 
 
-void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *voidPrimitivePointer)
+void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *voidPrimitivePointer)
 {
-    CsrWifiRouterCtrlWapiMulticastInd *primitive = (CsrWifiRouterCtrlWapiMulticastInd *) voidPrimitivePointer;
+    CsrWifiRouterCtrlWapiRxMicCheckInd *primitive = (CsrWifiRouterCtrlWapiRxMicCheckInd *) voidPrimitivePointer;
     CsrPmemFree(primitive->signal);
     CsrPmemFree(primitive->data);
     CsrPmemFree(primitive);
 }
 
 
+CsrSize CsrWifiRouterCtrlModeSetCfmSizeof(void *msg)
+{
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */
+    bufferSize += 2; /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */
+    bufferSize += 2; /* CsrUint16 primitive->interfaceTag */
+    bufferSize += 1; /* CsrWifiRouterCtrlMode primitive->mode */
+    bufferSize += 2; /* CsrResult primitive->status */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlModeSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
+    CsrUint8Ser(ptr, len, (CsrUint8) primitive->mode);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->status);
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlModeSetCfmDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlModeSetCfm *primitive = (CsrWifiRouterCtrlModeSetCfm *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlModeSetCfm));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
+    CsrUint8Des((CsrUint8 *) &primitive->mode, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->status, buffer, &offset);
+
+    return primitive;
+}
+
+
+CsrSize CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 10) */
+    bufferSize += 2;                     /* CsrWifiRouterCtrlRequestorInfo primitive->clientData */
+    bufferSize += 2;                     /* CsrUint16 primitive->interfaceTag */
+    bufferSize += 2;                     /* CsrUint16 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->clientData);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->interfaceTag);
+    CsrUint16Ser(ptr, len, (CsrUint16) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) CsrPmemAlloc(sizeof(CsrWifiRouterCtrlWapiUnicastTxEncryptInd));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->clientData, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->interfaceTag, buffer, &offset);
+    CsrUint16Des((CsrUint16 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiRouterCtrlWapiUnicastTxEncryptInd *primitive = (CsrWifiRouterCtrlWapiUnicastTxEncryptInd *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -105,10 +105,10 @@ extern CsrSize CsrWifiRouterCtrlTrafficConfigReqSizeof(void *msg);
 #define CsrWifiRouterCtrlWifiOffResSizeof CsrWifiEventCsrUint16Sizeof
 #define CsrWifiRouterCtrlWifiOffResSerFree CsrWifiRouterCtrlPfree
 
-#define CsrWifiRouterCtrlWifiOnReqSer CsrWifiEventCsrUint16Ser
-#define CsrWifiRouterCtrlWifiOnReqDes CsrWifiEventCsrUint16Des
-#define CsrWifiRouterCtrlWifiOnReqSizeof CsrWifiEventCsrUint16Sizeof
-#define CsrWifiRouterCtrlWifiOnReqSerFree CsrWifiRouterCtrlPfree
+extern CsrUint8* CsrWifiRouterCtrlWifiOnReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWifiOnReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWifiOnReqSizeof(void *msg);
+extern void CsrWifiRouterCtrlWifiOnReqSerFree(void *msg);
 
 extern CsrUint8* CsrWifiRouterCtrlWifiOnResSer(CsrUint8 *ptr, CsrSize *len, void *msg);
 extern void* CsrWifiRouterCtrlWifiOnResDes(CsrUint8 *buffer, CsrSize len);
@@ -155,21 +155,31 @@ extern void* CsrWifiRouterCtrlBlockAckDisableReqDes(CsrUint8 *buffer, CsrSize le
 extern CsrSize CsrWifiRouterCtrlBlockAckDisableReqSizeof(void *msg);
 #define CsrWifiRouterCtrlBlockAckDisableReqSerFree CsrWifiRouterCtrlPfree
 
-extern CsrUint8* CsrWifiRouterCtrlWapiMulticastReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
-extern void* CsrWifiRouterCtrlWapiMulticastReqDes(CsrUint8 *buffer, CsrSize len);
-extern CsrSize CsrWifiRouterCtrlWapiMulticastReqSizeof(void *msg);
-extern void CsrWifiRouterCtrlWapiMulticastReqSerFree(void *msg);
+extern CsrUint8* CsrWifiRouterCtrlWapiRxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiRxPktReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiRxPktReqSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiRxPktReqSerFree(void *msg);
 
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint8Ser
-#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint8Des
-#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiMulticastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiMulticastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
 #define CsrWifiRouterCtrlWapiMulticastFilterReqSerFree CsrWifiRouterCtrlPfree
 
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint8Ser
-#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint8Des
-#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiUnicastFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiUnicastFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
 #define CsrWifiRouterCtrlWapiUnicastFilterReqSerFree CsrWifiRouterCtrlPfree
 
+extern CsrUint8* CsrWifiRouterCtrlWapiUnicastTxPktReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiUnicastTxPktReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiUnicastTxPktReqSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiUnicastTxPktReqSerFree(void *msg);
+
+#define CsrWifiRouterCtrlWapiFilterReqSer CsrWifiEventCsrUint16CsrUint8Ser
+#define CsrWifiRouterCtrlWapiFilterReqDes CsrWifiEventCsrUint16CsrUint8Des
+#define CsrWifiRouterCtrlWapiFilterReqSizeof CsrWifiEventCsrUint16CsrUint8Sizeof
+#define CsrWifiRouterCtrlWapiFilterReqSerFree CsrWifiRouterCtrlPfree
+
 extern CsrUint8* CsrWifiRouterCtrlHipIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
 extern void* CsrWifiRouterCtrlHipIndDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiRouterCtrlHipIndSizeof(void *msg);
@@ -310,10 +320,20 @@ extern void* CsrWifiRouterCtrlStaInactiveIndDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiRouterCtrlStaInactiveIndSizeof(void *msg);
 #define CsrWifiRouterCtrlStaInactiveIndSerFree CsrWifiRouterCtrlPfree
 
-extern CsrUint8* CsrWifiRouterCtrlWapiMulticastIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
-extern void* CsrWifiRouterCtrlWapiMulticastIndDes(CsrUint8 *buffer, CsrSize len);
-extern CsrSize CsrWifiRouterCtrlWapiMulticastIndSizeof(void *msg);
-extern void CsrWifiRouterCtrlWapiMulticastIndSerFree(void *msg);
+extern CsrUint8* CsrWifiRouterCtrlWapiRxMicCheckIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiRxMicCheckIndDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiRxMicCheckIndSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiRxMicCheckIndSerFree(void *msg);
+
+extern CsrUint8* CsrWifiRouterCtrlModeSetCfmSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlModeSetCfmDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlModeSetCfmSizeof(void *msg);
+#define CsrWifiRouterCtrlModeSetCfmSerFree CsrWifiRouterCtrlPfree
+
+extern CsrUint8* CsrWifiRouterCtrlWapiUnicastTxEncryptIndSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiRouterCtrlWapiUnicastTxEncryptIndDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiRouterCtrlWapiUnicastTxEncryptIndSizeof(void *msg);
+extern void CsrWifiRouterCtrlWapiUnicastTxEncryptIndSerFree(void *msg);
 
 
 #ifdef __cplusplus

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -63,6 +63,7 @@ void CsrWifiSmeApFreeDownstreamMessageContents(CsrUint16 eventClass, void *messa
 const CsrCharString* CsrWifiSmeApAccessTypeToString(CsrWifiSmeApAccessType value);
 const CsrCharString* CsrWifiSmeApAuthSupportToString(CsrWifiSmeApAuthSupport value);
 const CsrCharString* CsrWifiSmeApAuthTypeToString(CsrWifiSmeApAuthType value);
+const CsrCharString* CsrWifiSmeApDirectionToString(CsrWifiSmeApDirection value);
 const CsrCharString* CsrWifiSmeApPhySupportToString(CsrWifiSmeApPhySupport value);
 const CsrCharString* CsrWifiSmeApTypeToString(CsrWifiSmeApType value);
 
@@ -79,6 +80,134 @@ const CsrCharString* CsrWifiSmeApPrimTypeToString(CsrPrim msgType);
 extern const CsrCharString *CsrWifiSmeApUpstreamPrimNames[CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT];
 extern const CsrCharString *CsrWifiSmeApDownstreamPrimNames[CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT];
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetReqSend
+
+  DESCRIPTION
+    This primitive used to retrieve information related to the active block
+    ack sessions
+
+  PARAMETERS
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+
+*******************************************************************************/
+#define CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__) \
+    msg__ = (CsrWifiSmeApActiveBaGetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApActiveBaGetReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__);
+
+#define CsrWifiSmeApActiveBaGetReqSendTo(dst__, src__, interfaceTag__) \
+    { \
+        CsrWifiSmeApActiveBaGetReq *msg__; \
+        CsrWifiSmeApActiveBaGetReqCreate(msg__, dst__, src__, interfaceTag__); \
+        CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApActiveBaGetReqSend(src__, interfaceTag__) \
+    CsrWifiSmeApActiveBaGetReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetCfmSend
+
+  DESCRIPTION
+    This primitive carries the information related to the active ba sessions
+
+  PARAMETERS
+    queue            - Destination Task Queue
+    interfaceTag     -
+    status           - Reports the result of the request
+    activeBaCount    - Number of active block ack session
+    activeBaSessions - Points to a buffer containing an array of
+                       CsrWifiSmeApBaSession structures.
+
+*******************************************************************************/
+#define CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \
+    msg__ = (CsrWifiSmeApActiveBaGetCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApActiveBaGetCfm)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->status = (status__); \
+    msg__->activeBaCount = (activeBaCount__); \
+    msg__->activeBaSessions = (activeBaSessions__);
+
+#define CsrWifiSmeApActiveBaGetCfmSendTo(dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \
+    { \
+        CsrWifiSmeApActiveBaGetCfm *msg__; \
+        CsrWifiSmeApActiveBaGetCfmCreate(msg__, dst__, src__, interfaceTag__, status__, activeBaCount__, activeBaSessions__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApActiveBaGetCfmSend(dst__, interfaceTag__, status__, activeBaCount__, activeBaSessions__) \
+    CsrWifiSmeApActiveBaGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, activeBaCount__, activeBaSessions__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteReqSend
+
+  DESCRIPTION
+    This primitive is used to delete an active block ack session
+
+  PARAMETERS
+    queue        - Message Source Task Queue (Cfm's will be sent to this Queue)
+    interfaceTag -
+    reason       -
+    baSession    - BA session to be deleted
+
+*******************************************************************************/
+#define CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__) \
+    msg__ = (CsrWifiSmeApBaDeleteReq *) CsrPmemAlloc(sizeof(CsrWifiSmeApBaDeleteReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_REQ, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->reason = (reason__); \
+    msg__->baSession = (baSession__);
+
+#define CsrWifiSmeApBaDeleteReqSendTo(dst__, src__, interfaceTag__, reason__, baSession__) \
+    { \
+        CsrWifiSmeApBaDeleteReq *msg__; \
+        CsrWifiSmeApBaDeleteReqCreate(msg__, dst__, src__, interfaceTag__, reason__, baSession__); \
+        CsrMsgTransport(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApBaDeleteReqSend(src__, interfaceTag__, reason__, baSession__) \
+    CsrWifiSmeApBaDeleteReqSendTo(CSR_WIFI_SME_IFACEQUEUE, src__, interfaceTag__, reason__, baSession__)
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteCfmSend
+
+  DESCRIPTION
+    This primitive confirms the BA is deleted
+
+  PARAMETERS
+    queue        - Destination Task Queue
+    interfaceTag -
+    status       - Reports the result of the request
+    baSession    - deleted BA session
+
+*******************************************************************************/
+#define CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__) \
+    msg__ = (CsrWifiSmeApBaDeleteCfm *) CsrPmemAlloc(sizeof(CsrWifiSmeApBaDeleteCfm)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_AP_PRIM, CSR_WIFI_SME_AP_BA_DELETE_CFM, dst__, src__); \
+    msg__->interfaceTag = (interfaceTag__); \
+    msg__->status = (status__); \
+    msg__->baSession = (baSession__);
+
+#define CsrWifiSmeApBaDeleteCfmSendTo(dst__, src__, interfaceTag__, status__, baSession__) \
+    { \
+        CsrWifiSmeApBaDeleteCfm *msg__; \
+        CsrWifiSmeApBaDeleteCfmCreate(msg__, dst__, src__, interfaceTag__, status__, baSession__); \
+        CsrSchedMessagePut(dst__, CSR_WIFI_SME_AP_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeApBaDeleteCfmSend(dst__, interfaceTag__, status__, baSession__) \
+    CsrWifiSmeApBaDeleteCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, interfaceTag__, status__, baSession__)
+
 /*******************************************************************************
 
   NAME

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -95,6 +95,23 @@ typedef CsrUint8 CsrWifiSmeApAuthType;
 #define CSR_WIFI_SME_AP_AUTH_TYPE_PERSONAL      ((CsrWifiSmeApAuthType) 0x01)
 #define CSR_WIFI_SME_AP_AUTH_TYPE_WEP           ((CsrWifiSmeApAuthType) 0x02)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApDirection
+
+  DESCRIPTION
+    Definition of Direction
+
+ VALUES
+    CSR_WIFI_AP_DIRECTION_RECEIPIENT - Receipient
+    CSR_WIFI_AP_DIRECTION_ORIGINATOR - Originator
+
+*******************************************************************************/
+typedef CsrUint8 CsrWifiSmeApDirection;
+#define CSR_WIFI_AP_DIRECTION_RECEIPIENT   ((CsrWifiSmeApDirection) 0x00)
+#define CSR_WIFI_AP_DIRECTION_ORIGINATOR   ((CsrWifiSmeApDirection) 0x01)
+
 /*******************************************************************************
 
   NAME
@@ -302,6 +319,28 @@ typedef struct
     CsrWifiSmeApWapiCapabilitiesMask wapiCapabilities;
 } CsrWifiSmeApAuthPers;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaSession
+
+  DESCRIPTION
+
+  MEMBERS
+    peerMacAddress - Indicates MAC address of the peer station
+    tid            - Specifies the TID of the MSDUs for which this Block Ack has
+                     been set up. Range: 0-15
+    direction      - Specifies if the AP is the originator or the recipient of
+                     the data stream that uses the Block Ack.
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiMacAddress     peerMacAddress;
+    CsrUint8              tid;
+    CsrWifiSmeApDirection direction;
+} CsrWifiSmeApBaSession;
+
 /*******************************************************************************
 
   NAME
@@ -456,9 +495,11 @@ typedef struct
 #define CSR_WIFI_SME_AP_WMM_PARAM_UPDATE_REQ              ((CsrWifiSmeApPrim) (0x0004 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_STA_DISCONNECT_REQ                ((CsrWifiSmeApPrim) (0x0005 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_WPS_CONFIGURATION_REQ             ((CsrWifiSmeApPrim) (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_REQ                 ((CsrWifiSmeApPrim) (0x0007 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_BA_DELETE_REQ                     ((CsrWifiSmeApPrim) (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST))
 
 
-#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST           (0x0006 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)
+#define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST           (0x0008 + CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)
 
 /* Upstream */
 #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -473,8 +514,10 @@ typedef struct
 #define CSR_WIFI_SME_AP_STA_DISCONNECT_CFM                ((CsrWifiSmeApPrim)(0x0007 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_WPS_CONFIGURATION_CFM             ((CsrWifiSmeApPrim)(0x0008 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
 #define CSR_WIFI_SME_AP_ERROR_IND                         ((CsrWifiSmeApPrim)(0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_ACTIVE_BA_GET_CFM                 ((CsrWifiSmeApPrim)(0x000A + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
+#define CSR_WIFI_SME_AP_BA_DELETE_CFM                     ((CsrWifiSmeApPrim)(0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST))
 
-#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST             (0x0009 + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)
+#define CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST             (0x000B + CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)
 
 #define CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_COUNT             (CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_HIGHEST + 1 - CSR_WIFI_SME_AP_PRIM_DOWNSTREAM_LOWEST)
 #define CSR_WIFI_SME_AP_PRIM_UPSTREAM_COUNT               (CSR_WIFI_SME_AP_PRIM_UPSTREAM_HIGHEST   + 1 - CSR_WIFI_SME_AP_PRIM_UPSTREAM_LOWEST)
@@ -655,6 +698,49 @@ typedef struct
     CsrWifiSmeWpsConfig wpsConfig;
 } CsrWifiSmeApWpsConfigurationReq;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetReq
+
+  DESCRIPTION
+    This primitive used to retrieve information related to the active block
+    ack sessions
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint16       interfaceTag;
+} CsrWifiSmeApActiveBaGetReq;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteReq
+
+  DESCRIPTION
+    This primitive is used to delete an active block ack session
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    reason       -
+    baSession    - BA session to be deleted
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent           common;
+    CsrUint16                 interfaceTag;
+    CsrWifiSmeIEEE80211Reason reason;
+    CsrWifiSmeApBaSession     baSession;
+} CsrWifiSmeApBaDeleteReq;
+
 /*******************************************************************************
 
   NAME
@@ -895,6 +981,55 @@ typedef struct
     CsrResult        status;
 } CsrWifiSmeApErrorInd;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApActiveBaGetCfm
+
+  DESCRIPTION
+    This primitive carries the information related to the active ba sessions
+
+  MEMBERS
+    common           - Common header for use with the CsrWifiFsm Module
+    interfaceTag     -
+    status           - Reports the result of the request
+    activeBaCount    - Number of active block ack session
+    activeBaSessions - Points to a buffer containing an array of
+                       CsrWifiSmeApBaSession structures.
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent        common;
+    CsrUint16              interfaceTag;
+    CsrResult              status;
+    CsrUint16              activeBaCount;
+    CsrWifiSmeApBaSession *activeBaSessions;
+} CsrWifiSmeApActiveBaGetCfm;
+
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeApBaDeleteCfm
+
+  DESCRIPTION
+    This primitive confirms the BA is deleted
+
+  MEMBERS
+    common       - Common header for use with the CsrWifiFsm Module
+    interfaceTag -
+    status       - Reports the result of the request
+    baSession    - deleted BA session
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent       common;
+    CsrUint16             interfaceTag;
+    CsrResult             status;
+    CsrWifiSmeApBaSession baSession;
+} CsrWifiSmeApBaDeleteCfm;
+
 
 #ifdef __cplusplus
 }

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -79,6 +79,7 @@ static CsrMsgConvMsgEntry csrwifisme_conv_lut[] = {
     { CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ, CsrWifiSmeSmeCommonConfigSetReqSizeof, CsrWifiSmeSmeCommonConfigSetReqSer, CsrWifiSmeSmeCommonConfigSetReqDes, CsrWifiSmeSmeCommonConfigSetReqSerFree },
     { CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ, CsrWifiSmeInterfaceCapabilityGetReqSizeof, CsrWifiSmeInterfaceCapabilityGetReqSer, CsrWifiSmeInterfaceCapabilityGetReqDes, CsrWifiSmeInterfaceCapabilityGetReqSerFree },
     { CSR_WIFI_SME_WPS_CONFIGURATION_REQ, CsrWifiSmeWpsConfigurationReqSizeof, CsrWifiSmeWpsConfigurationReqSer, CsrWifiSmeWpsConfigurationReqDes, CsrWifiSmeWpsConfigurationReqSerFree },
+    { CSR_WIFI_SME_SET_REQ, CsrWifiSmeSetReqSizeof, CsrWifiSmeSetReqSer, CsrWifiSmeSetReqDes, CsrWifiSmeSetReqSerFree },
     { CSR_WIFI_SME_ACTIVATE_CFM, CsrWifiSmeActivateCfmSizeof, CsrWifiSmeActivateCfmSer, CsrWifiSmeActivateCfmDes, CsrWifiSmeActivateCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_GET_CFM, CsrWifiSmeAdhocConfigGetCfmSizeof, CsrWifiSmeAdhocConfigGetCfmSer, CsrWifiSmeAdhocConfigGetCfmDes, CsrWifiSmeAdhocConfigGetCfmSerFree },
     { CSR_WIFI_SME_ADHOC_CONFIG_SET_CFM, CsrWifiSmeAdhocConfigSetCfmSizeof, CsrWifiSmeAdhocConfigSetCfmSer, CsrWifiSmeAdhocConfigSetCfmDes, CsrWifiSmeAdhocConfigSetCfmSerFree },
@@ -159,11 +160,11 @@ CsrMsgConvMsgEntry* CsrWifiSmeConverterLookup(CsrMsgConvMsgEntry *ce, CsrUint16
 {
     if (msgType & CSR_PRIM_UPSTREAM)
     {
-        CsrUint16 index = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT;
-        if (index < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) &&
-            csrwifisme_conv_lut[index].msgType == msgType)
+        CsrUint16 idx = (msgType & ~CSR_PRIM_UPSTREAM) + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT;
+        if (idx < (CSR_WIFI_SME_PRIM_UPSTREAM_COUNT + CSR_WIFI_SME_PRIM_DOWNSTREAM_COUNT) &&
+            csrwifisme_conv_lut[idx].msgType == msgType)
         {
-            return &csrwifisme_conv_lut[index];
+            return &csrwifisme_conv_lut[idx];
         }
     }
     else

+ 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
 
             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
 
             Refer to LICENSE.txt included with this source for details
@@ -172,6 +172,13 @@ void CsrWifiSmeFreeDownstreamMessageContents(CsrUint16 eventClass, void *message
             p->wpsConfig.secondaryDeviceType = NULL;
             break;
         }
+        case CSR_WIFI_SME_SET_REQ:
+        {
+            CsrWifiSmeSetReq *p = (CsrWifiSmeSetReq *)message;
+            CsrPmemFree(p->data);
+            p->data = NULL;
+            break;
+        }
 
         default:
             break;

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -3442,6 +3442,39 @@ extern const CsrCharString *CsrWifiSmeDownstreamPrimNames[CSR_WIFI_SME_PRIM_DOWN
 #define CsrWifiSmeScanResultsGetCfmSend(dst__, status__, scanResultsCount__, scanResults__) \
     CsrWifiSmeScanResultsGetCfmSendTo(dst__, CSR_WIFI_SME_IFACEQUEUE, status__, scanResultsCount__, scanResults__)
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeSetReqSend
+
+  DESCRIPTION
+    Used to pass custom data to the SME. Format is the same as 802.11 Info
+    Elements => | Id | Length | Data
+    1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01
+    (0x00|0x01)"
+
+  PARAMETERS
+    queue      - Message Source Task Queue (Cfm's will be sent to this Queue)
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
+
+*******************************************************************************/
+#define CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__) \
+    msg__ = (CsrWifiSmeSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSetReq)); \
+    CsrWifiFsmEventInit(&msg__->common, CSR_WIFI_SME_PRIM, CSR_WIFI_SME_SET_REQ, dst__, src__); \
+    msg__->dataLength = (dataLength__); \
+    msg__->data = (data__);
+
+#define CsrWifiSmeSetReqSendTo(dst__, src__, dataLength__, data__) \
+    { \
+        CsrWifiSmeSetReq *msg__; \
+        CsrWifiSmeSetReqCreate(msg__, dst__, src__, dataLength__, data__); \
+        CsrMsgTransport(dst__, CSR_WIFI_SME_PRIM, msg__); \
+    }
+
+#define CsrWifiSmeSetReqSend(src__, dataLength__, data__) \
+    CsrWifiSmeSetReqSendTo(CSR_WIFI_SME_LIB_DESTINATION_QUEUE, src__, dataLength__, data__)
+
 /*******************************************************************************
 
   NAME

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -1434,7 +1434,7 @@ typedef CsrUint8 CsrWifiSmeWepCredentialType;
     CsrWifiSmeWmmMode
 
   DESCRIPTION
-    Defines bits for wmmModeMask: enable/disable WMM features.
+    Defines bits for CsrWifiSmeWmmModeMask: enable/disable WMM features.
 
  VALUES
     CSR_WIFI_SME_WMM_MODE_DISABLED   - Disables the WMM features.
@@ -2410,40 +2410,6 @@ typedef struct
     CsrUint16 maxPassiveChannelTimeTu;
 } CsrWifiSmeScanConfigData;
 
-/*******************************************************************************
-
-  NAME
-    CsrWifiSmeStaConfig
-
-  DESCRIPTION
-    Station configuration options in the SME
-
-  MEMBERS
-    connectionQualityRssiChangeTrigger - Sets the difference of RSSI
-                                         measurements which triggers reports
-                                         from the Firmware
-    connectionQualitySnrChangeTrigger  - Sets the difference of SNR measurements
-                                         which triggers reports from the
-                                         Firmware
-    wmmModeMask                        - Mask containing one or more values from
-                                         CsrWifiSmeWmmMode
-    ifIndex                            - Indicates the band of frequencies used
-    allowUnicastUseGroupCipher         - If TRUE, it allows to use groupwise
-                                         keys if no pairwise key is specified
-    enableOpportunisticKeyCaching      - If TRUE, enables the Opportunistic Key
-                                         Caching feature
-
-*******************************************************************************/
-typedef struct
-{
-    CsrUint8          connectionQualityRssiChangeTrigger;
-    CsrUint8          connectionQualitySnrChangeTrigger;
-    CsrUint8          wmmModeMask;
-    CsrWifiSmeRadioIF ifIndex;
-    CsrBool           allowUnicastUseGroupCipher;
-    CsrBool           enableOpportunisticKeyCaching;
-} CsrWifiSmeStaConfig;
-
 /*******************************************************************************
 
   NAME
@@ -3197,6 +3163,40 @@ typedef struct
     } deviceInfo;
 } CsrWifiSmeScanResult;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeStaConfig
+
+  DESCRIPTION
+    Station configuration options in the SME
+
+  MEMBERS
+    connectionQualityRssiChangeTrigger - Sets the difference of RSSI
+                                         measurements which triggers reports
+                                         from the Firmware
+    connectionQualitySnrChangeTrigger  - Sets the difference of SNR measurements
+                                         which triggers reports from the
+                                         Firmware
+    wmmModeMask                        - Mask containing one or more values from
+                                         CsrWifiSmeWmmMode
+    ifIndex                            - Indicates the band of frequencies used
+    allowUnicastUseGroupCipher         - If TRUE, it allows to use groupwise
+                                         keys if no pairwise key is specified
+    enableOpportunisticKeyCaching      - If TRUE, enables the Opportunistic Key
+                                         Caching feature
+
+*******************************************************************************/
+typedef struct
+{
+    CsrUint8              connectionQualityRssiChangeTrigger;
+    CsrUint8              connectionQualitySnrChangeTrigger;
+    CsrWifiSmeWmmModeMask wmmModeMask;
+    CsrWifiSmeRadioIF     ifIndex;
+    CsrBool               allowUnicastUseGroupCipher;
+    CsrBool               enableOpportunisticKeyCaching;
+} CsrWifiSmeStaConfig;
+
 /*******************************************************************************
 
   NAME
@@ -3393,9 +3393,10 @@ typedef struct
 #define CSR_WIFI_SME_SME_COMMON_CONFIG_SET_REQ            ((CsrWifiSmePrim) (0x0034 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_INTERFACE_CAPABILITY_GET_REQ         ((CsrWifiSmePrim) (0x0035 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
 #define CSR_WIFI_SME_WPS_CONFIGURATION_REQ                ((CsrWifiSmePrim) (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
+#define CSR_WIFI_SME_SET_REQ                              ((CsrWifiSmePrim) (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST))
 
 
-#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST           (0x0036 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)
+#define CSR_WIFI_SME_PRIM_DOWNSTREAM_HIGHEST           (0x0037 + CSR_WIFI_SME_PRIM_DOWNSTREAM_LOWEST)
 
 /* Upstream */
 #define CSR_WIFI_SME_PRIM_UPSTREAM_LOWEST              (0x0000 + CSR_PRIM_UPSTREAM)
@@ -4809,6 +4810,30 @@ typedef struct
     CsrWifiSmeWpsConfig wpsConfig;
 } CsrWifiSmeWpsConfigurationReq;
 
+/*******************************************************************************
+
+  NAME
+    CsrWifiSmeSetReq
+
+  DESCRIPTION
+    Used to pass custom data to the SME. Format is the same as 802.11 Info
+    Elements => | Id | Length | Data
+    1) Cmanr Test Mode "Id:0 Length:1 Data:0x00 = OFF 0x01 = ON" "0x00 0x01
+    (0x00|0x01)"
+
+  MEMBERS
+    common     - Common header for use with the CsrWifiFsm Module
+    dataLength - Number of bytes in the buffer pointed to by 'data'
+    data       - Pointer to the buffer containing 'dataLength' bytes
+
+*******************************************************************************/
+typedef struct
+{
+    CsrWifiFsmEvent common;
+    CsrUint32       dataLength;
+    CsrUint8       *data;
+} CsrWifiSmeSetReq;
+
 /*******************************************************************************
 
   NAME

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -1356,7 +1356,7 @@ CsrSize CsrWifiSmeSmeStaConfigSetReqSizeof(void *msg)
     bufferSize += 2; /* CsrUint16 primitive->interfaceTag */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */
-    bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */
+    bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */
     bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */
@@ -1898,6 +1898,62 @@ void CsrWifiSmeWpsConfigurationReqSerFree(void *voidPrimitivePointer)
 }
 
 
+CsrSize CsrWifiSmeSetReqSizeof(void *msg)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) msg;
+    CsrSize bufferSize = 2;
+
+    /* Calculate the Size of the Serialised Data. Could be more efficient (Try 8) */
+    bufferSize += 4;                     /* CsrUint32 primitive->dataLength */
+    bufferSize += primitive->dataLength; /* CsrUint8 primitive->data */
+    return bufferSize;
+}
+
+
+CsrUint8* CsrWifiSmeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *)msg;
+    *len = 0;
+    CsrUint16Ser(ptr, len, primitive->common.type);
+    CsrUint32Ser(ptr, len, (CsrUint32) primitive->dataLength);
+    if (primitive->dataLength)
+    {
+        CsrMemCpySer(ptr, len, (const void *) primitive->data, ((CsrUint16) (primitive->dataLength)));
+    }
+    return(ptr);
+}
+
+
+void* CsrWifiSmeSetReqDes(CsrUint8 *buffer, CsrSize length)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) CsrPmemAlloc(sizeof(CsrWifiSmeSetReq));
+    CsrSize offset;
+    offset = 0;
+
+    CsrUint16Des(&primitive->common.type, buffer, &offset);
+    CsrUint32Des((CsrUint32 *) &primitive->dataLength, buffer, &offset);
+    if (primitive->dataLength)
+    {
+        primitive->data = (CsrUint8 *)CsrPmemAlloc(primitive->dataLength);
+        CsrMemCpyDes(primitive->data, buffer, &offset, ((CsrUint16) (primitive->dataLength)));
+    }
+    else
+    {
+        primitive->data = NULL;
+    }
+
+    return primitive;
+}
+
+
+void CsrWifiSmeSetReqSerFree(void *voidPrimitivePointer)
+{
+    CsrWifiSmeSetReq *primitive = (CsrWifiSmeSetReq *) voidPrimitivePointer;
+    CsrPmemFree(primitive->data);
+    CsrPmemFree(primitive);
+}
+
+
 CsrSize CsrWifiSmeAdhocConfigGetCfmSizeof(void *msg)
 {
     CsrSize bufferSize = 2;
@@ -5085,7 +5141,7 @@ CsrSize CsrWifiSmeSmeStaConfigGetCfmSizeof(void *msg)
     bufferSize += 2; /* CsrResult primitive->status */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualityRssiChangeTrigger */
     bufferSize += 1; /* CsrUint8 primitive->smeConfig.connectionQualitySnrChangeTrigger */
-    bufferSize += 1; /* CsrUint8 primitive->smeConfig.wmmModeMask */
+    bufferSize += 1; /* CsrWifiSmeWmmModeMask primitive->smeConfig.wmmModeMask */
     bufferSize += 1; /* CsrWifiSmeRadioIF primitive->smeConfig.ifIndex */
     bufferSize += 1; /* CsrBool primitive->smeConfig.allowUnicastUseGroupCipher */
     bufferSize += 1; /* CsrBool primitive->smeConfig.enableOpportunisticKeyCaching */

+ 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
 
             Refer to LICENSE.txt included with this source for details
@@ -300,6 +300,11 @@ extern void* CsrWifiSmeWpsConfigurationReqDes(CsrUint8 *buffer, CsrSize len);
 extern CsrSize CsrWifiSmeWpsConfigurationReqSizeof(void *msg);
 extern void CsrWifiSmeWpsConfigurationReqSerFree(void *msg);
 
+extern CsrUint8* CsrWifiSmeSetReqSer(CsrUint8 *ptr, CsrSize *len, void *msg);
+extern void* CsrWifiSmeSetReqDes(CsrUint8 *buffer, CsrSize len);
+extern CsrSize CsrWifiSmeSetReqSizeof(void *msg);
+extern void CsrWifiSmeSetReqSerFree(void *msg);
+
 #define CsrWifiSmeActivateCfmSer CsrWifiEventCsrUint16Ser
 #define CsrWifiSmeActivateCfmDes CsrWifiEventCsrUint16Des
 #define CsrWifiSmeActivateCfmSizeof CsrWifiEventCsrUint16Sizeof

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

@@ -47,12 +47,7 @@
 int buswidth = 0;               /* 0 means use default, values 1,4 */
 int sdio_clock = 50000;         /* kHz */
 int unifi_debug = 0;
-/*
- * fw_init prevents f/w initialisation on error.
- * Unless necessary, avoid usage in the CSR_SME_EMB build because it prevents
- * UniFi initialisation after getting out of suspend and also leaves
- * UniFi powered when the module unloads.
- */
+/* fw_init prevents f/w initialisation on error. */
 int fw_init[MAX_UNIFI_DEVS] = {-1, -1};
 int use_5g = 0;
 int led_mask = 0;               /* 0x0c00 for dev-pc-1503c, dev-pc-1528a */
@@ -67,6 +62,12 @@ int sdio_byte_mode = 0;        /* 0 for block mode + padding, 1 for byte mode */
 int coredump_max = CSR_WIFI_HIP_NUM_COREDUMP_BUFFERS;
 int run_bh_once = -1;          /* Set for scheduled interrupt mode, -1 = default */
 int bh_priority = -1;
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+#define UNIFI_LOG_HIP_SIGNALS_FILTER_SIGNAL     (1 << 0)
+#define UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA   (1 << 1)
+#define UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP  (1 << 2)
+int log_hip_signals = 0;
+#endif
 
 MODULE_DESCRIPTION("CSR UniFi (SDIO)");
 
@@ -87,6 +88,9 @@ module_param(sdio_byte_mode, int, S_IRUGO|S_IWUSR);
 module_param(coredump_max, int, S_IRUGO|S_IWUSR);
 module_param(run_bh_once, int, S_IRUGO|S_IWUSR);
 module_param(bh_priority, int, S_IRUGO|S_IWUSR);
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+module_param(log_hip_signals, int, S_IRUGO|S_IWUSR);
+#endif
 
 MODULE_PARM_DESC(buswidth, "SDIO bus width (0=default), set 1 for 1-bit or 4 for 4-bit mode");
 MODULE_PARM_DESC(sdio_clock, "SDIO bus frequency in kHz, (default = 50 MHz)");
@@ -105,6 +109,10 @@ MODULE_PARM_DESC(sdio_byte_mode, "Set to 1 for byte mode SDIO");
 MODULE_PARM_DESC(coredump_max, "Number of chip mini-coredump buffers to allocate");
 MODULE_PARM_DESC(run_bh_once, "Run BH only when firmware interrupts");
 MODULE_PARM_DESC(bh_priority, "Modify the BH thread priority");
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+MODULE_PARM_DESC(log_hip_signals, "Set to 1 to enable HIP signal offline logging");
+#endif
+
 
 /* Callback for event logging to UDI clients */
 static void udi_log_event(ul_client_t *client,
@@ -193,6 +201,54 @@ trace_putest_cmdid(unifi_putest_command_t putest_cmd)
     }
  }
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+int uf_register_hip_offline_debug(unifi_priv_t *priv)
+{
+    ul_client_t *udi_cli;
+    int i;
+
+    udi_cli = ul_register_client(priv, CLI_USING_WIRE_FORMAT, udi_log_event);
+    if (udi_cli == NULL) {
+        /* Too many clients already using this device */
+        unifi_error(priv, "Too many UDI clients already open\n");
+        return -ENOSPC;
+    }
+    unifi_trace(priv, UDBG1, "Offline HIP client is registered\n");
+
+    down(&priv->udi_logging_mutex);
+    udi_cli->event_hook = udi_log_event;
+    unifi_set_udi_hook(priv->card, logging_handler);
+    /* Log all signals by default */
+    for (i = 0; i < SIG_FILTER_SIZE; i++) {
+        udi_cli->signal_filter[i] = 0xFFFF;
+    }
+    priv->logging_client = udi_cli;
+    up(&priv->udi_logging_mutex);
+
+    return 0;
+}
+
+int uf_unregister_hip_offline_debug(unifi_priv_t *priv)
+{
+    ul_client_t *udi_cli = priv->logging_client;
+    if (udi_cli == NULL)
+    {
+        unifi_error(priv, "Unknown HIP client unregister request\n");
+        return -ERANGE;
+    }
+
+    unifi_trace(priv, UDBG1, "Offline HIP client is unregistered\n");
+
+    down(&priv->udi_logging_mutex);
+    priv->logging_client = NULL;
+    udi_cli->event_hook = NULL;
+    up(&priv->udi_logging_mutex);
+
+    ul_deregister_client(udi_cli);
+
+    return 0;
+}
+#endif
 
 
 /*
@@ -312,7 +368,6 @@ unifi_open(struct inode *inode, struct file *file)
 } /* unifi_open() */
 
 
-
 static int
 unifi_release(struct inode *inode, struct file *filp)
 {
@@ -354,6 +409,15 @@ unifi_release(struct inode *inode, struct file *filp)
         }
 
         uf_sme_deinit(priv);
+
+       /* It is possible that a blocking SME request was made from another process
+        * which did not get read by the SME before the WifiOffReq.
+        * So check for a pending request which will go unanswered and cancel
+        * the wait for event. As only one blocking request can be in progress at
+        * a time, up to one event should be completed.
+        */
+       uf_sme_cancel_request(priv, 0);
+
 #endif /* CSR_SME_USERSPACE */
     } else {
 
@@ -979,6 +1043,14 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
             goto out;
         }
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+        if (log_hip_signals) {
+            unifi_error(priv, "omnicli cannot be used when log_hip_signals is used\n");
+            r = -EFAULT;
+            goto out;
+        }
+#endif
+
         down(&priv->udi_logging_mutex);
         if (int_param) {
             pcli->event_hook = udi_log_event;
@@ -1264,6 +1336,11 @@ unifi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 
             unifi_info(priv, "UniFi ready\n");
 
+#ifdef ANDROID_BUILD
+            /* Release the wakelock */
+            unifi_trace(priv, UDBG1, "netdev_init: release wake lock\n");
+            wake_unlock(&unifi_sdio_wake_lock);
+#endif
 #ifdef CSR_NATIVE_SOFTMAC /* For softmac dev, force-enable the network interface rather than wait for a connected-ind */
             {
                 struct net_device *dev = priv->netdev[interfaceTag];
@@ -1720,6 +1797,40 @@ udi_log_event(ul_client_t *pcli,
         return;
     }
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    /* When HIP offline signal logging is enabled, omnicli cannot run */
+    if (log_hip_signals)
+    {
+        /* Add timestamp */
+        if (log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_TIMESTAMP)
+        {
+            int timestamp = jiffies_to_msecs(jiffies);
+            unifi_debug_log_to_buf("T:");
+            unifi_debug_log_to_buf("%04X%04X ", *(((CsrUint16*)&timestamp) + 1),
+                                   *(CsrUint16*)&timestamp);
+        }
+
+        /* Add signal */
+        unifi_debug_log_to_buf("S%s:%04X R:%04X D:%04X ",
+                               dir ? "T" : "F",
+                               *(CsrUint16*)signal,
+                               *(CsrUint16*)(signal + 2),
+                               *(CsrUint16*)(signal + 4));
+        unifi_debug_hex_to_buf(signal + 6, signal_len - 6);
+
+        /* Add bulk data (assume 1 bulk data per signal) */
+        if ((log_hip_signals & UNIFI_LOG_HIP_SIGNALS_FILTER_BULKDATA) &&
+            (bulkdata->d[0].data_length > 0))
+        {
+            unifi_debug_log_to_buf("\nD:");
+            unifi_debug_hex_to_buf(bulkdata->d[0].os_data_ptr, bulkdata->d[0].data_length);
+        }
+        unifi_debug_log_to_buf("\n");
+
+        return;
+    }
+#endif
+
 #ifdef CSR_NATIVE_LINUX
     uf_native_process_udi_signal(pcli, signal, signal_len, bulkdata, dir);
 #endif
@@ -1950,7 +2061,7 @@ int uf_create_device_nodes(unifi_priv_t *priv, int bus_id)
     priv->unifiudi_cdev.owner = THIS_MODULE;
 
     devno = MKDEV(MAJOR(unifi_first_devno),
-                  MINOR(unifi_first_devno) + (bus_id * MAX_UNIFI_DEVS) + 1);
+                  MINOR(unifi_first_devno) + (bus_id * 2) + 1);
     r = cdev_add(&priv->unifiudi_cdev, devno, 1);
     if (r) {
         device_destroy(unifi_class, priv->unifi_cdev.dev);
@@ -2081,7 +2192,9 @@ unifi_load(void)
 #endif
     printk("CSR native no WEXT support\n");
 #endif
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+    printk("Split patch support\n");
+#endif
     printk("Kernel %d.%d.%d\n",
            ((LINUX_VERSION_CODE) >> 16) & 0xff,
            ((LINUX_VERSION_CODE) >> 8) & 0xff,

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

@@ -296,7 +296,18 @@ uf_run_unifihelper(unifi_priv_t *priv)
 #endif
 } /* uf_run_unifihelper() */
 
+#ifdef CSR_WIFI_SPLIT_PATCH
+static CsrBool is_ap_mode(unifi_priv_t *priv)
+{
+    if (priv == NULL || priv->interfacePriv[0] == NULL)
+    {
+        return FALSE;
+    }
 
+    /* Test for mode requiring AP patch */
+    return(CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode));
+}
+#endif
 
 /*
  * ---------------------------------------------------------------------------
@@ -334,8 +345,13 @@ int uf_request_firmware_files(unifi_priv_t *priv, int is_fw)
     if (is_fw == UNIFI_FW_STA) {
         /* Free kernel buffer and reload */
         uf_release_firmware(priv, &priv->fw_sta);
+#ifdef CSR_WIFI_SPLIT_PATCH
         scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
-                  postfix, "sta.xbv");
+                  postfix, (is_ap_mode(priv) ? "ap.xbv" : "staonly.xbv") );
+#else
+        scnprintf(fw_name, UNIFI_MAX_FW_PATH_LEN, "unifi-sdio-%d/%s",
+                  postfix, "sta.xbv" );
+#endif
         r = request_firmware(&fw_entry, fw_name, priv->unifi_device);
         if (r == 0) {
             priv->fw_sta.dl_data = fw_entry->data;

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

+ 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;
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_SUPPORT_SME))
     priv->wapi_multicast_filter = 0;
     priv->wapi_unicast_filter = 0;
     priv->wapi_unicast_queued_pkt_filter = 0;
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    priv->isWapiConnection = FALSE;
+#endif
+#endif
 
     /* Enable all queues by default */
     interfacePriv->queueEnabled[0] = 1;
@@ -450,7 +455,15 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
     spin_lock_init(&priv->send_signal_lock);
 
     spin_lock_init(&priv->m4_lock);
-    spin_lock_init(&priv->ba_lock);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
+    sema_init(&priv->ba_mutex, 1);
+#else
+    init_MUTEX(&priv->ba_mutex);
+#endif
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    spin_lock_init(&priv->wapi_lock);
+#endif
 
 #ifdef CSR_SUPPORT_SME
     spin_lock_init(&priv->staRecord_lock);
@@ -472,6 +485,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
 
     /* Create m4 buffering work structure */
     INIT_WORK(&interfacePriv->send_m4_ready_task, uf_send_m4_ready_wq);
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Create work structure to buffer the WAPI data packets to be sent to SME for encryption */
+    INIT_WORK(&interfacePriv->send_pkt_to_encrypt, uf_send_pkt_to_encrypt);
+#endif
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
@@ -504,6 +522,11 @@ uf_alloc_netdevice(CsrSdioFunction *sdio_dev, int bus_id)
     }
 #endif /* CSR_SUPPORT_WEXT */
 
+#ifdef CSR_WIFI_SPLIT_PATCH
+    /* set it to some invalid value */
+    priv->pending_mode_set.common.destination = 0xaaaa;
+#endif
+
     return priv;
 } /* uf_alloc_netdevice() */
 
@@ -655,6 +678,19 @@ uf_free_netdevice(unifi_priv_t *priv)
     }
     spin_unlock_irqrestore(&priv->m4_lock, flags);
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Free any bulkdata buffers allocated for M4 caching */
+    spin_lock_irqsave(&priv->wapi_lock, flags);
+    for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
+        netInterface_priv_t *interfacePriv = priv->interfacePriv[i];
+        if (interfacePriv->wapi_unicast_bulk_data.data_length > 0) {
+            unifi_trace(priv, UDBG5, "uf_free_netdevice: free WAPI PKT bulk data %d\n", i);
+            unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
+        }
+    }
+    spin_unlock_irqrestore(&priv->wapi_lock, flags);
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
 #ifdef CONFIG_NET_SCHED
     /* Unregister the qdisc operations */
@@ -1556,7 +1592,7 @@ int prepare_and_add_macheader(unifi_priv_t *priv, struct sk_buff *skb, struct sk
     /* IF Qos Data or Qos Null Data then set QosControl field */
     if ((priority != CSR_CONTENTION) && (macHeaderLengthInBytes >= QOS_CONTROL_HEADER_SIZE)) {
 
-        if (priority >= 7) {
+        if (priority > 7) {
             unifi_trace(priv, UDBG1, "data packets priority is more than 7, priority = %x\n", priority);
             qc |= 7;
         } else {
@@ -1628,6 +1664,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
     CSR_TRANSMISSION_CONTROL transmissionControl = CSR_NO_CONFIRM_REQUIRED;
     CsrInt8 protection;
     netInterface_priv_t *interfacePriv = NULL;
+    CSR_RATE TransmitRate = (CSR_RATE)0;
 
     unifi_trace(priv, UDBG5, "entering send_ma_pkt_request\n");
 
@@ -1780,6 +1817,63 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
             return 0;
         }
 #endif
+    }/*EAPOL or WAI packet*/
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    if ((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) && \
+        (priv->wapi_unicast_filter) && \
+        (proto != ETH_P_PAE) && \
+        (proto != ETH_P_WAI) && \
+        (skb->len > 0))
+    {
+        CSR_SIGNAL signal;
+        CSR_MA_PACKET_REQUEST *req = &signal.u.MaPacketRequest;
+        netInterface_priv_t *netpriv = (netInterface_priv_t *)netdev_priv(priv->netdev[interfaceTag]);
+
+        unifi_trace(priv, UDBG4, "send_ma_pkt_request() - WAPI unicast data packet when USKID = 1 \n");
+
+        /* initialize signal to zero */
+        memset(&signal, 0, sizeof(CSR_SIGNAL));
+        /* Frame MA_PACKET request */
+        signal.SignalPrimitiveHeader.SignalId = CSR_MA_PACKET_REQUEST_ID;
+        signal.SignalPrimitiveHeader.ReceiverProcessId = 0;
+        signal.SignalPrimitiveHeader.SenderProcessId = priv->netdev_client->sender_id;
+
+        /* Fill the MA-PACKET.req */
+        req->TransmissionControl = 0;
+        req->Priority = priority;
+        unifi_trace(priv, UDBG3, "Tx Frame with Priority: %x\n", req->Priority);
+        req->TransmitRate = (CSR_RATE) 0; /* rate selected by firmware */
+        req->HostTag = 0xffffffff;        /* Ask for a new HostTag */
+        /* RA address matching with address 1 of Mac header */
+        memcpy(req->Ra.x, ((CsrUint8 *) bulkdata.d[0].os_data_ptr) + 4, ETH_ALEN);
+
+        /* Store the M4-PACKET.req for later */
+        spin_lock(&priv->wapi_lock);
+        interfacePriv->wapi_unicast_ma_pkt_sig = signal;
+        interfacePriv->wapi_unicast_bulk_data.net_buf_length = bulkdata.d[0].net_buf_length;
+        interfacePriv->wapi_unicast_bulk_data.data_length = bulkdata.d[0].data_length;
+        interfacePriv->wapi_unicast_bulk_data.os_data_ptr = bulkdata.d[0].os_data_ptr;
+        interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = bulkdata.d[0].os_net_buf_ptr;
+        spin_unlock(&priv->wapi_lock);
+
+        /* Signal the workqueue to call CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend().
+         * It cannot be called directly from the tx path because it
+         * does a non-atomic kmalloc via the framework's CsrPmemAlloc().
+         */
+        queue_work(priv->unifi_workqueue, &netpriv->send_pkt_to_encrypt);
+
+        return 0;
+    }
+#endif
+
+    if(priv->cmanrTestMode)
+    {
+        TransmitRate = priv->cmanrTestModeTransmitRate;
+        unifi_trace(priv, UDBG2, "send_ma_pkt_request: cmanrTestModeTransmitRate = %d TransmitRate=%d\n",
+                    priv->cmanrTestModeTransmitRate,
+                    TransmitRate
+                   );
     }
 
     /* Send UniFi msg */
@@ -1789,7 +1883,7 @@ send_ma_pkt_request(unifi_priv_t *priv, struct sk_buff *skb, const struct ethhdr
                                  0xffffffff,  /* Ask for a new HostTag */
                                  interfaceTag,
                                  transmissionControl,
-                                 (CSR_RATE)0,
+                                 TransmitRate,
                                  priority,
                                  priv->netdev_client->sender_id,
                                  &bulkdata);
@@ -1900,8 +1994,22 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
 #endif /* CONFIG_NET_SCHED */
 
     if (result == NETDEV_TX_OK) {
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    	/* Don't update the tx stats when the pkt is to be sent for sw encryption*/
+    	if (!((CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) &&
+              (priv->wapi_unicast_filter == 1)))
+        {
+            dev->trans_start = jiffies;
+            /* Should really count tx stats in the UNITDATA.status signal but
+             * that doesn't have the length.
+             */
+            interfacePriv->stats.tx_packets++;
+            /* count only the packet payload */
+            interfacePriv->stats.tx_bytes += skb->len;
 
-        dev->trans_start = jiffies;
+        }
+#else
+    	dev->trans_start = jiffies;
 
         /*
          * Should really count tx stats in the UNITDATA.status signal but
@@ -1910,7 +2018,7 @@ uf_net_xmit(struct sk_buff *skb, struct net_device *dev)
         interfacePriv->stats.tx_packets++;
         /* count only the packet payload */
         interfacePriv->stats.tx_bytes += skb->len;
-
+#endif
     } else if (result < 0) {
 
         /* Failed to send: fh queue was full, and the skb was discarded.
@@ -2118,6 +2226,13 @@ indicate_rx_skb(unifi_priv_t *priv, CsrUint16 ifTag, CsrUint8* dst_a, CsrUint8*
     }
 
 
+    if(priv->cmanrTestMode)
+    {
+        const CSR_MA_PACKET_INDICATION *pkt_ind = &signal->u.MaPacketIndication;
+        priv->cmanrTestModeTransmitRate = pkt_ind->ReceivedRate;
+        unifi_trace(priv, UDBG2, "indicate_rx_skb: cmanrTestModeTransmitRate=%d\n", priv->cmanrTestModeTransmitRate);
+    }
+
     /* Pass SKB up the stack */
 #ifdef CSR_WIFI_USE_NETIF_RX
         netif_rx(skb);
@@ -2780,36 +2895,17 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
             if((dataFrameType == QOS_DATA) || (dataFrameType == QOS_DATA_NULL)){
 
                 /*
-                  QoS control field is offset from frame control by 2 (frame control)
-                  + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN
-                */
+                 * QoS control field is offset from frame control by 2 (frame control)
+                 * + 2 (duration/ID) + 2 (sequence control) + 3*ETH_ALEN or 4*ETH_ALEN
+                 */
                 if((frameControl & IEEE802_11_FC_TO_DS_MASK) && (frameControl & IEEE802_11_FC_FROM_DS_MASK)){
                     qosControl= CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 30);
                 }
                 else{
                     qosControl = CSR_GET_UINT16_FROM_LITTLE_ENDIAN(pData->os_data_ptr + 24);
                 }
-
-                if((IS_DTIM_ACTIVE(interfacePriv->dtimActive,interfacePriv->multicastPduHostTag))){
-                    CSR_PRIORITY priority;
-                    unifi_TrafficQueue priority_q;
-                    priority = (CSR_PRIORITY)(qosControl & IEEE802_11_QC_TID_MASK);
-                    priority_q = unifi_frame_priority_to_queue((CSR_PRIORITY) priority);
-                    if((srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_ONLY_ENABLED)
-                               ||(srcStaInfo->powersaveMode[priority_q]==CSR_WIFI_AC_TRIGGER_AND_DELIVERY_ENABLED)){
-                        unsigned long lock_flags;
-                        spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
-                        srcStaInfo->uapsdSuspended = TRUE;
-                        spin_unlock_irqrestore(&priv->staRecord_lock,lock_flags);
-                        unifi_trace(priv, UDBG3, "%s: qos Trigger Frame received while DTIM Active for staid: 0x%x\n",__FUNCTION__,srcStaInfo->aid);
-                    }
-                }
-                else{
-
-
-                    unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl);
-                    uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag);
-                }
+                unifi_trace(priv, UDBG5, "%s: Check if U-APSD operations are triggered for qosControl: 0x%x\n",__FUNCTION__,qosControl);
+                uf_process_wmm_deliver_ac_uapsd(priv,srcStaInfo,qosControl,interfaceTag);
             }
         }
     }
@@ -2829,7 +2925,7 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
             ba_addr = bssid;
         }
 
-        spin_lock(&priv->ba_lock);
+        down(&priv->ba_mutex);
         for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
             ba_session = interfacePriv->ba_session_rx[ba_session_idx];
             if (ba_session){
@@ -2842,14 +2938,14 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
                         frame_desc.active = TRUE;
                         unifi_trace(priv, UDBG6, "%s: calling process_ba_frame (session=%d)\n", __FUNCTION__, ba_session_idx);
                         process_ba_frame(priv, interfacePriv, ba_session, &frame_desc);
-                        spin_unlock(&priv->ba_lock);
+                        up(&priv->ba_mutex);
                         process_ba_complete(priv, interfacePriv);
                         break;
                 }
             }
         }
         if (ba_session_idx == MAX_SUPPORTED_BA_SESSIONS_RX){
-            spin_unlock(&priv->ba_lock);
+            up(&priv->ba_mutex);
             unifi_trace(priv, UDBG6, "%s: calling process_amsdu()", __FUNCTION__);
             process_amsdu(priv, signal, bulkdata);
         }
@@ -2865,7 +2961,7 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
      * And also this code here takes care that timeout check is made for all
      * the receive indications
      */
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     for (i=0; i < MAX_SUPPORTED_BA_SESSIONS_RX; i++){
         ba_session_rx_struct *ba_session;
         ba_session = interfacePriv->ba_session_rx[i];
@@ -2873,8 +2969,8 @@ static void process_ma_packet_ind(unifi_priv_t *priv, CSR_SIGNAL *signal, bulk_d
                 check_ba_frame_age_timeout(priv, interfacePriv, ba_session);
             }
     }
+    up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
-    spin_unlock(&priv->ba_lock);
 
     func_exit();
 }
@@ -3879,7 +3975,7 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
     }
     sn = pkt_err_ind->SequenceNumber;
 
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     /* To find the right ba_session loop through the BA sessions, compare MAC address and tID */
     for (ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
         ba_session = interfacePriv->ba_session_rx[ba_session_idx];
@@ -3894,7 +3990,7 @@ static void process_ma_packet_error_ind(unifi_priv_t *priv, CSR_SIGNAL *signal,
         }
     }
 
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
     process_ba_complete(priv, interfacePriv);
     func_exit();
 }

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

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

+ 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");
         return -EFAULT;
     }
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_card_read16(priv->card, gp_r16_params.addr, &gp_r16_params.data);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_gp_read16: unifi_card_read16() GP=0x%x failed (csrResult=0x%x)\n", gp_r16_params.addr, csrResult);
@@ -240,8 +241,9 @@ int unifi_putest_gp_write16(unifi_priv_t *priv, unsigned char *arg)
     }
 
     unifi_trace(priv, UDBG2, "gp_w16: GP=0x%08x, data=0x%04x\n", gp_w16_params.addr, gp_w16_params.data);
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_card_write16(priv->card, gp_w16_params.addr, gp_w16_params.data);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_gp_write16: unifi_card_write16() GP=%x failed (csrResult=0x%x)\n", gp_w16_params.addr, csrResult);
@@ -265,7 +267,7 @@ int unifi_putest_set_sdio_clock(unifi_priv_t *priv, unsigned char *arg)
     unifi_trace(priv, UDBG2, "set sdio clock: %d KHz\n", sdio_clock_speed);
 
     CsrSdioClaim(priv->sdio);
-    csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed);
+    csrResult = CsrSdioMaxBusClockFrequencySet(priv->sdio, sdio_clock_speed * 1000);
     CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
@@ -304,7 +306,9 @@ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg)
 
     /* Application may have stopped the XAPs, but they are needed for reset */
     if (already_in_test) {
+        CsrSdioClaim(priv->sdio);
         csrResult = unifi_start_processors(priv->card);
+        CsrSdioRelease(priv->sdio);
         if (csrResult != CSR_RESULT_SUCCESS) {
             unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
         }
@@ -317,8 +321,9 @@ int unifi_putest_start(unifi_priv_t *priv, unsigned char *arg)
             unifi_error(priv, "CsrSdioPowerOn csrResult = %d\n", csrResult);
         }
     }
-
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_init(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_start: failed to init UniFi\n");
@@ -335,7 +340,9 @@ int unifi_putest_stop(unifi_priv_t *priv, unsigned char *arg)
     CsrResult csrResult;
 
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
     }
@@ -428,7 +435,9 @@ int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg)
     }
 
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
     }
@@ -436,7 +445,9 @@ int unifi_putest_dl_fw(unifi_priv_t *priv, unsigned char *arg)
     /* Download the f/w. On UF6xxx this will cause the f/w file to convert
      * into patch format and download via the ROM boot loader
      */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_download(priv->card, 0x0c00);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_dl_fw: failed to download the f/w\n");
@@ -504,7 +515,9 @@ int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg)
     priv->fw_sta.dl_len = fw_length;
 
     /* Application may have stopped the XAPs, but they are needed for reset */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_start_processors(priv->card);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to start XAPs. Hard reset required.\n");
     }
@@ -512,7 +525,9 @@ int unifi_putest_dl_fw_buff(unifi_priv_t *priv, unsigned char *arg)
     /* Download the f/w. On UF6xxx this will cause the f/w file to convert
      * into patch format and download via the ROM boot loader
      */
+    CsrSdioClaim(priv->sdio);
     csrResult = unifi_download(priv->card, 0x0c00);
+    CsrSdioRelease(priv->sdio);
     if (csrResult != CSR_RESULT_SUCCESS) {
         unifi_error(priv,
                     "unifi_putest_dl_fw_buff: failed to download the f/w\n");
@@ -581,7 +596,9 @@ int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg)
             }
 
             /* Card software reset */
+            CsrSdioClaim(priv->sdio);
             r = unifi_card_hard_reset(priv->card);
+            CsrSdioRelease(priv->sdio);
             if (r != CSR_RESULT_SUCCESS) {
                 unifi_error(priv, "unifi_card_hard_reset() failed %d\n", r);
             }
@@ -599,7 +616,9 @@ int unifi_putest_coredump_prepare(unifi_priv_t *priv, unsigned char *arg)
     /* Stop the XAPs for coredump. The PUTEST_STOP must be called, e.g. at
      * Raw SDIO deinit, to resume them.
      */
+    CsrSdioClaim(priv->sdio);
     r = unifi_card_stop_processor(priv->card, UNIFI_PROC_BOTH);
+    CsrSdioRelease(priv->sdio);
     if (r != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "Failed to stop processors\n");
     }
@@ -646,7 +665,9 @@ int unifi_putest_cmd52_block_read(unifi_priv_t *priv, unsigned char *arg)
         return -ENOMEM;
     }
 
+    CsrSdioClaim(priv->sdio);
     r = unifi_card_readn(priv->card, block_cmd52.addr, block_local_buffer, block_cmd52.length);
+    CsrSdioRelease(priv->sdio);
     if (r != CSR_RESULT_SUCCESS) {
         unifi_error(priv, "cmd52r_block: unifi_readn failed\n");
         return -EIO;

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

@@ -17,6 +17,7 @@
  */
 #include <linux/kmod.h>
 #include <linux/init.h>
+#include <linux/suspend.h>
 #include "csr_wifi_hip_unifi.h"
 #include "unifi_priv.h"
 
@@ -25,7 +26,16 @@
 /* The function driver context, i.e the UniFi Driver */
 static CsrSdioFunctionDriver *sdio_func_drv;
 
+#ifdef CONFIG_PM
+static int uf_sdio_emb_power_event(struct notifier_block *this, unsigned long event, void *ptr);
+#endif
 
+/* The Android wakelock is here for completeness. Typically the MMC driver is used
+ * instead of sdioemb, but sdioemb may be used for CSPI.
+ */
+#ifdef ANDROID_BUILD
+struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */
+#endif
 
 /* sdioemb driver uses POSIX error codes */
 static CsrResult
@@ -501,6 +511,131 @@ uf_glue_sdio_int_handler(struct sdioemb_dev *fdev)
     }
 }
 
+#ifdef CONFIG_PM
+
+/*
+ * Power Management notifier
+ */
+struct uf_sdio_emb_pm_notifier
+{
+    struct list_head list;
+
+    CsrSdioFunction *sdio_ctx;
+    struct notifier_block pm_notifier;
+};
+
+/* PM notifier list head */
+static struct uf_sdio_emb_pm_notifier uf_sdio_emb_pm_notifiers = {
+    .sdio_ctx = NULL,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_emb_register_pm_notifier
+ * uf_sdio_emb_unregister_pm_notifier
+ *
+ *      Register/unregister for power management events. A list is used to
+ *	allow multiple card instances to be supported.
+ *
+ *  Arguments:
+ *      sdio_ctx - CSR SDIO context to associate PM notifier to
+ *
+ *  Returns:
+ *      Register function returns NULL on error
+ * ---------------------------------------------------------------------------
+ */
+static struct uf_sdio_emb_pm_notifier *
+uf_sdio_emb_register_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    /* Allocate notifier context for this card instance */
+    struct uf_sdio_emb_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_emb_pm_notifier), GFP_KERNEL);
+
+    if (notifier_ctx)
+    {
+        notifier_ctx->sdio_ctx = sdio_ctx;
+        notifier_ctx->pm_notifier.notifier_call = uf_sdio_emb_power_event;
+
+        list_add(&notifier_ctx->list, &uf_sdio_emb_pm_notifiers.list);
+
+        if (register_pm_notifier(&notifier_ctx->pm_notifier)) {
+            printk(KERN_ERR "unifi: register_pm_notifier failed\n");
+        }
+    }
+
+    return notifier_ctx;
+}
+
+static void
+uf_sdio_emb_unregister_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    struct uf_sdio_emb_pm_notifier *notifier_ctx;
+    struct list_head *node, *q;
+
+    list_for_each_safe(node, q, &uf_sdio_emb_pm_notifiers.list) {
+        notifier_ctx = list_entry(node, struct uf_sdio_emb_pm_notifier, list);
+
+        /* If it matches, unregister and free the notifier context */
+        if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx)
+        {
+            if (unregister_pm_notifier(&notifier_ctx->pm_notifier)) {
+                printk(KERN_ERR "unifi: unregister_pm_notifier failed\n");
+            }
+
+            /* Remove from list */
+            notifier_ctx->sdio_ctx = NULL;
+            list_del(node);
+            kfree(notifier_ctx);
+        }
+    }
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_emb_power_event
+ *
+ *      Handler for power management events.
+ *
+ *      We need to handle suspend/resume events while the userspace is unsuspended
+ *      to allow the SME to run its suspend/resume state machines.
+ *
+ *  Arguments:
+ *      event   event ID
+ *
+ *  Returns:
+ *      Status of the event handling
+ * ---------------------------------------------------------------------------
+ */
+static int
+uf_sdio_emb_power_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+    struct uf_sdio_emb_pm_notifier *notifier_ctx = container_of(this,
+                                                                struct uf_sdio_emb_pm_notifier,
+                                                                pm_notifier);
+
+    /* Call the CSR SDIO function driver's suspend/resume method
+     * while the userspace is unsuspended.
+     */
+    switch (event) {
+        case PM_POST_HIBERNATION:
+        case PM_POST_SUSPEND:
+            printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->resume) {
+                sdio_func_drv->resume(notifier_ctx->sdio_ctx);
+            }
+            break;
+
+        case PM_HIBERNATION_PREPARE:
+        case PM_SUSPEND_PREPARE:
+            printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->suspend) {
+                sdio_func_drv->suspend(notifier_ctx->sdio_ctx);
+            }
+            break;
+    }
+    return NOTIFY_DONE;
+}
+
+#endif /* CONFIG_PM */
 
 /*
  * ---------------------------------------------------------------------------
@@ -550,16 +685,30 @@ uf_glue_sdio_probe(struct sdioemb_dev *fdev)
     unifi_trace(NULL, UDBG1, "Setting SDIO bus clock to %d kHz\n", sdio_clock);
     sdioemb_set_max_bus_freq(fdev, 1000 * sdio_clock);
 
+#ifdef CONFIG_PM
+    /* Register to get PM events */
+    if (uf_sdio_emb_register_pm_notifier(sdio_ctx) == NULL) {
+        unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__);
+    }
+#endif
+
     /* Call the main UniFi driver inserted handler */
     if (sdio_func_drv && sdio_func_drv->inserted) {
         uf_add_os_device(fdev->slot_id, fdev->os_device);
         sdio_func_drv->inserted(sdio_ctx);
     }
 
+#ifdef ANDROID_BUILD
+    /* Take the wakelock */
+    unifi_trace(NULL, UDBG1, "emb probe: take wake lock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
+
     return 0;
 } /* uf_glue_sdio_probe() */
 
 
+
 /*
  * ---------------------------------------------------------------------------
  *  uf_sdio_remove
@@ -585,6 +734,11 @@ uf_sdio_remove(struct sdioemb_dev *fdev)
         sdio_func_drv->removed(sdio_ctx);
     }
 
+#ifdef CONFIG_PM
+    /* Unregister for PM events */
+    uf_sdio_emb_unregister_pm_notifier(sdio_ctx);
+#endif
+
     kfree(sdio_ctx);
 
 } /* uf_sdio_remove */
@@ -606,14 +760,7 @@ uf_sdio_remove(struct sdioemb_dev *fdev)
 static void
 uf_glue_sdio_suspend(struct sdioemb_dev *fdev)
 {
-    CsrSdioFunction *sdio_ctx = fdev->drv_data;
-
-    unifi_trace(NULL, UDBG3, "Suspending...\n");
-
-    /* Pass event to UniFi Driver. */
-    if (sdio_func_drv && sdio_func_drv->suspend) {
-        sdio_func_drv->suspend(sdio_ctx);
-    }
+    unifi_info(NULL, "Suspending...\n");
 
 } /* uf_glue_sdio_suspend() */
 
@@ -634,14 +781,13 @@ uf_glue_sdio_suspend(struct sdioemb_dev *fdev)
 static void
 uf_glue_sdio_resume(struct sdioemb_dev *fdev)
 {
-    CsrSdioFunction *sdio_ctx = fdev->drv_data;
+    unifi_info(NULL, "Resuming...\n");
 
-    unifi_trace(NULL, UDBG3, "Resuming...\n");
+#ifdef ANDROID_BUILD
+    unifi_trace(NULL, UDBG1, "emb resume: take wakelock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
 
-    /* Pass event to UniFi Driver. */
-    if (sdio_func_drv && sdio_func_drv->resume) {
-        sdio_func_drv->resume(sdio_ctx);
-    }
 } /* uf_glue_sdio_resume() */
 
 
@@ -708,6 +854,15 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
     /* Save the registered driver description */
     sdio_func_drv = sdio_drv;
 
+#ifdef CONFIG_PM
+    /* Initialise PM notifier list */
+    INIT_LIST_HEAD(&uf_sdio_emb_pm_notifiers.list);
+#endif
+
+#ifdef ANDROID_BUILD
+    wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work");
+#endif
+
     /* Register ourself with sdioemb */
     r = sdioemb_driver_register(&unifi_sdioemb);
     if (r) {
@@ -724,6 +879,10 @@ CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 {
     sdioemb_driver_unregister(&unifi_sdioemb);
 
+#ifdef ANDROID_BUILD
+    wake_lock_destroy(&unifi_sdio_wake_lock);
+#endif
+
     sdio_func_drv = NULL;
 
     CsrPmemFree(unifi_sdioemb.id_table);

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

@@ -47,6 +47,12 @@ void unifi_suspend(void *ospriv)
     unifi_priv_t *priv = ospriv;
     int interfaceTag=0;
 
+    /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */
+    priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
+
+    unifi_trace(priv, UDBG1, "unifi_suspend: wol_suspend %d, enable_wol %d",
+                priv->wol_suspend, enable_wol );
+
     /* Stop network traffic. */
     /* need to stop all the netdevices*/
     for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++)
@@ -54,11 +60,20 @@ void unifi_suspend(void *ospriv)
         netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
         if (interfacePriv->netdev_registered == 1)
         {
-            netif_carrier_off(priv->netdev[interfaceTag]);
+            if( priv->wol_suspend ) {
+                unifi_trace(priv, UDBG1, "unifi_suspend: Don't netif_carrier_off");
+            } else {
+                unifi_trace(priv, UDBG1, "unifi_suspend: netif_carrier_off");
+                netif_carrier_off(priv->netdev[interfaceTag]);
+            }
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[interfaceTag]);
         }
     }
+
+    unifi_trace(priv, UDBG1, "unifi_suspend: suspend SME");
+
     sme_sys_suspend(priv);
+
 } /* unifi_suspend() */
 
 
@@ -76,12 +91,44 @@ void unifi_suspend(void *ospriv)
 void unifi_resume(void *ospriv)
 {
     unifi_priv_t *priv = ospriv;
+    int interfaceTag=0;
     int r;
+    int wol = priv->wol_suspend;
+
+    unifi_trace(priv, UDBG1, "unifi_resume: resume SME, enable_wol=%d", enable_wol);
 
+    /* The resume causes wifi-on which will re-enable the BH and reinstall the ISR */
     r = sme_sys_resume(priv);
     if (r) {
         unifi_error(priv, "Failed to resume UniFi\n");
     }
 
+    /* Resume the network interfaces. For the cold resume case, this will
+     * happen upon reconnection.
+     */
+    if (wol) {
+        unifi_trace(priv, UDBG1, "unifi_resume: try to enable carrier");
+
+        /* need to start all the netdevices*/
+        for( interfaceTag=0;interfaceTag<CSR_WIFI_NUM_INTERFACES;interfaceTag++) {
+            netInterface_priv_t *interfacePriv = priv->interfacePriv[interfaceTag];
+
+            unifi_trace(priv, UDBG1, "unifi_resume: interfaceTag %d netdev_registered %d mode %d\n",
+                   interfaceTag, interfacePriv->netdev_registered, interfacePriv->interfaceMode);
+
+            if (interfacePriv->netdev_registered == 1)
+            {
+                netif_carrier_on(priv->netdev[interfaceTag]);
+                UF_NETIF_TX_START_ALL_QUEUES(priv->netdev[interfaceTag]);
+            }
+        }
+
+        /* Kick the BH thread (with reason=host) to poll for data that may have
+         * arrived during a powered suspend. This caters for the case where the SME
+         * doesn't interact with the chip (e.g install autonomous scans) during resume.
+         */
+        unifi_send_signal(priv->card, NULL, 0, NULL);
+    }
+
 } /* unifi_resume() */
 

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

@@ -21,19 +21,28 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio.h>
+#include <linux/suspend.h>
 
 #include "unifi_priv.h"
 
+#ifdef ANDROID_BUILD
+struct wake_lock unifi_sdio_wake_lock; /* wakelock to prevent suspend while resuming */
+#endif
 
 static CsrSdioFunctionDriver *sdio_func_drv;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+static int uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr);
+#endif
+
 /*
  * We need to keep track of the power on/off because we can not call
  * mmc_power_restore_host() when the card is already powered.
  * Even then, we need to patch the MMC driver to add a power_restore handler
- * in the mmc_sdio_ops structure. If the MMC driver is not patched,
- * mmc_power_save_host() and mmc_power_restore_host() are no-ops.
+ * in the mmc_sdio_ops structure. If the MMC driver before 2.6.37 is not patched,
+ * mmc_power_save_host() and mmc_power_restore_host() are no-ops in the kernel,
+ * returning immediately (at least on x86).
  */
 static int card_is_powered = 1;
 #endif /* 2.6.32 */
@@ -312,17 +321,28 @@ csr_sdio_enable_hs(struct mmc_card *card)
     int ret;
     u8 speed;
 
-    if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
+    if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) {
+        /* We've asked for HS clock rates, but controller doesn't
+         * claim to support it. We should limit the clock
+         * to 25MHz via module parameter.
+         */
+        printk(KERN_INFO "unifi: request HS but not MMC_CAP_SD_HIGHSPEED");
         return 0;
+    }
 
     if (!card->cccr.high_speed)
         return 0;
 
+#if 1
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     if (ret)
         return ret;
 
     speed |= SDIO_SPEED_EHS;
+#else
+    /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */
+    speed = SDIO_SPEED_EHS | SDIO_SPEED_SHS;
+#endif
 
     ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
     if (ret)
@@ -346,12 +366,16 @@ csr_sdio_disable_hs(struct mmc_card *card)
 
     if (!card->cccr.high_speed)
         return 0;
-
+#if 1
     ret = csr_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
     if (ret)
         return ret;
 
     speed &= ~SDIO_SPEED_EHS;
+#else
+    /* Optimisation: Eliminate read by always assuming SHS and that reserved bits can be zero */
+    speed = SDIO_SPEED_SHS; /* clear SDIO_SPEED_EHS */
+#endif
 
     ret = csr_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
     if (ret)
@@ -460,6 +484,7 @@ CsrSdioInterruptEnable(CsrSdioFunction *function)
 
     func_exit();
     if (err) {
+        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
     }
 #endif
@@ -486,6 +511,7 @@ CsrSdioInterruptDisable(CsrSdioFunction *function)
 
     func_exit();
     if (err) {
+        printk(KERN_ERR "unifi: %s: error %d writing IENx\n", __FUNCTION__, err);
         return ConvertSdioToCsrSdioResult(err);
     }
 #endif
@@ -772,6 +798,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func)
     if (!sdio_ctx) {
         return;
     }
+
 #ifndef CSR_CONFIG_MMC_INT_BYPASS_KSOFTIRQD
     /*
      * Normally, we are not allowed to do any SDIO commands here.
@@ -785,7 +812,7 @@ uf_glue_sdio_int_handler(struct sdio_func *func)
     r = csr_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, 0x00, NULL);
 #endif
     if (r) {
-        printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts\n");
+        printk(KERN_ERR "UniFi MMC Int handler: Failed to disable interrupts %d\n", r);
     }
 #endif
 
@@ -824,6 +851,8 @@ csr_sdio_linux_remove_irq(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int r;
 
+    unifi_trace(NULL, UDBG1, "csr_sdio_linux_remove_irq\n");
+
     sdio_claim_host(func);
     r = sdio_release_irq(func);
     sdio_release_host(func);
@@ -853,6 +882,8 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function)
     struct sdio_func *func = (struct sdio_func *)function->priv;
     int r;
 
+    unifi_trace(NULL, UDBG1, "csr_sdio_linux_install_irq\n");
+
     /* Register our interrupt handle */
     sdio_claim_host(func);
     r = sdio_claim_irq(func, uf_glue_sdio_int_handler);
@@ -866,7 +897,133 @@ csr_sdio_linux_install_irq(CsrSdioFunction *function)
     return r;
 } /* csr_sdio_linux_install_irq() */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+
+/*
+ * Power Management notifier
+ */
+struct uf_sdio_mmc_pm_notifier
+{
+    struct list_head list;
+
+    CsrSdioFunction *sdio_ctx;
+    struct notifier_block pm_notifier;
+};
+
+/* PM notifier list head */
+static struct uf_sdio_mmc_pm_notifier uf_sdio_mmc_pm_notifiers = {
+    .sdio_ctx = NULL,
+};
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_mmc_register_pm_notifier
+ * uf_sdio_mmc_unregister_pm_notifier
+ *
+ *      Register/unregister for power management events. A list is used to
+ *      allow multiple card instances to be supported.
+ *
+ *  Arguments:
+ *      sdio_ctx - CSR SDIO context to associate PM notifier to
+ *
+ *  Returns:
+ *      Register function returns NULL on error
+ * ---------------------------------------------------------------------------
+ */
+static struct uf_sdio_mmc_pm_notifier *
+uf_sdio_mmc_register_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    /* Allocate notifier context for this card instance */
+    struct uf_sdio_mmc_pm_notifier *notifier_ctx = kmalloc(sizeof(struct uf_sdio_mmc_pm_notifier), GFP_KERNEL);
+
+    if (notifier_ctx)
+    {
+        notifier_ctx->sdio_ctx = sdio_ctx;
+        notifier_ctx->pm_notifier.notifier_call = uf_sdio_mmc_power_event;
+
+        list_add(&notifier_ctx->list, &uf_sdio_mmc_pm_notifiers.list);
+
+        if (register_pm_notifier(&notifier_ctx->pm_notifier)) {
+            printk(KERN_ERR "unifi: register_pm_notifier failed\n");
+        }
+    }
+
+    return notifier_ctx;
+}
+
+static void
+uf_sdio_mmc_unregister_pm_notifier(CsrSdioFunction *sdio_ctx)
+{
+    struct uf_sdio_mmc_pm_notifier *notifier_ctx;
+    struct list_head *node, *q;
+
+    list_for_each_safe(node, q, &uf_sdio_mmc_pm_notifiers.list) {
+        notifier_ctx = list_entry(node, struct uf_sdio_mmc_pm_notifier, list);
+
+        /* If it matches, unregister and free the notifier context */
+        if (notifier_ctx && notifier_ctx->sdio_ctx == sdio_ctx)
+        {
+            if (unregister_pm_notifier(&notifier_ctx->pm_notifier)) {
+                printk(KERN_ERR "unifi: unregister_pm_notifier failed\n");
+            }
+
+            /* Remove from list */
+            notifier_ctx->sdio_ctx = NULL;
+            list_del(node);
+            kfree(notifier_ctx);
+        }
+    }
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * uf_sdio_mmc_power_event
+ *
+ *      Handler for power management events.
+ *
+ *      We need to handle suspend/resume events while the userspace is unsuspended
+ *      to allow the SME to run its suspend/resume state machines.
+ *
+ *  Arguments:
+ *      event   event ID
+ *
+ *  Returns:
+ *      Status of the event handling
+ * ---------------------------------------------------------------------------
+ */
+static int
+uf_sdio_mmc_power_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+    struct uf_sdio_mmc_pm_notifier *notifier_ctx = container_of(this,
+                                                                struct uf_sdio_mmc_pm_notifier,
+                                                                pm_notifier);
+
+    /* Call the CSR SDIO function driver's suspend/resume method
+     * while the userspace is unsuspended.
+     */
+    switch (event) {
+        case PM_POST_HIBERNATION:
+        case PM_POST_SUSPEND:
+            printk(KERN_INFO "%s:%d resume\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->resume) {
+                sdio_func_drv->resume(notifier_ctx->sdio_ctx);
+            }
+            break;
+
+        case PM_HIBERNATION_PREPARE:
+        case PM_SUSPEND_PREPARE:
+            printk(KERN_INFO "%s:%d suspend\n", __FUNCTION__, __LINE__ );
+            if (sdio_func_drv && sdio_func_drv->suspend) {
+                sdio_func_drv->suspend(notifier_ctx->sdio_ctx);
+            }
+            break;
+    }
+    return NOTIFY_DONE;
+}
 
+#endif /* CONFIG_PM */
+#endif /* 2.6.32 */
 
 /*
  * ---------------------------------------------------------------------------
@@ -925,6 +1082,10 @@ uf_glue_sdio_probe(struct sdio_func *func,
         sdio_ctx->features |= CSR_SDIO_FEATURE_BYTE_MODE;
     }
 
+    if (func->card->host->caps & MMC_CAP_SD_HIGHSPEED) {
+        unifi_trace(NULL, UDBG1, "MMC_CAP_SD_HIGHSPEED is available\n");
+    }
+
 #ifdef MMC_QUIRK_LENIENT_FN0
     func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
 #endif
@@ -932,6 +1093,15 @@ uf_glue_sdio_probe(struct sdio_func *func,
     /* Pass context to the SDIO driver */
     sdio_set_drvdata(func, sdio_ctx);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+    /* Register to get PM events */
+    if (uf_sdio_mmc_register_pm_notifier(sdio_ctx) == NULL) {
+        unifi_error(NULL, "%s: Failed to register for PM events\n", __FUNCTION__);
+    }
+#endif
+#endif
+
     /* Register this device with the SDIO function driver */
     /* Call the main UniFi driver inserted handler */
     if (sdio_func_drv && sdio_func_drv->inserted) {
@@ -942,6 +1112,12 @@ uf_glue_sdio_probe(struct sdio_func *func,
     /* We have finished, so release the SDIO driver */
     sdio_release_host(func);
 
+#ifdef ANDROID_BUILD
+    /* Take the wakelock */
+    unifi_trace(NULL, UDBG1, "probe: take wake lock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
+
     func_exit();
     return 0;
 } /* uf_glue_sdio_probe() */
@@ -980,6 +1156,13 @@ uf_glue_sdio_remove(struct sdio_func *func)
         sdio_func_drv->removed(sdio_ctx);
     }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+    /* Unregister for PM events */
+    uf_sdio_mmc_unregister_pm_notifier(sdio_ctx);
+#endif
+#endif
+
     kfree(sdio_ctx);
 
     func_exit();
@@ -1006,7 +1189,7 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
  * ---------------------------------------------------------------------------
  *  uf_glue_sdio_suspend
  *
- *      Card suspend callback.
+ *      Card suspend callback. The userspace will already be suspended.
  *
  * Arguments:
  *      dev            The struct device owned by the MMC driver
@@ -1018,23 +1201,9 @@ MODULE_DEVICE_TABLE(sdio, unifi_ids);
 static int
 uf_glue_sdio_suspend(struct device *dev)
 {
-    struct sdio_func *func;
-    CsrSdioFunction *sdio_ctx;
-
     func_enter();
 
-    func = dev_to_sdio_func(dev);
-    WARN_ON(!func);
-
-    sdio_ctx = sdio_get_drvdata(func);
-    WARN_ON(!sdio_ctx);
-
-    unifi_trace(NULL, UDBG1, "System Suspend...\n");
-
-    /* Clean up the SDIO function driver */
-    if (sdio_func_drv && sdio_func_drv->suspend) {
-        sdio_func_drv->suspend(sdio_ctx);
-    }
+    unifi_trace(NULL, UDBG1, "uf_glue_sdio_suspend");
 
     func_exit();
     return 0;
@@ -1045,7 +1214,7 @@ uf_glue_sdio_suspend(struct device *dev)
  * ---------------------------------------------------------------------------
  *  uf_glue_sdio_resume
  *
- *      Card resume callback.
+ *      Card resume callback. The userspace will still be suspended.
  *
  * Arguments:
  *      dev            The struct device owned by the MMC driver
@@ -1057,23 +1226,14 @@ uf_glue_sdio_suspend(struct device *dev)
 static int
 uf_glue_sdio_resume(struct device *dev)
 {
-    struct sdio_func *func;
-    CsrSdioFunction *sdio_ctx;
-
     func_enter();
 
-    func = dev_to_sdio_func(dev);
-    WARN_ON(!func);
-
-    sdio_ctx = sdio_get_drvdata(func);
-    WARN_ON(!sdio_ctx);
+    unifi_trace(NULL, UDBG1, "uf_glue_sdio_resume");
 
-    unifi_trace(NULL, UDBG1, "System Resume...\n");
-
-    /* Clean up the SDIO function driver */
-    if (sdio_func_drv && sdio_func_drv->resume) {
-        sdio_func_drv->resume(sdio_ctx);
-    }
+#ifdef ANDROID_BUILD
+    unifi_trace(NULL, UDBG1, "resume: take wakelock\n");
+    wake_lock(&unifi_sdio_wake_lock);
+#endif
 
     func_exit();
     return 0;
@@ -1133,6 +1293,10 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
         return CSR_SDIO_RESULT_INVALID_VALUE;
     }
 
+#ifdef ANDROID_BUILD
+    wake_lock_init(&unifi_sdio_wake_lock, WAKE_LOCK_SUSPEND, "unifi_sdio_work");
+#endif
+
     /* Save the registered driver description */
     /*
      * FIXME:
@@ -1141,6 +1305,13 @@ CsrSdioFunctionDriverRegister(CsrSdioFunctionDriver *sdio_drv)
      */
     sdio_func_drv = sdio_drv;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
+#ifdef CONFIG_PM
+    /* Initialise PM notifier list */
+    INIT_LIST_HEAD(&uf_sdio_mmc_pm_notifiers.list);
+#endif
+#endif
+
     /* Register ourself with mmc_core */
     r = sdio_register_driver(&unifi_driver);
     if (r) {
@@ -1157,6 +1328,10 @@ void
 CsrSdioFunctionDriverUnregister(CsrSdioFunctionDriver *sdio_drv)
 {
     printk(KERN_INFO "UniFi: unregister from MMC sdio\n");
+
+#ifdef ANDROID_BUILD
+    wake_lock_destroy(&unifi_sdio_wake_lock);
+#endif
     sdio_unregister_driver(&unifi_driver);
 
     sdio_func_drv = NULL;

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

@@ -92,11 +92,15 @@ sme_init_request(unifi_priv_t *priv)
         return -EIO;
     }
 
+    unifi_trace(priv, UDBG5, "sme_init_request: wait sem\n");
+
     /* Grab the SME semaphore until the reply comes, or timeout */
     if (down_interruptible(&priv->sme_sem)) {
         unifi_error(priv, "sme_init_request: Failed to get SME semaphore\n");
         return -EIO;
     }
+    unifi_trace(priv, UDBG5, "sme_init_request: got sem: pending\n");
+
     priv->sme_reply.request_status = SME_REQUEST_PENDING;
 
     return 0;
@@ -118,6 +122,10 @@ uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *
                     (func ? func : ""), priv->sme_reply.request_status);
         return;
     }
+    unifi_trace(priv, UDBG5,
+                "sme_complete_request: completed %s (s:%d)\n",
+                (func ? func : ""), priv->sme_reply.request_status);
+
     priv->sme_reply.request_status = SME_REQUEST_RECEIVED;
     priv->sme_reply.reply_status = reply_status;
 
@@ -127,23 +135,66 @@ uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *
 }
 
 
+void
+uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status)
+{
+    /* Check for a blocking SME request in progress, and cancel the wait.
+     * This should be used when the character device is closed.
+     */
+
+    if (priv == NULL) {
+        unifi_error(priv, "sme_cancel_request: Invalid priv\n");
+        return;
+    }
+
+    /* If no request is pending, nothing to wake up */
+    if (priv->sme_reply.request_status != SME_REQUEST_PENDING) {
+        unifi_trace(priv, UDBG5,
+                    "sme_cancel_request: no request was pending (s:%d)\n",
+                    priv->sme_reply.request_status);
+        /* Nothing to do */
+        return;
+    }
+    unifi_trace(priv, UDBG5,
+                "sme_cancel_request: request cancelled (s:%d)\n",
+                priv->sme_reply.request_status);
+
+    /* Wake up the wait with an error status */
+    priv->sme_reply.request_status = SME_REQUEST_CANCELLED;
+    priv->sme_reply.reply_status = reply_status; /* unimportant since the CANCELLED state will fail the ioctl */
+
+    wake_up_interruptible(&priv->sme_request_wq);
+
+    return;
+}
+
+
 static int
 _sme_wait_for_reply(unifi_priv_t *priv,
         unsigned long timeout, const char *func)
 {
     long r;
 
-    unifi_trace(priv, UDBG5, "sme_wait_for_reply: sleep\n");
+    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s sleep\n", func ? func : "");
     r = wait_event_interruptible_timeout(priv->sme_request_wq,
                                          (priv->sme_reply.request_status != SME_REQUEST_PENDING),
                                          msecs_to_jiffies(timeout));
-    unifi_trace(priv, UDBG5, "sme_wait_for_reply: awake\n");
+    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s awake (%d)\n", func ? func : "", r);
 
     if (r == -ERESTARTSYS) {
         /* The thread was killed */
+        unifi_info(priv, "ERESTARTSYS in _sme_wait_for_reply\n");
         up(&priv->sme_sem);
         return r;
     }
+    if (priv->sme_reply.request_status == SME_REQUEST_CANCELLED) {
+        unifi_trace(priv, UDBG5, "Cancelled waiting for SME to reply (%s s:%d, t:%d, r:%d)\n",
+                    (func ? func : ""), priv->sme_reply.request_status, timeout, r);
+
+        /* Release the SME semaphore that was downed in sme_init_request() */
+        up(&priv->sme_sem);
+        return -EIO; /* fail the ioctl */
+    }
     if ((r == 0) && (priv->sme_reply.request_status != SME_REQUEST_RECEIVED)) {
         unifi_notice(priv, "Timeout waiting for SME to reply (%s s:%d, t:%d)\n",
                      (func ? func : ""), priv->sme_reply.request_status, timeout);
@@ -156,6 +207,9 @@ _sme_wait_for_reply(unifi_priv_t *priv,
         return -ETIMEDOUT;
     }
 
+    unifi_trace(priv, UDBG5, "sme_wait_for_reply: %s received (%d)\n",
+                func ? func : "", r);
+
     /* Release the SME semaphore that was downed in sme_init_request() */
     up(&priv->sme_sem);
 
@@ -1289,22 +1343,20 @@ int sme_sys_suspend(unifi_priv_t *priv)
         return -EIO;
     }
 
-    /* For powered suspend, tell the resume's wifi_on() not to reinit UniFi */
-    priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
-
-    /* Suspend the SME, which will cause it to power down UniFi */
+    /* Suspend the SME, which MAY cause it to power down UniFi */
     CsrWifiRouterCtrlSuspendIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, 0, priv->wol_suspend);
     r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
     if (r) {
         /* No reply - forcibly power down in case the request wasn't processed */
         unifi_notice(priv,
                      "suspend: SME did not reply %s, ",
-                     priv->ptest_mode ? "leave powered" : "power off UniFi anyway\n");
+                     (priv->ptest_mode | priv->wol_suspend) ? "leave powered" : "power off UniFi anyway\n");
 
         /* Leave power on for production test, though */
         if (!priv->ptest_mode) {
             /* Put UniFi to deep sleep, in case we can not power it off */
             CsrSdioClaim(priv->sdio);
+            unifi_trace(priv, UDBG1, "Force deep sleep");
             csrResult = unifi_force_low_power_mode(priv->card);
 
             /* For WOL, the UniFi must stay powered */
@@ -1319,13 +1371,40 @@ int sme_sys_suspend(unifi_priv_t *priv)
     if (priv->wol_suspend) {
         unifi_trace(priv, UDBG1, "UniFi left powered for WOL\n");
 
-        /* For PIO WOL, disable SDIO interrupt to enable PIO mode in the f/w */
-        if (enable_wol == UNIFI_WOL_PIO) {
-            unifi_trace(priv, UDBG1, "Remove IRQ to enable PIO WOL\n");
-            if (csr_sdio_linux_remove_irq(priv->sdio)) {
-                unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
+        /* Remove the IRQ, which also disables the card SDIO interrupt.
+         * Disabling the card SDIO interrupt enables the PIO WOL source.
+         * Removal of the of the handler ensures that in both SDIO and PIO cases
+         * the card interrupt only wakes the host. The card will be polled
+         * after resume to handle any pending data.
+         */
+        if (csr_sdio_linux_remove_irq(priv->sdio)) {
+            unifi_notice(priv, "WOL csr_sdio_linux_remove_irq failed\n");
+        }
+
+        if (enable_wol == UNIFI_WOL_SDIO) {
+            /* Because csr_sdio_linux_remove_irq() disabled the card SDIO interrupt,
+             * it must be left enabled to wake-on-SDIO.
+             */
+            unifi_trace(priv, UDBG1, "Enable card SDIO interrupt for SDIO WOL\n");
+
+            CsrSdioClaim(priv->sdio);
+            csrResult = CsrSdioInterruptEnable(priv->sdio);
+            CsrSdioRelease(priv->sdio);
+
+            if (csrResult != CSR_RESULT_SUCCESS) {
+                unifi_error(priv, "WOL CsrSdioInterruptEnable failed %d\n", csrResult);
             }
+        } else {
+            unifi_trace(priv, UDBG1, "Disabled card SDIO interrupt for PIO WOL\n");
         }
+
+        /* Prevent the BH thread from running during the suspend.
+         * Upon resume, sme_sys_resume() will trigger a wifi-on, this will cause
+         * the BH thread to be re-enabled and reinstall the ISR.
+         */
+        priv->bh_thread.block_thread = 1;
+
+        unifi_trace(priv, UDBG1, "unifi_suspend: suspended BH");
     }
 
     /* Consider UniFi to be uninitialised */
@@ -1354,22 +1433,10 @@ int sme_sys_resume(unifi_priv_t *priv)
 
     CsrWifiRouterCtrlResumeIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, priv->wol_suspend);
 
-    if (priv->ptest_mode == 1) {
-        r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
-        if (r) {
-            /* No reply - forcibly power down in case the request wasn't processed */
-            unifi_notice(priv,
-                    "resume: SME did not reply, return success anyway\n");
-        }
-    } else {
-
-        /*
-         * We are not going to wait for the reply because the SME might be in
-         * the userspace. In this case the event will reach it when the kernel
-         * resumes. So, release now the SME semaphore that was downed in
-         * sme_init_request().
-         */
-        up(&priv->sme_sem);
+    r = sme_wait_for_reply(priv, UNIFI_SME_SYS_LONG_TIMEOUT);
+    if (r) {
+        unifi_notice(priv,
+                "resume: SME did not reply, return success anyway\n");
     }
 
     return 0;

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

@@ -20,6 +20,8 @@
 #ifdef CSR_SUPPORT_WEXT_AP
 #include "sme_csr/csr_wifi_sme_sef.h"
 #endif
+
+
 /*
  * This file implements the SME SYS API and contains the following functions:
  * CsrWifiRouterCtrlMediaStatusReqHandler()
@@ -40,8 +42,10 @@
  * CsrWifiRouterCtrlTclasDelReqHandler()
  * CsrWifiRouterCtrlSetModeReqHandler()
  * CsrWifiRouterCtrlWapiMulticastFilterReqHandler()
- * CsrWifiRouterCtrlWapiMulticastReqHandler()
  * CsrWifiRouterCtrlWapiUnicastFilterReqHandler()
+ * CsrWifiRouterCtrlWapiUnicastTxPktReqHandler()
+ * CsrWifiRouterCtrlWapiRxPktReqHandler()
+ * CsrWifiRouterCtrlWapiFilterReqHandler()
  */
 
 #ifdef CSR_SUPPORT_SME
@@ -731,10 +735,31 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     if (priv == NULL) {
         return;
     }
-    for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
-        priv->interfacePriv[i]->interfaceMode = 0;
+    if( priv->wol_suspend ) {
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Don't reset mode\n");
+    } else {
+#ifdef ANDROID_BUILD
+        /* Take the wakelock while Wi-Fi On is in progress */
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: take wake lock\n");
+        wake_lock(&unifi_sdio_wake_lock);
+#endif
+        for (i=0; i<CSR_WIFI_NUM_INTERFACES; i++) {
+            unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: Setting interface %d to NONE\n", i );
+
+            priv->interfacePriv[i]->interfaceMode = 0;
+        }
+    }
+    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X) req->dataLength=%d req->data=0x%x\n", msg->source, req->dataLength, req->data);
+
+    if(req->dataLength==3 && req->data && req->data[0]==0 && req->data[1]==1 && req->data[2]==1)
+    {
+        priv->cmanrTestMode = TRUE;
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler: cmanrTestMode=%d\n", priv->cmanrTestMode);
+    }
+    else
+    {
+        priv->cmanrTestMode = FALSE;
     }
-    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWifiOnReqHandler(0x%.4X)\n", msg->source);
 
     /*
      * The request to initialise UniFi might come while UniFi is running.
@@ -747,11 +772,16 @@ void CsrWifiRouterCtrlWifiOnReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     /* Update the wifi_on state */
     priv->wifi_on_state = wifi_on_in_progress;
 
-    r = uf_request_firmware_files(priv, UNIFI_FW_STA);
-    if (r) {
-        unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n");
-        CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE);
-        return;
+    /* If UniFi was unpowered, acquire the firmware for download to chip */
+    if (!priv->wol_suspend) {
+        r = uf_request_firmware_files(priv, UNIFI_FW_STA);
+        if (r) {
+            unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to get f/w\n");
+            CsrWifiRouterCtrlWifiOnCfmSend(msg->source, req->clientData, CSR_RESULT_FAILURE);
+            return;
+        }
+    } else {
+        unifi_trace(priv, UDBG1, "Don't need firmware\n");
     }
 
     /* Power on UniFi (which may not necessarily have been off) */
@@ -832,6 +862,13 @@ wifi_off(unifi_priv_t *priv)
     int i;
     CsrResult csrResult;
 
+
+    /* Already off? */
+    if (priv->wifi_on_state == wifi_on_unspecified) {
+        unifi_trace(priv, UDBG1, "wifi_off already\n");
+        return;
+    }
+
     unifi_trace(priv, UDBG1, "wifi_off\n");
 
     /* Destroy the Traffic Analysis Module */
@@ -840,6 +877,7 @@ wifi_off(unifi_priv_t *priv)
     cancel_work_sync(&priv->ta_sample_ind_work.task);
 #ifdef CSR_SUPPORT_WEXT
     cancel_work_sync(&priv->sme_config_task);
+    wext_send_disassoc_event(priv);
 #endif
 
     /* Cancel pending M4 stuff */
@@ -908,9 +946,6 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWifiOffReq* req = (CsrWifiRouterCtrlWifiOffReq*)msg;
     int i = 0;
-#ifdef CSR_SUPPORT_WEXT_AP
-    CsrWifiSmeWifiOffCfm cfm;
-#endif
 
     if (priv == NULL) {
         return;
@@ -924,6 +959,7 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         if (interfacePriv->netdev_registered == 1) {
             netif_carrier_off(priv->netdev[i]);
             UF_NETIF_TX_STOP_ALL_QUEUES(priv->netdev[i]);
+            interfacePriv->connected = UnifiConnectedUnknown;
         }
         interfacePriv->interfaceMode = 0;
 
@@ -936,15 +972,11 @@ void CsrWifiRouterCtrlWifiOffReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     wifi_off(priv);
 
     CsrWifiRouterCtrlWifiOffCfmSend(msg->source,req->clientData);
-#ifdef CSR_SUPPORT_WEXT_AP
-    /* Router is turned off when WifiOffCfm is received
-     * hence for wext we don't see WifiOffCfm in the wext
-     * files. So just tell the waiting process that
-     * Wifi off is successful
+
+    /* If this is called in response to closing the character device, the
+     * caller must use uf_sme_cancel_request() to terminate any pending SME
+     * blocking request or there will be a delay while the operation times out.
      */
-    cfm.status =  CSR_RESULT_SUCCESS;
-    CsrWifiSmeWifiOffCfmHandler(priv,(CsrWifiFsmEvent*)(&cfm));
-#endif
 }
 
 
@@ -1065,7 +1097,9 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     {
         int i; /* used as a loop counter */
         CsrUint32 intmode = CSR_WIFI_INTMODE_DEFAULT;
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+        CsrBool switching_ap_fw = FALSE;
+#endif
         /* Register the UniFi device with the OS network manager */
         unifi_trace(priv, UDBG3, "Card Init Completed Successfully\n");
 
@@ -1099,6 +1133,16 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
                     return;
                 }
             }
+#ifdef CSR_WIFI_SPLIT_PATCH
+            else
+            {
+                /* If a netdev is already registered, we have received this WifiOnRes
+                 * in response to switching AP/STA firmware in a ModeSetReq.
+                 * Rememeber this in order to send a ModeSetCfm once
+                 */
+                switching_ap_fw = TRUE;
+            }
+#endif
         }
         priv->totalInterfaceCount = res->numInterfaceAddress;
 
@@ -1117,8 +1161,27 @@ void CsrWifiRouterCtrlWifiOnResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         /* Acknowledge the CsrWifiRouterCtrlWifiOnReq now */
         CsrWifiRouterCtrlWifiOnCfmSend(msg->source, res->clientData, CSR_RESULT_SUCCESS);
 
+#ifdef CSR_WIFI_SPLIT_PATCH
+        if (switching_ap_fw && (priv->pending_mode_set.common.destination != 0xaaaa)) {
+            unifi_info(priv, "Completed firmware reload with %s patch\n",
+                CSR_WIFI_HIP_IS_AP_FW(priv->interfacePriv[0]->interfaceMode) ? "AP" : "STA");
+
+            /* Confirm the ModeSetReq that requested the AP/STA patch switch */
+            CsrWifiRouterCtrlModeSetCfmSend(priv->pending_mode_set.common.source,
+                                            priv->pending_mode_set.clientData,
+                                            priv->pending_mode_set.interfaceTag,
+                                            priv->pending_mode_set.mode,
+                                            CSR_RESULT_SUCCESS);
+            priv->pending_mode_set.common.destination = 0xaaaa;
+        }
+#endif
         unifi_info(priv, "UniFi ready\n");
 
+#ifdef ANDROID_BUILD
+        /* Release the wakelock */
+        unifi_trace(priv, UDBG1, "ready: release wake lock\n");
+        wake_unlock(&unifi_sdio_wake_lock);
+#endif
         /* Firmware initialisation is complete, so let the SDIO bus
          * clock be raised when convienent to the core.
          */
@@ -1257,15 +1320,7 @@ void CsrWifiRouterCtrlResumeResHandler(void* drvpriv, CsrWifiFsmEvent* msg)
         return;
     }
 
-    /*
-     * Unless we are in ptest mode, nothing is waiting for the response.
-     * Do not call sme_complete_request(), otherwise the driver
-     * and the SME will be out of step.
-     */
-    if (priv->ptest_mode == 1) {
-        sme_complete_request(priv, res->status);
-    }
-
+    sme_complete_request(priv, res->status);
 }
 
 
@@ -1709,7 +1764,6 @@ void CsrWifiRouterCtrlInterfaceReset(unifi_priv_t *priv, CsrUint16 interfaceTag)
                                              &(interfacePriv->genericMulticastOrBroadCastFrames));
 
     uf_flush_list(priv,&(interfacePriv->genericMulticastOrBroadCastFrames));
-    uf_flush_maPktlist(priv,&(interfacePriv->directedMaPktReq));
 
     /*  process the list of frames that requested cfm
     and send cfm to requestor one by one */
@@ -1747,21 +1801,93 @@ void CsrWifiRouterCtrlModeSetReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
     if (req->interfaceTag < CSR_WIFI_NUM_INTERFACES)
     {
         netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
-
+#ifdef CSR_WIFI_SPLIT_PATCH
+        CsrUint8 old_mode = interfacePriv->interfaceMode;
+#endif
         unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlModeSetReqHandler: interfacePriv->interfaceMode = %d\n",
                 interfacePriv->interfaceMode);
 
-        /* Cleanup the database first for current existing mode, Then take
-         * care of setting the new mode (Transition seq: AnyMode->NoneMode->newMode)
-         * So for Every mode changes, Database Initialization/cleanup needed
+        interfacePriv->interfaceMode = req->mode;
+
+#ifdef CSR_WIFI_SPLIT_PATCH
+        /* Detect a change in mode that requires a switch to/from the AP firmware patch.
+         * This should only happen when transitioning in/out of AP modes.
          */
-        CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag);
+        if (CSR_WIFI_HIP_IS_AP_FW(req->mode) != CSR_WIFI_HIP_IS_AP_FW(old_mode))
+        {
+            CsrWifiRouterCtrlVersions versions;
+            int r;
+
+#ifdef ANDROID_BUILD
+            /* Take the wakelock while switching patch */
+            unifi_trace(priv, UDBG1, "patch switch: take wake lock\n");
+            wake_lock(&unifi_sdio_wake_lock);
+#endif
+            unifi_info(priv, "Resetting UniFi with %s patch\n", CSR_WIFI_HIP_IS_AP_FW(req->mode) ? "AP" : "STA");
+
+            r = uf_request_firmware_files(priv, UNIFI_FW_STA);
+            if (r) {
+                unifi_error(priv, "CsrWifiRouterCtrlModeSetReqHandler: Failed to get f/w\n");
+                CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag,
+                                                req->mode, CSR_RESULT_FAILURE);
+                return;
+            }
+
+            /* Block the I/O thread */
+            priv->bh_thread.block_thread = 1;
+
+            /* Reset and download the new patch */
+            r = uf_init_hw(priv);
+            if (r) {
+                unifi_error(priv, "CsrWifiRouterCtrlWifiOnReqHandler: Failed to initialise h/w, error %d\n", r);
+                CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag,
+                                                req->mode, CSR_RESULT_FAILURE);
+                return;
+            }
+
+            /* Re-enable the I/O thread */
+            priv->bh_thread.block_thread = 0;
+
+            /* Get the version information from the core */
+            unifi_card_info(priv->card, &priv->card_info);
+
+            /* Copy to the unifiio_card_info structure. */
+            versions.chipId = priv->card_info.chip_id;
+            versions.chipVersion = priv->card_info.chip_version;
+            versions.firmwareBuild = priv->card_info.fw_build;
+            versions.firmwareHip = priv->card_info.fw_hip_version;
+            versions.routerBuild = (CsrCharString*)CSR_WIFI_VERSION;
+            versions.routerHip = (UNIFI_HIP_MAJOR_VERSION << 8) | UNIFI_HIP_MINOR_VERSION;
+
+            /* Now that new firmware is running, send a WifiOnInd to the NME. This will
+             * cause it to retransfer the MIB.
+             */
+            CsrWifiRouterCtrlWifiOnIndSend(msg->source, 0, CSR_RESULT_SUCCESS, versions);
+
+            /* Store the request so we know where to send the ModeSetCfm */
+            priv->pending_mode_set = *req;
+        }
+        else
+#endif
+        {
+            /* No patch switch, confirm straightaway */
+            CsrWifiRouterCtrlModeSetCfmSend(msg->source, req->clientData, req->interfaceTag,
+                                            req->mode, CSR_RESULT_SUCCESS);
+        }
 
-        interfacePriv->interfaceMode = req->mode;
         interfacePriv->bssid = req->bssid;
         /* For modes other than AP/P2PGO, set below member FALSE */
         interfacePriv->intraBssEnabled = FALSE;
-
+        /* Initialise the variable bcTimSet with a value
+         * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value
+         */
+        interfacePriv->bcTimSet = 0xFF;
+        interfacePriv->bcTimSetReqPendingFlag = FALSE;
+        /* Initialise the variable bcTimSetReqQueued with a value
+         * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value
+         */
+        interfacePriv->bcTimSetReqQueued =0xFF;
+        CsrWifiRouterCtrlInterfaceReset(priv,req->interfaceTag);
 
         if(req->mode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
            req->mode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
@@ -1797,8 +1923,6 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
     unifi_port_config_t *controlledPort;
     unifi_port_config_t *unControlledPort;
     netInterface_priv_t *interfacePriv;
-    maPktReqList_t *maPktreq;
-    struct list_head *listHeadMaPktreq,*placeHolderMaPktreq;
 
     CsrUint8 ba_session_idx = 0;
     ba_session_rx_struct *ba_session_rx = NULL;
@@ -1832,21 +1956,6 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
             uf_flush_list(priv,&(staInfo->dataPdu[j]));
         }
 
-        /* There may be race condition
-           before getting the ma_packet_cfm from f/w, driver may receive peer del from SME
-        */
-        spin_lock_irqsave(&priv->tx_q_lock,lock_flags);
-        list_for_each_safe(listHeadMaPktreq, placeHolderMaPktreq, &interfacePriv->directedMaPktReq) {
-            maPktreq = list_entry(listHeadMaPktreq, maPktReqList_t, q);
-            if(maPktreq->staHandler== staInfo->assignedHandle){
-                dev_kfree_skb(maPktreq->skb);
-                list_del(listHeadMaPktreq);
-                kfree(maPktreq);
-            }
-
-        }
-        spin_unlock_irqrestore(&priv->tx_q_lock,lock_flags);
-
         spin_lock_irqsave(&priv->staRecord_lock,lock_flags);
         /* clear the port configure array info, for the corresponding peer entry */
         controlledPort = &interfacePriv->controlled_data_port;
@@ -1885,7 +1994,7 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
         /* Stop BA session if it is active, for this peer address all BA sessions
         (per tID per role) are closed */
 
-        spin_lock(&priv->ba_lock);
+        down(&priv->ba_mutex);
         for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
             ba_session_rx = priv->interfacePriv[req->interfaceTag]->ba_session_rx[ba_session_idx];
             if(ba_session_rx) {
@@ -1912,7 +2021,7 @@ static int peer_delete_record(unifi_priv_t *priv, CsrWifiRouterCtrlPeerDelReq *r
             }
         }
 
-        spin_unlock(&priv->ba_lock);
+        up(&priv->ba_mutex);
 
 #ifdef CSR_SUPPORT_SME
         unifi_trace(priv, UDBG1, "Canceling work queue for STA with AID: %d\n", staInfo->aid);
@@ -2134,8 +2243,16 @@ static int peer_add_new_record(unifi_priv_t *priv,CsrWifiRouterCtrlPeerAddReq *r
             newRecord->txSuspend = FALSE;
 
             /*U-APSD related data structure*/
+            newRecord->timRequestPendingFlag = FALSE;
+
+            /* Initialise the variable updateTimReqQueued with a value
+             * other then CSR_WIFI_TIM_SET or CSR_WIFI_TIM_RESET value
+             */
+            newRecord->updateTimReqQueued = 0xFF;
+            newRecord->timSet = CSR_WIFI_TIM_RESET;
             newRecord->uapsdActive = FALSE;
             newRecord->noOfSpFramesSent =0;
+            newRecord->triggerFramePriority = CSR_QOS_UP0;
 
             /* The protection bit is updated once the port opens for corresponding peer in
              * routerPortConfigure request */
@@ -2602,13 +2719,13 @@ void CsrWifiRouterCtrlBlockAckDisableReqHandler(void* drvpriv, CsrWifiFsmEvent*
 
     unifi_trace(priv, UDBG6, "%s: in ok\n", __FUNCTION__);
 
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     r = blockack_session_stop(priv,
                               req->interfaceTag,
                               req->role,
                               req->trafficStreamID,
                               req->macAddress);
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
 
     CsrWifiRouterCtrlBlockAckDisableCfmSend(msg->source,
                                             req->clientData,
@@ -2746,6 +2863,16 @@ CsrBool blockack_session_start(unifi_priv_t *priv,
                             init_timer(&ba_session_rx->timer);
                             mod_timer(&ba_session_rx->timer, (jiffies + usecs_to_jiffies((ba_session_rx->timeout) * 1024)));
                         }
+                        /*
+                         * The starting sequence number shall remain same if the BA
+                         * enable request is issued to update BA parameters only. If
+                         * it is not same, then we scroll our window to the new starting
+                         * sequence number. This could happen if the DELBA frame from
+                         * originator is lost and then we receive ADDBA frame with new SSN.
+                        */
+                        if(ba_session_rx->start_sn != start_sn) {
+                            scroll_ba_window(priv, interfacePriv, ba_session_rx, start_sn);
+                        }
                         return TRUE;
                     }
                 }
@@ -2768,6 +2895,21 @@ CsrBool blockack_session_start(unifi_priv_t *priv,
             return FALSE;
         }
 
+        /* It is observed that with some devices there is a race between
+         * EAPOL exchanges and BA session establishment. This results in
+         * some EAPOL authentication packets getting stuck in BA reorder
+         * buffer and hence the conection cannot be established. To avoid
+         * this we check here if the EAPOL authentication is complete and
+         * if so then only allow the BA session to establish.
+         *
+         * It is verified that the peers normally re-establish
+         * the BA session after the initial rejection.
+         */
+        if (CSR_WIFI_ROUTER_CTRL_PORT_ACTION_8021X_PORT_OPEN != uf_sme_port_state(priv, macAddress.a, UF_CONTROLLED_PORT_Q, interfacePriv->InterfaceTag))
+        {
+            unifi_warning(priv, "blockack_session_start: Controlled port not opened, Reject BA request\n");
+            return FALSE;
+        }
 
         ba_session_rx = kmalloc(sizeof(ba_session_rx_struct), GFP_KERNEL);
         if (!ba_session_rx) {
@@ -2814,7 +2956,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
 
     unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    spin_lock(&priv->ba_lock);
+    down(&priv->ba_mutex);
     r = blockack_session_start(priv,
                                req->interfaceTag,
                                req->trafficStreamID,
@@ -2824,7 +2966,7 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
                                req->ssn,
                                req->macAddress
                               );
-    spin_unlock(&priv->ba_lock);
+    up(&priv->ba_mutex);
 
     CsrWifiRouterCtrlBlockAckEnableCfmSend(msg->source,
                                            req->clientData,
@@ -2836,115 +2978,291 @@ void CsrWifiRouterCtrlBlockAckEnableReqHandler(void* drvpriv, CsrWifiFsmEvent* m
 
 void CsrWifiRouterCtrlWapiMulticastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 {
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWapiMulticastFilterReq* req = (CsrWifiRouterCtrlWapiMulticastFilterReq*)msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
 
-    unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status);
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
+
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
+
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiMulticastFilterReq: req->status = %d\n", req->status);
+
+        /* status 1 - Filter on
+        * status 0 - Filter off */
+        priv->wapi_multicast_filter = req->status;
+
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
 
-    /* status 1 - Filter on
-     * status 0 - Filter off */
-    priv->wapi_multicast_filter = req->status;
+    	unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
 
-    unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    }
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastFilterReqHandler: called when WAPI isn't enabled\n");
+#endif
 }
 
 void CsrWifiRouterCtrlWapiUnicastFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
 {
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
     CsrWifiRouterCtrlWapiUnicastFilterReq* req = (CsrWifiRouterCtrlWapiUnicastFilterReq*)msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
 
-    unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status);
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
 
-    if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) {
-        /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */
-		priv->wapi_unicast_queued_pkt_filter = 1;
-	}
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
 
-    /* status 1 - Filter ON
-     * status 0 - Filter OFF */
-    priv->wapi_unicast_filter = req->status;
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastFilterReq: req->status= %d\n", req->status);
 
-    unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
-}
+        if ((priv->wapi_unicast_filter == 1) && (req->status == 0)) {
+            /* When we have successfully re-associated and obtained a new unicast key with keyid = 0 */
+            priv->wapi_unicast_queued_pkt_filter = 1;
+        }
 
+        /* status 1 - Filter ON
+         * status 0 - Filter OFF */
+        priv->wapi_unicast_filter = req->status;
 
-void CsrWifiRouterCtrlWapiMulticastReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
-{
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
+
+    	 unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
+
+    }
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
     unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
-    CsrWifiRouterCtrlWapiMulticastReq* req =  (CsrWifiRouterCtrlWapiMulticastReq*)msg;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiUnicastFilterReqHandler: called when WAPI isn't enabled\n");
+#endif
+}
+
+void CsrWifiRouterCtrlWapiRxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
+{
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
 
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    CsrWifiRouterCtrlWapiRxPktReq* req =  (CsrWifiRouterCtrlWapiRxPktReq*)msg;
     int client_id, receiver_id;
     bulk_data_param_t bulkdata;
     CsrResult res;
     ul_client_t *client;
-
     CSR_SIGNAL signal;
     CSR_MA_PACKET_INDICATION *pkt_ind;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
 
-    unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
-    unifi_trace(priv, UDBG4, "CsrWifiRouterCtrlWapiMulticastReqHandler: \n");
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
 
-    if (priv == NULL) {
-        unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid priv\n",__FUNCTION__);
-        return;
-    }
+    	unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
 
-    if (priv->smepriv == NULL) {
-         unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler : invalid sme priv\n",__FUNCTION__);
-         return;
-    }
+        if (priv == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid priv\n",__FUNCTION__);
+            return;
+        }
 
-    if (req->dataLength == 0 || req->data == NULL) {
-         unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: invalid request\n",__FUNCTION__);
-         return;
-    }
+        if (priv->smepriv == NULL) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq : invalid sme priv\n",__FUNCTION__);
+             return;
+        }
 
-    res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength);
-    if (res != CSR_RESULT_SUCCESS) {
-        unifi_error(priv, "CsrWifiRouterCtrlWapiMulticastReqHandler: Could not allocate net data\n",__FUNCTION__);
-        return;
-    }
+        if (req->dataLength == 0 || req->data == NULL) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: invalid request\n",__FUNCTION__);
+             return;
+        }
 
-    /* This function is expected to be called only when the MIC has been verified by SME to be correct
-     * So reset the reception status to rx_success */
-    res = read_unpack_signal(req->signal, &signal);
-    if (res) {
-	    unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Received unknown or corrupted signal.\n");
-	    return;
-    }
-    pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication);
-    if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) {
-	     unifi_error(priv,"CsrWifiRouterCtrlWapiMulticastReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus);
-	     return;
-    }
-    else {
-	     unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiMulticastReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__);
-	     pkt_ind->ReceptionStatus = CSR_RX_SUCCESS;
-	     write_pack(&signal, req->signal, &(req->signalLength));
+        res = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength);
+        if (res != CSR_RESULT_SUCCESS) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiRxPktReq: Could not allocate net data\n",__FUNCTION__);
+             return;
+        }
+
+        /* This function is expected to be called only when the MIC has been verified by SME to be correct
+         * So reset the reception status to rx_success */
+        res = read_unpack_signal(req->signal, &signal);
+        if (res) {
+	          unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: Received unknown or corrupted signal.\n");
+	          return;
+        }
+        pkt_ind = (CSR_MA_PACKET_INDICATION*) (&((&signal)->u).MaPacketIndication);
+        if (pkt_ind->ReceptionStatus != CSR_MICHAEL_MIC_ERROR) {
+	          unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: Unknown signal with reception status = %d\n",pkt_ind->ReceptionStatus);
+	          return;
+        } else {
+	          unifi_trace(priv, UDBG4,"CsrWifiRouterCtrlWapiRxPktReqHandler: MIC verified , RX_SUCCESS \n",__FUNCTION__);
+	          pkt_ind->ReceptionStatus = CSR_RX_SUCCESS;
+	          write_pack(&signal, req->signal, &(req->signalLength));
+        }
+
+        memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength);
+
+        receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0;
+        client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
+
+        client = &priv->ul_clients[client_id];
+
+        if (client && client->event_hook) {
+              unifi_trace(priv, UDBG3,
+                          "CsrWifiRouterCtrlWapiRxPktReq: "
+                          "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n",
+                          client->client_id, client->sender_id, receiver_id,
+                          CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal));
+
+              client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST);
+        } else {
+              unifi_trace(priv, UDBG4, "No client to give the packet to\n");
+              unifi_net_data_free(priv, &bulkdata.d[0]);
+        }
+
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
+    	unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
     }
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiRxPktReqHandler: called when WAPI isn't enabled\n");
+#endif
+}
 
-    memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength);
+void CsrWifiRouterCtrlWapiUnicastTxPktReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
+{
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
 
-    receiver_id = CSR_GET_UINT16_FROM_LITTLE_ENDIAN((req->signal) + sizeof(CsrInt16)) & 0xFFF0;
-    client_id = (receiver_id & 0x0F00) >> UDI_SENDER_ID_SHIFT;
+	unifi_priv_t *priv = (unifi_priv_t*) drvpriv;
+    CsrWifiRouterCtrlWapiUnicastTxPktReq *req 	= (CsrWifiRouterCtrlWapiUnicastTxPktReq*) msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
+    bulk_data_param_t bulkdata;
+    CsrUint8 macHeaderLengthInBytes = MAC_HEADER_SIZE;
+    /*KeyID, Reserved, PN, MIC*/
+    CsrUint8 appendedCryptoFields = 1 + 1 + 16 + 16;
+    CsrResult result;
+    /* Retrieve the MA PACKET REQ fields from the Signal retained from send_ma_pkt_request() */
+    CSR_MA_PACKET_REQUEST *storedSignalMAPktReq = &interfacePriv->wapi_unicast_ma_pkt_sig.u.MaPacketRequest;
 
-    client = &priv->ul_clients[client_id];
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
+
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
+
+        if (priv == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid priv\n",__FUNCTION__);
+            return;
+        }
+        if (priv->smepriv == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler : invalid sme priv\n",__FUNCTION__);
+            return;
+        }
+        if (req->data == NULL) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid request\n",__FUNCTION__);
+            return;
+        } else {
+            /* If it is QoS data (type = data subtype = QoS), frame header contains QoS control field */
+            if ((req->data[0] & 0x88) == 0x88) {
+      	        macHeaderLengthInBytes  = macHeaderLengthInBytes + QOS_CONTROL_HEADER_SIZE;
+            }
+        }
+        if ( !(req->dataLength>(macHeaderLengthInBytes+appendedCryptoFields)) ) {
+            unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: invalid dataLength\n",__FUNCTION__);
+            return;
+        }
+
+	    /* Encrypted DATA Packet contained in (req->data)
+         * -------------------------------------------------------------------
+         * |MAC Header|  KeyId   | Reserved |    PN    | xxDataxx | xxMICxxx |
+         * -------------------------------------------------------------------
+         *                                             (<-----Encrypted----->)
+         * -------------------------------------------------------------------
+         * |24/26(QoS)|    1     |    1     |    16    |    x     |    16    |
+         * -------------------------------------------------------------------
+         */
+        result = unifi_net_data_malloc(priv, &bulkdata.d[0], req->dataLength);
+        if (result != CSR_RESULT_SUCCESS) {
+             unifi_error(priv, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: Could not allocate net data\n",__FUNCTION__);
+             return;
+        }
+        memcpy((void*)bulkdata.d[0].os_data_ptr, req->data, req->dataLength);
+        bulkdata.d[0].data_length = req->dataLength;
+        bulkdata.d[1].os_data_ptr = NULL;
+        bulkdata.d[1].data_length = 0;
+
+        /* Send UniFi msg */
+        /* Here hostTag is been sent as 0xffffffff, its been appended properly while framing MA-Packet request in pdu_processing.c file */
+        result = uf_process_ma_packet_req(priv,
+    	                                  storedSignalMAPktReq->Ra.x,
+                                          storedSignalMAPktReq->HostTag,/* Ask for a new HostTag */
+                                          req->interfaceTag,
+                                          storedSignalMAPktReq->TransmissionControl,
+                                          storedSignalMAPktReq->TransmitRate,
+                                          storedSignalMAPktReq->Priority, /* Retained value */
+                                          interfacePriv->wapi_unicast_ma_pkt_sig.SignalPrimitiveHeader.SenderProcessId, /*FIXME AP: VALIDATE ???*/
+                                          &bulkdata);
+
+        if (result == NETDEV_TX_OK) {
+             (priv->netdev[req->interfaceTag])->trans_start = jiffies;
+             /* Should really count tx stats in the UNITDATA.status signal but
+              * that doesn't have the length.
+              */
+             interfacePriv->stats.tx_packets++;
+
+             /* count only the packet payload */
+             interfacePriv->stats.tx_bytes += req->dataLength - macHeaderLengthInBytes - appendedCryptoFields;
+             unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Sent), sent count = %x\n", interfacePriv->stats.tx_packets);
+        } else {
+             /* Failed to send: fh queue was full, and the skb was discarded*/
+             unifi_trace(priv, UDBG1, "(HIP validation failure) Result = %d\n", result);
+             unifi_net_data_free(priv, &bulkdata.d[0]);
+
+             interfacePriv->stats.tx_dropped++;
+             unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: (Packet Drop), dropped count = %x\n", interfacePriv->stats.tx_dropped);
+        }
 
-    if (client && client->event_hook) {
-         unifi_trace(priv, UDBG3,
-                     "CsrWifiRouterCtrlWapiMulticastReqHandler: "
-                     "Sending signal to client %d, (s:0x%X, r:0x%X) - Signal 0x%X \n",
-                     client->client_id, client->sender_id, receiver_id,
-                     CSR_GET_UINT16_FROM_LITTLE_ENDIAN(req->signal));
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+
+    } else {
+
+    	unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
 
-         client->event_hook(client, req->signal, req->signalLength, &bulkdata, UDI_TO_HOST);
     }
-    else {
-         unifi_trace(priv, UDBG4, "No client to give the packet to\n");
-         unifi_net_data_free(priv, &bulkdata.d[0]);
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiUnicastTxPktReqHandler: called when WAPI SW ENCRYPTION isn't enabled\n");
+#endif
+}
+
+void CsrWifiRouterCtrlWapiFilterReqHandler(void* drvpriv, CsrWifiFsmEvent* msg)
+{
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    CsrWifiRouterCtrlWapiFilterReq* req = (CsrWifiRouterCtrlWapiFilterReq*)msg;
+    netInterface_priv_t *interfacePriv = priv->interfacePriv[req->interfaceTag];
+
+    if (CSR_WIFI_ROUTER_CTRL_MODE_STA == interfacePriv->interfaceMode) {
+
+        unifi_trace(priv, UDBG6, ">>%s\n", __FUNCTION__);
+
+        unifi_trace(priv, UDBG1, "CsrWifiRouterCtrlWapiFilterReq: req->isWapiConnected [0/1] = %d \n",req->isWapiConnected);
+
+        priv->isWapiConnection = req->isWapiConnected;
+
+        unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+    } else {
+
+    	unifi_warning(priv, "%s is NOT applicable for interface mode - %d\n", __FUNCTION__,interfacePriv->interfaceMode);
+
     }
+#endif
 
-    unifi_trace(priv, UDBG6, "<<%s\n", __FUNCTION__);
+#elif defined(UNIFI_DEBUG)
+    /*WAPI Disabled*/
+    unifi_priv_t *priv = (unifi_priv_t*)drvpriv;
+    unifi_error(priv,"CsrWifiRouterCtrlWapiFilterReq: called when WAPI isn't enabled\n");
+#endif
 }

+ 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->genericMulticastOrBroadCastMgtFrames);
         INIT_LIST_HEAD(&interfacePriv->genericMulticastOrBroadCastFrames);
-        INIT_LIST_HEAD(&interfacePriv->directedMaPktReq);
 
         for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {
             interfacePriv->staInfo[j] = NULL;
@@ -139,7 +138,7 @@ uf_sme_deinit(unifi_priv_t *priv)
 
     /* Remove all the Peer database, before going down */
     for (i = 0; i < CSR_WIFI_NUM_INTERFACES; i++) {
-        spin_lock(&priv->ba_lock);
+        down(&priv->ba_mutex);
         for(ba_session_idx=0; ba_session_idx < MAX_SUPPORTED_BA_SESSIONS_RX; ba_session_idx++){
             ba_session_rx = priv->interfacePriv[i]->ba_session_rx[ba_session_idx];
             if(ba_session_rx) {
@@ -161,7 +160,7 @@ uf_sme_deinit(unifi_priv_t *priv)
             }
         }
 
-        spin_unlock(&priv->ba_lock);
+        up(&priv->ba_mutex);
         interfacePriv = priv->interfacePriv[i];
         if(interfacePriv){
             for(j = 0; j < UNIFI_MAX_CONNECTIONS; j++) {

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

@@ -29,8 +29,10 @@
         }                                                   \
     } while (0)
 
-/* Workaround for the wpa_supplicant hanging issue */
+/* Workaround for the wpa_supplicant hanging issue - disabled on Android */
+#ifndef ANDROID_BUILD
 #define CSR_WIFI_WEXT_HANG_WORKAROUND
+#endif
 
 #ifdef CSR_WIFI_WEXT_HANG_WORKAROUND
 # define UF_RTNL_LOCK()    rtnl_lock()

+ 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) */
         CsrWifiRouterCtrlWifiOffIndSend(priv->CSR_WIFI_SME_IFACEQUEUE,0, (CsrWifiRouterCtrlControlIndication)(*conf_param));
     }
-
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+    unifi_debug_buf_dump();
+#endif
 #else
     bulk_data_param_t bulkdata;
 
@@ -420,10 +422,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
     CsrResult csrResult;
     unsigned long lock_flags;
     int r;
-#ifdef CSR_SUPPORT_SME
-    netInterface_priv_t *interfacePriv = priv->interfacePriv[0];
-    CsrUint32 alignOffset = 0;
-#endif
 
 
     csrResult = write_pack(sigptr, sigbuf, &packed_siglen);
@@ -431,12 +429,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
         unifi_error(priv, "Malformed HIP signal in ul_send_signal_unpacked()\n");
         return CsrHipResultToStatus(csrResult);
     }
-#ifdef CSR_SUPPORT_SME
-    if (bulkdata != NULL){
-        alignOffset = (CsrUint32)(long)(bulkdata->d[0].os_data_ptr) & (CSR_WIFI_ALIGN_BYTES-1);
-
-    }
-#endif
     r = _align_bulk_data_buffers(priv, sigbuf, (bulk_data_param_t*)bulkdata);
     if (r) {
         return r;
@@ -449,17 +441,6 @@ ul_send_signal_unpacked(unifi_priv_t *priv, CSR_SIGNAL *sigptr,
         spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags);
         return CsrHipResultToStatus(csrResult);
     }
-#ifdef CSR_SUPPORT_SME
-    if (sigptr->SignalPrimitiveHeader.SignalId == CSR_MA_PACKET_REQUEST_ID) {
-        if(interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_AP ||
-           interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO) {
-
-            uf_store_directed_ma_packet_referenece(priv, bulkdata, sigptr,alignOffset);
-
-        }
-    }
-#endif
-
     spin_unlock_irqrestore(&priv->send_signal_lock, lock_flags);
 
     return 0;

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

+ 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);
 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
 
+void unifi_error(void* ospriv, const char *fmt, ...);
+void unifi_warning(void* ospriv, const char *fmt, ...);
+void unifi_notice(void* ospriv, const char *fmt, ...);
+void unifi_info(void* ospriv, const char *fmt, ...);
+
+void unifi_trace(void* ospriv, int level, const char *fmt, ...);
+
 #else
 
 /* Stubs */
@@ -113,15 +120,16 @@ static inline void dump16(void *mem, CsrUint16 len) {}
 static inline void dump_str(void *mem, CsrUint16 len) {}
 #endif /* CSR_WIFI_HIP_DEBUG_OFFLINE */
 
-#endif /* UNIFI_DEBUG */
+void unifi_error_nop(void* ospriv, const char *fmt, ...);
+void unifi_trace_nop(void* ospriv, int level, const char *fmt, ...);
+#define unifi_error if(1);else unifi_error_nop
+#define unifi_warning if(1);else unifi_error_nop
+#define unifi_notice if(1);else unifi_error_nop
+#define unifi_info if(1);else unifi_error_nop
+#define unifi_trace if(1);else unifi_trace_nop
 
+#endif /* UNIFI_DEBUG */
 
-void unifi_error(void* ospriv, const char *fmt, ...);
-void unifi_warning(void* ospriv, const char *fmt, ...);
-void unifi_notice(void* ospriv, const char *fmt, ...);
-void unifi_info(void* ospriv, const char *fmt, ...);
-
-void unifi_trace(void* ospriv, int level, const char *fmt, ...);
 
 /* Different levels of diagnostic detail... */
 #define UDBG0       0   /* always prints in debug build */

File diff suppressed because it is too large
+ 421 - 339
drivers/staging/csr/unifi_pdu_processing.c


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

@@ -44,6 +44,10 @@
 
 #include <linux/fs.h>
 
+#ifdef ANDROID_BUILD
+#include <linux/wakelock.h>
+#endif
+
 #include "csr_wifi_hip_unifi.h"
 #include "csr_wifi_hip_unifi_udi.h"
 #include "csr_wifi_router_lib.h"
@@ -63,6 +67,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #include "unifi_wext.h"
 #endif
 
+#ifdef ANDROID_BUILD
+extern struct wake_lock unifi_sdio_wake_lock;
+#endif
+
 #include "unifi_clients.h"
 
 
@@ -98,18 +106,14 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #include "unifi_sme.h"
 #endif
 
-#undef  COMPARE_HOST_TAG_TO_ENQUEUE
-#define COMPARE_HOST_TAG_TO_ENQUEUE(tx_q_item_hosttag,maPktHostTag)        \
-      if(tx_q_item_hosttag > maPktHostTag){                                \
-        locationFound = TRUE;                                              \
-        ii++;                                                              \
-        break;                                                             \
-    }                                                                      \
-    ii++;                                                                  \
-
-
 /* The device major number to use when registering the udi driver */
 #define UNIFI_NAME      "unifi"
+/*
+ * MAX_UNIFI_DEVS defines the maximum number of UniFi devices that can be present.
+ * This number should be set to the number of SDIO slots supported by the SDIO
+ * host controller on the platform.
+ * Note: If MAX_UNIFI_DEVS value changes, fw_init[] needs to be corrected in drv.c
+ */
 #define MAX_UNIFI_DEVS  2
 
 /* 802.11 Mac header offsets */
@@ -156,6 +160,10 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #define IEEE802_11_QC_TID_MASK 0x0f
 #define IEEE802_11_QC_A_MSDU_PRESENT 0x80
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND))
+#define IEEE802_11_QC_NON_TID_BITS_MASK 0xFFF0
+#endif
+
 #define CSR_WIFI_EAPOL_M4_HOST_TAG 0x50000000
 #define IEEE802_11_DATA_FRAME_MAC_HEADER_SIZE 36
 #define MAX_ACCESS_CATOGORY 4
@@ -185,6 +193,9 @@ typedef struct CsrWifiSmeApConfig CsrWifiSmeApConfig_t;
 #define     STA_INACTIVE_DETECTION_TIMER_INTERVAL              30               /* in seconds */
 #define     STA_INACTIVE_TIMEOUT_VAL                           120*1000*1000    /* 120 seconds */
 
+/* Test for modes requiring AP firmware patch */
+#define CSR_WIFI_HIP_IS_AP_FW(mode) ((((mode) == CSR_WIFI_ROUTER_CTRL_MODE_AP) || \
+                                      ((mode) == CSR_WIFI_ROUTER_CTRL_MODE_P2PGO)) ? TRUE : FALSE)
 
 /* Defines used in beacon filtering in case of P2P */
 #define CSR_WIFI_P2P_WILDCARD_SSID_LENGTH        0x7
@@ -220,6 +231,9 @@ extern int sdio_block_size;
 extern int coredump_max;
 extern int run_bh_once;
 extern int bh_priority;
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+extern int log_hip_signals;
+#endif
 
 struct dlpriv {
     const unsigned char *dl_data;
@@ -331,7 +345,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
     CsrTime lastActivity;
 
     /* during m/c transmission sp suspended */
-    CsrBool uapsdSuspended;
+    CsrBool uspSuspend;
+    CSR_PRIORITY triggerFramePriority;
 #endif
     CsrWifiRouterCtrlPeerStatus currentPeerState;
     struct list_head dataPdu[MAX_ACCESS_CATOGORY];
@@ -349,6 +364,8 @@ typedef struct CsrWifiRouterCtrlStaInfo_t {
 #define CSR_WIFI_TIM_RESETTING   2
 #define CSR_WIFI_TIM_SETTING     3
 
+    CsrBool timRequestPendingFlag;
+    CsrUint8 updateTimReqQueued;
     CsrUint16 noOfPktQueued;
 }CsrWifiRouterCtrlStaInfo_t;
 
@@ -609,8 +626,14 @@ struct unifi_priv {
 
     /* Spinlock to protect M4 data */
     spinlock_t m4_lock;
-    /* Spinlock to protect BA RX data */
-    spinlock_t ba_lock;
+    /* Mutex to protect BA RX data */
+    struct semaphore ba_mutex;
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Spinlock to protect the WAPI data */
+    spinlock_t wapi_lock;
+#endif
+
 #ifndef ALLOW_Q_PAUSE
     /* Array to indicate if a particular Tx queue is paused, this may not be
      * required in a multiqueue implementation since we can directly stop kernel
@@ -630,10 +653,24 @@ struct unifi_priv {
     CsrUint32 rxUdpThroughput;
     CsrUint32 txUdpThroughput;
 
-
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+    /*Set if multicast KeyID = 1*/
     CsrUint8 wapi_multicast_filter;
+    /*Set if unicast KeyID = 1*/
     CsrUint8 wapi_unicast_filter;
     CsrUint8 wapi_unicast_queued_pkt_filter;
+#ifdef CSR_WIFI_SECURITY_WAPI_QOSCTRL_MIC_WORKAROUND
+    CsrBool  isWapiConnection;
+#endif
+#endif
+
+#ifdef CSR_WIFI_SPLIT_PATCH
+    CsrWifiRouterCtrlModeSetReq pending_mode_set;
+#endif
+
+    CsrBool cmanrTestMode;
+    CSR_RATE cmanrTestModeTransmitRate;
+
 };
 
 typedef struct {
@@ -682,6 +719,9 @@ typedef struct netInterface_priv
     CsrUint8 ba_complete_index;
     CsrUint8 queueEnabled[UNIFI_NO_OF_TX_QS];
     struct work_struct send_m4_ready_task;
+#ifdef CSR_WIFI_SECURITY_WAPI_ENABLE
+    struct work_struct send_pkt_to_encrypt;
+#endif
     struct net_device_stats stats;
     CsrUint8 interfaceMode;
     CsrBool protect;
@@ -721,7 +761,6 @@ typedef struct netInterface_priv
     struct list_head genericMgtFrames;
     struct list_head genericMulticastOrBroadCastFrames;
     struct list_head genericMulticastOrBroadCastMgtFrames;
-    struct list_head directedMaPktReq;
 
     /* Timer for detecting station inactivity */
     struct timer_list sta_activity_check_timer;
@@ -740,6 +779,13 @@ typedef struct netInterface_priv
     /* Buffered M4 signal to take care of WPA race condition */
     CSR_SIGNAL m4_signal;
     bulk_data_desc_t m4_bulk_data;
+
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+    /* Buffered WAPI Unicast MA Packet Request for encryption in Sme */
+    CSR_SIGNAL wapi_unicast_ma_pkt_sig;
+    bulk_data_desc_t wapi_unicast_bulk_data;
+#endif
+
     /* This should be removed and m4_hostTag should be used for checking*/
     CsrBool m4_sent;
     CSR_CLIENT_TAG m4_hostTag;
@@ -747,17 +793,11 @@ typedef struct netInterface_priv
     CsrBool intraBssEnabled;
     CsrUint32 multicastPduHostTag; /* Used to set the tim after getting
        a confirm for it */
+    CsrBool bcTimSet;
+    CsrBool bcTimSetReqPendingFlag;
+    CsrBool bcTimSetReqQueued;
 } netInterface_priv_t;
 
-typedef struct maPktReqList{
-    struct list_head q;
-    struct sk_buff *skb;
-    CSR_SIGNAL signal;
-    CSR_CLIENT_TAG hostTag;
-    CsrUint32 staHandler;
-    unsigned long jiffeTime;
-}maPktReqList_t;
-
 #ifndef ALLOW_Q_PAUSE
 #define net_is_tx_q_paused(priv, q)   (priv->tx_q_paused_flag[q])
 #define net_tx_q_unpause(priv, q)   (priv->tx_q_paused_flag[q] = 0)
@@ -925,7 +965,6 @@ int uf_ap_process_data_pdu(unifi_priv_t *priv, struct sk_buff *skb,
                    bulk_data_param_t *bulkdata,
                    CsrUint8 macHeaderLengthInBytes);
 CsrBool uf_is_more_data_for_non_delivery_ac(CsrWifiRouterCtrlStaInfo_t *staRecord);
-CsrBool uf_is_more_data_for_delivery_ac(unifi_priv_t *priv,CsrWifiRouterCtrlStaInfo_t *staRecord,CsrBool mgtCheck);
 void uf_process_wmm_deliver_ac_uapsd (  unifi_priv_t * priv,
                                         CsrWifiRouterCtrlStaInfo_t * srcStaInfo,
                                         CsrUint16 qosControl,
@@ -937,7 +976,6 @@ void uf_send_buffered_data_from_delivery_ac(unifi_priv_t *priv, CsrWifiRouterCtr
 void uf_continue_uapsd(unifi_priv_t *priv, CsrWifiRouterCtrlStaInfo_t * staInfo);
 void uf_send_qos_null(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo);
 void uf_send_nulldata(unifi_priv_t * priv,CsrUint16 interfaceTag, const CsrUint8 *da,CSR_PRIORITY priority,CsrWifiRouterCtrlStaInfo_t * srcStaInfo);
-void uf_store_directed_ma_packet_referenece(unifi_priv_t *priv, bulk_data_param_t *bulkdata,CSR_SIGNAL *sigptr,CsrUint32 alignOffset);
 
 
 
@@ -956,7 +994,6 @@ void send_auto_ma_packet_confirm(unifi_priv_t *priv,
                                  netInterface_priv_t *interfacePriv,
                                  struct list_head *buffered_frames_list);
 void uf_flush_list(unifi_priv_t * priv, struct list_head * list);
-void uf_flush_maPktlist(unifi_priv_t * priv, struct list_head * list);
 tx_buffered_packets_t *dequeue_tx_data_pdu(unifi_priv_t *priv, struct list_head *txList);
 void resume_unicast_buffered_frames(unifi_priv_t *priv, CsrUint16 interfaceTag);
 void update_eosp_to_head_of_broadcast_list_head(unifi_priv_t *priv,CsrUint16 interfaceTag);
@@ -1073,6 +1110,11 @@ void uf_process_rx_pending_queue(unifi_priv_t *priv, int queue,
                                  CsrWifiMacAddress source_address,
                                  int indicate, CsrUint16 interfaceTag);
 
+#ifdef CSR_WIFI_HIP_DEBUG_OFFLINE
+int uf_register_hip_offline_debug(unifi_priv_t *priv);
+int uf_unregister_hip_offline_debug(unifi_priv_t *priv);
+#endif
+
 /*
  *      inet.c
  */

+ 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;
     int rc;
+    int wol;
 
     if (get_user(cfg_power, (unifi_cfg_power_t*)(((unifi_cfg_command_t*)arg) + 1))) {
         unifi_error(priv, "UNIFI_CFG: Failed to get the argument\n");
@@ -455,16 +456,24 @@ int unifi_cfg_power(unifi_priv_t *priv, unsigned char *arg)
 
     switch (cfg_power) {
         case UNIFI_CFG_POWER_OFF:
+            priv->wol_suspend = (enable_wol == UNIFI_WOL_OFF) ? FALSE : TRUE;
             rc = sme_sys_suspend(priv);
             if (rc) {
                 return rc;
             }
             break;
         case UNIFI_CFG_POWER_ON:
+            wol = priv->wol_suspend;
             rc = sme_sys_resume(priv);
             if (rc) {
                 return rc;
             }
+            if (wol) {
+                /* Kick the BH to ensure pending transfers are handled when
+                 * a suspend happened with card powered.
+                 */
+                unifi_send_signal(priv->card, NULL, 0, NULL);
+            }
             break;
         default:
             unifi_error(priv, "WIFI POWER: Unknown value.\n");
@@ -921,10 +930,19 @@ int
         supportedRates[i++]=0x8b;
         supportedRates[i++]=0x96;
     } else if(n) {
+        /* For some strange reasons WiFi stack needs both b and g rates*/
         supportedRates[i++]=0x02;
         supportedRates[i++]=0x04;
         supportedRates[i++]=0x0b;
         supportedRates[i++]=0x16;
+        supportedRates[i++]=0x0c;
+        supportedRates[i++]=0x12;
+        supportedRates[i++]=0x18;
+	supportedRates[i++]=0x24;
+        supportedRates[i++]=0x30;
+        supportedRates[i++]=0x48;
+        supportedRates[i++]=0x60;
+        supportedRates[i++]=0x6c;
     }
     if(g) {
         if(!b) {
@@ -1162,3 +1180,65 @@ uf_send_m4_ready_wq(struct work_struct *work)
 
 } /* uf_send_m4_ready_wq() */
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+/*
+ * ---------------------------------------------------------------------------
+ *  uf_send_pkt_to_encrypt
+ *
+ *      Deferred work queue function to send the WAPI data pkts to SME when unicast KeyId = 1
+ *      These are done in a deferred work queue for two reasons:
+ *       - the CsrWifiRouterCtrl...Send() functions are not safe for atomic context
+ *       - we want to load the main driver data path as lightly as possible
+ *
+ *  Arguments:
+ *      work    Pointer to work queue item.
+ *
+ *  Returns:
+ *      None.
+ * ---------------------------------------------------------------------------
+ */
+void uf_send_pkt_to_encrypt(struct work_struct *work)
+{
+    netInterface_priv_t *interfacePriv = container_of(work, netInterface_priv_t, send_pkt_to_encrypt);
+    CsrUint16 interfaceTag = interfacePriv->InterfaceTag;
+    unifi_priv_t *priv = interfacePriv->privPtr;
+
+    CsrUint32 pktBulkDataLength;
+    CsrUint8 *pktBulkData;
+    unsigned long flags;
+
+    if (interfacePriv->interfaceMode == CSR_WIFI_ROUTER_CTRL_MODE_STA) {
+
+        func_enter();
+
+        pktBulkDataLength = interfacePriv->wapi_unicast_bulk_data.data_length;
+
+        if (pktBulkDataLength > 0) {
+		    pktBulkData = (CsrUint8 *)CsrPmemAlloc(pktBulkDataLength);
+		    CsrMemSet(pktBulkData, 0, pktBulkDataLength);
+	    } else {
+		    unifi_error(priv, "uf_send_pkt_to_encrypt() : invalid buffer\n");
+		    return;
+	    }
+
+        spin_lock_irqsave(&priv->wapi_lock, flags);
+        /* Copy over the MA PKT REQ bulk data */
+        CsrMemCpy(pktBulkData, (CsrUint8*)interfacePriv->wapi_unicast_bulk_data.os_data_ptr, pktBulkDataLength);
+        /* Free any bulk data buffers allocated for the WAPI Data pkt */
+        unifi_net_data_free(priv, &interfacePriv->wapi_unicast_bulk_data);
+        interfacePriv->wapi_unicast_bulk_data.net_buf_length = 0;
+        interfacePriv->wapi_unicast_bulk_data.data_length = 0;
+        interfacePriv->wapi_unicast_bulk_data.os_data_ptr = interfacePriv->wapi_unicast_bulk_data.os_net_buf_ptr = NULL;
+        spin_unlock_irqrestore(&priv->wapi_lock, flags);
+
+        CsrWifiRouterCtrlWapiUnicastTxEncryptIndSend(priv->CSR_WIFI_SME_IFACEQUEUE, 0, interfaceTag, pktBulkDataLength, pktBulkData);
+        unifi_trace(priv, UDBG1, "WapiUnicastTxEncryptInd sent to SME\n");
+
+        CsrPmemFree(pktBulkData); /* Would have been copied over by the SME Handler */
+
+        func_exit();
+    } else {
+	    unifi_warning(priv, "uf_send_pkt_to_encrypt() is NOT applicable for interface mode - %d\n",interfacePriv->interfaceMode);
+    }
+}/* uf_send_pkt_to_encrypt() */
+#endif

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

@@ -50,6 +50,7 @@ enum sme_request_status {
     SME_REQUEST_PENDING,
     SME_REQUEST_RECEIVED,
     SME_REQUEST_TIMEDOUT,
+    SME_REQUEST_CANCELLED,
 };
 
 /* Structure to hold a UDI logged signal */
@@ -123,6 +124,7 @@ void uf_ta_wq(struct work_struct *work);
 #endif
 
 void uf_sme_complete_request(unifi_priv_t *priv, CsrResult reply_status, const char *func);
+void uf_sme_cancel_request(unifi_priv_t *priv, CsrResult reply_status);
 
 
 /*
@@ -148,6 +150,13 @@ void uf_sme_config_wq(struct work_struct *work);
  */
 void uf_send_m4_ready_wq(struct work_struct *work);
 
+#if (defined(CSR_WIFI_SECURITY_WAPI_ENABLE) && defined(CSR_WIFI_SECURITY_WAPI_SW_ENCRYPTION))
+/*
+ * To send data pkt to Sme for encryption
+ */
+void uf_send_pkt_to_encrypt(struct work_struct *work);
+#endif
+
 int sme_mgt_power_config_set(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig);
 int sme_mgt_power_config_get(unifi_priv_t *priv, CsrWifiSmePowerConfig *powerConfig);
 int sme_mgt_host_config_set(unifi_priv_t *priv, CsrWifiSmeHostConfig *hostConfig);

+ 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 {

Some files were not shown because too many files changed in this diff