in devices/rio_mport_cdev.c [691:793]
static int do_dma_request(struct mport_dma_req *req,
struct rio_transfer_io *xfer,
enum rio_transfer_sync sync, int nents)
{
struct mport_cdev_priv *priv;
struct sg_table *sgt;
struct dma_chan *chan;
struct dma_async_tx_descriptor *tx;
dma_cookie_t cookie;
unsigned long tmo = msecs_to_jiffies(dma_timeout);
enum dma_transfer_direction dir;
long wret;
int ret = 0;
priv = req->priv;
sgt = &req->sgt;
chan = priv->dmach;
dir = (req->dir == DMA_FROM_DEVICE) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
rmcd_debug(DMA, "%s(%d) uses %s for DMA_%s",
current->comm, task_pid_nr(current),
dev_name(&chan->dev->device),
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE");
/* Initialize DMA transaction request */
tx = prep_dma_xfer(chan, xfer, sgt, nents, dir,
DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
if (!tx) {
rmcd_debug(DMA, "prep error for %s A:0x%llx L:0x%llx",
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE",
xfer->rio_addr, xfer->length);
ret = -EIO;
goto err_out;
} else if (IS_ERR(tx)) {
ret = PTR_ERR(tx);
rmcd_debug(DMA, "prep error %d for %s A:0x%llx L:0x%llx", ret,
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE",
xfer->rio_addr, xfer->length);
goto err_out;
}
tx->callback = dma_xfer_callback;
tx->callback_param = req;
req->status = DMA_IN_PROGRESS;
kref_get(&req->refcount);
cookie = dmaengine_submit(tx);
req->cookie = cookie;
rmcd_debug(DMA, "pid=%d DMA_%s tx_cookie = %d", task_pid_nr(current),
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE", cookie);
if (dma_submit_error(cookie)) {
rmcd_error("submit err=%d (addr:0x%llx len:0x%llx)",
cookie, xfer->rio_addr, xfer->length);
kref_put(&req->refcount, dma_req_free);
ret = -EIO;
goto err_out;
}
dma_async_issue_pending(chan);
if (sync == RIO_TRANSFER_ASYNC) {
spin_lock(&priv->req_lock);
list_add_tail(&req->node, &priv->async_list);
spin_unlock(&priv->req_lock);
return cookie;
} else if (sync == RIO_TRANSFER_FAF)
return 0;
wret = wait_for_completion_interruptible_timeout(&req->req_comp, tmo);
if (wret == 0) {
/* Timeout on wait occurred */
rmcd_error("%s(%d) timed out waiting for DMA_%s %d",
current->comm, task_pid_nr(current),
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE", cookie);
return -ETIMEDOUT;
} else if (wret == -ERESTARTSYS) {
/* Wait_for_completion was interrupted by a signal but DMA may
* be in progress
*/
rmcd_error("%s(%d) wait for DMA_%s %d was interrupted",
current->comm, task_pid_nr(current),
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE", cookie);
return -EINTR;
}
if (req->status != DMA_COMPLETE) {
/* DMA transaction completion was signaled with error */
rmcd_error("%s(%d) DMA_%s %d completed with status %d (ret=%d)",
current->comm, task_pid_nr(current),
(dir == DMA_DEV_TO_MEM)?"READ":"WRITE",
cookie, req->status, ret);
ret = -EIO;
}
err_out:
return ret;
}