diff -ur --new-file old/linux/include/linux/atmsvc.h new/linux/include/linux/atmsvc.h --- old/linux/include/linux/atmsvc.h Mon Mar 1 17:00:31 1999 +++ new/linux/include/linux/atmsvc.h Mon Mar 1 17:01:09 1999 @@ -1,6 +1,6 @@ /* atmsvc.h - ATM signaling kernel-demon interface definitions */ -/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ #ifndef _LINUX_ATMSVC_H @@ -46,7 +46,8 @@ * if signaling only uses one ATM interface). */ -#define SELECT_TOP_PCR(tp) ((tp).max_pcr && (tp).max_pcr != ATM_MAX_PCR ? \ - (tp).max_pcr : (tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR) +#define SELECT_TOP_PCR(tp) ((tp).pcr ? (tp).pcr : \ + (tp).max_pcr && (tp).max_pcr != ATM_MAX_PCR ? (tp).max_pcr : \ + (tp).min_pcr ? (tp).min_pcr : ATM_MAX_PCR) #endif diff -ur --new-file old/linux/net/atm/misc.c new/linux/net/atm/misc.c --- old/linux/net/atm/misc.c Mon Mar 1 17:00:32 1999 +++ new/linux/net/atm/misc.c Mon Mar 1 17:01:10 1999 @@ -1,6 +1,6 @@ /* net/atm/misc.c - Various functions for use by ATM drivers */ -/* Written 1995-1998 by Werner Almesberger, EPFL ICA */ +/* Written 1995-1999 by Werner Almesberger, EPFL ICA */ #include <linux/config.h> @@ -107,7 +107,7 @@ * - y * y- x y * y- * - y z z- x y z z- * - * All non-error cases can be convered with the following simple set of rules: + * All non-error cases can be converted with the following simple set of rules: * * if pcr == z then z- * else if min == x && pcr == - then x+ diff -ur --new-file old/linux/net/atm/svc.c new/linux/net/atm/svc.c --- old/linux/net/atm/svc.c Mon Mar 1 17:00:32 1999 +++ new/linux/net/atm/svc.c Mon Mar 1 17:01:10 1999 @@ -1,6 +1,6 @@ /* net/atm/svc.c - ATM SVC sockets */ -/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */ #include <linux/string.h> @@ -198,6 +198,7 @@ * #ifndef CONFIG_SINGLE_SIGITF */ vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp); + vcc->qos.txtp.pcr = 0; vcc->qos.txtp.min_pcr = 0; /* * #endif diff -ur --new-file old/linux/net/sched/sch_atm.c new/linux/net/sched/sch_atm.c --- old/linux/net/sched/sch_atm.c Mon Mar 1 17:00:32 1999 +++ new/linux/net/sched/sch_atm.c Mon Mar 1 17:01:10 1999 @@ -170,12 +170,12 @@ DPRINTK("atm_tc_put: f_count %d\n",flow->sock->file->f_count); sockfd_put(flow->sock); } + if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess); if (flow != &p->link) kfree(flow); /* * If flow == &p->link, the qdisc no longer works at this point and * needs to be removed. (By the caller of atm_tc_put.) */ - if (flow->excess) atm_tc_put(sch,(unsigned long) flow->excess); } @@ -184,7 +184,7 @@ { struct atm_qdisc_data *p = PRIV(sch); struct atm_flow_data *flow = (struct atm_flow_data *) *arg; - struct atm_flow_data *excess; + struct atm_flow_data *excess = NULL; struct rtattr *opt = tca[TCA_OPTIONS-1]; struct rtattr *tb[TCA_ATM_MAX]; struct socket *sock; @@ -196,7 +196,8 @@ /* * The concept of parents doesn't apply for this qdisc. */ - if (parent && parent != TC_H_ROOT) return -EINVAL; + if (parent && parent != TC_H_ROOT && parent != sch->handle) + return -EINVAL; /* * ATM classes cannot be changed. In order to change properties of the * ATM connection, that socket needs to be modified directly (via the @@ -287,6 +288,7 @@ *arg = (unsigned long) flow; return 0; err_out: + if (excess) atm_tc_put(sch,(unsigned long) excess); sockfd_put(sock); return error; } @@ -300,7 +302,15 @@ DPRINTK("atm_tc_delete(sch %p,[qdisc %p],flow %p)\n",sch,p,flow); if (!find_flow(PRIV(sch),flow)) return -EINVAL; if (flow->filter_list || flow == &p->link) return -EBUSY; - if (flow->ref > 1) return -EBUSY; /* catch references via excess, etc.*/ + /* + * Reference count must be 2: one for "keepalive" (set at class + * creation), and one for the reference held when calling delete. + */ + if (flow->ref < 2) { + printk(KERN_ERR "atm_tc_delete: flow->ref == %d\n",flow->ref); + return -EINVAL; + } + if (flow->ref > 2) return -EBUSY; /* catch references via excess, etc.*/ atm_tc_put(sch,arg); return 0; } @@ -522,6 +532,7 @@ DPRINTK("atm_tc_dump_class(sch %p,[qdisc %p],flow %p,skb %p,tcm %p)\n", sch,p,flow,skb,tcm); if (!find_flow(p,flow)) return -EINVAL; + tcm->tcm_handle = flow->classid; rta = (struct rtattr *) b; RTA_PUT(skb,TCA_OPTIONS,0,NULL); RTA_PUT(skb,TCA_ATM_HDR,flow->hdr_len,flow->hdr);