diff options
Diffstat (limited to 'drivers/net/gianfar.c')
-rw-r--r-- | drivers/net/gianfar.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ca6cf6ecb37b..4320a983a588 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -105,6 +105,7 @@ const char gfar_driver_version[] = "1.3"; | |||
105 | 105 | ||
106 | static int gfar_enet_open(struct net_device *dev); | 106 | static int gfar_enet_open(struct net_device *dev); |
107 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); | 107 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); |
108 | static void gfar_reset_task(struct work_struct *work); | ||
108 | static void gfar_timeout(struct net_device *dev); | 109 | static void gfar_timeout(struct net_device *dev); |
109 | static int gfar_close(struct net_device *dev); | 110 | static int gfar_close(struct net_device *dev); |
110 | struct sk_buff *gfar_new_skb(struct net_device *dev); | 111 | struct sk_buff *gfar_new_skb(struct net_device *dev); |
@@ -134,9 +135,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l | |||
134 | static void gfar_vlan_rx_register(struct net_device *netdev, | 135 | static void gfar_vlan_rx_register(struct net_device *netdev, |
135 | struct vlan_group *grp); | 136 | struct vlan_group *grp); |
136 | void gfar_halt(struct net_device *dev); | 137 | void gfar_halt(struct net_device *dev); |
137 | #ifdef CONFIG_PM | ||
138 | static void gfar_halt_nodisable(struct net_device *dev); | 138 | static void gfar_halt_nodisable(struct net_device *dev); |
139 | #endif | ||
140 | void gfar_start(struct net_device *dev); | 139 | void gfar_start(struct net_device *dev); |
141 | static void gfar_clear_exact_match(struct net_device *dev); | 140 | static void gfar_clear_exact_match(struct net_device *dev); |
142 | static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); | 141 | static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); |
@@ -211,6 +210,7 @@ static int gfar_probe(struct platform_device *pdev) | |||
211 | spin_lock_init(&priv->txlock); | 210 | spin_lock_init(&priv->txlock); |
212 | spin_lock_init(&priv->rxlock); | 211 | spin_lock_init(&priv->rxlock); |
213 | spin_lock_init(&priv->bflock); | 212 | spin_lock_init(&priv->bflock); |
213 | INIT_WORK(&priv->reset_task, gfar_reset_task); | ||
214 | 214 | ||
215 | platform_set_drvdata(pdev, dev); | 215 | platform_set_drvdata(pdev, dev); |
216 | 216 | ||
@@ -631,7 +631,6 @@ static void init_registers(struct net_device *dev) | |||
631 | } | 631 | } |
632 | 632 | ||
633 | 633 | ||
634 | #ifdef CONFIG_PM | ||
635 | /* Halt the receive and transmit queues */ | 634 | /* Halt the receive and transmit queues */ |
636 | static void gfar_halt_nodisable(struct net_device *dev) | 635 | static void gfar_halt_nodisable(struct net_device *dev) |
637 | { | 636 | { |
@@ -657,7 +656,6 @@ static void gfar_halt_nodisable(struct net_device *dev) | |||
657 | cpu_relax(); | 656 | cpu_relax(); |
658 | } | 657 | } |
659 | } | 658 | } |
660 | #endif | ||
661 | 659 | ||
662 | /* Halt the receive and transmit queues */ | 660 | /* Halt the receive and transmit queues */ |
663 | void gfar_halt(struct net_device *dev) | 661 | void gfar_halt(struct net_device *dev) |
@@ -666,6 +664,8 @@ void gfar_halt(struct net_device *dev) | |||
666 | struct gfar __iomem *regs = priv->regs; | 664 | struct gfar __iomem *regs = priv->regs; |
667 | u32 tempval; | 665 | u32 tempval; |
668 | 666 | ||
667 | gfar_halt_nodisable(dev); | ||
668 | |||
669 | /* Disable Rx and Tx */ | 669 | /* Disable Rx and Tx */ |
670 | tempval = gfar_read(®s->maccfg1); | 670 | tempval = gfar_read(®s->maccfg1); |
671 | tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); | 671 | tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); |
@@ -1214,6 +1214,7 @@ static int gfar_close(struct net_device *dev) | |||
1214 | 1214 | ||
1215 | napi_disable(&priv->napi); | 1215 | napi_disable(&priv->napi); |
1216 | 1216 | ||
1217 | cancel_work_sync(&priv->reset_task); | ||
1217 | stop_gfar(dev); | 1218 | stop_gfar(dev); |
1218 | 1219 | ||
1219 | /* Disconnect from the PHY */ | 1220 | /* Disconnect from the PHY */ |
@@ -1328,13 +1329,16 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) | |||
1328 | return 0; | 1329 | return 0; |
1329 | } | 1330 | } |
1330 | 1331 | ||
1331 | /* gfar_timeout gets called when a packet has not been | 1332 | /* gfar_reset_task gets scheduled when a packet has not been |
1332 | * transmitted after a set amount of time. | 1333 | * transmitted after a set amount of time. |
1333 | * For now, assume that clearing out all the structures, and | 1334 | * For now, assume that clearing out all the structures, and |
1334 | * starting over will fix the problem. */ | 1335 | * starting over will fix the problem. |
1335 | static void gfar_timeout(struct net_device *dev) | 1336 | */ |
1337 | static void gfar_reset_task(struct work_struct *work) | ||
1336 | { | 1338 | { |
1337 | dev->stats.tx_errors++; | 1339 | struct gfar_private *priv = container_of(work, struct gfar_private, |
1340 | reset_task); | ||
1341 | struct net_device *dev = priv->dev; | ||
1338 | 1342 | ||
1339 | if (dev->flags & IFF_UP) { | 1343 | if (dev->flags & IFF_UP) { |
1340 | stop_gfar(dev); | 1344 | stop_gfar(dev); |
@@ -1344,6 +1348,14 @@ static void gfar_timeout(struct net_device *dev) | |||
1344 | netif_tx_schedule_all(dev); | 1348 | netif_tx_schedule_all(dev); |
1345 | } | 1349 | } |
1346 | 1350 | ||
1351 | static void gfar_timeout(struct net_device *dev) | ||
1352 | { | ||
1353 | struct gfar_private *priv = netdev_priv(dev); | ||
1354 | |||
1355 | dev->stats.tx_errors++; | ||
1356 | schedule_work(&priv->reset_task); | ||
1357 | } | ||
1358 | |||
1347 | /* Interrupt Handler for Transmit complete */ | 1359 | /* Interrupt Handler for Transmit complete */ |
1348 | static int gfar_clean_tx_ring(struct net_device *dev) | 1360 | static int gfar_clean_tx_ring(struct net_device *dev) |
1349 | { | 1361 | { |