diff -ur --new-file old/linux/drivers/atm/eni.c new/linux/drivers/atm/eni.c --- old/linux/drivers/atm/eni.c Wed Jul 31 19:46:56 1996 +++ new/linux/drivers/atm/eni.c Wed Jul 31 19:47:25 1996 @@ -526,8 +526,14 @@ size = 0; } else { - printk(KERN_WARNING DEV_LABEL "(itf %d): discarding " - "PDU with CRC error\n",vcc->dev->number); + static unsigned long silence = 0; + + if (jiffies > silence) { + printk(KERN_WARNING DEV_LABEL "(itf %d): " + "discarding PDU(s) with CRC error\n", + vcc->dev->number); + silence = jiffies+2*HZ; + } size = (descr & MID_RED_COUNT)*(ATM_CELL_PAYLOAD >> 2); EVENT("CRC error (descr=0x%08lx,size=%ld)\n",descr, size); @@ -665,7 +671,7 @@ } ENI_VCC(vcc)->timestamp = xtime; ENI_VCC(vcc)->next = NULL; - if (vcc->rxtp.class == ATM_CBR) { + if (vcc->qos.rxtp.traffic_class == ATM_CBR) { if (eni_dev->fast) ENI_VCC(eni_dev->last_fast)->next = vcc; else eni_dev->fast = vcc; @@ -745,8 +751,8 @@ eni_dev = ENI_DEV(vcc->dev); eni_vcc = ENI_VCC(vcc); eni_vcc->rx = NULL; - if (vcc->rxtp.class == ATM_NONE) return 0; - size = vcc->rxtp.max_sdu*3; /* @@@ improve this */ + if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0; + size = vcc->qos.rxtp.max_sdu*3; /* @@@ improve this */ eni_vcc->recv = (volatile unsigned long *) eni_alloc_mem(eni_dev,&size); DPRINTK("rx at 0x%lx\n",(unsigned long) eni_vcc->recv); eni_vcc->words = size >> 2; @@ -1142,30 +1148,32 @@ eni_dev = ENI_DEV(vcc->dev); eni_vcc = ENI_VCC(vcc); eni_vcc->tx = NULL; - if (vcc->txtp.class == ATM_NONE) return 0; + if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; eni_vcc->txing = 0; - if (vcc->txtp.class != ATM_UBR) - size = vcc->txtp.max_sdu*3; /* @@@ improve */ + if (vcc->qos.txtp.traffic_class != ATM_UBR) + size = vcc->qos.txtp.max_sdu*3; /* @@@ improve */ else { if (eni_dev->ubr) { eni_vcc->tx = eni_dev->ubr; return 0; } size = UBR_BUFFER; - vcc->txtp.min_pcr = ATM_MAX_PCR; - vcc->txtp.max_pcr = 0; + vcc->qos.txtp.min_pcr = ATM_MAX_PCR; + vcc->qos.txtp.max_pcr = 0; } DPRINTK("get_tx\n"); mem = eni_alloc_mem(eni_dev,&size); if (!mem) return -ENOBUFS; - if ((tx_ind = alloc_tx(eni_dev,&pcr,vcc->txtp.min_pcr, - vcc->txtp.max_pcr,vcc->txtp.class == ATM_UBR)) < 0) { + if ((tx_ind = alloc_tx(eni_dev,&pcr,vcc->qos.txtp.min_pcr, + vcc->qos.txtp.max_pcr,vcc->qos.txtp.traffic_class == ATM_UBR)) < 0) + { eni_free_mem(eni_dev,mem,size); return tx_ind; } - if (vcc->txtp.class == ATM_UBR) eni_dev->ubr = &eni_dev->tx[tx_ind]; + if (vcc->qos.txtp.traffic_class == ATM_UBR) + eni_dev->ubr = &eni_dev->tx[tx_ind]; else eni_dev->tx_bw -= pcr; - vcc->txtp.min_pcr = vcc->txtp.max_pcr = pcr; + vcc->qos.txtp.min_pcr = vcc->qos.txtp.max_pcr = pcr; eni_dev->tx[tx_ind].send = (volatile unsigned long *) mem; eni_dev->tx[tx_ind].words = size >> 2; skb_queue_head_init(&eni_dev->tx[tx_ind].backlog); @@ -1664,15 +1672,16 @@ if (*vpi == ATM_VPI_ANY) *vpi = 0; if (*vci == ATM_VCI_ANY) { for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) { - if (vcc->rxtp.class != ATM_NONE && + if (vcc->qos.rxtp.traffic_class != ATM_NONE && ENI_DEV(vcc->dev)->rx_map[*vci]) continue; - if (vcc->txtp.class != ATM_NONE) { + if (vcc->qos.txtp.traffic_class != ATM_NONE) { for (walk = vcc->dev->vccs; walk; walk = walk->next) if ((walk->flags & ATM_VF_ADDR) && walk->vci == *vci && - walk->txtp.class != ATM_NONE) + walk->qos.txtp.traffic_class != + ATM_NONE) break; if (walk) continue; } @@ -1681,12 +1690,13 @@ return *vci == NR_VCI ? -EADDRINUSE : 0; } if (*vci == ATM_VCI_UNSPEC) return 0; - if (vcc->rxtp.class != ATM_NONE && ENI_DEV(vcc->dev)->rx_map[*vci]) + if (vcc->qos.rxtp.traffic_class != ATM_NONE && + ENI_DEV(vcc->dev)->rx_map[*vci]) return -EADDRINUSE; - if (vcc->txtp.class == ATM_NONE) return 0; + if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; for (walk = vcc->dev->vccs; walk; walk = walk->next) if ((walk->flags & ATM_VF_ADDR) && walk->vci == *vci && - walk->txtp.class != ATM_NONE) + walk->qos.txtp.traffic_class != ATM_NONE) return -EADDRINUSE; return 0; } diff -ur --new-file old/linux/drivers/atm/tneta1570.c new/linux/drivers/atm/tneta1570.c --- old/linux/drivers/atm/tneta1570.c Wed Jul 31 19:46:56 1996 +++ new/linux/drivers/atm/tneta1570.c Wed Jul 31 19:47:26 1996 @@ -791,7 +791,7 @@ tneta1570_vcc->tx_wait = NULL; - if (vcc->txtp.class == ATM_NONE) return 0; + if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; tneta1570_vcc->seg_ring_mptr=kmalloc(2*TX_SEG_RING_SIZE*4, GFP_KERNEL); if(!tneta1570_vcc->seg_ring_mptr) { diff -ur --new-file old/linux/drivers/atm/zatm.c new/linux/drivers/atm/zatm.c --- old/linux/drivers/atm/zatm.c Wed Jul 31 19:46:56 1996 +++ new/linux/drivers/atm/zatm.c Wed Jul 31 19:47:25 1996 @@ -384,7 +384,7 @@ pos = (zatm_dev->mbx_start[mbx] & ~0xffff) | zin(MTA(mbx)); while (x = zin(MWA(mbx)), (pos & 0xffff) != x) { unsigned long *here; - struct sk_buff *skb,*expect; + struct sk_buff *skb; struct atm_vcc *vcc; int cells,size,chan; @@ -436,17 +436,7 @@ vcc = zatm_dev->rx_map[chan]; if (skb == zatm_dev->last_free[ZATM_VCC(vcc)->pool]) zatm_dev->last_free[ZATM_VCC(vcc)->pool] = NULL; - expect = skb_dequeue(&zatm_dev->pool[ZATM_VCC(vcc)-> - pool]); - if (skb != expect) { - printk(KERN_CRIT DEV_LABEL "(itf %d): skb " - "mismatch - got 0x%08lx, expected " - "0x%08lx\n",dev->number, - (unsigned long) skb,(unsigned long) expect); - size = 0; - vcc = NULL; - event_dump(); - } + skb_unlink(skb); } else { printk(KERN_ERR DEV_LABEL "(itf %d): RX indication " @@ -456,8 +446,16 @@ event_dump(); } if (error) { - printk(KERN_WARNING DEV_LABEL "(itf %d): chan %d " - "error %s\n",dev->number,chan,err_txt[error]); + static unsigned long silence = 0; + static int last_error = 0; + + if (error != last_error || jiffies > silence) { + printk(KERN_WARNING DEV_LABEL "(itf %d): " + "chan %d error %s\n",dev->number,chan, + err_txt[error]); + last_error = error; + silence = jiffies+2*HZ; + } size = 0; } if (size && (size > cells*ATM_CELL_PAYLOAD-ATM_AAL5_TRAILER || @@ -507,13 +505,14 @@ zatm_dev = ZATM_DEV(vcc->dev); zatm_vcc = ZATM_VCC(vcc); zatm_vcc->rx_chan = 0; - if (vcc->rxtp.class == ATM_NONE) return 0; + if (vcc->qos.rxtp.traffic_class == ATM_NONE) return 0; if (vcc->aal == ATM_AAL5) { - if (vcc->rxtp.max_sdu > 65464) vcc->rxtp.max_sdu = 65464; + if (vcc->qos.rxtp.max_sdu > 65464) + vcc->qos.rxtp.max_sdu = 65464; /* fix this - we may want to receive 64kB SDUs later */ - cells = (vcc->rxtp.max_sdu+ATM_AAL5_TRAILER+ATM_CELL_PAYLOAD-1)/ - ATM_CELL_PAYLOAD; + cells = (vcc->qos.rxtp.max_sdu+ATM_AAL5_TRAILER+ + ATM_CELL_PAYLOAD-1)/ATM_CELL_PAYLOAD; zatm_vcc->pool = pool_index(cells*ATM_CELL_PAYLOAD); } else { @@ -795,8 +794,8 @@ for (shaper = 0; !((zatm_dev->free_shapers >> shaper) & 1); shaper++); zatm_dev->free_shapers &= ~1 << shaper; if (ubr) { - i = c = 5; - m = 1; + c = 5; + i = m = 1; zatm_dev->ubr_ref_cnt++; zatm_dev->ubr = shaper; } @@ -822,6 +821,11 @@ m = (ATM_OC3_PCR*255+max-1)/max; } } + if (i > m) { + printk(KERN_CRIT DEV_LABEL "shaper algorithm botched " + "[%d,%d] -> i=%ld,m=%ld\n",min,max,i,m); + m = i; + } *pcr = i*ATM_OC3_PCR/m; c = 20; /* @@@ should use max_cdv ! */ if ((min && *pcr < min) || (max && *pcr > max)) return -EINVAL; @@ -908,7 +912,7 @@ zatm_vcc->tx_chan = 0; zatm_dev->tx_map[chan] = NULL; if (zatm_vcc->shaper != zatm_dev->ubr) { - zatm_dev->tx_bw += vcc->txtp.min_pcr; + zatm_dev->tx_bw += vcc->qos.txtp.min_pcr; dealloc_shaper(vcc->dev,zatm_vcc->shaper); } if (zatm_vcc->ring) kfree(zatm_vcc->ring); @@ -927,7 +931,7 @@ zatm_dev = ZATM_DEV(vcc->dev); zatm_vcc = ZATM_VCC(vcc); zatm_vcc->tx_chan = 0; - if (vcc->txtp.class == ATM_NONE) return 0; + if (vcc->qos.txtp.traffic_class == ATM_NONE) return 0; save_flags(flags); cli(); zwait; @@ -938,18 +942,18 @@ restore_flags(flags); DPRINTK("chan is %d\n",chan); if (!chan) return -EAGAIN; - if (vcc->txtp.class == ATM_UBR && zatm_dev->ubr != -1) + if (vcc->qos.txtp.traffic_class == ATM_UBR && zatm_dev->ubr != -1) zatm_vcc->shaper = zatm_dev->ubr; else { - if (vcc->txtp.class == ATM_UBR) - vcc->txtp.max_sdu = ATM_MAX_AAL5_PDU; + if (vcc->qos.txtp.traffic_class == ATM_UBR) + vcc->qos.txtp.max_sdu = ATM_MAX_AAL5_PDU; if ((zatm_vcc->shaper = alloc_shaper(vcc->dev,&pcr, - vcc->txtp.min_pcr,vcc->txtp.max_pcr, - vcc->txtp.class == ATM_UBR)) < 0) { + vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr, + vcc->qos.txtp.traffic_class == ATM_UBR)) < 0) { close_tx(vcc); return zatm_vcc->shaper; } - vcc->txtp.min_pcr = vcc->txtp.max_pcr = pcr; + vcc->qos.txtp.min_pcr = vcc->qos.txtp.max_pcr = pcr; } zatm_vcc->tx_chan = chan; skb_queue_head_init(&zatm_vcc->tx_queue); @@ -1402,19 +1406,7 @@ int error; zatm_dev = ZATM_DEV(dev); -printk(KERN_CRIT "got here!\n"); switch (cmd) { -case ZATM_TUNE: -{ - unsigned long old; - - old = zin(GMR); -printk(KERN_INFO "got 0x%08lx\n",old); - zout((old & ~0xf00) | (arg & 0xf00),GMR); - return old; - -} - case ZATM_GETPOOLZ: if (!suser()) return -EPERM; /* fall through */ @@ -1529,12 +1521,14 @@ } +#if 0 static int zatm_sg_send(struct atm_vcc *vcc,unsigned long start, unsigned long size) { return vcc->aal == ATM_AAL5; /* @@@ should check size and maybe alignment*/ } +#endif static int zatm_send(struct atm_vcc *vcc,struct sk_buff *skb) @@ -1592,7 +1586,7 @@ zatm_getsockopt, zatm_setsockopt, zatm_send, - zatm_sg_send, + NULL /*zatm_sg_send*/, NULL, /* no poll */ NULL, /* no send_oam */ zatm_phy_put, diff -ur --new-file old/linux/drivers/atm/zatm.h new/linux/drivers/atm/zatm.h --- old/linux/drivers/atm/zatm.h Wed Jul 31 19:46:56 1996 +++ new/linux/drivers/atm/zatm.h Wed Jul 31 19:47:25 1996 @@ -14,7 +14,7 @@ /* get statistics and zero */ #define ZATM_SETPOOL _IOW('a',ATMIOC_SARPRV+3,struct atmif_sioc) /* set pool parameters */ -#define ZATM_TUNE _IOW('a',ATMIOC_SARPRV+4,struct atmif_sioc) + struct zatm_pool_info { int ref_count; /* free buffer pool usage counters */ diff -ur --new-file old/linux/include/linux/arequipa.h new/linux/include/linux/arequipa.h --- old/linux/include/linux/arequipa.h Wed Jul 31 19:46:58 1996 +++ new/linux/include/linux/arequipa.h Wed Jul 31 19:47:28 1996 @@ -13,6 +13,8 @@ #define AREQUIPA_INCOMING _IO('a',ATMIOC_AREQUIPA+1) #define AREQUIPA_EXPECT _IO('a',ATMIOC_AREQUIPA+2) #define AREQUIPA_CLOSE _IO('a',ATMIOC_AREQUIPA+3) +#define AREQUIPA_CTRL _IO('a',ATMIOC_AREQUIPA+4) +#define AREQUIPA_CLS3RD _IO('a',ATMIOC_AREQUIPA+5) #ifdef __KERNEL__ @@ -23,6 +25,7 @@ #include <net/route.h> +extern struct atm_vcc *aqd; /* for net/atm/proc.c */ /* extern struct rtable arequipa_rt; - not needed */ extern struct device *arequipa_dev; @@ -33,6 +36,9 @@ int arequipa_expect(struct sock *upper,int on); int arequipa_incoming(struct socket *lower); int arequipa_close(struct sock *upper); + +int arequipad_attach(struct atm_vcc *vcc); +void arequipa_close_vcc(struct atm_vcc *vcc); #endif /* __KERNEL__ */ diff -ur --new-file old/linux/include/linux/atm.h new/linux/include/linux/atm.h --- old/linux/include/linux/atm.h Wed Jul 31 19:46:56 1996 +++ new/linux/include/linux/atm.h Wed Jul 31 19:47:26 1996 @@ -135,8 +135,9 @@ #define ATM_MAX_PCR -1 /* maximum available PCR */ +#define class traffic_class /* backward compatibility */ struct atm_trafprm { - unsigned char class; /* traffic class (ATM_UBR, ...) */ + unsigned char traffic_class; /* traffic class (ATM_UBR, ...) */ int max_pcr; /* maximum PCR in cells per second */ int min_pcr; /* minimum PCR in cells per second */ int max_cdv; /* maximum CDV in microseconds */ @@ -164,8 +165,6 @@ short vpi; /* VPI (only 8 bits at UNI) */ int vci; /* VCI (only 16 bits at UNI) */ } sap_addr; /* PVC address */ - struct atm_trafprm sap_txtp; /* TX traffic parameters */ - struct atm_trafprm sap_rxtp; /* RX traffic parameters */ }; /* SVC addressing */ @@ -188,8 +187,6 @@ struct atm_blli *blli; /* local SAP, low-layer information */ struct atm_bhli bhli; /* local SAP, high-layer information */ } sas_addr; /* SVC address */ - struct atm_trafprm sas_txtp; /* TX traffic parameters */ - struct atm_trafprm sas_rxtp; /* RX traffic parameters */ }; diff -ur --new-file old/linux/include/linux/atmdev.h new/linux/include/linux/atmdev.h --- old/linux/include/linux/atmdev.h Wed Jul 31 19:46:56 1996 +++ new/linux/include/linux/atmdev.h Wed Jul 31 19:47:26 1996 @@ -10,6 +10,7 @@ #include <linux/config.h> #include <linux/uio.h> #include <linux/atmioc.h> +#include <asm/atomic.h> #define MAX_ATM_ITF 10 /* for now, should be lowered */ @@ -111,12 +112,12 @@ socket layer */ #define ATM_VF_RELEASED 16 /* demon has indicated/requested release, controlled by SVC socket layer */ -#define ATM_VF_HASQOS 32 /* QOS parameters have been set using the - new API */ +#define ATM_VF_HASQOS 32 /* QOS parameters have been set */ #define ATM_VF_LISTEN 64 /* socket is used for listening */ #define ATM_VF_META 128 /* SVC socket isn't used for normal data traffic and doesn't depend on signaling to be available */ +#define ATM_VF_AQREL 256 /* Arequipa socket is being released */ struct atm_vcc { unsigned short flags; /* VCC flags (ATM_VF_*) */ @@ -128,10 +129,9 @@ unsigned long aal_options; /* AAL layer options */ unsigned long atm_options; /* ATM layer options */ struct atm_dev *dev; /* device back pointer */ - struct atm_trafprm txtp,rxtp; /* traffic parameters */ - struct atm_qos qos; /* QOS - only valid if ATM_VF_HASQOS */ + struct atm_qos qos; /* QOS */ unsigned long tx_quota,rx_quota; /* buffer quotas */ - unsigned long tx_inuse,rx_inuse; /* buffer space in use */ + atomic_t tx_inuse,rx_inuse; /* buffer space in use */ void (*push)(struct atm_vcc *vcc,struct sk_buff *skb); void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */ struct sk_buff *(*peek)(struct atm_vcc *vcc,unsigned long pdu_size, diff -ur --new-file old/linux/include/linux/atmsvc.h new/linux/include/linux/atmsvc.h --- old/linux/include/linux/atmsvc.h Wed Jul 31 19:46:56 1996 +++ new/linux/include/linux/atmsvc.h Wed Jul 31 19:47:26 1996 @@ -13,23 +13,23 @@ #define ATMSIGD_CTRL _IO('a',ATMIOC_SPECIAL) /* become ATM signaling demon control socket */ -enum atmsvc_msg_type { as_catch_null,as_bind,as_establish,as_listen,as_okay, - as_indicate,as_close,as_itf_notify }; +enum atmsvc_msg_type { as_catch_null,as_bind,as_connect,as_accept,as_listen, + as_okay,as_error,as_indicate,as_close,as_itf_notify }; struct atmsvc_msg { enum atmsvc_msg_type type; unsigned long vcc; unsigned long listen_vcc; /* indicate */ - int reply; /* for okay and close: - * < 0: error before active - * (sigd has discarded ctx) - * ==0: success - * > 0: error when active (still need - * to close) - */ + int reply; /* for okay and close: */ + /* < 0: error before active */ + /* (sigd has discarded ctx) */ + /* ==0: success */ + /* > 0: error when active (still */ + /* need to close) */ unsigned char aal; /* AAL */ struct sockaddr_atmpvc pvc; /* indicate, okay (connect) */ struct sockaddr_atmsvc local; /* local SVC address */ + struct atm_qos qos; /* QOS parameters */ struct sockaddr_atmsvc svc; /* MUST BE BEFORE "blli", SVC address */ struct atm_blli blli[1]; /* MUST BE LAST */ }; @@ -41,18 +41,17 @@ * addr *xtp addr sap *xtp addr * bind K->D X - - - - - X X - - * - okay D->K X - - - - - X X - - - * establish K->D X - - X - - X X X X + * connect K->D X - - X - - X X X X * - okay D->K X - - - X X - - - X * listen K->D X - - X - - X X X - * - okay D->K X - - - - - - - - - - * indicate D->K - X - - X 2 X X X - - * accept1 K->D X X - - - - - - - - + * indicate D->K - X - - X 1 X X X - + * accept K->D X X - - - - - - - - * - okay D->K X - - - - - - - - X * close K->D X - - - - - - - - - * close D->K X - X - - - - - - - * - * 1 (establish) - * 2 same value as in svc.*xtp + * 1 same value as in svc.*xtp * * Note: we may have to get rid of the PVC part in indicate messages later, * so it's a good idea not to depend on it too heavily. diff -ur --new-file old/linux/include/linux/mm.h new/linux/include/linux/mm.h --- old/linux/include/linux/mm.h Wed Jul 31 19:46:57 1996 +++ new/linux/include/linux/mm.h Sun Jun 9 11:23:32 1996 @@ -142,7 +142,6 @@ #define PG_decr_after 5 #define PG_swap_unlock_after 6 #define PG_DMA 7 -#define PG_single_copy 8 /* page is locked for single copy */ #define PG_reserved 31 /* Make it prettier to test the above... */ @@ -155,7 +154,6 @@ #define PageDecrAfter(page) (test_bit(PG_decr_after, &(page)->flags)) #define PageSwapUnlockAfter(page) (test_bit(PG_swap_unlock_after, &(page)->flags)) #define PageDMA(page) (test_bit(PG_DMA, &(page)->flags)) -#define PageSingleCopy(page) (test_bit(PG_single_copy, &(page)->flags)) #define PageReserved(page) (test_bit(PG_reserved, &(page)->flags)) /* diff -ur --new-file old/linux/include/net/sock.h new/linux/include/net/sock.h --- old/linux/include/net/sock.h Wed Jul 31 19:46:58 1996 +++ new/linux/include/net/sock.h Wed Jul 31 19:47:28 1996 @@ -251,8 +251,8 @@ unsigned char max_ack_backlog; unsigned char priority; unsigned char debug; - unsigned short rcvbuf; - unsigned short sndbuf; + unsigned long rcvbuf; + unsigned long sndbuf; unsigned short type; unsigned char localroute; /* Route locally only */ #ifdef CONFIG_AX25 diff -ur --new-file old/linux/net/atm/arequipa.c new/linux/net/atm/arequipa.c --- old/linux/net/atm/arequipa.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/arequipa.c Wed Jul 31 19:47:26 1996 @@ -22,6 +22,7 @@ #include <asm/system.h> /* cli and such */ #include "protocols.h" +#include "tunable.h" #include "signaling.h" /* for indirect closing, see below */ #include "common.h" #include "ipcommon.h" @@ -36,6 +37,7 @@ struct device *arequipa_dev = NULL; /* must use a different null value if skb->dev can ever be NULL */ +struct atm_vcc *aqd = NULL; struct rtable arequipa_rt = { NULL, /* rt_next */ @@ -58,11 +60,34 @@ /* * Closing is tricky. Since we may be in an interrupt when executing * arequipa_close, we can't just go and call close_fp. So what we do it instead - * is to ask signaling nicely to close the SVC. Signaling does its job and then - * comes back to close us (in arequipa_callback). Now we're in a process - * context and can sleep, etc. + * is to ask arequipad nicely to close the VC. arequipad issues an + * AREQUIPA_CLS3RD ioctl to close us (via arequipa_close_vcc). Now we're in a + * process context and can sleep, etc. Ain't life sweet ? */ + +static void aqd_enq(struct atm_vcc *vcc) +{ + struct sk_buff *skb; + + if (!aqd) { + printk(KERN_CRIT "aqd_enq: no Arequipa demon\n"); + return; + } + skb = alloc_skb(sizeof(vcc),GFP_ATOMIC); + if (!skb) { + printk(KERN_CRIT "adq_enq: out of memory\n"); + return; + } + skb->free = 1; + skb->len = sizeof(vcc); + *(struct atm_vcc **) skb->data = vcc; + atomic_add(skb->truesize+ATM_PDU_OVHD,&aqd->rx_inuse); + skb_queue_tail(&aqd->recvq,skb); + wake_up(&aqd->sleep); +} + + int arequipa_close(struct sock *upper) { struct socket *lower; @@ -74,20 +99,32 @@ cli(); upper->arequipa = NULL; ATM_SD(lower)->upper = NULL; + if (!(ATM_SD(lower)->flags & ATM_VF_AQREL)) aqd_enq(ATM_SD(lower)); + ATM_SD(lower)->flags |= ATM_VF_AQREL; restore_flags(flags); - sigd_enq_atomic(ATM_SD(lower),as_close,NULL,NULL,NULL); - ATM_SD(lower)->flags &= ~ATM_VF_REGIS; return 0; } +void arequipa_close_vcc(struct atm_vcc *vcc) +{ + if (!(vcc->flags & ATM_VF_AQREL)) + printk(KERN_CRIT "arequipa_close_3rd_party: VCC %p doesn't " + "have ATM_VF_AQREL set\n",vcc); + else close_fp(vcc->sock->file); +} + static void arequipa_callback(struct atm_vcc *vcc) { + unsigned long flags; + DPRINTK("arequipa_callback\n"); svc_callback(vcc); if (!(vcc->flags & ATM_VF_RELEASED)) return; vcc->callback = svc_callback; /* paranoia ... */ + save_flags(flags); + cli(); if (vcc->upper) { if (!vcc->upper->arequipa) printk("arequipa_callback: upper pretends not to " @@ -95,17 +132,22 @@ ip_rt_put(vcc->upper->ip_route_cache); vcc->upper->ip_route_cache = NULL; vcc->upper->arequipa = NULL; - vcc->callback = svc_callback; } - close_fp(vcc->sock->file); + if (vcc->flags & ATM_VF_AQREL) { + restore_flags(flags); + return; + } + vcc->flags |= ATM_VF_AQREL; + restore_flags(flags); + arequipa_close_vcc(vcc); return; } static int check_aq_vcc(struct socket *lower) { - if (lower->ops->family != PF_ATMSVC) return -EPROTOTYPE; - /* no PVCs, because we need to be closed by a 3rd party */ + if (lower->ops->family != PF_ATMSVC && lower->ops->family != PF_ATMPVC) + return -EPROTOTYPE; if (lower->state != SS_CONNECTED) return -ENOTCONN; if (ATM_SD(lower)->aal != ATM_AAL5) return -EPROTONOSUPPORT; return 0; @@ -170,6 +212,10 @@ int arequipa_expect(struct sock *upper,int on) { DPRINTK("arequipa_expect %d\n",on); + if (!aqd) { + printk(KERN_ERR "arequipa_expect: no Arequipa demon\n"); + return -EUNATCH; + } if (on) { if (upper->aq_route) return 0; upper->aq_route = kmalloc(sizeof(struct rtable),GFP_KERNEL); @@ -187,6 +233,10 @@ { int error; + if (!aqd) { + printk(KERN_ERR "arequipa_preset: no Arequipa demon\n"); + return -EUNATCH; + } error = arequipa_expect(upper,1); if (error) return error; error = arequipa_attach(lower,upper); @@ -255,4 +305,63 @@ arequipa_dev->init = arequipa_init; arequipa_init(arequipa_dev); return 0; +} + + +static void aqd_close(struct atm_vcc *vcc) +{ + struct sk_buff *skb; + + DPRINTK("aqd_close\n"); + aqd = NULL; /* assumed to be atomic */ + barrier(); + if (skb_peek(&vcc->recvq)) + printk(KERN_CRIT "aqd_close: closing with requests " + "pending\n"); + while ((skb = skb_dequeue(&vcc->recvq))) kfree_skb(skb,FREE_READ); +} + + +static struct atmdev_ops aqd_dev_ops = { + NULL, /* no open */ + aqd_close, /* close */ + NULL, /* no ioctl */ + NULL, /* no getsockopt */ + NULL, /* no setsockopt */ + NULL, /* no send */ + NULL, /* no sg_send */ + NULL, /* no poll */ + NULL, /* no phy_put */ + NULL, /* no phy_get */ + NULL /* no feedback */ +}; + + +static struct atm_dev aqd_dev = { + &aqd_dev_ops, + NULL, /* no PHY */ + "aqd", /* type */ + 999, /* dummy device number */ + NULL,NULL, /* pretend not to have any VCCs */ + NULL,NULL, /* no data */ + 0, /* no flags */ + NULL, /* no local address */ + { 0 } /* no ESI, no statistics */ +}; + + +int arequipad_attach(struct atm_vcc *vcc) +{ + if (aqd) return -EADDRINUSE; + aqd = vcc; + vcc->flags |= ATM_VF_READY | ATM_VF_META; + /* allow replies and avoid getting closed if signaling dies */ + vcc->dev = &aqd_dev; + vcc->aal = ATM_AAL5; /* lie */ + vcc->push = NULL; + vcc->peek = NULL; /* crash */ + vcc->pop = NULL; /* crash */ + vcc->push_oam = NULL; /* crash */ + return 0; + } diff -ur --new-file old/linux/net/atm/atmarp.c new/linux/net/atm/atmarp.c --- old/linux/net/atm/atmarp.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/atmarp.c Wed Jul 31 19:47:26 1996 @@ -32,6 +32,7 @@ #include "common.h" +#include "tunable.h" #include "protocols.h" /* for atm_push_raw */ #include "ipcommon.h" #include "atmarp.h" @@ -116,6 +117,7 @@ ctrl->arg = arg; if (data) memcpy(ctrl->data,data,length); reply = WAITING; + atomic_add(skb->truesize+ATM_PDU_OVHD,&atmarpd->rx_inuse); skb_queue_tail(&atmarpd->recvq,skb); wake_up(&atmarpd->sleep); if (!need_reply) return 0; @@ -313,6 +315,8 @@ memcpy((void *) skb->data,llc_oui,sizeof(llc_oui)); ((unsigned short *) skb->data)[3] = htons(ETH_P_IP); } + DPRINTK("CX(A) %d += %d\n",entry->vcc->tx_inuse,skb->truesize); + atomic_add(skb->truesize,&entry->vcc->tx_inuse); skb->atm.iovcnt = 0; AE(entry->vcc)->last_use = jiffies; entry->vcc->dev->ops->send(entry->vcc,skb); @@ -559,7 +563,7 @@ NULL, /* no ioctl */ NULL, /* no getsockopt */ NULL, /* no setsockopt */ - atmarpd_send, /* no send */ + atmarpd_send, /* send */ NULL, /* no sg_send */ NULL, /* no poll */ NULL, /* no phy_put */ diff -ur --new-file old/linux/net/atm/clip.c new/linux/net/atm/clip.c --- old/linux/net/atm/clip.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/clip.c Wed Jul 31 19:47:26 1996 @@ -91,6 +91,7 @@ int atm_init_clip(struct atm_vcc *vcc) { struct device *dev; + int number; DPRINTK("atm_init_clip\n"); if (!suser()) return -EPERM; @@ -101,13 +102,14 @@ vcc->push_oam = NULL; vcc->proto_data = dev = kmalloc(sizeof(struct device)+ sizeof(struct clip_priv),GFP_KERNEL); - if (!vcc->proto_data) return -ENOMEM; + if (!dev) return -ENOMEM; memset(dev,0,sizeof(struct device)+sizeof(struct clip_priv)); dev->name = CLIP(dev)->name; - sprintf(dev->name,"atm%d",pvc_num++); + number = pvc_num++; + sprintf(dev->name,"atm%d",number); dev->init = clip_init; CLIP(dev)->vcc = vcc; if (register_netdev(dev)) return -EIO; DPRINTK("registered %s,0x%lx\n",dev->name,(unsigned long) vcc); - return 0; + return number; } diff -ur --new-file old/linux/net/atm/common.c new/linux/net/atm/common.c --- old/linux/net/atm/common.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/common.c Wed Jul 31 19:47:26 1996 @@ -48,7 +48,13 @@ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size) { - return alloc_skb(size,GFP_KERNEL); + struct sk_buff *skb; + + if (size+vcc->tx_inuse+ATM_PDU_OVHD > vcc->tx_quota) return NULL; + while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule(); + DPRINTK("AlTx %d += %d\n",vcc->tx_inuse,skb->truesize); + atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); + return skb; } @@ -71,8 +77,8 @@ vcc->callback = NULL; memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc)); memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc)); - vcc->tx_quota = ATM_RXBQ_DEF*1024; - vcc->rx_quota = ATM_TXBQ_DEF*1024; + vcc->tx_quota = ATM_TXBQ_DEF; + vcc->rx_quota = ATM_RXBQ_DEF; vcc->tx_inuse = vcc->rx_inuse = 0; switch (protocol) { /* @@ -146,23 +152,27 @@ static int adjust_tp(struct atm_trafprm *tp,unsigned char aal) { + int max_sdu; + if (!tp->class) return 0; if (tp->class != ATM_UBR && !tp->min_pcr && !tp->max_pcr) return -EINVAL; - if (!tp->max_sdu) - switch (aal) { - case ATM_AAL0: - tp->max_sdu = ATM_CELL_SIZE-1; - break; - case ATM_AAL34: - tp->max_sdu = ATM_MAX_AAL34_PDU; - break; - default: - printk(KERN_WARNING "ATM: AAL problems ... " - "(%d)\n",aal); - case ATM_AAL5: - tp->max_sdu = ATM_MAX_AAL5_PDU; - } + switch (aal) { + case ATM_AAL0: + max_sdu = ATM_CELL_SIZE-1; + break; + case ATM_AAL34: + max_sdu = ATM_MAX_AAL34_PDU; + break; + default: + printk(KERN_WARNING "ATM: AAL problems ... " + "(%d)\n",aal); + /* fall through */ + case ATM_AAL5: + max_sdu = ATM_MAX_AAL5_PDU; + } + if (!tp->max_sdu) tp->max_sdu = max_sdu; + else if (tp->max_sdu > max_sdu) return -EINVAL; if (!tp->max_cdv) tp->max_cdv = ATM_MAX_CDV; return 0; } @@ -174,9 +184,10 @@ for (walk = vcc->dev->vccs; walk; walk = walk->next) if ((walk->flags & ATM_VF_ADDR) && walk->vpi == vpi && - walk->vci == vci && ((walk->txtp.class != ATM_NONE && - vcc->txtp.class != ATM_NONE) || (walk->rxtp.class != - ATM_NONE && vcc->rxtp.class != ATM_NONE))) + walk->vci == vci && ((walk->qos.txtp.traffic_class != + ATM_NONE && vcc->qos.txtp.traffic_class != ATM_NONE) || + (walk->qos.rxtp.traffic_class != ATM_NONE && + vcc->qos.rxtp.traffic_class != ATM_NONE))) return -EADDRINUSE; /* allow VCCs with same VPI/VCI iff they don't collide on TX/RX (but we may refuse such sharing for other reasons, @@ -251,15 +262,15 @@ "(%d)\n",vcc->dev->type,vcc->dev->number,vcc->aal); return -EINVAL; } - error = adjust_tp(&vcc->txtp,vcc->aal); - if (!error) error = adjust_tp(&vcc->rxtp,vcc->aal); + error = adjust_tp(&vcc->qos.txtp,vcc->aal); + if (!error) error = adjust_tp(&vcc->qos.rxtp,vcc->aal); if (error) return error; vcc->dev = (struct atm_dev *) dev; DPRINTK("VCC %d.%d, AAL %d\n",vpi,vci,vcc->aal); - DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->txtp.class, - vcc->txtp.min_pcr,vcc->txtp.max_pcr,vcc->txtp.max_sdu); - DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->rxtp.class, - vcc->rxtp.min_pcr,vcc->rxtp.max_pcr,vcc->rxtp.max_sdu); + DPRINTK(" TX: %d, PCR %d..%d, SDU %d\n",vcc->qos.txtp.traffic_class, + vcc->qos.txtp.min_pcr,vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu); + DPRINTK(" RX: %d, PCR %d..%d, SDU %d\n",vcc->qos.rxtp.class, + vcc->qos.rxtp.min_pcr,vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); if (dev->ops->open) { error = dev->ops->open(vcc,vpi,vci); if (error) { @@ -290,10 +301,12 @@ vcc->flags &= ~ATM_VF_PARTIAL; else if (vcc->flags & ATM_VF_PARTIAL) return -EINVAL; printk("atm_connect (TX: cl %d,bw %d-%d,sdu %d; RX: cl %d,bw %d-%d," - "sdu %d)\n",vcc->txtp.class,vcc->txtp.min_pcr,vcc->txtp.max_pcr, - vcc->txtp.max_sdu,vcc->rxtp.class,vcc->rxtp.min_pcr, - vcc->rxtp.max_pcr,vcc->rxtp.max_sdu); - if (vcc->txtp.class == ATM_ANYCLASS || vcc->rxtp.class == ATM_ANYCLASS) + "sdu %d)\n",vcc->qos.txtp.traffic_class,vcc->qos.txtp.min_pcr, + vcc->qos.txtp.max_pcr,vcc->qos.txtp.max_sdu, + vcc->qos.rxtp.traffic_class,vcc->qos.rxtp.min_pcr, + vcc->qos.rxtp.max_pcr,vcc->qos.rxtp.max_sdu); + if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || + vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; if (itf != ATM_ITF_ANY) error = atm_do_connect(vcc,itf,vpi,vci); else { @@ -360,6 +373,8 @@ if (vcc->dev->ops->feedback) vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data, (unsigned long) buff,eff_len); + DPRINTK("RcvM %d -= %d\n",vcc->rx_inuse,skb->truesize); + atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->rx_inuse); #ifdef CONFIG_MMU_HACKS mmucp_tofs((unsigned long) buff,eff_len,skb,(unsigned long) skb->data); #else @@ -428,6 +443,8 @@ } else { DPRINTK("res is %d\n",res); + DPRINTK("Asnd %d += %d\n",vcc->tx_inuse,skb->truesize); + atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); skb->atm.iovcnt = res; skb_device_lock(skb); vcc->dev->ops->send(vcc,skb); @@ -437,8 +454,7 @@ } #endif eff = (size+3) & ~3; /* align to word boundary */ - while (size+vcc->tx_inuse+ATM_PDU_OVHD > vcc->tx_quota || - !(skb = vcc->alloc_tx(vcc,eff))) { + while (!(skb = vcc->alloc_tx(vcc,eff))) { if (nonblock) return -EAGAIN; interruptible_sleep_on(&vcc->sleep); if (current->signal & ~current->blocked) @@ -491,8 +507,8 @@ return 1; case SEL_OUT: if (sock->state == SS_CONNECTING) break; - if (vcc->txtp.class == ATM_NONE) return 1; - if (vcc->txtp.max_sdu+vcc->tx_inuse+ATM_PDU_OVHD > + if (vcc->qos.txtp.traffic_class == ATM_NONE) return 1; + if (vcc->qos.txtp.max_sdu+vcc->tx_inuse+ATM_PDU_OVHD > vcc->tx_quota) break; return 1; case SEL_EX: @@ -627,6 +643,15 @@ } case AREQUIPA_INCOMING: return arequipa_incoming(sock); + case AREQUIPA_CTRL: + if (!suser()) return -EPERM; + error = arequipad_attach(ATM_SD(sock)); + if (!error) sock->state = SS_CONNECTED; + return error; + case AREQUIPA_CLS3RD: + if (!suser()) return -EPERM; + arequipa_close_vcc((struct atm_vcc *) arg); + return 0; #endif #ifdef CONFIG_ATM_LANE case ATMLEC_CTRL: @@ -766,15 +791,17 @@ if (optlen != sizeof(value)) return -EINVAL; value = get_fs_long(optval); if (!value) value = ATM_TXBQ_DEF; + if (value < ATM_TXBQ_MIN) value = ATM_TXBQ_MIN; if (value > ATM_TXBQ_MAX) value = ATM_TXBQ_MAX; - vcc->tx_quota = value*1024; + vcc->tx_quota = value; return 0; case SO_RCVBUF: if (optlen != sizeof(value)) return -EINVAL; value = get_fs_long(optval); if (!value) value = ATM_RXBQ_DEF; + if (value < ATM_RXBQ_MIN) value = ATM_RXBQ_MIN; if (value > ATM_RXBQ_MAX) value = ATM_RXBQ_MAX; - vcc->rx_quota = value*1024; + vcc->rx_quota = value; return 0; default: return -EINVAL; @@ -783,9 +810,10 @@ if (level == SOL_ATM) { switch (optname) { case SO_ATMQOS: + if (sock->state != SS_UNCONNECTED) + return -EBADFD; if (optlen != sizeof(struct atm_qos)) return -EINVAL; - if (vcc->flags & ATM_VF_HASQOS) return -EINVAL; memcpy_fromfs(&vcc->qos,optval,optlen); vcc->flags |= ATM_VF_HASQOS; return 0; diff -ur --new-file old/linux/net/atm/ipcommon.c new/linux/net/atm/ipcommon.c --- old/linux/net/atm/ipcommon.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/ipcommon.c Wed Jul 31 19:47:26 1996 @@ -133,6 +133,13 @@ } +static int clip_open(struct device *dev) +{ + DPRINTK("clip_open called\n"); + return 0; +} + + static int clip_stop(struct device *dev) { DPRINTK("DOWN! (%s,0x%lx)\n",dev->name,(unsigned long) CLIP(dev)->vcc); @@ -155,6 +162,7 @@ dev->sg_xmit = NULL; #endif #endif + dev->open = clip_open; dev->stop = clip_stop; ether_setup(dev); dev->tbusy = 0; /* @@@ check */ diff -ur --new-file old/linux/net/atm/ipcommon.h new/linux/net/atm/ipcommon.h --- old/linux/net/atm/ipcommon.h Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/ipcommon.h Wed Jul 31 19:47:26 1996 @@ -50,6 +50,7 @@ memcpy(skb->data,llc_oui,sizeof(llc_oui)); ((unsigned short *) skb->data)[3] = htons(ETH_P_IP); /* hack */ } + atomic_add(skb->truesize,&vcc->tx_inuse); skb->atm.iovcnt = 0; vcc->dev->ops->send(vcc,skb); } diff -ur --new-file old/linux/net/atm/lec.c new/linux/net/atm/lec.c --- old/linux/net/atm/lec.c Wed Jul 31 19:46:58 1996 +++ new/linux/net/atm/lec.c Wed Jul 31 19:47:27 1996 @@ -168,6 +168,7 @@ /* Minimum ethernet-frame size */ if (skb->len <62) skb->len = 62; + atomic_add(skb->truesize,&send_vcc->tx_inuse); skb->atm.iovcnt = 0; send_vcc->dev->ops->send(send_vcc, skb); if (priv) diff -ur --new-file old/linux/net/atm/mmuio.c new/linux/net/atm/mmuio.c --- old/linux/net/atm/mmuio.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/mmuio.c Wed Jul 31 19:47:26 1996 @@ -4,11 +4,14 @@ #include <linux/config.h> -#include <linux/mmuio.h> #ifdef CONFIG_MMU_HACKS +#include <linux/mmuio.h> +#include <asm/atomic.h> + + #define invalidate flush_tlb_all /* @@@ improve this */ @@ -345,7 +348,6 @@ { struct vm_area_struct *vma; unsigned long end,last,from,page; - unsigned long flags; pgd_t *pgd; pmd_t *pmd; pte_t *pte; @@ -386,26 +388,13 @@ return -EINVAL; } map = mem_map+MAP_NR(page); - if (map->reserved) { + if (PageReserved(map)) { printk(KERN_ERR "lock_user: reserved\n"); event_dump(); return -EINVAL; } - if (!map->locked && PageSingleCopy(map)) - printk(KERN_CRIT "strange, !l && u\n"); - save_flags(flags); - cli(); - while (map->locked /* && SC = 0 or SC = max */) { - EVENT("Waiting for page ...\n",0,0,0); - wait_on_page(map); - } - if (!map->locked) { - map->count++; - map->locked = 1; - *pte = pte_wrprotect(*pte); - } - set_bit(PG_single_copy,&map->flags); - restore_flags(flags); + atomic_inc(&map->count); + *pte = pte_wrprotect(*pte); if (!last) { from = page+(start & (PAGE_SIZE-1)); start &= ~(PAGE_SIZE-1); @@ -457,15 +446,7 @@ mem_map_t *map; map = mem_map+MAP_NR(walk); - if (!clear_bit(PG_single_copy,&map->flags)) - printk(KERN_CRIT "unlock_user: returning " - "unlocked page\n"); - /* -- if last lock is gone */ - EVENT("returning page 0x%08lx\n",walk,0,0); - map->locked = 0; - wake_up(&map->wait); free_page(walk); - /* -- endif */ } iov++; } diff -ur --new-file old/linux/net/atm/proc.c new/linux/net/atm/proc.c --- old/linux/net/atm/proc.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/proc.c Wed Jul 31 19:47:26 1996 @@ -17,6 +17,7 @@ #include <linux/atmclip.h> #include <linux/atmarp.h> #include <linux/if_arp.h> +#include <linux/arequipa.h> /* to get aqd */ #include <asm/param.h> /* for HZ */ #include "static.h" /* ugly */ @@ -174,8 +175,9 @@ off = sprintf(buf,"%3d %3d %5d %-3s %7d %-5s %7d %-6s", vcc->dev->number,vcc->vpi,vcc->vci, vcc->aal >= sizeof(aal_name)/sizeof(aal_name[0]) ? "err" : - aal_name[vcc->aal],vcc->rxtp.min_pcr,class_name[vcc->rxtp.class], - vcc->txtp.min_pcr,class_name[vcc->txtp.class]); + aal_name[vcc->aal],vcc->qos.rxtp.min_pcr, + class_name[vcc->qos.rxtp.traffic_class],vcc->qos.txtp.min_pcr, + class_name[vcc->qos.txtp.traffic_class]); #ifdef CONFIG_ATM_CLIP if (vcc->push == atm_push_clip) { struct device *dev; @@ -215,6 +217,9 @@ here += sprintf(here,"%-10s ",vcc == sigd ? "Signaling" : #ifdef CONFIG_ATM_ATMARP vcc == atmarpd ? "ATMARPctrl" : +#endif +#ifdef CONFIG_AREQUIPA + vcc == aqd ? "Arequipa" : #endif vcc_state(vcc)); here += sprintf(here,"%s%s",vcc->remote.sas_addr.pub, diff -ur --new-file old/linux/net/atm/pvc.c new/linux/net/atm/pvc.c --- old/linux/net/atm/pvc.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/pvc.c Wed Jul 31 19:47:26 1996 @@ -41,24 +41,16 @@ { struct sockaddr_atmpvc *addr; struct atm_vcc *vcc; - /*int error;*/ if (sockaddr_len != sizeof(struct sockaddr_atmpvc)) return -EINVAL; addr = (struct sockaddr_atmpvc *) sockaddr; if (addr->sap_family != AF_ATMPVC) return -EAFNOSUPPORT; vcc = ATM_SD(sock); + if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; if (vcc->flags & ATM_VF_PARTIAL) { if (vcc->vpi != ATM_VPI_UNSPEC) addr->sap_addr.vpi = vcc->vpi; if (vcc->vci != ATM_VCI_UNSPEC) addr->sap_addr.vci = vcc->vci; } - else if (vcc->flags & ATM_VF_HASQOS) { - vcc->txtp = vcc->qos.txtp; - vcc->rxtp = vcc->qos.rxtp; - } - else { - vcc->txtp = addr->sap_txtp; - vcc->rxtp = addr->sap_rxtp; - } return atm_connect(sock,addr->sap_addr.itf,addr->sap_addr.vpi, addr->sap_addr.vci); } @@ -100,8 +92,6 @@ addr->sap_addr.itf = vcc->dev->number; addr->sap_addr.vpi = vcc->vpi; addr->sap_addr.vci = vcc->vci; - memcpy(&addr->sap_txtp,&vcc->txtp,sizeof(struct atm_trafprm)); - memcpy(&addr->sap_rxtp,&vcc->rxtp,sizeof(struct atm_trafprm)); return 0; } diff -ur --new-file old/linux/net/atm/raw.c new/linux/net/atm/raw.c --- old/linux/net/atm/raw.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/raw.c Wed Jul 31 19:47:26 1996 @@ -12,6 +12,7 @@ #include <linux/mmuio.h> #include <linux/uio.h> +#include "common.h" #include "protocols.h" #include "tunable.h" /* tunable parameters */ @@ -30,6 +31,8 @@ void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb) { if (skb) { + DPRINTK("APushR %d += %d\n",vcc->rx_inuse,skb->truesize); + atomic_add(skb->truesize+ATM_PDU_OVHD,&vcc->rx_inuse); skb_queue_tail(&vcc->recvq,skb); wake_up(&vcc->sleep); } @@ -65,16 +68,22 @@ { struct sk_buff *skb; - if (pdu_size+vcc->rx_inuse+ATM_PDU_OVHD <= vcc->rx_quota) { - skb = alloc_skb(((pdu_size+3) & ~3)+PAGE_SIZE-1,GFP_ATOMIC); - if (skb) { - skb->data = (unsigned char *) - (((unsigned long) skb->data+PAGE_SIZE-1) & - ~(PAGE_SIZE-1)); + if (pdu_size+vcc->rx_inuse+ATM_PDU_OVHD <= vcc->rx_quota) + if (pdu_size < PAGE_SIZE) { + skb = alloc_skb((pdu_size+3) & ~3,GFP_ATOMIC); + if (skb) return skb; + } + else { + skb = alloc_skb(((pdu_size+3) & ~3)+PAGE_SIZE-1, + GFP_ATOMIC); + if (skb) { + skb->data = (unsigned char *) + (((unsigned long) skb->data+PAGE_SIZE-1) & + ~(PAGE_SIZE-1)); DPRINTK("PEEK: data at 0x%lx\n",(unsigned long) skb->data); - return skb; + return skb; + } } - } vcc->stats->rx_drop++; return NULL; } @@ -86,6 +95,8 @@ if (skb->atm.iovcnt) unlock_user(skb->atm.iovcnt,(struct iovec *) skb->data); #endif + 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,FREE_WRITE); #if 0 /* experimental */ if (vcc->dev->sending != 1) printk("sending == %d !!!\n",vcc->dev->sending); diff -ur --new-file old/linux/net/atm/signaling.c new/linux/net/atm/signaling.c --- old/linux/net/atm/signaling.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/signaling.c Wed Jul 31 19:47:26 1996 @@ -13,6 +13,7 @@ #include <linux/atmsvc.h> #include <linux/atmdev.h> +#include "tunable.h" #include "static.h" #include "signaling.h" @@ -40,7 +41,6 @@ msg = (struct atmsvc_msg *) skb->data; DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,msg->vcc); vcc = (struct atm_vcc *) msg->vcc; - if (!vcc) vcc = (struct atm_vcc *) msg->listen_vcc; switch (msg->type) { case as_okay: vcc->reply = msg->reply; @@ -56,10 +56,14 @@ vcc->itf = msg->pvc.sap_addr.itf; vcc->vpi = msg->pvc.sap_addr.vpi; vcc->vci = msg->pvc.sap_addr.vci; - vcc->txtp = msg->pvc.sap_txtp; - vcc->rxtp = msg->pvc.sap_rxtp; + if (vcc->vpi || vcc->vci) vcc->qos = msg->qos; + break; + case as_error: + vcc->flags &= ~(ATM_VF_REGIS | ATM_VF_READY); + vcc->reply = msg->reply; break; case as_indicate: + vcc = (struct atm_vcc *) msg->listen_vcc; DPRINTK("as_indicate!!!\n"); if (!vcc->backlog_quota) { sigd_enq(0,as_close,(struct atm_vcc *) @@ -75,15 +79,9 @@ } return 0; case as_close: - if (msg->reply < 0) { - vcc->flags &= ~ATM_VF_REGIS; - vcc->reply = msg->reply; - } - else { - vcc->flags |= ATM_VF_RELEASED; - vcc->reply = -msg->reply; - } + vcc->flags |= ATM_VF_RELEASED; vcc->flags &= ~ATM_VF_READY; + vcc->reply = msg->reply; break; default: printk(KERN_ALERT "sigd_send: bad message type %d\n", @@ -96,9 +94,9 @@ } -static void _sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, +void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc,int atomic) + const struct sockaddr_atmsvc *svc) { struct sk_buff *skb; struct atmsvc_msg *msg; @@ -113,11 +111,7 @@ if (svc) for (walk = svc->sas_addr.blli; walk; walk = walk->next) size += sizeof(struct atm_blli); - if (!atomic) while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule(); - else if (!(skb = alloc_skb(size,GFP_ATOMIC))) { - printk(KERN_ALERT "sigd_enq: no memory for message\n"); - return; - } + while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule(); skb->free = 1; skb->len = size; msg = (struct atmsvc_msg *) skb->data; @@ -125,6 +119,7 @@ msg->vcc = (unsigned long) vcc; msg->listen_vcc = (unsigned long) listen_vcc; msg->aal = vcc ? vcc->aal : 0; + msg->qos = vcc->qos; if (!svc) msg->svc.sas_family = 0; else { msg->svc = *svc; @@ -153,25 +148,10 @@ return; #endif } + atomic_add(skb->truesize+ATM_PDU_OVHD,&sigd->rx_inuse); skb_queue_tail(&sigd->recvq,skb); wake_up(&sigd->sleep); if (vcc) vcc->flags |= ATM_VF_REGIS; -} - - -void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, - const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc) -{ - _sigd_enq(vcc,type,listen_vcc,pvc,svc,0); -} - - -void sigd_enq_atomic(struct atm_vcc *vcc,enum atmsvc_msg_type type, - const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc) -{ - _sigd_enq(vcc,type,listen_vcc,pvc,svc,1); } diff -ur --new-file old/linux/net/atm/signaling.h new/linux/net/atm/signaling.h --- old/linux/net/atm/signaling.h Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/signaling.h Wed Jul 31 19:47:26 1996 @@ -20,9 +20,6 @@ void sigd_enq(struct atm_vcc *vcc,enum atmsvc_msg_type type, const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, const struct sockaddr_atmsvc *svc); -void sigd_enq_atomic(struct atm_vcc *vcc,enum atmsvc_msg_type type, - const struct atm_vcc *listen_vcc,const struct sockaddr_atmpvc *pvc, - const struct sockaddr_atmsvc *svc); int sigd_attach(struct atm_vcc *vcc); #endif diff -ur --new-file old/linux/net/atm/svc.c new/linux/net/atm/svc.c --- old/linux/net/atm/svc.c Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/svc.c Wed Jul 31 19:47:26 1996 @@ -152,10 +152,7 @@ vcc = ATM_SD(sock); vcc->flags &= ~ATM_VF_BOUND; /* failing rebind will kill old binding */ /* @@@ check memory (de)allocation on rebind */ - if (vcc->flags & ATM_VF_HASQOS) { - addr->sas_txtp = vcc->qos.txtp; - addr->sas_rxtp = vcc->qos.rxtp; - } + if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; error = copy_svc_addr(&vcc->local,addr); if (error) return error; vcc->reply = WAITING; @@ -188,18 +185,16 @@ if (sock->state != SS_UNCONNECTED) return -EINVAL; addr = (struct sockaddr_atmsvc *) sockaddr; if (addr->sas_family != AF_ATMSVC) return -EAFNOSUPPORT; - if (vcc->flags & ATM_VF_HASQOS) { - addr->sas_txtp = vcc->qos.txtp; - addr->sas_rxtp = vcc->qos.rxtp; - } - if (addr->sas_txtp.class == ATM_ANYCLASS || - addr->sas_rxtp.class == ATM_ANYCLASS) return -EINVAL; - if (!addr->sas_txtp.class && !addr->sas_rxtp.class) + if (!(vcc->flags & ATM_VF_HASQOS)) return -EBADFD; + if (vcc->qos.txtp.traffic_class == ATM_ANYCLASS || + vcc->qos.rxtp.traffic_class == ATM_ANYCLASS) return -EINVAL; + if (!vcc->qos.txtp.traffic_class && + !vcc->qos.rxtp.traffic_class) return -EINVAL; error = copy_svc_addr(&vcc->remote,addr); if (error) return error; vcc->reply = WAITING; - sigd_enq(vcc,as_establish,NULL,NULL,&vcc->remote); + sigd_enq(vcc,as_connect,NULL,NULL,&vcc->remote); if (flags & O_NONBLOCK) { sock->state = SS_CONNECTING; return -EINPROGRESS; @@ -240,8 +235,8 @@ * * #ifndef CONFIG_SINGLE_SIGITF */ - vcc->txtp.max_pcr = SELECT_TOP_PCR(vcc->txtp); - vcc->txtp.min_pcr = 0; + vcc->qos.txtp.max_pcr = SELECT_TOP_PCR(vcc->qos.txtp); + vcc->qos.txtp.min_pcr = 0; /* * #endif */ @@ -290,7 +285,7 @@ error */ /* wait should be short, so we ignore the non-blocking flag */ new_vcc->reply = WAITING; - sigd_enq(new_vcc,as_establish,old_vcc,NULL,NULL); + sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL); while (new_vcc->reply == WAITING && sigd) sleep_on(&new_vcc->sleep); if (!sigd) return -EUNATCH; @@ -300,8 +295,7 @@ } if (!sigd) return -EUNATCH; msg = (struct atmsvc_msg *) skb->data; - new_vcc->txtp = msg->pvc.sap_txtp; - new_vcc->rxtp = msg->pvc.sap_rxtp; + new_vcc->qos = msg->qos; new_vcc->remote = msg->svc; /* copy BLLI @@@ */ new_vcc->remote.sas_addr.blli = NULL; @@ -324,7 +318,7 @@ { struct sockaddr_atmsvc *addr; - /* this will be fun ... we have: txtp/rxtp, public and private + /* this will be fun ... we have: public and private address, bhli and possibly a lot of bllis. Now address buffers are static ... argl */ /* The solution: use pointers to link bllis */ @@ -339,8 +333,6 @@ memcpy(addr,peer ? &ATM_SD(sock)->remote : &ATM_SD(sock)->local, sizeof(struct sockaddr_atmsvc)); addr->sas_addr.blli = NULL; /* @@@ no - copy it */ - memcpy(&addr->sas_txtp,&ATM_SD(sock)->txtp,sizeof(struct atm_trafprm)); - memcpy(&addr->sas_rxtp,&ATM_SD(sock)->rxtp,sizeof(struct atm_trafprm)); return 0; } diff -ur --new-file old/linux/net/atm/tunable.h new/linux/net/atm/tunable.h --- old/linux/net/atm/tunable.h Wed Jul 31 19:46:57 1996 +++ new/linux/net/atm/tunable.h Wed Jul 31 19:47:26 1996 @@ -1,6 +1,6 @@ /* net/atm/tunable.h - Tunable parameters of ATM support */ -/* Written 1995 by Werner Almesberger, EPFL LRC */ +/* Written 1995,1996 by Werner Almesberger, EPFL LRC */ #ifndef NET_ATM_TUNABLE_H @@ -13,10 +13,12 @@ drivers, in microseconds */ #endif -#define ATM_RXBQ_DEF 64 /* default RX buffer quota, in kB */ -#define ATM_TXBQ_DEF 64 /* default TX buffer quota, in kB */ -#define ATM_RXBQ_MAX 1024 /* RX buffer quota limit, in kB */ -#define ATM_TXBQ_MAX 1024 /* TX buffer quota limit, in kB */ +#define ATM_RXBQ_DEF ( 64*1024) /* default RX buffer quota, in bytes */ +#define ATM_TXBQ_DEF ( 64*1024) /* default TX buffer quota, in bytes */ +#define ATM_RXBQ_MIN ( 1*1024) /* RX buffer minimum, in bytes */ +#define ATM_TXBQ_MIN ( 1*1024) /* TX buffer minimum, in bytes */ +#define ATM_RXBQ_MAX (1024*1024) /* RX buffer quota limit, in bytes */ +#define ATM_TXBQ_MAX (1024*1024) /* TX buffer quota limit, in bytes */ #define ATM_PDU_OVHD 0 /* number of bytes to charge against buffer quota per PDU */