diff options
author | Par-Gunnar Hjalmdahl <par-gunnar.p.hjalmdahl@stericsson.com> | 2011-08-29 09:29:05 +0530 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:05:51 +0200 |
commit | 0e9b14d010fe2fa1eb5e1690e32e101e1adf9dab (patch) | |
tree | a7fdce790177301cedef819b5907894bc1d5743e /drivers/staging/cg2900/mfd/cg2900_audio.c | |
parent | d224ba380d6433d109eac46c94c18299258f9f28 (diff) |
cg2900: Fix crash when transport is closed
This patch fixes crashes caused by transport being removed
while users of the CG2900 driver still exist.
ST-Ericsson Linux next: Not tested, ER 336652
ST-Ericsson ID: 336652
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: I6318ce1086097a4fa63a1793b6795b01ea939715
Signed-off-by: Par-Gunnar Hjalmdahl <par-gunnar.p.hjalmdahl@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21781
Reviewed-by: QATEST
Reviewed-by: Lukasz RYMANOWSKI <lukasz.rymanowski@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29795
Reviewed-by: Virupax SADASHIVPETIMATH <virupax.sadashivpetimath@stericsson.com>
Tested-by: Virupax SADASHIVPETIMATH <virupax.sadashivpetimath@stericsson.com>
Diffstat (limited to 'drivers/staging/cg2900/mfd/cg2900_audio.c')
-rw-r--r-- | drivers/staging/cg2900/mfd/cg2900_audio.c | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/drivers/staging/cg2900/mfd/cg2900_audio.c b/drivers/staging/cg2900/mfd/cg2900_audio.c index 6eadd96b2de..a7b8eda4305 100644 --- a/drivers/staging/cg2900/mfd/cg2900_audio.c +++ b/drivers/staging/cg2900/mfd/cg2900_audio.c @@ -111,6 +111,7 @@ struct endpoint_config_node { * audio channel. * @dev_fm: Device registered by this driver for the FM * audio channel. + * @filp: Current char device file pointer. * @management_mutex: Mutex for handling access to CG2900 Audio driver * management. * @bt_mutex: Mutex for handling access to BT audio channel. @@ -136,6 +137,7 @@ struct audio_info { struct device *parent; struct device *dev_bt; struct device *dev_fm; + struct file *filp; struct mutex management_mutex; struct mutex bt_mutex; struct mutex fm_mutex; @@ -2825,6 +2827,7 @@ static int audio_dev_open(struct inode *inode, struct file *filp) } filp->private_data = char_dev_info; char_dev_info->info = info; + info->filp = filp; mutex_init(&char_dev_info->management_mutex); mutex_init(&char_dev_info->rw_mutex); @@ -2861,7 +2864,14 @@ static int audio_dev_release(struct inode *inode, struct file *filp) { int err = 0; struct char_dev_info *dev = filp->private_data; - struct audio_info *info = dev->info; + struct audio_info *info; + + if (!dev) { + pr_err("audio_dev_release: Transport closed"); + return -EBADF; + } + + info = dev->info; dev_dbg(BT_DEV, "audio_dev_release\n"); @@ -2879,6 +2889,7 @@ static int audio_dev_release(struct inode *inode, struct file *filp) kfree(dev); filp->private_data = NULL; + info->filp = NULL; return err; } @@ -2907,11 +2918,18 @@ static ssize_t audio_dev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct char_dev_info *dev = filp->private_data; - struct audio_info *info = dev->info; + struct audio_info *info; unsigned int bytes_to_copy; int err = 0; struct sk_buff *skb; + if (!dev) { + pr_err("audio_dev_read: Transport closed"); + return -EBADF; + } + + info = dev->info; + dev_dbg(BT_DEV, "audio_dev_read count %d\n", count); mutex_lock(&dev->rw_mutex); @@ -2988,7 +3006,7 @@ static ssize_t audio_dev_write(struct file *filp, const char __user *buf, pr_debug("audio_dev_write count %d", count); if (!dev) { - pr_err("No dev supplied in private data"); + pr_err("audio_dev_write: Transport closed"); return -EBADF; } info = dev->info; @@ -3170,7 +3188,7 @@ static unsigned int audio_dev_poll(struct file *filp, poll_table *wait) unsigned int mask = 0; if (!dev) { - pr_err("No dev supplied in private data"); + pr_err("audio_dev_poll: Transport closed"); return POLLERR | POLLRDHUP; } info = dev->info; @@ -3344,6 +3362,9 @@ static int common_remove(struct audio_info *info, struct device *dev) dev_err(dev, "Error %d deregistering misc dev\n", err); info->misc_registered = false; + if (info->filp) + info->filp->private_data = NULL; + dev_info(dev, "CG2900 Audio driver removed\n"); return err; } |