diff options
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r-- | drivers/net/ucc_geth.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index afaf088b72ea..eb8fe7e16c6c 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
@@ -1563,7 +1563,10 @@ static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode) | |||
1563 | 1563 | ||
1564 | static void ugeth_quiesce(struct ucc_geth_private *ugeth) | 1564 | static void ugeth_quiesce(struct ucc_geth_private *ugeth) |
1565 | { | 1565 | { |
1566 | /* Wait for and prevent any further xmits. */ | 1566 | /* Prevent any further xmits, plus detach the device. */ |
1567 | netif_device_detach(ugeth->ndev); | ||
1568 | |||
1569 | /* Wait for any current xmits to finish. */ | ||
1567 | netif_tx_disable(ugeth->ndev); | 1570 | netif_tx_disable(ugeth->ndev); |
1568 | 1571 | ||
1569 | /* Disable the interrupt to avoid NAPI rescheduling. */ | 1572 | /* Disable the interrupt to avoid NAPI rescheduling. */ |
@@ -1577,7 +1580,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth) | |||
1577 | { | 1580 | { |
1578 | napi_enable(&ugeth->napi); | 1581 | napi_enable(&ugeth->napi); |
1579 | enable_irq(ugeth->ug_info->uf_info.irq); | 1582 | enable_irq(ugeth->ug_info->uf_info.irq); |
1580 | netif_tx_wake_all_queues(ugeth->ndev); | 1583 | netif_device_attach(ugeth->ndev); |
1581 | } | 1584 | } |
1582 | 1585 | ||
1583 | /* Called every time the controller might need to be made | 1586 | /* Called every time the controller might need to be made |
@@ -1648,25 +1651,28 @@ static void adjust_link(struct net_device *dev) | |||
1648 | ugeth->oldspeed = phydev->speed; | 1651 | ugeth->oldspeed = phydev->speed; |
1649 | } | 1652 | } |
1650 | 1653 | ||
1651 | /* | ||
1652 | * To change the MAC configuration we need to disable the | ||
1653 | * controller. To do so, we have to either grab ugeth->lock, | ||
1654 | * which is a bad idea since 'graceful stop' commands might | ||
1655 | * take quite a while, or we can quiesce driver's activity. | ||
1656 | */ | ||
1657 | ugeth_quiesce(ugeth); | ||
1658 | ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); | ||
1659 | |||
1660 | out_be32(&ug_regs->maccfg2, tempval); | ||
1661 | out_be32(&uf_regs->upsmr, upsmr); | ||
1662 | |||
1663 | ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); | ||
1664 | ugeth_activate(ugeth); | ||
1665 | |||
1666 | if (!ugeth->oldlink) { | 1654 | if (!ugeth->oldlink) { |
1667 | new_state = 1; | 1655 | new_state = 1; |
1668 | ugeth->oldlink = 1; | 1656 | ugeth->oldlink = 1; |
1669 | } | 1657 | } |
1658 | |||
1659 | if (new_state) { | ||
1660 | /* | ||
1661 | * To change the MAC configuration we need to disable | ||
1662 | * the controller. To do so, we have to either grab | ||
1663 | * ugeth->lock, which is a bad idea since 'graceful | ||
1664 | * stop' commands might take quite a while, or we can | ||
1665 | * quiesce driver's activity. | ||
1666 | */ | ||
1667 | ugeth_quiesce(ugeth); | ||
1668 | ugeth_disable(ugeth, COMM_DIR_RX_AND_TX); | ||
1669 | |||
1670 | out_be32(&ug_regs->maccfg2, tempval); | ||
1671 | out_be32(&uf_regs->upsmr, upsmr); | ||
1672 | |||
1673 | ugeth_enable(ugeth, COMM_DIR_RX_AND_TX); | ||
1674 | ugeth_activate(ugeth); | ||
1675 | } | ||
1670 | } else if (ugeth->oldlink) { | 1676 | } else if (ugeth->oldlink) { |
1671 | new_state = 1; | 1677 | new_state = 1; |
1672 | ugeth->oldlink = 0; | 1678 | ugeth->oldlink = 0; |
@@ -3273,13 +3279,12 @@ static int ucc_geth_tx(struct net_device *dev, u8 txQ) | |||
3273 | /* Handle the transmitted buffer and release */ | 3279 | /* Handle the transmitted buffer and release */ |
3274 | /* the BD to be used with the current frame */ | 3280 | /* the BD to be used with the current frame */ |
3275 | 3281 | ||
3276 | if ((bd == ugeth->txBd[txQ]) && (netif_queue_stopped(dev) == 0)) | 3282 | skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; |
3283 | if (!skb) | ||
3277 | break; | 3284 | break; |
3278 | 3285 | ||
3279 | dev->stats.tx_packets++; | 3286 | dev->stats.tx_packets++; |
3280 | 3287 | ||
3281 | skb = ugeth->tx_skbuff[txQ][ugeth->skb_dirtytx[txQ]]; | ||
3282 | |||
3283 | if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN && | 3288 | if (skb_queue_len(&ugeth->rx_recycle) < RX_BD_RING_LEN && |
3284 | skb_recycle_check(skb, | 3289 | skb_recycle_check(skb, |
3285 | ugeth->ug_info->uf_info.max_rx_buf_length + | 3290 | ugeth->ug_info->uf_info.max_rx_buf_length + |
@@ -3601,6 +3606,7 @@ static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state) | |||
3601 | if (!netif_running(ndev)) | 3606 | if (!netif_running(ndev)) |
3602 | return 0; | 3607 | return 0; |
3603 | 3608 | ||
3609 | netif_device_detach(ndev); | ||
3604 | napi_disable(&ugeth->napi); | 3610 | napi_disable(&ugeth->napi); |
3605 | 3611 | ||
3606 | /* | 3612 | /* |
@@ -3659,7 +3665,7 @@ static int ucc_geth_resume(struct of_device *ofdev) | |||
3659 | phy_start(ugeth->phydev); | 3665 | phy_start(ugeth->phydev); |
3660 | 3666 | ||
3661 | napi_enable(&ugeth->napi); | 3667 | napi_enable(&ugeth->napi); |
3662 | netif_start_queue(ndev); | 3668 | netif_device_attach(ndev); |
3663 | 3669 | ||
3664 | return 0; | 3670 | return 0; |
3665 | } | 3671 | } |