summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortilghman <tilghman@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-06-22 20:23:41 +0000
committertilghman <tilghman@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2006-06-22 20:23:41 +0000
commitdf2e8131e92f1967eb61fb443036fdf9491ce745 (patch)
treeff896c23081a2c04ef47d1be583c9c7e612e7fe0
parente7324ee365da30e9b7b18d6baaec5ae21de1894b (diff)
Bug 5126 - Fix for incompatiblities between the TDMo* drivers and the 2.6 kernel
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@1157 5390a7c7-147a-4af0-8ec9-7488f05a26cb
-rw-r--r--zaptel.h3
-rw-r--r--ztd-eth.c22
-rw-r--r--ztd-loc.c3
-rw-r--r--ztdynamic.c55
4 files changed, 65 insertions, 18 deletions
diff --git a/zaptel.h b/zaptel.h
index c666c80..55542f3 100644
--- a/zaptel.h
+++ b/zaptel.h
@@ -1347,6 +1347,9 @@ struct zt_dynamic_driver {
/* Transmit a given message */
int (*transmit)(void *tpipe, unsigned char *msg, int msglen);
+ /* Flush any pending messages */
+ int (*flush)(void);
+
struct zt_dynamic_driver *next;
};
diff --git a/ztd-eth.c b/ztd-eth.c
index 41cc896..88d21da 100644
--- a/ztd-eth.c
+++ b/ztd-eth.c
@@ -56,6 +56,8 @@ static DEFINE_SPINLOCK(zlock);
static spinlock_t zlock = SPIN_LOCK_UNLOCKED;
#endif
+static struct sk_buff_head skbs;
+
static struct ztdeth {
unsigned char addr[ETH_ALEN];
unsigned short subaddr; /* Network byte order */
@@ -171,7 +173,7 @@ static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen)
skb->dev = dev;
if (dev->hard_header)
dev->hard_header(skb, dev, ETH_P_ZTDETH, addr, dev->dev_addr, skb->len);
- dev_queue_xmit(skb);
+ skb_queue_tail(&skbs, skb);
}
}
else
@@ -179,6 +181,18 @@ static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen)
return 0;
}
+
+static int ztdeth_flush(void)
+{
+ struct sk_buff *skb;
+
+ /* Handle all transmissions now */
+ while ((skb = skb_dequeue(&skbs))) {
+ dev_queue_xmit(skb);
+ }
+ return 0;
+}
+
static struct packet_type ztdeth_ptype = {
type: __constant_htons(ETH_P_ZTDETH), /* Protocol */
dev: NULL, /* Device (NULL = wildcard) */
@@ -381,7 +395,8 @@ static struct zt_dynamic_driver ztd_eth = {
"Ethernet",
ztdeth_create,
ztdeth_destroy,
- ztdeth_transmit
+ ztdeth_transmit,
+ ztdeth_flush
};
static struct notifier_block ztdeth_nblock = {
@@ -393,6 +408,9 @@ static int __init ztdeth_init(void)
dev_add_pack(&ztdeth_ptype);
register_netdevice_notifier(&ztdeth_nblock);
zt_dynamic_register(&ztd_eth);
+
+ skb_queue_head_init(&skbs);
+
return 0;
}
diff --git a/ztd-loc.c b/ztd-loc.c
index 0458293..fa72496 100644
--- a/ztd-loc.c
+++ b/ztd-loc.c
@@ -260,7 +260,8 @@ static struct zt_dynamic_driver ztd_local = {
"Local",
ztdlocal_create,
ztdlocal_destroy,
- ztdlocal_transmit
+ ztdlocal_transmit,
+ NULL /* flush */
};
/*static*/ int __init ztdlocal_init(void)
diff --git a/ztdynamic.c b/ztdynamic.c
index f15799b..c2c86ad 100644
--- a/ztdynamic.c
+++ b/ztdynamic.c
@@ -132,6 +132,12 @@ static DEFINE_SPINLOCK(dlock);
static spinlock_t dlock = SPIN_LOCK_UNLOCKED;
#endif
+#ifdef DEFINE_RWLOCK
+static DEFINE_RWLOCK(drvlock);
+#else
+static rwlock_t drvlock = RW_LOCK_UNLOCKED;
+#endif
+
static void checkmaster(void)
{
unsigned long flags;
@@ -142,15 +148,13 @@ static void checkmaster(void)
z = dspans;
while(z) {
if (z->timing) {
- if (z->timing) {
- z->master = 0;
- newhasmaster = 1;
- if (!z->alarm && (z->timing < best) && !z->dead) {
- /* If not in alarm and they're
- a better timing source, use them */
- master = z;
- best = z->timing;
- }
+ z->master = 0;
+ newhasmaster = 1;
+ if (!z->alarm && (z->timing < best) && !z->dead) {
+ /* If not in alarm and they're
+ a better timing source, use them */
+ master = z;
+ best = z->timing;
}
}
z = z->next;
@@ -230,6 +234,7 @@ static void __ztdynamic_run(void)
{
unsigned long flags;
struct zt_dynamic *z;
+ struct zt_dynamic_driver *drv;
int y;
spin_lock_irqsave(&dlock, flags);
z = dspans;
@@ -248,6 +253,17 @@ static void __ztdynamic_run(void)
z = z->next;
}
spin_unlock_irqrestore(&dlock, flags);
+
+ read_lock(&drvlock);
+ drv = drivers;
+ while(drv) {
+ /* Flush any traffic still pending in the driver */
+ if (drv->flush) {
+ drv->flush();
+ }
+ drv = drv->next;
+ }
+ read_unlock(&drvlock);
}
#ifdef ENABLE_TASKLETS
@@ -275,7 +291,7 @@ void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen)
int x, bits, sig;
int nchans, master;
int newalarm;
- unsigned short rxpos;
+ unsigned short rxpos, rxcnt;
spin_lock_irqsave(&dlock, flags);
@@ -373,6 +389,9 @@ void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen)
master = ztd->master;
+ rxcnt = ztd->rxcnt;
+ ztd->rxcnt = rxpos+1;
+
spin_unlock_irqrestore(&dlock, flags);
/* Check for Yellow alarm */
@@ -388,6 +407,10 @@ void zt_dynamic_receive(struct zt_span *span, unsigned char *msg, int msglen)
/* Keep track of last received packet */
ztd->rxjif = jiffies;
+ /* note if we had a missing packet */
+ if (rxpos != rxcnt)
+ printk("Span %s: Expected seq no %d, but received %d instead\n", span->name, rxcnt, rxpos);
+
/* If this is our master span, then run everything */
if (master)
ztdynamic_run();
@@ -715,14 +738,14 @@ int zt_dynamic_register(struct zt_dynamic_driver *dri)
{
unsigned long flags;
int res = 0;
- spin_lock_irqsave(&dlock, flags);
+ write_lock_irqsave(&drvlock, flags);
if (find_driver(dri->name))
res = -1;
else {
dri->next = drivers;
drivers = dri;
}
- spin_unlock_irqrestore(&dlock, flags);
+ write_unlock_irqrestore(&drvlock, flags);
return res;
}
@@ -731,7 +754,7 @@ void zt_dynamic_unregister(struct zt_dynamic_driver *dri)
struct zt_dynamic_driver *cur, *prev=NULL;
struct zt_dynamic *z, *zp, *zn;
unsigned long flags;
- spin_lock_irqsave(&dlock, flags);
+ write_lock_irqsave(&drvlock, flags);
cur = drivers;
while(cur) {
if (cur == dri) {
@@ -744,6 +767,8 @@ void zt_dynamic_unregister(struct zt_dynamic_driver *dri)
prev = cur;
cur = cur->next;
}
+ write_unlock_irqrestore(&drvlock, flags);
+ spin_lock_irqsave(&dlock, flags);
z = dspans;
zp = NULL;
while(z) {
@@ -778,8 +803,8 @@ static void check_for_red_alarm(unsigned long ignored)
z = dspans;
while(z) {
newalarm = z->span.alarms & ~ZT_ALARM_RED;
- /* If nothing received for a minute, consider that RED ALARM */
- if ((jiffies - z->rxjif) > 1000 / HZ) {
+ /* If nothing received for a second, consider that RED ALARM */
+ if ((jiffies - z->rxjif) > 1 * HZ) {
newalarm |= ZT_ALARM_RED;
if (z->span.alarms != newalarm) {
z->span.alarms = newalarm;