summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-10-29 08:49:56 -0600
committerKai Germaschewski <kai@tp1.ruhr-uni-bochum.de>2002-10-29 08:49:56 -0600
commit620a00187ea32b497e5cf46aa73949b5ad7a4fbf (patch)
tree8c030213c36e5583f96043ab2a53989e912af72e
parent772059d9ff21963bbc890b94f735f2d93d067173 (diff)
ISDN: Move the tty receive queue out of generic code
Moving the tty receive queue into the tty-specific data in fact simplifies the common code (which doesn't need to know it at all, now), and the tty code, which can access the queue more directly.
-rw-r--r--drivers/isdn/i4l/isdn_audio.c5
-rw-r--r--drivers/isdn/i4l/isdn_common.c182
-rw-r--r--drivers/isdn/i4l/isdn_common.h3
-rw-r--r--drivers/isdn/i4l/isdn_tty.c110
-rw-r--r--drivers/isdn/i4l/isdn_tty.h7
-rw-r--r--include/linux/isdn.h3
6 files changed, 119 insertions, 191 deletions
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
index 4a4bfcd68f6b..fddfa960b0bb 100644
--- a/drivers/isdn/i4l/isdn_audio.c
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -14,6 +14,7 @@
#include <linux/isdn.h>
#include "isdn_audio.h"
#include "isdn_common.h"
+#include "isdn_tty.h"
/*
* Misc. lookup-tables.
@@ -564,7 +565,7 @@ isdn_audio_eval_dtmf(modem_info * info)
cli();
di = isdn_slot_driver(info->isdn_slot);
ch = isdn_slot_channel(info->isdn_slot);
- isdn_slot_queue_tail(info->isdn_slot, skb, 2);
+ isdn_tty_queue_tail(info, skb, 2);
restore_flags(flags);
/* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched))
@@ -683,7 +684,7 @@ isdn_audio_put_dle_code(modem_info * info, u_char code)
cli();
di = isdn_slot_driver(info->isdn_slot);
ch = isdn_slot_channel(info->isdn_slot);
- isdn_slot_queue_tail(info->isdn_slot, skb, 2);
+ isdn_tty_queue_tail(info, skb, 2);
restore_flags(flags);
/* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched))
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 3383f1f341b2..8c58b98c3438 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -299,13 +299,8 @@ slot_data_req(struct fsm_inst *fi, int pr, void *arg)
{
struct isdn_slot *slot = fi->userdata;
struct sk_buff *skb = arg;
- int retval;
- /* Update statistics */
-// slots[sl].ibytes += skb->len;
-
- retval = isdn_drv_writebuf_skb(slot->di, slot->ch, 1, skb);
- return retval;
+ return isdn_drv_writebuf_skb(slot->di, slot->ch, 1, skb);
}
static int
@@ -401,7 +396,6 @@ slot_unbind(struct fsm_inst *fi, int pr, void *arg)
slot->iv110.v110 = NULL;
// 20.10.99 JIM, try to reinitialize v110 !
isdn_slot_set_usage(sl, ISDN_USAGE_NONE);
- isdn_slot_queue_purge(sl);
return 0;
}
@@ -497,12 +491,6 @@ struct isdn_driver {
int maxbufsize; /* Maximum Buffersize supported*/
int stavail; /* Chars avail on Status-device*/
isdn_if *interface; /* Interface to driver */
- int *rcverr; /* Error-counters for B rx */
- int *rcvcount; /* Byte-counters for B rx */
- struct sk_buff_head *rpqueue;
-#ifdef CONFIG_ISDN_AUDIO
- unsigned long DLEflag; /* Insert DLE at next read */
-#endif
char msn2eaz[10][ISDN_MSNLEN]; /* MSN->EAZ */
struct fsm_inst fi;
} driver;
@@ -578,13 +566,6 @@ isdn_drv_lookup(char *drvid)
static void
drv_destroy(struct isdn_driver *drv)
{
- int i;
-
- kfree(drv->rcverr);
- kfree(drv->rcvcount);
- for (i = 0; i < drv->channels; i++)
- skb_queue_purge(&drv->rpqueue[i]);
- kfree(drv->rpqueue);
kfree(drv);
}
@@ -1446,108 +1427,6 @@ isdn_getnum(char **p)
#define DLE 0x10
-/*
- * isdn_slot_readbchan() tries to get data from the read-queue.
- * It MUST be called with interrupts off.
- */
-int
-isdn_slot_readbchan(int sl, u_char * buf, u_char * fp, int len)
-{
- int count;
- int count_pull;
- int count_put;
- int dflag;
- int di = isdn_slot_driver(sl);
- int ch = isdn_slot_channel(sl);
- struct sk_buff *skb;
- u_char *cp;
-
- if (!drivers[di])
- return 0;
- if (skb_queue_empty(&drivers[di]->rpqueue[ch]))
- return 0;
-
- if (len > drivers[di]->rcvcount[ch])
- len = drivers[di]->rcvcount[ch];
- cp = buf;
- count = 0;
- while (len) {
- if (!(skb = skb_peek(&drivers[di]->rpqueue[ch])))
- break;
-#ifdef CONFIG_ISDN_AUDIO
- if (ISDN_AUDIO_SKB_LOCK(skb))
- break;
- ISDN_AUDIO_SKB_LOCK(skb) = 1;
- if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (drivers[di]->DLEflag & (1 << ch))) {
- char *p = skb->data;
- unsigned long DLEmask = (1 << ch);
-
- dflag = 0;
- count_pull = count_put = 0;
- while ((count_pull < skb->len) && (len > 0)) {
- len--;
- if (drivers[di]->DLEflag & DLEmask) {
- *cp++ = DLE;
- drivers[di]->DLEflag &= ~DLEmask;
- } else {
- *cp++ = *p;
- if (*p == DLE) {
- drivers[di]->DLEflag |= DLEmask;
- (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
- }
- p++;
- count_pull++;
- }
- count_put++;
- }
- if (count_pull >= skb->len)
- dflag = 1;
- } else {
-#endif
- /* No DLE's in buff, so simply copy it */
- dflag = 1;
- if ((count_pull = skb->len) > len) {
- count_pull = len;
- dflag = 0;
- }
- count_put = count_pull;
- memcpy(cp, skb->data, count_put);
- cp += count_put;
- len -= count_put;
-#ifdef CONFIG_ISDN_AUDIO
- }
-#endif
- count += count_put;
- if (fp) {
- memset(fp, 0, count_put);
- fp += count_put;
- }
- if (dflag) {
- /* We got all the data in this buff.
- * Now we can dequeue it.
- */
- if (fp)
- *(fp - 1) = 0xff;
-#ifdef CONFIG_ISDN_AUDIO
- ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
- skb = skb_dequeue(&drivers[di]->rpqueue[ch]);
- dev_kfree_skb(skb);
- } else {
- /* Not yet emptied this buff, so it
- * must stay in the queue, for further calls
- * but we pull off the data we got until now.
- */
- skb_pull(skb, count_pull);
-#ifdef CONFIG_ISDN_AUDIO
- ISDN_AUDIO_SKB_LOCK(skb) = 0;
-#endif
- }
- drivers[di]->rcvcount[ch] -= count_put;
- }
- return count;
-}
-
static __inline int
isdn_minor2drv(int minor)
{
@@ -2380,40 +2259,6 @@ isdn_add_channels(struct isdn_driver *d, int drvidx, int n, int adding)
ISDN_MAX_CHANNELS);
return -1;
}
- if ((adding) && (d->rcverr))
- kfree(d->rcverr);
- if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
- printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
- return -1;
- }
- memset((char *) d->rcverr, 0, sizeof(int) * m);
-
- if ((adding) && (d->rcvcount))
- kfree(d->rcvcount);
- if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
- printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
- if (!adding) kfree(d->rcverr);
- return -1;
- }
- memset((char *) d->rcvcount, 0, sizeof(int) * m);
-
- if ((adding) && (d->rpqueue)) {
- for (j = 0; j < d->channels; j++)
- skb_queue_purge(&d->rpqueue[j]);
- kfree(d->rpqueue);
- }
- if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
- printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
- if (!adding) {
- kfree(d->rcvcount);
- kfree(d->rcverr);
- }
- return -1;
- }
- for (j = 0; j < m; j++) {
- skb_queue_head_init(&d->rpqueue[j]);
- }
-
dev->channels += n;
save_flags(flags);
cli();
@@ -2690,31 +2535,6 @@ isdn_slot_priv(int sl)
}
int
-isdn_slot_queue_empty(int sl)
-{
- BUG_ON(sl < 0);
-
- return skb_queue_empty(&drivers[slots[sl].di]->rpqueue[slots[sl].ch]);
-}
-
-void
-isdn_slot_queue_tail(int sl, struct sk_buff *skb, int len)
-{
- BUG_ON(sl < 0);
-
- __skb_queue_tail(&drivers[slots[sl].di]->rpqueue[slots[sl].ch], skb);
- drivers[slots[sl].di]->rcvcount[slots[sl].ch] += len;
-}
-
-void
-isdn_slot_queue_purge(int sl)
-{
- BUG_ON(sl < 0);
-
- skb_queue_purge(&drivers[slots[sl].di]->rpqueue[slots[sl].ch]);
-}
-
-int
isdn_hard_header_len(void)
{
int drvidx;
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index f06ccab719f2..edcf4f00d8e2 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -99,9 +99,6 @@ extern void isdn_slot_set_priv(int sl, int usage, void *priv, int (*stat_cb)(in
extern void *isdn_slot_priv(int sl);
extern int isdn_hard_header_len(void);
-int isdn_slot_queue_empty(int sl);
-void isdn_slot_queue_tail(int sl, struct sk_buff *skb, int len);
-void isdn_slot_queue_purge(int sl);
int isdn_drv_maxbufsize(int di);
int isdn_drv_writebuf_skb(int di, int ch, int x, struct sk_buff *skb);
int isdn_drv_hdrlen(int di);
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index a4c7d393e58a..3a688ba73c07 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -110,6 +110,103 @@ isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
return 0;
}
+/*
+ * isdn_slot_readbchan() tries to get data from the read-queue.
+ * It MUST be called with interrupts off.
+ */
+static int
+isdn_tty_readbchan(struct modem_info *info, u_char * buf, u_char * fp, int len)
+{
+ int count;
+ int count_pull;
+ int count_put;
+ int dflag;
+ struct sk_buff *skb;
+ u_char *cp;
+
+ if (skb_queue_empty(&info->rpqueue))
+ return 0;
+
+ if (len > info->rcvcount)
+ len = info->rcvcount;
+ cp = buf;
+ count = 0;
+ while (len) {
+ if (!(skb = skb_peek(&info->rpqueue)))
+ break;
+#ifdef CONFIG_ISDN_AUDIO
+ if (ISDN_AUDIO_SKB_LOCK(skb))
+ break;
+ ISDN_AUDIO_SKB_LOCK(skb) = 1;
+ if (ISDN_AUDIO_SKB_DLECOUNT(skb) || info->DLEflag) {
+ char *p = skb->data;
+
+ dflag = 0;
+ count_pull = count_put = 0;
+ while ((count_pull < skb->len) && (len > 0)) {
+ len--;
+ if (info->DLEflag) {
+ *cp++ = DLE;
+ info->DLEflag = 0;
+ } else {
+ *cp++ = *p;
+ if (*p == DLE) {
+ info->DLEflag = 1;
+ (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
+ }
+ p++;
+ count_pull++;
+ }
+ count_put++;
+ }
+ if (count_pull >= skb->len)
+ dflag = 1;
+ } else {
+#endif
+ /* No DLE's in buff, so simply copy it */
+ dflag = 1;
+ if ((count_pull = skb->len) > len) {
+ count_pull = len;
+ dflag = 0;
+ }
+ count_put = count_pull;
+ memcpy(cp, skb->data, count_put);
+ cp += count_put;
+ len -= count_put;
+#ifdef CONFIG_ISDN_AUDIO
+ }
+#endif
+ count += count_put;
+ if (fp) {
+ memset(fp, 0, count_put);
+ fp += count_put;
+ }
+ if (dflag) {
+ /* We got all the data in this buff.
+ * Now we can dequeue it.
+ */
+ if (fp)
+ *(fp - 1) = 0xff;
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ skb = skb_dequeue(&info->rpqueue);
+ dev_kfree_skb(skb);
+ } else {
+ /* Not yet emptied this buff, so it
+ * must stay in the queue, for further calls
+ * but we pull off the data we got until now.
+ */
+ skb_pull(skb, count_pull);
+#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_LOCK(skb) = 0;
+#endif
+ }
+ info->rcvcount -= count_put;
+ }
+ return count;
+}
+
/* isdn_tty_readmodem() is called periodically from within timer-interrupt.
* It tries getting received data from the receive queue an stuff it into
* the tty's flip-buffer.
@@ -142,7 +239,7 @@ isdn_tty_readmodem(void)
if (c > 0) {
save_flags(flags);
cli();
- r = isdn_slot_readbchan(info->isdn_slot,
+ r = isdn_tty_readbchan(info,
tty->flip.char_buf_ptr,
tty->flip.flag_buf_ptr, c);
/* CISCO AsyncPPP Hack */
@@ -263,7 +360,7 @@ isdn_tty_rcv_skb(int i, struct sk_buff *skb)
/* Try to deliver directly via tty-flip-buf if queue is empty */
save_flags(flags);
cli();
- if (isdn_slot_queue_empty(i))
+ if (skb_queue_empty(&info->rpqueue))
if (isdn_tty_try_read(info, skb)) {
restore_flags(flags);
return 1;
@@ -271,7 +368,7 @@ isdn_tty_rcv_skb(int i, struct sk_buff *skb)
/* Direct deliver failed or queue wasn't empty.
* Queue up for later dequeueing via timer-irq.
*/
- isdn_slot_queue_tail(i, skb, skb->len
+ isdn_tty_queue_tail(info, skb, skb->len
#ifdef CONFIG_ISDN_AUDIO
+ ISDN_AUDIO_SKB_DLECOUNT(skb)
#endif
@@ -739,6 +836,7 @@ isdn_tty_modem_hup(modem_info * info, int local)
isdn_slot_all_eaz(slot);
info->emu.mdmreg[REG_RINGCNT] = 0;
+ skb_queue_purge(&info->rpqueue);
isdn_slot_free(slot);
isdn_slot_set_priv(slot, 0, NULL, NULL, NULL);
info->isdn_slot = -1;
@@ -2025,6 +2123,7 @@ isdn_tty_init(void)
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
info->isdn_slot = -1;
+ skb_queue_head_init(&info->rpqueue);
info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
skb_queue_head_init(&info->xmit_queue);
#ifdef CONFIG_ISDN_AUDIO
@@ -2067,6 +2166,7 @@ isdn_tty_exit(void)
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
info = &isdn_mdm.info[i];
isdn_tty_cleanup_xmit(info);
+ skb_queue_purge(&info->rpqueue);
#ifdef CONFIG_ISDN_TTY_FAX
kfree(info->fax);
#endif
@@ -2430,7 +2530,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
di = -1; ch = -1;
}
if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
- (!isdn_slot_queue_empty(info->isdn_slot)))) {
+ (!skb_queue_empty(&info->rpqueue)))) {
skb = alloc_skb(strlen(msg)
#ifdef CONFIG_ISDN_AUDIO
+ sizeof(isdn_audio_skb)
@@ -2473,7 +2573,7 @@ isdn_tty_at_cout(char *msg, modem_info * info)
}
}
if (skb) {
- isdn_slot_queue_tail(info->isdn_slot, skb, skb->len);
+ isdn_tty_queue_tail(info, skb, skb->len);
restore_flags(flags);
/* Schedule dequeuing */
if ((dev->modempoll) && (info->rcvsched))
diff --git a/drivers/isdn/i4l/isdn_tty.h b/drivers/isdn/i4l/isdn_tty.h
index 48194fd4c619..96c14d1765e0 100644
--- a/drivers/isdn/i4l/isdn_tty.h
+++ b/drivers/isdn/i4l/isdn_tty.h
@@ -129,3 +129,10 @@ struct isdn_modem {
};
extern struct isdn_modem isdn_mdm;
+
+static inline void
+isdn_tty_queue_tail(modem_info *info, struct sk_buff *skb, int len)
+{
+ __skb_queue_tail(&info->rpqueue, skb);
+ info->rcvcount += len;
+}
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
index 74376a0a5e38..4ab5ac856cc9 100644
--- a/include/linux/isdn.h
+++ b/include/linux/isdn.h
@@ -328,6 +328,8 @@ typedef struct modem_info {
int dialing; /* Dial in progress or ATA */
int rcvsched; /* Receive needs schedule */
int isdn_slot; /* Index to isdn-driver/channel */
+ struct sk_buff_head rpqueue; /* Queue of recv'd packets */
+ int rcvcount; /* Byte-counters for B rx */
int ncarrier; /* Flag: schedule NO CARRIER */
unsigned char last_cause[8]; /* Last cause message */
unsigned char last_num[ISDN_MSNLEN];
@@ -344,6 +346,7 @@ typedef struct modem_info {
struct sk_buff_head xmit_queue; /* transmit queue */
atomic_t xmit_lock; /* Semaphore for isdn_tty_write */
#ifdef CONFIG_ISDN_AUDIO
+ unsigned long DLEflag; /* Insert DLE at next read */
int vonline; /* Voice-channel status */
/* Bit 0 = recording */
/* Bit 1 = playback */