diff options
-rw-r--r-- | drivers/net/korina.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 26bf1b76b997..13533f937e05 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c | |||
@@ -135,6 +135,7 @@ struct korina_private { | |||
135 | struct napi_struct napi; | 135 | struct napi_struct napi; |
136 | struct timer_list media_check_timer; | 136 | struct timer_list media_check_timer; |
137 | struct mii_if_info mii_if; | 137 | struct mii_if_info mii_if; |
138 | struct work_struct restart_task; | ||
138 | struct net_device *dev; | 139 | struct net_device *dev; |
139 | int phy_addr; | 140 | int phy_addr; |
140 | }; | 141 | }; |
@@ -890,12 +891,12 @@ static int korina_init(struct net_device *dev) | |||
890 | 891 | ||
891 | /* | 892 | /* |
892 | * Restart the RC32434 ethernet controller. | 893 | * Restart the RC32434 ethernet controller. |
893 | * FIXME: check the return status where we call it | ||
894 | */ | 894 | */ |
895 | static int korina_restart(struct net_device *dev) | 895 | static void korina_restart_task(struct work_struct *work) |
896 | { | 896 | { |
897 | struct korina_private *lp = netdev_priv(dev); | 897 | struct korina_private *lp = container_of(work, |
898 | int ret; | 898 | struct korina_private, restart_task); |
899 | struct net_device *dev = lp->dev; | ||
899 | 900 | ||
900 | /* | 901 | /* |
901 | * Disable interrupts | 902 | * Disable interrupts |
@@ -916,10 +917,9 @@ static int korina_restart(struct net_device *dev) | |||
916 | 917 | ||
917 | napi_disable(&lp->napi); | 918 | napi_disable(&lp->napi); |
918 | 919 | ||
919 | ret = korina_init(dev); | 920 | if (korina_init(dev) < 0) { |
920 | if (ret < 0) { | ||
921 | printk(KERN_ERR "%s: cannot restart device\n", dev->name); | 921 | printk(KERN_ERR "%s: cannot restart device\n", dev->name); |
922 | return ret; | 922 | return; |
923 | } | 923 | } |
924 | korina_multicast_list(dev); | 924 | korina_multicast_list(dev); |
925 | 925 | ||
@@ -927,8 +927,6 @@ static int korina_restart(struct net_device *dev) | |||
927 | enable_irq(lp->ovr_irq); | 927 | enable_irq(lp->ovr_irq); |
928 | enable_irq(lp->tx_irq); | 928 | enable_irq(lp->tx_irq); |
929 | enable_irq(lp->rx_irq); | 929 | enable_irq(lp->rx_irq); |
930 | |||
931 | return ret; | ||
932 | } | 930 | } |
933 | 931 | ||
934 | static void korina_clear_and_restart(struct net_device *dev, u32 value) | 932 | static void korina_clear_and_restart(struct net_device *dev, u32 value) |
@@ -937,7 +935,7 @@ static void korina_clear_and_restart(struct net_device *dev, u32 value) | |||
937 | 935 | ||
938 | netif_stop_queue(dev); | 936 | netif_stop_queue(dev); |
939 | writel(value, &lp->eth_regs->ethintfc); | 937 | writel(value, &lp->eth_regs->ethintfc); |
940 | korina_restart(dev); | 938 | schedule_work(&lp->restart_task); |
941 | } | 939 | } |
942 | 940 | ||
943 | /* Ethernet Tx Underflow interrupt */ | 941 | /* Ethernet Tx Underflow interrupt */ |
@@ -962,11 +960,8 @@ static irqreturn_t korina_und_interrupt(int irq, void *dev_id) | |||
962 | static void korina_tx_timeout(struct net_device *dev) | 960 | static void korina_tx_timeout(struct net_device *dev) |
963 | { | 961 | { |
964 | struct korina_private *lp = netdev_priv(dev); | 962 | struct korina_private *lp = netdev_priv(dev); |
965 | unsigned long flags; | ||
966 | 963 | ||
967 | spin_lock_irqsave(&lp->lock, flags); | 964 | schedule_work(&lp->restart_task); |
968 | korina_restart(dev); | ||
969 | spin_unlock_irqrestore(&lp->lock, flags); | ||
970 | } | 965 | } |
971 | 966 | ||
972 | /* Ethernet Rx Overflow interrupt */ | 967 | /* Ethernet Rx Overflow interrupt */ |
@@ -1086,6 +1081,8 @@ static int korina_close(struct net_device *dev) | |||
1086 | 1081 | ||
1087 | napi_disable(&lp->napi); | 1082 | napi_disable(&lp->napi); |
1088 | 1083 | ||
1084 | cancel_work_sync(&lp->restart_task); | ||
1085 | |||
1089 | free_irq(lp->rx_irq, dev); | 1086 | free_irq(lp->rx_irq, dev); |
1090 | free_irq(lp->tx_irq, dev); | 1087 | free_irq(lp->tx_irq, dev); |
1091 | free_irq(lp->ovr_irq, dev); | 1088 | free_irq(lp->ovr_irq, dev); |
@@ -1198,6 +1195,8 @@ static int korina_probe(struct platform_device *pdev) | |||
1198 | } | 1195 | } |
1199 | setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev); | 1196 | setup_timer(&lp->media_check_timer, korina_poll_media, (unsigned long) dev); |
1200 | 1197 | ||
1198 | INIT_WORK(&lp->restart_task, korina_restart_task); | ||
1199 | |||
1201 | printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", | 1200 | printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", |
1202 | dev->name); | 1201 | dev->name); |
1203 | out: | 1202 | out: |