diff options
author | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2004-08-16 17:27:12 +0000 |
---|---|---|
committer | markster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2004-08-16 17:27:12 +0000 |
commit | 8239ad02390c0feec4c726160b7519f04caf25b9 (patch) | |
tree | 3566504c9c9f3ba77127c954d4f6d46bd565d02e /ztd-eth.c | |
parent | e4dfecf0f034a72e26d3cc0fc96b245e191fc553 (diff) |
Merge Paul Cadach's TDMoE fixes for using tasklet (Thanks!)
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@450 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'ztd-eth.c')
-rwxr-xr-x | ztd-eth.c | 39 |
1 files changed, 32 insertions, 7 deletions
@@ -134,32 +134,41 @@ static int ztdeth_transmit(void *pvt, unsigned char *msg, int msglen) struct sk_buff *skb; struct ztdeth_header *zh; unsigned long flags; + struct net_device *dev; + unsigned char addr[ETH_ALEN]; + unsigned short subaddr; /* Network byte order */ spin_lock_irqsave(&zlock, flags); z = pvt; if (z->dev) { - skb = dev_alloc_skb(msglen + z->dev->hard_header_len + sizeof(struct ztdeth_header) + 32); + /* Copy fields to local variables to remove spinlock ASAP */ + dev = z->dev; + memcpy(addr, z->addr, sizeof(z->addr)); + subaddr = z->subaddr; + spin_unlock_irqrestore(&zlock, flags); + skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32); if (skb) { /* Reserve header space */ - skb_reserve(skb, z->dev->hard_header_len + sizeof(struct ztdeth_header)); + skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header)); /* Copy message body */ memcpy(skb_put(skb, msglen), msg, msglen); /* Throw on header */ zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header)); - zh->subaddr = z->subaddr; + zh->subaddr = subaddr; /* Setup protocol and such */ skb->protocol = __constant_htons(ETH_P_ZTDETH); skb->nh.raw = skb->data; - skb->dev = z->dev; - if (z->dev->hard_header) - z->dev->hard_header(skb, z->dev, ETH_P_ZTDETH, z->addr, z->dev->dev_addr, skb->len); + 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); } } - spin_unlock_irqrestore(&zlock, flags); + else + spin_unlock_irqrestore(&zlock, flags); return 0; } @@ -245,6 +254,13 @@ static void ztdeth_destroy(void *pvt) cur = cur->next; } spin_unlock_irqrestore(&zlock, flags); + if (cur == z) { /* Successfully removed */ + printk("TDMoE: Removed interface for %s\n", z->span->name); + kfree(z); +#ifndef LINUX26 + MOD_DEC_USE_COUNT; +#endif + } } static void *ztdeth_create(struct zt_span *span, char *addr) @@ -341,6 +357,9 @@ static void *ztdeth_create(struct zt_span *span, char *addr) z->next = zdevs; zdevs = z; spin_unlock_irqrestore(&zlock, flags); +#ifndef LINUX26 + MOD_INC_USE_COUNT; +#endif } return z; } @@ -372,5 +391,11 @@ static void __exit ztdeth_exit(void) zt_dynamic_unregister(&ztd_eth); } +MODULE_DESCRIPTION("Zaptel Dynamic TDMoE Support"); +MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>"); +#ifdef MODULE_LICENSE +MODULE_LICENSE("GPL"); +#endif + module_init(ztdeth_init); module_exit(ztdeth_exit); |