From patchwork Sun May 1 09:29:37 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Nieder X-Patchwork-Id: 744982 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter2.kernel.org (8.14.4/8.14.3) with ESMTP id p419UGfm013380 for ; Sun, 1 May 2011 09:30:16 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753377Ab1EAJ3v (ORCPT ); Sun, 1 May 2011 05:29:51 -0400 Received: from mail-iw0-f174.google.com ([209.85.214.174]:56519 "EHLO mail-iw0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753185Ab1EAJ3l (ORCPT ); Sun, 1 May 2011 05:29:41 -0400 Received: by iwn34 with SMTP id 34so4016173iwn.19 for ; Sun, 01 May 2011 02:29:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:date:from:to:cc:subject:message-id:references :mime-version:content-type:content-disposition:in-reply-to :user-agent; bh=oFssko09LkyVoGcS0ufv0it07sAnp15Cy7fQyZQhAFI=; b=Jgzvwc66CxCzR1XEiyBpWI2T1xVoNNpJ/E8I6zlTj61dh8GnrWWw4KrP78SZGSevdG IEdh2Q3PVJejyvbfSymlaNDsGXiudGDL/NX0Nq2UhTxd1aBEe+POF+CwtAYuzxJ9kRmH A3/vqcvG2gKyzKsejhtQpMZS99XZMpW83UTiU= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=TuPuZ+EZryMDnlL2SjcQpLD6I1TJ2wS6+ILM6X8CdMj0sxmeNN69NMi49uP67B0Zh1 VHorjfq7l/jKhx/TPOUksJGnV9UrLFneZxyBASFc+VrquXsCqiNLtqTPphlFQUyFEXWX reEMlxunqfgz6KqfvBxdkd7IpMwidjIdYGZtk= Received: by 10.42.168.198 with SMTP id x6mr3477088icy.273.1304242180760; Sun, 01 May 2011 02:29:40 -0700 (PDT) Received: from elie (adsl-69-209-62-211.dsl.chcgil.sbcglobal.net [69.209.62.211]) by mx.google.com with ESMTPS id t1sm1871300ibm.55.2011.05.01.02.29.39 (version=SSLv3 cipher=OTHER); Sun, 01 May 2011 02:29:40 -0700 (PDT) Date: Sun, 1 May 2011 04:29:37 -0500 From: Jonathan Nieder To: linux-media@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Mauro Carvalho Chehab , Dan Carpenter , Hans Verkuil , Andi Huber , Marlon de Boer , Damien Churchill Subject: [PATCH 2/7] [media] cx88: fix locking of sub-driver operations Message-ID: <20110501092937.GB18380@elie> References: <20110501091710.GA18263@elie> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20110501091710.GA18263@elie> User-Agent: Mutt/1.5.21 (2010-09-15) 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.6 (demeter2.kernel.org [140.211.167.43]); Sun, 01 May 2011 09:30:16 +0000 (UTC) The BKL conversion of this driver seems to have gone wrong. Loading the cx88-blackbird driver deadlocks. The cause: mpeg_ops::open in the cx2388x blackbird driver acquires the device lock and calls the sub-driver's request_acquire, which tries to acquire the lock again. Fix it by clarifying the semantics of request_acquire, request_release, advise_acquire, and advise_release: now all will rely on the caller to acquire the device lock. Based on work by Ben Hutchings . Reported-by: Andi Huber Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=31962 Tested-by: Andi Huber Tested-by: Marlon de Boer Cc: stable@kernel.org Signed-off-by: Jonathan Nieder --- drivers/media/video/cx88/cx88-blackbird.c | 4 ++-- drivers/media/video/cx88/cx88-dvb.c | 3 +-- drivers/media/video/cx88/cx88-mpeg.c | 4 ---- drivers/media/video/cx88/cx88.h | 3 ++- 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index b93fbd3..a6f7d53 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -1125,13 +1125,13 @@ static int mpeg_release(struct file *file) /* Make sure we release the hardware */ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); - mutex_unlock(&dev->core->lock); - if (drv) drv->request_release(drv); atomic_dec(&dev->core->mpeg_users); + mutex_unlock(&dev->core->lock); + return 0; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 88a1507..5eccd02 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -134,8 +134,6 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) mutex_lock(&dev->core->lock); drv = cx8802_get_driver(dev, CX88_MPEG_DVB); - mutex_unlock(&dev->core->lock); - if (drv) { if (acquire){ dev->frontends.active_fe_id = fe_id; @@ -145,6 +143,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire) dev->frontends.active_fe_id = 0; } } + mutex_unlock(&dev->core->lock); return ret; } diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 918172b..9147c16 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -624,13 +624,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv) if (drv->advise_acquire) { - mutex_lock(&drv->core->lock); core->active_ref++; if (core->active_type_id == CX88_BOARD_NONE) { core->active_type_id = drv->type_id; drv->advise_acquire(drv); } - mutex_unlock(&drv->core->lock); mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); } @@ -643,14 +641,12 @@ static int cx8802_request_release(struct cx8802_driver *drv) { struct cx88_core *core = drv->core; - mutex_lock(&drv->core->lock); if (drv->advise_release && --core->active_ref == 0) { drv->advise_release(drv); core->active_type_id = CX88_BOARD_NONE; mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO)); } - mutex_unlock(&drv->core->lock); return 0; } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 6ff34c7..e912919 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -500,7 +500,8 @@ struct cx8802_driver { /* Caller must _not_ hold core->lock */ int (*probe)(struct cx8802_driver *drv); - /* Caller must hold core->lock */ + /* Callers to the following functions must hold core->lock */ + int (*remove)(struct cx8802_driver *drv); /* MPEG 8802 -> mini driver - Access for hardware control */