diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index 527860c..5eeefea 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -592,6 +592,23 @@ static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
 	return -1;
 }
 
+static int hostapd_cli_cmd_disconnect_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[128];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid command: needs one argument, sta mac address \n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "DISCONNECT_STA %s ", argv[0]);
+	if (res < 0 || (size_t) res >= sizeof(cmd))
+		return -1;
+	cmd[sizeof(cmd) - 1] = '\0';
+
+	return wpa_ctrl_command(ctrl, cmd);
+}
 
 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
@@ -732,6 +749,7 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = {
 	{ "relog", hostapd_cli_cmd_relog },
 	{ "sta", hostapd_cli_cmd_sta },
 	{ "all_sta", hostapd_cli_cmd_all_sta },
+	{ "disconnect_sta", hostapd_cli_cmd_disconnect_sta },
 	{ "new_sta", hostapd_cli_cmd_new_sta },
 	{ "deauthenticate", hostapd_cli_cmd_deauthenticate },
 	{ "disassociate", hostapd_cli_cmd_disassociate },
diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c
index d348dc1..5bc7793 100644
--- a/src/ap/ctrl_iface_ap.c
+++ b/src/ap/ctrl_iface_ap.c
@@ -19,6 +19,7 @@
 #include "ieee802_1x.h"
 #include "wpa_auth.h"
 #include "ieee802_11.h"
+#include "common/ieee802_11_defs.h"
 #include "sta_info.h"
 #include "wps_hostapd.h"
 #include "p2p_hostapd.h"
@@ -106,3 +107,24 @@ int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
 	}		
 	return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
 }
+
+int hostapd_ctrl_iface_disconnect_sta(struct hostapd_data *hapd, const char *txtaddr,
+				char *buf, size_t buflen)
+{
+	u8 addr[ETH_ALEN];
+	struct sta_info *sta;
+	int ret;
+
+	if (hwaddr_aton(txtaddr, addr) ||
+	    (sta = ap_get_sta(hapd, addr)) == NULL) {
+		wpa_printf(MSG_ERROR, "AP: Couldn't find sta_info for the "
+					"given mac_addr-"MACSTR, MAC2STR(addr));
+		ret = os_snprintf(buf, buflen, "FAIL\n");
+		if (ret < 0 || (size_t) ret >= buflen)
+			return 0;
+		return ret;
+	}
+	ap_sta_abrupt_disconnect(hapd->iface->bss[0], sta, addr,
+                                                WLAN_REASON_UNSPECIFIED);
+	return 0;
+}
diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h
index 8690bea..1054fd5 100644
--- a/src/ap/ctrl_iface_ap.h
+++ b/src/ap/ctrl_iface_ap.h
@@ -21,5 +21,7 @@ int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr,
 			   char *buf, size_t buflen);
 int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr,
 				char *buf, size_t buflen);
+int hostapd_ctrl_iface_disconnect_sta(struct hostapd_data *hapd, const char *txtaddr,
+				char *buf, size_t buflen);
 
 #endif /* CTRL_IFACE_AP_H */
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index d9c348e..de29efa 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -827,6 +827,27 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta,
 					sta->addr, authorized);
 }
 
+/* This call won't wait for the deauth callback. The sta_info for the sta
+ * is immediately removed after sending the deauth frame. This is required
+ * when sta is explicitly disconnected from AP/P2P Go side. We can't wait
+ * till AP_MAX_INACTIVITY_AFTER_DEAUTH to clear sta_info, because client
+ * may connect back before timer expiry. This is primarily intended for
+ * testing purpose to force disconnect a STA/P2P Client from AP/P2P GO side.
+*/
+void ap_sta_abrupt_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
+                       const u8 *addr, u16 reason) {
+
+	if (sta == NULL)
+		return;
+
+	if (addr)
+		hostapd_drv_sta_deauth(hapd, addr, reason);
+	ap_sta_set_authorized(hapd, sta, 0);
+	mlme_deauthenticate_indication(
+			hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID);
+	ap_free_sta(hapd, sta);
+
+}
 
 void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *addr, u16 reason)
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 4d3b5e9..cc1e78d 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -159,6 +159,8 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta,
 void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
 void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta);
 int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_sta_abrupt_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
+		       const u8 *addr, u16 reason);
 void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta,
 		       const u8 *addr, u16 reason);
 
diff --git a/wpa_supplicant/README-P2P b/wpa_supplicant/README-P2P
index db6e4ae..aa24561 100644
--- a/wpa_supplicant/README-P2P
+++ b/wpa_supplicant/README-P2P
@@ -485,6 +485,12 @@ p2p_peer <P2P Device Address>
 
 Fetch information about a known P2P peer.
 
+disconnect_sta <mac addr>
+
+Force disconnect a P2P Client from P2P GO. Note that the P2P Client may or
+may not connect back depending on how the CTRL-EVENT-DISCONNECTED is handled
+by the client side application. This is primarly intended for testing purpose.
+
 Group Status
 
 (These are used on the group interface.)
@@ -515,7 +521,6 @@ remove_network <network id>
 
 Remove a network entry from configuration. 
 
-
 wpa_cli action script
 ---------------------
 
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index a3b460e..0aaeb3d 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -875,6 +875,14 @@ int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
 					   buf, buflen);
 }
 
+int ap_ctrl_iface_disconnect_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
+			   char *buf, size_t buflen)
+{
+	if (wpa_s->ap_iface == NULL)
+		return -1;
+	return hostapd_ctrl_iface_disconnect_sta(wpa_s->ap_iface->bss[0], txtaddr,
+					   buf, buflen);
+}
 
 int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
 				 size_t buflen, int verbose)
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index aa4c362..edd3d60 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -37,6 +37,8 @@ int ap_ctrl_iface_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
 		      char *buf, size_t buflen);
 int ap_ctrl_iface_sta_next(struct wpa_supplicant *wpa_s, const char *txtaddr,
 			   char *buf, size_t buflen);
+int ap_ctrl_iface_disconnect_sta(struct wpa_supplicant *wpa_s, const char *txtaddr,
+			   char *buf, size_t buflen);
 int ap_ctrl_iface_wpa_get_status(struct wpa_supplicant *wpa_s, char *buf,
 				 size_t buflen, int verbose);
 void ap_tx_status(void *ctx, const u8 *addr,
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index b9ec347..ff4496d 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3673,6 +3673,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 	} else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
 		reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
 						   reply_size);
+	} else if (os_strncmp(buf, "DISCONNECT_STA ", 15) == 0) {
+		reply_len = ap_ctrl_iface_disconnect_sta(wpa_s, buf + 15, reply,
+					      reply_size);
 #endif /* CONFIG_AP */
 	} else if (os_strcmp(buf, "SUSPEND") == 0) {
 		wpas_notify_suspend(wpa_s->global);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 42c81cd..bcadac9 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1879,6 +1879,24 @@ static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
 
 	return -1;
 }
+
+static int wpa_cli_cmd_disconnect_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
+{
+	char cmd[128];
+	int res;
+
+	if (argc != 1) {
+		printf("Invalid command: needs one argument, sta mac address \n");
+		return -1;
+	}
+
+	res = os_snprintf(cmd, sizeof(cmd), "DISCONNECT_STA %s ", argv[0]);
+	if (res < 0 || (size_t) res >= sizeof(cmd))
+		return -1;
+	cmd[sizeof(cmd) - 1] = '\0';
+
+	return wpa_ctrl_command(ctrl, cmd);
+}
 #endif /* CONFIG_AP */
 
 
@@ -2911,6 +2929,9 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
 	{ "all_sta", wpa_cli_cmd_all_sta,
 	  cli_cmd_flag_none,
 	  "= get information about all associated stations (AP)" },
+	{ "disconnect_sta", wpa_cli_cmd_disconnect_sta,
+	  cli_cmd_flag_none,
+	  "= disconnect a particluar STA" },
 #endif /* CONFIG_AP */
 	{ "suspend", wpa_cli_cmd_suspend, cli_cmd_flag_none,
 	  "= notification of suspend/hibernate" },
