Commit 59fbcbc6 authored by Michael Grzeschik's avatar Michael Grzeschik

arcnet: add netif_carrier_on/off for reconnect

The arcnet device has no interrupt to detect if the link has changed
from disconnected to connected. This patch adds an timer to toggle the
link detection. The timer will get retriggered as long as the
reconnection interrupts accure. If the recon interrupts hold off
for >1s we define the connection stable again.
Signed-off-by: default avatarMichael Grzeschik <m.grzeschik@pengutronix.de>
parent 8890624a
...@@ -267,6 +267,8 @@ struct arcnet_local { ...@@ -267,6 +267,8 @@ struct arcnet_local {
struct led_trigger *recon_led_trig; struct led_trigger *recon_led_trig;
char recon_led_trig_name[ARCNET_LED_NAME_SZ]; char recon_led_trig_name[ARCNET_LED_NAME_SZ];
struct timer_list timer;
/* /*
* Buffer management: an ARCnet card has 4 x 512-byte buffers, each of * Buffer management: an ARCnet card has 4 x 512-byte buffers, each of
* which can be used for either sending or receiving. The new dynamic * which can be used for either sending or receiving. The new dynamic
......
...@@ -381,6 +381,16 @@ static void arcdev_setup(struct net_device *dev) ...@@ -381,6 +381,16 @@ static void arcdev_setup(struct net_device *dev)
dev->flags = IFF_BROADCAST; dev->flags = IFF_BROADCAST;
} }
static void arcnet_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev);
netdev_info(dev, "link up\n");
}
}
struct net_device *alloc_arcdev(const char *name) struct net_device *alloc_arcdev(const char *name)
{ {
struct net_device *dev; struct net_device *dev;
...@@ -392,6 +402,9 @@ struct net_device *alloc_arcdev(const char *name) ...@@ -392,6 +402,9 @@ struct net_device *alloc_arcdev(const char *name)
struct arcnet_local *lp = netdev_priv(dev); struct arcnet_local *lp = netdev_priv(dev);
spin_lock_init(&lp->lock); spin_lock_init(&lp->lock);
init_timer(&lp->timer);
lp->timer.data = (unsigned long) dev;
lp->timer.function = arcnet_timer;
} }
return dev; return dev;
...@@ -490,7 +503,9 @@ int arcnet_open(struct net_device *dev) ...@@ -490,7 +503,9 @@ int arcnet_open(struct net_device *dev)
lp->hw.intmask(dev, lp->intmask); lp->hw.intmask(dev, lp->intmask);
arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__); arc_printk(D_DEBUG, dev, "%s: %d: %s\n", __FILE__, __LINE__, __func__);
netif_carrier_off(dev);
netif_start_queue(dev); netif_start_queue(dev);
mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));
arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN); arcnet_led_event(dev, ARCNET_LED_EVENT_OPEN);
return 0; return 0;
...@@ -507,7 +522,10 @@ int arcnet_close(struct net_device *dev) ...@@ -507,7 +522,10 @@ int arcnet_close(struct net_device *dev)
struct arcnet_local *lp = netdev_priv(dev); struct arcnet_local *lp = netdev_priv(dev);
arcnet_led_event(dev, ARCNET_LED_EVENT_STOP); arcnet_led_event(dev, ARCNET_LED_EVENT_STOP);
del_timer_sync(&lp->timer);
netif_stop_queue(dev); netif_stop_queue(dev);
netif_carrier_off(dev);
/* flush TX and disable RX */ /* flush TX and disable RX */
lp->hw.intmask(dev, 0); lp->hw.intmask(dev, 0);
...@@ -908,6 +926,12 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) ...@@ -908,6 +926,12 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n", arc_printk(D_RECON, dev, "Network reconfiguration detected (status=%Xh)\n",
status); status);
if (netif_carrier_ok(dev)) {
netif_carrier_off(dev);
netdev_info(dev, "link down\n");
}
mod_timer(&lp->timer, jiffies + msecs_to_jiffies(1000));
arcnet_led_event(dev, ARCNET_LED_EVENT_RECON); arcnet_led_event(dev, ARCNET_LED_EVENT_RECON);
/* MYRECON bit is at bit 7 of diagstatus */ /* MYRECON bit is at bit 7 of diagstatus */
if (diagstatus & 0x80) if (diagstatus & 0x80)
...@@ -959,6 +983,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) ...@@ -959,6 +983,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
lp->num_recons = lp->network_down = 0; lp->num_recons = lp->network_down = 0;
arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n"); arc_printk(D_DURING, dev, "not recon: clearing counters anyway.\n");
netif_carrier_on(dev);
} }
if (didsomething) if (didsomething)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment