diff --git a/bsp/SCALP-FAST-ROUTER-FIRMWARE-BSP-V0.3.bsp b/bsp/SCALP-FAST-ROUTER-FIRMWARE-BSP-V0.3.bsp
new file mode 100644
index 0000000000000000000000000000000000000000..9089c790715ec8a1afbda3c68723efc56b5cf9c6
Binary files /dev/null and b/bsp/SCALP-FAST-ROUTER-FIRMWARE-BSP-V0.3.bsp differ
diff --git a/firmware-bin/BOOT.BIN b/firmware-bin/BOOT.BIN
index c87bdef3f6311112dceb07daa48a8617366ca7c6..980bb35b82c7af54cc555eb36c8a63869c90b82f 100644
Binary files a/firmware-bin/BOOT.BIN and b/firmware-bin/BOOT.BIN differ
diff --git a/firmware-bin/virtualfs-ext4.img b/firmware-bin/virtualfs-ext4.img
index 934528fa653ff7db6d89d14a382f54668772c468..c2c686c7a5c1f4ae549bcd21cd67568ec70cb50a 100644
Binary files a/firmware-bin/virtualfs-ext4.img and b/firmware-bin/virtualfs-ext4.img differ
diff --git a/firmware-bin/zynq_fsbl.elf b/firmware-bin/zynq_fsbl.elf
index 3b5f9e4ba3c5b2f7d2b2bf20468800a53959fb7e..d30d4afc5efca11795b39aa348e1e24393a5c103 100644
Binary files a/firmware-bin/zynq_fsbl.elf and b/firmware-bin/zynq_fsbl.elf differ
diff --git a/scalp_fast_router_firmware_petalinux/.petalinux/metadata b/scalp_fast_router_firmware_petalinux/.petalinux/metadata
index e13cb8125220ef161fcc7066dfa162902086137a..cf353cad5859f18e717c6845054deb343566a550 100644
--- a/scalp_fast_router_firmware_petalinux/.petalinux/metadata
+++ b/scalp_fast_router_firmware_petalinux/.petalinux/metadata
@@ -1,6 +1,6 @@
 PETALINUX_VER=2020.2
 VALIDATE_HW_CHKSUM=1
-HARDWARE_CHECKSUM=7e6e3678e1be9e766e25618ba6237679
+HARDWARE_CHECKSUM=c1efaea1a10d8a6a949bed6944192b91
 YOCTO_SDK=5ff8fc5f85d1566b314bb73eaa378212
-RFSCONFIG_CHKSUM=875fef99c2cf2a1f1c40d3a7bfaa5b32
+RFSCONFIG_CHKSUM=aaca83fde9c8a44dc5232f9f855bb35c
 HARDWARE_PATH=/home/jo/Documents/Projets/Hepia/scalp_project/scalp_firmware/designs/vivado/scalp_fast_router_firmware/2020.2/lin64/scalp_fast_router_firmware/scalp_fast_router_firmware.xsa
diff --git a/scalp_fast_router_firmware_petalinux/SCALP-FAST-ROUTER-FIRMWARE-BSP-V0.3.bsp b/scalp_fast_router_firmware_petalinux/SCALP-FAST-ROUTER-FIRMWARE-BSP-V0.3.bsp
new file mode 100644
index 0000000000000000000000000000000000000000..9089c790715ec8a1afbda3c68723efc56b5cf9c6
Binary files /dev/null and b/scalp_fast_router_firmware_petalinux/SCALP-FAST-ROUTER-FIRMWARE-BSP-V0.3.bsp differ
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/configs/config b/scalp_fast_router_firmware_petalinux/project-spec/configs/config
index 9312953f848e6e486957652b62f50f5b97593d2e..aaea5216d4c97c5ffe10e2659db3a87992c33cc8 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/configs/config
+++ b/scalp_fast_router_firmware_petalinux/project-spec/configs/config
@@ -161,7 +161,7 @@ CONFIG_SUBSYSTEM_EXTRA_DT_FILES=""
 #
 CONFIG_SUBSYSTEM_BOOTARGS_AUTO=y
 CONFIG_SUBSYSTEM_BOOTARGS_EARLYPRINTK=y
-CONFIG_SUBSYSTEM_BOOTARGS_GENERATED="console=ttyPS0,115200 earlycon"
+
 CONFIG_SUBSYSTEM_DEVICETREE_COMPILER_FLAGS="-@"
 # CONFIG_SUBSYSTEM_DTB_OVERLAY is not set
 # CONFIG_SUBSYSTEM_REMOVE_PL_DTB is not set
@@ -253,3 +253,4 @@ CONFIG_YOCTO_NETWORK_SSTATE_FEEDS_URL="http://petalinux.xilinx.com/sswreleases/r
 # User Layers
 #
 CONFIG_USER_LAYER_0=""
+CONFIG_SUBSYSTEM_BOOTARGS_GENERATED="console=ttyPS0,115200 earlycon"
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/configs/rootfs_config b/scalp_fast_router_firmware_petalinux/project-spec/configs/rootfs_config
index 5efa805dcbd78a5501e8f3b67d70715569ebeca1..78cfbbf20b569393cfbe461a450ce60326847b33 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/configs/rootfs_config
+++ b/scalp_fast_router_firmware_petalinux/project-spec/configs/rootfs_config
@@ -4037,6 +4037,11 @@ CONFIG_peekpoke=y
 CONFIG_sja1105-conf=y
 CONFIG_sja1105-init=y
 
+#
+# modules 
+#
+CONFIG_u-dma-buf=y
+
 #
 # user packages 
 #
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/hw-description/scalp_fast_router_firmware.bit b/scalp_fast_router_firmware_petalinux/project-spec/hw-description/scalp_fast_router_firmware.bit
index 27643205258b2ffd6e808126294edc1d19b4e998..797038e5dba1f6d97154c388173edcf38a64583b 100644
Binary files a/scalp_fast_router_firmware_petalinux/project-spec/hw-description/scalp_fast_router_firmware.bit and b/scalp_fast_router_firmware_petalinux/project-spec/hw-description/scalp_fast_router_firmware.bit differ
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/hw-description/system.xsa b/scalp_fast_router_firmware_petalinux/project-spec/hw-description/system.xsa
index 9d18a600111936fc9fb3b85ba7e4f46d03fba38f..10da3f6c9e124c44b44670ea67bc4df57116ceaa 100644
Binary files a/scalp_fast_router_firmware_petalinux/project-spec/hw-description/system.xsa and b/scalp_fast_router_firmware_petalinux/project-spec/hw-description/system.xsa differ
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/conf/user-rootfsconfig b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/conf/user-rootfsconfig
index c1ae806a7855a73c5c4589a48ec3073282bf46ff..c930624194f85534552c7ca91484e671af6852ca 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/conf/user-rootfsconfig
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/conf/user-rootfsconfig
@@ -16,3 +16,4 @@ CONFIG_scalp-locaddr
 CONFIG_scalplocaddr
 CONFIG_dmatest
 CONFIG_dmatest-devmem
+CONFIG_u-dma-buf
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/dmatest/files/dmatest.cc b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/dmatest/files/dmatest.cc
index 2d59bc7882f5b440684a90ac209c46eaff759f0f..866e3b3b8bc28d72c708304ff6a9ce8c1831a7d9 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/dmatest/files/dmatest.cc
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/dmatest/files/dmatest.cc
@@ -61,6 +61,13 @@ int main(int argc, char *argv[])
     uint32_t dstx = 0, dsty = 0, dstz = 0;
     uint32_t srcx = 0, srcy = 0, srcz = 0;
     uint32_t type = 0, pld_size = 0;
+    uint32_t qos_phy_status_north;
+    uint32_t qos_phy_status_east;
+    uint32_t qos_phy_status_south;
+    uint32_t qos_phy_status_west;
+    uint32_t qos_phy_status_top;
+    uint32_t qos_phy_status_bottom;
+    uint32_t qos_phy_status_local;
     uint32_t send = 0;
     uint32_t receive = 0;
     uint32_t buffer_len = 0;
@@ -220,6 +227,67 @@ int main(int argc, char *argv[])
     scalp_socket->dma_set_src_buf_len(buffer_len);
     scalp_socket->dma_set_dst_buf_len(buffer_len);
 
+    // Get QoS Phy Status
+    // North
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_north, libscalp::E_QOS_PHY_STATUS_NORTH)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    // Get QoS Phy Status
+    // East
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_east, libscalp::E_QOS_PHY_STATUS_EAST)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    // Get QoS Phy Status
+    // South
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_south, libscalp::E_QOS_PHY_STATUS_SOUTH)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    // Get QoS Phy Status
+    // West
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_west, libscalp::E_QOS_PHY_STATUS_WEST)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    // Get QoS Phy Status
+    // Top
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_top, libscalp::E_QOS_PHY_STATUS_TOP)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    // Get QoS Phy Status
+    // Bottom
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_bottom, libscalp::E_QOS_PHY_STATUS_BOTTOM)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    // Get QoS Phy Status
+    // Local
+    if((status = scalp_socket->get_qos_phy_status(&qos_phy_status_local, libscalp::E_QOS_PHY_STATUS_LOCAL)) != libscalp::E_SCALP_DMA_NO_ERR)
+    {
+        scalp_socket->perror("main - scalp_socket->get_qos_phy_status()", status);
+        return EXIT_FAILURE;
+    }
+
+    fprintf(stdout, "#> QoS GT Phy Status :\n\tNorth : %d\n\tEast : %d\n\tSouth : %d\n\tWest : %d\n\tTop : %d\n\tBottom : %d\n\tLocal : %d\n\n",
+            qos_phy_status_north, qos_phy_status_east, qos_phy_status_south,
+            qos_phy_status_west, qos_phy_status_top, qos_phy_status_bottom,
+            qos_phy_status_local);
+    
     if(def_locaddr == 1)
     {
         // Set local addr
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.cc b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.cc
index 321a0967b7ef22c840886cb2dcdfbc3f37da0f66..1bd47d8f6aac9fb65ab5235b3cce9c85b76d3713 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.cc
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.cc
@@ -798,6 +798,7 @@ int32_t libscalp::scalp_socket::rcvd(void)
 #ifdef SCALP_LIB_DEBUG_MODE
     std::cout << "libscalp::scalp_socket::rcvd() : wait interrupt" << endl;
 #endif
+
     // Sync on S2MM
     if((status = this->dma_s2mm_sync()) < 0)
         return status;
@@ -825,6 +826,47 @@ int32_t libscalp::scalp_socket::rcvd(void)
     return E_SCALP_DMA_NO_ERR;
 }
 
+int32_t libscalp::scalp_socket::rcvd_nb(void)
+{
+    int32_t status = 0;
+      
+    // Run MM2S channel
+    if((status = this->run_mm2s_chan()) != E_SCALP_DMA_NO_ERR)
+        return status;
+    
+    // Run S2MM channel
+    if((status = this->run_s2mm_chan()) != E_SCALP_DMA_NO_ERR)
+        return status;
+
+    // Set trnsfr len
+    if((status = this->set_trnsfr_len(0)) != E_SCALP_DMA_NO_ERR)
+        return status;   
+    
+    // Set buf len
+    if((status = this->set_buf_len(this->ddr_mem_dst_buf_len)) != E_SCALP_DMA_NO_ERR)
+        return status;    
+
+#ifdef SCALP_LIB_DEBUG_MODE
+    std::cout << "libscalp::scalp_socket::rcvd_nb() : check interrupt" << endl;
+#endif
+
+    if((status & E_IOC_IRQ_FLAG) && (status & E_IDLE_FLAG))
+    {
+#ifdef SCALP_LIB_DEBUG_MODE
+        this->dma_s2mm_status();
+        this->dma_mm2s_status();
+#endif
+        return E_SCALP_DMA_READ_TRSFR_CPLT;
+    }    
+    
+#ifdef SCALP_LIB_DEBUG_MODE
+    this->dma_s2mm_status();
+    this->dma_mm2s_status();
+#endif
+
+    return E_SCALP_DMA_NO_ERR;
+}
+
 int32_t libscalp::scalp_socket::set_locaddr(uint32_t x, uint32_t y, uint32_t z)
 {
     libscalp::scalp_fast_router_registers *_regs = NULL;
@@ -861,6 +903,26 @@ int32_t libscalp::scalp_socket::get_locaddr(uint32_t *x, uint32_t *y, uint32_t *
     return E_SCALP_DMA_NO_ERR;
 }
 
+int32_t libscalp::scalp_socket::get_qos_phy_status(uint32_t *qos_phy_status, uint32_t qos_phy_status_flag)
+{
+    libscalp::scalp_fast_router_registers *_regs = NULL;
+    uint32_t status = 0;
+
+    if((_regs = reinterpret_cast<libscalp::scalp_fast_router_registers *>(this->uio_mmap_scalp_router_virtual_reg->get_ptr())) == NULL)
+        return E_SCALP_DMA_ERR_PTR;
+
+    if(qos_phy_status != NULL)
+    {
+        status = (uint32_t)_regs->qos_phy_status;       
+        *qos_phy_status = (uint32_t)((status >> qos_phy_status_flag) & 0x00000001);
+    }
+    else
+        return E_SCALP_DMA_ERR_SRC_ADDR;
+
+    return E_SCALP_DMA_NO_ERR;
+}
+
+
 uint32_t * libscalp::scalp_socket::set_header(uint32_t dstx, uint32_t dsty, uint32_t dstz, uint32_t pld_size, uint32_t type)
 {
     // libscalp::scalp_fast_router_registers *_regs = NULL;
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.hh b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.hh
index 0cf0e1c69796001dc0e63b2fdabc5e197233b1f0..7eb8b913349f1e3ad5ad984350bfcb54e0751a9c 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.hh
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-apps/libscalp/files/scalp.hh
@@ -45,6 +45,19 @@ namespace libscalp
         std::atomic<uint32_t> dma_fifo_rx_wr_data_cnt;
         std::atomic<uint32_t> dma_fifo_rx_rd_data_cnt;
         std::atomic<uint32_t> dma_fifo_rx_status;
+        // QoS GT Phy Status
+        std::atomic<uint32_t> qos_phy_status;
+    };
+
+    enum scalp_qos_phy_status_flags
+    {
+        E_QOS_PHY_STATUS_NORTH  = 0x0,
+        E_QOS_PHY_STATUS_EAST   = 0x1,
+        E_QOS_PHY_STATUS_SOUTH  = 0x2,
+        E_QOS_PHY_STATUS_WEST   = 0x3,
+        E_QOS_PHY_STATUS_TOP    = 0x4,
+        E_QOS_PHY_STATUS_BOTTOM = 0x5,
+        E_QOS_PHY_STATUS_LOCAL  = 0x6
     };
 
     struct dma_registers
@@ -88,6 +101,13 @@ namespace libscalp
         E_ENABLE_ALL_IRQ          = 0x00007000
     };
 
+    enum scalp_dma_read_mode
+    {
+        E_SCALP_DMA_READ_BLOCKING_MODE     = 0x0,
+        E_SCALP_DMA_READ_NON_BLOCKING_MODE = 0x1,
+        E_SCALP_DMA_READ_TRSFR_CPLT        = 0x2
+    };
+    
     enum scalp_dma_ptr_type
     {
         E_SCALP_DMA_VIRTUAL_SRC_BUF = 0x0,
@@ -219,8 +239,10 @@ namespace libscalp
         int32_t  dma_init            (void);
         int32_t  send                (void);
         int32_t  rcvd                (void);
+        int32_t  rcvd_nb             (void);
         int32_t  set_locaddr         (uint32_t  x, uint32_t  y, uint32_t  z);
         int32_t  get_locaddr         (uint32_t *x, uint32_t *y, uint32_t *z);
+        int32_t  get_qos_phy_status  (uint32_t *qos_phy_status, uint32_t qos_phy_status_flag);
         uint32_t *set_header         (uint32_t  dstx, uint32_t  dsty, uint32_t  dstz, uint32_t  pld_size, uint32_t  type);
         uint32_t *get_header         (uint32_t *dstx, uint32_t *dsty, uint32_t *dstz,
                                       uint32_t *srcx, uint32_t *srcy, uint32_t *srcz,
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/scalp-router.dtsi b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/scalp-router.dtsi
index 27f2fe444ef06e9d3d61a1bb68b0ec3c4fec942d..b964e53570592c8f26589790b188f87abb509550 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/scalp-router.dtsi
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/scalp-router.dtsi
@@ -4,27 +4,36 @@
 	    #size-cells = <1>;
 	    compatible = "simple-bus";
 	    ranges ;
-
+       
         scalp_fast_router_dma_virtual_addr_1: scalp_fast_router_dma_virtual_addr@0x40400000 {
             compatible = "generic-uio";
             reg = <0x40400000 0x10000>;
             status = "okay";
         };
 
+        // udmabuf0@0 {
+        //     compatible = "ikwzm,u-dma-buf";
+		//     device-name = "udmabuf0";
+        //     minor-number = <0>;
+		//     size = <0x04000000>; // 64MiB
+        //     //dma-coherent;
+		//     memory-region = <&reserved_dmabuf_0>;
+	    // };
+
         scalp_fast_router_virtual_src_addr_1: scalp_fast_router_virtual_src_addr@0x0e000000 {
-            compatible = "generic-uio";
-            reg = <0x0e000000 0x10000>;
-            interrupt-parent = <&intc>;
-            interrupts = < 0 29 4 >;
-            status = "okay";
+           compatible = "generic-uio";
+           reg = <0x0e000000 0x10000>;
+           interrupt-parent = <&intc>;
+           interrupts = < 0 29 4 >;
+           status = "okay";
         };
 
         scalp_fast_router_virtual_dst_addr_1: scalp_fast_router_virtual_dst_addr@0x0f000000 {
-            compatible = "generic-uio";
-            reg = <0x0f000000 0x10000>;
-            interrupt-parent = <&intc>;
-            interrupts = < 0 30 4 >;
-            status = "okay";
+           compatible = "generic-uio";
+           reg = <0x0f000000 0x10000>;
+           interrupt-parent = <&intc>;
+           interrupts = < 0 30 4 >;
+           status = "okay";
         };
 
         scalp_fast_router_registers_0: scalp_fast_router_registers@0x43c00000 {
@@ -32,6 +41,7 @@
             reg = <0x43c00000 0x1000>;
             status = "okay";
         };
+        
     };
 };
 
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
index e9f6b87507129cffd70c017e838235516a860199..7a2de3eb7e6531ffa8c552c159f24f0a9a47776f 100644
--- a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
@@ -35,6 +35,20 @@
 		reg = <0 0x10000000>;
 	};
 
+    reserved-memory {
+      #address-cells = <2>;
+      #size-cells = <2>;
+      ranges;
+  
+      reserved_dmabuf_0: buffer@0 {
+         compatible = "shared-dma-pool";
+         reusable;
+         reg = <0x0 0x0c000000 0x0 0x04000000>;
+         linux,cma-default;
+         label = "reserved_dmabuf_0";
+      };
+   };
+    
     chosen {
            bootargs = "earlyprintk cpuidle.off=1 crashkernel=256M rw";
            stdout-path = "serial0:115200n8";
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/README b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/README
new file mode 100644
index 0000000000000000000000000000000000000000..d1772ab6a6da5b53d66b19180774ca157028f2ce
--- /dev/null
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/README
@@ -0,0 +1,53 @@
+PetaLinux User Module Template
+===================================
+
+This directory contains a PetaLinux kernel module created from a template.
+
+If you are developing your module from scratch, simply start editing the
+file u-dma-buf.c.
+
+You can easily import any existing module code by copying it into this 
+directory, and editing the automatically generated Makefile as described below.
+
+The "all:" target in the Makefile template will compile compile the module.
+
+Before building the module, you will need to enable the module from
+PetaLinux menuconfig by running:
+    "petalinux-config -c rootfs"
+You will see your module in the "modules --->" submenu.
+
+To compile and install your module to the target file system copy on the host,
+simply run the command.
+    "petalinux-build -c kernel" to build kernel first, and then run
+    "petalinux-build -c u-dma-buf" to build the module
+
+You will also need to rebuild PetaLinux bootable images so that the images
+is updated with the updated target filesystem copy, run this command:
+    "petalinux-build -c rootfs"
+
+You can also run one PetaLinux command to compile the module, install it
+to the target filesystem host copy and update the bootable images as follows:
+    "petalinux-build"
+
+If OF(OpenFirmware) is configured, you need to add the device node to the
+DTS(Device Tree Source) file so that the device can be probed when the module is
+loaded. Here is an example of the device node in the device tree:
+
+	u-dma-buf_instance: u-dma-buf@XXXXXXXX {
+		compatible = "vendor,u-dma-buf";
+		reg = <PHYSICAL_START_ADDRESS ADDRESS_RANGE>;
+		interrupt-parent = <&INTR_CONTROLLER_INSTANCE>;
+		interrupts = < INTR_NUM INTR_SENSITIVITY >;
+	};
+Notes:
+ * "u-dma-buf@XXXXXXXX" is the label of the device node, it is usually the "DEVICE_TYPE@PHYSICAL_START_ADDRESS". E.g. "u-dma-buf@89000000".
+ * "compatible" needs to match one of the the compatibles in the module's compatible list.
+ * "reg" needs to be pair(s) of the physical start address of the device and the address range.
+ * If the device has interrupt, the "interrupt-parent" needs to be the interrupt controller which the interrupt connects to. and the "interrupts" need to be pair(s) of the interrupt ID and the interrupt sensitivity.
+
+For more information about the the DTS file, please refer to this document in the Linux kernel: linux-2.6.x/Documentation/powerpc/booting-without-of.txt
+
+
+To add extra source code files (for example, to split a large module into 
+multiple source files), add the relevant .o files to the list in the local 
+Makefile where indicated.  
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/COPYING b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..6d45519c8c6cc926a7d6d96ebc45de7226f66099
--- /dev/null
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/Makefile b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d6b4c6851dfa90ba61acec38f332910fd68ca635
--- /dev/null
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/Makefile
@@ -0,0 +1,17 @@
+obj-m := u-dma-buf.o
+
+MY_CFLAGS += -g -DDEBUG
+ccflags-y += ${MY_CFLAGS}
+
+SRC := $(shell pwd)
+
+all:
+	$(MAKE) -C $(KERNEL_SRC) M=$(SRC)
+
+modules_install:
+	$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
+
+clean:
+	rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
+	rm -f Module.markers Module.symvers modules.order
+	rm -rf .tmp_versions Modules.symvers
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/u-dma-buf.c b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/u-dma-buf.c
new file mode 100644
index 0000000000000000000000000000000000000000..3d19a1c1e9c55263cd327d08406dd850d7853e71
--- /dev/null
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/files/u-dma-buf.c
@@ -0,0 +1,2134 @@
+/*********************************************************************************
+ *
+ *       Copyright (C) 2015-2020 Ichiro Kawazome
+ *       All rights reserved.
+ * 
+ *       Redistribution and use in source and binary forms, with or without
+ *       modification, are permitted provided that the following conditions
+ *       are met:
+ * 
+ *         1. Redistributions of source code must retain the above copyright
+ *            notice, this list of conditions and the following disclaimer.
+ * 
+ *         2. Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in
+ *            the documentation and/or other materials provided with the
+ *            distribution.
+ * 
+ *       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *       "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *       LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *       A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+ *       OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *       SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *       LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *       DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *       THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *       (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *       OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ ********************************************************************************/
+#include <linux/cdev.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/scatterlist.h>
+#include <linux/pagemap.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/version.h>
+#include <asm/page.h>
+#include <asm/byteorder.h>
+
+/**
+ * DOC: Udmabuf Constants 
+ */
+
+MODULE_DESCRIPTION("User space mappable DMA buffer device driver");
+MODULE_AUTHOR("ikwzm");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define DRIVER_VERSION     "3.2.4"
+#define DRIVER_NAME        "u-dma-buf"
+#define DEVICE_NAME_FORMAT "udmabuf%d"
+#define DEVICE_MAX_NUM      256
+#define UDMABUF_DEBUG       1
+#define USE_VMA_FAULT       1
+#define UDMABUF_MGR_ENABLE  1
+#define UDMABUF_MGR_NAME   "u-dma-buf-mgr"
+
+#if     ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) && (defined(CONFIG_ARM) || defined(CONFIG_ARM64)))
+#if     (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
+#if     (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
+#include <linux/dma-map-ops.h>
+#else
+#include <linux/dma-noncoherent.h>
+#endif
+#define IS_DMA_COHERENT(dev) dev_is_dma_coherent(dev)
+#else
+#define IS_DMA_COHERENT(dev) is_device_dma_coherent(dev)
+#endif
+#endif
+
+#if     (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+#define USE_DEV_GROUPS      1
+#else
+#define USE_DEV_GROUPS      0
+#endif
+
+#if     ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) && defined(CONFIG_OF))
+#define USE_OF_RESERVED_MEM 1
+#else
+#define USE_OF_RESERVED_MEM 0
+#endif
+
+#if     ((LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) && defined(CONFIG_OF))
+#define USE_OF_DMA_CONFIG   1
+#else
+#define USE_OF_DMA_CONFIG   0
+#endif
+
+#if     (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
+#define USE_DEV_PROPERTY    1
+#else
+#define USE_DEV_PROPERTY    0
+#endif
+
+#if     (UDMABUF_DEBUG == 1)
+#define UDMABUF_DEBUG_CHECK(this,debug) (this->debug)
+#else
+#define UDMABUF_DEBUG_CHECK(this,debug) (0)
+#endif
+
+#if     (USE_OF_RESERVED_MEM == 1)
+#include <linux/of_reserved_mem.h>
+#endif
+
+#ifndef U64_MAX
+#define U64_MAX ((u64)~0ULL)
+#endif
+
+/**
+ * DOC: Udmabuf Static Variables
+ *
+ * * udmabuf_sys_class - udmabuf system class
+ * * init_enable       - udmabuf install/uninstall infomation enable
+ * * dma_mask_bit      - udmabuf dma mask bit
+ */
+
+/**
+ * udmabuf_sys_class - udmabuf system class
+ */
+static struct class*  udmabuf_sys_class = NULL;
+
+/**
+ * info_enable module parameter
+ */
+static int        info_enable = 1;
+module_param(     info_enable , int, S_IRUGO);
+MODULE_PARM_DESC( info_enable , "udmabuf install/uninstall infomation enable");
+#define           DMA_INFO_ENABLE  (info_enable & 0x02)
+
+/**
+ * dma_mask_bit module parameter
+ */
+static int        dma_mask_bit = 32;
+module_param(     dma_mask_bit, int, S_IRUGO);
+MODULE_PARM_DESC( dma_mask_bit, "udmabuf dma mask bit(default=32)");
+
+/**
+ * DOC: Udmabuf Device Data Structure
+ *
+ * This section defines the structure of udmabuf device.
+ *
+ */
+
+/**
+ * struct udmabuf_device_data - udmabuf device data structure.
+ */
+struct udmabuf_device_data {
+    struct device*       sys_dev;
+    struct device*       dma_dev;
+    struct cdev          cdev;
+    dev_t                device_number;
+    struct mutex         sem;
+    bool                 is_open;
+    size_t               size;
+    size_t               alloc_size;
+    void*                virt_addr;
+    dma_addr_t           phys_addr;
+    int                  sync_mode;
+    u64                  sync_offset;
+    size_t               sync_size;
+    int                  sync_direction;
+    bool                 sync_owner;
+    u64                  sync_for_cpu;
+    u64                  sync_for_device;
+#if (USE_OF_RESERVED_MEM == 1)
+    bool                 of_reserved_mem;
+#endif
+#if ((UDMABUF_DEBUG == 1) && (USE_VMA_FAULT == 1))
+    bool                 debug_vma;
+#endif
+};
+
+/**
+ * sync_mode(synchronous mode) value
+ */
+#define SYNC_MODE_INVALID       (0x00)
+#define SYNC_MODE_NONCACHED     (0x01)
+#define SYNC_MODE_WRITECOMBINE  (0x02)
+#define SYNC_MODE_DMACOHERENT   (0x03)
+#define SYNC_MODE_MASK          (0x03)
+#define SYNC_MODE_MIN           (0x01)
+#define SYNC_MODE_MAX           (0x03)
+#define SYNC_ALWAYS             (0x04)
+
+/**
+ * DOC: Udmabuf System Class Device File Description
+ *
+ * This section define the device file created in system class when udmabuf is 
+ * loaded into the kernel.
+ *
+ * The device file created in system class is as follows.
+ *
+ * * /sys/class/udmabuf/<device-name>/driver_version
+ * * /sys/class/udmabuf/<device-name>/phys_addr
+ * * /sys/class/udmabuf/<device-name>/size
+ * * /sys/class/udmabuf/<device-name>/sync_mode
+ * * /sys/class/udmabuf/<device-name>/sync_offset
+ * * /sys/class/udmabuf/<device-name>/sync_size
+ * * /sys/class/udmabuf/<device-name>/sync_direction
+ * * /sys/class/udmabuf/<device-name>/sync_owner
+ * * /sys/class/udmabuf/<device-name>/sync_for_cpu
+ * * /sys/class/udmabuf/<device-name>/sync_for_device
+ * * /sys/class/udmabuf/<device-name>/dma_coherent
+ * * 
+ */
+
+#define  SYNC_COMMAND_DIR_MASK        (0x000000000000000C)
+#define  SYNC_COMMAND_DIR_SHIFT       (2)
+#define  SYNC_COMMAND_SIZE_MASK       (0x00000000FFFFFFF0)
+#define  SYNC_COMMAND_SIZE_SHIFT      (0)
+#define  SYNC_COMMAND_OFFSET_MASK     (0xFFFFFFFF00000000)
+#define  SYNC_COMMAND_OFFSET_SHIFT    (32)
+#define  SYNC_COMMAND_ARGMENT_MASK    (0xFFFFFFFFFFFFFFFE)
+/**
+ * udmabuf_sync_command_argments() - get argment for dma_sync_single_for_cpu() or dma_sync_single_for_device()
+ *                                  
+ * @this:       Pointer to the udmabuf device data structure.
+ * @command     sync command (this->sync_for_cpu or this->sync_for_device)
+ * @phys_addr   Pointer to the phys_addr for dma_sync_single_for_...()
+ * @size        Pointer to the size for dma_sync_single_for_...()
+ * @direction   Pointer to the direction for dma_sync_single_for_...()
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_sync_command_argments(
+    struct udmabuf_device_data *this     ,
+    u64                         command  ,
+    dma_addr_t                 *phys_addr,
+    size_t                     *size     ,
+    enum dma_data_direction    *direction
+) {
+    u64    sync_offset   ;
+    size_t sync_size     ;
+    int    sync_direction;
+    if ((command & SYNC_COMMAND_ARGMENT_MASK) != 0) {
+        sync_offset    = (u64   )((command & SYNC_COMMAND_OFFSET_MASK) >> SYNC_COMMAND_OFFSET_SHIFT);
+        sync_size      = (size_t)((command & SYNC_COMMAND_SIZE_MASK  ) >> SYNC_COMMAND_SIZE_SHIFT  );
+        sync_direction = (int   )((command & SYNC_COMMAND_DIR_MASK   ) >> SYNC_COMMAND_DIR_SHIFT   );
+    } else {
+        sync_offset    = this->sync_offset;
+        sync_size      = this->sync_size;
+        sync_direction = this->sync_direction;
+    }
+    if (sync_offset + sync_size > this->size)
+        return -EINVAL;
+    switch(sync_direction) {
+        case 1 : *direction = DMA_TO_DEVICE    ; break;
+        case 2 : *direction = DMA_FROM_DEVICE  ; break;
+        default: *direction = DMA_BIDIRECTIONAL; break;
+    }
+    *phys_addr = this->phys_addr + sync_offset;
+    *size      = sync_size;
+    return 0;
+} 
+
+/**
+ * udmabuf_sync_for_cpu() - call dma_sync_single_for_cpu() when (sync_for_cpu != 0)
+ * @this:       Pointer to the udmabuf device data structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_sync_for_cpu(struct udmabuf_device_data* this)
+{
+    int status = 0;
+
+    if (this->sync_for_cpu) {
+        dma_addr_t              phys_addr;
+        size_t                  size;
+        enum dma_data_direction direction;
+        status = udmabuf_sync_command_argments(this, this->sync_for_cpu, &phys_addr, &size, &direction);
+        if (status == 0) {
+            dma_sync_single_for_cpu(this->dma_dev, phys_addr, size, direction);
+            this->sync_for_cpu = 0;
+            this->sync_owner   = 0;
+        }
+    }
+    return status;
+}
+
+/**
+ * udmabuf_sync_for_device() - call dma_sync_single_for_device() when (sync_for_device != 0)
+ * @this:       Pointer to the udmabuf device data structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_sync_for_device(struct udmabuf_device_data* this)
+{
+    int status = 0;
+
+    if (this->sync_for_device) {
+        dma_addr_t              phys_addr;
+        size_t                  size;
+        enum dma_data_direction direction;
+        status = udmabuf_sync_command_argments(this, this->sync_for_device, &phys_addr, &size, &direction);
+        if (status == 0) {
+            dma_sync_single_for_device(this->dma_dev, phys_addr, size, direction);
+            this->sync_for_device = 0;
+            this->sync_owner      = 1;
+        }
+    }
+    return status;
+}
+
+#define DEF_ATTR_SHOW(__attr_name, __format, __value) \
+static ssize_t udmabuf_show_ ## __attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
+{                                                            \
+    ssize_t status;                                          \
+    struct udmabuf_device_data* this = dev_get_drvdata(dev); \
+    if (mutex_lock_interruptible(&this->sem) != 0)           \
+        return -ERESTARTSYS;                                 \
+    status = sprintf(buf, __format, (__value));              \
+    mutex_unlock(&this->sem);                                \
+    return status;                                           \
+}
+
+static inline int NO_ACTION(struct udmabuf_device_data* this){return 0;}
+
+#define DEF_ATTR_SET(__attr_name, __min, __max, __pre_action, __post_action) \
+static ssize_t udmabuf_set_ ## __attr_name(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) \
+{ \
+    ssize_t       status; \
+    u64           value;  \
+    struct udmabuf_device_data* this = dev_get_drvdata(dev);                 \
+    if (0 != mutex_lock_interruptible(&this->sem)){return -ERESTARTSYS;}     \
+    if (0 != (status = kstrtoull(buf, 0, &value))){            goto failed;} \
+    if ((value < __min) || (__max < value)) {status = -EINVAL; goto failed;} \
+    if (0 != (status = __pre_action(this)))       {            goto failed;} \
+    this->__attr_name = value;                                               \
+    if (0 != (status = __post_action(this)))      {            goto failed;} \
+    status = size;                                                           \
+  failed:                                                                    \
+    mutex_unlock(&this->sem);                                                \
+    return status;                                                           \
+}
+
+DEF_ATTR_SHOW(driver_version , "%s\n"    , DRIVER_VERSION                                 );
+DEF_ATTR_SHOW(size           , "%zu\n"   , this->size                                     );
+DEF_ATTR_SHOW(phys_addr      , "%pad\n"  , &this->phys_addr                               );
+DEF_ATTR_SHOW(sync_mode      , "%d\n"    , this->sync_mode                                );
+DEF_ATTR_SET( sync_mode                  , 0, 7,        NO_ACTION, NO_ACTION              );
+DEF_ATTR_SHOW(sync_offset    , "0x%llx\n", this->sync_offset                              );
+DEF_ATTR_SET( sync_offset                , 0, U64_MAX,  NO_ACTION, NO_ACTION              );
+DEF_ATTR_SHOW(sync_size      , "%zu\n"   , this->sync_size                                );
+DEF_ATTR_SET( sync_size                  , 0, SIZE_MAX, NO_ACTION, NO_ACTION              );
+DEF_ATTR_SHOW(sync_direction , "%d\n"    , this->sync_direction                           );
+DEF_ATTR_SET( sync_direction             , 0, 2,        NO_ACTION, NO_ACTION              );
+DEF_ATTR_SHOW(sync_owner     , "%d\n"    , this->sync_owner                               );
+DEF_ATTR_SHOW(sync_for_cpu   , "%llu\n"  , this->sync_for_cpu                             );
+DEF_ATTR_SET( sync_for_cpu               , 0, U64_MAX,  NO_ACTION, udmabuf_sync_for_cpu   );
+DEF_ATTR_SHOW(sync_for_device, "%llu\n"  , this->sync_for_device                          );
+DEF_ATTR_SET( sync_for_device            , 0, U64_MAX,  NO_ACTION, udmabuf_sync_for_device);
+#if defined(IS_DMA_COHERENT)
+DEF_ATTR_SHOW(dma_coherent   , "%d\n"    , IS_DMA_COHERENT(this->dma_dev)                 );
+#endif
+#if ((UDMABUF_DEBUG == 1) && (USE_VMA_FAULT == 1))
+DEF_ATTR_SHOW(debug_vma      , "%d\n"    , this->debug_vma                                );
+DEF_ATTR_SET( debug_vma                  , 0, 1,        NO_ACTION, NO_ACTION              );
+#endif
+
+static struct device_attribute udmabuf_device_attrs[] = {
+  __ATTR(driver_version , 0444, udmabuf_show_driver_version  , NULL                       ),
+  __ATTR(size           , 0444, udmabuf_show_size            , NULL                       ),
+  __ATTR(phys_addr      , 0444, udmabuf_show_phys_addr       , NULL                       ),
+  __ATTR(sync_mode      , 0664, udmabuf_show_sync_mode       , udmabuf_set_sync_mode      ),
+  __ATTR(sync_offset    , 0664, udmabuf_show_sync_offset     , udmabuf_set_sync_offset    ),
+  __ATTR(sync_size      , 0664, udmabuf_show_sync_size       , udmabuf_set_sync_size      ),
+  __ATTR(sync_direction , 0664, udmabuf_show_sync_direction  , udmabuf_set_sync_direction ),
+  __ATTR(sync_owner     , 0444, udmabuf_show_sync_owner      , NULL                       ),
+  __ATTR(sync_for_cpu   , 0664, udmabuf_show_sync_for_cpu    , udmabuf_set_sync_for_cpu   ),
+  __ATTR(sync_for_device, 0664, udmabuf_show_sync_for_device , udmabuf_set_sync_for_device),
+#if defined(IS_DMA_COHERENT)
+  __ATTR(dma_coherent   , 0444, udmabuf_show_dma_coherent    , NULL                       ),
+#endif
+#if ((UDMABUF_DEBUG == 1) && (USE_VMA_FAULT == 1))
+  __ATTR(debug_vma      , 0664, udmabuf_show_debug_vma       , udmabuf_set_debug_vma      ),
+#endif
+  __ATTR_NULL,
+};
+
+#if (USE_DEV_GROUPS == 1)
+
+#define udmabuf_device_attrs_size (sizeof(udmabuf_device_attrs)/sizeof(udmabuf_device_attrs[0]))
+
+static struct attribute* udmabuf_attrs[udmabuf_device_attrs_size] = {
+  NULL
+};
+static struct attribute_group udmabuf_attr_group = {
+  .attrs = udmabuf_attrs
+};
+static const struct attribute_group* udmabuf_attr_groups[] = {
+  &udmabuf_attr_group,
+  NULL
+};
+
+static inline void udmabuf_sys_class_set_attributes(void)
+{
+    int i;
+    for (i = 0 ; i < udmabuf_device_attrs_size-1 ; i++) {
+        udmabuf_attrs[i] = &(udmabuf_device_attrs[i].attr);
+    }
+    udmabuf_attrs[i] = NULL;
+    udmabuf_sys_class->dev_groups = udmabuf_attr_groups;
+}
+#else
+
+static inline void udmabuf_sys_class_set_attributes(void)
+{
+    udmabuf_sys_class->dev_attrs  = udmabuf_device_attrs;
+}
+
+#endif
+
+#if (USE_VMA_FAULT == 1)
+/**
+ * DOC: Udmabuf Device VM Area Operations
+ *
+ * This section defines the operation of vm when mmap-ed the udmabuf device file.
+ *
+ * * udmabuf_device_vma_open()  - udmabuf device vm area open operation.
+ * * udmabuf_device_vma_close() - udmabuf device vm area close operation.
+ * * udmabuf_device_vma_fault() - udmabuf device vm area fault operation.
+ * * udmabuf_device_vm_ops      - udmabuf device vm operation table.
+ */
+
+/**
+ * udmabuf_device_vma_open() - udmabuf device vm area open operation.
+ * @vma:        Pointer to the vm area structure.
+ * Return:      None
+ */
+static void udmabuf_device_vma_open(struct vm_area_struct* vma)
+{
+    struct udmabuf_device_data* this = vma->vm_private_data;
+    if (UDMABUF_DEBUG_CHECK(this, debug_vma))
+        dev_info(this->dma_dev, "vma_open(virt_addr=0x%lx, offset=0x%lx)\n", vma->vm_start, vma->vm_pgoff<<PAGE_SHIFT);
+}
+
+/**
+ * udmabuf_device_vma_close() - udmabuf device vm area close operation.
+ * @vma:        Pointer to the vm area structure.
+ * Return:      None
+ */
+static void udmabuf_device_vma_close(struct vm_area_struct* vma)
+{
+    struct udmabuf_device_data* this = vma->vm_private_data;
+    if (UDMABUF_DEBUG_CHECK(this, debug_vma))
+        dev_info(this->dma_dev, "vma_close()\n");
+}
+
+/**
+ * VM_FAULT_RETURN_TYPE - Type of udmabuf_device_vma_fault() return value.
+ */
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0))
+typedef vm_fault_t VM_FAULT_RETURN_TYPE;
+#else
+typedef int        VM_FAULT_RETURN_TYPE;
+#endif
+
+/**
+ * _udmabuf_device_vma_fault() - udmabuf device vm area fault operation.
+ * @vma:        Pointer to the vm area structure.
+ * @vfm:        Pointer to the vm fault structure.
+ * Return:      VM_FAULT_RETURN_TYPE (Success(=0) or error status(!=0)).
+ */
+static inline VM_FAULT_RETURN_TYPE _udmabuf_device_vma_fault(struct vm_area_struct* vma, struct vm_fault* vmf)
+{
+    struct udmabuf_device_data* this = vma->vm_private_data;
+    unsigned long offset             = vmf->pgoff << PAGE_SHIFT;
+    unsigned long phys_addr          = this->phys_addr + offset;
+    unsigned long page_frame_num     = phys_addr  >> PAGE_SHIFT;
+    unsigned long request_size       = 1          << PAGE_SHIFT;
+    unsigned long available_size     = this->alloc_size -offset;
+    unsigned long virt_addr;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0))
+    virt_addr = vmf->address;
+#else
+    virt_addr = (unsigned long)vmf->virtual_address;
+#endif
+
+    if (UDMABUF_DEBUG_CHECK(this, debug_vma))
+        dev_info(this->dma_dev,
+                 "vma_fault(virt_addr=%pad, phys_addr=%pad)\n", &virt_addr, &phys_addr
+        );
+
+    if (request_size > available_size)
+        return VM_FAULT_SIGBUS;
+
+    if (!pfn_valid(page_frame_num))
+        return VM_FAULT_SIGBUS;
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
+    return vmf_insert_pfn(vma, virt_addr, page_frame_num);
+#else
+    {
+        int err = vm_insert_pfn(vma, virt_addr, page_frame_num);
+        if (err == -ENOMEM)
+            return VM_FAULT_OOM;
+        if (err < 0 && err != -EBUSY)
+            return VM_FAULT_SIGBUS;
+
+        return VM_FAULT_NOPAGE;
+    }
+#endif
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
+/**
+ * udmabuf_device_vma_fault() - udmabuf device vm area fault operation.
+ * @vfm:        Pointer to the vm fault structure.
+ * Return:      VM_FAULT_RETURN_TYPE (Success(=0) or error status(!=0)).
+ */
+static VM_FAULT_RETURN_TYPE udmabuf_device_vma_fault(struct vm_fault* vmf)
+{
+    return _udmabuf_device_vma_fault(vmf->vma, vmf);
+}
+#else
+/**
+ * udmabuf_device_vma_fault() - udmabuf device vm area fault operation.
+ * @vma:        Pointer to the vm area structure.
+ * @vfm:        Pointer to the vm fault structure.
+ * Return:      VM_FAULT_RETURN_TYPE (Success(=0) or error status(!=0)).
+ */
+static VM_FAULT_RETURN_TYPE udmabuf_device_vma_fault(struct vm_area_struct* vma, struct vm_fault* vmf)
+{
+    return _udmabuf_device_vma_fault(vma, vmf);
+}
+#endif
+
+/**
+ * udmabuf device vm operation table.
+ */
+static const struct vm_operations_struct udmabuf_device_vm_ops = {
+    .open    = udmabuf_device_vma_open ,
+    .close   = udmabuf_device_vma_close,
+    .fault   = udmabuf_device_vma_fault,
+};
+
+#endif /* #if (USE_VMA_FAULT == 1) */
+
+/**
+ * DOC: Udmabuf Device File Operations
+ *
+ * This section defines the operation of the udmabuf device file.
+ *
+ * * udmabuf_device_file_open()    - udmabuf device file open operation.
+ * * udmabuf_device_file_release() - udmabuf device file release operation.
+ * * udmabuf_device_file_mmap()    - udmabuf device file memory map operation.
+ * * udmabuf_device_file_read()    - udmabuf device file read operation.
+ * * udmabuf_device_file_write()   - udmabuf device file write operation.
+ * * udmabuf_device_file_llseek()  - udmabuf device file llseek operation.
+ * * udmabuf_device_file_ops       - udmabuf device file operation table.
+ */
+
+/**
+ * udmabuf_device_file_open() - udmabuf device file open operation.
+ * @inode:      Pointer to the inode structure of this device.
+ * @file:       to the file structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_device_file_open(struct inode *inode, struct file *file)
+{
+    struct udmabuf_device_data* this;
+    int status = 0;
+
+    this = container_of(inode->i_cdev, struct udmabuf_device_data, cdev);
+    file->private_data = this;
+    this->is_open = 1;
+
+    return status;
+}
+
+/**
+ * udmabuf_device_file_release() - udmabuf device file release operation.
+ * @inode:      Pointer to the inode structure of this device.
+ * @file:       Pointer to the file structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_device_file_release(struct inode *inode, struct file *file)
+{
+    struct udmabuf_device_data* this = file->private_data;
+
+    this->is_open = 0;
+
+    return 0;
+}
+
+/**
+ * _PGPROT_NONCACHED    : vm_page_prot value when ((sync_mode & SYNC_MODE_MASK) == SYNC_MODE_NONCACHED   )
+ * _PGPROT_WRITECOMBINE : vm_page_prot value when ((sync_mode & SYNC_MODE_MASK) == SYNC_MODE_WRITECOMBINE)
+ * _PGPROT_DMACOHERENT  : vm_page_prot value when ((sync_mode & SYNC_MODE_MASK) == SYNC_MODE_DMACOHERENT )
+ */
+#if     defined(CONFIG_ARM)
+#define _PGPROT_NONCACHED(vm_page_prot)    pgprot_noncached(vm_page_prot)
+#define _PGPROT_WRITECOMBINE(vm_page_prot) pgprot_writecombine(vm_page_prot)
+#define _PGPROT_DMACOHERENT(vm_page_prot)  pgprot_dmacoherent(vm_page_prot)
+#elif   defined(CONFIG_ARM64)
+#define _PGPROT_NONCACHED(vm_page_prot)    pgprot_noncached(vm_page_prot)
+#define _PGPROT_WRITECOMBINE(vm_page_prot) pgprot_writecombine(vm_page_prot)
+#define _PGPROT_DMACOHERENT(vm_page_prot)  pgprot_writecombine(vm_page_prot)
+#else
+#define _PGPROT_NONCACHED(vm_page_prot)    pgprot_noncached(vm_page_prot)
+#define _PGPROT_WRITECOMBINE(vm_page_prot) pgprot_writecombine(vm_page_prot)
+#define _PGPROT_DMACOHERENT(vm_page_prot)  pgprot_writecombine(vm_page_prot)
+#endif
+
+/**
+ * udmabuf_device_file_mmap() - udmabuf device file memory map operation.
+ * @file:       Pointer to the file structure.
+ * @vma:        Pointer to the vm area structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_device_file_mmap(struct file *file, struct vm_area_struct* vma)
+{
+    struct udmabuf_device_data* this = file->private_data;
+
+    if (vma->vm_pgoff + vma_pages(vma) > (this->alloc_size >> PAGE_SHIFT))
+        return -EINVAL;
+
+    if ((file->f_flags & O_SYNC) | (this->sync_mode & SYNC_ALWAYS)) {
+        switch (this->sync_mode & SYNC_MODE_MASK) {
+            case SYNC_MODE_NONCACHED :
+                vma->vm_flags    |= VM_IO;
+                vma->vm_page_prot = _PGPROT_NONCACHED(vma->vm_page_prot);
+                break;
+            case SYNC_MODE_WRITECOMBINE :
+                vma->vm_flags    |= VM_IO;
+                vma->vm_page_prot = _PGPROT_WRITECOMBINE(vma->vm_page_prot);
+                break;
+            case SYNC_MODE_DMACOHERENT :
+                vma->vm_flags    |= VM_IO;
+                vma->vm_page_prot = _PGPROT_DMACOHERENT(vma->vm_page_prot);
+                break;
+            default :
+                break;
+        }
+    }
+    vma->vm_private_data = this;
+
+#if (USE_VMA_FAULT == 1)
+    {
+        unsigned long page_frame_num = (this->phys_addr >> PAGE_SHIFT) + vma->vm_pgoff;
+        if (pfn_valid(page_frame_num)) {
+            vma->vm_flags |= VM_PFNMAP;
+            vma->vm_ops    = &udmabuf_device_vm_ops;
+            udmabuf_device_vma_open(vma);
+            return 0;
+        }
+    }
+#endif
+
+    return dma_mmap_coherent(this->dma_dev, vma, this->virt_addr, this->phys_addr, this->alloc_size);
+}
+
+/**
+ * udmabuf_device_file_read() - udmabuf device file read operation.
+ * @file:       Pointer to the file structure.
+ * @buff:       Pointer to the user buffer.
+ * @count:      The number of bytes to be read.
+ * @ppos:       Pointer to the offset value.
+ * Return:      Transferd size.
+ */
+static ssize_t udmabuf_device_file_read(struct file* file, char __user* buff, size_t count, loff_t* ppos)
+{
+    struct udmabuf_device_data* this      = file->private_data;
+    int                         result    = 0;
+    size_t                      xfer_size;
+    size_t                      remain_size;
+    dma_addr_t                  phys_addr;
+    void*                       virt_addr;
+
+    if (mutex_lock_interruptible(&this->sem))
+        return -ERESTARTSYS;
+
+    if (*ppos >= this->size) {
+        result = 0;
+        goto return_unlock;
+    }
+
+    phys_addr = this->phys_addr + *ppos;
+    virt_addr = this->virt_addr + *ppos;
+    xfer_size = (*ppos + count >= this->size) ? this->size - *ppos : count;
+
+    if ((file->f_flags & O_SYNC) | (this->sync_mode & SYNC_ALWAYS))
+        dma_sync_single_for_cpu(this->dma_dev, phys_addr, xfer_size, DMA_FROM_DEVICE);
+
+    if ((remain_size = copy_to_user(buff, virt_addr, xfer_size)) != 0) {
+        result = 0;
+        goto return_unlock;
+    }
+
+    if ((file->f_flags & O_SYNC) | (this->sync_mode & SYNC_ALWAYS))
+        dma_sync_single_for_device(this->dma_dev, phys_addr, xfer_size, DMA_FROM_DEVICE);
+
+    *ppos += xfer_size;
+    result = xfer_size;
+ return_unlock:
+    mutex_unlock(&this->sem);
+    return result;
+}
+
+/**
+ * udmabuf_device_file_write() - udmabuf device file write operation.
+ * @file:       Pointer to the file structure.
+ * @buff:       Pointer to the user buffer.
+ * @count:      The number of bytes to be written.
+ * @ppos:       Pointer to the offset value
+ * Return:      Transferd size.
+ */
+static ssize_t udmabuf_device_file_write(struct file* file, const char __user* buff, size_t count, loff_t* ppos)
+{
+    struct udmabuf_device_data* this      = file->private_data;
+    int                         result    = 0;
+    size_t                      xfer_size;
+    size_t                      remain_size;
+    dma_addr_t                  phys_addr;
+    void*                       virt_addr;
+
+    if (mutex_lock_interruptible(&this->sem))
+        return -ERESTARTSYS;
+
+    if (*ppos >= this->size) {
+        result = 0;
+        goto return_unlock;
+    }
+
+    phys_addr = this->phys_addr + *ppos;
+    virt_addr = this->virt_addr + *ppos;
+    xfer_size = (*ppos + count >= this->size) ? this->size - *ppos : count;
+
+    if ((file->f_flags & O_SYNC) | (this->sync_mode & SYNC_ALWAYS))
+        dma_sync_single_for_cpu(this->dma_dev, phys_addr, xfer_size, DMA_TO_DEVICE);
+
+    if ((remain_size = copy_from_user(virt_addr, buff, xfer_size)) != 0) {
+        result = 0;
+        goto return_unlock;
+    }
+
+    if ((file->f_flags & O_SYNC) | (this->sync_mode & SYNC_ALWAYS))
+        dma_sync_single_for_device(this->dma_dev, phys_addr, xfer_size, DMA_TO_DEVICE);
+
+    *ppos += xfer_size;
+    result = xfer_size;
+ return_unlock:
+    mutex_unlock(&this->sem);
+    return result;
+}
+
+/**
+ * udmabuf_device_file_llseek() - udmabuf device file llseek operation.
+ * @file:       Pointer to the file structure.
+ * @offset:     File offset to seek.
+ * @whence:     Type of seek.
+ * Return:      The new position.
+ */
+static loff_t udmabuf_device_file_llseek(struct file* file, loff_t offset, int whence)
+{
+    struct udmabuf_device_data* this = file->private_data;
+    loff_t                      new_pos;
+
+    switch (whence) {
+        case 0 : /* SEEK_SET */
+            new_pos = offset;
+            break;
+        case 1 : /* SEEK_CUR */
+            new_pos = file->f_pos + offset;
+            break;
+        case 2 : /* SEEK_END */
+            new_pos = this->size  + offset;
+            break;
+        default:
+            return -EINVAL;
+    }
+    if (new_pos < 0         ){return -EINVAL;}
+    if (new_pos > this->size){return -EINVAL;}
+    file->f_pos = new_pos;
+    return new_pos;
+}
+
+/**
+ * udmabuf device file operation table.
+ */
+static const struct file_operations udmabuf_device_file_ops = {
+    .owner   = THIS_MODULE,
+    .open    = udmabuf_device_file_open,
+    .release = udmabuf_device_file_release,
+    .mmap    = udmabuf_device_file_mmap,
+    .read    = udmabuf_device_file_read,
+    .write   = udmabuf_device_file_write,
+    .llseek  = udmabuf_device_file_llseek,
+};
+
+/**
+ * DOC: Udmabuf Device Data Operations
+ *
+ * This section defines the operation of udmabuf device data.
+ *
+ * * udmabuf_device_ida         - Udmabuf Device Minor Number allocator variable.
+ * * udmabuf_device_number      - Udmabuf Device Major Number.
+ * * udmabuf_device_create()    - Create udmabuf device data.
+ * * udmabuf_device_setup()     - Setup the udmabuf device data.
+ * * udmabuf_device_info()      - Print infomation the udmabuf device data.
+ * * udmabuf_device_destroy()   - Destroy the udmabuf device data.
+ */
+static DEFINE_IDA(udmabuf_device_ida);
+static dev_t      udmabuf_device_number = 0;
+
+/**
+ * udmabuf_device_create() -  Create udmabuf device data.
+ * @name:       device name   or NULL.
+ * @parent:     parent device or NULL.
+ * @minor:      minor_number  or -1 or -2.
+ * Return:      Pointer to the udmabuf device data or NULL.
+ */
+static struct udmabuf_device_data* udmabuf_device_create(const char* name, struct device* parent, int minor)
+{
+    struct udmabuf_device_data* this     = NULL;
+    unsigned int                done     = 0;
+    const unsigned int          DONE_ALLOC_MINOR   = (1 << 0);
+    const unsigned int          DONE_CHRDEV_ADD    = (1 << 1);
+    const unsigned int          DONE_DEVICE_CREATE = (1 << 3);
+    const unsigned int          DONE_SET_DMA_DEV   = (1 << 4);
+    /*
+     * allocate device minor number
+     */
+    {
+        if ((0 <= minor) && (minor < DEVICE_MAX_NUM)) {
+            if (ida_simple_get(&udmabuf_device_ida, minor, minor+1, GFP_KERNEL) < 0) {
+                printk(KERN_ERR "couldn't allocate minor number(=%d).\n", minor);
+                goto failed;
+            }
+        } else if(minor < 0) {
+            if ((minor = ida_simple_get(&udmabuf_device_ida, 0, DEVICE_MAX_NUM, GFP_KERNEL)) < 0) {
+                printk(KERN_ERR "couldn't allocate new minor number. return=%d.\n", minor);
+                goto failed;
+            }
+        } else {
+                printk(KERN_ERR "invalid minor number(=%d), valid range is 0 to %d\n", minor, DEVICE_MAX_NUM-1);
+                goto failed;
+        }
+        done |= DONE_ALLOC_MINOR;
+    }
+    /*
+     * create (udmabuf_device_data*) this.
+     */
+    {
+        this = kzalloc(sizeof(*this), GFP_KERNEL);
+        if (IS_ERR_OR_NULL(this)) {
+            int retval = PTR_ERR(this);
+            this = NULL;
+            printk(KERN_ERR "kzalloc() failed. return=%d\n", retval);
+            goto failed;
+        }
+    }
+    /*
+     * set device_number
+     */
+    {
+        this->device_number = MKDEV(MAJOR(udmabuf_device_number), minor);
+    }
+    /*
+     * register /sys/class/udmabuf/<name>
+     */
+    {
+        if (name == NULL) {
+            this->sys_dev = device_create(udmabuf_sys_class,
+                                          parent,
+                                          this->device_number,
+                                          (void *)this,
+                                          DEVICE_NAME_FORMAT, MINOR(this->device_number));
+        } else {
+            this->sys_dev = device_create(udmabuf_sys_class,
+                                          parent,
+                                          this->device_number,
+                                          (void *)this,
+                                         "%s", name);
+        }
+        if (IS_ERR_OR_NULL(this->sys_dev)) {
+            int retval = PTR_ERR(this->sys_dev);
+            this->sys_dev = NULL;
+            printk(KERN_ERR "device_create() failed. return=%d\n", retval);
+            goto failed;
+        }
+        done |= DONE_DEVICE_CREATE;
+    }
+    /*
+     * add chrdev.
+     */
+    {
+        int retval;
+        cdev_init(&this->cdev, &udmabuf_device_file_ops);
+        this->cdev.owner = THIS_MODULE;
+        if ((retval = cdev_add(&this->cdev, this->device_number, 1)) != 0) {
+            printk(KERN_ERR "cdev_add() failed. return=%d\n", retval);
+            goto failed;
+        }
+        done |= DONE_CHRDEV_ADD;
+    }
+    /*
+     * set dma_dev
+     */
+    {
+        if (parent != NULL)
+            this->dma_dev = get_device(parent);
+        else
+            this->dma_dev = get_device(this->sys_dev);
+        /*
+         * set this->dma_dev->dma_mask
+         */
+        if (this->dma_dev->dma_mask == NULL) {
+            this->dma_dev->dma_mask = &this->dma_dev->coherent_dma_mask;
+        }
+        /*
+         * set *this->dma_dev->dma_mask and this->dma_dev->coherent_dma_mask
+         * Executing dma_set_mask_and_coherent() before of_dma_configure() may fail.
+         * Because dma_set_mask_and_coherent() will fail unless dev->dma_ops is set.
+         * When dma_set_mask_and_coherent() fails, it is forcefuly setting the dma-mask value.
+         */
+        if (*this->dma_dev->dma_mask == 0) {
+            int retval = dma_set_mask_and_coherent(this->dma_dev, DMA_BIT_MASK(dma_mask_bit));
+            if (retval != 0) {
+                printk(KERN_WARNING "dma_set_mask_and_coherent(DMA_BIT_MASK(%d)) failed. return=(%d)\n", dma_mask_bit, retval);
+                *this->dma_dev->dma_mask         = DMA_BIT_MASK(dma_mask_bit);
+                this->dma_dev->coherent_dma_mask = DMA_BIT_MASK(dma_mask_bit);
+            }
+        }
+        done |= DONE_SET_DMA_DEV;
+    }
+    /*
+     * initialize other variables.
+     */
+    {
+        this->size            = 0;
+        this->alloc_size      = 0;
+        this->sync_mode       = SYNC_MODE_NONCACHED;
+        this->sync_offset     = 0;
+        this->sync_size       = 0;
+        this->sync_direction  = 0;
+        this->sync_owner      = 0;
+        this->sync_for_cpu    = 0;
+        this->sync_for_device = 0;
+    }
+#if (USE_OF_RESERVED_MEM == 1)
+    {
+        this->of_reserved_mem = 0;
+    }
+#endif
+#if ((UDMABUF_DEBUG == 1) && (USE_VMA_FAULT == 1))
+    {
+        this->debug_vma       = 0;
+    }
+#endif
+    mutex_init(&this->sem);
+
+    return this;
+
+ failed:
+    if (done & DONE_SET_DMA_DEV  ) { put_device(this->dma_dev);}
+    if (done & DONE_CHRDEV_ADD   ) { cdev_del(&this->cdev); }
+    if (done & DONE_DEVICE_CREATE) { device_destroy(udmabuf_sys_class, this->device_number);}
+    if (done & DONE_ALLOC_MINOR  ) { ida_simple_remove(&udmabuf_device_ida, minor);}
+    if (this != NULL)              { kfree(this); }
+    return NULL;
+}
+
+/**
+ * udmabuf_device_setup() - Setup the udmabuf device data.
+ * @this:       Pointer to the udmabuf device data.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_device_setup(struct udmabuf_device_data* this)
+{
+    if (!this)
+        return -ENODEV;
+    /*
+     * setup buffer size and allocation size
+     */
+    this->alloc_size = ((this->size + ((1 << PAGE_SHIFT) - 1)) >> PAGE_SHIFT) << PAGE_SHIFT;
+    /*
+     * dma buffer allocation 
+     */
+    this->virt_addr  = dma_alloc_coherent(this->dma_dev, this->alloc_size, &this->phys_addr, GFP_KERNEL);
+    if (IS_ERR_OR_NULL(this->virt_addr)) {
+        int retval = PTR_ERR(this->virt_addr);
+        printk(KERN_ERR "dma_alloc_coherent(size=%zu) failed. return(%d)\n", this->alloc_size, retval);
+        this->virt_addr = NULL;
+        return (retval == 0) ? -ENOMEM : retval;
+    }
+    return 0;
+}
+
+/**
+ * udmabuf_device_info() - Print infomation the udmabuf device data structure.
+ * @this:       Pointer to the udmabuf device data structure.
+ */
+static void udmabuf_device_info(struct udmabuf_device_data* this)
+{
+    dev_info(this->sys_dev, "driver version = %s\n"  , DRIVER_VERSION);
+    dev_info(this->sys_dev, "major number   = %d\n"  , MAJOR(this->device_number));
+    dev_info(this->sys_dev, "minor number   = %d\n"  , MINOR(this->device_number));
+    dev_info(this->sys_dev, "phys address   = %pad\n", &this->phys_addr);
+    dev_info(this->sys_dev, "buffer size    = %zu\n" , this->alloc_size);
+    if (DMA_INFO_ENABLE) {
+        dev_info(this->sys_dev, "dma device     = %s\n"       , dev_name(this->dma_dev));
+#if defined(IS_DMA_COHERENT)
+        dev_info(this->sys_dev, "dma coherent   = %d\n"       , IS_DMA_COHERENT(this->dma_dev));
+#endif
+        dev_info(this->sys_dev, "dma mask       = 0x%016llx\n", dma_get_mask(this->dma_dev));
+    }
+}
+
+/**
+ * udmabuf_device_destroy() -  Destroy the udmabuf device data.
+ * @this:       Pointer to the udmabuf device data.
+ * Return:      Success(=0) or error status(<0).
+ *
+ * Unregister the device after releasing the resources.
+ */
+static int udmabuf_device_destroy(struct udmabuf_device_data* this)
+{
+    if (!this)
+        return -ENODEV;
+
+    if (this->virt_addr != NULL) {
+        dma_free_coherent(this->dma_dev, this->alloc_size, this->virt_addr, this->phys_addr);
+        this->virt_addr = NULL;
+    }
+    put_device(this->dma_dev);
+    cdev_del(&this->cdev);
+    device_destroy(udmabuf_sys_class, this->device_number);
+    ida_simple_remove(&udmabuf_device_ida, MINOR(this->device_number));
+    kfree(this);
+    return 0;
+}
+
+/**
+ * DOC: Udmabuf Platform Device.
+ *
+ * This section defines the udmabuf platform device list.
+ *
+ * * struct udmabuf_platform_device       - udmabuf platform device structure.
+ * * udmabuf_platform_device_list         - list of udmabuf platform device structure.
+ * * udmabuf_platform_device_sem          - semaphore of udmabuf platform device list.
+ * * udmabuf_platform_device_create()     - Create udmabuf platform device and add to list.
+ * * udmabuf_platform_device_remove()     - Remove udmabuf platform device and delete from list.
+ * * udmabuf_platform_device_remove_all() - Remove all udmabuf platform devices and clear list.
+ * * udmabuf_platform_device_search()     - Search udmabuf platform device from list by name or number.
+ * * udmabuf_get_device_name_property()   - Get "device-name"  property from udmabuf device.
+ * * udmabuf_get_size_property()          - Get "buffer-size"  property from udmabuf device.
+ * * udmabuf_get_minor_number_property()  - Get "minor-number" property from udmabuf device.
+ */
+
+#if (USE_DEV_PROPERTY != 0)
+#include <linux/property.h>
+#endif
+
+/**
+ * struct udmabuf_platform_device - udmabuf platform device structure.
+ */
+struct udmabuf_platform_device {
+    struct device*       dev;
+#if (USE_DEV_PROPERTY == 0)
+    const char*          device_name;
+    u32                  minor_number;
+    u64                  buffer_size;
+#endif
+    struct list_head     list;
+};
+
+/**
+ * udmabuf_platform_device_list   - list of udmabuf static device structure.
+ * udmabuf_platform_device_sem    - semaphore of udmabuf platform device list.
+ */
+static struct list_head udmabuf_platform_device_list;
+static struct mutex     udmabuf_platform_device_sem;
+
+/**
+ * udmabuf_get_device_name_property()  - Get "device-name"  property from udmabuf device.
+ * @dev:        handle to the device structure.
+ * @name:       address of device name.
+ * @lock:       use mutex_lock()/mutex_unlock()
+ * Return:      Success(=0) or error status(<0).
+ */
+static int  udmabuf_get_device_name_property(struct device *dev, const char** name, bool lock)
+{
+#if (USE_DEV_PROPERTY == 0)
+    int                             status = -1;
+    struct udmabuf_platform_device* plat;
+
+    if (lock)
+        mutex_lock(&udmabuf_platform_device_sem);
+    list_for_each_entry(plat, &udmabuf_platform_device_list, list) {
+        if (plat->dev == dev) {
+            if (plat->device_name == NULL) {
+                status = -1;
+            } else {
+                *name  = plat->device_name;
+                status = 0;
+            }
+            break;
+        }
+    }
+    if (lock)
+        mutex_unlock(&udmabuf_platform_device_sem);
+    return status;
+#else
+    return device_property_read_string(dev, "device-name", name);
+#endif
+}
+
+/**
+ * udmabuf_get_size_property()         - Get "buffer-size"  property from udmabuf device.
+ * @dev:        handle to the device structure.
+ * @value:      address of buffer size value.
+ * @lock:       use mutex_lock()/mutex_unlock()
+ * Return:      Success(=0) or error status(<0).
+ */
+static int  udmabuf_get_size_property(struct device *dev, u64* value, bool lock)
+{
+#if (USE_DEV_PROPERTY == 0)
+    int                             status = -1;
+    struct udmabuf_platform_device* plat;
+
+    if (lock)
+        mutex_lock(&udmabuf_platform_device_sem);
+    list_for_each_entry(plat, &udmabuf_platform_device_list, list) {
+        if (plat->dev == dev) {
+            *value = plat->buffer_size;
+            status = 0;
+            break;
+        }
+    }
+    if (lock)
+        mutex_unlock(&udmabuf_platform_device_sem);
+    return status;
+#else
+    return device_property_read_u64(dev, "size", value);
+#endif
+}
+
+/**
+ * udmabuf_get_minor_number_property() - Get "minor-number" property from udmabuf device.
+ * @dev:        handle to the device structure.
+ * @value:      address of minor number value.
+ * @lock:       use mutex_lock()/mutex_unlock()
+ * Return:      Success(=0) or error status(<0).
+ */
+
+static int  udmabuf_get_minor_number_property(struct device *dev, u32* value, bool lock)
+{
+#if (USE_DEV_PROPERTY == 0)
+    int                             status = -1;
+    struct udmabuf_platform_device* plat;
+
+    if (lock)
+        mutex_lock(&udmabuf_platform_device_sem);
+    list_for_each_entry(plat, &udmabuf_platform_device_list, list) {
+        if (plat->dev == dev) {
+            *value = plat->minor_number;
+            status = 0;
+            break;
+        }
+    }
+    if (lock) 
+        mutex_unlock(&udmabuf_platform_device_sem);
+    return status;
+#else
+    return device_property_read_u32(dev, "minor-number", value);
+#endif
+}
+
+/**
+ * udmabuf_platform_device_search()    - Search udmabuf platform device from list by name or number.
+ * @name:       device name or NULL.
+ * @id:         device id.
+ * Return:      Pointer to the udmabuf_platform_device or NULL.
+ */
+static struct udmabuf_platform_device* udmabuf_platform_device_search(const char* name, int id)
+{
+    struct udmabuf_platform_device* plat;
+    struct udmabuf_platform_device* found_plat = NULL;
+    mutex_lock(&udmabuf_platform_device_sem);
+    list_for_each_entry(plat, &udmabuf_platform_device_list, list) {
+        bool found_by_name = true;
+        bool found_by_id   = true;
+        if (name != NULL) {
+            const char* device_name;
+            found_by_name = false;
+            if (udmabuf_get_device_name_property(plat->dev, &device_name, false) == 0) 
+                if (strcmp(name, device_name) == 0)
+                    found_by_name = true;
+        }
+        if (id >= 0) {
+            u32 minor_number;
+            found_by_id = false;
+            if (udmabuf_get_minor_number_property(plat->dev, &minor_number, false) == 0) 
+                if (id == minor_number)
+                    found_by_id = true;
+        }
+        if ((found_by_name == true) && (found_by_id == true))
+            found_plat = plat;
+    }
+    mutex_unlock(&udmabuf_platform_device_sem);
+    return found_plat;
+}
+
+/**
+ * udmabuf_platform_device_create() - Create udmabuf platform device and add to list.
+ * @name:       device name or NULL.
+ * @id:         device id.
+ * @size:       buffer size.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_platform_device_create(const char* name, int id, unsigned int size)
+{
+    struct platform_device*         pdev       = NULL;
+    struct udmabuf_platform_device* plat       = NULL;
+    int                             retval     = 0;
+    bool                            list_added = false;
+
+    if (size == 0)
+        return -EINVAL;
+
+    pdev = platform_device_alloc(DRIVER_NAME, id);
+    if (IS_ERR_OR_NULL(pdev)) {
+        retval = PTR_ERR(pdev);
+        pdev   = NULL;
+        printk(KERN_ERR "platform_device_alloc(%s,%d) failed. return=%d\n", DRIVER_NAME, id, retval);
+        goto failed;
+    }
+
+    if (!pdev->dev.dma_mask)
+        pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+    pdev->dev.coherent_dma_mask = DMA_BIT_MASK(dma_mask_bit);
+    *pdev->dev.dma_mask         = DMA_BIT_MASK(dma_mask_bit);
+
+    plat = kzalloc(sizeof(*plat), GFP_KERNEL);
+    if (IS_ERR_OR_NULL(plat)) {
+        retval = PTR_ERR(plat);
+        plat   = NULL;
+        dev_err(&pdev->dev, "kzalloc() failed. return=%d\n", retval);
+        goto failed;
+    }
+
+#if (USE_DEV_PROPERTY == 0)
+    {
+        plat->device_name  = (name != NULL) ? kstrdup(name, GFP_KERNEL) : NULL;
+        plat->minor_number = id;
+        plat->buffer_size  = size;
+    }
+#else
+    {
+        struct property_entry   props_list[] = {
+            PROPERTY_ENTRY_STRING("device-name" , name),
+            PROPERTY_ENTRY_U64(   "size"        , size),
+            PROPERTY_ENTRY_U32(   "minor-number", id  ),
+            {},
+        };
+        struct property_entry* props = (name != NULL) ? &props_list[0] : &props_list[1];
+#if     (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
+        {
+            retval = device_add_properties(&pdev->dev, props);
+            if (retval != 0) {
+                dev_err(&pdev->dev, "device_add_properties failed. return=%d\n", retval);
+                goto failed;
+            }
+        }
+#else
+        {
+            const struct property_set pset = {
+                .properties = props,
+            };
+            retval = device_add_property_set(&pdev->dev, &pset);
+            if (retval != 0) {
+                dev_err(&pdev->dev, "device_add_propertiy_set failed. return=%d\n", retval);
+                goto failed;
+            }
+        }
+#endif
+    }
+#endif
+
+    plat->dev  = &pdev->dev;
+    mutex_lock(&udmabuf_platform_device_sem);
+    list_add_tail(&plat->list, &udmabuf_platform_device_list);
+    list_added = true;
+    mutex_unlock(&udmabuf_platform_device_sem);
+    
+    retval = platform_device_add(pdev);
+    if (retval != 0) {
+        dev_err(&pdev->dev, "platform_device_add failed. return=%d\n", retval);
+        goto failed;
+    }
+
+    return 0;
+
+ failed:
+    if (list_added == true) {
+        mutex_lock(&udmabuf_platform_device_sem);
+        list_del(&plat->list);
+        mutex_unlock(&udmabuf_platform_device_sem);
+    }
+    if (pdev != NULL) {
+        platform_device_put(pdev);
+    }
+    if (plat != NULL) {
+#if (USE_DEV_PROPERTY == 0)
+        if (plat->device_name != NULL)
+            kfree(plat->device_name);
+#endif
+        kfree(plat);
+    }
+    return retval;
+}
+
+/**
+ * udmabuf_platform_device_remove() - Remove udmabuf platform device and delete from list.
+ * @plat:       udmabuf_platform_device*
+ */
+static void udmabuf_platform_device_remove(struct udmabuf_platform_device* plat)
+{
+    struct device*           dev  = plat->dev;
+    struct platform_device*  pdev = to_platform_device(dev);
+    platform_device_del(pdev);
+    platform_device_put(pdev);
+    mutex_lock(&udmabuf_platform_device_sem);
+    list_del(&plat->list);
+    mutex_unlock(&udmabuf_platform_device_sem);
+#if (USE_DEV_PROPERTY == 0)
+    if (plat->device_name != NULL)
+        kfree(plat->device_name);
+#endif
+    kfree(plat);
+}
+
+/**
+ * udmabuf_platform_device_remove_all() - Remove all udmabuf platform devices and clear list.
+ */
+static void udmabuf_platform_device_remove_all(void)
+{
+    while(!list_empty(&udmabuf_platform_device_list)) {
+        struct udmabuf_platform_device* plat = list_first_entry(&udmabuf_platform_device_list, typeof(*(plat)), list);
+        udmabuf_platform_device_remove(plat);
+    }
+}
+
+/**
+ * DOC: Udmabuf Static Devices.
+ *
+ * This section defines the udmabuf device to be created with arguments when loaded
+ * into ther kernel with insmod.
+ *
+ */
+#define DEFINE_UDMABUF_STATIC_DEVICE_PARAM(__num)                        \
+    static int       udmabuf ## __num = 0;                               \
+    module_param(    udmabuf ## __num, int, S_IRUGO);                    \
+    MODULE_PARM_DESC(udmabuf ## __num, DRIVER_NAME #__num " buffer size");
+
+#define CALL_UDMABUF_STATIC_DEVICE_CREATE(__num)                         \
+    if (udmabuf ## __num != 0) {                                         \
+        ida_simple_remove(&udmabuf_device_ida, __num);                   \
+        udmabuf_platform_device_create(NULL, __num, udmabuf ## __num);   \
+    }
+
+#define CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(__num)           \
+    if (udmabuf ## __num != 0) {                                         \
+        ida_simple_get(&udmabuf_device_ida, __num, __num+1, GFP_KERNEL); \
+    }
+
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(0);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(1);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(2);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(3);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(4);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(5);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(6);
+DEFINE_UDMABUF_STATIC_DEVICE_PARAM(7);
+
+/**
+ * udmabuf_static_device_reserve_minor_number_all() - Reserve udmabuf static device's minor-number.
+ */
+static void udmabuf_static_device_reserve_minor_number_all(void)
+{
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(0);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(1);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(2);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(3);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(4);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(5);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(6);
+    CALL_UDMABUF_STATIC_DEVICE_RESERVE_MINOR_NUMBER(7);
+}
+
+/**
+ * udmabuf_static_device_create_all() - Create udmabuf static devices.
+ */
+static void udmabuf_static_device_create_all(void)
+{
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(0);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(1);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(2);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(3);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(4);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(5);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(6);
+    CALL_UDMABUF_STATIC_DEVICE_CREATE(7);
+}
+
+/**
+ * DOC: Udmabuf Device Driver probe/remove section.
+ *
+ * This section defines the udmabuf device driver.
+ *
+ * * udmabuf_device_probe()                      - Probe  call for the device driver.
+ * * udmabuf_device_remove()                     - Remove call for the device driver.
+ */
+
+/**
+ * udmabuf_device_remove()   - Remove udmabuf device driver.
+ * @dev:        handle to the device structure.
+ * @devdata     Pointer to the udmabuf device data structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_device_remove(struct device *dev, struct udmabuf_device_data *devdata)
+{
+    int retval = 0;
+
+    if (devdata != NULL) {
+#if (USE_OF_RESERVED_MEM == 1)
+        bool of_reserved_mem = devdata->of_reserved_mem;
+#endif
+        retval = udmabuf_device_destroy(devdata);
+        dev_set_drvdata(dev, NULL);
+#if (USE_OF_RESERVED_MEM == 1)
+        if (of_reserved_mem) {
+            of_reserved_mem_device_release(dev);
+        }
+#endif
+    } else {
+        retval = -ENODEV;
+    }
+    return retval;
+}
+
+/**
+ * of_property_read_ulong() -  Find and read a unsigned long intger from a property.
+ * @node:       device node which the property value is to be read.
+ * @propname:   name of property to be searched.
+ * @out_value:  pointer to return value, modified only if return value is 0.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int of_property_read_ulong(const struct device_node* node, const char* propname, u64* out_value)
+{
+    u32    u32_value;
+    u64    u64_value;
+    int    retval;
+
+    if ((retval = of_property_read_u64(node, propname, &u64_value)) == 0) {
+        *out_value = u64_value;
+        return 0;
+    }
+      
+    if ((retval = of_property_read_u32(node, propname, &u32_value)) == 0) {
+        *out_value = (u64)u32_value;
+        return 0;
+    }
+      
+    return retval;
+}
+
+/**
+ * udmabuf_device_probe() -  Probe call for the device.
+ * @dev:        handle to the device structure.
+ * Return:      Success(=0) or error status(<0).
+ *
+ * It does all the memory allocation and registration for the device.
+ */
+static int udmabuf_device_probe(struct device *dev)
+{
+    int                         retval       = 0;
+    int                         prop_status  = 0;
+    u32                         u32_value    = 0;
+    u64                         u64_value    = 0;
+    size_t                      size         = 0;
+    int                         minor_number = -1;
+    struct udmabuf_device_data* device_data  = NULL;
+    const char*                 device_name  = NULL;
+
+    /*
+     * size property
+     */
+    if        ((prop_status = udmabuf_get_size_property(dev, &u64_value, true)) == 0) {
+        size = u64_value;
+    } else if ((prop_status = of_property_read_ulong(dev->of_node, "size", &u64_value)) == 0) {
+        size = u64_value;
+    } else {
+        dev_err(dev, "invalid property size. status=%d\n", prop_status);
+        retval = -ENODEV;
+        goto failed;
+    }
+    if (size <= 0) {
+        dev_err(dev, "invalid size, size=%zu\n", size);
+        retval = -ENODEV;
+        goto failed;
+    }
+    /*
+     * minor-number property
+     */
+    if        (udmabuf_get_minor_number_property(dev, &u32_value, true) == 0) {
+        minor_number = u32_value;
+    } else if (of_property_read_u32(dev->of_node, "minor-number", &u32_value) == 0) {
+        minor_number = u32_value;
+    } else {
+        minor_number = -1;
+    }
+    /*
+     * device-name property
+     */
+    if (udmabuf_get_device_name_property(dev, &device_name, true) != 0)
+        device_name = of_get_property(dev->of_node, "device-name", NULL);
+    if (IS_ERR_OR_NULL(device_name)) {
+        if (minor_number < 0)
+            device_name = dev_name(dev);
+        else
+            device_name = NULL;
+    }
+    /*
+     * udmabuf_device_create()
+     */
+    device_data = udmabuf_device_create(device_name, dev, minor_number);
+    if (IS_ERR_OR_NULL(device_data)) {
+        retval = PTR_ERR(device_data);
+        dev_err(dev, "driver create failed. return=%d\n", retval);
+        device_data = NULL;
+        retval = (retval == 0) ? -EINVAL : retval;
+        goto failed;
+    }
+    dev_set_drvdata(dev, device_data);
+    /*
+     * set size
+     */
+    device_data->size = size;
+    /*
+     * dma-mask property
+     * If you want to set dma-mask, do it before of_dma_configure().
+     * Because of_dma_configure() needs the value of dev->coherent_dma_mask.
+     * However, executing dma_set_mask_and_coherent() before of_dma_configure() may fail.
+     * Because dma_set_mask_and_coherent() will fail unless dev->dma_ops is set.
+     * When dma_set_mask_and_coherent() fails, it is forcefuly setting the dma-mask value.
+     */
+    if (of_property_read_u32(dev->of_node, "dma-mask", &u32_value) == 0) {
+        if ((u32_value > 64) || (u32_value < 12)) {
+            dev_err(dev, "invalid dma-mask property value=%d\n", u32_value);
+            goto failed;
+        }
+        retval = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(u32_value));
+        if (retval != 0) {
+            dev_info(dev, "dma_set_mask_and_coherent(DMA_BIT_MASK(%d)) failed. return=%d\n", u32_value, retval);
+            retval = 0;
+            *dev->dma_mask         = DMA_BIT_MASK(u32_value);
+            dev->coherent_dma_mask = DMA_BIT_MASK(u32_value);
+        }
+    }
+    /*
+     * of_reserved_mem_device_init()
+     */
+#if (USE_OF_RESERVED_MEM == 1)
+    if (dev->of_node != NULL) {
+        retval = of_reserved_mem_device_init(dev);
+        if (retval == 0) {
+            device_data->of_reserved_mem = 1;
+        } else if (retval != -ENODEV) {
+            dev_err(dev, "of_reserved_mem_device_init failed. return=%d\n", retval);
+            goto failed;
+        }
+    }
+#endif
+#if (USE_OF_DMA_CONFIG == 1)
+    /*
+     * of_dma_configure()
+     * - set pdev->dev->dma_mask
+     * - set pdev->dev->coherent_dma_mask
+     * - call of_dma_is_coherent()
+     * - call arch_setup_dma_ops()
+     */
+#if ((USE_OF_RESERVED_MEM == 1) && (LINUX_VERSION_CODE < KERNEL_VERSION(5, 1, 0)))
+    /* 
+     * Under less than Linux Kernel 5.1, if "memory-region" property is specified, 
+     * of_dma_configure() will not be executed.
+     * Because in that case, it is already executed in of_reserved_mem_device_init().
+     */
+    if (device_data->of_reserved_mem == 0)
+#endif
+    {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 18, 0))
+        retval = of_dma_configure(dev, dev->of_node, true);
+#else
+        retval = of_dma_configure(dev, dev->of_node);
+#endif
+        if (retval != 0) {
+            dev_err(dev, "of_dma_configure failed. return=%d\n", retval);
+            goto failed;
+        }
+#else
+        of_dma_configure(dev, dev->of_node);
+#endif
+    }
+#endif
+    /*
+     * sync-mode property
+     */
+    if (of_property_read_u32(dev->of_node, "sync-mode", &u32_value) == 0) {
+        if ((u32_value < SYNC_MODE_MIN) || (u32_value > SYNC_MODE_MAX)) {
+            dev_err(dev, "invalid sync-mode property value=%d\n", u32_value);
+            goto failed;
+        }
+        device_data->sync_mode &= ~SYNC_MODE_MASK;
+        device_data->sync_mode |= (int)u32_value;
+    }
+    /*
+     * sync-always property
+     */
+    if (of_property_read_bool(dev->of_node, "sync-always")) {
+        device_data->sync_mode |= SYNC_ALWAYS;
+    }
+    /*
+     * sync-direction property
+     */
+    if (of_property_read_u32(dev->of_node, "sync-direction", &u32_value) == 0) {
+        if (u32_value > 2) {
+            dev_err(dev, "invalid sync-direction property value=%d\n", u32_value);
+            goto failed;
+        }
+        device_data->sync_direction = (int)u32_value;
+    }
+    /*
+     * sync-offset property
+     */
+    if (of_property_read_ulong(dev->of_node, "sync-offset", &u64_value) == 0) {
+        if (u64_value >= device_data->size) {
+            dev_err(dev, "invalid sync-offset property value=%llu\n", u64_value);
+            goto failed;
+        }
+        device_data->sync_offset = (int)u64_value;
+    }
+    /*
+     * sync-size property
+     */
+    if (of_property_read_ulong(dev->of_node, "sync-size", &u64_value) == 0) {
+        if (device_data->sync_offset + u64_value > device_data->size) {
+            dev_err(dev, "invalid sync-size property value=%llu\n", u64_value);
+            goto failed;
+        }
+        device_data->sync_size = (size_t)u64_value;
+    } else {
+        device_data->sync_size = device_data->size;
+    }
+    /*
+     * udmabuf_device_setup()
+     */
+    retval = udmabuf_device_setup(device_data);
+    if (retval) {
+        dev_err(dev, "driver setup failed. return=%d\n", retval);
+        goto failed;
+    }
+
+    if (info_enable) {
+        udmabuf_device_info(device_data);
+    }
+
+    return 0;
+
+failed:
+    udmabuf_device_remove(dev, device_data);
+
+    return retval;
+}
+
+/**
+ * DOC: Udmabuf Platform Driver
+ *
+ * This section defines the udmabuf platform driver.
+ *
+ * * udmabuf_platform_driver_probe()   - Probe call for the device.
+ * * udmabuf_platform_driver_remove()  - Remove call for the device.
+ * * udmabuf_of_match                  - Open Firmware Device Identifier Matching Table.
+ * * udmabuf_platform_driver           - Platform Driver Structure.
+ */
+
+/**
+ * udmabuf_platform_driver_probe() -  Probe call for the device.
+ * @pdev:       Handle to the platform device structure.
+ * Return:      Success(=0) or error status(<0).
+ *
+ * It does all the memory allocation and registration for the device.
+ */
+static int udmabuf_platform_driver_probe(struct platform_device *pdev)
+{
+    int retval = 0;
+
+    dev_dbg(&pdev->dev, "driver probe start.\n");
+
+    retval = udmabuf_device_probe(&pdev->dev);
+    
+    if (info_enable) {
+        dev_info(&pdev->dev, "driver installed.\n");
+    }
+    return retval;
+}
+/**
+ * udmabuf_platform_driver_remove() -  Remove call for the device.
+ * @pdev:       Handle to the platform device structure.
+ * Return:      Success(=0) or error status(<0).
+ *
+ * Unregister the device after releasing the resources.
+ */
+static int udmabuf_platform_driver_remove(struct platform_device *pdev)
+{
+    struct udmabuf_device_data* this   = dev_get_drvdata(&pdev->dev);
+    int                         retval = 0;
+
+    dev_dbg(&pdev->dev, "driver remove start.\n");
+
+    retval = udmabuf_device_remove(&pdev->dev, this);
+
+    if (info_enable) {
+        dev_info(&pdev->dev, "driver removed.\n");
+    }
+    return retval;
+}
+
+/**
+ * Open Firmware Device Identifier Matching Table
+ */
+static struct of_device_id udmabuf_of_match[] = {
+    { .compatible = "ikwzm,u-dma-buf", },
+    { /* end of table */}
+};
+MODULE_DEVICE_TABLE(of, udmabuf_of_match);
+
+/**
+ * Platform Driver Structure
+ */
+static struct platform_driver udmabuf_platform_driver = {
+    .probe  = udmabuf_platform_driver_probe,
+    .remove = udmabuf_platform_driver_remove,
+    .driver = {
+        .owner = THIS_MODULE,
+        .name  = DRIVER_NAME,
+        .of_match_table = udmabuf_of_match,
+    },
+};
+
+/**
+ * DOC: udmabuf manager device
+ *
+ * * enum udmabuf_manager_state        - udmabuf manager state enumeration.
+ * * struct udmabuf_manager_data       - udmabuf manager data structure.
+ * * udmabuf_manager_state_clear()     - udmabuf manager state clear.
+ * * udmabuf_manager_buffer_overflow() - udmabuf manager check buffer overflow.
+ * * udmabuf_manager_parse()           - udmabuf manager parse buffer.
+ * * udmabuf_manager_file_open()       - udmabuf manager file open operation.
+ * * udmabuf_manager_file_release()    - udmabuf manager file release operation.
+ * * udmabuf_manager_file_write()      - udmabuf manager file write operation.
+ * * udmabuf_manager_file_ops          - udmabuf manager file operation table.
+ * * udmabuf_manager_device            - udmabuf manager misc device structure.
+ * * udmabuf_manager_device_registerd  - udmabuf manager device registerd flag.
+ * * 
+ */
+#if (UDMABUF_MGR_ENABLE == 1)
+#include <linux/miscdevice.h>
+
+#define UDMABUF_MGR_BUFFER_SIZE 256
+
+/**
+ * enum   udmabuf_manager_state - udmabuf manager state enumeration.
+ */
+enum   udmabuf_manager_state {
+    udmabuf_manager_init_state    ,
+    udmabuf_manager_create_command,
+    udmabuf_manager_delete_command,
+    udmabuf_manager_parse_error   ,
+};
+
+/**
+ * struct udmabuf_manager_data - udmabuf manager data structure.
+ */
+struct udmabuf_manager_data {
+    const char*                  device_name;
+    int                          minor_number;
+    unsigned int                 size;
+    enum udmabuf_manager_state   state;
+    unsigned int                 buffer_offset;
+    char                         buffer[UDMABUF_MGR_BUFFER_SIZE];
+};
+
+/**
+ * udmabuf_manager_buffer_overflow() - udmabuf manager check buffer overflow.
+ * @this:       Pointer to the udmabuf manager data structure.
+ */
+static bool udmabuf_manager_buffer_overflow(struct udmabuf_manager_data *this)
+{
+    if (this == NULL)
+        return true;
+    else
+        return (this->buffer_offset >= UDMABUF_MGR_BUFFER_SIZE);
+}
+
+/**
+ * udmabuf_manager_state_clear() - udmabuf manager state clear.
+ * @this:       Pointer to the udmabuf manager data structure.
+ */
+static void udmabuf_manager_state_clear(struct udmabuf_manager_data *this)
+{
+    this->device_name   = NULL;
+    this->minor_number  = PLATFORM_DEVID_AUTO;
+    this->size          = 0;
+    this->state         = udmabuf_manager_init_state;
+    this->buffer_offset = 0;
+}
+
+/**
+ * udmabuf_manager_parse() - udmabuf manager parse buffer.
+ * @this:       Pointer to the udmabuf manager data structure.
+ * @buff:       Pointer to the user buffer.
+ * @count:      The number of bytes to be written.
+ * Return:      Size of copy from buff to this->buffer.
+ */
+static int udmabuf_manager_parse(struct udmabuf_manager_data *this, const char __user* buff, size_t count)
+{
+    bool   copy_done = false;
+    size_t copy_size;
+    int    parse_count;
+
+    if (this->buffer_offset + count > UDMABUF_MGR_BUFFER_SIZE)
+        copy_size = UDMABUF_MGR_BUFFER_SIZE - this->buffer_offset;
+    else
+        copy_size = count;
+
+    if (copy_from_user(&(this->buffer[this->buffer_offset]), buff, copy_size) != 0) {
+        return -EFAULT;
+    }
+
+    parse_count = 0;
+    while(parse_count < copy_size) {
+        char* ptr = &(this->buffer[this->buffer_offset+parse_count]);
+        parse_count++;
+        if ((*ptr == '\n') || (*ptr == '\0') || (*ptr == ';')) {
+            *ptr = '\0';
+            copy_done = true;
+            break;
+        }
+    }
+    this->buffer_offset += parse_count;
+
+    if (copy_done == true) {
+        char* parse_buffer = this->buffer;
+        char* ptr = strsep(&parse_buffer, " ");
+        if (ptr == NULL) {
+            this->state = udmabuf_manager_parse_error;
+            goto failed;
+        } else if (strncmp(ptr, "create", strlen("create")) == 0) {
+            this->state = udmabuf_manager_create_command;
+        } else if (strncmp(ptr, "delete", strlen("delete")) == 0) {
+            this->state = udmabuf_manager_delete_command;
+        } else {
+            this->state = udmabuf_manager_parse_error;
+            goto failed;
+        }
+        ptr = strsep(&parse_buffer, " ");
+        if (ptr == NULL) {
+            this->state = udmabuf_manager_parse_error;
+            goto failed;
+        } else {
+            this->device_name = ptr;
+        }
+        if (this->state == udmabuf_manager_create_command) {
+            ptr = strsep(&parse_buffer, " ");
+            if (ptr == NULL) {
+                this->state = udmabuf_manager_parse_error;
+                goto failed;
+            } else {
+                u64 value;
+                if (kstrtoull(ptr, 0, &value) != 0) {
+                    this->state = udmabuf_manager_parse_error;
+                    goto failed;
+                } else {
+                    this->size = value;
+                }
+            }
+        }
+    }
+failed:
+    return parse_count;    
+}
+
+/**
+ * udmabuf_manager_file_open() - udmabuf manager file open operation.
+ * @inode:      Pointer to the inode structure of this device.
+ * @file:       to the file structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_manager_file_open(struct inode *inode, struct file *file)
+{
+    struct udmabuf_manager_data* this;
+    int status = 0;
+
+    this = kzalloc(sizeof(*this), GFP_KERNEL);
+    if (IS_ERR_OR_NULL(this)) {
+        status = PTR_ERR(this);
+    } else {
+        status = 0;
+        udmabuf_manager_state_clear(this);
+        file->private_data = this;
+    }
+    return status;
+}
+
+/**
+ * udmabuf_manager_file_release() - udmabuf manager file release operation.
+ * @inode:      Pointer to the inode structure of this device.
+ * @file:       Pointer to the file structure.
+ * Return:      Success(=0) or error status(<0).
+ */
+static int udmabuf_manager_file_release(struct inode *inode, struct file *file)
+{
+    struct udmabuf_manager_data* this = file->private_data;
+    if (this != NULL) 
+        kfree(this);
+    return 0;
+}
+
+/**
+ * udmabuf_manager_file_write() - udmabuf manager file write operation.
+ * @file:       Pointer to the file structure.
+ * @buff:       Pointer to the user buffer.
+ * @count:      The number of bytes to be written.
+ * @ppos:       Pointer to the offset value
+ * Return:      Transferd size.
+ */
+static ssize_t udmabuf_manager_file_write(struct file* file, const char __user* buff, size_t count, loff_t* ppos)
+{
+    struct udmabuf_manager_data*    this      = file->private_data;
+    struct udmabuf_platform_device* plat;
+    int                             result    = 0;
+    size_t                          xfer_size = 0;
+
+    if (this == NULL)
+        return -EINVAL;
+
+    if (udmabuf_manager_buffer_overflow(this))
+        return -ENOSPC;
+    
+    while(xfer_size < count) {
+        int parse_size = udmabuf_manager_parse(this, buff + xfer_size, count - xfer_size);
+        if (parse_size < 0) {
+            result = parse_size;
+            goto failed;
+        }
+        switch (this->state) {
+            case udmabuf_manager_create_command :
+                printk(KERN_INFO "%s : create %s %d\n"  , UDMABUF_MGR_NAME, this->device_name, this->size);
+                result = udmabuf_platform_device_create(this->device_name, this->minor_number, this->size);
+                if (result == 0) {
+                    udmabuf_manager_state_clear(this);
+                } else {
+                    printk(KERN_ERR "%s : create error: %s result = %d\n", UDMABUF_MGR_NAME, this->device_name, result);
+                    udmabuf_manager_state_clear(this);
+                    goto failed;
+                }
+                break;
+            case udmabuf_manager_delete_command :
+                printk(KERN_INFO "%s : delete %s\n"     , UDMABUF_MGR_NAME, this->device_name);
+                plat = udmabuf_platform_device_search(this->device_name, this->minor_number);
+                if (plat != NULL) {
+                    udmabuf_platform_device_remove(plat);
+                    udmabuf_manager_state_clear(this);
+                } else {
+                    printk(KERN_ERR "%s : delete error: %s not found\n", UDMABUF_MGR_NAME, this->device_name);
+                    udmabuf_manager_state_clear(this);
+                    result = -EINVAL;
+                    goto failed;
+                }
+                break;
+            case udmabuf_manager_parse_error :
+                    printk(KERN_ERR "%s : parse error: ""%s""\n", UDMABUF_MGR_NAME, this->buffer);
+                    udmabuf_manager_state_clear(this);
+                    result = -EINVAL;
+                    goto failed;
+            default:
+                break;
+        }
+        xfer_size += parse_size;
+    }
+    *ppos += xfer_size;
+    result = xfer_size;
+  failed:
+    return result;
+}
+
+/**
+ * udmabuf manager file operation table.
+ */
+static const struct file_operations udmabuf_manager_file_ops = {
+    .owner   = THIS_MODULE,
+    .open    = udmabuf_manager_file_open,
+    .release = udmabuf_manager_file_release,
+    .write   = udmabuf_manager_file_write,
+};
+
+/**
+ * udmabuf manager misc device structure.
+ */
+static struct miscdevice udmabuf_manager_device = {
+    .minor   = MISC_DYNAMIC_MINOR,
+    .name    = UDMABUF_MGR_NAME,
+    .fops    = &udmabuf_manager_file_ops,
+};
+
+static bool udmabuf_manager_device_registerd = false;
+#endif
+
+/**
+ * DOC: u-dma-buf Kernel Module Operations
+ *
+ * * u_dma_buf_cleanup()
+ * * u_dma_buf_init()
+ * * u_dma_buf_exit()
+ */
+
+static bool udmabuf_platform_driver_registerd = false;
+
+/**
+ * u_dma_buf_cleanup()
+ */
+static void u_dma_buf_cleanup(void)
+{
+#if (UDMABUF_MGR_ENABLE == 1)
+    if (udmabuf_manager_device_registerd ){misc_deregister(&udmabuf_manager_device);}
+#endif
+    udmabuf_platform_device_remove_all();
+    if (udmabuf_platform_driver_registerd){platform_driver_unregister(&udmabuf_platform_driver);}
+    if (udmabuf_sys_class     != NULL    ){class_destroy(udmabuf_sys_class);}
+    if (udmabuf_device_number != 0       ){unregister_chrdev_region(udmabuf_device_number, 0);}
+    ida_destroy(&udmabuf_device_ida);
+}
+
+/**
+ * u_dma_buf_init()
+ */
+static int __init u_dma_buf_init(void)
+{
+    int retval = 0;
+
+    ida_init(&udmabuf_device_ida);
+    INIT_LIST_HEAD(&udmabuf_platform_device_list);
+    mutex_init(&udmabuf_platform_device_sem);
+
+    retval = alloc_chrdev_region(&udmabuf_device_number, 0, 0, DRIVER_NAME);
+    if (retval != 0) {
+        printk(KERN_ERR "%s: couldn't allocate device major number. return=%d\n", DRIVER_NAME, retval);
+        udmabuf_device_number = 0;
+        goto failed;
+    }
+
+    udmabuf_sys_class = class_create(THIS_MODULE, DRIVER_NAME);
+    if (IS_ERR_OR_NULL(udmabuf_sys_class)) {
+        retval = PTR_ERR(udmabuf_sys_class);
+        udmabuf_sys_class = NULL;
+        printk(KERN_ERR "%s: couldn't create sys class. return=%d\n", DRIVER_NAME, retval);
+        retval = (retval == 0) ? -ENOMEM : retval;
+        goto failed;
+    }
+
+    udmabuf_sys_class_set_attributes();
+
+    udmabuf_static_device_reserve_minor_number_all();
+
+    retval = platform_driver_register(&udmabuf_platform_driver);
+    if (retval) {
+        printk(KERN_ERR "%s: couldn't register platform driver. return=%d\n", DRIVER_NAME, retval);
+        udmabuf_platform_driver_registerd = false;
+        goto failed;
+    } else {
+        udmabuf_platform_driver_registerd = true;
+    }
+
+    udmabuf_static_device_create_all();
+
+#if (UDMABUF_MGR_ENABLE == 1)
+    retval = misc_register(&udmabuf_manager_device);
+    if (retval) {
+        printk(KERN_ERR "%s: couldn't register udmabuf-mgr. return=%d\n", DRIVER_NAME, retval);
+        udmabuf_manager_device_registerd = false;
+        goto failed;
+    } else {
+        udmabuf_manager_device_registerd = true;
+    }
+#endif
+    return 0;
+
+ failed:
+    u_dma_buf_cleanup();
+    return retval;
+}
+
+/**
+ * u_dma_buf_exit()
+ */
+static void __exit u_dma_buf_exit(void)
+{
+    u_dma_buf_cleanup();
+}
+
+module_init(u_dma_buf_init);
+module_exit(u_dma_buf_exit);
diff --git a/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/u-dma-buf.bb b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/u-dma-buf.bb
new file mode 100644
index 0000000000000000000000000000000000000000..5b165c4a3e04f3a0fc8c9f7a2583a84681f53696
--- /dev/null
+++ b/scalp_fast_router_firmware_petalinux/project-spec/meta-user/recipes-modules/u-dma-buf/u-dma-buf.bb
@@ -0,0 +1,18 @@
+SUMMARY = "Recipe for  build an external u-dma-buf Linux kernel module"
+SECTION = "PETALINUX/modules"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://COPYING;md5=12f884d2ae1ff87c09e5b7ccc2c4ca7e"
+
+inherit module
+
+INHIBIT_PACKAGE_STRIP = "1"
+
+SRC_URI = "file://Makefile \
+           file://u-dma-buf.c \
+	   file://COPYING \
+          "
+
+S = "${WORKDIR}"
+
+# The inherit of module.bbclass will automatically name module packages with
+# "kernel-module-" prefix as required by the oe-core build environment.