[PATCH v2 0/4][Xenial SRU] UBUNTU: SAUCE: Support latest Redpine WLAN/BT RS9113 driver

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 0/4][Xenial SRU] UBUNTU: SAUCE: Support latest Redpine WLAN/BT RS9113 driver

Shrirang Bagul
BugLink: http://bugs.launchpad.net/bugs/1657682

This work is based on xenial/master-next (tag: Ubuntu-4.4.0-61.82)

Dell Caracalla IoT gateways have Redpine RS9113 WLAN/BT card. To enable
this device, the vendor has provided the latest version of the driver.
However, there is an existing driver in upstream kernel, which does create
some confict esp. w.r.t exporting common symbols.

This patch-set adds the vendor's version of the driver to Ubuntu supplied
3rd party drivers list and also fixes the conflicts with the upstream version.

Darren Wu (1):
  UBUNTU: SAUCE: Redpine RS9113 WLAN/BT driver ver. 0.9.7

Shrirang Bagul (3):
  UBUNTU: SAUCE: Support Redpine RS9113 WLAN/BT
  UBUNTU: SAUCE: Separate Redpine RS9113 WLAN/BT vendor and kernel
    drivers
  UBUNTU: SAUCE: RS9113: Use vendor driver to support WLAN/BT card on
    Caracalla HW only

 ubuntu/Kconfig                |    1 +
 ubuntu/Makefile               |    3 +
 ubuntu/rsi/Kconfig            |   54 +
 ubuntu/rsi/Makefile           |   17 +
 ubuntu/rsi/rsi_91x_coex.c     |  178 +++
 ubuntu/rsi/rsi_91x_core.c     |  515 +++++++++
 ubuntu/rsi/rsi_91x_debugfs.c  |  531 +++++++++
 ubuntu/rsi/rsi_91x_hal.c      | 1354 ++++++++++++++++++++++
 ubuntu/rsi/rsi_91x_hci.c      |  556 ++++++++++
 ubuntu/rsi/rsi_91x_mac80211.c | 1883 +++++++++++++++++++++++++++++++
 ubuntu/rsi/rsi_91x_main.c     |  383 +++++++
 ubuntu/rsi/rsi_91x_mgmt.c     | 2469 +++++++++++++++++++++++++++++++++++++++++
 ubuntu/rsi/rsi_91x_ps.c       |  202 ++++
 ubuntu/rsi/rsi_91x_sdio.c     | 1281 +++++++++++++++++++++
 ubuntu/rsi/rsi_91x_sdio_ops.c |  451 ++++++++
 ubuntu/rsi/rsi_91x_usb.c      |  920 +++++++++++++++
 ubuntu/rsi/rsi_91x_usb_ops.c  |   71 ++
 ubuntu/rsi/rsi_boot_params.h  |  170 +++
 ubuntu/rsi/rsi_coex.h         |   53 +
 ubuntu/rsi/rsi_common.h       |   93 ++
 ubuntu/rsi/rsi_debugfs.h      |   48 +
 ubuntu/rsi/rsi_hal.h          |  155 +++
 ubuntu/rsi/rsi_hci.h          |  103 ++
 ubuntu/rsi/rsi_main.h         |  398 +++++++
 ubuntu/rsi/rsi_mgmt.h         |  564 ++++++++++
 ubuntu/rsi/rsi_ps.h           |   61 +
 ubuntu/rsi/rsi_sdio.h         |  154 +++
 ubuntu/rsi/rsi_usb.h          |   94 ++
 28 files changed, 12762 insertions(+)
 create mode 100644 ubuntu/rsi/Kconfig
 create mode 100644 ubuntu/rsi/Makefile
 create mode 100644 ubuntu/rsi/rsi_91x_coex.c
 create mode 100644 ubuntu/rsi/rsi_91x_core.c
 create mode 100644 ubuntu/rsi/rsi_91x_debugfs.c
 create mode 100644 ubuntu/rsi/rsi_91x_hal.c
 create mode 100644 ubuntu/rsi/rsi_91x_hci.c
 create mode 100644 ubuntu/rsi/rsi_91x_mac80211.c
 create mode 100644 ubuntu/rsi/rsi_91x_main.c
 create mode 100644 ubuntu/rsi/rsi_91x_mgmt.c
 create mode 100644 ubuntu/rsi/rsi_91x_ps.c
 create mode 100644 ubuntu/rsi/rsi_91x_sdio.c
 create mode 100644 ubuntu/rsi/rsi_91x_sdio_ops.c
 create mode 100644 ubuntu/rsi/rsi_91x_usb.c
 create mode 100644 ubuntu/rsi/rsi_91x_usb_ops.c
 create mode 100644 ubuntu/rsi/rsi_boot_params.h
 create mode 100644 ubuntu/rsi/rsi_coex.h
 create mode 100644 ubuntu/rsi/rsi_common.h
 create mode 100644 ubuntu/rsi/rsi_debugfs.h
 create mode 100644 ubuntu/rsi/rsi_hal.h
 create mode 100644 ubuntu/rsi/rsi_hci.h
 create mode 100644 ubuntu/rsi/rsi_main.h
 create mode 100644 ubuntu/rsi/rsi_mgmt.h
 create mode 100644 ubuntu/rsi/rsi_ps.h
 create mode 100644 ubuntu/rsi/rsi_sdio.h
 create mode 100644 ubuntu/rsi/rsi_usb.h

--
2.9.3


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 1/4][Xenial SRU] UBUNTU: SAUCE: Support Redpine RS9113 WLAN/BT

Shrirang Bagul
BugLink: http://bugs.launchpad.net/bugs/1657682

This patch adds support for RS9113 WLAN-BT cards found on Dell Caracalla
IoT gateways.
Vendor release: RS9113.NB0.NL.GNU.LNX.0.9.3 on 12/01/2016

Signed-off-by: Shrirang Bagul <[hidden email]>
---
 ubuntu/Kconfig                |    1 +
 ubuntu/Makefile               |    3 +
 ubuntu/rsi/Kconfig            |   54 +
 ubuntu/rsi/Makefile           |   15 +
 ubuntu/rsi/rsi_91x_coex.c     |  173 ++++
 ubuntu/rsi/rsi_91x_core.c     |  401 ++++++++
 ubuntu/rsi/rsi_91x_debugfs.c  |  502 +++++++++
 ubuntu/rsi/rsi_91x_hal.c      | 1119 ++++++++++++++++++++
 ubuntu/rsi/rsi_91x_hci.c      |  532 ++++++++++
 ubuntu/rsi/rsi_91x_mac80211.c | 1600 ++++++++++++++++++++++++++++
 ubuntu/rsi/rsi_91x_main.c     |  360 +++++++
 ubuntu/rsi/rsi_91x_mgmt.c     | 2288 +++++++++++++++++++++++++++++++++++++++++
 ubuntu/rsi/rsi_91x_ps.c       |  202 ++++
 ubuntu/rsi/rsi_91x_sdio.c     | 1170 +++++++++++++++++++++
 ubuntu/rsi/rsi_91x_sdio_ops.c |  423 ++++++++
 ubuntu/rsi/rsi_91x_usb.c      |  920 +++++++++++++++++
 ubuntu/rsi/rsi_91x_usb_ops.c  |   71 ++
 ubuntu/rsi/rsi_boot_params.h  |  170 +++
 ubuntu/rsi/rsi_coex.h         |   52 +
 ubuntu/rsi/rsi_common.h       |   91 ++
 ubuntu/rsi/rsi_debugfs.h      |   48 +
 ubuntu/rsi/rsi_hal.h          |  152 +++
 ubuntu/rsi/rsi_hci.h          |  105 ++
 ubuntu/rsi/rsi_main.h         |  371 +++++++
 ubuntu/rsi/rsi_mgmt.h         |  517 ++++++++++
 ubuntu/rsi/rsi_ps.h           |   61 ++
 ubuntu/rsi/rsi_sdio.h         |  152 +++
 ubuntu/rsi/rsi_usb.h          |   94 ++
 28 files changed, 11647 insertions(+)
 create mode 100644 ubuntu/rsi/Kconfig
 create mode 100644 ubuntu/rsi/Makefile
 create mode 100644 ubuntu/rsi/rsi_91x_coex.c
 create mode 100644 ubuntu/rsi/rsi_91x_core.c
 create mode 100644 ubuntu/rsi/rsi_91x_debugfs.c
 create mode 100644 ubuntu/rsi/rsi_91x_hal.c
 create mode 100644 ubuntu/rsi/rsi_91x_hci.c
 create mode 100644 ubuntu/rsi/rsi_91x_mac80211.c
 create mode 100644 ubuntu/rsi/rsi_91x_main.c
 create mode 100644 ubuntu/rsi/rsi_91x_mgmt.c
 create mode 100644 ubuntu/rsi/rsi_91x_ps.c
 create mode 100644 ubuntu/rsi/rsi_91x_sdio.c
 create mode 100644 ubuntu/rsi/rsi_91x_sdio_ops.c
 create mode 100644 ubuntu/rsi/rsi_91x_usb.c
 create mode 100644 ubuntu/rsi/rsi_91x_usb_ops.c
 create mode 100644 ubuntu/rsi/rsi_boot_params.h
 create mode 100644 ubuntu/rsi/rsi_coex.h
 create mode 100644 ubuntu/rsi/rsi_common.h
 create mode 100644 ubuntu/rsi/rsi_debugfs.h
 create mode 100644 ubuntu/rsi/rsi_hal.h
 create mode 100644 ubuntu/rsi/rsi_hci.h
 create mode 100644 ubuntu/rsi/rsi_main.h
 create mode 100644 ubuntu/rsi/rsi_mgmt.h
 create mode 100644 ubuntu/rsi/rsi_ps.h
 create mode 100644 ubuntu/rsi/rsi_sdio.h
 create mode 100644 ubuntu/rsi/rsi_usb.h

diff --git a/ubuntu/Kconfig b/ubuntu/Kconfig
index 3ec5899..5aefae2 100644
--- a/ubuntu/Kconfig
+++ b/ubuntu/Kconfig
@@ -22,6 +22,7 @@ source "ubuntu/hio/Kconfig"
 ##
 ##
 ##
+source "ubuntu/rsi/Kconfig"
 ##
 ##
 ##
diff --git a/ubuntu/Makefile b/ubuntu/Makefile
index 1f3d6fb..95cef1b 100644
--- a/ubuntu/Makefile
+++ b/ubuntu/Makefile
@@ -36,6 +36,9 @@ endif
 ##
 ##
 ##
+obj-$(CONFIG_WLAN_VENDOR_RSI) += rsi/
+##
+##
 ##
 ##
 ##
diff --git a/ubuntu/rsi/Kconfig b/ubuntu/rsi/Kconfig
new file mode 100644
index 0000000..64798a9
--- /dev/null
+++ b/ubuntu/rsi/Kconfig
@@ -0,0 +1,54 @@
+config WLAN_VENDOR_RSI
+ bool "Redpine Signals Inc devices"
+ depends on X86 || X86_64
+ default y
+ ---help---
+  If you have a wireless card belonging to this class, say Y.
+
+  Note that the answer to this question doesn't directly affect the
+  kernel: saying N will just cause the configurator to skip all
+  the questions about  cards. If you say Y, you will be asked for
+  your specific card in the following questions.
+
+if WLAN_VENDOR_RSI
+
+config RSI_91X
+ tristate "Redpine Signals Inc 91x WLAN driver support"
+ depends on MAC80211
+ ---help---
+  This option enabes support for RSI 1x1 devices.
+  Select M (recommended), if you have a RSI 1x1 wireless module.
+
+config RSI_DEBUGFS
+ bool "Redpine Signals Inc debug support"
+ depends on RSI_91X
+ default y
+ ---help---
+ Say Y, if you would like to enable debug support. This option
+ creates debugfs entries
+
+config RSI_SDIO
+ tristate "Redpine Signals SDIO bus support"
+ depends on MMC && RSI_91X
+ default m
+ ---help---
+  This option enables the SDIO bus support in rsi drivers.
+  Select M (recommended), if you have a RSI 1x1 wireless module.
+
+config RSI_USB
+ tristate "Redpine Signals USB bus support"
+ depends on USB && RSI_91X
+ default m
+ ---help---
+  This option enables the USB bus support in rsi drivers.
+  Select M (recommended), if you have a RSI 1x1 wireless module.
+
+config RSI_HCI
+ tristate "Redpine Signals HCI support"
+ depends on RSI_91X
+ default m
+ ---help---
+  This option enables the HCI support in rsi drivers for BT apps.
+  Select M (recommended), if you have a RSI 1x1 wireless module.
+
+endif # WLAN_VENDOR_RSI
diff --git a/ubuntu/rsi/Makefile b/ubuntu/rsi/Makefile
new file mode 100644
index 0000000..b4f662d
--- /dev/null
+++ b/ubuntu/rsi/Makefile
@@ -0,0 +1,15 @@
+rsi_91x-y += rsi_91x_main.o
+rsi_91x-y += rsi_91x_core.o
+rsi_91x-y += rsi_91x_mac80211.o
+rsi_91x-y += rsi_91x_mgmt.o
+rsi_91x-y += rsi_91x_hal.o
+rsi_91x-y += rsi_91x_ps.o
+rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o
+rsi_91x-$(CONFIG_RSI_HCI) += rsi_91x_hci.o
+rsi_91x-$(CONFIG_RSI_COEX) += rsi_91x_coex.o
+
+rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
+rsi_sdio-y += rsi_91x_sdio.o rsi_91x_sdio_ops.o
+obj-$(CONFIG_RSI_91X) += rsi_91x.o
+obj-$(CONFIG_RSI_SDIO) += rsi_sdio.o
+obj-$(CONFIG_RSI_USB) += rsi_usb.o
diff --git a/ubuntu/rsi/rsi_91x_coex.c b/ubuntu/rsi/rsi_91x_coex.c
new file mode 100644
index 0000000..998f912
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_coex.c
@@ -0,0 +1,173 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Developer:
+ * Prameela Rani Ganrepudi <[hidden email]>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+//#include "rsi_common.h"
+#include "rsi_main.h"
+#include "rsi_coex.h"
+#include"rsi_hal.h"
+
+
+static u8 rsi_coex_determine_coex_q(struct rsi_coex_ctrl_block *coex_cb)
+{
+ u8 q_num = INVALID_QUEUE;
+
+ if (skb_queue_len(&coex_cb->coex_tx_qs[VIP_Q]) > 0)
+ q_num = VIP_Q;
+ if (skb_queue_len(&coex_cb->coex_tx_qs[COEX_Q]) > 0)
+ q_num = COEX_Q;
+ if (skb_queue_len(&coex_cb->coex_tx_qs[BT_Q]) > 0)
+ q_num = BT_Q;
+ if (skb_queue_len(&coex_cb->coex_tx_qs[ZIGB_Q]) > 0)
+ q_num = ZIGB_Q;
+ if (skb_queue_len(&coex_cb->coex_tx_qs[WLAN_Q]) > 0)
+ q_num = WLAN_Q;
+
+ return q_num;
+}
+
+static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
+{
+ u8 coex_q;
+ struct sk_buff *skb;
+
+ while (1) {
+ coex_q = rsi_coex_determine_coex_q(coex_cb);
+ rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
+
+ if (coex_q == INVALID_QUEUE) {
+ rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
+ break;
+ }
+
+ mutex_lock(&coex_cb->coex_tx_lock);
+
+ if (coex_q == BT_Q) {
+ skb = skb_dequeue(&coex_cb->coex_tx_qs[BT_Q]);
+ rsi_send_bt_pkt(coex_cb->priv, skb);
+ }
+
+ mutex_unlock(&coex_cb->coex_tx_lock);
+ }
+}
+
+/**
+ * rsi_coex_scheduler_thread() - This function is a kernel thread to schedule
+ *       the coex packets to device
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: None.
+ */
+static void rsi_coex_scheduler_thread(struct rsi_coex_ctrl_block *coex_cb)
+{
+ struct rsi_common *common = (struct rsi_common *)coex_cb->priv;
+ u32 timeout = EVENT_WAIT_FOREVER;
+
+ do {
+ rsi_wait_event(&coex_cb->coex_tx_thread.event, timeout);
+ rsi_reset_event(&coex_cb->coex_tx_thread.event);
+
+ rsi_coex_sched_tx_pkts(coex_cb);
+ } while (atomic_read(&coex_cb->coex_tx_thread.thread_done) == 0);
+
+ complete_and_exit(&coex_cb->coex_tx_thread.completion, 0);
+}
+
+int rsi_coex_recv_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ return 0;
+}
+
+int rsi_coex_send_pkt(struct rsi_common *common,
+      struct sk_buff *skb,
+      u8 hal_queue)
+{
+ struct rsi_coex_ctrl_block *coex_cb = common->coex_cb;
+ int status = 0;
+
+ /* Add pkt to queue if not WLAN packet */
+ if (hal_queue != RSI_WLAN_Q) {
+ skb_queue_tail(&coex_cb->coex_tx_qs[hal_queue], skb);
+ rsi_set_event(&coex_cb->coex_tx_thread.event);
+ return status;
+ }
+
+ mutex_lock(&coex_cb->coex_tx_lock);
+
+ /* Send packet to hal */
+ status = rsi_send_data_pkt(common, skb);
+
+ mutex_unlock(&coex_cb->coex_tx_lock);
+
+ return 0;
+}
+
+int rsi_coex_init(struct rsi_common *common)
+{
+ struct rsi_coex_ctrl_block *coex_cb = NULL;
+ int cnt;
+
+ coex_cb = kzalloc(sizeof(*coex_cb), GFP_KERNEL);
+ if (!coex_cb) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed allocate coex control block\n",
+ __func__);
+ return -ENOMEM;
+ }
+ common->coex_cb = (void *)coex_cb;
+
+ /* Initialize co-ex queues */
+ for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
+ skb_queue_head_init(&coex_cb->coex_tx_qs[cnt]);
+ mutex_init(&coex_cb->coex_tx_lock);
+
+ /* Initialize co-ex thread */
+ if (rsi_create_kthread(common,
+       &coex_cb->coex_tx_thread,
+       rsi_coex_scheduler_thread,
+       "Coex-Tx-Thread")) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ return -1;
+}
+
+void rsi_coex_deinit(struct rsi_common *common)
+{
+ int cnt;
+
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
+
+ /* Stop the coex tx thread */
+ rsi_kill_thread(&coex_cb->coex_tx_thread);
+
+ /* Empty the coex queue */
+ for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
+ skb_queue_purge(&coex_cb->coex_tx_qs[cnt]);
+
+ /* Free the coex control block */
+ kfree(coex_cb);
+
+ return;
+}
diff --git a/ubuntu/rsi/rsi_91x_core.c b/ubuntu/rsi/rsi_91x_core.c
new file mode 100644
index 0000000..8f0d136
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_core.c
@@ -0,0 +1,401 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "rsi_mgmt.h"
+#include "rsi_common.h"
+
+/**
+ * rsi_determine_min_weight_queue() - This function determines the queue with
+ *      the min weight.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: q_num: Corresponding queue number.
+ */
+static u8 rsi_determine_min_weight_queue(struct rsi_common *common)
+{
+ struct wmm_qinfo *tx_qinfo = common->tx_qinfo;
+ u32 q_len = 0;
+ u8 ii = 0;
+
+ for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {
+ q_len = skb_queue_len(&common->tx_queue[ii]);
+ if ((tx_qinfo[ii].pkt_contended) && q_len) {
+ common->min_weight = tx_qinfo[ii].weight;
+ break;
+ }
+ }
+ return ii;
+}
+
+/**
+ * rsi_recalculate_weights() - This function recalculates the weights
+ *       corresponding to each queue.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: recontend_queue bool variable
+ */
+static bool rsi_recalculate_weights(struct rsi_common *common)
+{
+ struct wmm_qinfo *tx_qinfo = common->tx_qinfo;
+ bool recontend_queue = false;
+ u8 ii = 0;
+ u32 q_len = 0;
+
+ for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {
+ q_len = skb_queue_len(&common->tx_queue[ii]);
+ /* Check for the need of contention */
+ if (q_len) {
+ if (tx_qinfo[ii].pkt_contended) {
+ tx_qinfo[ii].weight =
+ ((tx_qinfo[ii].weight > common->min_weight) ?
+ tx_qinfo[ii].weight - common->min_weight : 0);
+ } else {
+ tx_qinfo[ii].pkt_contended = 1;
+ tx_qinfo[ii].weight = tx_qinfo[ii].wme_params;
+ recontend_queue = true;
+ }
+ } else { /* No packets so no contention */
+ tx_qinfo[ii].weight = 0;
+ tx_qinfo[ii].pkt_contended = 0;
+ }
+ }
+
+ return recontend_queue;
+}
+
+/**
+ * rsi_get_num_pkts_dequeue() - This function determines the number of
+ *                packets to be dequeued based on the number
+ *        of bytes calculated using txop.
+ *
+ * @common: Pointer to the driver private structure.
+ * @q_num: the queue from which pkts have to be dequeued
+ *
+ * Return: pkt_num: Number of pkts to be dequeued.
+ */
+static u32 rsi_get_num_pkts_dequeue(struct rsi_common *common, u8 q_num)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct sk_buff *skb;
+ u32 pkt_cnt = 0;
+ s16 txop = common->tx_qinfo[q_num].txop * 32;
+ __le16 r_txop;
+ struct ieee80211_rate rate;
+
+ rate.bitrate = RSI_RATE_MCS0 * 5 * 10; /* Convert to Kbps */
+ if (q_num == VI_Q)
+ txop = ((txop << 5) / 80);
+
+ if (skb_queue_len(&common->tx_queue[q_num]))
+ skb = skb_peek(&common->tx_queue[q_num]);
+ else
+ return 0;
+
+ do {
+ r_txop = ieee80211_generic_frame_duration(adapter->hw,
+  adapter->vifs[0],
+  common->band,
+  skb->len, &rate);
+ txop -= le16_to_cpu(r_txop);
+ pkt_cnt += 1;
+ /*checking if pkts are still there*/
+ if (skb_queue_len(&common->tx_queue[q_num]) - pkt_cnt)
+ skb = skb->next;
+ else
+ break;
+
+ } while (txop > 0);
+
+ return pkt_cnt;
+}
+
+/**
+ * rsi_core_determine_hal_queue() - This function determines the queue from
+ *    which packet has to be dequeued.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: q_num: Corresponding queue number on success.
+ */
+static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
+{
+ bool recontend_queue = false;
+ u32 q_len = 0;
+ u8 q_num = INVALID_QUEUE;
+ u8 ii;
+
+ if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) {
+ if (!common->mgmt_q_block)
+ q_num = MGMT_SOFT_Q;
+ return q_num;
+ }
+
+ if (common->hw_data_qs_blocked) {
+ rsi_dbg(INFO_ZONE, "%s: data queue blocked\n", __func__);
+ return q_num;
+ }
+
+ if (common->pkt_cnt != 0) {
+ --common->pkt_cnt;
+ return common->selected_qnum;
+ }
+
+get_queue_num:
+ recontend_queue = false;
+
+ q_num = rsi_determine_min_weight_queue(common);
+
+ ii = q_num;
+
+ /* Selecting the queue with least back off */
+ for (; ii < NUM_EDCA_QUEUES; ii++) {
+ q_len = skb_queue_len(&common->tx_queue[ii]);
+ if (((common->tx_qinfo[ii].pkt_contended) &&
+     (common->tx_qinfo[ii].weight < common->min_weight)) &&
+      q_len) {
+ common->min_weight = common->tx_qinfo[ii].weight;
+ q_num = ii;
+ }
+ }
+
+ if (q_num < NUM_EDCA_QUEUES)
+ common->tx_qinfo[q_num].pkt_contended = 0;
+
+ /* Adjust the back off values for all queues again */
+ recontend_queue = rsi_recalculate_weights(common);
+
+ q_len = skb_queue_len(&common->tx_queue[q_num]);
+ if (!q_len) {
+ /* If any queues are freshly contended and the selected queue
+ * doesn't have any packets
+ * then get the queue number again with fresh values
+ */
+ if (recontend_queue)
+ goto get_queue_num;
+
+ q_num = INVALID_QUEUE;
+ return q_num;
+ }
+
+ common->selected_qnum = q_num;
+ q_len = skb_queue_len(&common->tx_queue[q_num]);
+
+ if (q_num == VO_Q || q_num == VI_Q) {
+ common->pkt_cnt = rsi_get_num_pkts_dequeue(common, q_num);
+ common->pkt_cnt -= 1;
+ }
+
+ return q_num;
+}
+
+/**
+ * rsi_core_queue_pkt() - This functions enqueues the packet to the queue
+ *  specified by the queue number.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: None.
+ */
+static void rsi_core_queue_pkt(struct rsi_common *common,
+       struct sk_buff *skb)
+{
+ u8 q_num = skb->priority;
+
+ if (q_num >= NUM_SOFT_QUEUES) {
+ rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",
+ __func__, q_num);
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ skb_queue_tail(&common->tx_queue[q_num], skb);
+}
+
+/**
+ * rsi_core_dequeue_pkt() - This functions dequeues the packet from the queue
+ *    specified by the queue number.
+ * @common: Pointer to the driver private structure.
+ * @q_num: Queue number.
+ *
+ * Return: Pointer to sk_buff structure.
+ */
+static struct sk_buff *rsi_core_dequeue_pkt(struct rsi_common *common,
+    u8 q_num)
+{
+ if (q_num >= NUM_SOFT_QUEUES) {
+ rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",
+ __func__, q_num);
+ return NULL;
+ }
+
+ return skb_dequeue(&common->tx_queue[q_num]);
+}
+
+/**
+ * rsi_core_qos_processor() - This function is used to determine the wmm queue
+ *      based on the backoff procedure. Data packets are
+ *      dequeued from the selected hal queue and sent to
+ *      the below layers.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: None.
+ */
+void rsi_core_qos_processor(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct sk_buff *skb;
+ unsigned long tstamp_1, tstamp_2;
+ u8 q_num;
+ int status;
+
+ tstamp_1 = jiffies;
+ while (1) {
+ q_num = rsi_core_determine_hal_queue(common);
+ rsi_dbg(DATA_TX_ZONE,
+ "%s: Queue number = %d\n", __func__, q_num);
+
+ if (q_num == INVALID_QUEUE) {
+ rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__);
+ break;
+ }
+
+ mutex_lock(&common->tx_lock);
+
+ status = adapter->check_hw_queue_status(adapter, q_num);
+ if ((status <= 0)) {
+ mutex_unlock(&common->tx_lock);
+ break;
+ }
+
+ if ((q_num < MGMT_SOFT_Q) &&
+    ((skb_queue_len(&common->tx_queue[q_num])) <=
+      MIN_DATA_QUEUE_WATER_MARK)) {
+ if (ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
+ ieee80211_wake_queue(adapter->hw,
+     WME_AC(q_num));
+ }
+
+ skb = rsi_core_dequeue_pkt(common, q_num);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "skb null\n");
+ mutex_unlock(&common->tx_lock);
+ break;
+ }
+
+ if (q_num == MGMT_SOFT_Q)
+ status = rsi_send_mgmt_pkt(common, skb);
+ else
+ status = rsi_send_data_pkt(common, skb);
+
+ if (status) {
+ mutex_unlock(&common->tx_lock);
+ break;
+ }
+
+ common->tx_stats.total_tx_pkt_send[q_num]++;
+
+ tstamp_2 = jiffies;
+ mutex_unlock(&common->tx_lock);
+
+ if (tstamp_2 > tstamp_1 + (300 * HZ / 1000))
+ schedule();
+ }
+}
+
+/**
+ * rsi_core_xmit() - This function transmits the packets received from mac80211
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: None.
+ */
+void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_tx_info *info;
+ struct skb_info *tx_params;
+ struct ieee80211_hdr *tmp_hdr = NULL;
+ u8 q_num, tid = 0;
+
+ if ((!skb) || (!skb->len)) {
+ rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n",
+ __func__);
+ goto xmit_fail;
+ }
+
+ if (common->fsm_state != FSM_MAC_INIT_DONE) {
+ rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);
+ goto xmit_fail;
+ }
+
+ info = IEEE80211_SKB_CB(skb);
+ tx_params = (struct skb_info *)info->driver_data;
+ tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
+
+ if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) ||
+    (ieee80211_is_ctl(tmp_hdr->frame_control)) ||
+    (ieee80211_is_qos_nullfunc(tmp_hdr->frame_control))) {
+ q_num = MGMT_SOFT_Q;
+ skb->priority = q_num;
+
+ if (ieee80211_is_probe_req(tmp_hdr->frame_control)) {
+ rsi_dbg(MGMT_TX_ZONE, "%s: Probe Request\n", __func__);
+ if (is_broadcast_ether_addr(tmp_hdr->addr1)) {
+ rsi_dbg(INFO_ZONE, "%s: Probe request backup\n", __func__);
+ memcpy(common->bgscan_probe_req, skb->data, skb->len);
+ common->bgscan_probe_req_len = skb->len;
+ }
+ } else if (ieee80211_is_auth(tmp_hdr->frame_control))
+ rsi_dbg(MGMT_TX_ZONE, "%s: Auth Request\n", __func__);
+ else if (ieee80211_is_assoc_req(tmp_hdr->frame_control))
+ rsi_dbg(MGMT_TX_ZONE, "%s: Assoc Request\n", __func__);
+ else
+ rsi_dbg(MGMT_TX_ZONE, "%s: pkt_type=%04x\n",
+ __func__, tmp_hdr->frame_control);
+ } else {
+ rsi_dbg(DATA_TX_ZONE, "%s: Data Packet\n", __func__);
+ if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
+ tid = (skb->data[24] & IEEE80211_QOS_TID);
+ skb->priority = TID_TO_WME_AC(tid);
+ } else {
+ tid = IEEE80211_NONQOS_TID;
+ skb->priority = BE_Q;
+ }
+ q_num = skb->priority;
+ tx_params->tid = tid;
+ tx_params->sta_id = 0;
+ }
+
+ if ((q_num != MGMT_SOFT_Q) &&
+    ((skb_queue_len(&common->tx_queue[q_num]) + 1) >=
+ DATA_QUEUE_WATER_MARK)) {
+ rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
+ if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
+ ieee80211_stop_queue(adapter->hw, WME_AC(q_num));
+ rsi_set_event(&common->tx_thread.event);
+ goto xmit_fail;
+ }
+
+ rsi_core_queue_pkt(common, skb);
+ rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thead <===\n", __func__);
+ rsi_set_event(&common->tx_thread.event);
+
+ return;
+
+xmit_fail:
+ rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__);
+ /* Dropping pkt here */
+ ieee80211_free_txskb(common->priv->hw, skb);
+}
diff --git a/ubuntu/rsi/rsi_91x_debugfs.c b/ubuntu/rsi/rsi_91x_debugfs.c
new file mode 100644
index 0000000..257cb68
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_debugfs.c
@@ -0,0 +1,502 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "rsi_debugfs.h"
+#include "rsi_sdio.h"
+#include "rsi_mgmt.h"
+
+int g_bgscan_enable;
+
+/**
+ * rsi_sdio_stats_read() - This function returns the sdio status of the driver.
+ * @seq: Pointer to the sequence file structure.
+ * @data: Pointer to the data.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_sdio_stats_read(struct seq_file *seq, void *data)
+{
+ struct rsi_common *common = seq->private;
+ struct rsi_hw *adapter = common->priv;
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+
+ seq_printf(seq, "total_sdio_interrupts: %d\n",
+   dev->rx_info.sdio_int_counter);
+ seq_printf(seq, "sdio_msdu_pending_intr_count: %d\n",
+   dev->rx_info.total_sdio_msdu_pending_intr);
+ seq_printf(seq, "sdio_buff_full_count : %d\n",
+   dev->rx_info.buf_full_counter);
+ seq_printf(seq, "sdio_buf_semi_full_count %d\n",
+   dev->rx_info.buf_semi_full_counter);
+ seq_printf(seq, "sdio_unknown_intr_count: %d\n",
+   dev->rx_info.total_sdio_unknown_intr);
+ /* RX Path Stats */
+ seq_printf(seq, "BUFFER FULL STATUS  : %d\n",
+   dev->rx_info.buffer_full);
+ seq_printf(seq, "SEMI BUFFER FULL STATUS  : %d\n",
+   dev->rx_info.semi_buffer_full);
+ seq_printf(seq, "MGMT BUFFER FULL STATUS  : %d\n",
+   dev->rx_info.mgmt_buffer_full);
+ seq_printf(seq, "BUFFER FULL COUNTER  : %d\n",
+   dev->rx_info.buf_full_counter);
+ seq_printf(seq, "BUFFER SEMI FULL COUNTER  : %d\n",
+   dev->rx_info.buf_semi_full_counter);
+ seq_printf(seq, "MGMT BUFFER FULL COUNTER  : %d\n",
+   dev->rx_info.mgmt_buf_full_counter);
+
+ return 0;
+}
+
+/**
+ * rsi_sdio_stats_open() - This function calls single open function of seq_file
+ *   to open file and read contents from it.
+ * @inode: Pointer to the inode structure.
+ * @file: Pointer to the file structure.
+ *
+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
+ */
+static int rsi_sdio_stats_open(struct inode *inode,
+       struct file *file)
+{
+ return single_open(file, rsi_sdio_stats_read, inode->i_private);
+}
+
+/**
+ * rsi_version_read() - This function gives driver and firmware version number.
+ * @seq: Pointer to the sequence file structure.
+ * @data: Pointer to the data.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_version_read(struct seq_file *seq, void *data)
+{
+ struct rsi_common *common = seq->private;
+
+ common->driver_ver.major = 3;
+ common->driver_ver.minor = 0;
+ common->driver_ver.release_num = 0;
+ common->driver_ver.patch_num = 0;
+ seq_printf(seq, "Driver : %x.%d.%d.%d\nLMAC   : %d.%d.%d.%d\n",
+   common->driver_ver.major,
+   common->driver_ver.minor,
+   common->driver_ver.release_num,
+   common->driver_ver.patch_num,
+   common->fw_ver.major,
+   common->fw_ver.minor,
+   common->fw_ver.release_num,
+   common->fw_ver.patch_num);
+ return 0;
+}
+
+/**
+ * rsi_version_open() - This function calls single open function of seq_file to
+ * open file and read contents from it.
+ * @inode: Pointer to the inode structure.
+ * @file: Pointer to the file structure.
+ *
+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
+ */
+static int rsi_version_open(struct inode *inode,
+    struct file *file)
+{
+ return single_open(file, rsi_version_read, inode->i_private);
+}
+
+/**
+ * rsi_stats_read() - This function return the status of the driver.
+ * @seq: Pointer to the sequence file structure.
+ * @data: Pointer to the data.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_stats_read(struct seq_file *seq, void *data)
+{
+ struct rsi_common *common = seq->private;
+
+ unsigned char fsm_state[][32] = {
+ "FSM_CARD_NOT_READY",
+ "FSM_BOOT_PARAMS_SENT",
+ "FSM_EEPROM_READ_MAC_ADDR",
+ "FSM_RESET_MAC_SENT",
+ "FSM_RADIO_CAPS_SENT",
+ "FSM_BB_RF_PROG_SENT",
+ "FSM_MAC_INIT_DONE"
+ };
+ seq_puts(seq, "==> RSI STA DRIVER STATUS <==\n");
+ seq_puts(seq, "DRIVER_FSM_STATE: ");
+
+ if (common->fsm_state <= FSM_MAC_INIT_DONE)
+ seq_printf(seq, "%s", fsm_state[common->fsm_state]);
+
+ seq_printf(seq, "(%d)\n\n", common->fsm_state);
+
+ /* Mgmt TX Path Stats */
+ seq_printf(seq, "total_mgmt_pkt_send : %d\n",
+   common->tx_stats.total_tx_pkt_send[MGMT_SOFT_Q]);
+ seq_printf(seq, "total_mgmt_pkt_queued : %d\n",
+   skb_queue_len(&common->tx_queue[MGMT_SOFT_Q]));
+ seq_printf(seq, "total_mgmt_pkt_freed  : %d\n",
+   common->tx_stats.total_tx_pkt_freed[MGMT_SOFT_Q]);
+
+ /* Data TX Path Stats */
+ seq_printf(seq, "total_data_vo_pkt_send: %8d\t",
+   common->tx_stats.total_tx_pkt_send[VO_Q]);
+ seq_printf(seq, "total_data_vo_pkt_queued:  %8d\t",
+   skb_queue_len(&common->tx_queue[VO_Q]));
+ seq_printf(seq, "total_vo_pkt_freed: %8d\n",
+   common->tx_stats.total_tx_pkt_freed[VO_Q]);
+ seq_printf(seq, "total_data_vi_pkt_send: %8d\t",
+   common->tx_stats.total_tx_pkt_send[VI_Q]);
+ seq_printf(seq, "total_data_vi_pkt_queued:  %8d\t",
+   skb_queue_len(&common->tx_queue[VI_Q]));
+ seq_printf(seq, "total_vi_pkt_freed: %8d\n",
+   common->tx_stats.total_tx_pkt_freed[VI_Q]);
+ seq_printf(seq,  "total_data_be_pkt_send: %8d\t",
+   common->tx_stats.total_tx_pkt_send[BE_Q]);
+ seq_printf(seq, "total_data_be_pkt_queued:  %8d\t",
+   skb_queue_len(&common->tx_queue[BE_Q]));
+ seq_printf(seq, "total_be_pkt_freed: %8d\n",
+   common->tx_stats.total_tx_pkt_freed[BE_Q]);
+ seq_printf(seq, "total_data_bk_pkt_send: %8d\t",
+   common->tx_stats.total_tx_pkt_send[BK_Q]);
+ seq_printf(seq, "total_data_bk_pkt_queued:  %8d\t",
+   skb_queue_len(&common->tx_queue[BK_Q]));
+ seq_printf(seq, "total_bk_pkt_freed: %8d\n",
+   common->tx_stats.total_tx_pkt_freed[BK_Q]);
+
+ seq_puts(seq, "\n");
+ return 0;
+}
+
+/**
+ * rsi_stats_open() - This function calls single open function of seq_file to
+ *      open file and read contents from it.
+ * @inode: Pointer to the inode structure.
+ * @file: Pointer to the file structure.
+ *
+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
+ */
+static int rsi_stats_open(struct inode *inode,
+  struct file *file)
+{
+ return single_open(file, rsi_stats_read, inode->i_private);
+}
+
+/**
+ * rsi_debug_zone_read() - This function display the currently
+ * enabled debug zones.
+ * @seq: Pointer to the sequence file structure.
+ * @data: Pointer to the data.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_debug_zone_read(struct seq_file *seq, void *data)
+{
+ rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled);
+ seq_printf(seq, "The zones available are %#x\n",
+   rsi_zone_enabled);
+ return 0;
+}
+
+/**
+ * rsi_debug_read() - This function calls single open function of seq_file to
+ *      open file and read contents from it.
+ * @inode: Pointer to the inode structure.
+ * @file: Pointer to the file structure.
+ *
+ * Return: Pointer to the opened file status: 0 on success, ENOMEM on failure.
+ */
+static int rsi_debug_read(struct inode *inode,
+  struct file *file)
+{
+ return single_open(file, rsi_debug_zone_read, inode->i_private);
+}
+
+/**
+ * rsi_debug_zone_write() - This function writes into hal queues as per user
+ *    requirement.
+ * @filp: Pointer to the file structure.
+ * @buff: Pointer to the character buffer.
+ * @len: Length of the data to be written into buffer.
+ * @data: Pointer to the data.
+ *
+ * Return: len: Number of bytes read.
+ */
+static ssize_t rsi_debug_zone_write(struct file *filp,
+    const char __user *buff,
+    size_t len,
+    loff_t *data)
+{
+ unsigned long dbg_zone;
+ int ret;
+
+ if (!len)
+ return 0;
+
+ ret = kstrtoul_from_user(buff, len, 16, &dbg_zone);
+
+ if (ret)
+ return ret;
+
+ rsi_zone_enabled = dbg_zone;
+ return len;
+}
+
+/**
+ * rsi_bgscan_int_read() - This function display the default bgscan param
+ *   values.
+ * @seq: Pointer to the sequence file structure.
+ * @data: Pointer to the data.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_bgscan_int_read(struct seq_file *file, void *data)
+{
+ struct rsi_common *common = file->private;
+ struct bgscan_config_params *params = &common->bgscan_info;
+ int cnt;
+
+ seq_printf(file, "%d %d %d %d %d %d %d %d\n",
+   common->bgscan_en,
+   params->bgscan_threshold,
+   params->roam_threshold,
+   params->bgscan_periodicity,
+   params->active_scan_duration,
+   params->passive_scan_duration,
+   params->two_probe,
+   params->num_bg_channels);
+
+ for (cnt = 0; cnt < params->num_bg_channels; cnt++)
+ seq_printf(file, "%d ", params->channels2scan[cnt]);
+ seq_printf(file, "\n");
+
+ return 0;
+}
+
+static int rsi_bgscan_read(struct inode *inode, struct file *file)
+{
+ return single_open(file, rsi_bgscan_int_read, inode->i_private);
+}
+
+/**
+ * rsi_bgscan_write() - This function gets the bgscan params from user
+ *    and configures to device.
+ * @file: Pointer to the file structure.
+ * @user_buff: user buffer.
+ * @count: Length of the data written in buffer.
+ * @ppos: offset.
+ *
+ * Return: Number of bytes read.
+ */
+static ssize_t rsi_bgscan_write(struct file *file,
+        const char __user *user_buff,
+ size_t count,
+ loff_t *ppos)
+
+{
+ struct rsi_common *common = file->f_inode->i_private;
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+ char bgscan_buf[200];
+ int bgscan_vals[64] = { 0 };
+ int total_bytes, cnt = 0;
+ int bytes_read = 0, t_bytes;
+ int ret;
+
+ total_bytes = simple_write_to_buffer(bgscan_buf,
+     sizeof(bgscan_buf) - 1,
+     ppos, user_buff, count);
+ if (total_bytes < 1)
+ return -EINVAL;
+
+ /* make sure that buf is null terminated */
+ bgscan_buf[sizeof(bgscan_buf) - 1] = '\0';
+
+ ret = sscanf(bgscan_buf, "%d%n",
+     (int *)&g_bgscan_enable, &t_bytes);
+ if (ret <= 0)
+ return -EINVAL;
+
+ if (!g_bgscan_enable) {
+ /* return here if bgscan is already disabled */
+ if (!common->bgscan_en) {
+ rsi_dbg(ERR_ZONE, "bgscan already disabled\n");
+ return total_bytes;
+ }
+
+ mutex_lock(&common->mutex);
+ if (bss->assoc && !rsi_send_bgscan_params(common, 0)) {
+ rsi_dbg(ERR_ZONE, "*** bgscan disabled ***\n");
+ common->bgscan_en = 0;
+ }
+ mutex_unlock(&common->mutex);
+
+ return total_bytes;
+ } else if (common->bgscan_en) {
+ rsi_dbg(ERR_ZONE, "bgscan already enabled\n");
+ return total_bytes;
+ }
+
+ /* Return if bgscan is already in progress */
+ if (common->bgscan_en)
+ return total_bytes;
+
+ bytes_read += t_bytes;
+ while (1) {
+ ret = sscanf(bgscan_buf + bytes_read, "%d%n",
+     &bgscan_vals[cnt++],
+     &t_bytes);
+ if (ret <= 0)
+ break;
+ bytes_read += t_bytes;
+
+ if ((bgscan_vals[6] > 0) && (cnt > (6 + bgscan_vals[6])))
+ break;
+ }
+ common->bgscan_info.bgscan_threshold = bgscan_vals[0];
+ common->bgscan_info.roam_threshold = bgscan_vals[1];
+ common->bgscan_info.bgscan_periodicity = bgscan_vals[2];
+ common->bgscan_info.active_scan_duration = bgscan_vals[3];
+ common->bgscan_info.passive_scan_duration = bgscan_vals[4];
+ common->bgscan_info.two_probe = bgscan_vals[5];
+ common->bgscan_info.num_bg_channels = bgscan_vals[6];
+ for (cnt = 0; cnt < common->bgscan_info.num_bg_channels; cnt++)
+ common->bgscan_info.channels2scan[cnt] = bgscan_vals[7 + cnt];
+
+ rsi_dbg(INFO_ZONE,
+ "bgscan_count = %d, roam_count = %d, periodicity = %d\n",
+ common->bgscan_info.bgscan_threshold,
+ common->bgscan_info.roam_threshold,
+ common->bgscan_info.bgscan_periodicity);
+ rsi_dbg(INFO_ZONE,
+ "active_scan_dur = %d, passive_scan_dur = %d, two_probe = %d\n",
+ common->bgscan_info.active_scan_duration,
+ common->bgscan_info.passive_scan_duration,
+ common->bgscan_info.two_probe);
+ rsi_dbg(INFO_ZONE, "Number of scan channels = %d\n",
+ common->bgscan_info.num_bg_channels);
+ rsi_hex_dump(INFO_ZONE, "bgscan channels",
+     (u8 *)common->bgscan_info.channels2scan,
+     common->bgscan_info.num_bg_channels * 2);
+
+ /* If connection is not done don't send bgscan params */
+ if (!bss->assoc) {
+ rsi_dbg(INFO_ZONE, "Station not connected; skip now\n");
+ return total_bytes;
+ }
+
+ /* Send bgscan params to device */
+ mutex_lock(&common->mutex);
+ if (!rsi_send_bgscan_params(common, 1)) {
+ if (!rsi_send_bgscan_probe_req(common)) {
+ rsi_dbg(INFO_ZONE, "Background scan started ===>\n");
+ common->bgscan_en = 1;
+ } else {
+ rsi_dbg(ERR_ZONE, "Failed sending bgscan probe req\n");
+ common->bgscan_en = 0;
+ g_bgscan_enable = 0;
+ }
+ } else
+ rsi_dbg(ERR_ZONE, "Failed sending bgscan params req\n");
+ mutex_unlock(&common->mutex);
+
+ return total_bytes;
+}
+
+#define FOPS(fopen) { \
+ .owner = THIS_MODULE, \
+ .open = (fopen), \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+}
+
+#define FOPS_RW(fopen, fwrite) { \
+ .owner = THIS_MODULE, \
+ .open = (fopen), \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .write = (fwrite), \
+}
+
+static const struct rsi_dbg_files dev_debugfs_files[] = {
+ {"version", 0644, FOPS(rsi_version_open),},
+ {"stats", 0644, FOPS(rsi_stats_open),},
+ {"debug_zone", 0666, FOPS_RW(rsi_debug_read, rsi_debug_zone_write),},
+ {"bgscan", 0666, FOPS_RW(rsi_bgscan_read, rsi_bgscan_write),},
+ {"sdio_stats", 0644, FOPS(rsi_sdio_stats_open),},
+};
+
+/**
+ * rsi_init_dbgfs() - This function initializes the dbgfs entry.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_init_dbgfs(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+ struct rsi_debugfs *dev_dbgfs;
+ char devdir[6];
+ int ii;
+ const struct rsi_dbg_files *files;
+
+ dev_dbgfs = kzalloc(sizeof(*dev_dbgfs), GFP_KERNEL);
+ if (!dev_dbgfs)
+ return -ENOMEM;
+
+ adapter->dfsentry = dev_dbgfs;
+
+ snprintf(devdir, sizeof(devdir), "%s",
+ wiphy_name(adapter->hw->wiphy));
+
+ dev_dbgfs->subdir = debugfs_create_dir(devdir, NULL);
+
+ if (!dev_dbgfs->subdir) {
+ kfree(dev_dbgfs);
+ return -ENOMEM;
+ }
+
+ for (ii = 0; ii < adapter->num_debugfs_entries; ii++) {
+ files = &dev_debugfs_files[ii];
+ dev_dbgfs->rsi_files[ii] =
+ debugfs_create_file(files->name,
+    files->perms,
+    dev_dbgfs->subdir,
+    common,
+    &files->fops);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_init_dbgfs);
+
+/**
+ * rsi_remove_dbgfs() - Removes the previously created dbgfs file entries
+ * in the reverse order of creation.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+void rsi_remove_dbgfs(struct rsi_hw *adapter)
+{
+ struct rsi_debugfs *dev_dbgfs = adapter->dfsentry;
+
+ if (!dev_dbgfs)
+ return;
+
+ debugfs_remove_recursive(dev_dbgfs->subdir);
+}
+EXPORT_SYMBOL_GPL(rsi_remove_dbgfs);
diff --git a/ubuntu/rsi/rsi_91x_hal.c b/ubuntu/rsi/rsi_91x_hal.c
new file mode 100644
index 0000000..077c125
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_hal.c
@@ -0,0 +1,1119 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Developers
+ * Prameela Rani Garnepudi 2016 <[hidden email]>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/firmware.h>
+#include <linux/version.h>
+#include <linux/jiffies.h>
+#include <net/bluetooth/bluetooth.h>
+#include "rsi_mgmt.h"
+#include "rsi_hal.h"
+#include "rsi_sdio.h"
+#include "rsi_common.h"
+
+/* FLASH Firmware */
+struct ta_metadata metadata_flash_content[] = {
+ {"flash_content", 0x00010000},
+ {"RS9113_WLAN_QSPI.rps", 0x00010000},
+ {"RS9113_WLAN_BT_DUAL_MODE.rps", 0x00010000},
+ {"RS9113_WLAN_ZIGBEE.rps", 0x00010000},
+ {"RS9113_AP_BT_DUAL_MODE.rps", 0x00010000},
+ {"RS9113_WLAN_QSPI.rps", 0x00010000}
+};
+
+/**
+ * rsi_send_data_pkt() - This function sends the received data packet from
+ * driver to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hdr *wh = NULL;
+ struct ieee80211_tx_info *info;
+ struct skb_info *tx_params;
+ struct ieee80211_bss_conf *bss = NULL;
+ int status = -EINVAL;
+ u8 ieee80211_hdr_size = MIN_802_11_HDR_LEN;
+ u8 dword_align_bytes = 0;
+ u8 header_size = 0;
+ __le16 *frame_desc;
+ struct xtended_desc *xtend_desc;
+ u16 seq_num = 0;
+
+ info = IEEE80211_SKB_CB(skb);
+ bss = &info->control.vif->bss_conf;
+ tx_params = (struct skb_info *)info->driver_data;
+
+ if (!bss->assoc)
+ goto err;
+
+ dword_align_bytes = ((uintptr_t)skb->data & 0x3f);
+ header_size = dword_align_bytes + FRAME_DESC_SZ +
+ sizeof(struct xtended_desc);
+ if (header_size > skb_headroom(skb)) {
+ rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
+ status = -ENOSPC;
+ goto err;
+ }
+
+ skb_push(skb, header_size);
+ frame_desc = (__le16 *)&skb->data[0];
+ xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
+ memset((u8 *)frame_desc, 0, header_size);
+
+ wh = (struct ieee80211_hdr *)&skb->data[header_size];
+ seq_num = (le16_to_cpu(wh->seq_ctrl) >> 4);
+
+ frame_desc[2] = cpu_to_le16(header_size - FRAME_DESC_SZ);
+ if (ieee80211_is_data_qos(wh->frame_control)) {
+ ieee80211_hdr_size += 2;
+ frame_desc[6] |= cpu_to_le16(BIT(12));
+ }
+
+ if (adapter->ps_state == PS_ENABLED)
+ wh->frame_control |= BIT(12);
+
+ if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
+    (common->secinfo.security_enable)) {
+ if (rsi_is_cipher_wep(common))
+ ieee80211_hdr_size += 4;
+ else
+ ieee80211_hdr_size += 8;
+ frame_desc[6] |= cpu_to_le16(BIT(15));
+ }
+
+ frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+    (RSI_WIFI_DATA_Q << 12));
+ frame_desc[2] |= cpu_to_le16(ieee80211_hdr_size << 8);
+
+ if (common->min_rate != 0xffff) {
+ /* Send fixed rate */
+ frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
+ frame_desc[4] = cpu_to_le16(common->min_rate);
+
+ if (conf_is_ht40(&common->priv->hw->conf))
+ frame_desc[5] = cpu_to_le16(FULL40M_ENABLE);
+
+ if ((common->vif_info[0].sgi) && (common->min_rate & 0x100)) {
+ /* Only MCS rates */
+ frame_desc[4] |= cpu_to_le16(ENABLE_SHORTGI_RATE);
+ }
+ }
+
+ if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+ rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n");
+ frame_desc[6] |= cpu_to_le16(BIT(13));
+ frame_desc[1] |= cpu_to_le16(BIT(12));
+#define EAPOL_RETRY_CNT 15
+ xtend_desc->retry_cnt = EAPOL_RETRY_CNT;
+ }
+
+ frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
+ frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |
+    (skb->priority & 0xf) |
+    (tx_params->sta_id << 8));
+
+ rsi_hex_dump(DATA_TX_ZONE, "TX data pkt", skb->data, skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+   skb->data, skb->len);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to write data pkt\n", __func__);
+
+err:
+ ++common->tx_stats.total_tx_pkt_freed[skb->priority];
+ rsi_indicate_tx_status(common->priv, skb, status);
+ return status;
+}
+
+/**
+ * rsi_send_mgmt_pkt() - This functions prepares the descriptor for
+ * the given management packet and send to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_mgmt_pkt(struct rsi_common *common,
+      struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hdr *wh = NULL;
+ struct ieee80211_tx_info *info;
+ struct ieee80211_bss_conf *bss = NULL;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+ struct skb_info *tx_params;
+ int status = -E2BIG;
+ __le16 *desc = NULL;
+ struct xtended_desc *xtend_desc = NULL;
+ u8 header_size = 0;
+ u8 vap_id = 0;
+ u32 dword_align_req_bytes = 0;
+
+ info = IEEE80211_SKB_CB(skb);
+ tx_params = (struct skb_info *)info->driver_data;
+
+ if (tx_params->flags & INTERNAL_MGMT_PKT) {
+ skb->data[1] |= BIT(7); /* Immediate Wakeup bit*/
+ rsi_hex_dump(MGMT_TX_ZONE,
+     "Tx Command Packet",
+     skb->data, skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+   (u8 *)skb->data,
+   skb->len);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write the packet\n",
+ __func__);
+ }
+ dev_kfree_skb(skb);
+ return status;
+ }
+
+ /* Update header size */
+ header_size = FRAME_DESC_SZ + sizeof(struct xtended_desc) +
+ dword_align_req_bytes;
+ if (header_size > skb_headroom(skb)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to add extended descriptor\n",
+ __func__);
+ goto err;
+ }
+ skb_push(skb, header_size);
+ memset(&skb->data[0], 0, header_size);
+
+ bss = &info->control.vif->bss_conf;
+ wh = (struct ieee80211_hdr *)&skb->data[header_size];
+
+ desc = (__le16 *)skb->data;
+ xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
+
+ if (skb->len > MAX_MGMT_PKT_SIZE) {
+ rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
+ goto err;
+ }
+
+ desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+      (RSI_WIFI_MGMT_Q << 12));
+ desc[1] = cpu_to_le16(TX_DOT11_MGMT);
+ desc[2] = cpu_to_le16(MIN_802_11_HDR_LEN << 8);
+ desc[2] |= cpu_to_le16(header_size - FRAME_DESC_SZ);
+ desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
+ if (wh->addr1[0] & BIT(0))
+ desc[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
+ desc[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);
+
+ if (common->band == NL80211_BAND_2GHZ)
+ desc[4] = cpu_to_le16(RSI_11B_MODE);
+ else
+ desc[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
+
+ if (conf_is_ht40(conf)) {
+ desc[5] = cpu_to_le16(0x6);
+ }
+
+ /* Indicate to firmware to give cfm */
+ if (ieee80211_is_probe_req(wh->frame_control)) { // && (!bss->assoc)) {
+ if (!bss->assoc) {
+ rsi_dbg(INFO_ZONE, "%s: blocking mgmt queue\n", __func__);
+ desc[1] |= cpu_to_le16(RSI_DESC_REQUIRE_CFM_TO_HOST);
+ xtend_desc->confirm_frame_type = PROBEREQ_CONFIRM;
+ common->mgmt_q_block = true;
+ rsi_dbg(INFO_ZONE, "Mgmt queue blocked\n");
+ } else if (common->bgscan_en) {
+ /* Drop off channel probe request */
+ if (common->mac80211_cur_channel !=
+    rsi_get_connected_channel(adapter)) {
+ dev_kfree_skb(skb);
+ return 0;
+ } else if (wh->addr1[0] == 0xff) {
+ /* Drop broadcast probe in connected channel*/
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ }
+ rsi_dbg(MGMT_TX_ZONE, "Sending PROBE REQUEST =====>\n");
+ } else if (ieee80211_is_auth(wh->frame_control))
+ rsi_dbg(MGMT_TX_ZONE, "Sending AUTH REQUEST ======>\n");
+ else if (ieee80211_is_assoc_req(wh->frame_control))
+ rsi_dbg(MGMT_TX_ZONE, "Sending ASSOC REQUEST ======>\n");
+ else
+ rsi_dbg(MGMT_TX_ZONE,
+ "Sending Packet Type = %04x =====>\n",
+ wh->frame_control);
+
+ desc[7] |= cpu_to_le16(vap_id << 8); /* Station ID */
+ desc[4] |= cpu_to_le16(vap_id << 14);
+
+ rsi_hex_dump(MGMT_TX_ZONE, "Tx Mgmt Packet", skb->data, skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+   (u8 *)desc,
+   skb->len);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write the packet\n",
+ __func__);
+ }
+
+err:
+ rsi_indicate_tx_status(common->priv, skb, status);
+ return status;
+}
+
+int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ int status = -EINVAL;
+ u8 header_size = 0;
+ __le16 *frame_desc;
+
+ header_size = FRAME_DESC_SZ;
+ if (header_size > skb_headroom(skb)) {
+ rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
+ status = -ENOSPC;
+ goto err;
+ }
+ skb_push(skb, header_size);
+ frame_desc = (__le16 *)&skb->data[0];
+ memset((u8 *)frame_desc, 0, header_size);
+
+ frame_desc[0] = cpu_to_le16(skb->len - FRAME_DESC_SZ);
+ frame_desc[0] |= (cpu_to_le16 (RSI_BT_DATA_Q )& 0x7) << 12;
+
+ frame_desc[7] = cpu_to_le16(bt_cb(skb)->pkt_type);
+
+ rsi_hex_dump(DATA_TX_ZONE, "TX BT pkt", skb->data, skb->len);
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+   skb->data, skb->len);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to write bt pkt\n", __func__);
+
+err:
+ dev_kfree_skb(skb);
+ return status;
+}
+
+/**
+ * bl_cmd_timeout() - This function is called when BL command timed out
+ * @priv: Pointer to the hardware structure.
+ *
+ * Return: NONE.
+ */
+static void bl_cmd_timeout(unsigned long priv)
+{
+ struct rsi_hw *adapter = (struct rsi_hw *)priv;
+
+ adapter->blcmd_timer_expired = 1;
+ del_timer(&adapter->bl_cmd_timer);
+}
+
+/**
+ * bl_start_cmd_timer() - This function starts the BL command timer
+ * @adapter: Pointer to the hardware structure.
+ * @timeout: Timeout of the command in milliseconds
+ *
+ * Return: 0 on success.
+ */
+static int bl_start_cmd_timer(struct rsi_hw *adapter, u32 timeout)
+{
+ init_timer(&adapter->bl_cmd_timer);
+ adapter->bl_cmd_timer.data = (unsigned long)adapter;
+ adapter->bl_cmd_timer.function = (void *)&bl_cmd_timeout;
+ adapter->bl_cmd_timer.expires = (msecs_to_jiffies(timeout) + jiffies);
+
+ adapter->blcmd_timer_expired = 0;
+ add_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+/**
+ * bl_stop_cmd_timer() - This function stops the BL command timer
+ * @adapter: Pointer to the hardware structure.
+ *
+ * Return: 0 on success.
+ */
+static int bl_stop_cmd_timer(struct rsi_hw *adapter)
+{
+ adapter->blcmd_timer_expired = 0;
+ if (timer_pending(&adapter->bl_cmd_timer))
+ del_timer(&adapter->bl_cmd_timer);
+
+ return 0;
+}
+
+/**
+ * bl_write_cmd() - This function writes the BL command to device
+ * @adapter: Pointer to the hardware structure.
+ * @cmd: Command to write
+ * @exp_resp: Expected Response
+ * @cmd_resp: Received Response
+ *
+ * Return: 0 on success.
+ */
+int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 regin_val = 0, regout_val = 0;
+ u8 output = 0;
+ u32 regin_input = 0;
+
+ regin_input = (REGIN_INPUT | adapter->priv->coex_mode);
+
+ while (!adapter->blcmd_timer_expired) {
+ regin_val = 0;
+ if (hif_ops->master_reg_read(adapter,
+     SWBL_REGIN,
+     &regin_val,
+     2) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading failed..\n",
+ __func__, cmd);
+ goto fail;
+ }
+ mdelay(1);
+ if ((regin_val >> 12) != REGIN_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGIN reading timed out..\n",
+ __func__, cmd);
+ goto fail;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "Issuing write to Regin regin_val:%0x sending cmd:%0x\n",
+ regin_val, (cmd | regin_input << 8));
+ if ((hif_ops->master_reg_write(adapter,
+       SWBL_REGIN,
+       (cmd | regin_input << 8),
+       2)) < 0) {
+ goto fail;
+ }
+ mdelay(1);
+
+ if (cmd == LOAD_HOSTED_FW || cmd == JUMP_TO_ZERO_PC) {
+ /* JUMP_TO_ZERO_PC doesn't expect
+ * any response. So return from here
+ */
+ return 0;
+ }
+
+ while (!adapter->blcmd_timer_expired) {
+ regout_val = 0;
+ if (hif_ops->master_reg_read(adapter,
+     SWBL_REGOUT,
+     &regout_val,
+     2) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading failed..\n",
+ __func__, cmd);
+ goto fail;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT reading timed out..\n",
+ __func__, cmd);
+ goto fail;
+ }
+
+ *cmd_resp = ((u16 *)&regout_val)[0] & 0xffff;
+
+ output = ((u8 *)&regout_val)[0] & 0xff;
+
+ rsi_dbg(INFO_ZONE, "Invalidating regout\n");
+ if ((hif_ops->master_reg_write(adapter,
+       SWBL_REGOUT,
+       (cmd | REGOUT_INVALID << 8),
+       2)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %0x REGOUT writing failed..\n",
+ __func__, cmd);
+ goto fail;
+ }
+ mdelay(1);
+
+ if (output == exp_resp) {
+ rsi_dbg(INFO_ZONE,
+ "%s: Recvd Expected resp %x for cmd %0x\n",
+ __func__, output, cmd);
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: Recvd resp %x for cmd %0x\n",
+ __func__, output, cmd);
+ goto fail;
+ }
+ return 0;
+
+fail:
+ return -1;
+}
+
+/**
+ * bl_cmd() - This function initiates the BL command
+ * @adapter: Pointer to the hardware structure.
+ * @cmd: Command to write
+ * @exp_resp: Expected Response
+ * @str: Command string
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
+{
+ u16 regout_val = 0;
+ u32 timeout = 0;
+
+ rsi_dbg(INFO_ZONE, "Issuing cmd: \"%s\"\n", str);
+
+ if ((cmd == EOF_REACHED) || (cmd == PING_VALID) || (cmd == PONG_VALID))
+ timeout = BL_BURN_TIMEOUT;
+ else
+ timeout = BL_CMD_TIMEOUT;
+
+ bl_start_cmd_timer(adapter, timeout);
+ if (bl_write_cmd(adapter, cmd, exp_resp, &regout_val) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Command %s (%0x) writing failed..\n",
+ __func__, str, cmd);
+ goto fail;
+ }
+ bl_stop_cmd_timer(adapter);
+ return 0;
+
+fail:
+ return -1;
+}
+
+/**
+ * bl_write_header() - This function writes the BL header
+ * @adapter: Pointer to the hardware structure.
+ * @flash_content: Flash content
+ * @content_size: Flash content size
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int bl_write_header(struct rsi_hw *adapter,
+   u8 *flash_content, u32 content_size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ struct bl_header bl_hdr;
+ u32 write_addr, write_len;
+
+#define CHECK_SUM_OFFSET 20
+#define LEN_OFFSET 8
+#define ADDR_OFFSET 16
+
+ bl_hdr.flags = 0;
+ bl_hdr.image_no = cpu_to_le32(adapter->priv->coex_mode);
+ bl_hdr.check_sum = cpu_to_le32(
+ *(u32 *)&flash_content[CHECK_SUM_OFFSET]);
+ bl_hdr.flash_start_address = cpu_to_le32(
+ *(u32 *)&flash_content[ADDR_OFFSET]);
+ bl_hdr.flash_len = cpu_to_le32(*(u32 *)&flash_content[LEN_OFFSET]);
+ write_len = sizeof(struct bl_header);
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_USB) {
+ write_addr = PING_BUFFER_ADDRESS;
+ if ((hif_ops->write_reg_multiple(adapter,
+ write_addr,
+ (u8 *)&bl_hdr,
+ write_len)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ goto fail;
+ }
+ } else {
+ write_addr = PING_BUFFER_ADDRESS >> 16;
+ if ((hif_ops->master_access_msword(adapter, write_addr)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ goto fail;
+ }
+ write_addr = SD_REQUEST_MASTER |
+     (PING_BUFFER_ADDRESS & 0xFFFF);
+ if ((hif_ops->write_reg_multiple(adapter,
+ write_addr,
+ (u8 *)&bl_hdr,
+ write_len)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load Version/CRC structure\n",
+ __func__);
+ goto fail;
+ }
+ }
+ return 0;
+
+fail:
+ return -1;
+}
+
+/**
+ * read_flash_capacity() - This function reads the flash size from device
+ * @adapter: Pointer to the hardware structure.
+ *
+ * Return: flash capacity on success, 0 on failure.
+ */
+static u32 read_flash_capacity(struct rsi_hw *adapter)
+{
+ u32 flash_sz = 0;
+
+ if ((adapter->host_intf_ops->master_reg_read(adapter,
+     FLASH_SIZE_ADDR,
+     &flash_sz, 2)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash size reading failed..\n",
+ __func__);
+ return 0;
+ }
+ rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
+
+ return (flash_sz * 1024); /* Return size in kbytes */
+}
+
+/**
+ * ping_pong_write() - This function writes the flash contents throgh ping
+ * pong buffers
+ * @adapter: Pointer to the hardware structure.
+ * @cmd: command ping/pong write
+ * @addr: address to write
+ * @size: size
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ u32 block_size = 0;
+ u32 cmd_addr;
+ u16 cmd_resp = 0, cmd_req = 0;
+ u8 *str;
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO)
+ block_size = 256;
+ else
+ block_size = 252;
+
+ if (cmd == PING_WRITE) {
+ cmd_addr = PING_BUFFER_ADDRESS;
+ cmd_resp = PONG_AVAIL;
+ cmd_req = PING_VALID;
+ str = "PING_VALID";
+ } else {
+ cmd_addr = PONG_BUFFER_ADDRESS;
+ cmd_resp = PING_AVAIL;
+ cmd_req = PONG_VALID;
+ str = "PONG_VALID";
+ }
+
+ if (hif_ops->load_data_master_write(adapter,
+    cmd_addr,
+    size,
+    block_size,
+    addr)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
+ __func__, *addr);
+ goto fail;
+ }
+ if (bl_cmd(adapter, cmd_req, cmd_resp, str) < 0) {
+ bl_stop_cmd_timer(adapter);
+ goto fail;
+ }
+ return 0;
+
+fail:
+ return -1;
+}
+
+/**
+ * auto_fw_upgrade() - This function loads the firmware to device
+ * @adapter: Pointer to the hardware structure.
+ * @flash_content: Firmware to load
+ * @content_size: Size of the firmware
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int auto_fw_upgrade(struct rsi_hw *adapter,
+   u8 *flash_content,
+   u32 content_size)
+{
+ u8 cmd;
+ u8 *temp_flash_content;
+ u32 temp_content_size;
+ u32 num_flash;
+ u32 index;
+ u32 flash_start_address;
+
+ temp_flash_content = flash_content;
+
+ if (content_size > MAX_FLASH_FILE_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content size is more than 400K %u\n",
+ __func__, MAX_FLASH_FILE_SIZE);
+ goto fail;
+ }
+
+ flash_start_address = cpu_to_le32(
+ *(u32 *)&flash_content[FLASHING_START_ADDRESS]);
+ rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
+
+ if (flash_start_address < FW_IMAGE_MIN_ADDRESS) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Fw image Flash Start Address is less than 64K\n",
+ __func__);
+ goto fail;
+ }
+
+ if (flash_start_address % FLASH_SECTOR_SIZE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Start Address is not multiple of 4K\n",
+ __func__);
+ goto fail;
+ }
+
+ if ((flash_start_address + content_size) > adapter->flash_capacity) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Flash Content will cross max flash size\n",
+ __func__);
+ goto fail;
+ }
+
+ temp_content_size  = content_size;
+ num_flash = content_size / FLASH_WRITE_CHUNK_SIZE;
+
+ rsi_dbg(INFO_ZONE, "content_size: %d\n", content_size);
+ rsi_dbg(INFO_ZONE, "num_flash: %d\n", num_flash);
+
+ for (index = 0; index <= num_flash; index++) {
+ rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
+ if (index != num_flash) {
+ content_size = FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE,
+ "QSPI content_size:%d\n",
+ content_size);
+ } else {
+ content_size =
+ temp_content_size % FLASH_WRITE_CHUNK_SIZE;
+ rsi_dbg(INFO_ZONE,
+ "Writing last sector content_size:%d\n",
+ content_size);
+ if (!content_size) {
+ rsi_dbg(INFO_ZONE, "INSTRUCTION SIZE ZERO\n");
+ break;
+ }
+ }
+
+ if (index % 2)
+ cmd = PING_WRITE;
+ else
+ cmd = PONG_WRITE;
+
+ if (ping_pong_write(adapter,
+    cmd,
+    flash_content,
+    content_size)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to load %d block\n",
+ __func__, index);
+ goto fail;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Successfully loaded %d instructions\n",
+ __func__, index);
+ flash_content += content_size;
+ }
+
+ if (bl_cmd(adapter, EOF_REACHED, FW_LOADING_SUCCESSFUL,
+   "EOF_REACHED") < 0) {
+ bl_stop_cmd_timer(adapter);
+ goto fail;
+ }
+ rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
+ return 0;
+
+fail:
+ return -1;
+}
+
+/**
+ * read_flash_content() - This function reads the flash content
+ * from device
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+static int read_flash_content(struct rsi_hw *adapter,
+      u8 *temp_buf,
+      u32 address,
+      u32 len)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO) {
+ if (hif_ops->master_access_msword(adapter,
+  address >> 16) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return -1;
+ }
+ address &= 0xFFFF;
+ return hif_ops->read_reg_multiple(adapter,
+  address | SD_REQUEST_MASTER,
+  temp_buf, len);
+ } else {
+ return hif_ops->read_reg_multiple(adapter, address,
+  temp_buf, len);
+ }
+
+ return 0;
+}
+
+/**
+ * verify_flash_content() - This function verifies the loaded flash content
+ * from device
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int verify_flash_content(struct rsi_hw *adapter,
+ u8 *flash_content,
+ u32 instructions_sz,
+ u32 eeprom_offset,
+ u8  read_mode)
+{
+ int status = 0;
+ u32 num_loops = 0, idx;
+ u32 chunk_size = 0;
+ u8 *dest_addr = NULL;
+ u32 addr = 0;
+ u32 flash_chunk_size;
+
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_USB)
+ flash_chunk_size = USB_FLASH_READ_CHUNK_SIZE;
+ else
+ flash_chunk_size = SDIO_FLASH_READ_CHUNK_SIZE;
+
+ num_loops = instructions_sz / flash_chunk_size;
+
+ if (instructions_sz % flash_chunk_size)
+ num_loops++;
+
+ if (read_mode != EEPROM_READ_MODE) {
+ dest_addr  = kzalloc(instructions_sz, GFP_KERNEL);
+ if (!dest_addr) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Memory allocation for dest_addr failed\n",
+ __func__);
+ return -1;
+ }
+ }
+
+ rsi_dbg(INFO_ZONE, "Number of loops required: %d\n", num_loops);
+ for (idx = 0; idx < num_loops; idx++) {
+ if (instructions_sz < flash_chunk_size)
+ chunk_size = instructions_sz;
+ else
+ chunk_size = flash_chunk_size;
+ rsi_dbg(INFO_ZONE, "idx is %d and chunk size is %d\n",
+ idx, chunk_size);
+ if (read_mode == EEPROM_READ_MODE) {
+ adapter->eeprom.offset = eeprom_offset;
+ rsi_dbg(INFO_ZONE,
+ "eeprom offset is %x\n", eeprom_offset);
+ adapter->eeprom.length = chunk_size;
+ status = rsi_flash_read(adapter);
+ if (status == 0) {
+ rsi_dbg(INFO_ZONE,
+ "%s: BLOCK/SECTOR READING SUCCESSFUL\n",
+ __func__);
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: READING FROM FLASH FAILED\n",
+ __func__);
+ return -1;
+ }
+ } else {
+ memset(dest_addr, 0, chunk_size);
+ addr = SOC_FLASH_ADDR + eeprom_offset;
+ rsi_dbg(INFO_ZONE,
+ "Reading flash addr 0x%0x\n", addr);
+ if (read_flash_content(adapter, dest_addr, addr,
+       flash_chunk_size) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s:Failed to read calib data\n",
+ __func__);
+ status = -1;
+ goto out;
+ }
+ }
+ if (read_mode == EEPROM_READ_MODE) {
+ /* Wait for receive packet */
+ mdelay(10);
+ dest_addr = adapter->priv->rx_data_pkt;
+ if (!dest_addr) {
+ rsi_dbg(ERR_ZONE,
+ "Failed reading flash content\n");
+ status = -1;
+ goto out;
+ }
+ }
+ if (memcmp(&flash_content[idx * flash_chunk_size],
+   dest_addr,
+   chunk_size)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: VERIFICATION OF FLASH CHUNK FAILED\n",
+ __func__);
+ kfree(dest_addr);
+ status = -1;
+ goto out;
+ }
+ eeprom_offset += chunk_size;
+ instructions_sz -= chunk_size;
+ }
+
+out:
+ if (read_mode == MASTER_READ_MODE)
+ kfree(dest_addr);
+ return 0;
+}
+
+/**
+ * rsi_load_9113_firmware () - This function loads the TA firmware for 9113
+ * device.
+ * @adapter: Pointer to the rsi hw.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_load_9113_firmware(struct rsi_hw *adapter)
+{
+ struct rsi_host_intf_ops *hif_ops = adapter->host_intf_ops;
+ const struct firmware *fw_entry = NULL;
+ u32 regout_val = 0;
+ u16 tmp_regout_val = 0;
+ u8 *flash_content = NULL;
+ u32 content_size = 0;
+ struct ta_metadata *metadata_p;
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+
+ while (!adapter->blcmd_timer_expired) {
+ if ((hif_ops->master_reg_read(adapter,
+      SWBL_REGOUT,
+      &regout_val,
+      2)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: REGOUT read failed\n", __func__);
+ goto fail;
+ }
+ mdelay(1);
+ if ((regout_val >> 8) == REGOUT_VALID)
+ break;
+ }
+ if (adapter->blcmd_timer_expired) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
+ rsi_dbg(ERR_ZONE,
+ "%s: Soft boot loader not present\n", __func__);
+ goto fail;
+ }
+ bl_stop_cmd_timer(adapter);
+
+ rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
+ (regout_val & 0xff));
+
+ if ((hif_ops->master_reg_write(adapter,
+       SWBL_REGOUT,
+       (REGOUT_INVALID | REGOUT_INVALID << 8),
+       2)) < 0) {
+ rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
+ goto fail;
+ }
+ mdelay(1);
+
+ if ((bl_cmd(adapter, CONFIG_AUTO_READ_MODE, CMD_PASS,
+    "AUTO_READ_CMD")) < 0)
+ goto fail;
+
+ adapter->flash_capacity = read_flash_capacity(adapter);
+ if (adapter->flash_capacity <= 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to read flash size from EEPROM\n",
+ __func__);
+ goto fail;
+ }
+
+ metadata_p = &metadata_flash_content[adapter->priv->coex_mode];
+
+ rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name);
+
+ if ((request_firmware(&fw_entry, metadata_p->name,
+      adapter->device)) < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+ __func__, metadata_p->name);
+ goto fail;
+ }
+ flash_content = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!flash_content) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
+ goto fail;
+ }
+ content_size = fw_entry->size;
+ rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
+
+ if (bl_write_header(adapter, flash_content, content_size)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: RPS Image header loading failed\n",
+ __func__);
+ goto fail;
+ }
+
+ bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
+ if (bl_write_cmd(adapter, CHECK_CRC, CMD_PASS, &tmp_regout_val) < 0) {
+ bl_stop_cmd_timer(adapter);
+ rsi_dbg(ERR_ZONE,
+ "%s: CHECK_CRC Command writing failed..\n",
+ __func__);
+ if ((tmp_regout_val & 0xff) == CMD_FAIL) {
+ rsi_dbg(ERR_ZONE,
+ "CRC Fail.. Proceeding to Upgrade mode\n");
+ goto fw_upgrade;
+ }
+ }
+ bl_stop_cmd_timer(adapter);
+
+ if (bl_cmd(adapter, POLLING_MODE, CMD_PASS, "POLLING_MODE") < 0)
+ goto fail;
+
+load_image_cmd:
+ if ((bl_cmd(adapter,
+    LOAD_HOSTED_FW,
+    LOADING_INITIATED,
+    "LOAD_HOSTED_FW")) < 0)
+ goto fail;
+ rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
+ goto success;
+
+fw_upgrade:
+ /* After burning the RPS header, firmware has to be
+ * burned using the below steps
+ */
+ if (bl_cmd(adapter, BURN_HOSTED_FW, SEND_RPS_FILE, "FW_UPGRADE") < 0)
+ goto fail;
+
+ rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
+
+ if (auto_fw_upgrade(adapter, flash_content, content_size) == 0) {
+ rsi_dbg(ERR_ZONE, "***** Auto firmware successful *****\n");
+ goto load_image_cmd;
+ }
+
+ if (bl_cmd(adapter, CONFIG_AUTO_READ_MODE,
+   CMD_PASS, "AUTO_READ_MODE") < 0)
+ goto fail;
+
+ /* Not required for current flash mode */
+#if 0
+ rsi_dbg(INFO_ZONE, "Starting Flash Verification Process\n");
+
+ if ((verify_flash_content(adapter,
+  flash_content,
+  EEPROM_DATA_SIZE,
+  0,
+  EEPROM_READ_MODE)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: FLASHING SBL failed in Calib VERIFICATION phase\n",
+ __func__);
+ goto fail;
+ }
+ if ((verify_flash_content(adapter,
+  flash_content + BL_HEADER,
+  (content_size - BL_HEADER),
+  EEPROM_DATA_SIZE,
+  MASTER_READ_MODE)) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s:FLASHING SBL failed in SBL VERIFICATION phase\n",
+ __func__);
+ goto fail;
+ }
+ rsi_dbg(INFO_ZONE,
+ "Flash Verification Process Completed Successfully\n");
+#endif
+ rsi_dbg(INFO_ZONE, "SWBL FLASHING THROUGH SWBL PASSED...\n");
+
+success:
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return 0;
+
+fail:
+ kfree(flash_content);
+ release_firmware(fw_entry);
+ return -1;
+}
+
+/**
+ * rsi_hal_device_init() - This function initializes the Device
+ * @adapter: Pointer to the hardware structure
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_hal_device_init(struct rsi_hw *adapter)
+{
+
+#ifdef CONFIG_RSI_HCI
+ adapter->priv->coex_mode = 4;
+#else
+ adapter->priv->coex_mode = 1;
+#endif
+ adapter->device_model = RSI_DEV_9113;
+ switch (adapter->device_model) {
+ case RSI_DEV_9110:
+ /* Add code for 9110 */
+ break;
+ case RSI_DEV_9113:
+ if (rsi_load_9113_firmware(adapter)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to load TA instructions\n",
+ __func__);
+ return -1;
+ }
+ break;
+ case RSI_DEV_9116:
+ /* Add code for 9116 */
+ break;
+ default:
+ return -1;
+ }
+ adapter->common_hal_fsm = COMMAN_HAL_WAIT_FOR_CARD_READY;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_hal_device_init);
+
+
diff --git a/ubuntu/rsi/rsi_91x_hci.c b/ubuntu/rsi/rsi_91x_hci.c
new file mode 100644
index 0000000..9524849
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_hci.c
@@ -0,0 +1,532 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "rsi_hci.h"
+#include "rsi_mgmt.h"
+#include "rsi_coex.h"
+#include "rsi_hal.h"
+
+#define RSI_BT_GENL_FAMILY "RSI-BTgenl"
+#define RSI_USER_A_MAX (__RSI_USER_A_MAX - 1)
+#define RSI_VERSION_NR 1
+
+static struct nla_policy bt_genl_policy[RSI_USER_A_MAX + 1] = {
+ [RSI_USER_A_MSG] = { .type = NLA_NUL_STRING },
+};
+
+static struct genl_family bt_genl_family = {
+ .id      = 0,
+ .hdrsize = 0,
+ .name    = RSI_BT_GENL_FAMILY,
+ .version = RSI_VERSION_NR,
+ .maxattr = RSI_USER_A_MAX,
+};
+
+static struct genl_ops bt_genl_ops = {
+ .cmd    = RSI_USER_C_CMD,
+ .flags  = 0,
+ .policy = bt_genl_policy,
+ .doit   = rsi_genl_recv,
+ .dumpit = NULL,
+};
+
+/* Global GCB */
+static struct genl_cb *global_gcb;
+
+/**
+ * rsi_hci_open() - This function is called when HCI device is
+ * opened
+ *
+ * @hdev - pointer to HCI device
+ * @return - 0 on success
+ */
+static int rsi_hci_open(struct hci_dev *hdev)
+{
+ rsi_dbg(ERR_ZONE, "RSI HCI DEVICE \"%s\" open\n", hdev->name);
+
+ if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+ rsi_dbg(ERR_ZONE, "%s: device `%s' already running\n",
+ __func__, hdev->name);
+
+ return 0;
+}
+
+/**
+ * rsi_hci_close() - This function is called when HCI device is
+ * closed
+ *
+ * @hdev - pointer to HCI device
+ * @return - 0 on success
+ */
+static int rsi_hci_close(struct hci_dev *hdev)
+{
+ rsi_dbg(ERR_ZONE, "RSI HCI DEVICE \"%s\" closed\n", hdev->name);
+
+ if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+ rsi_dbg(ERR_ZONE, "%s: device `%s' not running\n",
+ __func__, hdev->name);
+
+ return 0;
+}
+
+/**
+ * rsi_hci_flush() - This function is called when HCI device is
+ * flushed
+ *
+ * @hdev - pointer to HCI device
+ * @return - 0 on success; negative error code on failure
+ */
+static int rsi_hci_flush(struct hci_dev *hdev)
+{
+ struct rsi_hci_adapter *h_adapter;
+
+ if (!(h_adapter = hci_get_drvdata(hdev)))
+ return -EFAULT;
+
+ rsi_dbg(ERR_ZONE, "RSI `%s' flush\n", hdev->name);
+
+ return 0;
+}
+
+/**
+ * rsi_hci_send_pkt() - This function is used send the packet received
+ * from HCI layer to co-ex module
+ *
+ * @hdev - pointer to HCI device
+ * @skb - Received packet from HCI
+ * @return - 0 on success; negative error code on failure
+ *  
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION (3, 13, 0)
+static int rsi_hci_send_pkt(struct sk_buff *skb)
+#else
+static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
+#endif
+{
+ struct rsi_hci_adapter *h_adapter;
+ struct sk_buff *new_skb = NULL;
+#if LINUX_VERSION_CODE < KERNEL_VERSION (3, 13, 0)
+ struct hci_dev *hdev = (struct hci_dev *)skb->dev;
+#endif
+ int status = 0;
+
+ if (skb->len <= 0) {
+ rsi_dbg(ERR_ZONE, "Zero length packet\n");
+ //hdev->sta.err_tx++;
+ status = -EINVAL;
+ goto fail;
+ }
+
+ if (!(h_adapter = hci_get_drvdata(hdev))) {
+ //hdev->sta.err_tx++;
+ status = -EFAULT;
+ goto fail;
+ }
+
+ if (h_adapter->fsm_state != BT_DEVICE_READY) {
+ rsi_dbg(ERR_ZONE, "BT Device not ready\n");
+ status = -ENODEV;
+ goto fail;
+ }
+
+ if (!test_bit(HCI_RUNNING, &hdev->flags)) {
+ status = -EBUSY;
+ goto fail;
+ }
+
+ switch (bt_cb(skb)->pkt_type) {
+ case HCI_COMMAND_PKT:
+ hdev->stat.cmd_tx++;
+ break;
+
+ case HCI_ACLDATA_PKT:
+ hdev->stat.acl_tx++;
+ break;
+
+ case HCI_SCODATA_PKT:
+ hdev->stat.sco_tx++;
+ break;
+
+ default:
+ dev_kfree_skb(skb);
+ status = -EILSEQ;
+ goto fail;
+ }
+
+ if (skb_headroom(skb) < REQUIRED_HEADROOM_FOR_BT_HAL) {
+               /* Re-allocate one more skb with sufficent headroom
+ * make copy of input-skb to new one */
+ u16 new_len = skb->len + REQUIRED_HEADROOM_FOR_BT_HAL;
+
+ new_skb = dev_alloc_skb(new_len);
+ if (!new_skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+ skb_reserve(new_skb, REQUIRED_HEADROOM_FOR_BT_HAL);
+                skb_put(new_skb, skb->len);
+ memcpy(new_skb->data, skb->data, skb->len);
+ bt_cb(new_skb)->pkt_type = bt_cb(skb)->pkt_type;
+                dev_kfree_skb(skb);
+                skb = new_skb;
+ }
+
+        rsi_hex_dump(DATA_RX_ZONE, "TX BT Pkt", skb->data, skb->len);
+
+#ifdef CONFIG_RSI_COEX
+ rsi_coex_send_pkt(h_adapter->priv, skb, RSI_BT_Q);
+#else
+        rsi_send_bt_pkt(h_adapter->priv, skb);
+#endif
+ return 0;
+
+fail:
+ return status;
+}
+
+int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
+{
+ struct sk_buff *skb = NULL;
+        struct rsi_hci_adapter *h_adapter;
+ struct hci_dev *hdev = NULL;
+ int pkt_len = rsi_get_length(pkt, 0);
+ u8 queue_no = rsi_get_queueno(pkt, 0);
+
+ rsi_dbg(INFO_ZONE, "qno:%d, len:%d, fsm:%d",
+ queue_no, pkt_len, common->fsm_state);
+
+ if (pkt[14] == BT_CARD_READY_IND) {
+ rsi_dbg(INIT_ZONE, "%s: ===> BT Card Ready Received <===\n",
+ __func__);
+
+ rsi_dbg(INFO_ZONE, "Attaching HCI module\n");
+
+ if (rsi_hci_attach(common)) {
+ rsi_dbg(ERR_ZONE, "Failed to attach HCI module\n");
+ return 0;
+ }
+
+#ifdef CONFIG_RSI_COEX
+ if (rsi_coex_init(common)) {
+ rsi_dbg(ERR_ZONE, "Failed to init COEX module\n");
+ goto err;
+ }
+#endif
+                h_adapter = (struct rsi_hci_adapter *)common->hci_adapter;
+ h_adapter->fsm_state = BT_DEVICE_READY;
+ return 0;
+ }
+                
+        h_adapter = (struct rsi_hci_adapter *)common->hci_adapter;
+
+ if (h_adapter->fsm_state != BT_DEVICE_READY) {
+ rsi_dbg(INFO_ZONE, "BT Device not ready\n");
+ return 0;
+ }
+
+ if (queue_no == RSI_BT_MGMT_Q) {
+ u8 msg_type = pkt[14] & 0xFF;
+
+ switch (msg_type) {
+ case RESULT_CONFIRM:
+ rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ return 0;
+ case BT_PER:
+ rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ return 0;
+ case BT_BER:
+ rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ return 0;
+ case BT_CW:
+ rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ skb = dev_alloc_skb(pkt_len);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n", __func__);
+ return -ENOMEM;
+ }
+        hdev = h_adapter->hdev;
+ memcpy(skb->data, pkt + FRAME_DESC_SZ, pkt_len);
+ skb_put(skb, pkt_len);
+ h_adapter->hdev->stat.byte_rx += skb->len;
+
+ skb->dev = (void *)hdev;
+ bt_cb(skb)->pkt_type = pkt[14];
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
+ return hci_recv_frame(skb);
+#else
+ return hci_recv_frame(hdev, skb);
+#endif
+}
+EXPORT_SYMBOL_GPL(rsi_hci_recv_pkt);
+
+/**
+ * rsi_genl_recv() - This function gets the command request from
+ * user space over netlink socket
+ *            
+ * @skb pointer to sk_buff structure
+ * @info read command info pointer
+ *
+ * @return 0 on success, negative error code on failure
+ */
+int rsi_genl_recv(struct sk_buff *skb, struct genl_info *info)
+{
+ struct rsi_hci_adapter *h_adapter = NULL;
+ struct genl_cb *gcb;
+ struct nlattr *na;
+ u8 *data;
+ int rc = -1, len, pkttype;
+ u8 dword_align_req_bytes = 0;
+
+ if (!(gcb = global_gcb))
+ return -1;
+
+ if (!(h_adapter = global_gcb->gc_drvpriv))
+ return -1;
+
+ gcb->gc_pid = get_portid(info);
+ gcb->gc_seq = info->snd_seq;
+
+ na = info->attrs[RSI_USER_A_MSG];
+ if (na) {
+ data = (u8 *)nla_data(na);
+ if (!data) {
+ rsi_dbg(ERR_ZONE,
+ "%s: no data recevied on family `%s'\n",
+ __func__, gcb->gc_name);
+ goto err;
+ }
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: netlink attr is NULL on family `%s'\n",
+ __func__, gcb->gc_name);
+ goto err;
+ }
+ gcb->gc_info = NULL;
+ gcb->gc_skb = NULL;
+
+ pkttype = *(u16 *)&data[0];
+ len = *(u16 *)&data[2];
+
+ data += 16;
+
+ rsi_dbg(ERR_ZONE, "%s: len %x pkt_type %x\n",
+ __func__, len, pkttype);
+
+ rsi_hex_dump (DATA_RX_ZONE, "BT TX data", data, len);
+
+ skb = dev_alloc_skb(len + REQUIRED_HEADROOM_FOR_BT_HAL);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+ skb_reserve(skb, REQUIRED_HEADROOM_FOR_BT_HAL);
+ dword_align_req_bytes = ((u32)skb->data) & 0x3f;
+ if (dword_align_req_bytes)
+ skb_push(skb, dword_align_req_bytes);
+ memcpy(skb->data, data, len);
+ bt_cb(skb)->pkt_type = pkttype;
+
+#ifdef CONFIG_RSI_COEX
+ return rsi_coex_send_pkt(h_adapter->priv, skb, RSI_BT_Q);
+#else
+        return rsi_send_bt_pkt(h_adapter->priv, skb);
+#endif
+
+err:
+ rsi_dbg(ERR_ZONE, "%s: error(%d) occured\n", __func__, rc);
+ return rc;
+}
+
+
+/**
+ * rsi_hci_attach () - This function initializes HCI interface
+ *      
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int rsi_hci_attach(struct rsi_common *common)
+{
+ struct rsi_hci_adapter *h_adapter = NULL;
+ struct genl_cb *gcb = NULL;
+ struct hci_dev *hdev;
+ int status = 0;
+
+ rsi_dbg (ERR_ZONE, "%s: In alloc HCI adapter\n", __func__);
+ /* Allocate HCI adapter */
+ /* TODO: Check GFP_ATOMIC */
+ h_adapter = kzalloc(sizeof (*h_adapter), GFP_KERNEL);
+ if (!h_adapter) {
+ rsi_dbg (ERR_ZONE, "%s: Failed to alloc HCI adapter\n", __func__);
+ return -ENOMEM;
+ }
+ h_adapter->priv = common;
+
+ /* Create HCI Interface */
+ hdev = hci_alloc_dev();
+ if (!hdev) {
+ rsi_dbg (ERR_ZONE, "%s: Failed to alloc HCI device\n", __func__);
+ goto err;
+ }
+ h_adapter->hdev = hdev;
+
+ if (common->priv->rsi_host_intf == RSI_HOST_INTF_SDIO)
+ hdev->bus = HCI_SDIO;
+ else
+ hdev->bus = HCI_USB;
+
+ hci_set_drvdata(hdev, h_adapter);
+ hdev->dev_type = HCI_BREDR;
+
+ hdev->open = rsi_hci_open;
+ hdev->close = rsi_hci_close;
+ hdev->flush = rsi_hci_flush;
+ hdev->send = rsi_hci_send_pkt;
+#if LINUX_VERSION_CODE <= KERNEL_VERSION (3, 3, 8)
+ hdev->destruct = rsi_hci_destruct;
+ hdev->owner = THIS_MODULE;
+#endif
+
+        /* Initialize TX queue */
+ skb_queue_head_init(&h_adapter->hci_tx_queue);
+ common->hci_adapter = (void *)h_adapter;
+ rsi_dbg (ERR_ZONE, "%s: In alloc HCI adapter\n", __func__);
+ status = hci_register_dev(hdev);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: HCI registration failed with errcode %d\n",
+ __func__, status);
+ goto err;
+ }
+ rsi_dbg(INIT_ZONE, "HCI Interface Created with name \'%s\'\n",
+ hdev->name);
+
+ /* Register for general netlink operations */
+ /* TODO: Check GFP_ATOMIC */
+ gcb = kzalloc(sizeof(*gcb), GFP_KERNEL);
+ if (!gcb) {
+ rsi_dbg (ERR_ZONE, "%s: Failed to alloc genl control block\n",
+ __func__);
+ goto err;
+ }
+ h_adapter->gcb = gcb;
+ global_gcb = gcb;
+
+ gcb->gc_drvpriv = h_adapter;
+ gcb->gc_family = &bt_genl_family;
+ gcb->gc_policy = &bt_genl_policy[0];
+ gcb->gc_ops = &bt_genl_ops;
+ gcb->gc_n_ops = 1;
+ gcb->gc_name = RSI_BT_GENL_FAMILY;
+ gcb->gc_pid = gcb->gc_done = 0;
+
+ rsi_dbg(INIT_ZONE, "genl-register: nl_family `%s'\n", gcb->gc_name);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
+ gcb->gc_family->ops = gcb->gc_ops;
+ gcb->gc_family->n_ops = gcb->gc_n_ops;
+#endif
+
+ if (genl_register_family(gcb->gc_family)) {
+ rsi_dbg(ERR_ZONE, "%s: genl_register_family failed\n",
+ __func__);
+ goto err;
+ }
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION (3, 12, 34)
+ if (genl_register_ops(gcb->gc_family, gcb->gc_ops)) {
+ rsi_dbg(ERR_ZONE, "%s: genl_register_ops failed\n", __func__);
+ genl_unregister_family(family);
+ goto err;
+ }
+#endif
+ gcb->gc_done = 1;
+
+        //h_adapter->fsm_state = BT_DEVICE_READY;
+ rsi_dbg(ERR_ZONE, " HCI module init done...\n");
+
+ return 0;
+
+err:
+ if (hdev) {
+ hci_unregister_dev(hdev);
+ hci_free_dev(hdev);
+ h_adapter->hdev = NULL;
+ }
+ if (gcb) {
+ genl_unregister_family(gcb->gc_family);
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 12, 34)
+ genl_unregister_ops(gcb->gc_family, gcb->gc_ops);
+#endif
+ }
+ h_adapter->gcb = NULL;
+ kfree(h_adapter);
+
+ return -EINVAL;
+}
+
+/**
+ * rsi_hci_attach () - This function initializes HCI interface
+ *      
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+void rsi_hci_detach(struct rsi_common *common)
+{
+ struct rsi_hci_adapter *h_adapter =
+ (struct rsi_hci_adapter *)common->hci_adapter;
+ struct hci_dev *hdev;
+ struct genl_cb *gcb;
+
+ rsi_dbg(INFO_ZONE, "Detaching HCI...\n");
+
+ if (!h_adapter)
+ return;
+
+ hdev = h_adapter->hdev;
+ if (hdev) {
+                //hci_dev_hold(hdev);
+ hci_unregister_dev(hdev);
+                //hci_dev_put(hdev);
+ hci_free_dev(hdev);
+ h_adapter->hdev = NULL;
+ }
+
+ gcb = h_adapter->gcb;
+ if (gcb) {
+ genl_unregister_family(gcb->gc_family);
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 12, 34)
+ genl_unregister_ops(gcb->gc_family, gcb->gc_ops);
+#endif
+ h_adapter->gcb = NULL;
+ }
+ kfree(h_adapter);
+
+ return;
+}
+EXPORT_SYMBOL_GPL(rsi_hci_attach);
+EXPORT_SYMBOL_GPL(rsi_hci_detach);
+
diff --git a/ubuntu/rsi/rsi_91x_mac80211.c b/ubuntu/rsi/rsi_91x_mac80211.c
new file mode 100644
index 0000000..9e989a7
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_mac80211.c
@@ -0,0 +1,1600 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if.h>
+#include <linux/version.h>
+#include "rsi_debugfs.h"
+#include "rsi_mgmt.h"
+#include "rsi_common.h"
+#include "rsi_ps.h"
+
+extern int g_bgscan_enable;
+
+static const struct ieee80211_channel rsi_2ghz_channels[] = {
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2412,
+  .hw_value = 1 }, /* Channel 1 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2417,
+  .hw_value = 2 }, /* Channel 2 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2422,
+  .hw_value = 3 }, /* Channel 3 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2427,
+  .hw_value = 4 }, /* Channel 4 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2432,
+  .hw_value = 5 }, /* Channel 5 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2437,
+  .hw_value = 6 }, /* Channel 6 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2442,
+  .hw_value = 7 }, /* Channel 7 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2447,
+  .hw_value = 8 }, /* Channel 8 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2452,
+  .hw_value = 9 }, /* Channel 9 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2457,
+  .hw_value = 10 }, /* Channel 10 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2462,
+  .hw_value = 11 }, /* Channel 11 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2467,
+  .hw_value = 12 }, /* Channel 12 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2472,
+  .hw_value = 13 }, /* Channel 13 */
+ { .band = NL80211_BAND_2GHZ, .center_freq = 2484,
+  .hw_value = 14 }, /* Channel 14 */
+};
+
+static const struct ieee80211_channel rsi_5ghz_channels[] = {
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5180,
+  .hw_value = 36,  }, /* Channel 36 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5200,
+  .hw_value = 40, }, /* Channel 40 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5220,
+  .hw_value = 44, }, /* Channel 44 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5240,
+  .hw_value = 48, }, /* Channel 48 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5260,
+  .hw_value = 52, }, /* Channel 52 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5280,
+  .hw_value = 56, }, /* Channel 56 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5300,
+  .hw_value = 60, }, /* Channel 60 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5320,
+  .hw_value = 64, }, /* Channel 64 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5500,
+  .hw_value = 100, }, /* Channel 100 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5520,
+  .hw_value = 104, }, /* Channel 104 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5540,
+  .hw_value = 108, }, /* Channel 108 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5560,
+  .hw_value = 112, }, /* Channel 112 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5580,
+  .hw_value = 116, }, /* Channel 116 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5600,
+  .hw_value = 120, }, /* Channel 120 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5620,
+  .hw_value = 124, }, /* Channel 124 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5640,
+  .hw_value = 128, }, /* Channel 128 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5660,
+  .hw_value = 132, }, /* Channel 132 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5680,
+  .hw_value = 136, }, /* Channel 136 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5700,
+  .hw_value = 140, }, /* Channel 140 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5745,
+  .hw_value = 149, }, /* Channel 149 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5765,
+  .hw_value = 153, }, /* Channel 153 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5785,
+  .hw_value = 157, }, /* Channel 157 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5805,
+  .hw_value = 161, }, /* Channel 161 */
+ { .band = NL80211_BAND_5GHZ, .center_freq = 5825,
+  .hw_value = 165, }, /* Channel 165 */
+};
+
+struct ieee80211_rate rsi_rates[12] = {
+ { .bitrate = STD_RATE_01  * 5, .hw_value = RSI_RATE_1 },
+ { .bitrate = STD_RATE_02  * 5, .hw_value = RSI_RATE_2 },
+ { .bitrate = STD_RATE_5_5 * 5, .hw_value = RSI_RATE_5_5 },
+ { .bitrate = STD_RATE_11  * 5, .hw_value = RSI_RATE_11 },
+ { .bitrate = STD_RATE_06  * 5, .hw_value = RSI_RATE_6 },
+ { .bitrate = STD_RATE_09  * 5, .hw_value = RSI_RATE_9 },
+ { .bitrate = STD_RATE_12  * 5, .hw_value = RSI_RATE_12 },
+ { .bitrate = STD_RATE_18  * 5, .hw_value = RSI_RATE_18 },
+ { .bitrate = STD_RATE_24  * 5, .hw_value = RSI_RATE_24 },
+ { .bitrate = STD_RATE_36  * 5, .hw_value = RSI_RATE_36 },
+ { .bitrate = STD_RATE_48  * 5, .hw_value = RSI_RATE_48 },
+ { .bitrate = STD_RATE_54  * 5, .hw_value = RSI_RATE_54 },
+};
+
+const u16 rsi_mcsrates[8] = {
+ RSI_RATE_MCS0, RSI_RATE_MCS1, RSI_RATE_MCS2, RSI_RATE_MCS3,
+ RSI_RATE_MCS4, RSI_RATE_MCS5, RSI_RATE_MCS6, RSI_RATE_MCS7
+};
+
+/**
+ * rsi_is_cipher_wep() -  This function determines if the cipher is WEP or not.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: If cipher type is WEP, a value of 1 is returned, else 0.
+ */
+
+bool rsi_is_cipher_wep(struct rsi_common *common)
+{
+ if (((common->secinfo.gtk_cipher == WLAN_CIPHER_SUITE_WEP104) ||
+     (common->secinfo.gtk_cipher == WLAN_CIPHER_SUITE_WEP40)) &&
+    (!common->secinfo.ptk_cipher))
+ return true;
+ else
+ return false;
+}
+
+/**
+ * rsi_register_rates_channels() - This function registers channels and rates.
+ * @adapter: Pointer to the adapter structure.
+ * @band: Operating band to be set.
+ *
+ * Return: None.
+ */
+static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
+{
+ struct ieee80211_supported_band *sbands = &adapter->sbands[band];
+ void *channels = NULL;
+
+ if (band == NL80211_BAND_2GHZ) {
+ channels = kzalloc(sizeof(rsi_2ghz_channels), GFP_KERNEL);
+ memcpy(channels,
+       rsi_2ghz_channels,
+       sizeof(rsi_2ghz_channels));
+ sbands->band = NL80211_BAND_2GHZ;
+ sbands->n_channels = ARRAY_SIZE(rsi_2ghz_channels);
+ sbands->bitrates = rsi_rates;
+ sbands->n_bitrates = ARRAY_SIZE(rsi_rates);
+ } else {
+ channels = kzalloc(sizeof(rsi_5ghz_channels), GFP_KERNEL);
+ memcpy(channels,
+       rsi_5ghz_channels,
+       sizeof(rsi_5ghz_channels));
+ sbands->band = NL80211_BAND_5GHZ;
+ sbands->n_channels = ARRAY_SIZE(rsi_5ghz_channels);
+ sbands->bitrates = &rsi_rates[4];
+ sbands->n_bitrates = ARRAY_SIZE(rsi_rates) - 4;
+ }
+
+ sbands->channels = channels;
+
+ memset(&sbands->ht_cap, 0, sizeof(struct ieee80211_sta_ht_cap));
+ sbands->ht_cap.ht_supported = true;
+ sbands->ht_cap.cap = (IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+      IEEE80211_HT_CAP_SGI_20 |
+      IEEE80211_HT_CAP_SGI_40);
+ sbands->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K;
+ sbands->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE;
+ sbands->ht_cap.mcs.rx_mask[0] = 0xff;
+ sbands->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+ /* sbands->ht_cap.mcs.rx_highest = 0x82; */
+}
+
+/**
+ * rsi_mac80211_detach() - This function is used to de-initialize the
+ *   Mac80211 stack.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+void rsi_mac80211_detach(struct rsi_hw *adapter)
+{
+ struct ieee80211_hw *hw = adapter->hw;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+ enum nl80211_band band;
+#else
+ int band;
+#endif
+
+ rsi_dbg(INFO_ZONE, "Detach mac80211...\n");
+
+ if (hw) {
+ ieee80211_stop_queues(hw);
+ ieee80211_unregister_hw(hw);
+ ieee80211_free_hw(hw);
+ }
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+ for (band = 0; band < NUM_NL80211_BANDS; band++) {
+#else
+ for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+#endif
+ struct ieee80211_supported_band *sband =
+ &adapter->sbands[band];
+
+ kfree(sband->channels);
+ }
+
+#ifdef CONFIG_RSI_DEBUGFS
+ rsi_remove_dbgfs(adapter);
+ kfree(adapter->dfsentry);
+#endif
+}
+EXPORT_SYMBOL_GPL(rsi_mac80211_detach);
+
+/**
+ * rsi_indicate_tx_status() - This function indicates the transmit status.
+ * @adapter: Pointer to the adapter structure.
+ * @skb: Pointer to the socket buffer structure.
+ * @status: Status
+ *
+ * Return: None.
+ */
+void rsi_indicate_tx_status(struct rsi_hw *adapter,
+    struct sk_buff *skb,
+    int status)
+{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ memset(info->driver_data, 0, IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
+
+ if (!status)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ ieee80211_tx_status_irqsafe(adapter->hw, skb);
+}
+
+/**
+ * rsi_mac80211_tx() - This is the handler that 802.11 module calls for each
+ *       transmitted frame.SKB contains the buffer starting
+ *       from the IEEE 802.11 header.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @control: Pointer to the ieee80211_tx_control structure
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: None
+ */
+static void rsi_mac80211_tx(struct ieee80211_hw *hw,
+    struct ieee80211_tx_control *control,
+    struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+#ifndef CONFIG_RSI_HCI
+ rsi_core_xmit(common, skb);
+#else
+#ifndef CONFIG_RSI_COEX
+        ieee80211_free_txskb(common->priv->hw, skb);
+#endif
+#endif
+}
+
+/**
+ * rsi_mac80211_start() - This is first handler that 802.11 module calls, since
+ *  the driver init is complete by then, just
+ *  returns success.
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 as success.
+ */
+static int rsi_mac80211_start(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ rsi_dbg(ERR_ZONE, "===> Interface UP <===\n");
+ mutex_lock(&common->mutex);
+
+ common->iface_down = false;
+        wiphy_rfkill_start_polling(hw->wiphy);
+ rsi_send_rx_filter_frame(common, 0);
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+/**
+ * rsi_mac80211_stop() - This is the last handler that 802.11 module calls.
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: None.
+ */
+static void rsi_mac80211_stop(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
+
+ mutex_lock(&common->mutex);
+
+ common->iface_down = true;
+ wiphy_rfkill_stop_polling(hw->wiphy);
+
+ /* Block all rx frames */
+ rsi_send_rx_filter_frame(common, 0xffff);
+
+ mutex_unlock(&common->mutex);
+}
+
+/**
+ * rsi_mac80211_add_interface() - This function is called when a netdevice
+ *  attached to the hardware is enabled.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ *
+ * Return: ret: 0 on success, negative error code on failure.
+ */
+static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
+      struct ieee80211_vif *vif)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ int ret = 0;
+
+ rsi_dbg(INFO_ZONE, "Add Interface Called\n");
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+ vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
+#endif
+
+ mutex_lock(&common->mutex);
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ if (!adapter->sc_nvifs) {
+ ++adapter->sc_nvifs;
+ adapter->vifs[0] = vif;
+ ret = rsi_set_vap_capabilities(common,
+       STA_OPMODE,
+       VAP_ADD);
+ }
+ break;
+ default:
+ rsi_dbg(ERR_ZONE,
+ "%s: Interface type %d not supported\n",
+ __func__, vif->type);
+ }
+
+ mutex_unlock(&common->mutex);
+
+ return ret;
+}
+
+/**
+ * rsi_mac80211_remove_interface() - This function notifies driver that an
+ *     interface is going down.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ *
+ * Return: None.
+ */
+static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ rsi_dbg(INFO_ZONE, "Remove Interface Called\n");
+ mutex_lock(&common->mutex);
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ adapter->sc_nvifs--;
+ rsi_set_vap_capabilities(common, STA_OPMODE, VAP_DELETE);
+ }
+
+ if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))
+ adapter->vifs[0] = NULL;
+ mutex_unlock(&common->mutex);
+}
+
+/**
+ * rsi_channel_change() - This function is a performs the checks
+ *  required for changing a channel and sets
+ *  the channel accordingly.
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_channel_change(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ int status = -EOPNOTSUPP;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ u16 channel = curchan->hw_value;
+ struct ieee80211_bss_conf *bss = NULL;
+
+ if (adapter->sc_nvifs <= 0) {
+ rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
+ return -EINVAL;
+ }
+ bss = &adapter->vifs[0]->bss_conf;
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Set channel: %d MHz type: %d channel_no %d\n",
+ __func__, curchan->center_freq,
+ curchan->flags, channel);
+
+ common->mac80211_cur_channel = channel;
+ if (bss->assoc) {
+ rsi_dbg(INFO_ZONE, "%s: connected\n", __func__);
+
+ if (common->bgscan_en)
+ return 0;
+
+ if (!common->hw_data_qs_blocked &&
+    (rsi_get_connected_channel(adapter) != channel)) {
+ rsi_dbg(INFO_ZONE, "blk data q %d\n", channel);
+ if (!rsi_send_block_unblock_frame(common, true))
+ common->hw_data_qs_blocked = true;
+ }
+ } else {
+ rsi_dbg(INFO_ZONE, "assoc status:%d channel:%d\n",
+ bss->assoc, channel);
+ }
+
+ status = rsi_band_check(common);
+ if (!status)
+ status = rsi_set_channel(adapter->priv, curchan);
+
+ if (bss->assoc) {
+ if (common->hw_data_qs_blocked &&
+    (rsi_get_connected_channel(adapter) == channel)) {
+ rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
+ }
+ } else {
+ if (common->hw_data_qs_blocked) {
+ rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * rsi_config_power() - This function configures tx power in device
+ * @hw: Pointer to the ieee80211_hw structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_config_power(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+ int status;
+
+ if (adapter->sc_nvifs <= 0) {
+ rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
+ return -EINVAL;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Set tx power: %d dBM\n", __func__, conf->power_level);
+
+ if (conf->power_level == common->tx_power)
+ return 0;
+
+ common->tx_power = conf->power_level;
+
+ status = rsi_send_radio_params_update(common);
+
+ return status;
+}
+
+/**
+ * rsi_mac80211_config() - This function is a handler for configuration
+ *   requests. The stack calls this function to
+ *   change hardware configuration, e.g., channel.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @changed: Changed flags set.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_mac80211_config(struct ieee80211_hw *hw,
+       u32 changed)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+ int status = -EOPNOTSUPP;
+
+ mutex_lock(&common->mutex);
+
+ /* channel */
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
+ status = rsi_channel_change(hw);
+
+ /* listen interval */
+ if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
+ rsi_dbg(INFO_ZONE,
+ "listen_int = %d\n", conf->listen_interval);
+ adapter->ps_info.num_bcns_per_lis_int = conf->listen_interval;
+ }
+
+ /* tx power */
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ rsi_dbg(INFO_ZONE, "%s: Configuring Power\n", __func__);
+ status = rsi_config_power(hw);
+ }
+
+ /* retry limit */
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+ /* FIXME */
+ }
+
+ /* Power save parameters */
+ if (changed & IEEE80211_CONF_CHANGE_PS) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->ps_lock, flags);
+ if (conf->flags & IEEE80211_CONF_PS)
+ rsi_enable_ps(adapter);
+ else
+ rsi_disable_ps(adapter);
+ spin_unlock_irqrestore(&adapter->ps_lock, flags);
+ }
+
+ /* RTS threshold */
+ if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
+ rsi_dbg(INFO_ZONE,"RTS threshold\n");
+ if ((common->rts_threshold) <= IEEE80211_MAX_RTS_THRESHOLD) {
+ rsi_dbg(INFO_ZONE,
+ "%s: Sending vap updates....\n", __func__);
+ status = rsi_send_vap_dynamic_update(common);
+ }
+ }
+
+ mutex_unlock(&common->mutex);
+
+ return status;
+}
+
+/**
+ * rsi_get_connected_channel() - This function is used to get the current
+ * connected channel number.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: Current connected AP's channel number is returned.
+ */
+u16 rsi_get_connected_channel(struct rsi_hw *adapter)
+{
+ struct ieee80211_vif *vif = adapter->vifs[0];
+
+ if (vif) {
+ struct ieee80211_bss_conf *bss = &vif->bss_conf;
+ struct ieee80211_channel *channel = bss->chandef.chan;
+
+ return channel->hw_value;
+ }
+
+ return 0;
+}
+
+void rsi_resume_conn_channel(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+
+ mutex_lock(&common->mutex);
+ if (bss->assoc) {
+ struct ieee80211_channel *channel = bss->chandef.chan;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 6, 0))
+ if (channel->band == NL80211_BAND_5GHZ)
+#else
+ if (channel->band == IEEE80211_BAND_5GHZ)
+#endif
+       rsi_program_bb_rf(common);
+
+ rsi_set_channel(common, channel);
+ }
+ mutex_unlock(&common->mutex);
+}
+
+/**
+ * rsi_mac80211_bss_info_changed() - This function is a handler for config
+ *     requests related to BSS parameters that
+ *     may vary during BSS's lifespan.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @bss_conf: Pointer to the ieee80211_bss_conf structure.
+ * @changed: Changed flags set.
+ *
+ * Return: None.
+ */
+static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
+  struct ieee80211_vif *vif,
+  struct ieee80211_bss_conf *bss_conf,
+  u32 changed)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+ u16 rx_filter_word = 0;
+
+ rsi_dbg(INFO_ZONE, "%s: BSS status changed\n", __func__);
+ mutex_lock(&common->mutex);
+ if (changed & BSS_CHANGED_ASSOC) {
+ rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n",
+ __func__, bss_conf->assoc);
+ rsi_hex_dump(INFO_ZONE, "BSSID: ", bss->bssid, ETH_ALEN);
+ bss->assoc = bss_conf->assoc;
+ if (bss_conf->assoc) {
+ /* Send the RX filter frame */
+ rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
+  ALLOW_CTRL_ASSOC_PEER |
+  ALLOW_MGMT_ASSOC_PEER);// |
+  //DISALLOW_BEACONS);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ }
+ rsi_dbg(INFO_ZONE,
+ "assoc_status=%d, qos=%d, aid=%d\n",
+ bss->assoc, bss->qos, bss->aid);
+ rsi_dbg(INFO_ZONE,
+ "bssid=%02x:%02x:%02x:%02x:%02x:%02x",
+ bss->bssid[0], bss->bssid[1], bss->bssid[2],
+ bss->bssid[3], bss->bssid[4], bss->bssid[5]);
+ rsi_inform_bss_status(common,
+      bss->assoc,
+      bss->bssid,
+      bss->qos,
+      bss->aid);
+
+ adapter->ps_info.listen_interval =
+ bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
+ adapter->ps_info.deep_sleep_wakeup_period = bss->beacon_int;
+
+ /* If UAPSD is updated send ps params */
+ if (common->uapsd_bitmap) {
+ rsi_dbg(INFO_ZONE, "Configuring UAPSD\n");
+ rsi_conf_uapsd(adapter);
+ }
+ }
+
+ if (changed & BSS_CHANGED_CQM) {
+ rsi_dbg(INFO_ZONE, "%s: Changed CQM\n", __func__);
+ common->cqm_info.last_cqm_event_rssi = 0;
+ common->cqm_info.rssi_thold = bss_conf->cqm_rssi_thold;
+ common->cqm_info.rssi_hyst = bss_conf->cqm_rssi_hyst;
+ rsi_dbg(INFO_ZONE, "RSSI throld & hysteresis are: %d %d\n",
+ common->cqm_info.rssi_thold,
+ common->cqm_info.rssi_hyst);
+ }
+
+ if (changed & BSS_CHANGED_TXPOWER) {
+ rsi_dbg(INFO_ZONE, "%s: Changed TX power: %d\n",
+ __func__, bss_conf->txpower);
+ }
+
+ if (changed & BSS_CHANGED_BEACON_INT) {
+ rsi_dbg(INFO_ZONE, "%s: Changed Beacon interval: %d\n",
+ __func__, bss_conf->beacon_int);
+ adapter->ps_info.listen_interval =
+ bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
+ }
+
+ mutex_unlock(&common->mutex);
+}
+
+/**
+ * rsi_mac80211_conf_filter() - This function configure the device's RX filter.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @changed: Changed flags set.
+ * @total_flags: Total initial flags set.
+ * @multicast: Multicast.
+ *
+ * Return: None.
+ */
+static void rsi_mac80211_conf_filter(struct ieee80211_hw *hw,
+     u32 changed_flags,
+     u32 *total_flags,
+     u64 multicast)
+{
+#if 0
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u16 rx_filter_word = 0;
+#endif
+
+ /* Not doing much here as of now */
+ *total_flags &= RSI_SUPP_FILTERS;
+
+// rsi_send_rx_filter_frame(common, rx_filter_word);
+}
+
+/**
+ * rsi_mac80211_conf_tx() - This function configures TX queue parameters
+ *    (EDCF (aifs, cw_min, cw_max), bursting)
+ *    for a hardware TX queue.
+ * @hw: Pointer to the ieee80211_hw structure
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @queue: Queue number.
+ * @params: Pointer to ieee80211_tx_queue_params structure.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u8 idx = 0;
+
+ if (queue >= IEEE80211_NUM_ACS)
+ return 0;
+
+ rsi_dbg(INFO_ZONE,
+ "[Conf] queue:%d, aifs:%d, cwmin:%d cwmax:%d, txop:%d uapsd:%d\n",
+ queue, params->aifs, params->cw_min, params->cw_max,
+ params->txop, params->uapsd);
+
+ mutex_lock(&common->mutex);
+ /* Map into the way the f/w expects */
+ switch (queue) {
+ case IEEE80211_AC_VO:
+ idx = VO_Q;
+ break;
+ case IEEE80211_AC_VI:
+ idx = VI_Q;
+ break;
+ case IEEE80211_AC_BE:
+ idx = BE_Q;
+ break;
+ case IEEE80211_AC_BK:
+ idx = BK_Q;
+ break;
+ default:
+ idx = BE_Q;
+ break;
+ }
+
+ memcpy(&common->edca_params[idx],
+       params,
+       sizeof(struct ieee80211_tx_queue_params));
+ mutex_unlock(&common->mutex);
+
+ if (params->uapsd)
+ common->uapsd_bitmap |= idx;
+
+ return 0;
+}
+
+/**
+ * rsi_hal_key_config() - This function loads the keys into the firmware.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @key: Pointer to the ieee80211_key_conf structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+static int rsi_hal_key_config(struct ieee80211_hw *hw,
+      struct ieee80211_vif *vif,
+      struct ieee80211_key_conf *key)
+{
+ struct rsi_hw *adapter = hw->priv;
+ int status;
+ u8 key_type;
+
+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+ key_type = RSI_PAIRWISE_KEY;
+ else
+ key_type = RSI_GROUP_KEY;
+
+ rsi_dbg(ERR_ZONE, "%s: Cipher 0x%x key_type: %d key_len: %d\n",
+ __func__, key->cipher, key_type, key->keylen);
+
+ if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) ||
+    (key->cipher == WLAN_CIPHER_SUITE_WEP40)) {
+ status = rsi_load_key(adapter->priv,
+      key->key,
+      key->keylen,
+      RSI_PAIRWISE_KEY,
+      key->keyidx,
+      key->cipher);
+ if (status)
+ return status;
+ }
+ return rsi_load_key(adapter->priv,
+ key->key,
+ key->keylen,
+ key_type,
+ key->keyidx,
+ key->cipher);
+}
+
+/**
+ * rsi_mac80211_set_key() - This function sets type of key to be loaded.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @cmd: enum set_key_cmd.
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @sta: Pointer to the ieee80211_sta structure.
+ * @key: Pointer to the ieee80211_key_conf structure.
+ *
+ * Return: status: 0 on success, negative error code on failure.
+ */
+static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
+ enum set_key_cmd cmd,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct ieee80211_key_conf *key)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct security_info *secinfo = &common->secinfo;
+ int status;
+
+ mutex_lock(&common->mutex);
+ switch (cmd) {
+ case SET_KEY:
+ secinfo->security_enable = true;
+ status = rsi_hal_key_config(hw, vif, key);
+ if (status) {
+ mutex_unlock(&common->mutex);
+ return status;
+ }
+
+ if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+ secinfo->ptk_cipher = key->cipher;
+ else
+ secinfo->gtk_cipher = key->cipher;
+
+ key->hw_key_idx = key->keyidx;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+ rsi_dbg(ERR_ZONE, "%s: RSI set_key\n", __func__);
+ break;
+
+ case DISABLE_KEY:
+ secinfo->security_enable = false;
+ rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
+ memset(key, 0, sizeof(struct ieee80211_key_conf));
+ status = rsi_hal_key_config(hw, vif, key);
+ break;
+
+ default:
+ status = -EOPNOTSUPP;
+ break;
+ }
+
+ mutex_unlock(&common->mutex);
+ return status;
+}
+
+/**
+ * rsi_mac80211_ampdu_action() - This function selects the AMPDU action for
+ * the corresponding mlme_action flag and
+ * informs the f/w regarding this.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @action: ieee80211_ampdu_mlme_action enum.
+ * @sta: Pointer to the ieee80211_sta structure.
+ * @tid: Traffic identifier.
+ * @ssn: Pointer to ssn value.
+ * @buf_size: Buffer size (for kernel version > 2.6.38).
+ *
+ * Return: status: 0 on success, negative error code on failure.
+ */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
+static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
+     struct ieee80211_vif *vif,
+     enum ieee80211_ampdu_mlme_action action,
+     struct ieee80211_sta *sta,
+     u16 tid,
+     u16 *ssn,
+     u8 buf_size)
+#elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
+static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
+     struct ieee80211_vif *vif,
+     enum ieee80211_ampdu_mlme_action action,
+     struct ieee80211_sta *sta,
+     u16 tid,
+     u16 *ssn,
+     u8 buf_size,
+     bool amsdu)
+#else
+static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
+     struct ieee80211_vif *vif,
+     struct ieee80211_ampdu_params *params)
+#endif
+{
+ int status = 1;
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u16 seq_no = 0;
+ u8 ii = 0;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
+ u16 tid = params->tid;
+ u8 buf_size = params->buf_size;
+ enum ieee80211_ampdu_mlme_action action = params->action;
+ struct ieee80211_sta *sta = params->sta;
+#endif
+
+ for (ii = 0; ii < RSI_MAX_VIFS; ii++) {
+ if (vif == adapter->vifs[ii])
+ break;
+ }
+
+ mutex_lock(&common->mutex);
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
+ if (ssn != NULL)
+ seq_no = *ssn;
+#else
+ seq_no = params->ssn;
+#endif
+
+ rsi_dbg(INFO_ZONE,
+ "%s: AMPDU action tid=%d ssn=0x%x, buf_size=%d\n",
+ __func__, tid, seq_no, buf_size);
+
+ switch (action) {
+ case IEEE80211_AMPDU_RX_START:
+ rsi_dbg(INFO_ZONE, "AMPDU action RX_START (%d)\n", action);
+ status = rsi_send_aggr_params_frame(common,
+    tid,
+    seq_no,
+    buf_size,
+    STA_RX_ADDBA_DONE);
+ break;
+
+ case IEEE80211_AMPDU_RX_STOP:
+ rsi_dbg(INFO_ZONE,
+ "AMPDU action RX_STOP (%d) called\n", action);
+ status = rsi_send_aggr_params_frame(common,
+    tid,
+    0,
+    buf_size,
+    STA_RX_DELBA);
+ break;
+
+ case IEEE80211_AMPDU_TX_START:
+ rsi_dbg(INFO_ZONE,
+ "AMPDU action TX_START (%d) called\n", action);
+ common->vif_info[ii].seq_start = seq_no;
+ ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ status = 0;
+ break;
+
+ case IEEE80211_AMPDU_TX_STOP_CONT:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ rsi_dbg(INFO_ZONE,
+ "AMPDU action TX_STOP_CONT / TX_STOP_FLUSH /"
+ " TX_STOP_FLUSH_CONT (%d) called\n", action);
+ status = rsi_send_aggr_params_frame(common,
+    tid,
+    seq_no,
+    buf_size,
+    STA_TX_DELBA);
+ if (!status)
+ ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ break;
+
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
+ rsi_dbg(INFO_ZONE,
+ "AMPDU action TX_OPERATIONAL(%d) called\n",
+ action);
+ status = rsi_send_aggr_params_frame(common,
+ tid,
+ common->vif_info[ii].seq_start,
+ buf_size,
+ STA_TX_ADDBA_DONE);
+ break;
+
+ default:
+ rsi_dbg(ERR_ZONE, "%s: Uknown AMPDU action\n", __func__);
+ break;
+ }
+
+ mutex_unlock(&common->mutex);
+ return status;
+}
+
+/**
+ * rsi_mac80211_set_rts_threshold() - This function sets rts threshold value.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @value: Rts threshold value.
+ *
+ * Return: 0 on success.
+ */
+static int rsi_mac80211_set_rts_threshold(struct ieee80211_hw *hw,
+  u32 value)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ mutex_lock(&common->mutex);
+ common->rts_threshold = value;
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+/**
+ * rsi_mac80211_set_rate_mask() - This function sets bitrate_mask to be used.
+ * @hw: Pointer to the ieee80211_hw structure
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @mask: Pointer to the cfg80211_bitrate_mask structure.
+ *
+ * Return: 0 on success.
+ */
+static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw,
+      struct ieee80211_vif *vif,
+      const struct cfg80211_bitrate_mask *mask)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ enum nl80211_band band = hw->conf.chandef.chan->band;
+
+ mutex_lock(&common->mutex);
+ common->fixedrate_mask[band] = 0;
+
+ if (mask->control[band].legacy == 0xfff) {
+ common->fixedrate_mask[band] =
+ (mask->control[band].ht_mcs[0] << 12);
+ } else {
+ common->fixedrate_mask[band] =
+ mask->control[band].legacy;
+ }
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+/**
+ * rsi_perform_cqm() - This function performs cqm.
+ * @common: Pointer to the driver private structure.
+ * @bssid: pointer to the bssid.
+ * @rssi: RSSI value.
+ */
+static void rsi_perform_cqm(struct rsi_common *common,
+    u8 *bssid,
+    s8 rssi)
+{
+ struct rsi_hw *adapter = common->priv;
+ s8 last_event = common->cqm_info.last_cqm_event_rssi;
+ int thold = common->cqm_info.rssi_thold;
+ u32 hyst = common->cqm_info.rssi_hyst;
+ enum nl80211_cqm_rssi_threshold_event event;
+
+ if (rssi < thold && (last_event == 0 || rssi < (last_event - hyst)))
+ event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+ else if (rssi > thold &&
+ (last_event == 0 || rssi > (last_event + hyst)))
+ event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+ else
+ return;
+
+ common->cqm_info.last_cqm_event_rssi = rssi;
+ rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
+ ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL);
+}
+
+void rsi_indicate_bcnmiss(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+
+ rsi_dbg(INFO_ZONE, "CQM: Notifying beacon miss\n" );
+ ieee80211_beacon_loss(adapter->vifs[0]);
+ return;
+}
+
+/**
+ * rsi_fill_rx_status() - This function fills rx status in
+ *  ieee80211_rx_status structure.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @skb: Pointer to the socket buffer structure.
+ * @common: Pointer to the driver private structure.
+ * @rxs: Pointer to the ieee80211_rx_status structure.
+ *
+ * Return: None.
+ */
+static void rsi_fill_rx_status(struct ieee80211_hw *hw,
+       struct sk_buff *skb,
+       struct rsi_common *common,
+       struct ieee80211_rx_status *rxs)
+{
+ struct ieee80211_bss_conf *bss = &common->priv->vifs[0]->bss_conf;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct skb_info *rx_params = (struct skb_info *)info->driver_data;
+ struct ieee80211_hdr *hdr;
+ char rssi = rx_params->rssi;
+ u8 hdrlen = 0;
+ u8 channel = rx_params->channel;
+ s32 freq;
+
+ hdr = ((struct ieee80211_hdr *)(skb->data));
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+ memset(info, 0, sizeof(struct ieee80211_tx_info));
+
+ rxs->signal = -(rssi);
+
+ rxs->band = common->band;
+
+ freq = ieee80211_channel_to_frequency(channel, rxs->band);
+
+ if (freq)
+ rxs->freq = freq;
+
+ if (ieee80211_has_protected(hdr->frame_control)) {
+ if (rsi_is_cipher_wep(common)) {
+ memmove(skb->data + 4, skb->data, hdrlen);
+ skb_pull(skb, 4);
+ } else {
+ memmove(skb->data + 8, skb->data, hdrlen);
+ skb_pull(skb, 8);
+ rxs->flag |= RX_FLAG_MMIC_STRIPPED;
+ }
+ rxs->flag |= RX_FLAG_DECRYPTED;
+ rxs->flag |= RX_FLAG_IV_STRIPPED;
+ }
+
+ /* CQM only for connected AP beacons, the RSSI is a weighted avg */
+ if (bss->assoc && ether_addr_equal(bss->bssid, hdr->addr2)) {
+ if (ieee80211_is_beacon(hdr->frame_control))
+ rsi_perform_cqm(common, hdr->addr2, rxs->signal);
+ }
+}
+
+/**
+ * rsi_indicate_pkt_to_os() - This function sends received packet to mac80211.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: None.
+ */
+void rsi_indicate_pkt_to_os(struct rsi_common *common,
+    struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
+
+ if ((common->iface_down) || (!adapter->sc_nvifs)) {
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ /* filling in the ieee80211_rx_status flags */
+ rsi_fill_rx_status(hw, skb, common, rx_status);
+
+ rsi_hex_dump(DATA_RX_ZONE, "802.11 RX packet", skb->data, skb->len);
+ ieee80211_rx_irqsafe(hw, skb);
+}
+
+static void rsi_set_min_rate(struct ieee80211_hw *hw,
+     struct ieee80211_sta *sta,
+     struct rsi_common *common)
+{
+ u8 band = hw->conf.chandef.chan->band;
+ u8 ii;
+ u32 rate_bitmap;
+ bool matched = false;
+
+ common->bitrate_mask[band] = sta->supp_rates[band];
+
+ rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]);
+
+ if (rate_bitmap & 0xfff) {
+ /* Find out the min rate */
+ for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {
+ if (rate_bitmap & BIT(ii)) {
+ common->min_rate = rsi_rates[ii].hw_value;
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ common->vif_info[0].is_ht = sta->ht_cap.ht_supported;
+
+ if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) {
+ for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) {
+ if ((rate_bitmap >> 12) & BIT(ii)) {
+ common->min_rate = rsi_mcsrates[ii];
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ if (!matched)
+ common->min_rate = 0xffff;
+}
+
+/**
+ * rsi_mac80211_sta_add() - This function notifies driver about a peer getting
+ *    connected.
+ * @hw: pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @sta: Pointer to the ieee80211_sta structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ rsi_hex_dump(INFO_ZONE, "Station Add: ", sta->addr, ETH_ALEN);
+
+ mutex_lock(&common->mutex);
+
+ rsi_set_min_rate(hw, sta, common);
+
+ if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
+    (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) {
+ common->vif_info[0].sgi = true;
+ }
+ if (g_bgscan_enable) {
+ if (!rsi_send_bgscan_params(common, 1)) {
+ if (!rsi_send_bgscan_probe_req(common)) {
+ rsi_dbg(INFO_ZONE,
+ "Background scan started ===>\n");
+ common->bgscan_en = 1;
+ }
+ }
+ }
+
+ if (sta->ht_cap.ht_supported)
+ ieee80211_start_tx_ba_session(sta, 0, 0);
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+/**
+ * rsi_mac80211_sta_remove() - This function notifies driver about a peer
+ *       getting disconnected.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @vif: Pointer to the ieee80211_vif structure.
+ * @sta: Pointer to the ieee80211_sta structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
+   struct ieee80211_vif *vif,
+   struct ieee80211_sta *sta)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+
+ rsi_hex_dump(INFO_ZONE, "Station Removed: ", sta->addr, ETH_ALEN);
+
+ /* Resetting all the fields to default values */
+ mutex_lock(&common->mutex);
+ memcpy((u8 *)bss->bssid, (u8 *)sta->addr, ETH_ALEN);
+ bss->qos = sta->wme;
+ common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
+ common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
+ common->min_rate = 0xffff;
+ common->vif_info[0].is_ht = false;
+ common->vif_info[0].sgi = false;
+ common->vif_info[0].seq_start = 0;
+ common->secinfo.ptk_cipher = 0;
+ common->secinfo.gtk_cipher = 0;
+ if (common->bgscan_en)
+ common->bgscan_en = 0;
+ mutex_unlock(&common->mutex);
+
+ if (!common->iface_down)
+ rsi_send_rx_filter_frame(common, 0);
+ return 0;
+}
+#if 0
+static void rsi_mac80211_sw_scan_start(struct ieee80211_hw *hw,
+       struct ieee80211_vif *vif,
+       const u8 *mac_addr)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+ u8 status = 0;
+// u16 rx_filter_word = 0;
+
+ if (!bss->assoc)
+ return;
+
+ mutex_lock(&common->mutex);
+
+ status = rsi_send_bgscan_params(common, 1);
+ if (!status) {
+ rsi_dbg(INFO_ZONE, "Background scan commensing\n");
+ if (!rsi_send_bgscan_probe_req(common))
+ common->bgscan_en = 1;
+ }
+
+ mutex_unlock(&common->mutex);
+
+ return ;
+}
+
+static void rsi_mac80211_sw_scan_stop(struct ieee80211_hw *hw,
+      struct ieee80211_vif *vif)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+// struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+// u16 rx_filter_word = 0;
+
+ mutex_lock(&common->mutex);
+
+ if (common->bgscan_en) {
+ if (!rsi_send_bgscan_params(common, 0))
+ common->bgscan_en = 0;
+ }
+#if 0
+ if (bss->assoc) {
+ rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
+ ALLOW_CTRL_ASSOC_PEER |
+ ALLOW_MGMT_ASSOC_PEER);
+ rsi_send_rx_filter_frame(common, rx_filter_word);
+ }
+
+ if (bss->assoc) {
+ if (!rsi_band_check(common)) {
+ rsi_set_channel(adapter->priv,
+ rsi_get_connected_channel(adapter));
+ }
+ }
+#endif
+
+ mutex_unlock(&common->mutex);
+
+ return;
+}
+#endif
+
+/**
+ * rsi_mac80211_set_antenna() - This function is used to configure
+ * tx and rx antennas.
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @tx_ant: Bitmap for tx antenna
+ * @rx_ant: Bitmap for rx antenna
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw,
+    u32 tx_ant, u32 rx_ant)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u32 antenna = 0;
+
+ if (tx_ant > 1 || rx_ant > 1) {
+ rsi_dbg(ERR_ZONE,
+ "Invalid antenna selection (tx: %d, rx:%d)\n",
+ tx_ant, rx_ant);
+ rsi_dbg(ERR_ZONE,
+ "Use 0 for int_ant, 1 for ext_ant\n");
+ return -EINVAL;
+ }
+
+ rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n",
+ __func__, tx_ant, rx_ant);
+
+ mutex_lock(&common->mutex);
+
+ antenna = tx_ant ? ANTENNA_SEL_UFL : ANTENNA_SEL_INT;
+ if (common->ant_in_use != antenna)
+ if (rsi_set_antenna(common, antenna))
+ goto fail_set_antenna;
+
+ rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n",
+ tx_ant ? "UFL" : "INT");
+
+ common->ant_in_use = antenna;
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+
+fail_set_antenna:
+ rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__);
+ mutex_unlock(&common->mutex);
+ return -EINVAL;
+}
+
+/**
+ * rsi_mac80211_get_antenna() - This function is used to configure
+ * tx and rx antennas.
+ *
+ * @hw: Pointer to the ieee80211_hw structure.
+ * @tx_ant: Bitmap for tx antenna
+ * @rx_ant: Bitmap for rx antenna
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mac80211_get_antenna(struct ieee80211_hw *hw,
+    u32 *tx_ant, u32 *rx_ant)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ mutex_lock(&common->mutex);
+
+ *tx_ant = (common->ant_in_use == ANTENNA_SEL_UFL) ? 1 : 0;
+ *rx_ant = 0;
+
+ mutex_unlock(&common->mutex);
+
+ return 0;
+}
+
+static void rsi_reg_notify(struct wiphy *wiphy,
+  struct regulatory_request *request)
+{
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+ struct rsi_hw * adapter = hw->priv;
+ int i;
+
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ if (ch->flags & IEEE80211_CHAN_RADAR)
+ ch->flags |= IEEE80211_CHAN_NO_IR;
+ }
+
+ rsi_dbg(INFO_ZONE,
+ "country = %s dfs_region = %d\n",
+ request->alpha2, request->dfs_region);
+ adapter->dfs_region = request->dfs_region;
+}
+
+void rsi_mac80211_rfkill_poll(struct ieee80211_hw *hw)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+
+ mutex_lock(&common->mutex);
+
+ if (common->fsm_state != FSM_MAC_INIT_DONE)
+ wiphy_rfkill_set_hw_state(hw->wiphy, true);
+ else
+ wiphy_rfkill_set_hw_state(hw->wiphy, false);
+
+ mutex_unlock(&common->mutex);
+}
+
+static struct ieee80211_ops mac80211_ops = {
+ .tx = rsi_mac80211_tx,
+ .start = rsi_mac80211_start,
+ .stop = rsi_mac80211_stop,
+ .add_interface = rsi_mac80211_add_interface,
+ .remove_interface = rsi_mac80211_remove_interface,
+ .config = rsi_mac80211_config,
+ .bss_info_changed = rsi_mac80211_bss_info_changed,
+ .conf_tx = rsi_mac80211_conf_tx,
+ .configure_filter = rsi_mac80211_conf_filter,
+ .set_key = rsi_mac80211_set_key,
+ .set_rts_threshold = rsi_mac80211_set_rts_threshold,
+ .set_bitrate_mask = rsi_mac80211_set_rate_mask,
+ .ampdu_action = rsi_mac80211_ampdu_action,
+ .sta_add = rsi_mac80211_sta_add,
+ .sta_remove = rsi_mac80211_sta_remove,
+ .set_antenna = rsi_mac80211_set_antenna,
+ .get_antenna = rsi_mac80211_get_antenna,
+        .rfkill_poll = rsi_mac80211_rfkill_poll
+};
+
+/**
+ * rsi_mac80211_attach() - This function is used to initialize Mac80211 stack.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_mac80211_attach(struct rsi_common *common)
+{
+ int status = 0;
+ struct ieee80211_hw *hw = NULL;
+ struct wiphy *wiphy = NULL;
+ struct rsi_hw *adapter = common->priv;
+ u8 addr_mask[ETH_ALEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x3};
+
+ rsi_dbg(INIT_ZONE, "%s: Performing mac80211 attach\n", __func__);
+
+ hw = ieee80211_alloc_hw(sizeof(struct rsi_hw), &mac80211_ops);
+ if (!hw) {
+ rsi_dbg(ERR_ZONE, "%s: ieee80211 hw alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ wiphy = hw->wiphy;
+
+ SET_IEEE80211_DEV(hw, adapter->device);
+
+ hw->priv = adapter;
+ adapter->hw = hw;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
+ ieee80211_hw_set(hw, SIGNAL_DBM);
+ ieee80211_hw_set(hw, HAS_RATE_CONTROL);
+ ieee80211_hw_set(hw, AMPDU_AGGREGATION);
+ ieee80211_hw_set(hw, SUPPORTS_PS);
+ ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);
+// ieee80211_hw_set(hw, CONNECTION_MONITOR);
+ ieee80211_hw_set(hw, SPECTRUM_MGMT);
+ ieee80211_hw_set(hw, MFP_CAPABLE);
+#else
+ hw->flags = IEEE80211_HW_SIGNAL_DBM |
+    IEEE80211_HW_HAS_RATE_CONTROL |
+    IEEE80211_HW_AMPDU_AGGREGATION |
+    IEEE80211_HW_SUPPORTS_PS |
+    IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
+//    IEEE80211_HW_CONNECTION_MONITOR |
+    IEEE80211_HW_MFP_CAPABLE |
+    0;
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
+ wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_RRM);
+#endif
+
+ hw->queues = MAX_HW_QUEUES;
+ hw->extra_tx_headroom = RSI_NEEDED_HEADROOM;
+
+ hw->max_rates = 1;
+ hw->max_rate_tries = MAX_RETRIES;
+ hw->uapsd_queues = IEEE80211_MARKALL_UAPSD_QUEUES;
+ hw->uapsd_max_sp_len = IEEE80211_STA_SP_ALL_PKTS;
+ hw->max_tx_aggregation_subframes = 6;
+
+ rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
+ rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
+ hw->rate_control_algorithm = "AARF";
+
+ SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
+ ether_addr_copy(hw->wiphy->addr_mask, addr_mask);
+
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+ wiphy->retry_short = RETRY_SHORT;
+ wiphy->retry_long  = RETRY_LONG;
+ wiphy->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
+ wiphy->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+ wiphy->flags = 0;
+ wiphy->available_antennas_tx = 1;
+ wiphy->available_antennas_rx = 1;
+ wiphy->bands[NL80211_BAND_2GHZ] =
+ &adapter->sbands[NL80211_BAND_2GHZ];
+ wiphy->bands[NL80211_BAND_5GHZ] =
+ &adapter->sbands[NL80211_BAND_5GHZ];
+
+ wiphy->reg_notifier = rsi_reg_notify;
+
+ status = ieee80211_register_hw(hw);
+ if (status)
+ return status;
+
+ return rsi_init_dbgfs(adapter);
+}
diff --git a/ubuntu/rsi/rsi_91x_main.c b/ubuntu/rsi/rsi_91x_main.c
new file mode 100644
index 0000000..b701e57
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_main.c
@@ -0,0 +1,360 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/firmware.h>
+#include "rsi_mgmt.h"
+#include "rsi_common.h"
+#include "rsi_hal.h"
+#ifdef CONFIG_RSI_HCI
+#include "rsi_hci.h"
+#endif
+#ifdef CONFIG_RSI_COEX
+#include "rsi_coex.h"
+#endif
+
+u32 rsi_zone_enabled = //INFO_ZONE |
+ INIT_ZONE |
+ //MGMT_TX_ZONE |
+ //MGMT_RX_ZONE |
+ //DATA_TX_ZONE |
+ //DATA_RX_ZONE |
+ //FSM_ZONE |
+ //ISR_ZONE |
+ ERR_ZONE |
+ 0;
+EXPORT_SYMBOL_GPL(rsi_zone_enabled);
+
+/**
+ * rsi_dbg() - This function outputs informational messages.
+ * @zone: Zone of interest for output message.
+ * @fmt: printf-style format for output message.
+ *
+ * Return: none
+ */
+void rsi_dbg(u32 zone, const char *fmt, ...)
+{
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ if (zone & rsi_zone_enabled)
+ pr_info("%pV", &vaf);
+ va_end(args);
+}
+EXPORT_SYMBOL_GPL(rsi_dbg);
+
+/**
+ * rsi_hex_dump() - This function prints the packet (/msg) in hex bytes.
+ * @zone: Zone of interest for output message.
+ * @msg_str: Message to be printed with packet
+ * @msg: Packet to be printed
+ * @len: Length of the packet
+ *
+ * Return: none
+ */
+void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len)
+{
+ int ii;
+
+ if (!(zone & rsi_zone_enabled))
+ return;
+ printk("%s: (length = %d)\n", msg_str, len);
+ for (ii = 0; ii < len; ii++) {
+ if (!(ii % 16))
+ printk("\n");
+ printk("%02x ", msg[ii]);
+ }
+ printk("\n");
+}
+EXPORT_SYMBOL_GPL(rsi_hex_dump);
+
+/**
+ * rsi_prepare_skb() - This function prepares the skb.
+ * @common: Pointer to the driver private structure.
+ * @buffer: Pointer to the packet data.
+ * @pkt_len: Length of the packet.
+ * @extended_desc: Extended descriptor.
+ *
+ * Return: Successfully skb.
+ */
+static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
+       u8 *buffer,
+       u32 pkt_len,
+       u8 extended_desc)
+{
+ struct ieee80211_tx_info *info;
+ struct skb_info *rx_params;
+ struct sk_buff *skb = NULL;
+ u8 payload_offset;
+
+ if (WARN(!pkt_len, "%s: Dummy pkt received", __func__))
+ return NULL;
+
+ if (pkt_len > (RSI_RCV_BUFFER_LEN * 4)) {
+ rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n",
+ __func__, pkt_len);
+ pkt_len = RSI_RCV_BUFFER_LEN * 4;
+ }
+
+ pkt_len -= extended_desc;
+ skb = dev_alloc_skb(pkt_len + FRAME_DESC_SZ);
+ if (!skb)
+ return NULL;
+
+ payload_offset = (extended_desc + FRAME_DESC_SZ);
+ skb_put(skb, pkt_len);
+ memcpy((skb->data), (buffer + payload_offset), skb->len);
+
+ info = IEEE80211_SKB_CB(skb);
+ rx_params = (struct skb_info *)info->driver_data;
+ rx_params->rssi = rsi_get_rssi(buffer);
+ rx_params->channel = rsi_get_connected_channel(common->priv);
+
+ return skb;
+}
+
+/**
+ * rsi_read_pkt() - This function reads frames from the card.
+ * @common: Pointer to the driver private structure.
+ * @rcv_pkt_len: Received pkt length. In case of USB it is 0.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
+{
+ u8 *frame_desc = NULL, extended_desc = 0;
+ u32 index = 0, length = 0, queueno = 0;
+ u16 actual_length = 0, offset;
+ struct sk_buff *skb = NULL;
+
+ do {
+ frame_desc = &rx_pkt[index];
+ actual_length = *(u16 *)&frame_desc[0];
+ offset = *(u16 *)&frame_desc[2];
+
+ if ((actual_length < (4 + FRAME_DESC_SZ)) || (offset < 4)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: actual_length (%d) is less than 20 or"
+ " offset(%d) is less than 4\n",
+ __func__, actual_length, offset);
+ break;
+ }
+ queueno = rsi_get_queueno(frame_desc, offset);
+ length = rsi_get_length(frame_desc, offset);
+ if (queueno == RSI_WIFI_DATA_Q || queueno == RSI_WIFI_MGMT_Q)
+ extended_desc = rsi_get_extended_desc(frame_desc,
+      offset);
+
+ switch (queueno) {
+ case RSI_COEX_Q:
+ rsi_hex_dump(MGMT_RX_ZONE,
+     "RX Command packet",
+     frame_desc + offset,
+     FRAME_DESC_SZ + length);
+ rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+ break;
+ case RSI_WIFI_DATA_Q:
+ rsi_hex_dump(DATA_RX_ZONE,
+     "RX Data pkt",
+     frame_desc + offset,
+     FRAME_DESC_SZ + length);
+ skb = rsi_prepare_skb(common,
+      (frame_desc + offset),
+      length,
+      extended_desc);
+ if (!skb)
+ goto fail;
+
+ rsi_indicate_pkt_to_os(common, skb);
+ break;
+
+ case RSI_WIFI_MGMT_Q:
+ rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+ break;
+#ifdef CONFIG_RSI_HCI
+ case RSI_BT_MGMT_Q:
+ case RSI_BT_DATA_Q:
+ rsi_hex_dump(DATA_RX_ZONE,
+     "RX BT Pkt",
+     frame_desc + offset,
+     FRAME_DESC_SZ + length);
+ rsi_hci_recv_pkt(common, frame_desc + offset);
+ break;
+#endif
+
+ default:
+ rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n",
+ __func__,   queueno);
+ goto fail;
+ }
+
+ index  += actual_length;
+ rcv_pkt_len -= actual_length;
+ } while (rcv_pkt_len > 0);
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(rsi_read_pkt);
+
+/**
+ * rsi_tx_scheduler_thread() - This function is a kernel thread to send the
+ *       packets to the device.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: None.
+ */
+static void rsi_tx_scheduler_thread(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ u32 timeout = EVENT_WAIT_FOREVER;
+
+ do {
+ if (adapter->determine_event_timeout)
+ timeout = adapter->determine_event_timeout(adapter);
+ rsi_wait_event(&common->tx_thread.event, timeout);
+ rsi_reset_event(&common->tx_thread.event);
+
+ if (common->init_done)
+ rsi_core_qos_processor(common);
+ } while (atomic_read(&common->tx_thread.thread_done) == 0);
+ complete_and_exit(&common->tx_thread.completion, 0);
+}
+
+/**
+ * rsi_91x_init() - This function initializes os interface operations.
+ * @void: Void.
+ *
+ * Return: Pointer to the adapter structure on success, NULL on failure .
+ */
+struct rsi_hw *rsi_91x_init(void)
+{
+ struct rsi_hw *adapter = NULL;
+ struct rsi_common *common = NULL;
+ u8 ii = 0;
+
+ adapter = kzalloc(sizeof(*adapter), GFP_KERNEL);
+ if (!adapter)
+ return NULL;
+
+ adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL);
+ if (!adapter->priv) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of priv\n",
+ __func__);
+ kfree(adapter);
+ return NULL;
+ }
+ common = adapter->priv;
+ common->priv = adapter;
+
+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
+ skb_queue_head_init(&common->tx_queue[ii]);
+
+ rsi_init_event(&common->tx_thread.event);
+ mutex_init(&common->mutex);
+ mutex_init(&common->tx_lock);
+ mutex_init(&common->rx_lock);
+
+ if (rsi_create_kthread(common,
+       &common->tx_thread,
+       rsi_tx_scheduler_thread,
+       "Tx-Thread")) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
+ goto err;
+ }
+ rsi_default_ps_params(adapter);
+ spin_lock_init(&adapter->ps_lock);
+ common->uapsd_bitmap = 0;
+ init_bgscan_params(common);
+
+ common->init_done = true;
+ return adapter;
+
+err:
+ kfree(common);
+ kfree(adapter);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(rsi_91x_init);
+
+/**
+ * rsi_91x_deinit() - This function de-intializes os intf operations.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+void rsi_91x_deinit(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+ u8 ii;
+
+ rsi_dbg(INFO_ZONE, "%s: Deinit core module...\n", __func__);
+
+ rsi_kill_thread(&common->tx_thread);
+
+ for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
+ skb_queue_purge(&common->tx_queue[ii]);
+
+ common->init_done = false;
+
+ kfree(common);
+ kfree(adapter->rsi_dev);
+ kfree(adapter);
+}
+EXPORT_SYMBOL_GPL(rsi_91x_deinit);
+
+/**
+ * rsi_91x_hal_module_init() - This function is invoked when the module is
+ *       loaded into the kernel.
+ *       It registers the client driver.
+ * @void: Void.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_91x_hal_module_init(void)
+{
+ rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__);
+ return 0;
+}
+
+/**
+ * rsi_91x_hal_module_exit() - This function is called at the time of
+ *       removing/unloading the module.
+ *       It unregisters the client driver.
+ * @void: Void.
+ *
+ * Return: None.
+ */
+static void rsi_91x_hal_module_exit(void)
+{
+ rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__);
+}
+
+module_init(rsi_91x_hal_module_init);
+module_exit(rsi_91x_hal_module_exit);
+MODULE_AUTHOR("Redpine Signals Inc");
+MODULE_DESCRIPTION("Station driver for RSI 91x devices");
+MODULE_SUPPORTED_DEVICE("RSI-91x");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/ubuntu/rsi/rsi_91x_mgmt.c b/ubuntu/rsi/rsi_91x_mgmt.c
new file mode 100644
index 0000000..c72d984
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_mgmt.c
@@ -0,0 +1,2288 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/etherdevice.h>
+#include "rsi_mgmt.h"
+#include "rsi_common.h"
+#include "rsi_ps.h"
+
+struct rsi_config_vals dev_config_vals[] = {
+ {
+ .lp_ps_handshake = 0,
+ .ulp_ps_handshake = 0,
+ .sleep_config_params = 0,
+ .ext_pa_or_bt_coex_en = 0,
+ },
+};
+
+/* Bootup Parameters for 20MHz */
+static struct bootup_params boot_params_20 = {
+ .magic_number = cpu_to_le16(0x5aa5),
+ .crystal_good_time = 0x0,
+ .valid = cpu_to_le32(VALID_20),
+ .reserved_for_valids = 0x0,
+ .bootup_mode_info = 0x0,
+ .digital_loop_back_params = 0x0,
+ .rtls_timestamp_en = 0x0,
+ .host_spi_intr_cfg = 0x0,
+ .device_clk_info = {{
+ /* WLAN params */
+ .pll_config_g = {
+ .tapll_info_g = {
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_20 << 8) |
+ (TAPLL_M_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_20),
+ },
+ .pll960_info_g = {
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8) |
+ (PLL960_N_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),
+ .pll_reg_3 = 0x0,
+ },
+ .afepll_info_g = {
+ .pll_reg = cpu_to_le16(0x9f0),
+ }
+ },
+ .switch_clk_g = {
+ .switch_umac_clk = 0x1,
+ .switch_qspi_clk = 0x1,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x1,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
+ .bbp_lmac_clk_reg_val = cpu_to_le16(0x111),
+ .umac_clock_reg_config = cpu_to_le16(0x48),
+ .qspi_uart_clock_reg_config = cpu_to_le16(0x1211)
+ }
+ },
+ /* Bluetooth params */
+ {
+ .pll_config_g = {
+ .tapll_info_g = {
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_20 << 8) |
+ (TAPLL_M_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_20),
+ },
+ .pll960_info_g = {
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8) |
+ (PLL960_N_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),
+ .pll_reg_3 = 0x0,
+ },
+ .afepll_info_g = {
+ .pll_reg = cpu_to_le16(0x9f0),
+ }
+ },
+ .switch_clk_g = {
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
+ .bbp_lmac_clk_reg_val = 0x0,
+ .umac_clock_reg_config = 0x0,
+ .qspi_uart_clock_reg_config = 0x0
+ }
+ },
+ /* Zigbee params */
+ {
+ .pll_config_g = {
+ .tapll_info_g = {
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_20 << 8) |
+ (TAPLL_M_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_20),
+ },
+ .pll960_info_g = {
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_20 << 8) |
+ (PLL960_N_VAL_20)),
+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_20),
+ .pll_reg_3 = 0x0,
+ },
+ .afepll_info_g = {
+ .pll_reg = cpu_to_le16(0x9f0),
+ }
+ },
+ .switch_clk_g = {
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
+ .bbp_lmac_clk_reg_val = 0x0,
+ .umac_clock_reg_config = 0x0,
+ .qspi_uart_clock_reg_config = 0x0
+ }
+ } },
+ /* ULP Params */
+ .buckboost_wakeup_cnt = 0x0,
+ .pmu_wakeup_wait = 0x0,
+ .shutdown_wait_time = 0x0,
+ .pmu_slp_clkout_sel = 0x0,
+ .wdt_prog_value = 0x0,
+ .wdt_soc_rst_delay = 0x0,
+ .dcdc_operation_mode = 0x0,
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
+};
+
+/* Bootup parameters for 40MHz */
+static struct bootup_params boot_params_40 = {
+ .magic_number = cpu_to_le16(0x5aa5),
+ .crystal_good_time = 0x0,
+ .valid = cpu_to_le32(VALID_40),
+ .reserved_for_valids = 0x0,
+ .bootup_mode_info = 0x0,
+ .digital_loop_back_params = 0x0,
+ .rtls_timestamp_en = 0x0,
+ .host_spi_intr_cfg = 0x0,
+ .device_clk_info = {{
+ /* WLAN params */
+ .pll_config_g = {
+ .tapll_info_g = {
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_40 << 8) |
+ (TAPLL_M_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_40),
+ },
+ .pll960_info_g = {
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8) |
+ (PLL960_N_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),
+ .pll_reg_3 = 0x0,
+ },
+ .afepll_info_g = {
+ .pll_reg = cpu_to_le16(0x9f0),
+ }
+ },
+ .switch_clk_g = {
+ .switch_umac_clk = 0x1,
+ .switch_qspi_clk = 0x1,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x1,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
+ .bbp_lmac_clk_reg_val = cpu_to_le16(0x1121),
+ .umac_clock_reg_config = cpu_to_le16(0x48),
+ .qspi_uart_clock_reg_config = cpu_to_le16(0x1211)
+ }
+ },
+ /* Bluetooth Params */
+ {
+ .pll_config_g = {
+ .tapll_info_g = {
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_40 << 8) |
+ (TAPLL_M_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_40),
+ },
+ .pll960_info_g = {
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8) |
+ (PLL960_N_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),
+ .pll_reg_3 = 0x0,
+ },
+ .afepll_info_g = {
+ .pll_reg = cpu_to_le16(0x9f0),
+ }
+ },
+ .switch_clk_g = {
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
+ .bbp_lmac_clk_reg_val = 0x0,
+ .umac_clock_reg_config = 0x0,
+ .qspi_uart_clock_reg_config = 0x0
+ }
+ },
+ /* Zigbee Params */
+ {
+ .pll_config_g = {
+ .tapll_info_g = {
+ .pll_reg_1 = cpu_to_le16((TAPLL_N_VAL_40 << 8) |
+ (TAPLL_M_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(TAPLL_P_VAL_40),
+ },
+ .pll960_info_g = {
+ .pll_reg_1 = cpu_to_le16((PLL960_P_VAL_40 << 8) |
+ (PLL960_N_VAL_40)),
+ .pll_reg_2 = cpu_to_le16(PLL960_M_VAL_40),
+ .pll_reg_3 = 0x0,
+ },
+ .afepll_info_g = {
+ .pll_reg = cpu_to_le16(0x9f0),
+ }
+ },
+ .switch_clk_g = {
+ .switch_umac_clk = 0x0,
+ .switch_qspi_clk = 0x0,
+ .switch_slp_clk_2_32 = 0x0,
+ .switch_bbp_lmac_clk_reg = 0x0,
+ .switch_mem_ctrl_cfg = 0x0,
+ .reserved = 0x0,
+ .bbp_lmac_clk_reg_val = 0x0,
+ .umac_clock_reg_config = 0x0,
+ .qspi_uart_clock_reg_config = 0x0
+ }
+ } },
+ /* ULP Params */
+ .buckboost_wakeup_cnt = 0x0,
+ .pmu_wakeup_wait = 0x0,
+ .shutdown_wait_time = 0x0,
+ .pmu_slp_clkout_sel = 0x0,
+ .wdt_prog_value = 0x0,
+ .wdt_soc_rst_delay = 0x0,
+ .dcdc_operation_mode = 0x0,
+ .soc_reset_wait_cnt = 0x0,
+ .waiting_time_at_fresh_sleep = 0x0,
+ .max_threshold_to_avoid_sleep = 0x0,
+ .beacon_resedue_alg_en = 0,
+};
+
+#define UNUSED_GPIO 1
+#define USED_GPIO 0
+struct rsi_ulp_gpio_vals unused_ulp_gpio_bitmap = {
+ .motion_sensor_gpio_ulp_wakeup = UNUSED_GPIO,
+ .sleep_ind_from_device = UNUSED_GPIO,
+ .ulp_gpio_2 = UNUSED_GPIO,
+ .push_button_ulp_wakeup = UNUSED_GPIO,
+};
+
+struct rsi_soc_gpio_vals unused_soc_gpio_bitmap = {
+ .pspi_csn_0 = USED_GPIO, //GPIO_0
+ .pspi_csn_1 = USED_GPIO, //GPIO_1
+ .host_wakeup_intr = UNUSED_GPIO, //GPIO_2
+ .pspi_data_0 = USED_GPIO, //GPIO_3
+ .pspi_data_1 = USED_GPIO, //GPIO_4
+ .pspi_data_2 = USED_GPIO, //GPIO_5
+ .pspi_data_3 = USED_GPIO, //GPIO_6
+ .i2c_scl = USED_GPIO, //GPIO_7
+ .i2c_sda = USED_GPIO, //GPIO_8
+ .uart1_rx = UNUSED_GPIO, //GPIO_9
+ .uart1_tx = UNUSED_GPIO, //GPIO_10
+ .uart1_rts_i2s_clk = UNUSED_GPIO, //GPIO_11
+ .uart1_cts_i2s_ws = UNUSED_GPIO, //GPIO_12
+ .dbg_uart_rx_i2s_din = UNUSED_GPIO, //GPIO_13
+ .dbg_uart_tx_i2s_dout = UNUSED_GPIO, //GPIO_14
+ .lp_wakeup_boot_bypass = UNUSED_GPIO, //GPIO_15
+ .led_0 = USED_GPIO, //GPIO_16
+ .btcoex_wlan_active_ext_pa_ant_sel_A = UNUSED_GPIO, //GPIO_17
+ .btcoex_bt_priority_ext_pa_ant_sel_B = UNUSED_GPIO, //GPIO_18
+ .btcoex_bt_active_ext_pa_on_off = UNUSED_GPIO, //GPIO_19
+ .rf_reset = USED_GPIO, //GPIO_20
+ .sleep_ind_from_device = UNUSED_GPIO,
+};
+
+static u16 mcs[] = {13, 26, 39, 52, 78, 104, 117, 130};
+
+/**
+ * rsi_set_default_parameters() - This function sets default parameters.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: none
+ */
+static void rsi_set_default_parameters(struct rsi_common *common)
+{
+ common->band = NL80211_BAND_2GHZ;
+ common->channel_width = BW_20MHZ;
+ common->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+ common->channel = 1;
+ common->min_rate = 0xffff;
+ common->fsm_state = FSM_CARD_NOT_READY;
+ common->iface_down = true;
+ common->endpoint = EP_2GHZ_20MHZ;
+ common->driver_mode = 1; /* End-to-End Mode */
+#ifdef CONFIG_RSI_HCI
+ common->coex_mode = 4;
+ common->oper_mode = 4;
+#else
+ common->coex_mode = 1; /*Default coex mode is WIFI alone */
+ common->oper_mode = 1;
+#endif
+ common->ta_aggr = 0;
+ common->skip_fw_load = 0; /* Default disable skipping fw loading */
+ common->lp_ps_handshake_mode = 0; /* Default No HandShake mode*/
+ common->ulp_ps_handshake_mode = 2; /* Default PKT HandShake mode*/
+ common->rf_power_val = 0; /* Default 1.9V */
+ common->device_gpio_type = TA_GPIO; /* Default TA GPIO */
+ common->country_code = 840; /* Default US */
+ common->wlan_rf_power_mode = 0;
+ common->bt_rf_power_mode = 0;
+ common->obm_ant_sel_val = 2;
+ common->antenna_diversity = 0;
+ common->tx_power = RSI_TXPOWER_MAX;
+}
+
+void init_bgscan_params(struct rsi_common *common)
+{
+ common->bgscan_info.bgscan_threshold = 50;
+ common->bgscan_info.roam_threshold = 10;
+ common->bgscan_info.bgscan_periodicity = 15;
+ common->bgscan_info.num_bg_channels = 11;
+ common->bgscan_info.two_probe = 1;
+ common->bgscan_info.active_scan_duration = 20;
+ common->bgscan_info.passive_scan_duration = 70;
+ common->bgscan_info.channels2scan[0] = 1;
+ common->bgscan_info.channels2scan[1] = 2;
+ common->bgscan_info.channels2scan[2] = 3;
+ common->bgscan_info.channels2scan[3] = 4;
+ common->bgscan_info.channels2scan[4] = 5;
+ common->bgscan_info.channels2scan[5] = 6;
+ common->bgscan_info.channels2scan[6] = 7;
+ common->bgscan_info.channels2scan[7] = 8;
+ common->bgscan_info.channels2scan[8] = 9;
+ common->bgscan_info.channels2scan[9] = 10;
+ common->bgscan_info.channels2scan[10] = 11;
+// common->bgscan_info.channels2scan[11] = 12;
+// common->bgscan_info.channels2scan[12] = 13;
+// common->bgscan_info.channels2scan[13] = 14;
+#if 0
+ common->bgscan_info.channels2scan[11] = 36;
+ common->bgscan_info.channels2scan[12] = 40;
+ common->bgscan_info.channels2scan[13] = 44;
+ common->bgscan_info.channels2scan[14] = 48;
+ common->bgscan_info.channels2scan[15] = 52;
+ common->bgscan_info.channels2scan[16] = 56;
+ common->bgscan_info.channels2scan[17] = 60;
+ common->bgscan_info.channels2scan[18] = 64;
+ common->bgscan_info.channels2scan[19] = 100;
+ common->bgscan_info.channels2scan[20] = 104;
+#endif
+}
+
+/**
+ * rsi_set_contention_vals() - This function sets the contention values for the
+ *       backoff procedure.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: None.
+ */
+static void rsi_set_contention_vals(struct rsi_common *common)
+{
+ u8 ii = 0;
+
+ for (; ii < NUM_EDCA_QUEUES; ii++) {
+ common->tx_qinfo[ii].wme_params =
+ (((common->edca_params[ii].cw_min / 2) +
+  (common->edca_params[ii].aifs)) *
+  WMM_SHORT_SLOT_TIME + SIFS_DURATION);
+ common->tx_qinfo[ii].weight = common->tx_qinfo[ii].wme_params;
+ common->tx_qinfo[ii].pkt_contended = 0;
+ }
+}
+
+/**
+ * rsi_send_internal_mgmt_frame() - This function sends management frames to
+ *    firmware.Also schedules packet to queue
+ *    for transmission.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_send_internal_mgmt_frame(struct rsi_common *common,
+ struct sk_buff *skb)
+{
+ struct skb_info *tx_params;
+
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: SKB is NULL\n", __func__);
+ return -EINVAL;
+ }
+ skb->data[1] |= BIT(7);
+ tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data;
+ tx_params->flags |= INTERNAL_MGMT_PKT;
+ skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb);
+ rsi_set_event(&common->tx_thread.event);
+ return 0;
+}
+
+/**
+ * rsi_load_radio_caps() - This function is used to send radio capabilities
+ *   values to firmware.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding negative error code on failure.
+ */
+static int rsi_load_radio_caps(struct rsi_common *common)
+{
+ struct rsi_radio_caps *radio_caps;
+ struct rsi_hw *adapter = common->priv;
+ u16 inx = 0;
+ int ii;
+ u8 radio_id = 0;
+ u16 gc[20] = {0xf0, 0xf0, 0xf0, 0xf0,
+      0xf0, 0xf0, 0xf0, 0xf0,
+      0xf0, 0xf0, 0xf0, 0xf0,
+      0xf0, 0xf0, 0xf0, 0xf0,
+      0xf0, 0xf0, 0xf0, 0xf0};
+ struct sk_buff *skb;
+
+ rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__);
+
+ skb = dev_alloc_skb(sizeof(struct rsi_radio_caps));
+ if (!skb)
+ return -ENOMEM;
+
+ memset(skb->data, 0, sizeof(struct rsi_radio_caps));
+ radio_caps = (struct rsi_radio_caps *)skb->data;
+
+ radio_caps->desc_word[1] = cpu_to_le16(RADIO_CAPABILITIES);
+ radio_caps->desc_word[4] = cpu_to_le16(common->channel);
+ radio_caps->desc_word[4] |= cpu_to_le16(RSI_RF_TYPE << 8);
+
+ radio_caps->desc_word[7] |= cpu_to_le16(RSI_LMAC_CLOCK_80MHZ);
+ if (common->channel_width == BW_40MHZ) {
+ radio_caps->desc_word[7] |= cpu_to_le16(RSI_ENABLE_40MHZ);
+
+ if (common->fsm_state == FSM_MAC_INIT_DONE) {
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (conf_is_ht40_plus(conf)) {
+ radio_caps->desc_word[5] =
+ cpu_to_le16(LOWER_20_ENABLE);
+ radio_caps->desc_word[5] |=
+ cpu_to_le16(LOWER_20_ENABLE >> 12);
+ } else if (conf_is_ht40_minus(conf)) {
+ radio_caps->desc_word[5] =
+ cpu_to_le16(UPPER_20_ENABLE);
+ radio_caps->desc_word[5] |=
+ cpu_to_le16(UPPER_20_ENABLE >> 12);
+ } else {
+ radio_caps->desc_word[5] =
+ cpu_to_le16(BW_40MHZ << 12);
+ radio_caps->desc_word[5] |=
+ cpu_to_le16(FULL40M_ENABLE);
+ }
+ }
+ }
+
+ radio_caps->sifs_tx_11n = cpu_to_le16(SIFS_TX_11N_VALUE);
+ radio_caps->sifs_tx_11b = cpu_to_le16(SIFS_TX_11B_VALUE);
+ radio_caps->slot_rx_11n = cpu_to_le16(SHORT_SLOT_VALUE);
+ radio_caps->ofdm_ack_tout = cpu_to_le16(OFDM_ACK_TOUT_VALUE);
+ radio_caps->cck_ack_tout = cpu_to_le16(CCK_ACK_TOUT_VALUE);
+ radio_caps->preamble_type = cpu_to_le16(LONG_PREAMBLE);
+
+ radio_caps->desc_word[7] |= cpu_to_le16(radio_id << 8);
+
+ for (ii = 0; ii < MAX_HW_QUEUES; ii++) {
+ radio_caps->qos_params[ii].cont_win_min_q = cpu_to_le16(3);
+ radio_caps->qos_params[ii].cont_win_max_q = cpu_to_le16(0x3f);
+ radio_caps->qos_params[ii].aifsn_val_q = cpu_to_le16(2);
+ radio_caps->qos_params[ii].txop_q = 0;
+ }
+
+ for (ii = 0; ii < NUM_EDCA_QUEUES; ii++) {
+ radio_caps->qos_params[ii].cont_win_min_q =
+ cpu_to_le16(common->edca_params[ii].cw_min);
+ radio_caps->qos_params[ii].cont_win_max_q =
+ cpu_to_le16(common->edca_params[ii].cw_max);
+ radio_caps->qos_params[ii].aifsn_val_q =
+ cpu_to_le16((common->edca_params[ii].aifs) << 8);
+ radio_caps->qos_params[ii].txop_q =
+ cpu_to_le16(common->edca_params[ii].txop);
+ }
+
+ radio_caps->qos_params[BROADCAST_HW_Q].txop_q = 0xffff;
+ radio_caps->qos_params[MGMT_HW_Q].txop_q = 0;
+ radio_caps->qos_params[BEACON_HW_Q].txop_q = 0xffff;
+
+ memcpy(&common->rate_pwr[0], &gc[0], 40);
+ for (ii = 0; ii < 20; ii++)
+ radio_caps->gcpd_per_rate[inx++] =
+ cpu_to_le16(common->rate_pwr[ii]  & 0x00FF);
+
+ radio_caps->desc_word[0] = cpu_to_le16((sizeof(struct rsi_radio_caps) -
+ FRAME_DESC_SZ) |
+ (RSI_WIFI_MGMT_Q << 12));
+
+ skb_put(skb, (sizeof(struct rsi_radio_caps)));
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_mgmt_pkt_to_core() - This function is the entry point for Mgmt module.
+ * @common: Pointer to the driver private structure.
+ * @msg: Pointer to received packet.
+ * @msg_len: Length of the received packet.
+ * @type: Type of received packet.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
+ u8 *msg,
+ s32 msg_len,
+ u8 type)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_tx_info *info;
+ struct skb_info *rx_params;
+ u8 pad_bytes = msg[4];
+ u8 pkt_recv;
+ struct sk_buff *skb;
+ char *buffer;
+
+ if (type == RX_DOT11_MGMT) {
+ if (!adapter->sc_nvifs)
+ return -ENOLINK;
+
+ msg_len -= pad_bytes;
+ if ((msg_len <= 0) || (!msg)) {
+ rsi_dbg(MGMT_RX_ZONE,
+ "%s: Invalid rx msg of len = %d\n",
+ __func__, msg_len);
+ return -EINVAL;
+ }
+
+ skb = dev_alloc_skb(msg_len);
+ if (!skb)
+ return -ENOMEM;
+
+ buffer = skb_put(skb, msg_len);
+
+ memcpy(buffer,
+       (u8 *)(msg +  FRAME_DESC_SZ + pad_bytes),
+       msg_len);
+
+ pkt_recv = buffer[0];
+
+ info = IEEE80211_SKB_CB(skb);
+ rx_params = (struct skb_info *)info->driver_data;
+ rx_params->rssi = rsi_get_rssi(msg);
+ rx_params->channel = rsi_get_channel(msg);
+ rsi_dbg(MGMT_RX_ZONE,
+ "%s: rssi=%d channel=%d\n",
+ __func__, rx_params->rssi, rx_params->channel);
+ rsi_indicate_pkt_to_os(common, skb);
+ } else
+ rsi_dbg(MGMT_TX_ZONE, "%s: Internal Packet\n", __func__);
+
+ return 0;
+}
+
+/**
+ * rsi_send_sta_notify_frame() - This function sends the station notify
+ *     frame to firmware.
+ * @common: Pointer to the driver private structure.
+ * @opmode: Operating mode of device.
+ * @notify_event: Notification about station connection.
+ * @bssid: bssid.
+ * @qos_enable: Qos is enabled.
+ * @aid: Aid (unique for all STA).
+ *
+ * Return: status: 0 on success, corresponding negative error code on failure.
+ */
+static int rsi_send_sta_notify_frame(struct rsi_common *common,
+     u8 opmode,
+     u8 notify_event,
+     const unsigned char *bssid,
+     u8 qos_enable,
+     u16 aid)
+{
+ struct sk_buff *skb = NULL;
+ struct rsi_peer_notify *peer_notify;
+ int status;
+ u16 vap_id = 0;
+ int frame_len = sizeof(*peer_notify);
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending station notify frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+ memset(skb->data, 0, frame_len);
+
+ peer_notify = (struct rsi_peer_notify *)skb->data;
+
+ peer_notify->command = 0; //cpu_to_le16(opmode << 1);
+
+ switch (notify_event) {
+ case STA_CONNECTED:
+ peer_notify->command |= cpu_to_le16(RSI_ADD_PEER);
+ break;
+ case STA_DISCONNECTED:
+ peer_notify->command |= cpu_to_le16(RSI_DELETE_PEER);
+ break;
+ default:
+ break;
+ }
+
+ peer_notify->command |= cpu_to_le16((aid & 0xfff) << 4);
+ ether_addr_copy(peer_notify->mac_addr, bssid);
+ peer_notify->mpdu_density = cpu_to_le16(0x08);
+ peer_notify->sta_flags = cpu_to_le32((qos_enable) ? 1 : 0);
+ peer_notify->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ) |
+ (RSI_WIFI_MGMT_Q << 12));
+ peer_notify->desc_word[1] = cpu_to_le16(PEER_NOTIFY);
+ peer_notify->desc_word[7] |= cpu_to_le16(vap_id << 8);
+
+ skb_put(skb, frame_len);
+ status = rsi_send_internal_mgmt_frame(common, skb);
+
+ if (!status && qos_enable) {
+ rsi_set_contention_vals(common);
+ status = rsi_load_radio_caps(common);
+ }
+
+ return status;
+}
+
+/**
+ * rsi_send_aggr_params_frame() - This function sends the ampdu
+ * indication frame to firmware.
+ * @common: Pointer to the driver private structure.
+ * @tid: traffic identifier.
+ * @ssn: ssn.
+ * @buf_size: buffer size.
+ * @event: notification about station connection.
+ *
+ * Return: 0 on success, corresponding negative error code on failure.
+ */
+int rsi_send_aggr_params_frame(struct rsi_common *common,
+       u16 tid,
+       u16 ssn,
+       u8 buf_size,
+       u8 event)
+{
+ struct sk_buff *skb = NULL;
+ struct rsi_mac_frame *mgmt_frame;
+ u8 peer_id = 0;
+ u8 window_size = 1;
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending AMPDU indication frame\n",
+ __func__);
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(AMPDU_IND);
+
+ if (event == STA_TX_ADDBA_DONE) {
+ mgmt_frame->desc_word[4] = cpu_to_le16(ssn);
+// mgmt_frame->desc_word[5] = cpu_to_le16(buf_size);
+ mgmt_frame->desc_word[5] = cpu_to_le16(window_size);
+ mgmt_frame->desc_word[7] =
+ cpu_to_le16((tid |
+    (START_AMPDU_AGGR << 4) |
+    (peer_id << 8)));
+ } else if (event == STA_RX_ADDBA_DONE) {
+ mgmt_frame->desc_word[4] = cpu_to_le16(ssn);
+ mgmt_frame->desc_word[7] = cpu_to_le16(tid |
+       (START_AMPDU_AGGR << 4) |
+       (RX_BA_INDICATION << 5) |
+       (peer_id << 8));
+ } else if (event == STA_TX_DELBA) {
+ mgmt_frame->desc_word[7] = cpu_to_le16(tid |
+       (STOP_AMPDU_AGGR << 4) |
+       (peer_id << 8));
+ } else if (event == STA_RX_DELBA) {
+ mgmt_frame->desc_word[7] = cpu_to_le16(tid |
+       (STOP_AMPDU_AGGR << 4) |
+       (RX_BA_INDICATION << 5) |
+       (peer_id << 8));
+ }
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_program_bb_rf() - This function starts base band and RF programming.
+ * This is called after initial configurations are done.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding negative error code on failure.
+ */
+int rsi_program_bb_rf(struct rsi_common *common)
+{
+ struct sk_buff *skb;
+ struct rsi_mac_frame *mgmt_frame;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending BB/RF program frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(BBP_PROG_IN_TA);
+ mgmt_frame->desc_word[4] = cpu_to_le16(common->endpoint);
+ mgmt_frame->desc_word[3] = cpu_to_le16(common->rf_pwr_mode);
+
+ if (common->rf_reset) {
+ mgmt_frame->desc_word[7] =  cpu_to_le16(RF_RESET_ENABLE);
+ rsi_dbg(MGMT_TX_ZONE, "%s: ===> RF RESET REQUEST SENT <===\n",
+ __func__);
+ common->rf_reset = 0;
+ }
+ common->bb_rf_prog_count = 1;
+ mgmt_frame->desc_word[7] |= cpu_to_le16(PUT_BBP_RESET |
+     BBP_REG_WRITE | (RSI_RF_TYPE << 4));
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_set_vap_capabilities() - This function send vap capability to firmware.
+ * @common: Pointer to the driver private structure.
+ * @opmode: Operating mode of device.
+ *
+ * Return: 0 on success, corresponding negative error code on failure.
+ */
+int rsi_set_vap_capabilities(struct rsi_common *common,
+     enum opmode mode,
+     u8 vap_status)
+{
+ struct sk_buff *skb = NULL;
+ struct rsi_vap_caps *vap_caps;
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hw *hw = adapter->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+ u16 vap_id = 0;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending VAP capabilities frame\n", __func__);
+
+ skb = dev_alloc_skb(sizeof(struct rsi_vap_caps));
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, sizeof(struct rsi_vap_caps));
+ vap_caps = (struct rsi_vap_caps *)skb->data;
+
+ vap_caps->desc_word[0] = cpu_to_le16((sizeof(struct rsi_vap_caps) -
+     FRAME_DESC_SZ) |
+     (RSI_WIFI_MGMT_Q << 12));
+ vap_caps->desc_word[1] = cpu_to_le16(VAP_CAPABILITIES);
+ vap_caps->desc_word[2] = cpu_to_le16(vap_status << 8);
+ vap_caps->desc_word[4] = cpu_to_le16(mode |
+     (common->channel_width << 8));
+ vap_caps->desc_word[7] = cpu_to_le16((vap_id << 8) |
+     (common->mac_id << 4) |
+     common->radio_id);
+
+ memcpy(vap_caps->mac_addr, common->mac_addr, IEEE80211_ADDR_LEN);
+ vap_caps->keep_alive_period = cpu_to_le16(90);
+ vap_caps->frag_threshold = cpu_to_le16(IEEE80211_MAX_FRAG_THRESHOLD);
+
+ vap_caps->rts_threshold = cpu_to_le16(common->rts_threshold);
+ vap_caps->default_mgmt_rate = cpu_to_le32(RSI_RATE_6);
+
+#if 0
+ if (common->band == NL80211_BAND_5GHZ) {
+ vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6);
+ if (conf_is_ht40(&common->priv->hw->conf)) {
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(FULL40M_ENABLE << 16);
+ }
+ } else {
+ vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_1);
+ if (conf_is_ht40_minus(conf))
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(UPPER_20_ENABLE << 16);
+ else if (conf_is_ht40_plus(conf))
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(LOWER_20_ENABLE << 16);
+ }
+#else
+ if (common->band == NL80211_BAND_5GHZ)
+ vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_6);
+ else
+ vap_caps->default_ctrl_rate = cpu_to_le32(RSI_RATE_1);
+
+ if (conf_is_ht40(conf)) {
+ if (conf_is_ht40_minus(conf))
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(UPPER_20_ENABLE << 16);
+ else if (conf_is_ht40_plus(conf))
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(LOWER_20_ENABLE << 16);
+ else
+ vap_caps->default_ctrl_rate |=
+ cpu_to_le32(FULL40M_ENABLE << 16);
+ }
+#endif
+
+ vap_caps->default_data_rate = 0;
+ vap_caps->beacon_interval = cpu_to_le16(200);
+ vap_caps->dtim_period = cpu_to_le16(4);
+// vap_caps->beacon_miss_threshold = cpu_to_le16(10);
+
+ skb_put(skb, sizeof(*vap_caps));
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_load_key() - This function is used to load keys within the firmware.
+ * @common: Pointer to the driver private structure.
+ * @data: Pointer to the key data.
+ * @key_len: Key length to be loaded.
+ * @key_type: Type of key: GROUP/PAIRWISE.
+ * @key_id: Key index.
+ * @cipher: Type of cipher used.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_load_key(struct rsi_common *common,
+ u8 *data,
+ u16 key_len,
+ u8 key_type,
+ u8 key_id,
+ u32 cipher)
+{
+ struct sk_buff *skb = NULL;
+ struct rsi_set_key *set_key;
+ u16 key_descriptor = 0;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending load key frame\n", __func__);
+
+ skb = dev_alloc_skb(sizeof(struct rsi_set_key));
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, sizeof(struct rsi_set_key));
+ set_key = (struct rsi_set_key *)skb->data;
+
+ if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
+    (cipher == WLAN_CIPHER_SUITE_WEP104)) {
+ key_len += 1;
+ key_descriptor |= BIT(2);
+ if (key_len >= 13)
+ key_descriptor |= BIT(3);
+ } else if (cipher != KEY_TYPE_CLEAR) {
+ key_descriptor |= BIT(4);
+ if (key_type == RSI_PAIRWISE_KEY)
+ key_id = 0;
+ if (cipher == WLAN_CIPHER_SUITE_TKIP)
+ key_descriptor |= BIT(5);
+ }
+ key_descriptor |= (key_type | BIT(13) | (key_id << 14));
+
+ set_key->desc_word[0] = cpu_to_le16((sizeof(struct rsi_set_key) -
+    FRAME_DESC_SZ) |
+    (RSI_WIFI_MGMT_Q << 12));
+ set_key->desc_word[1] = cpu_to_le16(SET_KEY_REQ);
+ set_key->desc_word[4] = cpu_to_le16(key_descriptor);
+
+ if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
+    (cipher == WLAN_CIPHER_SUITE_WEP104)) {
+ memcpy(&set_key->key[key_id][1], data, key_len * 2);
+ } else {
+ memcpy(&set_key->key[0][0], data, key_len);
+ }
+
+ memcpy(set_key->tx_mic_key, &data[16], 8);
+ memcpy(set_key->rx_mic_key, &data[24], 8);
+
+ skb_put(skb, sizeof(struct rsi_set_key));
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_common_dev_params() - This function send the common device
+ * configuration parameters to device.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_send_common_dev_params(struct rsi_common *common)
+{
+ struct sk_buff *skb = NULL;
+ u32 *soc_gpio, len;
+ u16 *frame, *ulp_gpio, *desc;
+
+ rsi_dbg(INFO_ZONE, "Sending common dev config params\n");
+
+ len = 0x20;
+
+ skb = dev_alloc_skb(len + FRAME_DESC_SZ);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, len + FRAME_DESC_SZ);
+
+ desc = (u16 *)&skb->data[0];
+ frame = (u16 *)&skb->data[FRAME_DESC_SZ];
+
+ desc[0] = cpu_to_le16(len | (RSI_COEX_Q << 12));
+ desc[1] = cpu_to_le16(COMMON_DEV_CONFIG);
+
+ frame[0] = (u16)common->lp_ps_handshake_mode;
+ frame[0] |= (u16)common->ulp_ps_handshake_mode << 8;
+
+ ulp_gpio = (u16 *)&unused_ulp_gpio_bitmap;
+ soc_gpio = (u32 *)&unused_soc_gpio_bitmap;
+
+ frame[1] |= (*ulp_gpio) << 8;
+ *(u32 *)&frame[2] = *soc_gpio;
+ frame[4] |= cpu_to_le16((u16)common->oper_mode << 8);
+ frame[5] |= cpu_to_le16((u16)common->wlan_rf_power_mode);
+ frame[5] |= cpu_to_le16((u16)common->bt_rf_power_mode << 8);
+ frame[6] |= cpu_to_le16((u16)common->driver_mode << 8);
+ frame[7] = cpu_to_le16(3); //((u16 )d_assets->region_code);
+ frame[7] |= cpu_to_le16((u16)common->obm_ant_sel_val << 8);
+
+ skb_put(skb, len + FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+#if 0
+int rsi_send_common_dev_params(struct rsi_common *common)
+{
+ struct sk_buff *skb = NULL;
+ u32 *unused_soc_gpio;
+ u32 frame_len = 0;
+ struct rsi_config_vals *dev_cfgs = NULL;
+
+ frame_len = sizeof(struct rsi_config_vals);
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending common device config params frame\n",
+ __func__);
+ skb = dev_alloc_skb(frame_len);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, frame_len);
+
+ dev_cfgs = (struct rsi_config_vals *)&skb->data[0];
+ memset(dev_cfgs, 0, (sizeof(struct rsi_config_vals)));
+
+ dev_cfgs->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ) |
+     (RSI_COEX_Q << 12));
+ dev_cfgs->desc_word[1] = cpu_to_le16(COMMON_DEV_CONFIG);
+
+ dev_cfgs->lp_ps_handshake = common->lp_ps_handshake_mode;
+ dev_cfgs->ulp_ps_handshake = common->ulp_ps_handshake_mode;
+
+ if (common->host_wakeup_intr_enable) {
+ dev_cfgs->sleep_config_params |=
+ common->host_wakeup_intr_enable;
+ dev_cfgs->sleep_config_params |= BIT(2);
+ if (common->host_wakeup_intr_active_high)
+ dev_cfgs->sleep_config_params |= BIT(3);
+ }
+
+ dev_config_vals[0].opermode = common->coex_mode;
+
+ if (dev_config_vals[0].ext_pa_or_bt_coex_en)
+ dev_cfgs->ext_pa_or_bt_coex_en =
+ dev_config_vals[0].ext_pa_or_bt_coex_en;
+ dev_cfgs->opermode = dev_config_vals[0].opermode;
+ dev_cfgs->wlan_rf_pwr_mode = common->wlan_rf_power_mode;
+ dev_cfgs->driver_mode = common->driver_mode;
+ dev_cfgs->region_code = 0; /* Default US */
+ dev_cfgs->antenna_sel_val = common->obm_ant_sel_val;
+
+ unused_soc_gpio = (u32 *)&unused_soc_gpio_bitmap;
+ dev_cfgs->unused_soc_gpio_bitmap = *unused_soc_gpio;
+
+ skb_put(skb, frame_len);
+
+ rsi_hex_dump(ERR_ZONE, "common dev config params ",
+     skb->data, skb->len);
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+#endif
+
+/*
+ * rsi_load_bootup_params() - This function send bootup params to the firmware.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+static int rsi_load_bootup_params(struct rsi_common *common)
+{
+ struct sk_buff *skb;
+ struct rsi_boot_params *boot_params;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__);
+ skb = dev_alloc_skb(sizeof(struct rsi_boot_params));
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, sizeof(struct rsi_boot_params));
+ boot_params = (struct rsi_boot_params *)skb->data;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s:\n", __func__);
+
+ if (common->channel_width == BW_40MHZ) {
+ memcpy(&boot_params->bootup_params,
+       &boot_params_40,
+       sizeof(struct bootup_params));
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Packet 40MHZ <=== %d\n", __func__,
+ UMAC_CLK_40BW);
+ boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40BW);
+ } else {
+ memcpy(&boot_params->bootup_params,
+       &boot_params_20,
+       sizeof(struct bootup_params));
+ if (boot_params_20.valid != cpu_to_le32(VALID_20)) {
+ boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_20BW);
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Packet 20MHZ <=== %d\n", __func__,
+ UMAC_CLK_20BW);
+ } else {
+ boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40MHZ);
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Packet 20MHZ <=== %d\n", __func__,
+ UMAC_CLK_40MHZ);
+ }
+ }
+
+ /**
+ * Bit{0:11} indicates length of the Packet
+ * Bit{12:15} indicates host queue number
+ */
+ boot_params->desc_word[0] = cpu_to_le16(sizeof(struct bootup_params) |
+    (RSI_WIFI_MGMT_Q << 12));
+ boot_params->desc_word[1] = cpu_to_le16(BOOTUP_PARAMS_REQUEST);
+
+ skb_put(skb, sizeof(struct rsi_boot_params));
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_reset_mac() - This function prepares reset MAC request and sends an
+ *  internal management frame to indicate it to firmware.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+static int rsi_send_reset_mac(struct rsi_common *common)
+{
+ struct sk_buff *skb;
+ struct rsi_mac_frame *mgmt_frame;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending reset MAC frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(RESET_MAC_REQ);
+#ifdef BYPASS_RX_DATA_PATH
+ mgmt_frame->desc_word[4] = cpu_to_le16(0x0001);
+#endif
+ mgmt_frame->desc_word[4] |= cpu_to_le16(RETRY_COUNT << 8);
+
+ /*TA level aggregation of pkts to host */
+ mgmt_frame->desc_word[3] |=  common->ta_aggr << 8;
+
+ if (common->antenna_diversity)
+ mgmt_frame->desc_word[6] = common->antenna_diversity;
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_band_check() - This function programs the band
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_band_check(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hw *hw = adapter->hw;
+ u8 prev_bw = common->channel_width;
+ u8 prev_ep = common->endpoint;
+ struct ieee80211_channel *curchan = hw->conf.chandef.chan;
+ int status = 0;
+
+ if (common->band != curchan->band) {
+ common->rf_reset = 1;
+ common->band = curchan->band;
+ }
+
+ if ((hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) ||
+    (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20))
+ common->channel_width = BW_20MHZ;
+ else
+ common->channel_width = BW_40MHZ;
+
+ if (common->band == NL80211_BAND_2GHZ) {
+ if (common->channel_width)
+ common->endpoint = EP_2GHZ_40MHZ;
+ else
+ common->endpoint = EP_2GHZ_20MHZ;
+ } else {
+ if (common->channel_width)
+ common->endpoint = EP_5GHZ_40MHZ;
+ else
+ common->endpoint = EP_5GHZ_20MHZ;
+ }
+
+ if (common->endpoint != prev_ep) {
+ status = rsi_program_bb_rf(common);
+ if (status)
+ return status;
+ }
+
+ if (common->channel_width != prev_bw) {
+ status = rsi_load_bootup_params(common);
+ if (status)
+ return status;
+
+ status = rsi_load_radio_caps(common);
+ if (status)
+ return status;
+ }
+
+ return status;
+}
+
+/**
+ * rsi_set_channel() - This function programs the channel.
+ * @common: Pointer to the driver private structure.
+ * @channel: Channel value to be set.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_set_channel(struct rsi_common *common,
+    struct ieee80211_channel *channel)
+{
+ struct sk_buff *skb = NULL;
+ struct rsi_mac_frame *mgmt_frame;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending scan req frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ if (!channel) {
+ dev_kfree_skb(skb);
+ return 0;
+ }
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST);
+ mgmt_frame->desc_word[4] = cpu_to_le16(channel->hw_value);
+
+ mgmt_frame->desc_word[4] |=
+ cpu_to_le16(((char)(channel->max_antenna_gain)) << 8);
+ mgmt_frame->desc_word[5] =
+ cpu_to_le16((char)(channel->max_antenna_gain));
+
+ mgmt_frame->desc_word[7] = cpu_to_le16(PUT_BBP_RESET |
+       BBP_REG_WRITE |
+       (RSI_RF_TYPE << 4));
+
+ if (!(channel->flags & IEEE80211_CHAN_NO_IR) &&
+       !(channel->flags & IEEE80211_CHAN_RADAR)) {
+ if (common->tx_power < channel->max_power)
+ mgmt_frame->desc_word[6] = cpu_to_le16(common->tx_power);
+ else
+ mgmt_frame->desc_word[6] = cpu_to_le16(channel->max_power);
+ }
+ mgmt_frame->desc_word[7] = cpu_to_le16(common->priv->dfs_region);
+
+ if (common->channel_width == BW_40MHZ)
+ mgmt_frame->desc_word[5] |= cpu_to_le16(0x1 << 8);
+
+ common->channel = channel->hw_value;
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_radio_params_update() - This function sends the radio
+ * parameters update to device
+ * @common: Pointer to the driver private structure.
+ * @channel: Channel value to be set.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_send_radio_params_update(struct rsi_common *common)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb = NULL;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending Radio Params update frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(RADIO_PARAMS_UPDATE);
+ mgmt_frame->desc_word[3] = cpu_to_le16(BIT(0));
+
+ mgmt_frame->desc_word[3] |= cpu_to_le16(common->tx_power << 8);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_vap_dynamic_update() - This function programs the threshold.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_send_vap_dynamic_update(struct rsi_common *common)
+{
+ struct sk_buff *skb = NULL;
+ struct rsi_dynamic_s *dynamic_frame = NULL;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending vap update indication frame\n", __func__);
+
+ skb = dev_alloc_skb(sizeof(struct rsi_dynamic_s));
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, sizeof(struct rsi_dynamic_s));
+ dynamic_frame = (struct rsi_dynamic_s *)skb->data;
+
+ dynamic_frame->desc_word[0] = cpu_to_le16(
+ (sizeof(dynamic_frame->frame_body)) |
+ (RSI_WIFI_MGMT_Q << 12));
+ dynamic_frame->desc_word[1] = cpu_to_le16(VAP_DYNAMIC_UPDATE);
+ dynamic_frame->desc_word[4] = cpu_to_le16(common->rts_threshold);
+#if 0
+ dynamic_frame->desc_word[5] = cpu_to_le16(common->frag_threshold);
+ dynamic_frame->desc_word[5] = cpu_to_le16(2352);
+#endif
+// dynamic_frame->desc_word[6] = cpu_to_le16(10); /* bmiss_threshold */
+ dynamic_frame->frame_body.keep_alive_period = cpu_to_le16(90);
+
+#if 0
+ dynamic_frame->frame_body.mgmt_rate = cpu_to_le32(RSI_RATE_6);
+
+ dynamic_frame->desc_word[2] |= cpu_to_le32(BIT(1));/* Self cts enable */
+
+ dynamic_frame->desc_word[3] |= cpu_to_le16(BIT(0));/* fixed rate */
+ dynamic_frame->frame_body.data_rate = cpu_to_le16(0);
+#endif
+
+ dynamic_frame->desc_word[7] |= cpu_to_le16((0 << 8)); /* vap id */
+
+ skb_put(skb, sizeof(struct rsi_dynamic_s));
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_flash_read() - This function sends the frash read frame to device
+ * @adapter: Pointer to the hardware structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_flash_read(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+ struct rsi_mac_frame *cmd_frame = NULL;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending flash read frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb)
+ return -ENOMEM;
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ cmd_frame = (struct rsi_mac_frame *)skb->data;
+
+ /* FrameType */
+ cmd_frame->desc_word[1] = cpu_to_le16(EEPROM_READ);
+
+ /* Format of length and offset differs for
+ * autoflashing and swbl flashing
+ */
+ cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+
+ /* Number of bytes to read */
+ rsi_dbg(INFO_ZONE, " eeprom length  0x%x, %d\n",
+ adapter->eeprom.length, adapter->eeprom.length);
+ cmd_frame->desc_word[3] = cpu_to_le16(adapter->eeprom.length << 4);
+
+ cmd_frame->desc_word[2] |= cpu_to_le16(3 << 8);
+ if (adapter->eeprom_init) {
+ rsi_dbg(INFO_ZONE, "spi init sent");
+ cmd_frame->desc_word[2] |= cpu_to_le16(BIT(13));
+ }
+
+ /* Address to read */
+ cmd_frame->desc_word[4] = cpu_to_le16(adapter->eeprom.offset);
+ cmd_frame->desc_word[5] = cpu_to_le16(adapter->eeprom.offset >> 16);
+ cmd_frame->desc_word[6] = cpu_to_le16(0); //delay = 0
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_compare() - This function is used to compare two integers
+ * @a: pointer to the first integer
+ * @b: pointer to the second integer
+ *
+ * Return: 0 if both are equal, -1 if the first is smaller, else 1
+ */
+static int rsi_compare(const void *a, const void *b)
+{
+ u16 _a = *(const u16 *)(a);
+ u16 _b = *(const u16 *)(b);
+
+ if (_a > _b)
+ return -1;
+
+ if (_a < _b)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * rsi_map_rates() - This function is used to map selected rates to hw rates.
+ * @rate: The standard rate to be mapped.
+ * @offset: Offset that will be returned.
+ *
+ * Return: 0 if it is a mcs rate, else 1
+ */
+static bool rsi_map_rates(u16 rate, int *offset)
+{
+ int kk;
+
+ for (kk = 0; kk < ARRAY_SIZE(rsi_mcsrates); kk++) {
+ if (rate == mcs[kk]) {
+ *offset = kk;
+ return false;
+ }
+ }
+
+ for (kk = 0; kk < ARRAY_SIZE(rsi_rates); kk++) {
+ if (rate == rsi_rates[kk].bitrate / 5) {
+ *offset = kk;
+ break;
+ }
+ }
+ return true;
+}
+
+/**
+ * rsi_send_auto_rate_request() - This function is to set rates for connection
+ *  and send autorate request to firmware.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+static int rsi_send_auto_rate_request(struct rsi_common *common)
+{
+ struct sk_buff *skb;
+ struct rsi_auto_rate *auto_rate;
+ int ii = 0, jj = 0, kk = 0;
+ struct ieee80211_hw *hw = common->priv->hw;
+ u8 band = hw->conf.chandef.chan->band;
+ u8 num_supported_rates = 0;
+ u8 rate_table_offset, rate_offset = 0;
+ u32 rate_bitmap = common->bitrate_mask[band];
+ u16 *selected_rates, min_rate;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending auto rate request frame\n", __func__);
+
+ skb = dev_alloc_skb(sizeof(struct rsi_auto_rate));
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ selected_rates = kzalloc(2 * RSI_TBL_SZ, GFP_KERNEL);
+ if (!selected_rates) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
+ __func__);
+ dev_kfree_skb(skb);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, sizeof(struct rsi_auto_rate));
+ memset(selected_rates, 0, 2 * RSI_TBL_SZ);
+
+ auto_rate = (struct rsi_auto_rate *)skb->data;
+
+ auto_rate->aarf_rssi = cpu_to_le16(((u16)3 << 6) | (u16)(18 & 0x3f));
+ auto_rate->collision_tolerance = cpu_to_le16(3);
+ auto_rate->failure_limit = cpu_to_le16(3);
+ auto_rate->initial_boundary = cpu_to_le16(3);
+ auto_rate->max_threshold_limt = cpu_to_le16(27);
+
+ auto_rate->desc_word[1] = cpu_to_le16(AUTO_RATE_IND);
+
+ if (common->channel_width == BW_40MHZ)
+ auto_rate->desc_word[7] |= cpu_to_le16(1);
+
+ if (band == NL80211_BAND_2GHZ) {
+ min_rate = RSI_RATE_1;
+ rate_table_offset = 0;
+ } else {
+ min_rate = RSI_RATE_6;
+ rate_table_offset = 4;
+ }
+
+ for (ii = 0, jj = 0;
+     ii < (ARRAY_SIZE(rsi_rates) - rate_table_offset); ii++) {
+ if (rate_bitmap & BIT(ii)) {
+ selected_rates[jj++] =
+ (rsi_rates[ii + rate_table_offset].bitrate / 5);
+ rate_offset++;
+ }
+ }
+ num_supported_rates = jj;
+
+ if (common->vif_info[0].is_ht) {
+ for (ii = 0; ii < ARRAY_SIZE(mcs); ii++)
+ selected_rates[jj++] = mcs[ii];
+ num_supported_rates += ARRAY_SIZE(mcs);
+ rate_offset += ARRAY_SIZE(mcs);
+ }
+
+ sort(selected_rates, jj, sizeof(u16), &rsi_compare, NULL);
+
+ /* mapping the rates to RSI rates */
+ for (ii = 0; ii < jj; ii++) {
+ if (rsi_map_rates(selected_rates[ii], &kk)) {
+ auto_rate->supported_rates[ii] =
+ cpu_to_le16(rsi_rates[kk].hw_value);
+ } else {
+ auto_rate->supported_rates[ii] =
+ cpu_to_le16(rsi_mcsrates[kk]);
+ }
+ }
+
+ /* loading HT rates in the bottom half of the auto rate table */
+ if (common->vif_info[0].is_ht) {
+ for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1;
+     ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) {
+ if (common->vif_info[0].sgi ||
+    conf_is_ht40(&common->priv->hw->conf))
+ auto_rate->supported_rates[ii++] =
+ cpu_to_le16(rsi_mcsrates[kk] | BIT(9));
+ auto_rate->supported_rates[ii] =
+ cpu_to_le16(rsi_mcsrates[kk--]);
+ }
+
+ for (; ii < (RSI_TBL_SZ - 1); ii++) {
+ auto_rate->supported_rates[ii] =
+ cpu_to_le16(rsi_mcsrates[0]);
+ }
+ }
+
+ for (; ii < RSI_TBL_SZ; ii++)
+ auto_rate->supported_rates[ii] = cpu_to_le16(min_rate);
+
+ auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2);
+ auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2);
+ auto_rate->desc_word[7] |= cpu_to_le16(0 << 8);
+ num_supported_rates *= 2;
+
+ auto_rate->desc_word[0] = cpu_to_le16((sizeof(*auto_rate) -
+       FRAME_DESC_SZ) |
+       (RSI_WIFI_MGMT_Q << 12));
+
+ skb_put(skb,
+ sizeof(struct rsi_auto_rate));
+ kfree(selected_rates);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_channel_valid() - This function is used to check
+ *              the user channel is valid or not.
+ * @chn_num: It holds the user or default channel for validation.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+static int rsi_channel_valid(u16 chn_num)
+{
+ int status = -1;
+
+ chn_num &= ~(BIT(15)); /* clearing DFS indication in channel num */
+
+ if (((chn_num >= 1) && (chn_num <= 14)) ||
+    ((chn_num >= 36) && (chn_num <= 64)) ||
+    ((chn_num >= 100) && (chn_num <= 140)) ||
+    ((chn_num >= 149) && (chn_num <= 165))) {
+ return 0;
+ }
+
+ return status;
+}
+
+/**
+ * rsi_send_bgscan_params() - This function sends the background
+ *      scan parameters to firmware.
+ * @common: Pointer to the driver private structure.
+ * @enable: bgscan enable/disable
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_send_bgscan_params(struct rsi_common *common, int enable)
+{
+ struct rsi_bgscan_params *bgscan;
+ struct bgscan_config_params *info = &common->bgscan_info;
+ struct sk_buff *skb;
+ u16 frame_len = sizeof(*bgscan);
+ u8 ii;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len);
+
+ if (!info->num_bg_channels) {
+ rsi_dbg(ERR_ZONE, "%s: BG Scan failed,No valid channel found\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ memset(skb->data, 0, frame_len);
+ bgscan = (struct rsi_bgscan_params *)skb->data;
+
+ bgscan->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ) |
+   (RSI_WIFI_MGMT_Q << 12));
+ bgscan->desc_word[1] = cpu_to_le16(BG_SCAN_PARAMS);
+
+ bgscan->bgscan_threshold = cpu_to_le16(info->bgscan_threshold);
+ bgscan->roam_threshold = cpu_to_le16(info->roam_threshold);
+ if (enable)
+ bgscan->bgscan_periodicity =
+ cpu_to_le16(info->bgscan_periodicity);
+ bgscan->active_scan_duration =
+ cpu_to_le16(info->active_scan_duration);
+ bgscan->passive_scan_duration =
+ cpu_to_le16(info->passive_scan_duration);
+ bgscan->two_probe = info->two_probe;
+
+ for (ii = 0; ii < info->num_bg_channels; ii++) {
+ int channel = info->channels2scan[ii];
+
+ if (!rsi_channel_valid(channel))
+ bgscan->channels2scan[ii] =
+ cpu_to_le16(info->channels2scan[ii]);
+ }
+
+ bgscan->num_bg_channels = info->num_bg_channels;
+
+ skb_put(skb, frame_len);
+
+ rsi_hex_dump(MGMT_TX_ZONE, "bgscan params req", skb->data, skb->len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_bgscan_probe_req() - This function sends the background
+ *                               scan probe request to firmware.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, corresponding error code on failure.
+ */
+int rsi_send_bgscan_probe_req(struct rsi_common *common)
+{
+ struct rsi_bgscan_probe *bgscan;
+ struct sk_buff *skb;
+ u16 frame_len = sizeof(*bgscan);
+ u16 len = 1500;
+ u16 pbreq_len = 0;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending bgscan probe req frame\n", __func__);
+
+ skb = dev_alloc_skb(frame_len + len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len + len);
+
+ bgscan = (struct rsi_bgscan_probe *)skb->data;
+
+ bgscan->desc_word[1] = cpu_to_le16(BG_SCAN_PROBE_REQ);
+
+ if (common->band == NL80211_BAND_5GHZ) {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_6);
+ bgscan->channel_num = cpu_to_le16(40);
+ } else {
+ bgscan->mgmt_rate = cpu_to_le16(RSI_RATE_1);
+ bgscan->channel_num = cpu_to_le16(11);
+ }
+
+ bgscan->channel_scan_time = cpu_to_le16(20);
+ if (common->bgscan_probe_req_len > 0) {
+ pbreq_len = common->bgscan_probe_req_len;
+ bgscan->probe_req_length = pbreq_len;
+ memcpy(&skb->data[frame_len], common->bgscan_probe_req, len);
+ *(u16 *)&skb->data[frame_len + 22] =
+ common->bgscan_probe_req[22] + 1;
+ }
+
+ bgscan->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ + pbreq_len) |
+   (RSI_WIFI_MGMT_Q << 12));
+
+ skb_put(skb, frame_len + pbreq_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_inform_bss_status() - This function informs about bss status with the
+ *     help of sta notify params by sending an internal
+ *     management frame to firmware.
+ * @common: Pointer to the driver private structure.
+ * @status: Bss status type.
+ * @bssid: Bssid.
+ * @qos_enable: Qos is enabled.
+ * @aid: Aid (unique for all STAs).
+ *
+ * Return: None.
+ */
+void rsi_inform_bss_status(struct rsi_common *common,
+   u8 status,
+   const unsigned char *bssid,
+   u8 qos_enable,
+   u16 aid)
+{
+ if (status) {
+ common->hw_data_qs_blocked = true;
+ rsi_send_sta_notify_frame(common,
+  RSI_IFTYPE_STATION,
+  STA_CONNECTED,
+  bssid,
+  qos_enable,
+  aid);
+ if (common->min_rate == 0xffff) {
+ rsi_dbg(INFO_ZONE, "Send auto rate request\n");
+ rsi_send_auto_rate_request(common);
+ }
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
+ } else {
+ common->hw_data_qs_blocked = true;
+ rsi_send_sta_notify_frame(common,
+  RSI_IFTYPE_STATION,
+  STA_DISCONNECTED,
+  bssid,
+  qos_enable,
+  aid);
+ rsi_send_block_unblock_frame(common, true);
+ }
+}
+
+/**
+ * rsi_eeprom_read() - This function sends a frame to read the mac address
+ *       from the eeprom.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_eeprom_read(struct rsi_common *common)
+{
+ struct rsi_mac_frame *mgmt_frame = NULL;
+ struct rsi_hw *adapter = common->priv;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE,
+ "%s: Sending EEPROM read req frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ /* FrameType */
+ mgmt_frame->desc_word[1] = cpu_to_le16(EEPROM_READ);
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+
+ /* Number of bytes to read */
+ mgmt_frame->desc_word[3] = cpu_to_le16(adapter->eeprom.length << 4);
+ mgmt_frame->desc_word[2] |= cpu_to_le16(3 << 8);
+
+ /* Address to read*/
+ mgmt_frame->desc_word[4] = cpu_to_le16(adapter->eeprom.offset);
+ mgmt_frame->desc_word[5] = cpu_to_le16(adapter->eeprom.offset >> 16);
+ mgmt_frame->desc_word[6] = cpu_to_le16(0); //delay = 0
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * This function sends a frame to block/unblock
+ * data queues in the firmware
+ *
+ * @param common Pointer to the driver private structure.
+ * @param block event - block if true, unblock if false
+ * @return 0 on success, -1 on failure.
+ */
+int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending block/unblock frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(BLOCK_HW_QUEUE);
+ mgmt_frame->desc_word[3] = cpu_to_le16(0x1);
+
+ if (block_event == true) {
+ rsi_dbg(INFO_ZONE, "blocking the data qs\n");
+ mgmt_frame->desc_word[4] = cpu_to_le16(0xf);
+ mgmt_frame->desc_word[4] |= cpu_to_le16(0xf << 4);
+ } else {
+ rsi_dbg(INFO_ZONE, "unblocking the data qs\n");
+ mgmt_frame->desc_word[5] = cpu_to_le16(0xf);
+ mgmt_frame->desc_word[5] |= cpu_to_le16(0xf << 4);
+ }
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * This function sends a frame to filter the RX packets
+ *
+ * @param common Pointer to the driver private structure.
+ * @param rx_filter_word - Flags of filter packets
+ * @return 0 on success, -1 on failure.
+ */
+int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb;
+
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sending RX filter frame\n", __func__);
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ mgmt_frame->desc_word[1] = cpu_to_le16(SET_RX_FILTER);
+ mgmt_frame->desc_word[4] = cpu_to_le16(rx_filter_word);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_send_ps_request() - Sends power save request.
+ *
+ * @adapter: pointer to rsi_hw structure.
+ * @enable: enable or disable power save.
+ *
+ * returns: 0 on success, negative error code on failure
+ */
+int rsi_send_ps_request(struct rsi_hw *adapter, bool enable)
+{
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+ struct rsi_request_ps *ps = NULL;
+ struct rsi_ps_info *ps_info = NULL;
+ struct sk_buff *skb = NULL;
+ int frame_len = sizeof(*ps);
+
+ skb = dev_alloc_skb(frame_len);
+ if (!skb)
+ return -ENOMEM;
+ memset(skb->data, 0, frame_len);
+
+ ps = (struct rsi_request_ps *)&skb->data[0];
+ ps_info = &adapter->ps_info;
+
+ ps->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ) |
+       (RSI_WIFI_MGMT_Q << 12));
+ ps->desc_word[1] = cpu_to_le16(WAKEUP_SLEEP_REQUEST);
+ if (enable) {
+ ps->ps_sleep.enable = 1;
+ ps->desc_word[6] = SLEEP_REQUEST;
+ } else {
+ ps->ps_sleep.enable = 0;
+ ps->desc_word[0] |= BIT(15);
+ ps->desc_word[6] = WAKEUP_REQUEST;
+ }
+
+ if (common->uapsd_bitmap) {
+// ps->ps_mimic_support = 1;
+ ps->ps_uapsd_acs = common->uapsd_bitmap;
+ }
+
+ ps->ps_sleep.sleep_type = ps_info->sleep_type;
+ ps->ps_sleep.num_bcns_per_lis_int =
+ cpu_to_le16(ps_info->num_bcns_per_lis_int);
+ ps->ps_sleep.sleep_duration =
+ cpu_to_le32(ps_info->deep_sleep_wakeup_period);
+
+ if (bss->assoc)
+ ps->ps_sleep.connected_sleep = CONNECTED_SLEEP;
+ else
+ ps->ps_sleep.connected_sleep = DEEP_SLEEP;
+
+ ps->ps_listen_interval = cpu_to_le32(ps_info->listen_interval);
+ ps->ps_dtim_interval_duration =
+ cpu_to_le32(ps_info->dtim_interval_duration);
+ ps->ps_num_dtim_intervals = cpu_to_le32(ps_info->num_dtims_per_sleep);
+
+ skb_put(skb, frame_len);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_set_antenna() - This fuction handles antenna selection functionality.
+ *
+ * @common: Pointer to the driver private structure.
+ * @antenna: bitmap for tx antenna selection
+ *
+ * Return: 0 on Success, < 0 on failure
+ */
+int rsi_set_antenna(struct rsi_common *common,
+    u8 antenna)
+{
+ struct rsi_mac_frame *mgmt_frame;
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ);
+ if (!skb) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ memset(skb->data, 0, FRAME_DESC_SZ);
+ mgmt_frame = (struct rsi_mac_frame *)skb->data;
+
+ mgmt_frame->desc_word[1] = cpu_to_le16(ANT_SEL_FRAME);
+ mgmt_frame->desc_word[3] = cpu_to_le16(antenna & 0x00ff);
+ mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+
+ skb_put(skb, FRAME_DESC_SZ);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+
+/**
+ * rsi_handle_ta_confirm() - This function handles the confirm frames.
+ * @common: Pointer to the driver private structure.
+ * @msg: Pointer to received packet.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
+{
+ struct rsi_hw *adapter = common->priv;
+ u8 sub_type = (msg[15] & 0xff);
+
+ rsi_dbg(MGMT_RX_ZONE, "%s: subtype=%d\n", __func__, sub_type);
+
+ switch (sub_type) {
+ case COMMON_DEV_CONFIG:
+ rsi_dbg(FSM_ZONE,
+ "Common Dev Config params confirm received\n");
+ if (common->fsm_state == FSM_COMMON_DEV_PARAMS_SENT) {
+ if (rsi_load_bootup_params(common)) {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ goto out;
+ } else {
+ common->fsm_state = FSM_BOOT_PARAMS_SENT;
+ }
+ } else {
+ rsi_dbg(INFO_ZONE,
+ "%s: Received common dev config params cfm in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
+ }
+ break;
+
+ case BOOTUP_PARAMS_REQUEST:
+ rsi_dbg(FSM_ZONE, "Bootup params confirmation.\n");
+ if (common->fsm_state == FSM_BOOT_PARAMS_SENT) {
+ adapter->eeprom.length = (IEEE80211_ADDR_LEN +
+  WLAN_MAC_MAGIC_WORD_LEN +
+  WLAN_HOST_MODE_LEN);
+ adapter->eeprom.offset = WLAN_MAC_EEPROM_ADDR;
+ if (rsi_eeprom_read(common)) {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ goto out;
+ } else
+ common->fsm_state = FSM_EEPROM_READ_MAC_ADDR;
+ } else {
+ rsi_dbg(INFO_ZONE,
+ "%s: Received bootup params cfm in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
+ }
+ break;
+
+ case EEPROM_READ:
+ rsi_dbg(FSM_ZONE, "EEPROM READ confirm received\n");
+ if (common->fsm_state == FSM_EEPROM_READ_MAC_ADDR) {
+ u32 msg_len = ((u16 *)msg)[0] & 0xfff;
+
+ if (msg_len <= 0) {
+ rsi_dbg(FSM_ZONE,
+ "%s: [EEPROM_READ] Invalid len %d\n",
+ __func__, msg_len);
+ goto out;
+ }
+ if (msg[16] == MAGIC_WORD) {
+ u8 offset = (FRAME_DESC_SZ +
+     WLAN_HOST_MODE_LEN +
+     WLAN_MAC_MAGIC_WORD_LEN);
+
+ memcpy(common->mac_addr,
+       &msg[offset],
+       IEEE80211_ADDR_LEN);
+ rsi_hex_dump(INIT_ZONE,
+     "MAC Addr",
+     common->mac_addr, ETH_ALEN);
+ adapter->eeprom.length =
+ ((WLAN_MAC_MAGIC_WORD_LEN + 3) & (~3));
+ adapter->eeprom.offset =
+ WLAN_EEPROM_RFTYPE_ADDR;
+ if (rsi_eeprom_read(common)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed reading RF band\n",
+ __func__);
+ common->fsm_state = FSM_CARD_NOT_READY;
+ } else {
+ common->fsm_state =
+ FSM_EEPROM_READ_RF_TYPE;
+ }
+ } else {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ break;
+ }
+ } else if (common->fsm_state == FSM_EEPROM_READ_RF_TYPE) {
+ u32 msg_len = ((u16 *)msg)[0] & 0xfff;
+
+ if (msg_len <= 0) {
+ rsi_dbg(FSM_ZONE,
+ "%s:[EEPROM_READ_CFM] Invalid len %d\n",
+ __func__, msg_len);
+ goto out;
+ }
+ if (msg[16] == MAGIC_WORD) {
+ if ((msg[17] & 0x3) == 0x3) {
+ rsi_dbg(INIT_ZONE,
+ "Dual band supported\n");
+ common->band = NL80211_BAND_5GHZ;
+ } else if ((msg[17] & 0x3) == 0x1) {
+ rsi_dbg(INIT_ZONE,
+ "Only 2.4Ghz band supported\n");
+ common->band = NL80211_BAND_2GHZ;
+ }
+ } else {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ break;
+ }
+ if (rsi_send_reset_mac(common))
+ goto out;
+ else
+ common->fsm_state = FSM_RESET_MAC_SENT;
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: Received eeprom read in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
+ }
+ break;
+
+ case RESET_MAC_REQ:
+ if (common->fsm_state == FSM_RESET_MAC_SENT) {
+ rsi_dbg(FSM_ZONE, "Reset MAC confirm\n");
+
+ if (rsi_load_radio_caps(common))
+ goto out;
+ else
+ common->fsm_state = FSM_RADIO_CAPS_SENT;
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: Received reset mac cfm in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
+ }
+ break;
+
+ case RADIO_CAPABILITIES:
+ if (common->fsm_state == FSM_RADIO_CAPS_SENT) {
+ common->rf_reset = 1;
+ if (rsi_program_bb_rf(common)) {
+ goto out;
+ } else {
+ common->fsm_state = FSM_BB_RF_PROG_SENT;
+ rsi_dbg(FSM_ZONE, "Radio caps confirm\n");
+ }
+ } else {
+ rsi_dbg(INFO_ZONE,
+ "%s: Received radio caps cfm in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
+ }
+ break;
+
+ case BB_PROG_VALUES_REQUEST:
+ case RF_PROG_VALUES_REQUEST:
+ case BBP_PROG_IN_TA:
+ rsi_dbg(FSM_ZONE, "BB/RF confirmation.\n");
+ if (common->fsm_state == FSM_BB_RF_PROG_SENT) {
+ common->bb_rf_prog_count--;
+ if (!common->bb_rf_prog_count) {
+ common->fsm_state = FSM_MAC_INIT_DONE;
+ return rsi_mac80211_attach(common);
+ }
+ } else {
+ rsi_dbg(INFO_ZONE,
+ "%s: Received bb_rf cfm in %d state\n",
+ __func__, common->fsm_state);
+ return 0;
+ }
+ break;
+
+ case AMPDU_IND:
+ rsi_dbg(FSM_ZONE, "AMPDU indication.\n");
+ break;
+
+ case SCAN_REQUEST:
+ rsi_dbg(FSM_ZONE, "Scan confirm.\n");
+ break;
+
+ case SET_RX_FILTER:
+ rsi_dbg(FSM_ZONE, "RX Filter confirmation.\n");
+ break;
+
+ case WAKEUP_SLEEP_REQUEST:
+ rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
+ return rsi_handle_ps_confirm(adapter, msg);
+
+ case BG_SCAN_PROBE_REQ:
+ rsi_dbg(INFO_ZONE, "BG scan complete event\n");
+
+ /* resume to connected channel if associated */
+ rsi_resume_conn_channel(adapter);
+ break;
+
+ default:
+ rsi_dbg(INFO_ZONE,
+ "%s: Invalid TA confirm type : %x\n",
+ __func__, sub_type);
+ break;
+ }
+ return 0;
+
+out:
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to send pkt/Invalid frame received\n",
+ __func__);
+ return -EINVAL;
+}
+
+/**
+ *rsi_handle_card_ready() - This function handles the card ready
+ *                       indication from firmware.
+ *@common: Pointer to the driver private structure.
+ *
+ *Return: 0 on success, -1 on failure.
+ */
+int rsi_handle_card_ready(struct rsi_common *common)
+{
+ switch (common->fsm_state) {
+ case FSM_CARD_NOT_READY:
+ rsi_dbg(INIT_ZONE, "Card ready indication from wlan.\n");
+ rsi_set_default_parameters(common);
+ if (rsi_send_common_dev_params(common) < 0)
+ return -EINVAL;
+ common->fsm_state = FSM_COMMON_DEV_PARAMS_SENT;
+ break;
+ case FSM_COMMON_DEV_PARAMS_SENT:
+ rsi_dbg(INIT_ZONE, "Common dev config params confirm\n");
+ if (rsi_load_bootup_params(common)) {
+ common->fsm_state = FSM_CARD_NOT_READY;
+ return -EINVAL;
+ }
+ common->fsm_state = FSM_BOOT_PARAMS_SENT;
+ break;
+ default:
+ rsi_dbg(ERR_ZONE,
+ "%s: card ready indication in invalid state %d.\n",
+ __func__, common->fsm_state);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * rsi_mgmt_pkt_recv() - This function processes the management packets
+ * received from the hardware.
+ * @common: Pointer to the driver private structure.
+ * @msg: Pointer to the received packet.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
+{
+ s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff);
+ u16 msg_type = msg[2];
+
+ switch (msg_type) {
+ case TA_CONFIRM_TYPE:
+ return rsi_handle_ta_confirm(common, msg);
+
+ case CARD_READY_IND:
+ return rsi_handle_card_ready(common);
+
+ case TX_STATUS_IND:
+ if (msg[15] == PROBEREQ_CONFIRM) {
+ common->mgmt_q_block = false;
+ rsi_dbg(INFO_ZONE, "Mgmt queue unblocked\n");
+ }
+ break;
+
+ case PS_NOTIFY_IND:
+ rsi_dbg(FSM_ZONE, "Powersave notify indication.\n");
+ break;
+
+ case SLEEP_NOTIFY_IND:
+ rsi_dbg(FSM_ZONE, "Sleep notify indication.\n");
+ break;
+
+ case DECRYPT_ERROR_IND:
+ rsi_dbg(INFO_ZONE, "Error in decrypt.\n");
+ break;
+
+ case DEBUG_IND:
+ rsi_dbg(INFO_ZONE, "Debugging indication.\n");
+ break;
+
+ case RX_MISC_IND:
+ rsi_dbg(INFO_ZONE, "RX misc indication.\n");
+ break;
+
+ case HW_BMISS_EVENT:
+ rsi_dbg(INFO_ZONE, "Hardware beacon miss event\n");
+ rsi_indicate_bcnmiss(common);
+ //if (common->bgscan_en)
+ rsi_resume_conn_channel(common->priv);
+ break;
+
+ default:
+ return rsi_mgmt_pkt_to_core(common, msg, msg_len, msg_type);
+ }
+
+ return 0;
+}
+
diff --git a/ubuntu/rsi/rsi_91x_ps.c b/ubuntu/rsi/rsi_91x_ps.c
new file mode 100644
index 0000000..7aa5ac9
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_ps.c
@@ -0,0 +1,202 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if.h>
+#include <linux/version.h>
+#include "rsi_debugfs.h"
+#include "rsi_mgmt.h"
+#include "rsi_common.h"
+#include "rsi_ps.h"
+
+/**
+ * str_psstate() - return the ps state in string format.
+ *
+ * @state - PS state.
+ *
+ * return: PS state in string format.
+ */
+char *str_psstate(enum ps_state state)
+{
+ switch (state) {
+ case PS_NONE:
+ return "PS_NONE";
+ case PS_DISABLE_REQ_SENT:
+ return "PS_DISABLE_REQ_SENT";
+ case PS_ENABLE_REQ_SENT:
+ return "PS_ENABLE_REQ_SENT";
+ case PS_ENABLED:
+ return "PS_ENABLED";
+ default:
+ return "INVALID_STATE";
+ }
+ return "INVALID_STATE";
+}
+
+/**
+ * rsi_modify_ps_state() - Modify PS state to a new state.
+ *
+ * @adapter: pointer to rsi_hw structure.
+ * @nstate: new PS state.
+ *
+ * return: new state.
+ */
+static inline void rsi_modify_ps_state(struct rsi_hw *adapter,
+       enum ps_state nstate)
+{
+ rsi_dbg(INFO_ZONE, "PS state changed %s => %s\n",
+ str_psstate(adapter->ps_state),
+ str_psstate(nstate));
+
+ adapter->ps_state = nstate;
+}
+
+/**
+ * rsi_default_ps_params() - Initalization of default powersave parameters.
+ *
+ * @adapter: pointer to rsi_hw structure.
+ *
+ * return: void.
+ */
+void rsi_default_ps_params(struct rsi_hw *adapter)
+{
+ struct rsi_ps_info *ps_info = &adapter->ps_info;
+
+ ps_info->enabled = true;
+ ps_info->sleep_type = 1; /* LP */
+ ps_info->tx_threshold = 0;
+ ps_info->rx_threshold = 0;
+ ps_info->tx_hysterisis = 0;
+ ps_info->rx_hysterisis = 0;
+ ps_info->monitor_interval = 0;
+ ps_info->listen_interval = 2 * 100;
+ ps_info->num_bcns_per_lis_int = 0;
+ ps_info->dtim_interval_duration = 0;
+ ps_info->num_dtims_per_sleep = 0;
+ ps_info->deep_sleep_wakeup_period = 100;
+}
+EXPORT_SYMBOL_GPL(rsi_default_ps_params);
+
+/**
+ * rsi_enable_ps() - enable power save
+ *
+ * @adapter: Pointer to rsi_hw structure.
+ *
+ * return: void.
+ */
+void rsi_enable_ps(struct rsi_hw *adapter)
+{
+ if (adapter->ps_state != PS_NONE) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Cannot accept enable PS in %s state\n",
+ __func__, str_psstate(adapter->ps_state));
+ return;
+ }
+
+ if (rsi_send_ps_request(adapter, true)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to send PS request to device\n",
+ __func__);
+ return;
+ }
+
+ rsi_modify_ps_state(adapter, PS_ENABLE_REQ_SENT);
+}
+
+/**
+ * rsi_disable_ps() - disable power save
+ *
+ * @adapter: Pointer to rsi_hw structure.
+ *
+ * return: void.
+ */
+void rsi_disable_ps(struct rsi_hw *adapter)
+{
+ if (adapter->ps_state != PS_ENABLED) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Cannot accept disable PS in %s state\n",
+ __func__, str_psstate(adapter->ps_state));
+ return;
+ }
+
+ if (rsi_send_ps_request(adapter, false)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to send PS request to device\n",
+ __func__);
+ return;
+ }
+
+ rsi_modify_ps_state(adapter, PS_DISABLE_REQ_SENT);
+}
+
+/**
+ * rsi_conf_uapsd() - configures UAPSD powersave.
+ *
+ * @adapter - Pointer to rsi_hw structure.
+ *
+ * return: void.
+ */
+void rsi_conf_uapsd(struct rsi_hw *adapter)
+{
+ if (adapter->ps_state != PS_ENABLED)
+ return;
+
+ if (rsi_send_ps_request(adapter, false)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to send PS request to device\n",
+ __func__);
+ return;
+ }
+
+ if (rsi_send_ps_request(adapter, true)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to send PS request to device\n",
+ __func__);
+ }
+}
+
+/**
+ * rsi_handle_ps_confirm() - Processes powersave confirmation.
+ *
+ * @adapter - Pointer to rsi_hw structure.
+ * @msg - Recevied buffer.
+ *
+ * return: 0 on success.
+ */
+int rsi_handle_ps_confirm(struct rsi_hw *adapter, u8 *msg)
+{
+ u16 cfm_type = 0;
+
+ cfm_type = *(u16 *)&msg[PS_CONFIRM_INDEX];
+
+ switch (cfm_type) {
+ case SLEEP_REQUEST:
+ if (adapter->ps_state == PS_ENABLE_REQ_SENT)
+ rsi_modify_ps_state(adapter, PS_ENABLED);
+ break;
+ case WAKEUP_REQUEST:
+ if (adapter->ps_state == PS_DISABLE_REQ_SENT)
+ rsi_modify_ps_state(adapter, PS_NONE);
+ break;
+ default:
+ rsi_dbg(ERR_ZONE,
+ "Invalid PS confirm type %x in state %s\n",
+ cfm_type, str_psstate(adapter->ps_state));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
new file mode 100644
index 0000000..fc99d51
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -0,0 +1,1170 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Developers:
+ * Fariya Fathima 2014 <[hidden email]>
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/module.h>
+#include "rsi_sdio.h"
+#include "rsi_common.h"
+#include "rsi_hal.h"
+
+/**
+ * rsi_sdio_set_cmd52_arg() - This function prepares cmd 52 read/write arg.
+ * @rw: Read/write
+ * @func: function number
+ * @raw: indicates whether to perform read after write
+ * @address: address to which to read/write
+ * @writedata: data to write
+ *
+ * Return: argument
+ */
+static u32 rsi_sdio_set_cmd52_arg(bool rw,
+  u8 func,
+  u8 raw,
+  u32 address,
+  u8 writedata)
+{
+ return ((rw & 1) << 31) | ((func & 0x7) << 28) |
+ ((raw & 1) << 27) | (1 << 26) |
+ ((address & 0x1FFFF) << 9) | (1 << 8) |
+ (writedata & 0xFF);
+}
+
+/**
+ * rsi_cmd52writebyte() - This function issues cmd52 byte write onto the card.
+ * @card: Pointer to the mmc_card.
+ * @address: Address to write.
+ * @byte: Data to write.
+ *
+ * Return: Write status.
+ */
+static int rsi_cmd52writebyte(struct mmc_card *card,
+      u32 address,
+      u8 byte)
+{
+ struct mmc_command io_cmd;
+ u32 arg;
+
+ memset(&io_cmd, 0, sizeof(io_cmd));
+ arg = rsi_sdio_set_cmd52_arg(1, 0, 0, address, byte);
+ io_cmd.opcode = SD_IO_RW_DIRECT;
+ io_cmd.arg = arg;
+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ return mmc_wait_for_cmd(card->host, &io_cmd, 0);
+}
+
+/**
+ * rsi_cmd52readbyte() - This function issues cmd52 byte read onto the card.
+ * @card: Pointer to the mmc_card.
+ * @address: Address to read from.
+ * @byte: Variable to store read value.
+ *
+ * Return: Read status.
+ */
+static int rsi_cmd52readbyte(struct mmc_card *card,
+     u32 address,
+     u8 *byte)
+{
+ struct mmc_command io_cmd;
+ u32 arg;
+ int err;
+
+ memset(&io_cmd, 0, sizeof(io_cmd));
+ arg = rsi_sdio_set_cmd52_arg(0, 0, 0, address, 0);
+ io_cmd.opcode = SD_IO_RW_DIRECT;
+ io_cmd.arg = arg;
+ io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+ err = mmc_wait_for_cmd(card->host, &io_cmd, 0);
+ if ((!err) && (byte))
+ *byte =  io_cmd.resp[0] & 0xFF;
+ return err;
+}
+
+/**
+ * rsi_issue_sdiocommand() - This function issues sdio commands.
+ * @func: Pointer to the sdio_func structure.
+ * @opcode: Opcode value.
+ * @arg: Arguments to pass.
+ * @flags: Flags which are set.
+ * @resp: Pointer to store response.
+ *
+ * Return: err: command status as 0 or -1.
+ */
+static int rsi_issue_sdiocommand(struct sdio_func *func,
+ u32 opcode,
+ u32 arg,
+ u32 flags,
+ u32 *resp)
+{
+ struct mmc_command cmd;
+ struct mmc_host *host;
+ int err;
+
+ host = func->card->host;
+
+ memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = opcode;
+ cmd.arg = arg;
+ cmd.flags = flags;
+ err = mmc_wait_for_cmd(host, &cmd, 3);
+
+ if ((!err) && (resp))
+ *resp = cmd.resp[0];
+
+ return err;
+}
+
+/**
+ * rsi_handle_interrupt() - This function is called upon the occurrence
+ *    of an interrupt.
+ * @function: Pointer to the sdio_func structure.
+ *
+ * Return: None.
+ */
+static void rsi_handle_interrupt(struct sdio_func *function)
+{
+ struct rsi_hw *adapter = sdio_get_drvdata(function);
+
+ sdio_release_host(function);
+ rsi_interrupt_handler(adapter);
+ sdio_claim_host(function);
+}
+
+void rsi_gspi_init(struct rsi_hw *adapter)
+{
+ unsigned long gspi_ctrl_reg0_val;
+
+ /* Programming gspi frequency = soc_frequency / 2 */
+ /* Warning : ULP seemed to be not working
+ * well at high frequencies. Modify accordingly */
+ gspi_ctrl_reg0_val = 0x4;
+ /* csb_setup_time [5:4] */
+ gspi_ctrl_reg0_val |= 0x10;
+ /* csb_hold_time [7:6] */
+ gspi_ctrl_reg0_val |= 0x40;
+ /* csb_high_time [9:8] */
+ gspi_ctrl_reg0_val |= 0x100;
+ /* spi_mode [10] */
+ gspi_ctrl_reg0_val |= 0x000;
+ /* clock_phase [11] */
+ gspi_ctrl_reg0_val |= 0x000;
+ /* Initializing GSPI for ULP read/writes */
+ rsi_sdio_master_reg_write(adapter,
+  GSPI_CTRL_REG0,
+  gspi_ctrl_reg0_val,
+  2);
+}
+
+void ulp_read_write(struct rsi_hw *adapter, u16 addr, u16 *data, u16 len_in_bits)
+{
+ rsi_sdio_master_reg_write(adapter,
+  GSPI_DATA_REG1,
+  ((addr << 6) | (data[1] & 0x3f)),
+  2);
+ rsi_sdio_master_reg_write(adapter,
+  GSPI_DATA_REG0,
+  *(u16 *)&data[0],
+  2);
+ rsi_gspi_init(adapter);
+ rsi_sdio_master_reg_write(adapter,
+  GSPI_CTRL_REG1,
+  ((len_in_bits - 1) | GSPI_TRIG),
+  2);
+ msleep(10);
+}
+
+static void rsi_reset_chip(struct rsi_hw *adapter)
+{
+ u16 temp[4] = {0};
+ u32 data;
+ u8 sdio_interrupt_status = 0;
+ u8 request = 1;
+
+ rsi_dbg(INFO_ZONE, "Writing disable to wakeup register\n");
+ if (rsi_sdio_write_register(adapter,
+ 0,
+    SDIO_WAKEUP_REG,
+    &request) < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to Write SDIO WAKEUP REG\n", __func__);
+ return;
+ }
+ msleep(3);
+ if (rsi_sdio_read_register(adapter,
+   RSI_FN1_INT_REGISTER,
+   &sdio_interrupt_status) < 0) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to Read Intr Status Register\n",
+ __func__);
+ return;
+ }
+ rsi_dbg(INFO_ZONE, "%s: Intr Status Register value = %d \n",
+ __func__, sdio_interrupt_status);
+
+ /* Put TA on hold */
+ if (rsi_sdio_master_access_msword(adapter, 0x2200)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return ;
+ }
+
+ data = TA_HOLD_THREAD_VALUE;
+ if (rsi_sdio_write_register_multiple(adapter,
+ TA_HOLD_THREAD_REG | SD_REQUEST_MASTER,
+ (u8 *)&data,
+ 4)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to hold TA threads\n", __func__);
+ return ;
+ }
+
+ /* This msleep will ensure TA processor to go to hold and any pending dma
+ * transfers to rf spi in device to finish */
+ msleep(100);
+
+ *(u32 *)temp = 0;
+ ulp_read_write(adapter, ULP_RESET_REG, temp, 32);
+ *(u32 *)temp = 2;
+ ulp_read_write(adapter, WATCH_DOG_TIMER_1, temp, 32);
+ *(u32 *)temp = 0;
+ ulp_read_write(adapter, WATCH_DOG_TIMER_2, temp, 32);
+ *(u32 *)temp = 50;
+ ulp_read_write(adapter, WATCH_DOG_DELAY_TIMER_1, temp, 32);
+ *(u32 *)temp = 0;
+ ulp_read_write(adapter, WATCH_DOG_DELAY_TIMER_2, temp, 32);
+ *(u32 *)temp = ((0xaa000) | RESTART_WDT | BYPASS_ULP_ON_WDT);
+ ulp_read_write(adapter, WATCH_DOG_TIMER_ENABLE, temp, 32);
+ msleep(1000);
+}
+
+/**
+ * rsi_reset_card() - This function resets and re-initializes the card.
+ * @pfunction: Pointer to the sdio_func structure.
+ *
+ * Return: None.
+ */
+static void rsi_reset_card(struct sdio_func *pfunction)
+{
+ int err;
+ struct mmc_card *card = pfunction->card;
+ struct mmc_host *host = card->host;
+ s32 bit = (fls(host->ocr_avail) - 1);
+ u8 cmd52_resp = 0;
+ u32 clock, resp, i;
+ u16 rca;
+
+#if 0
+ /* Reset 9110 chip */
+ ret = rsi_cmd52writebyte(pfunction->card,
+ SDIO_CCCR_ABORT,
+ (1 << 3));
+
+ /* Card will not send any response as it is getting reset immediately
+ * Hence expect a timeout status from host controller
+ */
+ if (ret != -ETIMEDOUT)
+ rsi_dbg(ERR_ZONE, "%s: Reset failed : %d\n", __func__, ret);
+#endif
+
+ /* Wait for few milli seconds to get rid of residue charges if any */
+ msleep(2);
+
+ /* Initialize the SDIO card */
+ host->ios.vdd = bit;
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ host->ios.power_mode = MMC_POWER_UP;
+ host->ios.bus_width = MMC_BUS_WIDTH_1;
+ host->ios.timing = MMC_TIMING_LEGACY;
+ host->ops->set_ios(host, &host->ios);
+
+ /*
+ * This delay should be sufficient to allow the power supply
+ * to reach the minimum voltage.
+ */
+ msleep(2);
+
+ host->ios.clock = host->f_min;
+ host->ios.power_mode = MMC_POWER_ON;
+ host->ops->set_ios(host, &host->ios);
+
+ /*
+ * This delay must be at least 74 clock sizes, or 1 ms, or the
+ * time required to reach a stable voltage.
+ */
+ msleep(2);
+
+ /* Issue CMD0. Goto idle state */
+ host->ios.chip_select = MMC_CS_HIGH;
+ host->ops->set_ios(host, &host->ios);
+ msleep(1);
+ err = rsi_issue_sdiocommand(pfunction,
+    MMC_GO_IDLE_STATE,
+    0,
+    (MMC_RSP_NONE | MMC_CMD_BC),
+    NULL);
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ops->set_ios(host, &host->ios);
+ msleep(1);
+ host->use_spi_crc = 0;
+
+ if (err)
+ rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);
+
+// if (!host->ocr_avail) {
+ if (1) {
+ /* Issue CMD5, arg = 0 */
+ err = rsi_issue_sdiocommand(pfunction,
+    SD_IO_SEND_OP_COND,
+    0,
+    (MMC_RSP_R4 | MMC_CMD_BCR),
+    &resp);
+ if (err)
+ rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
+ __func__, err);
+ card->ocr = resp;
+ }
+
+ /* Issue CMD5, arg = ocr. Wait till card is ready  */
+ for (i = 0; i < 100; i++) {
+ err = rsi_issue_sdiocommand(pfunction,
+    SD_IO_SEND_OP_COND,
+    card->ocr,
+    (MMC_RSP_R4 | MMC_CMD_BCR),
+    &resp);
+ if (err) {
+ rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
+ __func__, err);
+ break;
+ }
+
+ if (resp & MMC_CARD_BUSY)
+ break;
+ msleep(10);
+ }
+
+ if ((i == 100) || (err)) {
+ rsi_dbg(ERR_ZONE, "%s: card in not ready : %d %d\n",
+ __func__, i, err);
+ return;
+ }
+
+ /* Issue CMD3, get RCA */
+ err = rsi_issue_sdiocommand(pfunction,
+    SD_SEND_RELATIVE_ADDR,
+    0,
+    (MMC_RSP_R6 | MMC_CMD_BCR),
+    &resp);
+ if (err) {
+ rsi_dbg(ERR_ZONE, "%s: CMD3 failed : %d\n", __func__, err);
+ return;
+ }
+ rca = resp >> 16;
+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+ host->ops->set_ios(host, &host->ios);
+
+ /* Issue CMD7, select card  */
+ err = rsi_issue_sdiocommand(pfunction,
+    MMC_SELECT_CARD,
+    (rca << 16),
+    (MMC_RSP_R1 | MMC_CMD_AC),
+    NULL);
+ if (err) {
+ rsi_dbg(ERR_ZONE, "%s: CMD7 failed : %d\n", __func__, err);
+ return;
+ }
+
+ /* Enable high speed */
+ if (card->host->caps & MMC_CAP_SD_HIGHSPEED) {
+ rsi_dbg(ERR_ZONE, "%s: Set high speed mode\n", __func__);
+ err = rsi_cmd52readbyte(card, SDIO_CCCR_SPEED, &cmd52_resp);
+ if (err) {
+ rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",
+ __func__, err);
+ } else {
+ err = rsi_cmd52writebyte(card,
+ SDIO_CCCR_SPEED,
+ (cmd52_resp | SDIO_SPEED_EHS));
+ if (err) {
+ rsi_dbg(ERR_ZONE,
+ "%s: CCR speed regwrite failed %d\n",
+ __func__, err);
+ return;
+ }
+ host->ios.timing = MMC_TIMING_SD_HS;
+ host->ops->set_ios(host, &host->ios);
+ }
+ }
+
+ /* Set clock */
+ if (mmc_card_hs(card))
+ clock = 50000000;
+ else
+ clock = card->cis.max_dtr;
+
+ if (clock > host->f_max)
+ clock = host->f_max;
+
+ host->ios.clock = clock;
+ host->ops->set_ios(host, &host->ios);
+
+ if (card->host->caps & MMC_CAP_4_BIT_DATA) {
+ /* CMD52: Set bus width & disable card detect resistor */
+ err = rsi_cmd52writebyte(card,
+ SDIO_CCCR_IF,
+ (SDIO_BUS_CD_DISABLE |
+  SDIO_BUS_WIDTH_4BIT));
+ if (err) {
+ rsi_dbg(ERR_ZONE, "%s: Set bus mode failed : %d\n",
+ __func__, err);
+ return;
+ }
+ host->ios.bus_width = MMC_BUS_WIDTH_4;
+ host->ops->set_ios(host, &host->ios);
+ }
+}
+
+/**
+ * rsi_setclock() - This function sets the clock frequency.
+ * @adapter: Pointer to the adapter structure.
+ * @freq: Clock frequency.
+ *
+ * Return: None.
+ */
+static void rsi_setclock(struct rsi_hw *adapter, u32 freq)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ struct mmc_host *host = dev->pfunction->card->host;
+ u32 clock;
+
+ clock = freq * 1000;
+ if (clock > host->f_max)
+ clock = host->f_max;
+ host->ios.clock = clock;
+ host->ops->set_ios(host, &host->ios);
+}
+
+/**
+ * rsi_setblocklength() - This function sets the host block length.
+ * @adapter: Pointer to the adapter structure.
+ * @length: Block length to be set.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ int status;
+
+ rsi_dbg(INIT_ZONE, "%s: Setting the block length\n", __func__);
+
+ status = sdio_set_block_size(dev->pfunction, length);
+ dev->pfunction->max_blksize = 256;
+
+ rsi_dbg(INFO_ZONE,
+ "%s: Operational blk length is %d\n", __func__, length);
+ return status;
+}
+
+/**
+ * rsi_setupcard() - This function queries and sets the card's features.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+static int rsi_setupcard(struct rsi_hw *adapter)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ int status = 0;
+
+ rsi_setclock(adapter, 50000);
+
+ dev->tx_blk_size = 256;
+ adapter->tx_blk_size = dev->tx_blk_size;
+ status = rsi_setblocklength(adapter, dev->tx_blk_size);
+ if (status)
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set block length\n", __func__);
+ return status;
+}
+
+/**
+ * rsi_sdio_read_register() - This function reads one byte of information
+ *      from a register.
+ * @adapter: Pointer to the adapter structure.
+ * @addr: Address of the register.
+ * @data: Pointer to the data that stores the data read.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_sdio_read_register(struct rsi_hw *adapter,
+   u32 addr,
+   u8 *data)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ u8 fun_num = 0;
+ int status;
+
+ sdio_claim_host(dev->pfunction);
+
+ if (fun_num == 0)
+ *data = sdio_f0_readb(dev->pfunction, addr, &status);
+ else
+ *data = sdio_readb(dev->pfunction, addr, &status);
+
+ sdio_release_host(dev->pfunction);
+
+ return status;
+}
+
+/**
+ * rsi_sdio_write_register() - This function writes one byte of information
+ *       into a register.
+ * @adapter: Pointer to the adapter structure.
+ * @function: Function Number.
+ * @addr: Address of the register.
+ * @data: Pointer to the data tha has to be written.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_sdio_write_register(struct rsi_hw *adapter,
+    u8 function,
+    u32 addr,
+    u8 *data)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ int status = 0;
+
+ sdio_claim_host(dev->pfunction);
+
+ if (function == 0)
+ sdio_f0_writeb(dev->pfunction, *data, addr, &status);
+ else
+ sdio_writeb(dev->pfunction, *data, addr, &status);
+
+ sdio_release_host(dev->pfunction);
+
+ return status;
+}
+
+/**
+ * rsi_sdio_ack_intr() - This function acks the interrupt received.
+ * @adapter: Pointer to the adapter structure.
+ * @int_bit: Interrupt bit to write into register.
+ *
+ * Return: None.
+ */
+void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)
+{
+ int status;
+
+ status = rsi_sdio_write_register(adapter,
+ 1,
+ (SDIO_FUN1_INTR_CLR_REG |
+  SD_REQUEST_MASTER),
+ &int_bit);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: unable to send ack\n", __func__);
+}
+
+/**
+ * rsi_sdio_read_register_multiple() - This function read multiple bytes of
+ *       information from the SD card.
+ * @adapter: Pointer to the adapter structure.
+ * @addr: Address of the register.
+ * @count: Number of multiple bytes to be read.
+ * @data: Pointer to the read data.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
+    u32 addr,
+    u8 *data,
+    u16 count)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ u32 status = 0;
+
+ sdio_claim_host(dev->pfunction);
+
+ status =  sdio_readsb(dev->pfunction, data, addr, count);
+
+ sdio_release_host(dev->pfunction);
+
+ if (status != 0)
+ rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 read failed\n", __func__);
+ return status;
+}
+
+/**
+ * rsi_sdio_write_register_multiple() - This function writes multiple bytes of
+ * information to the SD card.
+ * @adapter: Pointer to the adapter structure.
+ * @addr: Address of the register.
+ * @data: Pointer to the data that has to be written.
+ * @count: Number of multiple bytes to be written.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
+     u32 addr,
+     u8 *data,
+     u16 count)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ int status;
+
+ if (dev->write_fail > 1) {
+ rsi_dbg(ERR_ZONE, "%s: Stopping card writes\n", __func__);
+ return 0;
+ } else if (dev->write_fail == 1) {
+ /**
+ * Assuming it is a CRC failure, we want to allow another
+ *  card write
+ */
+ rsi_dbg(ERR_ZONE, "%s: Continue card writes\n", __func__);
+ dev->write_fail++;
+ }
+
+ sdio_claim_host(dev->pfunction);
+
+ status = sdio_writesb(dev->pfunction, addr, data, count);
+
+ sdio_release_host(dev->pfunction);
+
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 write failed %d\n",
+ __func__, status);
+ dev->write_fail = 2;
+ } else {
+ memcpy(dev->prev_desc, data, FRAME_DESC_SZ);
+ }
+ return status;
+}
+
+int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
+    u32 base_address,
+    u32 instructions_sz,
+    u16 block_size,
+    u8 *ta_firmware)
+{
+ u32 num_blocks;
+ u16 msb_address;
+ u32 offset, ii;
+ u8 temp_buf[block_size];
+ u16 lsb_address;
+
+ num_blocks = instructions_sz / block_size;
+ msb_address = base_address >> 16;
+
+ rsi_dbg(INFO_ZONE, "ins_size: %d\n", instructions_sz);
+ rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+
+ /* Loading DM ms word in the sdio slave */
+ if (rsi_sdio_master_access_msword(adapter, msb_address)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return -1;
+ }
+
+ for (offset = 0, ii = 0; ii < num_blocks; ii++, offset += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + offset, block_size);
+ lsb_address = (u16)base_address;
+ if (rsi_sdio_write_register_multiple(adapter,
+ lsb_address | SD_REQUEST_MASTER,
+ temp_buf, block_size)) {
+ rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
+ return -1;
+ }
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, ii);
+ base_address += block_size;
+
+ if ((base_address >> 16) != msb_address) {
+ msb_address += 1;
+
+ /* Loading DM ms word in the sdio slave */
+ if (rsi_sdio_master_access_msword(adapter,
+  msb_address)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word reg\n",
+ __func__);
+ return -1;
+ }
+ }
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf,
+       ta_firmware + offset,
+       instructions_sz % block_size);
+ lsb_address = (u16)base_address;
+ if (rsi_sdio_write_register_multiple(adapter,
+ lsb_address | SD_REQUEST_MASTER,
+ temp_buf,
+ instructions_sz % block_size)) {
+ return -1;
+ }
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ offset | SD_REQUEST_MASTER);
+ }
+ return 0;
+}
+
+#define align_address(a) ((unsigned long)(a) & ~0x7)
+
+int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
+     u32 *read_buf, u16 size)
+{
+ u32 *data = NULL;
+ u16 ms_addr = 0;
+ u32 align[2] = {};
+ u32 addr_on_bus;
+
+ data = (u32 *)align_address(&align[1]);
+
+ ms_addr = (addr >> 16);
+ if (rsi_sdio_master_access_msword(adapter, ms_addr)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return -1;
+ }
+ addr = addr & 0xFFFF;
+
+ addr_on_bus = (addr & 0xFF000000);
+ if ((addr_on_bus == (FLASH_SIZE_ADDR & 0xFF000000)) ||
+    (addr_on_bus == 0x0)) {
+ addr_on_bus = (addr & ~(0x3));
+ } else
+ addr_on_bus = addr;
+
+ /* Bringing TA out of reset */
+ if (rsi_sdio_read_register_multiple(adapter,
+    (addr_on_bus | SD_REQUEST_MASTER),
+    (u8 *)data, 4)) {
+ rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
+ return -1;
+ }
+ if (size == 2) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else
+ *read_buf  = (*data >> 16);
+ *read_buf = (*read_buf & 0xFFFF);
+ } else if (size == 1) {
+ if ((addr & 0x3) == 0)
+ *read_buf = *data;
+ else if ((addr & 0x3) == 1)
+ *read_buf = (*data >> 8);
+ else if ((addr & 0x3) == 2)
+ *read_buf = (*data >> 16);
+ else
+ *read_buf = (*data >> 24);
+ *read_buf = (*read_buf & 0xFF);
+ } else { /*size is 4 */
+ *read_buf = *data;
+ }
+
+ return 0;
+}
+
+int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
+      unsigned long addr,
+      unsigned long data,
+      u16 size)
+{
+ unsigned long data1[2];
+ unsigned long *data_alligned;
+
+ data_alligned = (unsigned long *)align_address(&data1[1]);
+
+ if (size == 2) {
+ *data_alligned = ((data << 16) | (data & 0xFFFF));
+ } else if (size == 1) {
+ u32 temp_data;
+
+ temp_data = (data & 0xFF);
+ *data_alligned = ((temp_data << 24) |
+  (temp_data << 16) |
+  (temp_data << 8) |
+  (temp_data));
+ } else {
+ *data_alligned = data;
+ }
+ size = 4;
+
+ if (rsi_sdio_master_access_msword(adapter, (addr >> 16))) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to set ms word to common reg\n",
+ __func__);
+ return -1;
+ }
+ addr = addr & 0xFFFF;
+
+ /* Bringing TA out of reset */
+ if (rsi_sdio_write_register_multiple(adapter,
+     (addr | SD_REQUEST_MASTER),
+     (u8 *)data_alligned, size)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Unable to do AHB reg write\n", __func__);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * rsi_sdio_host_intf_write_pkt() - This function writes the packet to device.
+ * @adapter: Pointer to the adapter structure.
+ * @pkt: Pointer to the data to be written on to the device.
+ * @len: length of the data to be written on to the device.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter,
+ u8 *pkt,
+ u32 len)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ u32 block_size = dev->tx_blk_size;
+ u32 num_blocks, address, length;
+ u32 queueno;
+ int status;
+
+ queueno = ((pkt[1] >> 4) & 0xf);
+ if (queueno == RSI_BT_DATA_Q)
+ queueno = RSI_BT_Q;
+
+ num_blocks = len / block_size;
+
+ if (len % block_size)
+ num_blocks++;
+
+ address = (num_blocks * block_size | (queueno << 12));
+ length  = num_blocks * block_size;
+
+ status = rsi_sdio_write_register_multiple(adapter,
+  address,
+  pkt,
+  length);
+ if (status < 0)
+ rsi_dbg(ERR_ZONE, "%s: Unable to write onto the card: %d\n",
+ __func__, status);
+ rsi_dbg(DATA_TX_ZONE, "%s: Successfully written onto card\n", __func__);
+ return status;
+}
+
+/**
+ * rsi_sdio_host_intf_read_pkt() - This function reads the packet
+   from the device.
+ * @adapter: Pointer to the adapter data structure.
+ * @pkt: Pointer to the packet data to be read from the the device.
+ * @length: Length of the data to be read from the device.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,
+ u8 *pkt,
+ u32 length)
+{
+ int status = -EINVAL;
+
+ if (!length) {
+ rsi_dbg(ERR_ZONE, "%s: Pkt size is zero\n", __func__);
+ return status;
+ }
+
+ status = rsi_sdio_read_register_multiple(adapter,
+ length,
+ (u8 *)pkt,
+ length);
+
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
+ status);
+ return status;
+}
+
+/**
+ * rsi_init_sdio_interface() - This function does init specific to SDIO.
+ *
+ * @adapter: Pointer to the adapter data structure.
+ * @pkt: Pointer to the packet data to be read from the the device.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+
+static int rsi_init_sdio_interface(struct rsi_hw *adapter,
+   struct sdio_func *pfunction)
+{
+ struct rsi_91x_sdiodev *rsi_91x_dev;
+ int status = -ENOMEM;
+
+ rsi_91x_dev = kzalloc(sizeof(*rsi_91x_dev), GFP_KERNEL);
+ if (!rsi_91x_dev)
+ return status;
+
+ adapter->rsi_dev = rsi_91x_dev;
+
+ sdio_claim_host(pfunction);
+
+ pfunction->enable_timeout = 100;
+ status = sdio_enable_func(pfunction);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to enable interface\n", __func__);
+ sdio_release_host(pfunction);
+ return status;
+ }
+
+ rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
+
+ rsi_91x_dev->pfunction = pfunction;
+ adapter->device = &pfunction->dev;
+
+ sdio_set_drvdata(pfunction, adapter);
+
+ status = rsi_setupcard(adapter);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to setup card\n", __func__);
+ goto fail;
+ }
+
+ rsi_dbg(INIT_ZONE, "%s: Setup card successfully\n", __func__);
+
+ status = rsi_init_sdio_slave_regs(adapter);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to init slave regs\n", __func__);
+ goto fail;
+ }
+ sdio_release_host(pfunction);
+
+ adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
+ adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
+
+#ifdef CONFIG_RSI_DEBUGFS
+ adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES;
+#endif
+ return status;
+fail:
+ sdio_disable_func(pfunction);
+ sdio_release_host(pfunction);
+ return status;
+}
+
+static struct rsi_host_intf_ops sdio_host_intf_ops = {
+ .write_pkt = rsi_sdio_host_intf_write_pkt,
+ .read_pkt = rsi_sdio_host_intf_read_pkt,
+ .master_access_msword = rsi_sdio_master_access_msword,
+ .master_reg_read = rsi_sdio_master_reg_read,
+ .master_reg_write = rsi_sdio_master_reg_write,
+ .read_reg_multiple = rsi_sdio_read_register_multiple,
+ .write_reg_multiple = rsi_sdio_write_register_multiple,
+ .load_data_master_write = rsi_sdio_load_data_master_write,
+};
+
+/**
+ * rsi_probe() - This function is called by kernel when the driver provided
+ * Vendor and device IDs are matched. All the initialization
+ * work is done here.
+ * @pfunction: Pointer to the sdio_func structure.
+ * @id: Pointer to sdio_device_id structure.
+ *
+ * Return: 0 on success, 1 on failure.
+ */
+static int rsi_probe(struct sdio_func *pfunction,
+     const struct sdio_device_id *id)
+{
+ struct rsi_hw *adapter;
+
+ rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
+
+ adapter = rsi_91x_init();
+ if (!adapter) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
+ __func__);
+ return 1;
+ }
+ adapter->rsi_host_intf = RSI_HOST_INTF_SDIO;
+ adapter->host_intf_ops = &sdio_host_intf_ops;
+
+ if (rsi_init_sdio_interface(adapter, pfunction)) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
+ __func__);
+ goto fail;
+ }
+
+ sdio_claim_host(pfunction);
+ if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
+ sdio_release_host(pfunction);
+ goto fail;
+ }
+
+ sdio_release_host(pfunction);
+ rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
+
+ if (rsi_hal_device_init(adapter)) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
+ sdio_claim_host(pfunction);
+ sdio_disable_func(pfunction);
+ sdio_release_host(pfunction);
+ goto fail;
+ }
+ rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
+
+ if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ return -1;
+ }
+ rsi_dbg(INIT_ZONE, "%s: Setting ms word to 0x41050000\n", __func__);
+
+
+ return 0;
+
+fail:
+ rsi_91x_deinit(adapter);
+ rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
+ return 1;
+}
+
+/**
+ * rsi_disconnect() - This function performs the reverse of the probe function.
+ * @pfunction: Pointer to the sdio_func structure.
+ *
+ * Return: void.
+ */
+static void rsi_disconnect(struct sdio_func *pfunction)
+{
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+ struct rsi_91x_sdiodev *dev;
+
+ if (!adapter)
+ return;
+
+ dev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+
+ rsi_mac80211_detach(adapter);
+ mdelay(10);
+#ifdef CONFIG_RSI_HCI
+        rsi_hci_detach(adapter->priv);
+#endif
+        mdelay(10);
+
+ sdio_claim_host(pfunction);
+ sdio_release_irq(pfunction);
+ sdio_release_host(pfunction);
+ mdelay(10);
+
+ /* Reset Chip */
+ rsi_reset_chip(adapter);
+
+ /* Resetting to take care of the case, where-in driver is re-loaded */
+ sdio_claim_host(pfunction);
+ rsi_reset_card(pfunction);
+ sdio_disable_func(pfunction);
+ sdio_release_host(pfunction);
+ dev->write_fail = 2;
+ rsi_91x_deinit(adapter);
+ rsi_dbg(ERR_ZONE, "##### RSI SDIO device disconnected #####\n");
+}
+
+#ifdef CONFIG_PM
+static int rsi_suspend(struct device *dev)
+{
+ /* Not yet implemented */
+ return -ENOSYS;
+}
+
+static int rsi_resume(struct device *dev)
+{
+ /* Not yet implemented */
+ return -ENOSYS;
+}
+
+static const struct dev_pm_ops rsi_pm_ops = {
+ .suspend = rsi_suspend,
+ .resume = rsi_resume,
+};
+#endif
+
+static const struct sdio_device_id rsi_dev_table[] =  {
+ { SDIO_DEVICE(0x303, 0x100) },
+ { SDIO_DEVICE(0x041B, 0x0301) },
+ { SDIO_DEVICE(0x041B, 0x0201) },
+ { SDIO_DEVICE(0x041B, 0x9330) },
+ { /* Blank */},
+};
+
+static struct sdio_driver rsi_driver = {
+ .name       = "RSI-SDIO WLAN",
+ .probe      = rsi_probe,
+ .remove     = rsi_disconnect,
+ .id_table   = rsi_dev_table,
+#ifdef CONFIG_PM
+ .drv = {
+ .pm = &rsi_pm_ops,
+ }
+#endif
+};
+
+/**
+ * rsi_module_init() - This function registers the sdio module.
+ * @void: Void.
+ *
+ * Return: 0 on success.
+ */
+static int rsi_module_init(void)
+{
+ int ret;
+
+ ret = sdio_register_driver(&rsi_driver);
+ rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
+ return ret;
+}
+
+/**
+ * rsi_module_exit() - This function unregisters the sdio module.
+ * @void: Void.
+ *
+ * Return: None.
+ */
+static void rsi_module_exit(void)
+{
+ sdio_unregister_driver(&rsi_driver);
+ rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);
+}
+
+module_init(rsi_module_init);
+module_exit(rsi_module_exit);
+
+MODULE_AUTHOR("Redpine Signals Inc");
+MODULE_DESCRIPTION("Common SDIO layer for RSI drivers");
+MODULE_SUPPORTED_DEVICE("RSI-91x");
+MODULE_DEVICE_TABLE(sdio, rsi_dev_table);
+MODULE_FIRMWARE(FIRMWARE_RSI9113);
+MODULE_VERSION("0.1");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/ubuntu/rsi/rsi_91x_sdio_ops.c b/ubuntu/rsi/rsi_91x_sdio_ops.c
new file mode 100644
index 0000000..cabb8ec
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_sdio_ops.c
@@ -0,0 +1,423 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include "rsi_sdio.h"
+#include "rsi_common.h"
+#include "rsi_hal.h"
+
+/**
+ * rsi_sdio_master_access_msword() - This function sets the AHB master access
+ *     MS word in the SDIO slave registers.
+ * @adapter: Pointer to the adapter structure.
+ * @ms_word: ms word need to be initialized.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
+  u16 ms_word)
+{
+ u8 byte;
+ u8 function = 0;
+ int status = 0;
+
+ byte = (u8)(ms_word & 0x00FF);
+
+ rsi_dbg(INFO_ZONE,
+ "%s: MASTER_ACCESS_MSBYTE:0x%x\n", __func__, byte);
+
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_MASTER_ACCESS_MSBYTE,
+ &byte);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: fail to access MASTER_ACCESS_MSBYTE\n",
+ __func__);
+ return -1;
+ }
+
+ byte = (u8)(ms_word >> 8);
+
+ rsi_dbg(INFO_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte);
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_MASTER_ACCESS_LSBYTE,
+ &byte);
+ return status;
+}
+
+/**
+ * rsi_process_pkt() - This Function reads rx_blocks register and figures out
+ *       the size of the rx pkt.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: 0 on success, -1 on failure.
+ */
+static int rsi_process_pkt(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ u8 num_blks = 0;
+ u32 rcv_pkt_len = 0;
+ int status = 0;
+ u8 value = 0;
+ u8 protocol = 0, unaggr_pkt = 0;
+
+#define COEX_PKT 0
+#define WLAN_PKT 3
+#define ZIGB_PKT 1
+#define BT_PKT   2
+ num_blks = ((adapter->interrupt_status & 1) |
+ ((adapter->interrupt_status >> 4) << 1));
+
+ if (!num_blks) {
+ status = rsi_sdio_read_register(adapter,
+ SDIO_RX_NUM_BLOCKS_REG,
+ &value);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to read pkt length from the card:\n",
+ __func__);
+ return status;
+ }
+
+ protocol = value >> 5;
+ num_blks = value & 0x1f;
+ } else {
+ protocol = WLAN_PKT;
+ }
+
+ if (dev->write_fail == 2) {
+ rsi_sdio_ack_intr(common->priv, (1 << MSDU_PKT_PENDING));
+ }
+ if (unlikely(!num_blks)) {
+ dev->write_fail = 2;
+ return -1;
+ }
+
+ if (protocol == BT_PKT || protocol == ZIGB_PKT)  //unaggr_pkt FIXME
+ unaggr_pkt = 1;
+
+ rcv_pkt_len = (num_blks * 256);
+
+ common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL);
+ if (!common->rx_data_pkt) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ status = rsi_sdio_host_intf_read_pkt(adapter,
+     common->rx_data_pkt,
+     rcv_pkt_len);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
+ __func__);
+ goto fail;
+ }
+
+ status = rsi_read_pkt(common, common->rx_data_pkt, rcv_pkt_len);
+
+fail:
+ kfree(common->rx_data_pkt);
+ return status;
+}
+
+/**
+ * rsi_init_sdio_slave_regs() - This function does the actual initialization
+ * of SDBUS slave registers.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ u8 function = 0;
+ u8 byte;
+ int status = 0;
+
+ if (dev->next_read_delay) {
+ byte = dev->next_read_delay;
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_NXT_RD_DELAY2,
+ &byte);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write SDIO_NXT_RD_DELAY2\n",
+ __func__);
+ return -1;
+ }
+ }
+
+ if (dev->sdio_high_speed_enable) {
+ rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__);
+ byte = 0x3;
+
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_REG_HIGH_SPEED,
+ &byte);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to enable SDIO high speed\n",
+ __func__);
+ return -1;
+ }
+ }
+
+ /* This tells SDIO FIFO when to start read to host */
+ rsi_dbg(INIT_ZONE, "%s: Initialzing SDIO read start level\n", __func__);
+ byte = 0x24;
+
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_READ_START_LVL,
+ &byte);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write SDIO_READ_START_LVL\n", __func__);
+ return -1;
+ }
+
+ rsi_dbg(INIT_ZONE, "%s: Initialzing FIFO ctrl registers\n", __func__);
+ byte = (128 - 32);
+
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_READ_FIFO_CTL,
+ &byte);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write SDIO_READ_FIFO_CTL\n", __func__);
+ return -1;
+ }
+
+ byte = 32;
+ status = rsi_sdio_write_register(adapter,
+ function,
+ SDIO_WRITE_FIFO_CTL,
+ &byte);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to write SDIO_WRITE_FIFO_CTL\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * rsi_interrupt_handler() - This function read and process SDIO interrupts.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+void rsi_interrupt_handler(struct rsi_hw *adapter)
+{
+ struct rsi_common *common = adapter->priv;
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ int status;
+ enum sdio_interrupt_type isr_type;
+ u8 isr_status = 0;
+ u8 fw_status = 0;
+
+ dev->rx_info.sdio_int_counter++;
+
+ do {
+ mutex_lock(&common->rx_lock);
+ status = rsi_sdio_read_register(common->priv,
+ RSI_FN1_INT_REGISTER,
+ &isr_status);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to Read Intr Status Register\n",
+ __func__);
+ mutex_unlock(&common->rx_lock);
+ return;
+ }
+
+ adapter->interrupt_status = isr_status;
+ isr_status &= 0xE;
+
+ if (isr_status == 0) {
+ rsi_set_event(&common->tx_thread.event);
+ dev->rx_info.sdio_intr_status_zero++;
+ mutex_unlock(&common->rx_lock);
+ return;
+ }
+
+// adapter->interrupt_status = isr_status;
+// isr_status &= 0xE;
+
+ rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",
+ __func__, isr_status, (1 << MSDU_PKT_PENDING),
+ (1 << FW_ASSERT_IND));
+
+ do {
+ RSI_GET_SDIO_INTERRUPT_TYPE(isr_status, isr_type);
+
+ switch (isr_type) {
+ case BUFFER_AVAILABLE:
+ dev->rx_info.watch_bufferfull_count = 0;
+ dev->rx_info.buffer_full = false;
+ dev->rx_info.semi_buffer_full = false;
+ dev->rx_info.mgmt_buffer_full = false;
+ rsi_sdio_ack_intr(common->priv,
+  (1 << PKT_BUFF_AVAILABLE));
+ rsi_set_event(&common->tx_thread.event);
+
+ rsi_dbg(ISR_ZONE,
+ "%s: ==> BUFFER_AVAILABLE <==\n",
+ __func__);
+ dev->rx_info.buf_available_counter++;
+ break;
+
+ case FIRMWARE_ASSERT_IND:
+ rsi_dbg(ERR_ZONE,
+ "%s: ==> FIRMWARE Assert <==\n",
+ __func__);
+ status = rsi_sdio_read_register(common->priv,
+ SDIO_FW_STATUS_REG,
+ &fw_status);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to read f/w reg\n",
+ __func__);
+ } else {
+ rsi_dbg(ERR_ZONE,
+ "%s: Firmware Status is 0x%x\n",
+ __func__, fw_status);
+ rsi_sdio_ack_intr(common->priv,
+  (1 << FW_ASSERT_IND));
+ }
+
+ common->fsm_state = FSM_CARD_NOT_READY;
+ break;
+
+ case MSDU_PACKET_PENDING:
+ rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
+ dev->rx_info.total_sdio_msdu_pending_intr++;
+
+ status = rsi_process_pkt(common);
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to read pkt\n",
+ __func__);
+ mutex_unlock(&common->rx_lock);
+ return;
+ }
+ break;
+ default:
+ rsi_sdio_ack_intr(common->priv, isr_status);
+ dev->rx_info.total_sdio_unknown_intr++;
+ isr_status = 0;
+ rsi_dbg(ISR_ZONE,
+ "Unknown Interrupt %x\n",
+ isr_status);
+ break;
+ }
+ isr_status ^= BIT(isr_type - 1);
+ } while (isr_status);
+ mutex_unlock(&common->rx_lock);
+ } while (1);
+}
+
+/**
+ * rsi_sdio_read_buffer_status_register() - This function is used to the read
+ *    buffer status register and set
+ *    relevant fields in
+ *    rsi_91x_sdiodev struct.
+ * @adapter: Pointer to the driver hw structure.
+ * @q_num: The Q number whose status is to be found.
+ *
+ * Return: status: -1 on failure or else queue full/stop is indicated.
+ */
+int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
+{
+ struct rsi_common *common = adapter->priv;
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ u8 buf_status = 0;
+ int status = 0;
+
+ status = rsi_sdio_read_register(common->priv,
+ RSI_DEVICE_BUFFER_STATUS_REGISTER,
+ &buf_status);
+
+ if (status) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed to read status register\n", __func__);
+ return -1;
+ }
+
+ if (buf_status & (BIT(PKT_MGMT_BUFF_FULL))) {
+ if (!dev->rx_info.mgmt_buffer_full)
+ dev->rx_info.mgmt_buf_full_counter++;
+ dev->rx_info.mgmt_buffer_full = true;
+ } else {
+ dev->rx_info.mgmt_buffer_full = false;
+ }
+
+ if (buf_status & (BIT(PKT_BUFF_FULL))) {
+ if (!dev->rx_info.buffer_full)
+ dev->rx_info.buf_full_counter++;
+ dev->rx_info.buffer_full = true;
+ } else {
+ dev->rx_info.buffer_full = false;
+ }
+
+ if (buf_status & (BIT(PKT_BUFF_SEMI_FULL))) {
+ if (!dev->rx_info.semi_buffer_full)
+ dev->rx_info.buf_semi_full_counter++;
+ dev->rx_info.semi_buffer_full = true;
+ } else {
+ dev->rx_info.semi_buffer_full = false;
+ }
+
+ if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))
+ return QUEUE_FULL;
+
+ if (dev->rx_info.buffer_full)
+ return QUEUE_FULL;
+
+ return QUEUE_NOT_FULL;
+}
+
+/**
+ * rsi_sdio_determine_event_timeout() - This Function determines the event
+ * timeout duration.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: timeout duration is returned.
+ */
+int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+
+ /* Once buffer full is seen, event timeout to occur every 2 msecs */
+ if (dev->rx_info.buffer_full)
+ return 2;
+
+ return EVENT_WAIT_FOREVER;
+}
diff --git a/ubuntu/rsi/rsi_91x_usb.c b/ubuntu/rsi/rsi_91x_usb.c
new file mode 100644
index 0000000..5aac3df
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_usb.c
@@ -0,0 +1,920 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Developers:
+ * Prameela Rani Garnepudi 2016 <[hidden email]>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "rsi_usb.h"
+#include "rsi_hal.h"
+
+static struct rsi_host_intf_ops usb_host_intf_ops = {
+ .write_pkt = rsi_usb_host_intf_write_pkt,
+ .master_reg_read = rsi_usb_master_reg_read,
+ .master_reg_write = rsi_usb_master_reg_write,
+ .read_reg_multiple = rsi_usb_read_register_multiple,
+ .write_reg_multiple = rsi_usb_write_register_multiple,
+ .load_data_master_write = rsi_usb_load_data_master_write,
+};
+
+/**
+ * rsi_usb_card_write() - This function writes data to the USB Card.
+ * @adapter: Pointer to the adapter structure.
+ * @buf: Pointer to the buffer from where the data has to be taken.
+ * @len: Length to be written.
+ * @endpoint: Type of endpoint.
+ *
+ * Return: status: 0 on success, a negative error code on failure.
+ */
+static int rsi_usb_card_write(struct rsi_hw *adapter,
+      u8 *buf,
+      u16 len,
+      u32 endpoint)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ int status = 0;
+ u8 *seg = dev->tx_buffer;
+ int transfer = 0;
+ int ep = dev->bulkout_endpoint_addr[endpoint - 1];
+
+ memset(seg, 0, len + 128);
+ memcpy(seg + 128, buf, len);
+ len += 128;
+ transfer = len;
+
+ status = usb_bulk_msg(dev->usbdev,
+      usb_sndbulkpipe(dev->usbdev, ep),
+      (void *)seg,
+      (int)len,
+      &transfer,
+      HZ * 5);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Card write failed with error code :%d\n", status);
+ dev->write_fail = 1;
+ goto fail;
+ }
+ rsi_dbg(MGMT_TX_ZONE, "%s: Sent Message successfully\n", __func__);
+
+fail:
+ return status;
+}
+
+/**
+ * rsi_write_multiple() - This function writes multiple bytes of information
+ *  to the USB card.
+ * @adapter: Pointer to the adapter structure.
+ * @addr: Address of the register.
+ * @data: Pointer to the data that has to be written.
+ * @count: Number of multiple bytes to be written.
+ *
+ * Return: 0 on success, a negative error code on failure.
+ */
+static int rsi_write_multiple(struct rsi_hw *adapter,
+      u32 addr,
+      u8 *data,
+      u32 count)
+{
+ struct rsi_91x_usbdev *dev =
+ (struct rsi_91x_usbdev *)adapter->rsi_dev;
+
+ if (!adapter || addr == 0) {
+ rsi_dbg(INFO_ZONE,
+ "%s: Unable to write to card\n", __func__);
+ return -1;
+ }
+
+ if (dev->write_fail)
+ return -1;
+
+ return rsi_usb_card_write(adapter, data, count, addr);
+}
+
+#define RSI_USB_REQ_OUT (USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE)
+#define RSI_USB_REQ_IN (USB_TYPE_VENDOR | USB_DIR_IN | USB_RECIP_DEVICE)
+
+/* rsi_usb_reg_read() - This function reads data from given register address.
+ * @usbdev: Pointer to the usb_device structure.
+ * @reg: Address of the register to be read.
+ * @value: Value to be read.
+ * @len: length of data to be read.
+ *
+ * Return: status: 0 on success, a negative error code on failure.
+ */
+static int rsi_usb_reg_read(struct usb_device *usbdev,
+    u32 reg,
+    u32 *value,
+    u16 len)
+{
+ u8 buf[4];
+ int status = 0;
+ u16 reg_value;
+ u16 index;
+
+ len = 2;
+ reg_value = cpu_to_le16(((u16 *)&reg)[1] & 0xffff);
+ index = cpu_to_le16(((u16 *)&reg)[0] & 0xffff);
+ status = usb_control_msg(usbdev,
+ usb_rcvctrlpipe(usbdev, 0),
+ USB_VENDOR_REGISTER_READ,
+ RSI_USB_REQ_IN,
+ reg_value,
+ index,
+ (void *)buf,
+ len,
+ USB_CTRL_GET_TIMEOUT);
+
+ *value = (buf[0] | (buf[1] << 8));
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Reg read failed with error code :%d\n",
+ __func__, status);
+ }
+
+ return status;
+}
+
+/**
+ * rsi_usb_reg_write() - This function writes the given data into the given
+ * register address.
+ * @usbdev: Pointer to the usb_device structure.
+ * @reg: Address of the register.
+ * @value: Value to write.
+ * @len: Length of data to be written.
+ *
+ * Return: status: 0 on success, a negative error code on failure.
+ */
+static int rsi_usb_reg_write(struct usb_device *usbdev,
+     unsigned long reg,
+     unsigned long value,
+     u16 len)
+{
+ u8 usb_reg_buf[4];
+ int status = 0;
+ u16 reg_value, index;
+
+ usb_reg_buf[0] = (value & 0x00ff);
+ usb_reg_buf[1] = (value & 0xff00) >> 8;
+ usb_reg_buf[2] = 0x0;
+ usb_reg_buf[3] = 0x0;
+
+ reg_value = ((u16 *)&reg)[1] & 0xffff;
+ index = ((u16 *)&reg)[0] & 0xffff;
+ status = usb_control_msg(usbdev,
+ usb_sndctrlpipe(usbdev, 0),
+ USB_VENDOR_REGISTER_WRITE,
+ RSI_USB_REQ_OUT,
+ reg_value,
+ index,
+ (void *)usb_reg_buf,
+ len,
+ USB_CTRL_SET_TIMEOUT);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Reg write failed with error code :%d\n",
+ __func__, status);
+ }
+
+ return status;
+}
+
+/**
+ * rsi_usb_read_register_multiple() - This function reads multiple
+ * bytes of data from the address.
+ * @adapter: Pointer to the adapter structure.
+ * @addr: Address of the register.
+ * @data: Read data.
+ * @len: Number of bytes to read.
+ *
+ * Return: status: 0 on success, a negative error code on failure.
+ */
+int rsi_usb_read_register_multiple(struct rsi_hw *adapter,
+   u32 addr,
+   u8 *data,
+   u16 count)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ u8 *buf;
+ u16 transfer;
+ int status = 0;
+ u16 reg_val, index;
+
+ if (addr == 0)
+ return -EINVAL;
+
+ buf = kzalloc(4096, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ reg_val = ((u16 *)&addr)[1] & 0xffff;
+ index = ((u16 *)&addr)[0] & 0xffff;
+ while (count) {
+ transfer = min_t(u16, count, 4096);
+ status = usb_control_msg(dev->usbdev,
+ usb_rcvctrlpipe(dev->usbdev, 0),
+ USB_VENDOR_REGISTER_READ,
+ RSI_USB_REQ_IN,
+ reg_val,
+ index,
+ (void *)buf,
+ transfer,
+ USB_CTRL_GET_TIMEOUT);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Reg read failed with error code :%d\n",
+ status);
+ kfree(buf);
+ return status;
+
+ } else {
+ memcpy(data, buf, transfer);
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
+ }
+ }
+ kfree(buf);
+ return status;
+}
+
+/**
+ * rsi_usb_write_register_multiple() - This function writes multiple bytes of
+ *       information to the given address.
+ * @adapter: Pointer to the adapter structure.
+ * @addr: Address of the register.
+ * @data: Pointer to the data that has to be written.
+ * @count: Number of multiple bytes to be written on to the registers.
+ *
+ * Return: status: 0 on success, a negative error code on failure.
+ */
+int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
+    u32 addr,
+    u8 *data,
+    u16 count)
+{
+ struct rsi_91x_usbdev *dev =
+ (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ u8 *buf;
+ u16 transfer;
+ int status = 0;
+ u16 reg_val, index;
+
+ buf = kzalloc(4096, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ reg_val = ((u16 *)&addr)[1] & 0xffff;
+ index = ((u16 *)&addr)[0] & 0xffff;
+ while (count) {
+ transfer = min_t(u16, count, 4096);
+ memcpy(buf, data, transfer);
+ status = usb_control_msg(dev->usbdev,
+ usb_sndctrlpipe(dev->usbdev, 0),
+ USB_VENDOR_REGISTER_WRITE,
+ RSI_USB_REQ_OUT,
+ reg_val,
+ index,
+ (void *)buf,
+ transfer,
+ USB_CTRL_SET_TIMEOUT);
+ if (status < 0) {
+ rsi_dbg(ERR_ZONE,
+ "Reg write failed with error code :%d\n",
+ status);
+ kfree(buf);
+ return status;
+ }
+ count -= transfer;
+ data += transfer;
+ addr += transfer;
+ }
+
+ kfree(buf);
+ return status;
+}
+
+/**
+ * rsi_rx_done_handler() - This function is called when a packet is received
+ *   from USB stack. This is callback to receive done.
+ * @urb: Received URB.
+ *
+ * Return: None.
+ */
+static void rsi_rx_done_handler(struct urb *urb)
+{
+ struct rx_usb_ctrl_block *rx_cb = urb->context;
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)rx_cb->data;
+
+ if (urb->status)
+ return;
+
+ if (urb->actual_length <= 0) {
+ rsi_dbg(INFO_ZONE, "%s: Zero length packet\n", __func__);
+ return;
+ }
+ rx_cb->pend = 1;
+
+ rsi_set_event(&dev->rx_thread.event);
+}
+
+/**
+ * rsi_rx_urb_submit() - This function submits the given URB to the USB stack.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: 0 on success, a negative error code on failure.
+ */
+static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ struct rx_usb_ctrl_block *rx_cb = &dev->rx_cb[ep_num - 1];
+ struct urb *urb = rx_cb->rx_urb;
+ int status;
+
+ usb_fill_bulk_urb(urb,
+ dev->usbdev,
+ usb_rcvbulkpipe(dev->usbdev,
+ dev->bulkin_endpoint_addr[ep_num - 1]),
+ urb->transfer_buffer,
+ 3000,
+ rsi_rx_done_handler,
+ rx_cb);
+
+ status = usb_submit_urb(urb, GFP_KERNEL);
+ if (status)
+ rsi_dbg(ERR_ZONE, "%s: Failed in urb submission\n", __func__);
+
+ return status;
+}
+
+/**
+ *rsi_usb_host_intf_write_pkt() - This function writes the packet to the
+ *   USB card.
+ * @adapter: Pointer to the adapter structure.
+ * @pkt: Pointer to the data to be written on to the card.
+ * @len: Length of the data to be written on to the card.
+ *
+ * Return: 0 on success, a negative error code on failure.
+ */
+int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
+ u8 *pkt,
+ u32 len)
+{
+ u32 queueno = ((pkt[1] >> 4) & 0x7);
+ u8 endpoint;
+
+ rsi_dbg(DATA_TX_ZONE, "%s: queueno=%d\n", __func__, queueno);
+ endpoint = ((queueno == RSI_WIFI_MGMT_Q || queueno == RSI_COEX_Q ||
+     queueno == RSI_WIFI_DATA_Q) ?
+    MGMT_EP : DATA_EP);
+
+ return rsi_write_multiple(adapter,
+  endpoint,
+  pkt,
+  len);
+}
+
+int rsi_usb_master_reg_read(struct rsi_hw *adapter,
+    u32 reg,
+    u32 *value,
+    u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_read(usbdev, reg, value, len);
+}
+
+int rsi_usb_master_reg_write(struct rsi_hw *adapter,
+     unsigned long reg,
+     unsigned long value,
+     u16 len)
+{
+ struct usb_device *usbdev =
+ ((struct rsi_91x_usbdev *)adapter->rsi_dev)->usbdev;
+
+ return rsi_usb_reg_write(usbdev, reg, value, len);
+}
+
+int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
+   u32 base_address,
+   u32 instructions_sz,
+   u16 block_size,
+   u8 *ta_firmware)
+{
+ u16 num_blocks;
+ u32 cur_indx, ii;
+ u8  temp_buf[256];
+
+ num_blocks = instructions_sz / block_size;
+ rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+
+ for (cur_indx = 0, ii = 0;
+     ii < num_blocks;
+     ii++, cur_indx += block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx, block_size);
+ if ((rsi_usb_write_register_multiple(adapter,
+     base_address,
+     (u8 *)(temp_buf),
+     block_size)) < 0)
+ return -1;
+
+ rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, ii);
+ base_address += block_size;
+ }
+
+ if (instructions_sz % block_size) {
+ memset(temp_buf, 0, block_size);
+ memcpy(temp_buf, ta_firmware + cur_indx,
+       instructions_sz % block_size);
+ if ((rsi_usb_write_register_multiple(adapter,
+     base_address,
+     (u8 *)temp_buf,
+     instructions_sz % block_size)) < 0)
+ return -1;
+ rsi_dbg(INFO_ZONE,
+ "Written Last Block in Address 0x%x Successfully\n",
+ cur_indx);
+ }
+ return 0;
+}
+
+/**
+ * rsi_deinit_usb_interface() - This function deinitializes the usb interface.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: None.
+ */
+static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+
+ rsi_dbg(INFO_ZONE, "Deinitializing USB interface...\n");
+
+ rsi_kill_thread(&dev->rx_thread);
+ kfree(dev->rx_cb[0].rx_buffer);
+ usb_free_urb(dev->rx_cb[0].rx_urb);
+#ifdef CONFIG_RSI_HCI
+ kfree(dev->rx_cb[1].rx_buffer);
+ usb_free_urb(dev->rx_cb[1].rx_urb);
+#endif
+ kfree(dev->saved_tx_buffer);
+}
+
+/**
+ * rsi_find_bulk_in_and_out_endpoints() - This function initializes the bulk
+ *  endpoints to the device.
+ * @interface: Pointer to the USB interface structure.
+ * @adapter: Pointer to the adapter structure.
+ *
+ * Return: ret_val: 0 on success, -ENOMEM on failure.
+ */
+static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface,
+      struct rsi_hw *adapter)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ __le16 buffer_size;
+ int ii, bin_found = 0, bout_found = 0;
+
+ iface_desc = &interface->altsetting[0];
+
+ for (ii = 0; ii < iface_desc->desc.bNumEndpoints; ++ii) {
+ endpoint = &(iface_desc->endpoint[ii].desc);
+
+ if ((!dev->bulkin_endpoint_addr[bin_found]) &&
+    (endpoint->bEndpointAddress & USB_DIR_IN) &&
+    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+     USB_ENDPOINT_XFER_BULK)) {
+ buffer_size = endpoint->wMaxPacketSize;
+ dev->bulkin_size[bin_found] = buffer_size;
+ dev->bulkin_endpoint_addr[bin_found] =
+ endpoint->bEndpointAddress;
+ printk("bulkin addr[%d] = %d\n", bin_found, dev->bulkin_endpoint_addr[bin_found]);
+ bin_found++;
+ }
+
+ if (!dev->bulkout_endpoint_addr[bout_found] &&
+    !(endpoint->bEndpointAddress & USB_DIR_IN) &&
+    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+     USB_ENDPOINT_XFER_BULK)) {
+ printk("%s:%d\n", __func__, __LINE__);
+ buffer_size = endpoint->wMaxPacketSize;
+ dev->bulkout_endpoint_addr[bout_found] =
+ endpoint->bEndpointAddress;
+ buffer_size = endpoint->wMaxPacketSize;
+ dev->bulkout_size[bout_found] = buffer_size;
+ printk("bulkout addr[%d] = %d\n", bout_found, dev->bulkout_endpoint_addr[bout_found]);
+ bout_found++;
+ }
+
+ if ((bin_found >= MAX_BULK_EP) || (bout_found >= MAX_BULK_EP))
+ break;
+ }
+
+ if (!(dev->bulkin_endpoint_addr[0]) &&
+    (dev->bulkout_endpoint_addr[0]))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int rsi_usb_init_rx(struct rsi_hw *adapter)
+{
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ struct rx_usb_ctrl_block *rx_cb;
+ u8 dword_align_bytes = 0, idx;
+
+ for (idx = 0; idx < MAX_RX_URBS; idx++) {
+ rx_cb = &dev->rx_cb[idx];
+
+ rx_cb->rx_buffer = kzalloc(2000 * 4, GFP_KERNEL | GFP_DMA);
+ if (!rx_cb->rx_buffer)
+ return -ENOMEM
+ ;
+ rx_cb->orig_rx_buffer = rx_cb->rx_buffer;
+ dword_align_bytes = (unsigned long)rx_cb->rx_buffer & 0x3f;
+ if (dword_align_bytes)
+ rx_cb->rx_buffer = rx_cb->rx_buffer +
+   (64 - dword_align_bytes);
+
+ rx_cb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!rx_cb->rx_urb) {
+ rsi_dbg(ERR_ZONE, "Failed alloc rx urb[%d]\n", idx);
+ goto err;
+ }
+ rx_cb->rx_urb->transfer_buffer = rx_cb->rx_buffer;
+ rx_cb->ep_num = idx + 1;
+ rx_cb->data = (void *)dev;
+ }
+ return 0;
+
+err:
+ kfree(rx_cb[0].rx_buffer);
+ kfree(rx_cb[0].rx_urb);
+ kfree(rx_cb[1].rx_buffer);
+ kfree(rx_cb[1].rx_urb);
+ return -1;
+}
+
+/**
+ * rsi_init_usb_interface() - This function initializes the usb interface.
+ * @adapter: Pointer to the adapter structure.
+ * @pfunction: Pointer to USB interface structure.
+ *
+ * Return: 0 on success, a negative error code on failure.
+ */
+static int rsi_init_usb_interface(struct rsi_hw *adapter,
+  struct usb_interface *pfunction)
+{
+ struct rsi_91x_usbdev *rsi_dev;
+ struct rsi_common *common = adapter->priv;
+ int status = 0;
+ u8 dword_align_bytes = 0;
+
+ rsi_dev = kzalloc(sizeof(*rsi_dev), GFP_KERNEL);
+ if (!rsi_dev)
+ return -ENOMEM;
+
+ adapter->rsi_dev = rsi_dev;
+ rsi_dev->usbdev = interface_to_usbdev(pfunction);
+
+ if (rsi_find_bulk_in_and_out_endpoints(pfunction, adapter))
+ return -EINVAL;
+
+ adapter->device = &pfunction->dev;
+ usb_set_intfdata(pfunction, adapter);
+
+ rsi_dev->tx_buffer = kmalloc(2048, GFP_KERNEL);
+ if (!rsi_dev->tx_buffer) {
+ status = -ENOMEM;
+ goto fail_1;
+ }
+ rsi_dev->saved_tx_buffer = rsi_dev->tx_buffer;
+ dword_align_bytes = (unsigned long)rsi_dev->tx_buffer & 0x3f;
+ if (dword_align_bytes)
+ rsi_dev->tx_buffer = rsi_dev->tx_buffer +
+     (64 - dword_align_bytes);
+
+ /* Initialize RX handle */
+ if (rsi_usb_init_rx(adapter)) {
+ rsi_dbg(ERR_ZONE, "Failed to init RX handle\n");
+ goto fail_1;
+ }
+
+ rsi_dev->tx_blk_size = 252;
+ adapter->tx_blk_size = rsi_dev->tx_blk_size;
+
+ /* Initializing function callbacks */
+ adapter->rx_urb_submit = rsi_rx_urb_submit;
+ adapter->check_hw_queue_status = rsi_usb_check_queue_status;
+ adapter->determine_event_timeout = rsi_usb_event_timeout;
+ adapter->host_intf_ops = &usb_host_intf_ops;
+ rsi_dev->priv = (void *)adapter;
+
+ rsi_init_event(&rsi_dev->rx_thread.event);
+ status = rsi_create_kthread(common, &rsi_dev->rx_thread,
+    rsi_usb_rx_thread, "RX-Thread");
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
+ goto fail_2;
+ }
+
+#ifdef CONFIG_RSI_DEBUGFS
+ /* In USB, one less than the MAX_DEBUGFS_ENTRIES entries
+ * is required */
+ adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES - 1;
+#endif
+
+ rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
+ return 0;
+
+fail_2:
+ kfree(rsi_dev->saved_tx_buffer);
+ rsi_kill_thread(&rsi_dev->rx_thread);
+fail_1:
+ return status;
+}
+
+static int rsi_usb_gspi_init(struct rsi_hw *adapter)
+{
+ u32 gspi_ctrl_reg0_val;
+
+ /**
+ * Programming gspi frequency = soc_frequency / 2
+ * Warning : ULP seemed to be not working
+ * well at high frequencies. Modify accordingly
+ */
+ gspi_ctrl_reg0_val = 0x4;
+ gspi_ctrl_reg0_val |= 0x10;
+ gspi_ctrl_reg0_val |= 0x40;
+ gspi_ctrl_reg0_val |= 0x100;
+ gspi_ctrl_reg0_val |= 0x000;
+ gspi_ctrl_reg0_val |= 0x000;
+
+ /* Initializing GSPI for ULP read/writes */
+ return rsi_usb_master_reg_write(adapter, GSPI_CTRL_REG0,
+ gspi_ctrl_reg0_val, 2);
+}
+
+static int usb_ulp_read_write(struct rsi_hw *adapter,
+      u16 addr,
+      u16 *data,
+      u16 len_in_bits)
+{
+ if ((rsi_usb_master_reg_write(adapter,
+      GSPI_DATA_REG1,
+      ((addr << 6) | (data[1] & 0x3f)),
+      2) < 0))
+ goto fail;
+
+ if ((rsi_usb_master_reg_write(adapter,
+      GSPI_DATA_REG0,
+      (*(u16 *)&data[0]),
+      2)) < 0)
+ goto fail;
+
+ if ((rsi_usb_gspi_init(adapter)) < 0)
+ goto fail;
+
+ if ((rsi_usb_master_reg_write(adapter, GSPI_CTRL_REG1,
+      ((len_in_bits - 1) | GSPI_TRIG),
+      2)) < 0)
+ goto fail;
+
+ msleep(10);
+
+ return 0;
+
+fail:
+ return -1;
+}
+
+static int rsi_reset_card(struct rsi_hw *adapter)
+{
+ u16 temp[4] = {0};
+
+ rsi_dbg(INFO_ZONE, "Resetting Card...\n");
+
+#define TA_HOLD_REG 0x22000844
+ rsi_usb_master_reg_write(adapter, TA_HOLD_REG, 0xE, 4);
+ msleep(100);
+ *(u32 *)temp = 2;
+ if ((usb_ulp_read_write(adapter,
+ WATCH_DOG_TIMER_1,
+ &temp[0], 32)) < 0) {
+ goto fail;
+ }
+
+ *(u32 *)temp = 0;
+ if ((usb_ulp_read_write(adapter,
+ WATCH_DOG_TIMER_2,
+ temp, 32)) < 0) {
+ goto fail;
+ }
+
+ *(u32 *)temp = 50;
+ if ((usb_ulp_read_write(adapter,
+ WATCH_DOG_DELAY_TIMER_1,
+ temp, 32)) < 0) {
+ goto fail;
+ }
+
+ *(u32 *)temp = 0;
+ if ((usb_ulp_read_write(adapter,
+ WATCH_DOG_DELAY_TIMER_2,
+ temp, 32)) < 0) {
+ goto fail;
+ }
+
+ *(u32 *)temp = ((0xaa000) | RESTART_WDT | BYPASS_ULP_ON_WDT);
+ if ((usb_ulp_read_write(adapter,
+ WATCH_DOG_TIMER_ENABLE,
+ temp, 32)) < 0) {
+ goto fail;
+ }
+ rsi_dbg(INFO_ZONE, "Card Reset Done\n");
+ return 0;
+
+fail:
+ rsi_dbg(ERR_ZONE, "Reset card Failed\n");
+ return -1;
+}
+
+/**
+ * rsi_probe() - This function is called by kernel when the driver provided
+ * Vendor and device IDs are matched. All the initialization
+ * work is done here.
+ * @pfunction: Pointer to the USB interface structure.
+ * @id: Pointer to the usb_device_id structure.
+ *
+ * Return: 0 on success, a negative error code on failure.
+ */
+static int rsi_probe(struct usb_interface *pfunction,
+     const struct usb_device_id *id)
+{
+ struct rsi_hw *adapter;
+ struct rsi_91x_usbdev *dev;
+ u32 fw_status = 0;
+ int status = 0;
+
+ rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
+
+ adapter = rsi_91x_init();
+ if (!adapter) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
+ __func__);
+ return -ENOMEM;
+ }
+ adapter->rsi_host_intf = RSI_HOST_INTF_USB;
+
+ status = rsi_init_usb_interface(adapter, pfunction);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n",
+ __func__);
+ goto err;
+ }
+
+ rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__);
+
+ dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+
+ status = rsi_usb_reg_read(dev->usbdev, FW_STATUS_REG, &fw_status, 2);
+ if (status < 0)
+ goto err1;
+ else
+ fw_status &= 1;
+
+ if (!fw_status) {
+ rsi_dbg(INIT_ZONE, "Loading firmware...\n");
+ status = rsi_hal_device_init(adapter);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
+ __func__);
+ goto err1;
+ }
+ rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
+ }
+
+ status = rsi_rx_urb_submit(adapter, 1 /* RX_WLAN_EP */);  
+ if (status)
+ goto err1;
+
+#ifdef CONFIG_RSI_HCI
+ status = rsi_rx_urb_submit(adapter, 2 /* RX_BT_EP */);
+ if (status)
+ goto err1;
+#endif
+
+ return 0;
+err1:
+ rsi_deinit_usb_interface(adapter);
+err:
+ rsi_91x_deinit(adapter);
+ rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
+ return status;
+}
+
+/**
+ * rsi_disconnect() - This function performs the reverse of the probe function,
+ *      it deintialize the driver structure.
+ * @pfunction: Pointer to the USB interface structure.
+ *
+ * Return: None.
+ */
+static void rsi_disconnect(struct usb_interface *pfunction)
+{
+ struct rsi_hw *adapter = usb_get_intfdata(pfunction);
+ if (!adapter)
+ return;
+
+ rsi_mac80211_detach(adapter);
+ rsi_dbg(INFO_ZONE, "mac80211 detach done\n");
+
+ rsi_reset_card(adapter);
+
+#ifdef CONFIG_RSI_HCI
+        rsi_hci_detach(adapter->priv);
+ rsi_dbg(INFO_ZONE, "HCI Detach Done\n");
+#endif
+
+ rsi_deinit_usb_interface(adapter);
+ rsi_dbg(INFO_ZONE, "USB interface down\n");
+
+ rsi_91x_deinit(adapter);
+
+ rsi_dbg(INFO_ZONE, "%s: Deinitialization completed\n", __func__);
+}
+
+#ifdef CONFIG_PM
+static int rsi_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ /* Not yet implemented */
+ return -ENOSYS;
+}
+
+static int rsi_resume(struct usb_interface *intf)
+{
+ /* Not yet implemented */
+ return -ENOSYS;
+}
+#endif
+
+static const struct usb_device_id rsi_dev_table[] = {
+ { USB_DEVICE(0x0303, 0x0100) },
+ { USB_DEVICE(0x041B, 0x0301) },
+ { USB_DEVICE(0x041B, 0x0201) },
+ { USB_DEVICE(0x041B, 0x9330) },
+ { USB_DEVICE(0x1618, 0x9113) },
+ { /* Blank */},
+};
+
+static struct usb_driver rsi_driver = {
+ .name       = "RSI-USB WLAN",
+ .probe      = rsi_probe,
+ .disconnect = rsi_disconnect,
+ .id_table   = rsi_dev_table,
+#ifdef CONFIG_PM
+ .suspend    = rsi_suspend,
+ .resume     = rsi_resume,
+#endif
+};
+
+static int __init rsi_usb_module_init(void)
+{
+ rsi_dbg(INIT_ZONE,
+ "=====> RSI USB Module Initialize <=====\n");
+ return usb_register(&rsi_driver);
+}
+
+static void __exit rsi_usb_module_exit(void)
+{
+ usb_deregister(&rsi_driver);
+}
+
+module_init(rsi_usb_module_init);
+module_exit(rsi_usb_module_exit);
+
+MODULE_AUTHOR("Redpine Signals Inc");
+MODULE_DESCRIPTION("Common USB layer for RSI drivers");
+MODULE_SUPPORTED_DEVICE("RSI-91x");
+MODULE_DEVICE_TABLE(usb, rsi_dev_table);
+MODULE_FIRMWARE(FIRMWARE_RSI9113);
+MODULE_VERSION("0.1");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/ubuntu/rsi/rsi_91x_usb_ops.c b/ubuntu/rsi/rsi_91x_usb_ops.c
new file mode 100644
index 0000000..a9ac168
--- /dev/null
+++ b/ubuntu/rsi/rsi_91x_usb_ops.c
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/firmware.h>
+#include "rsi_usb.h"
+
+/**
+ * rsi_usb_rx_thread() - This is a kernel thread to receive the packets from
+ * the USB device.
+ * @common: Pointer to the driver private structure.
+ *
+ * Return: None.
+ */
+void rsi_usb_rx_thread(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
+ struct rx_usb_ctrl_block *rx_cb;
+ int status, idx;
+
+ do {
+ rsi_wait_event(&dev->rx_thread.event, EVENT_WAIT_FOREVER);
+
+ if (atomic_read(&dev->rx_thread.thread_done))
+ break;
+
+ for (idx = 0; idx < MAX_RX_URBS; idx++) {
+ rx_cb = &dev->rx_cb[idx];
+ if (!rx_cb->pend)
+ continue;
+
+ mutex_lock(&common->rx_lock);
+ status = rsi_read_pkt(common, rx_cb->rx_buffer, 0);
+ if (status) {
+ rsi_dbg(ERR_ZONE, "%s: Failed To read data",
+ __func__);
+ mutex_unlock(&common->rx_lock);
+ break;
+ }
+ rx_cb->pend = 0;
+ mutex_unlock(&common->rx_lock);
+
+ if (adapter->rx_urb_submit(adapter, rx_cb->ep_num)) {
+ rsi_dbg(ERR_ZONE,
+ "%s: Failed in urb submission", __func__);
+ break;
+ }
+ }
+ rsi_reset_event(&dev->rx_thread.event);
+
+ } while (1);
+
+ rsi_dbg(INFO_ZONE, "%s: Terminated USB RX thread\n", __func__);
+ atomic_inc(&dev->rx_thread.thread_done);
+ complete_and_exit(&dev->rx_thread.completion, 0);
+}
+
diff --git a/ubuntu/rsi/rsi_boot_params.h b/ubuntu/rsi/rsi_boot_params.h
new file mode 100644
index 0000000..0129b4f
--- /dev/null
+++ b/ubuntu/rsi/rsi_boot_params.h
@@ -0,0 +1,170 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_BOOTPARAMS_HEADER_H__
+#define __RSI_BOOTPARAMS_HEADER_H__
+
+#define CRYSTAL_GOOD_TIME BIT(0)
+#define BOOTUP_MODE_INFO                BIT(1)
+#define WIFI_TAPLL_CONFIGS              BIT(5)
+#define WIFI_PLL960_CONFIGS             BIT(6)
+#define WIFI_AFEPLL_CONFIGS             BIT(7)
+#define WIFI_SWITCH_CLK_CONFIGS         BIT(8)
+
+#define TAPLL_M_VAL_20 9
+#define TAPLL_N_VAL_20 0
+#define TAPLL_P_VAL_20 4
+
+#define PLL960_M_VAL_20                 0x14
+#define PLL960_N_VAL_20                 0
+#define PLL960_P_VAL_20                 5
+
+#define UMAC_CLK_40MHZ                  80
+
+#define TAPLL_M_VAL_40                  9
+#define TAPLL_N_VAL_40                  0
+#define TAPLL_P_VAL_40                  4
+
+#define PLL960_M_VAL_40                 0x14
+#define PLL960_N_VAL_40                 0
+#define PLL960_P_VAL_40                 5
+
+#define UMAC_CLK_20BW \
+ (((TAPLL_M_VAL_20 + 1) * 40) / \
+ ((TAPLL_N_VAL_20 + 1) * (TAPLL_P_VAL_20 + 1)))
+#define VALID_20 \
+ (WIFI_TAPLL_CONFIGS | WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | \
+ WIFI_SWITCH_CLK_CONFIGS | BOOTUP_MODE_INFO | CRYSTAL_GOOD_TIME)
+
+#define UMAC_CLK_40BW   \
+ (((TAPLL_M_VAL_40 + 1) * 40) / \
+ ((TAPLL_N_VAL_40 + 1) * (TAPLL_P_VAL_40 + 1)))
+#define VALID_40 \
+ (WIFI_PLL960_CONFIGS | WIFI_AFEPLL_CONFIGS | WIFI_SWITCH_CLK_CONFIGS | \
+ WIFI_TAPLL_CONFIGS | CRYSTAL_GOOD_TIME | BOOTUP_MODE_INFO)
+
+/* TAPLL programming configurations */
+struct tapll_info {
+ __le16 pll_reg_1;
+ __le16 pll_reg_2;
+} __packed;
+
+/* PLL960 programming configurations */
+struct pll960_info {
+ __le16 pll_reg_1;
+ __le16 pll_reg_2;
+ __le16 pll_reg_3;
+} __packed;
+
+/* AFEPLL programming configurations */
+struct afepll_info {
+ __le16 pll_reg;
+} __packed;
+
+/* PLL configurations */
+struct pll_config {
+ struct tapll_info tapll_info_g;
+ struct pll960_info pll960_info_g;
+ struct afepll_info afepll_info_g;
+} __packed;
+
+/* UMAC clk programming configurations */
+struct switch_clk {
+ __le16 switch_umac_clk : 1; /* If set rest is valid */
+ __le16 switch_qspi_clk : 1; /* If set qspi clk will be changed */
+ __le16 switch_slp_clk_2_32 : 1;
+ __le16 switch_bbp_lmac_clk_reg : 1;
+ __le16 switch_mem_ctrl_cfg : 1;
+ __le16 reserved : 11;
+
+ /* If switch_bbp_lmac_clk_reg is set then this value will be programmed
+ * into reg
+ */
+ __le16 bbp_lmac_clk_reg_val;
+ /* if switch_umac_clk is set then this value will be programmed */
+ __le16 umac_clock_reg_config;
+ /* if switch_qspi_clk is set then this value will be programmed */
+ __le16 qspi_uart_clock_reg_config;
+} __packed;
+
+struct device_clk_info {
+ struct pll_config pll_config_g;
+ struct switch_clk switch_clk_g;
+} __packed;
+
+struct bootup_params {
+ __le16 magic_number;
+#define LOADED_TOKEN  0x5AA5   /* Bootup params are installed by host
+ * or OTP/FLASH (Bootloader)
+ */
+#define ROM_TOKEN     0x55AA   /* Bootup params are taken from ROM
+ * itself in MCU mode.
+ */
+ __le16 crystal_good_time;
+ __le32 valid;
+#define CRYSTAL_GOOD_TIME                BIT(0)
+#define BOOTUP_MODE_INFO                 BIT(1)
+#define DIGITAL_LOOP_BACK_PARAMS         BIT(2)
+#define RTLS_TIMESTAMP_EN                BIT(3)
+#define HOST_SPI_INTR_CFG                BIT(4)
+#define WIFI_TAPLL_CONFIGS               BIT(5)
+#define WIFI_PLL960_CONFIGS              BIT(6)
+#define WIFI_AFEPLL_CONFIGS              BIT(7)
+#define WIFI_SWITCH_CLK_CONFIGS          BIT(8)
+#define BT_TAPLL_CONFIGS                 BIT(9)
+#define BT_PLL960_CONFIGS                BIT(10)
+#define BT_AFEPLL_CONFIGS                BIT(11)
+#define BT_SWITCH_CLK_CONFIGS            BIT(12)
+#define ZB_TAPLL_CONFIGS                 BIT(13)
+#define ZB_PLL960_CONFIGS                BIT(14)
+#define ZB_AFEPLL_CONFIGS                BIT(15)
+#define ZB_SWITCH_CLK_CONFIGS            BIT(16)
+#define BUCKBOOST_WAIT_INFO              BIT(17)
+#define PMU_WAKEUP_SHUTDOWN_W            BIT(18)
+#define WDT_PROG_VALUES                  BIT(19)
+#define WDT_RESET_DELAY_VALUE            BIT(20)
+#define DCDC_OPERATION_MODE_VALID        BIT(21)
+#define PMU_SLP_CLKOUT_SEL               BIT(22)
+#define SOC_RESET_WAIT_CNT               BIT(23)
+ __le32 reserved_for_valids;
+ __le16 bootup_mode_info;
+#define BT_COEXIST                       BIT(0)
+#define BOOTUP_MODE                     (BIT(2) | BIT(1))
+#define CUR_DEV_MODE                    (bootup_params.bootup_mode_info >> 1)
+ __le16 digital_loop_back_params;
+ __le16 rtls_timestamp_en;
+ __le16 host_spi_intr_cfg;
+ struct device_clk_info device_clk_info[3];
+ /* ulp buckboost wait time  */
+ __le32 buckboost_wakeup_cnt;
+ /* pmu wakeup wait time & WDT EN info */
+ __le16 pmu_wakeup_wait;
+ u8 shutdown_wait_time;
+ /* Sleep clock source selection */
+ u8 pmu_slp_clkout_sel;
+ /* WDT programming values */
+ __le32 wdt_prog_value;
+ /* WDT soc reset delay */
+ __le32 wdt_soc_rst_delay;
+ /* dcdc modes configs */
+ __le32 dcdc_operation_mode;
+ __le32 soc_reset_wait_cnt;
+ __le32 waiting_time_at_fresh_sleep;
+ __le32 max_threshold_to_avoid_sleep;
+ u8 beacon_resedue_alg_en;
+} __packed;
+
+#endif
diff --git a/ubuntu/rsi/rsi_coex.h b/ubuntu/rsi/rsi_coex.h
new file mode 100644
index 0000000..c9fbb60
--- /dev/null
+++ b/ubuntu/rsi/rsi_coex.h
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_COEX_H__
+#define __RSI_COEX_H__
+
+#include "rsi_common.h"
+
+#define RSI_COEX_TXQ_MAX_PKTS 64
+#define RSI_COEX_TXQ_WATER_MARK 50
+
+#define COEX_Q 0
+#define BT_Q 1
+#define WLAN_Q 2
+#define VIP_Q 3
+#define ZIGB_Q 4
+#define NUM_COEX_TX_QUEUES 5
+
+#include "rsi_main.h"
+
+enum rsi_proto {
+ RSI_PROTO_WLAN = 0,
+ RSI_PROTO_BT
+};
+
+struct rsi_coex_ctrl_block {
+ struct rsi_common *priv;
+ struct sk_buff_head coex_tx_qs[NUM_COEX_TX_QUEUES];
+
+ struct rsi_thread coex_tx_thread;
+ struct mutex coex_tx_lock;
+};
+
+int rsi_coex_init(struct rsi_common *common);
+int rsi_coex_send_pkt(struct rsi_common *common,
+      struct sk_buff *skb,
+      u8 proto_type);
+
+#endif
diff --git a/ubuntu/rsi/rsi_common.h b/ubuntu/rsi/rsi_common.h
new file mode 100644
index 0000000..a10e32c
--- /dev/null
+++ b/ubuntu/rsi/rsi_common.h
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_COMMON_H__
+#define __RSI_COMMON_H__
+
+#include <linux/kthread.h>
+
+#define EVENT_WAIT_FOREVER              0
+#define QUEUE_NOT_FULL                  1
+#define QUEUE_FULL                      0
+
+static inline int rsi_init_event(struct rsi_event *pevent)
+{
+ atomic_set(&pevent->event_condition, 1);
+ init_waitqueue_head(&pevent->event_queue);
+ return 0;
+}
+
+static inline int rsi_wait_event(struct rsi_event *event, u32 timeout)
+{
+ int status = 0;
+
+ if (!timeout)
+ status = wait_event_interruptible(event->event_queue,
+ (!atomic_read(&event->event_condition)));
+ else
+ status = wait_event_interruptible_timeout(event->event_queue,
+ (!atomic_read(&event->event_condition)),
+ timeout);
+ return status;
+}
+
+static inline void rsi_set_event(struct rsi_event *event)
+{
+ atomic_set(&event->event_condition, 0);
+ wake_up_interruptible(&event->event_queue);
+}
+
+static inline void rsi_reset_event(struct rsi_event *event)
+{
+ atomic_set(&event->event_condition, 1);
+}
+
+static inline int rsi_create_kthread(struct rsi_common *common,
+     struct rsi_thread *thread,
+     void *func_ptr,
+     u8 *name)
+{
+ init_completion(&thread->completion);
+ atomic_set(&thread->thread_done, 0);
+ thread->task = kthread_run(func_ptr, common, "%s", name);
+ if (IS_ERR(thread->task))
+ return (int)PTR_ERR(thread->task);
+
+ return 0;
+}
+
+static inline int rsi_kill_thread(struct rsi_thread *handle)
+{
+ if (atomic_read(&handle->thread_done) > 0)
+ return 0;
+ atomic_inc(&handle->thread_done);
+ rsi_set_event(&handle->event);
+
+ wait_for_completion(&handle->completion);
+ return kthread_stop(handle->task);
+}
+
+void rsi_mac80211_detach(struct rsi_hw *hw);
+u16 rsi_get_connected_channel(struct rsi_hw *adapter);
+struct rsi_hw *rsi_91x_init(void);
+void rsi_91x_deinit(struct rsi_hw *adapter);
+int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len);
+void rsi_indicate_bcnmiss(struct rsi_common *common);
+void rsi_resume_conn_channel(struct rsi_hw *adapter);
+void rsi_hci_detach(struct rsi_common *common);
+#endif
diff --git a/ubuntu/rsi/rsi_debugfs.h b/ubuntu/rsi/rsi_debugfs.h
new file mode 100644
index 0000000..580ad3b
--- /dev/null
+++ b/ubuntu/rsi/rsi_debugfs.h
@@ -0,0 +1,48 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_DEBUGFS_H__
+#define __RSI_DEBUGFS_H__
+
+#include "rsi_main.h"
+#include <linux/debugfs.h>
+
+#ifndef CONFIG_RSI_DEBUGFS
+static inline int rsi_init_dbgfs(struct rsi_hw *adapter)
+{
+ return 0;
+}
+
+static inline void rsi_remove_dbgfs(struct rsi_hw *adapter)
+{
+ return;
+}
+#else
+struct rsi_dbg_files {
+ const char *name;
+ umode_t perms;
+ const struct file_operations fops;
+};
+
+struct rsi_debugfs {
+ struct dentry *subdir;
+ struct rsi_dbg_ops *dfs_get_ops;
+ struct dentry *rsi_files[MAX_DEBUGFS_ENTRIES];
+};
+int rsi_init_dbgfs(struct rsi_hw *adapter);
+void rsi_remove_dbgfs(struct rsi_hw *adapter);
+#endif
+#endif
diff --git a/ubuntu/rsi/rsi_hal.h b/ubuntu/rsi/rsi_hal.h
new file mode 100644
index 0000000..4b554cd
--- /dev/null
+++ b/ubuntu/rsi/rsi_hal.h
@@ -0,0 +1,152 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HAL_H__
+#define __RSI_HAL_H__
+
+#define TA_LOAD_ADDRESS 0x00
+#define FIRMWARE_RSI9113 "rsi_91x.fw"
+#define FLASH_WRITE_CHUNK_SIZE (4 * 1024)
+#define USB_FLASH_READ_CHUNK_SIZE ((2 * 1024) - 4)
+#define SDIO_FLASH_READ_CHUNK_SIZE (2 * 1024)
+#define FLASH_SECTOR_SIZE (4 * 1024)
+#define STARTING_BLOCK_INDEX 0
+#define FLASH_BLOCK_SIZE (32 * 1024)
+
+#define FLASH_SIZE_ADDR 0x04000016
+#define PING_BUFFER_ADDRESS 0x19000
+#define PONG_BUFFER_ADDRESS 0x1a000
+#define SWBL_REGIN 0x41050034
+#define SWBL_REGOUT 0x4105003c
+#define PING_WRITE 0x1
+#define PONG_WRITE 0x2
+
+#define BL_CMD_TIMEOUT 2000
+#define BL_BURN_TIMEOUT (50 * 1000)
+
+#define MASTER_READ_MODE 1
+#define EEPROM_READ_MODE 2
+
+#define REGIN_VALID 0xA
+#define REGIN_INPUT 0xA0
+#define REGOUT_VALID 0xAB
+#define REGOUT_INVALID (~0xAB)
+#define CMD_PASS 0xAA
+#define CMD_FAIL 0xCC
+#define INVALID_ADDR 0x4C
+
+#define BURN_BL 0x23
+#define LOAD_HOSTED_FW 'A'
+#define BURN_HOSTED_FW 'B'
+#define PING_VALID 'I'
+#define PONG_VALID 'O'
+#define PING_AVAIL 'I'
+#define PONG_AVAIL 'O'
+#define EOF_REACHED 'E'
+#define CHECK_CRC 'K'
+#define POLLING_MODE 'P'
+#define CONFIG_AUTO_READ_MODE 'R'
+#define JUMP_TO_ZERO_PC 'J'
+#define FW_LOADING_SUCCESSFUL 'S'
+#define LOADING_INITIATED '1'
+
+/* Boot loader commands */
+#define HOST_INTF_REG_OUT 0x4105003C
+#define HOST_INTF_REG_IN 0x41050034
+#define BOARD_READY 0xABCD
+#define REG_READ 0xD1
+#define REG_WRITE 0xD2
+#define SEND_RPS_FILE '2'
+#define BOOTUP_OPTIONS_LAST_CONFIG_NOT_SAVED 0xF1
+#define BOOTUP_OPTIONS_CHECKSUM_FAIL 0xF2
+#define INVALID_OPTION 0xF3
+#define CHECKSUM_SUCCESS 0xAA
+#define CHECKSUM_FAILURE 0xCC
+#define CHECKSUM_INVALID_ADDRESS 0x4C
+
+#define EEPROM_VERSION_OFFSET 77
+#define CALIB_CRC_OFFSET 4092
+#define MAGIC_WORD 0x5A
+#define MAGIC_WORD_OFFSET_1 40
+#define MAGIC_WORD_OFFSET_2 424
+#define FW_IMAGE_MIN_ADDRESS (68 * 1024)
+#define FLASH_MAX_ADDRESS (4 * 1024 * 1024) //4MB
+#define MAX_FLASH_FILE_SIZE (400 * 1024) //400K
+#define FLASHING_START_ADDRESS 16
+#define CALIB_VALUES_START_ADDR 16
+#define SOC_FLASH_ADDR 0x04000000
+#define EEPROM_DATA_SIZE 4096
+#define CALIB_DATA_SIZE (EEPROM_DATA_SIZE - CALIB_VALUES_START_ADDR)
+#define BL_HEADER 32
+
+#define BT_CARD_READY_IND 0x89
+#define WLAN_CARD_READY_IND 0x0
+#define COMMON_HAL_CARD_READY_IND 0x0
+#define ZIGB_CARD_READY_IND 0xff
+
+#define COMMAN_HAL_WAIT_FOR_CARD_READY 1
+#define COMMON_HAL_SEND_CONFIG_PARAMS 2
+#define COMMON_HAL_TX_ACCESS 3
+#define COMMON_HAL_WAIT_FOR_PROTO_CARD_READY 4
+#define HEX_FILE 1
+#define BIN_FILE 0
+#define UNIX_FILE_TYPE 8
+#define DOS_FILE_TYPE 9
+#define LMAC_INSTRUCTIONS_SIZE (16  * 1024) /* 16Kbytes */
+
+#define ULP_RESET_REG 0x161
+#define WATCH_DOG_TIMER_1 0x16c
+#define WATCH_DOG_TIMER_2 0x16d
+#define WATCH_DOG_DELAY_TIMER_1 0x16e
+#define WATCH_DOG_DELAY_TIMER_2 0x16f
+#define WATCH_DOG_TIMER_ENABLE 0x170
+
+#define RESTART_WDT BIT(11)
+#define BYPASS_ULP_ON_WDT BIT(1)
+
+#define RF_SPI_PROG_REG_BASE_ADDR 0x40080000
+
+#define GSPI_CTRL_REG0 (RF_SPI_PROG_REG_BASE_ADDR)
+#define GSPI_CTRL_REG1 (RF_SPI_PROG_REG_BASE_ADDR + 0x2)
+#define GSPI_DATA_REG0 (RF_SPI_PROG_REG_BASE_ADDR + 0x4)
+#define GSPI_DATA_REG1 (RF_SPI_PROG_REG_BASE_ADDR + 0x6)
+#define GSPI_DATA_REG2 (RF_SPI_PROG_REG_BASE_ADDR + 0x8)
+
+#define GSPI_DMA_MODE BIT(13)
+
+#define GSPI_2_ULP BIT(12)
+#define GSPI_TRIG BIT(7)
+#define GSPI_READ BIT(6)
+#define GSPI_RF_SPI_ACTIVE BIT(8)
+
+struct bl_header {
+ u32 flags;
+ u32 image_no;
+ u32 check_sum;
+ u32 flash_start_address;
+ u32 flash_len;
+} __packed;
+
+struct ta_metadata {
+ char *name;
+ unsigned int address;
+};
+
+int rsi_hal_device_init(struct rsi_hw *adapter);
+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
+int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb);
+
+#endif
diff --git a/ubuntu/rsi/rsi_hci.h b/ubuntu/rsi/rsi_hci.h
new file mode 100644
index 0000000..08f7e1e
--- /dev/null
+++ b/ubuntu/rsi/rsi_hci.h
@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_HCI_H__
+#define __RSI_HCI_H__
+
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/genetlink.h>
+#include <linux/version.h>
+
+#include "rsi_main.h"
+
+#define BB_READ 0x0
+#define BB_WRITE 0x1
+#define RF_READ 0x2
+#define RF_WRITE 0x3
+#define BT_PER_TRANSMIT 0x4
+#define BT_RECEIVE 0x5
+#define BUFFER_READ 0x6
+#define BUFFER_WRITE 0x7
+#define BT_PER_STATS 0x8
+#define ANT_SEL 0x9
+#define BT_BER_PKT_CNT 0xA
+#define BT_BER_RECEIVE 0xB
+#define BT_BER_MODE 0xC
+#define BT_CW_MODE 0xD
+#define TX_STATUS 0xE
+#define GET_DRV_COEX_MODE 0xF
+
+/* RX frame types */
+#define RESULT_CONFIRM 0x80
+#define BT_PER 0x10
+#define BT_BER 0x11
+#define BT_CW 0x12
+
+#define REQUIRED_HEADROOM_FOR_BT_HAL     16
+
+#define GET_ADAPTER_FROM_GENLCB (gcb) \
+        (struct rsi_hci_adapter *)((gcb)->gc_drvpriv)
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 11)
+# define get_portid(_info) (_info)->snd_pid
+#else
+# define get_portid(_info) (_info)->snd_portid
+#endif
+    
+enum {
+ RSI_USER_A_UNSPEC,
+ RSI_USER_A_MSG,
+ __RSI_USER_A_MAX,
+};
+
+enum {
+ RSI_USER_C_UNSPEC,
+ RSI_USER_C_CMD,
+ __RSI_USER_C_MAX,
+};
+
+struct genl_cb {
+ unsigned char gc_cmd, *gc_name;
+ int gc_seq, gc_pid;
+ int gc_done;
+ int gc_n_ops;
+ void  *gc_drvpriv;
+ struct nla_policy *gc_policy;
+ struct genl_family *gc_family;
+ struct genl_ops *gc_ops;
+ struct genl_info *gc_info;
+ struct sk_buff *gc_skb;
+};
+
+enum {
+ BT_DEVICE_NOT_READY = 0,
+ BT_DEVICE_READY
+};
+
+struct rsi_hci_adapter {
+ struct rsi_common *priv;
+ struct hci_dev *hdev;
+ struct genl_cb *gcb;
+ struct sk_buff_head hci_tx_queue;
+ int fsm_state;
+};
+
+int rsi_genl_recv (struct sk_buff *skb, struct genl_info *info);
+int rsi_hci_attach (struct rsi_common *common);
+void rsi_hci_detach(struct rsi_common *common);
+//int rsi_hci_recv_pkt(struct rsi_hci_adapter *h_adapter, u8 *pkt);
+int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt);
+
+#endif
diff --git a/ubuntu/rsi/rsi_main.h b/ubuntu/rsi/rsi_main.h
new file mode 100644
index 0000000..c94e34f
--- /dev/null
+++ b/ubuntu/rsi/rsi_main.h
@@ -0,0 +1,371 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_MAIN_H__
+#define __RSI_MAIN_H__
+
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <linux/version.h>
+
+struct rsi_hw;
+
+#include "rsi_ps.h"
+
+#define ERR_ZONE                        BIT(0) /* Error Msgs */
+#define INFO_ZONE                       BIT(1) /* General Debug Msgs */
+#define INIT_ZONE                       BIT(2) /* Driver Init Msgs */
+#define MGMT_TX_ZONE                    BIT(3) /* TX Mgmt Path Msgs */
+#define MGMT_RX_ZONE                    BIT(4) /* RX Mgmt Path Msgs */
+#define DATA_TX_ZONE                    BIT(5) /* TX Data Path Msgs */
+#define DATA_RX_ZONE                    BIT(6) /* RX Data Path Msgs */
+#define FSM_ZONE                        BIT(7) /* State Machine Msgs */
+#define ISR_ZONE                        BIT(8) /* Interrupt Msgs */
+
+#define FSM_CARD_NOT_READY              0
+#define FSM_COMMON_DEV_PARAMS_SENT 1
+#define FSM_BOOT_PARAMS_SENT            2
+#define FSM_EEPROM_READ_MAC_ADDR        3
+#define FSM_EEPROM_READ_RF_TYPE 4
+#define FSM_RESET_MAC_SENT              5
+#define FSM_RADIO_CAPS_SENT             6
+#define FSM_BB_RF_PROG_SENT             7
+#define FSM_MAC_INIT_DONE               8
+
+extern u32 rsi_zone_enabled;
+extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
+void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len);
+
+#define RSI_MAX_VIFS                    1
+#define NUM_EDCA_QUEUES                 4
+#define IEEE80211_ADDR_LEN              6
+#define FRAME_DESC_SZ                   16
+#define MIN_802_11_HDR_LEN              24
+
+#define DATA_QUEUE_WATER_MARK           400
+#define MIN_DATA_QUEUE_WATER_MARK       300
+#define MULTICAST_WATER_MARK            200
+#define MAC_80211_HDR_FRAME_CONTROL     0
+#define WME_NUM_AC                      4
+#define NUM_SOFT_QUEUES                 5
+#define MAX_HW_QUEUES                   12
+#define INVALID_QUEUE                   0xff
+#define MAX_CONTINUOUS_VO_PKTS          8
+#define MAX_CONTINUOUS_VI_PKTS          4
+#define MGMT_HW_Q 10 /* Queue No 10 is used for
+    * MGMT_QUEUE in Device FW,
+    *  Hence this is Reserved
+    */
+#define BROADCAST_HW_Q 9
+#define BEACON_HW_Q 11
+#define MAX_NUM_SCAN_BGCHANS 24
+
+/* Queue information */
+#define RSI_COEX_Q 0x0
+#define RSI_ZIGB_Q 0x1
+#define RSI_BT_Q 0x2
+#define RSI_WLAN_Q 0x3
+#define RSI_WIFI_MGMT_Q                 0x4
+#define RSI_WIFI_DATA_Q                 0x5
+#define RSI_BT_MGMT_Q 0x6
+#define RSI_BT_DATA_Q 0x7
+#define IEEE80211_MGMT_FRAME            0x00
+#define IEEE80211_CTL_FRAME             0x04
+
+#define IEEE80211_QOS_TID               0x0f
+#define IEEE80211_NONQOS_TID            16
+
+#define MAX_DEBUGFS_ENTRIES             5
+
+#define TID_TO_WME_AC(_tid) (      \
+ ((_tid) == 0 || (_tid) == 3) ? BE_Q : \
+ ((_tid) < 3) ? BK_Q : \
+ ((_tid) < 6) ? VI_Q : \
+ VO_Q)
+
+#define WME_AC(_q) (    \
+ ((_q) == BK_Q) ? IEEE80211_AC_BK : \
+ ((_q) == BE_Q) ? IEEE80211_AC_BE : \
+ ((_q) == VI_Q) ? IEEE80211_AC_VI : \
+ IEEE80211_AC_VO)
+
+struct version_info {
+ u16 major;
+ u16 minor;
+ u16 release_num;
+ u16 patch_num;
+} __packed;
+
+struct skb_info {
+ s8 rssi;
+ u32 flags;
+ u16 channel;
+ s8 tid;
+ s8 sta_id;
+};
+
+enum edca_queue {
+ BK_Q = 0,
+ BE_Q,
+ VI_Q,
+ VO_Q,
+ MGMT_SOFT_Q
+};
+
+struct security_info {
+ bool security_enable;
+ u32 ptk_cipher;
+ u32 gtk_cipher;
+};
+
+struct wmm_qinfo {
+ s32 weight;
+ s32 wme_params;
+ s32 pkt_contended;
+ s32 txop;
+};
+
+struct transmit_q_stats {
+ u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 1];
+ u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 1];
+};
+
+struct vif_priv {
+ bool is_ht;
+ bool sgi;
+ u16 seq_start;
+};
+
+struct rsi_event {
+ atomic_t event_condition;
+ wait_queue_head_t event_queue;
+};
+
+struct rsi_thread {
+ void (*thread_function)(void *);
+ struct completion completion;
+ struct task_struct *task;
+ struct rsi_event event;
+ atomic_t thread_done;
+};
+
+struct cqm_info {
+ s8 last_cqm_event_rssi;
+ int rssi_thold;
+ u32 rssi_hyst;
+};
+
+struct bgscan_config_params {
+ u16 bgscan_threshold;
+ u16 roam_threshold;
+ u16 bgscan_periodicity;
+ u8 num_bg_channels;
+ u8 two_probe;
+ u16 active_scan_duration;
+ u16 passive_scan_duration;
+ u16 channels2scan[MAX_NUM_SCAN_BGCHANS];
+};
+
+struct xtended_desc {
+ u8 confirm_frame_type;
+ u8 retry_cnt;
+ u16 reserved;
+};
+
+struct rsi_hw;
+
+struct rsi_common {
+ struct rsi_hw *priv;
+ struct vif_priv vif_info[RSI_MAX_VIFS];
+
+ bool mgmt_q_block;
+ struct version_info driver_ver;
+ struct version_info fw_ver;
+
+ struct rsi_thread tx_thread;
+ struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 1];
+ /* Mutex declaration */
+ struct mutex mutex;
+ struct mutex pslock;
+ /* Mutex used between tx/rx threads */
+ struct mutex tx_lock;
+ struct mutex rx_lock;
+ u8 endpoint;
+
+ /* Channel/band related */
+ u8 band;
+ u8 channel_width;
+
+ u16 rts_threshold;
+ u16 bitrate_mask[2];
+ u32 fixedrate_mask[2];
+
+ u8 rf_reset;
+ struct transmit_q_stats tx_stats;
+ struct security_info secinfo;
+ struct wmm_qinfo tx_qinfo[NUM_EDCA_QUEUES];
+ struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];
+ u8 mac_addr[IEEE80211_ADDR_LEN];
+
+ /* state related */
+ u32 fsm_state;
+ bool init_done;
+ u8 bb_rf_prog_count;
+ bool iface_down;
+
+ /* Generic */
+ u8 channel;
+ u8 *rx_data_pkt;
+ u8 *saved_rx_data_pkt;
+ u8 mac_id;
+ u8 radio_id;
+ u16 rate_pwr[20];
+ u16 min_rate;
+
+ /* WMM algo related */
+ u8 selected_qnum;
+ u32 pkt_cnt;
+ u8 min_weight;
+
+ /* bgscan related */
+ struct cqm_info cqm_info;
+ struct bgscan_config_params bgscan_info;
+ int bgscan_en;
+ u8 bgscan_probe_req[1500];
+ int bgscan_probe_req_len;
+ u16 bgscan_seq_ctrl;
+ u8 mac80211_cur_channel;
+
+ bool hw_data_qs_blocked;
+ u8 driver_mode;
+ u8 coex_mode;
+ u8 oper_mode;
+ u8 ta_aggr;
+ u8 skip_fw_load;
+ u8 lp_ps_handshake_mode;
+ u8 ulp_ps_handshake_mode;
+ u8 uapsd_bitmap;
+ u8 rf_power_val;
+ u8 device_gpio_type;
+ u16 country_code;
+ u8 wlan_rf_power_mode;
+ u8 bt_rf_power_mode;
+ u8 obm_ant_sel_val;
+ u8 antenna_diversity;
+ u16 rf_pwr_mode;
+ char antenna_gain[2];
+ u8 host_wakeup_intr_enable;
+ u8 host_wakeup_intr_active_high;
+ int tx_power;
+ u8 ant_in_use;
+
+#ifdef CONFIG_RSI_HCI
+ void *hci_adapter;
+#endif
+
+#ifdef CONFIG_RSI_COEX
+ void *coex_cb;
+#endif
+};
+
+enum host_intf {
+ RSI_HOST_INTF_SDIO = 0,
+ RSI_HOST_INTF_USB
+};
+
+enum rsi_dev_model {
+ RSI_DEV_9110 = 0,
+ RSI_DEV_9113,
+ RSI_DEV_9116
+};
+
+struct eepromrw_info {
+ u32 offset;
+ u32 length;
+ u8  write;
+ u16 eeprom_erase;
+ u8 data[480];
+};
+
+struct eeprom_read {
+ u16 length;
+ u16 off_set;
+};
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
+#define NUM_NL80211_BANDS 3
+#endif
+
+struct rsi_hw {
+ struct rsi_common *priv;
+ enum rsi_dev_model device_model;
+ struct ieee80211_hw *hw;
+ struct ieee80211_vif *vifs[RSI_MAX_VIFS];
+ struct ieee80211_tx_queue_params edca_params[NUM_EDCA_QUEUES];
+
+ struct ieee80211_supported_band sbands[NUM_NL80211_BANDS];
+
+ struct device *device;
+ u8 sc_nvifs;
+ enum host_intf rsi_host_intf;
+ enum ps_state ps_state;
+ struct rsi_ps_info ps_info;
+ spinlock_t ps_lock;
+
+#ifdef CONFIG_RSI_DEBUGFS
+ struct rsi_debugfs *dfsentry;
+ u8 num_debugfs_entries;
+#endif
+
+ struct timer_list bl_cmd_timer;
+ u8 blcmd_timer_expired;
+ u32 flash_capacity;
+ u32 tx_blk_size;
+ u32 common_hal_fsm;
+ u8 eeprom_init;
+ struct eepromrw_info eeprom;
+ u32 interrupt_status;
+
+ u8 dfs_region;
+ void *rsi_dev;
+
+ struct rsi_host_intf_ops *host_intf_ops;
+ int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
+ int (*rx_urb_submit)(struct rsi_hw *adapter, u8 ep_num);
+ int (*determine_event_timeout)(struct rsi_hw *adapter);
+};
+
+struct rsi_host_intf_ops {
+ int (*read_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*write_pkt)(struct rsi_hw *adapter, u8 *pkt, u32 len);
+ int (*master_access_msword)(struct rsi_hw *adapter, u16 ms_word);
+ int (*read_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+ u8 *data, u16 count);
+ int (*write_reg_multiple)(struct rsi_hw *adapter, u32 addr,
+  u8 *data, u16 count);
+ int (*master_reg_read)(struct rsi_hw *adapter, u32 addr,
+       u32 *read_buf, u16 size);
+ int (*master_reg_write)(struct rsi_hw *adapter,
+ unsigned long addr, unsigned long data,
+ u16 size);
+ int (*load_data_master_write)(struct rsi_hw *adapter, u32 addr,
+      u32 instructions_size, u16 block_size,
+      u8 *fw);
+};
+
+#endif
diff --git a/ubuntu/rsi/rsi_mgmt.h b/ubuntu/rsi/rsi_mgmt.h
new file mode 100644
index 0000000..4b85e4d
--- /dev/null
+++ b/ubuntu/rsi/rsi_mgmt.h
@@ -0,0 +1,517 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_MGMT_H__
+#define __RSI_MGMT_H__
+
+#include <linux/sort.h>
+#include "rsi_boot_params.h"
+#include "rsi_main.h"
+
+#define MAX_MGMT_PKT_SIZE               512
+#define RSI_NEEDED_HEADROOM             80
+#define RSI_RCV_BUFFER_LEN              2000
+
+#define RSI_11B_MODE                    0
+#define RSI_11G_MODE                    BIT(7)
+#define RETRY_COUNT                     8
+#define RETRY_LONG                      4
+#define RETRY_SHORT                     7
+#define WMM_SHORT_SLOT_TIME             9
+#define SIFS_DURATION                   16
+
+#define KEY_TYPE_CLEAR                  0
+#define RSI_PAIRWISE_KEY                1
+#define RSI_GROUP_KEY                   2
+
+/* EPPROM_READ_ADDRESS */
+#define WLAN_MAC_EEPROM_ADDR            40
+#define WLAN_MAC_MAGIC_WORD_LEN         0x01
+#define WLAN_HOST_MODE_LEN              0x04
+#define WLAN_FW_VERSION_LEN             0x08
+#define MAGIC_WORD                      0x5A
+#define WLAN_EEPROM_RFTYPE_ADDR 424
+
+/* Receive Frame Types */
+enum rx_cmd_type {
+ CARD_READY_IND = 0x0,
+ TA_CONFIRM_TYPE = 0x01,
+ RX_DOT11_MGMT = 0x02,
+ RX_DOT11_DATA = 0x03,
+ TX_STATUS_IND = 0x04,
+ PS_NOTIFY_IND = 0x05,
+ SLEEP_NOTIFY_IND = 0x06,
+ DECRYPT_ERROR_IND = 0x07,
+ BEACON_EVENT_IND = 0x08,
+ DEBUG_IND = 0x09,
+ RX_MISC_IND = 0xa,
+ UNCONNECTED_PEER = 0xb,
+ HW_BMISS_EVENT = 0xc,
+ RATE_GC_TABLE_UPDATE = 0xd,
+ RADAR_DETECTED = 0x0e,
+ TSF_SYNC_CONFIRM = 0xc0,
+ ANTENNA_SELECT = 0xf,
+};
+
+#define EAPOL4_CONFIRM 1
+#define PROBEREQ_CONFIRM                2
+#define NULLDATA_CONFIRM 3
+
+#define RSI_DELETE_PEER                 0x0
+#define RSI_ADD_PEER                    0x1
+#define START_AMPDU_AGGR                0x1
+#define STOP_AMPDU_AGGR                 0x0
+#define INTERNAL_MGMT_PKT               0x99
+
+#define PUT_BBP_RESET                   0
+#define BBP_REG_WRITE                   0
+#define RF_RESET_ENABLE                 BIT(3)
+#define RATE_INFO_ENABLE                BIT(0)
+#define RSI_BROADCAST_PKT               BIT(9)
+#define RSI_DESC_11G_MODE BIT(7)
+#define RSI_DESC_REQUIRE_CFM_TO_HOST BIT(10)
+
+#define UPPER_20_ENABLE                 (0x2 << 12)
+#define LOWER_20_ENABLE                 (0x4 << 12)
+#define FULL40M_ENABLE                  0x6
+
+#define RSI_LMAC_CLOCK_80MHZ            0x1
+#define RSI_ENABLE_40MHZ                (0x1 << 3)
+#define ENABLE_SHORTGI_RATE BIT(9)
+
+#define RX_BA_INDICATION 1
+#define RSI_TBL_SZ 40
+#define MAX_RETRIES 8
+#define RSI_IFTYPE_STATION 1
+
+#define STD_RATE_MCS7 0x07
+#define STD_RATE_MCS6 0x06
+#define STD_RATE_MCS5 0x05
+#define STD_RATE_MCS4 0x04
+#define STD_RATE_MCS3 0x03
+#define STD_RATE_MCS2 0x02
+#define STD_RATE_MCS1 0x01
+#define STD_RATE_MCS0 0x00
+#define STD_RATE_54 0x6c
+#define STD_RATE_48 0x60
+#define STD_RATE_36 0x48
+#define STD_RATE_24 0x30
+#define STD_RATE_18 0x24
+#define STD_RATE_12 0x18
+#define STD_RATE_11 0x16
+#define STD_RATE_09 0x12
+#define STD_RATE_06 0x0C
+#define STD_RATE_5_5 0x0B
+#define STD_RATE_02 0x04
+#define STD_RATE_01 0x02
+
+#define RSI_RF_TYPE                     1
+#define RSI_RATE_00                     0x00
+#define RSI_RATE_1                      0x0
+#define RSI_RATE_2                      0x2
+#define RSI_RATE_5_5                    0x4
+#define RSI_RATE_11                     0x6
+#define RSI_RATE_6                      0x8b
+#define RSI_RATE_9                      0x8f
+#define RSI_RATE_12                     0x8a
+#define RSI_RATE_18                     0x8e
+#define RSI_RATE_24                     0x89
+#define RSI_RATE_36                     0x8d
+#define RSI_RATE_48                     0x88
+#define RSI_RATE_54                     0x8c
+#define RSI_RATE_MCS0                   0x100
+#define RSI_RATE_MCS1                   0x101
+#define RSI_RATE_MCS2                   0x102
+#define RSI_RATE_MCS3                   0x103
+#define RSI_RATE_MCS4                   0x104
+#define RSI_RATE_MCS5                   0x105
+#define RSI_RATE_MCS6                   0x106
+#define RSI_RATE_MCS7                   0x107
+#define RSI_RATE_MCS7_SG                0x307
+
+#define BW_20MHZ                        0
+#define BW_40MHZ                        1
+
+#define EP_2GHZ_20MHZ 0
+#define EP_2GHZ_40MHZ 1
+#define EP_5GHZ_20MHZ 2
+#define EP_5GHZ_40MHZ 3
+
+#define SIFS_TX_11N_VALUE 580
+#define SIFS_TX_11B_VALUE 346
+#define SHORT_SLOT_VALUE 360
+#define LONG_SLOT_VALUE 640
+#define OFDM_ACK_TOUT_VALUE 2720
+#define CCK_ACK_TOUT_VALUE 9440
+#define LONG_PREAMBLE 0x0000
+#define SHORT_PREAMBLE 0x0001
+
+#define RSI_SUPP_FILTERS (FIF_ALLMULTI | FIF_PROBE_REQ |\
+ FIF_BCN_PRBRESP_PROMISC)
+
+#define ANTENNA_SEL_INT 0x02 /* RF_OUT_2 / Integerated */
+#define ANTENNA_SEL_UFL 0x03 /* RF_OUT_1 / U.FL */
+
+/* Power save handshake types */
+#define NO_HAND_SHAKE 0
+#define GPIO_HAND_SHAKE 1
+#define PACKET_HAND_SHAKE 2
+#define TA_GPIO 0
+#define ULP_GPIO 1
+#define RF_POWER_3_3 1
+#define RF_POWER_1_9 0
+
+/* Rx filter word definitions */
+#define PROMISCOUS_MODE BIT(0)
+#define ALLOW_DATA_ASSOC_PEER BIT(1)
+#define ALLOW_MGMT_ASSOC_PEER BIT(2)
+#define ALLOW_CTRL_ASSOC_PEER BIT(3)
+#define DISALLOW_BEACONS BIT(4)
+#define ALLOW_CONN_PEER_MGMT_WHILE_BUF_FULL BIT(5)
+#define DISALLOW_BROADCAST_DATA BIT(6)
+
+#define RSI_TXPOWER_MAX 30
+#define RSI_TXPOWER_MIN -127
+
+#define DEEP_SLEEP 1
+#define CONNECTED_SLEEP 2
+
+#define SLEEP_REQUEST 1
+#define WAKEUP_REQUEST 2
+
+#define RSI_TXPOWER_MAX 30
+#define RSI_TXPOWER_MIN -127
+
+#define IEEE80211_MARKALL_UAPSD_QUEUES \
+ (IEEE80211_WMM_IE_STA_QOSINFO_AC_VO | \
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_VI | \
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_BE | \
+ IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
+#define IEEE80211_STA_SP_ALL_PKTS 0x00
+
+enum opmode {
+ STA_OPMODE = 1,
+ AP_OPMODE = 2
+};
+
+enum vap_status {
+ VAP_ADD = 1,
+ VAP_DELETE = 2,
+ VAP_UPDATE = 3
+};
+
+/*
+ * Subtypes for RX_MISC_IND frame
+ * Frame sub types from LMAC to Host
+ */
+enum rx_misc_ind_subtype {
+ FW_UPGRADE_REQ
+};
+
+extern struct ieee80211_rate rsi_rates[12];
+extern const u16 rsi_mcsrates[8];
+
+enum sta_notify_events {
+ STA_CONNECTED = 0,
+ STA_DISCONNECTED,
+ STA_TX_ADDBA_DONE,
+ STA_TX_DELBA,
+ STA_RX_ADDBA_DONE,
+ STA_RX_DELBA
+};
+
+/* Send Frames Types */
+enum cmd_frame_type {
+ TX_DOT11_MGMT = 0,
+ RESET_MAC_REQ, /* 0x1 */
+ RADIO_CAPABILITIES, /* 0x2 */
+ BB_PROG_VALUES_REQUEST, /* 0x3 */
+ RF_PROG_VALUES_REQUEST, /* 0x4 */
+ WAKEUP_SLEEP_REQUEST, /* 0x5 */
+ SCAN_REQUEST, /* 0x6 */
+ TSF_UPDATE, /* 0x7 */
+ PEER_NOTIFY, /* 0x8 */
+ BLOCK_HW_QUEUE, /* 0x9 */
+ SET_KEY_REQ, /* 0xA */
+ AUTO_RATE_IND, /* 0xB */
+ BOOTUP_PARAMS_REQUEST, /* 0xC */
+ VAP_CAPABILITIES, /* 0xD */
+ EEPROM_READ, /* 0xE */
+ EEPROM_WRITE, /* 0xF */
+ GPIO_PIN_CONFIG, /* 0x10 */
+ SET_RX_FILTER, /* 0x11 */
+ AMPDU_IND, /* 0x12 */
+ STATS_REQUEST, /* 0x13 */
+ BB_BUF_PROG_VALUES_REQ, /* 0x14 */
+ BBP_PROG_IN_TA, /* 0x15 */
+ BG_SCAN_PARAMS, /* 0x16 */
+ BG_SCAN_PROBE_REQ, /* 0x17 */
+ CW_MODE_REQ, /* 0x18 */
+ PER_CMD_PKT, /* 0x19 */
+ DEV_SLEEP_REQUEST, /* 0x1A */
+ DEV_WAKEUP_CNF,  /* 0x1B */
+ RF_LOOPBACK_REQ, /* 0x1C */
+ RF_LPBK_M3,  /* 0x1D */
+ RF_RESET_FRAME,  /* 0x1E */
+ LMAC_REG_OPS,  /* 0x1F */
+ ANT_SEL_FRAME, /* 0x20 */
+ CONFIRM, /* 0x21 */
+ WLAN_DE_REGISTER, /* 0x22 */
+ DEBUG_FRAME,  /* 0x23 */
+ HW_BMISS_HANDLE, /* 0x24 */
+ MULTICAST_ENABLE, /* 0x25 */
+ TX_MISC_IND, /* 0x26 */
+ VAP_DYNAMIC_UPDATE, /* 0x27 */
+ COMMON_DEV_CONFIG, /* 0x28 */
+ RADIO_PARAMS_UPDATE, /* 0x29 */
+ RADAR_REQUEST, /* 0x2A */
+ WOWLAN_CONFIG_PARAMS, /* 2B */
+ IAP_CONFIG, /* 0x2C */
+};
+
+/* RSI Command packet formats */
+struct rsi_mac_frame {
+ __le16 desc_word[8];
+} __packed;
+
+struct rsi_boot_params {
+ __le16 desc_word[8];
+ struct bootup_params bootup_params;
+} __packed;
+
+struct rsi_peer_notify {
+ __le16 desc_word[8];
+ u8 mac_addr[6];
+ __le16 command;
+ __le16 mpdu_density;
+ __le16 reserved;
+ __le32 sta_flags;
+} __packed;
+
+struct rsi_vap_caps {
+ __le16 desc_word[8];
+ u8 mac_addr[6];
+ __le16 keep_alive_period;
+ u8 bssid[6];
+ __le16 reserved;
+ __le32 flags;
+ __le16 frag_threshold;
+ __le16 rts_threshold;
+ __le32 default_mgmt_rate;
+ __le32 default_ctrl_rate;
+ __le32 default_data_rate;
+ __le16 beacon_interval;
+ __le16 dtim_period;
+ __le16 beacon_miss_threshold;
+} __packed;
+
+struct rsi_dynamic_s {
+ __le16 desc_word[8];
+
+ struct framebody {
+ __le16 data_rate;
+ __le16 mgmt_rate;
+ __le16 keep_alive_period;
+ } frame_body;
+} __packed;
+
+struct rsi_bgscan_params {
+ __le16 desc_word[8];
+ __le16 bgscan_threshold;
+ __le16 roam_threshold;
+ __le16 bgscan_periodicity;
+ u8 num_bg_channels;
+ u8 two_probe;
+ __le16 active_scan_duration;
+ __le16 passive_scan_duration;
+ __le16 channels2scan[MAX_NUM_SCAN_BGCHANS];
+} __packed;
+
+struct rsi_bgscan_probe {
+ __le16 desc_word[8];
+ __le16 mgmt_rate;
+ __le16 flags;
+ __le16 channel_num;
+ __le16 channel_scan_time;
+ __le16 probe_req_length;
+} __packed;
+
+struct rsi_set_key {
+ __le16 desc_word[8];
+ u8 key[4][32];
+ u8 tx_mic_key[8];
+ u8 rx_mic_key[8];
+} __packed;
+
+struct rsi_auto_rate {
+ __le16 desc_word[8];
+ __le16 failure_limit;
+ __le16 initial_boundary;
+ __le16 max_threshold_limt;
+ __le16 num_supported_rates;
+ __le16 aarf_rssi;
+ __le16 moderate_rate_inx;
+ __le16 collision_tolerance;
+ __le16 supported_rates[40];
+} __packed;
+
+struct qos_params {
+ __le16 cont_win_min_q;
+ __le16 cont_win_max_q;
+ __le16 aifsn_val_q;
+ __le16 txop_q;
+} __packed;
+
+struct rsi_radio_caps {
+ __le16 desc_word[8];
+ struct qos_params qos_params[MAX_HW_QUEUES];
+ u8 num_11n_rates;
+ u8 num_11ac_rates;
+ __le16 gcpd_per_rate[20];
+ __le16 sifs_tx_11n;
+ __le16 sifs_tx_11b;
+ __le16 slot_rx_11n;
+ __le16 ofdm_ack_tout;
+ __le16 cck_ack_tout;
+ __le16 preamble_type;
+} __packed;
+
+struct rsi_ulp_gpio_vals {
+ u8 motion_sensor_gpio_ulp_wakeup : 1;
+ u8 sleep_ind_from_device : 1;
+ u8 ulp_gpio_2 :1;
+ u8 push_button_ulp_wakeup : 1;
+ u8 reserved : 4;
+} __packed;
+
+struct rsi_soc_gpio_vals {
+ u32 pspi_csn_0 : 1;
+ u32 pspi_csn_1 : 1;
+ u32 host_wakeup_intr :1;
+ u32 pspi_data_0 : 1;
+ u32 pspi_data_1 : 1;
+ u32 pspi_data_2 : 1;
+ u32 pspi_data_3 : 1;
+ u32 i2c_scl :1;
+ u32 i2c_sda   :1;
+ u32 uart1_rx :1;
+ u32 uart1_tx  :1;
+ u32 uart1_rts_i2s_clk :1;
+ u32 uart1_cts_i2s_ws :1;
+ u32 dbg_uart_rx_i2s_din :1;
+ u32 dbg_uart_tx_i2s_dout :1;
+ u32 lp_wakeup_boot_bypass :1;
+ u32 led_0 :1;
+ u32 btcoex_wlan_active_ext_pa_ant_sel_A :1;
+ u32 btcoex_bt_priority_ext_pa_ant_sel_B :1;
+ u32 btcoex_bt_active_ext_pa_on_off :1;
+ u32 rf_reset :1;
+ u32 sleep_ind_from_device :1;
+} __packed;
+
+struct rsi_config_vals {
+ u16 desc_word[8];
+ u8 lp_ps_handshake;
+ u8 ulp_ps_handshake;
+ u8 sleep_config_params; /* 0 for no handshake,
+ * 1 for GPIO based handshake,
+ * 2 packet handshake
+ */
+ u8 unused_ulp_gpio;
+ u32 unused_soc_gpio_bitmap;
+ u8 ext_pa_or_bt_coex_en;
+ u8 opermode;
+ u8 wlan_rf_pwr_mode;
+ u8 bt_rf_pwr_mode;
+ u8 zigbee_rf_pwr_mode;
+ u8 driver_mode;
+ u8 region_code;
+ u8 antenna_sel_val;
+#define EXT_PA      1
+#define EXT_BT_COEX 2
+} __packed;
+
+struct rsi_request_ps {
+ u16 desc_word[8];
+ struct ps_sleep_params ps_sleep;
+ u8 ps_mimic_support;
+ u8 ps_uapsd_acs;
+ u8 ps_uapsd_wakeup_period;
+ u8 reserved;
+ u32 ps_listen_interval;
+ u32 ps_dtim_interval_duration;
+ u16 ps_num_dtim_intervals;
+} __packed;
+
+static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
+{
+ return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
+}
+
+static inline u32 rsi_get_length(u8 *addr, u16 offset)
+{
+ return (le16_to_cpu(*(__le16 *)&addr[offset])) & 0x0fff;
+}
+
+static inline u8 rsi_get_extended_desc(u8 *addr, u16 offset)
+{
+ return le16_to_cpu(*((__le16 *)&addr[offset + 4])) & 0x00ff;
+}
+
+static inline u8 rsi_get_rssi(u8 *addr)
+{
+ return *(u8 *)(addr + FRAME_DESC_SZ);
+}
+
+static inline u8 rsi_get_channel(u8 *addr)
+{
+ return *(char *)(addr + 15);
+}
+
+int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
+int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
+     u8 vap_status);
+int rsi_send_aggr_params_frame(struct rsi_common *common, u16 tid,
+       u16 ssn, u8 buf_size, u8 event);
+int rsi_load_key(struct rsi_common *common, u8 *data, u16 key_len,
+ u8 key_type, u8 key_id, u32 cipher);
+int rsi_set_channel(struct rsi_common *common,
+    struct ieee80211_channel *channel);
+int rsi_send_vap_dynamic_update(struct rsi_common *common);
+int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
+void rsi_inform_bss_status(struct rsi_common *common, u8 status,
+   const u8 *bssid, u8 qos_enable, u16 aid);
+void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb);
+int rsi_mac80211_attach(struct rsi_common *common);
+int rsi_send_bgscan_params(struct rsi_common *common, int enable);
+int rsi_send_bgscan_probe_req(struct rsi_common *common);
+void rsi_indicate_tx_status(struct rsi_hw *common, struct sk_buff *skb,
+    int status);
+bool rsi_is_cipher_wep(struct rsi_common *common);
+void rsi_core_qos_processor(struct rsi_common *common);
+void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb);
+int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb);
+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
+int rsi_band_check(struct rsi_common *common);
+int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word);
+int rsi_flash_read(struct rsi_hw *adapter);
+int rsi_program_bb_rf(struct rsi_common *common);
+int rsi_send_radio_params_update(struct rsi_common *common);
+void init_bgscan_params(struct rsi_common *common);
+int rsi_set_antenna(struct rsi_common *common, u8 antenna);
+int rsi_hci_attach(struct rsi_common *common);
+
+#endif
diff --git a/ubuntu/rsi/rsi_ps.h b/ubuntu/rsi/rsi_ps.h
new file mode 100644
index 0000000..a2e794e
--- /dev/null
+++ b/ubuntu/rsi/rsi_ps.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef __RSI_PS_H__
+#define __RSI_PS_H__
+
+#define PS_CONFIRM_INDEX 12
+
+enum ps_state {
+ PS_NONE = 0,
+ PS_ENABLE_REQ_SENT = 1,
+ PS_DISABLE_REQ_SENT = 2,
+ PS_ENABLED = 3
+};
+
+struct ps_sleep_params {
+ u8 enable;
+ u8 sleep_type; //LP or ULP type
+ u8 connected_sleep;
+ u8 reserved1;
+ u16 num_bcns_per_lis_int;
+ u16 wakeup_type;
+ u32 sleep_duration;
+} __packed;
+
+struct rsi_ps_info {
+ u8 enabled;
+ u8 sleep_type;
+ u8 tx_threshold;
+ u8 rx_threshold;
+ u8 tx_hysterisis;
+ u8 rx_hysterisis;
+ u16 monitor_interval;
+ u32 listen_interval;
+ u16 num_bcns_per_lis_int;
+ u32 dtim_interval_duration;
+ u16 num_dtims_per_sleep;
+ u32 deep_sleep_wakeup_period;
+} __packed;
+
+char *str_psstate(enum ps_state state);
+void rsi_enable_ps(struct rsi_hw *adapter);
+void rsi_disable_ps(struct rsi_hw *adapter);
+int rsi_handle_ps_confirm(struct rsi_hw *adapter, u8 *msg);
+void rsi_default_ps_params(struct rsi_hw *hw);
+int rsi_send_ps_request(struct rsi_hw *adapter, bool enable);
+void rsi_conf_uapsd(struct rsi_hw *adapter);
+
+#endif
diff --git a/ubuntu/rsi/rsi_sdio.h b/ubuntu/rsi/rsi_sdio.h
new file mode 100644
index 0000000..315a506
--- /dev/null
+++ b/ubuntu/rsi/rsi_sdio.h
@@ -0,0 +1,152 @@
+/**
+ * @section LICENSE
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef __RSI_SDIO_INTF__
+#define __RSI_SDIO_INTF__
+
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/sdio_ids.h>
+#include "rsi_main.h"
+
+/* Buffer status register related info */
+#define PKT_BUFF_SEMI_FULL 0
+#define PKT_BUFF_FULL 1
+#define PKT_MGMT_BUFF_FULL 2
+#define MSDU_PKT_PENDING 3
+
+/* Interrupt Bit Related Macros */
+#define PKT_BUFF_AVAILABLE 1
+#define FW_ASSERT_IND 2
+
+#define RSI_DEVICE_BUFFER_STATUS_REGISTER 0xf3
+#define RSI_FN1_INT_REGISTER 0xf9
+#define SD_REQUEST_MASTER 0x10000
+
+/* FOR SD CARD ONLY */
+#define SDIO_RX_NUM_BLOCKS_REG 0x000F1
+#define SDIO_FW_STATUS_REG 0x000F2
+#define SDIO_NXT_RD_DELAY2 0x000F5
+#define SDIO_MASTER_ACCESS_MSBYTE 0x000FA
+#define SDIO_MASTER_ACCESS_LSBYTE 0x000FB
+#define SDIO_READ_START_LVL 0x000FC
+#define SDIO_READ_FIFO_CTL 0x000FD
+#define SDIO_WRITE_FIFO_CTL 0x000FE
+#define SDIO_WAKEUP_REG 0x000FF
+
+#define SDIO_FUN1_INTR_CLR_REG 0x0008
+#define SDIO_REG_HIGH_SPEED 0x0013
+#define TA_SOFT_RESET_REG 0x0004
+#define TA_TH0_PC_REG 0x0400
+#define TA_HOLD_THREAD_REG 0x0844      
+#define TA_RELEASE_THREAD_REG 0x0848
+#define TA_POLL_BREAK_STATUS_REG 0x085C
+
+
+#define RSI_GET_SDIO_INTERRUPT_TYPE(_I, TYPE)      \
+ {   \
+ TYPE =                             \
+ (_I & (1 << PKT_BUFF_AVAILABLE)) ? \
+ BUFFER_AVAILABLE :   \
+ (_I & (1 << MSDU_PKT_PENDING)) ?   \
+ MSDU_PACKET_PENDING :              \
+ (_I & (1 << FW_ASSERT_IND)) ?      \
+ FIRMWARE_ASSERT_IND : UNKNOWN_INT; \
+ }
+
+/* common registers in SDIO function1 */
+#define TA_SOFT_RESET_REG 0x0004
+#define TA_TH0_PC_REG 0x0400
+#define TA_HOLD_THREAD_REG 0x0844
+#define TA_RELEASE_THREAD_REG 0x0848
+
+#define TA_SOFT_RST_CLR 0
+#define TA_SOFT_RST_SET BIT(0)
+#define TA_PC_ZERO 0
+#define TA_HOLD_THREAD_VALUE cpu_to_le32(0xF)
+#define TA_RELEASE_THREAD_VALUE cpu_to_le32(0xF)
+#define TA_BASE_ADDR 0x2200
+#define MISC_CFG_BASE_ADDR 0x4105
+
+enum sdio_interrupt_type {
+ BUFFER_FULL = 0x0,
+ BUFFER_AVAILABLE = 0x2,
+ FIRMWARE_ASSERT_IND = 0x3,
+ MSDU_PACKET_PENDING = 0x4,
+ UNKNOWN_INT = 0XE
+};
+
+struct receive_info {
+ bool buffer_full;
+ bool semi_buffer_full;
+ bool mgmt_buffer_full;
+ u32 mgmt_buf_full_counter;
+ u32 buf_semi_full_counter;
+ u8 watch_bufferfull_count;
+ u32 sdio_intr_status_zero;
+ u32 sdio_int_counter;
+ u32 total_sdio_msdu_pending_intr;
+ u32 total_sdio_unknown_intr;
+ u32 buf_full_counter;
+ u32 buf_available_counter;
+};
+
+struct rsi_91x_sdiodev {
+ struct sdio_func *pfunction;
+ struct task_struct *in_sdio_litefi_irq;
+ struct receive_info rx_info;
+ u32 next_read_delay;
+ u32 sdio_high_speed_enable;
+ u8 sdio_clock_speed;
+ u32 cardcapability;
+ u8 prev_desc[16];
+ u32 tx_blk_size;
+ u8 write_fail;
+};
+
+void rsi_interrupt_handler(struct rsi_hw *adapter);
+int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
+int rsi_sdio_device_init(struct rsi_common *common);
+int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
+int rsi_sdio_write_register(struct rsi_hw *adapter, u8 function,
+    u32 addr, u8 *data);
+int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length);
+int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter, u8 *pkt, u32 len);
+int rsi_sdio_read_register_multiple(struct rsi_hw *adapter, u32 addr,
+    u8 *data, u16 count);
+int rsi_sdio_write_register_multiple(struct rsi_hw *adapter, u32 addr,
+     u8 *data, u16 count);
+int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
+  u16 ms_word);
+int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
+    u32 base_address, u32 instructions_sz,
+    u16 block_size, u8 *ta_firmware);
+int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
+     u32 *read_buf, u16 size);
+int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
+      unsigned long addr,
+      unsigned long data,
+      u16 size);
+void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
+int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
+int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
+#endif
diff --git a/ubuntu/rsi/rsi_usb.h b/ubuntu/rsi/rsi_usb.h
new file mode 100644
index 0000000..c72637f
--- /dev/null
+++ b/ubuntu/rsi/rsi_usb.h
@@ -0,0 +1,94 @@
+/**
+ * @section LICENSE
+ * Copyright (c) 2014 Redpine Signals Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __RSI_USB_INTF__
+#define __RSI_USB_INTF__
+
+#include <linux/usb.h>
+#include "rsi_main.h"
+#include "rsi_common.h"
+
+#define FW_STATUS_REG                0x41050012
+
+#define USB_VENDOR_REGISTER_READ     0x15
+#define USB_VENDOR_REGISTER_WRITE    0x16
+#define RSI_USB_TX_HEAD_ROOM         128
+
+#define MAX_TX_URBS                  1
+#ifdef CONFIG_RSI_HCI
+#define MAX_RX_URBS                  2
+#else
+#define MAX_RX_URBS                  1
+#endif
+#define MAX_BULK_EP                  8
+#define MGMT_EP                      1
+#define DATA_EP                      2
+
+struct rx_usb_ctrl_block {
+ u8 *data;
+ struct urb *rx_urb;
+ u8 *rx_buffer;
+ u8 *orig_rx_buffer;
+ u8 ep_num;
+ u8 pend;
+};
+
+struct rsi_91x_usbdev {
+ void *priv;
+ struct rsi_thread rx_thread;
+ u8 endpoint;
+ struct usb_device *usbdev;
+ struct usb_interface *pfunction;
+ struct rx_usb_ctrl_block rx_cb[MAX_RX_URBS];
+ u8 *tx_buffer;
+ u8 *saved_tx_buffer;
+ __le16 bulkin_size[MAX_BULK_EP];
+ u8 bulkin_endpoint_addr[MAX_BULK_EP];
+ __le16 bulkout_size[MAX_BULK_EP];
+ u8 bulkout_endpoint_addr[MAX_BULK_EP];
+ u32 tx_blk_size;
+ u8 write_fail;
+};
+
+static inline int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num)
+{
+ /* In USB, there isn't any need to check the queue status */
+ return QUEUE_NOT_FULL;
+}
+
+static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
+{
+ return EVENT_WAIT_FOREVER;
+}
+
+int rsi_usb_device_init(struct rsi_common *common);
+int rsi_usb_read_register_multiple(struct rsi_hw *adapter, u32 addr,
+   u8 *data, u16 count);
+int rsi_usb_write_register_multiple(struct rsi_hw *adapter, u32 addr,
+    u8 *data, u16 count);
+void rsi_usb_rx_thread(struct rsi_common *common);
+
+int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter, u8 *pkt, u32 len);
+int rsi_usb_master_reg_read(struct rsi_hw *adapter, u32 reg,
+    u32 *value, u16 len);
+int rsi_usb_master_reg_write(struct rsi_hw *adapter, unsigned long reg,
+     unsigned long value, u16 len);
+int rsi_usb_load_data_master_write(struct rsi_hw *adapter, u32 base_address,
+   u32 instructions_sz,
+   u16 block_size,
+   u8 *ta_firmware);
+#endif
--
2.9.3


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 2/4][Xenial SRU] UBUNTU: SAUCE: Separate Redpine RS9113 WLAN/BT vendor and kernel drivers

Shrirang Bagul
In reply to this post by Shrirang Bagul
BugLink: http://bugs.launchpad.net/bugs/1657682

The driver submitted by vendor Redpine for RS9113 WLAN/BT exports same
symbols as their existing old driver in the kernel. This patch tries to
resolve this conflict.

Signed-off-by: Shrirang Bagul <[hidden email]>
---
 ubuntu/rsi/Kconfig            | 18 +++++++++---------
 ubuntu/rsi/Makefile           | 28 ++++++++++++++--------------
 ubuntu/rsi/rsi_91x_hal.c      |  2 +-
 ubuntu/rsi/rsi_91x_hci.c      |  6 +++---
 ubuntu/rsi/rsi_91x_mac80211.c |  6 +++---
 ubuntu/rsi/rsi_91x_main.c     |  6 +++---
 ubuntu/rsi/rsi_91x_mgmt.c     |  2 +-
 ubuntu/rsi/rsi_91x_sdio.c     |  4 ++--
 ubuntu/rsi/rsi_91x_usb.c      |  8 ++++----
 ubuntu/rsi/rsi_debugfs.h      |  2 +-
 ubuntu/rsi/rsi_main.h         |  6 +++---
 ubuntu/rsi/rsi_usb.h          |  2 +-
 12 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/ubuntu/rsi/Kconfig b/ubuntu/rsi/Kconfig
index 64798a9..e1a370f 100644
--- a/ubuntu/rsi/Kconfig
+++ b/ubuntu/rsi/Kconfig
@@ -12,40 +12,40 @@ config WLAN_VENDOR_RSI
 
 if WLAN_VENDOR_RSI
 
-config RSI_91X
+config VEN_RSI_91X
  tristate "Redpine Signals Inc 91x WLAN driver support"
  depends on MAC80211
  ---help---
   This option enabes support for RSI 1x1 devices.
   Select M (recommended), if you have a RSI 1x1 wireless module.
 
-config RSI_DEBUGFS
+config VEN_RSI_DEBUGFS
  bool "Redpine Signals Inc debug support"
- depends on RSI_91X
+ depends on VEN_RSI_91X
  default y
  ---help---
  Say Y, if you would like to enable debug support. This option
  creates debugfs entries
 
-config RSI_SDIO
+config VEN_RSI_SDIO
  tristate "Redpine Signals SDIO bus support"
- depends on MMC && RSI_91X
+ depends on MMC && VEN_RSI_91X
  default m
  ---help---
   This option enables the SDIO bus support in rsi drivers.
   Select M (recommended), if you have a RSI 1x1 wireless module.
 
-config RSI_USB
+config VEN_RSI_USB
  tristate "Redpine Signals USB bus support"
- depends on USB && RSI_91X
+ depends on USB && VEN_RSI_91X
  default m
  ---help---
   This option enables the USB bus support in rsi drivers.
   Select M (recommended), if you have a RSI 1x1 wireless module.
 
-config RSI_HCI
+config VEN_RSI_HCI
  tristate "Redpine Signals HCI support"
- depends on RSI_91X
+ depends on VEN_RSI_91X
  default m
  ---help---
   This option enables the HCI support in rsi drivers for BT apps.
diff --git a/ubuntu/rsi/Makefile b/ubuntu/rsi/Makefile
index b4f662d..519db07 100644
--- a/ubuntu/rsi/Makefile
+++ b/ubuntu/rsi/Makefile
@@ -1,15 +1,15 @@
-rsi_91x-y += rsi_91x_main.o
-rsi_91x-y += rsi_91x_core.o
-rsi_91x-y += rsi_91x_mac80211.o
-rsi_91x-y += rsi_91x_mgmt.o
-rsi_91x-y += rsi_91x_hal.o
-rsi_91x-y += rsi_91x_ps.o
-rsi_91x-$(CONFIG_RSI_DEBUGFS) += rsi_91x_debugfs.o
-rsi_91x-$(CONFIG_RSI_HCI) += rsi_91x_hci.o
-rsi_91x-$(CONFIG_RSI_COEX) += rsi_91x_coex.o
+ven_rsi_91x-y += rsi_91x_main.o
+ven_rsi_91x-y += rsi_91x_core.o
+ven_rsi_91x-y += rsi_91x_mac80211.o
+ven_rsi_91x-y += rsi_91x_mgmt.o
+ven_rsi_91x-y += rsi_91x_hal.o
+ven_rsi_91x-y += rsi_91x_ps.o
+ven_rsi_91x-$(CONFIG_VEN_RSI_DEBUGFS) += rsi_91x_debugfs.o
+ven_rsi_91x-$(CONFIG_VEN_RSI_HCI) += rsi_91x_hci.o
+ven_rsi_91x-$(CONFIG_RSI_COEX) += rsi_91x_coex.o
 
-rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
-rsi_sdio-y += rsi_91x_sdio.o rsi_91x_sdio_ops.o
-obj-$(CONFIG_RSI_91X) += rsi_91x.o
-obj-$(CONFIG_RSI_SDIO) += rsi_sdio.o
-obj-$(CONFIG_RSI_USB) += rsi_usb.o
+ven_rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
+ven_rsi_sdio-y += rsi_91x_sdio.o rsi_91x_sdio_ops.o
+obj-$(CONFIG_VEN_RSI_91X) += ven_rsi_91x.o
+obj-$(CONFIG_VEN_RSI_SDIO) += ven_rsi_sdio.o
+obj-$(CONFIG_VEN_RSI_USB) += ven_rsi_usb.o
diff --git a/ubuntu/rsi/rsi_91x_hal.c b/ubuntu/rsi/rsi_91x_hal.c
index 077c125..cac5cc8 100644
--- a/ubuntu/rsi/rsi_91x_hal.c
+++ b/ubuntu/rsi/rsi_91x_hal.c
@@ -1086,7 +1086,7 @@ fail:
 int rsi_hal_device_init(struct rsi_hw *adapter)
 {
 
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
  adapter->priv->coex_mode = 4;
 #else
  adapter->priv->coex_mode = 1;
diff --git a/ubuntu/rsi/rsi_91x_hci.c b/ubuntu/rsi/rsi_91x_hci.c
index 9524849..e4d9daa 100644
--- a/ubuntu/rsi/rsi_91x_hci.c
+++ b/ubuntu/rsi/rsi_91x_hci.c
@@ -187,7 +187,7 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
 
         rsi_hex_dump(DATA_RX_ZONE, "TX BT Pkt", skb->data, skb->len);
 
-#ifdef CONFIG_RSI_COEX
+#ifdef CONFIG_VEN_RSI_COEX
  rsi_coex_send_pkt(h_adapter->priv, skb, RSI_BT_Q);
 #else
         rsi_send_bt_pkt(h_adapter->priv, skb);
@@ -220,7 +220,7 @@ int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
  return 0;
  }
 
-#ifdef CONFIG_RSI_COEX
+#ifdef CONFIG_VEN_RSI_COEX
  if (rsi_coex_init(common)) {
  rsi_dbg(ERR_ZONE, "Failed to init COEX module\n");
  goto err;
@@ -348,7 +348,7 @@ int rsi_genl_recv(struct sk_buff *skb, struct genl_info *info)
  memcpy(skb->data, data, len);
  bt_cb(skb)->pkt_type = pkttype;
 
-#ifdef CONFIG_RSI_COEX
+#ifdef CONFIG_VEN_RSI_COEX
  return rsi_coex_send_pkt(h_adapter->priv, skb, RSI_BT_Q);
 #else
         return rsi_send_bt_pkt(h_adapter->priv, skb);
diff --git a/ubuntu/rsi/rsi_91x_mac80211.c b/ubuntu/rsi/rsi_91x_mac80211.c
index 9e989a7..000f4c8 100644
--- a/ubuntu/rsi/rsi_91x_mac80211.c
+++ b/ubuntu/rsi/rsi_91x_mac80211.c
@@ -224,7 +224,7 @@ void rsi_mac80211_detach(struct rsi_hw *adapter)
  kfree(sband->channels);
  }
 
-#ifdef CONFIG_RSI_DEBUGFS
+#ifdef CONFIG_VEN_RSI_DEBUGFS
  rsi_remove_dbgfs(adapter);
  kfree(adapter->dfsentry);
 #endif
@@ -270,10 +270,10 @@ static void rsi_mac80211_tx(struct ieee80211_hw *hw,
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
 
-#ifndef CONFIG_RSI_HCI
+#ifndef CONFIG_VEN_RSI_HCI
  rsi_core_xmit(common, skb);
 #else
-#ifndef CONFIG_RSI_COEX
+#ifndef CONFIG_VEN_RSI_COEX
         ieee80211_free_txskb(common->priv->hw, skb);
 #endif
 #endif
diff --git a/ubuntu/rsi/rsi_91x_main.c b/ubuntu/rsi/rsi_91x_main.c
index b701e57..f9ee129 100644
--- a/ubuntu/rsi/rsi_91x_main.c
+++ b/ubuntu/rsi/rsi_91x_main.c
@@ -21,10 +21,10 @@
 #include "rsi_mgmt.h"
 #include "rsi_common.h"
 #include "rsi_hal.h"
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
 #include "rsi_hci.h"
 #endif
-#ifdef CONFIG_RSI_COEX
+#ifdef CONFIG_VEN_RSI_COEX
 #include "rsi_coex.h"
 #endif
 
@@ -191,7 +191,7 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
  case RSI_WIFI_MGMT_Q:
  rsi_mgmt_pkt_recv(common, (frame_desc + offset));
  break;
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
  case RSI_BT_MGMT_Q:
  case RSI_BT_DATA_Q:
  rsi_hex_dump(DATA_RX_ZONE,
diff --git a/ubuntu/rsi/rsi_91x_mgmt.c b/ubuntu/rsi/rsi_91x_mgmt.c
index c72d984..c38b12f 100644
--- a/ubuntu/rsi/rsi_91x_mgmt.c
+++ b/ubuntu/rsi/rsi_91x_mgmt.c
@@ -309,7 +309,7 @@ static void rsi_set_default_parameters(struct rsi_common *common)
  common->iface_down = true;
  common->endpoint = EP_2GHZ_20MHZ;
  common->driver_mode = 1; /* End-to-End Mode */
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
  common->coex_mode = 4;
  common->oper_mode = 4;
 #else
diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
index fc99d51..0b2a217 100644
--- a/ubuntu/rsi/rsi_91x_sdio.c
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -965,7 +965,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
  adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
  adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
 
-#ifdef CONFIG_RSI_DEBUGFS
+#ifdef CONFIG_VEN_RSI_DEBUGFS
  adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES;
 #endif
  return status;
@@ -1069,7 +1069,7 @@ static void rsi_disconnect(struct sdio_func *pfunction)
 
  rsi_mac80211_detach(adapter);
  mdelay(10);
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
         rsi_hci_detach(adapter->priv);
 #endif
         mdelay(10);
diff --git a/ubuntu/rsi/rsi_91x_usb.c b/ubuntu/rsi/rsi_91x_usb.c
index 5aac3df..907adb8 100644
--- a/ubuntu/rsi/rsi_91x_usb.c
+++ b/ubuntu/rsi/rsi_91x_usb.c
@@ -469,7 +469,7 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
  rsi_kill_thread(&dev->rx_thread);
  kfree(dev->rx_cb[0].rx_buffer);
  usb_free_urb(dev->rx_cb[0].rx_urb);
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
  kfree(dev->rx_cb[1].rx_buffer);
  usb_free_urb(dev->rx_cb[1].rx_urb);
 #endif
@@ -636,7 +636,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
  goto fail_2;
  }
 
-#ifdef CONFIG_RSI_DEBUGFS
+#ifdef CONFIG_VEN_RSI_DEBUGFS
  /* In USB, one less than the MAX_DEBUGFS_ENTRIES entries
  * is required */
  adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES - 1;
@@ -816,7 +816,7 @@ static int rsi_probe(struct usb_interface *pfunction,
  if (status)
  goto err1;
 
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
  status = rsi_rx_urb_submit(adapter, 2 /* RX_BT_EP */);
  if (status)
  goto err1;
@@ -849,7 +849,7 @@ static void rsi_disconnect(struct usb_interface *pfunction)
 
  rsi_reset_card(adapter);
 
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
         rsi_hci_detach(adapter->priv);
  rsi_dbg(INFO_ZONE, "HCI Detach Done\n");
 #endif
diff --git a/ubuntu/rsi/rsi_debugfs.h b/ubuntu/rsi/rsi_debugfs.h
index 580ad3b..7b7e75f 100644
--- a/ubuntu/rsi/rsi_debugfs.h
+++ b/ubuntu/rsi/rsi_debugfs.h
@@ -20,7 +20,7 @@
 #include "rsi_main.h"
 #include <linux/debugfs.h>
 
-#ifndef CONFIG_RSI_DEBUGFS
+#ifndef CONFIG_VEN_RSI_DEBUGFS
 static inline int rsi_init_dbgfs(struct rsi_hw *adapter)
 {
  return 0;
diff --git a/ubuntu/rsi/rsi_main.h b/ubuntu/rsi/rsi_main.h
index c94e34f..183b412 100644
--- a/ubuntu/rsi/rsi_main.h
+++ b/ubuntu/rsi/rsi_main.h
@@ -274,11 +274,11 @@ struct rsi_common {
  int tx_power;
  u8 ant_in_use;
 
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
  void *hci_adapter;
 #endif
 
-#ifdef CONFIG_RSI_COEX
+#ifdef CONFIG_VEN_RSI_COEX
  void *coex_cb;
 #endif
 };
@@ -327,7 +327,7 @@ struct rsi_hw {
  struct rsi_ps_info ps_info;
  spinlock_t ps_lock;
 
-#ifdef CONFIG_RSI_DEBUGFS
+#ifdef CONFIG_VEN_RSI_DEBUGFS
  struct rsi_debugfs *dfsentry;
  u8 num_debugfs_entries;
 #endif
diff --git a/ubuntu/rsi/rsi_usb.h b/ubuntu/rsi/rsi_usb.h
index c72637f..a202e70 100644
--- a/ubuntu/rsi/rsi_usb.h
+++ b/ubuntu/rsi/rsi_usb.h
@@ -29,7 +29,7 @@
 #define RSI_USB_TX_HEAD_ROOM         128
 
 #define MAX_TX_URBS                  1
-#ifdef CONFIG_RSI_HCI
+#ifdef CONFIG_VEN_RSI_HCI
 #define MAX_RX_URBS                  2
 #else
 #define MAX_RX_URBS                  1
--
2.9.3


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 3/4][Xenial SRU] UBUNTU: SAUCE: Redpine RS9113 WLAN/BT driver ver. 0.9.7

Shrirang Bagul
In reply to this post by Shrirang Bagul
From: Darren Wu <[hidden email]>

BugLink: http://bugs.launchpad.net/bugs/1657682

This is the beta2 release for RS9113 driver from Redpine

Signed-off-by: Darren Wu <[hidden email]>
Signed-off-by: Shrirang Bagul <[hidden email]>
---
 ubuntu/rsi/Makefile           |   6 +-
 ubuntu/rsi/rsi_91x_coex.c     |  69 ++---
 ubuntu/rsi/rsi_91x_core.c     | 182 ++++++++++---
 ubuntu/rsi/rsi_91x_debugfs.c  |  75 ++++--
 ubuntu/rsi/rsi_91x_hal.c      | 519 ++++++++++++++++++++++++++----------
 ubuntu/rsi/rsi_91x_hci.c      | 140 ++++++----
 ubuntu/rsi/rsi_91x_mac80211.c | 607 +++++++++++++++++++++++++++++++-----------
 ubuntu/rsi/rsi_91x_main.c     |  81 ++++--
 ubuntu/rsi/rsi_91x_mgmt.c     | 547 ++++++++++++++++++++++++-------------
 ubuntu/rsi/rsi_91x_ps.c       |  16 +-
 ubuntu/rsi/rsi_91x_sdio.c     | 315 +++++++++++++++-------
 ubuntu/rsi/rsi_91x_sdio_ops.c |  78 ++++--
 ubuntu/rsi/rsi_91x_usb.c      |  88 +++---
 ubuntu/rsi/rsi_91x_usb_ops.c  |   8 +-
 ubuntu/rsi/rsi_coex.h         |   9 +-
 ubuntu/rsi/rsi_common.h       |  10 +-
 ubuntu/rsi/rsi_debugfs.h      |   4 +-
 ubuntu/rsi/rsi_hal.h          |   3 +
 ubuntu/rsi/rsi_hci.h          |   2 -
 ubuntu/rsi/rsi_main.h         |  41 ++-
 ubuntu/rsi/rsi_mgmt.h         |  59 +++-
 ubuntu/rsi/rsi_sdio.h         |   4 +-
 ubuntu/rsi/rsi_usb.h          |   2 +-
 23 files changed, 1989 insertions(+), 876 deletions(-)

diff --git a/ubuntu/rsi/Makefile b/ubuntu/rsi/Makefile
index 519db07..941848c 100644
--- a/ubuntu/rsi/Makefile
+++ b/ubuntu/rsi/Makefile
@@ -1,12 +1,14 @@
+EXTRA_CFLAGS += -DCONFIG_DELL_BOARD -DCONFIG_VEN_RSI_COEX -DLINUX -Wimplicit -Wstrict-prototypes -DCONFIG_VEN_RSI_DEBUGFS -DPLATFORM_X86
+
 ven_rsi_91x-y += rsi_91x_main.o
 ven_rsi_91x-y += rsi_91x_core.o
 ven_rsi_91x-y += rsi_91x_mac80211.o
 ven_rsi_91x-y += rsi_91x_mgmt.o
 ven_rsi_91x-y += rsi_91x_hal.o
 ven_rsi_91x-y += rsi_91x_ps.o
-ven_rsi_91x-$(CONFIG_VEN_RSI_DEBUGFS) += rsi_91x_debugfs.o
+ven_rsi_91x-y += rsi_91x_debugfs.o
 ven_rsi_91x-$(CONFIG_VEN_RSI_HCI) += rsi_91x_hci.o
-ven_rsi_91x-$(CONFIG_RSI_COEX) += rsi_91x_coex.o
+ven_rsi_91x-y += rsi_91x_hci.o rsi_91x_coex.o
 
 ven_rsi_usb-y += rsi_91x_usb.o rsi_91x_usb_ops.o
 ven_rsi_sdio-y += rsi_91x_sdio.o rsi_91x_sdio_ops.o
diff --git a/ubuntu/rsi/rsi_91x_coex.c b/ubuntu/rsi/rsi_91x_coex.c
index 998f912..3b58b58 100644
--- a/ubuntu/rsi/rsi_91x_coex.c
+++ b/ubuntu/rsi/rsi_91x_coex.c
@@ -16,13 +16,10 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-
-
-//#include "rsi_common.h"
 #include "rsi_main.h"
 #include "rsi_coex.h"
-#include"rsi_hal.h"
-
+#include "rsi_hal.h"
+#include "rsi_mgmt.h"
 
 static u8 rsi_coex_determine_coex_q(struct rsi_coex_ctrl_block *coex_cb)
 {
@@ -49,21 +46,21 @@ static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
 
  while (1) {
  coex_q = rsi_coex_determine_coex_q(coex_cb);
- rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
+ ven_rsi_dbg(INFO_ZONE, "queue = %d\n", coex_q);
 
  if (coex_q == INVALID_QUEUE) {
- rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
+ ven_rsi_dbg(DATA_TX_ZONE, "No more pkt\n");
  break;
  }
 
- mutex_lock(&coex_cb->coex_tx_lock);
+ down(&coex_cb->tx_bus_lock);
 
  if (coex_q == BT_Q) {
  skb = skb_dequeue(&coex_cb->coex_tx_qs[BT_Q]);
  rsi_send_bt_pkt(coex_cb->priv, skb);
  }
 
- mutex_unlock(&coex_cb->coex_tx_lock);
+ up(&coex_cb->tx_bus_lock);
  }
 }
 
@@ -74,9 +71,11 @@ static void rsi_coex_sched_tx_pkts(struct rsi_coex_ctrl_block *coex_cb)
  *
  * Return: None.
  */
-static void rsi_coex_scheduler_thread(struct rsi_coex_ctrl_block *coex_cb)
+static void rsi_coex_scheduler_thread(struct rsi_common *common)
 {
- struct rsi_common *common = (struct rsi_common *)coex_cb->priv;
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
+
  u32 timeout = EVENT_WAIT_FOREVER;
 
  do {
@@ -85,20 +84,31 @@ static void rsi_coex_scheduler_thread(struct rsi_coex_ctrl_block *coex_cb)
 
  rsi_coex_sched_tx_pkts(coex_cb);
  } while (atomic_read(&coex_cb->coex_tx_thread.thread_done) == 0);
-
+
  complete_and_exit(&coex_cb->coex_tx_thread.completion, 0);
 }
 
-int rsi_coex_recv_pkt(struct rsi_common *common, struct sk_buff *skb)
+int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg)
 {
+ u16 msg_type = msg[2];
+
+ if (msg_type == COMMON_CARD_READY_IND) {
+ ven_rsi_dbg(INFO_ZONE, "COMMON CARD READY RECEIVED\n");
+ rsi_handle_card_ready(common);
+ } else if (msg_type == SLEEP_NOTIFY_IND) {
+ ven_rsi_dbg(INFO_ZONE, "\n\n sleep notify RECEIVED\n");
+ rsi_mgmt_pkt_recv(common, msg);
+ }
+
  return 0;
 }
 
-int rsi_coex_send_pkt(struct rsi_common *common,
+int rsi_coex_send_pkt(struct rsi_common *common,
       struct sk_buff *skb,
       u8 hal_queue)
 {
- struct rsi_coex_ctrl_block *coex_cb = common->coex_cb;
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
  int status = 0;
 
  /* Add pkt to queue if not WLAN packet */
@@ -108,48 +118,45 @@ int rsi_coex_send_pkt(struct rsi_common *common,
  return status;
  }
 
- mutex_lock(&coex_cb->coex_tx_lock);
-
  /* Send packet to hal */
- status = rsi_send_data_pkt(common, skb);
-
- mutex_unlock(&coex_cb->coex_tx_lock);
+ if (skb->priority == MGMT_SOFT_Q)
+ status = rsi_send_mgmt_pkt(common, skb);
+ else
+ status = rsi_send_data_pkt(common, skb);
 
  return 0;
 }
 
 int rsi_coex_init(struct rsi_common *common)
 {
- struct rsi_coex_ctrl_block *coex_cb = NULL;
+ struct rsi_coex_ctrl_block *coex_cb = NULL;
  int cnt;
 
  coex_cb = kzalloc(sizeof(*coex_cb), GFP_KERNEL);
- if (!coex_cb) {
- rsi_dbg(ERR_ZONE,
- "%s: Failed allocate coex control block\n",
- __func__);
+ if (!coex_cb)
  return -ENOMEM;
- }
+
  common->coex_cb = (void *)coex_cb;
+ coex_cb->priv = common;
+ sema_init(&coex_cb->tx_bus_lock, 1);
 
  /* Initialize co-ex queues */
  for (cnt = 0; cnt < NUM_COEX_TX_QUEUES; cnt++)
  skb_queue_head_init(&coex_cb->coex_tx_qs[cnt]);
- mutex_init(&coex_cb->coex_tx_lock);
+ rsi_init_event(&coex_cb->coex_tx_thread.event);
 
  /* Initialize co-ex thread */
  if (rsi_create_kthread(common,
        &coex_cb->coex_tx_thread,
        rsi_coex_scheduler_thread,
        "Coex-Tx-Thread")) {
- rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
  goto err;
  }
-
  return 0;
 
 err:
- return -1;
+ return -EINVAL;
 }
 
 void rsi_coex_deinit(struct rsi_common *common)
@@ -168,6 +175,4 @@ void rsi_coex_deinit(struct rsi_common *common)
 
  /* Free the coex control block */
  kfree(coex_cb);
-
- return;
 }
diff --git a/ubuntu/rsi/rsi_91x_core.c b/ubuntu/rsi/rsi_91x_core.c
index 8f0d136..eaf0e29 100644
--- a/ubuntu/rsi/rsi_91x_core.c
+++ b/ubuntu/rsi/rsi_91x_core.c
@@ -16,6 +16,10 @@
 
 #include "rsi_mgmt.h"
 #include "rsi_common.h"
+#include "rsi_hal.h"
+#ifdef CONFIG_VEN_RSI_COEX
+#include "rsi_coex.h"
+#endif
 
 /**
  * rsi_determine_min_weight_queue() - This function determines the queue with
@@ -143,7 +147,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common)
  }
 
  if (common->hw_data_qs_blocked) {
- rsi_dbg(INFO_ZONE, "%s: data queue blocked\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: data queue blocked\n", __func__);
  return q_num;
  }
 
@@ -214,7 +218,7 @@ static void rsi_core_queue_pkt(struct rsi_common *common,
  u8 q_num = skb->priority;
 
  if (q_num >= NUM_SOFT_QUEUES) {
- rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",
  __func__, q_num);
  dev_kfree_skb(skb);
  return;
@@ -235,7 +239,7 @@ static struct sk_buff *rsi_core_dequeue_pkt(struct rsi_common *common,
     u8 q_num)
 {
  if (q_num >= NUM_SOFT_QUEUES) {
- rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Invalid Queue Number: q_num = %d\n",
  __func__, q_num);
  return NULL;
  }
@@ -263,11 +267,11 @@ void rsi_core_qos_processor(struct rsi_common *common)
  tstamp_1 = jiffies;
  while (1) {
  q_num = rsi_core_determine_hal_queue(common);
- rsi_dbg(DATA_TX_ZONE,
+ ven_rsi_dbg(DATA_TX_ZONE,
  "%s: Queue number = %d\n", __func__, q_num);
 
  if (q_num == INVALID_QUEUE) {
- rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__);
+ ven_rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__);
  break;
  }
 
@@ -289,15 +293,18 @@ void rsi_core_qos_processor(struct rsi_common *common)
 
  skb = rsi_core_dequeue_pkt(common, q_num);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "skb null\n");
+ ven_rsi_dbg(ERR_ZONE, "skb null\n");
  mutex_unlock(&common->tx_lock);
  break;
  }
-
+#ifdef CONFIG_VEN_RSI_COEX
+ status = rsi_coex_send_pkt(common, skb, RSI_WLAN_Q);
+#else
  if (q_num == MGMT_SOFT_Q)
  status = rsi_send_mgmt_pkt(common, skb);
  else
  status = rsi_send_data_pkt(common, skb);
+#endif
 
  if (status) {
  mutex_unlock(&common->tx_lock);
@@ -314,6 +321,61 @@ void rsi_core_qos_processor(struct rsi_common *common)
  }
 }
 
+inline char *dot11_pkt_type(__le16 frame_control)
+{
+ if (ieee80211_is_beacon(frame_control))
+ return "BEACON";
+ if (ieee80211_is_assoc_req(frame_control))
+ return "ASSOC_REQ";
+ if (ieee80211_is_assoc_resp(frame_control))
+ return "ASSOC_RESP";
+ if (ieee80211_is_reassoc_req(frame_control))
+ return "REASSOC_REQ";
+ if (ieee80211_is_reassoc_resp(frame_control))
+ return "REASSOC_RESP";
+ if (ieee80211_is_auth(frame_control))
+ return "AUTH";
+ if (ieee80211_is_probe_req(frame_control))
+ return "PROBE_REQ";
+ if (ieee80211_is_probe_resp(frame_control))
+ return "PROBE_RESP";
+ if (ieee80211_is_disassoc(frame_control))
+ return "DISASSOC";
+ if (ieee80211_is_deauth(frame_control))
+ return "DEAUTH";
+ if (ieee80211_is_action(frame_control))
+ return "ACTION";
+ if (ieee80211_is_data_qos(frame_control))
+ return "QOS DATA";
+ if (ieee80211_is_pspoll(frame_control))
+ return "PS_POLL";
+ if (ieee80211_is_nullfunc(frame_control))
+ return "NULL_DATA";
+ if (ieee80211_is_qos_nullfunc(frame_control))
+ return "QOS_NULL_DATA";
+
+ if (ieee80211_is_mgmt(frame_control))
+ return "DOT11_MGMT";
+ if (ieee80211_is_data(frame_control))
+ return "DOT11_DATA";
+ if (ieee80211_is_ctl(frame_control))
+ return "DOT11_CTRL";
+
+ return "UNKNOWN";
+}
+
+struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr)
+{
+ int i;
+
+ for (i = 0; i < common->num_stations; i++) {
+ if (!(memcmp(common->stations[i].sta->addr,
+     mac_addr, ETH_ALEN)))
+ return &common->stations[i];
+ }
+ return NULL;
+}
+
 /**
  * rsi_core_xmit() - This function transmits the packets received from mac80211
  * @common: Pointer to the driver private structure.
@@ -326,62 +388,114 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
  struct rsi_hw *adapter = common->priv;
  struct ieee80211_tx_info *info;
  struct skb_info *tx_params;
- struct ieee80211_hdr *tmp_hdr = NULL;
+ struct ieee80211_hdr *wlh = NULL;
+ struct ieee80211_vif *vif = adapter->vifs[0];
  u8 q_num, tid = 0;
 
  if ((!skb) || (!skb->len)) {
- rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Null skb/zero Length packet\n",
  __func__);
  goto xmit_fail;
  }
 
  if (common->fsm_state != FSM_MAC_INIT_DONE) {
- rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);
  goto xmit_fail;
  }
 
  info = IEEE80211_SKB_CB(skb);
  tx_params = (struct skb_info *)info->driver_data;
- tmp_hdr = (struct ieee80211_hdr *)&skb->data[0];
+ wlh = (struct ieee80211_hdr *)&skb->data[0];
 
- if ((ieee80211_is_mgmt(tmp_hdr->frame_control)) ||
-    (ieee80211_is_ctl(tmp_hdr->frame_control)) ||
-    (ieee80211_is_qos_nullfunc(tmp_hdr->frame_control))) {
+ if ((ieee80211_is_mgmt(wlh->frame_control)) ||
+    (ieee80211_is_ctl(wlh->frame_control)) ||
+    (ieee80211_is_qos_nullfunc(wlh->frame_control))) {
  q_num = MGMT_SOFT_Q;
  skb->priority = q_num;
 
- if (ieee80211_is_probe_req(tmp_hdr->frame_control)) {
- rsi_dbg(MGMT_TX_ZONE, "%s: Probe Request\n", __func__);
- if (is_broadcast_ether_addr(tmp_hdr->addr1)) {
- rsi_dbg(INFO_ZONE, "%s: Probe request backup\n", __func__);
- memcpy(common->bgscan_probe_req, skb->data, skb->len);
+ ven_rsi_dbg(INFO_ZONE, "Core: TX Dot11 Mgmt Pkt Type: %s\n",
+ dot11_pkt_type(wlh->frame_control));
+ if (ieee80211_is_probe_req(wlh->frame_control)) {
+ if ((is_broadcast_ether_addr(wlh->addr1)) &&
+    (skb->data[MIN_802_11_HDR_LEN + 1] == 0)) {
+ memcpy(common->bgscan_probe_req,
+       skb->data, skb->len);
  common->bgscan_probe_req_len = skb->len;
  }
- } else if (ieee80211_is_auth(tmp_hdr->frame_control))
- rsi_dbg(MGMT_TX_ZONE, "%s: Auth Request\n", __func__);
- else if (ieee80211_is_assoc_req(tmp_hdr->frame_control))
- rsi_dbg(MGMT_TX_ZONE, "%s: Assoc Request\n", __func__);
- else
- rsi_dbg(MGMT_TX_ZONE, "%s: pkt_type=%04x\n",
- __func__, tmp_hdr->frame_control);
+ }
+ if (rsi_prepare_mgmt_desc(common, skb)) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to prepeare desc\n");
+ goto xmit_fail;
+ }
  } else {
- rsi_dbg(DATA_TX_ZONE, "%s: Data Packet\n", __func__);
- if (ieee80211_is_data_qos(tmp_hdr->frame_control)) {
- tid = (skb->data[24] & IEEE80211_QOS_TID);
+ struct rsi_sta *sta = NULL;
+
+ ven_rsi_dbg(INFO_ZONE, "Core: TX Data Packet\n");
+ rsi_hex_dump(DATA_TX_ZONE, "TX Data Packet",
+     skb->data, skb->len);
+
+ if (ieee80211_is_data_qos(wlh->frame_control)) {
+ u8 *qos = ieee80211_get_qos_ctl(wlh);
+
+ tid = *qos & IEEE80211_QOS_CTL_TID_MASK;
  skb->priority = TID_TO_WME_AC(tid);
+
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+    (!is_broadcast_ether_addr(wlh->addr1)) &&
+    (!is_multicast_ether_addr(wlh->addr1))) {
+ sta = rsi_find_sta(common, wlh->addr1);
+ if (!sta)
+ goto xmit_fail;
+ }
  } else {
  tid = IEEE80211_NONQOS_TID;
  skb->priority = BE_Q;
+
+ if ((!is_broadcast_ether_addr(wlh->addr1)) &&
+    (!is_multicast_ether_addr(wlh->addr1)) &&
+    (vif->type == NL80211_IFTYPE_AP)) {
+ sta = rsi_find_sta(common, wlh->addr1);
+ if (!sta)
+ goto xmit_fail;
+ }
  }
  q_num = skb->priority;
  tx_params->tid = tid;
- tx_params->sta_id = 0;
+
+ if (sta) {
+ wlh->seq_ctrl =
+ cpu_to_le16((sta->seq_no[skb->priority] << 4) &
+    IEEE80211_SCTL_SEQ);
+ sta->seq_no[skb->priority] =
+ (sta->seq_no[skb->priority] + 1) % IEEE80211_MAX_SN;
+ tx_params->sta_id = sta->sta_id;
+ } else {
+ if (vif->type == NL80211_IFTYPE_AP) {
+ wlh->seq_ctrl =
+ cpu_to_le16((common->bc_mc_seqno << 4) &
+    IEEE80211_SCTL_SEQ);
+ common->bc_mc_seqno =
+ (common->bc_mc_seqno + 1) % IEEE80211_MAX_SN;
+ }
+ tx_params->sta_id = 0;
+ }
+
+#ifdef EAPOL_IN_MGMT_Q
+ if (skb->protocol == cpu_to_le16(ETH_P_PAE)) {
+ q_num = MGMT_SOFT_Q;
+ skb->priority = q_num;
+ }
+#endif
+ if (rsi_prepare_data_desc(common, skb)) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to prepare data desc\n");
+ goto xmit_fail;
+ }
  }
 
  if ((q_num != MGMT_SOFT_Q) &&
     ((skb_queue_len(&common->tx_queue[q_num]) + 1) >=
- DATA_QUEUE_WATER_MARK)) {
- rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
+      DATA_QUEUE_WATER_MARK)) {
+ ven_rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
  if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
  ieee80211_stop_queue(adapter->hw, WME_AC(q_num));
  rsi_set_event(&common->tx_thread.event);
@@ -389,13 +503,13 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
  }
 
  rsi_core_queue_pkt(common, skb);
- rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thead <===\n", __func__);
+ ven_rsi_dbg(DATA_TX_ZONE, "%s: ===> Scheduling TX thead <===\n", __func__);
  rsi_set_event(&common->tx_thread.event);
 
  return;
 
 xmit_fail:
- rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to queue packet\n", __func__);
  /* Dropping pkt here */
  ieee80211_free_txskb(common->priv->hw, skb);
 }
diff --git a/ubuntu/rsi/rsi_91x_debugfs.c b/ubuntu/rsi/rsi_91x_debugfs.c
index 257cb68..aeb0834 100644
--- a/ubuntu/rsi/rsi_91x_debugfs.c
+++ b/ubuntu/rsi/rsi_91x_debugfs.c
@@ -206,9 +206,9 @@ static int rsi_stats_open(struct inode *inode,
  */
 static int rsi_debug_zone_read(struct seq_file *seq, void *data)
 {
- rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", rsi_zone_enabled);
+ ven_rsi_dbg(FSM_ZONE, "%x: rsi_enabled zone", ven_rsi_zone_enabled);
  seq_printf(seq, "The zones available are %#x\n",
-   rsi_zone_enabled);
+   ven_rsi_zone_enabled);
  return 0;
 }
 
@@ -252,7 +252,7 @@ static ssize_t rsi_debug_zone_write(struct file *filp,
  if (ret)
  return ret;
 
- rsi_zone_enabled = dbg_zone;
+ ven_rsi_zone_enabled = dbg_zone;
  return len;
 }
 
@@ -280,8 +280,13 @@ static int rsi_bgscan_int_read(struct seq_file *file, void *data)
    params->two_probe,
    params->num_bg_channels);
 
- for (cnt = 0; cnt < params->num_bg_channels; cnt++)
- seq_printf(file, "%d ", params->channels2scan[cnt]);
+ for (cnt = 0; cnt < params->num_bg_channels; cnt++) {
+ if (params->channels2scan[cnt] & (BIT(15)))
+ seq_printf(file, "%d[DFS] ",
+   (params->channels2scan[cnt] & 0x7FFF));
+ else
+ seq_printf(file, "%d ", params->channels2scan[cnt]);
+ }
  seq_printf(file, "\n");
 
  return 0;
@@ -334,20 +339,26 @@ static ssize_t rsi_bgscan_write(struct file *file,
  if (!g_bgscan_enable) {
  /* return here if bgscan is already disabled */
  if (!common->bgscan_en) {
- rsi_dbg(ERR_ZONE, "bgscan already disabled\n");
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(ERR_ZONE, "bgscan already disabled\n");
+#endif
  return total_bytes;
  }
 
  mutex_lock(&common->mutex);
  if (bss->assoc && !rsi_send_bgscan_params(common, 0)) {
- rsi_dbg(ERR_ZONE, "*** bgscan disabled ***\n");
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(ERR_ZONE, "*** bgscan disabled ***\n");
+#endif
  common->bgscan_en = 0;
  }
  mutex_unlock(&common->mutex);
 
  return total_bytes;
  } else if (common->bgscan_en) {
- rsi_dbg(ERR_ZONE, "bgscan already enabled\n");
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(ERR_ZONE, "bgscan already enabled\n");
+#endif
  return total_bytes;
  }
 
@@ -373,29 +384,39 @@ static ssize_t rsi_bgscan_write(struct file *file,
  common->bgscan_info.active_scan_duration = bgscan_vals[3];
  common->bgscan_info.passive_scan_duration = bgscan_vals[4];
  common->bgscan_info.two_probe = bgscan_vals[5];
- common->bgscan_info.num_bg_channels = bgscan_vals[6];
- for (cnt = 0; cnt < common->bgscan_info.num_bg_channels; cnt++)
- common->bgscan_info.channels2scan[cnt] = bgscan_vals[7 + cnt];
-
- rsi_dbg(INFO_ZONE,
+ common->bgscan_info.num_user_channels = bgscan_vals[6];
+ memset(&common->bgscan_info.user_channels, 0,
+       (MAX_BGSCAN_CHANNELS * 2));
+ common->bgscan_info.num_user_channels =
+ ((bgscan_vals[6] > MAX_BGSCAN_CHANNELS) ?
+ MAX_BGSCAN_CHANNELS : bgscan_vals[6]);
+
+ for (cnt = 0; cnt < common->bgscan_info.num_user_channels; cnt++)
+ common->bgscan_info.user_channels[cnt] = bgscan_vals[7 + cnt];
+
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(INFO_ZONE,
  "bgscan_count = %d, roam_count = %d, periodicity = %d\n",
  common->bgscan_info.bgscan_threshold,
  common->bgscan_info.roam_threshold,
  common->bgscan_info.bgscan_periodicity);
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "active_scan_dur = %d, passive_scan_dur = %d, two_probe = %d\n",
  common->bgscan_info.active_scan_duration,
  common->bgscan_info.passive_scan_duration,
  common->bgscan_info.two_probe);
- rsi_dbg(INFO_ZONE, "Number of scan channels = %d\n",
- common->bgscan_info.num_bg_channels);
+ ven_rsi_dbg(INFO_ZONE, "Number of scan channels = %d\n",
+ common->bgscan_info.num_user_channels);
  rsi_hex_dump(INFO_ZONE, "bgscan channels",
-     (u8 *)common->bgscan_info.channels2scan,
-     common->bgscan_info.num_bg_channels * 2);
+     (u8 *)common->bgscan_info.user_channels,
+     common->bgscan_info.num_user_channels * 2);
+#endif
 
  /* If connection is not done don't send bgscan params */
  if (!bss->assoc) {
- rsi_dbg(INFO_ZONE, "Station not connected; skip now\n");
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(INFO_ZONE, "Station not connected; skip now\n");
+#endif
  return total_bytes;
  }
 
@@ -403,15 +424,23 @@ static ssize_t rsi_bgscan_write(struct file *file,
  mutex_lock(&common->mutex);
  if (!rsi_send_bgscan_params(common, 1)) {
  if (!rsi_send_bgscan_probe_req(common)) {
- rsi_dbg(INFO_ZONE, "Background scan started ===>\n");
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(INFO_ZONE, "Background scan started ===>\n");
+#endif
  common->bgscan_en = 1;
  } else {
- rsi_dbg(ERR_ZONE, "Failed sending bgscan probe req\n");
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(ERR_ZONE, "Failed sending bgscan probe req\n");
+#endif
  common->bgscan_en = 0;
  g_bgscan_enable = 0;
  }
- } else
- rsi_dbg(ERR_ZONE, "Failed sending bgscan params req\n");
+
+} else {
+#ifdef PLATFORM_X86
+ ven_rsi_dbg(ERR_ZONE, "Failed sending bgscan params req\n");
+#endif
+ }
  mutex_unlock(&common->mutex);
 
  return total_bytes;
diff --git a/ubuntu/rsi/rsi_91x_hal.c b/ubuntu/rsi/rsi_91x_hal.c
index cac5cc8..45f83e9 100644
--- a/ubuntu/rsi/rsi_91x_hal.c
+++ b/ubuntu/rsi/rsi_91x_hal.c
@@ -25,6 +25,12 @@
 #include "rsi_hal.h"
 #include "rsi_sdio.h"
 #include "rsi_common.h"
+#if defined(CONFIG_VEN_RSI_COEX) || defined(CONFIG_VEN_RSI_HCI)
+#include "rsi_hci.h"
+#endif
+#ifdef CONFIG_VEN_RSI_COEX
+#include "rsi_coex.h"
+#endif
 
 /* FLASH Firmware */
 struct ta_metadata metadata_flash_content[] = {
@@ -37,20 +43,49 @@ struct ta_metadata metadata_flash_content[] = {
 };
 
 /**
- * rsi_send_data_pkt() - This function sends the received data packet from
+ * rsi_send_pkt() - This function sends the received packet from
  * driver to device.
  * @common: Pointer to the driver private structure.
  * @skb: Pointer to the socket buffer structure.
  *
  * Return: status: 0 on success, -1 on failure.
  */
-int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
+int rsi_send_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+#ifdef CONFIG_VEN_RSI_COEX
+ struct rsi_coex_ctrl_block *coex_cb =
+ (struct rsi_coex_ctrl_block *)common->coex_cb;
+#endif
+ int status = -EINVAL;
+
+#ifdef CONFIG_VEN_RSI_COEX
+ down(&coex_cb->tx_bus_lock);
+#endif
+ status = adapter->host_intf_ops->write_pkt(common->priv,
+   skb->data, skb->len);
+#ifdef CONFIG_VEN_RSI_COEX
+ up(&coex_cb->tx_bus_lock);
+#endif
+ return status;
+}
+
+/**
+ * rsi_prepare_data_desc() - This function prepares the device specific descriptor
+ *     for the given data packet
+ *
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, negative error code on failure.
+ */
+int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
 {
  struct rsi_hw *adapter = common->priv;
+ struct ieee80211_vif *vif = adapter->vifs[0];
  struct ieee80211_hdr *wh = NULL;
  struct ieee80211_tx_info *info;
  struct skb_info *tx_params;
- struct ieee80211_bss_conf *bss = NULL;
  int status = -EINVAL;
  u8 ieee80211_hdr_size = MIN_802_11_HDR_LEN;
  u8 dword_align_bytes = 0;
@@ -60,28 +95,31 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
  u16 seq_num = 0;
 
  info = IEEE80211_SKB_CB(skb);
- bss = &info->control.vif->bss_conf;
  tx_params = (struct skb_info *)info->driver_data;
 
- if (!bss->assoc)
+ header_size = FRAME_DESC_SZ + sizeof(struct xtended_desc);
+ if (header_size > skb_headroom(skb)) {
+ ven_rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
+ status = -ENOSPC;
  goto err;
-
- dword_align_bytes = ((uintptr_t)skb->data & 0x3f);
- header_size = dword_align_bytes + FRAME_DESC_SZ +
- sizeof(struct xtended_desc);
+ }
+ skb_push(skb, header_size);
+ dword_align_bytes = ((unsigned long)skb->data & 0x3f);
  if (header_size > skb_headroom(skb)) {
- rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
  status = -ENOSPC;
  goto err;
  }
+ skb_push(skb, dword_align_bytes);
+ header_size += dword_align_bytes;
 
- skb_push(skb, header_size);
+ tx_params->internal_hdr_size = header_size;
  frame_desc = (__le16 *)&skb->data[0];
  xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
  memset((u8 *)frame_desc, 0, header_size);
 
  wh = (struct ieee80211_hdr *)&skb->data[header_size];
- seq_num = (le16_to_cpu(wh->seq_ctrl) >> 4);
+ seq_num = le16_to_cpu(IEEE80211_SEQ_TO_SN(wh->seq_ctrl));
 
  frame_desc[2] = cpu_to_le16(header_size - FRAME_DESC_SZ);
  if (ieee80211_is_data_qos(wh->frame_control)) {
@@ -89,7 +127,8 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
  frame_desc[6] |= cpu_to_le16(BIT(12));
  }
 
- if (adapter->ps_state == PS_ENABLED)
+ if ((vif->type == NL80211_IFTYPE_STATION) &&
+    (adapter->ps_state == PS_ENABLED))
  wh->frame_control |= BIT(12);
 
  if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) &&
@@ -120,23 +159,40 @@ int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
  }
 
  if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
- rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n");
+ ven_rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n");
  frame_desc[6] |= cpu_to_le16(BIT(13));
  frame_desc[1] |= cpu_to_le16(BIT(12));
 #define EAPOL_RETRY_CNT 15
  xtend_desc->retry_cnt = EAPOL_RETRY_CNT;
+#ifdef EAPOL_IN_MGMT_Q
+ skb->priority = VO_Q;
+#endif
  }
 
- frame_desc[6] |= cpu_to_le16(seq_num & 0xfff);
+ frame_desc[6] |= cpu_to_le16(seq_num);
  frame_desc[7] = cpu_to_le16(((tx_params->tid & 0xf) << 4) |
     (skb->priority & 0xf) |
     (tx_params->sta_id << 8));
 
- rsi_hex_dump(DATA_TX_ZONE, "TX data pkt", skb->data, skb->len);
- status = adapter->host_intf_ops->write_pkt(common->priv,
-   skb->data, skb->len);
- if (status)
- rsi_dbg(ERR_ZONE, "%s: Failed to write data pkt\n", __func__);
+ if ((is_broadcast_ether_addr(wh->addr1)) ||
+    (is_multicast_ether_addr(wh->addr1))) {
+ frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
+ frame_desc[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
+#if 0
+ if (common->min_rate == 0xffff) {
+ if (common->band == NL80211_BAND_5GHZ)
+ frame_desc[4] = cpu_to_le16(RSI_RATE_6);
+ else
+ frame_desc[4] = cpu_to_le16(RSI_RATE_1);
+ }
+#endif
+ }
+
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+    (ieee80211_has_moredata(wh->frame_control)))
+ frame_desc[3] |= cpu_to_le16(MORE_DATA_PRESENT);
+
+ return 0;
 
 err:
  ++common->tx_stats.total_tx_pkt_freed[skb->priority];
@@ -145,70 +201,62 @@ err:
 }
 
 /**
- * rsi_send_mgmt_pkt() - This functions prepares the descriptor for
- * the given management packet and send to device.
+ * rsi_prepare_mgmt_desc() - This functions prepares the descriptor for
+ *     the given management packet.
+ *
  * @common: Pointer to the driver private structure.
  * @skb: Pointer to the socket buffer structure.
  *
  * Return: status: 0 on success, -1 on failure.
  */
-int rsi_send_mgmt_pkt(struct rsi_common *common,
-      struct sk_buff *skb)
+int rsi_prepare_mgmt_desc(struct rsi_common *common,struct sk_buff *skb)
 {
  struct rsi_hw *adapter = common->priv;
  struct ieee80211_hdr *wh = NULL;
  struct ieee80211_tx_info *info;
- struct ieee80211_bss_conf *bss = NULL;
- struct ieee80211_hw *hw = adapter->hw;
- struct ieee80211_conf *conf = &hw->conf;
+ struct ieee80211_conf *conf = &adapter->hw->conf;
+ struct ieee80211_vif *vif = adapter->vifs[0];
  struct skb_info *tx_params;
- int status = -E2BIG;
+ int status = -EINVAL;
  __le16 *desc = NULL;
  struct xtended_desc *xtend_desc = NULL;
  u8 header_size = 0;
  u8 vap_id = 0;
- u32 dword_align_req_bytes = 0;
+ u32 dword_align_bytes = 0;
 
  info = IEEE80211_SKB_CB(skb);
  tx_params = (struct skb_info *)info->driver_data;
 
- if (tx_params->flags & INTERNAL_MGMT_PKT) {
- skb->data[1] |= BIT(7); /* Immediate Wakeup bit*/
- rsi_hex_dump(MGMT_TX_ZONE,
-     "Tx Command Packet",
-     skb->data, skb->len);
- status = adapter->host_intf_ops->write_pkt(common->priv,
-   (u8 *)skb->data,
-   skb->len);
- if (status) {
- rsi_dbg(ERR_ZONE,
- "%s: Failed to write the packet\n",
- __func__);
- }
- dev_kfree_skb(skb);
- return status;
- }
-
  /* Update header size */
- header_size = FRAME_DESC_SZ + sizeof(struct xtended_desc) +
- dword_align_req_bytes;
+ header_size = FRAME_DESC_SZ + sizeof(struct xtended_desc);
  if (header_size > skb_headroom(skb)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to add extended descriptor\n",
  __func__);
+ status = -ENOSPC;
  goto err;
  }
  skb_push(skb, header_size);
+ dword_align_bytes = ((unsigned long)skb->data & 0x3f);
+ if (dword_align_bytes > skb_headroom(skb)) {
+ ven_rsi_dbg(ERR_ZONE,
+ "%s: Failed to add dword align\n", __func__);
+ status = -ENOSPC;
+ goto err;
+ }
+ skb_push(skb, dword_align_bytes);
+ header_size += dword_align_bytes;
+
+ tx_params->internal_hdr_size = header_size;
  memset(&skb->data[0], 0, header_size);
 
- bss = &info->control.vif->bss_conf;
  wh = (struct ieee80211_hdr *)&skb->data[header_size];
 
  desc = (__le16 *)skb->data;
  xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
 
  if (skb->len > MAX_MGMT_PKT_SIZE) {
- rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
  goto err;
  }
 
@@ -220,7 +268,7 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
  desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
  if (wh->addr1[0] & BIT(0))
  desc[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
- desc[6] = cpu_to_le16(le16_to_cpu(wh->seq_ctrl) >> 4);
+ desc[6] = cpu_to_le16(IEEE80211_SEQ_TO_SN(wh->seq_ctrl));
 
  if (common->band == NL80211_BAND_2GHZ)
  desc[4] = cpu_to_le16(RSI_11B_MODE);
@@ -228,17 +276,135 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
  desc[4] = cpu_to_le16((RSI_RATE_6 & 0x0f) | RSI_11G_MODE);
 
  if (conf_is_ht40(conf)) {
- desc[5] = cpu_to_le16(0x6);
+ desc[5] = cpu_to_le16(FULL40M_ENABLE);
+ }
+
+ if (ieee80211_is_probe_resp(wh->frame_control)) {
+ desc[1] |= cpu_to_le16(ADD_DELTA_TSF_VAP_ID |
+       FETCH_RETRY_CNT_FRM_HST);
+#define PROBE_RESP_RETRY_CNT 3
+ xtend_desc->retry_cnt = PROBE_RESP_RETRY_CNT;
+ }
+
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+    (ieee80211_is_action(wh->frame_control))) {
+ struct rsi_sta *sta = rsi_find_sta(common, wh->addr1);
+ if (sta)
+ desc[7] |= cpu_to_le16(sta->sta_id << 8);
+ else
+ goto err;
+ } else
+ desc[7] |= cpu_to_le16(vap_id << 8); /* Station ID */
+ desc[4] |= cpu_to_le16(vap_id << 14);
+
+ return 0;
+
+err:
+ return status;
+}
+
+/**
+ * rsi_send_data_pkt() - This function sends the received data packet from
+ * driver to device.
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_vif *vif = adapter->vifs[0];
+ struct ieee80211_hdr *wh = NULL;
+ struct ieee80211_tx_info *info;
+ struct skb_info *tx_params;
+ struct ieee80211_bss_conf *bss = NULL;
+ int status = -EINVAL;
+ u8 header_size = 0;
+
+ info = IEEE80211_SKB_CB(skb);
+ bss = &info->control.vif->bss_conf;
+ tx_params = (struct skb_info *)info->driver_data;
+
+ header_size = tx_params->internal_hdr_size;
+ wh = (struct ieee80211_hdr *)&skb->data[header_size];
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ if (!bss->assoc)
+ goto err;
+ if (!ether_addr_equal(wh->addr1, bss->bssid))
+ goto err;
+ }
+
+ ven_rsi_dbg(INFO_ZONE, "hal: Sending data pkt");
+ rsi_hex_dump(DATA_TX_ZONE, "TX data pkt", skb->data, skb->len);
+
+ status = rsi_send_pkt(common, skb);
+ if (status)
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to write data pkt\n", __func__);
+
+err:
+ ++common->tx_stats.total_tx_pkt_freed[skb->priority];
+ rsi_indicate_tx_status(common->priv, skb, status);
+ return status;
+}
+
+/**
+ * rsi_send_mgmt_pkt() - This function prepares sends the given mgmt packet
+ * to device.
+ *
+ * @common: Pointer to the driver private structure.
+ * @skb: Pointer to the socket buffer structure.
+ *
+ * Return: status: 0 on success, -1 on failure.
+ */
+int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct ieee80211_hdr *wh = NULL;
+ struct ieee80211_tx_info *info;
+ struct skb_info *tx_params;
+ u8 header_size = 0;
+ int status = -EINVAL;
+ struct ieee80211_bss_conf *bss = NULL;
+ __le16 *desc = NULL;
+ struct xtended_desc *xtend_desc = NULL;
+
+ info = IEEE80211_SKB_CB(skb);
+ tx_params = (struct skb_info *)info->driver_data;
+ header_size = tx_params->internal_hdr_size;
+
+ if (tx_params->flags & INTERNAL_MGMT_PKT) {
+ skb->data[1] |= BIT(7); /* Immediate Wakeup bit*/
+ rsi_hex_dump(MGMT_TX_ZONE,
+     "Tx Command Packet",
+     skb->data, skb->len);
+
+ status = rsi_send_pkt(common, skb);
+
+ if (status) {
+ ven_rsi_dbg(ERR_ZONE,
+ "%s: Failed to write the packet\n",
+ __func__);
+ }
+ dev_kfree_skb(skb);
+ return status;
  }
 
+ bss = &info->control.vif->bss_conf;
+ wh = (struct ieee80211_hdr *)&skb->data[header_size];
+
+ desc = (__le16 *)skb->data;
+ xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
+
  /* Indicate to firmware to give cfm */
  if (ieee80211_is_probe_req(wh->frame_control)) { // && (!bss->assoc)) {
  if (!bss->assoc) {
- rsi_dbg(INFO_ZONE, "%s: blocking mgmt queue\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: blocking mgmt queue\n", __func__);
  desc[1] |= cpu_to_le16(RSI_DESC_REQUIRE_CFM_TO_HOST);
  xtend_desc->confirm_frame_type = PROBEREQ_CONFIRM;
  common->mgmt_q_block = true;
- rsi_dbg(INFO_ZONE, "Mgmt queue blocked\n");
+ ven_rsi_dbg(INFO_ZONE, "Mgmt queue blocked\n");
  } else if (common->bgscan_en) {
  /* Drop off channel probe request */
  if (common->mac80211_cur_channel !=
@@ -251,30 +417,22 @@ int rsi_send_mgmt_pkt(struct rsi_common *common,
  return 0;
  }
  }
- rsi_dbg(MGMT_TX_ZONE, "Sending PROBE REQUEST =====>\n");
- } else if (ieee80211_is_auth(wh->frame_control))
- rsi_dbg(MGMT_TX_ZONE, "Sending AUTH REQUEST ======>\n");
- else if (ieee80211_is_assoc_req(wh->frame_control))
- rsi_dbg(MGMT_TX_ZONE, "Sending ASSOC REQUEST ======>\n");
- else
- rsi_dbg(MGMT_TX_ZONE,
- "Sending Packet Type = %04x =====>\n",
- wh->frame_control);
+ ven_rsi_dbg(MGMT_TX_ZONE, "Sending PROBE REQUEST =====>\n");
+ }
 
- desc[7] |= cpu_to_le16(vap_id << 8); /* Station ID */
- desc[4] |= cpu_to_le16(vap_id << 14);
+ ven_rsi_dbg(MGMT_TX_ZONE,
+ "Sending Packet : %s =====>\n",
+ dot11_pkt_type(wh->frame_control));
 
  rsi_hex_dump(MGMT_TX_ZONE, "Tx Mgmt Packet", skb->data, skb->len);
- status = adapter->host_intf_ops->write_pkt(common->priv,
-   (u8 *)desc,
-   skb->len);
+ status = rsi_send_pkt(common, skb);
+
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to write the packet\n",
  __func__);
  }
 
-err:
  rsi_indicate_tx_status(common->priv, skb, status);
  return status;
 }
@@ -288,7 +446,7 @@ int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
 
  header_size = FRAME_DESC_SZ;
  if (header_size > skb_headroom(skb)) {
- rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
  status = -ENOSPC;
  goto err;
  }
@@ -297,7 +455,7 @@ int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
  memset((u8 *)frame_desc, 0, header_size);
 
  frame_desc[0] = cpu_to_le16(skb->len - FRAME_DESC_SZ);
- frame_desc[0] |= (cpu_to_le16 (RSI_BT_DATA_Q )& 0x7) << 12;
+ frame_desc[0] |= (cpu_to_le16(RSI_BT_DATA_Q) & 0x7) << 12;
 
  frame_desc[7] = cpu_to_le16(bt_cb(skb)->pkt_type);
 
@@ -305,13 +463,82 @@ int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
  status = adapter->host_intf_ops->write_pkt(common->priv,
    skb->data, skb->len);
  if (status)
- rsi_dbg(ERR_ZONE, "%s: Failed to write bt pkt\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to write bt pkt\n", __func__);
 
 err:
  dev_kfree_skb(skb);
  return status;
 }
 
+int rsi_send_beacon(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ struct rsi_mac_frame *bcn_frm = NULL;
+ u16 bcn_len = common->beacon_frame_len;
+ struct sk_buff *skb = NULL;
+ struct ieee80211_hw *hw = common->priv->hw;
+ struct ieee80211_conf *conf = &hw->conf;
+ u8 vap_id = 0;
+ u8 dword_align_bytes = 0;
+ u8 header_size = 0;
+
+ skb = dev_alloc_skb(FRAME_DESC_SZ + bcn_len + 64);
+ if (!skb)
+ return -ENOMEM;
+
+ dword_align_bytes = ((unsigned long)skb->data & 0x3f);
+ printk("%s: dword_bytes = %d\n", __func__, dword_align_bytes);
+ header_size = dword_align_bytes + FRAME_DESC_SZ;
+ printk("header_size = %d\n", header_size);
+ memset(skb->data, 0, header_size + bcn_len + 64);
+
+ common->beacon_cnt++;
+ bcn_frm = (struct rsi_mac_frame *)skb->data;
+ bcn_frm->desc_word[0] = cpu_to_le16(bcn_len | (RSI_WIFI_DATA_Q << 12));
+ bcn_frm->desc_word[1] = 0; // FIXME: Fill type later
+ bcn_frm->desc_word[2] = cpu_to_le16((MIN_802_11_HDR_LEN << 8) |
+    dword_align_bytes);
+ bcn_frm->desc_word[3] = cpu_to_le16(MAC_BBP_INFO | NO_ACK_IND |
+    BEACON_FRAME | INSERT_TSF |
+    INSERT_SEQ_NO);
+ bcn_frm->desc_word[3] |= cpu_to_le16(RATE_INFO_ENABLE);
+ bcn_frm->desc_word[4] = cpu_to_le16(vap_id << 14);
+ bcn_frm->desc_word[7] = cpu_to_le16(BEACON_HW_Q);
+
+ if (conf_is_ht40_plus(conf)) {
+ bcn_frm->desc_word[5] = cpu_to_le16(LOWER_20_ENABLE);
+ bcn_frm->desc_word[5] |= cpu_to_le16(LOWER_20_ENABLE >> 12);
+ } else if (conf_is_ht40_minus(conf)) {
+ bcn_frm->desc_word[5] = cpu_to_le16(UPPER_20_ENABLE);
+ bcn_frm->desc_word[5] |= cpu_to_le16(UPPER_20_ENABLE >> 12);
+ }
+
+ if (common->band == NL80211_BAND_2GHZ)
+ bcn_frm->desc_word[4] |= cpu_to_le16(0xB | RSI_11G_MODE);
+ else
+ bcn_frm->desc_word[4] |= cpu_to_le16(RSI_11B_MODE);
+
+ //if (!(common->beacon_cnt % common->dtim_cnt))
+ if (1) //FIXME check this
+ bcn_frm->desc_word[3] |= cpu_to_le16(DTIM_BEACON);
+
+ memcpy(&skb->data[header_size], common->beacon_frame, bcn_len);
+
+ skb_put(skb, bcn_len + header_size);
+
+ rsi_hex_dump(MGMT_TX_ZONE, "Beacon Frame", skb->data, skb->len);
+
+ if (adapter->host_intf_ops->write_pkt(adapter, skb->data, skb->len) < 0) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to send Beacon\n");
+ goto err;
+ }
+ return 0;
+
+err:
+ dev_kfree_skb(skb);
+ return -1;
+}
+
 /**
  * bl_cmd_timeout() - This function is called when BL command timed out
  * @priv: Pointer to the hardware structure.
@@ -385,7 +612,7 @@ int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
      SWBL_REGIN,
      &regin_val,
      2) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Command %0x REGIN reading failed..\n",
  __func__, cmd);
  goto fail;
@@ -395,13 +622,13 @@ int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
  break;
  }
  if (adapter->blcmd_timer_expired) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Command %0x REGIN reading timed out..\n",
  __func__, cmd);
  goto fail;
  }
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "Issuing write to Regin regin_val:%0x sending cmd:%0x\n",
  regin_val, (cmd | regin_input << 8));
  if ((hif_ops->master_reg_write(adapter,
@@ -425,7 +652,7 @@ int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
      SWBL_REGOUT,
      &regout_val,
      2) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Command %0x REGOUT reading failed..\n",
  __func__, cmd);
  goto fail;
@@ -435,7 +662,7 @@ int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
  break;
  }
  if (adapter->blcmd_timer_expired) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Command %0x REGOUT reading timed out..\n",
  __func__, cmd);
  goto fail;
@@ -445,12 +672,12 @@ int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
 
  output = ((u8 *)&regout_val)[0] & 0xff;
 
- rsi_dbg(INFO_ZONE, "Invalidating regout\n");
+ ven_rsi_dbg(INFO_ZONE, "Invalidating regout\n");
  if ((hif_ops->master_reg_write(adapter,
        SWBL_REGOUT,
        (cmd | REGOUT_INVALID << 8),
        2)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Command %0x REGOUT writing failed..\n",
  __func__, cmd);
  goto fail;
@@ -458,11 +685,11 @@ int bl_write_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, u16 *cmd_resp)
  mdelay(1);
 
  if (output == exp_resp) {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Recvd Expected resp %x for cmd %0x\n",
  __func__, output, cmd);
  } else {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Recvd resp %x for cmd %0x\n",
  __func__, output, cmd);
  goto fail;
@@ -487,7 +714,7 @@ int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
  u16 regout_val = 0;
  u32 timeout = 0;
 
- rsi_dbg(INFO_ZONE, "Issuing cmd: \"%s\"\n", str);
+ ven_rsi_dbg(INFO_ZONE, "Issuing cmd: \"%s\"\n", str);
 
  if ((cmd == EOF_REACHED) || (cmd == PING_VALID) || (cmd == PONG_VALID))
  timeout = BL_BURN_TIMEOUT;
@@ -496,7 +723,7 @@ int bl_cmd(struct rsi_hw *adapter, u8 cmd, u8 exp_resp, char *str)
 
  bl_start_cmd_timer(adapter, timeout);
  if (bl_write_cmd(adapter, cmd, exp_resp, &regout_val) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Command %s (%0x) writing failed..\n",
  __func__, str, cmd);
  goto fail;
@@ -542,7 +769,7 @@ static int bl_write_header(struct rsi_hw *adapter,
  write_addr,
  (u8 *)&bl_hdr,
  write_len)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to load Version/CRC structure\n",
  __func__);
  goto fail;
@@ -550,7 +777,7 @@ static int bl_write_header(struct rsi_hw *adapter,
  } else {
  write_addr = PING_BUFFER_ADDRESS >> 16;
  if ((hif_ops->master_access_msword(adapter, write_addr)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set ms word to common reg\n",
  __func__);
  goto fail;
@@ -561,7 +788,7 @@ static int bl_write_header(struct rsi_hw *adapter,
  write_addr,
  (u8 *)&bl_hdr,
  write_len)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to load Version/CRC structure\n",
  __func__);
  goto fail;
@@ -586,12 +813,12 @@ static u32 read_flash_capacity(struct rsi_hw *adapter)
  if ((adapter->host_intf_ops->master_reg_read(adapter,
      FLASH_SIZE_ADDR,
      &flash_sz, 2)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Flash size reading failed..\n",
  __func__);
  return 0;
  }
- rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
+ ven_rsi_dbg(INIT_ZONE, "Flash capacity: %d KiloBytes\n", flash_sz);
 
  return (flash_sz * 1024); /* Return size in kbytes */
 }
@@ -636,7 +863,7 @@ static int ping_pong_write(struct rsi_hw *adapter, u8 cmd, u8 *addr, u32 size)
     size,
     block_size,
     addr)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to write blk at addr %0x\n",
  __func__, *addr);
  goto fail;
  }
@@ -672,7 +899,7 @@ static int auto_fw_upgrade(struct rsi_hw *adapter,
  temp_flash_content = flash_content;
 
  if (content_size > MAX_FLASH_FILE_SIZE) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Flash Content size is more than 400K %u\n",
  __func__, MAX_FLASH_FILE_SIZE);
  goto fail;
@@ -680,24 +907,24 @@ static int auto_fw_upgrade(struct rsi_hw *adapter,
 
  flash_start_address = cpu_to_le32(
  *(u32 *)&flash_content[FLASHING_START_ADDRESS]);
- rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
+ ven_rsi_dbg(INFO_ZONE, "flash start address: %08x\n", flash_start_address);
 
  if (flash_start_address < FW_IMAGE_MIN_ADDRESS) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Fw image Flash Start Address is less than 64K\n",
  __func__);
  goto fail;
  }
 
  if (flash_start_address % FLASH_SECTOR_SIZE) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Flash Start Address is not multiple of 4K\n",
  __func__);
  goto fail;
  }
 
  if ((flash_start_address + content_size) > adapter->flash_capacity) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Flash Content will cross max flash size\n",
  __func__);
  goto fail;
@@ -706,24 +933,24 @@ static int auto_fw_upgrade(struct rsi_hw *adapter,
  temp_content_size  = content_size;
  num_flash = content_size / FLASH_WRITE_CHUNK_SIZE;
 
- rsi_dbg(INFO_ZONE, "content_size: %d\n", content_size);
- rsi_dbg(INFO_ZONE, "num_flash: %d\n", num_flash);
+ ven_rsi_dbg(INFO_ZONE, "content_size: %d\n", content_size);
+ ven_rsi_dbg(INFO_ZONE, "num_flash: %d\n", num_flash);
 
  for (index = 0; index <= num_flash; index++) {
- rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
+ ven_rsi_dbg(INFO_ZONE, "flash index: %d\n", index);
  if (index != num_flash) {
  content_size = FLASH_WRITE_CHUNK_SIZE;
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "QSPI content_size:%d\n",
  content_size);
  } else {
  content_size =
  temp_content_size % FLASH_WRITE_CHUNK_SIZE;
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "Writing last sector content_size:%d\n",
  content_size);
  if (!content_size) {
- rsi_dbg(INFO_ZONE, "INSTRUCTION SIZE ZERO\n");
+ ven_rsi_dbg(INFO_ZONE, "INSTRUCTION SIZE ZERO\n");
  break;
  }
  }
@@ -737,13 +964,13 @@ static int auto_fw_upgrade(struct rsi_hw *adapter,
     cmd,
     flash_content,
     content_size)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to load %d block\n",
  __func__, index);
  goto fail;
  }
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Successfully loaded %d instructions\n",
  __func__, index);
  flash_content += content_size;
@@ -754,7 +981,7 @@ static int auto_fw_upgrade(struct rsi_hw *adapter,
  bl_stop_cmd_timer(adapter);
  goto fail;
  }
- rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
+ ven_rsi_dbg(INFO_ZONE, "FW loading is done and FW is running..\n");
  return 0;
 
 fail:
@@ -778,7 +1005,7 @@ static int read_flash_content(struct rsi_hw *adapter,
  if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO) {
  if (hif_ops->master_access_msword(adapter,
   address >> 16) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set ms word to common reg\n",
  __func__);
  return -1;
@@ -828,33 +1055,33 @@ int verify_flash_content(struct rsi_hw *adapter,
  if (read_mode != EEPROM_READ_MODE) {
  dest_addr  = kzalloc(instructions_sz, GFP_KERNEL);
  if (!dest_addr) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Memory allocation for dest_addr failed\n",
  __func__);
  return -1;
  }
  }
 
- rsi_dbg(INFO_ZONE, "Number of loops required: %d\n", num_loops);
+ ven_rsi_dbg(INFO_ZONE, "Number of loops required: %d\n", num_loops);
  for (idx = 0; idx < num_loops; idx++) {
  if (instructions_sz < flash_chunk_size)
  chunk_size = instructions_sz;
  else
  chunk_size = flash_chunk_size;
- rsi_dbg(INFO_ZONE, "idx is %d and chunk size is %d\n",
+ ven_rsi_dbg(INFO_ZONE, "idx is %d and chunk size is %d\n",
  idx, chunk_size);
  if (read_mode == EEPROM_READ_MODE) {
  adapter->eeprom.offset = eeprom_offset;
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "eeprom offset is %x\n", eeprom_offset);
  adapter->eeprom.length = chunk_size;
  status = rsi_flash_read(adapter);
  if (status == 0) {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: BLOCK/SECTOR READING SUCCESSFUL\n",
  __func__);
  } else {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: READING FROM FLASH FAILED\n",
  __func__);
  return -1;
@@ -862,11 +1089,11 @@ int verify_flash_content(struct rsi_hw *adapter,
  } else {
  memset(dest_addr, 0, chunk_size);
  addr = SOC_FLASH_ADDR + eeprom_offset;
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "Reading flash addr 0x%0x\n", addr);
  if (read_flash_content(adapter, dest_addr, addr,
        flash_chunk_size) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s:Failed to read calib data\n",
  __func__);
  status = -1;
@@ -878,7 +1105,7 @@ int verify_flash_content(struct rsi_hw *adapter,
  mdelay(10);
  dest_addr = adapter->priv->rx_data_pkt;
  if (!dest_addr) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Failed reading flash content\n");
  status = -1;
  goto out;
@@ -887,7 +1114,7 @@ int verify_flash_content(struct rsi_hw *adapter,
  if (memcmp(&flash_content[idx * flash_chunk_size],
    dest_addr,
    chunk_size)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: VERIFICATION OF FLASH CHUNK FAILED\n",
  __func__);
  kfree(dest_addr);
@@ -928,7 +1155,7 @@ int rsi_load_9113_firmware(struct rsi_hw *adapter)
       SWBL_REGOUT,
       &regout_val,
       2)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: REGOUT read failed\n", __func__);
  goto fail;
  }
@@ -937,21 +1164,21 @@ int rsi_load_9113_firmware(struct rsi_hw *adapter)
  break;
  }
  if (adapter->blcmd_timer_expired) {
- rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE, "%s: REGOUT read timedout\n", __func__);
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Soft boot loader not present\n", __func__);
  goto fail;
  }
  bl_stop_cmd_timer(adapter);
 
- rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
+ ven_rsi_dbg(INFO_ZONE, "Received Board Version Number: %x\n",
  (regout_val & 0xff));
 
  if ((hif_ops->master_reg_write(adapter,
        SWBL_REGOUT,
        (REGOUT_INVALID | REGOUT_INVALID << 8),
        2)) < 0) {
- rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: REGOUT writing failed..\n", __func__);
  goto fail;
  }
  mdelay(1);
@@ -962,7 +1189,7 @@ int rsi_load_9113_firmware(struct rsi_hw *adapter)
 
  adapter->flash_capacity = read_flash_capacity(adapter);
  if (adapter->flash_capacity <= 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to read flash size from EEPROM\n",
  __func__);
  goto fail;
@@ -970,24 +1197,24 @@ int rsi_load_9113_firmware(struct rsi_hw *adapter)
 
  metadata_p = &metadata_flash_content[adapter->priv->coex_mode];
 
- rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name);
+ ven_rsi_dbg(INIT_ZONE, "%s: loading file %s\n", __func__, metadata_p->name);
 
  if ((request_firmware(&fw_entry, metadata_p->name,
       adapter->device)) < 0) {
- rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to open file %s\n",
  __func__, metadata_p->name);
  goto fail;
  }
  flash_content = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
  if (!flash_content) {
- rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to copy firmware\n", __func__);
  goto fail;
  }
  content_size = fw_entry->size;
- rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
+ ven_rsi_dbg(INFO_ZONE, "FW Length = %d bytes\n", content_size);
 
  if (bl_write_header(adapter, flash_content, content_size)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: RPS Image header loading failed\n",
  __func__);
  goto fail;
@@ -996,11 +1223,11 @@ int rsi_load_9113_firmware(struct rsi_hw *adapter)
  bl_start_cmd_timer(adapter, BL_CMD_TIMEOUT);
  if (bl_write_cmd(adapter, CHECK_CRC, CMD_PASS, &tmp_regout_val) < 0) {
  bl_stop_cmd_timer(adapter);
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: CHECK_CRC Command writing failed..\n",
  __func__);
  if ((tmp_regout_val & 0xff) == CMD_FAIL) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "CRC Fail.. Proceeding to Upgrade mode\n");
  goto fw_upgrade;
  }
@@ -1016,7 +1243,7 @@ load_image_cmd:
     LOADING_INITIATED,
     "LOAD_HOSTED_FW")) < 0)
  goto fail;
- rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
+ ven_rsi_dbg(INFO_ZONE, "Load Image command passed..\n");
  goto success;
 
 fw_upgrade:
@@ -1026,10 +1253,10 @@ fw_upgrade:
  if (bl_cmd(adapter, BURN_HOSTED_FW, SEND_RPS_FILE, "FW_UPGRADE") < 0)
  goto fail;
 
- rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
+ ven_rsi_dbg(INFO_ZONE, "Burn Command Pass.. Upgrading the firmware\n");
 
  if (auto_fw_upgrade(adapter, flash_content, content_size) == 0) {
- rsi_dbg(ERR_ZONE, "***** Auto firmware successful *****\n");
+ ven_rsi_dbg(ERR_ZONE, "***** Auto firmware successful *****\n");
  goto load_image_cmd;
  }
 
@@ -1039,14 +1266,14 @@ fw_upgrade:
 
  /* Not required for current flash mode */
 #if 0
- rsi_dbg(INFO_ZONE, "Starting Flash Verification Process\n");
+ ven_rsi_dbg(INFO_ZONE, "Starting Flash Verification Process\n");
 
  if ((verify_flash_content(adapter,
   flash_content,
   EEPROM_DATA_SIZE,
   0,
   EEPROM_READ_MODE)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: FLASHING SBL failed in Calib VERIFICATION phase\n",
  __func__);
  goto fail;
@@ -1056,15 +1283,15 @@ fw_upgrade:
   (content_size - BL_HEADER),
   EEPROM_DATA_SIZE,
   MASTER_READ_MODE)) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s:FLASHING SBL failed in SBL VERIFICATION phase\n",
  __func__);
  goto fail;
  }
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "Flash Verification Process Completed Successfully\n");
 #endif
- rsi_dbg(INFO_ZONE, "SWBL FLASHING THROUGH SWBL PASSED...\n");
+ ven_rsi_dbg(INFO_ZONE, "SWBL FLASHING THROUGH SWBL PASSED...\n");
 
 success:
  kfree(flash_content);
@@ -1085,12 +1312,17 @@ fail:
  */
 int rsi_hal_device_init(struct rsi_hw *adapter)
 {
-
-#ifdef CONFIG_VEN_RSI_HCI
- adapter->priv->coex_mode = 4;
+#if defined(CONFIG_VEN_RSI_HCI)
+ adapter->priv->coex_mode = 2;
+#elif defined(CONFIG_VEN_RSI_COEX)
+ adapter->priv->coex_mode = 2;
 #else
  adapter->priv->coex_mode = 1;
 #endif
+
+#ifdef CONFIG_RSI_BT_LE
+ adapter->priv->coex_mode = 2;
+#endif
  adapter->device_model = RSI_DEV_9113;
  switch (adapter->device_model) {
  case RSI_DEV_9110:
@@ -1098,7 +1330,7 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
  break;
  case RSI_DEV_9113:
  if (rsi_load_9113_firmware(adapter)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to load TA instructions\n",
  __func__);
  return -1;
@@ -1112,8 +1344,11 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
  }
  adapter->common_hal_fsm = COMMAN_HAL_WAIT_FOR_CARD_READY;
 
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
+ adapter->priv->bt_fsm_state = BT_DEVICE_NOT_READY;
+#endif
+
  return 0;
 }
 EXPORT_SYMBOL_GPL(rsi_hal_device_init);
 
-
diff --git a/ubuntu/rsi/rsi_91x_hci.c b/ubuntu/rsi/rsi_91x_hci.c
index e4d9daa..773e216 100644
--- a/ubuntu/rsi/rsi_91x_hci.c
+++ b/ubuntu/rsi/rsi_91x_hci.c
@@ -20,8 +20,8 @@
 #include "rsi_hal.h"
 
 #define RSI_BT_GENL_FAMILY "RSI-BTgenl"
-#define RSI_USER_A_MAX (__RSI_USER_A_MAX - 1)
-#define RSI_VERSION_NR 1
+#define RSI_USER_A_MAX (__RSI_USER_A_MAX - 1)
+#define RSI_VERSION_NR 1
 
 static struct nla_policy bt_genl_policy[RSI_USER_A_MAX + 1] = {
  [RSI_USER_A_MSG] = { .type = NLA_NUL_STRING },
@@ -55,10 +55,10 @@ static struct genl_cb *global_gcb;
  */
 static int rsi_hci_open(struct hci_dev *hdev)
 {
- rsi_dbg(ERR_ZONE, "RSI HCI DEVICE \"%s\" open\n", hdev->name);
+ ven_rsi_dbg(ERR_ZONE, "RSI HCI DEVICE \"%s\" open\n", hdev->name);
 
  if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
- rsi_dbg(ERR_ZONE, "%s: device `%s' already running\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: device `%s' already running\n",
  __func__, hdev->name);
 
  return 0;
@@ -73,10 +73,10 @@ static int rsi_hci_open(struct hci_dev *hdev)
  */
 static int rsi_hci_close(struct hci_dev *hdev)
 {
- rsi_dbg(ERR_ZONE, "RSI HCI DEVICE \"%s\" closed\n", hdev->name);
+ ven_rsi_dbg(ERR_ZONE, "RSI HCI DEVICE \"%s\" closed\n", hdev->name);
 
  if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
- rsi_dbg(ERR_ZONE, "%s: device `%s' not running\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: device `%s' not running\n",
  __func__, hdev->name);
 
  return 0;
@@ -96,7 +96,7 @@ static int rsi_hci_flush(struct hci_dev *hdev)
  if (!(h_adapter = hci_get_drvdata(hdev)))
  return -EFAULT;
 
- rsi_dbg(ERR_ZONE, "RSI `%s' flush\n", hdev->name);
+ ven_rsi_dbg(ERR_ZONE, "RSI `%s' flush\n", hdev->name);
 
  return 0;
 }
@@ -124,7 +124,7 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
  int status = 0;
 
  if (skb->len <= 0) {
- rsi_dbg(ERR_ZONE, "Zero length packet\n");
+ ven_rsi_dbg(ERR_ZONE, "Zero length packet\n");
  //hdev->sta.err_tx++;
  status = -EINVAL;
  goto fail;
@@ -136,8 +136,8 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
  goto fail;
  }
 
- if (h_adapter->fsm_state != BT_DEVICE_READY) {
- rsi_dbg(ERR_ZONE, "BT Device not ready\n");
+ if (h_adapter->priv->bt_fsm_state != BT_DEVICE_READY) {
+ ven_rsi_dbg(ERR_ZONE, "BT Device not ready\n");
  status = -ENODEV;
  goto fail;
  }
@@ -173,7 +173,7 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
 
  new_skb = dev_alloc_skb(new_len);
  if (!new_skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -188,7 +188,7 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
         rsi_hex_dump(DATA_RX_ZONE, "TX BT Pkt", skb->data, skb->len);
 
 #ifdef CONFIG_VEN_RSI_COEX
- rsi_coex_send_pkt(h_adapter->priv, skb, RSI_BT_Q);
+ rsi_coex_send_pkt(h_adapter->priv, skb, BT_Q);
 #else
         rsi_send_bt_pkt(h_adapter->priv, skb);
 #endif
@@ -198,43 +198,72 @@ fail:
  return status;
 }
 
+void rsi_hci_scheduler_thread(struct rsi_common *common)
+{
+ struct rsi_hw *adapter = common->priv;
+ int status = 0;
+
+ do {
+ status = adapter->check_intr_status_reg(adapter);
+ if (adapter->isr_pending)
+ adapter->isr_pending = 0;
+ msleep(20);
+
+ } while (atomic_read(&common->hci_thread.thread_done) == 0);
+ complete_and_exit(&common->hci_thread.completion, 0);
+}
+
 int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 {
+ struct rsi_hci_adapter *h_adapter =
+ (struct rsi_hci_adapter *)common->hci_adapter;
  struct sk_buff *skb = NULL;
-        struct rsi_hci_adapter *h_adapter;
  struct hci_dev *hdev = NULL;
  int pkt_len = rsi_get_length(pkt, 0);
  u8 queue_no = rsi_get_queueno(pkt, 0);
 
- rsi_dbg(INFO_ZONE, "qno:%d, len:%d, fsm:%d",
- queue_no, pkt_len, common->fsm_state);
-
- if (pkt[14] == BT_CARD_READY_IND) {
- rsi_dbg(INIT_ZONE, "%s: ===> BT Card Ready Received <===\n",
+ if ((common->bt_fsm_state == BT_DEVICE_NOT_READY) &&
+    (pkt[14] == BT_CARD_READY_IND)) {
+ ven_rsi_dbg(INIT_ZONE, "%s: ===> BT Card Ready Received <===\n",
  __func__);
 
- rsi_dbg(INFO_ZONE, "Attaching HCI module\n");
+ ven_rsi_dbg(INFO_ZONE, "Attaching HCI module\n");
 
  if (rsi_hci_attach(common)) {
- rsi_dbg(ERR_ZONE, "Failed to attach HCI module\n");
+ ven_rsi_dbg(ERR_ZONE, "Failed to attach HCI module\n");
  return 0;
  }
 
-#ifdef CONFIG_VEN_RSI_COEX
- if (rsi_coex_init(common)) {
- rsi_dbg(ERR_ZONE, "Failed to init COEX module\n");
- goto err;
+ /* TODO: Work aroud for Dell; move this to module_param */
+#if (defined(CONFIG_DELL_BOARD) &&  defined(CONFIG_VEN_RSI_HCI))
+ if (rsi_set_antenna(common, ANTENNA_SEL_UFL)) {
+ ven_rsi_dbg(ERR_ZONE,
+ "%s: Failed to configure external antenna\n",
+ __func__);
+ } else
+ ven_rsi_dbg(INFO_ZONE, "***** UFL antenna is configured\n");
+
+#endif
+
+#if (defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX))
+#if defined(CONFIG_DELL_BOARD)
+ if (common->priv->rsi_host_intf == RSI_HOST_INTF_SDIO) {
+ rsi_init_event(&common->hci_thread.event);
+ if (rsi_create_kthread(common,
+ &common->hci_thread,
+ rsi_hci_scheduler_thread,
+ "hci-Thread")) {
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to init hci thrd\n",
+ __func__);
  }
-#endif
-                h_adapter = (struct rsi_hci_adapter *)common->hci_adapter;
- h_adapter->fsm_state = BT_DEVICE_READY;
+ }
+#endif
+#endif
  return 0;
  }
-                
-        h_adapter = (struct rsi_hci_adapter *)common->hci_adapter;
 
- if (h_adapter->fsm_state != BT_DEVICE_READY) {
- rsi_dbg(INFO_ZONE, "BT Device not ready\n");
+ if (common->bt_fsm_state != BT_DEVICE_READY) {
+ ven_rsi_dbg(INFO_ZONE, "BT Device not ready\n");
  return 0;
  }
 
@@ -243,16 +272,13 @@ int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 
  switch (msg_type) {
  case RESULT_CONFIRM:
- rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
- return 0;
- case BT_PER:
- rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ ven_rsi_dbg(MGMT_RX_ZONE, "BT Result Confirm\n");
  return 0;
  case BT_BER:
- rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ ven_rsi_dbg(MGMT_RX_ZONE, "BT Ber\n");
  return 0;
  case BT_CW:
- rsi_dbg(MGMT_RX_ZONE, "%s: BT Result Confirm\n", __func__);
+ ven_rsi_dbg(MGMT_RX_ZONE, "BT CW\n");
  return 0;
  default:
  break;
@@ -261,7 +287,7 @@ int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 
  skb = dev_alloc_skb(pkt_len);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n", __func__);
  return -ENOMEM;
  }
         hdev = h_adapter->hdev;
@@ -311,13 +337,13 @@ int rsi_genl_recv(struct sk_buff *skb, struct genl_info *info)
  if (na) {
  data = (u8 *)nla_data(na);
  if (!data) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: no data recevied on family `%s'\n",
  __func__, gcb->gc_name);
  goto err;
  }
  } else {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: netlink attr is NULL on family `%s'\n",
  __func__, gcb->gc_name);
  goto err;
@@ -330,14 +356,14 @@ int rsi_genl_recv(struct sk_buff *skb, struct genl_info *info)
 
  data += 16;
 
- rsi_dbg(ERR_ZONE, "%s: len %x pkt_type %x\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: len %x pkt_type %x\n",
  __func__, len, pkttype);
 
  rsi_hex_dump (DATA_RX_ZONE, "BT TX data", data, len);
 
  skb = dev_alloc_skb(len + REQUIRED_HEADROOM_FOR_BT_HAL);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to alloc skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -355,7 +381,7 @@ int rsi_genl_recv(struct sk_buff *skb, struct genl_info *info)
 #endif
 
 err:
- rsi_dbg(ERR_ZONE, "%s: error(%d) occured\n", __func__, rc);
+ ven_rsi_dbg(ERR_ZONE, "%s: error(%d) occured\n", __func__, rc);
  return rc;
 }
 
@@ -374,12 +400,11 @@ int rsi_hci_attach(struct rsi_common *common)
  struct hci_dev *hdev;
  int status = 0;
 
- rsi_dbg (ERR_ZONE, "%s: In alloc HCI adapter\n", __func__);
  /* Allocate HCI adapter */
  /* TODO: Check GFP_ATOMIC */
  h_adapter = kzalloc(sizeof (*h_adapter), GFP_KERNEL);
  if (!h_adapter) {
- rsi_dbg (ERR_ZONE, "%s: Failed to alloc HCI adapter\n", __func__);
+ ven_rsi_dbg (ERR_ZONE, "Failed to alloc HCI adapter\n");
  return -ENOMEM;
  }
  h_adapter->priv = common;
@@ -387,7 +412,7 @@ int rsi_hci_attach(struct rsi_common *common)
  /* Create HCI Interface */
  hdev = hci_alloc_dev();
  if (!hdev) {
- rsi_dbg (ERR_ZONE, "%s: Failed to alloc HCI device\n", __func__);
+ ven_rsi_dbg (ERR_ZONE, "Failed to alloc HCI device\n");
  goto err;
  }
  h_adapter->hdev = hdev;
@@ -412,22 +437,22 @@ int rsi_hci_attach(struct rsi_common *common)
         /* Initialize TX queue */
  skb_queue_head_init(&h_adapter->hci_tx_queue);
  common->hci_adapter = (void *)h_adapter;
- rsi_dbg (ERR_ZONE, "%s: In alloc HCI adapter\n", __func__);
+ ven_rsi_dbg (ERR_ZONE, "%s: In alloc HCI adapter\n", __func__);
  status = hci_register_dev(hdev);
  if (status < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: HCI registration failed with errcode %d\n",
  __func__, status);
  goto err;
  }
- rsi_dbg(INIT_ZONE, "HCI Interface Created with name \'%s\'\n",
+ ven_rsi_dbg(INIT_ZONE, "HCI Interface Created with name \'%s\'\n",
  hdev->name);
 
  /* Register for general netlink operations */
  /* TODO: Check GFP_ATOMIC */
  gcb = kzalloc(sizeof(*gcb), GFP_KERNEL);
  if (!gcb) {
- rsi_dbg (ERR_ZONE, "%s: Failed to alloc genl control block\n",
+ ven_rsi_dbg (ERR_ZONE, "%s: Failed to alloc genl control block\n",
  __func__);
  goto err;
  }
@@ -442,7 +467,7 @@ int rsi_hci_attach(struct rsi_common *common)
  gcb->gc_name = RSI_BT_GENL_FAMILY;
  gcb->gc_pid = gcb->gc_done = 0;
 
- rsi_dbg(INIT_ZONE, "genl-register: nl_family `%s'\n", gcb->gc_name);
+ ven_rsi_dbg(INIT_ZONE, "genl-register: nl_family `%s'\n", gcb->gc_name);
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
  gcb->gc_family->ops = gcb->gc_ops;
@@ -450,22 +475,21 @@ int rsi_hci_attach(struct rsi_common *common)
 #endif
 
  if (genl_register_family(gcb->gc_family)) {
- rsi_dbg(ERR_ZONE, "%s: genl_register_family failed\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: genl_register_family failed\n",
  __func__);
  goto err;
  }
 
 #if LINUX_VERSION_CODE <= KERNEL_VERSION (3, 12, 34)
  if (genl_register_ops(gcb->gc_family, gcb->gc_ops)) {
- rsi_dbg(ERR_ZONE, "%s: genl_register_ops failed\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: genl_register_ops failed\n", __func__);
  genl_unregister_family(family);
  goto err;
  }
 #endif
  gcb->gc_done = 1;
-
-        //h_adapter->fsm_state = BT_DEVICE_READY;
- rsi_dbg(ERR_ZONE, " HCI module init done...\n");
+ common->bt_fsm_state = BT_DEVICE_READY;
+ ven_rsi_dbg(ERR_ZONE, " HCI module init done...\n");
 
  return 0;
 
@@ -486,6 +510,7 @@ err:
 
  return -EINVAL;
 }
+EXPORT_SYMBOL_GPL(rsi_hci_attach);
 
 /**
  * rsi_hci_attach () - This function initializes HCI interface
@@ -501,7 +526,7 @@ void rsi_hci_detach(struct rsi_common *common)
  struct hci_dev *hdev;
  struct genl_cb *gcb;
 
- rsi_dbg(INFO_ZONE, "Detaching HCI...\n");
+ ven_rsi_dbg(INFO_ZONE, "Detaching HCI...\n");
 
  if (!h_adapter)
  return;
@@ -527,6 +552,5 @@ void rsi_hci_detach(struct rsi_common *common)
 
  return;
 }
-EXPORT_SYMBOL_GPL(rsi_hci_attach);
 EXPORT_SYMBOL_GPL(rsi_hci_detach);
 
diff --git a/ubuntu/rsi/rsi_91x_mac80211.c b/ubuntu/rsi/rsi_91x_mac80211.c
index 000f4c8..1d18b10 100644
--- a/ubuntu/rsi/rsi_91x_mac80211.c
+++ b/ubuntu/rsi/rsi_91x_mac80211.c
@@ -189,14 +189,65 @@ static void rsi_register_rates_channels(struct rsi_hw *adapter, int band)
  /* sbands->ht_cap.mcs.rx_highest = 0x82; */
 }
 
+static void rsi_set_min_rate(struct ieee80211_hw *hw,
+     struct ieee80211_sta *sta,
+     struct rsi_common *common)
+{
+ struct ieee80211_vif *vif = common->priv->vifs[0];
+ u8 band = hw->conf.chandef.chan->band;
+ u8 ii;
+ u32 rate_bitmap;
+ bool matched = false;
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ common->bitrate_mask[band] = common->fixedrate_mask[band];
+ rate_bitmap = common->bitrate_mask[band];
+ } else {
+ common->bitrate_mask[band] = sta->supp_rates[band];
+ rate_bitmap = (common->fixedrate_mask[band] &
+       sta->supp_rates[band]);
+ }
+ ven_rsi_dbg(INFO_ZONE, "bitrate_mask = %x\n", common->bitrate_mask[band]);
+ ven_rsi_dbg(INFO_ZONE, "rate_bitmap = %x\n", rate_bitmap);
+
+ if (rate_bitmap & 0xfff) {
+ /* Find out the min rate */
+ for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {
+ if (rate_bitmap & BIT(ii)) {
+ common->min_rate = rsi_rates[ii].hw_value;
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ if (vif->type == NL80211_IFTYPE_STATION)
+ common->vif_info[0].is_ht = sta->ht_cap.ht_supported;
+
+ if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) {
+ for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) {
+ if ((rate_bitmap >> 12) & BIT(ii)) {
+ common->min_rate = rsi_mcsrates[ii];
+ matched = true;
+ break;
+ }
+ }
+ }
+
+ if (!matched)
+ common->min_rate = 0xffff;
+
+ ven_rsi_dbg(INFO_ZONE, "Min Rate = %d\n", common->min_rate);
+}
+
 /**
- * rsi_mac80211_detach() - This function is used to de-initialize the
+ * ven_rsi_mac80211_detach() - This function is used to de-initialize the
  *   Mac80211 stack.
  * @adapter: Pointer to the adapter structure.
  *
  * Return: None.
  */
-void rsi_mac80211_detach(struct rsi_hw *adapter)
+void ven_rsi_mac80211_detach(struct rsi_hw *adapter)
 {
  struct ieee80211_hw *hw = adapter->hw;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
@@ -205,12 +256,13 @@ void rsi_mac80211_detach(struct rsi_hw *adapter)
  int band;
 #endif
 
- rsi_dbg(INFO_ZONE, "Detach mac80211...\n");
+ ven_rsi_dbg(INFO_ZONE, "Detach mac80211...\n");
 
  if (hw) {
  ieee80211_stop_queues(hw);
  ieee80211_unregister_hw(hw);
  ieee80211_free_hw(hw);
+ adapter->hw = NULL;
  }
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
@@ -229,7 +281,7 @@ void rsi_mac80211_detach(struct rsi_hw *adapter)
  kfree(adapter->dfsentry);
 #endif
 }
-EXPORT_SYMBOL_GPL(rsi_mac80211_detach);
+EXPORT_SYMBOL_GPL(ven_rsi_mac80211_detach);
 
 /**
  * rsi_indicate_tx_status() - This function indicates the transmit status.
@@ -245,6 +297,11 @@ void rsi_indicate_tx_status(struct rsi_hw *adapter,
 {
  struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
+ if (!adapter->hw) {
+ ven_rsi_dbg(ERR_ZONE, "##### No Hardware #####\n");
+ return;
+ }
+
  memset(info->driver_data, 0, IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
 
  if (!status)
@@ -269,6 +326,12 @@ static void rsi_mac80211_tx(struct ieee80211_hw *hw,
 {
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
+ struct ieee80211_hdr *wlh = (struct ieee80211_hdr *)skb->data;
+
+ if (ieee80211_is_beacon(wlh->frame_control)) {
+ ieee80211_free_txskb(common->priv->hw, skb);
+ return;
+ }
 
 #ifndef CONFIG_VEN_RSI_HCI
  rsi_core_xmit(common, skb);
@@ -292,7 +355,7 @@ static int rsi_mac80211_start(struct ieee80211_hw *hw)
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
 
- rsi_dbg(ERR_ZONE, "===> Interface UP <===\n");
+ ven_rsi_dbg(ERR_ZONE, "===> Interface UP <===\n");
  mutex_lock(&common->mutex);
 
  common->iface_down = false;
@@ -315,7 +378,7 @@ static void rsi_mac80211_stop(struct ieee80211_hw *hw)
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
 
- rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
+ ven_rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
 
  mutex_lock(&common->mutex);
 
@@ -341,30 +404,47 @@ static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
 {
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
+ enum opmode intf_mode;
  int ret = 0;
 
- rsi_dbg(INFO_ZONE, "Add Interface Called\n");
+ ven_rsi_dbg(INFO_ZONE, "Add Interface Called\n");
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
  vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
 #endif
 
+ if ((vif->type != NL80211_IFTYPE_STATION) &&
+    (vif->type != NL80211_IFTYPE_AP))
+ return -1;
+
  mutex_lock(&common->mutex);
 
+ /* Not supporting concurrent mode now */
+ if (adapter->sc_nvifs > 0)
+ return -1;
+
+ adapter->vifs[adapter->sc_nvifs++] = vif;
+
  switch (vif->type) {
  case NL80211_IFTYPE_STATION:
- if (!adapter->sc_nvifs) {
- ++adapter->sc_nvifs;
- adapter->vifs[0] = vif;
- ret = rsi_set_vap_capabilities(common,
-       STA_OPMODE,
-       VAP_ADD);
- }
+ intf_mode = STA_OPMODE;
+ break;
+ case NL80211_IFTYPE_AP:
+ intf_mode = AP_OPMODE;
  break;
  default:
- rsi_dbg(ERR_ZONE,
- "%s: Interface type %d not supported\n",
- __func__, vif->type);
+ return -1;
+ }
+ ret = rsi_set_vap_capabilities(common, intf_mode, VAP_ADD);
+ if (ret) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to send VAP capabilities\n");
+ return ret;
+ }
+
+ if (vif->type == NL80211_IFTYPE_AP) {
+ common->bc_mc_seqno = 1;
+ rsi_send_rx_filter_frame(common, DISALLOW_BEACONS);
+ rsi_set_min_rate(hw, NULL, common);
  }
 
  mutex_unlock(&common->mutex);
@@ -386,13 +466,14 @@ static void rsi_mac80211_remove_interface(struct ieee80211_hw *hw,
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
 
- rsi_dbg(INFO_ZONE, "Remove Interface Called\n");
+ ven_rsi_dbg(INFO_ZONE, "Remove Interface Called\n");
  mutex_lock(&common->mutex);
 
- if (vif->type == NL80211_IFTYPE_STATION) {
- adapter->sc_nvifs--;
+ adapter->sc_nvifs--;
+ if (vif->type == NL80211_IFTYPE_STATION)
  rsi_set_vap_capabilities(common, STA_OPMODE, VAP_DELETE);
- }
+ else if (vif->type == NL80211_IFTYPE_AP)
+ rsi_set_vap_capabilities(common, AP_OPMODE, VAP_DELETE);
 
  if (!memcmp(adapter->vifs[0], vif, sizeof(struct ieee80211_vif)))
  adapter->vifs[0] = NULL;
@@ -415,33 +496,47 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
  struct ieee80211_channel *curchan = hw->conf.chandef.chan;
  u16 channel = curchan->hw_value;
  struct ieee80211_bss_conf *bss = NULL;
+ struct ieee80211_vif *vif = adapter->vifs[0];
 
  if (adapter->sc_nvifs <= 0) {
- rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
  return -EINVAL;
  }
- bss = &adapter->vifs[0]->bss_conf;
+ bss = &vif->bss_conf;
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Set channel: %d MHz type: %d channel_no %d\n",
  __func__, curchan->center_freq,
  curchan->flags, channel);
 
+ if (vif->type == NL80211_IFTYPE_AP) {
+ ven_rsi_dbg(INFO_ZONE, "Configure channel %d for AP\n", channel);
+ if (rsi_band_check(common)) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to set band\n");
+ return -EINVAL;
+ }
+ if (rsi_set_channel(common, curchan)) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to set the channel\n");
+ return -EINVAL;
+ }
+ common->ap_channel = curchan;
+ return 0;
+ }
  common->mac80211_cur_channel = channel;
  if (bss->assoc) {
- rsi_dbg(INFO_ZONE, "%s: connected\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: connected\n", __func__);
 
  if (common->bgscan_en)
  return 0;
 
  if (!common->hw_data_qs_blocked &&
     (rsi_get_connected_channel(adapter) != channel)) {
- rsi_dbg(INFO_ZONE, "blk data q %d\n", channel);
+ ven_rsi_dbg(INFO_ZONE, "blk data q %d\n", channel);
  if (!rsi_send_block_unblock_frame(common, true))
  common->hw_data_qs_blocked = true;
  }
  } else {
- rsi_dbg(INFO_ZONE, "assoc status:%d channel:%d\n",
+ ven_rsi_dbg(INFO_ZONE, "assoc status:%d channel:%d\n",
  bss->assoc, channel);
  }
 
@@ -452,13 +547,13 @@ static int rsi_channel_change(struct ieee80211_hw *hw)
  if (bss->assoc) {
  if (common->hw_data_qs_blocked &&
     (rsi_get_connected_channel(adapter) == channel)) {
- rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+ ven_rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
  if (!rsi_send_block_unblock_frame(common, false))
  common->hw_data_qs_blocked = false;
  }
  } else {
  if (common->hw_data_qs_blocked) {
- rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
+ ven_rsi_dbg(INFO_ZONE, "unblk data q %d\n", channel);
  if (!rsi_send_block_unblock_frame(common, false))
  common->hw_data_qs_blocked = false;
  }
@@ -481,11 +576,11 @@ static int rsi_config_power(struct ieee80211_hw *hw)
  int status;
 
  if (adapter->sc_nvifs <= 0) {
- rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: No virtual interface found\n", __func__);
  return -EINVAL;
  }
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Set tx power: %d dBM\n", __func__, conf->power_level);
 
  if (conf->power_level == common->tx_power)
@@ -512,6 +607,7 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
 {
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
+ struct ieee80211_vif *vif = adapter->vifs[0];
  struct ieee80211_conf *conf = &hw->conf;
  int status = -EOPNOTSUPP;
 
@@ -523,14 +619,14 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
 
  /* listen interval */
  if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "listen_int = %d\n", conf->listen_interval);
  adapter->ps_info.num_bcns_per_lis_int = conf->listen_interval;
  }
 
  /* tx power */
  if (changed & IEEE80211_CONF_CHANGE_POWER) {
- rsi_dbg(INFO_ZONE, "%s: Configuring Power\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Configuring Power\n", __func__);
  status = rsi_config_power(hw);
  }
 
@@ -540,7 +636,8 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
  }
 
  /* Power save parameters */
- if (changed & IEEE80211_CONF_CHANGE_PS) {
+ if ((changed & IEEE80211_CONF_CHANGE_PS) &&
+    (vif->type == NL80211_IFTYPE_STATION)) {
  unsigned long flags;
 
  spin_lock_irqsave(&adapter->ps_lock, flags);
@@ -553,9 +650,9 @@ static int rsi_mac80211_config(struct ieee80211_hw *hw,
 
  /* RTS threshold */
  if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
- rsi_dbg(INFO_ZONE,"RTS threshold\n");
+ ven_rsi_dbg(INFO_ZONE,"RTS threshold\n");
  if ((common->rts_threshold) <= IEEE80211_MAX_RTS_THRESHOLD) {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Sending vap updates....\n", __func__);
  status = rsi_send_vap_dynamic_update(common);
  }
@@ -608,6 +705,27 @@ void rsi_resume_conn_channel(struct rsi_hw *adapter)
  mutex_unlock(&common->mutex);
 }
 
+static void rsi_update_beacon(struct ieee80211_hw *hw,
+      struct ieee80211_vif *vif)
+{
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_mutable_offsets offs = {};
+ struct sk_buff *bcn;
+
+ bcn = ieee80211_beacon_get_template(hw, vif, &offs);
+ if (!bcn) {
+ ven_rsi_dbg(ERR_ZONE,
+ "failed to get beacon template from mac80211\n");
+ return;
+ }
+ memcpy(common->beacon_frame, bcn->data, bcn->len);
+ common->beacon_frame_len = bcn->len;
+
+ rsi_hex_dump(INFO_ZONE, "mac80211: Beacon",
+     common->beacon_frame, common->beacon_frame_len);
+}
+
 /**
  * rsi_mac80211_bss_info_changed() - This function is a handler for config
  *     requests related to BSS parameters that
@@ -629,65 +747,85 @@ static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
  struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
  u16 rx_filter_word = 0;
 
- rsi_dbg(INFO_ZONE, "%s: BSS status changed\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: BSS status changed\n", __func__);
+
  mutex_lock(&common->mutex);
- if (changed & BSS_CHANGED_ASSOC) {
- rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n",
+
+ if ((changed & BSS_CHANGED_ASSOC) &&
+    (vif->type == NL80211_IFTYPE_STATION)) {
+ ven_rsi_dbg(INFO_ZONE, "%s: Changed Association status: %d\n",
  __func__, bss_conf->assoc);
- rsi_hex_dump(INFO_ZONE, "BSSID: ", bss->bssid, ETH_ALEN);
  bss->assoc = bss_conf->assoc;
- if (bss_conf->assoc) {
+ if (bss->assoc) {
  /* Send the RX filter frame */
  rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
   ALLOW_CTRL_ASSOC_PEER |
-  ALLOW_MGMT_ASSOC_PEER);// |
-  //DISALLOW_BEACONS);
+  ALLOW_MGMT_ASSOC_PEER |
+#ifdef RSI_HW_CONN_MONITOR
+  DISALLOW_BEACONS |
+#endif
+ 0);
  rsi_send_rx_filter_frame(common, rx_filter_word);
  }
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "assoc_status=%d, qos=%d, aid=%d\n",
  bss->assoc, bss->qos, bss->aid);
- rsi_dbg(INFO_ZONE,
- "bssid=%02x:%02x:%02x:%02x:%02x:%02x",
- bss->bssid[0], bss->bssid[1], bss->bssid[2],
- bss->bssid[3], bss->bssid[4], bss->bssid[5]);
- rsi_inform_bss_status(common,
-      bss->assoc,
-      bss->bssid,
-      bss->qos,
-      bss->aid);
+ ven_rsi_dbg(INFO_ZONE,
+ "bssid=%02x:%02x:%02x:%02x:%02x:%02x",
+ bss->bssid[0], bss->bssid[1], bss->bssid[2],
+ bss->bssid[3], bss->bssid[4], bss->bssid[5]);
+
+ /* Send peer notify to device */
+ ven_rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
+ rsi_inform_bss_status(common, STA_OPMODE, bss->assoc,
+      bss->bssid, bss->qos, bss->aid, 0);
 
  adapter->ps_info.listen_interval =
- bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
+ bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
  adapter->ps_info.deep_sleep_wakeup_period = bss->beacon_int;
 
  /* If UAPSD is updated send ps params */
  if (common->uapsd_bitmap) {
- rsi_dbg(INFO_ZONE, "Configuring UAPSD\n");
+ ven_rsi_dbg(INFO_ZONE, "Configuring UAPSD\n");
  rsi_conf_uapsd(adapter);
  }
  }
 
- if (changed & BSS_CHANGED_CQM) {
- rsi_dbg(INFO_ZONE, "%s: Changed CQM\n", __func__);
+ if ((vif->type == NL80211_IFTYPE_STATION) &&
+    changed & BSS_CHANGED_CQM) {
+ ven_rsi_dbg(INFO_ZONE, "%s: Changed CQM\n", __func__);
  common->cqm_info.last_cqm_event_rssi = 0;
  common->cqm_info.rssi_thold = bss_conf->cqm_rssi_thold;
  common->cqm_info.rssi_hyst = bss_conf->cqm_rssi_hyst;
- rsi_dbg(INFO_ZONE, "RSSI throld & hysteresis are: %d %d\n",
+ ven_rsi_dbg(INFO_ZONE, "RSSI throld & hysteresis are: %d %d\n",
  common->cqm_info.rssi_thold,
  common->cqm_info.rssi_hyst);
  }
 
  if (changed & BSS_CHANGED_TXPOWER) {
- rsi_dbg(INFO_ZONE, "%s: Changed TX power: %d\n",
+ ven_rsi_dbg(INFO_ZONE, "%s: Changed TX power: %d\n",
  __func__, bss_conf->txpower);
  }
 
  if (changed & BSS_CHANGED_BEACON_INT) {
- rsi_dbg(INFO_ZONE, "%s: Changed Beacon interval: %d\n",
+ ven_rsi_dbg(INFO_ZONE, "%s: Changed Beacon interval: %d\n",
  __func__, bss_conf->beacon_int);
  adapter->ps_info.listen_interval =
- bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
+ bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
+ }
+
+ if ((changed & BSS_CHANGED_BEACON) &&
+    (vif->type == NL80211_IFTYPE_AP)) {
+ ven_rsi_dbg(INFO_ZONE, "%s: Changed Beacon\n", __func__);
+ rsi_update_beacon(hw, vif);
+ }
+
+ if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
+    (vif->type == NL80211_IFTYPE_AP)) {
+ if (bss->enable_beacon)
+ ven_rsi_dbg(INFO_ZONE, "===> BEACON ENABLED <===\n");
+ else
+ ven_rsi_dbg(INFO_ZONE, "===> BEACON DISABLED <===\n");
  }
 
  mutex_unlock(&common->mutex);
@@ -741,7 +879,7 @@ static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw,
  if (queue >= IEEE80211_NUM_ACS)
  return 0;
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "[Conf] queue:%d, aifs:%d, cwmin:%d cwmax:%d, txop:%d uapsd:%d\n",
  queue, params->aifs, params->cw_min, params->cw_max,
  params->txop, params->uapsd);
@@ -769,11 +907,11 @@ static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw,
  memcpy(&common->edca_params[idx],
        params,
        sizeof(struct ieee80211_tx_queue_params));
- mutex_unlock(&common->mutex);
 
  if (params->uapsd)
  common->uapsd_bitmap |= idx;
 
+ mutex_unlock(&common->mutex);
  return 0;
 }
 
@@ -787,19 +925,32 @@ static int rsi_mac80211_conf_tx(struct ieee80211_hw *hw,
  */
 static int rsi_hal_key_config(struct ieee80211_hw *hw,
       struct ieee80211_vif *vif,
-      struct ieee80211_key_conf *key)
+      struct ieee80211_key_conf *key,
+      struct ieee80211_sta *sta)
 {
  struct rsi_hw *adapter = hw->priv;
  int status;
  u8 key_type;
+ s16 sta_id;
 
  if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
  key_type = RSI_PAIRWISE_KEY;
  else
  key_type = RSI_GROUP_KEY;
 
- rsi_dbg(ERR_ZONE, "%s: Cipher 0x%x key_type: %d key_len: %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Cipher 0x%x key_type: %d key_len: %d\n",
  __func__, key->cipher, key_type, key->keylen);
+ ven_rsi_dbg(INFO_ZONE, "hw_key_idx %d\n", key->hw_key_idx);
+
+ if (sta && vif->type == NL80211_IFTYPE_AP) {
+ struct rsi_sta *rsta = rsi_find_sta(adapter->priv, sta->addr);
+
+ if (rsta)
+ sta_id = rsta->sta_id;
+ else
+ return -EINVAL;
+ } else
+ sta_id = 0;
 
  if ((key->cipher == WLAN_CIPHER_SUITE_WEP104) ||
     (key->cipher == WLAN_CIPHER_SUITE_WEP40)) {
@@ -808,7 +959,8 @@ static int rsi_hal_key_config(struct ieee80211_hw *hw,
       key->keylen,
       RSI_PAIRWISE_KEY,
       key->keyidx,
-      key->cipher);
+      key->cipher,
+      sta_id);
  if (status)
  return status;
  }
@@ -817,7 +969,8 @@ static int rsi_hal_key_config(struct ieee80211_hw *hw,
  key->keylen,
  key_type,
  key->keyidx,
- key->cipher);
+ key->cipher,
+ sta_id);
 }
 
 /**
@@ -845,7 +998,7 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
  switch (cmd) {
  case SET_KEY:
  secinfo->security_enable = true;
- status = rsi_hal_key_config(hw, vif, key);
+ status = rsi_hal_key_config(hw, vif, key, sta);
  if (status) {
  mutex_unlock(&common->mutex);
  return status;
@@ -859,14 +1012,14 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
  key->hw_key_idx = key->keyidx;
  key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
 
- rsi_dbg(ERR_ZONE, "%s: RSI set_key\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: RSI set_key\n", __func__);
  break;
 
  case DISABLE_KEY:
  secinfo->security_enable = false;
- rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
  memset(key, 0, sizeof(struct ieee80211_key_conf));
- status = rsi_hal_key_config(hw, vif, key);
+ status = rsi_hal_key_config(hw, vif, key, sta);
  break;
 
  default:
@@ -942,13 +1095,13 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
  seq_no = params->ssn;
 #endif
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: AMPDU action tid=%d ssn=0x%x, buf_size=%d\n",
  __func__, tid, seq_no, buf_size);
 
  switch (action) {
  case IEEE80211_AMPDU_RX_START:
- rsi_dbg(INFO_ZONE, "AMPDU action RX_START (%d)\n", action);
+ ven_rsi_dbg(INFO_ZONE, "AMPDU action RX_START (%d)\n", action);
  status = rsi_send_aggr_params_frame(common,
     tid,
     seq_no,
@@ -957,7 +1110,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
  break;
 
  case IEEE80211_AMPDU_RX_STOP:
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "AMPDU action RX_STOP (%d) called\n", action);
  status = rsi_send_aggr_params_frame(common,
     tid,
@@ -967,7 +1120,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
  break;
 
  case IEEE80211_AMPDU_TX_START:
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "AMPDU action TX_START (%d) called\n", action);
  common->vif_info[ii].seq_start = seq_no;
  ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
@@ -977,7 +1130,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
  case IEEE80211_AMPDU_TX_STOP_CONT:
  case IEEE80211_AMPDU_TX_STOP_FLUSH:
  case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "AMPDU action TX_STOP_CONT / TX_STOP_FLUSH /"
  " TX_STOP_FLUSH_CONT (%d) called\n", action);
  status = rsi_send_aggr_params_frame(common,
@@ -990,7 +1143,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
  break;
 
  case IEEE80211_AMPDU_TX_OPERATIONAL:
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "AMPDU action TX_OPERATIONAL(%d) called\n",
  action);
  status = rsi_send_aggr_params_frame(common,
@@ -1001,7 +1154,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
  break;
 
  default:
- rsi_dbg(ERR_ZONE, "%s: Uknown AMPDU action\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Uknown AMPDU action\n", __func__);
  break;
  }
 
@@ -1052,8 +1205,7 @@ static int rsi_mac80211_set_rate_mask(struct ieee80211_hw *hw,
  common->fixedrate_mask[band] =
  (mask->control[band].ht_mcs[0] << 12);
  } else {
- common->fixedrate_mask[band] =
- mask->control[band].legacy;
+ common->fixedrate_mask[band] = mask->control[band].legacy;
  }
  mutex_unlock(&common->mutex);
 
@@ -1085,7 +1237,7 @@ static void rsi_perform_cqm(struct rsi_common *common,
  return;
 
  common->cqm_info.last_cqm_event_rssi = rssi;
- rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
+ ven_rsi_dbg(INFO_ZONE, "CQM: Notifying event: %d\n", event);
  ieee80211_cqm_rssi_notify(adapter->vifs[0], event, GFP_KERNEL);
 }
 
@@ -1093,7 +1245,7 @@ void rsi_indicate_bcnmiss(struct rsi_common *common)
 {
  struct rsi_hw *adapter = common->priv;
 
- rsi_dbg(INFO_ZONE, "CQM: Notifying beacon miss\n" );
+ ven_rsi_dbg(INFO_ZONE, "CQM: Notifying beacon miss\n" );
  ieee80211_beacon_loss(adapter->vifs[0]);
  return;
 }
@@ -1113,7 +1265,8 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
        struct rsi_common *common,
        struct ieee80211_rx_status *rxs)
 {
- struct ieee80211_bss_conf *bss = &common->priv->vifs[0]->bss_conf;
+ struct ieee80211_vif *vif = common->priv->vifs[0];
+ struct ieee80211_bss_conf *bss = &vif->bss_conf;
  struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  struct skb_info *rx_params = (struct skb_info *)info->driver_data;
  struct ieee80211_hdr *hdr;
@@ -1150,7 +1303,8 @@ static void rsi_fill_rx_status(struct ieee80211_hw *hw,
  }
 
  /* CQM only for connected AP beacons, the RSSI is a weighted avg */
- if (bss->assoc && ether_addr_equal(bss->bssid, hdr->addr2)) {
+ if ((vif->type == NL80211_IFTYPE_STATION) && bss->assoc &&
+    ether_addr_equal(bss->bssid, hdr->addr2)) {
  if (ieee80211_is_beacon(hdr->frame_control))
  rsi_perform_cqm(common, hdr->addr2, rxs->signal);
  }
@@ -1182,46 +1336,6 @@ void rsi_indicate_pkt_to_os(struct rsi_common *common,
  ieee80211_rx_irqsafe(hw, skb);
 }
 
-static void rsi_set_min_rate(struct ieee80211_hw *hw,
-     struct ieee80211_sta *sta,
-     struct rsi_common *common)
-{
- u8 band = hw->conf.chandef.chan->band;
- u8 ii;
- u32 rate_bitmap;
- bool matched = false;
-
- common->bitrate_mask[band] = sta->supp_rates[band];
-
- rate_bitmap = (common->fixedrate_mask[band] & sta->supp_rates[band]);
-
- if (rate_bitmap & 0xfff) {
- /* Find out the min rate */
- for (ii = 0; ii < ARRAY_SIZE(rsi_rates); ii++) {
- if (rate_bitmap & BIT(ii)) {
- common->min_rate = rsi_rates[ii].hw_value;
- matched = true;
- break;
- }
- }
- }
-
- common->vif_info[0].is_ht = sta->ht_cap.ht_supported;
-
- if ((common->vif_info[0].is_ht) && (rate_bitmap >> 12)) {
- for (ii = 0; ii < ARRAY_SIZE(rsi_mcsrates); ii++) {
- if ((rate_bitmap >> 12) & BIT(ii)) {
- common->min_rate = rsi_mcsrates[ii];
- matched = true;
- break;
- }
- }
- }
-
- if (!matched)
- common->min_rate = 0xffff;
-}
-
 /**
  * rsi_mac80211_sta_add() - This function notifies driver about a peer getting
  *    connected.
@@ -1237,28 +1351,60 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 {
  struct rsi_hw *adapter = hw->priv;
  struct rsi_common *common = adapter->priv;
+ bool sta_exist = 0;
 
  rsi_hex_dump(INFO_ZONE, "Station Add: ", sta->addr, ETH_ALEN);
 
  mutex_lock(&common->mutex);
 
- rsi_set_min_rate(hw, sta, common);
+ if (vif->type == NL80211_IFTYPE_AP) {
+ u8 i, j;
+
+ /* Send peer notify to device */
+ ven_rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
+ for (i = 0; i < common->num_stations; i++) {
+ if (!memcmp(common->stations[i].sta->addr,
+    sta->addr, ETH_ALEN)) {
+ ven_rsi_dbg(INFO_ZONE, "Station exists\n");
+ sta_exist = 1;
+ break;
+ }
+ }
+ if (!sta_exist) {
+ ven_rsi_dbg(INFO_ZONE, "New Station\n");
+ rsi_inform_bss_status(common, AP_OPMODE, 1, sta->addr,
+      sta->wme, sta->aid, i);
+ common->stations[i].sta = sta;
+ common->stations[i].sta_id = i;
+ for (j = 0; j < IEEE80211_NUM_ACS; j++)
+ common->stations[i].seq_no[j] = 1;
+ common->num_stations++;
+ } else {
+ common->stations[i].sta = sta;
+ for (j = 0; j < IEEE80211_NUM_ACS; j++)
+ common->stations[i].seq_no[j] = 1;
+ }
+ }
 
  if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
     (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40)) {
  common->vif_info[0].sgi = true;
  }
- if (g_bgscan_enable) {
- if (!rsi_send_bgscan_params(common, 1)) {
- if (!rsi_send_bgscan_probe_req(common)) {
- rsi_dbg(INFO_ZONE,
- "Background scan started ===>\n");
- common->bgscan_en = 1;
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ rsi_set_min_rate(hw, sta, common);
+ if (g_bgscan_enable) {
+ if (!rsi_send_bgscan_params(common, 1)) {
+ if (!rsi_send_bgscan_probe_req(common)) {
+ ven_rsi_dbg(INFO_ZONE,
+ "Bgscan started ===>\n");
+ common->bgscan_en = 1;
+ }
  }
  }
  }
 
- if (sta->ht_cap.ht_supported)
+ if ((vif->type == NL80211_IFTYPE_STATION) &&
+    sta->ht_cap.ht_supported)
  ieee80211_start_tx_ba_session(sta, 0, 0);
 
  mutex_unlock(&common->mutex);
@@ -1285,24 +1431,49 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
 
  rsi_hex_dump(INFO_ZONE, "Station Removed: ", sta->addr, ETH_ALEN);
 
- /* Resetting all the fields to default values */
- mutex_lock(&common->mutex);
- memcpy((u8 *)bss->bssid, (u8 *)sta->addr, ETH_ALEN);
- bss->qos = sta->wme;
- common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
- common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
- common->min_rate = 0xffff;
- common->vif_info[0].is_ht = false;
- common->vif_info[0].sgi = false;
- common->vif_info[0].seq_start = 0;
- common->secinfo.ptk_cipher = 0;
- common->secinfo.gtk_cipher = 0;
- if (common->bgscan_en)
- common->bgscan_en = 0;
- mutex_unlock(&common->mutex);
+ if (vif->type == NL80211_IFTYPE_AP) {
+ u8 i, j;
+
+ /* Send peer notify to device */
+ ven_rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
+ for (i = 0; i < common->num_stations; i++) {
+ if (!memcmp(common->stations[i].sta->addr,
+    sta->addr, ETH_ALEN)) {
+ rsi_inform_bss_status(common, AP_OPMODE, 0,
+      sta->addr, sta->wme,
+      sta->aid, i);
+ common->stations[i].sta = NULL;
+ common->stations[i].sta_id = -1;
+ for (j = 0; j < IEEE80211_NUM_ACS; j++)
+ common->stations[i].seq_no[j] = 0;
+ common->num_stations--;
+ break;
+ }
+ }
+ if (i >= RSI_MAX_ASSOC_STAS)
+ ven_rsi_dbg(ERR_ZONE, "%s: No station found\n", __func__);
+ }
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ /* Resetting all the fields to default values */
+ mutex_lock(&common->mutex);
+ memcpy((u8 *)bss->bssid, (u8 *)sta->addr, ETH_ALEN);
+ bss->qos = sta->wme;
+ common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
+ common->bitrate_mask[NL80211_BAND_5GHZ] = 0;
+ common->min_rate = 0xffff;
+ common->vif_info[0].is_ht = false;
+ common->vif_info[0].sgi = false;
+ common->vif_info[0].seq_start = 0;
+ common->secinfo.ptk_cipher = 0;
+ common->secinfo.gtk_cipher = 0;
+ if (common->bgscan_en)
+ common->bgscan_en = 0;
+ mutex_unlock(&common->mutex);
 
- if (!common->iface_down)
- rsi_send_rx_filter_frame(common, 0);
+ if (!common->iface_down)
+ rsi_send_rx_filter_frame(common, 0);
+ }
  return 0;
 }
 #if 0
@@ -1323,7 +1494,7 @@ static void rsi_mac80211_sw_scan_start(struct ieee80211_hw *hw,
 
  status = rsi_send_bgscan_params(common, 1);
  if (!status) {
- rsi_dbg(INFO_ZONE, "Background scan commensing\n");
+ ven_rsi_dbg(INFO_ZONE, "Background scan commensing\n");
  if (!rsi_send_bgscan_probe_req(common))
  common->bgscan_en = 1;
  }
@@ -1386,15 +1557,15 @@ static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw,
  u32 antenna = 0;
 
  if (tx_ant > 1 || rx_ant > 1) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Invalid antenna selection (tx: %d, rx:%d)\n",
  tx_ant, rx_ant);
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Use 0 for int_ant, 1 for ext_ant\n");
  return -EINVAL;
  }
 
- rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n",
+ ven_rsi_dbg(INFO_ZONE, "%s: Antenna map Tx %x Rx %d\n",
  __func__, tx_ant, rx_ant);
 
  mutex_lock(&common->mutex);
@@ -1404,7 +1575,7 @@ static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw,
  if (rsi_set_antenna(common, antenna))
  goto fail_set_antenna;
 
- rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n",
+ ven_rsi_dbg(INFO_ZONE, "(%s) Antenna path configured successfully\n",
  tx_ant ? "UFL" : "INT");
 
  common->ant_in_use = antenna;
@@ -1414,7 +1585,7 @@ static int rsi_mac80211_set_antenna(struct ieee80211_hw *hw,
  return 0;
 
 fail_set_antenna:
- rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed.\n", __func__);
  mutex_unlock(&common->mutex);
  return -EINVAL;
 }
@@ -1449,11 +1620,14 @@ static void rsi_reg_notify(struct wiphy *wiphy,
   struct regulatory_request *request)
 {
  struct ieee80211_supported_band *sband;
- struct ieee80211_channel *ch;
  struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
  struct rsi_hw * adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ struct ieee80211_channel *ch;
  int i;
 
+ mutex_lock(&common->mutex);
+
  sband = wiphy->bands[NL80211_BAND_5GHZ];
 
  for (i = 0; i < sband->n_channels; i++) {
@@ -1465,10 +1639,27 @@ static void rsi_reg_notify(struct wiphy *wiphy,
  ch->flags |= IEEE80211_CHAN_NO_IR;
  }
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "country = %s dfs_region = %d\n",
  request->alpha2, request->dfs_region);
+
+ /* If DFS region or country is changed configure back ground scan
+ * params to device again */
+ if ((adapter->dfs_region != request->dfs_region) ||
+    (memcmp(adapter->country, request->alpha2, 2))) {
+ if (common->bgscan_en) {
+ rsi_send_bgscan_params(common, 0);
+ common->bgscan_en = 0;
+ mdelay(10);
+ rsi_send_bgscan_params(common, 1);
+ common->bgscan_en = 1;
+ }
+ }
+
  adapter->dfs_region = request->dfs_region;
+ adapter->country[0] = request->alpha2[0];
+ adapter->country[1] = request->alpha2[1];
+ mutex_unlock(&common->mutex);
 }
 
 void rsi_mac80211_rfkill_poll(struct ieee80211_hw *hw)
@@ -1486,6 +1677,85 @@ void rsi_mac80211_rfkill_poll(struct ieee80211_hw *hw)
  mutex_unlock(&common->mutex);
 }
 
+#ifdef CONFIG_RSI_WOW
+static const struct wiphy_wowlan_support rsi_wowlan_support = {
+ .flags =WIPHY_WOWLAN_ANY |
+ WIPHY_WOWLAN_MAGIC_PKT |
+ WIPHY_WOWLAN_DISCONNECT |
+ WIPHY_WOWLAN_GTK_REKEY_FAILURE  |
+ WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+ WIPHY_WOWLAN_EAP_IDENTITY_REQ   |
+ WIPHY_WOWLAN_4WAY_HANDSHAKE,
+ .n_patterns = 0,
+ .pattern_min_len = 1,
+ .pattern_max_len = 0,
+};
+
+static u16 rsi_wow_map_triggers(struct rsi_common *common,
+ struct cfg80211_wowlan *wowlan)
+{
+ u16 wow_triggers = 0;
+
+ ven_rsi_dbg(INFO_ZONE,"Mapping wowlan triggers\n");
+
+ if (wowlan->any)
+ wow_triggers |= RSI_WOW_ANY;
+ if (wowlan->magic_pkt)
+ wow_triggers |= RSI_WOW_MAGIC_PKT;
+ if (wowlan->disconnect)
+ wow_triggers |= RSI_WOW_DISCONNECT;
+ if (wowlan->gtk_rekey_failure || wowlan->eap_identity_req ||
+    wowlan->four_way_handshake)
+ wow_triggers |= RSI_WOW_SUPPORTS_GTK_REKEY;
+
+ return wow_triggers;
+}
+#endif
+
+#ifdef CONFIG_PM
+int rsi_mac80211_suspend(struct ieee80211_hw *hw,
+ struct cfg80211_wowlan *wowlan)
+{
+#ifdef CONFIG_RSI_WOW
+ struct rsi_hw *adapter = hw->priv;
+ struct rsi_common *common = adapter->priv;
+ u16 triggers;
+#endif
+ int ret = 0;
+
+ ven_rsi_dbg(INFO_ZONE, "***** mac80211 suspend called ******\n");
+
+#ifdef CONFIG_RSI_WOW
+ if (WARN_ON(!wowlan)) {
+ ven_rsi_dbg(ERR_ZONE,
+ "##### WoW triggers not enabled #####\n");
+ ret = -EINVAL;
+ goto fail_wow;
+ }
+
+ triggers = rsi_wow_map_triggers(common, wowlan);
+ if (!triggers) {
+ ven_rsi_dbg(ERR_ZONE, "%s:No valid WoW triggers\n",__func__);
+ ret = 1;
+ goto fail_wow;
+ }
+ ven_rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
+
+ rsi_send_wowlan_request(common, triggers, wowlan);
+
+fail_wow:
+#endif
+ return ret;
+}
+
+static int rsi_mac80211_resume(struct ieee80211_hw *hw)
+{
+ ven_rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
+
+ return 0;
+}
+#endif
+
 static struct ieee80211_ops mac80211_ops = {
  .tx = rsi_mac80211_tx,
  .start = rsi_mac80211_start,
@@ -1504,7 +1774,12 @@ static struct ieee80211_ops mac80211_ops = {
  .sta_remove = rsi_mac80211_sta_remove,
  .set_antenna = rsi_mac80211_set_antenna,
  .get_antenna = rsi_mac80211_get_antenna,
-        .rfkill_poll = rsi_mac80211_rfkill_poll
+ .rfkill_poll = rsi_mac80211_rfkill_poll,
+#ifdef CONFIG_PM
+ .suspend = rsi_mac80211_suspend,
+ .resume  = rsi_mac80211_resume,
+#endif
+
 };
 
 /**
@@ -1521,11 +1796,11 @@ int rsi_mac80211_attach(struct rsi_common *common)
  struct rsi_hw *adapter = common->priv;
  u8 addr_mask[ETH_ALEN] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x3};
 
- rsi_dbg(INIT_ZONE, "%s: Performing mac80211 attach\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Performing mac80211 attach\n", __func__);
 
  hw = ieee80211_alloc_hw(sizeof(struct rsi_hw), &mac80211_ops);
  if (!hw) {
- rsi_dbg(ERR_ZONE, "%s: ieee80211 hw alloc failed\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: ieee80211 hw alloc failed\n", __func__);
  return -ENOMEM;
  }
 
@@ -1572,26 +1847,34 @@ int rsi_mac80211_attach(struct rsi_common *common)
  rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
  rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
  hw->rate_control_algorithm = "AARF";
+ hw->sta_data_size = sizeof(struct rsi_sta);
 
  SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
  ether_addr_copy(hw->wiphy->addr_mask, addr_mask);
 
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP);
  wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
  wiphy->retry_short = RETRY_SHORT;
  wiphy->retry_long  = RETRY_LONG;
  wiphy->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
  wiphy->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
- wiphy->flags = 0;
  wiphy->available_antennas_tx = 1;
  wiphy->available_antennas_rx = 1;
  wiphy->bands[NL80211_BAND_2GHZ] =
  &adapter->sbands[NL80211_BAND_2GHZ];
  wiphy->bands[NL80211_BAND_5GHZ] =
  &adapter->sbands[NL80211_BAND_5GHZ];
+ wiphy->max_ap_assoc_sta = RSI_MAX_ASSOC_STAS;
+
+ wiphy->flags = WIPHY_FLAG_REPORTS_OBSS;
 
  wiphy->reg_notifier = rsi_reg_notify;
 
+#ifdef CONFIG_RSI_WOW
+ wiphy->wowlan = &rsi_wowlan_support;
+#endif
+
  status = ieee80211_register_hw(hw);
  if (status)
  return status;
diff --git a/ubuntu/rsi/rsi_91x_main.c b/ubuntu/rsi/rsi_91x_main.c
index f9ee129..006dbd9 100644
--- a/ubuntu/rsi/rsi_91x_main.c
+++ b/ubuntu/rsi/rsi_91x_main.c
@@ -21,14 +21,14 @@
 #include "rsi_mgmt.h"
 #include "rsi_common.h"
 #include "rsi_hal.h"
-#ifdef CONFIG_VEN_RSI_HCI
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
 #include "rsi_hci.h"
 #endif
 #ifdef CONFIG_VEN_RSI_COEX
 #include "rsi_coex.h"
 #endif
 
-u32 rsi_zone_enabled = //INFO_ZONE |
+u32 ven_rsi_zone_enabled = //INFO_ZONE |
  INIT_ZONE |
  //MGMT_TX_ZONE |
  //MGMT_RX_ZONE |
@@ -38,16 +38,16 @@ u32 rsi_zone_enabled = //INFO_ZONE |
  //ISR_ZONE |
  ERR_ZONE |
  0;
-EXPORT_SYMBOL_GPL(rsi_zone_enabled);
+EXPORT_SYMBOL_GPL(ven_rsi_zone_enabled);
 
 /**
- * rsi_dbg() - This function outputs informational messages.
+ * ven_rsi_dbg() - This function outputs informational messages.
  * @zone: Zone of interest for output message.
  * @fmt: printf-style format for output message.
  *
  * Return: none
  */
-void rsi_dbg(u32 zone, const char *fmt, ...)
+void ven_rsi_dbg(u32 zone, const char *fmt, ...)
 {
  struct va_format vaf;
  va_list args;
@@ -57,11 +57,11 @@ void rsi_dbg(u32 zone, const char *fmt, ...)
  vaf.fmt = fmt;
  vaf.va = &args;
 
- if (zone & rsi_zone_enabled)
+ if (zone & ven_rsi_zone_enabled)
  pr_info("%pV", &vaf);
  va_end(args);
 }
-EXPORT_SYMBOL_GPL(rsi_dbg);
+EXPORT_SYMBOL_GPL(ven_rsi_dbg);
 
 /**
  * rsi_hex_dump() - This function prints the packet (/msg) in hex bytes.
@@ -76,7 +76,7 @@ void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len)
 {
  int ii;
 
- if (!(zone & rsi_zone_enabled))
+ if (!(zone & ven_rsi_zone_enabled))
  return;
  printk("%s: (length = %d)\n", msg_str, len);
  for (ii = 0; ii < len; ii++) {
@@ -111,7 +111,7 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
  return NULL;
 
  if (pkt_len > (RSI_RCV_BUFFER_LEN * 4)) {
- rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Pkt size > max rx buf size %d\n",
  __func__, pkt_len);
  pkt_len = RSI_RCV_BUFFER_LEN * 4;
  }
@@ -128,19 +128,23 @@ static struct sk_buff *rsi_prepare_skb(struct rsi_common *common,
  info = IEEE80211_SKB_CB(skb);
  rx_params = (struct skb_info *)info->driver_data;
  rx_params->rssi = rsi_get_rssi(buffer);
- rx_params->channel = rsi_get_connected_channel(common->priv);
+
+// if (vif->type == NL80211_IFTYPE_STATION)
+ rx_params->channel = rsi_get_connected_channel(common->priv);
+// else
+// rx_params->channel = common->ap_channel->hw_value;
 
  return skb;
 }
 
 /**
- * rsi_read_pkt() - This function reads frames from the card.
+ * ven_rsi_read_pkt() - This function reads frames from the card.
  * @common: Pointer to the driver private structure.
  * @rcv_pkt_len: Received pkt length. In case of USB it is 0.
  *
  * Return: 0 on success, -1 on failure.
  */
-int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
+int ven_rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
 {
  u8 *frame_desc = NULL, extended_desc = 0;
  u32 index = 0, length = 0, queueno = 0;
@@ -153,7 +157,7 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
  offset = *(u16 *)&frame_desc[2];
 
  if ((actual_length < (4 + FRAME_DESC_SZ)) || (offset < 4)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: actual_length (%d) is less than 20 or"
  " offset(%d) is less than 4\n",
  __func__, actual_length, offset);
@@ -168,10 +172,14 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
  switch (queueno) {
  case RSI_COEX_Q:
  rsi_hex_dump(MGMT_RX_ZONE,
-     "RX Command packet",
+     "RX Command co ex packet",
      frame_desc + offset,
      FRAME_DESC_SZ + length);
+#ifdef CONFIG_VEN_RSI_COEX
+ rsi_coex_recv_pkt(common, (frame_desc + offset));
+#else
  rsi_mgmt_pkt_recv(common, (frame_desc + offset));
+#endif
  break;
  case RSI_WIFI_DATA_Q:
  rsi_hex_dump(DATA_RX_ZONE,
@@ -191,19 +199,19 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
  case RSI_WIFI_MGMT_Q:
  rsi_mgmt_pkt_recv(common, (frame_desc + offset));
  break;
-#ifdef CONFIG_VEN_RSI_HCI
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
  case RSI_BT_MGMT_Q:
  case RSI_BT_DATA_Q:
  rsi_hex_dump(DATA_RX_ZONE,
      "RX BT Pkt",
      frame_desc + offset,
-     FRAME_DESC_SZ + length);
+     FRAME_DESC_SZ + length);
  rsi_hci_recv_pkt(common, frame_desc + offset);
  break;
 #endif
 
  default:
- rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: pkt from invalid queue: %d\n",
  __func__,   queueno);
  goto fail;
  }
@@ -216,7 +224,7 @@ int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len)
 fail:
  return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(rsi_read_pkt);
+EXPORT_SYMBOL_GPL(ven_rsi_read_pkt);
 
 /**
  * rsi_tx_scheduler_thread() - This function is a kernel thread to send the
@@ -243,12 +251,12 @@ static void rsi_tx_scheduler_thread(struct rsi_common *common)
 }
 
 /**
- * rsi_91x_init() - This function initializes os interface operations.
+ * ven_rsi_91x_init() - This function initializes os interface operations.
  * @void: Void.
  *
  * Return: Pointer to the adapter structure on success, NULL on failure .
  */
-struct rsi_hw *rsi_91x_init(void)
+struct rsi_hw *ven_rsi_91x_init(void)
 {
  struct rsi_hw *adapter = NULL;
  struct rsi_common *common = NULL;
@@ -260,7 +268,7 @@ struct rsi_hw *rsi_91x_init(void)
 
  adapter->priv = kzalloc(sizeof(*common), GFP_KERNEL);
  if (!adapter->priv) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of priv\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of priv\n",
  __func__);
  kfree(adapter);
  return NULL;
@@ -268,6 +276,11 @@ struct rsi_hw *rsi_91x_init(void)
  common = adapter->priv;
  common->priv = adapter;
 
+ common->beacon_frame = kzalloc(512, GFP_KERNEL);
+ if (!common->beacon_frame)
+ goto err;
+ common->beacon_frame_len = 0;
+
  for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
  skb_queue_head_init(&common->tx_queue[ii]);
 
@@ -280,9 +293,16 @@ struct rsi_hw *rsi_91x_init(void)
        &common->tx_thread,
        rsi_tx_scheduler_thread,
        "Tx-Thread")) {
- rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to init tx thrd\n", __func__);
  goto err;
  }
+
+#ifdef CONFIG_VEN_RSI_COEX
+ if (rsi_coex_init(common)) {
+ ven_rsi_dbg(ERR_ZONE, "Failed to init COEX module\n");
+ goto err;
+ }
+#endif
  rsi_default_ps_params(adapter);
  spin_lock_init(&adapter->ps_lock);
  common->uapsd_bitmap = 0;
@@ -296,33 +316,36 @@ err:
  kfree(adapter);
  return NULL;
 }
-EXPORT_SYMBOL_GPL(rsi_91x_init);
+EXPORT_SYMBOL_GPL(ven_rsi_91x_init);
 
 /**
- * rsi_91x_deinit() - This function de-intializes os intf operations.
+ * ven_rsi_91x_deinit() - This function de-intializes os intf operations.
  * @adapter: Pointer to the adapter structure.
  *
  * Return: None.
  */
-void rsi_91x_deinit(struct rsi_hw *adapter)
+void ven_rsi_91x_deinit(struct rsi_hw *adapter)
 {
  struct rsi_common *common = adapter->priv;
  u8 ii;
 
- rsi_dbg(INFO_ZONE, "%s: Deinit core module...\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Deinit core module...\n", __func__);
 
  rsi_kill_thread(&common->tx_thread);
 
  for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
  skb_queue_purge(&common->tx_queue[ii]);
 
+#ifdef CONFIG_VEN_RSI_COEX
+ rsi_coex_deinit(common);
+#endif
  common->init_done = false;
 
  kfree(common);
  kfree(adapter->rsi_dev);
  kfree(adapter);
 }
-EXPORT_SYMBOL_GPL(rsi_91x_deinit);
+EXPORT_SYMBOL_GPL(ven_rsi_91x_deinit);
 
 /**
  * rsi_91x_hal_module_init() - This function is invoked when the module is
@@ -334,7 +357,7 @@ EXPORT_SYMBOL_GPL(rsi_91x_deinit);
  */
 static int rsi_91x_hal_module_init(void)
 {
- rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Module init called\n", __func__);
  return 0;
 }
 
@@ -348,7 +371,7 @@ static int rsi_91x_hal_module_init(void)
  */
 static void rsi_91x_hal_module_exit(void)
 {
- rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Module exit called\n", __func__);
 }
 
 module_init(rsi_91x_hal_module_init);
diff --git a/ubuntu/rsi/rsi_91x_mgmt.c b/ubuntu/rsi/rsi_91x_mgmt.c
index c38b12f..3329204 100644
--- a/ubuntu/rsi/rsi_91x_mgmt.c
+++ b/ubuntu/rsi/rsi_91x_mgmt.c
@@ -18,6 +18,10 @@
 #include "rsi_mgmt.h"
 #include "rsi_common.h"
 #include "rsi_ps.h"
+#include "rsi_hal.h"
+#ifdef CONFIG_VEN_RSI_COEX
+#include "rsi_coex.h"
+#endif
 
 struct rsi_config_vals dev_config_vals[] = {
  {
@@ -309,13 +313,21 @@ static void rsi_set_default_parameters(struct rsi_common *common)
  common->iface_down = true;
  common->endpoint = EP_2GHZ_20MHZ;
  common->driver_mode = 1; /* End-to-End Mode */
-#ifdef CONFIG_VEN_RSI_HCI
- common->coex_mode = 4;
+#if defined(CONFIG_VEN_RSI_HCI)
+ common->coex_mode = 2;
  common->oper_mode = 4;
+#elif defined(CONFIG_VEN_RSI_COEX)
+ common->coex_mode = 2; /*Default coex mode is WIFI alone */
+ common->oper_mode = 5;
 #else
  common->coex_mode = 1; /*Default coex mode is WIFI alone */
  common->oper_mode = 1;
 #endif
+
+#ifdef CONFIG_RSI_BT_LE
+ common->coex_mode = 2;
+ common->oper_mode = 8;
+#endif
  common->ta_aggr = 0;
  common->skip_fw_load = 0; /* Default disable skipping fw loading */
  common->lp_ps_handshake_mode = 0; /* Default No HandShake mode*/
@@ -328,6 +340,7 @@ static void rsi_set_default_parameters(struct rsi_common *common)
  common->obm_ant_sel_val = 2;
  common->antenna_diversity = 0;
  common->tx_power = RSI_TXPOWER_MAX;
+ common->dtim_cnt = 2;
 }
 
 void init_bgscan_params(struct rsi_common *common)
@@ -403,12 +416,13 @@ static int rsi_send_internal_mgmt_frame(struct rsi_common *common,
  struct skb_info *tx_params;
 
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: SKB is NULL\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: SKB is NULL\n", __func__);
  return -EINVAL;
  }
  skb->data[1] |= BIT(7);
  tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data;
  tx_params->flags |= INTERNAL_MGMT_PKT;
+ skb->priority = MGMT_SOFT_Q;
  skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb);
  rsi_set_event(&common->tx_thread.event);
  return 0;
@@ -435,7 +449,7 @@ static int rsi_load_radio_caps(struct rsi_common *common)
       0xf0, 0xf0, 0xf0, 0xf0};
  struct sk_buff *skb;
 
- rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Sending rate symbol req frame\n", __func__);
 
  skb = dev_alloc_skb(sizeof(struct rsi_radio_caps));
  if (!skb)
@@ -531,8 +545,7 @@ static int rsi_load_radio_caps(struct rsi_common *common)
  */
 static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
  u8 *msg,
- s32 msg_len,
- u8 type)
+ s32 msg_len)
 {
  struct rsi_hw *adapter = common->priv;
  struct ieee80211_tx_info *info;
@@ -541,41 +554,42 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
  u8 pkt_recv;
  struct sk_buff *skb;
  char *buffer;
+ struct ieee80211_hdr *wlh;
 
- if (type == RX_DOT11_MGMT) {
- if (!adapter->sc_nvifs)
- return -ENOLINK;
+ if (!adapter->sc_nvifs)
+ return -ENOLINK;
 
- msg_len -= pad_bytes;
- if ((msg_len <= 0) || (!msg)) {
- rsi_dbg(MGMT_RX_ZONE,
- "%s: Invalid rx msg of len = %d\n",
- __func__, msg_len);
- return -EINVAL;
- }
+ msg_len -= pad_bytes;
+ if ((msg_len <= 0) || (!msg)) {
+ ven_rsi_dbg(MGMT_RX_ZONE,
+ "%s: Invalid rx msg of len = %d\n",
+ __func__, msg_len);
+ return -EINVAL;
+ }
 
- skb = dev_alloc_skb(msg_len);
- if (!skb)
- return -ENOMEM;
+ skb = dev_alloc_skb(msg_len);
+ if (!skb)
+ return -ENOMEM;
 
- buffer = skb_put(skb, msg_len);
+ buffer = skb_put(skb, msg_len);
 
- memcpy(buffer,
-       (u8 *)(msg +  FRAME_DESC_SZ + pad_bytes),
-       msg_len);
+ memcpy(buffer,
+ (u8 *)(msg +  FRAME_DESC_SZ + pad_bytes),
+ msg_len);
 
- pkt_recv = buffer[0];
+ pkt_recv = buffer[0];
 
- info = IEEE80211_SKB_CB(skb);
- rx_params = (struct skb_info *)info->driver_data;
- rx_params->rssi = rsi_get_rssi(msg);
- rx_params->channel = rsi_get_channel(msg);
- rsi_dbg(MGMT_RX_ZONE,
- "%s: rssi=%d channel=%d\n",
- __func__, rx_params->rssi, rx_params->channel);
- rsi_indicate_pkt_to_os(common, skb);
- } else
- rsi_dbg(MGMT_TX_ZONE, "%s: Internal Packet\n", __func__);
+ info = IEEE80211_SKB_CB(skb);
+ rx_params = (struct skb_info *)info->driver_data;
+ rx_params->rssi = rsi_get_rssi(msg);
+ rx_params->channel = rsi_get_channel(msg);
+ ven_rsi_dbg(MGMT_RX_ZONE,
+ "%s: rssi=%d channel=%d\n",
+ __func__, rx_params->rssi, rx_params->channel);
+ wlh = (struct ieee80211_hdr *)skb->data;
+ ven_rsi_dbg(INFO_ZONE, "RX Dot11 Mgmt Pkt Type: %s\n",
+ dot11_pkt_type(wlh->frame_control));
+ rsi_indicate_pkt_to_os(common, skb);
 
  return 0;
 }
@@ -593,23 +607,25 @@ static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
  * Return: status: 0 on success, corresponding negative error code on failure.
  */
 static int rsi_send_sta_notify_frame(struct rsi_common *common,
-     u8 opmode,
+     enum opmode opmode,
      u8 notify_event,
      const unsigned char *bssid,
      u8 qos_enable,
-     u16 aid)
+     u16 aid,
+     u16 sta_id)
 {
+ struct ieee80211_vif *vif = common->priv->vifs[0];
  struct sk_buff *skb = NULL;
  struct rsi_peer_notify *peer_notify;
  int status;
  u16 vap_id = 0;
  int frame_len = sizeof(*peer_notify);
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending station notify frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending station notify frame\n", __func__);
 
  skb = dev_alloc_skb(frame_len);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -617,7 +633,10 @@ static int rsi_send_sta_notify_frame(struct rsi_common *common,
 
  peer_notify = (struct rsi_peer_notify *)skb->data;
 
- peer_notify->command = 0; //cpu_to_le16(opmode << 1);
+ if (opmode == STA_OPMODE)
+ peer_notify->command = cpu_to_le16(PEER_TYPE_AP << 1);
+ else if (opmode == AP_OPMODE)
+ peer_notify->command = cpu_to_le16(PEER_TYPE_STA << 1);
 
  switch (notify_event) {
  case STA_CONNECTED:
@@ -629,21 +648,22 @@ static int rsi_send_sta_notify_frame(struct rsi_common *common,
  default:
  break;
  }
-
  peer_notify->command |= cpu_to_le16((aid & 0xfff) << 4);
  ether_addr_copy(peer_notify->mac_addr, bssid);
- peer_notify->mpdu_density = cpu_to_le16(0x08);
+ peer_notify->mpdu_density = cpu_to_le16(0x08); //FIXME check this
  peer_notify->sta_flags = cpu_to_le32((qos_enable) ? 1 : 0);
  peer_notify->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ) |
  (RSI_WIFI_MGMT_Q << 12));
  peer_notify->desc_word[1] = cpu_to_le16(PEER_NOTIFY);
- peer_notify->desc_word[7] |= cpu_to_le16(vap_id << 8);
+ peer_notify->desc_word[7] |= cpu_to_le16(sta_id | vap_id << 8);
 
  skb_put(skb, frame_len);
  status = rsi_send_internal_mgmt_frame(common, skb);
 
- if (!status && qos_enable) {
+ if ((vif->type == NL80211_IFTYPE_STATION) &&
+    (!status) && qos_enable) {
  rsi_set_contention_vals(common);
+ mdelay(1);
  status = rsi_load_radio_caps(common);
  }
 
@@ -674,7 +694,7 @@ int rsi_send_aggr_params_frame(struct rsi_common *common,
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -682,7 +702,7 @@ int rsi_send_aggr_params_frame(struct rsi_common *common,
  memset(skb->data, 0, FRAME_DESC_SZ);
  mgmt_frame = (struct rsi_mac_frame *)skb->data;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending AMPDU indication frame\n",
  __func__);
 
@@ -731,11 +751,11 @@ int rsi_program_bb_rf(struct rsi_common *common)
  struct sk_buff *skb;
  struct rsi_mac_frame *mgmt_frame;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending BB/RF program frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending BB/RF program frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -750,7 +770,7 @@ int rsi_program_bb_rf(struct rsi_common *common)
 
  if (common->rf_reset) {
  mgmt_frame->desc_word[7] =  cpu_to_le16(RF_RESET_ENABLE);
- rsi_dbg(MGMT_TX_ZONE, "%s: ===> RF RESET REQUEST SENT <===\n",
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: ===> RF RESET REQUEST SENT <===\n",
  __func__);
  common->rf_reset = 0;
  }
@@ -781,12 +801,12 @@ int rsi_set_vap_capabilities(struct rsi_common *common,
  struct ieee80211_conf *conf = &hw->conf;
  u16 vap_id = 0;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending VAP capabilities frame\n", __func__);
 
  skb = dev_alloc_skb(sizeof(struct rsi_vap_caps));
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -849,8 +869,10 @@ int rsi_set_vap_capabilities(struct rsi_common *common,
 
  vap_caps->default_data_rate = 0;
  vap_caps->beacon_interval = cpu_to_le16(200);
- vap_caps->dtim_period = cpu_to_le16(4);
+ vap_caps->dtim_period = cpu_to_le16(common->dtim_cnt);
 // vap_caps->beacon_miss_threshold = cpu_to_le16(10);
+ if (mode == AP_OPMODE)
+ vap_caps->beacon_miss_threshold = cpu_to_le16(10);
 
  skb_put(skb, sizeof(*vap_caps));
 
@@ -873,17 +895,21 @@ int rsi_load_key(struct rsi_common *common,
  u16 key_len,
  u8 key_type,
  u8 key_id,
- u32 cipher)
+ u32 cipher,
+ s16 sta_id)
 {
+ struct ieee80211_vif *vif = common->priv->vifs[0];
  struct sk_buff *skb = NULL;
  struct rsi_set_key *set_key;
  u16 key_descriptor = 0;
+ u8 key_t1 = 0;
+ u8 vap_id = 0;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending load key frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending load key frame\n", __func__);
 
  skb = dev_alloc_skb(sizeof(struct rsi_set_key));
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -891,6 +917,38 @@ int rsi_load_key(struct rsi_common *common,
  memset(skb->data, 0, sizeof(struct rsi_set_key));
  set_key = (struct rsi_set_key *)skb->data;
 
+ switch (key_type) {
+ case RSI_GROUP_KEY:
+ key_t1 = 1 << 1;
+ if (vif->type == NL80211_IFTYPE_AP)
+ key_descriptor = BIT(7);
+ break;
+ case RSI_PAIRWISE_KEY:
+ if ((vif->type == NL80211_IFTYPE_AP) &&
+    (sta_id >= RSI_MAX_ASSOC_STAS)) {
+ ven_rsi_dbg(INFO_ZONE, "Invalid Sta_id %d\n", sta_id);
+ return -1;
+ }
+ key_t1 = 0 << 1;
+ if ((cipher != WLAN_CIPHER_SUITE_WEP40) &&
+    (cipher != WLAN_CIPHER_SUITE_WEP104))
+ key_id = 0;
+ break;
+ }
+ if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
+    (cipher == WLAN_CIPHER_SUITE_WEP104)) {
+ key_descriptor |= BIT(2);
+ if (key_len >= 13) {
+ key_descriptor |= BIT(3);
+ }
+ } else if (cipher != KEY_TYPE_CLEAR) {
+ key_descriptor |= BIT(4);
+ if (cipher == WLAN_CIPHER_SUITE_TKIP)
+ key_descriptor |= BIT(5);
+ }
+ key_descriptor |= (key_t1 | BIT(13) | (key_id << 14));
+
+#if 0
  if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
     (cipher == WLAN_CIPHER_SUITE_WEP104)) {
  key_len += 1;
@@ -905,22 +963,32 @@ int rsi_load_key(struct rsi_common *common,
  key_descriptor |= BIT(5);
  }
  key_descriptor |= (key_type | BIT(13) | (key_id << 14));
+#endif
 
  set_key->desc_word[0] = cpu_to_le16((sizeof(struct rsi_set_key) -
     FRAME_DESC_SZ) |
     (RSI_WIFI_MGMT_Q << 12));
  set_key->desc_word[1] = cpu_to_le16(SET_KEY_REQ);
  set_key->desc_word[4] = cpu_to_le16(key_descriptor);
+ set_key->desc_word[7] = cpu_to_le16(sta_id | (vap_id << 8));
 
+#if 0
  if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
     (cipher == WLAN_CIPHER_SUITE_WEP104)) {
  memcpy(&set_key->key[key_id][1], data, key_len * 2);
  } else {
  memcpy(&set_key->key[0][0], data, key_len);
  }
-
- memcpy(set_key->tx_mic_key, &data[16], 8);
- memcpy(set_key->rx_mic_key, &data[24], 8);
+#endif
+ if (data) {
+ memcpy(&set_key->key[0][0], data, key_len);
+ //memcpy(&set_key->key, data, 4 * 32);
+ memcpy(set_key->tx_mic_key, &data[16], 8);
+ memcpy(set_key->rx_mic_key, &data[24], 8);
+ } else {
+ memset(&set_key[FRAME_DESC_SZ], 0,
+       sizeof(struct rsi_set_key) - FRAME_DESC_SZ);
+ }
 
  skb_put(skb, sizeof(struct rsi_set_key));
 
@@ -940,7 +1008,7 @@ int rsi_send_common_dev_params(struct rsi_common *common)
  u32 *soc_gpio, len;
  u16 *frame, *ulp_gpio, *desc;
 
- rsi_dbg(INFO_ZONE, "Sending common dev config params\n");
+ ven_rsi_dbg(INFO_ZONE, "Sending common dev config params\n");
 
  len = 0x20;
 
@@ -985,12 +1053,12 @@ int rsi_send_common_dev_params(struct rsi_common *common)
 
  frame_len = sizeof(struct rsi_config_vals);
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending common device config params frame\n",
  __func__);
  skb = dev_alloc_skb(frame_len);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);
  return -ENOMEM;
  }
 
@@ -1047,10 +1115,10 @@ static int rsi_load_bootup_params(struct rsi_common *common)
  struct sk_buff *skb;
  struct rsi_boot_params *boot_params;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending boot params frame\n", __func__);
  skb = dev_alloc_skb(sizeof(struct rsi_boot_params));
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1058,13 +1126,13 @@ static int rsi_load_bootup_params(struct rsi_common *common)
  memset(skb->data, 0, sizeof(struct rsi_boot_params));
  boot_params = (struct rsi_boot_params *)skb->data;
 
- rsi_dbg(MGMT_TX_ZONE, "%s:\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s:\n", __func__);
 
  if (common->channel_width == BW_40MHZ) {
  memcpy(&boot_params->bootup_params,
        &boot_params_40,
        sizeof(struct bootup_params));
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Packet 40MHZ <=== %d\n", __func__,
  UMAC_CLK_40BW);
  boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40BW);
@@ -1074,12 +1142,12 @@ static int rsi_load_bootup_params(struct rsi_common *common)
        sizeof(struct bootup_params));
  if (boot_params_20.valid != cpu_to_le32(VALID_20)) {
  boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_20BW);
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Packet 20MHZ <=== %d\n", __func__,
  UMAC_CLK_20BW);
  } else {
  boot_params->desc_word[7] = cpu_to_le16(UMAC_CLK_40MHZ);
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Packet 20MHZ <=== %d\n", __func__,
  UMAC_CLK_40MHZ);
  }
@@ -1110,11 +1178,11 @@ static int rsi_send_reset_mac(struct rsi_common *common)
  struct sk_buff *skb;
  struct rsi_mac_frame *mgmt_frame;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending reset MAC frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending reset MAC frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1210,12 +1278,12 @@ int rsi_set_channel(struct rsi_common *common,
  struct sk_buff *skb = NULL;
  struct rsi_mac_frame *mgmt_frame;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending scan req frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1240,12 +1308,16 @@ int rsi_set_channel(struct rsi_common *common,
        BBP_REG_WRITE |
        (RSI_RF_TYPE << 4));
 
- if (!(channel->flags & IEEE80211_CHAN_NO_IR) &&
-       !(channel->flags & IEEE80211_CHAN_RADAR)) {
+ if ((channel->flags & IEEE80211_CHAN_NO_IR) ||
+    (channel->flags & IEEE80211_CHAN_RADAR)) {
+ mgmt_frame->desc_word[4] |= BIT(15);
+ } else {
  if (common->tx_power < channel->max_power)
- mgmt_frame->desc_word[6] = cpu_to_le16(common->tx_power);
+ mgmt_frame->desc_word[6] =
+ cpu_to_le16(common->tx_power);
  else
- mgmt_frame->desc_word[6] = cpu_to_le16(channel->max_power);
+ mgmt_frame->desc_word[6] =
+ cpu_to_le16(channel->max_power);
  }
  mgmt_frame->desc_word[7] = cpu_to_le16(common->priv->dfs_region);
 
@@ -1272,12 +1344,12 @@ int rsi_send_radio_params_update(struct rsi_common *common)
  struct rsi_mac_frame *mgmt_frame;
  struct sk_buff *skb = NULL;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending Radio Params update frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1307,12 +1379,12 @@ int rsi_send_vap_dynamic_update(struct rsi_common *common)
  struct sk_buff *skb = NULL;
  struct rsi_dynamic_s *dynamic_frame = NULL;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending vap update indication frame\n", __func__);
 
  skb = dev_alloc_skb(sizeof(struct rsi_dynamic_s));
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1360,7 +1432,7 @@ int rsi_flash_read(struct rsi_hw *adapter)
  struct rsi_mac_frame *cmd_frame = NULL;
  struct sk_buff *skb;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending flash read frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending flash read frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb)
@@ -1378,13 +1450,13 @@ int rsi_flash_read(struct rsi_hw *adapter)
  cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
 
  /* Number of bytes to read */
- rsi_dbg(INFO_ZONE, " eeprom length  0x%x, %d\n",
+ ven_rsi_dbg(INFO_ZONE, " eeprom length  0x%x, %d\n",
  adapter->eeprom.length, adapter->eeprom.length);
  cmd_frame->desc_word[3] = cpu_to_le16(adapter->eeprom.length << 4);
 
  cmd_frame->desc_word[2] |= cpu_to_le16(3 << 8);
  if (adapter->eeprom_init) {
- rsi_dbg(INFO_ZONE, "spi init sent");
+ ven_rsi_dbg(INFO_ZONE, "spi init sent");
  cmd_frame->desc_word[2] |= cpu_to_le16(BIT(13));
  }
 
@@ -1453,7 +1525,8 @@ static bool rsi_map_rates(u16 rate, int *offset)
  *
  * Return: 0 on success, corresponding error code on failure.
  */
-static int rsi_send_auto_rate_request(struct rsi_common *common)
+static int rsi_send_auto_rate_request(struct rsi_common *common,
+      u16 sta_id)
 {
  struct sk_buff *skb;
  struct rsi_auto_rate *auto_rate;
@@ -1465,19 +1538,19 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
  u32 rate_bitmap = common->bitrate_mask[band];
  u16 *selected_rates, min_rate;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending auto rate request frame\n", __func__);
 
- skb = dev_alloc_skb(sizeof(struct rsi_auto_rate));
+ skb = dev_alloc_skb(MAX_MGMT_PKT_SIZE);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
 
  selected_rates = kzalloc(2 * RSI_TBL_SZ, GFP_KERNEL);
  if (!selected_rates) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
  __func__);
  dev_kfree_skb(skb);
  return -ENOMEM;
@@ -1497,7 +1570,8 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
  auto_rate->desc_word[1] = cpu_to_le16(AUTO_RATE_IND);
 
  if (common->channel_width == BW_40MHZ)
- auto_rate->desc_word[7] |= cpu_to_le16(1);
+ auto_rate->desc_word[7] = cpu_to_le16(1);
+ auto_rate->desc_word[7] |= cpu_to_le16(sta_id << 8);
 
  if (band == NL80211_BAND_2GHZ) {
  min_rate = RSI_RATE_1;
@@ -1560,41 +1634,93 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
 
  auto_rate->num_supported_rates = cpu_to_le16(num_supported_rates * 2);
  auto_rate->moderate_rate_inx = cpu_to_le16(num_supported_rates / 2);
- auto_rate->desc_word[7] |= cpu_to_le16(0 << 8);
  num_supported_rates *= 2;
 
  auto_rate->desc_word[0] = cpu_to_le16((sizeof(*auto_rate) -
        FRAME_DESC_SZ) |
        (RSI_WIFI_MGMT_Q << 12));
 
- skb_put(skb,
- sizeof(struct rsi_auto_rate));
+ skb_put(skb, sizeof(struct rsi_auto_rate));
  kfree(selected_rates);
 
  return rsi_send_internal_mgmt_frame(common, skb);
 }
 
 /**
- * rsi_channel_valid() - This function is used to check
- *              the user channel is valid or not.
+ * rsi_validate_bgscan_channels() - This function is used to validate
+ * the user configured bgscan channels for
+ * current regulatory domain
  * @chn_num: It holds the user or default channel for validation.
  *
  * Return: 0 on success, corresponding error code on failure.
  */
-static int rsi_channel_valid(u16 chn_num)
+static void rsi_validate_bgscan_channels(struct rsi_hw *adapter,
+ struct bgscan_config_params *params)
 {
- int status = -1;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_channel *ch;
+ struct wiphy *wiphy = adapter->hw->wiphy;
+ u16 bgscan_channels[MAX_BGSCAN_CHANNELS] = {1, 2, 3, 4, 5, 6, 7, 8, 9,
+    10, 11, 12, 13, 14, 36, 40,
+    44, 48, 52, 56, 60, 64, 100,
+    104, 108, 112, 116, 120, 124,
+    128, 132, 136, 140, 149, 153,
+    157, 161, 165};
+
+ int ch_num, i;
+ int num_valid_chs = 0, cnt;
+
+ /* If user passes 0 for num of bgscan channels, take all channels */
+ if (params->num_user_channels == 0) {
+ params->num_user_channels = MAX_BGSCAN_CHANNELS;
+ for (cnt = 0; cnt < MAX_BGSCAN_CHANNELS; cnt++)
+ params->user_channels[cnt] = bgscan_channels[cnt];
+ }
 
- chn_num &= ~(BIT(15)); /* clearing DFS indication in channel num */
+ ven_rsi_dbg(INFO_ZONE, "Final bgscan channels:\n");
+ for (cnt = 0; cnt < params->num_user_channels; cnt++) {
+ ch_num = params->user_channels[cnt];
+
+ if ((ch_num < 1) ||
+    ((ch_num > 14) && (ch_num < 36)) ||
+    ((ch_num > 64) && (ch_num < 100)) ||
+    ((ch_num > 140) && (ch_num < 149)) ||
+    (ch_num > 165))
+ continue;
+ if ((ch_num >= 36) && (ch_num < 149) && (ch_num % 4))
+ continue;
+
+ if (ch_num > 14)
+ sband = wiphy->bands[NL80211_BAND_5GHZ];
+ else
+ sband = wiphy->bands[NL80211_BAND_2GHZ];
 
- if (((chn_num >= 1) && (chn_num <= 14)) ||
-    ((chn_num >= 36) && (chn_num <= 64)) ||
-    ((chn_num >= 100) && (chn_num <= 140)) ||
-    ((chn_num >= 149) && (chn_num <= 165))) {
- return 0;
- }
+ for (i = 0; i < sband->n_channels; i++) {
+ ch = &sband->channels[i];
 
- return status;
+ if (ch->hw_value == ch_num)
+ break;
+ }
+ if (i >= sband->n_channels)
+ continue;
+
+ /* Check channel availablity for the current reg domain */
+ if (ch->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ params->channels2scan[num_valid_chs] = ch_num;
+ printk("%d ", ch_num);
+ if ((ch->flags & IEEE80211_CHAN_NO_IR) ||
+    (ch->flags & IEEE80211_CHAN_RADAR)) {
+ printk("[DFS]");
+ params->channels2scan[num_valid_chs] |=
+ (cpu_to_le16(BIT(15))); /* DFS indication */
+ }
+ num_valid_chs++;
+ printk(" ");
+ }
+ printk("\n");
+ params->num_bg_channels = num_valid_chs;
 }
 
 /**
@@ -1611,22 +1737,20 @@ int rsi_send_bgscan_params(struct rsi_common *common, int enable)
  struct bgscan_config_params *info = &common->bgscan_info;
  struct sk_buff *skb;
  u16 frame_len = sizeof(*bgscan);
- u8 ii;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending bgscan params frame\n", __func__);
+
+ rsi_validate_bgscan_channels(common->priv, info);
+ if (!info->num_bg_channels) {
+ ven_rsi_dbg(ERR_ZONE, "##### No valid bgscan channels #####\n");
+ return -1;
+ }
 
  skb = dev_alloc_skb(frame_len);
  if (!skb)
  return -ENOMEM;
  memset(skb->data, 0, frame_len);
 
- if (!info->num_bg_channels) {
- rsi_dbg(ERR_ZONE, "%s: BG Scan failed,No valid channel found\n",
- __func__);
- return -EINVAL;
- }
-
- memset(skb->data, 0, frame_len);
  bgscan = (struct rsi_bgscan_params *)skb->data;
 
  bgscan->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ) |
@@ -1644,14 +1768,9 @@ int rsi_send_bgscan_params(struct rsi_common *common, int enable)
  cpu_to_le16(info->passive_scan_duration);
  bgscan->two_probe = info->two_probe;
 
- for (ii = 0; ii < info->num_bg_channels; ii++) {
- int channel = info->channels2scan[ii];
-
- if (!rsi_channel_valid(channel))
- bgscan->channels2scan[ii] =
- cpu_to_le16(info->channels2scan[ii]);
- }
-
+ memcpy(bgscan->channels2scan,
+       info->channels2scan,
+       info->num_bg_channels * 2);
  bgscan->num_bg_channels = info->num_bg_channels;
 
  skb_put(skb, frame_len);
@@ -1676,7 +1795,7 @@ int rsi_send_bgscan_probe_req(struct rsi_common *common)
  u16 len = 1500;
  u16 pbreq_len = 0;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending bgscan probe req frame\n", __func__);
 
  skb = dev_alloc_skb(frame_len + len);
@@ -1700,9 +1819,8 @@ int rsi_send_bgscan_probe_req(struct rsi_common *common)
  if (common->bgscan_probe_req_len > 0) {
  pbreq_len = common->bgscan_probe_req_len;
  bgscan->probe_req_length = pbreq_len;
- memcpy(&skb->data[frame_len], common->bgscan_probe_req, len);
- *(u16 *)&skb->data[frame_len + 22] =
- common->bgscan_probe_req[22] + 1;
+ memcpy(&skb->data[frame_len], common->bgscan_probe_req,
+       common->bgscan_probe_req_len);
  }
 
  bgscan->desc_word[0] = cpu_to_le16((frame_len - FRAME_DESC_SZ + pbreq_len) |
@@ -1726,34 +1844,43 @@ int rsi_send_bgscan_probe_req(struct rsi_common *common)
  * Return: None.
  */
 void rsi_inform_bss_status(struct rsi_common *common,
+   enum opmode opmode,
    u8 status,
-   const unsigned char *bssid,
+   u8 *bssid,
    u8 qos_enable,
-   u16 aid)
+   u16 aid,
+   u16 sta_id)
 {
  if (status) {
- common->hw_data_qs_blocked = true;
+ if (opmode == STA_OPMODE)
+ common->hw_data_qs_blocked = true;
  rsi_send_sta_notify_frame(common,
-  RSI_IFTYPE_STATION,
+  opmode,
   STA_CONNECTED,
   bssid,
   qos_enable,
-  aid);
+  aid,
+  sta_id);
  if (common->min_rate == 0xffff) {
- rsi_dbg(INFO_ZONE, "Send auto rate request\n");
- rsi_send_auto_rate_request(common);
+ ven_rsi_dbg(INFO_ZONE, "Send auto rate request\n");
+ rsi_send_auto_rate_request(common, sta_id);
+ }
+ if (opmode == STA_OPMODE) {
+ if (!rsi_send_block_unblock_frame(common, false))
+ common->hw_data_qs_blocked = false;
  }
- if (!rsi_send_block_unblock_frame(common, false))
- common->hw_data_qs_blocked = false;
  } else {
- common->hw_data_qs_blocked = true;
+ if (opmode == STA_OPMODE)
+ common->hw_data_qs_blocked = true;
  rsi_send_sta_notify_frame(common,
-  RSI_IFTYPE_STATION,
+  opmode,
   STA_DISCONNECTED,
   bssid,
   qos_enable,
-  aid);
- rsi_send_block_unblock_frame(common, true);
+  aid,
+  sta_id);
+ if (opmode == STA_OPMODE)
+ rsi_send_block_unblock_frame(common, true);
  }
 }
 
@@ -1770,12 +1897,12 @@ static int rsi_eeprom_read(struct rsi_common *common)
  struct rsi_hw *adapter = common->priv;
  struct sk_buff *skb;
 
- rsi_dbg(MGMT_TX_ZONE,
+ ven_rsi_dbg(MGMT_TX_ZONE,
  "%s: Sending EEPROM read req frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1814,11 +1941,11 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
  struct rsi_mac_frame *mgmt_frame;
  struct sk_buff *skb;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending block/unblock frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending block/unblock frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1831,11 +1958,11 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
  mgmt_frame->desc_word[3] = cpu_to_le16(0x1);
 
  if (block_event == true) {
- rsi_dbg(INFO_ZONE, "blocking the data qs\n");
+ ven_rsi_dbg(INFO_ZONE, "blocking the data qs\n");
  mgmt_frame->desc_word[4] = cpu_to_le16(0xf);
  mgmt_frame->desc_word[4] |= cpu_to_le16(0xf << 4);
  } else {
- rsi_dbg(INFO_ZONE, "unblocking the data qs\n");
+ ven_rsi_dbg(INFO_ZONE, "unblocking the data qs\n");
  mgmt_frame->desc_word[5] = cpu_to_le16(0xf);
  mgmt_frame->desc_word[5] |= cpu_to_le16(0xf << 4);
  }
@@ -1857,11 +1984,11 @@ int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word)
  struct rsi_mac_frame *mgmt_frame;
  struct sk_buff *skb;
 
- rsi_dbg(MGMT_TX_ZONE, "%s: Sending RX filter frame\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending RX filter frame\n", __func__);
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1957,7 +2084,7 @@ int rsi_set_antenna(struct rsi_common *common,
 
  skb = dev_alloc_skb(FRAME_DESC_SZ);
  if (!skb) {
- rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
  __func__);
  return -ENOMEM;
  }
@@ -1986,11 +2113,11 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  struct rsi_hw *adapter = common->priv;
  u8 sub_type = (msg[15] & 0xff);
 
- rsi_dbg(MGMT_RX_ZONE, "%s: subtype=%d\n", __func__, sub_type);
+ ven_rsi_dbg(MGMT_RX_ZONE, "%s: subtype=%d\n", __func__, sub_type);
 
  switch (sub_type) {
  case COMMON_DEV_CONFIG:
- rsi_dbg(FSM_ZONE,
+ ven_rsi_dbg(FSM_ZONE,
  "Common Dev Config params confirm received\n");
  if (common->fsm_state == FSM_COMMON_DEV_PARAMS_SENT) {
  if (rsi_load_bootup_params(common)) {
@@ -2000,7 +2127,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  common->fsm_state = FSM_BOOT_PARAMS_SENT;
  }
  } else {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Received common dev config params cfm in %d state\n",
  __func__, common->fsm_state);
  return 0;
@@ -2008,7 +2135,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  break;
 
  case BOOTUP_PARAMS_REQUEST:
- rsi_dbg(FSM_ZONE, "Bootup params confirmation.\n");
+ ven_rsi_dbg(FSM_ZONE, "Bootup params confirmation.\n");
  if (common->fsm_state == FSM_BOOT_PARAMS_SENT) {
  adapter->eeprom.length = (IEEE80211_ADDR_LEN +
   WLAN_MAC_MAGIC_WORD_LEN +
@@ -2020,7 +2147,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  } else
  common->fsm_state = FSM_EEPROM_READ_MAC_ADDR;
  } else {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Received bootup params cfm in %d state\n",
  __func__, common->fsm_state);
  return 0;
@@ -2028,12 +2155,12 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  break;
 
  case EEPROM_READ:
- rsi_dbg(FSM_ZONE, "EEPROM READ confirm received\n");
+ ven_rsi_dbg(FSM_ZONE, "EEPROM READ confirm received\n");
  if (common->fsm_state == FSM_EEPROM_READ_MAC_ADDR) {
  u32 msg_len = ((u16 *)msg)[0] & 0xfff;
 
  if (msg_len <= 0) {
- rsi_dbg(FSM_ZONE,
+ ven_rsi_dbg(FSM_ZONE,
  "%s: [EEPROM_READ] Invalid len %d\n",
  __func__, msg_len);
  goto out;
@@ -2054,7 +2181,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  adapter->eeprom.offset =
  WLAN_EEPROM_RFTYPE_ADDR;
  if (rsi_eeprom_read(common)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed reading RF band\n",
  __func__);
  common->fsm_state = FSM_CARD_NOT_READY;
@@ -2070,18 +2197,18 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  u32 msg_len = ((u16 *)msg)[0] & 0xfff;
 
  if (msg_len <= 0) {
- rsi_dbg(FSM_ZONE,
+ ven_rsi_dbg(FSM_ZONE,
  "%s:[EEPROM_READ_CFM] Invalid len %d\n",
  __func__, msg_len);
  goto out;
  }
  if (msg[16] == MAGIC_WORD) {
  if ((msg[17] & 0x3) == 0x3) {
- rsi_dbg(INIT_ZONE,
+ ven_rsi_dbg(INIT_ZONE,
  "Dual band supported\n");
  common->band = NL80211_BAND_5GHZ;
  } else if ((msg[17] & 0x3) == 0x1) {
- rsi_dbg(INIT_ZONE,
+ ven_rsi_dbg(INIT_ZONE,
  "Only 2.4Ghz band supported\n");
  common->band = NL80211_BAND_2GHZ;
  }
@@ -2094,7 +2221,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  else
  common->fsm_state = FSM_RESET_MAC_SENT;
  } else {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Received eeprom read in %d state\n",
  __func__, common->fsm_state);
  return 0;
@@ -2103,14 +2230,14 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
 
  case RESET_MAC_REQ:
  if (common->fsm_state == FSM_RESET_MAC_SENT) {
- rsi_dbg(FSM_ZONE, "Reset MAC confirm\n");
+ ven_rsi_dbg(FSM_ZONE, "Reset MAC confirm\n");
 
  if (rsi_load_radio_caps(common))
  goto out;
  else
  common->fsm_state = FSM_RADIO_CAPS_SENT;
  } else {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Received reset mac cfm in %d state\n",
  __func__, common->fsm_state);
  return 0;
@@ -2124,10 +2251,10 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  goto out;
  } else {
  common->fsm_state = FSM_BB_RF_PROG_SENT;
- rsi_dbg(FSM_ZONE, "Radio caps confirm\n");
+ ven_rsi_dbg(FSM_ZONE, "Radio caps confirm\n");
  }
  } else {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Received radio caps cfm in %d state\n",
  __func__, common->fsm_state);
  return 0;
@@ -2137,7 +2264,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  case BB_PROG_VALUES_REQUEST:
  case RF_PROG_VALUES_REQUEST:
  case BBP_PROG_IN_TA:
- rsi_dbg(FSM_ZONE, "BB/RF confirmation.\n");
+ ven_rsi_dbg(FSM_ZONE, "BB/RF confirmation.\n");
  if (common->fsm_state == FSM_BB_RF_PROG_SENT) {
  common->bb_rf_prog_count--;
  if (!common->bb_rf_prog_count) {
@@ -2145,7 +2272,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  return rsi_mac80211_attach(common);
  }
  } else {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Received bb_rf cfm in %d state\n",
  __func__, common->fsm_state);
  return 0;
@@ -2153,30 +2280,30 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  break;
 
  case AMPDU_IND:
- rsi_dbg(FSM_ZONE, "AMPDU indication.\n");
+ ven_rsi_dbg(INFO_ZONE, "AMPDU indication.\n");
  break;
 
  case SCAN_REQUEST:
- rsi_dbg(FSM_ZONE, "Scan confirm.\n");
+ ven_rsi_dbg(INFO_ZONE, "Scan confirm.\n");
  break;
 
  case SET_RX_FILTER:
- rsi_dbg(FSM_ZONE, "RX Filter confirmation.\n");
+ ven_rsi_dbg(INFO_ZONE, "RX Filter confirmation.\n");
  break;
 
  case WAKEUP_SLEEP_REQUEST:
- rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
+ ven_rsi_dbg(INFO_ZONE, "Wakeup/Sleep confirmation.\n");
  return rsi_handle_ps_confirm(adapter, msg);
 
  case BG_SCAN_PROBE_REQ:
- rsi_dbg(INFO_ZONE, "BG scan complete event\n");
+ ven_rsi_dbg(INFO_ZONE, "BG scan complete event\n");
 
  /* resume to connected channel if associated */
  rsi_resume_conn_channel(adapter);
  break;
 
  default:
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Invalid TA confirm type : %x\n",
  __func__, sub_type);
  break;
@@ -2184,7 +2311,7 @@ static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
  return 0;
 
 out:
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to send pkt/Invalid frame received\n",
  __func__);
  return -EINVAL;
@@ -2201,14 +2328,14 @@ int rsi_handle_card_ready(struct rsi_common *common)
 {
  switch (common->fsm_state) {
  case FSM_CARD_NOT_READY:
- rsi_dbg(INIT_ZONE, "Card ready indication from wlan.\n");
+ ven_rsi_dbg(INIT_ZONE, "Card ready indication from Common HAL\n");
  rsi_set_default_parameters(common);
  if (rsi_send_common_dev_params(common) < 0)
  return -EINVAL;
  common->fsm_state = FSM_COMMON_DEV_PARAMS_SENT;
  break;
  case FSM_COMMON_DEV_PARAMS_SENT:
- rsi_dbg(INIT_ZONE, "Common dev config params confirm\n");
+ ven_rsi_dbg(INIT_ZONE, "Common dev config params confirm\n");
  if (rsi_load_bootup_params(common)) {
  common->fsm_state = FSM_CARD_NOT_READY;
  return -EINVAL;
@@ -2216,7 +2343,7 @@ int rsi_handle_card_ready(struct rsi_common *common)
  common->fsm_state = FSM_BOOT_PARAMS_SENT;
  break;
  default:
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: card ready indication in invalid state %d.\n",
  __func__, common->fsm_state);
  return -EINVAL;
@@ -2225,6 +2352,45 @@ int rsi_handle_card_ready(struct rsi_common *common)
  return 0;
 }
 
+#ifdef CONFIG_RSI_WOW
+int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
+    struct cfg80211_wowlan *wowlan)
+{
+ struct rsi_wowlan_req *cmd_frame;
+ struct sk_buff *skb;
+ u8 length;
+ u8 sourceid[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ ven_rsi_dbg(ERR_ZONE, "%s: Sending wowlan request frame\n", __func__);
+
+ skb = dev_alloc_skb(sizeof(*cmd_frame));
+ if (!skb) {
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+ __func__);
+ return -ENOMEM;
+ }
+ memset(skb->data, 0, sizeof(*cmd_frame));
+ cmd_frame = (struct rsi_wowlan_req *)skb->data;
+
+ cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+ cmd_frame->desc_word[1] |= cpu_to_le16(WOWLAN_CONFIG_PARAMS);
+
+ memcpy(cmd_frame->sourceid, &sourceid, IEEE80211_ADDR_LEN);
+
+ cmd_frame->wow_flags = flags; /* TODO: check for the magic packet */
+ cmd_frame->host_sleep_status = 1; /* TODO: check for the host status */
+
+ length = FRAME_DESC_SZ + IEEE80211_ADDR_LEN + 2 + 2;
+
+ cmd_frame->desc_word[0] |= cpu_to_le16(length - FRAME_DESC_SZ);
+ cmd_frame->desc_word[2] |= cpu_to_le16(0);
+
+ skb_put(skb, length);
+
+ return rsi_send_internal_mgmt_frame(common, skb);
+}
+#endif
+
 /**
  * rsi_mgmt_pkt_recv() - This function processes the management packets
  * received from the hardware.
@@ -2243,44 +2409,59 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
  return rsi_handle_ta_confirm(common, msg);
 
  case CARD_READY_IND:
+ ven_rsi_dbg(INIT_ZONE, "CARD READY INDICATION FROM WLAN.\n");
  return rsi_handle_card_ready(common);
 
  case TX_STATUS_IND:
  if (msg[15] == PROBEREQ_CONFIRM) {
  common->mgmt_q_block = false;
- rsi_dbg(INFO_ZONE, "Mgmt queue unblocked\n");
+ ven_rsi_dbg(INFO_ZONE, "Mgmt queue unblocked\n");
  }
  break;
 
  case PS_NOTIFY_IND:
- rsi_dbg(FSM_ZONE, "Powersave notify indication.\n");
+ ven_rsi_dbg(FSM_ZONE, "Powersave notify indication.\n");
  break;
 
  case SLEEP_NOTIFY_IND:
- rsi_dbg(FSM_ZONE, "Sleep notify indication.\n");
+ ven_rsi_dbg(FSM_ZONE, "Sleep notify indication.\n");
  break;
 
  case DECRYPT_ERROR_IND:
- rsi_dbg(INFO_ZONE, "Error in decrypt.\n");
+ ven_rsi_dbg(INFO_ZONE, "Error in decrypt.\n");
  break;
 
  case DEBUG_IND:
- rsi_dbg(INFO_ZONE, "Debugging indication.\n");
+ ven_rsi_dbg(INFO_ZONE, "Debugging indication.\n");
  break;
 
  case RX_MISC_IND:
- rsi_dbg(INFO_ZONE, "RX misc indication.\n");
+ ven_rsi_dbg(INFO_ZONE, "RX misc indication.\n");
  break;
 
  case HW_BMISS_EVENT:
- rsi_dbg(INFO_ZONE, "Hardware beacon miss event\n");
+ ven_rsi_dbg(INFO_ZONE, "Hardware beacon miss event\n");
  rsi_indicate_bcnmiss(common);
- //if (common->bgscan_en)
- rsi_resume_conn_channel(common->priv);
+ rsi_resume_conn_channel(common->priv);
+ break;
+
+ case BEACON_EVENT_IND:
+ ven_rsi_dbg(INFO_ZONE, "Beacon event\n");
+ if (common->fsm_state != FSM_MAC_INIT_DONE)
+ return -1;
+ if (common->iface_down)
+ return -1;
+ mutex_lock(&common->mutex);
+ rsi_send_beacon(common);
+ mutex_unlock(&common->mutex);
  break;
 
+ case RX_DOT11_MGMT:
+ return rsi_mgmt_pkt_to_core(common, msg, msg_len);
+
  default:
- return rsi_mgmt_pkt_to_core(common, msg, msg_len, msg_type);
+ ven_rsi_dbg(INFO_ZONE, "Cmd Frame Type: %d\n", msg_type);
+ break;
  }
 
  return 0;
diff --git a/ubuntu/rsi/rsi_91x_ps.c b/ubuntu/rsi/rsi_91x_ps.c
index 7aa5ac9..ac1924d 100644
--- a/ubuntu/rsi/rsi_91x_ps.c
+++ b/ubuntu/rsi/rsi_91x_ps.c
@@ -57,7 +57,7 @@ char *str_psstate(enum ps_state state)
 static inline void rsi_modify_ps_state(struct rsi_hw *adapter,
        enum ps_state nstate)
 {
- rsi_dbg(INFO_ZONE, "PS state changed %s => %s\n",
+ ven_rsi_dbg(INFO_ZONE, "PS state changed %s => %s\n",
  str_psstate(adapter->ps_state),
  str_psstate(nstate));
 
@@ -100,14 +100,14 @@ EXPORT_SYMBOL_GPL(rsi_default_ps_params);
 void rsi_enable_ps(struct rsi_hw *adapter)
 {
  if (adapter->ps_state != PS_NONE) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Cannot accept enable PS in %s state\n",
  __func__, str_psstate(adapter->ps_state));
  return;
  }
 
  if (rsi_send_ps_request(adapter, true)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to send PS request to device\n",
  __func__);
  return;
@@ -126,14 +126,14 @@ void rsi_enable_ps(struct rsi_hw *adapter)
 void rsi_disable_ps(struct rsi_hw *adapter)
 {
  if (adapter->ps_state != PS_ENABLED) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Cannot accept disable PS in %s state\n",
  __func__, str_psstate(adapter->ps_state));
  return;
  }
 
  if (rsi_send_ps_request(adapter, false)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to send PS request to device\n",
  __func__);
  return;
@@ -155,14 +155,14 @@ void rsi_conf_uapsd(struct rsi_hw *adapter)
  return;
 
  if (rsi_send_ps_request(adapter, false)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to send PS request to device\n",
  __func__);
  return;
  }
 
  if (rsi_send_ps_request(adapter, true)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to send PS request to device\n",
  __func__);
  }
@@ -192,7 +192,7 @@ int rsi_handle_ps_confirm(struct rsi_hw *adapter, u8 *msg)
  rsi_modify_ps_state(adapter, PS_NONE);
  break;
  default:
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Invalid PS confirm type %x in state %s\n",
  cfm_type, str_psstate(adapter->ps_state));
  return -1;
diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
index 0b2a217..496d3b5 100644
--- a/ubuntu/rsi/rsi_91x_sdio.c
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -130,6 +130,11 @@ static int rsi_issue_sdiocommand(struct sdio_func *func,
  return err;
 }
 
+static void rsi_dummy_isr(struct sdio_func *function)
+{
+ return;
+}
+
 /**
  * rsi_handle_interrupt() - This function is called upon the occurrence
  *    of an interrupt.
@@ -140,10 +145,12 @@ static int rsi_issue_sdiocommand(struct sdio_func *func,
 static void rsi_handle_interrupt(struct sdio_func *function)
 {
  struct rsi_hw *adapter = sdio_get_drvdata(function);
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
 
- sdio_release_host(function);
+ dev->sdio_irq_task = current;
  rsi_interrupt_handler(adapter);
- sdio_claim_host(function);
+ dev->sdio_irq_task = NULL;
 }
 
 void rsi_gspi_init(struct rsi_hw *adapter)
@@ -196,12 +203,12 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
  u8 sdio_interrupt_status = 0;
  u8 request = 1;
 
- rsi_dbg(INFO_ZONE, "Writing disable to wakeup register\n");
+ ven_rsi_dbg(INFO_ZONE, "Writing disable to wakeup register\n");
  if (rsi_sdio_write_register(adapter,
  0,
     SDIO_WAKEUP_REG,
     &request) < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to Write SDIO WAKEUP REG\n", __func__);
  return;
  }
@@ -209,16 +216,16 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
  if (rsi_sdio_read_register(adapter,
    RSI_FN1_INT_REGISTER,
    &sdio_interrupt_status) < 0) {
- rsi_dbg(ERR_ZONE, "%s: Failed to Read Intr Status Register\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to Read Intr Status Register\n",
  __func__);
  return;
  }
- rsi_dbg(INFO_ZONE, "%s: Intr Status Register value = %d \n",
+ ven_rsi_dbg(INFO_ZONE, "%s: Intr Status Register value = %d \n",
  __func__, sdio_interrupt_status);
 
  /* Put TA on hold */
  if (rsi_sdio_master_access_msword(adapter, 0x2200)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set ms word to common reg\n",
  __func__);
  return ;
@@ -229,7 +236,7 @@ static void rsi_reset_chip(struct rsi_hw *adapter)
  TA_HOLD_THREAD_REG | SD_REQUEST_MASTER,
  (u8 *)&data,
  4)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to hold TA threads\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to hold TA threads\n", __func__);
  return ;
  }
 
@@ -267,22 +274,27 @@ static void rsi_reset_card(struct sdio_func *pfunction)
  u8 cmd52_resp = 0;
  u32 clock, resp, i;
  u16 rca;
+ u32 cmd_delay = 0;
 
-#if 0
+#ifdef CONFIG_DELL_BOARD
  /* Reset 9110 chip */
- ret = rsi_cmd52writebyte(pfunction->card,
+ err = rsi_cmd52writebyte(pfunction->card,
  SDIO_CCCR_ABORT,
  (1 << 3));
 
  /* Card will not send any response as it is getting reset immediately
  * Hence expect a timeout status from host controller
  */
- if (ret != -ETIMEDOUT)
- rsi_dbg(ERR_ZONE, "%s: Reset failed : %d\n", __func__, ret);
+ if (err != -ETIMEDOUT)
+ ven_rsi_dbg(ERR_ZONE, "%s: Reset failed : %d\n", __func__, err);
+
+ cmd_delay = 20;
+#else
+ cmd_delay = 2;
 #endif
 
  /* Wait for few milli seconds to get rid of residue charges if any */
- msleep(2);
+ msleep(cmd_delay);
 
  /* Initialize the SDIO card */
  host->ios.vdd = bit;
@@ -297,7 +309,7 @@ static void rsi_reset_card(struct sdio_func *pfunction)
  * This delay should be sufficient to allow the power supply
  * to reach the minimum voltage.
  */
- msleep(2);
+ msleep(cmd_delay);
 
  host->ios.clock = host->f_min;
  host->ios.power_mode = MMC_POWER_ON;
@@ -307,12 +319,12 @@ static void rsi_reset_card(struct sdio_func *pfunction)
  * This delay must be at least 74 clock sizes, or 1 ms, or the
  * time required to reach a stable voltage.
  */
- msleep(2);
+ msleep(cmd_delay);
 
  /* Issue CMD0. Goto idle state */
  host->ios.chip_select = MMC_CS_HIGH;
  host->ops->set_ios(host, &host->ios);
- msleep(1);
+ msleep(cmd_delay);
  err = rsi_issue_sdiocommand(pfunction,
     MMC_GO_IDLE_STATE,
     0,
@@ -320,14 +332,17 @@ static void rsi_reset_card(struct sdio_func *pfunction)
     NULL);
  host->ios.chip_select = MMC_CS_DONTCARE;
  host->ops->set_ios(host, &host->ios);
- msleep(1);
+ msleep(cmd_delay);
  host->use_spi_crc = 0;
 
  if (err)
- rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);
+ ven_rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);
 
-// if (!host->ocr_avail) {
+#ifdef CONFIG_DELL_BOARD
+ if (!host->ocr_avail) {
+#else
  if (1) {
+#endif
  /* Issue CMD5, arg = 0 */
  err = rsi_issue_sdiocommand(pfunction,
     SD_IO_SEND_OP_COND,
@@ -335,31 +350,39 @@ static void rsi_reset_card(struct sdio_func *pfunction)
     (MMC_RSP_R4 | MMC_CMD_BCR),
     &resp);
  if (err)
- rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
  __func__, err);
+#ifdef CONFIG_DELL_BOARD
+ host->ocr_avail = resp;
+#else
  card->ocr = resp;
+#endif
  }
 
  /* Issue CMD5, arg = ocr. Wait till card is ready  */
  for (i = 0; i < 100; i++) {
  err = rsi_issue_sdiocommand(pfunction,
     SD_IO_SEND_OP_COND,
+#ifdef CONFIG_DELL_BOARD
+    host->ocr_avail,
+#else
     card->ocr,
+#endif
     (MMC_RSP_R4 | MMC_CMD_BCR),
     &resp);
  if (err) {
- rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
  __func__, err);
  break;
  }
 
  if (resp & MMC_CARD_BUSY)
  break;
- msleep(10);
+ msleep(cmd_delay);
  }
 
  if ((i == 100) || (err)) {
- rsi_dbg(ERR_ZONE, "%s: card in not ready : %d %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: card in not ready : %d %d\n",
  __func__, i, err);
  return;
  }
@@ -371,7 +394,7 @@ static void rsi_reset_card(struct sdio_func *pfunction)
     (MMC_RSP_R6 | MMC_CMD_BCR),
     &resp);
  if (err) {
- rsi_dbg(ERR_ZONE, "%s: CMD3 failed : %d\n", __func__, err);
+ ven_rsi_dbg(ERR_ZONE, "%s: CMD3 failed : %d\n", __func__, err);
  return;
  }
  rca = resp >> 16;
@@ -385,23 +408,23 @@ static void rsi_reset_card(struct sdio_func *pfunction)
     (MMC_RSP_R1 | MMC_CMD_AC),
     NULL);
  if (err) {
- rsi_dbg(ERR_ZONE, "%s: CMD7 failed : %d\n", __func__, err);
+ ven_rsi_dbg(ERR_ZONE, "%s: CMD7 failed : %d\n", __func__, err);
  return;
  }
 
  /* Enable high speed */
  if (card->host->caps & MMC_CAP_SD_HIGHSPEED) {
- rsi_dbg(ERR_ZONE, "%s: Set high speed mode\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Set high speed mode\n", __func__);
  err = rsi_cmd52readbyte(card, SDIO_CCCR_SPEED, &cmd52_resp);
  if (err) {
- rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",
  __func__, err);
  } else {
  err = rsi_cmd52writebyte(card,
  SDIO_CCCR_SPEED,
  (cmd52_resp | SDIO_SPEED_EHS));
  if (err) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: CCR speed regwrite failed %d\n",
  __func__, err);
  return;
@@ -430,13 +453,14 @@ static void rsi_reset_card(struct sdio_func *pfunction)
  (SDIO_BUS_CD_DISABLE |
   SDIO_BUS_WIDTH_4BIT));
  if (err) {
- rsi_dbg(ERR_ZONE, "%s: Set bus mode failed : %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Set bus mode failed : %d\n",
  __func__, err);
  return;
  }
  host->ios.bus_width = MMC_BUS_WIDTH_4;
  host->ops->set_ios(host, &host->ios);
  }
+ mdelay(cmd_delay);
 }
 
 /**
@@ -473,12 +497,12 @@ static int rsi_setblocklength(struct rsi_hw *adapter, u32 length)
  (struct rsi_91x_sdiodev *)adapter->rsi_dev;
  int status;
 
- rsi_dbg(INIT_ZONE, "%s: Setting the block length\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Setting the block length\n", __func__);
 
  status = sdio_set_block_size(dev->pfunction, length);
  dev->pfunction->max_blksize = 256;
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Operational blk length is %d\n", __func__, length);
  return status;
 }
@@ -501,7 +525,7 @@ static int rsi_setupcard(struct rsi_hw *adapter)
  adapter->tx_blk_size = dev->tx_blk_size;
  status = rsi_setblocklength(adapter, dev->tx_blk_size);
  if (status)
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set block length\n", __func__);
  return status;
 }
@@ -524,14 +548,16 @@ int rsi_sdio_read_register(struct rsi_hw *adapter,
  u8 fun_num = 0;
  int status;
 
- sdio_claim_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_claim_host(dev->pfunction);
 
  if (fun_num == 0)
  *data = sdio_f0_readb(dev->pfunction, addr, &status);
  else
  *data = sdio_readb(dev->pfunction, addr, &status);
 
- sdio_release_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_release_host(dev->pfunction);
 
  return status;
 }
@@ -555,14 +581,16 @@ int rsi_sdio_write_register(struct rsi_hw *adapter,
  (struct rsi_91x_sdiodev *)adapter->rsi_dev;
  int status = 0;
 
- sdio_claim_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_claim_host(dev->pfunction);
 
  if (function == 0)
  sdio_f0_writeb(dev->pfunction, *data, addr, &status);
  else
  sdio_writeb(dev->pfunction, *data, addr, &status);
 
- sdio_release_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_release_host(dev->pfunction);
 
  return status;
 }
@@ -584,7 +612,7 @@ void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit)
   SD_REQUEST_MASTER),
  &int_bit);
  if (status)
- rsi_dbg(ERR_ZONE, "%s: unable to send ack\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: unable to send ack\n", __func__);
 }
 
 /**
@@ -606,14 +634,16 @@ int rsi_sdio_read_register_multiple(struct rsi_hw *adapter,
  (struct rsi_91x_sdiodev *)adapter->rsi_dev;
  u32 status = 0;
 
- sdio_claim_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_claim_host(dev->pfunction);
 
  status =  sdio_readsb(dev->pfunction, data, addr, count);
 
- sdio_release_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_release_host(dev->pfunction);
 
  if (status != 0)
- rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 read failed\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 read failed\n", __func__);
  return status;
 }
 
@@ -637,25 +667,27 @@ int rsi_sdio_write_register_multiple(struct rsi_hw *adapter,
  int status;
 
  if (dev->write_fail > 1) {
- rsi_dbg(ERR_ZONE, "%s: Stopping card writes\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Stopping card writes\n", __func__);
  return 0;
  } else if (dev->write_fail == 1) {
  /**
  * Assuming it is a CRC failure, we want to allow another
  *  card write
  */
- rsi_dbg(ERR_ZONE, "%s: Continue card writes\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Continue card writes\n", __func__);
  dev->write_fail++;
  }
 
- sdio_claim_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_claim_host(dev->pfunction);
 
  status = sdio_writesb(dev->pfunction, addr, data, count);
 
- sdio_release_host(dev->pfunction);
+ if (likely(dev->sdio_irq_task != current))
+ sdio_release_host(dev->pfunction);
 
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 write failed %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Synch Cmd53 write failed %d\n",
  __func__, status);
  dev->write_fail = 2;
  } else {
@@ -679,12 +711,12 @@ int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
  num_blocks = instructions_sz / block_size;
  msb_address = base_address >> 16;
 
- rsi_dbg(INFO_ZONE, "ins_size: %d\n", instructions_sz);
- rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+ ven_rsi_dbg(INFO_ZONE, "ins_size: %d\n", instructions_sz);
+ ven_rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
 
  /* Loading DM ms word in the sdio slave */
  if (rsi_sdio_master_access_msword(adapter, msb_address)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
  return -1;
  }
 
@@ -695,10 +727,10 @@ int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
  if (rsi_sdio_write_register_multiple(adapter,
  lsb_address | SD_REQUEST_MASTER,
  temp_buf, block_size)) {
- rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: failed to write\n", __func__);
  return -1;
  }
- rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, ii);
+ ven_rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, ii);
  base_address += block_size;
 
  if ((base_address >> 16) != msb_address) {
@@ -707,7 +739,7 @@ int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
  /* Loading DM ms word in the sdio slave */
  if (rsi_sdio_master_access_msword(adapter,
   msb_address)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set ms word reg\n",
  __func__);
  return -1;
@@ -727,15 +759,13 @@ int rsi_sdio_load_data_master_write(struct rsi_hw *adapter,
  instructions_sz % block_size)) {
  return -1;
  }
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "Written Last Block in Address 0x%x Successfully\n",
  offset | SD_REQUEST_MASTER);
  }
  return 0;
 }
 
-#define align_address(a) ((unsigned long)(a) & ~0x7)
-
 int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
      u32 *read_buf, u16 size)
 {
@@ -744,11 +774,11 @@ int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
  u32 align[2] = {};
  u32 addr_on_bus;
 
- data = (u32 *)align_address(&align[1]);
+ data = PTR_ALIGN(&align[0], 8);
 
  ms_addr = (addr >> 16);
  if (rsi_sdio_master_access_msword(adapter, ms_addr)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set ms word to common reg\n",
  __func__);
  return -1;
@@ -766,7 +796,7 @@ int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr,
  if (rsi_sdio_read_register_multiple(adapter,
     (addr_on_bus | SD_REQUEST_MASTER),
     (u8 *)data, 4)) {
- rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__);
  return -1;
  }
  if (size == 2) {
@@ -798,27 +828,27 @@ int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
       u16 size)
 {
  unsigned long data1[2];
- unsigned long *data_alligned;
+ unsigned long *data_aligned;
 
- data_alligned = (unsigned long *)align_address(&data1[1]);
+ data_aligned = PTR_ALIGN(&data1[0], 8);
 
  if (size == 2) {
- *data_alligned = ((data << 16) | (data & 0xFFFF));
+ *data_aligned = ((data << 16) | (data & 0xFFFF));
  } else if (size == 1) {
  u32 temp_data;
 
  temp_data = (data & 0xFF);
- *data_alligned = ((temp_data << 24) |
+ *data_aligned = ((temp_data << 24) |
   (temp_data << 16) |
   (temp_data << 8) |
   (temp_data));
  } else {
- *data_alligned = data;
+ *data_aligned = data;
  }
  size = 4;
 
  if (rsi_sdio_master_access_msword(adapter, (addr >> 16))) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to set ms word to common reg\n",
  __func__);
  return -1;
@@ -828,8 +858,8 @@ int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
  /* Bringing TA out of reset */
  if (rsi_sdio_write_register_multiple(adapter,
      (addr | SD_REQUEST_MASTER),
-     (u8 *)data_alligned, size)) {
- rsi_dbg(ERR_ZONE,
+     (u8 *)data_aligned, size)) {
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Unable to do AHB reg write\n", __func__);
  return -1;
  }
@@ -872,9 +902,9 @@ int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter,
   pkt,
   length);
  if (status < 0)
- rsi_dbg(ERR_ZONE, "%s: Unable to write onto the card: %d\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to write onto the card: %d\n",
  __func__, status);
- rsi_dbg(DATA_TX_ZONE, "%s: Successfully written onto card\n", __func__);
+ ven_rsi_dbg(DATA_TX_ZONE, "%s: Successfully written onto card\n", __func__);
  return status;
 }
 
@@ -894,7 +924,7 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,
  int status = -EINVAL;
 
  if (!length) {
- rsi_dbg(ERR_ZONE, "%s: Pkt size is zero\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Pkt size is zero\n", __func__);
  return status;
  }
 
@@ -904,7 +934,7 @@ int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter,
  length);
 
  if (status)
- rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to read frame: %d\n", __func__,
  status);
  return status;
 }
@@ -929,18 +959,19 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
  return status;
 
  adapter->rsi_dev = rsi_91x_dev;
+ rsi_91x_dev->sdio_irq_task = NULL;
 
  sdio_claim_host(pfunction);
 
  pfunction->enable_timeout = 100;
  status = sdio_enable_func(pfunction);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed to enable interface\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to enable interface\n", __func__);
  sdio_release_host(pfunction);
  return status;
  }
 
- rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
 
  rsi_91x_dev->pfunction = pfunction;
  adapter->device = &pfunction->dev;
@@ -949,21 +980,23 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
 
  status = rsi_setupcard(adapter);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed to setup card\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to setup card\n", __func__);
  goto fail;
  }
 
- rsi_dbg(INIT_ZONE, "%s: Setup card successfully\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Setup card successfully\n", __func__);
 
  status = rsi_init_sdio_slave_regs(adapter);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed to init slave regs\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to init slave regs\n", __func__);
  goto fail;
  }
  sdio_release_host(pfunction);
 
  adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
  adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
+ adapter->process_isr_hci = rsi_interrupt_handler;
+ adapter->check_intr_status_reg = rsi_read_intr_status_reg;
 
 #ifdef CONFIG_VEN_RSI_DEBUGFS
  adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES;
@@ -1000,11 +1033,11 @@ static int rsi_probe(struct sdio_func *pfunction,
 {
  struct rsi_hw *adapter;
 
- rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
 
- adapter = rsi_91x_init();
+ adapter = ven_rsi_91x_init();
  if (!adapter) {
- rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
  __func__);
  return 1;
  }
@@ -1012,42 +1045,52 @@ static int rsi_probe(struct sdio_func *pfunction,
  adapter->host_intf_ops = &sdio_host_intf_ops;
 
  if (rsi_init_sdio_interface(adapter, pfunction)) {
- rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to init sdio interface\n",
  __func__);
  goto fail;
  }
 
  sdio_claim_host(pfunction);
- if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
- rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
+// if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
+ if (sdio_claim_irq(pfunction, rsi_dummy_isr)) {
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
  sdio_release_host(pfunction);
  goto fail;
  }
-
  sdio_release_host(pfunction);
- rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
 
  if (rsi_hal_device_init(adapter)) {
- rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
  sdio_claim_host(pfunction);
+ sdio_release_irq(pfunction);
  sdio_disable_func(pfunction);
  sdio_release_host(pfunction);
  goto fail;
  }
- rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
+ ven_rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
 
  if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
- rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
  return -1;
  }
- rsi_dbg(INIT_ZONE, "%s: Setting ms word to 0x41050000\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Setting ms word to 0x41050000\n", __func__);
 
+ sdio_claim_host(pfunction);
+ sdio_release_irq(pfunction);
+ mdelay(10);
+ if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
+ sdio_release_host(pfunction);
+ goto fail;
+ }
+ sdio_release_host(pfunction);
 
  return 0;
 
 fail:
- rsi_91x_deinit(adapter);
- rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
+ ven_rsi_91x_deinit(adapter);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
  return 1;
 }
 
@@ -1067,20 +1110,27 @@ static void rsi_disconnect(struct sdio_func *pfunction)
 
  dev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
 
- rsi_mac80211_detach(adapter);
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
+#if defined(CONFIG_DELL_BOARD)
+ if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO)
+ rsi_kill_thread(&adapter->priv->hci_thread);
+#endif
+#endif
+
+ ven_rsi_mac80211_detach(adapter);
+ mdelay(10);
+
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
+ rsi_hci_detach(adapter->priv);
  mdelay(10);
-#ifdef CONFIG_VEN_RSI_HCI
-        rsi_hci_detach(adapter->priv);
 #endif
-        mdelay(10);
-
  sdio_claim_host(pfunction);
  sdio_release_irq(pfunction);
  sdio_release_host(pfunction);
  mdelay(10);
 
  /* Reset Chip */
- rsi_reset_chip(adapter);
+ rsi_reset_chip(adapter);
 
  /* Resetting to take care of the case, where-in driver is re-loaded */
  sdio_claim_host(pfunction);
@@ -1088,21 +1138,80 @@ static void rsi_disconnect(struct sdio_func *pfunction)
  sdio_disable_func(pfunction);
  sdio_release_host(pfunction);
  dev->write_fail = 2;
- rsi_91x_deinit(adapter);
- rsi_dbg(ERR_ZONE, "##### RSI SDIO device disconnected #####\n");
+ ven_rsi_91x_deinit(adapter);
+ ven_rsi_dbg(ERR_ZONE, "##### RSI SDIO device disconnected #####\n");
 }
 
 #ifdef CONFIG_PM
+int rsi_set_sdio_pm_caps(struct rsi_hw *adapter)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+ struct sdio_func *func = dev->pfunction;
+ mmc_pm_flag_t flags;
+ int ret;
+
+ /*Getting the host power management capabilities*/
+ flags = sdio_get_host_pm_caps(func);
+ ven_rsi_dbg(INFO_ZONE, "sdio suspend pm_caps 0x%x\n", flags);
+ if ((!(flags & MMC_PM_WAKE_SDIO_IRQ)) ||
+    (!(flags & MMC_PM_KEEP_POWER)))
+ return -EINVAL;
+
+ /* Keep Power to the MMC while suspend*/
+ ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+ if (ret) {
+ ven_rsi_dbg(ERR_ZONE, "set sdio keep pwr flag failed: %d\n", ret);
+ return ret;
+ }
+
+ /* sdio irq wakes up host */
+ ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
+ if (ret)
+ ven_rsi_dbg(ERR_ZONE,"set sdio wake irq flag failed: %d\n", ret);
+
+ return ret;
+}
+
+int rsi_sdio_suspend(struct rsi_hw *adapter)
+{
+ struct rsi_91x_sdiodev *dev =
+ (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+
+ ven_rsi_dbg(INFO_ZONE,"Suspend SDIO\n");
+
+ sdio_claim_host(dev->pfunction);
+ sdio_release_irq(dev->pfunction);
+ sdio_release_host(dev->pfunction);
+
+ return 0;
+}
+
 static int rsi_suspend(struct device *dev)
 {
- /* Not yet implemented */
- return -ENOSYS;
+ int ret = 0;
+ struct sdio_func *pfunction = dev_to_sdio_func(dev);
+ struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+
+ ven_rsi_dbg(INFO_ZONE,"***** SUSPEND CALLED ******\n");
+
+ ret = rsi_set_sdio_pm_caps(adapter);
+ if (ret){
+ ven_rsi_dbg(INFO_ZONE,"failed %s:%d\n",__func__,__LINE__);
+ }
+ ret = rsi_sdio_suspend(adapter);
+
+ if (ret && ret != -ENOTCONN)
+ ven_rsi_dbg(ERR_ZONE,"wow suspend failed: %d\n", ret);
+
+ return 0;
 }
 
-static int rsi_resume(struct device *dev)
+int rsi_resume(struct device *dev)
 {
- /* Not yet implemented */
- return -ENOSYS;
+ ven_rsi_dbg(INFO_ZONE,"rsi_sdio_resume returning\n");
+ return 0;
+
 }
 
 static const struct dev_pm_ops rsi_pm_ops = {
@@ -1142,7 +1251,7 @@ static int rsi_module_init(void)
  int ret;
 
  ret = sdio_register_driver(&rsi_driver);
- rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Registering driver\n", __func__);
  return ret;
 }
 
@@ -1155,7 +1264,7 @@ static int rsi_module_init(void)
 static void rsi_module_exit(void)
 {
  sdio_unregister_driver(&rsi_driver);
- rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Unregistering driver\n", __func__);
 }
 
 module_init(rsi_module_init);
diff --git a/ubuntu/rsi/rsi_91x_sdio_ops.c b/ubuntu/rsi/rsi_91x_sdio_ops.c
index cabb8ec..be62d42 100644
--- a/ubuntu/rsi/rsi_91x_sdio_ops.c
+++ b/ubuntu/rsi/rsi_91x_sdio_ops.c
@@ -37,7 +37,7 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
 
  byte = (u8)(ms_word & 0x00FF);
 
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: MASTER_ACCESS_MSBYTE:0x%x\n", __func__, byte);
 
  status = rsi_sdio_write_register(adapter,
@@ -45,7 +45,7 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
  SDIO_MASTER_ACCESS_MSBYTE,
  &byte);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: fail to access MASTER_ACCESS_MSBYTE\n",
  __func__);
  return -1;
@@ -53,7 +53,7 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
 
  byte = (u8)(ms_word >> 8);
 
- rsi_dbg(INFO_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte);
+ ven_rsi_dbg(INFO_ZONE, "%s:MASTER_ACCESS_LSBYTE:0x%x\n", __func__, byte);
  status = rsi_sdio_write_register(adapter,
  function,
  SDIO_MASTER_ACCESS_LSBYTE,
@@ -91,7 +91,7 @@ static int rsi_process_pkt(struct rsi_common *common)
  SDIO_RX_NUM_BLOCKS_REG,
  &value);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to read pkt length from the card:\n",
  __func__);
  return status;
@@ -118,7 +118,7 @@ static int rsi_process_pkt(struct rsi_common *common)
 
  common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL);
  if (!common->rx_data_pkt) {
- rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n",
  __func__);
  return -ENOMEM;
  }
@@ -127,12 +127,12 @@ static int rsi_process_pkt(struct rsi_common *common)
      common->rx_data_pkt,
      rcv_pkt_len);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
  __func__);
  goto fail;
  }
 
- status = rsi_read_pkt(common, common->rx_data_pkt, rcv_pkt_len);
+ status = ven_rsi_read_pkt(common, common->rx_data_pkt, rcv_pkt_len);
 
 fail:
  kfree(common->rx_data_pkt);
@@ -161,7 +161,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  SDIO_NXT_RD_DELAY2,
  &byte);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to write SDIO_NXT_RD_DELAY2\n",
  __func__);
  return -1;
@@ -169,7 +169,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  }
 
  if (dev->sdio_high_speed_enable) {
- rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Enabling SDIO High speed\n", __func__);
  byte = 0x3;
 
  status = rsi_sdio_write_register(adapter,
@@ -177,7 +177,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  SDIO_REG_HIGH_SPEED,
  &byte);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to enable SDIO high speed\n",
  __func__);
  return -1;
@@ -185,7 +185,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  }
 
  /* This tells SDIO FIFO when to start read to host */
- rsi_dbg(INIT_ZONE, "%s: Initialzing SDIO read start level\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Initialzing SDIO read start level\n", __func__);
  byte = 0x24;
 
  status = rsi_sdio_write_register(adapter,
@@ -193,12 +193,12 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  SDIO_READ_START_LVL,
  &byte);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to write SDIO_READ_START_LVL\n", __func__);
  return -1;
  }
 
- rsi_dbg(INIT_ZONE, "%s: Initialzing FIFO ctrl registers\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Initialzing FIFO ctrl registers\n", __func__);
  byte = (128 - 32);
 
  status = rsi_sdio_write_register(adapter,
@@ -206,7 +206,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  SDIO_READ_FIFO_CTL,
  &byte);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to write SDIO_READ_FIFO_CTL\n", __func__);
  return -1;
  }
@@ -217,7 +217,7 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  SDIO_WRITE_FIFO_CTL,
  &byte);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to write SDIO_WRITE_FIFO_CTL\n", __func__);
  return -1;
  }
@@ -225,6 +225,22 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter)
  return 0;
 }
 
+int rsi_read_intr_status_reg(struct rsi_hw *adapter)
+{
+ u8 isr_status = 0;
+ struct rsi_common *common = adapter->priv;
+ int status;
+
+ status = rsi_sdio_read_register(common->priv,
+ RSI_FN1_INT_REGISTER,
+ &isr_status);
+ isr_status &= 0xE;
+
+ if(isr_status & BIT(MSDU_PKT_PENDING))
+ adapter->isr_pending = 1;
+ return 0;
+}
+
 /**
  * rsi_interrupt_handler() - This function read and process SDIO interrupts.
  * @adapter: Pointer to the adapter structure.
@@ -249,7 +265,7 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
  RSI_FN1_INT_REGISTER,
  &isr_status);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to Read Intr Status Register\n",
  __func__);
  mutex_unlock(&common->rx_lock);
@@ -269,7 +285,7 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
 // adapter->interrupt_status = isr_status;
 // isr_status &= 0xE;
 
- rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",
+ ven_rsi_dbg(ISR_ZONE, "%s: Intr_status = %x %d %d\n",
  __func__, isr_status, (1 << MSDU_PKT_PENDING),
  (1 << FW_ASSERT_IND));
 
@@ -286,25 +302,26 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
   (1 << PKT_BUFF_AVAILABLE));
  rsi_set_event(&common->tx_thread.event);
 
- rsi_dbg(ISR_ZONE,
+ ven_rsi_dbg(ISR_ZONE,
  "%s: ==> BUFFER_AVAILABLE <==\n",
  __func__);
  dev->rx_info.buf_available_counter++;
+ dev->buff_status_updated = 1;
  break;
 
  case FIRMWARE_ASSERT_IND:
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: ==> FIRMWARE Assert <==\n",
  __func__);
  status = rsi_sdio_read_register(common->priv,
  SDIO_FW_STATUS_REG,
  &fw_status);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to read f/w reg\n",
  __func__);
  } else {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Firmware Status is 0x%x\n",
  __func__, fw_status);
  rsi_sdio_ack_intr(common->priv,
@@ -315,12 +332,12 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
  break;
 
  case MSDU_PACKET_PENDING:
- rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
+ ven_rsi_dbg(ISR_ZONE, "Pkt pending interrupt\n");
  dev->rx_info.total_sdio_msdu_pending_intr++;
 
  status = rsi_process_pkt(common);
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to read pkt\n",
  __func__);
  mutex_unlock(&common->rx_lock);
@@ -331,7 +348,7 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
  rsi_sdio_ack_intr(common->priv, isr_status);
  dev->rx_info.total_sdio_unknown_intr++;
  isr_status = 0;
- rsi_dbg(ISR_ZONE,
+ ven_rsi_dbg(ISR_ZONE,
  "Unknown Interrupt %x\n",
  isr_status);
  break;
@@ -359,13 +376,22 @@ int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
  (struct rsi_91x_sdiodev *)adapter->rsi_dev;
  u8 buf_status = 0;
  int status = 0;
+#if 0
+ static int counter = 4;
+
+ if ((!dev->buff_status_updated) && counter) {
+ counter--;
+ goto out;
+ }
+#endif
 
+ dev->buff_status_updated = 0;
  status = rsi_sdio_read_register(common->priv,
  RSI_DEVICE_BUFFER_STATUS_REGISTER,
  &buf_status);
 
  if (status) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed to read status register\n", __func__);
  return -1;
  }
@@ -393,7 +419,9 @@ int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
  } else {
  dev->rx_info.semi_buffer_full = false;
  }
+// (dev->rx_info.semi_buffer_full ? (counter = 4) : (counter = 1));
 
+out:
  if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))
  return QUEUE_FULL;
 
diff --git a/ubuntu/rsi/rsi_91x_usb.c b/ubuntu/rsi/rsi_91x_usb.c
index 907adb8..dc5cb89 100644
--- a/ubuntu/rsi/rsi_91x_usb.c
+++ b/ubuntu/rsi/rsi_91x_usb.c
@@ -64,12 +64,12 @@ static int rsi_usb_card_write(struct rsi_hw *adapter,
       &transfer,
       HZ * 5);
  if (status < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Card write failed with error code :%d\n", status);
  dev->write_fail = 1;
  goto fail;
  }
- rsi_dbg(MGMT_TX_ZONE, "%s: Sent Message successfully\n", __func__);
+ ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sent Message successfully\n", __func__);
 
 fail:
  return status;
@@ -94,7 +94,7 @@ static int rsi_write_multiple(struct rsi_hw *adapter,
  (struct rsi_91x_usbdev *)adapter->rsi_dev;
 
  if (!adapter || addr == 0) {
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "%s: Unable to write to card\n", __func__);
  return -1;
  }
@@ -141,7 +141,7 @@ static int rsi_usb_reg_read(struct usb_device *usbdev,
 
  *value = (buf[0] | (buf[1] << 8));
  if (status < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Reg read failed with error code :%d\n",
  __func__, status);
  }
@@ -185,7 +185,7 @@ static int rsi_usb_reg_write(struct usb_device *usbdev,
  len,
  USB_CTRL_SET_TIMEOUT);
  if (status < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Reg write failed with error code :%d\n",
  __func__, status);
  }
@@ -235,7 +235,7 @@ int rsi_usb_read_register_multiple(struct rsi_hw *adapter,
  transfer,
  USB_CTRL_GET_TIMEOUT);
  if (status < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Reg read failed with error code :%d\n",
  status);
  kfree(buf);
@@ -293,7 +293,7 @@ int rsi_usb_write_register_multiple(struct rsi_hw *adapter,
  transfer,
  USB_CTRL_SET_TIMEOUT);
  if (status < 0) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "Reg write failed with error code :%d\n",
  status);
  kfree(buf);
@@ -324,7 +324,7 @@ static void rsi_rx_done_handler(struct urb *urb)
  return;
 
  if (urb->actual_length <= 0) {
- rsi_dbg(INFO_ZONE, "%s: Zero length packet\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Zero length packet\n", __func__);
  return;
  }
  rx_cb->pend = 1;
@@ -356,7 +356,7 @@ static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num)
 
  status = usb_submit_urb(urb, GFP_KERNEL);
  if (status)
- rsi_dbg(ERR_ZONE, "%s: Failed in urb submission\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in urb submission\n", __func__);
 
  return status;
 }
@@ -377,7 +377,7 @@ int rsi_usb_host_intf_write_pkt(struct rsi_hw *adapter,
  u32 queueno = ((pkt[1] >> 4) & 0x7);
  u8 endpoint;
 
- rsi_dbg(DATA_TX_ZONE, "%s: queueno=%d\n", __func__, queueno);
+ ven_rsi_dbg(DATA_TX_ZONE, "%s: queueno=%d\n", __func__, queueno);
  endpoint = ((queueno == RSI_WIFI_MGMT_Q || queueno == RSI_COEX_Q ||
      queueno == RSI_WIFI_DATA_Q) ?
     MGMT_EP : DATA_EP);
@@ -421,7 +421,7 @@ int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
  u8  temp_buf[256];
 
  num_blocks = instructions_sz / block_size;
- rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
+ ven_rsi_dbg(INFO_ZONE, "num_blocks: %d\n", num_blocks);
 
  for (cur_indx = 0, ii = 0;
      ii < num_blocks;
@@ -434,7 +434,7 @@ int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
      block_size)) < 0)
  return -1;
 
- rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, ii);
+ ven_rsi_dbg(INFO_ZONE, "%s: loading block: %d\n", __func__, ii);
  base_address += block_size;
  }
 
@@ -447,7 +447,7 @@ int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
      (u8 *)temp_buf,
      instructions_sz % block_size)) < 0)
  return -1;
- rsi_dbg(INFO_ZONE,
+ ven_rsi_dbg(INFO_ZONE,
  "Written Last Block in Address 0x%x Successfully\n",
  cur_indx);
  }
@@ -464,12 +464,12 @@ static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
 {
  struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 
- rsi_dbg(INFO_ZONE, "Deinitializing USB interface...\n");
+ ven_rsi_dbg(INFO_ZONE, "Deinitializing USB interface...\n");
 
  rsi_kill_thread(&dev->rx_thread);
  kfree(dev->rx_cb[0].rx_buffer);
  usb_free_urb(dev->rx_cb[0].rx_urb);
-#ifdef CONFIG_VEN_RSI_HCI
+#if defined (CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
  kfree(dev->rx_cb[1].rx_buffer);
  usb_free_urb(dev->rx_cb[1].rx_urb);
 #endif
@@ -556,7 +556,7 @@ static int rsi_usb_init_rx(struct rsi_hw *adapter)
 
  rx_cb->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
  if (!rx_cb->rx_urb) {
- rsi_dbg(ERR_ZONE, "Failed alloc rx urb[%d]\n", idx);
+ ven_rsi_dbg(ERR_ZONE, "Failed alloc rx urb[%d]\n", idx);
  goto err;
  }
  rx_cb->rx_urb->transfer_buffer = rx_cb->rx_buffer;
@@ -614,7 +614,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
 
  /* Initialize RX handle */
  if (rsi_usb_init_rx(adapter)) {
- rsi_dbg(ERR_ZONE, "Failed to init RX handle\n");
+ ven_rsi_dbg(ERR_ZONE, "Failed to init RX handle\n");
  goto fail_1;
  }
 
@@ -632,7 +632,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
  status = rsi_create_kthread(common, &rsi_dev->rx_thread,
     rsi_usb_rx_thread, "RX-Thread");
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
  goto fail_2;
  }
 
@@ -642,7 +642,7 @@ static int rsi_init_usb_interface(struct rsi_hw *adapter,
  adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES - 1;
 #endif
 
- rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Enabled the interface\n", __func__);
  return 0;
 
 fail_2:
@@ -710,7 +710,7 @@ static int rsi_reset_card(struct rsi_hw *adapter)
 {
  u16 temp[4] = {0};
 
- rsi_dbg(INFO_ZONE, "Resetting Card...\n");
+ ven_rsi_dbg(INFO_ZONE, "Resetting Card...\n");
 
 #define TA_HOLD_REG 0x22000844
  rsi_usb_master_reg_write(adapter, TA_HOLD_REG, 0xE, 4);
@@ -749,11 +749,11 @@ static int rsi_reset_card(struct rsi_hw *adapter)
  temp, 32)) < 0) {
  goto fail;
  }
- rsi_dbg(INFO_ZONE, "Card Reset Done\n");
+ ven_rsi_dbg(INFO_ZONE, "Card Reset Done\n");
  return 0;
 
 fail:
- rsi_dbg(ERR_ZONE, "Reset card Failed\n");
+ ven_rsi_dbg(ERR_ZONE, "Reset card Failed\n");
  return -1;
 }
 
@@ -774,11 +774,11 @@ static int rsi_probe(struct usb_interface *pfunction,
  u32 fw_status = 0;
  int status = 0;
 
- rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
 
- adapter = rsi_91x_init();
+ adapter = ven_rsi_91x_init();
  if (!adapter) {
- rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to init os intf ops\n",
  __func__);
  return -ENOMEM;
  }
@@ -786,12 +786,12 @@ static int rsi_probe(struct usb_interface *pfunction,
 
  status = rsi_init_usb_interface(adapter, pfunction);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed to init usb interface\n",
  __func__);
  goto err;
  }
 
- rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__);
+ ven_rsi_dbg(ERR_ZONE, "%s: Initialized os intf ops\n", __func__);
 
  dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 
@@ -802,21 +802,21 @@ static int rsi_probe(struct usb_interface *pfunction,
  fw_status &= 1;
 
  if (!fw_status) {
- rsi_dbg(INIT_ZONE, "Loading firmware...\n");
+ ven_rsi_dbg(INIT_ZONE, "Loading firmware...\n");
  status = rsi_hal_device_init(adapter);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in device init\n",
  __func__);
  goto err1;
  }
- rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
+ ven_rsi_dbg(INIT_ZONE, "%s: Device Init Done\n", __func__);
  }
 
  status = rsi_rx_urb_submit(adapter, 1 /* RX_WLAN_EP */);  
  if (status)
  goto err1;
 
-#ifdef CONFIG_VEN_RSI_HCI
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
  status = rsi_rx_urb_submit(adapter, 2 /* RX_BT_EP */);
  if (status)
  goto err1;
@@ -826,8 +826,8 @@ static int rsi_probe(struct usb_interface *pfunction,
 err1:
  rsi_deinit_usb_interface(adapter);
 err:
- rsi_91x_deinit(adapter);
- rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
+ ven_rsi_91x_deinit(adapter);
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
  return status;
 }
 
@@ -844,22 +844,22 @@ static void rsi_disconnect(struct usb_interface *pfunction)
  if (!adapter)
  return;
 
- rsi_mac80211_detach(adapter);
- rsi_dbg(INFO_ZONE, "mac80211 detach done\n");
-
- rsi_reset_card(adapter);
+ ven_rsi_mac80211_detach(adapter);
+ ven_rsi_dbg(INFO_ZONE, "mac80211 detach done\n");
 
-#ifdef CONFIG_VEN_RSI_HCI
-        rsi_hci_detach(adapter->priv);
- rsi_dbg(INFO_ZONE, "HCI Detach Done\n");
+#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
+ rsi_hci_detach(adapter->priv);
+ ven_rsi_dbg(INFO_ZONE, "HCI Detach Done\n");
 #endif
 
+ rsi_reset_card(adapter);
+
  rsi_deinit_usb_interface(adapter);
- rsi_dbg(INFO_ZONE, "USB interface down\n");
+ ven_rsi_dbg(INFO_ZONE, "USB interface down\n");
 
- rsi_91x_deinit(adapter);
+ ven_rsi_91x_deinit(adapter);
 
- rsi_dbg(INFO_ZONE, "%s: Deinitialization completed\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Deinitialization completed\n", __func__);
 }
 
 #ifdef CONFIG_PM
@@ -898,7 +898,7 @@ static struct usb_driver rsi_driver = {
 
 static int __init rsi_usb_module_init(void)
 {
- rsi_dbg(INIT_ZONE,
+ ven_rsi_dbg(INIT_ZONE,
  "=====> RSI USB Module Initialize <=====\n");
  return usb_register(&rsi_driver);
 }
diff --git a/ubuntu/rsi/rsi_91x_usb_ops.c b/ubuntu/rsi/rsi_91x_usb_ops.c
index a9ac168..5d61091 100644
--- a/ubuntu/rsi/rsi_91x_usb_ops.c
+++ b/ubuntu/rsi/rsi_91x_usb_ops.c
@@ -44,9 +44,9 @@ void rsi_usb_rx_thread(struct rsi_common *common)
  continue;
 
  mutex_lock(&common->rx_lock);
- status = rsi_read_pkt(common, rx_cb->rx_buffer, 0);
+ status = ven_rsi_read_pkt(common, rx_cb->rx_buffer, 0);
  if (status) {
- rsi_dbg(ERR_ZONE, "%s: Failed To read data",
+ ven_rsi_dbg(ERR_ZONE, "%s: Failed To read data",
  __func__);
  mutex_unlock(&common->rx_lock);
  break;
@@ -55,7 +55,7 @@ void rsi_usb_rx_thread(struct rsi_common *common)
  mutex_unlock(&common->rx_lock);
 
  if (adapter->rx_urb_submit(adapter, rx_cb->ep_num)) {
- rsi_dbg(ERR_ZONE,
+ ven_rsi_dbg(ERR_ZONE,
  "%s: Failed in urb submission", __func__);
  break;
  }
@@ -64,7 +64,7 @@ void rsi_usb_rx_thread(struct rsi_common *common)
 
  } while (1);
 
- rsi_dbg(INFO_ZONE, "%s: Terminated USB RX thread\n", __func__);
+ ven_rsi_dbg(INFO_ZONE, "%s: Terminated USB RX thread\n", __func__);
  atomic_inc(&dev->rx_thread.thread_done);
  complete_and_exit(&dev->rx_thread.completion, 0);
 }
diff --git a/ubuntu/rsi/rsi_coex.h b/ubuntu/rsi/rsi_coex.h
index c9fbb60..027bc77 100644
--- a/ubuntu/rsi/rsi_coex.h
+++ b/ubuntu/rsi/rsi_coex.h
@@ -21,6 +21,7 @@
 
 #define RSI_COEX_TXQ_MAX_PKTS 64
 #define RSI_COEX_TXQ_WATER_MARK 50
+#define COMMON_CARD_READY_IND           0
 
 #define COEX_Q 0
 #define BT_Q 1
@@ -39,14 +40,14 @@ enum rsi_proto {
 struct rsi_coex_ctrl_block {
  struct rsi_common *priv;
  struct sk_buff_head coex_tx_qs[NUM_COEX_TX_QUEUES];
-
+ struct semaphore tx_bus_lock;
  struct rsi_thread coex_tx_thread;
- struct mutex coex_tx_lock;
 };
 
 int rsi_coex_init(struct rsi_common *common);
-int rsi_coex_send_pkt(struct rsi_common *common,
+int rsi_coex_send_pkt(struct rsi_common *common,
       struct sk_buff *skb,
       u8 proto_type);
-
+int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg);
+void rsi_coex_deinit(struct rsi_common *common);
 #endif
diff --git a/ubuntu/rsi/rsi_common.h b/ubuntu/rsi/rsi_common.h
index a10e32c..5067af9 100644
--- a/ubuntu/rsi/rsi_common.h
+++ b/ubuntu/rsi/rsi_common.h
@@ -80,12 +80,14 @@ static inline int rsi_kill_thread(struct rsi_thread *handle)
  return kthread_stop(handle->task);
 }
 
-void rsi_mac80211_detach(struct rsi_hw *hw);
+void ven_rsi_mac80211_detach(struct rsi_hw *hw);
 u16 rsi_get_connected_channel(struct rsi_hw *adapter);
-struct rsi_hw *rsi_91x_init(void);
-void rsi_91x_deinit(struct rsi_hw *adapter);
-int rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len);
+struct rsi_hw *ven_rsi_91x_init(void);
+void ven_rsi_91x_deinit(struct rsi_hw *adapter);
+int ven_rsi_read_pkt(struct rsi_common *common, u8 *rx_pkt, s32 rcv_pkt_len);
 void rsi_indicate_bcnmiss(struct rsi_common *common);
 void rsi_resume_conn_channel(struct rsi_hw *adapter);
 void rsi_hci_detach(struct rsi_common *common);
+inline char *dot11_pkt_type(__le16 frame_control);
+struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr);
 #endif
diff --git a/ubuntu/rsi/rsi_debugfs.h b/ubuntu/rsi/rsi_debugfs.h
index 7b7e75f..7ca8dc4 100644
--- a/ubuntu/rsi/rsi_debugfs.h
+++ b/ubuntu/rsi/rsi_debugfs.h
@@ -14,8 +14,8 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef __RSI_DEBUGFS_H__
-#define __RSI_DEBUGFS_H__
+#ifndef __VEN_RSI_DEBUGFS_H__
+#define __VEN_RSI_DEBUGFS_H__
 
 #include "rsi_main.h"
 #include <linux/debugfs.h>
diff --git a/ubuntu/rsi/rsi_hal.h b/ubuntu/rsi/rsi_hal.h
index 4b554cd..d3b1798 100644
--- a/ubuntu/rsi/rsi_hal.h
+++ b/ubuntu/rsi/rsi_hal.h
@@ -145,8 +145,11 @@ struct ta_metadata {
  unsigned int address;
 };
 
+int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb);
+int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb);
 int rsi_hal_device_init(struct rsi_hw *adapter);
 int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
 int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb);
+int rsi_send_beacon(struct rsi_common *common);
 
 #endif
diff --git a/ubuntu/rsi/rsi_hci.h b/ubuntu/rsi/rsi_hci.h
index 08f7e1e..d7fe052 100644
--- a/ubuntu/rsi/rsi_hci.h
+++ b/ubuntu/rsi/rsi_hci.h
@@ -93,13 +93,11 @@ struct rsi_hci_adapter {
  struct hci_dev *hdev;
  struct genl_cb *gcb;
  struct sk_buff_head hci_tx_queue;
- int fsm_state;
 };
 
 int rsi_genl_recv (struct sk_buff *skb, struct genl_info *info);
 int rsi_hci_attach (struct rsi_common *common);
 void rsi_hci_detach(struct rsi_common *common);
-//int rsi_hci_recv_pkt(struct rsi_hci_adapter *h_adapter, u8 *pkt);
 int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt);
 
 #endif
diff --git a/ubuntu/rsi/rsi_main.h b/ubuntu/rsi/rsi_main.h
index 183b412..09b9c82 100644
--- a/ubuntu/rsi/rsi_main.h
+++ b/ubuntu/rsi/rsi_main.h
@@ -28,7 +28,7 @@ struct rsi_hw;
 #include "rsi_ps.h"
 
 #define ERR_ZONE                        BIT(0) /* Error Msgs */
-#define INFO_ZONE                       BIT(1) /* General Debug Msgs */
+#define INFO_ZONE                       BIT(1) /* Generic Debug Msgs */
 #define INIT_ZONE                       BIT(2) /* Driver Init Msgs */
 #define MGMT_TX_ZONE                    BIT(3) /* TX Mgmt Path Msgs */
 #define MGMT_RX_ZONE                    BIT(4) /* RX Mgmt Path Msgs */
@@ -47,8 +47,8 @@ struct rsi_hw;
 #define FSM_BB_RF_PROG_SENT             7
 #define FSM_MAC_INIT_DONE               8
 
-extern u32 rsi_zone_enabled;
-extern __printf(2, 3) void rsi_dbg(u32 zone, const char *fmt, ...);
+extern u32 ven_rsi_zone_enabled;
+extern __printf(2, 3) void ven_rsi_dbg(u32 zone, const char *fmt, ...);
 void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len);
 
 #define RSI_MAX_VIFS                    1
@@ -73,7 +73,6 @@ void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len);
     */
 #define BROADCAST_HW_Q 9
 #define BEACON_HW_Q 11
-#define MAX_NUM_SCAN_BGCHANS 24
 
 /* Queue information */
 #define RSI_COEX_Q 0x0
@@ -87,10 +86,13 @@ void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len);
 #define IEEE80211_MGMT_FRAME            0x00
 #define IEEE80211_CTL_FRAME             0x04
 
+#define RSI_MAX_ASSOC_STAS 4
 #define IEEE80211_QOS_TID               0x0f
 #define IEEE80211_NONQOS_TID            16
 
 #define MAX_DEBUGFS_ENTRIES             5
+#define MAX_BGSCAN_CHANNELS 38
+
 
 #define TID_TO_WME_AC(_tid) (      \
  ((_tid) == 0 || (_tid) == 3) ? BE_Q : \
@@ -117,6 +119,8 @@ struct skb_info {
  u16 channel;
  s8 tid;
  s8 sta_id;
+ u8 internal_hdr_size;
+ struct ieee80211_sta *sta;
 };
 
 enum edca_queue {
@@ -174,11 +178,13 @@ struct bgscan_config_params {
  u16 bgscan_threshold;
  u16 roam_threshold;
  u16 bgscan_periodicity;
+ u8 num_user_channels;
  u8 num_bg_channels;
  u8 two_probe;
  u16 active_scan_duration;
  u16 passive_scan_duration;
- u16 channels2scan[MAX_NUM_SCAN_BGCHANS];
+ u16 user_channels[MAX_BGSCAN_CHANNELS];
+ u16 channels2scan[MAX_BGSCAN_CHANNELS];
 };
 
 struct xtended_desc {
@@ -187,6 +193,12 @@ struct xtended_desc {
  u16 reserved;
 };
 
+struct rsi_sta {
+ struct ieee80211_sta *sta;
+ s16 sta_id;
+ u16 seq_no[IEEE80211_NUM_ACS];
+};
+
 struct rsi_hw;
 
 struct rsi_common {
@@ -198,6 +210,7 @@ struct rsi_common {
  struct version_info fw_ver;
 
  struct rsi_thread tx_thread;
+ struct rsi_thread hci_thread;
  struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 1];
  /* Mutex declaration */
  struct mutex mutex;
@@ -224,6 +237,7 @@ struct rsi_common {
 
  /* state related */
  u32 fsm_state;
+ u8 bt_fsm_state;
  bool init_done;
  u8 bb_rf_prog_count;
  bool iface_down;
@@ -274,13 +288,23 @@ struct rsi_common {
  int tx_power;
  u8 ant_in_use;
 
-#ifdef CONFIG_VEN_RSI_HCI
+#if defined (CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
  void *hci_adapter;
 #endif
 
 #ifdef CONFIG_VEN_RSI_COEX
  void *coex_cb;
 #endif
+
+ /* AP mode related */
+ u8 *beacon_frame;
+ u16 beacon_frame_len;
+ u16 beacon_cnt;
+ u8 dtim_cnt;
+ u16 bc_mc_seqno;
+ struct rsi_sta stations[RSI_MAX_ASSOC_STAS + 1];
+ u8 num_stations;
+ struct ieee80211_channel *ap_channel;
 };
 
 enum host_intf {
@@ -326,7 +350,7 @@ struct rsi_hw {
  enum ps_state ps_state;
  struct rsi_ps_info ps_info;
  spinlock_t ps_lock;
-
+ u32 isr_pending;
 #ifdef CONFIG_VEN_RSI_DEBUGFS
  struct rsi_debugfs *dfsentry;
  u8 num_debugfs_entries;
@@ -342,12 +366,15 @@ struct rsi_hw {
  u32 interrupt_status;
 
  u8 dfs_region;
+ char country[2];
  void *rsi_dev;
 
  struct rsi_host_intf_ops *host_intf_ops;
  int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
  int (*rx_urb_submit)(struct rsi_hw *adapter, u8 ep_num);
  int (*determine_event_timeout)(struct rsi_hw *adapter);
+ void (*process_isr_hci)(struct rsi_hw *adapter);
+ int  (*check_intr_status_reg)(struct rsi_hw *adapter);
 };
 
 struct rsi_host_intf_ops {
diff --git a/ubuntu/rsi/rsi_mgmt.h b/ubuntu/rsi/rsi_mgmt.h
index 4b85e4d..ece9b40 100644
--- a/ubuntu/rsi/rsi_mgmt.h
+++ b/ubuntu/rsi/rsi_mgmt.h
@@ -66,6 +66,10 @@ enum rx_cmd_type {
  ANTENNA_SELECT = 0xf,
 };
 
+#ifdef RSI_ENABLE_WOW
+#define WOW_MAX_FILTERS_PER_LIST 16
+#define WOW_PATTERN_SIZE 256
+#endif
 #define EAPOL4_CONFIRM 1
 #define PROBEREQ_CONFIRM                2
 #define NULLDATA_CONFIRM 3
@@ -80,9 +84,12 @@ enum rx_cmd_type {
 #define BBP_REG_WRITE                   0
 #define RF_RESET_ENABLE                 BIT(3)
 #define RATE_INFO_ENABLE                BIT(0)
+#define MORE_DATA_PRESENT BIT(1)
 #define RSI_BROADCAST_PKT               BIT(9)
 #define RSI_DESC_11G_MODE BIT(7)
 #define RSI_DESC_REQUIRE_CFM_TO_HOST BIT(10)
+#define ADD_DELTA_TSF_VAP_ID BIT(11)
+#define FETCH_RETRY_CNT_FRM_HST BIT(12)
 
 #define UPPER_20_ENABLE                 (0x2 << 12)
 #define LOWER_20_ENABLE                 (0x4 << 12)
@@ -202,9 +209,28 @@ enum rx_cmd_type {
  IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
 #define IEEE80211_STA_SP_ALL_PKTS 0x00
 
+/* Tx data frame format */
+#define MAC_BBP_INFO BIT(0)
+#define NO_ACK_IND BIT(9)
+#define QOS_EN BIT(12)
+/* frame type bit{11:10} */
+#define NORMAL_FRAME 0x00
+#define DTIM_BEACON_GATED_FRAME BIT(10)
+#define BEACON_FRAME BIT(11)
+#define DTIM_BEACON BIT(10) | BIT(11)
+#define INSERT_TSF BIT(15)
+#define INSERT_SEQ_NO BIT(2)
+
+#ifdef CONFIG_PM
+#define RSI_WOW_ANY                      BIT(0)
+#define RSI_WOW_SUPPORTS_GTK_REKEY       BIT(3)
+#define RSI_WOW_MAGIC_PKT                BIT(4)
+#define RSI_WOW_DISCONNECT               BIT(5)
+#endif
+
 enum opmode {
+ AP_OPMODE,
  STA_OPMODE = 1,
- AP_OPMODE = 2
 };
 
 enum vap_status {
@@ -213,6 +239,14 @@ enum vap_status {
  VAP_UPDATE = 3
 };
 
+enum peer_type {
+ PEER_TYPE_AP,
+ PEER_TYPE_STA,
+ PEER_TYPE_P2P_GO,
+ PEER_TYPE_P2P_CLIENT,
+ PEER_TYPE_IBSS
+};
+
 /*
  * Subtypes for RX_MISC_IND frame
  * Frame sub types from LMAC to Host
@@ -337,7 +371,7 @@ struct rsi_bgscan_params {
  u8 two_probe;
  __le16 active_scan_duration;
  __le16 passive_scan_duration;
- __le16 channels2scan[MAX_NUM_SCAN_BGCHANS];
+ __le16 channels2scan[MAX_BGSCAN_CHANNELS];
 } __packed;
 
 struct rsi_bgscan_probe {
@@ -456,6 +490,14 @@ struct rsi_request_ps {
  u16 ps_num_dtim_intervals;
 } __packed;
 
+struct rsi_wowlan_req {
+ __le16 desc_word[8];
+ u8 sourceid[ETH_ALEN];
+ u16 wow_flags;
+ u16 host_sleep_status;
+} __packed;
+
+
 static inline u32 rsi_get_queueno(u8 *addr, u16 offset)
 {
  return (le16_to_cpu(*(__le16 *)&addr[offset]) & 0x7000) >> 12;
@@ -487,13 +529,14 @@ int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
 int rsi_send_aggr_params_frame(struct rsi_common *common, u16 tid,
        u16 ssn, u8 buf_size, u8 event);
 int rsi_load_key(struct rsi_common *common, u8 *data, u16 key_len,
- u8 key_type, u8 key_id, u32 cipher);
+ u8 key_type, u8 key_id, u32 cipher, s16 sta_id);
 int rsi_set_channel(struct rsi_common *common,
     struct ieee80211_channel *channel);
 int rsi_send_vap_dynamic_update(struct rsi_common *common);
 int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
-void rsi_inform_bss_status(struct rsi_common *common, u8 status,
-   const u8 *bssid, u8 qos_enable, u16 aid);
+void rsi_inform_bss_status(struct rsi_common *common, enum opmode opmode,
+   u8 status, u8 *bssid, u8 qos_enable, u16 aid,
+   u16 sta_id);
 void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb);
 int rsi_mac80211_attach(struct rsi_common *common);
 int rsi_send_bgscan_params(struct rsi_common *common, int enable);
@@ -513,5 +556,9 @@ int rsi_send_radio_params_update(struct rsi_common *common);
 void init_bgscan_params(struct rsi_common *common);
 int rsi_set_antenna(struct rsi_common *common, u8 antenna);
 int rsi_hci_attach(struct rsi_common *common);
-
+int rsi_handle_card_ready(struct rsi_common *common);
+#ifdef CONFIG_RSI_WOW
+int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
+    struct cfg80211_wowlan *wowlan);
+#endif
 #endif
diff --git a/ubuntu/rsi/rsi_sdio.h b/ubuntu/rsi/rsi_sdio.h
index 315a506..d043668 100644
--- a/ubuntu/rsi/rsi_sdio.h
+++ b/ubuntu/rsi/rsi_sdio.h
@@ -112,7 +112,7 @@ struct receive_info {
 
 struct rsi_91x_sdiodev {
  struct sdio_func *pfunction;
- struct task_struct *in_sdio_litefi_irq;
+ struct task_struct *sdio_irq_task;
  struct receive_info rx_info;
  u32 next_read_delay;
  u32 sdio_high_speed_enable;
@@ -121,6 +121,7 @@ struct rsi_91x_sdiodev {
  u8 prev_desc[16];
  u32 tx_blk_size;
  u8 write_fail;
+ u8 buff_status_updated;
 };
 
 void rsi_interrupt_handler(struct rsi_hw *adapter);
@@ -149,4 +150,5 @@ int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
 void rsi_sdio_ack_intr(struct rsi_hw *adapter, u8 int_bit);
 int rsi_sdio_determine_event_timeout(struct rsi_hw *adapter);
 int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num);
+int rsi_read_intr_status_reg(struct rsi_hw *adapter);
 #endif
diff --git a/ubuntu/rsi/rsi_usb.h b/ubuntu/rsi/rsi_usb.h
index a202e70..a5de80a 100644
--- a/ubuntu/rsi/rsi_usb.h
+++ b/ubuntu/rsi/rsi_usb.h
@@ -29,7 +29,7 @@
 #define RSI_USB_TX_HEAD_ROOM         128
 
 #define MAX_TX_URBS                  1
-#ifdef CONFIG_VEN_RSI_HCI
+#if defined (CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
 #define MAX_RX_URBS                  2
 #else
 #define MAX_RX_URBS                  1
--
2.9.3


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

[PATCH v2 4/4][Xenial SRU] UBUNTU: SAUCE: RS9113: Use vendor driver to support WLAN/BT card on Caracalla HW only

Shrirang Bagul
In reply to this post by Shrirang Bagul
BugLink: http://bugs.launchpad.net/bugs/1657682

This patch limits the RS9113 driver from vendor to be used for the WLAN/BT
card mounted on Dell Caracalla IoT gateways.

Signed-off-by: Shrirang Bagul <[hidden email]>
---
 ubuntu/rsi/rsi_91x_sdio.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
index 496d3b5..15083e5 100644
--- a/ubuntu/rsi/rsi_91x_sdio.c
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -1221,9 +1221,11 @@ static const struct dev_pm_ops rsi_pm_ops = {
 #endif
 
 static const struct sdio_device_id rsi_dev_table[] =  {
+#if 0
  { SDIO_DEVICE(0x303, 0x100) },
  { SDIO_DEVICE(0x041B, 0x0301) },
  { SDIO_DEVICE(0x041B, 0x0201) },
+#endif
  { SDIO_DEVICE(0x041B, 0x9330) },
  { /* Blank */},
 };
--
2.9.3


--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK w/cmt: [PATCH v2 0/4][Xenial SRU] UBUNTU: SAUCE: Support latest Redpine WLAN/BT RS9113 driver

Tim Gardner-2
In reply to this post by Shrirang Bagul
This appears to be well isolated except that there is still a PCI ID
that will conflict with ubuntu/rsi/rsi_91x_sdio.c:

drivers/net/wireless/rsi/rsi_91x_usb.c: { USB_DEVICE(0x041B, 0x9330) },

Depending on load order is likely not the best approach, though I'm sure
it does work in this case. I'd still like to see that line commented out
in drivers/net/wireless/rsi/rsi_91x_usb.c

rtg
--
Tim Gardner [hidden email]

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

ACK w/cmt: [PATCH v2 0/4][Xenial SRU] UBUNTU: SAUCE: Support latest Redpine WLAN/BT RS9113 driver

Brad Figg-2
In reply to this post by Shrirang Bagul

I agree with Tim's comment.

--
Brad Figg [hidden email] http://www.canonical.com

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team
Reply | Threaded
Open this post in threaded view
|

APPLIED: [PATCH v2 0/4][Xenial SRU] UBUNTU: SAUCE: Support latest Redpine WLAN/BT RS9113 driver

Luis Henriques
In reply to this post by Shrirang Bagul
Applied to xenial master-next branch.  Added an extra patch (see below) to
address reviewers comments.

Cheers,
--
Luís

From 508f695b636c91de213b3eeaad2d45f302b45349 Mon Sep 17 00:00:00 2001
From: Luis Henriques <[hidden email]>
Date: Fri, 20 Jan 2017 15:15:11 +0000
Subject: [PATCH] UBUNTU: SAUCE: RS9113: Comment out IDs from upstream driver

BugLink: http://bugs.launchpad.net/bugs/1657682

Signed-off-by: Luis Henriques <[hidden email]>
---
 drivers/net/wireless/rsi/rsi_91x_sdio.c | 2 +-
 drivers/net/wireless/rsi/rsi_91x_usb.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 8428858204a6..e3b8d7e7bdb5 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -796,7 +796,7 @@ static const struct sdio_device_id rsi_dev_table[] =  {
  { SDIO_DEVICE(0x303, 0x100) },
  { SDIO_DEVICE(0x041B, 0x0301) },
  { SDIO_DEVICE(0x041B, 0x0201) },
- { SDIO_DEVICE(0x041B, 0x9330) },
+ /* { SDIO_DEVICE(0x041B, 0x9330) }, LP:#1657682 replaced by ubuntu/rsi/ */
  { /* Blank */},
 };
 
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c
index ef5d394f185b..dd2030558084 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb.c
@@ -553,7 +553,7 @@ static const struct usb_device_id rsi_dev_table[] = {
  { USB_DEVICE(0x0303, 0x0100) },
  { USB_DEVICE(0x041B, 0x0301) },
  { USB_DEVICE(0x041B, 0x0201) },
- { USB_DEVICE(0x041B, 0x9330) },
+ /* { USB_DEVICE(0x041B, 0x9330) }, LP:#1657682 replaced by ubuntu/rsi/ */
  { /* Blank */},
 };
 

--
kernel-team mailing list
[hidden email]
https://lists.ubuntu.com/mailman/listinfo/kernel-team