int test(void) { dma_set_pc(DMA_PHYS, 0, dma_program1); dma_set_source_address(DMA_PHYS, 0, (uint64_t)source1); dma_set_dest_address(DMA_PHYS, 0, (uint64_t)dest1); dma_start_transfer(DMA_PHYS, 0); //We can set up the new transfer whilst the old transfer is happening. dma_set_pc(DMA_PHYS, 0, dma_program2); dma_set_source_address(DMA_PHYS, 0, (uint64_t)source2); dma_set_dest_address(DMA_PHYS, 0, (uint64_t)dest2); while (!dma_thread_ready(DMA_PHYS, 0)) { DEBUG_NOP(); DEBUG_NOP(); DEBUG_NOP(); DEBUG_NOP(); } dma_start_transfer(DMA_PHYS, 0); while (!dma_thread_ready(DMA_PHYS, 0)) { DEBUG_NOP(); DEBUG_NOP(); DEBUG_NOP(); DEBUG_NOP(); } assert(dest1[0] == 0xBE); assert(dest2[0] == 0xDEADBEEF); return 0; }
int test(void) { dma_set_pc(DMA_PHYS, 0, dma_program); dma_set_source_address(DMA_PHYS, 0, (uint64_t)(source + 2)); dma_set_dest_address(DMA_PHYS, 0, (uint64_t)(dest + 2)); dma_start_transfer(DMA_PHYS, 0); while (!dma_thread_ready(DMA_PHYS, 0)) { asm("nop"); asm("nop"); asm("nop"); asm("nop"); } assert(dest[0] == -1); assert(dest[1] == -1); assert(dest[2] == -2); return 0; }
int test(void) { dma_set_pc(DMA_PHYS, 0, dma_program); dma_set_source_address(DMA_PHYS, 0, (uint64_t)source); dma_set_dest_address(DMA_PHYS, 0, (uint64_t)dest); dma_start_transfer(DMA_PHYS, 0); while(!dma_thread_ready(DMA_PHYS, 0)) { asm("nop"); asm("nop"); asm("nop"); asm("nop"); } assert(dest[0] == 1); assert(dest[3] == 2); assert(dest[7] == 3); assert(dest[8] == 0xBEEF); return 0; }
/* * Kernel thread that processes the update requests */ static void test_thread(void) { struct test_cfg *cfg = &gCfg; unsigned int i; int rc; void *virt_addr; enum dma_data_direction dir; dma_addr_t devPhysAddr; unsigned long time_left; unsigned long trials = 0; if (!cfg->setup_is_done) { printk(KERN_ERR "Need to set up parameters before running the test\n"); return; } cfg->kill_thread = 0; cfg->in_use = 1; /* allocate memory for dstination and source */ cfg->src_ptr = alloc_mem(&cfg->src_addr, cfg->len, cfg->src_type); if (cfg->src_ptr == NULL) { printk(KERN_ERR "alloc_mem for src failed\n"); goto exit_free_mem; } cfg->dst_ptr = alloc_mem(&cfg->dst_addr, cfg->len, cfg->dst_type); if (cfg->dst_ptr == NULL) { printk(KERN_ERR "alloc_mem for dst failed\n"); goto exit_free_mem; } /* init mmap */ rc = dma_mmap_init_map(&cfg->mmap_cfg); if (rc < 0) { printk(KERN_ERR "dma_mmap_init_map failed\n"); goto exit_free_mem; } if (cfg->dir) { /* mem-to-dev, map src memory */ virt_addr = cfg->src_ptr; dir = DMA_TO_DEVICE; devPhysAddr = cfg->dst_addr; } else { /* dev-to-mem, map dst memory */ virt_addr = cfg->dst_ptr; dir = DMA_FROM_DEVICE; devPhysAddr = cfg->src_addr; } daemonize(MODULE_NAME); allow_signal(SIGKILL); for (;;) { /* driver shutting down... let's quit the kthread */ if (cfg->kill_thread) goto exit_term_mmap; if (signal_pending(current)) goto exit_term_mmap; /* write some values into the source buffer */ for (i = 0; i < cfg->len; i++) { ((unsigned char *)cfg->src_ptr)[i] = cnt++; } /* clear the destination buffer */ memset(cfg->dst_ptr, 0, cfg->len); /* map memories */ rc = dma_mmap_map(&cfg->mmap_cfg, virt_addr, cfg->len, dir); if (rc < 0) { printk(KERN_ERR "dma_mmap_map failed\n"); goto exit_term_mmap; } /* reserve the DMA channel and set up descriptors */ if (cfg->dma_type == DMA_TYPE_SDMA) { cfg->sdma_hdl = sdma_request_channel(cfg->device); if (cfg->sdma_hdl < 0) { printk(KERN_ERR "sdma_request_channel failed\n"); goto exit_unmap; } rc = sdma_map_create_descriptor_ring(cfg->sdma_hdl, &cfg->mmap_cfg, devPhysAddr, DMA_UPDATE_MODE_INC); if (rc < 0) { printk(KERN_ERR "create desc ring failed\n"); goto exit_free_dma_channel; } } else { printk(KERN_ERR "only support SDMA for now\n"); rc = -EINVAL; goto exit_unmap; #if 0 cfg->dma_hdl = dma_request_channel(cfg->device); if (cfg->dma_hdl < 0) { printk(KERN_ERR "dma_request_channel failed\n"); goto exit_unmap; } rc = dma_map_create_descriptor_ring(cfg->device, &cfg->mmap_cfg, devPhysAddr, DMA_UPDATE_MODE_INC); if (rc < 0) { printk(KERN_ERR "create desc ring failed\n"); goto exit_free_dma_channel; } #endif } /* set DMA interrupt handler */ rc = set_dev_handler(cfg); if (rc < 0) { printk(KERN_ERR "set_dev_handler failed\n"); goto exit_free_dma_channel; } INIT_COMPLETION(cfg->dma_done); if (cfg->dma_type == DMA_TYPE_SDMA) { rc = sdma_start_transfer(cfg->sdma_hdl); if (rc < 0) { printk(KERN_ERR "sdma_transfer failed\n"); goto exit_free_dma_channel; } } #if 0 else { /* synopsys DMA */ rc = dma_start_transfer(cfg->dma_hdl, cfg->len); if (rc < 0) { printk(KERN_ERR "dma_start_transfer failed\n"); goto exit_free_dma_channel; } } #endif time_left = wait_for_completion_timeout(&cfg->dma_done, TIMEOUT_TIME); if (time_left == 0) { printk(KERN_ERR "DMA MMAP test timeout after %lu trials\n", trials); goto exit_free_dma_channel; } /* free DMA channel and unmap memory */ if (cfg->dma_type == DMA_TYPE_SDMA) sdma_free_channel(cfg->sdma_hdl); #if 0 else dma_free_channel(cfg->dma_hdl); #endif dma_mmap_unmap(&cfg->mmap_cfg, 0); /* verify the result */ for (i = 0; i < cfg->len; i++) { if (((unsigned char *)cfg->src_ptr)[i] != ((unsigned char *)cfg->dst_ptr)[i]) { printk(KERN_ERR "src[%u]=%u != dst[%u]=%u trials=%lu\n", i, ((unsigned char *)cfg->src_ptr)[i], i, ((unsigned char *)cfg->dst_ptr)[i], trials); goto exit_term_mmap; } } trials++; } exit_free_dma_channel: if (cfg->dma_type == DMA_TYPE_SDMA) sdma_free_channel(cfg->sdma_hdl); #if 0 else dma_free_channel(cfg->dma_hdl); #endif exit_unmap: dma_mmap_unmap(&cfg->mmap_cfg, 0); exit_term_mmap: dma_mmap_term_map(&cfg->mmap_cfg); exit_free_mem: if (cfg->src_ptr) { free_mem(cfg->src_ptr, cfg->src_addr, cfg->len, cfg->src_type); cfg->src_ptr = NULL; } if (cfg->dst_ptr) { free_mem(cfg->dst_ptr, cfg->dst_addr, cfg->len, cfg->dst_type); cfg->dst_ptr = NULL; } cfg->thread = NULL; cfg->in_use = 0; cfg->kill_thread = 0; printk(KERN_INFO "Quitted test thread\n"); }