in devices/rio_mport_cdev.c [1943:1999]
static void mport_cdev_release_dma(struct file *filp)
{
struct mport_cdev_priv *priv = filp->private_data;
struct mport_dev *md;
struct mport_dma_req *req, *req_next;
unsigned long tmo = msecs_to_jiffies(dma_timeout);
long wret;
LIST_HEAD(list);
rmcd_debug(EXIT, "from filp=%p %s(%d)",
filp, current->comm, task_pid_nr(current));
if (!priv->dmach) {
rmcd_debug(EXIT, "No DMA channel for filp=%p", filp);
return;
}
md = priv->md;
spin_lock(&priv->req_lock);
if (!list_empty(&priv->async_list)) {
rmcd_debug(EXIT, "async list not empty filp=%p %s(%d)",
filp, current->comm, task_pid_nr(current));
list_splice_init(&priv->async_list, &list);
}
spin_unlock(&priv->req_lock);
if (!list_empty(&list)) {
rmcd_debug(EXIT, "temp list not empty");
list_for_each_entry_safe(req, req_next, &list, node) {
rmcd_debug(EXIT, "free req->filp=%p cookie=%d compl=%s",
req->filp, req->cookie,
completion_done(&req->req_comp)?"yes":"no");
list_del(&req->node);
kref_put(&req->refcount, dma_req_free);
}
}
put_dma_channel(priv);
wret = wait_for_completion_interruptible_timeout(&priv->comp, tmo);
if (wret <= 0) {
rmcd_error("%s(%d) failed waiting for DMA release err=%ld",
current->comm, task_pid_nr(current), wret);
}
if (priv->dmach != priv->md->dma_chan) {
rmcd_debug(EXIT, "Release DMA channel for filp=%p %s(%d)",
filp, current->comm, task_pid_nr(current));
rio_release_dma(priv->dmach);
} else {
rmcd_debug(EXIT, "Adjust default DMA channel refcount");
kref_put(&md->dma_ref, mport_release_def_dma);
}
priv->dmach = NULL;
}