Commit 65c9ec4d authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN: Use a skb queue instead of open coded solution in isdn_ppp.c

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