diff mbox

UBUNTU: SAUCE: Redpine: Upgrade to version 1.2

Message ID 1500044194-3851-1-git-send-email-amitkarwar@gmail.com
State New
Headers show

Commit Message

Amitkumar Karwar July 14, 2017, 2:56 p.m. UTC
From: Amitkumar Karwar <amit.karwar@redpinesignals.com>

BugLink: https://bugs.launchpad.net/bugs/1697829

Vendor release ver: 1.2

Changelog:

1.2 -
 WLAN Supported Features:
 ------------------------
 1) Station mode
 2) 802.11bgn
 3) Secutiry modes: Open, WEP, WPA, WPA2
 4) AP mode
 5) Bgscan and roaming
 6) Legacy and UAPSD power save
 7) Regulatory support
 8) WoWLAN
 9) Management frame protection
 10) Wi-Fi direct mode

 WLAN Bug Fixes:
 ---------------
 1) WoWLAN from S5 fails (lp: #1686283)
 2) After wifi-ap is set, system will kernel panic (lp: #1699753)
 3) Connect to "n" AP will cause system kernel panic (lp: #1699686)
 4) Low throughput observed in some channels for TCP downlink traffic in
 Coex mode.

 WLAN Limitations/Features NOT Supported:
 ----------------------------------------
 1) For GTK rekey, wakeup trigger send to host.

 BT Supported Features:
 ----------------------
 1) BT EDR mode
 2) BT LE mode
 3) BT Coex mode
        * WLAN STA + BT EDR
        * WLAN STA + BT LE
        * WLAN STA + BT EDR + BT LE
        * WLAN AP + BT EDR
        * WLAN AP + BT EDR + BT LE

 BT Limitations/Features NOT Supported:
 ----------------------------------------
 1) To connect multiple BT slaves, connection should be initiated
 from rsi module.
 2) In coex mode, BT file transfer fails at times with certain mobiles.

1.2.RC16 -
 WLAN Bug Fixes:
 ---------------
 1. WoWLAN from S5 fails (lp: #1686283)
 2. After wifi-ap is set, system will kernel panic (lp: #1699753)
 3. Connect to "n" AP will cause system kernel panic (lp: #1699686)

 WLAN Limitations/Features NOT Supported:
 ----------------------------------------
 1) For GTK rekey, wakeup trigger send to host.
 2) Low throughput observed for TCP downlink traffic in Coex mode

 BT Limitations/Features NOT Supported:
 ----------------------------------------
 1) To connect multiple BT slaves, connection should be initiated
 from rsi module.
 2) In coex mode, BT file transfer fails at times with certain mobiles.

1.2.RC15 -
 WLAN Bug Fixes:
 ---------------
 1) Coverity scan fixes (lp: #1694733)
 2) Avoid driver reload at S4 resume

 BT Limitations/Features NOT Supported:
 ----------------------------------------
 1) To connect multiple BT slaves, connection should be initiated
 from rsi module.
 2) In coex mode, BT file transfer fails at times with certain mobiles.

1.2.RC14 -
 WLAN Bug Fixes:
 ---------------
 1) Low throughput with 40MHz issue resolved.

 WLAN Limitations/Features NOT Supported:
 ----------------------------------------
 1) S5 with WoWLAN does not work.
 2) For GTK rekey, wakeup trigger send to host.
 3) Low throughput observed for TCP downlink traffic in Coex mode

 BT Limitations/Features NOT Supported:
 ----------------------------------------
 1) To connect multiple BT slaves, connection should be initiated
 from rsi module.
 2) In coex mode, BT file transfer fails at times with certain mobiles.

Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
---
 ubuntu/rsi/rsi_91x_coex.c     |   1 +
 ubuntu/rsi/rsi_91x_core.c     |  16 +--
 ubuntu/rsi/rsi_91x_hal.c      |   6 +-
 ubuntu/rsi/rsi_91x_hci.c      |  19 ++--
 ubuntu/rsi/rsi_91x_mac80211.c | 193 +++++++++++++++++++----------------
 ubuntu/rsi/rsi_91x_mgmt.c     |  56 +++++------
 ubuntu/rsi/rsi_91x_sdio.c     | 228 +++++++++++++++++++++++++-----------------
 ubuntu/rsi/rsi_91x_sdio_ops.c |  71 ++++++++++---
 ubuntu/rsi/rsi_91x_usb.c      |  58 ++++++-----
 ubuntu/rsi/rsi_91x_usb_ops.c  |  34 +++----
 ubuntu/rsi/rsi_common.h       |   3 +
 ubuntu/rsi/rsi_main.h         |  26 ++---
 ubuntu/rsi/rsi_mgmt.h         |  12 +--
 ubuntu/rsi/rsi_sdio.h         |   9 ++
 ubuntu/rsi/rsi_usb.h          |   6 +-
 15 files changed, 440 insertions(+), 298 deletions(-)

Comments

Shrirang Bagul July 17, 2017, 1:58 a.m. UTC | #1
On Fri, 2017-07-14 at 20:26 +0530, Amitkumar Karwar wrote:
> From: Amitkumar Karwar <amit.karwar@redpinesignals.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1697829
> 
> Vendor release ver: 1.2
> 
> Changelog:
> 
> 1.2 -
>  WLAN Supported Features:
>  ------------------------
>  1) Station mode
>  2) 802.11bgn
>  3) Secutiry modes: Open, WEP, WPA, WPA2
>  4) AP mode
>  5) Bgscan and roaming
>  6) Legacy and UAPSD power save
>  7) Regulatory support
>  8) WoWLAN
>  9) Management frame protection
>  10) Wi-Fi direct mode
> 
>  WLAN Bug Fixes:
>  ---------------
>  1) WoWLAN from S5 fails (lp: #1686283)
>  2) After wifi-ap is set, system will kernel panic (lp: #1699753)
>  3) Connect to "n" AP will cause system kernel panic (lp: #1699686)
>  4) Low throughput observed in some channels for TCP downlink traffic in
>  Coex mode.
> 
>  WLAN Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) For GTK rekey, wakeup trigger send to host.
> 
>  BT Supported Features:
>  ----------------------
>  1) BT EDR mode
>  2) BT LE mode
>  3) BT Coex mode
>         * WLAN STA + BT EDR
>         * WLAN STA + BT LE
>         * WLAN STA + BT EDR + BT LE
>         * WLAN AP + BT EDR
>         * WLAN AP + BT EDR + BT LE
> 
>  BT Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) To connect multiple BT slaves, connection should be initiated
>  from rsi module.
>  2) In coex mode, BT file transfer fails at times with certain mobiles.
> 
> 1.2.RC16 -
>  WLAN Bug Fixes:
>  ---------------
>  1. WoWLAN from S5 fails (lp: #1686283)
>  2. After wifi-ap is set, system will kernel panic (lp: #1699753)
>  3. Connect to "n" AP will cause system kernel panic (lp: #1699686)
> 
>  WLAN Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) For GTK rekey, wakeup trigger send to host.
>  2) Low throughput observed for TCP downlink traffic in Coex mode
> 
>  BT Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) To connect multiple BT slaves, connection should be initiated
>  from rsi module.
>  2) In coex mode, BT file transfer fails at times with certain mobiles.
> 
> 1.2.RC15 -
>  WLAN Bug Fixes:
>  ---------------
>  1) Coverity scan fixes (lp: #1694733)
>  2) Avoid driver reload at S4 resume
> 
>  BT Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) To connect multiple BT slaves, connection should be initiated
>  from rsi module.
>  2) In coex mode, BT file transfer fails at times with certain mobiles.
> 
> 1.2.RC14 -
>  WLAN Bug Fixes:
>  ---------------
>  1) Low throughput with 40MHz issue resolved.
> 
>  WLAN Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) S5 with WoWLAN does not work.
>  2) For GTK rekey, wakeup trigger send to host.
>  3) Low throughput observed for TCP downlink traffic in Coex mode
> 
>  BT Limitations/Features NOT Supported:
>  ----------------------------------------
>  1) To connect multiple BT slaves, connection should be initiated
>  from rsi module.
>  2) In coex mode, BT file transfer fails at times with certain mobiles.
> 
> Signed-off-by: Amitkumar Karwar <amit.karwar@redpinesignals.com>
> ---
A version of this patch was already sent/applied for same bug report:

https://lists.ubuntu.com/archives/kernel-team/2017-July/085589.html

Shrirang
diff mbox

Patch

diff --git a/ubuntu/rsi/rsi_91x_coex.c b/ubuntu/rsi/rsi_91x_coex.c
index 5b3b3ac..51ec270 100644
--- a/ubuntu/rsi/rsi_91x_coex.c
+++ b/ubuntu/rsi/rsi_91x_coex.c
@@ -105,6 +105,7 @@  int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg)
 	u16 msg_type = msg[2];
 
 	if (msg_type == COMMON_CARD_READY_IND) {
+		common->hibernate_resume = false;
 		ven_rsi_dbg(INFO_ZONE, "COMMON CARD READY RECEIVED\n");
 		rsi_handle_card_ready(common, msg);
 	} else if (msg_type == SLEEP_NOTIFY_IND) {
diff --git a/ubuntu/rsi/rsi_91x_core.c b/ubuntu/rsi/rsi_91x_core.c
index db320e2..049f6ea 100644
--- a/ubuntu/rsi/rsi_91x_core.c
+++ b/ubuntu/rsi/rsi_91x_core.c
@@ -303,8 +303,8 @@  void rsi_core_qos_processor(struct rsi_common *common)
 			if ((q_num < MGMT_SOFT_Q) ||
 			    ((!adapter->peer_notify) &&
 			     (q_num == MGMT_SOFT_Q))) {
-			mutex_unlock(&common->tx_lock);
-			break;
+				mutex_unlock(&common->tx_lock);
+				break;
 			}
 		}
 
@@ -321,16 +321,16 @@  void rsi_core_qos_processor(struct rsi_common *common)
 		}
 
 		skb = rsi_core_dequeue_pkt(common, q_num);
-		if ((adapter->peer_notify) &&
-		    (skb->data[2] == PEER_NOTIFY)) {
-			adapter->peer_notify = false;
-			ven_rsi_dbg(INFO_ZONE, "%s RESET PEER_NOTIFY\n", __func__);
-		}
 		if (!skb) {
 			ven_rsi_dbg(ERR_ZONE, "skb null\n");
 			mutex_unlock(&common->tx_lock);
 			break;
 		}
+		if ((adapter->peer_notify) &&
+		    (skb->data[2] == PEER_NOTIFY)) {
+			adapter->peer_notify = false;
+			ven_rsi_dbg(INFO_ZONE, "%s RESET PEER_NOTIFY\n", __func__);
+		}
 #ifdef CONFIG_VEN_RSI_COEX
 		if (q_num == MGMT_BEACON_Q) {
 			status = rsi_send_pkt(common, skb);
@@ -343,7 +343,7 @@  void rsi_core_qos_processor(struct rsi_common *common)
 		else if(q_num == MGMT_BEACON_Q) {
 			status = rsi_send_pkt(common, skb);
 			dev_kfree_skb(skb);
-		} else 
+		} else
 			status = rsi_send_data_pkt(common, skb);
 #endif
 
diff --git a/ubuntu/rsi/rsi_91x_hal.c b/ubuntu/rsi/rsi_91x_hal.c
index 6b2be02..cccedaf 100644
--- a/ubuntu/rsi/rsi_91x_hal.c
+++ b/ubuntu/rsi/rsi_91x_hal.c
@@ -247,7 +247,7 @@  int rsi_prepare_mgmt_desc(struct rsi_common *common,struct sk_buff *skb)
 	struct rsi_hw *adapter = common->priv;
 	struct ieee80211_hdr *wh = NULL;
 	struct ieee80211_tx_info *info;
-	struct ieee80211_conf *conf = &adapter->hw->conf;
+	struct ieee80211_conf *conf;// = &adapter->hw->conf;
 	struct ieee80211_vif *vif = NULL;
 	struct skb_info *tx_params;
 	int status = -EINVAL;
@@ -257,6 +257,9 @@  int rsi_prepare_mgmt_desc(struct rsi_common *common,struct sk_buff *skb)
 	u8 vap_id = 0;
 	u32 dword_align_bytes = 0;
 
+	if (!adapter->hw)
+		goto err;
+	conf = &adapter->hw->conf;
 	info = IEEE80211_SKB_CB(skb);
 	tx_params = (struct skb_info *)info->driver_data;
 
@@ -1272,6 +1275,7 @@  int rsi_hal_device_init(struct rsi_hw *adapter)
 		return -EINVAL;
 	}
 	adapter->common_hal_fsm = COMMAN_HAL_WAIT_FOR_CARD_READY;
+	common->fsm_state = FSM_CARD_NOT_READY;
 
 #if defined(CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
 	adapter->priv->bt_fsm_state = BT_DEVICE_NOT_READY;
diff --git a/ubuntu/rsi/rsi_91x_hci.c b/ubuntu/rsi/rsi_91x_hci.c
index 5599622..d5f99fa 100644
--- a/ubuntu/rsi/rsi_91x_hci.c
+++ b/ubuntu/rsi/rsi_91x_hci.c
@@ -227,6 +227,7 @@  int rsi_send_rfmode_frame(struct rsi_common *common)
 {
 	struct sk_buff *skb;
 	struct rsi_bt_rfmode_frame *cmd_frame;
+	int status;
 
 	ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending BT RF mode frame\n", __func__);
 
@@ -246,7 +247,11 @@  int rsi_send_rfmode_frame(struct rsi_common *common)
 	skb_put(skb, sizeof(struct rsi_bt_rfmode_frame));
 
 //	return rsi_coex_send_pkt(common, skb, RSI_BT_Q);
-	return common->priv->host_intf_ops->write_pkt(common->priv, skb->data, skb->len);
+	status = common->priv->host_intf_ops->write_pkt(common->priv,
+							skb->data,
+							skb->len);
+	dev_kfree_skb(skb);
+	return status;
 }
 EXPORT_SYMBOL_GPL(rsi_send_rfmode_frame);
 
@@ -254,6 +259,7 @@  int rsi_deregister_bt(struct rsi_common *common)
 {
 	struct sk_buff *skb;
 	struct rsi_bt_cmd_frame *cmd_frame;
+	int status;
 
 	ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending BT register frame\n", __func__);
 
@@ -271,7 +277,11 @@  int rsi_deregister_bt(struct rsi_common *common)
 	skb_put(skb, sizeof(struct rsi_bt_cmd_frame));
 
 	//return rsi_coex_send_pkt(common, skb, RSI_BT_Q);
-	return common->priv->host_intf_ops->write_pkt(common->priv, skb->data, skb->len);
+	status = common->priv->host_intf_ops->write_pkt(common->priv,
+							skb->data,
+							skb->len);
+	dev_kfree_skb(skb);
+	return status;
 }
 EXPORT_SYMBOL_GPL(rsi_deregister_bt);
 
@@ -304,7 +314,7 @@  int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 
 		return 0;
 	}
- 
+
 	if (common->bt_fsm_state != BT_DEVICE_READY) {
 		ven_rsi_dbg(INFO_ZONE, "BT Device not ready\n");
 		return 0;
@@ -578,9 +588,6 @@  void rsi_hci_detach(struct rsi_common *common)
 	if (!h_adapter)
 		return;
 
-	if (common->suspend_in_prog)
-		rsi_deregister_bt(common);
-
 	hdev = h_adapter->hdev;
 	if (hdev) {
                 //hci_dev_hold(hdev);
diff --git a/ubuntu/rsi/rsi_91x_mac80211.c b/ubuntu/rsi/rsi_91x_mac80211.c
index 75aaa08..bc6f1bd 100644
--- a/ubuntu/rsi/rsi_91x_mac80211.c
+++ b/ubuntu/rsi/rsi_91x_mac80211.c
@@ -456,6 +456,9 @@  static void rsi_mac80211_hw_scan_cancel(struct ieee80211_hw *hw,
 void ven_rsi_mac80211_detach(struct rsi_hw *adapter)
 {
 	struct ieee80211_hw *hw = adapter->hw;
+#ifdef CONFIG_HW_SCAN_OFFLOAD
+	struct rsi_common *common = adapter->priv;
+#endif
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
 	enum nl80211_band band;
 #else
@@ -464,11 +467,15 @@  void ven_rsi_mac80211_detach(struct rsi_hw *adapter)
 
 	ven_rsi_dbg(INFO_ZONE, "Detach mac80211...\n");
 
+#ifdef CONFIG_HW_SCAN_OFFLOAD
+	flush_workqueue(common->scan_workqueue);
+#endif
 	if (hw) {
 		ieee80211_stop_queues(hw);
 		ieee80211_unregister_hw(hw);
 		ieee80211_free_hw(hw);
 		adapter->hw = NULL;
+		adapter->sc_nvifs = 0;
 	}
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
@@ -536,7 +543,7 @@  static void rsi_mac80211_tx(struct ieee80211_hw *hw,
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
 	struct ieee80211_hdr *wlh = (struct ieee80211_hdr *)skb->data;
-  struct ieee80211_vif *vif = adapter->vifs[adapter->sc_nvifs - 1];
+	struct ieee80211_vif *vif = adapter->vifs[adapter->sc_nvifs - 1];
 
 #ifdef CONFIG_VEN_RSI_WOW
 	if (common->wow_flags & RSI_WOW_ENABLED) {
@@ -549,15 +556,15 @@  static void rsi_mac80211_tx(struct ieee80211_hw *hw,
 		return;
 	}
 
-  if ((common->coex_mode == 4) &&
-      (vif->type == NL80211_IFTYPE_STATION) &&
-      ((ieee80211_is_probe_req(wlh->frame_control) ||
-       (ieee80211_is_auth(wlh->frame_control))))) {
-    ven_rsi_dbg(ERR_ZONE,
-        "Dropping Station packets in AP+BT dual mode\n");
-    ieee80211_free_txskb(common->priv->hw, skb);
-    return;
-  }
+	if ((common->coex_mode == 4) &&
+	    (vif->type == NL80211_IFTYPE_STATION) &&
+	    ((ieee80211_is_probe_req(wlh->frame_control) ||
+	      (ieee80211_is_auth(wlh->frame_control))))) {
+		ven_rsi_dbg(ERR_ZONE,
+			"Dropping Station packets in AP+BT dual mode\n");
+		ieee80211_free_txskb(common->priv->hw, skb);
+		return;
+	}
 
 #ifndef CONFIG_VEN_RSI_BT_ALONE
 	rsi_core_xmit(common, skb);
@@ -606,14 +613,9 @@  static void rsi_mac80211_stop(struct ieee80211_hw *hw)
 {
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
-	struct cfg80211_scan_info info;
-#endif
+	
 	ven_rsi_dbg(ERR_ZONE, "===> Interface DOWN <===\n");
 
-	if (common->fsm_state != FSM_MAC_INIT_DONE)
-		return;
-
 	mutex_lock(&common->mutex);
 	
 	common->iface_down = true;
@@ -625,7 +627,8 @@  static void rsi_mac80211_stop(struct ieee80211_hw *hw)
 	wiphy_rfkill_stop_polling(hw->wiphy);
 
 	/* Block all rx frames */
-	rsi_send_rx_filter_frame(common, 0xffff);
+	if (common->fsm_state == FSM_MAC_INIT_DONE)
+		rsi_send_rx_filter_frame(common, 0xffff);
 	
 	mutex_unlock(&common->mutex);
 }
@@ -862,26 +865,26 @@  static int rsi_mac80211_change_interface(struct ieee80211_hw *hw,
 			goto out;
 	}
 //	if (intf_mode == AP_OPMODE) {
-    rsi_set_vap_capabilities(common,
+		rsi_set_vap_capabilities(common,
 					 //STA_OPMODE,
 					 common->last_vap_type,
-        vif->addr,
-        vif_info->vap_id,
-        VAP_DELETE);
-    status = rsi_set_vap_capabilities(common,
-        intf_mode,
-        vif->addr,
-        vif_info->vap_id,
-        VAP_ADD);
+					 vif->addr,
+					 vif_info->vap_id,
+					 VAP_DELETE);
+		status = rsi_set_vap_capabilities(common,
+						  intf_mode,
+						  vif->addr,
+						  vif_info->vap_id,
+						  VAP_ADD);
 #if 0
-  } else if ((intf_mode != common->last_vap_type) ||
-      (!ether_addr_equal(vif->addr, common->last_vap_addr))) {
-    status = rsi_set_vap_capabilities(common,
-        intf_mode,
-        vif->addr,
-        vif_info->vap_id,
-        VAP_UPDATE);
-  }
+	} else if ((intf_mode != common->last_vap_type) ||
+		   (!ether_addr_equal(vif->addr, common->last_vap_addr))) {
+		status = rsi_set_vap_capabilities(common,
+						  intf_mode,
+						  vif->addr,
+						  vif_info->vap_id,
+						  VAP_UPDATE);
+	}
 #endif
 	if ((vif->type == NL80211_IFTYPE_AP) ||
 	    (vif->type == NL80211_IFTYPE_P2P_GO)) {
@@ -1460,7 +1463,7 @@  static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
 	case DISABLE_KEY:
 		if ((vif->type == NL80211_IFTYPE_STATION) ||
 		    (vif->type == NL80211_IFTYPE_P2P_CLIENT))
-		secinfo->security_enable = false;
+			secinfo->security_enable = false;
 		ven_rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
 		memset(key, 0, sizeof(struct ieee80211_key_conf));
 		status = rsi_hal_key_config(hw, vif, key, sta);
@@ -1489,6 +1492,7 @@  static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
  *
  * Return: status: 0 on success, negative error code on failure.
  */
+#ifndef CONFIG_CARACALLA_BOARD
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0))
 static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
@@ -1511,6 +1515,12 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 				     struct ieee80211_vif *vif,
 				     struct ieee80211_ampdu_params *params)
 #endif
+#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;
@@ -1520,7 +1530,7 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 	u8 ii = 0;
 	u8 sta_id = 0;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
+#if ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) || defined(CONFIG_CARACALLA_BOARD))
 	u16 tid = params->tid;
 	u8 buf_size = params->buf_size;
 	enum ieee80211_ampdu_mlme_action action = params->action;
@@ -1534,7 +1544,7 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 
 	mutex_lock(&common->mutex);
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0))
+#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4, 6, 0)) && !(defined(CONFIG_CARACALLA_BOARD)))
 	if (ssn != NULL)
 		seq_no = *ssn;
 #else
@@ -1886,12 +1896,12 @@  static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 			    ((common->key->cipher == WLAN_CIPHER_SUITE_WEP104) ||
 			    (common->key->cipher == WLAN_CIPHER_SUITE_WEP40))) {
 				rsi_load_key(adapter->priv,
-					      common->key->key,
-					      common->key->keylen,
-					      RSI_PAIRWISE_KEY,
-					      common->key->keyidx,
-					      common->key->cipher,
-					      i);
+					     common->key->key,
+					     common->key->keylen,
+					     RSI_PAIRWISE_KEY,
+					     common->key->keyidx,
+					     common->key->cipher,
+					     i);
 			}
 			for (j = 0; j < IEEE80211_NUM_ACS; j++)
 				common->stations[i].seq_no[j] = 1;
@@ -2026,7 +2036,7 @@  static void rsi_mac80211_sw_scan_start(struct ieee80211_hw *hw,
 	struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
 
 	if (common->fsm_state != FSM_MAC_INIT_DONE)
-		return -ENODEV;
+		return;
 
 	if (common->p2p_enabled)
 		return;
@@ -2367,41 +2377,31 @@  static u16 rsi_wow_map_triggers(struct rsi_common *common,
 }
 #endif
 
-#ifdef CONFIG_PM
-int rsi_mac80211_suspend(struct ieee80211_hw *hw,
-			 struct cfg80211_wowlan *wowlan)
-{
 #ifdef CONFIG_VEN_RSI_WOW
-	struct rsi_hw *adapter = hw->priv;
+int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan)
+{
 	struct rsi_common *common = adapter->priv;
 	u16 triggers = 0;
-	u16 rx_filter_word = 0;
+       	u16 rx_filter_word = 0;
 	struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
-#endif
-	int ret = 0;
 
-	ven_rsi_dbg(INFO_ZONE, "***** mac80211 suspend called ******\n");
+	ven_rsi_dbg(INFO_ZONE, "Config WoWLAN to device\n");
 
-#ifdef CONFIG_VEN_RSI_WOW
 	if (WARN_ON(!wowlan)) {
-		ven_rsi_dbg(ERR_ZONE,
-			"##### WoW triggers not enabled #####\n");
-		ret = -EINVAL;
-		goto fail_wow;
+		ven_rsi_dbg(ERR_ZONE, "WoW triggers not enabled\n");
+		return -EINVAL;
 	}
 
 	triggers = rsi_wow_map_triggers(common, wowlan);
 	if (!triggers) {
 		ven_rsi_dbg(ERR_ZONE, "%s:No valid WoW triggers\n",__func__);
-		ret = -EINVAL;
-		goto fail_wow;
+		return -EINVAL;
 	}
 	if (!bss->assoc) {
 		ven_rsi_dbg(ERR_ZONE,
 			"Cannot configure WoWLAN (Station not connected)\n");
 		common->wow_flags |= RSI_WOW_NO_CONNECTION;
-		ret = 0;
-		goto fail_wow;
+		return 0;
 	}
 	ven_rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
 	rsi_send_wowlan_request(common, triggers, 1);
@@ -2415,9 +2415,29 @@  int rsi_mac80211_suspend(struct ieee80211_hw *hw,
 	rsi_send_rx_filter_frame(common, rx_filter_word);
 
         common->wow_flags |= RSI_WOW_ENABLED;
-fail_wow:
+        
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rsi_config_wowlan);
+#endif
+
+#ifdef CONFIG_PM
+static int rsi_mac80211_suspend(struct ieee80211_hw *hw,
+				struct cfg80211_wowlan *wowlan)
+{
+#ifdef CONFIG_VEN_RSI_WOW
+	struct rsi_hw *adapter = hw->priv;
+	struct rsi_common *common = adapter->priv;
+
+	mutex_lock(&common->mutex);
+	if (rsi_config_wowlan(adapter, wowlan)) {
+		ven_rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
+		mutex_unlock(&common->mutex);
+		return 1;
+	}
+	mutex_unlock(&common->mutex);
 #endif
-        return (ret ? 1 : 0);
+	return 0;
 }
 
 static int rsi_mac80211_resume(struct ieee80211_hw *hw)
@@ -2426,9 +2446,9 @@  static int rsi_mac80211_resume(struct ieee80211_hw *hw)
 	struct rsi_common *common = adapter->priv;
 #ifdef CONFIG_VEN_RSI_WOW
 	u16 rx_filter_word = 0;
-#endif
         
 	adapter->priv->wow_flags = 0;
+#endif
 	
 	ven_rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
 
@@ -2436,6 +2456,7 @@  static int rsi_mac80211_resume(struct ieee80211_hw *hw)
 		return 0;
 
 #ifdef CONFIG_VEN_RSI_WOW
+	mutex_lock(&common->mutex);
 	rsi_send_wowlan_request(common, 0, 0);
 
 	rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
@@ -2443,7 +2464,9 @@  static int rsi_mac80211_resume(struct ieee80211_hw *hw)
 			  ALLOW_MGMT_ASSOC_PEER |
 			  0);
 	rsi_send_rx_filter_frame(common, rx_filter_word);
+	mutex_unlock(&common->mutex);
 #endif
+
 	return 0;
 }
 #endif
@@ -2502,14 +2525,12 @@  void rsi_roc_timeout(unsigned long data)
 	struct rsi_common *common = (struct rsi_common *)data;
 	struct ieee80211_vif *vif = common->roc_vif;
 	struct vif_priv *vif_info = (struct vif_priv *)vif->drv_priv;
-	enum opmode intf_mode;
-
-	ven_rsi_dbg(INFO_ZONE, "Remain on channel expired\n");
+	enum opmode intf_mode; 
 
 	mutex_lock(&common->mutex);
-
+	
 	ieee80211_remain_on_channel_expired(common->priv->hw);
-
+	
 	if (timer_pending(&common->roc_timer))
 		del_timer(&common->roc_timer);
 
@@ -2540,8 +2561,8 @@  static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw)
 	struct rsi_common *common = adapter->priv;
 	struct ieee80211_vif *vif = common->roc_vif;
 	struct vif_priv *vif_info = (struct vif_priv *)vif->drv_priv;
-	enum opmode intf_mode;
-
+	enum opmode intf_mode; 
+	
 	ven_rsi_dbg(INFO_ZONE, "Cancel remain on channel\n");
 
 	mutex_lock(&common->mutex);
@@ -2569,7 +2590,7 @@  static int rsi_mac80211_cancel_roc(struct ieee80211_hw *hw)
 	}
 
 	mutex_unlock(&common->mutex);
-
+	
 	return 0;
 }
 
@@ -2741,7 +2762,7 @@  int rsi_mac80211_attach(struct rsi_common *common)
 	hw->uapsd_queues = IEEE80211_MARKALL_UAPSD_QUEUES;
 	hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
 	hw->max_tx_aggregation_subframes = 8;
-//	hw->max_rx_aggregation_subframes = 8;
+	hw->max_rx_aggregation_subframes = 8;
 
 	rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
 	wiphy->bands[NL80211_BAND_2GHZ] =
@@ -2758,18 +2779,18 @@  int rsi_mac80211_attach(struct rsi_common *common)
 	SET_IEEE80211_PERM_ADDR(hw, common->mac_addr);
 	ether_addr_copy(hw->wiphy->addr_mask, addr_mask);
 
-  if (common->coex_mode == 4) {
-    wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-                             BIT(NL80211_IFTYPE_AP);
-  } else if (common->coex_mode == 2) {
-    wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
-  } else {
-	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-				 BIT(NL80211_IFTYPE_AP) |
-				 BIT(NL80211_IFTYPE_P2P_DEVICE) |
-				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
-				 BIT(NL80211_IFTYPE_P2P_GO);
-  }
+	if (common->coex_mode == 4) {
+		  wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+			  		   BIT(NL80211_IFTYPE_AP);
+	} else if (common->coex_mode == 2) {
+		  wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	} else {
+		  wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+			  		   BIT(NL80211_IFTYPE_AP) |
+					   BIT(NL80211_IFTYPE_P2P_DEVICE) |
+					   BIT(NL80211_IFTYPE_P2P_CLIENT) |
+					   BIT(NL80211_IFTYPE_P2P_GO);
+	}
 	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 	wiphy->retry_short = RETRY_SHORT;
 	wiphy->retry_long  = RETRY_LONG;
diff --git a/ubuntu/rsi/rsi_91x_mgmt.c b/ubuntu/rsi/rsi_91x_mgmt.c
index 2cd37bd..3cb2b20 100644
--- a/ubuntu/rsi/rsi_91x_mgmt.c
+++ b/ubuntu/rsi/rsi_91x_mgmt.c
@@ -429,7 +429,7 @@  static int rsi_send_internal_mgmt_frame(struct rsi_common *common,
 	if (skb->data[2] == PEER_NOTIFY)
 		skb_queue_head(&common->tx_queue[MGMT_SOFT_Q], skb);
 	else
-	skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb);
+		skb_queue_tail(&common->tx_queue[MGMT_SOFT_Q], skb);
 	rsi_set_event(&common->tx_thread.event);
 	return 0;
 }
@@ -1207,7 +1207,7 @@  void rsi_apply_carcalla_power_values(struct rsi_hw *adapter,
 			if (channel->hw_value == 12)
 				max_power = 15;
 			else if (channel->hw_value == 13)
-				max_power = 7; 
+				max_power = 7;
 			else
 				return;
 		} else {
@@ -1222,7 +1222,7 @@  void rsi_apply_carcalla_power_values(struct rsi_hw *adapter,
 		if (channel->hw_value == 12)
 			max_power = 7; 
 		else if (channel->hw_value == 13)
-			max_power = 5; 
+			max_power = 5;
 		else
 			return;
 	} else {
@@ -1231,7 +1231,7 @@  void rsi_apply_carcalla_power_values(struct rsi_hw *adapter,
 		else if (channel->hw_value == 9)
 			max_power = 5; 
 		else if (channel->hw_value == 10)
-			max_power = 4; 
+			max_power = 4;
 		else
 			return;
 	}
@@ -2166,28 +2166,28 @@  int rsi_set_antenna(struct rsi_common *common,
 int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
 			    u16 sleep_status)
 {
-	struct rsi_wowlan_req *cmd_frame;
-	struct sk_buff *skb;
-	u8 length;
-	u8 sourceid[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-	ven_rsi_dbg(ERR_ZONE, "%s: Sending wowlan request frame\n", __func__);
-
-	skb = dev_alloc_skb(sizeof(*cmd_frame));
-	if (!skb) {
-		ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
-				__func__);
-		return -ENOMEM;
-	}
-	memset(skb->data, 0, sizeof(*cmd_frame));
-	cmd_frame = (struct rsi_wowlan_req *)skb->data;
-
-	cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
-	cmd_frame->desc_word[1] |= cpu_to_le16(WOWLAN_CONFIG_PARAMS);
-
-	memcpy(cmd_frame->sourceid, &sourceid, IEEE80211_ADDR_LEN);
-
-	cmd_frame->host_sleep_status = sleep_status;
+        struct rsi_wowlan_req *cmd_frame;
+        struct sk_buff *skb;
+        u8 length;
+        u8 sourceid[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+        ven_rsi_dbg(ERR_ZONE, "%s: Sending wowlan request frame\n", __func__);
+
+        skb = dev_alloc_skb(sizeof(*cmd_frame));
+        if (!skb) {
+                ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n",
+                                __func__);
+                return -ENOMEM;
+        }
+        memset(skb->data, 0, sizeof(*cmd_frame));
+        cmd_frame = (struct rsi_wowlan_req *)skb->data;
+
+        cmd_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
+        cmd_frame->desc_word[1] |= cpu_to_le16(WOWLAN_CONFIG_PARAMS);
+ 
+        memcpy(cmd_frame->sourceid, &sourceid, IEEE80211_ADDR_LEN);
+	
+        cmd_frame->host_sleep_status = sleep_status;
 	if ((common->secinfo.security_enable) &&
 	    (common->secinfo.gtk_cipher))
 		flags |= RSI_WOW_GTK_REKEY;
@@ -2666,8 +2666,8 @@  static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
 		ven_rsi_dbg(INFO_ZONE, "BG scan complete event\n");
 		if (common->bgscan_en) {
 			if (!rsi_send_bgscan_params(common, 0))
-			common->bgscan_en = 0;
-		}	
+				common->bgscan_en = 0;
+		}
 #ifdef CONFIG_HW_SCAN_OFFLOAD
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
 		info.aborted = false;
diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
index eb7821b..af9f096 100644
--- a/ubuntu/rsi/rsi_91x_sdio.c
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -37,12 +37,12 @@ 
 /* Default operating mode is Wi-Fi alone */
 #ifdef CONFIG_CARACALLA_BOARD
 #if defined (CONFIG_VEN_RSI_COEX) || defined(CONFIG_VEN_RSI_BT_ALONE)
-u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
+static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
 #else
-u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
+static u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
 #endif
 #else
-u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
+static u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
 #endif
 module_param(dev_oper_mode, ushort, S_IRUGO);
 MODULE_PARM_DESC(dev_oper_mode,
@@ -164,11 +164,6 @@  static int rsi_issue_sdiocommand(struct sdio_func *func,
 	return err;
 }
 
-static void rsi_dummy_isr(struct sdio_func *function)
-{
-	return;
-}
-
 /**
  * rsi_handle_interrupt() - This function is called upon the occurrence
  *			    of an interrupt.
@@ -182,6 +177,8 @@  static void rsi_handle_interrupt(struct sdio_func *function)
 	struct rsi_91x_sdiodev *dev =
 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
 
+	if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
+		return;
 	dev->sdio_irq_task = current;
 	rsi_interrupt_handler(adapter);
 	dev->sdio_irq_task = NULL;
@@ -1066,6 +1063,8 @@  static int rsi_probe(struct sdio_func *pfunction,
 		     const struct sdio_device_id *id)
 {
 	struct rsi_hw *adapter;
+	struct rsi_91x_sdiodev *sdev;
+	int status;
 
 	ven_rsi_dbg(INIT_ZONE, "%s: Init function called\n", __func__);
 
@@ -1084,48 +1083,54 @@  static int rsi_probe(struct sdio_func *pfunction,
 			__func__);
 		goto fail;
 	}
+
+	/* Initialize receive path */
+	sdev = adapter->rsi_dev;
+	rsi_init_event(&sdev->rx_thread.event);
+	status = rsi_create_kthread(adapter->priv, &sdev->rx_thread,
+				    rsi_sdio_rx_thread, "SDIO-RX-Thread");
+	if (status) {
+		ven_rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
+		goto fail;
+	}
+	skb_queue_head_init(&sdev->rx_q.head);
+	sdev->rx_q.num_rx_pkts = 0;
+
 #ifdef CONFIG_SDIO_INTR_POLL
 	init_sdio_intr_status_poll_thread(adapter->priv);
 #endif
 	sdio_claim_host(pfunction);
-//	if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
-	if (sdio_claim_irq(pfunction, rsi_dummy_isr)) {
+	if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
 		sdio_release_host(pfunction);
-		goto fail;
+		goto fail1;
 	}
 	sdio_release_host(pfunction);
 	ven_rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__);
 
 	if (rsi_hal_device_init(adapter)) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__);
-		sdio_claim_host(pfunction);
-		sdio_release_irq(pfunction);
-		sdio_disable_func(pfunction);
-		sdio_release_host(pfunction);
-		goto fail;
+		goto fail1;
 	}
 	ven_rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n");
 	
 	if (rsi_sdio_master_access_msword(adapter, MISC_CFG_BASE_ADDR)) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Unable to set ms word reg\n", __func__);
-		return -EIO;
+		goto fail2;
 	}
 	ven_rsi_dbg(INIT_ZONE, "%s: Setting ms word to 0x41050000\n", __func__);
 
-	sdio_claim_host(pfunction);
-		sdio_release_irq(pfunction);
-	mdelay(10);
-	if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) {
-		ven_rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__);
-		sdio_release_host(pfunction);
-		goto fail;
-	}
-	sdio_release_host(pfunction);
 	adapter->priv->hibernate_resume = false;
 
 	return 0;
 
+fail2:
+	sdio_claim_host(pfunction);
+	sdio_release_irq(pfunction);
+	sdio_disable_func(pfunction);
+	sdio_release_host(pfunction);
+fail1:
+	rsi_kill_thread(&sdev->rx_thread);
 fail:
 #ifdef CONFIG_SDIO_INTR_POLL
 	rsi_kill_thread(&adapter->priv->sdio_intr_poll_thread);
@@ -1154,6 +1159,8 @@  static void rsi_disconnect(struct sdio_func *pfunction)
 #ifdef CONFIG_SDIO_INTR_POLL
 	rsi_kill_thread(&adapter->priv->sdio_intr_poll_thread);
 #endif
+	rsi_kill_thread(&dev->rx_thread);
+
 	sdio_claim_host(pfunction);
 	sdio_release_irq(pfunction);
 	sdio_release_host(pfunction);
@@ -1164,17 +1171,15 @@  static void rsi_disconnect(struct sdio_func *pfunction)
 	rsi_hci_detach(adapter->priv);
 #endif
 
-	if (!adapter->priv->hibernate_resume) {
-		/* Reset Chip */
-		rsi_reset_chip(adapter);
+	/* 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);
-	}
+	/* 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;
 	ven_rsi_91x_deinit(adapter);
 	ven_rsi_dbg(ERR_ZONE, "##### RSI SDIO device disconnected #####\n");
@@ -1210,7 +1215,7 @@  static int rsi_sdio_disable_interrupts(struct sdio_func *pfunction)
 				       RSI_FN1_INT_REGISTER,
 				       &isr_status);
 		ven_rsi_dbg(ERR_ZONE, ".");
-	} while (isr_status);
+	} while (isr_status); 
 	ven_rsi_dbg(ERR_ZONE, "\nInterrupts cleared");
 
 	sdio_claim_host(pfunction);
@@ -1246,7 +1251,7 @@  static int rsi_sdio_disable_interrupts(struct sdio_func *pfunction)
 	ven_rsi_dbg(INFO_ZONE, "INTR_EN reg content. = %x\n", data);
 
 	sdio_release_host(pfunction);
-	
+
 	return 0;
 }
 
@@ -1308,20 +1313,10 @@  static int rsi_suspend(struct device *dev)
 
 	common->suspend_in_prog = true;
 #ifdef CONFIG_VEN_RSI_WOW
-	if (common->wow_flags & RSI_WOW_ENABLED) {
-		if (common->wow_flags & RSI_WOW_NO_CONNECTION)
-			ven_rsi_dbg(ERR_ZONE,
-				"##### Device can not wake up through WLAN\n");
-
-#if 0
-#if defined(CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
-		if ((common->coex_mode == 2) || (common->coex_mode == 4)) {
-			/* Deregister BT protocol */
-			rsi_hci_detach(common);
-		}
-#endif
-#endif
-	}
+	if ((common->wow_flags & RSI_WOW_ENABLED) &&
+	    (common->wow_flags & RSI_WOW_NO_CONNECTION))
+		ven_rsi_dbg(ERR_ZONE,
+			"##### Device can not wake up through WLAN\n");
 #endif
 
 	ret = rsi_sdio_disable_interrupts(pfunction);
@@ -1335,7 +1330,7 @@  static int rsi_suspend(struct device *dev)
 			"Setting power management caps failed\n");
 
 	common->fsm_state = FSM_CARD_NOT_READY;
-	ven_rsi_dbg(INFO_ZONE, "***** SDIO BUS SUSPEND DONE ******\n");
+	ven_rsi_dbg(INFO_ZONE, "***** RSI module suspended ******\n");
 
 	return 0;
 }
@@ -1347,27 +1342,15 @@  int rsi_resume(struct device *dev)
 	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
 	struct rsi_common *common = adapter->priv;
         
-	ven_rsi_dbg(INFO_ZONE, "***** BUS RESUME ******\n");
+	ven_rsi_dbg(INFO_ZONE, "SDIO Bus resume =====>\n");
 
 	common->suspend_in_prog = false;
 	common->fsm_state = FSM_MAC_INIT_DONE;
 
 	ret = rsi_sdio_enable_interrupts(pfunction);
 
-#if 0
-#ifdef CONFIG_VEN_RSI_WOW
-#if defined(CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
-	if ((common->wow_flags & RSI_WOW_ENABLED) &&
-	    ((common->coex_mode == 2) || (common->coex_mode == 4))) {
-		/* Register BT protocol */
-		rsi_hci_attach(common);
-	}
-#endif
-        adapter->priv->wow_flags = 0;
-#endif
-#endif
-
 	ven_rsi_dbg(INFO_ZONE, "***** RSI module resumed *****\n");
+
 	return 0;
 }
 
@@ -1376,9 +1359,8 @@  static int rsi_freeze(struct device *dev)
 	int ret = 0;
 	struct sdio_func *pfunction = dev_to_sdio_func(dev);
 	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
-	struct rsi_common *common = adapter->priv;
-	struct rsi_91x_sdiodev *sdev =
-		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
+	struct rsi_common *common;
+	struct rsi_91x_sdiodev *sdev;
 
 	ven_rsi_dbg(INFO_ZONE, "SDIO Bus freeze ===>\n");
 
@@ -1387,22 +1369,18 @@  static int rsi_freeze(struct device *dev)
 		return -ENODEV;
 	}
 
+	common = adapter->priv;
+	sdev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
+
 	common->suspend_in_prog = true;
 #ifdef CONFIG_VEN_RSI_WOW
-	if (common->wow_flags & RSI_WOW_ENABLED) {
-		if (common->wow_flags & RSI_WOW_NO_CONNECTION)
-			ven_rsi_dbg(ERR_ZONE,
-				"##### Device can not wake up through WLAN\n");
-
-#if 0
-#if defined(CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
-		if ((common->coex_mode == 2) || (common->coex_mode == 4)) {
-			/* Deregister BT protocol */
-			rsi_deregister_bt(common);
-		}
-#endif
+	if ((common->wow_flags & RSI_WOW_ENABLED) &&
+	    (common->wow_flags & RSI_WOW_NO_CONNECTION))
+		ven_rsi_dbg(ERR_ZONE,
+			"##### Device can not wake up through WLAN\n");
 #endif
-	}
+#if defined(CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
+	rsi_hci_detach(common);
 #endif
 
 	ret = rsi_sdio_disable_interrupts(pfunction);
@@ -1414,6 +1392,8 @@  static int rsi_freeze(struct device *dev)
 	if (ret)
 		ven_rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
 	
+	ven_rsi_dbg(INFO_ZONE, "***** RSI module freezed *****\n");
+
 	return 0;
 }
 
@@ -1421,10 +1401,9 @@  int rsi_thaw(struct device *dev)
 {
 	struct sdio_func *pfunction = dev_to_sdio_func(dev);
 	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+        
+	ven_rsi_dbg(ERR_ZONE, "SDIO Bus thaw =====>\n");
 
-	ven_rsi_dbg(ERR_ZONE, "***** BUS THAW ******\n");
-
-//	adapter->priv->suspend_in_prog = false;
 	adapter->priv->hibernate_resume = true;
 	adapter->priv->fsm_state = FSM_CARD_NOT_READY;
 	adapter->priv->bt_fsm_state = BT_DEVICE_NOT_READY;
@@ -1432,7 +1411,8 @@  int rsi_thaw(struct device *dev)
 
 	rsi_sdio_enable_interrupts(pfunction);
 
-	ven_rsi_dbg(INFO_ZONE, "RSI module resumed\n");
+	ven_rsi_dbg(INFO_ZONE, "***** RSI module thaw done *****\n");
+
 	return 0;
 }
 
@@ -1443,7 +1423,67 @@  static int rsi_poweroff(struct device *dev)
 
 static void rsi_shutdown(struct device *dev)
 {
-	rsi_freeze(dev);
+	struct sdio_func *pfunction = dev_to_sdio_func(dev);
+	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+	struct rsi_91x_sdiodev *sdev =
+		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
+#ifdef CONFIG_VEN_RSI_WOW
+	struct ieee80211_hw *hw = adapter->hw;
+	struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;
+#endif
+
+	ven_rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n");
+
+	adapter->priv->suspend_in_prog = true;
+
+#ifdef CONFIG_VEN_RSI_WOW
+	if (rsi_config_wowlan(adapter, wowlan))
+		ven_rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n");
+#endif
+
+#if defined(CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
+	rsi_hci_detach(adapter->priv);
+#endif
+
+	rsi_sdio_disable_interrupts(sdev->pfunction);
+
+	if (sdev->write_fail)
+		ven_rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
+	
+	if (rsi_set_sdio_pm_caps(adapter))
+		ven_rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
+
+	ven_rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n");
+}
+
+static int rsi_sdio_reinit_device(struct rsi_hw *adapter)
+{
+	struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
+	struct sdio_func *pfunction = sdev->pfunction;
+	int ii;
+
+	/* Flush soft queues */
+	for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
+		skb_queue_purge(&adapter->priv->tx_queue[ii]);
+
+	/* Detach MAC */
+	ven_rsi_mac80211_detach(adapter);
+	
+	/* Initialize device again */
+	sdio_claim_host(pfunction);
+
+	sdio_release_irq(pfunction);
+	rsi_reset_card(pfunction);
+
+	sdio_enable_func(pfunction);
+	rsi_setupcard(adapter);
+	rsi_init_sdio_slave_regs(adapter);
+	sdio_claim_irq(pfunction, rsi_handle_interrupt);
+	rsi_hal_device_init(adapter);
+
+	sdio_release_host(pfunction);
+
+	return 0;
 }
 
 int rsi_restore(struct device *dev)
@@ -1451,12 +1491,22 @@  int rsi_restore(struct device *dev)
 	struct sdio_func *pfunction = dev_to_sdio_func(dev);
 	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
 
+	ven_rsi_dbg(INFO_ZONE, "SDIO Bus restore ======>\n");
+
 	adapter->priv->suspend_in_prog = false;
 	adapter->priv->hibernate_resume = true;
-	adapter->priv->fsm_state = FSM_CARD_NOT_READY;
+	adapter->priv->fsm_state = FSM_FW_NOT_LOADED;
 	adapter->priv->bt_fsm_state = BT_DEVICE_NOT_READY;
 	adapter->priv->iface_down = true;
 
+	/* Initialize device again */
+	rsi_sdio_reinit_device(adapter);
+
+#ifdef CONFIG_VEN_RSI_WOW
+	adapter->priv->wow_flags = 0;
+#endif
+	adapter->priv->iface_down = false;
+
 	ven_rsi_dbg(INFO_ZONE, "RSI module restored\n");
 
 	return 0;
diff --git a/ubuntu/rsi/rsi_91x_sdio_ops.c b/ubuntu/rsi/rsi_91x_sdio_ops.c
index d575567..608afef 100644
--- a/ubuntu/rsi/rsi_91x_sdio_ops.c
+++ b/ubuntu/rsi/rsi_91x_sdio_ops.c
@@ -74,6 +74,50 @@  int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
 	return status;
 }
 
+void rsi_sdio_rx_thread(struct rsi_common *common)
+{
+	struct rsi_hw *adapter = common->priv;
+	struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
+	struct sk_buff *skb;
+	int status;
+	bool done = false;
+
+	do {
+		rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER);
+
+		if (atomic_read(&sdev->rx_thread.thread_done))
+			break;
+
+		while (true) {
+			skb = skb_dequeue(&sdev->rx_q.head);
+			if (!skb)
+				break;
+			status = ven_rsi_read_pkt(common, skb->data, skb->len);
+			if (status) {
+				ven_rsi_dbg(ERR_ZONE, "Failed to read the packet\n");
+				dev_kfree_skb(skb);
+				return;
+			}
+			dev_kfree_skb(skb);
+			if (sdev->rx_q.num_rx_pkts > 0)
+				sdev->rx_q.num_rx_pkts--;
+			
+			if (atomic_read(&sdev->rx_thread.thread_done)) {
+				done = true;
+				break;
+			}
+		}
+		rsi_reset_event(&sdev->rx_thread.event);
+		if (done)
+			break;
+	} while (1);
+
+	ven_rsi_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
+	skb_queue_purge(&sdev->rx_q.head);
+	atomic_inc(&sdev->rx_thread.thread_done);
+	complete_and_exit(&sdev->rx_thread.completion, 0);
+}
+
 /**
  * rsi_process_pkt() - This Function reads rx_blocks register and figures out
  *		       the size of the rx pkt.
@@ -91,6 +135,7 @@  static int rsi_process_pkt(struct rsi_common *common)
 	int status = 0;
 	u8 value = 0;
 	u8 protocol = 0, unaggr_pkt = 0;
+	struct sk_buff *skb;
 
 #define COEX_PKT 0
 #define WLAN_PKT 3
@@ -128,28 +173,30 @@  static int rsi_process_pkt(struct rsi_common *common)
 		unaggr_pkt = 1;
 
 	rcv_pkt_len = (num_blks * 256);
+	
+	if (dev->rx_q.num_rx_pkts >= RSI_SDIO_MAX_RX_PKTS)
+		return -EINVAL;
 
-	common->rx_data_pkt = kmalloc(rcv_pkt_len, GFP_KERNEL);
-	if (!common->rx_data_pkt) {
-		ven_rsi_dbg(ERR_ZONE, "%s: Failed in memory allocation\n",
+	skb = dev_alloc_skb(rcv_pkt_len);
+	if (!skb) {
+		ven_rsi_dbg(ERR_ZONE, "%s: Failed to allocate rx packet\n",
 			__func__);
 		return -ENOMEM;
 	}
+	skb_put(skb, rcv_pkt_len);
 
-	status = rsi_sdio_host_intf_read_pkt(adapter,
-					     common->rx_data_pkt,
-					     rcv_pkt_len);
+	status = rsi_sdio_host_intf_read_pkt(adapter, skb->data, skb->len);
 	if (status) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n",
 			__func__);
-		goto fail;
+		dev_kfree_skb(skb);
+		return status;
 	}
+	skb_queue_tail(&dev->rx_q.head, skb);
+	dev->rx_q.num_rx_pkts++;
+	rsi_set_event(&dev->rx_thread.event);
 
-	status = ven_rsi_read_pkt(common, common->rx_data_pkt, rcv_pkt_len);
-
-fail:
-	kfree(common->rx_data_pkt);
-	return status;
+	return 0;
 }
 
 /**
diff --git a/ubuntu/rsi/rsi_91x_usb.c b/ubuntu/rsi/rsi_91x_usb.c
index bdc26aa..5876bc0 100644
--- a/ubuntu/rsi/rsi_91x_usb.c
+++ b/ubuntu/rsi/rsi_91x_usb.c
@@ -36,12 +36,12 @@ 
 /* Default operating mode is Wi-Fi alone */
 #ifdef CONFIG_CARACALLA_BOARD
 #if defined (CONFIG_VEN_RSI_COEX) || defined(CONFIG_VEN_RSI_BT_ALONE)
-u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
+static u16 dev_oper_mode = DEV_OPMODE_STA_BT_DUAL;
 #else
-u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
+static u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
 #endif
 #else
-u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
+static u16 dev_oper_mode = DEV_OPMODE_WIFI_ALONE;
 #endif
 module_param(dev_oper_mode, ushort, S_IRUGO);
 MODULE_PARM_DESC(dev_oper_mode,
@@ -359,9 +359,14 @@  static void rsi_rx_done_handler(struct urb *urb)
 		ven_rsi_dbg(INFO_ZONE, "%s: Zero length packet\n", __func__);
 		return;
 	}
-	rx_cb->pend = 1;
+	skb_put(rx_cb->rx_skb, urb->actual_length);
+	skb_queue_tail(&dev->rx_q[rx_cb->ep_num - 1], rx_cb->rx_skb);
 
 	rsi_set_event(&dev->rx_thread.event);
+
+	if (rsi_rx_urb_submit(dev->priv, rx_cb->ep_num))
+		ven_rsi_dbg(ERR_ZONE, "%s: Failed in urb submission", __func__);
+
 }
 
 /**
@@ -370,12 +375,24 @@  static void rsi_rx_done_handler(struct urb *urb)
  *
  * Return: 0 on success, a negative error code on failure.
  */
-static int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num)
+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;
+	struct sk_buff *skb;
+	u8 dword_align_bytes;
+
+	skb = dev_alloc_skb(3000);
+	if (!skb)
+		return -ENOMEM;
+	skb_reserve(skb, 64); /* For dword alignment */
+	dword_align_bytes = (unsigned long)skb->data & 0x3f;
+	if (dword_align_bytes)
+		skb_push(skb, dword_align_bytes);
+	urb->transfer_buffer = skb->data;
+	rx_cb->rx_skb = skb;
 
 	usb_fill_bulk_urb(urb,
 			dev->usbdev,
@@ -488,12 +505,13 @@  int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
 
 int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num)
 {
+	return QUEUE_NOT_FULL;
+
+#if 0
 	struct rsi_91x_usbdev *dev = (struct rsi_91x_usbdev *)adapter->rsi_dev;
 	int status;
 	u32 buf_status = 0;
 
-	return QUEUE_NOT_FULL;
-
 	if (adapter->priv->fsm_state != FSM_MAC_INIT_DONE)
 		return QUEUE_NOT_FULL;
 
@@ -534,6 +552,7 @@  int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num)
 		return QUEUE_FULL;
 
 	return QUEUE_NOT_FULL;
+#endif
 }
 
 /**
@@ -549,10 +568,11 @@  static void rsi_deinit_usb_interface(struct rsi_hw *adapter)
 	ven_rsi_dbg(INFO_ZONE, "Deinitializing USB interface...\n");
 
 	rsi_kill_thread(&dev->rx_thread);
-	kfree(dev->rx_cb[0].rx_buffer);
+	//kfree(dev->rx_cb[0].rx_buffer);
+	skb_queue_purge(&dev->rx_q[0]);
 	usb_free_urb(dev->rx_cb[0].rx_urb);
 #if defined (CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
-	kfree(dev->rx_cb[1].rx_buffer);
+	//kfree(dev->rx_cb[1].rx_buffer);
 	usb_free_urb(dev->rx_cb[1].rx_urb);
 #endif
 	kfree(dev->saved_tx_buffer);
@@ -621,36 +641,26 @@  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;
+	u8 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) {
 			ven_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;
+
+		skb_queue_head_init(&dev->rx_q[idx]);
 	}
 	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;
 }
@@ -676,6 +686,7 @@  static int rsi_init_usb_interface(struct rsi_hw *adapter,
 
 	adapter->rsi_dev = rsi_dev;
 	rsi_dev->usbdev = interface_to_usbdev(pfunction);
+	rsi_dev->priv = (void *)adapter;
 
 	if (rsi_find_bulk_in_and_out_endpoints(pfunction, adapter))
 		return -EINVAL;
@@ -708,11 +719,10 @@  static int rsi_init_usb_interface(struct rsi_hw *adapter,
 	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");
+				    rsi_usb_rx_thread, "USB-RX-Thread");
 	if (status) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
 		goto fail_2;
diff --git a/ubuntu/rsi/rsi_91x_usb_ops.c b/ubuntu/rsi/rsi_91x_usb_ops.c
index 2f4c43e..e97a774 100644
--- a/ubuntu/rsi/rsi_91x_usb_ops.c
+++ b/ubuntu/rsi/rsi_91x_usb_ops.c
@@ -42,7 +42,7 @@  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;
+	struct sk_buff *skb;
 	int status, idx;
 
 	do {
@@ -52,28 +52,18 @@  void rsi_usb_rx_thread(struct rsi_common *common)
 			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 = ven_rsi_read_pkt(common, rx_cb->rx_buffer, 0);
-			if (status) {
-				ven_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)) {
-				ven_rsi_dbg(ERR_ZONE,
-					"%s: Failed in urb submission", __func__);
-				break;
+			while (true) {
+				skb = skb_dequeue(&dev->rx_q[idx]);
+				if (!skb)
+					break;
+
+				status = ven_rsi_read_pkt(common, skb->data, 0);
+				if (status) {
+					ven_rsi_dbg(ERR_ZONE, "%s: Failed To read data",
+							__func__);
+				}
+				dev_kfree_skb(skb);
 			}
-			/* Update TX buffer status */
-			//rsi_usb_check_queue_status(adapter, 0);
 		}
 		rsi_reset_event(&dev->rx_thread.event);
 	} while (1);
diff --git a/ubuntu/rsi/rsi_common.h b/ubuntu/rsi/rsi_common.h
index afd0e6d..d4385de 100644
--- a/ubuntu/rsi/rsi_common.h
+++ b/ubuntu/rsi/rsi_common.h
@@ -112,4 +112,7 @@  void init_sdio_intr_status_poll_thread(struct rsi_common *common);
 #endif
 void rsi_roc_timeout(unsigned long data);
 struct ieee80211_vif *rsi_get_vif(struct rsi_hw *adapter, u8 *mac);
+#ifdef CONFIG_VEN_RSI_WOW
+int rsi_config_wowlan(struct rsi_hw *adapter, struct cfg80211_wowlan *wowlan);
+#endif
 #endif
diff --git a/ubuntu/rsi/rsi_main.h b/ubuntu/rsi/rsi_main.h
index eb1afbb..3f55e36 100644
--- a/ubuntu/rsi/rsi_main.h
+++ b/ubuntu/rsi/rsi_main.h
@@ -41,7 +41,7 @@  struct rsi_hw;
 
 #include "rsi_ps.h"
 
-#define DRV_VER				"RS9113.NB0.NL.GNU.LNX.1.2.RC12"
+#define DRV_VER				"RS9113.NB0.NL.GNU.LNX.1.2"
 
 #define ERR_ZONE                        BIT(0) /* Error Msgs		*/
 #define INFO_ZONE                       BIT(1) /* Generic Debug Msgs	*/
@@ -53,15 +53,16 @@  struct rsi_hw;
 #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
+#define FSM_FW_NOT_LOADED		0
+#define FSM_CARD_NOT_READY              1
+#define FSM_COMMON_DEV_PARAMS_SENT	2
+#define FSM_BOOT_PARAMS_SENT            3
+#define FSM_EEPROM_READ_MAC_ADDR        4
+#define FSM_EEPROM_READ_RF_TYPE		5
+#define FSM_RESET_MAC_SENT              6
+#define FSM_RADIO_CAPS_SENT             7
+#define FSM_BB_RF_PROG_SENT             8
+#define FSM_MAC_INIT_DONE               9
 
 extern u16 ven_rsi_zone_enabled;
 extern __printf(2, 3) void ven_rsi_dbg(u32 zone, const char *fmt, ...);
@@ -179,8 +180,8 @@  struct wmm_qinfo {
 };
 
 struct transmit_q_stats {
-	u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 1];
-	u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 1];
+	u32 total_tx_pkt_send[NUM_EDCA_QUEUES + 2];
+	u32 total_tx_pkt_freed[NUM_EDCA_QUEUES + 2];
 };
 
 struct vif_priv {
@@ -285,7 +286,6 @@  struct rsi_common {
 
 	/* Generic */
 	u8 channel;
-	u8 *rx_data_pkt;
 	u8 *saved_rx_data_pkt;
 	u8 mac_id;
 	u8 radio_id;
diff --git a/ubuntu/rsi/rsi_mgmt.h b/ubuntu/rsi/rsi_mgmt.h
index 8965f23..01bcfc5 100644
--- a/ubuntu/rsi/rsi_mgmt.h
+++ b/ubuntu/rsi/rsi_mgmt.h
@@ -60,11 +60,11 @@ 
 #define WLAN_EEPROM_RFTYPE_ADDR		424
 
 /*WOWLAN RESUME WAKEUP TYPES*/
-#define	UNICAST_MAGIC_PKT       	BIT(0)
-#define	BROADCAST_MAGICPKT      	BIT(1)
-#define	EAPOL_PKT               	BIT(2)
-#define	DISCONNECT_PKT          	BIT(3)
-#define	HW_BMISS_PKT            	BIT(4)
+#define	UNICAST_MAGIC_PKT       	BIT(0) 
+#define	BROADCAST_MAGICPKT      	BIT(1) 
+#define	EAPOL_PKT               	BIT(2) 
+#define	DISCONNECT_PKT          	BIT(3) 
+#define	HW_BMISS_PKT            	BIT(4) 
 #define INSERT_SEQ_IN_FW                BIT(2)
 
 /* Receive Frame Types */
@@ -596,7 +596,7 @@  int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
 #endif
 void rsi_scan_start(struct work_struct *data);
 #ifdef CONFIG_HW_SCAN_OFFLOAD
-int rsi_send_probe_request(struct rsi_common *common,
+int rsi_send_probe_request(struct rsi_common *common, 
 			   struct cfg80211_scan_request *scan_req, u8 n_ssid,
 			   u8 channel, u8 scan_type);
 #endif
diff --git a/ubuntu/rsi/rsi_sdio.h b/ubuntu/rsi/rsi_sdio.h
index f2ce060..4d9978d 100644
--- a/ubuntu/rsi/rsi_sdio.h
+++ b/ubuntu/rsi/rsi_sdio.h
@@ -116,6 +116,12 @@  struct receive_info {
 	u32 buf_available_counter;
 };
 
+#define RSI_SDIO_MAX_RX_PKTS	32
+struct rsi_sdio_rx_q {
+	u8 num_rx_pkts;
+	struct sk_buff_head head;
+};
+
 struct rsi_91x_sdiodev {
 	struct sdio_func *pfunction;
 	struct task_struct *sdio_irq_task;
@@ -128,6 +134,8 @@  struct rsi_91x_sdiodev {
 	u32 tx_blk_size;
 	u8 write_fail;
 	u8 buff_status_updated;
+	struct rsi_sdio_rx_q rx_q;
+	struct rsi_thread rx_thread;
 };
 
 void rsi_interrupt_handler(struct rsi_hw *adapter);
@@ -157,4 +165,5 @@  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_check_buffer_status(struct rsi_hw *adapter, u8 q_num);
 int rsi_read_intr_status_reg(struct rsi_hw *adapter);
+void rsi_sdio_rx_thread(struct rsi_common *common);
 #endif
diff --git a/ubuntu/rsi/rsi_usb.h b/ubuntu/rsi/rsi_usb.h
index c08ba6c..d2dd097 100644
--- a/ubuntu/rsi/rsi_usb.h
+++ b/ubuntu/rsi/rsi_usb.h
@@ -54,10 +54,8 @@ 
 struct rx_usb_ctrl_block {
 	u8 *data;
 	struct urb *rx_urb;
-	u8 *rx_buffer;
-	u8 *orig_rx_buffer;
+	struct sk_buff *rx_skb;
 	u8 ep_num;
-	u8 pend;
 };
 
 struct receive_info {
@@ -87,6 +85,7 @@  struct rsi_91x_usbdev {
 	u8 bulkout_endpoint_addr[MAX_BULK_EP];
 	u32 tx_blk_size;
 	u8 write_fail;
+	struct sk_buff_head rx_q[MAX_RX_URBS]; 
 };
 
 static inline int rsi_usb_event_timeout(struct rsi_hw *adapter)
@@ -111,4 +110,5 @@  int rsi_usb_load_data_master_write(struct rsi_hw *adapter, u32 base_address,
 				   u16 block_size,
 				   u8 *ta_firmware);
 int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num);
+int rsi_rx_urb_submit(struct rsi_hw *adapter, u8 ep_num);
 #endif