diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/clip.c | 67 | ||||
-rw-r--r-- | net/atm/lec.c | 255 | ||||
-rw-r--r-- | net/atm/mpoa_proc.c | 9 | ||||
-rw-r--r-- | net/atm/proc.c | 13 | ||||
-rw-r--r-- | net/atm/raw.c | 4 | ||||
-rw-r--r-- | net/bridge/br_device.c | 8 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 9 | ||||
-rw-r--r-- | net/bridge/br_forward.c | 2 | ||||
-rw-r--r-- | net/bridge/br_if.c | 2 | ||||
-rw-r--r-- | net/bridge/br_input.c | 63 | ||||
-rw-r--r-- | net/bridge/br_ioctl.c | 2 | ||||
-rw-r--r-- | net/bridge/br_notify.c | 2 | ||||
-rw-r--r-- | net/bridge/br_stp.c | 2 | ||||
-rw-r--r-- | net/bridge/br_stp_bpdu.c | 2 | ||||
-rw-r--r-- | net/bridge/br_stp_if.c | 2 | ||||
-rw-r--r-- | net/bridge/br_stp_timer.c | 2 | ||||
-rw-r--r-- | net/core/dev.c | 41 | ||||
-rw-r--r-- | net/decnet/af_decnet.c | 3 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 7 | ||||
-rw-r--r-- | net/ipv4/igmp.c | 11 | ||||
-rw-r--r-- | net/ipv4/ipconfig.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 2 | ||||
-rw-r--r-- | net/irda/ircomm/ircomm_tty.c | 5 | ||||
-rw-r--r-- | net/netsyms.c | 3 | ||||
-rw-r--r-- | net/packet/af_packet.c | 4 | ||||
-rw-r--r-- | net/sched/sch_atm.c | 67 | ||||
-rw-r--r-- | net/sched/sch_cbq.c | 2 | ||||
-rw-r--r-- | net/sched/sch_dsmark.c | 8 | ||||
-rw-r--r-- | net/wanrouter/wanproc.c | 46 |
29 files changed, 352 insertions, 293 deletions
diff --git a/net/atm/clip.c b/net/atm/clip.c index 43cf3d9a2..98d51c094 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -73,6 +73,7 @@ static void link_vcc(struct clip_vcc *clip_vcc,struct atmarp_entry *entry) DPRINTK("link_vcc %p to entry %p (neigh %p)\n",clip_vcc,entry, entry->neigh); clip_vcc->entry = entry; + clip_vcc->xoff = 0; /* @@@ may overrun buffer by one packet */ clip_vcc->next = entry->vccs; entry->vccs = clip_vcc; entry->neigh->used = jiffies; @@ -95,6 +96,8 @@ static void unlink_clip_vcc(struct clip_vcc *clip_vcc) *walk = clip_vcc->next; /* atomic */ clip_vcc->entry = NULL; + if (clip_vcc->xoff) + netif_wake_queue(entry->neigh->dev); if (entry->vccs) return; entry->expires = jiffies-1; /* force resolution or expiration */ @@ -218,13 +221,27 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) } +/* + * Note: these spinlocks _must_not_ block on non-SMP. The only goal is that + * clip_pop is atomic with respect to the critical section in clip_start_xmit. + */ + + static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb) { + struct clip_vcc *clip_vcc = CLIP_VCC(vcc); + int old; + DPRINTK("clip_pop(vcc %p)\n",vcc); - CLIP_VCC(vcc)->old_pop(vcc,skb); + clip_vcc->old_pop(vcc,skb); /* skb->dev == NULL in outbound ARP packets */ - if (atm_may_send(vcc,0) && skb->dev) - netif_wake_queue(skb->dev); + if (!skb->dev) return; + spin_lock(&PRIV(skb->dev)->xoff_lock); + if (atm_may_send(vcc,0)) { + old = xchg(&clip_vcc->xoff,0); + if (old) netif_wake_queue(skb->dev); + } + spin_unlock(&PRIV(skb->dev)->xoff_lock); } @@ -354,8 +371,10 @@ int clip_encap(struct atm_vcc *vcc,int mode) static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) { + struct clip_priv *clip_priv = PRIV(dev); struct atmarp_entry *entry; struct atm_vcc *vcc; + int old; DPRINTK("clip_start_xmit (skb %p)\n",skb); if (!skb->dst) { @@ -368,7 +387,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) skb->dst->neighbour = clip_find_neighbour(skb->dst,1); if (!skb->dst->neighbour) { dev_kfree_skb(skb); /* lost that one */ - PRIV(dev)->stats.tx_dropped++; + clip_priv->stats.tx_dropped++; return 0; } #endif @@ -386,7 +405,7 @@ return 0; skb_queue_tail(&entry->neigh->arp_queue,skb); else { dev_kfree_skb(skb); - PRIV(dev)->stats.tx_dropped++; + clip_priv->stats.tx_dropped++; } return 0; } @@ -401,15 +420,33 @@ return 0; ((u16 *) here)[3] = skb->protocol; } atomic_add(skb->truesize,&vcc->tx_inuse); - if (!atm_may_send(vcc,0)) - netif_stop_queue(dev); ATM_SKB(skb)->iovcnt = 0; ATM_SKB(skb)->atm_options = vcc->atm_options; entry->vccs->last_use = jiffies; DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev); - PRIV(dev)->stats.tx_packets++; - PRIV(dev)->stats.tx_bytes += skb->len; + old = xchg(&entry->vccs->xoff,1); /* assume XOFF ... */ + if (old) { + printk(KERN_WARNING "clip_start_xmit: XOFF->XOFF transition\n"); + return 0; + } + clip_priv->stats.tx_packets++; + clip_priv->stats.tx_bytes += skb->len; (void) vcc->dev->ops->send(vcc,skb); + if (atm_may_send(vcc,0)) { + entry->vccs->xoff = 0; + return 0; + } + if (old) return 0; + spin_lock(&clip_priv->xoff_lock); + netif_stop_queue(dev); /* XOFF -> throttle immediately */ + barrier(); + if (!entry->vccs->xoff) + netif_start_queue(dev); + /* Oh, we just raced with clip_pop. netif_start_queue should be + good enough, because nothing should really be asleep because + of the brief netif_stop_queue. If this isn't true or if it + changes, use netif_wake_queue instead. */ + spin_unlock(&clip_priv->xoff_lock); return 0; } @@ -434,6 +471,7 @@ int clip_mkip(struct atm_vcc *vcc,int timeout) clip_vcc->vcc = vcc; vcc->user_back = clip_vcc; clip_vcc->entry = NULL; + clip_vcc->xoff = 0; clip_vcc->encap = 1; clip_vcc->last_use = jiffies; clip_vcc->idle_timeout = timeout*HZ; @@ -523,7 +561,7 @@ static int clip_init(struct net_device *dev) dev->hard_header_len = RFC1483LLC_LEN; dev->mtu = RFC1626_MTU; dev->addr_len = 0; - dev->tx_queue_len = 100; /* "normal" queue */ + dev->tx_queue_len = 100; /* "normal" queue (packets) */ /* When using a "real" qdisc, the qdisc determines the queue */ /* length. tx_queue_len is only used for the default case, */ /* without any more elaborate queuing. 100 is a reasonable */ @@ -538,6 +576,7 @@ static int clip_init(struct net_device *dev) int clip_create(int number) { struct net_device *dev; + struct clip_priv *clip_priv; int error; if (number != -1) { @@ -554,16 +593,18 @@ int clip_create(int number) GFP_KERNEL); if (!dev) return -ENOMEM; memset(dev,0,sizeof(struct net_device)+sizeof(struct clip_priv)); - dev->name = PRIV(dev)->name; + clip_priv = PRIV(dev); + dev->name = clip_priv->name; sprintf(dev->name,"atm%d",number); dev->init = clip_init; - PRIV(dev)->number = number; + spin_lock_init(&clip_priv->xoff_lock); + clip_priv->number = number; error = register_netdev(dev); if (error) { kfree(dev); return error; } - PRIV(dev)->next = clip_devs; + clip_priv->next = clip_devs; clip_devs = dev; DPRINTK("registered (net:%s)\n",dev->name); return number; diff --git a/net/atm/lec.c b/net/atm/lec.c index 5b0e9138f..8c6d8d4af 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -184,9 +184,7 @@ lec_open(struct net_device *dev) { struct lec_priv *priv = (struct lec_priv *)dev->priv; - dev->tbusy = 0; - dev->start = 1; - dev->interrupt = 1; + netif_start_queue(dev); memset(&priv->stats,0,sizeof(struct net_device_stats)); return 0; @@ -214,165 +212,148 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) if (!priv->lecd) { printk("%s:No lecd attached\n",dev->name); priv->stats.tx_errors++; - dev->tbusy = 1; + netif_stop_queue(dev); return -EUNATCH; } - if (dev->tbusy) { - /* - * If we get here, some higher level has decided we are broken. - * There should really be a "kick me" function call instead. - */ - printk("%s: transmit timed out\n", dev->name); - dev->tbusy = 0; - } - /* - * Block a timer-based transmit from overlapping. This could better be - * done with atomic_swap(1, dev->tbusy), but set_bit() works as well. - */ - - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - printk(KERN_WARNING "%s: Transmitter access conflict.\n", - dev->name); - } else { - DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", - (long)skb->head, (long)skb->data, (long)skb->tail, - (long)skb->end); + DPRINTK("skbuff head:%lx data:%lx tail:%lx end:%lx\n", + (long)skb->head, (long)skb->data, (long)skb->tail, + (long)skb->end); #ifdef CONFIG_BRIDGE - if (skb->pkt_bridged == IS_BRIDGED) - handle_bridge(skb, dev); + if (skb->pkt_bridged == IS_BRIDGED) + handle_bridge(skb, dev); #endif /* CONFIG_BRIDGE */ - /* Make sure we have room for lec_id */ - if (skb_headroom(skb) < 2) { + /* Make sure we have room for lec_id */ + if (skb_headroom(skb) < 2) { - DPRINTK("lec_send_packet: reallocating skb\n"); - skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); - kfree_skb(skb); - if (skb2 == NULL) return 0; - skb = skb2; - } - skb_push(skb, 2); + DPRINTK("lec_send_packet: reallocating skb\n"); + skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); + kfree_skb(skb); + if (skb2 == NULL) return 0; + skb = skb2; + } + skb_push(skb, 2); - /* Put le header to place, works for TokenRing too */ - lec_h = (struct lecdatahdr_8023*)skb->data; - lec_h->le_header = htons(priv->lecid); + /* Put le header to place, works for TokenRing too */ + lec_h = (struct lecdatahdr_8023*)skb->data; + lec_h->le_header = htons(priv->lecid); #ifdef CONFIG_TR - /* Ugly. Use this to realign Token Ring packets for - * e.g. PCA-200E driver. */ - if (priv->is_trdev) { - skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); - kfree_skb(skb); - if (skb2 == NULL) return 0; - skb = skb2; - } + /* Ugly. Use this to realign Token Ring packets for + * e.g. PCA-200E driver. */ + if (priv->is_trdev) { + skb2 = skb_realloc_headroom(skb, LEC_HEADER_LEN); + kfree_skb(skb); + if (skb2 == NULL) return 0; + skb = skb2; + } #endif #if DUMP_PACKETS > 0 - printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, - skb->len, priv->lecid); + printk("%s: send datalen:%ld lecid:%4.4x\n", dev->name, + skb->len, priv->lecid); #if DUMP_PACKETS >= 2 - for(i=0;i<skb->len && i <99;i++) { - sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); - } + for(i=0;i<skb->len && i <99;i++) { + sprintf(buf+i*3,"%2.2x ",0xff&skb->data[i]); + } #elif DUMP_PACKETS >= 1 - for(i=0;i<skb->len && i < 30;i++) { - sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); - } + for(i=0;i<skb->len && i < 30;i++) { + sprintf(buf+i*3,"%2.2x ", 0xff&skb->data[i]); + } #endif /* DUMP_PACKETS >= 1 */ - if (i==skb->len) - printk("%s\n",buf); - else - printk("%s...\n",buf); + if (i==skb->len) + printk("%s\n",buf); + else + printk("%s...\n",buf); #endif /* DUMP_PACKETS > 0 */ - /* Minimum ethernet-frame size */ - if (skb->len <62) { - if (skb->truesize < 62) { - printk("%s:data packet %d / %d\n", - dev->name, - skb->len,skb->truesize); - nb=(unsigned char*)kmalloc(64, GFP_ATOMIC); - memcpy(nb,skb->data,skb->len); - kfree(skb->head); - skb->head = skb->data = nb; - skb->tail = nb+62; - skb->end = nb+64; - skb->len=62; - skb->truesize = 64; - } else { - skb->len = 62; - } + /* Minimum ethernet-frame size */ + if (skb->len <62) { + if (skb->truesize < 62) { + printk("%s:data packet %d / %d\n", + dev->name, + skb->len,skb->truesize); + nb=(unsigned char*)kmalloc(64, GFP_ATOMIC); + memcpy(nb,skb->data,skb->len); + kfree(skb->head); + skb->head = skb->data = nb; + skb->tail = nb+62; + skb->end = nb+64; + skb->len=62; + skb->truesize = 64; + } else { + skb->len = 62; } - - /* Send to right vcc */ - is_rdesc = 0; - dst = lec_h->h_dest; + } + + /* Send to right vcc */ + is_rdesc = 0; + dst = lec_h->h_dest; #ifdef CONFIG_TR - if (priv->is_trdev) { - dst = get_tr_dst(skb->data+2, rdesc); - if (dst == NULL) { - dst = rdesc; - is_rdesc = 1; - } + if (priv->is_trdev) { + dst = get_tr_dst(skb->data+2, rdesc); + if (dst == NULL) { + dst = rdesc; + is_rdesc = 1; } + } #endif - entry = NULL; - send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); - DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name, - send_vcc, send_vcc?send_vcc->flags:0, entry); - if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) { - if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { - DPRINTK("%s:lec_send_packet: queuing packet, ", dev->name); - DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], - lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); - skb_queue_tail(&entry->tx_wait, skb); - } else { - DPRINTK("%s:lec_send_packet: tx queue full or no arp entry, dropping, ", dev->name); - DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], - lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); - priv->stats.tx_dropped++; - dev_kfree_skb(skb); - } - dev->tbusy=0; - return 0; + entry = NULL; + send_vcc = lec_arp_resolve(priv, dst, is_rdesc, &entry); + DPRINTK("%s:send_vcc:%p vcc_flags:%x, entry:%p\n", dev->name, + send_vcc, send_vcc?send_vcc->flags:0, entry); + if (!send_vcc || !(send_vcc->flags & ATM_VF_READY)) { + if (entry && (entry->tx_wait.qlen < LEC_UNRES_QUE_LEN)) { + DPRINTK("%s:lec_send_packet: queuing packet, ", dev->name); + DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], + lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); + skb_queue_tail(&entry->tx_wait, skb); + } else { + DPRINTK("%s:lec_send_packet: tx queue full or no arp entry, dropping, ", dev->name); + DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], + lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); + priv->stats.tx_dropped++; + dev_kfree_skb(skb); } + return 0; + } #if DUMP_PACKETS > 0 - printk("%s:sending to vpi:%d vci:%d\n", dev->name, - send_vcc->vpi, send_vcc->vci); + printk("%s:sending to vpi:%d vci:%d\n", dev->name, + send_vcc->vpi, send_vcc->vci); #endif /* DUMP_PACKETS > 0 */ - while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { - DPRINTK("lec.c: emptying tx queue, "); - DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", - lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], - lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); - ATM_SKB(skb2)->vcc = send_vcc; - atomic_add(skb2->truesize, &send_vcc->tx_inuse); - ATM_SKB(skb2)->iovcnt = 0; - ATM_SKB(skb2)->atm_options = send_vcc->atm_options; - DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name, - send_vcc->vpi, send_vcc->vci); - priv->stats.tx_packets++; - priv->stats.tx_bytes += skb2->len; - send_vcc->dev->ops->send(send_vcc, skb2); - } - - ATM_SKB(skb)->vcc = send_vcc; - atomic_add(skb->truesize, &send_vcc->tx_inuse); - ATM_SKB(skb)->iovcnt = 0; - ATM_SKB(skb)->atm_options = send_vcc->atm_options; + while (entry && (skb2 = skb_dequeue(&entry->tx_wait))) { + DPRINTK("lec.c: emptying tx queue, "); + DPRINTK("MAC address 0x%02x:%02x:%02x:%02x:%02x:%02x\n", + lec_h->h_dest[0], lec_h->h_dest[1], lec_h->h_dest[2], + lec_h->h_dest[3], lec_h->h_dest[4], lec_h->h_dest[5]); + ATM_SKB(skb2)->vcc = send_vcc; + atomic_add(skb2->truesize, &send_vcc->tx_inuse); + ATM_SKB(skb2)->iovcnt = 0; + ATM_SKB(skb2)->atm_options = send_vcc->atm_options; + DPRINTK("%s:sending to vpi:%d vci:%d\n", dev->name, + send_vcc->vpi, send_vcc->vci); priv->stats.tx_packets++; - priv->stats.tx_bytes += skb->len; - send_vcc->dev->ops->send(send_vcc, skb); + priv->stats.tx_bytes += skb2->len; + send_vcc->dev->ops->send(send_vcc, skb2); } + + ATM_SKB(skb)->vcc = send_vcc; + atomic_add(skb->truesize, &send_vcc->tx_inuse); + ATM_SKB(skb)->iovcnt = 0; + ATM_SKB(skb)->atm_options = send_vcc->atm_options; + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + send_vcc->dev->ops->send(send_vcc, skb); + +#if 0 /* Should we wait for card's device driver to notify us? */ dev->tbusy=0; - +#endif return 0; } @@ -380,8 +361,7 @@ lec_send_packet(struct sk_buff *skb, struct net_device *dev) static int lec_close(struct net_device *dev) { - dev->tbusy = 1; - dev->start = 0; + netif_stop_queue(dev); return 0; } @@ -530,9 +510,7 @@ lec_atm_close(struct atm_vcc *vcc) priv->lecd = NULL; /* Do something needful? */ - dev->tbusy = 1; - dev->start = 0; - + netif_stop_queue(dev); lec_arp_destroy(priv); if (skb_peek(&vcc->recvq)) @@ -698,7 +676,7 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) if (!(dst[0]&0x01) && /* Never filter Multi/Broadcast */ !priv->is_proxy && /* Proxy wants all the packets */ - memcmp(dst, dev->dev_addr, sizeof(dev->dev_addr))) { + memcmp(dst, dev->dev_addr, dev->addr_len)) { dev_kfree_skb(skb); return; } @@ -814,8 +792,7 @@ lecd_attach(struct atm_vcc *vcc, int arg) priv->path_switching_delay = (6*HZ); if (dev_lec[i]->flags & IFF_UP) { - dev_lec[i]->tbusy = 0; - dev_lec[i]->start = 1; + netif_start_queue(dev_lec[i]); } MOD_INC_USE_COUNT; return i; diff --git a/net/atm/mpoa_proc.c b/net/atm/mpoa_proc.c index c779b18eb..bb6eddfe6 100644 --- a/net/atm/mpoa_proc.c +++ b/net/atm/mpoa_proc.c @@ -45,13 +45,6 @@ static struct file_operations mpc_file_operations = { write: proc_mpc_write, }; -/* - * Define allowed INODE OPERATIONS - */ -static struct inode_operations mpc_inode_operations = { - &mpc_file_operations, -}; - static int print_header(char *buff,struct mpoa_client *mpc){ if(mpc != NULL){ return sprintf(buff,"\nInterface %d:\n\n",mpc->dev_num); @@ -330,7 +323,7 @@ int mpc_proc_init(void) printk(KERN_ERR "Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME); return -ENOMEM; } - p->ops = &mpc_inode_operations; + p->proc_fops = &mpc_file_operations; return 0; } diff --git a/net/atm/proc.c b/net/atm/proc.c index b67ae428a..904dc43ba 100644 --- a/net/atm/proc.c +++ b/net/atm/proc.c @@ -63,15 +63,6 @@ static struct file_operations proc_spec_atm_operations = { read: proc_spec_atm_read, }; -static struct inode_operations proc_dev_atm_inode_operations = { - &proc_dev_atm_operations, /* default ATM directory file-ops */ -}; - -static struct inode_operations proc_spec_atm_inode_operations = { - &proc_spec_atm_operations, /* default ATM directory file-ops */ -}; - - static void add_stats(char *buf,const char *aal, const struct atm_aal_stats *stats) { @@ -563,7 +554,7 @@ int atm_proc_dev_register(struct atm_dev *dev) if (!dev->proc_entry) goto fail0; dev->proc_entry->data = dev; - dev->proc_entry->ops = &proc_dev_atm_inode_operations; + dev->proc_entry->proc_fops = &proc_dev_atm_operations; return 0; kfree(dev->proc_entry); fail0: @@ -584,7 +575,7 @@ void atm_proc_dev_deregister(struct atm_dev *dev) name = create_proc_entry(#name,0,atm_proc_root); \ if (!name) goto cleanup; \ name->data = atm_##name##_info; \ - name->ops = &proc_spec_atm_inode_operations + name->proc_fops = &proc_spec_atm_operations int __init atm_proc_init(void) diff --git a/net/atm/raw.c b/net/atm/raw.c index 0db4aabb6..355382502 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c @@ -1,6 +1,6 @@ /* net/atm/raw.c - Raw AAL0 and AAL5 transports */ -/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #include <linux/module.h> @@ -38,7 +38,7 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) { DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize); atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); - dev_kfree_skb(skb); + dev_kfree_skb_irq(skb); wake_up(&vcc->wsleep); } diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index de14e83a8..d2fac6697 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_device.c,v 1.1 2000/02/18 16:47:11 davem Exp $ + * $Id: br_device.c,v 1.2 2000/02/24 19:48:06 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -116,12 +116,10 @@ static int br_dev_stop(struct net_device *dev) return 0; } -#ifdef CONFIG_NET_FASTROUTE static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst) { return -1; } -#endif void br_dev_setup(struct net_device *dev) { @@ -133,9 +131,7 @@ void br_dev_setup(struct net_device *dev) dev->open = br_dev_open; dev->set_multicast_list = br_dev_set_multicast_list; dev->stop = br_dev_stop; -#ifdef CONFIG_NET_FASTROUTE dev->accept_fastpath = br_dev_accept_fastpath; -#endif - dev->tx_queue_len = 0; + dev->set_mac_address = NULL; } diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 2ca3c7fdd..be9d1867a 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_fdb.c,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_fdb.c,v 1.4 2000/02/24 06:16:45 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -14,9 +14,9 @@ */ #include <linux/kernel.h> +#include <linux/spinlock.h> #include <linux/if_bridge.h> #include <asm/atomic.h> -#include <asm/spinlock.h> #include <asm/uaccess.h> #include "br_private.h" @@ -216,6 +216,7 @@ int br_fdb_get_entries(struct net_bridge *br, struct __fdb_entry ent; int err; struct net_bridge_fdb_entry *g; + struct net_bridge_fdb_entry **pp; if (has_expired(br, f)) { f = f->next_hash; @@ -236,13 +237,13 @@ int br_fdb_get_entries(struct net_bridge *br, read_lock_bh(&br->hash_lock); g = f->next_hash; + pp = f->pprev_hash; br_fdb_put(f); if (err) goto out_fault; - if (f->next_hash == NULL && - f->pprev_hash == NULL) + if (g == NULL && pp == NULL) goto out_disappeared; num++; diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index e33850fd2..10e744a2f 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_forward.c,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_forward.c,v 1.2 2000/02/21 15:51:33 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index cbba5296d..dc77c5ffd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_if.c,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_if.c,v 1.2 2000/02/21 15:51:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e3175dac9..e6fa6b379 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_input.c,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_input.c,v 1.3 2000/02/24 19:48:06 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,21 +23,15 @@ unsigned char bridge_ula[5] = { 0x01, 0x80, 0xc2, 0x00, 0x00 }; static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) { - if (br->dev.flags & IFF_UP) { - br->statistics.rx_packets++; - br->statistics.rx_bytes += skb->len; - - skb->dev = &br->dev; - skb->pkt_type = PACKET_HOST; - skb->mac.raw = skb->data; - skb_pull(skb, skb->nh.raw - skb->data); - skb->protocol = eth_type_trans(skb, &br->dev); - netif_rx(skb); - - return; - } - - kfree_skb(skb); + br->statistics.rx_packets++; + br->statistics.rx_bytes += skb->len; + + skb->dev = &br->dev; + skb->pkt_type = PACKET_HOST; + skb->mac.raw = skb->data; + skb_pull(skb, skb->nh.raw - skb->data); + skb->protocol = eth_type_trans(skb, &br->dev); + netif_rx(skb); } static void __br_handle_frame(struct sk_buff *skb) @@ -46,17 +40,44 @@ static void __br_handle_frame(struct sk_buff *skb) unsigned char *dest; struct net_bridge_fdb_entry *dst; struct net_bridge_port *p; + int passedup; skb->nh.raw = skb->mac.raw; dest = skb->mac.ethernet->h_dest; p = skb->dev->br_port; br = p->br; + passedup = 0; + + if (!(br->dev.flags & IFF_UP) || + p->state == BR_STATE_DISABLED) + goto freeandout; + + if (br->dev.flags & IFF_PROMISC) { + struct sk_buff *skb2; + + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) { + passedup = 1; + br_pass_frame_up(br, skb2); + } + } - if (p->state == BR_STATE_DISABLED || - skb->mac.ethernet->h_source[0] & 1) + if (skb->mac.ethernet->h_source[0] & 1) goto freeandout; + if (!passedup && + (dest[0] & 1) && + (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL)) { + struct sk_buff *skb2; + + skb2 = skb_clone(skb, GFP_ATOMIC); + if (skb2) { + passedup = 1; + br_pass_frame_up(br, skb2); + } + } + if (!memcmp(dest, bridge_ula, 5) && !(dest[5] & 0xF0)) goto handle_special_frame; @@ -71,14 +92,16 @@ static void __br_handle_frame(struct sk_buff *skb) if (dest[0] & 1) { br_flood(br, skb, 1); - br_pass_frame_up(br, skb); + if (!passedup) + br_pass_frame_up(br, skb); return; } dst = br_fdb_get(br, dest); if (dst != NULL && dst->is_local) { - br_pass_frame_up(br, skb); + if (!passedup) + br_pass_frame_up(br, skb); br_fdb_put(dst); return; } diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index 8830cd747..dad96fb99 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_ioctl.c,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_ioctl.c,v 1.2 2000/02/21 15:51:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 8a109d7c3..6ed309b75 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_notify.c,v 1.1 2000/02/18 16:47:12 davem Exp $ + * $Id: br_notify.c,v 1.2 2000/02/21 15:51:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index a35d03f20..db5c18733 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_stp.c,v 1.1 2000/02/18 16:47:13 davem Exp $ + * $Id: br_stp.c,v 1.2 2000/02/21 15:51:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index 345792f83..71e51ffb2 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_stp_bpdu.c,v 1.1 2000/02/18 16:47:13 davem Exp $ + * $Id: br_stp_bpdu.c,v 1.2 2000/02/21 15:51:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index bbffc4126..263ac21af 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_stp_if.c,v 1.1 2000/02/18 16:47:13 davem Exp $ + * $Id: br_stp_if.c,v 1.2 2000/02/21 15:51:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index ca4e6e568..c530f14f8 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br_stp_timer.c,v 1.1 2000/02/18 16:47:13 davem Exp $ + * $Id: br_stp_timer.c,v 1.2 2000/02/21 15:51:35 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/core/dev.c b/net/core/dev.c index d2ed4f523..638ab6432 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -933,20 +933,19 @@ void net_call_rx_atomic(void (*fn)(void)) void (*br_handle_frame_hook)(struct sk_buff *skb) = NULL; #endif -#define HANDLE_BRIDGE(SKB, PT_PREV) \ -do { \ - if ((SKB)->dev->br_port != NULL && \ - br_handle_frame_hook != NULL) { \ - if (PT_PREV) \ - if (!(PT_PREV->data)) \ - deliver_to_old_ones(PT_PREV, SKB, 1); \ - else \ - pt_prev->func(SKB, SKB->dev, PT_PREV); \ - \ - br_handle_frame_hook(SKB); \ - continue; \ - } \ -} while(0) +static void __inline__ handle_bridge(struct sk_buff *skb, + struct packet_type *pt_prev) +{ + if (pt_prev) + deliver_to_old_ones(pt_prev, skb, 0); + else { + atomic_inc(&skb->users); + pt_prev->func(skb, skb->dev, pt_prev); + } + + br_handle_frame_hook(skb); +} + static void net_rx_action(struct softirq_action *h) { @@ -999,7 +998,11 @@ static void net_rx_action(struct softirq_action *h) } #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) - HANDLE_BRIDGE(skb, pt_prev); + if (skb->dev->br_port != NULL && + br_handle_frame_hook != NULL) { + handle_bridge(skb, pt_prev); + continue; + } #endif for (ptype=ptype_base[ntohs(type)&15];ptype;ptype=ptype->next) { @@ -1856,6 +1859,14 @@ int register_netdevice(struct net_device *dev) *dp = dev; dev_hold(dev); write_unlock_bh(&dev_base_lock); + + /* + * Default initial state at registry is that the + * device is present. + */ + + set_bit(__LINK_STATE_PRESENT, &dev->state); + return 0; } diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 1b16e7734..04728d5d8 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -1837,7 +1837,8 @@ static int dn_sendmsg(struct socket *sock, struct msghdr *msg, int size, scp->persist_fxn = dn_nsp_xmit_timeout; while(sent < size) { - if ((err = sock_error(sk) != 0)) + err = sock_error(sk); + if (err) goto out; if (signal_pending(current)) { diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index b7512a1c9..b848151a9 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -5,7 +5,7 @@ * * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.107 2000/02/18 16:47:20 davem Exp $ + * Version: $Id: af_inet.c,v 1.108 2000/02/21 16:25:59 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -135,7 +135,9 @@ extern int dlci_ioctl(unsigned int, void*); int (*dlci_ioctl_hook)(unsigned int, void *) = NULL; #endif +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) int (*br_ioctl_hook)(unsigned long) = NULL; +#endif /* New destruction routine */ @@ -837,13 +839,14 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return(devinet_ioctl(cmd,(void *) arg)); case SIOCGIFBR: case SIOCSIFBR: +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #ifdef CONFIG_KMOD if (br_ioctl_hook == NULL) request_module("bridge"); #endif if (br_ioctl_hook != NULL) return br_ioctl_hook(arg); - +#endif return -ENOPKG; case SIOCADDDLCI: diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 3aad90680..c93da55f9 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -8,7 +8,7 @@ * the older version didn't come out right using gcc 2.5.8, the newer one * seems to fall out with gcc 2.6.2. * - * Version: $Id: igmp.c,v 1.37 2000/02/09 11:16:40 davem Exp $ + * Version: $Id: igmp.c,v 1.38 2000/02/27 01:20:02 davem Exp $ * * Authors: * Alan Cox <Alan.Cox@linux.org> @@ -93,6 +93,7 @@ #include <net/route.h> #include <net/sock.h> #include <net/checksum.h> +#include <linux/netfilter_ipv4.h> #ifdef CONFIG_IP_MROUTE #include <linux/mroute.h> #endif @@ -185,6 +186,11 @@ static void igmp_mod_timer(struct ip_mc_list *im, int max_delay) #define IGMP_SIZE (sizeof(struct igmphdr)+sizeof(struct iphdr)+4) +static inline int igmp_send_report2(struct sk_buff *skb) +{ + return skb->dst->output(skb); +} + static int igmp_send_report(struct net_device *dev, u32 group, int type) { struct sk_buff *skb; @@ -242,7 +248,8 @@ static int igmp_send_report(struct net_device *dev, u32 group, int type) ih->group=group; ih->csum=ip_compute_csum((void *)ih, sizeof(struct igmphdr)); - return skb->dst->output(skb); + return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, + igmp_send_report2); } diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index bcdd71354..454e81fea 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.26 2000/01/29 07:42:08 davem Exp $ + * $Id: ipconfig.c,v 1.27 2000/02/21 15:51:41 davem Exp $ * * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied * information to configure own IP address and routes. diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 37ab925bf..887aaa519 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.121 2000/02/08 21:27:19 davem Exp $ + * Version: $Id: tcp_output.c,v 1.122 2000/02/21 15:51:41 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index b53f8a8cf..ac70091af 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -6,7 +6,7 @@ * Status: Experimental. * Author: Dag Brattli <dagb@cs.uit.no> * Created at: Sun Jun 6 21:00:56 1999 - * Modified at: Tue Jan 4 14:12:06 2000 + * Modified at: Wed Feb 23 00:09:02 2000 * Modified by: Dag Brattli <dagb@cs.uit.no> * Sources: serial.c and previous IrCOMM work by Takahide Higuchi * @@ -1079,6 +1079,9 @@ void ircomm_tty_check_modem_status(struct ircomm_tty_cb *self) "(), CTS tx start...\n"); tty->hw_stopped = 0; + /* Wake up processes blocked on open */ + wake_up_interruptible(&self->open_wait); + queue_task(&self->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH); return; diff --git a/net/netsyms.c b/net/netsyms.c index fbb07ab5a..d03c0a1b1 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -507,9 +507,6 @@ EXPORT_SYMBOL(dev_load); #endif EXPORT_SYMBOL(dev_ioctl); EXPORT_SYMBOL(dev_queue_xmit); -#ifdef CONFIG_NET_FASTROUTE -EXPORT_SYMBOL(dev_fastroute_stat); -#endif #ifdef CONFIG_NET_HW_FLOWCONTROL EXPORT_SYMBOL(netdev_register_fc); EXPORT_SYMBOL(netdev_unregister_fc); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 46439faa3..3a9d20e9c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.31 2000/02/18 16:47:23 davem Exp $ + * Version: $Id: af_packet.c,v 1.32 2000/02/21 16:25:55 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1438,12 +1438,14 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg case SIOCGIFBR: case SIOCSIFBR: +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #ifdef CONFIG_KMOD if (br_ioctl_hook == NULL) request_module("bridge"); #endif if (br_ioctl_hook != NULL) return br_ioctl_hook(arg); +#endif return -ENOPKG; diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index e81541cea..a3b25f2a7 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -6,6 +6,7 @@ #include <linux/config.h> #include <linux/module.h> #include <linux/skbuff.h> +#include <linux/interrupt.h> #include <linux/atmdev.h> #include <linux/atmclip.h> #include <linux/netdevice.h> @@ -20,7 +21,7 @@ extern struct socket *sockfd_lookup(int fd, int *err); /* @@@ fix this */ __inline__ in socket.c */ -#if 1 /* control */ +#if 0 /* control */ #define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) #else #define DPRINTK(format,args...) @@ -64,6 +65,7 @@ struct atm_flow_data { struct tcf_proto *filter_list; struct atm_vcc *vcc; /* VCC; NULL if VCC is closed */ void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* chaining */ + struct atm_qdisc_data *parent; /* parent qdisc */ struct socket *sock; /* for closing */ u32 classid; /* x:y type ID */ int ref; /* reference count */ @@ -79,6 +81,7 @@ struct atm_qdisc_data { struct atm_flow_data link; /* unclassified skbs go here */ struct atm_flow_data *flows; /* NB: "link" is also on this list */ + struct tasklet_struct task; /* requeue tasklet */ }; @@ -153,6 +156,18 @@ static unsigned long atm_tc_bind_filter(struct Qdisc *sch, } +static void destroy_filters(struct atm_flow_data *flow) +{ + struct tcf_proto *filter; + + while ((filter = flow->filter_list)) { + DPRINTK("destroy_filters: destroying filter %p\n",filter); + flow->filter_list = filter->next; + filter->ops->destroy(filter); + } +} + + /* * atm_tc_put handles all destructions, including the ones that are explicitly * requested (atm_tc_destroy, etc.). The assumption here is that we never drop @@ -164,7 +179,6 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl) struct atm_qdisc_data *p = PRIV(sch); struct atm_flow_data *flow = (struct atm_flow_data *) cl; struct atm_flow_data **prev; - struct tcf_proto *filter; DPRINTK("atm_tc_put(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); if (--flow->ref) return; @@ -178,14 +192,10 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl) *prev = flow->next; DPRINTK("atm_tc_put: qdisc %p\n",flow->q); qdisc_destroy(flow->q); - while ((filter = flow->filter_list)) { - DPRINTK("atm_tc_put: destroying filter %p\n",filter); - flow->filter_list = filter->next; - DPRINTK("atm_tc_put: filter %p\n",filter); - filter->ops->destroy(filter); - } + destroy_filters(flow); if (flow->sock) { - DPRINTK("atm_tc_put: f_count %d\n",file_count(flow->sock->file)); + DPRINTK("atm_tc_put: f_count %d\n", + file_count(flow->sock->file)); flow->vcc->pop = flow->old_pop; sockfd_put(flow->sock); } @@ -200,8 +210,11 @@ static void atm_tc_put(struct Qdisc *sch, unsigned long cl) static void sch_atm_pop(struct atm_vcc *vcc,struct sk_buff *skb) { + struct atm_qdisc_data *p = VCC2FLOW(vcc)->parent; + + D2PRINTK("sch_atm_pop(vcc %p,skb %p,[qdisc %p])\n",vcc,skb,p); VCC2FLOW(vcc)->old_pop(vcc,skb); - mark_bh(NET_BH); /* may allow to send more */ + tasklet_schedule(&p->task); } @@ -302,6 +315,7 @@ static int atm_tc_change(struct Qdisc *sch, u32 classid, u32 parent, flow->vcc->user_back = flow; DPRINTK("atm_tc_change: vcc %p\n",flow->vcc); flow->old_pop = flow->vcc->pop; + flow->parent = p; flow->vcc->pop = sch_atm_pop; flow->classid = classid; flow->ref = 1; @@ -440,21 +454,31 @@ static int atm_tc_enqueue(struct sk_buff *skb,struct Qdisc *sch) } -static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) +/* + * Dequeue packets and send them over ATM. Note that we quite deliberately + * avoid checking net_device's flow control here, simply because sch_atm + * uses its own channels, which have nothing to do with any CLIP/LANE/or + * non-ATM interfaces. + */ + + +static void sch_atm_dequeue(unsigned long data) { + struct Qdisc *sch = (struct Qdisc *) data; struct atm_qdisc_data *p = PRIV(sch); struct atm_flow_data *flow; struct sk_buff *skb; - D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p); + D2PRINTK("sch_atm_dequeue(sch %p,[qdisc %p])\n",sch,p); for (flow = p->link.next; flow; flow = flow->next) /* * If traffic is properly shaped, this won't generate nasty - * little bursts. Otherwise, it may ... @@@ + * little bursts. Otherwise, it may ... (but that's okay) */ while ((skb = flow->q->dequeue(flow->q))) { if (!atm_may_send(flow->vcc,skb->truesize)) { - flow->q->ops->requeue(skb,flow->q); + if (flow->q->ops->requeue(skb,flow->q)) + sch->q.qlen--; break; } sch->q.qlen--; @@ -469,7 +493,7 @@ static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) if (!new) continue; skb = new; } - D2PRINTK("atm_tc_dequeue: ip %p, data %p\n", + D2PRINTK("sch_atm_dequeue: ip %p, data %p\n", skb->nh.iph,skb->data); ATM_SKB(skb)->vcc = flow->vcc; memcpy(skb_push(skb,flow->hdr_len),flow->hdr, @@ -479,6 +503,16 @@ static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) /* atm.atm_options are already set by atm_tc_enqueue */ (void) flow->vcc->dev->ops->send(flow->vcc,skb); } +} + + +static struct sk_buff *atm_tc_dequeue(struct Qdisc *sch) +{ + struct atm_qdisc_data *p = PRIV(sch); + struct sk_buff *skb; + + D2PRINTK("atm_tc_dequeue(sch %p,[qdisc %p])\n",sch,p); + tasklet_schedule(&p->task); skb = p->link.q->dequeue(p->link.q); if (skb) sch->q.qlen--; return skb; @@ -530,6 +564,7 @@ static int atm_tc_init(struct Qdisc *sch,struct rtattr *opt) p->link.classid = sch->handle; p->link.ref = 1; p->link.next = NULL; + tasklet_init(&p->task,sch_atm_dequeue,(unsigned long) sch); MOD_INC_USE_COUNT; return 0; } @@ -554,6 +589,7 @@ static void atm_tc_destroy(struct Qdisc *sch) DPRINTK("atm_tc_destroy(sch %p,[qdisc %p])\n",sch,p); /* races ? */ while ((flow = p->flows)) { + destroy_filters(flow); if (flow->ref > 1) printk(KERN_ERR "atm_destroy: %p->ref = %d\n",flow, flow->ref); @@ -565,6 +601,7 @@ static void atm_tc_destroy(struct Qdisc *sch) break; } } + tasklet_kill(&p->task); MOD_DEC_USE_COUNT; } diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 0b741fa4e..bb6b3a291 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -878,7 +878,7 @@ cbq_dequeue_prio(struct Qdisc *sch, int prio) /* Start round */ do { - struct cbq_class *borrow = NULL; + struct cbq_class *borrow = cl; if (cl->q->q.qlen && (borrow = cbq_under_limit(cl)) == NULL) diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 1c1a48582..76f2fc394 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -278,10 +278,16 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch) { + int ret; struct dsmark_qdisc_data *p = PRIV(sch); D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p); - return p->q->ops->requeue(skb,p->q); + if ((ret = p->q->ops->requeue(skb, p->q)) == 0) { + sch->q.qlen++; + return 0; + } + sch->stats.drops++; + return ret; } diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index cb8419990..39d7781d0 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c @@ -95,25 +95,11 @@ static struct file_operations router_fops = static struct inode_operations router_inode = { - &router_fops, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* truncate */ - router_proc_perms, /* permission */ - NULL /* revalidate */ + permission: router_proc_perms, }; /* - * /proc/net/router/<device> file and inode operations + * /proc/net/router/<device> file operations */ static struct file_operations wandev_fops = @@ -122,25 +108,6 @@ static struct file_operations wandev_fops = ioctl: wanrouter_ioctl, }; -static struct inode_operations wandev_inode = -{ - &wandev_fops, - NULL, /* create */ - NULL, /* lookup */ - NULL, /* link */ - NULL, /* unlink */ - NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ - NULL, /* mknod */ - NULL, /* rename */ - NULL, /* readlink */ - NULL, /* follow_link */ - NULL, /* truncate */ - router_proc_perms, /* permission */ - NULL /* revalidate */ -}; - /* * /proc/net/router */ @@ -175,12 +142,14 @@ int __init wanrouter_proc_init (void) p = create_proc_entry("config",0,proc_router); if (!p) goto fail_config; - p->ops = &router_inode; + p->proc_fops = &router_fops; + p->proc_iops = &router_inode; p->get_info = config_get_info; p = create_proc_entry("status",0,proc_router); if (!p) goto fail_stat; - p->ops = &router_inode; + p->proc_fops = &router_fops; + p->proc_iops = &router_inode; p->get_info = status_get_info; return 0; fail_stat: @@ -214,7 +183,8 @@ int wanrouter_proc_add (wan_device_t* wandev) wandev->dent = create_proc_entry(wandev->name, 0, proc_router); if (!wandev->dent) return -ENOMEM; - wandev->dent->ops = &wandev_inode; + wandev->dent->proc_fops = &wandev_fops; + wandev->dent->proc_iops = &router_inode; wandev->dent->get_info = wandev_get_info; wandev->dent->data = wandev; return 0; |