为什么PL330在读取时始终会触发RX超时?

时间:2016-05-11 13:48:35

标签: linux linux-kernel linux-device-driver embedded-linux dma

我们正在使用带有集成ARM Cortex-A9双核处理器系统的CycloneV FPGA系统。该处理器系统运行带有4.1内核的angstrom linux,并具有pl330 DMA内核。我们正在尝试编写一个内核模块来使用这个DMAC将数据推送到FPGA架构并从中读取。

写入FPGA工作(尽管速度很慢),但每次我们尝试读取时都会看到读取传输发生,但是linux dmaengine报告超时并且在内核级别,传输永远不会完成。

有人知道为什么会这样吗?我可以注释掉超时逻辑并从中获取数据,所以我猜它可能与缓存一致性或类似的东西有关。

这是我们内核模块中的read函数:

static int dma_start_rx(struct platform_device *pdev, unsigned datalen, unsigned char *databuf, u32 burst_size, bool isDecrypt) {
  struct mRiddler_dev *pdata = platform_get_drvdata(pdev);
  struct dma_chan *dmaChan;
  struct dma_slave_config dmaConf;
  struct dma_async_tx_descriptor *dmaDesc = NULL;

  dmaChan = pdata->dma_rx_chan;
  memset(&dmaConf, 0, sizeof(dmaConf)); // Clear memory for DMA config

  // Build DMA configuration
  dmaConf.direction = DMA_DEV_TO_MEM;

  if (isDecrypt)
    dmaConf.src_addr = pdata->dma_datareg_phy + RID_DMA_DATA_READ_DECRYPT;
  else
    dmaConf.src_addr = pdata->dma_datareg_phy + RID_DMA_DATA_READ_ENCRYPT;

  #ifdef DEBUG
  pr_info("Accessing device address: %u, based on dma_datareg_phy: %u\n", dmaConf.src_addr, pdata->dma_datareg_phy);
  #endif

  dmaConf.src_addr_width = 8;
  dmaConf.src_maxburst = burst_size;

  pdata->dma_rx_addr = dma_map_single(&pdev->dev, databuf, datalen, DMA_FROM_DEVICE);

  // Error handling
  if (dma_mapping_error(&pdev->dev, pdata->dma_rx_addr)) {
    pr_err("dma_map_single for RX failed!\n");
    return -EINVAL;
  }

  // Setup slave config
  dmaengine_slave_config(dmaChan, &dmaConf);

  // Get DMA descriptor
  dmaDesc = dmaengine_prep_slave_single(dmaChan, pdata->dma_rx_addr, datalen, dmaConf.direction, DMA_PREP_INTERRUPT);

  // Error handling
  if (!dmaDesc) {
    dma_shutdown(pdata);
    return -ENOMEM;
  }

  // Set callbacks
  dmaDesc->callback = dma_rx_done;
  dmaDesc->callback_param = pdata;

  // Get cookie and submit transfer to queue
  pdata->dma_rx_cookie = dmaengine_submit(dmaDesc);

  // Error handling
  if (dma_submit_error(pdata->dma_rx_cookie)) 
    pr_err("RX cookie error on dmaengine_submit\n");

  #ifdef DEBUG
  pr_info("Issueing RX transfer to DMA engine...\n");
  #endif

  // Start DMA
  dma_async_issue_pending(dmaChan);

  return 0;
}

编辑:这是设置超时并调用DMA读取功能的地方:

if (numBytes > 0) {

    #ifdef DEBUG
    pr_info("Calling dma_start_rx with following values: numBytes=%d, burstSize=%d\n", numBytes, burstSize);
    #endif

    retVal = dma_start_rx(pdata->pdev, numBytes, pdata->dma_rx_buffer, burstSize, false);

    if (retVal) {
      pr_err("Error starting RX DMA!\n");
      return retVal;
    }

    if (!wait_for_completion_timeout(&dma_read_complete, msecs_to_jiffies(timeout))) {
      pr_err("Timeout while waiting for RX DMA\n");
      dmaengine_terminate_all(pdata->dma_rx_chan);
      return -ETIMEDOUT;
    }

    *offset = 0;
  }

当我尝试从设备读取时,这是dmesg输出:

[  326.486364] Issueing DMA transfer...
[  326.489952] DMA TX transfer finished!
[  335.607286] There are 4 words available in enc_tx FIFO!
[  335.612497] DMA read 32 > requested bytes 16, adjusting...
[  335.617992] Now reading 16 bytes in 2 words!
[  335.622246] Adjusted burstSize/numWords, new values: 2 and 2
[  335.627898] Calling dma_start_rx with following values: numBytes=16, burstSize=2
[  335.635283] Accessing device address: 3221225480, based on dma_datareg_phy: 3221225472
[  335.643168] Issueing RX transfer to DMA engine...
[  336.643795] Timeout while waiting for RX DMA, cookie: 2

0 个答案:

没有答案