Anton Vorontsov 79675900cb ucc_geth: Fix three oopses in PHY {de,}initialization code
When there are no free snums, UCC ethernet should gracefully fail, but
currently it oopses this way:

  # ifconfig eth0 up
  fill_init_enet_entries: Can not get SNUM.
  ucc_geth_startup: Can not fill p_init_enet_param_shadow.
  eth0: Cannot configure net device, aborting.
  Unable to handle kernel paging request for data at address 0x00000190
  Faulting instruction address: 0xc0294c88
  Oops: Kernel access of bad area, sig: 11 [#1]
  [...]
  NIP [c0294c88] mutex_lock+0x0/0x1c
  LR [c01b6be8] phy_stop+0x20/0x70
  Call Trace:
  [efb25da0] [efb2eb60] 0xefb2eb60 (unreliable)
  [efb25db0] [c01b2058] ucc_geth_stop+0x2c/0x8c
  [efb25dd0] [c01b4194] ucc_geth_open+0x48/0x27c
  [efb25df0] [c020eec0] dev_open+0xc0/0x118
  [...]

This is because the ucc_geth_stop() routine assumes that ugeth->phydev
is always initialized by the ucc_geth_open(), while it is not in case
of errors.

If we add a check to the ucc_geth_stop(), then another oops pops up:

  Unable to handle kernel paging request for data at address 0x00000004
  Faulting instruction address: 0xc01b46a4
  Oops: Kernel access of bad area, sig: 11 [#1]
  [...]
  NIP [c01b46a4] adjust_link+0x20/0x1b4
  LR [c01b770c] phy_state_machine+0xdc/0x44c
  Call Trace:
  [ef83bf10] [c021b388] linkwatch_schedule_work+0x74/0xf8 (unreliable)
  [ef83bf40] [c01b770c] phy_state_machine+0xdc/0x44c
  [ef83bf60] [c004c13c] run_workqueue+0xb8/0x148
  [ef83bf90] [c004c870] worker_thread+0x70/0xd0
  [ef83bfd0] [c00505fc] kthread+0x48/0x84
  [ef83bff0] [c000f464] kernel_thread+0x4c/0x68
  [...]

That one happens because ucc_geth_stop() does not call phy_disconnect()
and so phylib state machine is running without any idea that a MAC has
just died.

Also, when device tree specifies fixed-link, and CONFIG_FIXED_PHY
is disabled, we'll get this oops:

  0:01 not found
  eth2: Could not attach to PHY
  eth2: Cannot initialize PHY, aborting.
  Unable to handle kernel paging request for data at address 0x00000190
  Faulting instruction address: 0xc02967d0
  Oops: Kernel access of bad area, sig: 11 [#1]
  [...]
  NIP [c02967d0] mutex_lock+0x0/0x1c
  LR [c01b6bcc] phy_stop+0x20/0x70
  Call Trace:
  [ef82be50] [efb6bb60] 0xefb6bb60 (unreliable)
  [ef82be60] [c01b2058] ucc_geth_stop+0x2c/0x8c
  [ef82be80] [c01b4194] ucc_geth_open+0x48/0x27c
  [ef82bea0] [c0210a04] dev_open+0xc0/0x118
  [ef82bec0] [c020f85c] dev_change_flags+0x84/0x1ac
  [ef82bee0] [c037b768] ic_open_devs+0x168/0x2bc
  [ef82bf20] [c037ca98] ip_auto_config+0x90/0x28c
  [ef82bf60] [c0001b9c] do_one_initcall+0x34/0x1a0
  [ef82bfd0] [c035e240] do_initcalls+0x38/0x58
  [ef82bfe0] [c035e2c4] kernel_init+0x30/0x90
  [ef82bff0] [c000f464] kernel_thread+0x4c/0x68
  [...]

And again, ucc_geth_stop() assumes that ugeth->phydev is there, while
it isn't.

This patch fixes all three oopses simply by rearranging some code:

- In ucc_geth_open(): move init_phy() call to the beginning, so
  that we only call ucc_geth_stop() with a PHY attached;
- Move phy_disconnect() call from ucc_geth_close() to
  ucc_geth_stop(), so that we'll always disconnect the PHY.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2009-03-27 16:00:03 -07:00
..
2009-03-23 01:18:58 -07:00
2008-12-17 15:37:55 -08:00
2009-03-26 01:10:00 -07:00
2009-03-21 22:37:56 -07:00
2009-01-21 14:02:21 -08:00
2008-12-08 01:14:16 -08:00
2009-03-27 00:46:38 -07:00
2009-01-21 14:02:23 -08:00
2009-01-21 14:02:24 -08:00
2009-01-21 14:02:24 -08:00
2009-01-21 14:02:25 -08:00
2008-11-25 18:12:49 -08:00
2009-03-18 18:17:48 -07:00
2008-11-25 18:25:32 -08:00
2009-01-07 18:10:24 -08:00
2009-02-12 16:53:48 -08:00
2009-02-12 16:53:22 -08:00
2009-03-02 22:32:48 -08:00
2009-02-15 23:32:01 -08:00
2009-02-15 23:32:01 -08:00
2009-02-15 23:32:01 -08:00
2009-03-02 22:32:43 -08:00
2008-09-22 19:27:10 -07:00
2009-01-07 17:34:36 -08:00
2009-01-07 17:34:36 -08:00
2008-11-21 17:31:51 -08:00
2008-02-01 20:54:03 +11:00
2009-03-22 21:28:39 -07:00
2008-11-20 20:28:00 -08:00
2009-01-07 17:30:09 -08:00
2009-01-21 14:33:50 -08:00
2009-03-21 19:06:53 -07:00
2008-11-25 18:23:59 -08:00
2009-02-01 00:58:26 -08:00
2009-03-10 05:29:52 -07:00
2009-02-04 16:43:44 -08:00
2009-01-07 18:13:49 -08:00
2009-02-26 21:02:19 -08:00
2008-11-25 18:24:57 -08:00
2009-01-21 14:33:50 -08:00
2009-01-06 10:47:44 -08:00
2009-01-07 17:26:14 -08:00
2008-08-14 04:26:38 -04:00
2009-01-21 14:33:50 -08:00
2009-03-27 00:46:48 -07:00
2008-11-25 18:24:38 -08:00
2007-10-19 11:53:42 -07:00
2007-04-28 11:01:05 -04:00
2008-11-25 18:23:35 -08:00
2008-10-27 17:06:18 -07:00
2009-03-27 00:46:53 -07:00
2008-03-26 00:18:00 -04:00
2009-03-27 00:46:53 -07:00
2008-03-05 16:34:41 -06:00
2008-12-08 01:14:16 -08:00
2009-01-21 14:33:50 -08:00
2009-01-07 17:26:48 -08:00
2009-03-13 16:09:12 -07:00
2008-01-28 15:11:27 -08:00
2009-03-13 16:09:12 -07:00
2009-03-13 16:09:12 -07:00
2008-11-10 15:11:56 -05:00
2009-01-21 14:33:50 -08:00
2009-01-07 17:56:54 -08:00
2009-01-21 14:03:42 -08:00
2009-03-18 23:31:49 -07:00
2009-01-07 17:35:41 -08:00
2009-01-21 14:33:50 -08:00
2007-10-16 21:10:29 -04:00
2009-02-03 15:08:36 -08:00
2008-08-07 01:55:50 -04:00
2008-01-28 15:11:27 -08:00
2009-01-07 18:09:36 -08:00
2009-03-27 00:46:48 -07:00
2007-07-16 15:02:47 +02:00
2008-04-16 20:06:50 -04:00
2008-11-25 18:25:49 -08:00
2008-12-08 01:14:16 -08:00
2008-08-29 02:13:33 -07:00
2008-01-28 15:07:10 -08:00
2008-08-29 02:14:29 -07:00
2008-08-29 02:14:43 -07:00
2009-03-20 00:51:22 -07:00
2009-02-26 23:20:56 -08:00
2009-02-26 23:20:56 -08:00
2009-03-04 15:08:19 -08:00
2009-01-07 17:27:15 -08:00
2008-05-30 22:18:02 -04:00
2009-02-14 20:46:39 -08:00
2009-03-02 22:15:09 -08:00
2009-03-03 23:36:04 -08:00
2009-01-11 00:06:36 -08:00
2009-01-21 14:02:31 -08:00