From 18033b350193d8e3517c3446436979ab495cd950 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 17 Nov 2009 12:02:43 +0100 Subject: [PATCH] net: at91_ether: Make mdio protection -rt safe commit 05d5f5080a2e3fbbc0f762875b66721588f5e251 in tip. Neither the phy interrupt nor the timer callback which updates the link status in absense of a phy interrupt are taking lp->lock which serializes the MDIO access. This works on mainline as at91 is an UP machine. On preempt-rt the timer callback can run even in the spin_lock_irq(&lp->lock) protected code pathes because spin_lock_irq is neither disabling interrupts nor disabling preemption. Fix this by adding proper locking to at91ether_phy_interrupt() and at91_check_ether() which serializes the access on -rt. Signed-off-by: Thomas Gleixner Signed-off-by: Paul Gortmaker --- drivers/net/arm/at91_ether.c | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index aed5b54..75146af 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c @@ -199,7 +199,9 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) struct net_device *dev = (struct net_device *) dev_id; struct at91_private *lp = netdev_priv(dev); unsigned int phy; + unsigned long flags; + spin_lock_irqsave(&lp->lock, flags); /* * This hander is triggered on both edges, but the PHY chips expect * level-triggering. We therefore have to check if the PHY actually has @@ -241,6 +243,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id) done: disable_mdi(); + spin_unlock_irqrestore(&lp->lock, flags); return IRQ_HANDLED; } @@ -397,9 +400,11 @@ static void at91ether_check_link(unsigned long dev_id) struct net_device *dev = (struct net_device *) dev_id; struct at91_private *lp = netdev_priv(dev); + spin_lock_irq(&lp->lock); enable_mdi(); update_linkspeed(dev, 1); disable_mdi(); + spin_unlock_irq(&lp->lock); mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL); } -- 1.7.0.4