diff mbox

[v2,Xenial,SRU] UBUNTU: SAUCE: Redpine driver to support Host AP mode

Message ID 20170217043222.12774-1-shrirang.bagul@canonical.com
State New
Headers show

Commit Message

Shrirang Bagul Feb. 17, 2017, 4:32 a.m. UTC
BugLink: http://bugs.launchpad.net/bugs/1665211

Dell Caracalla IoT gateways sport a Redpine RS9113 WLAN-BT combo card.
This patch adds Host AP mode support to the Redpine RS9113 driver.
Vendor release version: 0.9.8.3 (Beta)

Other fixes:
- Connection drop issue with multiple APs/mobile phone hotspots

Signed-off-by: Shrirang Bagul <shrirang.bagul@canonical.com>
---
 ubuntu/rsi/Makefile           |   2 +-
 ubuntu/rsi/rsi_91x_core.c     |  50 +++++++++--
 ubuntu/rsi/rsi_91x_debugfs.c  |  35 ++++++--
 ubuntu/rsi/rsi_91x_hal.c      |  78 ++++++++++------
 ubuntu/rsi/rsi_91x_hci.c      |  44 +--------
 ubuntu/rsi/rsi_91x_mac80211.c | 160 +++++++++++++++++++++++++--------
 ubuntu/rsi/rsi_91x_main.c     |  94 +++++++++++++++++++
 ubuntu/rsi/rsi_91x_mgmt.c     | 204 +++++++++++++++++++++++++++---------------
 ubuntu/rsi/rsi_91x_sdio.c     |  92 ++++++++-----------
 ubuntu/rsi/rsi_91x_sdio_ops.c |  11 ++-
 ubuntu/rsi/rsi_coex.h         |   2 +-
 ubuntu/rsi/rsi_common.h       |   6 ++
 ubuntu/rsi/rsi_main.h         |  16 +++-
 ubuntu/rsi/rsi_mgmt.h         |  17 ++--
 14 files changed, 545 insertions(+), 266 deletions(-)

Comments

Brad Figg Feb. 17, 2017, 5:03 a.m. UTC | #1

Stefan Bader Feb. 17, 2017, 8:52 a.m. UTC | #2
On 17.02.2017 05:32, Shrirang Bagul wrote:
> BugLink: http://bugs.launchpad.net/bugs/1665211
> 
> Dell Caracalla IoT gateways sport a Redpine RS9113 WLAN-BT combo card.
> This patch adds Host AP mode support to the Redpine RS9113 driver.
> Vendor release version: 0.9.8.3 (Beta)
> 
> Other fixes:
> - Connection drop issue with multiple APs/mobile phone hotspots
> 

What I am missing either in the patch (but in this case bug report would be
better) is an assessment about impact and risk of regressing other things. From
the patch itself it is changing something that exists. What I cannot remember is
whether that only exists because it was specifically added for that specific HW.
I suppose I could go and dig the repo for an answer but it would speed up the
whole thing if whoever submits those kind of changes (I assume whoever does it
will remember those things) would add context and save me the hassle. ;)

-Stefan
Shrirang Bagul Feb. 17, 2017, 12:20 p.m. UTC | #3
On Fri, 2017-02-17 at 09:52 +0100, Stefan Bader wrote:
> On 17.02.2017 05:32, Shrirang Bagul wrote:
> > BugLink: http://bugs.launchpad.net/bugs/1665211
> > 
> > Dell Caracalla IoT gateways sport a Redpine RS9113 WLAN-BT combo card.
> > This patch adds Host AP mode support to the Redpine RS9113 driver.
> > Vendor release version: 0.9.8.3 (Beta)
> > 
> > Other fixes:
> > - Connection drop issue with multiple APs/mobile phone hotspots
> > 
> 
> What I am missing either in the patch (but in this case bug report would be
> better) is an assessment about impact and risk of regressing other things.
> From
> the patch itself it is changing something that exists. What I cannot remember
> is
> whether that only exists because it was specifically added for that specific
> HW.
> I suppose I could go and dig the repo for an answer but it would speed up the
> whole thing if whoever submits those kind of changes (I assume whoever does it
> will remember those things) would add context and save me the hassle. ;)
> 
> -Stefan
Got it. Henceforth, patch commit messages and bugs reports will have more
details about version history/changes, target HW and impact. Esp. because this
driver from the vendor is refactored and merged to ubuntu third party drivers to
resolve conflicts with existing driver in drivers/net/wireless/rsi.

-Shrirang
> 
>
Tim Gardner Feb. 17, 2017, 12:46 p.m. UTC | #4
Only affects one driver.
Thadeu Lima de Souza Cascardo Feb. 22, 2017, 11:50 a.m. UTC | #5
Applied to xenial master-next branch.

Thanks.
Cascardo.
diff mbox

Patch

diff --git a/ubuntu/rsi/Makefile b/ubuntu/rsi/Makefile
index 941848c..a7db51c 100644
--- a/ubuntu/rsi/Makefile
+++ b/ubuntu/rsi/Makefile
@@ -1,4 +1,4 @@ 
-EXTRA_CFLAGS += -DCONFIG_DELL_BOARD -DCONFIG_VEN_RSI_COEX -DLINUX -Wimplicit -Wstrict-prototypes -DCONFIG_VEN_RSI_DEBUGFS -DPLATFORM_X86
+EXTRA_CFLAGS += -DCONFIG_CARACALLA_BOARD -DCONFIG_VEN_RSI_COEX -DLINUX -Wimplicit -Wstrict-prototypes -DCONFIG_VEN_RSI_DEBUGFS -DPLATFORM_X86 -DCONFIG_RSI_WOW
 
 ven_rsi_91x-y			+= rsi_91x_main.o
 ven_rsi_91x-y			+= rsi_91x_core.o
diff --git a/ubuntu/rsi/rsi_91x_core.c b/ubuntu/rsi/rsi_91x_core.c
index eaf0e29..c44e435 100644
--- a/ubuntu/rsi/rsi_91x_core.c
+++ b/ubuntu/rsi/rsi_91x_core.c
@@ -270,15 +270,13 @@  void rsi_core_qos_processor(struct rsi_common *common)
 		ven_rsi_dbg(DATA_TX_ZONE,
 			"%s: Queue number = %d\n", __func__, q_num);
 
-		if (q_num == INVALID_QUEUE) {
-			ven_rsi_dbg(DATA_TX_ZONE, "%s: No More Pkt\n", __func__);
+		if (q_num == INVALID_QUEUE)
 			break;
-		}
 
 		mutex_lock(&common->tx_lock);
 
 		status = adapter->check_hw_queue_status(adapter, q_num);
-		if ((status <= 0)) {
+		if (status <= 0) {
 			mutex_unlock(&common->tx_lock);
 			break;
 		}
@@ -286,6 +284,8 @@  void rsi_core_qos_processor(struct rsi_common *common)
 		if ((q_num < MGMT_SOFT_Q) &&
 		    ((skb_queue_len(&common->tx_queue[q_num])) <=
 		      MIN_DATA_QUEUE_WATER_MARK)) {
+			if (!adapter->hw)
+				break;
 			if (ieee80211_queue_stopped(adapter->hw, WME_AC(q_num)))
 				ieee80211_wake_queue(adapter->hw,
 						     WME_AC(q_num));
@@ -368,7 +368,9 @@  struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr)
 {
 	int i;
 
-	for (i = 0; i < common->num_stations; i++) {
+	for (i = 0; i < RSI_MAX_ASSOC_STAS; i++) {
+		if (!common->stations[i].sta)
+			continue;
 		if (!(memcmp(common->stations[i].sta->addr,
 			     mac_addr, ETH_ALEN)))
 			return &common->stations[i];
@@ -397,7 +399,12 @@  void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 			__func__);
 		goto xmit_fail;
 	}
-
+#ifdef CONFIG_RSI_WOW
+	if(common->suspend_flag) {
+		ven_rsi_dbg(ERR_ZONE, "%s: Blocking Tx_packets when WOWLAN is enabled\n", __func__);
+		goto xmit_fail;
+	}
+#endif
 	if (common->fsm_state != FSM_MAC_INIT_DONE) {
 		ven_rsi_dbg(ERR_ZONE, "%s: FSM state not open\n", __func__);
 		goto xmit_fail;
@@ -410,9 +417,24 @@  void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 	if ((ieee80211_is_mgmt(wlh->frame_control)) ||
 	    (ieee80211_is_ctl(wlh->frame_control)) ||
 	    (ieee80211_is_qos_nullfunc(wlh->frame_control))) {
+		if ((ieee80211_is_assoc_req(wlh->frame_control)) ||
+	 	    (ieee80211_is_reassoc_req(wlh->frame_control))) {
+			struct ieee80211_bss_conf *bss = NULL;
+
+			bss = &adapter->vifs[0]->bss_conf;
+			rsi_send_sta_notify_frame(common, STA_OPMODE,
+						  STA_CONNECTED,
+						  bss->bssid, bss->qos,
+						  bss->aid, 0);
+		}
 		q_num = MGMT_SOFT_Q;
 		skb->priority = q_num;
-
+#ifdef CONFIG_RSI_WOW          
+		if ((ieee80211_is_deauth(wlh->frame_control)) && (common->suspend_flag)) {
+			ven_rsi_dbg(ERR_ZONE, "%s: Discarding Deauth when WOWLAN is enabled\n", __func__);
+			goto xmit_fail; 
+		}
+#endif
 		ven_rsi_dbg(INFO_ZONE, "Core: TX Dot11 Mgmt Pkt Type: %s\n",
 			dot11_pkt_type(wlh->frame_control));
 		if (ieee80211_is_probe_req(wlh->frame_control)) {
@@ -434,9 +456,19 @@  void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 		rsi_hex_dump(DATA_TX_ZONE, "TX Data Packet",
 			     skb->data, skb->len);
 
+		/* Drop the null packets if bgscan is enabled
+ 		 * as it is already handled in firmware */
+		if ((vif->type == NL80211_IFTYPE_STATION) && (common->bgscan_en)) {
+			if (ieee80211_is_qos_nullfunc(wlh->frame_control)) {
+				++common->tx_stats.total_tx_pkt_freed[skb->priority];
+				rsi_indicate_tx_status(adapter, skb, 0);
+				return;
+			}
+		}
+
 		if (ieee80211_is_data_qos(wlh->frame_control)) {
 			u8 *qos = ieee80211_get_qos_ctl(wlh);
-
+			
 			tid = *qos & IEEE80211_QOS_CTL_TID_MASK;
 			skb->priority = TID_TO_WME_AC(tid);
 
@@ -450,7 +482,7 @@  void rsi_core_xmit(struct rsi_common *common, struct sk_buff *skb)
 		} else {
 			tid = IEEE80211_NONQOS_TID;
 			skb->priority = BE_Q;
-
+		
 			if ((!is_broadcast_ether_addr(wlh->addr1)) &&
 			    (!is_multicast_ether_addr(wlh->addr1)) &&
 			    (vif->type == NL80211_IFTYPE_AP)) {
diff --git a/ubuntu/rsi/rsi_91x_debugfs.c b/ubuntu/rsi/rsi_91x_debugfs.c
index aeb0834..be4aec2 100644
--- a/ubuntu/rsi/rsi_91x_debugfs.c
+++ b/ubuntu/rsi/rsi_91x_debugfs.c
@@ -267,9 +267,19 @@  static ssize_t rsi_debug_zone_write(struct file *filp,
 static int rsi_bgscan_int_read(struct seq_file *file, void *data)
 {
 	struct rsi_common *common = file->private;
-	struct bgscan_config_params *params = &common->bgscan_info;
+	struct bgscan_config_params *params = NULL;
 	int cnt;
 
+	if (!common) {
+		ven_rsi_dbg(ERR_ZONE, "No Interface\n");
+		return -ENODEV;
+	}
+	if (common->iface_down) {
+		ven_rsi_dbg(ERR_ZONE, "Interface Down\n");
+		return -ENODEV;
+	}
+	params = &common->bgscan_info;
+
 	seq_printf(file, "%d %d %d %d %d %d %d %d\n",
 		   common->bgscan_en,
 		   params->bgscan_threshold,
@@ -314,14 +324,25 @@  static ssize_t rsi_bgscan_write(struct file *file,
 
 {
 	struct rsi_common *common = file->f_inode->i_private;
-	struct rsi_hw *adapter = common->priv;
-	struct ieee80211_bss_conf *bss = &adapter->vifs[0]->bss_conf;
+	struct rsi_hw *adapter = NULL;
+	struct ieee80211_bss_conf *bss = NULL;
 	char bgscan_buf[200];
 	int bgscan_vals[64] = { 0 };
 	int total_bytes, cnt = 0;
 	int bytes_read = 0, t_bytes;
 	int ret;
 
+	if (!common) {
+		ven_rsi_dbg(ERR_ZONE, "No Interface\n");
+		return -ENODEV;
+	}
+	if (common->iface_down) {
+		ven_rsi_dbg(ERR_ZONE, "Interface Down\n");
+		return -ENODEV;
+	}
+	adapter = common->priv;
+	bss = &adapter->vifs[0]->bss_conf;
+
 	total_bytes = simple_write_to_buffer(bgscan_buf,
 					     sizeof(bgscan_buf) - 1,
 					     ppos, user_buff, count);
@@ -387,10 +408,10 @@  static ssize_t rsi_bgscan_write(struct file *file,
 	common->bgscan_info.num_user_channels = bgscan_vals[6];
 	memset(&common->bgscan_info.user_channels, 0,
 	       (MAX_BGSCAN_CHANNELS * 2));
-	common->bgscan_info.num_user_channels =
+	common->bgscan_info.num_user_channels = 
 		((bgscan_vals[6] > MAX_BGSCAN_CHANNELS) ?
-		 MAX_BGSCAN_CHANNELS : bgscan_vals[6]);
-
+		 MAX_BGSCAN_CHANNELS : bgscan_vals[6]); 
+	
 	for (cnt = 0; cnt < common->bgscan_info.num_user_channels; cnt++)
 		common->bgscan_info.user_channels[cnt] = bgscan_vals[7 + cnt];
 
@@ -435,7 +456,7 @@  static ssize_t rsi_bgscan_write(struct file *file,
 			common->bgscan_en = 0;
 			g_bgscan_enable = 0;
 		}
-
+	
 } else {
 #ifdef PLATFORM_X86
 		ven_rsi_dbg(ERR_ZONE, "Failed sending bgscan params req\n");
diff --git a/ubuntu/rsi/rsi_91x_hal.c b/ubuntu/rsi/rsi_91x_hal.c
index 45f83e9..9181b54 100644
--- a/ubuntu/rsi/rsi_91x_hal.c
+++ b/ubuntu/rsi/rsi_91x_hal.c
@@ -160,11 +160,27 @@  int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
 
 	if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
 		ven_rsi_dbg(INFO_ZONE, "*** Tx EAPOL ***\n");
+		
+		frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
+		if (common->band == NL80211_BAND_5GHZ)
+				frame_desc[4] = cpu_to_le16(RSI_RATE_6);
+			else
+				frame_desc[4] = cpu_to_le16(RSI_RATE_1);
 		frame_desc[6] |= cpu_to_le16(BIT(13));
 		frame_desc[1] |= cpu_to_le16(BIT(12));
+		if (vif->type == NL80211_IFTYPE_STATION) {
+			frame_desc[0] = cpu_to_le16((skb->len - FRAME_DESC_SZ) |
+					(RSI_WIFI_MGMT_Q << 12));
+			if ((skb->len - header_size) == 133) {
+				ven_rsi_dbg(INFO_ZONE, "*** Tx EAPOL 4*****\n");
+				frame_desc[1] |=
+					cpu_to_le16(RSI_DESC_REQUIRE_CFM_TO_HOST);
+				xtend_desc->confirm_frame_type = EAPOL4_CONFIRM;
+			}
+		}
 #define EAPOL_RETRY_CNT 15
 		xtend_desc->retry_cnt = EAPOL_RETRY_CNT;
-#ifdef EAPOL_IN_MGMT_Q
+#if 0 
 		skb->priority = VO_Q;
 #endif
 	}
@@ -178,14 +194,12 @@  int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
 	    (is_multicast_ether_addr(wh->addr1))) {
 		frame_desc[3] = cpu_to_le16(RATE_INFO_ENABLE);
 		frame_desc[3] |= cpu_to_le16(RSI_BROADCAST_PKT);
-#if 0
-		if (common->min_rate == 0xffff) {
+		if (vif->type == NL80211_IFTYPE_AP) {
 			if (common->band == NL80211_BAND_5GHZ)
 				frame_desc[4] = cpu_to_le16(RSI_RATE_6);
 			else
 				frame_desc[4] = cpu_to_le16(RSI_RATE_1);
 		}
-#endif
 	}
 
 	if ((vif->type == NL80211_IFTYPE_AP) &&
@@ -196,7 +210,7 @@  int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb)
 
 err:
 	++common->tx_stats.total_tx_pkt_freed[skb->priority];
-	rsi_indicate_tx_status(common->priv, skb, status);
+	rsi_indicate_tx_status(adapter, skb, status);
 	return status;
 }
 
@@ -323,6 +337,8 @@  int rsi_send_data_pkt(struct rsi_common *common, struct sk_buff *skb)
 	u8 header_size = 0;
 
 	info = IEEE80211_SKB_CB(skb);
+	if (!info->control.vif)
+		goto err;
 	bss = &info->control.vif->bss_conf;
 	tx_params = (struct skb_info *)info->driver_data;
 
@@ -381,7 +397,6 @@  int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb)
 			     skb->data, skb->len);
 
 		status = rsi_send_pkt(common, skb);
-
 		if (status) {
 			ven_rsi_dbg(ERR_ZONE,
 				"%s: Failed to write the packet\n",
@@ -391,6 +406,8 @@  int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb)
 		return status;
 	}
 
+	if (!info->control.vif)
+		goto out;
 	bss = &info->control.vif->bss_conf;
 	wh = (struct ieee80211_hdr *)&skb->data[header_size];
 
@@ -398,23 +415,24 @@  int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb)
 	xtend_desc = (struct xtended_desc *)&skb->data[FRAME_DESC_SZ];
 
 	/* Indicate to firmware to give cfm */
-	if (ieee80211_is_probe_req(wh->frame_control)) { // && (!bss->assoc)) {
+	if (ieee80211_is_probe_req(wh->frame_control)) {
 		if (!bss->assoc) {
-			ven_rsi_dbg(INFO_ZONE, "%s: blocking mgmt queue\n", __func__);
+			ven_rsi_dbg(INFO_ZONE,
+				"%s: blocking mgmt queue\n", __func__);
 			desc[1] |= cpu_to_le16(RSI_DESC_REQUIRE_CFM_TO_HOST);
 			xtend_desc->confirm_frame_type = PROBEREQ_CONFIRM;
 			common->mgmt_q_block = true;
 			ven_rsi_dbg(INFO_ZONE, "Mgmt queue blocked\n");
 		} else if (common->bgscan_en) {
-			/* Drop off channel probe request */
 			if (common->mac80211_cur_channel !=
 			    rsi_get_connected_channel(adapter)) { 
-				dev_kfree_skb(skb);
-				return 0;
+				/* Drop off channel probe request */
+				status = 0;
+				goto out;
 			} else if (wh->addr1[0] == 0xff) {
 				/* Drop broadcast probe in connected channel*/
-				dev_kfree_skb(skb);
-				return 0;
+				status = 0;
+				goto out;
 			}
 		}
 		ven_rsi_dbg(MGMT_TX_ZONE, "Sending PROBE REQUEST =====>\n");
@@ -433,6 +451,7 @@  int rsi_send_mgmt_pkt(struct rsi_common *common, struct sk_buff *skb)
 			__func__);
 	}
 
+out:
 	rsi_indicate_tx_status(common->priv, skb, status);
 	return status;
 }
@@ -472,7 +491,6 @@  err:
 
 int rsi_send_beacon(struct rsi_common *common)
 {
-	struct rsi_hw *adapter = common->priv;
 	struct rsi_mac_frame *bcn_frm = NULL;
 	u16 bcn_len = common->beacon_frame_len;
 	struct sk_buff *skb = NULL;
@@ -481,16 +499,18 @@  int rsi_send_beacon(struct rsi_common *common)
 	u8 vap_id = 0;
 	u8 dword_align_bytes = 0;
 	u8 header_size = 0;
+	int status = 0;
 
-	skb = dev_alloc_skb(FRAME_DESC_SZ + bcn_len + 64);
+	skb = dev_alloc_skb(MAX_MGMT_PKT_SIZE);
 	if (!skb)
 		return -ENOMEM;
 
 	dword_align_bytes = ((unsigned long)skb->data & 0x3f);
-	printk("%s: dword_bytes = %d\n", __func__, dword_align_bytes);
-	header_size = dword_align_bytes + FRAME_DESC_SZ;
-	printk("header_size = %d\n", header_size);
-	memset(skb->data, 0, header_size + bcn_len + 64);
+	if (dword_align_bytes) {
+		skb_pull(skb, (64 - dword_align_bytes));
+	}
+	header_size = FRAME_DESC_SZ;
+	memset(skb->data, 0, MAX_MGMT_PKT_SIZE);
 
 	common->beacon_cnt++;
 	bcn_frm = (struct rsi_mac_frame *)skb->data;
@@ -504,7 +524,7 @@  int rsi_send_beacon(struct rsi_common *common)
 	bcn_frm->desc_word[3] |= cpu_to_le16(RATE_INFO_ENABLE);
 	bcn_frm->desc_word[4] = cpu_to_le16(vap_id << 14);
 	bcn_frm->desc_word[7] = cpu_to_le16(BEACON_HW_Q);
-
+	
 	if (conf_is_ht40_plus(conf)) {
 		bcn_frm->desc_word[5] = cpu_to_le16(LOWER_20_ENABLE);
 		bcn_frm->desc_word[5] |= cpu_to_le16(LOWER_20_ENABLE >> 12);
@@ -514,29 +534,31 @@  int rsi_send_beacon(struct rsi_common *common)
 	}
 
 	if (common->band == NL80211_BAND_2GHZ)
-		bcn_frm->desc_word[4] |= cpu_to_le16(0xB | RSI_11G_MODE);
+		bcn_frm->desc_word[4] |= cpu_to_le16(RSI_RATE_1);
 	else
-		bcn_frm->desc_word[4] |= cpu_to_le16(RSI_11B_MODE);
+		bcn_frm->desc_word[4] |= cpu_to_le16(RSI_RATE_6);
 
 	//if (!(common->beacon_cnt % common->dtim_cnt))
 	if (1) //FIXME check this
 		bcn_frm->desc_word[3] |= cpu_to_le16(DTIM_BEACON);
 
+	//mutex_lock(&common->mutex);
 	memcpy(&skb->data[header_size], common->beacon_frame, bcn_len);
+	//mutex_unlock(&common->mutex);
 
 	skb_put(skb, bcn_len + header_size);
 
-	rsi_hex_dump(MGMT_TX_ZONE, "Beacon Frame", skb->data, skb->len);
+	rsi_hex_dump(MGMT_TX_ZONE, "Beacon Frame", skb->data, skb->len);	
 
-	if (adapter->host_intf_ops->write_pkt(adapter, skb->data, skb->len) < 0) {
+	mutex_lock(&common->tx_lock);
+	if (rsi_send_pkt(common, skb)) {
 		ven_rsi_dbg(ERR_ZONE, "Failed to send Beacon\n");
-		goto err;
+		status = -EINVAL;
 	}
-	return 0;
+	mutex_unlock(&common->tx_lock);
 
-err:
 	dev_kfree_skb(skb);
-	return -1;
+	return status;
 }
 
 /**
diff --git a/ubuntu/rsi/rsi_91x_hci.c b/ubuntu/rsi/rsi_91x_hci.c
index 773e216..4442651 100644
--- a/ubuntu/rsi/rsi_91x_hci.c
+++ b/ubuntu/rsi/rsi_91x_hci.c
@@ -198,21 +198,6 @@  fail:
 	return status;
 }
 
-void rsi_hci_scheduler_thread(struct rsi_common *common)
-{
-	struct rsi_hw *adapter = common->priv;
-	int status = 0;
-
-	do {
-		status = adapter->check_intr_status_reg(adapter);
-		if (adapter->isr_pending)
-			adapter->isr_pending = 0;
-		msleep(20);
-
-	} while (atomic_read(&common->hci_thread.thread_done) == 0);
-	complete_and_exit(&common->hci_thread.completion, 0);
-}
-
 int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 {
 	struct rsi_hci_adapter *h_adapter =
@@ -234,34 +219,9 @@  int rsi_hci_recv_pkt(struct rsi_common *common, u8 *pkt)
 			return 0;
 		}
 
-		/* TODO: Work aroud for Dell; move this to module_param */
-#if (defined(CONFIG_DELL_BOARD) &&  defined(CONFIG_VEN_RSI_HCI))
-		if (rsi_set_antenna(common, ANTENNA_SEL_UFL)) {
-			ven_rsi_dbg(ERR_ZONE,
-				"%s: Failed to configure external antenna\n",
-				__func__);
-		} else
-			ven_rsi_dbg(INFO_ZONE, "***** UFL antenna is configured\n");
-
-#endif
-
-#if (defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX))
-#if defined(CONFIG_DELL_BOARD)
-	if (common->priv->rsi_host_intf == RSI_HOST_INTF_SDIO) {
-		rsi_init_event(&common->hci_thread.event);
-		if (rsi_create_kthread(common,
-					&common->hci_thread,
-					rsi_hci_scheduler_thread,
-					"hci-Thread")) {
-			ven_rsi_dbg(ERR_ZONE, "%s: Unable to init hci thrd\n",
-				__func__);
-		}
-	}
-#endif
-#endif
 		return 0;
 	}
-
+ 
 	if (common->bt_fsm_state != BT_DEVICE_READY) {
 		ven_rsi_dbg(INFO_ZONE, "BT Device not ready\n");
 		return 0;
@@ -504,6 +464,7 @@  err:
 #if LINUX_VERSION_CODE <= KERNEL_VERSION(3, 12, 34)
 		genl_unregister_ops(gcb->gc_family, gcb->gc_ops);
 #endif
+		kfree(gcb);
 	}
 	h_adapter->gcb = NULL;
 	kfree(h_adapter);
@@ -547,6 +508,7 @@  void rsi_hci_detach(struct rsi_common *common)
 		genl_unregister_ops(gcb->gc_family, gcb->gc_ops);
 #endif
 		h_adapter->gcb = NULL;
+		kfree(gcb);
 	}
 	kfree(h_adapter);
 
diff --git a/ubuntu/rsi/rsi_91x_mac80211.c b/ubuntu/rsi/rsi_91x_mac80211.c
index 1d18b10..181a4b5 100644
--- a/ubuntu/rsi/rsi_91x_mac80211.c
+++ b/ubuntu/rsi/rsi_91x_mac80211.c
@@ -419,10 +419,10 @@  static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
 
 	mutex_lock(&common->mutex);
 
-	/* Not supporting concurrent mode now */
+	/* Not supporting concurrent mode now */	
 	if (adapter->sc_nvifs > 0)
 		return -1;
-
+	
 	adapter->vifs[adapter->sc_nvifs++] = vif;
 
 	switch (vif->type) {
@@ -442,9 +442,15 @@  static int rsi_mac80211_add_interface(struct ieee80211_hw *hw,
 	}
 
 	if (vif->type == NL80211_IFTYPE_AP) {
+		int i;
+
 		common->bc_mc_seqno = 1;
 		rsi_send_rx_filter_frame(common, DISALLOW_BEACONS);
-		rsi_set_min_rate(hw, NULL, common);
+		common->min_rate = 0xffff;
+		//common->bitrate_mask[NL80211_BAND_2GHZ] = 0xfff;
+		//common->bitrate_mask[NL80211_BAND_5GHZ] = 0xfff;
+		for (i = 0; i < RSI_MAX_ASSOC_STAS; i++)
+			common->stations[i].sta = NULL;
 	}
 
 	mutex_unlock(&common->mutex);
@@ -762,7 +768,7 @@  static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
 					  ALLOW_CTRL_ASSOC_PEER |
 					  ALLOW_MGMT_ASSOC_PEER |
 #ifdef RSI_HW_CONN_MONITOR
-					  DISALLOW_BEACONS |
+					  //DISALLOW_BEACONS |
 #endif
 					0);
 			rsi_send_rx_filter_frame(common, rx_filter_word);
@@ -778,7 +784,7 @@  static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
 		/* Send peer notify to device */
 		ven_rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
 		rsi_inform_bss_status(common, STA_OPMODE, bss->assoc,
-				      bss->bssid, bss->qos, bss->aid, 0);
+				      bss->bssid, bss->qos, bss->aid, NULL, 0);
 
 		adapter->ps_info.listen_interval =
 			bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
@@ -810,6 +816,7 @@  static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
 	if (changed & BSS_CHANGED_BEACON_INT) {
 		ven_rsi_dbg(INFO_ZONE, "%s: Changed Beacon interval: %d\n",
 			__func__, bss_conf->beacon_int);
+		common->beacon_interval = bss->beacon_int; 
 		adapter->ps_info.listen_interval =
 			bss->beacon_int * adapter->ps_info.num_bcns_per_lis_int;
 	}
@@ -822,10 +829,19 @@  static void rsi_mac80211_bss_info_changed(struct ieee80211_hw *hw,
 
 	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
 	    (vif->type == NL80211_IFTYPE_AP)) {
-		if (bss->enable_beacon)
+		if (bss->enable_beacon) {
 			ven_rsi_dbg(INFO_ZONE, "===> BEACON ENABLED <===\n");
-		else
+			common->beacon_enabled = 1;
+#ifdef CONFIG_CARACALLA_BOARD
+			rsi_init_bcn_timer(common);
+#endif
+		} else {
 			ven_rsi_dbg(INFO_ZONE, "===> BEACON DISABLED <===\n");
+			common->beacon_enabled = 0;
+#ifdef CONFIG_CARACALLA_BOARD
+			rsi_del_bcn_timer(common);
+#endif
+		}
 	}
 
 	mutex_unlock(&common->mutex);
@@ -1073,6 +1089,7 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 	struct rsi_common *common = adapter->priv;
 	u16 seq_no = 0;
 	u8 ii = 0;
+	u8 sta_id = 0;
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
 	u16 tid = params->tid;
@@ -1094,6 +1111,15 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 #else
 	seq_no = params->ssn;
 #endif
+	if (vif->type == NL80211_IFTYPE_AP) {
+		struct rsi_sta *rsta = rsi_find_sta(common, sta->addr);
+
+		if (!rsta) {
+			ven_rsi_dbg(ERR_ZONE, "No station mapped\n");
+			return 0;
+		}
+		sta_id = rsta->sta_id;
+	}
 
 	ven_rsi_dbg(INFO_ZONE,
 		"%s: AMPDU action tid=%d ssn=0x%x, buf_size=%d\n",
@@ -1106,7 +1132,8 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 						    tid,
 						    seq_no,
 						    buf_size,
-						    STA_RX_ADDBA_DONE);
+						    STA_RX_ADDBA_DONE,
+						    sta_id);
 		break;
 
 	case IEEE80211_AMPDU_RX_STOP:
@@ -1116,7 +1143,8 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 						    tid,
 						    0,
 						    buf_size,
-						    STA_RX_DELBA);
+						    STA_RX_DELBA,
+						    sta_id);
 		break;
 
 	case IEEE80211_AMPDU_TX_START:
@@ -1137,7 +1165,8 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 						    tid,
 						    seq_no,
 						    buf_size,
-						    STA_TX_DELBA);
+						    STA_TX_DELBA,
+						    sta_id);
 		if (!status)
 			ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
 		break;
@@ -1150,7 +1179,8 @@  static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
 						tid,
 						common->vif_info[ii].seq_start,
 						buf_size,
-						STA_TX_ADDBA_DONE);
+						STA_TX_ADDBA_DONE,
+						sta_id);
 		break;
 
 	default:
@@ -1332,6 +1362,8 @@  void rsi_indicate_pkt_to_os(struct rsi_common *common,
 	/* filling in the ieee80211_rx_status flags */
 	rsi_fill_rx_status(hw, skb, common, rx_status);
 
+	ven_rsi_dbg(INFO_ZONE, "RX Packet Type: %s\n",
+		dot11_pkt_type(skb->data[0]));
 	rsi_hex_dump(DATA_RX_ZONE, "802.11 RX packet", skb->data, skb->len);
 	ieee80211_rx_irqsafe(hw, skb);
 }
@@ -1359,10 +1391,22 @@  static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 
 	if (vif->type == NL80211_IFTYPE_AP) {
 		u8 i, j;
+		int free_index = -1;
+
+		/* Check if max stations reached */
+		if (common->num_stations >= RSI_MAX_ASSOC_STAS) {
+			ven_rsi_dbg(ERR_ZONE, "Reject: Max Stations exists\n");
+			return -EINVAL;
+		}
 
 		/* Send peer notify to device */
 		ven_rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
-		for (i = 0; i < common->num_stations; i++) {
+		for (i = 0; i < RSI_MAX_ASSOC_STAS; i++) {
+			if (!common->stations[i].sta) {
+				if (free_index < 0)
+					free_index = i;
+				continue; 
+			}
 			if (!memcmp(common->stations[i].sta->addr,
 				    sta->addr, ETH_ALEN)) {
 				ven_rsi_dbg(INFO_ZONE, "Station exists\n");
@@ -1372,15 +1416,18 @@  static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 		}
 		if (!sta_exist) {
 			ven_rsi_dbg(INFO_ZONE, "New Station\n");
-			rsi_inform_bss_status(common, AP_OPMODE, 1, sta->addr,
-					      sta->wme, sta->aid, i);
+			if (free_index >= 0)
+				i = free_index;
 			common->stations[i].sta = sta;
 			common->stations[i].sta_id = i;
+			rsi_inform_bss_status(common, AP_OPMODE, 1, sta->addr,
+					      sta->wme, sta->aid, sta, i);
 			for (j = 0; j < IEEE80211_NUM_ACS; j++)
 				common->stations[i].seq_no[j] = 1;
 			common->num_stations++;
 		} else {
 			common->stations[i].sta = sta;
+			common->stations[i].sta_id = i;
 			for (j = 0; j < IEEE80211_NUM_ACS; j++)
 				common->stations[i].seq_no[j] = 1;
 		}
@@ -1403,8 +1450,11 @@  static int rsi_mac80211_sta_add(struct ieee80211_hw *hw,
 		}
 	}
 
+#if 0
 	if ((vif->type == NL80211_IFTYPE_STATION) &&
 	    sta->ht_cap.ht_supported)
+#endif
+	if (sta->ht_cap.ht_supported)
 		ieee80211_start_tx_ba_session(sta, 0, 0);
 
 	mutex_unlock(&common->mutex);
@@ -1431,22 +1481,27 @@  static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
 
 	rsi_hex_dump(INFO_ZONE, "Station Removed: ", sta->addr, ETH_ALEN);
 
+	mutex_lock(&common->mutex);
 	if (vif->type == NL80211_IFTYPE_AP) {
 		u8 i, j;
 
 		/* Send peer notify to device */
 		ven_rsi_dbg(INFO_ZONE, "Indicate bss status to device\n");
-		for (i = 0; i < common->num_stations; i++) {
+		for (i = 0; i < RSI_MAX_ASSOC_STAS; i++) {
+			if (!common->stations[i].sta)
+				continue;
 			if (!memcmp(common->stations[i].sta->addr,
 				    sta->addr, ETH_ALEN)) {
 				rsi_inform_bss_status(common, AP_OPMODE, 0,
 						      sta->addr, sta->wme,
-						      sta->aid, i);
+						      sta->aid, sta, i);
 				common->stations[i].sta = NULL;
 				common->stations[i].sta_id = -1;
 				for (j = 0; j < IEEE80211_NUM_ACS; j++)
 					common->stations[i].seq_no[j] = 0;
 				common->num_stations--;
+				if (common->num_stations < 0)
+					common->num_stations = 0;
 				break;
 			}
 		}
@@ -1456,7 +1511,6 @@  static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
 
 	if (vif->type == NL80211_IFTYPE_STATION) {
 		/* Resetting all the fields to default values */
-		mutex_lock(&common->mutex);
 		memcpy((u8 *)bss->bssid, (u8 *)sta->addr, ETH_ALEN);
 		bss->qos = sta->wme;
 		common->bitrate_mask[NL80211_BAND_2GHZ] = 0;
@@ -1469,11 +1523,11 @@  static int rsi_mac80211_sta_remove(struct ieee80211_hw *hw,
 		common->secinfo.gtk_cipher = 0;
 		if (common->bgscan_en)
 			common->bgscan_en = 0;
-		mutex_unlock(&common->mutex);
 
 		if (!common->iface_down)
 			rsi_send_rx_filter_frame(common, 0);
 	}
+	mutex_unlock(&common->mutex);
 	return 0;
 }
 #if 0
@@ -1626,6 +1680,8 @@  static void rsi_reg_notify(struct wiphy *wiphy,
 	struct ieee80211_channel *ch;
 	int i;
 
+	if (common->num_supp_bands == 1)
+		return;
 	mutex_lock(&common->mutex);
 
 	sband = wiphy->bands[NL80211_BAND_5GHZ];
@@ -1655,7 +1711,7 @@  static void rsi_reg_notify(struct wiphy *wiphy,
 			common->bgscan_en = 1;
 		}
 	}
-
+	
 	adapter->dfs_region = request->dfs_region;
 	adapter->country[0] = request->alpha2[0];
 	adapter->country[1] = request->alpha2[1];
@@ -1679,13 +1735,13 @@  void rsi_mac80211_rfkill_poll(struct ieee80211_hw *hw)
 
 #ifdef CONFIG_RSI_WOW
 static const struct wiphy_wowlan_support rsi_wowlan_support = {
-	.flags =WIPHY_WOWLAN_ANY |
-		WIPHY_WOWLAN_MAGIC_PKT |
-		WIPHY_WOWLAN_DISCONNECT |
-		WIPHY_WOWLAN_GTK_REKEY_FAILURE  |
-		WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
-		WIPHY_WOWLAN_EAP_IDENTITY_REQ   |
-		WIPHY_WOWLAN_4WAY_HANDSHAKE,
+	.flags = WIPHY_WOWLAN_ANY |
+		 WIPHY_WOWLAN_MAGIC_PKT |
+		 WIPHY_WOWLAN_DISCONNECT |
+		 WIPHY_WOWLAN_GTK_REKEY_FAILURE  |
+		 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
+		 WIPHY_WOWLAN_EAP_IDENTITY_REQ   |
+		 WIPHY_WOWLAN_4WAY_HANDSHAKE,
 	.n_patterns = 0,
 	.pattern_min_len = 1,
 	.pattern_max_len = 0,
@@ -1707,7 +1763,7 @@  static u16 rsi_wow_map_triggers(struct rsi_common *common,
 	if (wowlan->gtk_rekey_failure || wowlan->eap_identity_req ||
 	    wowlan->four_way_handshake)
 		wow_triggers |= RSI_WOW_SUPPORTS_GTK_REKEY;
-
+	
 	return wow_triggers;
 }
 #endif
@@ -1719,7 +1775,7 @@  int rsi_mac80211_suspend(struct ieee80211_hw *hw,
 #ifdef CONFIG_RSI_WOW
 	struct rsi_hw *adapter = hw->priv;
 	struct rsi_common *common = adapter->priv;
-	u16 triggers;
+	u16 triggers, rx_filter_word = 0;
 #endif
 	int ret = 0;
 
@@ -1736,22 +1792,45 @@  int rsi_mac80211_suspend(struct ieee80211_hw *hw,
 	triggers = rsi_wow_map_triggers(common, wowlan);
 	if (!triggers) {
 		ven_rsi_dbg(ERR_ZONE, "%s:No valid WoW triggers\n",__func__);
-		ret = 1;
+		ret = -EINVAL;
 		goto fail_wow;
 	}
 	ven_rsi_dbg(INFO_ZONE, "TRIGGERS %x\n", triggers);
 
-	 rsi_send_wowlan_request(common, triggers, wowlan);
+	rsi_send_wowlan_request(common, triggers, 1);
 
+ 	 rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
+			   ALLOW_CTRL_ASSOC_PEER |
+			   ALLOW_MGMT_ASSOC_PEER |
+			   DISALLOW_BEACONS |
+			   0);
+	rsi_send_rx_filter_frame(common, rx_filter_word);
+        common->suspend_flag = 1;
 fail_wow:
 #endif
-	return ret;
+        return ret;
 }
 
 static int rsi_mac80211_resume(struct ieee80211_hw *hw)
 {
+#ifdef CONFIG_RSI_WOW
+	struct rsi_hw *adapter = hw->priv;
+	struct rsi_common *common = adapter->priv;
+	u16 rx_filter_word = 0;
+#endif
+	
 	ven_rsi_dbg(INFO_ZONE, "%s: mac80211 resume\n", __func__);
 
+#ifdef CONFIG_RSI_WOW
+	rsi_send_wowlan_request(common, 0, 0);
+	//rx_filter_word = 0xE ;
+
+	rx_filter_word = (ALLOW_DATA_ASSOC_PEER |
+			  ALLOW_CTRL_ASSOC_PEER |
+			  ALLOW_MGMT_ASSOC_PEER |
+			  0);
+	rsi_send_rx_filter_frame(common, rx_filter_word);
+#endif
 	return 0;
 }
 #endif
@@ -1774,8 +1853,8 @@  static struct ieee80211_ops mac80211_ops = {
 	.sta_remove = rsi_mac80211_sta_remove,
 	.set_antenna = rsi_mac80211_set_antenna,
 	.get_antenna = rsi_mac80211_get_antenna,
-	.rfkill_poll = rsi_mac80211_rfkill_poll,
-#ifdef CONFIG_PM
+        .rfkill_poll = rsi_mac80211_rfkill_poll,
+#ifdef CONFIG_PM 
 	.suspend = rsi_mac80211_suspend,
 	.resume  = rsi_mac80211_resume,
 #endif
@@ -1842,10 +1921,17 @@  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_STA_SP_ALL_PKTS;
-	hw->max_tx_aggregation_subframes = 6;
+//	hw->max_tx_aggregation_subframes = 6;
+	hw->max_tx_aggregation_subframes = 4;
 
 	rsi_register_rates_channels(adapter, NL80211_BAND_2GHZ);
-	rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
+	wiphy->bands[NL80211_BAND_2GHZ] =
+		&adapter->sbands[NL80211_BAND_2GHZ];
+	if (common->num_supp_bands == 2) {
+		rsi_register_rates_channels(adapter, NL80211_BAND_5GHZ);
+		wiphy->bands[NL80211_BAND_5GHZ] =
+			&adapter->sbands[NL80211_BAND_5GHZ];
+	}
 	hw->rate_control_algorithm = "AARF";
 	hw->sta_data_size = sizeof(struct rsi_sta);
 
@@ -1861,10 +1947,6 @@  int rsi_mac80211_attach(struct rsi_common *common)
 	wiphy->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
 	wiphy->available_antennas_tx = 1;
 	wiphy->available_antennas_rx = 1;
-	wiphy->bands[NL80211_BAND_2GHZ] =
-		&adapter->sbands[NL80211_BAND_2GHZ];
-	wiphy->bands[NL80211_BAND_5GHZ] =
-		&adapter->sbands[NL80211_BAND_5GHZ];
 	wiphy->max_ap_assoc_sta = RSI_MAX_ASSOC_STAS;
 
 	wiphy->flags = WIPHY_FLAG_REPORTS_OBSS;
diff --git a/ubuntu/rsi/rsi_91x_main.c b/ubuntu/rsi/rsi_91x_main.c
index 006dbd9..f6f85d8 100644
--- a/ubuntu/rsi/rsi_91x_main.c
+++ b/ubuntu/rsi/rsi_91x_main.c
@@ -226,6 +226,54 @@  fail:
 }
 EXPORT_SYMBOL_GPL(ven_rsi_read_pkt);
 
+#ifdef CONFIG_CARACALLA_BOARD
+static void rsi_bcn_sched(unsigned long data)
+{
+	struct rsi_common *common = (struct rsi_common *)data;
+
+	rsi_set_event(&common->bcn_thread.event);
+
+	common->bcn_timer.expires =
+		msecs_to_jiffies(common->beacon_interval - 5) + jiffies;
+	add_timer(&common->bcn_timer);
+}
+
+void rsi_init_bcn_timer(struct rsi_common *common)
+{
+	init_timer(&common->bcn_timer);
+
+	common->bcn_timer.data = (unsigned long)common;
+	common->bcn_timer.expires =
+		msecs_to_jiffies(common->beacon_interval - 5) + jiffies;
+	common->bcn_timer.function = (void *)rsi_bcn_sched;
+
+	add_timer(&common->bcn_timer);
+}
+
+void rsi_del_bcn_timer(struct rsi_common *common)
+{
+	del_timer(&common->bcn_timer);
+}
+
+void rsi_bcn_scheduler_thread(struct rsi_common *common)
+{
+	do {
+		rsi_wait_event(&common->bcn_thread.event,
+			       msecs_to_jiffies(common->beacon_interval));
+		rsi_reset_event(&common->bcn_thread.event);
+
+		if (!common->beacon_enabled)
+			continue;
+		if (!common->init_done)
+			continue;
+		if (common->iface_down)
+			continue;
+		rsi_send_beacon(common);
+	} while (atomic_read(&common->bcn_thread.thread_done) == 0);
+	complete_and_exit(&common->bcn_thread.completion, 0);
+}
+#endif
+
 /**
  * rsi_tx_scheduler_thread() - This function is a kernel thread to send the
  *			       packets to the device.
@@ -250,6 +298,36 @@  static void rsi_tx_scheduler_thread(struct rsi_common *common)
 	complete_and_exit(&common->tx_thread.completion, 0);
 }
 
+#ifdef CONFIG_SDIO_INTR_POLL
+void rsi_sdio_intr_poll_scheduler_thread(struct rsi_common *common)
+{
+        struct rsi_hw *adapter = common->priv;
+        int status = 0;
+
+        do {
+                status = adapter->check_intr_status_reg(adapter);
+                if (adapter->isr_pending)
+                        adapter->isr_pending = 0;
+                msleep(20);
+
+        } while (atomic_read(&common->sdio_intr_poll_thread.thread_done) == 0);
+        complete_and_exit(&common->sdio_intr_poll_thread.completion, 0);
+}
+
+void init_sdio_intr_status_poll_thread(struct rsi_common *common)
+{
+	rsi_init_event(&common->sdio_intr_poll_thread.event);
+	if (rsi_create_kthread(common,
+			       &common->sdio_intr_poll_thread,
+			       rsi_sdio_intr_poll_scheduler_thread,
+			       "Sdio Intr poll-Thread")) {
+		rsi_dbg(ERR_ZONE, "%s: Unable to init sdio intr poll thrd\n",
+				__func__);
+	}
+}
+EXPORT_SYMBOL_GPL(init_sdio_intr_status_poll_thread);
+#endif
+
 /**
  * ven_rsi_91x_init() - This function initializes os interface operations.
  * @void: Void.
@@ -285,6 +363,7 @@  struct rsi_hw *ven_rsi_91x_init(void)
 		skb_queue_head_init(&common->tx_queue[ii]);
 
 	rsi_init_event(&common->tx_thread.event);
+	rsi_init_event(&common->bcn_thread.event);
 	mutex_init(&common->mutex);
 	mutex_init(&common->tx_lock);
 	mutex_init(&common->rx_lock);
@@ -297,6 +376,16 @@  struct rsi_hw *ven_rsi_91x_init(void)
 		goto err;
 	}
 
+#ifdef CONFIG_CARACALLA_BOARD
+	if (rsi_create_kthread(common,
+			       &common->bcn_thread,
+			       rsi_bcn_scheduler_thread,
+			       "Beacon-Thread")) {
+		ven_rsi_dbg(ERR_ZONE, "%s: Unable to init bcn thrd\n", __func__);
+		goto err;
+	}
+#endif
+
 #ifdef CONFIG_VEN_RSI_COEX
 	if (rsi_coex_init(common)) {
 		ven_rsi_dbg(ERR_ZONE, "Failed to init COEX module\n");
@@ -332,6 +421,9 @@  void ven_rsi_91x_deinit(struct rsi_hw *adapter)
 	ven_rsi_dbg(INFO_ZONE, "%s: Deinit core module...\n", __func__);
 
 	rsi_kill_thread(&common->tx_thread);
+#ifdef CONFIG_CARACALLA_BOARD
+	rsi_kill_thread(&common->bcn_thread);
+#endif
 
 	for (ii = 0; ii < NUM_SOFT_QUEUES; ii++)
 		skb_queue_purge(&common->tx_queue[ii]);
@@ -341,6 +433,8 @@  void ven_rsi_91x_deinit(struct rsi_hw *adapter)
 #endif
 	common->init_done = false;
 
+	kfree(common->beacon_frame);
+	common->beacon_frame = NULL;
 	kfree(common);
 	kfree(adapter->rsi_dev);
 	kfree(adapter);
diff --git a/ubuntu/rsi/rsi_91x_mgmt.c b/ubuntu/rsi/rsi_91x_mgmt.c
index 3329204..d4c2000 100644
--- a/ubuntu/rsi/rsi_91x_mgmt.c
+++ b/ubuntu/rsi/rsi_91x_mgmt.c
@@ -341,6 +341,7 @@  static void rsi_set_default_parameters(struct rsi_common *common)
 	common->antenna_diversity = 0;
 	common->tx_power = RSI_TXPOWER_MAX;
 	common->dtim_cnt = 2;
+	common->beacon_interval = 100;
 }
 
 void init_bgscan_params(struct rsi_common *common)
@@ -606,13 +607,13 @@  static int rsi_mgmt_pkt_to_core(struct rsi_common *common,
  *
  * Return: status: 0 on success, corresponding negative error code on failure.
  */
-static int rsi_send_sta_notify_frame(struct rsi_common *common,
-				     enum opmode opmode,
-				     u8 notify_event,
-				     const unsigned char *bssid,
-				     u8 qos_enable,
-				     u16 aid,
-				     u16 sta_id)
+int rsi_send_sta_notify_frame(struct rsi_common *common,
+			      enum opmode opmode,
+			      u8 notify_event,
+			      const unsigned char *bssid,
+			      u8 qos_enable,
+			      u16 aid,
+			      u16 sta_id)
 {
 	struct ieee80211_vif *vif = common->priv->vifs[0];
 	struct sk_buff *skb = NULL;
@@ -685,7 +686,8 @@  int rsi_send_aggr_params_frame(struct rsi_common *common,
 			       u16 tid,
 			       u16 ssn,
 			       u8 buf_size,
-			       u8 event)
+			       u8 event,
+			       u8 sta_id)
 {
 	struct sk_buff *skb = NULL;
 	struct rsi_mac_frame *mgmt_frame;
@@ -868,7 +870,7 @@  int rsi_set_vap_capabilities(struct rsi_common *common,
 #endif
 
 	vap_caps->default_data_rate = 0;
-	vap_caps->beacon_interval = cpu_to_le16(200);
+	vap_caps->beacon_interval = cpu_to_le16(common->beacon_interval);
 	vap_caps->dtim_period = cpu_to_le16(common->dtim_cnt);
 //	vap_caps->beacon_miss_threshold = cpu_to_le16(10);
 	if (mode == AP_OPMODE)
@@ -972,22 +974,18 @@  int rsi_load_key(struct rsi_common *common,
 	set_key->desc_word[4] = cpu_to_le16(key_descriptor);
 	set_key->desc_word[7] = cpu_to_le16(sta_id | (vap_id << 8));
 
-#if 0
-	if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
-	    (cipher == WLAN_CIPHER_SUITE_WEP104)) {
-		memcpy(&set_key->key[key_id][1], data, key_len * 2);
-	} else {
-		memcpy(&set_key->key[0][0], data, key_len);
-	}
-#endif
 	if (data) {
-		memcpy(&set_key->key[0][0], data, key_len);
-		//memcpy(&set_key->key, data, 4 * 32);
+		if ((cipher == WLAN_CIPHER_SUITE_WEP40) ||
+		    (cipher == WLAN_CIPHER_SUITE_WEP104)) {
+			memcpy(&set_key->key[key_id][1], data, key_len * 2);
+		} else {
+			memcpy(&set_key->key[0][0], data, key_len);
+		}
 		memcpy(set_key->tx_mic_key, &data[16], 8);
 		memcpy(set_key->rx_mic_key, &data[24], 8);
 	} else {
 		memset(&set_key[FRAME_DESC_SZ], 0,
-		       sizeof(struct rsi_set_key) - FRAME_DESC_SZ);
+		       sizeof(struct rsi_set_key) - FRAME_DESC_SZ);				
 	}
 
 	skb_put(skb, sizeof(struct rsi_set_key));
@@ -1401,8 +1399,13 @@  int rsi_send_vap_dynamic_update(struct rsi_common *common)
 	dynamic_frame->desc_word[5] = cpu_to_le16(common->frag_threshold);
 	dynamic_frame->desc_word[5] = cpu_to_le16(2352);
 #endif
-//	dynamic_frame->desc_word[6] = cpu_to_le16(10); /* bmiss_threshold */
+
+#ifdef CONFIG_RSI_WOW
+	dynamic_frame->desc_word[6] = cpu_to_le16(24); /* bmiss_threshold */
+	dynamic_frame->frame_body.keep_alive_period = cpu_to_le16(10);
+#else
 	dynamic_frame->frame_body.keep_alive_period = cpu_to_le16(90);
+#endif
 
 #if 0
 	dynamic_frame->frame_body.mgmt_rate = cpu_to_le32(RSI_RATE_6);
@@ -1526,8 +1529,10 @@  static bool rsi_map_rates(u16 rate, int *offset)
  * Return: 0 on success, corresponding error code on failure.
  */
 static int rsi_send_auto_rate_request(struct rsi_common *common,
+				      struct ieee80211_sta *sta,
 				      u16 sta_id)
 {
+	struct ieee80211_vif *vif = common->priv->vifs[0];
 	struct sk_buff *skb;
 	struct rsi_auto_rate *auto_rate;
 	int ii = 0, jj = 0, kk = 0;
@@ -1535,8 +1540,9 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 	u8 band = hw->conf.chandef.chan->band;
 	u8 num_supported_rates = 0;
 	u8 rate_table_offset, rate_offset = 0;
-	u32 rate_bitmap = common->bitrate_mask[band];
+	u32 rate_bitmap = 0;
 	u16 *selected_rates, min_rate;
+	bool is_ht = false, is_sgi = false;
 
 	ven_rsi_dbg(MGMT_TX_ZONE,
 		"%s: Sending auto rate request frame\n", __func__);
@@ -1548,6 +1554,8 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 		return -ENOMEM;
 	}
 
+	memset(skb->data, 0, MAX_MGMT_PKT_SIZE);
+
 	selected_rates = kzalloc(2 * RSI_TBL_SZ, GFP_KERNEL);
 	if (!selected_rates) {
 		ven_rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
@@ -1555,8 +1563,6 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 		dev_kfree_skb(skb);
 		return -ENOMEM;
 	}
-
-	memset(skb->data, 0, sizeof(struct rsi_auto_rate));
 	memset(selected_rates, 0, 2 * RSI_TBL_SZ);
 
 	auto_rate = (struct rsi_auto_rate *)skb->data;
@@ -1573,11 +1579,31 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 		auto_rate->desc_word[7] = cpu_to_le16(1);
 	auto_rate->desc_word[7] |= cpu_to_le16(sta_id << 8);
 
+	if (vif->type == NL80211_IFTYPE_STATION) {
+		rate_bitmap = common->bitrate_mask[band];
+		is_ht = common->vif_info[0].is_ht;
+		is_sgi = common->vif_info[0].sgi;
+	} else {
+		rate_bitmap = sta->supp_rates[band];
+		is_ht = sta->ht_cap.ht_supported;
+		if ((sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ||
+		    (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40))
+			is_sgi = true;
+	}
+	printk("rate_bitmap = %x\n", rate_bitmap);
+	printk("is_ht = %d\n", is_ht);
+
 	if (band == NL80211_BAND_2GHZ) {
-		min_rate = RSI_RATE_1;
+		if ((rate_bitmap == 0) && (is_ht))
+			min_rate = RSI_RATE_MCS0;
+		else
+			min_rate = RSI_RATE_1;
 		rate_table_offset = 0;
 	} else {
-		min_rate = RSI_RATE_6;
+		if ((rate_bitmap == 0) && (is_ht))
+			min_rate = RSI_RATE_MCS0;
+		else
+			min_rate = RSI_RATE_6;
 		rate_table_offset = 4;
 	}
 
@@ -1591,7 +1617,7 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 	}
 	num_supported_rates = jj;
 
-	if (common->vif_info[0].is_ht) {
+	if (is_ht) {
 		for (ii = 0; ii < ARRAY_SIZE(mcs); ii++)
 			selected_rates[jj++] = mcs[ii];
 		num_supported_rates += ARRAY_SIZE(mcs);
@@ -1612,13 +1638,16 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 	}
 
 	/* loading HT rates in the bottom half of the auto rate table */
-	if (common->vif_info[0].is_ht) {
+	if (is_ht) {
 		for (ii = rate_offset, kk = ARRAY_SIZE(rsi_mcsrates) - 1;
 		     ii < rate_offset + 2 * ARRAY_SIZE(rsi_mcsrates); ii++) {
-			if (common->vif_info[0].sgi ||
-			    conf_is_ht40(&common->priv->hw->conf))
+			if (is_sgi || conf_is_ht40(&common->priv->hw->conf)) {
 				auto_rate->supported_rates[ii++] =
 					cpu_to_le16(rsi_mcsrates[kk] | BIT(9));
+			} else {
+				auto_rate->supported_rates[ii++] =
+					cpu_to_le16(rsi_mcsrates[kk]);
+			}
 			auto_rate->supported_rates[ii] =
 				cpu_to_le16(rsi_mcsrates[kk--]);
 		}
@@ -1637,8 +1666,8 @@  static int rsi_send_auto_rate_request(struct rsi_common *common,
 	num_supported_rates *= 2;
 
 	auto_rate->desc_word[0] = cpu_to_le16((sizeof(*auto_rate) -
-					       FRAME_DESC_SZ) |
-					       (RSI_WIFI_MGMT_Q << 12));
+					      FRAME_DESC_SZ) |
+					      (RSI_WIFI_MGMT_Q << 12));
 
 	skb_put(skb, sizeof(struct rsi_auto_rate));
 	kfree(selected_rates);
@@ -1659,7 +1688,7 @@  static void rsi_validate_bgscan_channels(struct rsi_hw *adapter,
 {
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_channel *ch;
-	struct wiphy *wiphy = adapter->hw->wiphy;
+	struct wiphy *wiphy = adapter->hw->wiphy; 
 	u16 bgscan_channels[MAX_BGSCAN_CHANNELS] = {1, 2, 3, 4, 5, 6, 7, 8, 9,
 						    10, 11, 12, 13, 14, 36, 40,
 						    44, 48, 52, 56, 60, 64, 100,
@@ -1745,7 +1774,7 @@  int rsi_send_bgscan_params(struct rsi_common *common, int enable)
 		ven_rsi_dbg(ERR_ZONE, "##### No valid bgscan channels #####\n");
 		return -1;
 	}
-
+	
 	skb = dev_alloc_skb(frame_len);
 	if (!skb)
 		return -ENOMEM;
@@ -1849,6 +1878,7 @@  void rsi_inform_bss_status(struct rsi_common *common,
 			   u8 *bssid,
 			   u8 qos_enable,
 			   u16 aid,
+			   struct ieee80211_sta *sta,
 			   u16 sta_id)
 {
 	if (status) {
@@ -1863,15 +1893,21 @@  void rsi_inform_bss_status(struct rsi_common *common,
 					  sta_id);
 		if (common->min_rate == 0xffff) {
 			ven_rsi_dbg(INFO_ZONE, "Send auto rate request\n");
-			rsi_send_auto_rate_request(common, sta_id);
+			rsi_send_auto_rate_request(common, sta, sta_id);
 		}
 		if (opmode == STA_OPMODE) {
-			if (!rsi_send_block_unblock_frame(common, false))
-				common->hw_data_qs_blocked = false;
+			if ((!common->secinfo.security_enable) ||
+			    (rsi_is_cipher_wep(common))) {
+				if (!rsi_send_block_unblock_frame(common, false))
+					common->hw_data_qs_blocked = false;
+			}
 		}
 	} else {
 		if (opmode == STA_OPMODE)
 			common->hw_data_qs_blocked = true;
+#ifdef CONFIG_RSI_WOW
+		if (!common->suspend_flag) {
+#endif
 		rsi_send_sta_notify_frame(common,
 					  opmode,
 					  STA_DISCONNECTED,
@@ -1879,6 +1915,9 @@  void rsi_inform_bss_status(struct rsi_common *common,
 					  qos_enable,
 					  aid,
 					  sta_id);
+#ifdef CONFIG_RSI_WOW
+		}
+#endif
 		if (opmode == STA_OPMODE)
 			rsi_send_block_unblock_frame(common, true);
 	}
@@ -2004,6 +2043,7 @@  int rsi_send_rx_filter_frame(struct rsi_common *common, u16 rx_filter_word)
 
 	return rsi_send_internal_mgmt_frame(common, skb);
 }
+EXPORT_SYMBOL_GPL(rsi_send_rx_filter_frame); 
 
 /**
  * rsi_send_ps_request() - Sends power save request.
@@ -2207,10 +2247,12 @@  static int rsi_handle_ta_confirm(struct rsi_common *common, u8 *msg)
 					ven_rsi_dbg(INIT_ZONE,
 						"Dual band supported\n");
 					common->band = NL80211_BAND_5GHZ;
+					common->num_supp_bands = 2;
 				} else if ((msg[17] & 0x3) == 0x1) {
 					ven_rsi_dbg(INIT_ZONE,
 						"Only 2.4Ghz band supported\n");
 					common->band = NL80211_BAND_2GHZ;
+					common->num_supp_bands = 1;
 				}
 			} else {
 				common->fsm_state = FSM_CARD_NOT_READY;
@@ -2352,42 +2394,45 @@  int rsi_handle_card_ready(struct rsi_common *common)
 	return 0;
 }
 
-#ifdef CONFIG_RSI_WOW
+#ifdef CONFIG_RSI_WOW 
 int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
-			    struct cfg80211_wowlan *wowlan)
+		            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->wow_flags = flags; /* TODO: check for the magic packet */
-	cmd_frame->host_sleep_status = 1; /* TODO: check for the host status */
-
-	length = FRAME_DESC_SZ + IEEE80211_ADDR_LEN + 2 + 2;
-
-	cmd_frame->desc_word[0] |= cpu_to_le16(length - FRAME_DESC_SZ);
-	cmd_frame->desc_word[2] |= cpu_to_le16(0);
+        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 (sleep_status)
+		cmd_frame->wow_flags = flags; /* TODO: check for magic packet */
+        ven_rsi_dbg(INFO_ZONE, "Host_Sleep_Status : %d Flags : %d\n",
+		cmd_frame->host_sleep_status, cmd_frame->wow_flags );
+	
+        length = FRAME_DESC_SZ + IEEE80211_ADDR_LEN + 2 + 2;
 
-	skb_put(skb, length);
+        cmd_frame->desc_word[0] |= cpu_to_le16(length - FRAME_DESC_SZ);
+        cmd_frame->desc_word[2] |= cpu_to_le16(0);
+  
+  	skb_put(skb, length);
 
-	return rsi_send_internal_mgmt_frame(common, skb);
+        return rsi_send_internal_mgmt_frame(common, skb);
 }
 #endif
 
@@ -2403,6 +2448,7 @@  int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
 {
 	s32 msg_len = (le16_to_cpu(*(__le16 *)&msg[0]) & 0x0fff);
 	u16 msg_type = msg[2];
+	struct ieee80211_vif *vif = common->priv->vifs[0];
 
 	switch (msg_type) {
 	case TA_CONFIRM_TYPE:
@@ -2417,6 +2463,18 @@  int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
 			common->mgmt_q_block = false;
 			ven_rsi_dbg(INFO_ZONE, "Mgmt queue unblocked\n");
 		}
+		if ((msg[15] & 0xff) == EAPOL4_CONFIRM) {
+			u8 status = msg[12];
+
+			if (status) {	
+				if(vif->type == NL80211_IFTYPE_STATION) {
+					ven_rsi_dbg(ERR_ZONE, "EAPOL 4 confirm\n");
+					common->eapol4_confirm = 1;
+					if (!rsi_send_block_unblock_frame(common, false))
+						common->hw_data_qs_blocked = false;
+				}
+			}
+		}
 		break;
 
 	case PS_NOTIFY_IND:
@@ -2447,13 +2505,15 @@  int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg)
 
 	case BEACON_EVENT_IND:
 		ven_rsi_dbg(INFO_ZONE, "Beacon event\n");
-		if (common->fsm_state != FSM_MAC_INIT_DONE)
+#ifndef CONFIG_CARACALLA_BOARD
+		if (!common->init_done)
 			return -1;
 		if (common->iface_down)
 			return -1;
-		mutex_lock(&common->mutex);
+		if (!common->beacon_enabled)
+			return -1;
 		rsi_send_beacon(common);
-		mutex_unlock(&common->mutex);
+#endif
 		break;
 
 	case RX_DOT11_MGMT:
diff --git a/ubuntu/rsi/rsi_91x_sdio.c b/ubuntu/rsi/rsi_91x_sdio.c
index 15083e5..02276a0 100644
--- a/ubuntu/rsi/rsi_91x_sdio.c
+++ b/ubuntu/rsi/rsi_91x_sdio.c
@@ -276,7 +276,7 @@  static void rsi_reset_card(struct sdio_func *pfunction)
 	u16 rca;
 	u32 cmd_delay = 0;
 
-#ifdef CONFIG_DELL_BOARD
+#ifdef CONFIG_CARACALLA_BOARD
 	/* Reset 9110 chip */
 	err = rsi_cmd52writebyte(pfunction->card,
 				 SDIO_CCCR_ABORT,
@@ -338,7 +338,7 @@  static void rsi_reset_card(struct sdio_func *pfunction)
 	if (err)
 		ven_rsi_dbg(ERR_ZONE, "%s: CMD0 failed : %d\n", __func__, err);
 
-#ifdef CONFIG_DELL_BOARD
+#ifdef CONFIG_CARACALLA_BOARD
 	if (!host->ocr_avail) {
 #else
 	if (1) {
@@ -352,7 +352,7 @@  static void rsi_reset_card(struct sdio_func *pfunction)
 		if (err)
 			ven_rsi_dbg(ERR_ZONE, "%s: CMD5 failed : %d\n",
 				__func__, err);
-#ifdef CONFIG_DELL_BOARD
+#ifdef CONFIG_CARACALLA_BOARD
 		host->ocr_avail = resp;
 #else
 		card->ocr = resp;
@@ -363,7 +363,7 @@  static void rsi_reset_card(struct sdio_func *pfunction)
 	for (i = 0; i < 100; i++) {
 		err = rsi_issue_sdiocommand(pfunction,
 					    SD_IO_SEND_OP_COND,
-#ifdef CONFIG_DELL_BOARD
+#ifdef CONFIG_CARACALLA_BOARD
 					    host->ocr_avail,
 #else
 					    card->ocr,
@@ -997,7 +997,7 @@  static int rsi_init_sdio_interface(struct rsi_hw *adapter,
 	adapter->check_hw_queue_status = rsi_sdio_read_buffer_status_register;
 	adapter->process_isr_hci = rsi_interrupt_handler;
 	adapter->check_intr_status_reg = rsi_read_intr_status_reg;
-
+	
 #ifdef CONFIG_VEN_RSI_DEBUGFS
 	adapter->num_debugfs_entries = MAX_DEBUGFS_ENTRIES;
 #endif
@@ -1049,7 +1049,9 @@  static int rsi_probe(struct sdio_func *pfunction,
 			__func__);
 		goto fail;
 	}
-
+#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)) {
@@ -1089,6 +1091,9 @@  static int rsi_probe(struct sdio_func *pfunction,
 	return 0;
 
 fail:
+#ifdef CONFIG_SDIO_INTR_POLL
+	rsi_kill_thread(&adapter->priv->sdio_intr_poll_thread);
+#endif
 	ven_rsi_91x_deinit(adapter);
 	ven_rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__);
 	return 1;
@@ -1110,12 +1115,13 @@  static void rsi_disconnect(struct sdio_func *pfunction)
 
 	dev = (struct rsi_91x_sdiodev *)adapter->rsi_dev;
 
-#if defined(CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
-#if defined(CONFIG_DELL_BOARD)
-	if (adapter->rsi_host_intf == RSI_HOST_INTF_SDIO)
-		rsi_kill_thread(&adapter->priv->hci_thread);
-#endif
+#ifdef CONFIG_SDIO_INTR_POLL
+	rsi_kill_thread(&adapter->priv->sdio_intr_poll_thread);
 #endif
+	sdio_claim_host(pfunction);
+	sdio_release_irq(pfunction);
+	sdio_release_host(pfunction);
+	mdelay(10);
 
 	ven_rsi_mac80211_detach(adapter);
 	mdelay(10);
@@ -1124,10 +1130,6 @@  static void rsi_disconnect(struct sdio_func *pfunction)
 	rsi_hci_detach(adapter->priv);
 	mdelay(10);
 #endif
-	sdio_claim_host(pfunction);
-	sdio_release_irq(pfunction);
-	sdio_release_host(pfunction);
-	mdelay(10);
 
 	/* Reset Chip */
 	rsi_reset_chip(adapter);
@@ -1148,16 +1150,8 @@  int rsi_set_sdio_pm_caps(struct rsi_hw *adapter)
 	struct rsi_91x_sdiodev *dev =
 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
 	struct sdio_func *func = dev->pfunction;
-	mmc_pm_flag_t flags;
 	int ret;
 
-	/*Getting the host power management capabilities*/
-	flags = sdio_get_host_pm_caps(func);
-	ven_rsi_dbg(INFO_ZONE, "sdio suspend pm_caps 0x%x\n", flags);
-	if ((!(flags & MMC_PM_WAKE_SDIO_IRQ)) ||
-	    (!(flags & MMC_PM_KEEP_POWER)))
-		return -EINVAL;
-
 	/* Keep Power to the MMC while suspend*/
 	ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
 	if (ret) {
@@ -1165,53 +1159,45 @@  int rsi_set_sdio_pm_caps(struct rsi_hw *adapter)
 		return ret;
 	}
 
-	/* sdio irq wakes up host */
-	ret = sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
-	if (ret)
-		ven_rsi_dbg(ERR_ZONE,"set sdio wake irq flag failed: %d\n", ret);
-
 	return ret;
 }
 
-int rsi_sdio_suspend(struct rsi_hw *adapter)
-{
-	struct rsi_91x_sdiodev *dev =
-		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
-
-	ven_rsi_dbg(INFO_ZONE,"Suspend SDIO\n");
-
-	sdio_claim_host(dev->pfunction);
-	sdio_release_irq(dev->pfunction);
-	sdio_release_host(dev->pfunction);
-
-	return 0;
-}
-
 static int rsi_suspend(struct device *dev)
 {
 	int ret = 0;
 	struct sdio_func *pfunction = dev_to_sdio_func(dev);
 	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+	u8 isr_status = 0;
 
-	ven_rsi_dbg(INFO_ZONE,"***** SUSPEND CALLED ******\n");
-
-	ret = rsi_set_sdio_pm_caps(adapter);
-	if (ret){
-		ven_rsi_dbg(INFO_ZONE,"failed %s:%d\n",__func__,__LINE__);
-	}
-	ret = rsi_sdio_suspend(adapter);
+	ven_rsi_dbg(INFO_ZONE,"%s : ***** BUS SUSPEND  ******\n",__func__);
 
-	if (ret && ret != -ENOTCONN)
-		ven_rsi_dbg(ERR_ZONE,"wow suspend failed: %d\n", ret);
+	ven_rsi_dbg(INFO_ZONE, "Waiting for interrupts to be cleared..");
+	do {
+		rsi_sdio_read_register(adapter,
+				       RSI_FN1_INT_REGISTER,
+				       &isr_status);
+		printk(".");
+	} 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;
 }
 
 int rsi_resume(struct device *dev)
 {
-	ven_rsi_dbg(INFO_ZONE,"rsi_sdio_resume returning\n");
-	return 0;
+#ifdef CONFIG_RSI_WOW
+	struct sdio_func *pfunction = dev_to_sdio_func(dev);
+	struct rsi_hw *adapter = sdio_get_drvdata(pfunction);
+        
+	ven_rsi_dbg(INFO_ZONE,"%s: ***** BUS RESUME ******\n",__func__);
+        adapter->priv->suspend_flag = 0;
+#endif
 
+	ven_rsi_dbg(INFO_ZONE, "RSI module resumed\n");
+	return 0;
 }
 
 static const struct dev_pm_ops rsi_pm_ops = {
diff --git a/ubuntu/rsi/rsi_91x_sdio_ops.c b/ubuntu/rsi/rsi_91x_sdio_ops.c
index be62d42..7d412f0 100644
--- a/ubuntu/rsi/rsi_91x_sdio_ops.c
+++ b/ubuntu/rsi/rsi_91x_sdio_ops.c
@@ -235,7 +235,7 @@  int rsi_read_intr_status_reg(struct rsi_hw *adapter)
 						RSI_FN1_INT_REGISTER,
 						&isr_status);
 	isr_status &= 0xE;
-
+	
 	if(isr_status & BIT(MSDU_PKT_PENDING))
 		adapter->isr_pending = 1;
 	return 0;
@@ -376,9 +376,9 @@  int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
 		(struct rsi_91x_sdiodev *)adapter->rsi_dev;
 	u8 buf_status = 0;
 	int status = 0;
-#if 0
-	static int counter = 4;
+//	static int counter = 4;
 
+#if 0
 	if ((!dev->buff_status_updated) && counter) {
 		counter--;
 		goto out;
@@ -389,7 +389,6 @@  int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
 	status = rsi_sdio_read_register(common->priv,
 					RSI_DEVICE_BUFFER_STATUS_REGISTER,
 					&buf_status);
-
 	if (status) {
 		ven_rsi_dbg(ERR_ZONE,
 			"%s: Failed to read status register\n", __func__);
@@ -421,11 +420,11 @@  int rsi_sdio_read_buffer_status_register(struct rsi_hw *adapter, u8 q_num)
 	}
 //	(dev->rx_info.semi_buffer_full ? (counter = 4) : (counter = 1));
 
-out:
+//out:
 	if ((q_num == MGMT_SOFT_Q) && (dev->rx_info.mgmt_buffer_full))
 		return QUEUE_FULL;
 
-	if (dev->rx_info.buffer_full)
+	if ((q_num < MGMT_SOFT_Q) && (dev->rx_info.buffer_full))
 		return QUEUE_FULL;
 
 	return QUEUE_NOT_FULL;
diff --git a/ubuntu/rsi/rsi_coex.h b/ubuntu/rsi/rsi_coex.h
index 027bc77..24b8688 100644
--- a/ubuntu/rsi/rsi_coex.h
+++ b/ubuntu/rsi/rsi_coex.h
@@ -40,7 +40,7 @@  enum rsi_proto {
 struct rsi_coex_ctrl_block {
 	struct rsi_common *priv;
 	struct sk_buff_head coex_tx_qs[NUM_COEX_TX_QUEUES];
-	struct semaphore tx_bus_lock;
+        struct semaphore tx_bus_lock;
 	struct rsi_thread coex_tx_thread;
 };
 
diff --git a/ubuntu/rsi/rsi_common.h b/ubuntu/rsi/rsi_common.h
index 5067af9..47951cf 100644
--- a/ubuntu/rsi/rsi_common.h
+++ b/ubuntu/rsi/rsi_common.h
@@ -90,4 +90,10 @@  void rsi_resume_conn_channel(struct rsi_hw *adapter);
 void rsi_hci_detach(struct rsi_common *common);
 inline char *dot11_pkt_type(__le16 frame_control);
 struct rsi_sta *rsi_find_sta(struct rsi_common *common, u8 *mac_addr);
+void rsi_init_bcn_timer(struct rsi_common *common);
+void rsi_del_bcn_timer(struct rsi_common *common);
+void rsi_bcn_scheduler_thread(struct rsi_common *common);
+#ifdef CONFIG_SDIO_INTR_POLL
+void init_sdio_intr_status_poll_thread(struct rsi_common *common);
+#endif
 #endif
diff --git a/ubuntu/rsi/rsi_main.h b/ubuntu/rsi/rsi_main.h
index 09b9c82..cb03818 100644
--- a/ubuntu/rsi/rsi_main.h
+++ b/ubuntu/rsi/rsi_main.h
@@ -210,7 +210,9 @@  struct rsi_common {
 	struct version_info fw_ver;
 
 	struct rsi_thread tx_thread;
-	struct rsi_thread hci_thread;
+#ifdef CONFIG_SDIO_INTR_POLL
+	struct rsi_thread sdio_intr_poll_thread;
+#endif
 	struct sk_buff_head tx_queue[NUM_EDCA_QUEUES + 1];
 	/* Mutex declaration */
 	struct mutex mutex;
@@ -222,6 +224,7 @@  struct rsi_common {
 
 	/* Channel/band related */
 	u8 band;
+	u8 num_supp_bands;
 	u8 channel_width;
 
 	u16 rts_threshold;
@@ -287,6 +290,9 @@  struct rsi_common {
 	u8 host_wakeup_intr_active_high;
 	int tx_power;
 	u8 ant_in_use;
+#ifdef CONFIG_RSI_WOW
+	u8 suspend_flag;
+#endif
 
 #if defined (CONFIG_VEN_RSI_HCI) || defined(CONFIG_VEN_RSI_COEX)
 	void *hci_adapter;
@@ -297,14 +303,20 @@  struct rsi_common {
 #endif
 
 	/* AP mode related */
+	u8 beacon_enabled;
+	u16 beacon_interval;
 	u8 *beacon_frame;
 	u16 beacon_frame_len;
 	u16 beacon_cnt;
 	u8 dtim_cnt;
 	u16 bc_mc_seqno;
 	struct rsi_sta stations[RSI_MAX_ASSOC_STAS + 1];
-	u8 num_stations;
+	int num_stations;
 	struct ieee80211_channel *ap_channel;
+	struct rsi_thread bcn_thread;
+	struct timer_list bcn_timer;
+	struct ieee80211_key_conf *key;
+	u8 eapol4_confirm;
 };
 
 enum host_intf {
diff --git a/ubuntu/rsi/rsi_mgmt.h b/ubuntu/rsi/rsi_mgmt.h
index ece9b40..2b902e5 100644
--- a/ubuntu/rsi/rsi_mgmt.h
+++ b/ubuntu/rsi/rsi_mgmt.h
@@ -66,7 +66,7 @@  enum rx_cmd_type {
 	ANTENNA_SELECT = 0xf,
 };
 
-#ifdef RSI_ENABLE_WOW
+#ifdef CONFIG_RSI_WOW
 #define WOW_MAX_FILTERS_PER_LIST 16
 #define WOW_PATTERN_SIZE 256
 #endif
@@ -210,12 +210,12 @@  enum rx_cmd_type {
 #define IEEE80211_STA_SP_ALL_PKTS	0x00
 
 /* Tx data frame format */
-#define MAC_BBP_INFO			BIT(0)
+#define MAC_BBP_INFO			BIT(0) 
 #define NO_ACK_IND			BIT(9)
 #define QOS_EN				BIT(12)
 /* frame type bit{11:10} */
 #define NORMAL_FRAME			0x00
-#define DTIM_BEACON_GATED_FRAME		BIT(10)
+#define DTIM_BEACON_GATED_FRAME		BIT(10) 
 #define BEACON_FRAME			BIT(11)
 #define DTIM_BEACON			BIT(10) | BIT(11)
 #define INSERT_TSF			BIT(15)
@@ -490,7 +490,7 @@  struct rsi_request_ps {
 	u16 ps_num_dtim_intervals;
 } __packed;
 
-struct rsi_wowlan_req {
+struct rsi_wowlan_req { 
 	__le16 desc_word[8];
 	u8 sourceid[ETH_ALEN];
 	u16 wow_flags;
@@ -527,7 +527,7 @@  int rsi_mgmt_pkt_recv(struct rsi_common *common, u8 *msg);
 int rsi_set_vap_capabilities(struct rsi_common *common, enum opmode mode,
 			     u8 vap_status);
 int rsi_send_aggr_params_frame(struct rsi_common *common, u16 tid,
-			       u16 ssn, u8 buf_size, u8 event);
+			       u16 ssn, u8 buf_size, u8 event, u8 sta_id);
 int rsi_load_key(struct rsi_common *common, u8 *data, u16 key_len,
 		 u8 key_type, u8 key_id, u32 cipher, s16 sta_id);
 int rsi_set_channel(struct rsi_common *common,
@@ -536,7 +536,10 @@  int rsi_send_vap_dynamic_update(struct rsi_common *common);
 int rsi_send_block_unblock_frame(struct rsi_common *common, bool event);
 void rsi_inform_bss_status(struct rsi_common *common, enum opmode opmode,
 			   u8 status, u8 *bssid, u8 qos_enable, u16 aid,
-			   u16 sta_id);
+			   struct ieee80211_sta *sta, u16 sta_id);
+int rsi_send_sta_notify_frame(struct rsi_common *common, enum opmode opmode,
+			      u8 notify_event, const unsigned char *bssid,
+			      u8 qos_enable, u16 aid, u16 sta_id);
 void rsi_indicate_pkt_to_os(struct rsi_common *common, struct sk_buff *skb);
 int rsi_mac80211_attach(struct rsi_common *common);
 int rsi_send_bgscan_params(struct rsi_common *common, int enable);
@@ -559,6 +562,6 @@  int rsi_hci_attach(struct rsi_common *common);
 int rsi_handle_card_ready(struct rsi_common *common);
 #ifdef CONFIG_RSI_WOW
 int rsi_send_wowlan_request(struct rsi_common *common, u16 flags,
-			    struct cfg80211_wowlan *wowlan);
+			    u16 sleep_status);
 #endif
 #endif