diff options
| author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2010-11-11 22:55:08 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2010-11-12 15:21:17 -0500 |
| commit | 2040bd57b5f0c52dc4503e0e960b1dcafaf30a8b (patch) | |
| tree | 3c1f30cc90180320af9dc476bc16fb6abe07ce77 | |
| parent | 1f18b7176e2e41fada24584ce3c80e9abfaca52b (diff) | |
ucc_geth: Do not bring the whole IF down when TX failure.
ucc_geth_close lacks a cancel_work_sync(&ugeth->timeout_work)
to stop any outstanding processing of TX fail. However, one
can not call cancel_work_sync without fixing the timeout function
otherwise it will deadlock. This patch brings ucc_geth in line with
gianfar:
Don't bring the interface down and up, just reinit controller HW
and PHY.
Signed-off-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Reviewed-by: Anton Vorontsov <cbouatmailru@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ucc_geth.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index a4c3f5708246..cf6653f71d23 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
| @@ -2065,9 +2065,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth) | |||
| 2065 | /* Disable Rx and Tx */ | 2065 | /* Disable Rx and Tx */ |
| 2066 | clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); | 2066 | clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX); |
| 2067 | 2067 | ||
| 2068 | phy_disconnect(ugeth->phydev); | ||
| 2069 | ugeth->phydev = NULL; | ||
| 2070 | |||
| 2071 | ucc_geth_memclean(ugeth); | 2068 | ucc_geth_memclean(ugeth); |
| 2072 | } | 2069 | } |
| 2073 | 2070 | ||
| @@ -3550,7 +3547,10 @@ static int ucc_geth_close(struct net_device *dev) | |||
| 3550 | 3547 | ||
| 3551 | napi_disable(&ugeth->napi); | 3548 | napi_disable(&ugeth->napi); |
| 3552 | 3549 | ||
| 3550 | cancel_work_sync(&ugeth->timeout_work); | ||
| 3553 | ucc_geth_stop(ugeth); | 3551 | ucc_geth_stop(ugeth); |
| 3552 | phy_disconnect(ugeth->phydev); | ||
| 3553 | ugeth->phydev = NULL; | ||
| 3554 | 3554 | ||
| 3555 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev); | 3555 | free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev); |
| 3556 | 3556 | ||
| @@ -3579,8 +3579,12 @@ static void ucc_geth_timeout_work(struct work_struct *work) | |||
| 3579 | * Must reset MAC *and* PHY. This is done by reopening | 3579 | * Must reset MAC *and* PHY. This is done by reopening |
| 3580 | * the device. | 3580 | * the device. |
| 3581 | */ | 3581 | */ |
| 3582 | ucc_geth_close(dev); | 3582 | netif_tx_stop_all_queues(dev); |
| 3583 | ucc_geth_open(dev); | 3583 | ucc_geth_stop(ugeth); |
| 3584 | ucc_geth_init_mac(ugeth); | ||
| 3585 | /* Must start PHY here */ | ||
| 3586 | phy_start(ugeth->phydev); | ||
| 3587 | netif_tx_start_all_queues(dev); | ||
| 3584 | } | 3588 | } |
| 3585 | 3589 | ||
| 3586 | netif_tx_schedule_all(dev); | 3590 | netif_tx_schedule_all(dev); |
| @@ -3594,7 +3598,6 @@ static void ucc_geth_timeout(struct net_device *dev) | |||
| 3594 | { | 3598 | { |
| 3595 | struct ucc_geth_private *ugeth = netdev_priv(dev); | 3599 | struct ucc_geth_private *ugeth = netdev_priv(dev); |
| 3596 | 3600 | ||
| 3597 | netif_carrier_off(dev); | ||
| 3598 | schedule_work(&ugeth->timeout_work); | 3601 | schedule_work(&ugeth->timeout_work); |
| 3599 | } | 3602 | } |
| 3600 | 3603 | ||
