aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fec.c
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2009-09-01 19:14:15 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-03 02:46:03 -0400
commit84177a20799072c65a69b62571660d4d9780823c (patch)
tree2655c26b0601acf13509d25670d3924ae051449c /drivers/net/fec.c
parent3eb0027594e25f5947f074ae53fea30c15c5a7f6 (diff)
fec: fix recursive locking of mii_lock
mii_discover_phy is only called by fec_enet_mii (via mip->mii_func). So &fep->mii_lock is already held and mii_discover_phy must not call mii_queue which locks &fep->mii_lock, too. This was noticed by lockdep: ============================================= [ INFO: possible recursive locking detected ] 2.6.31-rc8-00038-g37d0892 #109 --------------------------------------------- swapper/1 is trying to acquire lock: (&fep->mii_lock){-.....}, at: [<c01569f8>] mii_queue+0x2c/0xcc but task is already holding lock: (&fep->mii_lock){-.....}, at: [<c0156328>] fec_enet_interrupt+0x78/0x460 other info that might help us debug this: 2 locks held by swapper/1: #0: (rtnl_mutex){+.+.+.}, at: [<c0183534>] rtnl_lock+0x18/0x20 #1: (&fep->mii_lock){-.....}, at: [<c0156328>] fec_enet_interrupt+0x78/0x460 stack backtrace: Backtrace: [<c00226fc>] (dump_backtrace+0x0/0x108) from [<c01eac14>] (dump_stack+0x18/0x1c) r6:c781d118 r5:c03e41d8 r4:00000001 [<c01eabfc>] (dump_stack+0x0/0x1c) from [<c005bae4>] (__lock_acquire+0x1a20/0x1a88) [<c005a0c4>] (__lock_acquire+0x0/0x1a88) from [<c005bbac>] (lock_acquire+0x60/0x74) [<c005bb4c>] (lock_acquire+0x0/0x74) from [<c01edda8>] (_spin_lock_irqsave+0x54/0x68) r7:60000093 r6:c01569f8 r5:c785e468 r4:00000000 [<c01edd54>] (_spin_lock_irqsave+0x0/0x68) from [<c01569f8>] (mii_queue+0x2c/0xcc) r7:c785e468 r6:c0156b24 r5:600a0000 r4:c785e000 [<c01569cc>] (mii_queue+0x0/0xcc) from [<c0156b78>] (mii_discover_phy+0x54/0xa8) r8:00000002 r7:00000032 r6:c785e000 r5:c785e360 r4:c785e000 [<c0156b24>] (mii_discover_phy+0x0/0xa8) from [<c0156354>] (fec_enet_interrupt+0xa4/0x460) r5:c785e360 r4:c077a170 [<c01562b0>] (fec_enet_interrupt+0x0/0x460) from [<c0066674>] (handle_IRQ_event+0x48/0x120) [<c006662c>] (handle_IRQ_event+0x0/0x120) from [<c0068438>] (handle_level_irq+0x94/0x11c) ... Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Cc: Greg Ungerer <gerg@uclinux.org> Cc: Ben Hutchings <ben@decadent.org.uk> Cc: Patrick McHardy <kaber@trash.net> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Matt Waddel <Matt.Waddel@freescale.com> Cc: netdev@vger.kernel.org Cc: Tim Sander <tim01@vlsi.informatik.tu-darmstadt.de> Acked-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/fec.c')
-rw-r--r--drivers/net/fec.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 967ad01b1925..e730da26d290 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -637,16 +637,15 @@ unlock:
637} 637}
638 638
639static int 639static int
640mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *)) 640mii_queue_unlocked(struct net_device *dev, int regval,
641 void (*func)(uint, struct net_device *))
641{ 642{
642 struct fec_enet_private *fep; 643 struct fec_enet_private *fep;
643 unsigned long flags;
644 mii_list_t *mip; 644 mii_list_t *mip;
645 int retval; 645 int retval;
646 646
647 /* Add PHY address to register command */ 647 /* Add PHY address to register command */
648 fep = netdev_priv(dev); 648 fep = netdev_priv(dev);
649 spin_lock_irqsave(&fep->mii_lock, flags);
650 649
651 regval |= fep->phy_addr << 23; 650 regval |= fep->phy_addr << 23;
652 retval = 0; 651 retval = 0;
@@ -667,6 +666,19 @@ mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_devi
667 retval = 1; 666 retval = 1;
668 } 667 }
669 668
669 return retval;
670}
671
672static int
673mii_queue(struct net_device *dev, int regval,
674 void (*func)(uint, struct net_device *))
675{
676 struct fec_enet_private *fep;
677 unsigned long flags;
678 int retval;
679 fep = netdev_priv(dev);
680 spin_lock_irqsave(&fep->mii_lock, flags);
681 retval = mii_queue_unlocked(dev, regval, func);
670 spin_unlock_irqrestore(&fep->mii_lock, flags); 682 spin_unlock_irqrestore(&fep->mii_lock, flags);
671 return retval; 683 return retval;
672} 684}
@@ -1373,11 +1385,11 @@ mii_discover_phy(uint mii_reg, struct net_device *dev)
1373 1385
1374 /* Got first part of ID, now get remainder */ 1386 /* Got first part of ID, now get remainder */
1375 fep->phy_id = phytype << 16; 1387 fep->phy_id = phytype << 16;
1376 mii_queue(dev, mk_mii_read(MII_REG_PHYIR2), 1388 mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR2),
1377 mii_discover_phy3); 1389 mii_discover_phy3);
1378 } else { 1390 } else {
1379 fep->phy_addr++; 1391 fep->phy_addr++;
1380 mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), 1392 mii_queue_unlocked(dev, mk_mii_read(MII_REG_PHYIR1),
1381 mii_discover_phy); 1393 mii_discover_phy);
1382 } 1394 }
1383 } else { 1395 } else {