static int mport_cdev_release()

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;
}