From patchwork Mon May 2 07:59:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 746852 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 p427wLqb006207 for ; Mon, 2 May 2011 07:59:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756593Ab1EBH7J (ORCPT ); Mon, 2 May 2011 03:59:09 -0400 Received: from moutng.kundenserver.de ([212.227.126.171]:58462 "EHLO moutng.kundenserver.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756455Ab1EBH7J (ORCPT ); Mon, 2 May 2011 03:59:09 -0400 Received: from axis700.grange (pD9EB91DC.dip0.t-ipconnect.de [217.235.145.220]) by mrelayeu.kundenserver.de (node=mrbap4) with ESMTP (Nemesis) id 0Lr20J-1Pd5ld3Mt1-00edry; Mon, 02 May 2011 09:59:02 +0200 Received: by axis700.grange (Postfix, from userid 1000) id 5E48D189B89; Mon, 2 May 2011 09:59:02 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by axis700.grange (Postfix) with ESMTP id 49F4E189B88; Mon, 2 May 2011 09:59:02 +0200 (CEST) Date: Mon, 2 May 2011 09:59:02 +0200 (CEST) From: Guennadi Liakhovetski X-X-Sender: lyakh@axis700.grange To: linux-sh@vger.kernel.org cc: Paul Mundt , Dan Williams , Simon Horman , Magnus Damm Subject: [PATCH/RFC] dmaengine: shdma: synchronize RCU before freeing, simplify spinlock Message-ID: MIME-Version: 1.0 X-Provags-ID: V02:K0:D+YbMFiLqBUtXOeWmuEbgZ9ROGcow75L/Tzau4+w5il YtJH8LuQiXtNYxxuaX1P6IQgQV9s21iHpKEo/e4S3vKI6NwOtD 8DpPZ2x8Qga3yvB11Rag9O+p0YWni/KT0VyAszdCX9rfpbASaM SgtdN+n8wA2uATsuBtGmYIbjnB+YewGkGNfqZCyPjUB3nCezU+ qh3chjCtYSQLaza5EKpDghxQQ+OD0Xst4tZeSJJHNg= Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@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]); Mon, 02 May 2011 07:59:10 +0000 (UTC) List elements, deleted using list_del_rcu(), cannot be freed without synchronising RCU. Further, the spinlock, used to protect the RCU writer, is called in process context, so, we don't have to save flags. Signed-off-by: Guennadi Liakhovetski --- Paul, you added the NMI handler to shdma, using RCU and a global spinlock. Please, have a look, whether this patch is correct. drivers/dma/shdma.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index d50da41..b7f27f5 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c @@ -1045,7 +1045,6 @@ static int __init sh_dmae_probe(struct platform_device *pdev) struct sh_dmae_pdata *pdata = pdev->dev.platform_data; unsigned long irqflags = IRQF_DISABLED, chan_flag[SH_DMAC_MAX_CHANNELS] = {}; - unsigned long flags; int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; int err, i, irq_cnt = 0, irqres = 0; struct sh_dmae_device *shdev; @@ -1111,9 +1110,9 @@ static int __init sh_dmae_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_sync(&pdev->dev); - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_add_tail_rcu(&shdev->node, &sh_dmae_devices); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); /* reset dma controller */ err = sh_dmae_rst(shdev); @@ -1218,15 +1217,16 @@ eirqres: eirq_err: #endif rst_err: - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_del_rcu(&shdev->node); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); pm_runtime_put(&pdev->dev); if (dmars) iounmap(shdev->dmars); emapdmars: iounmap(shdev->chan_reg); + synchronize_rcu(); emapchan: kfree(shdev); ealloc: @@ -1242,7 +1242,6 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) { struct sh_dmae_device *shdev = platform_get_drvdata(pdev); struct resource *res; - unsigned long flags; int errirq = platform_get_irq(pdev, 0); dma_async_device_unregister(&shdev->common); @@ -1250,9 +1249,9 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) if (errirq > 0) free_irq(errirq, shdev); - spin_lock_irqsave(&sh_dmae_lock, flags); + spin_lock_irq(&sh_dmae_lock); list_del_rcu(&shdev->node); - spin_unlock_irqrestore(&sh_dmae_lock, flags); + spin_unlock_irq(&sh_dmae_lock); /* channel data remove */ sh_dmae_chan_remove(shdev); @@ -1263,6 +1262,7 @@ static int __exit sh_dmae_remove(struct platform_device *pdev) iounmap(shdev->dmars); iounmap(shdev->chan_reg); + synchronize_rcu(); kfree(shdev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);