diff --git a/platform/linux-netmap/Makefile.am b/platform/linux-netmap/Makefile.am
index 0b08cad..98e0962 100644
--- a/platform/linux-netmap/Makefile.am
+++ b/platform/linux-netmap/Makefile.am
@@ -67,7 +67,7 @@ __LIB__libodp_la_SOURCES = \
 			   ../linux-generic/odp_classification.c \
 			   ../linux-generic/odp_coremask.c \
 			   ../linux-generic/odp_crypto.c \
-			   ../linux-generic/odp_init.c \
+			   odp_init.c \
 			   ../linux-generic/odp_linux.c \
 			   ../linux-generic/odp_packet.c \
 			   ../linux-generic/odp_packet_flags.c \
diff --git a/platform/linux-netmap/include/odp_internal.h b/platform/linux-netmap/include/odp_internal.h
new file mode 100644
index 0000000..b2592c6
--- /dev/null
+++ b/platform/linux-netmap/include/odp_internal.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+
+/**
+ * @file
+ *
+ * ODP HW system information
+ */
+
+#ifndef ODP_INTERNAL_H_
+#define ODP_INTERNAL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+int odp_system_info_init(void);
+
+int odp_thread_init_global(void);
+int odp_thread_init_local(void);
+
+int odp_shm_init_global(void);
+int odp_shm_init_local(void);
+
+int odp_buffer_pool_init_global(void);
+
+int odp_pktio_init_global(void);
+int odp_pktio_init_local(void);
+
+int odp_queue_init_global(void);
+
+int odp_crypto_init_global(void);
+
+int odp_schedule_init_global(void);
+int odp_schedule_init_local(void);
+
+int odp_timer_init_global(void);
+int odp_timer_disarm_all(void);
+
+int odp_netmap_init_global(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-netmap/odp_init.c b/platform/linux-netmap/odp_init.c
new file mode 100644
index 0000000..22c52b4
--- /dev/null
+++ b/platform/linux-netmap/odp_init.c
@@ -0,0 +1,96 @@
+/* Copyright (c) 2013, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp_init.h>
+#include <odp_internal.h>
+#include <odp_debug.h>
+#include <odp_debug_internal.h>
+
+
+int odp_init_global(odp_init_t *params  ODP_UNUSED,
+			odp_platform_init_t *platform_params ODP_UNUSED)
+{
+	odp_system_info_init();
+
+	if (odp_shm_init_global()) {
+		ODP_ERR("ODP shm init failed.\n");
+		return -1;
+	}
+
+	if (odp_thread_init_global()) {
+		ODP_ERR("ODP thread init failed.\n");
+		return -1;
+	}
+
+	if (odp_buffer_pool_init_global()) {
+		ODP_ERR("ODP buffer pool init failed.\n");
+		return -1;
+	}
+
+	if (odp_queue_init_global()) {
+		ODP_ERR("ODP queue init failed.\n");
+		return -1;
+	}
+
+	if (odp_schedule_init_global()) {
+		ODP_ERR("ODP schedule init failed.\n");
+		return -1;
+	}
+
+	if (odp_pktio_init_global()) {
+		ODP_ERR("ODP packet io init failed.\n");
+		return -1;
+	}
+
+	if (odp_timer_init_global()) {
+		ODP_ERR("ODP timer init failed.\n");
+		return -1;
+	}
+
+	if (odp_crypto_init_global()) {
+		ODP_ERR("ODP crypto init failed.\n");
+		return -1;
+	}
+
+	if (odp_netmap_init_global()) {
+		ODP_ERR("ODP netmap global init failed.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int odp_term_global(void)
+{
+	ODP_UNIMPLEMENTED();
+	return 0;
+}
+
+int odp_init_local(void)
+{
+	if (odp_thread_init_local()) {
+		ODP_ERR("ODP thread local init failed.\n");
+		return -1;
+	}
+
+	if (odp_pktio_init_local()) {
+		ODP_ERR("ODP packet io local init failed.\n");
+		return -1;
+	}
+
+	if (odp_schedule_init_local()) {
+		ODP_ERR("ODP schedule local init failed.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int odp_term_local(void)
+{
+	ODP_UNIMPLEMENTED();
+	return 0;
+}
diff --git a/platform/linux-netmap/odp_packet_netmap.c b/platform/linux-netmap/odp_packet_netmap.c
index 6243040..936c9b7 100644
--- a/platform/linux-netmap/odp_packet_netmap.c
+++ b/platform/linux-netmap/odp_packet_netmap.c
@@ -27,6 +27,7 @@
 #include <linux/ethtool.h>
 #include <linux/sockios.h>
 
+#include <odp_internal.h>
 #include <odp_packet_internal.h>
 #include <odp_hints.h>
 #include <odp_thread.h>
@@ -54,6 +55,17 @@
 #define WAITLINK_TMO 2
 #define POLL_TMO     50
 
+static struct nm_desc mmap_desc;	/** Used to store the mmap address;
+					  filled in first time, used for
+					  subsequent calls to nm_open */
+static odp_spinlock_t mmap_desc_lock;
+
+int odp_netmap_init_global(void)
+{
+	odp_spinlock_init(&mmap_desc_lock);
+	return 0;
+}
+
 static int nm_do_ioctl(pkt_netmap_t * const pkt_nm, unsigned long cmd,
 		       int subcmd)
 {
@@ -134,13 +146,30 @@ int setup_pkt_netmap(pkt_netmap_t * const pkt_nm, const char *netdev,
 
 	strncpy(pkt_nm->ifname, netdev, sizeof(pkt_nm->ifname));
 	snprintf(ifname, sizeof(ifname), "netmap:%s", netdev);
-	pkt_nm->nm_desc = nm_open(ifname, NULL, 0, 0);
+
+	odp_spinlock_lock(&mmap_desc_lock);
+	ODP_DBG("[%04d] Initial mmap addr: %p\n",
+		odp_thread_id(),
+		mmap_desc.mem);
+
+	if (mmap_desc.mem == NULL)
+		pkt_nm->nm_desc = nm_open(ifname, NULL, 0, NULL);
+	else
+		pkt_nm->nm_desc = nm_open(ifname, NULL, NM_OPEN_NO_MMAP,
+					  &mmap_desc);
 
 	if (pkt_nm->nm_desc == NULL) {
 		ODP_ERR("Error opening nm interface: %s\n", strerror(errno));
+		odp_spinlock_unlock(&mmap_desc_lock);
 		return -1;
 	}
 
+	if (mmap_desc.mem == NULL) {
+		mmap_desc.mem = pkt_nm->nm_desc->mem;
+		mmap_desc.memsize = pkt_nm->nm_desc->memsize;
+	}
+	odp_spinlock_unlock(&mmap_desc_lock);
+
 	ODP_DBG("thread %d mmap addr %p\n",
 		odp_thread_id(),
 		pkt_nm->nm_desc->mem);
