]> git.neil.brown.name Git - history.git/commitdiff
ISDN: Use a skb queue instead of open coded solution in isdn_ppp.c
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Mon, 30 Sep 2002 09:17:05 +0000 (04:17 -0500)
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>
Mon, 30 Sep 2002 09:17:05 +0000 (04:17 -0500)
Apart from cleaning up and simplifying the code, this also gets rid of
some cli() and stuff, since skb_queue accesses are atomic via an internal
spinlock.

drivers/isdn/i4l/isdn_ppp.c
include/linux/isdn_ppp.h

index 846b11a11d8fe39bcd8b11e4fcf9d006f20363d7..ba642a459ae1bc69eb2832f28de8be69edb73cf3 100644 (file)
@@ -314,8 +314,6 @@ isdn_ppp_open(struct inode *ino, struct file *file)
        is->maxcid = 16;        /* VJ: maxcid */
        is->tk = current;
        init_waitqueue_head(&is->wq);
-       is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
-       is->last = is->rq;
        is->minor = minor;
 #ifdef CONFIG_ISDN_PPP_VJ
        /*
@@ -337,7 +335,6 @@ static int
 isdn_ppp_release(struct inode *ino, struct file *file)
 {
        uint minor = minor(ino->i_rdev) - ISDN_MINOR_PPP;
-       int i;
        struct ippp_struct *is;
 
        lock_kernel();
@@ -356,14 +353,7 @@ isdn_ppp_release(struct inode *ino, struct file *file)
                is->state &= ~IPPP_CONNECT;
                isdn_net_hangup(is->idev);
        }
-       for (i = 0; i < NUM_RCV_BUFFS; i++) {
-               if (is->rq[i].buf) {
-                       kfree(is->rq[i].buf);
-                       is->rq[i].buf = NULL;
-               }
-       }
-       is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
-       is->last = is->rq;
+       skb_queue_purge(&is->rq);
 
 #ifdef CONFIG_ISDN_PPP_VJ
 /* TODO: if this was the previous master: link the slcomp to the new master */
@@ -595,12 +585,9 @@ static unsigned int
 isdn_ppp_poll(struct file *file, poll_table * wait)
 {
        unsigned int mask;
-       struct ippp_buf_queue *bf;
-       struct ippp_buf_queue *bl;
        unsigned long flags;
        struct ippp_struct *is;
 
-       lock_kernel();
        is = file->private_data;
 
        if (is->debug & 0x2)
@@ -622,21 +609,15 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
        /* we're always ready to send .. */
        mask = POLLOUT | POLLWRNORM;
 
-       save_flags(flags);
-       cli();
-       bl = is->last;
-       bf = is->first;
        /*
         * if IPPP_NOBLOCK is set we return even if we have nothing to read
         */
-       if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
+       if (!skb_queue_empty(&is->rq) || is->state & IPPP_NOBLOCK) {
                is->state &= ~IPPP_NOBLOCK;
                mask |= POLLIN | POLLRDNORM;
        }
-       restore_flags(flags);
 
  out:
-       unlock_kernel();
        return mask;
 }
 
@@ -647,10 +628,8 @@ isdn_ppp_poll(struct file *file, poll_table * wait)
 static int
 isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
 {
-       struct ippp_buf_queue *bf,
-       *bl;
-       unsigned long flags;
-       unsigned char *nbuf;
+       struct sk_buff *skb;
+       unsigned char *p;
        struct ippp_struct *is;
 
        if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
@@ -663,36 +642,23 @@ isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
                printk(KERN_DEBUG "ippp: device not activated.\n");
                return 0;
        }
-       nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
-       if (!nbuf) {
-               printk(KERN_WARNING "ippp: Can't alloc buf\n");
+       if (skb_queue_len(&is->rq) > IPPP_MAX_RQ_LEN) {
+               printk(KERN_WARNING "ippp: Queue is full\n");
                return 0;
        }
-       nbuf[0] = PPP_ALLSTATIONS;
-       nbuf[1] = PPP_UI;
-       nbuf[2] = proto >> 8;
-       nbuf[3] = proto & 0xff;
-       memcpy(nbuf + 4, buf, len);
-
-       save_flags(flags);
-       cli();
-
-       bf = is->first;
-       bl = is->last;
-
-       if (bf == bl) {
-               printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
-               bf = bf->next;
-               kfree(bf->buf);
-               is->first = bf;
+       skb = dev_alloc_skb(len + 4);
+       if (!skb) {
+               printk(KERN_WARNING "ippp: Can't alloc buf\n");
+               return 0;
        }
-       bl->buf = (char *) nbuf;
-       bl->len = len + 4;
-
-       is->last = bl->next;
-       restore_flags(flags);
+       p = skb_put(skb, 4);
+       p += put_u8(p, PPP_ALLSTATIONS);
+       p += put_u8(p, PPP_UI);
+       p += put_u16(p, proto);
+       memcpy(skb_put(skb, len), buf, len);
 
-               wake_up_interruptible(&is->wq);
+       skb_queue_tail(&is->rq, skb);
+       wake_up_interruptible(&is->wq);
 
        return len;
 }
@@ -706,54 +672,36 @@ static ssize_t
 isdn_ppp_read(struct file *file, char *buf, size_t count, loff_t *off)
 {
        struct ippp_struct *is;
-       struct ippp_buf_queue *b;
-       unsigned long flags;
-       unsigned char *save_buf;
+       struct sk_buff *skb;
        int retval;
 
        if (off != &file->f_pos)
                return -ESPIPE;
        
-       lock_kernel();
-
        is = file->private_data;
 
        if (!(is->state & IPPP_OPEN)) {
                retval = 0;
                goto out;
        }
-       retval = verify_area(VERIFY_WRITE, (void *) buf, count);
-       if (retval)
-               goto out;
-
-       save_flags(flags);
-       cli();
-
-       b = is->first->next;
-       save_buf = b->buf;
-       if (!save_buf) {
-               restore_flags(flags);
+       skb = skb_dequeue(&is->rq);
+       if (!skb) {
                retval = -EAGAIN;
                goto out;
        }
-       if (b->len < count)
-               count = b->len;
-       b->buf = NULL;
-       is->first = b;
-
-       restore_flags(flags);
-
-       if (copy_to_user(buf, save_buf, count)) {
-               kfree(save_buf);
+       if (skb->len > count) {
+               retval = -EMSGSIZE;
+               goto out_free;
+       }
+       if (copy_to_user(buf, skb->data, skb->len)) {
                retval = -EFAULT;
-               goto out;
+               goto out_free;
        }
-       kfree(save_buf);
-
-       retval = count;
+       retval = skb->len;
 
+ out_free:
+       dev_kfree_skb(skb);
  out:
-       unlock_kernel();
        return retval;
 }
 
@@ -881,15 +829,7 @@ isdn_ppp_init(void)
                }
                memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
                ippp_table[i]->state = 0;
-               ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
-               ippp_table[i]->last = ippp_table[i]->rq;
-
-               for (j = 0; j < NUM_RCV_BUFFS; j++) {
-                       ippp_table[i]->rq[j].buf = NULL;
-                       ippp_table[i]->rq[j].last = ippp_table[i]->rq +
-                           (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
-                       ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
-               }
+               skb_queue_head_init(&ippp_table[i]->rq);
        }
        return 0;
 }
index dcd0ad4aa68bc8f096511af16071ceb4986a30ec..68353a39b98c9c4cf778cb4b7dfbc0ae0097c647 100644 (file)
@@ -159,14 +159,7 @@ typedef struct {
   isdn_mppp_stats stats;
 } ippp_bundle;
 
-#define NUM_RCV_BUFFS     64
-
-struct ippp_buf_queue {
-  struct ippp_buf_queue *next;
-  struct ippp_buf_queue *last;
-  char *buf;                 /* NULL here indicates end of queue */
-  int len;
-};
+#define IPPP_MAX_RQ_LEN     8
 
 /* The data structure for one CCP reset transaction */
 enum ippp_ccp_reset_states {
@@ -201,9 +194,7 @@ struct ippp_ccp_reset {
 struct ippp_struct {
   struct ippp_struct *next_link;
   int state;
-  struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
-  struct ippp_buf_queue *first;  /* pointer to (current) first packet */
-  struct ippp_buf_queue *last;   /* pointer to (current) last used packet in queue */
+  struct sk_buff_head rq;
   wait_queue_head_t wq;
   struct task_struct *tk;
   unsigned int mpppcfg;