Commit 2424dc63 authored by Krzysztof Halasa's avatar Krzysztof Halasa Committed by Jeff Garzik

[PATCH] 2.6 Generic HDLC update

The attached patch updates generic HDLC:
- fixed some carrier-related problems (Cisco HDLC and FR links could
  report valid link when no carrier was detected at startup).
- fixed kbuild problems with wanxl firmware (building kernel in separate
  tree). $(src)/wanxlfw.inc is now wanxlfw.inc_shipped.
parent ee4571db
...@@ -61,6 +61,9 @@ obj-$(CONFIG_C101) += c101.o ...@@ -61,6 +61,9 @@ obj-$(CONFIG_C101) += c101.o
obj-$(CONFIG_WANXL) += wanxl.o obj-$(CONFIG_WANXL) += wanxl.o
obj-$(CONFIG_PCI200SYN) += pci200syn.o obj-$(CONFIG_PCI200SYN) += pci200syn.o
clean-files := wanxlfw.inc
$(obj)/wanxl.o: $(obj)/wanxlfw.inc
ifeq ($(CONFIG_WANXL_BUILD_FIRMWARE),y) ifeq ($(CONFIG_WANXL_BUILD_FIRMWARE),y)
ifeq ($(ARCH),m68k) ifeq ($(ARCH),m68k)
AS68K = $(AS) AS68K = $(AS)
...@@ -72,12 +75,12 @@ endif ...@@ -72,12 +75,12 @@ endif
quiet_cmd_build_wanxlfw = BLD FW $@ quiet_cmd_build_wanxlfw = BLD FW $@
cmd_build_wanxlfw = \ cmd_build_wanxlfw = \
$(CPP) -Wp,-MD,$(depfile) -Iinclude $(obj)/wanxlfw.S | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \ $(CPP) -Wp,-MD,$(depfile) -I$(srctree)/include $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
$(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \ $(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \ hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o
$(obj)/wanxlfw.inc: $(obj)/wanxlfw.S $(obj)/wanxlfw.inc: $(src)/wanxlfw.S
$(call if_changed_dep,build_wanxlfw) $(call if_changed_dep,build_wanxlfw)
targets += wanxlfw.inc targets += wanxlfw.inc
endif endif
...@@ -379,8 +379,6 @@ static int __init c101_run(unsigned long irq, unsigned long winbase) ...@@ -379,8 +379,6 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
return result; return result;
} }
/* XXX: are we OK with having that done when card is already up? */
sca_init_sync_port(card); /* Set up C101 memory */ sca_init_sync_port(card); /* Set up C101 memory */
hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev); hdlc_set_carrier(!(sca_in(MSCI1_OFFSET + ST3, card) & ST3_DCD), dev);
......
...@@ -180,7 +180,8 @@ static int cisco_rx(struct sk_buff *skb) ...@@ -180,7 +180,8 @@ static int cisco_rx(struct sk_buff *skb)
case CISCO_KEEPALIVE_REQ: case CISCO_KEEPALIVE_REQ:
hdlc->state.cisco.rxseq = ntohl(cisco_data->par1); hdlc->state.cisco.rxseq = ntohl(cisco_data->par1);
if (ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) { if (hdlc->state.cisco.request_sent &&
ntohl(cisco_data->par2)==hdlc->state.cisco.txseq) {
hdlc->state.cisco.last_poll = jiffies; hdlc->state.cisco.last_poll = jiffies;
if (!hdlc->state.cisco.up) { if (!hdlc->state.cisco.up) {
u32 sec, min, hrs, days; u32 sec, min, hrs, days;
...@@ -192,8 +193,9 @@ static int cisco_rx(struct sk_buff *skb) ...@@ -192,8 +193,9 @@ static int cisco_rx(struct sk_buff *skb)
"uptime %ud%uh%um%us)\n", "uptime %ud%uh%um%us)\n",
dev->name, days, hrs, dev->name, days, hrs,
min, sec); min, sec);
netif_carrier_on(dev);
hdlc->state.cisco.up = 1;
} }
hdlc->state.cisco.up = 1;
} }
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -219,17 +221,18 @@ static void cisco_timer(unsigned long arg) ...@@ -219,17 +221,18 @@ static void cisco_timer(unsigned long arg)
struct net_device *dev = (struct net_device *)arg; struct net_device *dev = (struct net_device *)arg;
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->state.cisco.up && jiffies - hdlc->state.cisco.last_poll >= if (hdlc->state.cisco.up &&
hdlc->state.cisco.settings.timeout * HZ) { time_after(jiffies, hdlc->state.cisco.last_poll +
hdlc->state.cisco.settings.timeout * HZ)) {
hdlc->state.cisco.up = 0; hdlc->state.cisco.up = 0;
printk(KERN_INFO "%s: Link down\n", dev->name); printk(KERN_INFO "%s: Link down\n", dev->name);
if (netif_carrier_ok(dev)) netif_carrier_off(dev);
netif_carrier_off(dev);
} }
cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ, cisco_keepalive_send(dev, CISCO_KEEPALIVE_REQ,
++hdlc->state.cisco.txseq, ++hdlc->state.cisco.txseq,
hdlc->state.cisco.rxseq); hdlc->state.cisco.rxseq);
hdlc->state.cisco.request_sent = 1;
hdlc->state.cisco.timer.expires = jiffies + hdlc->state.cisco.timer.expires = jiffies +
hdlc->state.cisco.settings.interval * HZ; hdlc->state.cisco.settings.interval * HZ;
hdlc->state.cisco.timer.function = cisco_timer; hdlc->state.cisco.timer.function = cisco_timer;
...@@ -242,8 +245,8 @@ static void cisco_timer(unsigned long arg) ...@@ -242,8 +245,8 @@ static void cisco_timer(unsigned long arg)
static void cisco_start(struct net_device *dev) static void cisco_start(struct net_device *dev)
{ {
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
hdlc->state.cisco.last_poll = 0;
hdlc->state.cisco.up = 0; hdlc->state.cisco.up = 0;
hdlc->state.cisco.request_sent = 0;
hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0; hdlc->state.cisco.txseq = hdlc->state.cisco.rxseq = 0;
init_timer(&hdlc->state.cisco.timer); init_timer(&hdlc->state.cisco.timer);
...@@ -257,9 +260,12 @@ static void cisco_start(struct net_device *dev) ...@@ -257,9 +260,12 @@ static void cisco_start(struct net_device *dev)
static void cisco_stop(struct net_device *dev) static void cisco_stop(struct net_device *dev)
{ {
del_timer_sync(&dev_to_hdlc(dev)->state.cisco.timer); hdlc_device *hdlc = dev_to_hdlc(dev);
del_timer_sync(&hdlc->state.cisco.timer);
if (netif_carrier_ok(dev)) if (netif_carrier_ok(dev))
netif_carrier_off(dev); netif_carrier_off(dev);
hdlc->state.cisco.up = 0;
hdlc->state.cisco.request_sent = 0;
} }
......
...@@ -584,8 +584,9 @@ static void fr_timer(unsigned long arg) ...@@ -584,8 +584,9 @@ static void fr_timer(unsigned long arg)
u32 list; u32 list;
if (hdlc->state.fr.settings.dce) if (hdlc->state.fr.settings.dce)
reliable = (jiffies - hdlc->state.fr.last_poll < reliable = hdlc->state.fr.request &&
hdlc->state.fr.settings.t392 * HZ); time_before(jiffies, hdlc->state.fr.last_poll +
hdlc->state.fr.settings.t392 * HZ);
else { else {
hdlc->state.fr.last_errors <<= 1; /* Shift the list */ hdlc->state.fr.last_errors <<= 1; /* Shift the list */
if (hdlc->state.fr.request) { if (hdlc->state.fr.request) {
...@@ -617,6 +618,7 @@ static void fr_timer(unsigned long arg) ...@@ -617,6 +618,7 @@ static void fr_timer(unsigned long arg)
fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0); fr_lmi_send(dev, hdlc->state.fr.n391cnt == 0);
hdlc->state.fr.last_poll = jiffies;
hdlc->state.fr.request = 1; hdlc->state.fr.request = 1;
hdlc->state.fr.timer.expires = jiffies + hdlc->state.fr.timer.expires = jiffies +
hdlc->state.fr.settings.t391 * HZ; hdlc->state.fr.settings.t391 * HZ;
...@@ -689,6 +691,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) ...@@ -689,6 +691,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
dev->name, reptype); dev->name, reptype);
return 1; return 1;
} }
hdlc->state.fr.last_poll = jiffies;
} }
error = 0; error = 0;
...@@ -728,7 +731,12 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) ...@@ -728,7 +731,12 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
/* DTE */ /* DTE */
if (reptype != LMI_FULLREP || error) hdlc->state.fr.request = 0; /* got response, no request pending */
if (error)
return 0;
if (reptype != LMI_FULLREP)
return 0; return 0;
stat_len = 3; stat_len = 3;
...@@ -829,9 +837,6 @@ static int fr_rx(struct sk_buff *skb) ...@@ -829,9 +837,6 @@ static int fr_rx(struct sk_buff *skb)
if (fr_lmi_recv(ndev, skb)) if (fr_lmi_recv(ndev, skb))
goto rx_error; goto rx_error;
else { else {
/* No request pending */
hdlc->state.fr.request = 0;
hdlc->state.fr.last_poll = jiffies;
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
} }
...@@ -946,9 +951,6 @@ static void fr_start(struct net_device *dev) ...@@ -946,9 +951,6 @@ static void fr_start(struct net_device *dev)
printk(KERN_DEBUG "fr_start\n"); printk(KERN_DEBUG "fr_start\n");
#endif #endif
if (hdlc->state.fr.settings.lmi != LMI_NONE) { if (hdlc->state.fr.settings.lmi != LMI_NONE) {
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
hdlc->state.fr.last_poll = 0;
hdlc->state.fr.reliable = 0; hdlc->state.fr.reliable = 0;
hdlc->state.fr.dce_changed = 1; hdlc->state.fr.dce_changed = 1;
hdlc->state.fr.request = 0; hdlc->state.fr.request = 0;
......
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
* * X.25 * * X.25
* *
* Use sethdlc utility to set line parameters, protocol and PVCs * Use sethdlc utility to set line parameters, protocol and PVCs
*
* How does it work:
* - proto.open(), close(), start(), stop() calls are serialized.
* The order is: open, [ start, stop ... ] close ...
* - proto.start() and stop() are called with spin_lock_irq held.
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -33,7 +38,7 @@ ...@@ -33,7 +38,7 @@
#include <linux/hdlc.h> #include <linux/hdlc.h>
static const char* version = "HDLC support module revision 1.16"; static const char* version = "HDLC support module revision 1.17";
#undef DEBUG_LINK #undef DEBUG_LINK
...@@ -69,51 +74,75 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -69,51 +74,75 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
static void __hdlc_set_carrier_on(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.start)
return hdlc->proto.start(dev);
#ifdef DEBUG_LINK
if (netif_carrier_ok(dev))
printk(KERN_ERR "hdlc_set_carrier_on(): already on\n");
#endif
netif_carrier_on(dev);
}
static void __hdlc_set_carrier_off(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
if (hdlc->proto.stop)
return hdlc->proto.stop(dev);
#ifdef DEBUG_LINK
if (!netif_carrier_ok(dev))
printk(KERN_ERR "hdlc_set_carrier_off(): already off\n");
#endif
netif_carrier_off(dev);
}
void hdlc_set_carrier(int on, struct net_device *dev) void hdlc_set_carrier(int on, struct net_device *dev)
{ {
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
unsigned long flags;
on = on ? 1 : 0; on = on ? 1 : 0;
#ifdef DEBUG_LINK #ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_set_carrier %i\n", on); printk(KERN_DEBUG "hdlc_set_carrier %i\n", on);
#endif #endif
spin_lock_irq(&hdlc->state_lock); spin_lock_irqsave(&hdlc->state_lock, flags);
if (hdlc->carrier == on) if (hdlc->carrier == on)
goto carrier_exit; /* no change in DCD line level */ goto carrier_exit; /* no change in DCD line level */
printk(KERN_INFO "%s: carrier %s\n", dev->name, #ifdef DEBUG_LINK
on ? "ON" : "off"); printk(KERN_INFO "%s: carrier %s\n", dev->name, on ? "ON" : "off");
#endif
hdlc->carrier = on; hdlc->carrier = on;
if (!hdlc->open) if (!hdlc->open)
goto carrier_exit; goto carrier_exit;
if (hdlc->carrier) { if (hdlc->carrier)
if (hdlc->proto.start) __hdlc_set_carrier_on(dev);
hdlc->proto.start(dev); else
else if (!netif_carrier_ok(dev)) __hdlc_set_carrier_off(dev);
netif_carrier_on(dev);
} else { /* no carrier */
if (hdlc->proto.stop)
hdlc->proto.stop(dev);
else if (netif_carrier_ok(dev))
netif_carrier_off(dev);
}
carrier_exit: carrier_exit:
spin_unlock_irq(&hdlc->state_lock); spin_unlock_irqrestore(&hdlc->state_lock, flags);
} }
/* Must be called by hardware driver when HDLC device is being opened */ /* Must be called by hardware driver when HDLC device is being opened */
int hdlc_open(struct net_device *dev) int hdlc_open(struct net_device *dev)
{ {
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
#ifdef DEBUG_LINK #ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_open carrier %i open %i\n", printk(KERN_DEBUG "hdlc_open() carrier %i open %i\n",
hdlc->carrier, hdlc->open); hdlc->carrier, hdlc->open);
#endif #endif
...@@ -128,14 +157,8 @@ int hdlc_open(struct net_device *dev) ...@@ -128,14 +157,8 @@ int hdlc_open(struct net_device *dev)
spin_lock_irq(&hdlc->state_lock); spin_lock_irq(&hdlc->state_lock);
if (hdlc->carrier) { if (hdlc->carrier)
if (hdlc->proto.start) __hdlc_set_carrier_on(dev);
hdlc->proto.start(dev);
else if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
} else if (netif_carrier_ok(dev))
netif_carrier_off(dev);
hdlc->open = 1; hdlc->open = 1;
...@@ -150,15 +173,15 @@ void hdlc_close(struct net_device *dev) ...@@ -150,15 +173,15 @@ void hdlc_close(struct net_device *dev)
{ {
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
#ifdef DEBUG_LINK #ifdef DEBUG_LINK
printk(KERN_DEBUG "hdlc_close carrier %i open %i\n", printk(KERN_DEBUG "hdlc_close() carrier %i open %i\n",
hdlc->carrier, hdlc->open); hdlc->carrier, hdlc->open);
#endif #endif
spin_lock_irq(&hdlc->state_lock); spin_lock_irq(&hdlc->state_lock);
hdlc->open = 0; hdlc->open = 0;
if (hdlc->carrier && hdlc->proto.stop) if (hdlc->carrier)
hdlc->proto.stop(dev); __hdlc_set_carrier_off(dev);
spin_unlock_irq(&hdlc->state_lock); spin_unlock_irq(&hdlc->state_lock);
...@@ -185,7 +208,7 @@ void hdlc_close(struct net_device *dev) ...@@ -185,7 +208,7 @@ void hdlc_close(struct net_device *dev)
#endif #endif
#ifndef CONFIG_HDLC_FR #ifndef CONFIG_HDLC_FR
#define hdlc_fr_ioctl(dev, ifr) -ENOSYS #define hdlc_fr_ioctl(dev, ifr) -ENOSYS
#endif #endif
#ifndef CONFIG_HDLC_X25 #ifndef CONFIG_HDLC_X25
...@@ -257,25 +280,7 @@ struct net_device *alloc_hdlcdev(void *priv) ...@@ -257,25 +280,7 @@ struct net_device *alloc_hdlcdev(void *priv)
int register_hdlc_device(struct net_device *dev) int register_hdlc_device(struct net_device *dev)
{ {
int result; int result = dev_alloc_name(dev, "hdlc%d");
hdlc_device *hdlc = dev_to_hdlc(dev);
dev->get_stats = hdlc_get_stats;
dev->change_mtu = hdlc_change_mtu;
dev->mtu = HDLC_MAX_MTU;
dev->type = ARPHRD_RAWHDLC;
dev->hard_header_len = 16;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
hdlc->proto.id = -1;
hdlc->proto.detach = NULL;
hdlc->carrier = 1;
hdlc->open = 0;
spin_lock_init(&hdlc->state_lock);
result = dev_alloc_name(dev, "hdlc%d");
if (result < 0) if (result < 0)
return result; return result;
...@@ -283,6 +288,9 @@ int register_hdlc_device(struct net_device *dev) ...@@ -283,6 +288,9 @@ int register_hdlc_device(struct net_device *dev)
if (result != 0) if (result != 0)
return -EIO; return -EIO;
if (netif_carrier_ok(dev))
netif_carrier_off(dev); /* no carrier until DCD goes up */
return 0; return 0;
} }
......
...@@ -134,7 +134,7 @@ typedef struct hdlc_device_struct { ...@@ -134,7 +134,7 @@ typedef struct hdlc_device_struct {
int dce_pvc_count; int dce_pvc_count;
struct timer_list timer; struct timer_list timer;
int last_poll; unsigned long last_poll;
int reliable; int reliable;
int dce_changed; int dce_changed;
int request; int request;
...@@ -149,8 +149,9 @@ typedef struct hdlc_device_struct { ...@@ -149,8 +149,9 @@ typedef struct hdlc_device_struct {
cisco_proto settings; cisco_proto settings;
struct timer_list timer; struct timer_list timer;
int last_poll; unsigned long last_poll;
int up; int up;
int request_sent;
u32 txseq; /* TX sequence number */ u32 txseq; /* TX sequence number */
u32 rxseq; /* RX sequence number */ u32 rxseq; /* RX sequence number */
}cisco; }cisco;
......
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