diff mbox

[1/4] UBUNTU: SAUCE: Support Redpine RS9113 WLAN/BT

Message ID 20170119091148.21278-2-shrirang.bagul@canonical.com
State New
Headers show

Commit Message

Shrirang Bagul Jan. 19, 2017, 9:11 a.m. UTC
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 <shrirang.bagul@canonical.com>
---
 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 mbox

Patch

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 <prameela.garnepudi@redpinesignals.com>
+ *
+ * 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 <prameela.garnepudi@redpinesignals.com>
+ *
+ * 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 <fariya.f@redpinesignals.com>
+ * 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 <prameela.garnepudi@redpinesignals.com>
+ *
+ * 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