From patchwork Wed May 5 17:05:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Ellingsworth X-Patchwork-Id: 97155 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o45HbqH6010329 for ; Wed, 5 May 2010 17:37:53 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756464Ab0EERhU (ORCPT ); Wed, 5 May 2010 13:37:20 -0400 Received: from 99-34-136-231.lightspeed.bcvloh.sbcglobal.net ([99.34.136.231]:48162 "EHLO desource.dyndns.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755912Ab0EERhQ (ORCPT ); Wed, 5 May 2010 13:37:16 -0400 Received: from root by desource.dyndns.org with local (Exim 4.71) (envelope-from ) id 1O9i2Q-0005mY-E6; Wed, 05 May 2010 13:05:34 -0400 From: David Ellingsworth To: linux-media@vger.kernel.org Cc: David Ellingsworth Subject: [PATCH/RFC 1/7] dsbr100: implement proper locking Date: Wed, 5 May 2010 13:05:24 -0400 Message-Id: <1273079130-21999-2-git-send-email-david@identd.dyndns.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1273079130-21999-1-git-send-email-david@identd.dyndns.org> References: <1273079130-21999-1-git-send-email-david@identd.dyndns.org> X-SA-Exim-Connect-IP: X-SA-Exim-Rcpt-To: linux-media@vger.kernel.org, david@identd.dyndns.org X-SA-Exim-Mail-From: root@desource.dyndns.org X-SA-Exim-Scanned: No (on desource.dyndns.org); SAEximRunCond expanded to false Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Wed, 05 May 2010 17:37:53 +0000 (UTC) diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c index ed9cd7a..673eda8 100644 --- a/drivers/media/radio/dsbr100.c +++ b/drivers/media/radio/dsbr100.c @@ -182,7 +182,7 @@ static int dsbr100_start(struct dsbr100_device *radio) int retval; int request; - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), @@ -207,11 +207,9 @@ static int dsbr100_start(struct dsbr100_device *radio) } radio->status = STARTED; - mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; usb_control_msg_failed: - mutex_unlock(&radio->lock); dev_err(&radio->usbdev->dev, "%s - usb_control_msg returned %i, request %i\n", __func__, retval, request); @@ -225,7 +223,7 @@ static int dsbr100_stop(struct dsbr100_device *radio) int retval; int request; - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), @@ -250,11 +248,9 @@ static int dsbr100_stop(struct dsbr100_device *radio) } radio->status = STOPPED; - mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; usb_control_msg_failed: - mutex_unlock(&radio->lock); dev_err(&radio->usbdev->dev, "%s - usb_control_msg returned %i, request %i\n", __func__, retval, request); @@ -269,7 +265,7 @@ static int dsbr100_setfreq(struct dsbr100_device *radio) int request; int freq = (radio->curfreq / 16 * 80) / 1000 + 856; - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), @@ -306,12 +302,10 @@ static int dsbr100_setfreq(struct dsbr100_device *radio) } radio->stereo = !((radio->transfer_buffer)[0] & 0x01); - mutex_unlock(&radio->lock); return (radio->transfer_buffer)[0]; usb_control_msg_failed: radio->stereo = -1; - mutex_unlock(&radio->lock); dev_err(&radio->usbdev->dev, "%s - usb_control_msg returned %i, request %i\n", __func__, retval, request); @@ -324,7 +318,7 @@ static void dsbr100_getstat(struct dsbr100_device *radio) { int retval; - mutex_lock(&radio->lock); + BUG_ON(!mutex_is_locked(&radio->lock)); retval = usb_control_msg(radio->usbdev, usb_rcvctrlpipe(radio->usbdev, 0), @@ -340,8 +334,6 @@ static void dsbr100_getstat(struct dsbr100_device *radio) } else { radio->stereo = !(radio->transfer_buffer[0] & 0x01); } - - mutex_unlock(&radio->lock); } /* USB subsystem interface begins here */ @@ -385,10 +377,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); - /* safety check */ - if (radio->removed) - return -EIO; - if (v->index > 0) return -EINVAL; @@ -410,12 +398,6 @@ static int vidioc_g_tuner(struct file *file, void *priv, static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *v) { - struct dsbr100_device *radio = video_drvdata(file); - - /* safety check */ - if (radio->removed) - return -EIO; - if (v->index > 0) return -EINVAL; @@ -428,17 +410,12 @@ static int vidioc_s_frequency(struct file *file, void *priv, struct dsbr100_device *radio = video_drvdata(file); int retval; - /* safety check */ - if (radio->removed) - return -EIO; - - mutex_lock(&radio->lock); radio->curfreq = f->frequency; - mutex_unlock(&radio->lock); retval = dsbr100_setfreq(radio); if (retval < 0) dev_warn(&radio->usbdev->dev, "Set frequency failed\n"); + return 0; } @@ -447,10 +424,6 @@ static int vidioc_g_frequency(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); - /* safety check */ - if (radio->removed) - return -EIO; - f->type = V4L2_TUNER_RADIO; f->frequency = radio->curfreq; return 0; @@ -472,10 +445,6 @@ static int vidioc_g_ctrl(struct file *file, void *priv, { struct dsbr100_device *radio = video_drvdata(file); - /* safety check */ - if (radio->removed) - return -EIO; - switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: ctrl->value = radio->status; @@ -490,10 +459,6 @@ static int vidioc_s_ctrl(struct file *file, void *priv, struct dsbr100_device *radio = video_drvdata(file); int retval; - /* safety check */ - if (radio->removed) - return -EIO; - switch (ctrl->id) { case V4L2_CID_AUDIO_MUTE: if (ctrl->value) { @@ -513,6 +478,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv, } return 0; } + return -EINVAL; } @@ -548,12 +514,34 @@ static int vidioc_s_audio(struct file *file, void *priv, return 0; } +static long usb_dsbr100_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct dsbr100_device *radio = video_drvdata(file); + long retval = 0; + + mutex_lock(&radio->lock); + + if (radio->removed) { + retval = -EIO; + goto unlock; + } + + retval = video_ioctl2(file, cmd, arg); + +unlock: + mutex_unlock(&radio->lock); + return retval; +} + /* Suspend device - stop device. */ static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) { struct dsbr100_device *radio = usb_get_intfdata(intf); int retval; + mutex_lock(&radio->lock); + if (radio->status == STARTED) { retval = dsbr100_stop(radio); if (retval < 0) @@ -564,12 +552,10 @@ static int usb_dsbr100_suspend(struct usb_interface *intf, pm_message_t message) * we set status equal to STARTED. * On resume we will check status and run radio if needed. */ - - mutex_lock(&radio->lock); radio->status = STARTED; - mutex_unlock(&radio->lock); } + mutex_unlock(&radio->lock); dev_info(&intf->dev, "going into suspend..\n"); return 0; @@ -581,12 +567,15 @@ static int usb_dsbr100_resume(struct usb_interface *intf) struct dsbr100_device *radio = usb_get_intfdata(intf); int retval; + mutex_lock(&radio->lock); + if (radio->status == STARTED) { retval = dsbr100_start(radio); if (retval < 0) dev_warn(&intf->dev, "dsbr100_start failed\n"); } + mutex_unlock(&radio->lock); dev_info(&intf->dev, "coming out of suspend..\n"); return 0; @@ -605,7 +594,7 @@ static void usb_dsbr100_video_device_release(struct video_device *videodev) /* File system interface */ static const struct v4l2_file_operations usb_dsbr100_fops = { .owner = THIS_MODULE, - .ioctl = video_ioctl2, + .unlocked_ioctl = usb_dsbr100_ioctl, }; static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {