summaryrefslogtreecommitdiffstats
path: root/drivers/net/gianfar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/gianfar.c')
-rw-r--r--drivers/net/gianfar.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index b8394cf..b5bb7ae 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -105,6 +105,7 @@ const char gfar_driver_version[] = "1.3";
static int gfar_enet_open(struct net_device *dev);
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void gfar_reset_task(struct work_struct *work);
static void gfar_timeout(struct net_device *dev);
static int gfar_close(struct net_device *dev);
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
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
void gfar_halt(struct net_device *dev);
-#ifdef CONFIG_PM
static void gfar_halt_nodisable(struct net_device *dev);
-#endif
void gfar_start(struct net_device *dev);
static void gfar_clear_exact_match(struct net_device *dev);
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)
spin_lock_init(&priv->txlock);
spin_lock_init(&priv->rxlock);
spin_lock_init(&priv->bflock);
+ INIT_WORK(&priv->reset_task, gfar_reset_task);
platform_set_drvdata(pdev, dev);
@@ -339,6 +339,9 @@ static int gfar_probe(struct platform_device *pdev)
/* Enable most messages by default */
priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
+ /* Carrier starts down, phylib will bring it up */
+ netif_carrier_off(dev);
+
err = register_netdev(dev);
if (err) {
@@ -414,9 +417,7 @@ static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
spin_unlock(&priv->rxlock);
spin_unlock_irqrestore(&priv->txlock, flags);
-#ifdef CONFIG_GFAR_NAPI
napi_disable(&priv->napi);
-#endif
if (magic_packet) {
/* Enable interrupt on Magic Packet */
@@ -469,9 +470,7 @@ static int gfar_resume(struct platform_device *pdev)
netif_device_attach(dev);
-#ifdef CONFIG_GFAR_NAPI
napi_enable(&priv->napi);
-#endif
return 0;
}
@@ -635,7 +634,6 @@ static void init_registers(struct net_device *dev)
}
-#ifdef CONFIG_PM
/* Halt the receive and transmit queues */
static void gfar_halt_nodisable(struct net_device *dev)
{
@@ -661,7 +659,6 @@ static void gfar_halt_nodisable(struct net_device *dev)
cpu_relax();
}
}
-#endif
/* Halt the receive and transmit queues */
void gfar_halt(struct net_device *dev)
@@ -670,6 +667,8 @@ void gfar_halt(struct net_device *dev)
struct gfar __iomem *regs = priv->regs;
u32 tempval;
+ gfar_halt_nodisable(dev);
+
/* Disable Rx and Tx */
tempval = gfar_read(&regs->maccfg1);
tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
@@ -1218,6 +1217,7 @@ static int gfar_close(struct net_device *dev)
napi_disable(&priv->napi);
+ cancel_work_sync(&priv->reset_task);
stop_gfar(dev);
/* Disconnect from the PHY */
@@ -1332,13 +1332,16 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
-/* gfar_timeout gets called when a packet has not been
+/* gfar_reset_task gets scheduled when a packet has not been
* transmitted after a set amount of time.
* For now, assume that clearing out all the structures, and
- * starting over will fix the problem. */
-static void gfar_timeout(struct net_device *dev)
+ * starting over will fix the problem.
+ */
+static void gfar_reset_task(struct work_struct *work)
{
- dev->stats.tx_errors++;
+ struct gfar_private *priv = container_of(work, struct gfar_private,
+ reset_task);
+ struct net_device *dev = priv->dev;
if (dev->flags & IFF_UP) {
stop_gfar(dev);
@@ -1348,6 +1351,14 @@ static void gfar_timeout(struct net_device *dev)
netif_tx_schedule_all(dev);
}
+static void gfar_timeout(struct net_device *dev)
+{
+ struct gfar_private *priv = netdev_priv(dev);
+
+ dev->stats.tx_errors++;
+ schedule_work(&priv->reset_task);
+}
+
/* Interrupt Handler for Transmit complete */
static int gfar_clean_tx_ring(struct net_device *dev)
{
OpenPOWER on IntegriCloud