SOURCES: linux-2.6-atmdd.patch (NEW) - ported from linux-2.4.25-at...

baggins baggins at pld-linux.org
Thu Aug 25 19:06:41 CEST 2005


Author: baggins                      Date: Thu Aug 25 17:06:41 2005 GMT
Module: SOURCES                       Tag: HEAD
---- Log message:
- ported from linux-2.4.25-atmdd.patch

---- Files affected:
SOURCES:
   linux-2.6-atmdd.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: SOURCES/linux-2.6-atmdd.patch
diff -u /dev/null SOURCES/linux-2.6-atmdd.patch:1.1
--- /dev/null	Thu Aug 25 19:06:41 2005
+++ SOURCES/linux-2.6-atmdd.patch	Thu Aug 25 19:06:36 2005
@@ -0,0 +1,953 @@
+diff -urN linux-2.4.25/drivers/atm/Makefile linux-2.4.25-atmdd/drivers/atm/Makefile
+--- linux-2.4.25/drivers/atm/Makefile	2004-02-23 15:18:29.000000000 +0100
++++ linux-2.4.25-atmdd/drivers/atm/Makefile	2004-02-29 22:51:26.000000000 +0100
+@@ -31,6 +31,7 @@
+   obj-$(CONFIG_ATM_IDT77252)	+= suni.o
+ endif
+ 
++obj-$(CONFIG_ATM_DD)		+= atmdd.o
+ obj-$(CONFIG_ATM_TCP)		+= atmtcp.o
+ obj-$(CONFIG_ATM_FIRESTREAM)	+= firestream.o
+ obj-$(CONFIG_ATM_LANAI)		+= lanai.o
+diff -urN linux-2.4.25/drivers/atm/Kconfig linux-2.4.25-atmdd/drivers/atm/Kconfig
+--- linux-2.4.25/drivers/atm/Kcnfig	2003-08-25 13:44:41.000000000 +0200
++++ linux-2.4.25-atmdd/drivers/atm/Kconfig	2004-02-29 22:52:59.000000000 +0100
+@@ -4,6 +4,14 @@
+ 
+ menu "ATM drivers"
+ 	depends on NETDEVICES && ATM
++
++config ATM_DD
++	tristate "ATM loopback"
++	depends on INET && ATM
++	help
++	  This is an example atm driver.  It does not require any actual ATM
++	  hardware.  It supports AAL5 and AAL0.  Frames are merely looped back
++	  to the sender on the same VC they were sent.
+ 
+ config ATM_TCP
+ 	tristate "ATM over TCP"
+diff -urN linux-2.4.25/drivers/atm/atmdd.c linux-2.4.25-atmdd/drivers/atm/atmdd.c
+--- linux-2.4.25/drivers/atm/atmdd.c	1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.25-atmdd/drivers/atm/atmdd.c	2004-02-29 22:58:11.000000000 +0100
+@@ -0,0 +1,920 @@
++/*
++#######################################################################
++#
++# (C) Copyright 2001
++# Alex Zeffertt, Cambridge Broadband Ltd, ajz at cambridgebroadband.com
++#
++# This program is free software; you can redistribute it and/or
++# modify it under the terms of the GNU General Public License as
++# published by the Free Software Foundation; either version 2 of
++# the License, or (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++# MA 02111-1307 USA
++#######################################################################
++# Notes:
++# 
++# This is an example atm driver.  It does not require any actual ATM
++# hardware.  It supports AAL5 and AAL0.  frames are merely looped back
++# to the sender on the same VC they were sent.
++# 
++#######################################################################
++*/
++
++/*############ Includes ###############################################*/
++
++#include <linux/module.h>
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/atm.h>
++#include <linux/atmdev.h>
++#include <linux/skbuff.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/sched.h> /* for xtime */
++
++/*############ Defines ################################################*/
++
++#define MYATMDD "atmdd"
++#define KLOG_PREAMBLE MYATMDD ": "
++#define MYATMDD_VPI_BITS 1     /* Allow ?.1.? but not ?.2.? */
++#define MYATMDD_VCI_BITS 11    /* Allow ?.?.2047 but not ?.?.2048 */
++#define MYATMDD_PCR 100000
++#define RXQ_SZ 16
++#define TXQ_SZ 16
++#define AAL5_MTU (1510+8) /* Default AAL5 Maximum Transmission Unit (and length of AAL5 buffers) */
++#define AAL5_BUFLEN (((AAL5_MTU + 47)/48)*48) /* Round up to n*48 bytes */
++#if 0
++# define DEBUG(format,args...) printk(format,##args)
++#else
++# define DEBUG(format,args...)
++#endif
++/*############ Types ##################################################*/
++
++/* status flags shared between s/w and emulated h/w */
++typedef enum {
++    RX_EMPTY, /* No sk_buff present */
++    RX_FULL,  /* sk_buff present and awaiting data */
++    RX_RECVD, /* sk_buff present and contains valid data */
++} myatmdd_rxstatus_e;
++
++/* status flags shared between s/w and emulated h/w */
++typedef enum {
++    TX_EMPTY, /* No sk_buff present */
++    TX_FULL,  /* sk_buff present and awaiting transmission */
++    TX_SENT,  /* sk_buff present and has been sent */
++} myatmdd_txstatus_e;
++
++typedef struct {
++    struct sk_buff **start;
++    struct sk_buff **end;
++    struct sk_buff **head;
++    struct sk_buff **tail;
++
++    /* everything below this line emulates h/w */
++    myatmdd_rxstatus_e *status;
++    struct sk_buff **hw_ptr;
++    int *pkt_len;
++
++} myatmdd_rxq_t;
++
++typedef struct {
++    struct sk_buff **start;
++    struct sk_buff **end;
++    struct sk_buff **head;
++    struct sk_buff **tail;
++
++    /* everything below this line emulates h/w */
++    myatmdd_txstatus_e *status;
++    struct sk_buff **hw_ptr;
++    int *pkt_len;
++
++} myatmdd_txq_t;
++
++typedef struct {
++} myatmdd_devdata_t;
++
++typedef struct {
++    myatmdd_rxq_t rxqueue;
++    myatmdd_txq_t txqueue;
++} myatmdd_vccdata_t;
++
++/*############ Module paramters #######################################*/
++
++MODULE_AUTHOR("Alex Zeffertt, ajz at cambridgebroadband.com");
++MODULE_DESCRIPTION("Example ATM device driver (loopback)");
++#ifdef MODULE_LICENSE
++MODULE_LICENSE("GPL");
++#endif
++/*#################### Forward declarations ###########################*/
++
++static void myatmdd_emulate_loopback_hardware(struct atm_vcc *vcc);
++
++static void myatmdd_free_tx_skb(struct sk_buff *skb);
++
++/* these functions will need modifying in a real ATM driver */
++static void myatmdd_rx_interrupt(struct atm_vcc *vcc);
++static void myatmdd_tx_interrupt(struct atm_vcc *vcc);
++
++/* functions for manipulating circular bufs */
++static int myatmdd_init_rxq(myatmdd_rxq_t *queue, int size);
++static int myatmdd_init_txq(myatmdd_txq_t *queue, int size);
++static int myatmdd_release_rxq(myatmdd_rxq_t *queue);
++static int myatmdd_release_txq(myatmdd_txq_t *queue);
++static int myatmdd_txq_enqueue(myatmdd_txq_t *queue, struct sk_buff *skb);
++static int myatmdd_rxq_enqueue(myatmdd_rxq_t *queue, struct sk_buff *skb /* empty buffer */);
++static struct sk_buff *myatmdd_txq_dequeue(myatmdd_txq_t *queue);
++static struct sk_buff *myatmdd_rxq_dequeue(myatmdd_rxq_t *queue, int *pkt_len);
++
++/* myatmdd_ops registered by ATM device */
++static int myatmdd_open(struct atm_vcc *vcc);
++static void myatmdd_close(struct atm_vcc *vcc);
++static int myatmdd_ioctl(struct atm_dev *dev, unsigned int cmd,void *arg);
++static int myatmdd_setsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen);
++static int myatmdd_getsockopt(struct atm_vcc *vcc,int level,int optname, void *optval,int optlen);
++static int myatmdd_send(struct atm_vcc *vcc,struct sk_buff *skb);
++static int myatmdd_change_qos(struct atm_vcc *vcc,struct atm_qos *qos,int flgs);
++static int myatmdd_proc_read(struct atm_dev *dev,loff_t *pos,char *page);
++
++/* myatmdd_phy_ops registered by phy driver */
++static void myatmdd_phy_int(struct atm_dev *dev);
++static int myatmdd_phy_start(struct atm_dev *dev); /* <-- This is the only thing exported by PHY driver */
++static int myatmdd_phy_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg);
++
++/*#################### Global scope variables #########################*/
++
++/* operations registered by the atm device */
++static const struct atmdev_ops myatmdd_ops =
++{
++	open:        myatmdd_open,
++	close:       myatmdd_close,
++	ioctl:       myatmdd_ioctl,
++	getsockopt:  myatmdd_getsockopt,
++	setsockopt:  myatmdd_setsockopt,
++	send:        myatmdd_send,
++	change_qos:  myatmdd_change_qos,
++	proc_read:   myatmdd_proc_read,
++    owner:       THIS_MODULE,
++};
++
++/* operations registered by the phy driver */
++static const struct atmphy_ops myatmdd_phy_ops = {
++	start:      myatmdd_phy_start,
++	ioctl:      myatmdd_phy_ioctl,
++	interrupt:  myatmdd_phy_int,
++};
++
++struct atm_dev *myatmdd_dev;
++
++/*#################### Function definitions ###########################*/
++
++
++/*
++#########################################################
++#
++#  Function : myatmdd_rx_interrupt, and myatmdd_tx_interrupt
++#             
++#  Purpose  : handle interrupt from hardware.  In first 
++#             case this means extract recvd buffers and pass
++#             it up protocol stack.  In 2nd case this means
++#             free the sent buffers.
++#             
++#  Args     : pointer to private data of the VCC concerned
++#             
++#  Returns  : nowt
++#             
++#  Notes    : 
++#             
++##########################################################
++#  Edit history:
++#  Who     When    What
++#  AJZ     10Apr03 Created
++##########################################################
++*/
++
++static void myatmdd_rx_interrupt(struct atm_vcc *vcc)
++{
++    struct sk_buff *skb;
++    myatmdd_vccdata_t *priv = vcc->dev_data;
++    int pkt_len;
++
++    DEBUG("%s\n", __FUNCTION__);
++
++    while ((skb = myatmdd_rxq_dequeue(&priv->rxqueue, &pkt_len)))
++    {
++        struct sk_buff *newskb;
++
++        /* Get a new skb to replace the one just consumed */
++        if (!(newskb = dev_alloc_skb(AAL5_BUFLEN)))
++        {
++            atomic_inc(&vcc->stats->rx_err);
++            printk(KERN_ERR KLOG_PREAMBLE "cannot receive packet - out of memory\n");
++            /* put skb back in rx queue) */
++            myatmdd_rxq_enqueue(&priv->rxqueue, skb);
++            return;
++        }
++        myatmdd_rxq_enqueue(&priv->rxqueue, newskb);
++
++        if (!atm_charge (vcc, skb->truesize))
++        {
++            /* Exceeded memory quota for this vcc
++             * NOTE: if atm_charge succeeds you must then push or accounting will screw up
++             */
++            dev_kfree_skb(skb);
++            /* &vcc->stats->drop stats incremented in atm_charge */
++        }
++        else
++        {
++            /* sk_buff passed all sanity checks! */
++            
++            /* Add received length to socket buffer */
++            skb_put(skb, pkt_len);
++        
++            /* update device stats */
++            atomic_inc(&vcc->stats->rx);
++
++            /* add timestamp for upper layers to use */
++	    do_gettimeofday(&skb->stamp);
++        
++            /* Point socket buffer at the right VCC before giving to socket layer */
++            ATM_SKB(skb)->vcc = vcc;
++        
++            /* push socket buffer up to ATM layer */
++            vcc->push(vcc, skb);
++        }
++    }
++}
++
++static void myatmdd_tx_interrupt(struct atm_vcc *vcc)
++{
++    struct sk_buff *skb;
++    myatmdd_vccdata_t *priv = vcc->dev_data;
++
++    DEBUG("%s\n", __FUNCTION__);
++
++    while ((skb = myatmdd_txq_dequeue(&priv->txqueue)))
++    {
++        // Update channel stats and free the memory
++        atomic_inc(&vcc->stats->tx);
++        myatmdd_free_tx_skb(skb);
++    }
++}
++
++/*
++#########################################################
++#
++#  Function : myatmdd_emulate_loopback_hardware
++#             
++#  Purpose  : emulate things normally done by hardware
++#             i.e. copying tx bufs to rx bufs (we're modelling
++#             a loopback system here), calling the tx done
++#             interrupt, and calling the rx done interrupt.
++#
++#  Args     : priv = data private to VCC
++#             
++#  Returns  : nowt
++#             
++#  Notes    : 
++#             
++##########################################################
++#  Edit history:
++#  Who     When    What
++#  AJZ     10Apr03 Created
++##########################################################
++*/
++static void myatmdd_emulate_loopback_hardware(struct atm_vcc *vcc)
++{
++    myatmdd_vccdata_t *priv = vcc->dev_data;
++    struct sk_buff **ptxskb;
++    struct sk_buff **prxskb;
++
++    DEBUG("%s\n", __FUNCTION__);
++
++    ptxskb = priv->txqueue.hw_ptr;
++    prxskb = priv->rxqueue.hw_ptr;
++
++    /* Send each tx buff waiting to go */
++    while (priv->txqueue.status[ptxskb - priv->txqueue.start] == TX_FULL)
++    {
++        struct sk_buff *txskb = *ptxskb;
++        struct sk_buff *rxskb = *prxskb;
++        int pkt_len = priv->txqueue.pkt_len[ptxskb - priv->txqueue.start];
++        
++        /* Is there an rx buffer? */
++        if (priv->rxqueue.status[prxskb - priv->rxqueue.start] == RX_FULL)
++        {
++            /* Yes - Is the length in range? */
++            if (pkt_len <= AAL5_BUFLEN)
++            {
++                /* Yes - do the copy */
++                memcpy(rxskb->data, txskb->data,pkt_len);
++                priv->rxqueue.pkt_len[prxskb - priv->rxqueue.start] = pkt_len;
++                
++                /* Indicate rx buffer recvd */
++                priv->rxqueue.status[prxskb - priv->rxqueue.start] = RX_RECVD;
++                
++                /* increment and maybe wrap rx pointer */
++                if (++prxskb == priv->rxqueue.end)
++                    prxskb = priv->rxqueue.start;
++                priv->rxqueue.hw_ptr = prxskb;
++            }
++            else
++            {
++                /* No - then h/w cannot do a recv */
++                printk(KERN_ERR KLOG_PREAMBLE "recvd frame too long - discarded\n");
++            }
++        }
++        else
++        {
++            /* No - then h/w cannot do a recv */
++            printk(KERN_ERR KLOG_PREAMBLE "no rx buffers available\n");
++        }
++        
++        /* Indicate tx buffer sent */
++        priv->txqueue.status[ptxskb - priv->txqueue.start] = TX_SENT;
++
++        /* increment and maybe wrap tx pointer */
++        if (++ptxskb == priv->txqueue.end)
++            ptxskb = priv->txqueue.start;
++        priv->txqueue.hw_ptr = ptxskb;
++        
++        /* Call tx ring interrupt handler */
++        myatmdd_tx_interrupt(vcc);
++           
++        /* Call tx ring interrupt handler */
++        myatmdd_rx_interrupt(vcc);
++    }
++}
++
++/*
++#########################################################
++#
++#  Function : functions for manipulating circular buffs
++#             
++#  Purpose  : 
++#             
++#  Args     : 
++#             
++#  Returns  : 
++#             
++#  Notes    : 
++#             
++##########################################################
++#  Edit history:
++#  Who     When    What
++#  AJZ     10Apr03 Created
++##########################################################
++*/
++
++static int myatmdd_init_rxq(myatmdd_rxq_t *queue, int size)
++{
++    /* TODO - cope with kmalloc failure */
++    struct sk_buff **pskb;
++    int i;
++
++    DEBUG("%s\n", __FUNCTION__);
++    queue->hw_ptr = queue->head = queue->tail = 
++        queue->start = kmalloc(size * sizeof(struct sk_buff *), GFP_KERNEL);
++    queue->end = &queue->start[size];
++    for (pskb = queue->start; pskb < queue->end; pskb++)
++        *pskb = NULL;
++
++    queue->status = kmalloc(size * sizeof(myatmdd_rxstatus_e),GFP_KERNEL);
++    for (i = 0; i < size; i++)
++        queue->status[i] = RX_EMPTY;
++
++    queue->pkt_len = kmalloc(size * sizeof(int),GFP_KERNEL);
++    for (i = 0; i < size; i++)
++        queue->pkt_len[i] = 0;
++
++    return 0;
++}
++
++static int myatmdd_init_txq(myatmdd_txq_t *queue, int size)
++{
++    /* TODO - cope with kmalloc failure */
++    struct sk_buff **pskb;
++    int i;
++
++    DEBUG("%s\n", __FUNCTION__);
++    queue->hw_ptr = queue->head = queue->tail = 
++        queue->start = kmalloc(size * sizeof(struct sk_buff *), GFP_KERNEL);
++    queue->end = &queue->start[size];
++    for (pskb = queue->start; pskb < queue->end; pskb++)
++        *pskb = NULL;
++
++    queue->status = kmalloc(size * sizeof(myatmdd_rxstatus_e),GFP_KERNEL);
++    for (i = 0; i < size; i++)
++        queue->status[i] = TX_EMPTY;
++
++    queue->pkt_len = kmalloc(size * sizeof(int),GFP_KERNEL);
++    for (i = 0; i < size; i++)
++        queue->pkt_len[i] = 0;
++
++    return 0;
++}
++
++static int myatmdd_release_rxq(myatmdd_rxq_t *queue)
++{
++    struct sk_buff **pskb;
++
++    DEBUG("%s\n", __FUNCTION__);
++    for (pskb = queue->start; pskb < queue->end; pskb++)
++    {
++        /* Is there an skb here */
++        if (*pskb == NULL)
++            continue;   /* No, so skip this entry in ring */
++
++        /* Yes - free it */
++        dev_kfree_skb(*pskb);
++    }
++    kfree(queue->start);
++    kfree(queue->status);
++    kfree(queue->pkt_len);
++
++    return 0;
++}
++
++static int myatmdd_release_txq(myatmdd_txq_t *queue)
++{
++    struct sk_buff **pskb;
++
++    DEBUG("%s\n", __FUNCTION__);
++    /* Scan through all TX bd's and cleanup */
++    for (pskb = queue->start; pskb < queue->end; pskb++)
++    {  
++        /* Is this buffer currently unused - i.e. no skb */
++        if (*pskb == NULL)
++            continue;             /* Yes, so ignore it */
++
++        /* If we reach here, we have found a socket buffer that
++         * exists in the TX ring and is waiting to be released.
++         */
++        printk(KERN_WARNING KLOG_PREAMBLE "discarding unsent tx sk_buff\n");
++        atomic_inc(&ATM_SKB(*pskb)->vcc->stats->tx_err);
++        myatmdd_free_tx_skb(*pskb);
++    }
++    kfree(queue->start);
++    kfree(queue->status);
++    kfree(queue->pkt_len);
++
++    return 0;
++}
++
++/* returns non-zero for "out of space" */
++static int myatmdd_txq_enqueue(myatmdd_txq_t *queue, struct sk_buff *skb)
++{
++    /* increment head and wrap */
++    struct sk_buff **newhead = queue->head + 1;
++    if (newhead == queue->end)
++        newhead = queue->start;
++
++    DEBUG("%s\n", __FUNCTION__);
++
++    /* abort if tx ring full */
++    if (newhead == queue->tail)
++        return -1;
++    
++    /* all is okay if we're here */
++    *queue->head = skb;
++    /* Tell hardware there's a buffer to send */
++    queue->status[queue->head - queue->start] = TX_FULL;
++    queue->pkt_len[queue->head - queue->start] = skb->len;
++    queue->head = newhead;
++    return 0;
++}
++
++/* returns non-zero for "out of space" */
++static int myatmdd_rxq_enqueue(myatmdd_rxq_t *queue, struct sk_buff *skb /* empty buffer */)
++{
++    /* increment head and wrap */
++    struct sk_buff **newhead = queue->head + 1;
++    if (newhead == queue->end)
++        newhead = queue->start;
++
++    DEBUG("%s\n", __FUNCTION__);
++
++    /* abort if rx ring full */
++    if (newhead == queue->tail)
++        return -1;
++    
++    /* all is okay if we're here */
++    *queue->head = skb;
++    /* Tell hardware there's a buffer to send */
++    queue->status[queue->head - queue->start] = RX_FULL;
++    queue->head = newhead;
++    return 0;
++}
++
++static struct sk_buff *myatmdd_txq_dequeue(myatmdd_txq_t *queue)
++{
++    DEBUG("%s\n", __FUNCTION__);
++    if (queue->tail != queue->head && queue->status[queue->tail - queue->start] == TX_SENT)
++    {
++        struct sk_buff *skb = *queue->tail;
++
++        /* increment tail and wrap */
++        struct sk_buff **newtail = queue->tail + 1;
++        if (newtail == queue->end)
++            newtail = queue->start;
++        *queue->tail = NULL;
++        queue->status[queue->tail - queue->start] = TX_EMPTY;
++        queue->tail = newtail;
++        return skb;
++    }
++    return NULL;
++}
++
++/* returns NULL for "no new recvd frames" */
++static struct sk_buff *myatmdd_rxq_dequeue(myatmdd_rxq_t *queue, int *pkt_len)
++{
++    DEBUG("%s\n", __FUNCTION__);
++    if (queue->tail != queue->head && queue->status[queue->tail - queue->start] == RX_RECVD)
++    {
++        struct sk_buff *skb = *queue->tail;
++
++        /* increment tail and wrap */
++        struct sk_buff **newtail = queue->tail + 1;
++        if (newtail == queue->end)
++            newtail = queue->start;
++        *queue->tail = NULL;
++        queue->status[queue->tail - queue->start] = RX_EMPTY;
++        *pkt_len = queue->pkt_len[queue->tail - queue->start];
++        queue->tail = newtail;
++        return skb;
++    }
++    return NULL;
++}
++
++/*
++#########################################################
<<Diff was trimmed, longer than 597 lines>>



More information about the pld-cvs-commit mailing list