summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/atm/clip.c67
-rw-r--r--net/atm/lec.c255
-rw-r--r--net/atm/mpoa_proc.c9
-rw-r--r--net/atm/proc.c13
-rw-r--r--net/atm/raw.c4
-rw-r--r--net/bridge/br_device.c8
-rw-r--r--net/bridge/br_fdb.c9
-rw-r--r--net/bridge/br_forward.c2
-rw-r--r--net/bridge/br_if.c2
-rw-r--r--net/bridge/br_input.c63
-rw-r--r--net/bridge/br_ioctl.c2
-rw-r--r--net/bridge/br_notify.c2
-rw-r--r--net/bridge/br_stp.c2
-rw-r--r--net/bridge/br_stp_bpdu.c2
-rw-r--r--net/bridge/br_stp_if.c2
-rw-r--r--net/bridge/br_stp_timer.c2
-rw-r--r--net/core/dev.c41
-rw-r--r--net/decnet/af_decnet.c3
-rw-r--r--net/ipv4/af_inet.c7
-rw-r--r--net/ipv4/igmp.c11
-rw-r--r--net/ipv4/ipconfig.c2
-rw-r--r--net/ipv4/tcp_output.c2
-rw-r--r--net/irda/ircomm/ircomm_tty.c5
-rw-r--r--net/netsyms.c3
-rw-r--r--net/packet/af_packet.c4
-rw-r--r--net/sched/sch_atm.c67
-rw-r--r--net/sched/sch_cbq.c2
-rw-r--r--net/sched/sch_dsmark.c8
-rw-r--r--net/wanrouter/wanproc.c46
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;