diff --git a/platform/linux-dpdk/pktio/dpdk.c b/platform/linux-dpdk/pktio/dpdk.c
index a6e2573e5..99851c3f5 100644
--- a/platform/linux-dpdk/pktio/dpdk.c
+++ b/platform/linux-dpdk/pktio/dpdk.c
@@ -147,8 +147,7 @@ static int setup_pkt_dpdk(odp_pktio_t pktio ODP_UNUSED,
 {
 	uint8_t portid = 0;
 	struct rte_eth_dev_info dev_info;
-	pktio_ops_dpdk_data_t *pkt_dpdk =
-		odp_ops_data(pktio_entry, dpdk);
+	pktio_ops_dpdk_data_t *pkt_dpdk = NULL;
 	int i;
 
 	if (!_dpdk_netdev_is_valid(netdev)) {
@@ -157,17 +156,21 @@ static int setup_pkt_dpdk(odp_pktio_t pktio ODP_UNUSED,
 		return -1;
 	}
 
+	pkt_dpdk = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_dpdk));
 	if (odp_unlikely(pkt_dpdk == NULL)) {
 		ODP_ERR("Failed to allocate pktio_ops_dpdk_data_t struct");
 		return -1;
 	}
 
+	memset(pkt_dpdk, 0, sizeof(*pkt_dpdk));
+
 	portid = atoi(netdev);
 	pkt_dpdk->portid = portid;
 	memset(&dev_info, 0, sizeof(struct rte_eth_dev_info));
 	rte_eth_dev_info_get(portid, &dev_info);
 	if (dev_info.driver_name == NULL) {
 		ODP_DBG("No driver found for interface: %s\n", netdev);
+		odp_ops_data_free(pktio_entry);
 		return -1;
 	}
 	if (!strcmp(dev_info.driver_name, "rte_ixgbe_pmd"))
@@ -197,7 +200,7 @@ static int close_pkt_dpdk(pktio_entry_t *pktio_entry)
 	if (pktio_entry->s.state == PKTIO_STATE_STOPPED)
 		rte_eth_dev_close(pkt_dpdk->portid);
 
-	return 0;
+	return odp_ops_data_free(pktio_entry);
 }
 
 static int start_pkt_dpdk(pktio_entry_t *pktio_entry)
diff --git a/platform/linux-generic/include/odp_packet_io_internal.h b/platform/linux-generic/include/odp_packet_io_internal.h
index 7df11618e..6912b8519 100644
--- a/platform/linux-generic/include/odp_packet_io_internal.h
+++ b/platform/linux-generic/include/odp_packet_io_internal.h
@@ -43,8 +43,8 @@ typedef union pktio_entry_u pktio_entry_t;
 
 struct pktio_entry {
 	const pktio_ops_module_t *ops;	/**< Implementation specific methods */
-	uint8_t ops_data[ODP_PKTIO_ODPS_DATA_MAX_SIZE]; /**< IO operation
-							specific data */
+	void *ops_data;			/**< IO operation specific data */
+
 	/* These two locks together lock the whole pktio device */
 	odp_ticketlock_t rxl;		/**< RX ticketlock */
 	odp_ticketlock_t txl;		/**< TX ticketlock */
diff --git a/platform/linux-generic/include/odp_pktio_ops_subsystem.h b/platform/linux-generic/include/odp_pktio_ops_subsystem.h
index 42cb6d2c5..31ce9a655 100644
--- a/platform/linux-generic/include/odp_pktio_ops_subsystem.h
+++ b/platform/linux-generic/include/odp_pktio_ops_subsystem.h
@@ -87,12 +87,8 @@ typedef ODP_MODULE_CLASS(pktio_ops) {
 	odp_api_proto(pktio_ops, print) print;
 } pktio_ops_module_t;
 
-/* Maximum size of pktio specific ops data.*/
-#define ODP_PKTIO_ODPS_DATA_MAX_SIZE 80000
-
 /* Extract pktio ops data from pktio entry structure */
-#define odp_ops_data(_p, _mod) \
-	((pktio_ops_ ## _mod ## _data_t *)(uintptr_t)_p->s.ops_data)
+#define odp_ops_data(_p, _mod) _p->s.ops_data
 
 #define odp_ops_data_alloc(_p, _size)					\
 ({									\
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index 4ef111c34..7501784cb 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -934,7 +934,7 @@ static int dpdk_close(pktio_entry_t *pktio_entry)
 			rte_pktmbuf_free(pkt_dpdk->rx_cache[i].s.pkt[idx++]);
 	}
 
-	return 0;
+	return odp_ops_data_free(pktio_entry);
 }
 
 static int dpdk_pktio_init(void)
@@ -1208,8 +1208,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 		     const char *netdev,
 		     odp_pool_t pool)
 {
-	pktio_ops_dpdk_data_t *pkt_dpdk =
-		odp_ops_data(pktio_entry, dpdk);
+	pktio_ops_dpdk_data_t *pkt_dpdk = NULL;
 	struct rte_eth_dev_info dev_info;
 	struct rte_mempool *pkt_pool;
 	char pool_name[RTE_MEMPOOL_NAMESIZE];
@@ -1223,6 +1222,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 
 	if (pool == ODP_POOL_INVALID)
 		return -1;
+
 	pool_entry = pool_entry_from_hdl(pool);
 
 	if (!dpdk_netdev_is_valid(netdev)) {
@@ -1237,6 +1237,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 		dpdk_initialized = 1;
 	}
 
+	pkt_dpdk = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_dpdk));
 	if (odp_unlikely(pkt_dpdk == NULL)) {
 		ODP_ERR("Failed to allocate pktio_ops_dpdk_data_t struct");
 		return -1;
@@ -1250,6 +1251,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 
 	if (rte_eth_dev_count() == 0) {
 		ODP_ERR("No DPDK ports found\n");
+		odp_ops_data_free(pktio_entry);
 		return -1;
 	}
 
@@ -1258,6 +1260,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 	mtu = dpdk_mtu_get(pktio_entry);
 	if (mtu == 0) {
 		ODP_ERR("Failed to read interface MTU\n");
+		odp_ops_data_free(pktio_entry);
 		return -1;
 	}
 	pkt_dpdk->mtu = mtu + _ODP_ETHHDR_LEN;
@@ -1294,6 +1297,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
 	}
 	if (pkt_pool == NULL) {
 		ODP_ERR("Cannot init mbuf packet pool\n");
+		odp_ops_data_free(pktio_entry);
 		return -1;
 	}
 
diff --git a/platform/linux-generic/pktio/ipc.c b/platform/linux-generic/pktio/ipc.c
index 5ab957403..9e134c533 100644
--- a/platform/linux-generic/pktio/ipc.c
+++ b/platform/linux-generic/pktio/ipc.c
@@ -343,7 +343,7 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED,
 	char name[ODP_POOL_NAME_LEN + sizeof("_info")];
 	char tail[ODP_POOL_NAME_LEN];
 	odp_shm_t shm;
-	pktio_ops_ipc_data_t *pkt_ipc = odp_ops_data(pktio_entry, ipc);
+	pktio_ops_ipc_data_t *pkt_ipc;
 
 	ODP_STATIC_ASSERT(ODP_POOL_NAME_LEN == _RING_NAMESIZE,
 			  "mismatch pool and ring name arrays");
@@ -351,6 +351,14 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED,
 	if (strncmp(dev, "ipc", 3))
 		return -1;
 
+	pkt_ipc = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_ipc));
+	if (odp_unlikely(pkt_ipc == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_ipc_data_t struct");
+		return -1;
+	}
+
+	memset(pkt_ipc, 0, sizeof(*pkt_ipc));
+
 	odp_atomic_init_u32(&pkt_ipc->ready, 0);
 
 	pkt_ipc->rx.cache = _ring_create("ipc_rx_cache",
@@ -364,12 +372,15 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED,
 		snprintf(name, sizeof(name), "ipc:%s_info", tail);
 		IPC_ODP_DBG("lookup for name %s for pid %d\n", name, pid);
 		shm = odp_shm_import(name, pid, name);
-		if (ODP_SHM_INVALID == shm)
+		if (ODP_SHM_INVALID == shm) {
+			odp_ops_data_free(pktio_entry);
 			return -1;
+		}
 		pinfo = odp_shm_addr(shm);
 
 		if (!pinfo->master.init_done) {
 			odp_shm_free(shm);
+			odp_ops_data_free(pktio_entry);
 			return -1;
 		}
 		pkt_ipc->pinfo = pinfo;
@@ -384,6 +395,7 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED,
 				      _ODP_ISHM_EXPORT | _ODP_ISHM_LOCK);
 		if (ODP_SHM_INVALID == shm) {
 			ODP_ERR("can not create shm %s\n", name);
+			odp_ops_data_free(pktio_entry);
 			return -1;
 		}
 
@@ -396,6 +408,8 @@ static int ipc_pktio_open(odp_pktio_t id ODP_UNUSED,
 		ret = _ipc_init_master(pktio_entry, dev, pool);
 	}
 
+	if (ret)
+		odp_ops_data_free(pktio_entry);
 	return ret;
 }
 
@@ -776,7 +790,7 @@ static int ipc_close(pktio_entry_t *pktio_entry)
 	_ring_destroy(ipc_shm_name);
 	_ring_destroy("ipc_rx_cache");
 
-	return 0;
+	return odp_ops_data_free(pktio_entry);
 }
 
 static int ipc_pktio_init_global(void)
diff --git a/platform/linux-generic/pktio/loopback.c b/platform/linux-generic/pktio/loopback.c
index 60bee5913..ce36cb319 100644
--- a/platform/linux-generic/pktio/loopback.c
+++ b/platform/linux-generic/pktio/loopback.c
@@ -32,20 +32,29 @@ static int loopback_stats_reset(pktio_entry_t *pktio_entry);
 static int loopback_open(odp_pktio_t id, pktio_entry_t *pktio_entry,
 			 const char *devname, odp_pool_t pool ODP_UNUSED)
 {
-	pktio_ops_loopback_data_t *pkt_lbk =
-		odp_ops_data(pktio_entry, loopback);
+	pktio_ops_loopback_data_t *pkt_lbk = NULL;
 
 	if (strcmp(devname, "loop"))
 		return -1;
 
+	pkt_lbk = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_lbk));
+	if (odp_unlikely(pkt_lbk == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_loopback_data_t struct");
+		return -1;
+	}
+
+	memset(pkt_lbk, 0, sizeof(*pkt_lbk));
+
 	char loopq_name[ODP_QUEUE_NAME_LEN];
 
 	snprintf(loopq_name, sizeof(loopq_name), "%" PRIu64 "-pktio_loopq",
 		 odp_pktio_to_u64(id));
 	pkt_lbk->loopq = odp_queue_create(loopq_name, NULL);
 
-	if (pkt_lbk->loopq == ODP_QUEUE_INVALID)
+	if (pkt_lbk->loopq == ODP_QUEUE_INVALID) {
+		odp_ops_data_free(pktio_entry);
 		return -1;
+	}
 
 	loopback_stats_reset(pktio_entry);
 
@@ -54,10 +63,17 @@ static int loopback_open(odp_pktio_t id, pktio_entry_t *pktio_entry,
 
 static int loopback_close(pktio_entry_t *pktio_entry)
 {
+	int result = 0;
 	pktio_ops_loopback_data_t *pkt_lbk =
 		odp_ops_data(pktio_entry, loopback);
 
-	return odp_queue_destroy(pkt_lbk->loopq);
+	if (odp_queue_destroy(pkt_lbk->loopq))
+		result = -1;
+
+	if (odp_ops_data_free(pktio_entry))
+		result = -1;
+
+	return result;
 }
 
 static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
index 29c449e40..69e484162 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -209,6 +209,7 @@ static inline void netmap_close_descriptors(pktio_entry_t *pktio_entry)
 
 static int netmap_close(pktio_entry_t *pktio_entry)
 {
+	int status = 0;
 	pktio_ops_netmap_data_t *pkt_nm =
 		odp_ops_data(pktio_entry, netmap);
 
@@ -217,9 +218,17 @@ static int netmap_close(pktio_entry_t *pktio_entry)
 	if (pkt_nm->sockfd != -1 && close(pkt_nm->sockfd) != 0) {
 		__odp_errno = errno;
 		ODP_ERR("close(sockfd): %s\n", strerror(errno));
-		return -1;
+
+		status = -1;
 	}
-	return 0;
+
+	if (odp_ops_data_free(pktio_entry)) {
+		ODP_ERR("ops_data_free(netmap) failed\n");
+
+		status = -1;
+	}
+
+	return status;
 }
 
 static int netmap_link_status(pktio_entry_t *pktio_entry)
@@ -343,8 +352,7 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
 	const char *prefix;
 	uint32_t mtu;
 	uint32_t buf_size;
-	pktio_ops_netmap_data_t *pkt_nm =
-		odp_ops_data(pktio_entry, netmap);
+	pktio_ops_netmap_data_t *pkt_nm = NULL;
 	struct nm_desc *desc;
 	struct netmap_ring *ring;
 	odp_pktin_hash_proto_t hash_proto;
@@ -356,6 +364,11 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
 	if (pool == ODP_POOL_INVALID)
 		return -1;
 
+	pkt_nm = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_nm));
+	if (odp_unlikely(pkt_nm == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_netmap_data_t struct");
+		return -1;
+	}
 	/* Init pktio entry */
 	memset(pkt_nm, 0, sizeof(*pkt_nm));
 	pkt_nm->sockfd = -1;
diff --git a/platform/linux-generic/pktio/pcap.c b/platform/linux-generic/pktio/pcap.c
index 5bfaeef0e..fecd3a133 100644
--- a/platform/linux-generic/pktio/pcap.c
+++ b/platform/linux-generic/pktio/pcap.c
@@ -140,10 +140,16 @@ static int _pcapif_init_tx(pktio_ops_pcap_data_t *pcap)
 static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
 		       const char *devname, odp_pool_t pool)
 {
-	pktio_ops_pcap_data_t *pcap = odp_ops_data(pktio_entry, pcap);
+	pktio_ops_pcap_data_t *pcap = NULL;
 	int ret;
 
-	memset(pcap, 0, sizeof(pktio_ops_pcap_data_t));
+	pcap = odp_ops_data_alloc(pktio_entry, sizeof(*pcap));
+	if (odp_unlikely(pcap == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_pcap_data_t struct");
+		return -1;
+	}
+
+	memset(pcap, 0, sizeof(*pcap));
 	pcap->loop_cnt = 1;
 	pcap->loops = 1;
 	pcap->pool = pool;
@@ -162,6 +168,9 @@ static int pcapif_init(odp_pktio_t id ODP_UNUSED, pktio_entry_t *pktio_entry,
 
 	(void)pcapif_stats_reset(pktio_entry);
 
+	if (ret)
+		odp_ops_data_free(pktio_entry);
+
 	return ret;
 }
 
@@ -182,7 +191,7 @@ static int pcapif_close(pktio_entry_t *pktio_entry)
 	free(pcap->fname_rx);
 	free(pcap->fname_tx);
 
-	return 0;
+	return odp_ops_data_free(pktio_entry);
 }
 
 static int _pcapif_reopen(pktio_ops_pcap_data_t *pcap)
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index d9f85b29a..ccbe465e9 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -110,16 +110,22 @@ int sendmmsg(int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
  */
 static int sock_close(pktio_entry_t *pktio_entry)
 {
+	int result = 0;
 	pktio_ops_socket_data_t *pkt_sock =
 		odp_ops_data(pktio_entry, socket);
 
 	if (pkt_sock->sockfd != -1 && close(pkt_sock->sockfd) != 0) {
 		__odp_errno = errno;
 		ODP_ERR("close(sockfd): %s\n", strerror(errno));
-		return -1;
+		result = -1;
 	}
 
-	return 0;
+	if (odp_ops_data_free(pktio_entry)) {
+		ODP_ERR("ops_data_free(socket) failed\n");
+		result = -1;
+	}
+
+	return result;
 }
 
 /*
@@ -134,18 +140,24 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
 	struct ifreq ethreq;
 	struct sockaddr_ll sa_ll;
 	char shm_name[ODP_SHM_NAME_LEN];
-	pktio_ops_socket_data_t *pkt_sock =
-		odp_ops_data(pktio_entry, socket);
+	pktio_ops_socket_data_t *pkt_sock = NULL;
 	odp_pktio_stats_t cur_stats;
 
+	if (pool == ODP_POOL_INVALID)
+		return -1;
+
+	pkt_sock = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_sock));
+	if (odp_unlikely(pkt_sock == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_socket_data_t struct");
+		return -1;
+	}
+
 	/* Init pktio entry */
 	memset(pkt_sock, 0, sizeof(*pkt_sock));
 	/* set sockfd to -1, because a valid socked might be initialized to 0 */
 	pkt_sock->sockfd = -1;
-
-	if (pool == ODP_POOL_INVALID)
-		return -1;
 	pkt_sock->pool = pool;
+
 	snprintf(shm_name, ODP_SHM_NAME_LEN, "%s-%s", "pktio", netdev);
 	shm_name[ODP_SHM_NAME_LEN - 1] = '\0';
 
@@ -212,7 +224,6 @@ static int sock_setup_pkt(pktio_entry_t *pktio_entry, const char *netdev,
 
 error:
 	sock_close(pktio_entry);
-
 	return -1;
 }
 
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index b5c27ef4b..f752c3ffd 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -497,20 +497,25 @@ static int sock_mmap_close(pktio_entry_t *entry)
 	pktio_ops_socket_mmap_data_t
 		*const pkt_sock = odp_ops_data(entry, socket_mmap);
 	int ret;
+	int status = 0;
 
 	ret = mmap_unmap_sock(pkt_sock);
 	if (ret != 0) {
 		ODP_ERR("mmap_unmap_sock() %s\n", strerror(errno));
-		return -1;
+		status = -1;
 	}
 
 	if (pkt_sock->sockfd != -1 && close(pkt_sock->sockfd) != 0) {
 		__odp_errno = errno;
 		ODP_ERR("close(sockfd): %s\n", strerror(errno));
-		return -1;
+		status = -1;
 	}
 
-	return 0;
+	if (odp_ops_data_free(entry)) {
+		ODP_ERR("ops_data_free(sock_mmap) failed\n");
+		status = -1;
+	}
+	return status;
 }
 
 static int sock_mmap_open(odp_pktio_t id ODP_UNUSED,
@@ -520,22 +525,26 @@ static int sock_mmap_open(odp_pktio_t id ODP_UNUSED,
 	int if_idx;
 	int ret = 0;
 	odp_pktio_stats_t cur_stats;
+	pktio_ops_socket_mmap_data_t *pkt_sock;
+	int fanout = 1;
 
 	if (disable_pktio)
 		return -1;
 
-	pktio_ops_socket_mmap_data_t
-		*const pkt_sock = odp_ops_data(pktio_entry, socket_mmap);
-	int fanout = 1;
+	if (pool == ODP_POOL_INVALID)
+		return -1;
+
+	pkt_sock = odp_ops_data_alloc(pktio_entry, sizeof(*pkt_sock));
+	if (odp_unlikely(pkt_sock == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_socket_mmap_data_t struct");
+		return -1;
+	}
 
 	/* Init pktio entry */
 	memset(pkt_sock, 0, sizeof(*pkt_sock));
 	/* set sockfd to -1, because a valid socked might be initialized to 0 */
 	pkt_sock->sockfd = -1;
 
-	if (pool == ODP_POOL_INVALID)
-		return -1;
-
 	/* Store eth buffer offset for pkt buffers from this pool */
 	pkt_sock->frame_offset = 0;
 
diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c
index 5bc7481d8..d4edee7c5 100644
--- a/platform/linux-generic/pktio/tap.c
+++ b/platform/linux-generic/pktio/tap.c
@@ -92,23 +92,30 @@ static int tap_pktio_open(odp_pktio_t id ODP_UNUSED,
 	int fd, skfd, flags;
 	uint32_t mtu;
 	struct ifreq ifr;
-	pktio_ops_tap_data_t *tap = odp_ops_data(pktio_entry, tap);
+	pktio_ops_tap_data_t *tap = NULL;
 
 	if (strncmp(devname, "tap:", 4) != 0)
 		return -1;
 
+	if (pool == ODP_POOL_INVALID)
+		return -1;
+
+	tap = odp_ops_data_alloc(pktio_entry, sizeof(*tap));
+	if (odp_unlikely(tap == NULL)) {
+		ODP_ERR("Failed to allocate pktio_ops_tap_data_t struct");
+		return -1;
+	}
+
 	/* Init pktio entry */
 	memset(tap, 0, sizeof(*tap));
 	tap->fd = -1;
 	tap->skfd = -1;
 
-	if (pool == ODP_POOL_INVALID)
-		return -1;
-
 	fd = open("/dev/net/tun", O_RDWR);
 	if (fd < 0) {
 		__odp_errno = errno;
 		ODP_ERR("failed to open /dev/net/tun: %s\n", strerror(errno));
+		odp_ops_data_free(pktio_entry);
 		return -1;
 	}
 
@@ -170,6 +177,7 @@ static int tap_pktio_open(odp_pktio_t id ODP_UNUSED,
 tap_err:
 	close(fd);
 	ODP_ERR("Tap device alloc failed.\n");
+	odp_ops_data_free(pktio_entry);
 	return -1;
 }
 
@@ -252,6 +260,11 @@ static int tap_pktio_close(pktio_entry_t *pktio_entry)
 		ret = -1;
 	}
 
+	if (odp_ops_data_free(pktio_entry)) {
+		ODP_ERR("ops_data_free(tap) failed\n");
+		ret = -1;
+	}
+
 	return ret;
 }
 
