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 | } |
