diff --git a/Foreign/CUDA/Analysis/Device.chs b/Foreign/CUDA/Analysis/Device.chs
--- a/Foreign/CUDA/Analysis/Device.chs
+++ b/Foreign/CUDA/Analysis/Device.chs
@@ -150,6 +150,7 @@
       Compute 2 0 -> DeviceResources 32 1536  8 48  32 49152 128 32768  64 2  63 Warp   -- Fermi GF100
       Compute 2 1 -> DeviceResources 32 1536  8 48  48 49152 128 32768  64 2  63 Warp   -- Fermi GF10x
       Compute 3 0 -> DeviceResources 32 2048 16 64 192 49152 256 65536 256 4  63 Warp   -- Kepler GK10x
+      Compute 3 2 -> DeviceResources 32 2048 16 64 192 49152 256 65536 256 4 255 Warp   -- Jetson TK1 (speculative)
       Compute 3 5 -> DeviceResources 32 2048 16 64 192 49152 256 65536 256 4 255 Warp   -- Kepler GK11x
       Compute 5 0 -> DeviceResources 32 2048 32 64 128 65536 256 65536 256 4 255 Warp   -- Maxwell GM10x
 
@@ -162,6 +163,6 @@
       -- is likely the user code is as well.
       --
       _           -> trace warning $ resources (Compute 3 0)
-        where warning = unlines [ "*** Warning: unknown CUDA device compute capability: " ++ show compute
+        where warning = unlines [ "*** Warning: Unknown CUDA device compute capability: " ++ show compute
                                 , "*** Please submit a bug report at https://github.com/tmcdonell/cuda/issues" ]
 
diff --git a/Foreign/CUDA/Driver/Marshal.chs b/Foreign/CUDA/Driver/Marshal.chs
--- a/Foreign/CUDA/Driver/Marshal.chs
+++ b/Foreign/CUDA/Driver/Marshal.chs
@@ -27,9 +27,9 @@
   mallocManagedArray,
 
   -- * Marshalling
-  peekArray, peekArrayAsync, peekListArray,
-  pokeArray, pokeArrayAsync, pokeListArray,
-  copyArrayAsync,
+  peekArray, peekArrayAsync, peekArray2D, peekArray2DAsync, peekListArray,
+  pokeArray, pokeArrayAsync, pokeArray2D, pokeArray2DAsync, pokeListArray,
+  copyArray, copyArrayAsync, copyArray2D, copyArray2DAsync,
   copyArrayPeer, copyArrayPeerAsync,
 
   -- * Combined Allocation and Marshalling
@@ -284,6 +284,9 @@
 -- Marshalling
 --------------------------------------------------------------------------------
 
+-- Device -> Host
+-- --------------
+
 -- |
 -- Copy a number of elements from the device to host memory. This is a
 -- synchronous operation
@@ -324,6 +327,105 @@
 
 
 -- |
+-- Copy a 2D array from the device to the host.
+--
+{-# INLINEABLE peekArray2D #-}
+peekArray2D
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Int                      -- ^ source x-coordinate
+    -> Int                      -- ^ source y-coordinate
+    -> Ptr a                    -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Int                      -- ^ destination x-coordinate
+    -> Int                      -- ^ destination y-coordinate
+    -> IO ()
+peekArray2D !w !h !dptr !dw !dx !dy !hptr !hw !hx !hy = doPeek undefined dptr
+  where
+    doPeek :: Storable a' => a' -> DevicePtr a' -> IO ()
+    doPeek x _ =
+      let bytes = sizeOf x
+          w'    = w  * bytes
+          hw'   = hw * bytes
+          hx'   = hx * bytes
+          dw'   = dw * bytes
+          dx'   = dx * bytes
+      in
+      nothingIfOk =<< cuMemcpy2DDtoH hptr hw' hx' hy dptr dw' dx' dy w' h
+
+{-# INLINE cuMemcpy2DDtoH #-}
+{# fun unsafe cuMemcpy2DDtoH
+  { castPtr         `Ptr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  }
+  -> `Status' cToEnum #}
+
+
+-- |
+-- Copy a 2D array from the device to the host asynchronously, possibly
+-- associated with a particular execution stream. The destination host memory
+-- must be page-locked.
+--
+{-# INLINEABLE peekArray2DAsync #-}
+peekArray2DAsync
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Int                      -- ^ source x-coordinate
+    -> Int                      -- ^ source y-coordinate
+    -> HostPtr a                -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Int                      -- ^ destination x-coordinate
+    -> Int                      -- ^ destination y-coordinate
+    -> Maybe Stream             -- ^ stream to associate to
+    -> IO ()
+peekArray2DAsync !w !h !dptr !dw !dx !dy !hptr !hw !hx !hy !mst = doPeek undefined dptr
+  where
+    doPeek :: Storable a' => a' -> DevicePtr a' -> IO ()
+    doPeek x _ =
+      let bytes = sizeOf x
+          w'    = w  * bytes
+          hw'   = hw * bytes
+          hx'   = hx * bytes
+          dw'   = dw * bytes
+          dx'   = dx * bytes
+          st    = fromMaybe (Stream nullPtr) mst
+      in
+      nothingIfOk =<< cuMemcpy2DDtoHAsync hptr hw' hx' hy dptr dw' dx' dy w' h st
+
+{-# INLINE cuMemcpy2DDtoHAsync #-}
+{# fun unsafe cuMemcpy2DDtoHAsync
+  { useHP           `HostPtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useStream       `Stream'
+  }
+  -> `Status' cToEnum #}
+  where
+    useHP = castPtr . useHostPtr
+
+
+-- |
 -- Copy a number of elements from the device into a new Haskell list. Note that
 -- this requires two memory copies: firstly from the device into a heap
 -- allocated array, and from there marshalled into a list.
@@ -336,6 +438,9 @@
     F.peekArray n p
 
 
+-- Host -> Device
+-- --------------
+
 -- |
 -- Copy a number of elements onto the device. This is a synchronous operation
 --
@@ -375,6 +480,105 @@
 
 
 -- |
+-- Copy a 2D array from the host to the device.
+--
+{-# INLINEABLE pokeArray2D #-}
+pokeArray2D
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> Ptr a                    -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Int                      -- ^ source x-coordinate
+    -> Int                      -- ^ source y-coordinate
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Int                      -- ^ destination x-coordinate
+    -> Int                      -- ^ destination y-coordinate
+    -> IO ()
+pokeArray2D !w !h !hptr !hw !hx !hy !dptr !dw !dx !dy = doPoke undefined dptr
+  where
+    doPoke :: Storable a' => a' -> DevicePtr a' -> IO ()
+    doPoke x _ =
+      let bytes = sizeOf x
+          w'    = w  * bytes
+          hw'   = hw * bytes
+          hx'   = hx * bytes
+          dw'   = dw * bytes
+          dx'   = dx * bytes
+      in
+      nothingIfOk =<< cuMemcpy2DHtoD dptr dw' dx' dy hptr hw' hx' hy w' h
+
+{-# INLINE cuMemcpy2DHtoD #-}
+{# fun unsafe cuMemcpy2DHtoD
+  { useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , castPtr         `Ptr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  }
+  -> `Status' cToEnum #}
+
+
+-- |
+-- Copy a 2D array from the host to the device asynchronously, possibly
+-- associated with a particular execution stream. The source host memory must be
+-- page-locked.
+--
+{-# INLINEABLE pokeArray2DAsync #-}
+pokeArray2DAsync
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> HostPtr a                -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Int                      -- ^ source x-coordinate
+    -> Int                      -- ^ source y-coordinate
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Int                      -- ^ destination x-coordinate
+    -> Int                      -- ^ destination y-coordinate
+    -> Maybe Stream             -- ^ stream to associate to
+    -> IO ()
+pokeArray2DAsync !w !h !hptr !hw !hx !hy !dptr !dw !dx !dy !mst = doPoke undefined dptr
+  where
+    doPoke :: Storable a' => a' -> DevicePtr a' -> IO ()
+    doPoke x _ =
+      let bytes = sizeOf x
+          w'    = w  * bytes
+          hw'   = hw * bytes
+          hx'   = hx * bytes
+          dw'   = dw * bytes
+          dx'   = dx * bytes
+          st    = fromMaybe (Stream nullPtr) mst
+      in
+      nothingIfOk =<< cuMemcpy2DHtoDAsync dptr dw' dx' dy hptr hw' hx' hy w' h st
+
+{-# INLINE cuMemcpy2DHtoDAsync #-}
+{# fun unsafe cuMemcpy2DHtoDAsync
+  { useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useHP           `HostPtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useStream       `Stream'
+  }
+  -> `Status' cToEnum #}
+  where
+    useHP = castPtr . useHostPtr
+
+
+-- |
 -- Write a list of storable elements into a device array. The device array must
 -- be sufficiently large to hold the entire list. This requires two marshalling
 -- operations.
@@ -384,15 +588,18 @@
 pokeListArray !xs !dptr = F.withArrayLen xs $ \ !len !p -> pokeArray len p dptr
 
 
+-- Device -> Device
+-- ----------------
+
 -- |
 -- Copy the given number of elements from the first device array (source) to the
--- second (destination). The copied areas may not overlap. This operation is
--- asynchronous with respect to the host, but will never overlap with kernel
+-- second device (destination). The copied areas may not overlap. This operation
+-- is asynchronous with respect to the host, but will never overlap with kernel
 -- execution.
 --
-{-# INLINEABLE copyArrayAsync #-}
-copyArrayAsync :: Storable a => Int -> DevicePtr a -> DevicePtr a -> IO ()
-copyArrayAsync !n = docopy undefined
+{-# INLINEABLE copyArray #-}
+copyArray :: Storable a => Int -> DevicePtr a -> DevicePtr a -> IO ()
+copyArray !n = docopy undefined
   where
     docopy :: Storable a' => a' -> DevicePtr a' -> DevicePtr a' -> IO ()
     docopy x src dst = nothingIfOk =<< cuMemcpyDtoD dst src (n * sizeOf x)
@@ -403,6 +610,132 @@
   , useDeviceHandle `DevicePtr a'
   ,                 `Int'         } -> `Status' cToEnum #}
 
+
+-- |
+-- Copy the given number of elements from the first device array (source) to the
+-- second device array (destination). The copied areas may not overlap. The
+-- operation is asynchronous with respect to the host, and can be asynchronous
+-- to other device operations by associating it with a particular stream.
+--
+{-# INLINEABLE copyArrayAsync #-}
+copyArrayAsync :: Storable a => Int -> DevicePtr a -> DevicePtr a -> Maybe Stream -> IO ()
+copyArrayAsync !n !src !dst !mst = docopy undefined src
+  where
+    docopy :: Storable a' => a' -> DevicePtr a' -> IO ()
+    docopy x _ = nothingIfOk =<< cuMemcpyDtoDAsync dst src (n * sizeOf x) (fromMaybe (Stream nullPtr) mst)
+
+{-# INLINE cuMemcpyDtoDAsync #-}
+{# fun unsafe cuMemcpyDtoDAsync
+  { useDeviceHandle `DevicePtr a'
+  , useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  , useStream       `Stream'      } -> `Status' cToEnum #}
+
+
+-- |
+-- Copy a 2D array from the first device array (source) to the second device
+-- array (destination). The copied areas must not overlap. This operation is
+-- asynchronous with respect to the host, but will never overlap with kernel
+-- execution.
+--
+{-# INLINEABLE copyArray2D #-}
+copyArray2D
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Int                      -- ^ source x-coordinate
+    -> Int                      -- ^ source y-coordinate
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Int                      -- ^ destination x-coordinate
+    -> Int                      -- ^ destination y-coordinate
+    -> IO ()
+copyArray2D !w !h !src !hw !hx !hy !dst !dw !dx !dy = doCopy undefined dst
+  where
+    doCopy :: Storable a' => a' -> DevicePtr a' -> IO ()
+    doCopy x _ =
+      let bytes = sizeOf x
+          w'    = w  * bytes
+          hw'   = hw * bytes
+          hx'   = hx * bytes
+          dw'   = dw * bytes
+          dx'   = dx * bytes
+      in
+      nothingIfOk =<< cuMemcpy2DDtoD dst dw' dx' dy src hw' hx' hy w' h
+
+{-# INLINE cuMemcpy2DDtoD #-}
+{# fun unsafe cuMemcpy2DDtoD
+  { useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  }
+  -> `Status' cToEnum #}
+
+
+-- |
+-- Copy a 2D array from the first device array (source) to the second device
+-- array (destination). The copied areas may not overlap. The operation is
+-- asynchronous with respect to the host, and can be asynchronous to other
+-- device operations by associating it with a particular execution stream.
+--
+{-# INLINEABLE copyArray2DAsync #-}
+copyArray2DAsync
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Int                      -- ^ source x-coordinate
+    -> Int                      -- ^ source y-coordinate
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Int                      -- ^ destination x-coordinate
+    -> Int                      -- ^ destination y-coordinate
+    -> Maybe Stream             -- ^ stream to associate to
+    -> IO ()
+copyArray2DAsync !w !h !src !hw !hx !hy !dst !dw !dx !dy !mst = doCopy undefined dst
+  where
+    doCopy :: Storable a' => a' -> DevicePtr a' -> IO ()
+    doCopy x _ =
+      let bytes = sizeOf x
+          w'    = w  * bytes
+          hw'   = hw * bytes
+          hx'   = hx * bytes
+          dw'   = dw * bytes
+          dx'   = dx * bytes
+          st    = fromMaybe (Stream nullPtr) mst
+      in
+      nothingIfOk =<< cuMemcpy2DDtoDAsync dst dw' dx' dy src hw' hx' hy w' h st
+
+{-# INLINE cuMemcpy2DDtoDAsync #-}
+{# fun unsafe cuMemcpy2DDtoDAsync
+  { useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useDeviceHandle `DevicePtr a'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  ,                 `Int'
+  , useStream       `Stream'
+  }
+  -> `Status' cToEnum #}
+
+
+
+-- Context -> Context
+-- ------------------
 
 -- |
 -- Copies an array from device memory in one context to device memory in another
diff --git a/Foreign/CUDA/Runtime/Marshal.chs b/Foreign/CUDA/Runtime/Marshal.chs
--- a/Foreign/CUDA/Runtime/Marshal.chs
+++ b/Foreign/CUDA/Runtime/Marshal.chs
@@ -25,9 +25,9 @@
   mallocManagedArray,
 
   -- * Marshalling
-  peekArray, peekArrayAsync, peekListArray,
-  pokeArray, pokeArrayAsync, pokeListArray,
-  copyArray, copyArrayAsync,
+  peekArray, peekArrayAsync, peekArray2D, peekArray2DAsync, peekListArray,
+  pokeArray, pokeArrayAsync, pokeArray2D, pokeArray2DAsync, pokeListArray,
+  copyArray, copyArrayAsync, copyArray2D, copyArray2DAsync,
 
   -- * Combined Allocation and Marshalling
   newListArray,  newListArrayLen,
@@ -49,6 +49,7 @@
 
 -- System
 import Data.Int
+import Data.Maybe
 import Control.Exception
 
 import Foreign.C
@@ -246,6 +247,44 @@
 
 
 -- |
+-- Copy a 2D memory area from the device to the host. This is a synchronous
+-- operation.
+--
+{-# INLINEABLE peekArray2D #-}
+peekArray2D
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> Ptr a                    -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> IO ()
+peekArray2D !w !h !dptr !dw !hptr !hw =
+  memcpy2D hptr hw (useDevicePtr dptr) dw w h DeviceToHost
+
+
+-- |
+-- Copy a 2D memory area from the device to the host asynchronously, possibly
+-- associated with a particular stream. The destination array must be page
+-- locked.
+--
+{-# INLINEABLE peekArray2DAsync #-}
+peekArray2DAsync
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> HostPtr a                -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Maybe Stream
+    -> IO ()
+peekArray2DAsync !w !h !dptr !dw !hptr !hw !mst =
+  memcpy2DAsync (useHostPtr hptr) hw (useDevicePtr dptr) dw w h DeviceToHost mst
+
+
+-- |
 -- Copy a number of elements from the device into a new Haskell list. Note that
 -- this requires two memory copies: firstly from the device into a heap
 -- allocated array, and from there marshalled into a list
@@ -277,6 +316,41 @@
 
 
 -- |
+-- Copy a 2D memory area onto the device. This is a synchronous operation.
+--
+{-# INLINEABLE pokeArray2D #-}
+pokeArray2D
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> Ptr a                    -- ^ source array
+    -> Int                      -- ^ source array width
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> IO ()
+pokeArray2D !w !h !hptr !dw !dptr !hw =
+  memcpy2D (useDevicePtr dptr) dw hptr hw w h HostToDevice
+
+
+-- |
+-- Copy a 2D memory area onto the device asynchronously, possibly associated
+-- with a particular stream. The source array must be page locked.
+--
+{-# INLINEABLE pokeArray2DAsync #-}
+pokeArray2DAsync
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> HostPtr a                -- ^ source array
+    -> Int                      -- ^ source array width
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Maybe Stream
+    -> IO ()
+pokeArray2DAsync !w !h !hptr !hw !dptr !dw !mst =
+  memcpy2DAsync (useDevicePtr dptr) dw (useHostPtr hptr) hw w h HostToDevice mst
+
+-- |
 -- Write a list of storable elements into a device array. The array must be
 -- sufficiently large to hold the entire list. This requires two marshalling
 -- operations
@@ -288,8 +362,9 @@
 
 -- |
 -- Copy the given number of elements from the first device array (source) to the
--- second (destination). The copied areas may not overlap. This is a synchronous
--- operation.
+-- second (destination). The copied areas may not overlap. This operation is
+-- asynchronous with respect to host, but will not overlap other device
+-- operations.
 --
 {-# INLINEABLE copyArray #-}
 copyArray :: Storable a => Int -> DevicePtr a -> DevicePtr a -> IO ()
@@ -299,8 +374,8 @@
 -- |
 -- Copy the given number of elements from the first device array (source) to the
 -- second (destination). The copied areas may not overlap. This operation is
--- asynchronous with respect to host, but will never overlap with kernel
--- execution.
+-- asynchronous with respect to the host, and may be associated with a
+-- particular stream.
 --
 {-# INLINEABLE copyArrayAsync #-}
 copyArrayAsync :: Storable a => Int -> DevicePtr a -> DevicePtr a -> Maybe Stream -> IO ()
@@ -308,7 +383,48 @@
   memcpyAsync (useDevicePtr dst) (useDevicePtr src) n DeviceToDevice mst
 
 
+-- |
+-- Copy a 2D memory area from the first device array (source) to the second
+-- (destination). The copied areas may not overlap. This operation is
+-- asynchronous with respect to the host, but will not overlap other device
+-- operations.
 --
+{-# INLINEABLE copyArray2D #-}
+copyArray2D
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> IO ()
+copyArray2D !w !h !src !sw !dst !dw =
+  memcpy2D (useDevicePtr dst) dw (useDevicePtr src) sw w h DeviceToDevice
+
+
+-- |
+-- Copy a 2D memory area from the first device array (source) to the second
+-- device array (destination). The copied areas may not overlay. This operation
+-- is asynchronous with respect to the host, and may be associated with a
+-- particular stream.
+--
+{-# INLINEABLE copyArray2DAsync #-}
+copyArray2DAsync
+    :: Storable a
+    => Int                      -- ^ width to copy (elements)
+    -> Int                      -- ^ height to copy (elements)
+    -> DevicePtr a              -- ^ source array
+    -> Int                      -- ^ source array width
+    -> DevicePtr a              -- ^ destination array
+    -> Int                      -- ^ destination array width
+    -> Maybe Stream
+    -> IO ()
+copyArray2DAsync !w !h !src !sw !dst !dw !mst =
+  memcpy2DAsync (useDevicePtr dst) dw (useDevicePtr src) sw w h DeviceToDevice mst
+
+
+--
 -- Memory copy kind
 --
 {# enum cudaMemcpyKind as CopyDirection {}
@@ -356,7 +472,7 @@
     doMemcpy :: Storable a' => a' -> Ptr a' -> IO ()
     doMemcpy x _ =
       let bytes = fromIntegral n * fromIntegral (sizeOf x) in
-      nothingIfOk =<< cudaMemcpyAsync dst src bytes kind (maybe defaultStream id mst)
+      nothingIfOk =<< cudaMemcpyAsync dst src bytes kind (fromMaybe defaultStream mst)
 
 {-# INLINE cudaMemcpyAsync #-}
 {# fun unsafe cudaMemcpyAsync
@@ -365,6 +481,88 @@
   , cIntConv  `Int64'
   , cFromEnum `CopyDirection'
   , useStream `Stream'        } -> `Status' cToEnum #}
+
+
+-- |
+-- Copy a 2D memory area between the host and device. This is a synchronous
+-- operation.
+--
+{-# INLINEABLE memcpy2D #-}
+memcpy2D :: Storable a
+         => Ptr a               -- ^ destination
+         -> Int                 -- ^ width of destination array
+         -> Ptr a               -- ^ source
+         -> Int                 -- ^ width of source array
+         -> Int                 -- ^ width to copy
+         -> Int                 -- ^ height to copy
+         -> CopyDirection
+         -> IO ()
+memcpy2D !dst !dw !src !sw !w !h !kind = doCopy undefined dst
+  where
+    doCopy :: Storable a' => a' -> Ptr a' -> IO ()
+    doCopy x _ =
+      let bytes = fromIntegral (sizeOf x)
+          dw'   = fromIntegral dw * bytes
+          sw'   = fromIntegral sw * bytes
+          w'    = fromIntegral w  * bytes
+          h'    = fromIntegral h
+      in
+      nothingIfOk =<< cudaMemcpy2D dst dw' src sw' w' h' kind
+
+{-# INLINE cudaMemcpy2D #-}
+{# fun unsafe cudaMemcpy2D
+  { castPtr   `Ptr a'
+  ,           `Int64'
+  , castPtr   `Ptr a'
+  ,           `Int64'
+  ,           `Int64'
+  ,           `Int64'
+  , cFromEnum `CopyDirection'
+  }
+  -> `Status' cToEnum #}
+
+
+-- |
+-- Copy a 2D memory area between the host and device asynchronously, possibly
+-- associated with a particular stream. The host-side memory must be
+-- page-locked.
+--
+{-# INLINEABLE memcpy2DAsync #-}
+memcpy2DAsync :: Storable a
+              => Ptr a          -- ^ destination
+              -> Int            -- ^ width of destination array
+              -> Ptr a          -- ^ source
+              -> Int            -- ^ width of source array
+              -> Int            -- ^ width to copy
+              -> Int            -- ^ height to copy
+              -> CopyDirection
+              -> Maybe Stream
+              -> IO ()
+memcpy2DAsync !dst !dw !src !sw !w !h !kind !mst = doCopy undefined dst
+  where
+    doCopy :: Storable a' => a' -> Ptr a' -> IO ()
+    doCopy x _ =
+      let bytes = fromIntegral (sizeOf x)
+          dw'   = fromIntegral dw * bytes
+          sw'   = fromIntegral sw * bytes
+          w'    = fromIntegral w  * bytes
+          h'    = fromIntegral h
+          st    = fromMaybe defaultStream mst
+      in
+      nothingIfOk =<< cudaMemcpy2DAsync dst dw' src sw' w' h' kind st
+
+{-# INLINE cudaMemcpy2DAsync #-}
+{# fun unsafe cudaMemcpy2DAsync
+  { castPtr   `Ptr a'
+  ,           `Int64'
+  , castPtr   `Ptr a'
+  ,           `Int64'
+  ,           `Int64'
+  ,           `Int64'
+  , cFromEnum `CopyDirection'
+  , useStream `Stream'
+  }
+  -> `Status' cToEnum #}
 
 
 --------------------------------------------------------------------------------
diff --git a/cbits/stubs.c b/cbits/stubs.c
--- a/cbits/stubs.c
+++ b/cbits/stubs.c
@@ -6,10 +6,16 @@
 
 
 cudaError_t
-cudaConfigureCallSimple(int gx, int gy, int bx, int by, int bz, size_t sharedMem, cudaStream_t stream)
+cudaConfigureCallSimple
+(
+    int gridX,  int gridY,
+    int blockX, int blockY, int blockZ,
+    size_t sharedMem,
+    cudaStream_t stream
+)
 {
-    dim3 gridDim  = {gx,gy,1};
-    dim3 blockDim = {bx,by,bz};
+    dim3 gridDim  = {gridX, gridY, 1};
+    dim3 blockDim = {blockX,blockY,blockZ};
 
     return cudaConfigureCall(gridDim, blockDim, sharedMem, stream);
 }
@@ -21,17 +27,234 @@
 }
 
 CUresult
-cuTexRefSetAddress2DSimple(CUtexref tex, CUarray_format fmt, int chn, CUdeviceptr dptr, int width, int height, int pitch)
+cuTexRefSetAddress2DSimple
+(
+    CUtexref tex,
+    CUarray_format format,
+    unsigned int numChannels,
+    CUdeviceptr dptr,
+    size_t width,
+    size_t height,
+    size_t pitch
+)
 {
     CUDA_ARRAY_DESCRIPTOR desc;
-    desc.Format      = fmt;
-    desc.NumChannels = chn;
+    desc.Format      = format;
+    desc.NumChannels = numChannels;
     desc.Width       = width;
     desc.Height      = height;
 
     return cuTexRefSetAddress2D(tex, &desc, dptr, pitch);
 }
 
+CUresult
+cuMemcpy2DHtoD
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    void* srcHost,         unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height
+)
+{
+    CUDA_MEMCPY2D desc;
+
+    // source array (host)
+    // srcStart = (void*)((char*)srcHost + srcY * srcPitch + srcXInBytes)
+    desc.srcMemoryType  = CU_MEMORYTYPE_HOST;
+    desc.srcHost        = srcHost;
+    desc.srcXInBytes    = srcXInBytes;
+    desc.srcY           = srcY;
+    desc.srcPitch       = srcPitch;
+
+    // destination array (device)
+    // dstStart = dstDevice + dstY * dstPitch + dstXInBytes
+    desc.dstMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.dstDevice      = dstDevice;
+    desc.dstXInBytes    = dstXInBytes;
+    desc.dstY           = dstY;
+    desc.dstPitch       = dstPitch;
+
+    // transfer description
+    desc.WidthInBytes   = widthInBytes;
+    desc.Height         = height;
+
+    return cuMemcpy2D(&desc);
+}
+
+CUresult
+cuMemcpy2DHtoDAsync
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    void* srcHost,         unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height,
+    CUstream hStream
+)
+{
+    CUDA_MEMCPY2D desc;
+
+    // source array (host)
+    // srcStart = (void*)((char*)srcHost + srcY * srcPitch + srcXInBytes)
+    desc.srcMemoryType  = CU_MEMORYTYPE_HOST;
+    desc.srcHost        = srcHost;
+    desc.srcXInBytes    = srcXInBytes;
+    desc.srcY           = srcY;
+    desc.srcPitch       = srcPitch;
+
+    // destination array (device)
+    // dstStart = dstDevice + dstY * dstPitch + dstXInBytes
+    desc.dstMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.dstDevice      = dstDevice;
+    desc.dstXInBytes    = dstXInBytes;
+    desc.dstY           = dstY;
+    desc.dstPitch       = dstPitch;
+
+    // transfer description
+    desc.WidthInBytes   = widthInBytes;
+    desc.Height         = height;
+
+    return cuMemcpy2DAsync(&desc, hStream);
+}
+
+CUresult
+cuMemcpy2DDtoH
+(
+    void* dstHost,         unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height
+)
+{
+    CUDA_MEMCPY2D desc;
+
+    // source array (device)
+    // srcStart = srcDevice + srcY * srcPitch + srcXInBytes
+    desc.srcMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.srcDevice      = srcDevice;
+    desc.srcXInBytes    = srcXInBytes;
+    desc.srcY           = srcY;
+    desc.srcPitch       = srcPitch;
+
+    // destination array (host)
+    // dstStart = (void*)((char*)dstHost + dstY * dstPitch + dstXInBytes)
+    desc.dstMemoryType  = CU_MEMORYTYPE_HOST;
+    desc.dstHost        = dstHost;
+    desc.dstXInBytes    = dstXInBytes;
+    desc.dstY           = dstY;
+    desc.dstPitch       = dstPitch;
+
+    // transfer description
+    desc.WidthInBytes   = widthInBytes;
+    desc.Height         = height;
+
+    return cuMemcpy2D(&desc);
+}
+
+CUresult
+cuMemcpy2DDtoHAsync
+(
+    void* dstHost,         unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height,
+    CUstream hStream
+)
+{
+    CUDA_MEMCPY2D desc;
+
+    // source array (device)
+    // srcStart = srcDevice + srcY * srcPitch + srcXInBytes
+    desc.srcMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.srcDevice      = srcDevice;
+    desc.srcXInBytes    = srcXInBytes;
+    desc.srcY           = srcY;
+    desc.srcPitch       = srcPitch;
+
+    // destination array (host)
+    // dstStart = (void*)((char*)dstHost + dstY * dstPitch + dstXInBytes)
+    desc.dstMemoryType  = CU_MEMORYTYPE_HOST;
+    desc.dstHost        = dstHost;
+    desc.dstXInBytes    = dstXInBytes;
+    desc.dstY           = dstY;
+    desc.dstPitch       = dstPitch;
+
+    // transfer description
+    desc.WidthInBytes   = widthInBytes;
+    desc.Height         = height;
+
+    return cuMemcpy2DAsync(&desc, hStream);
+}
+
+CUresult
+cuMemcpy2DDtoD
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height
+)
+{
+    CUDA_MEMCPY2D desc;
+
+    // source array (device)
+    // srcStart = srcDevice + srcY * srcPitch + srcXInBytes
+    desc.srcMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.srcDevice      = srcDevice;
+    desc.srcXInBytes    = srcXInBytes;
+    desc.srcY           = srcY;
+    desc.srcPitch       = srcPitch;
+
+    // destination array (device)
+    // dstStart = dstDevice + dstY * dstPitch + dstXInBytes
+    desc.dstMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.dstDevice      = dstDevice;
+    desc.dstXInBytes    = dstXInBytes;
+    desc.dstY           = dstY;
+    desc.dstPitch       = dstPitch;
+
+    // transfer description
+    desc.WidthInBytes   = widthInBytes;
+    desc.Height         = height;
+
+    return cuMemcpy2D(&desc);
+}
+
+CUresult
+cuMemcpy2DDtoDAsync
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height,
+    CUstream hStream
+)
+{
+    CUDA_MEMCPY2D desc;
+
+    // source array (device)
+    // srcStart = srcDevice + srcY * srcPitch + srcXInBytes
+    desc.srcMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.srcDevice      = srcDevice;
+    desc.srcXInBytes    = srcXInBytes;
+    desc.srcY           = srcY;
+    desc.srcPitch       = srcPitch;
+
+    // destination array (device)
+    // dstStart = dstDevice + dstY * dstPitch + dstXInBytes
+    desc.dstMemoryType  = CU_MEMORYTYPE_DEVICE;
+    desc.dstDevice      = dstDevice;
+    desc.dstXInBytes    = dstXInBytes;
+    desc.dstY           = dstY;
+    desc.dstPitch       = dstPitch;
+
+    // transfer description
+    desc.WidthInBytes   = widthInBytes;
+    desc.Height         = height;
+
+    return cuMemcpy2DAsync(&desc, hStream);
+}
+
+
 #if CUDA_VERSION >= 3020
 /*
  * Extra exports for CUDA-3.2
@@ -91,6 +314,11 @@
     return cuMemcpyDtoD_v2(dstDevice, srcDevice, ByteCount);
 }
 
+CUresult CUDAAPI cuMemcpyDtoDAsync(CUdeviceptr dstDevice, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream)
+{
+    return cuMemcpyDtoDAsync_v2(dstDevice, srcDevice, ByteCount, hStream);
+}
+
 CUresult CUDAAPI cuMemcpyHtoDAsync(CUdeviceptr dstDevice, const void *srcHost, size_t ByteCount, CUstream hStream)
 {
     return cuMemcpyHtoDAsync_v2(dstDevice, srcHost, ByteCount, hStream);
@@ -120,8 +348,8 @@
 {
     return cuTexRefSetAddress_v2(ByteOffset, hTexRef, dptr, bytes);
 }
-
 #endif
+
 #if CUDA_VERSION >= 4000
 CUresult CUDAAPI cuCtxDestroy(CUcontext ctx)
 {
@@ -147,5 +375,12 @@
 {
     return cuEventDestroy_v2(hEvent);
 }
+#endif
 
+#if CUDA_VERSION >= 6050
+CUresult CUDAAPI cuMemHostRegister(void *p, size_t bytesize, unsigned int Flags)
+{
+    return cuMemHostRegister_v2(p, bytesize, Flags);
+}
 #endif
+
diff --git a/cbits/stubs.h b/cbits/stubs.h
--- a/cbits/stubs.h
+++ b/cbits/stubs.h
@@ -23,14 +23,87 @@
 #endif
 
 cudaError_t
-cudaConfigureCallSimple(int gx, int gy, int bx, int by, int bz, size_t sharedMem, cudaStream_t stream);
+cudaConfigureCallSimple
+(
+    int gridX,  int gridY,
+    int blockX, int blockY, int blockZ,
+    size_t sharedMem,
+    cudaStream_t stream
+);
 
 const char*
 cudaGetErrorStringWrapper(cudaError_t error);
 
 CUresult
-cuTexRefSetAddress2DSimple(CUtexref tex, CUarray_format fmt, int chn, CUdeviceptr dptr, int width, int height, int pitch);
+cuTexRefSetAddress2DSimple
+(
+    CUtexref            tex,
+    CUarray_format      format,
+    unsigned int        numChannels,
+    CUdeviceptr         dptr,
+    size_t              width,
+    size_t              height,
+    size_t              pitch
+);
 
+CUresult
+cuMemcpy2DHtoD
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    void* srcHost,         unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height
+);
+
+CUresult
+cuMemcpy2DHtoDAsync
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    void* srcHost,         unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height,
+    CUstream hStream
+);
+
+CUresult
+cuMemcpy2DDtoH
+(
+    void* dstHost,         unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height
+);
+
+CUresult
+cuMemcpy2DDtoHAsync
+(
+    void* dstHost,         unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height,
+    CUstream hStream
+);
+
+CUresult
+cuMemcpy2DDtoD
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height
+);
+
+CUresult
+cuMemcpy2DDtoDAsync
+(
+    CUdeviceptr dstDevice, unsigned int dstPitch, unsigned int dstXInBytes, unsigned int dstY,
+    CUdeviceptr srcDevice, unsigned int srcPitch, unsigned int srcXInBytes, unsigned int srcY,
+    unsigned int widthInBytes,
+    unsigned int height,
+    CUstream hStream
+);
+
+
 /*
  * Need to re-export some symbols as they are now generated by #defines, which
  * c2hs does not like in the function binding hooks.
@@ -56,13 +129,13 @@
 #undef cuMemcpyAtoA
 #undef cuMemcpyHtoAAsync
 #undef cuMemcpyAtoHAsync
-#undef cuMemcpy2D
+// #undef cuMemcpy2D
 #undef cuMemcpy2DUnaligned
 #undef cuMemcpy3D
 #undef cuMemcpyHtoDAsync
 #undef cuMemcpyDtoHAsync
 #undef cuMemcpyDtoDAsync
-#undef cuMemcpy2DAsync
+// #undef cuMemcpy2DAsync
 #undef cuMemcpy3DAsync
 #undef cuMemsetD8
 #undef cuMemsetD16
@@ -104,7 +177,7 @@
 // CUresult CUDAAPI cuMemcpy3D(const CUDA_MEMCPY3D *pCopy);
 CUresult CUDAAPI cuMemcpyHtoDAsync(CUdeviceptr dstDevice, const void *srcHost, size_t ByteCount, CUstream hStream);
 CUresult CUDAAPI cuMemcpyDtoHAsync(void *dstHost, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream);
-// CUresult CUDAAPI cuMemcpyDtoDAsync(CUdeviceptr dstDevice, CUdeviceptr srcDevice, unsigned int ByteCount, CUstream hStream);
+CUresult CUDAAPI cuMemcpyDtoDAsync(CUdeviceptr dstDevice, CUdeviceptr srcDevice, size_t ByteCount, CUstream hStream);
 // CUresult CUDAAPI cuMemcpy2DAsync(const CUDA_MEMCPY2D *pCopy, CUstream hStream);
 // CUresult CUDAAPI cuMemcpy3DAsync(const CUDA_MEMCPY3D *pCopy, CUstream hStream);
 CUresult CUDAAPI cuMemsetD8(CUdeviceptr dstDevice, unsigned char uc, size_t N);
@@ -135,6 +208,12 @@
 CUresult CUDAAPI cuCtxPushCurrent(CUcontext ctx);
 CUresult CUDAAPI cuStreamDestroy(CUstream hStream);
 CUresult CUDAAPI cuEventDestroy(CUevent hEvent);
+#endif
+
+#if CUDA_VERSION >= 6050
+#undef cuMemHostRegister
+
+CUresult CUDAAPI cuMemHostRegister(void *p, size_t bytesize, unsigned int Flags);
 #endif
 
 #ifdef __cplusplus
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Haskell CUDA bindings 0.6.0.0.
+# Generated by GNU Autoconf 2.69 for Haskell CUDA bindings 0.6.5.0.
 #
 # Report bugs to <tmcdonell@cse.unsw.edu.au>.
 #
@@ -580,8 +580,8 @@
 # Identity of this package.
 PACKAGE_NAME='Haskell CUDA bindings'
 PACKAGE_TARNAME='cuda'
-PACKAGE_VERSION='0.6.0.0'
-PACKAGE_STRING='Haskell CUDA bindings 0.6.0.0'
+PACKAGE_VERSION='0.6.5.0'
+PACKAGE_STRING='Haskell CUDA bindings 0.6.5.0'
 PACKAGE_BUGREPORT='tmcdonell@cse.unsw.edu.au'
 PACKAGE_URL=''
 
@@ -1249,7 +1249,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Haskell CUDA bindings 0.6.0.0 to adapt to many kinds of systems.
+\`configure' configures Haskell CUDA bindings 0.6.5.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1315,7 +1315,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Haskell CUDA bindings 0.6.0.0:";;
+     short | recursive ) echo "Configuration of Haskell CUDA bindings 0.6.5.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1402,7 +1402,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Haskell CUDA bindings configure 0.6.0.0
+Haskell CUDA bindings configure 0.6.5.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1704,7 +1704,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Haskell CUDA bindings $as_me 0.6.0.0, which was
+It was created by Haskell CUDA bindings $as_me 0.6.5.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4288,7 +4288,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Haskell CUDA bindings $as_me 0.6.0.0, which was
+This file was extended by Haskell CUDA bindings $as_me 0.6.5.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4341,7 +4341,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Haskell CUDA bindings config.status 0.6.0.0
+Haskell CUDA bindings config.status 0.6.5.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([Haskell CUDA bindings], [0.6.0.0], [tmcdonell@cse.unsw.edu.au], [cuda])
+AC_INIT([Haskell CUDA bindings], [0.6.5.0], [tmcdonell@cse.unsw.edu.au], [cuda])
 AC_CONFIG_SRCDIR([Foreign/CUDA.hs])
 AC_CONFIG_FILES([cuda.buildinfo])
 AC_PROG_CC
diff --git a/cuda.cabal b/cuda.cabal
--- a/cuda.cabal
+++ b/cuda.cabal
@@ -1,5 +1,5 @@
 Name:                   cuda
-Version:                0.6.0.1
+Version:                0.6.5.0
 Synopsis:               FFI binding to the CUDA interface for programming NVIDIA GPUs
 Description:
     The CUDA library provides a direct, general purpose C-like SPMD programming
