diff --git a/platform/linux-keystone2/Makefile.am b/platform/linux-keystone2/Makefile.am
index 69dd247..a156c00 100644
--- a/platform/linux-keystone2/Makefile.am
+++ b/platform/linux-keystone2/Makefile.am
@@ -23,11 +23,11 @@ include_HEADERS = \
 odpincludedir= $(includedir)/odp
 odpinclude_HEADERS = \
 		  $(srcdir)/include/odp/buffer.h \
-		  $(srcdir)/include/odp/buffer_pool.h \
 		  $(srcdir)/include/odp/crypto.h \
 		  $(srcdir)/include/odp/event.h \
 		  $(srcdir)/include/odp/packet_io.h \
 		  $(srcdir)/include/odp/packet.h \
+		  $(srcdir)/include/odp/pool.h \
 		  $(linux_generic_srcdir)/include/odp/align.h \
 		  $(linux_generic_srcdir)/include/odp/atomic.h \
 		  $(linux_generic_srcdir)/include/odp/barrier.h \
@@ -59,21 +59,21 @@ odpinclude_HEADERS = \
 odpplatincludedir = $(includedir)/odp/plat
 odpplatinclude_HEADERS = \
 		  $(srcdir)/include/odp/plat/align.h \
+		  $(srcdir)/include/odp/plat/buffer_types.h \
 		  $(srcdir)/include/odp/plat/debug.h \
 		  $(srcdir)/include/odp/plat/event_types.h \
 		  $(srcdir)/include/odp/plat/mcsdk_tune.h \
 		  $(srcdir)/include/odp/plat/osal.h \
+		  $(srcdir)/include/odp/plat/pool_types.h \
 		  $(srcdir)/include/odp/plat/state.h \
 		  $(srcdir)/include/odp/plat/ti_mcsdk.h \
 		  $(linux_generic_srcdir)/include/odp/plat/atomic_types.h \
-		  $(linux_generic_srcdir)/include/odp/plat/buffer_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/byteorder_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/classification_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/cpumask_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/crypto_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/packet_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/packet_io_types.h \
-		  $(linux_generic_srcdir)/include/odp/plat/pool_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/queue_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/schedule_types.h \
 		  $(linux_generic_srcdir)/include/odp/plat/shared_memory_types.h \
@@ -132,6 +132,8 @@ subdirheaders_HEADERS = \
 
 __LIB__libodp_la_SOURCES = \
 			   odp_init.c \
+			   odp_pool.c \
+			   odp_buffer.c \
 			   mcsdk/mcsdk_init.c \
 			   mcsdk/mcsdk_navig.c \
 			   mcsdk/mcsdk_rmclient.c \
diff --git a/platform/linux-keystone2/include/odp.h b/platform/linux-keystone2/include/odp.h
index 7526d93..cf52c25 100644
--- a/platform/linux-keystone2/include/odp.h
+++ b/platform/linux-keystone2/include/odp.h
@@ -36,6 +36,8 @@ extern "C" {
 #include <odp/system_info.h>
 #include <odp/thread.h>
 #include <odp/shared_memory.h>
+#include <odp/buffer.h>
+#include <odp/pool.h>
 #include <odp/ticketlock.h>
 #include <odp/time.h>
 #include <odp/sync.h>
diff --git a/platform/linux-keystone2/include/odp/buffer.h b/platform/linux-keystone2/include/odp/buffer.h
index 1889cfb..4b3bf14 100644
--- a/platform/linux-keystone2/include/odp/buffer.h
+++ b/platform/linux-keystone2/include/odp/buffer.h
@@ -19,38 +19,39 @@
 extern "C" {
 #endif
 
-#include <odp_std_types.h>
-#include <odp_ti_mcsdk.h>
+#include <odp/std_types.h>
+#include <odp/plat/osal.h>
+#include <odp/plat/event_types.h>
+#include <odp/plat/buffer_types.h>
+#include <odp/plat/pool_types.h>
+#include <odp/plat/debug.h>
+#include <odp/plat/align.h>
+
+#include <odp/debug.h>
+#include <odp/event.h>
+#include <odp/pool.h>
 
-/**
- * ODP buffer
- */
-typedef Ti_Pkt * odp_buffer_t;
 
-#define ODP_BUFFER_INVALID ((odp_buffer_t)0) /**< Invalid buffer */
+typedef struct odp_bufhdr {
+	/* Empty structure for now */
+} odp_buffer_hdr_t;
 
 /**
- * @internal Convert ODP buffer to PKTLIB packet handle
- *
- * @param buf   Buffer handle
- *
- * @return PKTLIB packet handle
+ * Buffer headroom size reserved for implementation buffer metadata.
  */
-static inline Ti_Pkt *_odp_buf_to_ti_pkt(odp_buffer_t buf)
+#define _ODP_BUFHDR_SIZE   ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_buffer_hdr_t))
+
+_ODP_STATIC_ASSERT(_ODP_BUFHDR_SIZE <= ODP_CACHE_LINE_SIZE,
+		   "_ODP_BUFHDR_SIZE <= ODP_CACHE_LINE_SIZE");
+
+static inline odp_buffer_t _odp_ev_to_buf(odp_event_t ev)
 {
-	return (Ti_Pkt *)buf;
+	return (odp_buffer_t)ev;
 }
 
-/**
- * @internal Convert PKTLIB packet handle to ODP buffer
- *
- * @param pkt   PKTLIB packet handle
- *
- * @return ODP buffer handle
- */
-static inline odp_buffer_t _ti_pkt_to_odp_buf(Ti_Pkt *pkt)
+static inline odp_event_t _odp_buf_to_ev(odp_buffer_t buf)
 {
-	return (odp_buffer_t)pkt;
+	return (odp_event_t)buf;
 }
 
 /**
@@ -62,7 +63,7 @@ static inline odp_buffer_t _ti_pkt_to_odp_buf(Ti_Pkt *pkt)
  */
 static inline Cppi_HostDesc *_odp_buf_to_cppi_desc(odp_buffer_t buf)
 {
-	return Pktlib_getDescFromPacket(_odp_buf_to_ti_pkt(buf));
+	return _odp_ev_to_cppi_desc(_odp_buf_to_ev(buf));
 }
 
 /**
@@ -74,99 +75,84 @@ static inline Cppi_HostDesc *_odp_buf_to_cppi_desc(odp_buffer_t buf)
  */
 static inline odp_buffer_t _cppi_desc_to_odp_buf(Cppi_HostDesc *desc)
 {
-	return _ti_pkt_to_odp_buf(Pktlib_getPacketFromDesc(desc));
+	return _odp_ev_to_buf(_cppi_desc_to_odp_ev(desc));
 }
-
+#if 0
 /**
- * Buffer start address
+ * @internal Convert ODP buffer to PKTLIB packet handle
  *
- * @param buf      Buffer handle
+ * @param buf   Buffer handle
  *
- * @return Buffer start address
+ * @return PKTLIB packet handle
  */
-static inline void *odp_buffer_addr(odp_buffer_t buf)
+static inline Ti_Pkt *_odp_buf_to_ti_pkt(odp_buffer_t buf)
 {
-	return (void *)_odp_buf_to_cppi_desc(buf)->buffPtr;
+	return Pktlib_getPacketFromDesc(_odp_buf_to_cppi_desc(buf));
 }
 
 /**
- * Buffer maximum data size
+ * @internal Convert PKTLIB packet handle to ODP buffer
  *
- * @param buf      Buffer handle
+ * @param pkt   PKTLIB packet handle
  *
- * @return Buffer maximum data size
+ * @return ODP buffer handle
  */
-static inline size_t odp_buffer_size(odp_buffer_t buf)
+static inline odp_buffer_t _ti_pkt_to_odp_buf(Ti_Pkt *pkt)
 {
-	return _odp_buf_to_cppi_desc(buf)->buffLen;
+	return _cppi_desc_to_odp_buf(Pktlib_getDescFromPacket(pkt));
 }
+#endif
 
-#define ODP_BUFFER_TYPE_INVALID (-1) /**< Buffer type invalid */
-#define ODP_BUFFER_TYPE_ANY       0  /**< Buffer that can hold any other
-					  buffer type */
-#define ODP_BUFFER_TYPE_RAW       1  /**< Raw buffer, no additional metadata */
-#define ODP_BUFFER_TYPE_PACKET    2  /**< Packet buffer */
-#define ODP_BUFFER_TYPE_TIMEOUT   3  /**< Timeout buffer */
-/**
- * Buffer type
- *
- * @param buf      Buffer handle
- *
- * @return Buffer type
- */
-static inline int odp_buffer_type(odp_buffer_t buf)
+static inline odp_buffer_t odp_buffer_from_event(odp_event_t ev)
 {
-	return Pktlib_getUsrFlags(_odp_buf_to_ti_pkt(buf));
+	return _odp_ev_to_buf(ev);
 }
 
-/**
- * Tests if buffer is valid
- *
- * @param buf      Buffer handle
- *
- * @return 1 if valid, otherwise 0
- */
-static inline int odp_buffer_is_valid(odp_buffer_t buf)
+static inline odp_event_t odp_buffer_to_event(odp_buffer_t buf)
 {
-	return (buf != ODP_BUFFER_INVALID);
+	return _odp_buf_to_ev(buf);
 }
 
-/**
- * Print buffer metadata to STDOUT
- *
- * @param buf      Buffer handle
- */
-void odp_buffer_print(odp_buffer_t buf);
+static inline struct odp_bufhdr *_odp_buf_hdr(odp_buffer_t buf)
+{
+	Cppi_HostDesc *desc = _odp_buf_to_cppi_desc(buf);
+	uint8_t *orig_ptr = _cppi_desc_orig_vptr(desc);
+	ODP_ASSERT(ODP_ALIGNED_CHECK(orig_ptr, ODP_ALIGNOF(struct odp_bufhdr)),
+		   "Wrong buffer header alignment");
+	return (struct odp_bufhdr *)(void *)orig_ptr;
+}
 
-/**
- * @internal Set buffer user context
- *
- * @param buffer   Buffer handle
- * @param context  User context
- */
-static inline void odp_buffer_set_ctx(odp_buffer_t buffer, void *context)
+/* Compatibility function for timer code reused from linux-generic */
+static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
 {
-	Cppi_setTimeStamp(Cppi_DescType_HOST,
-			  (Cppi_Desc *)_odp_buf_to_cppi_desc(buffer),
-			  (uint32_t) context);
+	return (odp_buffer_hdr_t *)_odp_buf_hdr(buf);
 }
 
-/**
- * @internal Get buffer user context
- *
- * @param buffer   Buffer handle
- *
- * @return User context
- */
-static inline void *odp_buffer_get_ctx(odp_buffer_t buffer)
+static inline void *odp_buffer_addr(odp_buffer_t buf)
+{
+	Cppi_HostDesc *desc = _odp_buf_to_cppi_desc(buf);
+	return _cppi_desc_orig_vptr(desc) + _ODP_BUFHDR_SIZE;
+}
+
+static inline uint32_t odp_buffer_size(odp_buffer_t buf)
+{
+	Cppi_HostDesc *desc = _odp_buf_to_cppi_desc(buf);
+	return _cppi_desc_orig_len(desc) - _ODP_BUFHDR_SIZE;
+}
+
+static inline int odp_buffer_is_valid(odp_buffer_t buf)
+{
+	return (buf != ODP_BUFFER_INVALID);
+}
+
+static inline odp_pool_t odp_buffer_pool(odp_buffer_t buf)
 {
-	uint32_t app_ctx_id = 0;
-	Cppi_getTimeStamp(Cppi_DescType_HOST,
-			  (Cppi_Desc *)_odp_buf_to_cppi_desc(buffer),
-			  &app_ctx_id);
-	return (void *)app_ctx_id;
+	return _odp_event_pool(_odp_buf_to_ev(buf));
 }
 
+#include <odp/api/buffer.h>
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/platform/linux-keystone2/include/odp/buffer_pool.h b/platform/linux-keystone2/include/odp/buffer_pool.h
deleted file mode 100644
index 970c33a..0000000
--- a/platform/linux-keystone2/include/odp/buffer_pool.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2014, Linaro Limited
- * Copyright (c) 2014, Texas Instruments Incorporated
- * All rights reserved.
- *
- * SPDX-License-Identifier:     BSD-3-Clause
- */
-
-/**
- * @file
- *
- * ODP buffer pool
- */
-
-#ifndef ODP_BUFFER_POOL_H_
-#define ODP_BUFFER_POOL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-
-#include <odp_std_types.h>
-#include <odp_buffer.h>
-#include <ti/runtime/pktlib/pktlib.h>
-
-/** Maximum queue name length in chars */
-/* #define ODP_BUFFER_POOL_NAME_LEN  PKTLIB_MAX_HEAP_NAME */
-
-/** Invalid buffer pool */
-#define ODP_BUFFER_POOL_INVALID  (NULL)
-
-/** ODP buffer pool */
-typedef Pktlib_HeapHandle odp_buffer_pool_t;
-
-
-/**
- * Create a buffer pool
- *
- * @param name      Name of the pool (max ODP_BUFFER_POOL_NAME_LEN - 1 chars)
- * @param base_addr Pool base address
- * @param size      Pool size in bytes
- * @param buf_size  Buffer size in bytes
- * @param buf_align Minimum buffer alignment
- * @param buf_type  Buffer type
- *
- * @return Buffer pool handle
- */
-odp_buffer_pool_t odp_buffer_pool_create(const char *name,
-					 void *base_addr, uint64_t size,
-					 size_t buf_size, size_t buf_align,
-					 int buf_type);
-
-
-/**
- * Find a buffer pool by name
- *
- * @param name      Name of the pool
- *
- * @return Buffer pool handle, or ODP_BUFFER_POOL_INVALID if not found.
- */
-odp_buffer_pool_t odp_buffer_pool_lookup(const char *name);
-
-
-/**
- * Print buffer pool info
- *
- * @param pool      Pool handle
- *
- */
-void odp_buffer_pool_print(odp_buffer_pool_t pool);
-
-
-
-/**
- * Buffer alloc
- *
- * @param pool      Pool handle
- *
- * @return Buffer handle or ODP_BUFFER_INVALID
- */
-odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool);
-
-
-/**
- * Buffer free
- *
- * @param buf       Buffer handle
- *
- */
-void odp_buffer_free(odp_buffer_t buf);
-
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/platform/linux-keystone2/include/odp/event.h b/platform/linux-keystone2/include/odp/event.h
index 1233e92..17b26bb 100644
--- a/platform/linux-keystone2/include/odp/event.h
+++ b/platform/linux-keystone2/include/odp/event.h
@@ -19,6 +19,7 @@ extern "C" {
 
 #include <odp/plat/event_types.h>
 #include <odp/plat/osal.h>
+#include <odp/pool.h>
 
 /**
  * @internal Convert ODP event to CPPI descriptor
@@ -44,6 +45,14 @@ static inline odp_event_t _cppi_desc_to_odp_ev(Cppi_HostDesc *desc)
 	return (odp_event_t)desc;
 }
 
+static inline odp_pool_t _odp_event_pool(odp_event_t ev)
+{
+	Cppi_HostDesc *desc = _odp_ev_to_cppi_desc(ev);
+	uint8_t pool_id = _cppi_desc_pool_id(desc);
+	pool_entry_t *pool_entry = _odp_pool_id_to_entry(pool_id);
+	return _odp_pool_from_entry(pool_entry);
+}
+
 /** @ingroup odp_event
  *  @{
  */
diff --git a/platform/linux-keystone2/include/odp/plat/buffer_types.h b/platform/linux-keystone2/include/odp/plat/buffer_types.h
new file mode 100644
index 0000000..80319af
--- /dev/null
+++ b/platform/linux-keystone2/include/odp/plat/buffer_types.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, Linaro Limited
+ * Copyright (c) 2014, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP buffer types
+ */
+
+#ifndef ODP_PLAT_BUFFER_TYPES_H_
+#define ODP_PLAT_BUFFER_TYPES_H_
+
+#include <odp/std_types.h>
+#include <odp/plat/strong_types.h>
+
+/**
+ * ODP buffer
+ */
+typedef odp_handle_t odp_buffer_t;
+
+#define ODP_BUFFER_INVALID ((odp_buffer_t)0) /**< Invalid buffer */
+
+#endif
diff --git a/platform/linux-keystone2/include/odp/plat/pool_types.h b/platform/linux-keystone2/include/odp/plat/pool_types.h
new file mode 100644
index 0000000..82a7c8f
--- /dev/null
+++ b/platform/linux-keystone2/include/odp/plat/pool_types.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * Copyright (c) 2014, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP pool types
+ */
+
+#ifndef ODP_PLAT_POOL_TYPES_H_
+#define ODP_PLAT_POOL_TYPES_H_
+
+#include <odp/std_types.h>
+#include <odp/plat/strong_types.h>
+
+/** @addtogroup odp_buffer
+ *  Operations on a pool.
+ *  @{
+ */
+
+#define ODP_POOL_NAME_LEN  32
+
+typedef odp_handle_t odp_pool_t;
+
+/** Invalid buffer pool */
+#define ODP_POOL_INVALID  ((odp_pool_t)0)
+
+/** Get printable format of odp_pool_t */
+static inline uint64_t odp_pool_to_u64(odp_pool_t hdl)
+{
+	return _odp_pri(hdl);
+}
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/platform/linux-keystone2/include/odp/pool.h b/platform/linux-keystone2/include/odp/pool.h
new file mode 100644
index 0000000..790e814
--- /dev/null
+++ b/platform/linux-keystone2/include/odp/pool.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * Copyright (c) 2014, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP buffer pool
+ */
+
+#ifndef ODP_POOL_H_
+#define ODP_POOL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/plat/pool_types.h>
+#include <odp/plat/ti_mcsdk.h>
+#include <odp/plat/shared_memory_types.h>
+#include <odp/plat/event_types.h>
+#include <odp/api/pool.h>
+
+/* Use ticketlock instead of spinlock */
+#define POOL_USE_TICKETLOCK
+
+#ifdef POOL_USE_TICKETLOCK
+#include <odp/ticketlock.h>
+#define POOL_LOCK(a)      odp_ticketlock_lock(a)
+#define POOL_UNLOCK(a)    odp_ticketlock_unlock(a)
+#define POOL_LOCK_INIT(a) odp_ticketlock_init(a)
+#define POOL_LOCK_T       odp_ticketlock_t
+#else
+#include <odp/spinlock.h>
+#define POOL_LOCK(a)      odp_spinlock_lock(a)
+#define POOL_UNLOCK(a)    odp_spinlock_unlock(a)
+#define POOL_LOCK_INIT(a) odp_spinlock_init(a)
+#define POOL_LOCK_T       odp_spinlock_t
+#endif
+
+typedef uint8_t _pool_id_t;
+
+struct pool_entry_s {
+	POOL_LOCK_T       lock ODP_ALIGNED_CACHE;
+	Qmss_QueueHnd     free_queue;
+	char              name[ODP_POOL_NAME_LEN];
+	_pool_id_t        id;
+	uint32_t          headroom;
+	uint32_t          tailroom;
+	uint32_t          buf_size;
+	uint32_t          buf_align;
+	uint32_t          num_bufs;
+
+	struct {
+		Cppi_FlowHnd handle;
+		uint32_t id;
+	} cppi_flow;
+
+	union {
+		uint32_t all;
+		struct {
+			uint32_t allocated:1;
+			uint32_t has_name:1;
+			uint32_t predefined:1;
+		};
+	} flags;
+
+	odp_pool_param_t orig_params;
+};
+
+typedef struct pool_entry_s pool_entry_t;
+
+extern pool_entry_t *pool_tbl;
+
+static inline
+pool_entry_t *_odp_pool_entry(odp_pool_t pool)
+{
+	return (pool_entry_t *)(uintptr_t)pool;
+}
+
+static inline
+pool_entry_t *_odp_pool_id_to_entry(_pool_id_t pool_id)
+{
+	return &pool_tbl[pool_id];
+}
+
+static inline
+odp_pool_t _odp_pool_from_entry(pool_entry_t *entry)
+{
+	return (odp_pool_t)entry;
+}
+
+static inline
+_pool_id_t _odp_pool_id(odp_pool_t pool)
+{
+	return _odp_pool_entry(pool)->id;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-keystone2/include/odp_buffer_internal.h b/platform/linux-keystone2/include/odp_buffer_internal.h
index c3228ec..dade794 100644
--- a/platform/linux-keystone2/include/odp_buffer_internal.h
+++ b/platform/linux-keystone2/include/odp_buffer_internal.h
@@ -19,40 +19,12 @@
 extern "C" {
 #endif
 
-#include <odp_std_types.h>
-#include <odp_atomic.h>
-#include <odp_buffer_pool.h>
-#include <odp_buffer.h>
-#include <odp_queue.h>
-#include <odp_debug_internal.h>
-#include <odp_align.h>
-
-typedef struct odp_bufhdr {
-	int type;
-} odp_buffer_hdr_t;
-
-ODP_STATIC_ASSERT(sizeof(Cppi_HostDesc) <= ODP_CACHE_LINE_SIZE,
-		  "ODP_BUFFER_HDR_T__SIZE_ERROR");
-
-static inline struct odp_bufhdr *odp_buffer_hdr(odp_buffer_t buf)
-{
-	return (struct odp_bufhdr *)(_odp_buf_to_cppi_desc(buf)->origBuffPtr);
-}
-
-/* Compatibility function for timer code reused from linux-generic */
-static inline odp_buffer_hdr_t *odp_buf_to_hdr(odp_buffer_t buf)
-{
-	return (odp_buffer_hdr_t *)odp_buffer_hdr(buf);
-}
-
-extern odp_buffer_pool_t odp_buf_to_pool(odp_buffer_t buf);
+#include <odp/std_types.h>
 
+#include <odp/plat/buffer_types.h>
 
 int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf);
 
-void odp_buffer_copy_scatter(odp_buffer_t buf_dst, odp_buffer_t buf_src);
-
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/platform/linux-keystone2/include/odp_buffer_pool_internal.h b/platform/linux-keystone2/include/odp_buffer_pool_internal.h
deleted file mode 100644
index 95960c9..0000000
--- a/platform/linux-keystone2/include/odp_buffer_pool_internal.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2014, Linaro Limited
- * Copyright (c) 2014, Texas Instruments Incorporated
- * All rights reserved.
- *
- * SPDX-License-Identifier:     BSD-3-Clause
- */
-
-/**
- * @file
- *
- * ODP buffer pool - internal header
- */
-
-#ifndef ODP_BUFFER_POOL_INTERNAL_H_
-#define ODP_BUFFER_POOL_INTERNAL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <odp_std_types.h>
-#include <odp_buffer_pool.h>
-
-uint32_t _odp_pool_get_free_queue(odp_buffer_pool_t pool_id);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/platform/linux-keystone2/include/odp_internal.h b/platform/linux-keystone2/include/odp_internal.h
index 816e74f..2131e5a 100644
--- a/platform/linux-keystone2/include/odp_internal.h
+++ b/platform/linux-keystone2/include/odp_internal.h
@@ -34,7 +34,7 @@ int odp_shm_init_global(void);
 int odp_shm_term_global(void);
 int odp_shm_init_local(void);
 
-int odp_buffer_pool_init_global(void);
+int odp_pool_init_global(void);
 
 int odp_pktio_init_global(void);
 
diff --git a/platform/linux-keystone2/include/odp_pool_internal.h b/platform/linux-keystone2/include/odp_pool_internal.h
new file mode 100644
index 0000000..b605cf6
--- /dev/null
+++ b/platform/linux-keystone2/include/odp_pool_internal.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * Copyright (c) 2014, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP pool - internal header
+ */
+
+#ifndef ODP_POOL_INTERNAL_H_
+#define ODP_POOL_INTERNAL_H_
+
+#include <odp/std_types.h>
+#include <odp/pool.h>
+
+Qmss_QueueHnd _odp_pool_get_free_queue(odp_pool_t pool_id);
+int32_t _odp_pool_cppi_flow_id(odp_pool_t pool);
+
+#endif
diff --git a/platform/linux-keystone2/odp_buffer.c b/platform/linux-keystone2/odp_buffer.c
index 676a8a4..1e04ccb 100644
--- a/platform/linux-keystone2/odp_buffer.c
+++ b/platform/linux-keystone2/odp_buffer.c
@@ -6,9 +6,70 @@
  * SPDX-License-Identifier:     BSD-3-Clause
  */
 
-#include <odp_buffer.h>
+#include <odp/plat/pool_types.h>
+#include <odp/plat/debug.h>
+
+#include <odp/config.h>
+#include <odp/buffer.h>
+
 #include <odp_buffer_internal.h>
-#include <odp_buffer_pool_internal.h>
+
+odp_buffer_t odp_buffer_alloc(odp_pool_t pool)
+{
+	Cppi_HostDesc *desc;
+	uintptr_t desc_phys;
+	pool_entry_t *pool_entry = _odp_pool_entry(pool);
+	uint32_t headroom = pool_entry->headroom;
+	odp_pa_t buf_phys;
+
+	desc_phys = QMSS_DESC_PTR(Qmss_queuePopRaw(pool_entry->free_queue));
+	desc = _odp_mem_phys_to_virt(desc_phys);
+
+	if (!desc)
+		return ODP_BUFFER_INVALID;
+
+	ODP_ASSERT(_cppi_desc_next(desc) == 0,
+		   "Pool should not have linked buffers");
+
+	buf_phys = _cppi_desc_orig_ptr(desc);
+	if (buf_phys) {
+		uint8_t *buf_addr = _odp_mem_phys_to_virt(buf_phys);
+		ODP_ASSERT(buf_addr, "Failed phys to virt translation");
+
+		_cppi_desc_orig_vptr_set(desc, buf_addr);
+		/* Leave space for buffer metadata */
+		_cppi_desc_buf_vptr_set(desc, buf_addr + headroom);
+		_cppi_desc_buf_len_set(desc, _cppi_desc_orig_len(desc) -
+				       headroom);
+	}
+
+	odp_pr_vdbg("pool_id: %p, pkt: %p, buf: %p\n", id, pkt, buf);
+	return _cppi_desc_to_odp_buf(desc);
+}
+
+void odp_buffer_free(odp_buffer_t buf)
+{
+	Cppi_HostDesc *desc;
+	uint32_t pool_id;
+	pool_entry_t *pool_entry;
+
+	odp_pr_vdbg("buf: %p\n", buf);
+	desc = _odp_buf_to_cppi_desc(buf);
+	ODP_ASSERT(_cppi_desc_vnext(desc) == NULL,
+		   "Pool should not have linked buffers");
+
+	pool_id = _cppi_desc_pool_id(desc);
+	pool_entry = _odp_pool_id_to_entry(pool_id);
+
+	if (_cppi_desc_orig_vptr(desc)) {
+		_cppi_desc_orig_ptr_set(desc, _odp_mem_virt_to_phys(
+						_cppi_desc_orig_vptr(desc)));
+	}
+
+	Qmss_queuePushDescSizeRaw(pool_entry->free_queue,
+				  (void *)_odp_mem_virt_to_phys(desc),
+				  16);
+}
 
 int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
 {
@@ -35,7 +96,7 @@ int odp_buffer_snprint(char *str, size_t n, odp_buffer_t buf)
 	len += snprintf(&str[len], n-len,
 			"  buf_len   0x%x\n",      desc->buffLen);
 	len += snprintf(&str[len], n-len,
-			"  pool        %p\n",      odp_buf_to_pool(buf));
+			"  pool        %p\n",      odp_buffer_pool(buf));
 
 	len += snprintf(&str[len], n-len, "\n");
 
@@ -62,9 +123,3 @@ void odp_buffer_print(odp_buffer_t buf)
 		      desc->buffPtr - desc->origBuffPtr + 128,
 		      "Buffer start");
 }
-
-void odp_buffer_copy_scatter(odp_buffer_t buf_dst, odp_buffer_t buf_src)
-{
-	(void)buf_dst;
-	(void)buf_src;
-}
diff --git a/platform/linux-keystone2/odp_buffer_pool.c b/platform/linux-keystone2/odp_buffer_pool.c
deleted file mode 100644
index 13656a9..0000000
--- a/platform/linux-keystone2/odp_buffer_pool.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2014, Linaro Limited
- * Copyright (c) 2014, Texas Instruments Incorporated
- * All rights reserved.
- *
- * SPDX-License-Identifier:     BSD-3-Clause
- */
-
-#include <odp_std_types.h>
-#include <odp_buffer_pool.h>
-#include <odp_buffer_pool_internal.h>
-#include <odp_buffer_internal.h>
-#include <odp_align.h>
-#include <odp_internal.h>
-#include <odp_config.h>
-#include <odp_hints.h>
-#include <odp_debug.h>
-
-#include <string.h>
-#include <stdlib.h>
-
-/**
- * @todo: Currently a number of HW descriptors is limited,
- *        so temporary limit max number of buffers per pool
- *        to be albe to run ODP example apps.
- *        Descriptor management have to be made more intelligent
- *        To remove this limitation.
- */
-#define MAX_BUFS_PER_POOL	1024
-
-int odp_buffer_pool_init_global(void)
-{
-	/* Pktlib initialized in mcsdk_global_init() */
-	return 0;
-}
-
-odp_buffer_pool_t odp_buffer_pool_create(const char *name,
-		void *base_addr ODP_UNUSED, uint64_t size,
-		size_t buf_size, size_t buf_align,
-		int buf_type ODP_UNUSED)
-{
-	Pktlib_HeapCfg heap_cfg;
-	Pktlib_HeapHandle heap_handle;
-	int num_bufs;
-	int err_code;
-
-	buf_size  = ODP_ALIGN_ROUNDUP(buf_size, buf_align);
-	/*
-	 * XXX: size is used only to get number of buffers.
-	 * Memory is allocated for each buffer separately
-	 */
-	num_bufs  = size / buf_size;
-	buf_size += odp_global->cfg.min_buf_headroom_size;
-	buf_size  = ODP_CACHE_LINE_SIZE_ROUNDUP(buf_size);
-
-
-	if (num_bufs > MAX_BUFS_PER_POOL) {
-		odp_pr_dbg("Limiting number of buffer in %s from %d to %d\n",
-			   name, num_bufs, MAX_BUFS_PER_POOL);
-		num_bufs = MAX_BUFS_PER_POOL;
-	}
-
-	/* Initialize the heap configuration. */
-	memset((void *)&heap_cfg, 0, sizeof(Pktlib_HeapCfg));
-	/* Populate the heap configuration */
-	heap_cfg.name               = name;
-	heap_cfg.memRegion          = odp_global->public_desc_memregion;
-	heap_cfg.sharedHeap         = 1;
-	heap_cfg.useStarvationQueue = 0;
-	heap_cfg.dataBufferSize     = buf_size;
-	heap_cfg.numPkts            = num_bufs;
-	heap_cfg.numZeroBufferPackets   = 0;
-	heap_cfg.heapInterfaceTable.data_malloc =
-			pktlib_if_table.data_malloc;
-	heap_cfg.heapInterfaceTable.data_free =
-			pktlib_if_table.data_free;
-	heap_cfg.dataBufferPktThreshold = 0;
-	heap_cfg.zeroBufferPktThreshold = 0;
-	odp_pr_dbg("name: %s, buf_size: %u, num_bufs: %u\n", name, buf_size,
-		   num_bufs);
-	/* Create Shared Heap with specified configuration. */
-	heap_handle = Pktlib_createHeap(&heap_cfg, &err_code);
-	odp_pr_dbg("heap_handle: %p, err_code: %d\n", heap_handle, err_code);
-	return heap_handle;
-}
-
-odp_buffer_pool_t odp_buffer_pool_lookup(const char *name)
-{
-	return Pktlib_findHeapByName(name);
-}
-
-odp_buffer_t odp_buffer_alloc(odp_buffer_pool_t pool_id)
-{
-	Ti_Pkt *pkt;
-	odp_buffer_t buf;
-	Cppi_HostDesc *desc;
-
-	pkt = Pktlib_allocPacket(pool_id, -1);
-	if (!pkt)
-		return ODP_BUFFER_INVALID;
-
-	buf = _ti_pkt_to_odp_buf(pkt);
-	desc = _odp_buf_to_cppi_desc(buf);
-
-	/* Leave space for buffer metadata. There must be enough space. */
-	desc->buffPtr = desc->origBuffPtr +
-			odp_global->cfg.min_buf_headroom_size;
-
-	odp_pr_vdbg("pool_id: %p, pkt: %p, buf: %p\n", pool_id, pkt, buf);
-	return buf;
-}
-
-void odp_buffer_free(odp_buffer_t buf)
-{
-	odp_pr_vdbg("buf: %p\n", buf);
-	Pktlib_freePacket(_odp_buf_to_ti_pkt(buf));
-}
-
-void odp_buffer_pool_print(odp_buffer_pool_t pool_id)
-{
-	(void)pool_id;
-}
-
-odp_buffer_pool_t odp_buf_to_pool(odp_buffer_t buf)
-{
-	return Pktlib_getPktHeap(_odp_buf_to_ti_pkt(buf));
-}
-
-uint32_t _odp_pool_get_free_queue(odp_buffer_pool_t pool_id)
-{
-	return Pktlib_getInternalHeapQueue(pool_id);
-}
diff --git a/platform/linux-keystone2/odp_init.c b/platform/linux-keystone2/odp_init.c
index 86df7fe..38055e0 100644
--- a/platform/linux-keystone2/odp_init.c
+++ b/platform/linux-keystone2/odp_init.c
@@ -45,12 +45,12 @@ int odp_init_global(odp_init_t *params ODP_UNUSED,
 		odp_pr_err("ODP McSDK init failed.\n");
 		return -1;
 	}
-#if 0
-	if (odp_buffer_pool_init_global()) {
+	if (odp_pool_init_global()) {
 		odp_pr_err("ODP buffer pool init failed.\n");
 		return -1;
 	}
 
+#if 0
 	if (odp_queue_init_global()) {
 		odp_pr_err("ODP queue init failed.\n");
 		return -1;
diff --git a/platform/linux-keystone2/odp_pool.c b/platform/linux-keystone2/odp_pool.c
new file mode 100644
index 0000000..93fac4b
--- /dev/null
+++ b/platform/linux-keystone2/odp_pool.c
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2014, Linaro Limited
+ * Copyright (c) 2014, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/std_types.h>
+#include <odp/pool.h>
+#include <odp/buffer.h>
+#include <odp_pool_internal.h>
+#include <odp_buffer_internal.h>
+#include <odp_align_internal.h>
+#include <odp_internal.h>
+#include <odp/config.h>
+#include <odp/hints.h>
+#include <odp/plat/debug.h>
+#include <odp/plat/osal.h>
+#include <odp/shared_memory.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+pool_entry_t *pool_tbl;
+/**
+ * @todo: Currently a number of HW descriptors is limited,
+ *        so temporary limit max number of buffers per pool
+ *        to be albe to run ODP example apps.
+ *        Descriptor management have to be made more intelligent
+ *        To remove this limitation.
+ */
+#define MAX_BUFS_PER_POOL	1024
+
+int odp_pool_init_global(void)
+{
+	_pool_id_t i;
+	odp_shm_t shm;
+	size_t shm_size = sizeof(pool_entry_t) * ODP_CONFIG_POOLS;
+
+	shm = odp_shm_reserve("odp_pools",
+			      shm_size,
+			      sizeof(pool_entry_t), 0);
+
+	pool_tbl = odp_shm_addr(shm);
+
+	if (pool_tbl == NULL)
+		return -1;
+
+	memset(pool_tbl, 0, shm_size);
+
+	for (i = 0; i < ODP_CONFIG_POOLS; i++) {
+		/* init locks */
+		pool_entry_t *entry = _odp_pool_id_to_entry(i);
+		POOL_LOCK_INIT(&entry->lock);
+		entry->id = i;
+	}
+
+	ODP_DBG("\nBuffer pool init global\n");
+	ODP_DBG("  pool_entry_t size     %zu\n", sizeof(pool_entry_t));
+	ODP_DBG("\n");
+	return 0;
+}
+
+static pool_entry_t *find_free_pool_entry_locked(void)
+{
+	int i;
+
+	for (i = 0; i < ODP_CONFIG_POOLS; i++) {
+		pool_entry_t *entry = _odp_pool_id_to_entry(i);
+
+		POOL_LOCK(&entry->lock);
+		if (!entry->flags.allocated)
+			return entry;
+		POOL_UNLOCK(&entry->lock);
+	}
+	return NULL;
+}
+
+static void _free_descriptors(Qmss_MemRegion mem_region,
+			     Qmss_QueueHnd queue)
+{
+	Qmss_QueueHnd mem_reg_queue = Qmss_getMemRegQueueHandle(mem_region);
+	Qmss_Result result;
+
+	while (Qmss_getQueueEntryCount(queue) != 0) {
+		uintptr_t desc_phys = QMSS_DESC_PTR(Qmss_queuePopRaw(queue));
+		ODP_ASSERT(desc_phys, "No descriptors in a pool free queue");
+
+		/* Place back the descriptor into the memory region queue. */
+		Qmss_queuePushDescSizeRaw(mem_reg_queue, (void *)desc_phys, 16);
+	}
+	result = Qmss_queueClose(queue);
+	ODP_ASSERT(result >= 0, "Queue close failed");
+}
+
+static Qmss_QueueHnd _alloc_descriptors(Qmss_MemRegion mem_region,
+				       uint32_t desc_num)
+{
+	Cppi_DescCfg desc_cfg;
+	Qmss_QueueHnd queue;
+	uint32_t num_allocated;
+
+	/* Initialize the descriptor configuration */
+	memset((void *)&desc_cfg, 0, sizeof(Cppi_DescCfg));
+
+	/* Populate the descriptor configuration:  */
+	desc_cfg.memRegion             = mem_region;
+	desc_cfg.descNum               = desc_num;
+	desc_cfg.destQueueNum          = QMSS_PARAM_NOT_SPECIFIED;
+	desc_cfg.queueGroup            = 0;
+	desc_cfg.queueType             = Qmss_QueueType_GENERAL_PURPOSE_QUEUE;
+	desc_cfg.initDesc              = Cppi_InitDesc_INIT_DESCRIPTOR;
+	desc_cfg.descType              = Cppi_DescType_HOST;
+	desc_cfg.returnQueue.qMgr      = QMSS_PARAM_NOT_SPECIFIED;
+	desc_cfg.returnQueue.qNum      = QMSS_PARAM_NOT_SPECIFIED;
+	desc_cfg.epibPresent           = Cppi_EPIB_EPIB_PRESENT;
+	desc_cfg.returnPushPolicy      = Qmss_Location_TAIL;
+	desc_cfg.cfg.host.returnPolicy = Cppi_ReturnPolicy_RETURN_BUFFER;
+	desc_cfg.cfg.host.psLocation   = Cppi_PSLoc_PS_IN_DESC;
+
+	/* Initialize the descriptors and place them into a queue. */
+	queue = Cppi_initDescriptor(&desc_cfg, &num_allocated);
+	if (queue < 0) {
+		ODP_ERR("Cppi_initDescriptor() failed: %i\n", (int32_t)queue);
+		return queue;
+	}
+
+	if (num_allocated != desc_num) {
+		ODP_ERR("Wrong number of descriptors allocated: requested: %u, allocated: %u\n",
+			desc_num, num_allocated);
+		_free_descriptors(mem_region, queue);
+		return (Qmss_QueueHnd)QMSS_LLD_EBASE;
+	}
+
+	ODP_ASSERT(Qmss_getQueueEntryCount(queue) == desc_num,
+		   "Wrong number of descriptors in queue");
+
+	return queue;
+}
+
+static void _detach_buffers(Qmss_QueueHnd queue)
+{
+	uint32_t num_bufs = Qmss_getQueueEntryCount(queue);
+	uint32_t i;
+
+	for (i = 0; i < num_bufs; i++) {
+		uint8_t *buf_ptr;
+		odp_pa_t buf_phys;
+		uint32_t buf_size;
+		odp_pa_t desc_phys = QMSS_DESC_PTR(Qmss_queuePopRaw(queue));
+		Cppi_HostDesc *desc = _odp_mem_phys_to_virt(desc_phys);
+		ODP_ASSERT(desc != NULL, "No descriptors in a pool free queue");
+
+		_cppi_desc_orig_info(desc, &buf_phys, &buf_size);
+		buf_ptr = _odp_mem_phys_to_virt(buf_phys);
+		if (buf_ptr) {
+			hplib_vmMemFree(buf_ptr, buf_size, 0);
+			_cppi_desc_orig_info_set(desc, 0, 0);
+		}
+
+		/* Push this descriptor into the corresponding queue */
+		Qmss_queuePushDescSizeRaw(queue, (void *)desc_phys, 16);
+	}
+}
+
+static int _attach_buffers(Qmss_QueueHnd queue,
+			   uint32_t buf_size,
+			   uint32_t buf_align,
+			   int buf_type,
+			   int pool_id)
+{
+	uint32_t num_bufs = Qmss_getQueueEntryCount(queue);
+	uint32_t i;
+
+	if (num_bufs == 0)
+		return -1;
+
+	for (i = 0; i < num_bufs; i++) {
+		uint8_t *buf_ptr;
+		odp_pa_t buf_phys;
+		/* Pop a descriptor of the free queue. */
+		odp_pa_t desc_phys = QMSS_DESC_PTR(Qmss_queuePopRaw(queue));
+		Cppi_HostDesc *desc = _odp_mem_phys_to_virt(desc_phys);
+		ODP_ASSERT(desc != NULL, "No descriptors in a pool free queue");
+
+		/* Allocate memory for the data buffer. */
+		buf_ptr = hplib_vmMemAlloc(buf_size, buf_align, 0);
+		if (buf_ptr == NULL) {
+			/* Return descriptor to a queue and detach buffers */
+			Qmss_queuePushDescSizeRaw(queue, (void *)desc_phys, 16);
+			_detach_buffers(queue);
+			return -1;
+		}
+
+		buf_phys = _odp_mem_virt_to_phys(buf_ptr);
+		/* Set the original buffer information in the descriptor. */
+		_cppi_desc_orig_info_set(desc, buf_phys, buf_size);
+
+		/* Set the data and payload length into the packet. */
+		_cppi_desc_buf_info_set(desc, buf_phys, buf_size);
+
+		_cppi_desc_pkt_type_set(desc, buf_type);
+		_cppi_desc_pool_id_set(desc, pool_id);
+
+		/* Push this descriptor into the corresponding queue */
+		Qmss_queuePushDescSizeRaw(queue, (void *)desc_phys, 16);
+	}
+
+	return 0;
+}
+
+Qmss_QueueHnd _odp_pool_get_free_queue(odp_pool_t pool)
+{
+	pool_entry_t *entry = _odp_pool_entry(pool);
+	return entry->free_queue;
+}
+
+static int _odp_buffer_pool_init(pool_entry_t *entry)
+{
+	uint32_t buf_align = entry->orig_params.buf.align;
+	uint32_t buf_size  = entry->orig_params.buf.size;
+
+	/* Set correct alignment based on input request */
+	if (buf_align == 0)
+		buf_align = ODP_CACHE_LINE_SIZE;
+	else if (buf_align < ODP_CONFIG_BUFFER_ALIGN_MIN)
+		buf_align = ODP_CONFIG_BUFFER_ALIGN_MIN;
+	else if (buf_align > ODP_CONFIG_BUFFER_ALIGN_MAX)
+		return -1;
+
+	if (buf_size > ODP_CONFIG_PACKET_SEG_LEN_MAX)
+		return -1;
+
+	entry->headroom = _ODP_BUFHDR_SIZE;
+	entry->tailroom = 0;
+
+	buf_size += entry->headroom;
+	buf_size  = ODP_CACHE_LINE_SIZE_ROUNDUP(buf_size);
+
+	entry->buf_size = buf_size;
+	entry->buf_align = buf_align;
+
+	if (_attach_buffers(entry->free_queue,
+			    buf_size,
+			    buf_align,
+			    entry->orig_params.type,
+			    entry->id)) {
+		return -1;
+	}
+
+	return 0;
+}
+
+odp_pool_t odp_pool_create(const char *name,
+					 odp_shm_t shm,
+					 odp_pool_param_t *params)
+{
+	uint32_t num_bufs;
+	pool_entry_t *entry;
+	static const char anon_name[] = "anonymous";
+	int ret = 0;
+
+	if (params == NULL)
+		return ODP_POOL_INVALID;
+
+	if (shm != ODP_SHM_INVALID) {
+		ODP_ERR("Pool from user memory is not yet supported\n");
+		return ODP_POOL_INVALID;
+	}
+
+	entry = find_free_pool_entry_locked();
+	if (entry == NULL)
+		return ODP_POOL_INVALID;
+
+	entry->flags.all = 0;
+	entry->flags.allocated = 1;
+
+	if (name == NULL) {
+		entry->name[0] = 0;
+		name = anon_name;
+	} else {
+		strncpy(entry->name, name, ODP_POOL_NAME_LEN - 1);
+		entry->name[ODP_POOL_NAME_LEN - 1] = 0;
+		entry->flags.has_name = 1;
+	}
+
+	num_bufs = params->buf.num;
+	if (num_bufs > MAX_BUFS_PER_POOL) {
+		odp_pr_dbg("Limiting number of buffer in %s from %d to %d\n",
+			   name, num_bufs, MAX_BUFS_PER_POOL);
+		num_bufs = MAX_BUFS_PER_POOL;
+	}
+
+	entry->free_queue = _alloc_descriptors(
+					odp_global->public_desc_memregion,
+					num_bufs);
+	if (entry->free_queue < 0) {
+		entry->flags.allocated = 0;
+		POOL_UNLOCK(&entry->lock);
+		return ODP_POOL_INVALID;
+	}
+
+	memcpy(&entry->orig_params, params, sizeof(entry->orig_params));
+	entry->num_bufs = num_bufs;
+
+	switch (params->type) {
+	case ODP_POOL_BUFFER:
+		ret = _odp_buffer_pool_init(entry);
+		break;
+	case ODP_POOL_PACKET:
+		ret = -1;
+		break;
+	case ODP_POOL_TIMEOUT:
+		ret = -1;
+		break;
+	default:
+		ODP_ERR("Wrong pool type\n");
+		ret = -1;
+	}
+	if (ret) {
+		_free_descriptors(odp_global->public_desc_memregion,
+				  entry->free_queue);
+		entry->flags.allocated = 0;
+		POOL_UNLOCK(&entry->lock);
+		return ODP_POOL_INVALID;
+	}
+
+	POOL_UNLOCK(&entry->lock);
+	return _odp_pool_from_entry(entry);
+}
+
+int odp_pool_destroy(odp_pool_t pool)
+{
+	pool_entry_t *entry = _odp_pool_entry(pool);
+
+	if (entry == NULL)
+		return -1;
+
+	POOL_LOCK(&entry->lock);
+
+	/* Call fails if pool is not allocated or predefined*/
+	if (!entry->flags.allocated || entry->flags.predefined) {
+		POOL_UNLOCK(&entry->lock);
+		return -1;
+	}
+
+	if (Qmss_getQueueEntryCount(entry->free_queue) != entry->num_bufs) {
+		ODP_ERR("Not all buffers are returned to the pool\n");
+		POOL_UNLOCK(&entry->lock);
+		return -1;
+	}
+
+	_detach_buffers(entry->free_queue);
+	_free_descriptors(odp_global->public_desc_memregion,
+			  entry->free_queue);
+
+	POOL_UNLOCK(&entry->lock);
+	return 0;
+}
+odp_pool_t odp_pool_lookup(const char *name)
+{
+	uint32_t i;
+	pool_entry_t *entry;
+
+	for (i = 0; i < ODP_CONFIG_POOLS; i++) {
+		entry = _odp_pool_id_to_entry(i);
+
+		POOL_LOCK(&entry->lock);
+		if (strcmp(name, entry->name) == 0) {
+			/* found it */
+			POOL_UNLOCK(&entry->lock);
+			return _odp_pool_from_entry(entry);
+		}
+		POOL_UNLOCK(&entry->lock);
+	}
+	return ODP_POOL_INVALID;
+}
+
+int odp_pool_info(odp_pool_t pool,
+			 odp_pool_info_t *info)
+{
+	pool_entry_t *entry = _odp_pool_entry(pool);
+
+	if (entry == NULL || info == NULL)
+		return -1;
+
+	info->name = entry->name;
+	info->shm  = ODP_SHM_INVALID;
+	memcpy(&info->params, &entry->orig_params, sizeof(entry->orig_params));
+
+	return 0;
+}
+
+static const char *_odp_buffer_type_string(int type)
+{
+	switch (type) {
+	case ODP_POOL_BUFFER:
+		return "buffer";
+	case ODP_POOL_PACKET:
+		return "packet";
+	case ODP_POOL_TIMEOUT:
+		return "timeout";
+	default:
+		return "invalid";
+	}
+}
+
+static uint32_t _odp_pool_available_bufs(odp_pool_t pool)
+{
+	pool_entry_t *entry = _odp_pool_entry(pool);
+	return Qmss_getQueueEntryCount(entry->free_queue);
+}
+
+void odp_pool_print(odp_pool_t pool)
+{
+	pool_entry_t *entry = _odp_pool_entry(pool);
+
+	if (!entry)
+		return;
+
+	ODP_PRINT("Pool info\n");
+	ODP_PRINT("---------\n");
+	ODP_PRINT(" pool            %p\n", pool);
+	ODP_PRINT(" pool_id         %i\n", _odp_pool_id(pool));
+	ODP_PRINT(" name            %s\n",
+		  entry->flags.has_name ? entry->name : "Unnamed Pool");
+	ODP_PRINT(" pool type       %s\n",
+		  _odp_buffer_type_string(entry->orig_params.type));
+	ODP_PRINT(" buf size        %u requested, %u used\n",
+		  entry->orig_params.buf.size, entry->buf_size);
+	ODP_PRINT(" buf align       %u requested, %u used\n",
+		  entry->orig_params.buf.align, entry->buf_align);
+	ODP_PRINT(" num_bufs        %u requested, %u used\n",
+		  entry->orig_params.buf.num, entry->num_bufs);
+	ODP_PRINT(" bufs available  %u\n", _odp_pool_available_bufs(pool));
+}
+
+static Cppi_FlowHnd _create_cppi_flow(Qmss_QueueHnd queue, uint32_t sop_offset)
+{
+	Cppi_RxFlowCfg  rx_flow_cfg;
+	Uint8           is_alloc;
+	Qmss_Queue      tmp_queue;
+	Cppi_FlowHnd    flow;
+
+	memset(&rx_flow_cfg, 0, sizeof(Cppi_RxFlowCfg));
+
+	/* Configure Rx flow */
+	tmp_queue = Qmss_getQueueNumber(odp_global->nwal.info.defFlowQ);
+	rx_flow_cfg.rx_dest_qnum   = tmp_queue.qNum;  /* Override in PA */
+	rx_flow_cfg.rx_dest_qmgr   = tmp_queue.qMgr;
+	rx_flow_cfg.flowIdNum      = CPPI_PARAM_NOT_SPECIFIED;
+	rx_flow_cfg.rx_sop_offset  = sop_offset;
+	rx_flow_cfg.rx_ps_location = Cppi_PSLoc_PS_IN_DESC;
+	rx_flow_cfg.rx_desc_type   = Cppi_DescType_HOST;
+	rx_flow_cfg.rx_error_handling = 1;
+	rx_flow_cfg.rx_psinfo_present = 1;
+	rx_flow_cfg.rx_einfo_present  = 1;
+
+	rx_flow_cfg.rx_size_thresh0_en = 0;
+	rx_flow_cfg.rx_size_thresh1_en = 0;
+	rx_flow_cfg.rx_size_thresh2_en = 0;
+
+	rx_flow_cfg.rx_dest_tag_lo_sel = 0;
+	rx_flow_cfg.rx_dest_tag_hi_sel = 0;
+	rx_flow_cfg.rx_src_tag_lo_sel  = 0;
+	rx_flow_cfg.rx_src_tag_hi_sel  = 0;
+
+	tmp_queue = Qmss_getQueueNumber(queue);
+
+	rx_flow_cfg.rx_fdq0_sz0_qnum = tmp_queue.qNum;
+	rx_flow_cfg.rx_fdq0_sz0_qmgr = tmp_queue.qMgr;
+
+	rx_flow_cfg.rx_fdq1_qnum = tmp_queue.qNum;
+	rx_flow_cfg.rx_fdq1_qmgr = tmp_queue.qMgr;
+
+	rx_flow_cfg.rx_fdq2_qnum = tmp_queue.qNum;
+	rx_flow_cfg.rx_fdq2_qmgr = tmp_queue.qMgr;
+
+	rx_flow_cfg.rx_fdq3_qnum = tmp_queue.qNum;
+	rx_flow_cfg.rx_fdq3_qmgr = tmp_queue.qMgr;
+
+	flow = Cppi_configureRxFlow(odp_global->nwal.info.passCppiHandle,
+					 &rx_flow_cfg,
+					 &is_alloc);
+	return flow;
+}
+
+int32_t _odp_pool_cppi_flow_id(odp_pool_t pool)
+{
+	Cppi_FlowHnd flow;
+	pool_entry_t *entry = _odp_pool_entry(pool);
+	ODP_ASSERT(entry, "Invalid pool entry");
+
+	POOL_LOCK(&entry->lock);
+	if (entry->cppi_flow.handle) {
+		POOL_UNLOCK(&entry->lock);
+		return entry->cppi_flow.id;
+	}
+
+	flow = _create_cppi_flow(entry->free_queue,
+				 entry->headroom);
+	if (!flow) {
+		POOL_UNLOCK(&entry->lock);
+		return -1;
+	}
+
+	entry->cppi_flow.handle = flow;
+	entry->cppi_flow.id = Cppi_getFlowId(flow);
+	POOL_UNLOCK(&entry->lock);
+
+	return entry->cppi_flow.id;
+}
