diff options
author | Alan Cox <alan@linux.intel.com> | 2009-08-14 14:41:16 (GMT) |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-15 19:02:15 (GMT) |
commit | 4c29e9799878b6a5fc9ec37d40132c2380911e0f (patch) | |
tree | 8627008b311621ab6fafcbd1627b6c7840757ac7 /drivers/staging/sep | |
parent | 6f13ea3df5de2af5c50e15218553c2434e455be9 (diff) | |
download | linux-fsl-qoriq-4c29e9799878b6a5fc9ec37d40132c2380911e0f.tar.xz |
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: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/sep')
-rw-r--r-- | drivers/staging/sep/sep_dev.h | 2 | ||||
-rw-r--r-- | drivers/staging/sep/sep_driver.c | 89 |
2 files changed, 52 insertions, 39 deletions
diff --git a/drivers/staging/sep/sep_dev.h b/drivers/staging/sep/sep_dev.h index f0dc715..d4f0a69 100644 --- a/drivers/staging/sep/sep_dev.h +++ b/drivers/staging/sep/sep_dev.h @@ -32,6 +32,8 @@ struct sep_device { /* pointer to pci dev */ struct pci_dev *pdev; + unsigned long in_use; + unsigned long io_bus; unsigned long io_end_bus; unsigned long io_memory_size; diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c index 4d3b163..51c0050 100644 --- a/drivers/staging/sep/sep_driver.c +++ b/drivers/staging/sep/sep_driver.c @@ -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 - must also release the memory data pool allocations -------------------------------------------------------------------------*/ -static int sep_open(struct inode *inode, struct file *filp) +/** + * sep_try_open - attempt to open a SEP device + * @sep: device to attempt to open + * + * 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; +} - dbg("SEP Driver:--------> open start\n"); +/** + * 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. + */ + +static int sep_open(struct inode *inode, struct file *filp) +{ + if (sep_dev == NULL) + return -ENODEV; /* check the blocking mode */ - if (filp->f_flags & O_NDELAY) - error = mutex_trylock(&sep_mutex); - else - /* lock mutex */ - mutex_lock(&sep_mutex); + if (filp->f_flags & O_NDELAY) { + if (sep_try_open(sep_dev) == 0) + return -EAGAIN; + } else + 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 */ filp->private_data = sep_dev; - if (sep_dev == NULL) - return -ENODEV; - /* release data pool allocations */ sep_dev->data_pool_bytes_allocated = 0; - - -end_function: - dbg("SEP Driver:<-------- open end\n"); - return error; + return 0; } +/** + * 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. + */ - -/*------------------------------------------------------------ - release function --------------------------------------------------------------*/ -static int sep_release(struct inode *inode_ptr, struct file *filp) +static int sep_release(struct inode *inode, struct file *filp) { - struct sep_driver *sep = filp->private_data; - dbg("----------->SEP Driver: sep_release start\n"); - + struct sep_device *sep = filp->private_data; #if 0 /*!SEP_DRIVER_POLLING_MODE */ /* close IMR */ 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) free_irq(SEP_DIRVER_IRQ_NUM, sep); #endif - /* unlock the sep mutex */ - mutex_unlock(&sep_mutex); - dbg("SEP Driver:<-------- sep_release end\n"); + /* Ensure any blocked open progresses */ + clear_bit(0, &sep->in_use); + wake_up(&sep_event); return 0; } - - - /*--------------------------------------------------------------- map function - this functions maps the message shared area -----------------------------------------------------------------*/ |