Commit 4c29e979 authored by Alan Cox's avatar Alan Cox Committed by Greg Kroah-Hartman

Staging: sep: Implement some proper open/close methods

Use the mutex as a protection for open close rather than leaving it hanging
invalidly across userspace.
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 6f13ea3d
...@@ -32,6 +32,8 @@ struct sep_device { ...@@ -32,6 +32,8 @@ struct sep_device {
/* pointer to pci dev */ /* pointer to pci dev */
struct pci_dev *pdev; struct pci_dev *pdev;
unsigned long in_use;
unsigned long io_bus; unsigned long io_bus;
unsigned long io_end_bus; unsigned long io_end_bus;
unsigned long io_memory_size; unsigned long io_memory_size;
......
...@@ -296,53 +296,67 @@ static void *sep_shared_area_bus_to_virt(struct sep_device *sep, ...@@ -296,53 +296,67 @@ static void *sep_shared_area_bus_to_virt(struct sep_device *sep,
} }
/*---------------------------------------------------------------------- /**
open function of the character driver - must only lock the mutex * sep_try_open - attempt to open a SEP device
must also release the memory data pool allocations * @sep: device to attempt to open
------------------------------------------------------------------------*/ *
static int sep_open(struct inode *inode, struct file *filp) * Atomically attempt to get ownership of a SEP device.
* Returns 1 if the device was opened, 0 on failure.
*/
static int sep_try_open(struct sep_device *sep)
{ {
int error = 0; if (!test_and_set_bit(0, &sep->in_use))
return 1;
return 0;
}
/**
* sep_open - device open method
* @inode: inode of sep device
* @filp: file handle to sep device
*
* Open method for the SEP device. Called when userspace opens
* the SEP device node. Must also release the memory data pool
* allocations.
*
* Returns zero on success otherwise an error code.
*/
dbg("SEP Driver:--------> open start\n"); static int sep_open(struct inode *inode, struct file *filp)
{
if (sep_dev == NULL)
return -ENODEV;
/* check the blocking mode */ /* check the blocking mode */
if (filp->f_flags & O_NDELAY) if (filp->f_flags & O_NDELAY) {
error = mutex_trylock(&sep_mutex); if (sep_try_open(sep_dev) == 0)
else return -EAGAIN;
/* lock mutex */ } else
mutex_lock(&sep_mutex); if (wait_event_interruptible(sep_event, sep_try_open(sep_dev)) < 0)
return -EINTR;
/* check the error */
if (error) {
edbg("SEP Driver: down_interruptible failed\n");
goto end_function;
}
/* Bind to the device, we only have one which makes it easy */ /* Bind to the device, we only have one which makes it easy */
filp->private_data = sep_dev; filp->private_data = sep_dev;
if (sep_dev == NULL)
return -ENODEV;
/* release data pool allocations */ /* release data pool allocations */
sep_dev->data_pool_bytes_allocated = 0; sep_dev->data_pool_bytes_allocated = 0;
return 0;
end_function:
dbg("SEP Driver:<-------- open end\n");
return error;
} }
/**
* sep_release - close a SEP device
* @inode: inode of SEP device
* @filp: file handle being closed
*
* Called on the final close of a SEP device. As the open protects against
* multiple simultaenous opens that means this method is called when the
* final reference to the open handle is dropped.
*/
static int sep_release(struct inode *inode, struct file *filp)
/*------------------------------------------------------------
release function
-------------------------------------------------------------*/
static int sep_release(struct inode *inode_ptr, struct file *filp)
{ {
struct sep_driver *sep = filp->private_data; struct sep_device *sep = filp->private_data;
dbg("----------->SEP Driver: sep_release start\n");
#if 0 /*!SEP_DRIVER_POLLING_MODE */ #if 0 /*!SEP_DRIVER_POLLING_MODE */
/* close IMR */ /* close IMR */
sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF); sep_write_reg(sep, HW_HOST_IMR_REG_ADDR, 0x7FFF);
...@@ -350,15 +364,12 @@ static int sep_release(struct inode *inode_ptr, struct file *filp) ...@@ -350,15 +364,12 @@ static int sep_release(struct inode *inode_ptr, struct file *filp)
free_irq(SEP_DIRVER_IRQ_NUM, sep); free_irq(SEP_DIRVER_IRQ_NUM, sep);
#endif #endif
/* unlock the sep mutex */ /* Ensure any blocked open progresses */
mutex_unlock(&sep_mutex); clear_bit(0, &sep->in_use);
dbg("SEP Driver:<-------- sep_release end\n"); wake_up(&sep_event);
return 0; return 0;
} }
/*--------------------------------------------------------------- /*---------------------------------------------------------------
map function - this functions maps the message shared area map function - this functions maps the message shared area
-----------------------------------------------------------------*/ -----------------------------------------------------------------*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment