in devices/rio_mport_cdev.c [2007:2058]
static int mport_cdev_release(struct inode *inode, struct file *filp)
{
struct mport_cdev_priv *priv = filp->private_data;
struct mport_dev *chdev;
struct rio_mport_pw_filter *pw_filter, *pw_filter_next;
struct rio_mport_db_filter *db_filter, *db_filter_next;
struct rio_mport_mapping *map, *_map;
unsigned long flags;
rmcd_debug(EXIT, "%s filp=%p", dev_name(&priv->md->dev), filp);
chdev = priv->md;
mport_cdev_release_dma(filp);
priv->event_mask = 0;
spin_lock_irqsave(&chdev->pw_lock, flags);
if (!list_empty(&priv->pw_filters)) {
list_for_each_entry_safe(pw_filter, pw_filter_next,
&priv->pw_filters, priv_node)
rio_mport_delete_pw_filter(pw_filter);
}
spin_unlock_irqrestore(&chdev->pw_lock, flags);
spin_lock_irqsave(&chdev->db_lock, flags);
list_for_each_entry_safe(db_filter, db_filter_next,
&priv->db_filters, priv_node) {
rio_mport_delete_db_filter(db_filter);
}
spin_unlock_irqrestore(&chdev->db_lock, flags);
kfifo_free(&priv->event_fifo);
mutex_lock(&chdev->buf_mutex);
list_for_each_entry_safe(map, _map, &chdev->mappings, node) {
if (map->filp == filp) {
rmcd_debug(EXIT, "release mapping %p filp=%p",
map->virt_addr, filp);
kref_put(&map->ref, mport_release_mapping);
}
}
mutex_unlock(&chdev->buf_mutex);
mport_cdev_fasync(-1, filp, 0);
filp->private_data = NULL;
mutex_lock(&chdev->file_mutex);
list_del(&priv->list);
mutex_unlock(&chdev->file_mutex);
put_device(&chdev->dev);
kfree(priv);
return 0;
}