summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2009-11-17 12:02:43 +0100
committerClark Williams <williams@redhat.com>2012-02-15 10:32:31 -0600
commit57c8ea9f160d1d44fb761c3a2301a812856832f0 (patch)
tree0a591853fb21e719b0d28d6d948b02da8752babb /drivers/net
parent0f11aaf172fcafa1be5e9d281cf7309b88f78d13 (diff)
drivers: net: at91_ether: Make mdio protection -rt safe
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 <tglx@linutronix.de>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/cadence/at91_ether.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/net/ethernet/cadence/at91_ether.c b/drivers/net/ethernet/cadence/at91_ether.c
index 56624d303487..ad4dbea804d4 100644
--- a/drivers/net/ethernet/cadence/at91_ether.c
+++ b/drivers/net/ethernet/cadence/at91_ether.c
@@ -200,7 +200,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
@@ -242,6 +244,7 @@ static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
done:
disable_mdi();
+ spin_unlock_irqrestore(&lp->lock, flags);
return IRQ_HANDLED;
}
@@ -398,9 +401,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);
}