[dahdi-commits] fjoe: freebsd/trunk r7837 - in /freebsd/trunk: ./ drivers/dahdi/ freebsd/
SVN commits to the DAHDI project
dahdi-commits at lists.digium.com
Sun Jan 10 15:40:06 CST 2010
Author: fjoe
Date: Sun Jan 10 15:40:03 2010
New Revision: 7837
URL: http://svnview.digium.com/svn/dahdi?view=rev&rev=7837
Log:
Port of dahdi_dynamic_ethmf.
Modified:
freebsd/trunk/README.freebsd
freebsd/trunk/drivers/dahdi/dahdi_dynamic_ethmf.c
freebsd/trunk/freebsd/Makefile
Modified: freebsd/trunk/README.freebsd
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/README.freebsd?view=diff&rev=7837&r1=7836&r2=7837
==============================================================================
--- freebsd/trunk/README.freebsd (original)
+++ freebsd/trunk/README.freebsd Sun Jan 10 15:40:03 2010
@@ -13,7 +13,7 @@
- dahdi_dummy
- dahdi_dynamic
- dahdi_dynamic_loc
-- dahdi_dynamic_eth (requires ng_ether module to be loaded)
+- dahdi_dynamic_eth and dahdi_dynamic_ethmf
- wct4xxp, including HW echo cancellation support (Octasic)
- wcb4xxp
@@ -25,4 +25,10 @@
Just run "make", then "make install" in directory freebsd/
+NOTES
+=====
+
+dahdi_dynamic_eth and dahdi_dynamic_ethmf require ng_ether kernel module
+to be loaded.
+
Max Khon <fjoe at FreeBSD.org>
Modified: freebsd/trunk/drivers/dahdi/dahdi_dynamic_ethmf.c
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/drivers/dahdi/dahdi_dynamic_ethmf.c?view=diff&rev=7837&r1=7836&r2=7837
==============================================================================
--- freebsd/trunk/drivers/dahdi/dahdi_dynamic_ethmf.c (original)
+++ freebsd/trunk/drivers/dahdi/dahdi_dynamic_ethmf.c Sun Jan 10 15:40:03 2010
@@ -24,6 +24,15 @@
*/
#if defined(__FreeBSD__)
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/module.h>
+
+#include "ng_dahdi_netdev.h"
+
+#define ETH_ALEN ETHER_ADDR_LEN
+#define crc32_le(crc, data, len) crc32_raw(data, len, crc)
#else /* !__FreeBSD__ */
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -63,6 +72,7 @@
#define ETHMF_MAX_GROUPS 16
#define ETHMF_FLAG_IGNORE_CHAN0 (1 << 3)
#define ETHMF_MAX_SPANS 4
+#define ETHMF_MAX_CHANNELS 31
struct ztdeth_header {
unsigned short subaddr;
@@ -74,13 +84,20 @@
/* Whether or not the timer has been deleted */
static atomic_t timer_deleted = ATOMIC_INIT(0);
+#ifdef USE_PROC_FS
/* Global error counter */
static atomic_t errcount = ATOMIC_INIT(0);
+#endif
/* Whether or not we are in shutdown */
static atomic_t shutdown = ATOMIC_INIT(0);
+#if defined(__FreeBSD__)
+static char g_padding[ETHMF_MAX_CHANNELS * 8];
+static char g_padding_ignore[8];
+#else
static struct sk_buff_head skbs;
+#endif
#ifdef USE_PROC_FS
struct ethmf_group {
@@ -125,19 +142,19 @@
atomic_t no_front_padding;
/* counter to pseudo lock the rcvbuf */
atomic_t refcnt;
-
+
struct list_head list;
};
/**
- * Lock for adding and removing items in ethmf_list
+ * Lock for ethmf_list
*/
-static DEFINE_SPINLOCK(ethmf_lock);
+static DEFINE_RWLOCK(ethmf_lock);
/**
* The active list of all running spans
*/
-static LIST_HEAD(ethmf_list);
+static _LIST_HEAD(ethmf_list);
static inline void ethmf_errors_inc(void)
{
@@ -168,15 +185,15 @@
*
* NOTE: RCU read lock must already be held.
*/
-static inline void find_ethmf(const unsigned char *addr,
- const unsigned short subaddr, struct ztdeth **ze,
+static inline void find_ethmf(const unsigned char *addr,
+ const unsigned short subaddr, struct ztdeth **ze,
struct dahdi_span **span)
{
struct ztdeth *z;
-
- list_for_each_entry_rcu(z, ðmf_list, list) {
+
+ list_for_each_entry(z, ðmf_list, list) {
if (!atomic_read(&z->delay)) {
- if (!memcmp(addr, z->addr, ETH_ALEN)
+ if (!memcmp(addr, z->addr, ETH_ALEN)
&& z->subaddr == subaddr) {
*ze = z;
*span = z->span;
@@ -184,7 +201,7 @@
}
}
}
-
+
/* no results */
*ze = NULL;
*span = NULL;
@@ -201,8 +218,8 @@
{
struct ztdeth *t;
int span_count = 0, spans_ready = 0;
-
- list_for_each_entry_rcu(t, ðmf_list, list) {
+
+ list_for_each_entry(t, ðmf_list, list) {
if (!atomic_read(&t->delay) && t->addr_hash == addr_hash) {
++span_count;
if (atomic_read(&t->ready)) {
@@ -217,7 +234,7 @@
}
}
}
-
+
if (span_count && spans_ready && span_count == spans_ready) {
return spans_ready;
}
@@ -227,37 +244,48 @@
/**
* Ethernet receiving side processing function.
*/
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
-static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
+#if defined(__FreeBSD__)
+static int ztdethmf_rcv(struct net_device *dev, struct ether_header *eh,
+ unsigned char *msg, int msglen)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
+static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
#else
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
-#endif
+#endif /* !__FreeBSD__ */
{
int num_spans = 0, span_index = 0;
+ unsigned char *src_addr;
unsigned char *data;
struct dahdi_span *span;
struct ztdeth *z = NULL;
struct ztdeth_header *zh;
unsigned int samples, channels, rbslen, flags;
unsigned int skip = 0;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
+
+#if defined(__FreeBSD__)
+ if (msglen < sizeof(*zh))
+ return 0;
+ zh = (struct ztdeth_header *) msg;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
zh = (struct ztdeth_header *) skb_network_header(skb);
#else
zh = (struct ztdeth_header *) skb->nh.raw;
-#endif
+#endif /* !__FreeBSD__ */
if (ntohs(zh->subaddr) & 0x8000) {
/* got a multi-span frame */
num_spans = ntohs(zh->subaddr) & 0xFF;
-
+
/* Currently max of 4 spans supported */
if (unlikely(num_spans > ETHMF_MAX_SPANS)) {
- kfree_skb(skb);
- return 0;
- }
-
+ goto out;
+ }
+
+#if defined(__FreeBSD__)
+ data = msg + sizeof(*zh);
+ src_addr = eh->ether_shost;
+#else /* !__FreeBSD__ */
skb_pull(skb, sizeof(struct ztdeth_header));
#ifdef NEW_SKB_LINEARIZE
if (skb_is_nonlinear(skb))
@@ -267,41 +295,36 @@
skb_linearize(skb, GFP_KERNEL);
#endif
data = (unsigned char *) skb->data;
-
- rcu_read_lock();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
+ src_addr = eth_hdr(skb)->h_source;
+#else
+ src_addr = skb->mac.ethernet->h_source;
+#endif
+#endif /* !__FreeBSD__ */
+
+ read_lock(ðmf_lock);
do {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
- find_ethmf(eth_hdr(skb)->h_source,
- htons(span_index), &z, &span);
-#else
- find_ethmf(skb->mac.ethernet->h_source,
- htons(span_index), &z, &span);
-#endif
+ find_ethmf(src_addr, htons(span_index), &z, &span);
if (unlikely(!z || !span)) {
/* The recv'd span does not belong to us */
/* ethmf_errors_inc(); */
++span_index;
continue;
}
-
+
samples = data[(span_index * 6)] & 0xFF;
flags = data[((span_index * 6) + 1)] & 0xFF;
channels = data[((span_index * 6) + 5)] & 0xFF;
-
+
/* Precomputed defaults for most typical values */
- if (channels == 24)
- rbslen = 12;
- else if (channels == 31)
- rbslen = 16;
- else
- rbslen = ((channels + 3) / 4) * 2;
-
- if (unlikely(samples != 8 || channels >= 32 || channels == 0)) {
+ rbslen = ((channels + 3) / 4) * 2;
+
+ if (unlikely(samples != 8 || channels > ETHMF_MAX_CHANNELS || channels == 0)) {
ethmf_errors_inc();
++span_index;
continue;
}
-
+
if (atomic_dec_and_test(&z->refcnt) == 0) {
memcpy(z->rcvbuf, data + 6*span_index, 6); /* TDM Header */
/*
@@ -310,10 +333,10 @@
*/
if (flags & ETHMF_FLAG_IGNORE_CHAN0) {
skip = 8;
-
+
/* Remove this flag since ztdynamic may not understand it */
z->rcvbuf[1] = flags & ~(ETHMF_FLAG_IGNORE_CHAN0);
-
+
/* Additionally, now we will transmit with front padding */
atomic_set(&z->no_front_padding, 0);
} else {
@@ -322,12 +345,12 @@
}
memcpy(z->rcvbuf + 6, data + 6*num_spans + 16
*span_index, rbslen); /* RBS Header */
-
+
/* 256 == 32*8; if padding lengths change, this must be modified */
memcpy(z->rcvbuf + 6 + rbslen, data + 6*num_spans + 16
*num_spans + (256)*span_index + skip, channels
* 8); /* Payload */
-
+
dahdi_dynamic_receive(span, z->rcvbuf, 6 + rbslen
+ channels*8);
} else {
@@ -335,21 +358,24 @@
printk(KERN_INFO "TDMoE span overflow detected. Span %d was dropped.", span_index);
}
atomic_inc(&z->refcnt);
-
+
#ifdef USE_PROC_FS
if (span_index == 0) {
atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].rxframecount));
atomic_add(skb->len + z->dev->hard_header_len +
- sizeof(struct ztdeth_header),
+ sizeof(struct ztdeth_header),
&(ethmf_groups[hashaddr_to_index(z->addr_hash)].rxbytecount));
}
#endif
++span_index;
} while (!atomic_read(&shutdown) && span_index < num_spans);
- rcu_read_unlock();
- }
-
+ read_unlock(ðmf_lock);
+ }
+
+out:
+#if !defined(__FreeBSD__)
kfree_skb(skb);
+#endif
return 0;
}
@@ -358,12 +384,12 @@
{
struct net_device *dev = ptr;
struct ztdeth *z;
-
+
switch (event) {
case NETDEV_GOING_DOWN:
case NETDEV_DOWN:
- rcu_read_lock();
- list_for_each_entry_rcu(z, ðmf_list, list) {
+ read_lock(ðmf_lock);
+ list_for_each_entry(z, ðmf_list, list) {
/* Note that the device no longer exists */
if (z->dev == dev) {
z->dev = NULL;
@@ -372,11 +398,11 @@
#endif
}
}
- rcu_read_unlock();
+ read_unlock(ðmf_lock);
break;
case NETDEV_UP:
- rcu_read_lock();
- list_for_each_entry_rcu(z, ðmf_list, list) {
+ read_lock(ðmf_lock);
+ list_for_each_entry(z, ðmf_list, list) {
/* Now that the device exists again, use it */
if (!strcmp(z->ethdev, dev->name)) {
z->dev = dev;
@@ -385,7 +411,7 @@
#endif
}
}
- rcu_read_unlock();
+ read_unlock(ðmf_lock);
break;
}
return 0;
@@ -394,35 +420,47 @@
static int ztdethmf_transmit(void *pvt, unsigned char *msg, int msglen)
{
struct ztdeth *z = pvt, *ready_spans[ETHMF_MAX_PER_SPAN_GROUP];
+#if defined(__FreeBSD__)
+ struct mbuf *m;
+ struct ether_header eh;
+ struct ztdeth_header zh;
+#else
struct sk_buff *skb;
struct ztdeth_header *zh;
+ unsigned char addr[ETH_ALEN];
+#endif
+ unsigned short subaddr;
struct net_device *dev;
- unsigned char addr[ETH_ALEN];
int spans_ready = 0, index = 0;
-
+
if (atomic_read(&shutdown))
return 0;
-
- rcu_read_lock();
-
+
+ read_lock(ðmf_lock);
if (unlikely(!z || !z->dev)) {
- rcu_read_unlock();
+ read_unlock(ðmf_lock);
return 0;
}
-
- if (!atomic_read(&z->ready)) {
- if (atomic_inc_return(&z->ready) == 1) {
- memcpy(z->msgbuf, msg, msglen);
- z->msgbuf_len = msglen;
- }
- }
-
+
+#if defined(__FreeBSD__)
+ if (atomic_cmpset_int(&z->ready, 0, 1)) {
+#else
+ if (atomic_cmpxchg(&z->ready, 0, 1) == 0) {
+#endif
+ memcpy(z->msgbuf, msg, msglen);
+ z->msgbuf_len = msglen;
+ }
+
if ((spans_ready = ethmf_trx_spans_ready(z->addr_hash, &ready_spans))) {
int pad[ETHMF_MAX_SPANS], rbs[ETHMF_MAX_SPANS];
-
+
dev = z->dev;
+#if defined(__FreeBSD__)
+ bcopy(z->addr, &eh.ether_dhost, sizeof(eh.ether_dhost));
+#else /* !__FreeBSD__ */
memcpy(addr, z->addr, sizeof(z->addr));
-
+#endif /* !__FreeBSD__ */
+
for (index = 0; index < spans_ready; index++) {
int chan = ready_spans[index]->real_channels;
/* By default we pad to 32 channels, but if
@@ -433,66 +471,105 @@
if (atomic_read(&(ready_spans[index]->no_front_padding)))
pad[index] = (32 - chan)*8;
else
- pad[index] = (31 - chan)*8;
-
- if (chan == 24)
- rbs[index] = 12;
- else if (chan == 31)
- rbs[index] = 16;
- else
- // Shouldn't this be index, not spans_ready?
- rbs[spans_ready] = ((chan + 3) / 4) * 2;
- }
-
+ pad[index] = (ETHMF_MAX_CHANNELS - chan)*8;
+
+ rbs[index] = ((chan + 3) / 4) * 2;
+ }
+
+#if defined(__FreeBSD__)
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+ read_unlock(ðmf_lock);
+ ethmf_errors_inc();
+ return 0;
+ }
+ MCLGET(m, M_DONTWAIT);
+
+ /* copy ethernet header and reserve space for ztdeth header */
+ bcopy(dev->dev_addr, &eh.ether_shost, sizeof(eh.ether_shost));
+ eh.ether_type = __constant_htons(ETH_P_ZTDETH);
+ m_copyback(m, 0, sizeof(eh), (caddr_t) &eh);
+ m->m_pkthdr.len = m->m_len = sizeof(eh) + sizeof(zh);
+#else /* !__FreeBSD__ */
/* Allocate the standard size for a 32-chan frame */
skb = dev_alloc_skb(1112 + dev->hard_header_len
+ sizeof(struct ztdeth_header) + 32);
if (unlikely(!skb)) {
- rcu_read_unlock();
+ read_unlock(ðmf_lock);
ethmf_errors_inc();
return 0;
}
-
+
/* Reserve header space */
skb_reserve(skb, dev->hard_header_len
+ sizeof(struct ztdeth_header));
+#endif
/* copy each spans header */
for (index = 0; index < spans_ready; index++) {
- if (!atomic_read(&(ready_spans[index]->no_front_padding)))
+ if (!atomic_read(&(ready_spans[index]->no_front_padding))) {
ready_spans[index]->msgbuf[1]
|= ETHMF_FLAG_IGNORE_CHAN0;
-
+ }
+#if defined(__FreeBSD__)
+ m_append(m, 6, ready_spans[index]->msgbuf);
+#else
memcpy(skb_put(skb, 6), ready_spans[index]->msgbuf, 6);
- }
-
+#endif
+ }
+
/* copy each spans RBS payload */
for (index = 0; index < spans_ready; index++) {
+#if defined(__FreeBSD__)
+ m_append(m, 16, ready_spans[index]->msgbuf + 6);
+#else
memcpy(skb_put(skb, 16), ready_spans[index]->msgbuf + 6,
rbs[index]);
- }
-
+#endif
+ }
+
/* copy each spans data/voice payload */
for (index = 0; index < spans_ready; index++) {
int chan = ready_spans[index]->real_channels;
if (!atomic_read(&(ready_spans[index]->no_front_padding))) {
/* This adds an additional (padded) channel to our total */
+#if defined(__FreeBSD__)
+ m_append(m, sizeof(g_padding_ignore), g_padding_ignore);
+#else
memset(skb_put(skb, 8), 0xA5, 8); /* ETHMF_IGNORE_CHAN0 */
- }
+#endif
+ }
+#if defined(__FreeBSD__)
+ m_append(m, chan * 8, ready_spans[index]->msgbuf + (6 + rbs[index]));
+#else
memcpy(skb_put(skb, chan*8), ready_spans[index]->msgbuf
+ (6 + rbs[index]), chan*8);
+#endif
if (pad[index] > 0) {
+#if defined(__FreeBSD__)
+ m_append(m, pad[index], g_padding);
+#else
memset(skb_put(skb, pad[index]), 0xDD, pad[index]);
- }
-
+#endif
+ }
+
/* mark span as ready for new data/voice */
atomic_set(&(ready_spans[index]->ready), 0);
}
-
+
+ subaddr = htons((unsigned short)(0x8000 | (unsigned char)(spans_ready & 0xFF)));
+#if defined(__FreeBSD__)
+ /* copy ztdeth header */
+ zh.subaddr = subaddr;
+ m_copyback(m, sizeof(eh), sizeof(zh), (caddr_t) &zh);
+
+ /* send raw ethernet frame */
+ dev_xmit(dev, m);
+#else /* !__FreeBSD__ */
/* Throw on header */
zh = (struct ztdeth_header *)skb_push(skb,
sizeof(struct ztdeth_header));
- zh->subaddr = htons((unsigned short)(0x8000 | (unsigned char)(spans_ready & 0xFF)));
-
+ zh->subaddr = subaddr;
+
/* Setup protocol type */
skb->protocol = __constant_htons(ETH_P_ZTDETH);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
@@ -507,33 +584,35 @@
if (dev->hard_header)
dev->hard_header(skb, dev, ETH_P_ZTDETH, addr,
dev->dev_addr, skb->len);
-#endif
+#endif
/* queue frame for delivery */
skb_queue_tail(&skbs, skb);
+#endif /* !__FreeBSD__ */
#ifdef USE_PROC_FS
atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].txframecount));
atomic_add(skb->len, &(ethmf_groups[hashaddr_to_index(z->addr_hash)].txbytecount));
#endif
}
-
- rcu_read_unlock();
-
+ read_unlock(ðmf_lock);
+
return 0;
}
static int ztdethmf_flush(void)
{
+#if !defined(__FreeBSD__)
struct sk_buff *skb;
-
+
/* Handle all transmissions now */
while ((skb = skb_dequeue(&skbs))) {
dev_queue_xmit(skb);
}
+#endif /* !__FreeBSD__ */
return 0;
}
static struct packet_type ztdethmf_ptype =
-{
+{
.type = __constant_htons(ETH_P_ZTDETH), /* Protocol */
.dev = NULL, /* Device (NULL = wildcard) */
.func = ztdethmf_rcv, /* Receiver */
@@ -542,17 +621,16 @@
static void ztdethmf_destroy(void *pvt)
{
struct ztdeth *z = pvt;
- unsigned long flags;
-
+
atomic_set(&shutdown, 1);
- synchronize_rcu();
-
- spin_lock_irqsave(ðmf_lock, flags);
- list_del_rcu(&z->list);
- spin_unlock_irqrestore(ðmf_lock, flags);
- synchronize_rcu();
+
+ write_lock(ðmf_lock);
+ list_del(&z->list);
+ write_unlock(ðmf_lock);
+#if defined(USE_PROC_FS)
atomic_dec(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].spans));
-
+#endif
+
if (z) { /* Successfully removed */
printk(KERN_INFO "Removed interface for %s\n",
z->span->name);
@@ -573,26 +651,29 @@
char src[256];
char *src_ptr;
int x, bufsize, num_matched;
- unsigned long flags;
-
+
BUG_ON(!span);
BUG_ON(!addr);
-
+
+ if (span->channels > ETHMF_MAX_CHANNELS) {
+ printk(KERN_ERR "span %s, %d channels, but max %d channels supported\n",
+ span->name, span->channels, ETHMF_MAX_CHANNELS);
+ }
z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL);
if (!z)
return NULL;
-
+
/* Zero it out */
memset(z, 0, sizeof(struct ztdeth));
-
+
/* set a delay for xmit/recv to workaround Zaptel problems */
atomic_set(&z->delay, 4);
-
- /* create a msg buffer. MAX OF 31 CHANNELS!!!! */
- bufsize = 31 * DAHDI_CHUNKSIZE + 31 / 4 + 48;
+
+ /* create a msg buffer. max of ETHMF_MAX_CHANNELS channels */
+ bufsize = ETHMF_MAX_CHANNELS * DAHDI_CHUNKSIZE + ETHMF_MAX_CHANNELS / 4 + 48;
z->msgbuf = kmalloc(bufsize, GFP_KERNEL);
z->rcvbuf = kmalloc(bufsize, GFP_KERNEL);
-
+
/* Address should be <dev>/<macaddr>/subaddr */
dahdi_copy_string(src, addr, sizeof(src));
/* replace all / with space; otherwise kernel sscanf does not work */
@@ -602,10 +683,10 @@
*src_ptr = ' ';
++src_ptr;
}
- if (8 != (num_matched = sscanf(src,
- "%16s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hu",
+ if (8 != (num_matched = sscanf(src,
+ "%16s %hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hu",
z->ethdev, &z->addr[0], &z->addr[1],
- &z->addr[2], &z->addr[3], &z->addr[4],
+ &z->addr[2], &z->addr[3], &z->addr[4],
&z->addr[5], &z->subaddr))) {
printk(KERN_ERR "Only matched %d entries in '%s'\n", num_matched, src);
printk(KERN_ERR "Invalid TDMoE Multiframe address: %s\n", addr);
@@ -626,27 +707,29 @@
z->subaddr = htons(z->subaddr);
z->addr_hash = crc32_le(0, z->addr, ETH_ALEN);
z->real_channels = span->channels;
-
+
src[0] ='\0';
for (x=0; x<5; x++)
sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]);
sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]);
-
+
printk(KERN_INFO "TDMoEmf: Added new interface for %s at %s "
- "(addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name,
+ "(addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name,
addr, src, ntohs(z->subaddr));
-
+
atomic_set(&z->ready, 0);
atomic_set(&z->refcnt, 0);
-
- spin_lock_irqsave(ðmf_lock, flags);
- list_add_rcu(&z->list, ðmf_list);
- spin_unlock_irqrestore(ðmf_lock, flags);
+
+ write_lock(ðmf_lock);
+ list_add(&z->list, ðmf_list);
+ write_unlock(ðmf_lock);
+#if defined(USE_PROC_FS)
atomic_inc(&(ethmf_groups[hashaddr_to_index(z->addr_hash)].spans));
-
+#endif
+
if (!try_module_get(THIS_MODULE))
printk(KERN_ERR "TDMoEmf: Unable to increment module use count\n");
-
+
/* enable the timer for enabling the spans */
mod_timer(&timer, jiffies + HZ);
atomic_set(&shutdown, 0);
@@ -656,7 +739,7 @@
static struct dahdi_dynamic_driver ztd_ethmf = {
"ethmf",
"Ethernet",
- ztdethmf_create,
+ ztdethmf_create,
ztdethmf_destroy,
ztdethmf_transmit,
ztdethmf_flush
@@ -674,16 +757,16 @@
{
struct ztdeth *z;
int count_nonzero = 0;
-
- rcu_read_lock();
- list_for_each_entry_rcu(z, ðmf_list, list) {
+
+ read_lock(ðmf_lock);
+ list_for_each_entry(z, ðmf_list, list) {
if (atomic_read(&z->delay)) {
atomic_dec(&z->delay);
++count_nonzero;
} else
atomic_set(&z->delay, 0);
}
- rcu_read_unlock();
+ read_unlock(ðmf_lock);
return count_nonzero;
}
@@ -700,7 +783,6 @@
}
} else {
printk(KERN_INFO "All TDMoE multiframe span groups are active.\n");
- del_timer(&timer);
}
}
@@ -713,19 +795,19 @@
struct ztdeth *z = NULL;
int len = 0, i = 0;
unsigned int group = 0, c = 0;
-
- rcu_read_lock();
-
+
+ read_lock(ðmf_lock);
len += sprintf(page + len, "Errors: %d\n\n", atomic_read(&errcount));
-
+
for (group = 0; group < ETHMF_MAX_GROUPS; ++group) {
if (atomic_read(&(ethmf_groups[group].spans))) {
len += sprintf(page + len, "Group #%d (0x%x)\n", i++, ethmf_groups[group].hash_addr);
- len += sprintf(page + len, " Spans: %d\n",
+ len += sprintf(page + len, " Spans: %d\n",
atomic_read(&(ethmf_groups[group].spans)));
-
+
+
c = 1;
- list_for_each_entry_rcu(z, ðmf_list, list) {
+ list_for_each_entry(z, ðmf_list, list) {
if (z->addr_hash == ethmf_groups[group].hash_addr) {
if (c == 1) {
len += sprintf(page + len,
@@ -735,7 +817,7 @@
z->addr[3], z->addr[4], z->addr[5]);
}
len += sprintf(page + len, " Span %d: subaddr=%u ready=%d delay=%d real_channels=%d no_front_padding=%d\n",
- c++, ntohs(z->subaddr),
+ c++, ntohs(z->subaddr),
atomic_read(&z->ready), atomic_read(&z->delay),
z->real_channels, atomic_read(&z->no_front_padding));
}
@@ -760,8 +842,8 @@
break;
}
}
- rcu_read_unlock();
-
+ read_unlock(ðmf_lock);
+
if (len <= off) {
off -= len;
len = 0;
@@ -779,15 +861,18 @@
init_timer(&timer);
timer.expires = jiffies + HZ;
timer.function = &timer_callback;
- if (!timer_pending(&timer))
- add_timer(&timer);
-
+ add_timer(&timer);
+
dev_add_pack(&ztdethmf_ptype);
register_netdevice_notifier(&ztdethmf_nblock);
dahdi_dynamic_register(&ztd_ethmf);
-
+
+#if defined(__FreeBSD__)
+ memset(g_padding, 0xdd, sizeof(g_padding));
+ memset(g_padding_ignore, 0xa5, sizeof(g_padding_ignore));
+#else
skb_queue_head_init(&skbs);
-
+#endif
#ifdef USE_PROC_FS
proc_entry = create_proc_read_entry(ztdethmf_procname, 0444, NULL,
ztdethmf_proc_read, NULL);
@@ -795,7 +880,7 @@
printk(KERN_ALERT "create_proc_read_entry failed.\n");
}
#endif
-
+
return 0;
}
@@ -815,6 +900,25 @@
}
#if defined(__FreeBSD__)
+static int
+dahdi_dynamic_ethmf_modevent(module_t mod __unused, int type, void *data __unused)
+{
+ switch (type) {
+ case MOD_LOAD:
+ return ztdethmf_init();
+ case MOD_UNLOAD:
+ ztdethmf_exit();
+ return 0;
+ default:
+ return EOPNOTSUPP;
+ }
+}
+
+DEV_MODULE(dahdi_dynamic_ethmf, dahdi_dynamic_ethmf_modevent, NULL);
+MODULE_VERSION(dahdi_dynamic_ethmf, 1);
+MODULE_DEPEND(dahdi_dynamic_ethmf, dahdi, 1, 1, 1);
+MODULE_DEPEND(dahdi_dynamic_ethmf, dahdi_dynamic, 1, 1, 1);
+MODULE_DEPEND(dahdi_dynamic_ethmf, ng_dahdi_netdev, 1, 1, 1);
#else /* !__FreeBSD__ */
MODULE_DESCRIPTION("DAHDI Dynamic TDMoEmf Support");
MODULE_AUTHOR("Joseph Benden <joe at thrallingpenguin.com>");
Modified: freebsd/trunk/freebsd/Makefile
URL: http://svnview.digium.com/svn/dahdi/freebsd/trunk/freebsd/Makefile?view=diff&rev=7837&r1=7836&r2=7837
==============================================================================
--- freebsd/trunk/freebsd/Makefile (original)
+++ freebsd/trunk/freebsd/Makefile Sun Jan 10 15:40:03 2010
@@ -6,6 +6,7 @@
dahdi_dynamic\
dahdi_dynamic_loc\
dahdi_dynamic_eth\
+ dahdi_dynamic_ethmf\
dahdi_echocan_jpah\
dahdi_echocan_kb1\
dahdi_echocan_mg2\
More information about the dahdi-commits
mailing list