[PATCH][Xenial SRU] UBUNTU: SAUCE: Redpine: Upgrade to ver. 1.2.RC9

Shrirang Bagul shrirang.bagul at canonical.com
Wed May 17 03:29:02 UTC 2017


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

Vendor release ver: 1.2.RC9

Changelog:

1.2.RC9 -
    WLAN Bug Fixes:
    ---------------
    1) BT reset added before going to S3/S4/S5 sleep when WoWLAN is enabled.
    2) Station connection check before going to S3/S4/S5 sleep removed.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.

    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.RC8 -
    WLAN Bug Fixes:
    ---------------
    1) Added power leak fixes for S4.
    2) S5 WoLAN issue resolved.
    3) Wakeup short pulse issue resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.

    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.RC7 -
    WLAN Bug Fixes:
    ---------------
    1) Configured host wakeup pin as active low from driver.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.

    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.RC6 -
    WLAN Bug Fixes:
    ---------------
    1) AP data throughput issue resolved.
    2) Scan results issue resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.

    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.RC4 -
    WLAN Bug Fixes:
    ---------------
    1) Buffer status interrupt handling improved.
    2) Scan results update in sta+bt dual mode issue resolved

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.

    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.RC3 -
    WLAN Bug Fixes:
    ---------------
    1) WoWLAN multiple cycles issue resolved.
    2) Driver Version is correctly updated.
    3) Default operating mode for Caracalla board is corrected.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.

    BT New Features:
    ----------------
    1) Multiple slaves issue in WLAN-BT coex mode resolved.

    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.RC2 -
    WLAN Bug Fixes:
    ---------------
    1) Suspend/resume issues resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.
    3) EAP not tested

    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.RC1 -
    WLAN New Features:
    ------------------
    1) Restrict functional modes as per device operating mode
    2) Default operating mode for Caracalla board is 13

    WLAN Bug Fixes:
    ---------------
    1) Driver oops issue if more than 4 clients try to connect in
       operating mode 14 resolved.
    2) Issue with connecting more than max clients and disconnection
       issue resolved.
    3) L2 test stop when wlan interface down issue resolved.
    4) Driver version corrected.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.
    3) EAP not tested
    4) For channels 12 and 13 in US region max TX power is coming 0 in
       beacons.

    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.1 -
    Generic
    -------
    1) Firmware file name is displayed along with version information.
       at the driver load time.
    2) Device operating mode is made available in the below files:
       /sys/module/rsi_sdio/parameters/dev_oper_mode
       /sys/module/rsi_usb/parameters/dev_oper_mode
    3) Wi-Fi BT radio sharing has been improved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.
    3) EAP not tested
    4) For channels 12 and 13 in US region max TX power is coming 0 in beacons.

    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.0.RC7 -
    Generic
    -------
    1) Driver version, Firmware version and operating mode information is displayed
       at the driver load time.
    2) Driver version is made available in the below files:
       /sys/module/rsi_91x/version
       /sys/module/rsi_sdio/version
       /sys/module/rsi_usb/version

    WLAN Bug Fixes:
    ---------------
    1) Power save latencies resolved

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.
    3) EAP not tested

    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.0 -
    WLAN New Features:
    ------------------
    1) Station mode
    2) All Security modes (WEP/WPA/WPA2)
    3) Station Power save (legacy and UAPSD)
    4) Bgscan and roaming
    5) External antenna selection
    6) Neighbour report request in RRM
    7) Regulatory (802)11d) support
    8) Management frame protection support (802)11w)
    9) Software RF-kill
    10) AP mode
    11) S3, S4 suspend and resume
    12) WoWLAN
    13) AP Power save
    14) Wi-Fi direct

    WLAN Bug Fixes:
    ---------------
    1) Allowed channels 12 and 13 in FCC region.
    2) For the allowed channels 12 and 13 in any region, power configuration
       updated as per Caracalla regulatory rules.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S5 with WoWLAN does not work.
    2) For GTK rekey, wakeup trigger send to host.
    3) EAP not tested

    BT New Features:
    ----------------
    1) BT EDR mode
    2) BT LE mode
    3) BT coex mode (All the coex modes))
    4) Multi-slave mode supported)

    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.0_RC3 -
    Gerenic:
    --------
    1) Device operating mode is changed as module parameter. Please check
       README or TRM on how to configure this while loading the modules.
    2) Max number of stations supported in Wi-Fi AP alone mode is 32, and AP +
       BT coex mode is 4.
    3) AP + BT-EDR + BLE support added.

    WLAN Bug Fixes:
    ---------------
    1) Bgscan probe request issue resolved.
    2) WoWLAN before association issue resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) S4 with and without WoWLAN works with the work-around implemented by Canonical.
    2) S5 with WoWLAN does not work.
    3) For GTK rekey, wakeup trigger send to host.
    4) EAP not tested
    5) To connect multiple BT slaves, connection should be initiated from rsi module.
    6) In coex mode, BT file transfer fails at times with certain mobiles.

    BT New Features:
    ----------------
    1) Multi-slave mode supported.

    BT Bug Fixes:
    -------------
    1) Radio sharing of coex modes improved.

1.0.RC2 -
    WLAN Bug Fixes:
    ---------------
    1) PVB preparation issue in AP mode resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Issue while Resume in S4 with or without WoWLAN.
    3) S5 with WoWLAN does not work.
    4) For GTK rekey, wakeup trigger send to host.

    BT Bug Fixes:
    -------------
    1) BT dual mode disconnection issue resolved
    2) AP BT dual mode issue resolved

1.0_RC1 -
    WLAN Bug Fixes:
    ---------------
    1) WoWLAN in Co-ex mode issue resolved.
    2) AP beacon DTIM count update issue resolved.
    3) Firmware assertion (0x5d) in bgscan issue is resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Issue while Resume in S4 with or without WoWLAN.
    3) S5 with WoWLAN does not work.
    4) For GTK rekey, wakeup trigger send to host.

0.9.8.5_RC6 -
    WLAN Bug Fixes:
    ---------------
    1) Firmware CRC check fail issue resolved
    2) Compilation fails on 4.10.1 kernel issue resolved
    3) BG scan issues resolved
    4) AP mode regulatory fixes
    5) WoWLAN issues resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Issue while Resume in S4 with or without WoWLAN.
    3) S5 with WoWLAN does not work.
    4) For GTK rekey, wakeup trigger send to host.

0.9.8.5_RC4 -
    WLAN Bug Fixes:
    -------------------
    1) AP mode configuration in channels 12 and 13 for EU region issue resolved.
    2) Data latencies in AP mode issue resolved.
    3) Roaming issues resolved.
    4) AP WEP mode issue resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Issue while Resume in S4 with or without WoWLAN.
    3) S5 with WoWLAN does not work.
    4) For GTK rekey, wakeup trigger send to host.
    5) WoWLAN does not work in WEP mode.

    Others:
    -------
    1) USB binds only to RS9113, let upstream kernel driver handle other RSI chips

0.9.8.5_RC3 -
    WLAN Bug Fixes:
    -------------------
    1) Power save issue in station mode (By default UAPSD is enabled on
    Caracalla board) fixed.
    2) WoWLAN with S3 issue resolved

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Not verified removing SDIO interrupt polling
    3) S4/S5 sleep states not supported (with and without WoWLAN)

0.9.8.5_RC2 -
    WLAN Bug Fixes:
    -------------------
    1) Power save issue in station mode (By default UAPSD is enabled on
    Caracalla board) fixed.
    2) Firmware assert 0x71 (while doing bgscan) issue fixed.
    3) Keep alive functionality in station mode issue fixed.
    4) Data traffic stops when connected to multiple stations issue resolved
    5) WoWLAN not working issue is resolved

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Not verified removing SDIO interrupt polling
    3) S4/S5 sleep states not supported (with and without WoWLAN)
    4) Wi-Fi direct testing is in progress

0.9.8.5_RC1 -
    WLAN Bug Fixes:
    -------------------
    1) Observed unicast probe requests during bgscan issue fixed
    2) Firmware assert 0x71 (while doing bgscan) issue fixed.
    3) Crash when doing rmmod while data traffic is going on issue resolved.
    4) Beacons stopped after 5 minutes of data traffic issue fixed.
    5) Keep alive functionality in station mode issue fixed
    6) 11n data rates issue in station mode resolved.

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) EAP not supported
    2) Not verified removing SDIO interrupt polling
    3) S4/S5 sleep states not supported (with.without WoWLAN)
    4) power save is not working consistently
    5) WoWLAN is not working consistently

0.9.8.3 -
    WLAN New Features:
    -----------------------------------------
    1) AP Mode
    2) S3, S4 suspend and resume
    3) WoWLAN [Testing in progress]

    WLAN Bug Fixes:
    -------------------
    1) First EAPOL drop issue is resolved
    2) Firmware Assert while roaming issue is resolved
       (Provide driver bgsan should be enabled along with supplicant bgscan)
    3) Roaming takes longer time issue is resolved
    4) Added polling support as a work-around for the SDIO interrupt issue
       on some platforms

    WLAN Limitations/Features NOT Supported:
    ----------------------------------------
    1) Wi-Fi Direct mode not supported
    2) EAP not supported
    3) SDIO interrupts are not being delivered to the 9113 driver
    4) In S4 state 9113 device gets reset but device isn't getting re-enumerated.

Signed-off-by: Shrirang Bagul <shrirang.bagul at canonical.com>
---
 ubuntu/rsi/rsi_91x_coex.c     |   2 +-
 ubuntu/rsi/rsi_91x_core.c     |  57 +++++++--
 ubuntu/rsi/rsi_91x_hal.c      |  19 ++-
 ubuntu/rsi/rsi_91x_hci.c      |  67 ++++++++++-
 ubuntu/rsi/rsi_91x_mac80211.c |  35 +++---
 ubuntu/rsi/rsi_91x_main.c     |   2 +
 ubuntu/rsi/rsi_91x_mgmt.c     |  90 ++++----------
 ubuntu/rsi/rsi_91x_sdio.c     | 269 ++++++++++++++++++++++++++----------------
 ubuntu/rsi/rsi_91x_sdio_ops.c |  63 +++-------
 ubuntu/rsi/rsi_91x_usb.c      |  51 ++++++++
 ubuntu/rsi/rsi_91x_usb_ops.c  |   3 +-
 ubuntu/rsi/rsi_hal.h          |   8 ++
 ubuntu/rsi/rsi_hci.h          |  29 +++++
 ubuntu/rsi/rsi_main.h         |  18 ++-
 ubuntu/rsi/rsi_mgmt.h         |   5 +-
 ubuntu/rsi/rsi_sdio.h         |   8 +-
 ubuntu/rsi/rsi_usb.h          |  19 ++-
 17 files changed, 472 insertions(+), 273 deletions(-)

diff --git a/ubuntu/rsi/rsi_91x_coex.c b/ubuntu/rsi/rsi_91x_coex.c
index 05a87d6b81e4..5b3b3ac3bec9 100644
--- a/ubuntu/rsi/rsi_91x_coex.c
+++ b/ubuntu/rsi/rsi_91x_coex.c
@@ -106,7 +106,7 @@ int rsi_coex_recv_pkt(struct rsi_common *common, u8 *msg)
 
 	if (msg_type == COMMON_CARD_READY_IND) {
 		ven_rsi_dbg(INFO_ZONE, "COMMON CARD READY RECEIVED\n");
-		rsi_handle_card_ready(common);
+		rsi_handle_card_ready(common, msg);
 	} else if (msg_type == SLEEP_NOTIFY_IND) {
 		ven_rsi_dbg(INFO_ZONE, "\n\n sleep notify RECEIVED\n");
 		rsi_mgmt_pkt_recv(common, msg);
diff --git a/ubuntu/rsi/rsi_91x_core.c b/ubuntu/rsi/rsi_91x_core.c
index db365e4aa160..a349f973f0e8 100644
--- a/ubuntu/rsi/rsi_91x_core.c
+++ b/ubuntu/rsi/rsi_91x_core.c
@@ -294,10 +294,15 @@ void rsi_core_qos_processor(struct rsi_common *common)
 
 		mutex_lock(&common->tx_lock);
 
-		status = adapter->check_hw_queue_status(adapter, q_num);
+		status = adapter->host_intf_ops->check_hw_queue_status(adapter,
+								       q_num);
 		if (status <= 0) {
+			if ((q_num < MGMT_SOFT_Q) ||
+			    ((!adapter->peer_notify) &&
+			     (q_num == MGMT_SOFT_Q))) {
 			mutex_unlock(&common->tx_lock);
 			break;
+			}
 		}
 
 		if ((q_num < MGMT_SOFT_Q) &&
@@ -313,6 +318,11 @@ 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);
@@ -429,7 +439,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 		goto xmit_fail;
 	}
 #ifdef CONFIG_VEN_RSI_WOW
-	if (common->suspend_flag) {
+	if (common->wow_flags & RSI_WOW_ENABLED) {
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Blocking Tx_packets when WOWLAN is enabled\n",
 			__func__);
@@ -466,7 +476,7 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 
 #ifdef CONFIG_VEN_RSI_WOW          
 		if ((ieee80211_is_deauth(wlh->frame_control)) &&
-			(common->suspend_flag)) {
+		    (common->wow_flags & RSI_WOW_ENABLED)) {
 			ven_rsi_dbg(ERR_ZONE,
 				"%s: Discarding Deauth when WOWLAN is enabled\n",
 				__func__);
@@ -513,7 +523,6 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 			
 			tid = *qos & IEEE80211_QOS_CTL_TID_MASK;
 			skb->priority = TID_TO_WME_AC(tid);
-
 		} else {
 			tid = IEEE80211_NONQOS_TID;
 			skb->priority = BE_Q;
@@ -539,6 +548,12 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 				ieee80211_sn_inc(sta->seq_no[skb->priority]);
 #endif
 			tx_params->sta_id = sta->sta_id;
+			
+			/* Start aggregation if not done for this tid */
+			if (!sta->start_tx_aggr[tid]) {
+				sta->start_tx_aggr[tid] = true;
+				ieee80211_start_tx_ba_session(sta->sta, tid, 0);
+			}
 		} else {
 #if 0
 			seq = IEEE80211_SN_TO_SEQ(common->bc_mc_seqno);
@@ -563,14 +578,32 @@ void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 		}
 	}
 
-	if ((q_num != MGMT_SOFT_Q) &&
-	    ((skb_queue_len(&common->tx_queue[q_num]) + 1) >=
-	      DATA_QUEUE_WATER_MARK)) {
-		ven_rsi_dbg(ERR_ZONE, "%s: sw queue full\n", __func__);
-		if (!ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
-			ieee80211_stop_queue(adapter->hw, WME_AC(q_num));
-		rsi_set_event(&common->tx_thread.event);
-		goto xmit_fail;
+	if (q_num != MGMT_SOFT_Q)  {
+		u16 water_mark = DATA_QUEUE_WATER_MARK;
+
+		switch (q_num) {
+		case BK_Q:
+			water_mark = BK_DATA_QUEUE_WATER_MARK;
+			break;
+		case BE_Q:
+			water_mark = BE_DATA_QUEUE_WATER_MARK;
+			break;
+		case VI_Q:
+			water_mark = VI_DATA_QUEUE_WATER_MARK;
+			break;
+		case VO_Q:
+			water_mark = VO_DATA_QUEUE_WATER_MARK;
+			break;
+		}
+		if ((skb_queue_len(&common->tx_queue[q_num]) + 1) >= 
+	   	    water_mark) {
+			ven_rsi_dbg(ERR_ZONE, "%s: queue %d is full\n",
+				__func__, q_num);
+			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);
diff --git a/ubuntu/rsi/rsi_91x_hal.c b/ubuntu/rsi/rsi_91x_hal.c
index 51154e3088ff..6b2be0293b32 100644
--- a/ubuntu/rsi/rsi_91x_hal.c
+++ b/ubuntu/rsi/rsi_91x_hal.c
@@ -476,7 +476,6 @@ int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb)
 				goto out;
 			}
 		}
-		ven_rsi_dbg(MGMT_TX_ZONE, "Sending PROBE REQUEST =====>\n");
 	}
 
 	ven_rsi_dbg(MGMT_TX_ZONE,
@@ -503,12 +502,25 @@ int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
 	int status = -EINVAL;
 	u8 header_size = 0;
 	__le16 *frame_desc;
+	u8 queueno = ((skb->data[1] >> 4) & 0xf);
+
+	if (queueno == RSI_BT_MGMT_Q) {
+		rsi_hex_dump(MGMT_TX_ZONE, "TX BT Mgmt Pkt",
+			     skb->data, skb->len);
+		status = adapter->host_intf_ops->write_pkt(common->priv,
+							   skb->data,
+							   skb->len);
+		if (status)
+			ven_rsi_dbg(ERR_ZONE, "%s: Failed to write bt mgmt pkt\n",
+				__func__);
+		goto out;
+	}
 
 	header_size = FRAME_DESC_SZ;
 	if (header_size > skb_headroom(skb)) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Not enough headroom\n", __func__);
 		status = -ENOSPC;
-		goto err;
+		goto out;
 	}
 	skb_push(skb, header_size);
 	frame_desc = (__le16 *)&skb->data[0];
@@ -525,7 +537,7 @@ int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb)
 	if (status)
 		ven_rsi_dbg(ERR_ZONE, "%s: Failed to write bt pkt\n", __func__);
 
-err:
+out:
 	dev_kfree_skb(skb);
 	return status;
 }
@@ -1213,6 +1225,7 @@ int rsi_hal_device_init(struct rsi_hw *adapter)
 	case DEV_OPMODE_STA_BT_LE:
 	case DEV_OPMODE_BT_ALONE:
 	case DEV_OPMODE_BT_LE_ALONE:
+	case DEV_OPMODE_BT_DUAL:
 		common->coex_mode = 2;
 		break;
 	case DEV_OPMODE_AP_BT_DUAL:
diff --git a/ubuntu/rsi/rsi_91x_hci.c b/ubuntu/rsi/rsi_91x_hci.c
index c74d40c0f4e1..2f982bdab470 100644
--- a/ubuntu/rsi/rsi_91x_hci.c
+++ b/ubuntu/rsi/rsi_91x_hci.c
@@ -152,7 +152,7 @@ static int rsi_hci_send_pkt(struct hci_dev *hdev, struct sk_buff *skb)
 
 #ifdef CONFIG_VEN_RSI_WOW
 	/* Stop here when in suspend */
-	if (h_adapter->priv->suspend_flag) {
+	if (h_adapter->priv->wow_flags & RSI_WOW_ENABLED) {
 		ven_rsi_dbg(INFO_ZONE, "In suspend: Dropping the pkt\n");
 		status = -ENETDOWN;
 		goto fail;
@@ -223,6 +223,58 @@ fail:
 	return status;
 }
 
+int rsi_send_rfmode_frame(struct rsi_common *common)
+{
+	struct sk_buff *skb;
+	struct rsi_bt_rfmode_frame *cmd_frame;
+
+	ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending BT RF mode frame\n", __func__);
+
+	skb = dev_alloc_skb(sizeof(struct rsi_bt_rfmode_frame));
+	if (!skb)
+		return -ENOMEM;
+
+	memset(skb->data, 0, sizeof(struct rsi_bt_rfmode_frame));
+	cmd_frame = (struct rsi_bt_rfmode_frame *)skb->data;
+
+	/* Length is 0 */
+	cmd_frame->desc.q_no = RSI_BT_MGMT_Q;
+	cmd_frame->desc.pkt_type = RSI_BT_PKT_TYPE_RFMODE;
+	cmd_frame->bt_rf_tx_power_mode = 0;
+	cmd_frame->bt_rf_tx_power_mode = 0;
+
+	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);
+}
+EXPORT_SYMBOL_GPL(rsi_send_rfmode_frame);
+
+int rsi_deregister_bt(struct rsi_common *common)
+{
+	struct sk_buff *skb;
+	struct rsi_bt_cmd_frame *cmd_frame;
+
+	ven_rsi_dbg(MGMT_TX_ZONE, "%s: Sending BT register frame\n", __func__);
+
+	skb = dev_alloc_skb(sizeof(struct rsi_bt_cmd_frame));
+	if (!skb)
+		return -ENOMEM;
+
+	memset(skb->data, 0, sizeof(struct rsi_bt_cmd_frame));
+	cmd_frame = (struct rsi_bt_cmd_frame *)skb->data;
+
+	/* Length is 0 */
+	cmd_frame->q_no = RSI_BT_MGMT_Q;
+	cmd_frame->pkt_type = RSI_BT_PKT_TYPE_DEREGISTR;
+
+	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);
+}
+EXPORT_SYMBOL_GPL(rsi_deregister_bt);
+
 int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 {
 	struct rsi_hci_adapter *h_adapter =
@@ -237,6 +289,14 @@ int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 		ven_rsi_dbg(INIT_ZONE, "%s: ===> BT Card Ready Received <===\n",
 			__func__);
 
+		if (common->suspend_in_prog) {
+			ven_rsi_dbg(INFO_ZONE,
+				"Suspend is in prog; Do not process\n");
+			return 0;
+		}
+
+		rsi_send_rfmode_frame(common);
+
 		ven_rsi_dbg(INFO_ZONE, "Attaching HCI module\n");
 
 		if (rsi_hci_attach(common)) {
@@ -370,7 +430,6 @@ err:
 	return rc;
 }
 
-
 /**
  * rsi_hci_attach () - This function initializes HCI interface
  *				      
@@ -521,6 +580,9 @@ 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);
@@ -540,6 +602,7 @@ void rsi_hci_detach(struct rsi_common *common)
 		kfree(gcb);
 	}
 	kfree(h_adapter);
+	common->bt_fsm_state = BT_DEVICE_NOT_READY;
 
 	return;
 }
diff --git a/ubuntu/rsi/rsi_91x_mac80211.c b/ubuntu/rsi/rsi_91x_mac80211.c
index 19b851ef0978..185444f77cf9 100644
--- a/ubuntu/rsi/rsi_91x_mac80211.c
+++ b/ubuntu/rsi/rsi_91x_mac80211.c
@@ -513,7 +513,7 @@ static void rsi_mac80211_tx(struct ieee80211_hw *hw,
   struct ieee80211_vif *vif = adapter->vifs[adapter->sc_nvifs - 1];
 
 #ifdef CONFIG_VEN_RSI_WOW
-	if (common->suspend_flag) {
+	if (common->wow_flags & RSI_WOW_ENABLED) {
 		ieee80211_free_txskb(common->priv->hw, skb);
 		return;
 	}
@@ -1418,6 +1418,8 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw,
 		break;
 
 	case DISABLE_KEY:
+		if ((vif->type == NL80211_IFTYPE_STATION) ||
+		    (vif->type == NL80211_IFTYPE_P2P_CLIENT))
 		secinfo->security_enable = false;
 		ven_rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__);
 		memset(key, 0, sizeof(struct ieee80211_key_conf));
@@ -1800,7 +1802,7 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 	struct rsi_common *common = adapter->priv;
 	bool sta_exist = 0;
 
-	rsi_hex_dump(INFO_ZONE, "Station Add: ", sta->addr, ETH_ALEN);
+	rsi_hex_dump(INFO_ZONE, "Station Add", sta->addr, ETH_ALEN);
 
 	mutex_lock(&common->mutex);
 
@@ -1853,12 +1855,16 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 			}
 			for (j = 0; j < IEEE80211_NUM_ACS; j++)
 				common->stations[i].seq_no[j] = 1;
+			for (j = 0; j < IEEE80211_NUM_TIDS; j++)
+				common->stations[i].start_tx_aggr[j] = false;
 			common->num_stations++;
 		} else {
 			common->stations[i].sta = sta;
 			common->stations[i].sta_id = i;
 			for (j = 0; j < IEEE80211_NUM_ACS; j++)
 				common->stations[i].seq_no[j] = 1;
+			for (j = 0; j < IEEE80211_NUM_TIDS; j++)
+				common->stations[i].start_tx_aggr[j] = false;
 		}
 	}
 
@@ -1879,7 +1885,9 @@ static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 		}
 	}
 
-	if (sta->ht_cap.ht_supported) {
+	if (((vif->type == NL80211_IFTYPE_STATION) ||
+	     (vif->type == NL80211_IFTYPE_P2P_CLIENT)) &&
+	    (sta->ht_cap.ht_supported)) {
 		common->vif_info[0].is_ht = true;
 		common->bitrate_mask[NL80211_BAND_2GHZ] =
 				sta->supp_rates[NL80211_BAND_2GHZ];
@@ -1910,9 +1918,8 @@ static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
 	struct ieee80211_bss_conf *bss = &vif->bss_conf;
-//		&adapter->vifs[adapter->sc_nvifs - 1]->bss_conf;
 
-	rsi_hex_dump(INFO_ZONE, "Station Removed: ", sta->addr, ETH_ALEN);
+	rsi_hex_dump(INFO_ZONE, "Station Removed", sta->addr, ETH_ALEN);
 
 	mutex_lock(&common->mutex);
 	if ((vif->type == NL80211_IFTYPE_AP) ||
@@ -2325,10 +2332,12 @@ int rsi_mac80211_suspend(struct ieee80211_hw *hw,
 	if (!bss->assoc) {
 		ven_rsi_dbg(ERR_ZONE,
 			"Cannot configure WoWLAN (Station not connected)\n");
-		common->suspend_flag = STATION_NOT_CONNECTED;
+		common->wow_flags |= RSI_WOW_NO_CONNECTION;
 		ret = 0;
 		goto fail_wow;
 	}
+	ven_rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
+	rsi_send_wowlan_request(common, triggers, 1);
 
 	/* Send updated vap caps */
 	rsi_send_vap_dynamic_update(common);
@@ -2336,13 +2345,9 @@ int rsi_mac80211_suspend(struct ieee80211_hw *hw,
 	rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
 			  DISALLOW_BEACONS |
 			  0);
-
-
-	rsi_send_wowlan_request(common, triggers, 1);
-	ven_rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
 	rsi_send_rx_filter_frame(common, rx_filter_word);
 
-        common->suspend_flag = 1;
+        common->wow_flags |= RSI_WOW_ENABLED;
 fail_wow:
 #endif
         return (ret ? 1 : 0);
@@ -2355,7 +2360,7 @@ static int rsi_mac80211_resume(struct ieee80211_hw *hw)
 	struct rsi_common *common = adapter->priv;
 	u16 rx_filter_word = 0;
 
-	adapter->priv->suspend_flag = 0;
+	adapter->priv->wow_flags = 0;
 #endif
 	
 	ven_rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
@@ -2665,8 +2670,8 @@ int rsi_mac80211_attach(struct rsi_common *common)
 	hw->max_rate_tries = MAX_RETRIES;
 	hw->uapsd_queues = IEEE80211_MARKALL_UAPSD_QUEUES;
 	hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
-//	hw->max_tx_aggregation_subframes = 6;
-	hw->max_tx_aggregation_subframes = 4;
+	hw->max_tx_aggregation_subframes = 8;
+//	hw->max_rx_aggregation_subframes = 8;
 
 	rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
 	wiphy->bands[NL80211_BAND_2GHZ] =
@@ -2714,6 +2719,7 @@ int rsi_mac80211_attach(struct rsi_common *common)
 	/* AP Parameters */
 	wiphy->flags = WIPHY_FLAG_REPORTS_OBSS;
 	wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
 
 	/*wiphy->regulatory_flags = (REGULATORY_STRICT_REG |
 				   REGULATORY_CUSTOM_REG);
@@ -2732,7 +2738,6 @@ int rsi_mac80211_attach(struct rsi_common *common)
 	hw->max_listen_interval = 10;
 	wiphy->iface_combinations = rsi_iface_combinations;
 	wiphy->n_iface_combinations = ARRAY_SIZE(rsi_iface_combinations);
-	wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
 //	wiphy->features |= (NL80211_FEATURE_P2P_GO_CTWIN |
 //			    NL80211_FEATURE_P2P_GO_OPPPS);
 #endif
diff --git a/ubuntu/rsi/rsi_91x_main.c b/ubuntu/rsi/rsi_91x_main.c
index 07cf4f4108f1..72b80ba1a878 100644
--- a/ubuntu/rsi/rsi_91x_main.c
+++ b/ubuntu/rsi/rsi_91x_main.c
@@ -111,6 +111,8 @@ char *opmode_str(int oper_mode)
 	       return "BT EDR alone";
 	case DEV_OPMODE_BT_LE_ALONE:
 	       return "BT LE alone";
+	case DEV_OPMODE_BT_DUAL:
+	       return "BT Dual";
 	case DEV_OPMODE_STA_BT:
 	       return "Wi-Fi STA + BT EDR";
 	case DEV_OPMODE_STA_BT_LE:
diff --git a/ubuntu/rsi/rsi_91x_mgmt.c b/ubuntu/rsi/rsi_91x_mgmt.c
index b12be2ed501e..2cd37bd5a8f9 100644
--- a/ubuntu/rsi/rsi_91x_mgmt.c
+++ b/ubuntu/rsi/rsi_91x_mgmt.c
@@ -286,7 +286,7 @@ struct rsi_ulp_gpio_vals unused_ulp_gpio_bitmap = {
 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
+	.host_wakeup_intr	= USED_GPIO,	//GPIO_2
 	.pspi_data_0		= USED_GPIO,	//GPIO_3
 	.pspi_data_1		= USED_GPIO,	//GPIO_4
 	.pspi_data_2		= USED_GPIO,	//GPIO_5
@@ -426,6 +426,9 @@ static int rsi_send_internal_mgmt_frame(struct rsi_common *common,
 	tx_params = (struct skb_info *)&IEEE80211_SKB_CB(skb)->driver_data;
 	tx_params->flags |= INTERNAL_MGMT_PKT;
 	skb->priority = MGMT_SOFT_Q;
+	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);
 	rsi_set_event(&common->tx_thread.event);
 	return 0;
@@ -655,6 +658,7 @@ int rsi_send_sta_notify_frame(struct rsi_common *common,
 	default:
 		break;
 	}
+	adapter->peer_notify = true;
 	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); //FIXME check this
@@ -992,57 +996,12 @@ int rsi_load_key(struct rsi_common *common,
 int rsi_send_common_dev_params(struct rsi_common *common)
 {
 	struct sk_buff *skb = NULL;
-	u32 *soc_gpio, len;
-	u16 *frame, *ulp_gpio, *desc;
-
-	ven_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);
 
-	ven_rsi_dbg(MGMT_TX_ZONE,
-		"%s: Sending common device config params frame\n",
-		__func__);
+	ven_rsi_dbg(MGMT_TX_ZONE, "Sending common device config params\n");
 	skb = dev_alloc_skb(frame_len);
 	if (!skb) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Unable to allocate skb\n", __func__);
@@ -1061,35 +1020,22 @@ int rsi_send_common_dev_params(struct rsi_common *common)
 	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;
+	dev_cfgs->unused_ulp_gpio = *(u8 *)&unused_ulp_gpio_bitmap;
+	dev_cfgs->unused_soc_gpio_bitmap =
+		cpu_to_le32(*(u32 *)&unused_soc_gpio_bitmap);
 
-	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->opermode = common->oper_mode;
 	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->region_code = NL80211_DFS_FCC;
 	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.
@@ -1975,7 +1921,7 @@ void rsi_inform_bss_status(struct rsi_common *common,
 		if (opmode == STA_OPMODE)
 			common->hw_data_qs_blocked = true;
 #ifdef CONFIG_VEN_RSI_WOW
-		if (!common->suspend_flag) {
+		if (!(common->wow_flags & RSI_WOW_ENABLED)) {
 #endif
 		rsi_send_sta_notify_frame(common,
 					  opmode,
@@ -2756,7 +2702,7 @@ out:
  *
  *Return: 0 on success, -1 on failure.
  */
-int rsi_handle_card_ready(struct rsi_common *common)
+int rsi_handle_card_ready(struct rsi_common *common, u8 *msg)
 {
 	switch (common->fsm_state) {
 	case FSM_CARD_NOT_READY:
@@ -2767,7 +2713,13 @@ int rsi_handle_card_ready(struct rsi_common *common)
 		common->fsm_state = FSM_COMMON_DEV_PARAMS_SENT;
 		break;
 	case FSM_COMMON_DEV_PARAMS_SENT:
-		ven_rsi_dbg(INIT_ZONE, "Common dev config params confirm\n");
+		ven_rsi_dbg(INIT_ZONE, "Card ready indication from WLAN HAL\n");
+
+		/* Get usb buffer status register address */
+		common->priv->usb_buffer_status_reg = *(u32 *)&msg[8];
+		ven_rsi_dbg(INFO_ZONE, "USB buffer status register = %x\n",
+			common->priv->usb_buffer_status_reg);
+
 		if (rsi_load_bootup_params(common)) {
 			common->fsm_state = FSM_CARD_NOT_READY;
 			return -EINVAL;
@@ -2805,7 +2757,7 @@ int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
 
 	case CARD_READY_IND:
 		ven_rsi_dbg(INIT_ZONE, "CARD READY INDICATION FROM WLAN.\n");
-		return rsi_handle_card_ready(common);
+		return rsi_handle_card_ready(common, msg);
 
 	case TX_STATUS_IND:
 		if (msg[15] == PROBEREQ_CONFIRM) {
diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
index 497484849ac1..8eb939868b0b 100644
--- a/ubuntu/rsi/rsi_91x_sdio.c
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -32,6 +32,7 @@
 #include "rsi_sdio.h"
 #include "rsi_common.h"
 #include "rsi_hal.h"
+#include "rsi_hci.h"
 
 /* Default operating mode is Wi-Fi alone */
 #ifdef CONFIG_CARACALLA_BOARD
@@ -919,7 +920,7 @@ int rsi_sdio_host_intf_write_pkt(struct rsi_hw *adapter,
 	int status;
 
 	queueno = ((pkt[1] >> 4) & 0xf);
-	if (queueno == RSI_BT_DATA_Q)
+	if ((queueno == RSI_BT_DATA_Q) || (queueno == RSI_BT_MGMT_Q))
 		queueno = RSI_BT_Q;
 
 	num_blocks = len / block_size;
@@ -1027,7 +1028,6 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
 	sdio_release_host(pfunction);
 
 	adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
-	adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
 	adapter->process_isr_hci = rsi_interrupt_handler;
 	adapter->check_intr_status_reg = rsi_read_intr_status_reg;
 	
@@ -1050,6 +1050,7 @@ static struct rsi_host_intf_ops sdio_host_intf_ops = {
 	.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,
+	.check_hw_queue_status	= rsi_sdio_check_buffer_status,
 };
 
 /**
@@ -1196,90 +1197,28 @@ int rsi_set_sdio_pm_caps(struct rsi_hw *adapter)
 	return ret;
 }
 
-static int rsi_freeze(struct device *dev)
+static int rsi_sdio_disable_interrupts(struct sdio_func *pfunction)
 {
-	int ret = 0;
-	struct sdio_func *pfunction = dev_to_sdio_func(dev);
 	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
-#ifdef CONFIG_VEN_RSI_WOW
-	struct rsi_91x_sdiodev *sdev =
-		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
-#endif
-	u8 isr_status = 0;
-
-	ven_rsi_dbg(INFO_ZONE, "SDIO Bus freeze ===>\n");
+	u8 isr_status = 0, data = 0;
+	int ret;
 
-#ifdef CONFIG_VEN_RSI_WOW
-	if ((adapter->priv->suspend_flag == STATION_NOT_CONNECTED) ||
-	    (sdev->write_fail)) { 
-		ven_rsi_dbg(ERR_ZONE,
-			"SUSPEND Cannot proceed as Device is not ready\n");
-		ven_rsi_dbg(ERR_ZONE,
-			"Disable WoWLAN / Connect to AP\n");
-		return -EBUSY;
-	}
-#endif
-	ven_rsi_dbg(INFO_ZONE, "Waiting for interrupts to be cleared..");
+	ven_rsi_dbg(ERR_ZONE, "Waiting for interrupts to be cleared..");
 	do {
 		rsi_sdio_read_register(adapter,
 				       RSI_FN1_INT_REGISTER,
 				       &isr_status);
-		printk(".");
+		ven_rsi_dbg(ERR_ZONE, ".");
 	} while (isr_status);
-	printk("\n");
-
-	ret = rsi_set_sdio_pm_caps(adapter);
-	if (ret)
-		ven_rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
-
-	return 0;
-}
-
-static int rsi_suspend(struct device *dev)
-{
-	int ret = 0;
-	struct sdio_func *pfunction = dev_to_sdio_func(dev);
-	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
-#ifdef CONFIG_VEN_RSI_WOW
-	struct rsi_91x_sdiodev *sdev =
-		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
-#endif
-	u8 isr_status = 0;
-	u8 data = 0;
-
-	ven_rsi_dbg(INFO_ZONE, "SDIO Bus suspend ===>\n");
-
-	if (!adapter) {
-		ven_rsi_dbg(ERR_ZONE, "Device is not ready\n");
-		return -ENODEV;
-	}
+	ven_rsi_dbg(ERR_ZONE, "\nInterrupts cleared");
 
-#ifdef CONFIG_VEN_RSI_WOW
-	if ((adapter->priv->suspend_flag == STATION_NOT_CONNECTED) ||
-	    (sdev->write_fail)) { 
-		ven_rsi_dbg(ERR_ZONE,
-			"SUSPEND Cannot proceed; Device is not ready\n");
-		ven_rsi_dbg(ERR_ZONE,
-			"Disable WoWLAN / Connect to AP\n");
-		return -EBUSY;
-	}
-#endif
-	printk("Waiting for interrupts to be cleared..");
-	do {
-		rsi_sdio_read_register(adapter,
-				       RSI_FN1_INT_REGISTER,
-				       &isr_status);
-		printk(".");
-	} while (isr_status); 
-	printk("\n");
-
-	/* Release IRQ */
 	sdio_claim_host(pfunction);
 	ret = rsi_cmd52readbyte(pfunction->card, 0x04, &data);
 	if (ret < 0) {
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to read INTR_EN register\n",
 			__func__);
+		sdio_release_host(pfunction);
 		return ret;
 	}
 	ven_rsi_dbg(INFO_ZONE, "INTR_EN reg content = %x\n", data);
@@ -1292,6 +1231,7 @@ static int rsi_suspend(struct device *dev)
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to Write to INTR_EN register\n",
 			__func__);
+		sdio_release_host(pfunction);
 		return ret;
 	}
 	ret = rsi_cmd52readbyte(pfunction->card, 0x04, &data);
@@ -1299,39 +1239,27 @@ static int rsi_suspend(struct device *dev)
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to read INTR_EN register\n",
 			__func__);
+		sdio_release_host(pfunction);
 		return ret;
 	}
 	ven_rsi_dbg(INFO_ZONE, "INTR_EN reg content. = %x\n", data);
 
 	sdio_release_host(pfunction);
-
-	ret = rsi_set_sdio_pm_caps(adapter);
-	if (ret)
-		ven_rsi_dbg(INFO_ZONE,
-			"Setting power management caps failed\n");
-
-	ven_rsi_dbg(INFO_ZONE, "***** SDIO BUS SUSPEND DONE ******\n");
 	
 	return 0;
 }
 
-int rsi_resume(struct device *dev)
+static int rsi_sdio_enable_interrupts(struct sdio_func *pfunction)
 {
-	int ret = 0;
-	u8 data = 0;
-	struct sdio_func *pfunction = dev_to_sdio_func(dev);
-#ifdef CONFIG_VEN_RSI_WOW
-	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
-        
-	ven_rsi_dbg(INFO_ZONE, "***** BUS RESUME ******\n");
-        adapter->priv->suspend_flag = 0;
-#endif
+	u8 data;
+	int ret;
 
 	sdio_claim_host(pfunction);
 	ret = rsi_cmd52readbyte(pfunction->card, 0x04, &data);
 	if (ret < 0) {
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to read INTR_EN register\n", __func__);
+		sdio_release_host(pfunction);
 		return ret;
 	}
 	ven_rsi_dbg(INFO_ZONE, "INTR_EN reg content1 = %x\n", data);
@@ -1344,6 +1272,7 @@ int rsi_resume(struct device *dev)
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to Write to INTR_EN register\n",
 			__func__);
+		sdio_release_host(pfunction);
 		return ret;
 	}
 	
@@ -1351,56 +1280,187 @@ int rsi_resume(struct device *dev)
 	if (ret < 0) {
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to read INTR_EN register\n", __func__);
+		sdio_release_host(pfunction);
 		return ret;
 	}
 	ven_rsi_dbg(INFO_ZONE, "INTR_EN reg content1.. = %x\n", data);
 	sdio_release_host(pfunction);
 
-	ven_rsi_dbg(INFO_ZONE, "***** RSI module resumed *****\n");
-	return 0;
+	return ret;
 }
 
-int rsi_thaw(struct device *dev)
+static int rsi_suspend(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;
 #ifdef CONFIG_VEN_RSI_WOW
+	struct rsi_91x_sdiodev *sdev =
+		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
+#endif
+
+	ven_rsi_dbg(INFO_ZONE, "SDIO Bus suspend ===>\n");
+
+	if (!adapter) {
+		ven_rsi_dbg(ERR_ZONE, "Device is not ready\n");
+		return -ENODEV;
+	}
+
+	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 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
+
+	ret = rsi_sdio_disable_interrupts(pfunction);
+	if (ret)
+		return ret;
+
+	if (sdev->write_fail) {
+		ven_rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
+		return 0;
+	}
+
+	ret = rsi_set_sdio_pm_caps(adapter);
+	if (ret)
+		ven_rsi_dbg(INFO_ZONE,
+			"Setting power management caps failed\n");
+
+	ven_rsi_dbg(INFO_ZONE, "***** SDIO BUS SUSPEND DONE ******\n");
+
+	return 0;
+}
+
+int rsi_resume(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;
+        
+	ven_rsi_dbg(INFO_ZONE, "***** BUS RESUME ******\n");
 
-	ven_rsi_dbg(INFO_ZONE, "***** BUS THAW ******\n");
-	adapter->priv->suspend_flag = 0;
+	common->suspend_in_prog = false;
+
+	ret = rsi_sdio_enable_interrupts(pfunction);
+	if (ret)
+		return ret;
+
+#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
 
-	ven_rsi_dbg(INFO_ZONE, "RSI module resumed\n");
+	ven_rsi_dbg(INFO_ZONE, "***** RSI module resumed *****\n");
 	return 0;
 }
 
-int rsi_restore(struct device *dev)
+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;
+#ifdef CONFIG_VEN_RSI_WOW
+	struct rsi_91x_sdiodev *sdev =
+		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
+#endif
+
+	ven_rsi_dbg(INFO_ZONE, "SDIO Bus freeze ===>\n");
+
+	if (!adapter) {
+		ven_rsi_dbg(ERR_ZONE, "Device is not ready\n");
+		return -ENODEV;
+	}
 
+	common->suspend_in_prog = true;
 #ifdef CONFIG_VEN_RSI_WOW
-	ven_rsi_dbg(INFO_ZONE, "***** BUS RESTORE ******\n");
-	adapter->priv->suspend_flag = 0;
+	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 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
+	}
 #endif
-	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);
+	ret = rsi_sdio_disable_interrupts(pfunction);
+	if (ret)
+		return ret;
+
+	if (sdev->write_fail) {
+		ven_rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n");
+		return 0;
+	}
+	
+	ret = rsi_set_sdio_pm_caps(adapter);
+	if (ret)
+		ven_rsi_dbg(INFO_ZONE, "Setting power management caps failed\n");
+	
+	return 0;
+}
+
+int rsi_thaw(struct device *dev)
+{
+	int ret;
+	struct sdio_func *pfunction = dev_to_sdio_func(dev);
+	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+
+	ven_rsi_dbg(INFO_ZONE, "***** BUS THAW ******\n");
+
+	adapter->priv->suspend_in_prog = false;
+
+	ret = rsi_sdio_enable_interrupts(pfunction);
+	if (ret)
+		return ret;
 
 	ven_rsi_dbg(INFO_ZONE, "RSI module resumed\n");
 	return 0;
 }
 
+static int rsi_poweroff(struct device *dev)
+{
+	return rsi_suspend(dev);
+}
+
+static void rsi_shutdown(struct device *dev)
+{
+	rsi_suspend(dev);
+}
+
+int rsi_restore(struct device *dev)
+{
+	return rsi_thaw(dev);
+}
+
 static const struct dev_pm_ops rsi_pm_ops = {
 	.suspend = rsi_suspend,
 	.resume = rsi_resume,
 	.freeze = rsi_freeze,
 	.thaw = rsi_thaw,
-	.poweroff = rsi_suspend,
+	.poweroff = rsi_poweroff,
 	.restore = rsi_restore,
 };
 #endif
@@ -1423,6 +1483,7 @@ static struct sdio_driver rsi_driver = {
 #ifdef CONFIG_PM
 	.drv = {
 		.pm = &rsi_pm_ops,
+	        .shutdown   = rsi_shutdown,
 	}
 #endif
 };
diff --git a/ubuntu/rsi/rsi_91x_sdio_ops.c b/ubuntu/rsi/rsi_91x_sdio_ops.c
index 801bb57d1093..d575567ac3b8 100644
--- a/ubuntu/rsi/rsi_91x_sdio_ops.c
+++ b/ubuntu/rsi/rsi_91x_sdio_ops.c
@@ -269,7 +269,6 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
 	enum sdio_interrupt_type isr_type;
 	u8 isr_status = 0;
 	u8 fw_status = 0;
-	u8 buf_status = 0;
 
 	dev->rx_info.sdio_int_counter++;
 
@@ -308,40 +307,11 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
 
 			switch (isr_type) {
 			case BUFFER_AVAILABLE:
-				status = rsi_sdio_read_register(common->priv,
-						RSI_DEVICE_BUFFER_STATUS_REGISTER,
-						&buf_status);
-				if (status) {
+				status = rsi_sdio_check_buffer_status(adapter, 0);
+				if (status < 0)
 					ven_rsi_dbg(ERR_ZONE,
-						"%s: Failed to read status register\n",
+						"%s: Failed to check buffer status\n",
 						__func__);
-					return;
-				}
-				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.buf_available_counter++;
-					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.buf_available_counter++;
-				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.buf_available_counter++;
-				dev->rx_info.semi_buffer_full = false;
-				}
-
 				rsi_sdio_ack_intr(common->priv,
 						  (1 << PKT_BUFF_AVAILABLE));
 				rsi_set_event(&common->tx_thread.event);
@@ -403,7 +373,7 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
 }
 
 /**
- * rsi_sdio_read_buffer_status_register() - This function is used to the read
+ * rsi_sdio_check_buffer_status() - This function is used to the read
  *					    buffer status register and set
  *					    relevant fields in
  *					    rsi_91x_sdiodev struct.
@@ -412,21 +382,19 @@ void rsi_interrupt_handler(struct rsi_hw *adapter)
  *
  * 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)
+int rsi_sdio_check_buffer_status(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;
-//	static int counter = 4;
+	static int counter = 4;
 
-#if 0
-	if ((!dev->buff_status_updated) && counter) {
+	if (!dev->buff_status_updated && counter) {
 		counter--;
 		goto out;
 	}
-#endif
 
 	dev->buff_status_updated = 0;
 	status = rsi_sdio_read_register(common->priv,
@@ -442,28 +410,29 @@ int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
 		if (!dev->rx_info.mgmt_buffer_full)
 			dev->rx_info.mgmt_buf_full_counter++;
 		dev->rx_info.mgmt_buffer_full = true;
-	} else {
+	} 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 {
+	} 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 {
+	} else
 		dev->rx_info.semi_buffer_full = false;
-	}
-//	(dev->rx_info.semi_buffer_full ? (counter = 4) : (counter = 1));
 
-//out:
+	if (dev->rx_info.mgmt_buffer_full || dev->rx_info.buf_full_counter)
+		counter = 1;
+	else
+		counter = 4;
+
+out:
 	if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))
 		return QUEUE_FULL;
 
diff --git a/ubuntu/rsi/rsi_91x_usb.c b/ubuntu/rsi/rsi_91x_usb.c
index e6de38606451..bdc26aa9fb98 100644
--- a/ubuntu/rsi/rsi_91x_usb.c
+++ b/ubuntu/rsi/rsi_91x_usb.c
@@ -61,6 +61,7 @@ static struct rsi_host_intf_ops usb_host_intf_ops = {
 	.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,
+	.check_hw_queue_status	= rsi_usb_check_queue_status,
 };
 
 /**
@@ -485,6 +486,56 @@ int rsi_usb_load_data_master_write(struct rsi_hw *adapter,
 	return 0;
 }
 
+int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num)
+{
+	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;
+
+	status = rsi_usb_reg_read(dev->usbdev, adapter->usb_buffer_status_reg,
+				  &buf_status, 2);
+	if (status < 0)
+		return status;
+
+	printk("buffer_status = %x\n", buf_status);
+	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 ((q_num < MGMT_SOFT_Q) && (dev->rx_info.buffer_full))
+		return QUEUE_FULL;
+
+	return QUEUE_NOT_FULL;
+}
+
 /**
  * rsi_deinit_usb_interface() - This function deinitializes the usb interface.
  * @adapter: Pointer to the adapter structure.
diff --git a/ubuntu/rsi/rsi_91x_usb_ops.c b/ubuntu/rsi/rsi_91x_usb_ops.c
index c587bc95185f..2f4c43e8a3c0 100644
--- a/ubuntu/rsi/rsi_91x_usb_ops.c
+++ b/ubuntu/rsi/rsi_91x_usb_ops.c
@@ -72,9 +72,10 @@ void rsi_usb_rx_thread(struct rsi_common *common)
 					"%s: Failed in urb submission", __func__);
 				break;
 			}
+			/* Update TX buffer status */
+			//rsi_usb_check_queue_status(adapter, 0);
 		}
 		rsi_reset_event(&dev->rx_thread.event);
-	
 	} while (1);
 
 	ven_rsi_dbg(INFO_ZONE, "%s: Terminated USB RX thread\n", __func__);
diff --git a/ubuntu/rsi/rsi_hal.h b/ubuntu/rsi/rsi_hal.h
index 900c1b29af30..ccb0e64d5de0 100644
--- a/ubuntu/rsi/rsi_hal.h
+++ b/ubuntu/rsi/rsi_hal.h
@@ -35,6 +35,7 @@
 #define DEV_OPMODE_WIFI_ALONE		1
 #define DEV_OPMODE_BT_ALONE		4
 #define DEV_OPMODE_BT_LE_ALONE		8
+#define DEV_OPMODE_BT_DUAL		12
 #define DEV_OPMODE_STA_BT		5
 #define DEV_OPMODE_STA_BT_LE		9
 #define DEV_OPMODE_STA_BT_DUAL		13
@@ -159,6 +160,12 @@
 #define FW_FLASH_OFFSET			0x820
 #define LMAC_VER_OFFSET			FW_FLASH_OFFSET +0x200
 
+/* 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
+
 struct bl_header {
 	__le32 flags;
 	__le32 image_no;
@@ -178,5 +185,6 @@ int rsi_hal_device_init(struct rsi_hw *adapter);
 int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb);
 int rsi_send_bt_pkt(struct rsi_common *common, struct sk_buff *skb);
 int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb);
+int rsi_deregister_bt(struct rsi_common *common);
 
 #endif
diff --git a/ubuntu/rsi/rsi_hci.h b/ubuntu/rsi/rsi_hci.h
index 26f554d4e522..2b6977c8c178 100644
--- a/ubuntu/rsi/rsi_hci.h
+++ b/ubuntu/rsi/rsi_hci.h
@@ -109,6 +109,35 @@ struct rsi_hci_adapter {
 	struct sk_buff_head hci_tx_queue;
 };
 
+/* TX BT command packet types */
+#define RSI_BT_PKT_TYPE_DEREGISTR		0x11
+#define RSI_BT_PKT_TYPE_RFMODE			0x55
+
+struct rsi_bt_cmd_frame {
+#ifdef __LITTLE_ENDIAN
+	u16 len:12;
+	u16 q_no:4;
+#else
+	u16 reserved1:4;
+	u16 q_no:12;
+#endif
+	__le16 reserved2[6];
+	u8 pkt_type;
+	u8 reserved3;
+};
+
+struct rsi_bt_rfmode_frame {
+	struct rsi_bt_cmd_frame desc;
+#ifdef __LITTLE_ENDIAN
+	u8 bt_rf_tx_power_mode:4;
+	u8 bt_rf_rx_power_mode:4;
+#else
+	u8 bt_rf_rx_power_mode:4;
+	u8 bt_rf_tx_power_mode:4;
+#endif
+	u8 reserved;
+};
+
 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);
diff --git a/ubuntu/rsi/rsi_main.h b/ubuntu/rsi/rsi_main.h
index 1e91db2bf1d6..0fc3ce316bf1 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.RC4"
+#define DRV_VER				"RS9113.NB0.NL.GNU.LNX.1.2.RC9"
 
 #define ERR_ZONE                        BIT(0) /* Error Msgs		*/
 #define INFO_ZONE                       BIT(1) /* Generic Debug Msgs	*/
@@ -75,6 +75,10 @@ void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len);
 
 #define DATA_QUEUE_WATER_MARK           400
 #define MIN_DATA_QUEUE_WATER_MARK       300
+#define BK_DATA_QUEUE_WATER_MARK	600
+#define BE_DATA_QUEUE_WATER_MARK	3200
+#define VI_DATA_QUEUE_WATER_MARK	3900
+#define VO_DATA_QUEUE_WATER_MARK	4500
 #define MULTICAST_WATER_MARK            200
 #define MAC_80211_HDR_FRAME_CONTROL     0
 #define WME_NUM_AC                      4
@@ -123,7 +127,10 @@ void rsi_hex_dump(u32 zone, char *msg_str, const u8 *msg, u32 len);
 	((_q) == VI_Q) ? IEEE80211_AC_VI : \
 	IEEE80211_AC_VO)
 
-#define STATION_NOT_CONNECTED		BIT(1)
+/* WoWLAN flags */
+#define RSI_WOW_ENABLED			BIT(0)
+#define RSI_WOW_NO_CONNECTION		BIT(1)
+
 struct version_info {
 	u16 major;
 	u16 minor;
@@ -223,6 +230,7 @@ struct rsi_sta {
 	s16 sta_id;
 	u16 seq_no[IEEE80211_NUM_ACS];
 	u16 seq_start[IEEE80211_NUM_ACS];
+	bool start_tx_aggr[IEEE80211_NUM_TIDS];
 };
 
 struct rsi_hw;
@@ -318,8 +326,9 @@ struct rsi_common {
 	u8 host_wakeup_intr_active_high;
 	int tx_power;
 	u8 ant_in_use;
+	bool suspend_in_prog;
 #ifdef CONFIG_VEN_RSI_WOW
-	u8 suspend_flag;
+	u8 wow_flags;
 #endif
 
 #if defined (CONFIG_VEN_RSI_BT_ALONE) || defined(CONFIG_VEN_RSI_COEX)
@@ -412,6 +421,7 @@ struct rsi_hw {
 	struct rsi_ps_info ps_info;
 	spinlock_t ps_lock;
 	u32 isr_pending;
+	u32 usb_buffer_status_reg;
 #ifdef CONFIG_VEN_RSI_DEBUGFS
 	struct rsi_debugfs *dfsentry;
 	u8 num_debugfs_entries;
@@ -429,6 +439,7 @@ struct rsi_hw {
 
 	u8 dfs_region;
 	char country[2];
+	bool peer_notify;
 	void *rsi_dev;
 
 	struct rsi_host_intf_ops *host_intf_ops;
@@ -457,6 +468,7 @@ struct rsi_host_intf_ops {
 				      u32 instructions_size, u16 block_size,
 				      u8 *fw);
 	int (*rsi_check_bus_status)(struct rsi_hw *adapter);
+	int (*check_hw_queue_status)(struct rsi_hw *adapter, u8 q_num);
 };
 
 #endif
diff --git a/ubuntu/rsi/rsi_mgmt.h b/ubuntu/rsi/rsi_mgmt.h
index 40a046c155a8..8965f237ac2b 100644
--- a/ubuntu/rsi/rsi_mgmt.h
+++ b/ubuntu/rsi/rsi_mgmt.h
@@ -501,8 +501,7 @@ struct rsi_config_vals {
 	u8 driver_mode;
 	u8 region_code;
 	u8 antenna_sel_val;
-#define EXT_PA      1
-#define EXT_BT_COEX 2
+	u8 reserved[16];
 } __packed;
 
 struct rsi_request_ps {
@@ -588,7 +587,7 @@ int rsi_send_radio_params_update(struct rsi_common *common);
 void init_bgscan_params(struct rsi_common *common);
 int rsi_set_antenna(struct rsi_common *common, u8 antenna);
 int rsi_hci_attach(struct rsi_common *common);
-int rsi_handle_card_ready(struct rsi_common *common);
+int rsi_handle_card_ready(struct rsi_common *common, u8 *msg);
 void rsi_validate_bgscan_channels(struct rsi_hw *adapter,
 				  struct bgscan_config_params *params);
 #ifdef CONFIG_VEN_RSI_WOW
diff --git a/ubuntu/rsi/rsi_sdio.h b/ubuntu/rsi/rsi_sdio.h
index 4f17d6402fd1..f2ce06099999 100644
--- a/ubuntu/rsi/rsi_sdio.h
+++ b/ubuntu/rsi/rsi_sdio.h
@@ -40,12 +40,6 @@
 #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
@@ -161,6 +155,6 @@ int rsi_sdio_master_reg_write(struct rsi_hw *adapter,
 			      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);
+int rsi_sdio_check_buffer_status(struct rsi_hw *adapter, u8 q_num);
 int rsi_read_intr_status_reg(struct rsi_hw *adapter);
 #endif
diff --git a/ubuntu/rsi/rsi_usb.h b/ubuntu/rsi/rsi_usb.h
index d91cef3beff9..c08ba6c18e25 100644
--- a/ubuntu/rsi/rsi_usb.h
+++ b/ubuntu/rsi/rsi_usb.h
@@ -60,8 +60,20 @@ struct rx_usb_ctrl_block {
 	u8 pend;
 };
 
+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 buf_full_counter;
+	u32 buf_available_counter;
+};
+
 struct rsi_91x_usbdev {
 	void *priv;
+	struct receive_info rx_info;
 	struct rsi_thread rx_thread;
 	u8 endpoint;
 	struct usb_device *usbdev;
@@ -77,12 +89,6 @@ struct rsi_91x_usbdev {
 	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;
@@ -104,4 +110,5 @@ int rsi_usb_load_data_master_write(struct rsi_hw *adapter, u32 base_address,
 				   u32 instructions_sz,
 				   u16 block_size,
 				   u8 *ta_firmware);
+int rsi_usb_check_queue_status(struct rsi_hw *adapter, u8 q_num);
 #endif
-- 
2.11.0





More information about the kernel-team mailing list