From patchwork Sun Mar 22 23:12:12 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Brownell X-Patchwork-Id: 24904 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id 2D376DDED8 for ; Mon, 23 Mar 2009 10:19:14 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756768AbZCVXTN (ORCPT ); Sun, 22 Mar 2009 19:19:13 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756607AbZCVXTN (ORCPT ); Sun, 22 Mar 2009 19:19:13 -0400 Received: from n6.bullet.mud.yahoo.com ([216.252.100.57]:36757 "HELO n6.bullet.mud.yahoo.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with SMTP id S1756371AbZCVXTL (ORCPT ); Sun, 22 Mar 2009 19:19:11 -0400 X-Greylist: delayed 415 seconds by postgrey-1.27 at vger.kernel.org; Sun, 22 Mar 2009 19:19:11 EDT Received: from [68.142.200.226] by n6.bullet.mud.yahoo.com with NNFMP; 22 Mar 2009 23:12:15 -0000 Received: from [68.142.201.247] by t7.bullet.mud.yahoo.com with NNFMP; 22 Mar 2009 23:12:14 -0000 Received: from [127.0.0.1] by omp408.mail.mud.yahoo.com with NNFMP; 22 Mar 2009 23:12:14 -0000 X-Yahoo-Newman-Id: 848774.37572.bm@omp408.mail.mud.yahoo.com Received: (qmail 9979 invoked from network); 22 Mar 2009 23:12:14 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=pacbell.net; h=Received:X-YMail-OSG:X-Yahoo-Newman-Property:From:To:Subject:Date:User-Agent:MIME-Version:Content-Type:Content-Transfer-Encoding:Content-Disposition:Message-Id; b=HdSfqrJlEeLs2ccYfNI+v0ahAm6FM314PpiPcn5lDtixNAM6kdCwh0vwG9DslucDwc06nZJzR3KvJowt2+8oPKo1bETfgvXJH4KjGdp6t5B18MBlCGN2homN/JuMFdRsx6ZYtb12tkTjyd71gKyKiP78bM+pZKFh4V4g/cX+Rqo= ; Received: from unknown (HELO pogo) (david-b@69.226.231.133 with plain) by smtp102.sbc.mail.sp1.yahoo.com with SMTP; 22 Mar 2009 23:12:13 -0000 X-YMail-OSG: Wru6FOUVM1k1z_8JHqYaoKuoee.ji0cjl2VQQozxOuZhytD8kU4a020ZvtQ.rHJ.PTAas4eWSDjfPGaB4G71s8Poh42adaJBZZit4gCo7kIITcDiuIWO6y8tEPTN7ZFYLqPGeXekzlWabbR2t9znlYUCI2i_TOF.Hixy4qo1cXNTlTnEpXzvP6UbmJ0EDj7Fb5FshxT1CCqStA3wyQtZmfgagix_20KhYXNMNQ-- X-Yahoo-Newman-Property: ymail-3 From: David Brownell To: netdev@vger.kernel.org Subject: [patch 2.6.29-rc8] dm9000 locking bugfix Date: Sun, 22 Mar 2009 16:12:12 -0700 User-Agent: KMail/1.9.10 MIME-Version: 1.0 Content-Disposition: inline Message-Id: <200903221612.13055.david-b@pacbell.net> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: David Brownell This fixes a locking bug in the dm9000 driver. It calls request_irq() without setting IRQF_DISABLED ... which is correct for handlers that support IRQ sharing, since that behavior is not guaranteed for shared IRQs. However, its IRQ handler then wrongly assumes that IRQs are blocked. So the fix just uses the right spinlock primitives in the IRQ handler. NOTE: this is a classic example of the type of bug which lockdep currently masks by forcibly setting IRQF_DISABLED on IRQ handlers that did not request that flag. Signed-off-by: David Brownell --- The annoying "watchdog timeouts" seem unrelated to this. But on at least one problem, enabling lockdep makes them go away ... good fun, eh? drivers/net/dm9000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -930,13 +930,15 @@ static irqreturn_t dm9000_interrupt(int struct net_device *dev = dev_id; board_info_t *db = netdev_priv(dev); int int_status; + unsigned long flags; u8 reg_save; dm9000_dbg(db, 3, "entering %s\n", __func__); /* A real interrupt coming */ - spin_lock(&db->lock); + /* holders of db->lock must always block IRQs */ + spin_lock_irqsave(&db->lock, flags); /* Save previous register address */ reg_save = readb(db->io_addr); @@ -972,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int /* Restore previous register address */ writeb(reg_save, db->io_addr); - spin_unlock(&db->lock); + spin_unlock_irqrestore(&db->lock, flags); return IRQ_HANDLED; }