diff --git a/platform/linux-generic/include/odp_ipsec_internal.h b/platform/linux-generic/include/odp_ipsec_internal.h
index 1340ca7bd..09a7ac126 100644
--- a/platform/linux-generic/include/odp_ipsec_internal.h
+++ b/platform/linux-generic/include/odp_ipsec_internal.h
@@ -74,9 +74,20 @@ void _odp_ipsec_status_free(ipsec_status_t status);
 int _odp_ipsec_status_send(odp_queue_t queue,
 			   odp_ipsec_status_id_t id,
 			   odp_ipsec_sa_t sa,
-			   int result,
 			   odp_ipsec_warn_t warn);
 
+/**
+ * @internal Send SA_DISABLED event
+ *
+ * Sends the packet notifying application that SA finished all processing and
+ * is now disabled.
+ *
+ * @param queue         destination queue
+ * @param sa            SA respective to the operation
+ */
+int _odp_ipsec_sa_disabled_send(odp_queue_t queue,
+				odp_ipsec_sa_t sa);
+
 #define IPSEC_MAX_IV_LEN	32   /**< Maximum IV length in bytes */
 
 #define IPSEC_MAX_SALT_LEN	4    /**< Maximum salt length in bytes */
@@ -191,6 +202,13 @@ int _odp_ipsec_sa_update_stats(ipsec_sa_t *ipsec_sa, uint32_t len,
 int _odp_ipsec_try_inline(odp_packet_t pkt);
 
 /**
+ * Return IPsec result instance connected to the IPsec packet
+ *
+ * @param packet packet of ODP_EVENT_PACKET_IPSEC subtype
+ */
+odp_ipsec_packet_result_t *_odp_ipsec_pkt_result(odp_packet_t packet);
+
+/**
  * @}
  */
 
diff --git a/platform/linux-generic/odp_ipsec.c b/platform/linux-generic/odp_ipsec.c
index e57736c2a..e9bf88c17 100644
--- a/platform/linux-generic/odp_ipsec.c
+++ b/platform/linux-generic/odp_ipsec.c
@@ -93,7 +93,7 @@ int odp_ipsec_config(const odp_ipsec_config_t *config)
 	return 0;
 }
 
-static odp_ipsec_packet_result_t *ipsec_pkt_result(odp_packet_t packet)
+odp_ipsec_packet_result_t *_odp_ipsec_pkt_result(odp_packet_t packet)
 {
 	ODP_ASSERT(ODP_EVENT_PACKET_IPSEC ==
 		   odp_event_subtype(odp_packet_to_event(packet)));
@@ -902,7 +902,7 @@ int odp_ipsec_in(const odp_packet_t pkt_in[], int num_in,
 
 		_odp_buffer_event_subtype_set(packet_to_buffer(pkt),
 					      ODP_EVENT_PACKET_IPSEC);
-		result = ipsec_pkt_result(pkt);
+		result = _odp_ipsec_pkt_result(pkt);
 		memset(result, 0, sizeof(*result));
 		result->status = status;
 		if (NULL != ipsec_sa)
@@ -966,7 +966,7 @@ int odp_ipsec_out(const odp_packet_t pkt_in[], int num_in,
 
 		_odp_buffer_event_subtype_set(packet_to_buffer(pkt),
 					      ODP_EVENT_PACKET_IPSEC);
-		result = ipsec_pkt_result(pkt);
+		result = _odp_ipsec_pkt_result(pkt);
 		memset(result, 0, sizeof(*result));
 		result->status = status;
 		result->sa = ipsec_sa->ipsec_sa_hdl;
@@ -1014,7 +1014,7 @@ int odp_ipsec_in_enq(const odp_packet_t pkt_in[], int num_in,
 
 		_odp_buffer_event_subtype_set(packet_to_buffer(pkt),
 					      ODP_EVENT_PACKET_IPSEC);
-		result = ipsec_pkt_result(pkt);
+		result = _odp_ipsec_pkt_result(pkt);
 		memset(result, 0, sizeof(*result));
 		result->status = status;
 		if (NULL != ipsec_sa) {
@@ -1075,7 +1075,7 @@ int odp_ipsec_out_enq(const odp_packet_t pkt_in[], int num_in,
 
 		_odp_buffer_event_subtype_set(packet_to_buffer(pkt),
 					      ODP_EVENT_PACKET_IPSEC);
-		result = ipsec_pkt_result(pkt);
+		result = _odp_ipsec_pkt_result(pkt);
 		memset(result, 0, sizeof(*result));
 		result->status = status;
 		result->sa = ipsec_sa->ipsec_sa_hdl;
@@ -1115,7 +1115,7 @@ int _odp_ipsec_try_inline(odp_packet_t pkt)
 
 	_odp_buffer_event_subtype_set(packet_to_buffer(pkt),
 				      ODP_EVENT_PACKET_IPSEC);
-	result = ipsec_pkt_result(pkt);
+	result = _odp_ipsec_pkt_result(pkt);
 	memset(result, 0, sizeof(*result));
 	result->status = status;
 	result->sa = ipsec_sa->ipsec_sa_hdl;
@@ -1192,7 +1192,7 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in,
 
 		_odp_buffer_event_subtype_set(packet_to_buffer(pkt),
 					      ODP_EVENT_PACKET_IPSEC);
-		result = ipsec_pkt_result(pkt);
+		result = _odp_ipsec_pkt_result(pkt);
 		memset(result, 0, sizeof(*result));
 		result->sa = ipsec_sa->ipsec_sa_hdl;
 		result->status = status;
@@ -1217,7 +1217,7 @@ int odp_ipsec_out_inline(const odp_packet_t pkt_in[], int num_in,
 			buf = packet_to_buffer(pkt);
 			_odp_buffer_event_subtype_set(buf,
 						      ODP_EVENT_PACKET_IPSEC);
-			result = ipsec_pkt_result(pkt);
+			result = _odp_ipsec_pkt_result(pkt);
 			memset(result, 0, sizeof(*result));
 			result->sa = ipsec_sa->ipsec_sa_hdl;
 			result->status = status;
@@ -1246,7 +1246,7 @@ int odp_ipsec_result(odp_ipsec_packet_result_t *result, odp_packet_t packet)
 
 	ODP_ASSERT(result != NULL);
 
-	res = ipsec_pkt_result(packet);
+	res = _odp_ipsec_pkt_result(packet);
 
 	/* FIXME: maybe postprocess here, setting alg error in case of crypto
 	 * error instead of processing packet fully in ipsec_in/out_single */
diff --git a/platform/linux-generic/odp_ipsec_events.c b/platform/linux-generic/odp_ipsec_events.c
index 3a7ebd6e8..3a3a9f5f5 100644
--- a/platform/linux-generic/odp_ipsec_events.c
+++ b/platform/linux-generic/odp_ipsec_events.c
@@ -6,6 +6,8 @@
 
 #include "config.h"
 
+#include <string.h>
+
 #include <odp/api/ipsec.h>
 #include <odp/api/shared_memory.h>
 
@@ -13,6 +15,8 @@
 #include <odp_buffer_inlines.h>
 #include <odp_debug_internal.h>
 #include <odp_ipsec_internal.h>
+#include <odp/api/packet.h>
+#include <odp/api/plat/packet_inlines.h>
 #include <odp_pool_internal.h>
 
 typedef struct {
@@ -23,6 +27,7 @@ typedef struct {
 } ipsec_status_hdr_t;
 
 static odp_pool_t ipsec_status_pool = ODP_POOL_INVALID;
+static odp_pool_t ipsec_sa_disabled_pool = ODP_POOL_INVALID;
 
 #define IPSEC_EVENTS_POOL_BUF_COUNT 1024
 
@@ -43,8 +48,24 @@ int _odp_ipsec_events_init_global(void)
 		goto err_status;
 	}
 
+	odp_pool_param_init(&param);
+
+	param.pkt.seg_len = 16;
+	param.pkt.len     = 16;
+	param.pkt.num     = ODP_CONFIG_IPSEC_SAS;
+	param.type        = ODP_POOL_PACKET;
+
+	ipsec_sa_disabled_pool = odp_pool_create("ipsec_sa_disabled_pool",
+						 &param);
+	if (ODP_POOL_INVALID == ipsec_sa_disabled_pool) {
+		ODP_ERR("Error: sa_disabled pool create failed.\n");
+		goto err_sa_disabled;
+	}
+
 	return 0;
 
+err_sa_disabled:
+	odp_pool_destroy(ipsec_status_pool);
 err_status:
 	return -1;
 }
@@ -54,6 +75,12 @@ int _odp_ipsec_events_term_global(void)
 	int ret = 0;
 	int rc = 0;
 
+	ret = odp_pool_destroy(ipsec_sa_disabled_pool);
+	if (ret < 0) {
+		ODP_ERR("sa_disabled pool destroy failed");
+		rc = -1;
+	}
+
 	ret = odp_pool_destroy(ipsec_status_pool);
 	if (ret < 0) {
 		ODP_ERR("status pool destroy failed");
@@ -112,7 +139,6 @@ void _odp_ipsec_status_free(ipsec_status_t status)
 int _odp_ipsec_status_send(odp_queue_t queue,
 			   odp_ipsec_status_id_t id,
 			   odp_ipsec_sa_t sa,
-			   int result,
 			   odp_ipsec_warn_t warn)
 {
 	ipsec_status_t ipsec_ev = odp_ipsec_status_alloc();
@@ -125,7 +151,6 @@ int _odp_ipsec_status_send(odp_queue_t queue,
 
 	status_hdr->status.id = id;
 	status_hdr->status.sa = sa;
-	status_hdr->status.result = result;
 	status_hdr->status.warn = warn;
 
 	if (odp_queue_enq(queue, ipsec_status_to_event(ipsec_ev))) {
@@ -154,3 +179,28 @@ int odp_ipsec_status(odp_ipsec_status_t *status, odp_event_t event)
 
 	return 0;
 }
+
+int _odp_ipsec_sa_disabled_send(odp_queue_t queue,
+				odp_ipsec_sa_t sa)
+{
+	odp_packet_t packet;
+	odp_ipsec_packet_result_t *result;
+
+	ODP_ASSERT(ODP_POOL_INVALID != ipsec_sa_disabled_pool);
+	packet = odp_packet_alloc(ipsec_sa_disabled_pool, 0);
+	ODP_ASSERT(ODP_PACKET_INVALID != packet);
+
+	_odp_buffer_event_subtype_set(packet_to_buffer(packet),
+				      ODP_EVENT_PACKET_IPSEC);
+	result = _odp_ipsec_pkt_result(packet);
+	memset(result, 0, sizeof(*result));
+	result->status.error.sa_disabled = 1;
+	result->sa = sa;
+
+	if (odp_queue_enq(queue, odp_ipsec_packet_to_event(packet))) {
+		odp_packet_free(packet);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/platform/linux-generic/odp_ipsec_sad.c b/platform/linux-generic/odp_ipsec_sad.c
index f0b5b9e4a..a1eff8849 100644
--- a/platform/linux-generic/odp_ipsec_sad.c
+++ b/platform/linux-generic/odp_ipsec_sad.c
@@ -171,7 +171,6 @@ void _odp_ipsec_sa_unuse(ipsec_sa_t *ipsec_sa)
 {
 	odp_queue_t queue;
 	odp_ipsec_sa_t sa;
-	odp_ipsec_warn_t warn = { .all = 0 };
 
 	ODP_ASSERT(NULL != ipsec_sa);
 
@@ -179,9 +178,7 @@ void _odp_ipsec_sa_unuse(ipsec_sa_t *ipsec_sa)
 	sa = ipsec_sa->ipsec_sa_hdl;
 
 	if (ipsec_sa_unlock(ipsec_sa) && ODP_QUEUE_INVALID != queue)
-		_odp_ipsec_status_send(queue,
-				       ODP_IPSEC_STATUS_SA_DISABLE,
-				       sa, 0, warn);
+		_odp_ipsec_sa_disabled_send(queue, sa);
 }
 
 void odp_ipsec_sa_param_init(odp_ipsec_sa_param_t *param)
@@ -370,17 +367,12 @@ int odp_ipsec_sa_disable(odp_ipsec_sa_t sa)
 	}
 
 	if (ODP_QUEUE_INVALID != ipsec_sa->queue) {
-		odp_ipsec_warn_t warn = { .all = 0 };
-
 		/*
-		 * If there were not active state when we disabled SA,
-		 * send the event.
+		 * If there was no active state when we disabled SA, send the
+		 * event. Otherwise it will be sent by _odp_ipsec_sa_unuse().
 		 */
 		if (0 == state)
-			_odp_ipsec_status_send(ipsec_sa->queue,
-					       ODP_IPSEC_STATUS_SA_DISABLE,
-					       ipsec_sa->ipsec_sa_hdl,
-					       0, warn);
+			_odp_ipsec_sa_disabled_send(ipsec_sa->queue, sa);
 
 		return 0;
 	}
