Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 41451
b: refs/heads/master
c: 3c3070d
h: refs/heads/master
i:
  41449: efa6c9c
  41447: 9be948a
v: v3
  • Loading branch information
Maciej W. Rozycki authored and Jeff Garzik committed Dec 2, 2006
1 parent fcccd72 commit 03fc3a0
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 13df29f69749a61b5209d52b71fcbf7300e5d6fb
refs/heads/master: 3c3070d713d798f7f9e7ee3614e49b47655d14d8
32 changes: 26 additions & 6 deletions trunk/drivers/net/phy/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
* Copyright (c) 2006 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
Expand All @@ -32,6 +33,8 @@
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/phy.h>
#include <linux/timer.h>
#include <linux/workqueue.h>

#include <asm/io.h>
#include <asm/irq.h>
Expand Down Expand Up @@ -484,6 +487,9 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
{
struct phy_device *phydev = phy_dat;

if (PHY_HALTED == phydev->state)
return IRQ_NONE; /* It can't be ours. */

/* The MDIO bus is not allowed to be written in interrupt
* context, so we need to disable the irq here. A work
* queue will write the PHY to disable and clear the
Expand Down Expand Up @@ -577,6 +583,13 @@ int phy_stop_interrupts(struct phy_device *phydev)
if (err)
phy_error(phydev);

/*
* Finish any pending work; we might have been scheduled
* to be called from keventd ourselves, though.
*/
if (!current_is_keventd())
flush_scheduled_work();

free_irq(phydev->irq, phydev);

return err;
Expand All @@ -603,7 +616,8 @@ static void phy_change(void *data)
enable_irq(phydev->irq);

/* Reenable interrupts */
err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);
if (PHY_HALTED != phydev->state)
err = phy_config_interrupt(phydev, PHY_INTERRUPT_ENABLED);

if (err)
goto irq_enable_err;
Expand All @@ -624,18 +638,24 @@ void phy_stop(struct phy_device *phydev)
if (PHY_HALTED == phydev->state)
goto out_unlock;

if (phydev->irq != PHY_POLL) {
/* Clear any pending interrupts */
phy_clear_interrupt(phydev);
phydev->state = PHY_HALTED;

if (phydev->irq != PHY_POLL) {
/* Disable PHY Interrupts */
phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
}

phydev->state = PHY_HALTED;
/* Clear any pending interrupts */
phy_clear_interrupt(phydev);
}

out_unlock:
spin_unlock(&phydev->lock);

/*
* Cannot call flush_scheduled_work() here as desired because
* of rtnl_lock(), but PHY_HALTED shall guarantee phy_change()
* will not reenable interrupts.
*/
}


Expand Down

0 comments on commit 03fc3a0

Please sign in to comment.