X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fatm%2Fbr2684.c;h=83a1c1b1d6cd2901761d5bc67b96c9594df094ba;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=f469813faff8b4506fd00ba4402f42fa0e11676c;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/atm/br2684.c b/net/atm/br2684.c index f469813fa..83a1c1b1d 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c @@ -5,7 +5,6 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary */ #include -#include #include #include #include @@ -18,12 +17,12 @@ Author: Marcell GAL, 2000, XDSL Ltd, Hungary #include #include #include +#include #include #include #include "common.h" -#include "ipcommon.h" /* * Define this to use a version of the code which interacts with the higher @@ -97,7 +96,7 @@ struct br2684_dev { * do read-locking under interrupt context, so write locking must block * the current CPU's interrupts */ -static rwlock_t devs_lock = RW_LOCK_UNLOCKED; +static DEFINE_RWLOCK(devs_lock); static LIST_HEAD(br2684_devs); @@ -190,7 +189,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, dev_kfree_skb(skb); return 0; } - atomic_add(skb->truesize, &atmvcc->sk->sk_wmem_alloc); + atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); ATM_SKB(skb)->atm_options = atmvcc->atm_options; brdev->stats.tx_packets++; brdev->stats.tx_bytes += skb->len; @@ -220,7 +219,7 @@ static int br2684_start_xmit(struct sk_buff *skb, struct net_device *dev) /* netif_stop_queue(dev); */ dev_kfree_skb(skb); read_unlock(&devs_lock); - return -EUNATCH; + return 0; } if (!br2684_xmit_vcc(skb, brdev, brvcc)) { /* @@ -289,21 +288,20 @@ xmit will add the additional header part in that case */ * This is similar to eth_type_trans, which cannot be used because of * our dev->hard_header_len */ -static inline unsigned short br_type_trans(struct sk_buff *skb, - struct net_device *dev) +static inline __be16 br_type_trans(struct sk_buff *skb, struct net_device *dev) { struct ethhdr *eth; unsigned char *rawp; - eth = skb->mac.ethernet; + eth = eth_hdr(skb); - if (*eth->h_dest & 1) { - if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) + if (is_multicast_ether_addr(eth->h_dest)) { + if (!compare_ether_addr(eth->h_dest, dev->broadcast)) skb->pkt_type = PACKET_BROADCAST; else skb->pkt_type = PACKET_MULTICAST; } - else if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) + else if (compare_ether_addr(eth->h_dest, dev->dev_addr)) skb->pkt_type = PACKET_OTHERHOST; if (ntohs(eth->h_proto) >= 1536) @@ -342,12 +340,12 @@ static int br2684_mac_addr(struct net_device *dev, void *p) #ifdef CONFIG_ATM_BR2684_IPFILTER /* this IOCTL is experimental. */ -static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg) +static int br2684_setfilt(struct atm_vcc *atmvcc, void __user *arg) { struct br2684_vcc *brvcc; struct br2684_filter_set fs; - if (copy_from_user(&fs, (void *) arg, sizeof fs)) + if (copy_from_user(&fs, arg, sizeof fs)) return -EFAULT; if (fs.ifspec.method != BR2684_FIND_BYNOTHING) { /* @@ -373,7 +371,7 @@ static int br2684_setfilt(struct atm_vcc *atmvcc, unsigned long arg) /* Returns 1 if packet should be dropped */ static inline int -packet_fails_filter(u16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) +packet_fails_filter(__be16 type, struct br2684_vcc *brvcc, struct sk_buff *skb) { if (brvcc->filter.netmask == 0) return 0; /* no filter in place */ @@ -494,25 +492,25 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) netif_rx(skb); } -static int br2684_regvcc(struct atm_vcc *atmvcc, unsigned long arg) +static int br2684_regvcc(struct atm_vcc *atmvcc, void __user *arg) { /* assign a vcc to a dev Note: we do not have explicit unassign, but look at _push() */ int err; struct br2684_vcc *brvcc; - struct sk_buff_head copy; struct sk_buff *skb; + struct sk_buff_head *rq; struct br2684_dev *brdev; struct net_device *net_dev; struct atm_backend_br2684 be; + unsigned long flags; - if (copy_from_user(&be, (void *) arg, sizeof be)) + if (copy_from_user(&be, arg, sizeof be)) return -EFAULT; - brvcc = kmalloc(sizeof(struct br2684_vcc), GFP_KERNEL); + brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL); if (!brvcc) return -ENOMEM; - memset(brvcc, 0, sizeof(struct br2684_vcc)); write_lock_irq(&devs_lock); net_dev = br2684_find_dev(&be.ifspec); if (net_dev == NULL) { @@ -556,14 +554,32 @@ Note: we do not have explicit unassign, but look at _push() brvcc->old_push = atmvcc->push; barrier(); atmvcc->push = br2684_push; - skb_queue_head_init(©); - skb_migrate(&atmvcc->sk->sk_receive_queue, ©); - while ((skb = skb_dequeue(©))) { + + rq = &sk_atm(atmvcc)->sk_receive_queue; + + spin_lock_irqsave(&rq->lock, flags); + if (skb_queue_empty(rq)) { + skb = NULL; + } else { + /* NULL terminate the list. */ + rq->prev->next = NULL; + skb = rq->next; + } + rq->prev = rq->next = (struct sk_buff *)rq; + rq->qlen = 0; + spin_unlock_irqrestore(&rq->lock, flags); + + while (skb) { + struct sk_buff *next = skb->next; + + skb->next = skb->prev = NULL; BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; BRPRIV(skb->dev)->stats.rx_packets--; br2684_push(atmvcc, skb); + + skb = next; } - (void) try_module_get(THIS_MODULE); + __module_get(THIS_MODULE); return 0; error: write_unlock_irq(&devs_lock); @@ -593,7 +609,7 @@ static void br2684_setup(struct net_device *netdev) INIT_LIST_HEAD(&brdev->brvccs); } -static int br2684_create(unsigned long arg) +static int br2684_create(void __user *arg) { int err; struct net_device *netdev; @@ -602,7 +618,7 @@ static int br2684_create(unsigned long arg) DPRINTK("br2684_create\n"); - if (copy_from_user(&ni, (void *) arg, sizeof ni)) { + if (copy_from_user(&ni, arg, sizeof ni)) { return -EFAULT; } if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) { @@ -642,13 +658,14 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct atm_vcc *atmvcc = ATM_SD(sock); + void __user *argp = (void __user *)arg; int err; switch(cmd) { case ATM_SETBACKEND: case ATM_NEWBACKENDIF: { atm_backend_t b; - err = get_user(b, (atm_backend_t *) arg); + err = get_user(b, (atm_backend_t __user *) argp); if (err) return -EFAULT; if (b != ATM_BACKEND_BR2684) @@ -656,9 +673,9 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd, if (!capable(CAP_NET_ADMIN)) return -EPERM; if (cmd == ATM_SETBACKEND) - return br2684_regvcc(atmvcc, arg); + return br2684_regvcc(atmvcc, argp); else - return br2684_create(arg); + return br2684_create(argp); } #ifdef CONFIG_ATM_BR2684_IPFILTER case BR2684_SETFILT: @@ -666,7 +683,7 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd, return -ENOIOCTLCMD; if (!capable(CAP_NET_ADMIN)) return -EPERM; - err = br2684_setfilt(atmvcc, arg); + err = br2684_setfilt(atmvcc, argp); return err; #endif /* CONFIG_ATM_BR2684_IPFILTER */ }