in devices/rio_mport_cdev.c [1008:1084]
static int rio_mport_wait_for_async_dma(struct file *filp, void __user *arg)
{
struct mport_cdev_priv *priv;
struct rio_async_tx_wait w_param;
struct mport_dma_req *req;
dma_cookie_t cookie;
unsigned long tmo;
long wret;
int found = 0;
int ret;
priv = (struct mport_cdev_priv *)filp->private_data;
if (unlikely(copy_from_user(&w_param, arg, sizeof(w_param))))
return -EFAULT;
cookie = w_param.token;
if (w_param.timeout)
tmo = msecs_to_jiffies(w_param.timeout);
else /* Use default DMA timeout */
tmo = msecs_to_jiffies(dma_timeout);
spin_lock(&priv->req_lock);
list_for_each_entry(req, &priv->async_list, node) {
if (req->cookie == cookie) {
list_del(&req->node);
found = 1;
break;
}
}
spin_unlock(&priv->req_lock);
if (!found)
return -EAGAIN;
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 ASYNC DMA_%s",
current->comm, task_pid_nr(current),
(req->dir == DMA_FROM_DEVICE)?"READ":"WRITE");
ret = -ETIMEDOUT;
goto err_tmo;
} else if (wret == -ERESTARTSYS) {
/* Wait_for_completion was interrupted by a signal but DMA may
* be still in progress
*/
rmcd_error("%s(%d) wait for ASYNC DMA_%s was interrupted",
current->comm, task_pid_nr(current),
(req->dir == DMA_FROM_DEVICE)?"READ":"WRITE");
ret = -EINTR;
goto err_tmo;
}
if (req->status != DMA_COMPLETE) {
/* DMA transaction completion signaled with transfer error */
rmcd_error("%s(%d) ASYNC DMA_%s completion with status %d",
current->comm, task_pid_nr(current),
(req->dir == DMA_FROM_DEVICE)?"READ":"WRITE",
req->status);
ret = -EIO;
} else
ret = 0;
if (req->status != DMA_IN_PROGRESS && req->status != DMA_PAUSED)
kref_put(&req->refcount, dma_req_free);
return ret;
err_tmo:
/* Return request back into async queue */
spin_lock(&priv->req_lock);
list_add_tail(&req->node, &priv->async_list);
spin_unlock(&priv->req_lock);
return ret;
}