linux/drivers/net/phy
Anton Vorontsov ef24b16b5d phylib: Fix race between returning phydev and calling adjust_link
It is possible that phylib will call adjust_link before returning
from {,of_}phy_connect(), which may cause the following [very rare,
though] oops upon reopening the device:

  Unable to handle kernel paging request for data at address 0x0000024c
  Oops: Kernel access of bad area, sig: 11 [#1]
  PREEMPT SMP NR_CPUS=2 LTT NESTING LEVEL : 0
  P1021 RDB
  Modules linked in:
  NIP: c0345dac LR: c0345dac CTR: c0345d84
  TASK = dffab6b0[30] 'events/0' THREAD: c0d24000 CPU: 0
  [...]
  NIP [c0345dac] adjust_link+0x28/0x19c
  LR [c0345dac] adjust_link+0x28/0x19c
  Call Trace:
  [c0d25f00] [000045e1] 0x45e1 (unreliable)
  [c0d25f30] [c036c158] phy_state_machine+0x3ac/0x554
  [...]

Here is why. Drivers store phydev in their private structures, e.g.
gianfar driver:

static int init_phy(struct net_device *dev)
{
	...
	priv->phydev = of_phy_connect(...);
	...
}

So that adjust_link could retrieve it back:

static void adjust_link(struct net_device *dev)
{
	...
	struct phy_device *phydev = priv->phydev;
	...
}

If the device has been opened before, then phydev->state is set to
PHY_HALTED (or undefined if the driver didn't call phy_stop()).

Now, phy_connect starts the PHY state machine before returning phydev to
the driver:

	phy_start_machine(phydev, NULL);

	if (phydev->irq > 0)
		phy_start_interrupts(phydev);

	return phydev;

The time between 'phy_start_machine()' and 'return phydev' is undefined.
The start machine routine delays execution for 1 second, which is enough
for most cases. But under heavy load, or if you're unlucky, it is quite
possible that PHY state machine will execute before phy_connect()
returns, and so adjust_link callback will try to dereference phydev,
which is not yet ready.

To fix the issue, simply initialize the PHY's state to PHY_READY during
phy_attach(). This will ensure that phylib won't call adjust_link before
phy_start().

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2010-08-24 14:46:12 -07:00
..
bcm63xx.c PHY: fix typo in bcm63xx PHY driver table 2010-04-13 03:29:36 -07:00
broadcom.c broadcom: Add 5241 support 2010-06-24 21:30:09 -07:00
cicada.c Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2010-04-11 14:53:53 -07:00
davicom.c Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2010-04-11 14:53:53 -07:00
et1011c.c Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2010-04-11 14:53:53 -07:00
fixed.c include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h 2010-03-30 22:02:32 +09:00
icplus.c phy: add suspend/resume in the ic+ 2010-07-20 13:24:25 -07:00
Kconfig phylib: available for any speed ethernet 2010-08-11 23:03:50 -07:00
lxt.c phylib: Add autoload support for the LXT973 phy. 2010-06-26 22:12:03 -07:00
Makefile drivers/net/phy: micrel phy driver 2010-05-03 15:43:26 -07:00
marvell.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6 2010-08-04 11:47:58 -07:00
mdio_bus.c NET: Support clause 45 MDIO commands at the MDIO bus level 2010-03-16 21:23:42 -07:00
mdio-bitbang.c Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2010-04-11 14:53:53 -07:00
mdio-gpio.c of: Remove duplicate fields from of_platform_driver 2010-05-22 00:10:40 -06:00
mdio-octeon.c netdev: mdio-octeon: Fix section mismatch errors. 2010-06-28 23:58:54 -07:00
micrel.c micrel phy driver - updated(1) 2010-06-29 00:58:32 -07:00
national.c drivers/net: Remove unnecessary returns from void function()s 2010-05-14 00:19:28 -07:00
phy_device.c phylib: Fix race between returning phydev and calling adjust_link 2010-08-24 14:46:12 -07:00
phy.c phy.c: fix kernel-doc warnings 2010-08-10 00:09:21 -07:00
qsemi.c Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6 2010-04-11 14:53:53 -07:00
realtek.c phylib: Add module table to all existing phy drivers 2010-04-02 14:30:40 -07:00
smsc.c phylib: Add module table to all existing phy drivers 2010-04-02 14:30:40 -07:00
ste10Xp.c phylib: Add module table to all existing phy drivers 2010-04-02 14:30:40 -07:00
vitesse.c phylib: Add module table to all existing phy drivers 2010-04-02 14:30:40 -07:00