diff --git a/doc/make_constants.py b/doc/make_constants.py
index fbfde06f4c1aab6dab29f270edac4cf8b05649bc..d03f4bfeda8ef09f9b0f8594d6548ad0af8ead50 100644
--- a/doc/make_constants.py
+++ b/doc/make_constants.py
@@ -13,6 +13,7 @@ ctype = cl.command_type
 memf = cl.mem_flags
 dppe = cl.device_partition_property_ext
 ade = cl.affinity_domain_ext
+mof = cl.migrate_mem_object_flags_ext
 
 def get_extra_lines(tup):
     ext_name, pyopencl_ver = tup
@@ -132,12 +133,15 @@ const_ext_lookup = {
             getattr(ctype, "WRITE_BUFFER_RECT", None): ("CL_1.1", "0.92"),
             getattr(ctype, "COPY_BUFFER_RECT", None): ("CL_1.1", "0.92"),
             getattr(ctype, "USER", None): ("CL_1.1", "0.92"),
+            getattr(ctype, "MIGRATE_MEM_OBJECT_EXT", None): 
+            ("cl_ext_migrate_memobject", "2011.1.3"),
             },
 
         memf: {
             getattr(memf, "USE_PERSISTENT_MEM_AMD", None): 
             ("cl_amd_device_memory_flags", "2011.1"),
             },
+
         dppe: {
             getattr(dppe, "EQUALLY", None): ("cl_ext_device_fission", "2011.1"),
             getattr(dppe, "BY_COUNTS", None): ("cl_ext_device_fission", "2011.1"),
@@ -155,8 +159,11 @@ const_ext_lookup = {
             getattr(ade, "L4_CACHE", None): ("cl_ext_device_fission", "2011.1"),
             getattr(ade, "NUMA", None): ("cl_ext_device_fission", "2011.1"),
             getattr(ade, "NEXT_FISSIONABLE", None): ("cl_ext_device_fission", "2011.1"),
-            }
-        }
+            },
+
+        mof: {
+            getattr(mof, "HOST", None): ("cl_ext_migrate_memobject", "2011.1.3"),
+            },
 try:
     gl_ci = cl.gl_context_info
 except AttributeError:
diff --git a/doc/source/runtime.rst b/doc/source/runtime.rst
index 88e72140ab83ec16e60979b5cd7e4ef3bb3eacad..37c8dbc34ad22920fc506de021006644acec03a5 100644
--- a/doc/source/runtime.rst
+++ b/doc/source/runtime.rst
@@ -294,6 +294,15 @@ Memory
 
     |comparable|
 
+.. function:: enqueue_migrate_mem_object(queue, mem_objects, flags=0, wait_for=None)
+
+    :param flags: from :class:`migrate_mem_object_flags_ext`
+
+    ..versionadded:: 2011.1.3
+
+    Only available with the `cl_ext_migrate_memobject`
+    extension.
+
 Buffers
 ^^^^^^^
 
diff --git a/src/wrapper/wrap_cl.hpp b/src/wrapper/wrap_cl.hpp
index 0228e75b8edb4365a59bf2ad5c537d389306453e..041aa5457537db2e7508e69034cbd257fbb462e7 100644
--- a/src/wrapper/wrap_cl.hpp
+++ b/src/wrapper/wrap_cl.hpp
@@ -77,6 +77,16 @@
         EXTRA_MSG); \
   }
 
+#define PYOPENCL_GET_EXT_FUN(NAME, VAR) \
+    NAME##_fn VAR \
+      = (NAME##_fn) \
+      clGetExtensionFunctionAddress(#NAME); \
+    \
+    if (!VAR) \
+      throw error(#NAME, CL_INVALID_VALUE, #NAME \
+          "not available");
+
+
 // }}}
 
 // {{{ tracing and error reporting
@@ -371,15 +381,10 @@ namespace pyopencl
 #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
           if (retain)
           {
-            clRetainDeviceEXT_fn cl_retain_device
-              = (clRetainDeviceEXT_fn)
-              clGetExtensionFunctionAddress("clRetainDeviceEXT");
+            PYOPENCL_GET_EXT_FUN(
+                clRetainDeviceEXT, retain_func);
 
-            if (!cl_retain_device)
-              throw error("Device", CL_INVALID_VALUE,
-                  "clRetainDeviceEXT not available");
-
-            PYOPENCL_CALL_GUARDED(cl_retain_device, (did));
+            PYOPENCL_CALL_GUARDED(retain_func, (did));
           }
 #else
           throw error("Device", CL_INVALID_VALUE, 
@@ -393,15 +398,10 @@ namespace pyopencl
 #if defined(cl_ext_device_fission) && defined(PYOPENCL_USE_DEVICE_FISSION)
         if (m_ownable_reference)
         {
-          clReleaseDeviceEXT_fn cl_release_device
-            = (clReleaseDeviceEXT_fn)
-            clGetExtensionFunctionAddress("clReleaseDeviceEXT");
-
-          if (!cl_release_device)
-            throw error("Device", CL_INVALID_VALUE,
-                "clReleaseDeviceEXT not available");
+          PYOPENCL_GET_EXT_FUN(
+              clReleaseDeviceEXT, release_func);
 
-          PYOPENCL_CALL_GUARDED_CLEANUP(cl_release_device, (m_device));
+          PYOPENCL_CALL_GUARDED_CLEANUP(release_func, (m_device));
         }
 #endif
       }
@@ -546,13 +546,7 @@ namespace pyopencl
       {
         std::vector<cl_device_partition_property_ext> properties;
 
-        clCreateSubDevicesEXT_fn cl_create_sub_devices
-          = (clCreateSubDevicesEXT_fn)
-          clGetExtensionFunctionAddress("clCreateSubDevicesEXT");
-
-        if (!cl_create_sub_devices)
-          throw error("Device.create_sub_devices", CL_INVALID_VALUE,
-              "clCreateSubDevicesEXT not available");
+        PYOPENCL_GET_EXT_FUN(clCreateSubDevicesEXT, create_sub_dev);
 
         COPY_PY_LIST(cl_device_partition_property_ext, properties);
         properties.push_back(CL_PROPERTIES_LIST_END_EXT);
@@ -561,13 +555,13 @@ namespace pyopencl
           = properties.empty( ) ? NULL : &properties.front();
 
         cl_uint num_entries;
-        PYOPENCL_CALL_GUARDED(cl_create_sub_devices,
+        PYOPENCL_CALL_GUARDED(create_sub_dev,
             (m_device, props_ptr, 0, NULL, &num_entries));
 
         std::vector<cl_device_id> result;
         result.resize(num_entries);
 
-        PYOPENCL_CALL_GUARDED(cl_create_sub_devices,
+        PYOPENCL_CALL_GUARDED(create_sub_dev,
             (m_device, props_ptr, num_entries, &result.front(), NULL));
 
         py::list py_result;
@@ -1233,6 +1227,33 @@ namespace pyopencl
 
   };
 
+#ifdef cl_ext_migrate_memobject
+  inline
+  event *enqueue_migrate_mem_object(
+      command_queue &cq,
+      py::object py_mem_objects,
+      cl_mem_migration_flags_ext flags,
+      py::object py_wait_for)
+  {
+    PYOPENCL_PARSE_WAIT_FOR;
+    PYOPENCL_GET_EXT_FUN(
+        clEnqueueMigrateMemObjectEXT, enqueue_migrate_fn);
+
+    std::vector<cl_mem> mem_objects;
+    PYTHON_FOREACH(mo, py_mem_objects)
+      mem_objects.push_back(py::extract<memory_object &>(mo)().data());
+
+    cl_event evt;
+    PYOPENCL_CALL_GUARDED(enqueue_migrate_fn, (
+          cq.data(),
+          mem_objects.size(), mem_objects.empty( ) ? NULL : &mem_objects.front(),
+          flags,
+          num_events_in_wait_list, event_wait_list.empty( ) ? NULL : &event_wait_list.front(), &evt
+          ));
+    PYOPENCL_RETURN_NEW_EVENT(evt);
+  }
+#endif
+
   // }}}
 
   // {{{ buffer
diff --git a/src/wrapper/wrap_cl_part_1.cpp b/src/wrapper/wrap_cl_part_1.cpp
index 701b5099325437ce43674ab6e2fbe2b01c73cb9b..b4e578b4e6fe6800585b736b6c9d062bac086805 100644
--- a/src/wrapper/wrap_cl_part_1.cpp
+++ b/src/wrapper/wrap_cl_part_1.cpp
@@ -141,6 +141,14 @@ void pyopencl_expose_part_1()
       ;
   }
 
+#ifdef cl_ext_migrate_memobject
+  py::def("enqueue_migrate_mem_object", enqueue_migrate_mem_object,
+      (py::args("queue", "mem_objects"),
+       py::arg("flags")=0,
+       py::arg("wait_for")=py::object()
+       ),
+      py::return_value_policy<py::manage_new_object>());
+#endif
   // }}}
 
   // {{{ buffer
diff --git a/src/wrapper/wrap_constants.cpp b/src/wrapper/wrap_constants.cpp
index 84025b4e11b732ebb538ec9e498a953b980b3fae..321fd43f928e46147e9117f22fb814fd582e9a07 100644
--- a/src/wrapper/wrap_constants.cpp
+++ b/src/wrapper/wrap_constants.cpp
@@ -74,6 +74,7 @@ namespace
 
   class gl_object_type { };
   class gl_texture_info { };
+  class migrate_mem_object_flags {};
   // }}}
 }
 
@@ -574,6 +575,9 @@ void pyopencl_expose_constants()
     ADD_ATTR(COMMAND_, WRITE_BUFFER_RECT);
     ADD_ATTR(COMMAND_, COPY_BUFFER_RECT);
     ADD_ATTR(COMMAND_, USER);
+#endif
+#ifdef cl_ext_migrate_memobject
+    ADD_ATTR_SUFFIX(COMMAND_, MIGRATE_MEM_OBJECT, _EXT);
 #endif
   }
 
@@ -643,6 +647,13 @@ void pyopencl_expose_constants()
   }
 #endif
 
+  {
+    py::class_<migrate_mem_object_flags> cls("migrate_mem_object_flags_ext", py::no_init);
+#ifdef cl_ext_migrate_memobject
+    ADD_ATTR_SUFFIX(MIGRATE_MEM_OBJECT_, HOST, _EXT);
+#endif
+  }
+
   // }}}
 }