summaryrefslogtreecommitdiffstats
path: root/drivers/isdn
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn')
-rw-r--r--drivers/isdn/Config.in2
-rw-r--r--drivers/isdn/avmb1/b1lli.c6
-rw-r--r--drivers/isdn/hisax/callc.c9
-rw-r--r--drivers/isdn/hisax/config.c2
-rw-r--r--drivers/isdn/icn/icn.h4
-rw-r--r--drivers/isdn/isdn_common.c208
-rw-r--r--drivers/isdn/isdn_common.h6
-rw-r--r--drivers/isdn/isdn_net.c42
-rw-r--r--drivers/isdn/isdn_ppp.c25
-rw-r--r--drivers/isdn/isdn_x25iface.c2
10 files changed, 193 insertions, 113 deletions
diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in
index 3787c735f..08e3b78b8 100644
--- a/drivers/isdn/Config.in
+++ b/drivers/isdn/Config.in
@@ -38,7 +38,9 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool 'HiSax Support for NETjet card' CONFIG_HISAX_NETJET
bool 'HiSax Support for Niccy PnP/PCI card' CONFIG_HISAX_NICCY
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
bool 'HiSax Support for Am7930' CONFIG_HISAX_AMD7930
+ fi
fi
fi
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
diff --git a/drivers/isdn/avmb1/b1lli.c b/drivers/isdn/avmb1/b1lli.c
index 1c4c0b806..db6fe1453 100644
--- a/drivers/isdn/avmb1/b1lli.c
+++ b/drivers/isdn/avmb1/b1lli.c
@@ -173,7 +173,7 @@ static inline int B1_rx_full(unsigned short base)
static inline unsigned char B1_get_byte(unsigned short base)
{
unsigned long i = jiffies + 5 * HZ; /* maximum wait time 5 sec */
- while (!B1_rx_full(base) && i > jiffies);
+ while (!B1_rx_full(base) && time_before(jiffies, i));
if (B1_rx_full(base))
return inb(base + B1_READ);
printk(KERN_CRIT "b1lli: rx not full after 5 second\n");
@@ -477,7 +477,7 @@ int B1_loaded(unsigned short base)
if (loaddebug)
printk(KERN_DEBUG "b1capi: loaded: wait 1 ..\n");
- for (i = jiffies + 10 * HZ; i > jiffies;) {
+ for (i = jiffies + 10 * HZ; time_before(jiffies, i);) {
if (B1_tx_empty(base))
break;
}
@@ -487,7 +487,7 @@ int B1_loaded(unsigned short base)
}
B1_put_byte(base, SEND_POLL);
printk(KERN_DEBUG "b1capi: loaded: wait 2 ..\n");
- for (i = jiffies + 10 * HZ; i > jiffies;) {
+ for (i = jiffies + 10 * HZ; time_before(jiffies, i);) {
if (B1_rx_full(base)) {
if ((ans = B1_get_byte(base)) == RECEIVE_POLL) {
if (loaddebug)
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 6924e3f9e..bcd305058 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -62,7 +62,7 @@
#include "hisax.h"
#ifdef MODULE
-#define MOD_USE_COUNT ((&__this_module)->usecount)
+#define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
#endif /* MODULE */
const char *lli_revision = "$Revision: 2.13 $";
@@ -2055,7 +2055,7 @@ HiSax_command(isdn_ctrl * ic)
if (csta->channel[0].debug & 0x400) {
jiftime(tmp, jiffies);
i = strlen(tmp);
- sprintf(tmp + i, " LOCK modcnt %lx\n", MOD_USE_COUNT);
+ sprintf(tmp + i, " LOCK modcnt %d\n", MOD_USE_COUNT);
HiSax_putstatus(csta, tmp);
}
#endif /* MODULE */
@@ -2066,7 +2066,7 @@ HiSax_command(isdn_ctrl * ic)
if (csta->channel[0].debug & 0x400) {
jiftime(tmp, jiffies);
i = strlen(tmp);
- sprintf(tmp + i, " UNLOCK modcnt %lx\n", MOD_USE_COUNT);
+ sprintf(tmp + i, " UNLOCK modcnt %d\n", MOD_USE_COUNT);
HiSax_putstatus(csta, tmp);
}
#endif /* MODULE */
@@ -2128,7 +2128,8 @@ HiSax_command(isdn_ctrl * ic)
break;
#ifdef MODULE
case (55):
- MOD_USE_COUNT = 0;
+ while ( MOD_USE_COUNT > 0)
+ MOD_DEC_USE_COUNT;
HiSax_mod_inc_use_count();
break;
#endif /* MODULE */
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 67e308e43..e6b3a9a52 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -97,9 +97,11 @@
#ifdef CONFIG_HISAX_ELSA
#define DEFAULT_CARD ISDN_CTYPE_ELSA
#define DEFAULT_CFG {0,0,0,0}
+#ifdef MODULE
int elsa_init_pcmcia(void*, int, int*, int);
EXPORT_SYMBOL(elsa_init_pcmcia);
#endif
+#endif
#ifdef CONFIG_HISAX_AVM_A1
#undef DEFAULT_CARD
#undef DEFAULT_CFG
diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h
index 3bd2819ce..4aba68b38 100644
--- a/drivers/isdn/icn/icn.h
+++ b/drivers/isdn/icn/icn.h
@@ -318,9 +318,9 @@ static char *icn_id2 = "\0";
#ifdef MODULE
MODULE_AUTHOR("Fritz Elfert");
MODULE_PARM(portbase, "i");
-MODULE_PARM_DESC(portbase, "Port adress of first card");
+MODULE_PARM_DESC(portbase, "Port address of first card");
MODULE_PARM(membase, "i");
-MODULE_PARM_DESC(membase, "Shared memory adress of all cards");
+MODULE_PARM_DESC(membase, "Shared memory address of all cards");
MODULE_PARM(icn_id, "s");
MODULE_PARM_DESC(icn_id, "ID-String of first card");
MODULE_PARM(icn_id2, "s");
diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c
index 331842fab..92e2ee544 100644
--- a/drivers/isdn/isdn_common.c
+++ b/drivers/isdn/isdn_common.c
@@ -20,6 +20,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_common.c,v $
* Revision 1.55 1998/02/23 23:35:32 fritz
* Eliminated some compiler warnings.
@@ -770,9 +774,18 @@ isdn_getnum(char **p)
/*
* isdn_readbchan() tries to get data from the read-queue.
* It MUST be called with interrupts off.
+ *
+ * Be aware that this is not an atomic operation when sleep != 0, even though
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he
*/
int
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
{
int left;
int count;
@@ -785,8 +798,8 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user
if (!dev->drv[di])
return 0;
if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
- if (user)
- interruptible_sleep_on(&dev->drv[di]->rcv_waitq[channel]);
+ if (sleep)
+ interruptible_sleep_on(sleep);
else
return 0;
}
@@ -808,16 +821,10 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user
count_pull = count_put = 0;
while ((count_pull < skb->len) && (left-- > 0)) {
if (dev->drv[di]->DLEflag & DLEmask) {
- if (user)
- put_user(DLE, cp++);
- else
- *cp++ = DLE;
+ *cp++ = DLE;
dev->drv[di]->DLEflag &= ~DLEmask;
} else {
- if (user)
- put_user(*p, cp++);
- else
- *cp++ = *p;
+ *cp++ = *p;
if (*p == DLE) {
dev->drv[di]->DLEflag |= DLEmask;
(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
@@ -838,10 +845,7 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user
dflag = 0;
}
count_put = count_pull;
- if (user)
- copy_to_user(cp, skb->data, count_put);
- else
- memcpy(cp, skb->data, count_put);
+ memcpy(cp, skb->data, count_put);
cp += count_put;
left -= count_put;
#ifdef CONFIG_ISDN_AUDIO
@@ -966,12 +970,12 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
ulong flags;
int drvidx;
int chidx;
+ char *p;
if (off != &file->f_pos)
return -ESPIPE;
if (minor == ISDN_MINOR_STATUS) {
- char *p;
if (!file->private_data) {
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -996,11 +1000,15 @@ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
if (!dev->drv[drvidx]->running)
return -ENODEV;
chidx = isdn_minor2chan(minor);
+ if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM;
save_flags(flags);
cli();
- len = isdn_readbchan(drvidx, chidx, buf, 0, count, 1);
+ len = isdn_readbchan(drvidx, chidx, p, 0, count,
+ &dev->drv[drvidx]->rcv_waitq[chidx]);
*off += len;
restore_flags(flags);
+ if( copy_to_user(buf,p,len) ) len = -EFAULT;
+ kfree(p);
return len;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
@@ -1124,6 +1132,11 @@ isdn_poll(struct file *file, poll_table * wait)
return POLLERR;
}
+/*
+ * This accesses user space with interrupts off, but is not needed by
+ * any of the isdn4k-util programs anyway. Thus, in contrast to your
+ * first impression after looking at the code, fixing is trival!*/
+#if 0
static int
isdn_set_allcfg(char *src)
{
@@ -1135,8 +1148,7 @@ isdn_set_allcfg(char *src)
if ((ret = isdn_net_rmall()))
return ret;
- if ((ret = copy_from_user((char *) &i, src, sizeof(int))))
- return ret;
+ if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT;
save_flags(flags);
cli();
src += sizeof(int);
@@ -1144,9 +1156,9 @@ isdn_set_allcfg(char *src)
int phone_len;
int out_flag;
- if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) {
+ if (copy_from_user((char *) &cfg, src, sizeof(cfg))) {
restore_flags(flags);
- return ret;
+ return -EFAULT;
}
src += sizeof(cfg);
if (!isdn_net_new(cfg.name, NULL)) {
@@ -1256,6 +1268,7 @@ isdn_get_allcfg(char *dest)
restore_flags(flags);
return 0;
}
+#endif
static int
isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1319,59 +1332,83 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return 0;
}
if (minor <= ISDN_MINOR_CTRLMAX) {
+/*
+ * isdn net devices manage lots of configuration variables as linked lists.
+ * Those lists must only be manipulated from user space. Some of the ioctl's
+ * service routines access user space and are not atomic. Therefor, ioctl's
+ * manipulating the lists and ioctl's sleeping while accessing the lists
+ * are serialized by means of a semaphore.
+ */
switch (cmd) {
#ifdef CONFIG_NETDEVICES
case IIOCNETAIF:
/* Add a network-interface */
if (arg) {
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
s = name;
- } else
+ } else {
s = NULL;
+ }
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
if ((s = isdn_net_new(s, NULL))) {
- if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
+ if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+ ret = -EFAULT;
+ } else {
+ ret = 0;
+ }
} else
- return -ENODEV;
+ ret = -ENODEV;
+ up(&dev->sem);
+ return ret;
case IIOCNETASL:
/* Add a slave to a network-interface */
if (arg) {
- if ((ret = copy_from_user(bname, (char *) arg, sizeof(bname) - 1)))
- return ret;
+ if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
+ return -EFAULT;
} else
return -EINVAL;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
if ((s = isdn_net_newslave(bname))) {
- if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
- return ret;
- return 0;
+ if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+ ret = -EFAULT;
+ } else {
+ ret = 0;
+ }
} else
- return -ENODEV;
+ ret = -ENODEV;
+ up(&dev->sem);
+ return ret;
case IIOCNETDIF:
/* Delete a network-interface */
if (arg) {
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
- return isdn_net_rm(name);
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_rm(name);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETSCF:
/* Set configurable parameters of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
- return ret;
+ if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
return isdn_net_setcfg(&cfg);
} else
return -EINVAL;
case IIOCNETGCF:
/* Get configurable parameters of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
- return ret;
+ if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+ return -EFAULT;
if (!(ret = isdn_net_getcfg(&cfg))) {
- if ((ret = copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))))
- return ret;
+ if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+ return -EFAULT;
}
return ret;
} else
@@ -1379,32 +1416,44 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
case IIOCNETANM:
/* Add a phone-number to a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_addphone(&phone);
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_addphone(&phone);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETGNM:
/* Get list of phone-numbers of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_getphones(&phone, (char *) arg);
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_getphones(&phone, (char *) arg);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETDNM:
/* Delete a phone-number of a network-interface */
if (arg) {
- if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
- return ret;
- return isdn_net_delphone(&phone);
+ if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+ return -EFAULT;
+ ret = down_interruptible(&dev->sem);
+ if( ret ) return ret;
+ ret = isdn_net_delphone(&phone);
+ up(&dev->sem);
+ return ret;
} else
return -EINVAL;
case IIOCNETDIL:
/* Force dialing of a network-interface */
if (arg) {
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_net_force_dial(name);
} else
return -EINVAL;
@@ -1412,22 +1461,22 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
case IIOCNETALN:
if (!arg)
return -EINVAL;
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_ppp_dial_slave(name);
case IIOCNETDLN:
if (!arg)
return -EINVAL;
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_ppp_hangup_slave(name);
#endif
case IIOCNETHUP:
/* Force hangup of a network-interface */
if (!arg)
return -EINVAL;
- if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
- return ret;
+ if (copy_from_user(name, (char *) arg, sizeof(name)))
+ return -EFAULT;
return isdn_net_force_hangup(name);
break;
#endif /* CONFIG_NETDEVICES */
@@ -1448,9 +1497,9 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
int i;
char *p;
- if ((ret = copy_from_user((char *) &iocts, (char *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
+ if (copy_from_user((char *) &iocts, (char *) arg,
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1466,6 +1515,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return -ENODEV;
dev->drv[drvidx]->reject_bus = iocts.arg;
return 0;
+#if 0
case IIOCGETSET:
/* Get complete setup (all network-interfaces and profile-
settings of all tty-devices */
@@ -1482,6 +1532,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
else
return -EINVAL;
break;
+#endif
case IIOCSIGPRF:
dev->profd = current;
return 0;
@@ -1522,12 +1573,12 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return ret;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
- if ((ret = copy_from_user(dev->mdm.info[i].emu.profile, p,
- ISDN_MODEM_ANZREG)))
- return ret;
+ if (copy_from_user(dev->mdm.info[i].emu.profile, p,
+ ISDN_MODEM_ANZREG))
+ return -EFAULT;
p += ISDN_MODEM_ANZREG;
- if ((ret = copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)))
- return ret;
+ if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+ return -EFAULT;
p += ISDN_MSNLEN;
}
return 0;
@@ -1539,10 +1590,10 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
/* Set/Get MSN->EAZ-Mapping for a driver */
if (arg) {
- if ((ret = copy_from_user((char *) &iocts,
+ if (copy_from_user((char *) &iocts,
(char *) arg,
- sizeof(isdn_ioctl_struct))))
- return ret;
+ sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
if (strlen(iocts.drvid)) {
drvidx = -1;
for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1591,8 +1642,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
strlen(dev->drv[drvidx]->msn2eaz[i]) ?
dev->drv[drvidx]->msn2eaz[i] : "-",
(i < 9) ? "," : "\0");
- if ((ret = copy_to_user(p, bname, strlen(bname) + 1)))
- return ret;
+ if (copy_to_user(p, bname, strlen(bname) + 1))
+ return -EFAULT;
p += strlen(bname);
}
}
@@ -1601,8 +1652,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
return -EINVAL;
case IIOCDBGVAR:
if (arg) {
- if ((ret = copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))))
- return ret;
+ if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
+ return -EFAULT;
return 0;
} else
return -EINVAL;
@@ -1615,8 +1666,8 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
if (arg) {
int i;
char *p;
- if ((ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))))
- return ret;
+ if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
+ return -EFAULT;
if (strlen(iocts.drvid)) {
if ((p = strchr(iocts.drvid, ',')))
*p = 0;
@@ -1639,7 +1690,7 @@ isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
ret = isdn_command(&c);
memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
- if ((copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))))
+ if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
return -EFAULT;
return ret;
} else
@@ -2164,6 +2215,7 @@ isdn_init(void)
memset((char *) dev, 0, sizeof(isdn_dev));
init_timer(&dev->timer);
dev->timer.function = isdn_timer_funct;
+ dev->sem = MUTEX;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
dev->drvmap[i] = -1;
dev->chanmap[i] = -1;
diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h
index b9d5df715..6cb503b9f 100644
--- a/drivers/isdn/isdn_common.h
+++ b/drivers/isdn/isdn_common.h
@@ -20,6 +20,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_common.h,v $
* Revision 1.9 1998/02/20 17:19:01 fritz
* Added common stub for sending commands to lowlevel.
@@ -86,7 +90,7 @@ extern char *isdn_map_eaz2msn(char *msn, int di);
extern void isdn_timer_ctrl(int tf, int onoff);
extern void isdn_unexclusive_channel(int di, int ch);
extern int isdn_getnum(char **);
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, int);
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
extern int isdn_get_free_channel(int, int, int, int, int);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c
index 33b122c96..daafceb1a 100644
--- a/drivers/isdn/isdn_net.c
+++ b/drivers/isdn/isdn_net.c
@@ -20,6 +20,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_net.c,v $
* Revision 1.55 1998/02/23 19:38:22 fritz
* Corrected check for modified feature-flags.
@@ -243,7 +247,7 @@
#include <linux/module.h>
#include <linux/isdn.h>
#include <net/arp.h>
-#include <net/icmp.h>
+#include <net/dst.h>
#ifndef DEV_NUMBUFFS
#include <net/pkt_sched.h>
#endif
@@ -277,9 +281,18 @@ char *isdn_net_revision = "$Revision: 1.55 $";
static void
isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
{
- printk(KERN_DEBUG "isdn_net: %s: %s, send ICMP\n",
- dev->name, reason);
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+
+ if(skb) {
+
+ u_short proto = ntohs(skb->protocol);
+
+ printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
+ dev->name,
+ (reason != NULL) ? reason : "unknown",
+ (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
+
+ dst_link_failure(skb);
+ }
}
static void
@@ -610,6 +623,13 @@ isdn_net_stat_callback(int idx, isdn_ctrl *c)
if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
lp->first_skb = NULL;
+ } else {
+ /*
+ * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
+ * With an empty lp->first_skb, we need to do this ourselves
+ */
+ lp->netdev->dev.tbusy = 0;
+ mark_bh(NET_BH);
}
return 1;
}
@@ -2696,7 +2716,8 @@ isdn_net_addphone(isdn_net_ioctl_phone * phone)
}
/*
- * Return a string of all phone-numbers of an interface.
+ * Copy a string of all phone-numbers of an interface to user space.
+ * This might sleep and must be called with the isdn semaphore down.
*/
int
isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
@@ -2706,22 +2727,17 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
int more = 0;
int count = 0;
isdn_net_phone *n;
- int flags;
- int ret;
if (!p)
return -ENODEV;
- save_flags(flags);
- cli();
inout &= 1;
for (n = p->local->phone[inout]; n; n = n->next) {
if (more) {
put_user(' ', phones++);
count++;
}
- if ((ret = copy_to_user(phones, n->num, strlen(n->num) + 1))) {
- restore_flags(flags);
- return ret;
+ if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
+ return -EFAULT;
}
phones += strlen(n->num);
count += strlen(n->num);
@@ -2729,7 +2745,6 @@ isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
}
put_user(0, phones);
count++;
- restore_flags(flags);
return count;
}
@@ -2760,6 +2775,7 @@ isdn_net_delphone(isdn_net_ioctl_phone * phone)
else
p->local->phone[inout] = n->next;
kfree(n);
+ restore_flags(flags);
return 0;
}
m = n;
diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c
index a4a45d9ea..5da3a49f0 100644
--- a/drivers/isdn/isdn_ppp.c
+++ b/drivers/isdn/isdn_ppp.c
@@ -18,6 +18,10 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
* $Log: isdn_ppp.c,v $
* Revision 1.33 1998/02/20 17:11:54 fritz
* Changes for recent kernels.
@@ -500,11 +504,10 @@ isdn_ppp_release(int min, struct file *file)
static int
get_arg(void *b, void *val, int len)
{
- int r;
if (len <= 0)
len = sizeof(unsigned long);
- if ((r = copy_from_user((void *) val, b, len)))
- return r;
+ if (copy_from_user((void *) val, b, len))
+ return -EFAULT;
return 0;
}
@@ -514,13 +517,12 @@ get_arg(void *b, void *val, int len)
static int
set_arg(void *b, unsigned long val, void *str)
{
- int r;
if (!str) {
- if ((r = copy_to_user(b, (void *) &val, 4)))
- return r;
+ if (copy_to_user(b, (void *) &val, 4))
+ return -EFAULT;
} else {
- if ((r = copy_to_user(b, str, val)))
- return r;
+ if (copy_to_user(b, str, val))
+ return -EFAULT;
}
return 0;
}
@@ -1851,13 +1853,14 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct device *dev)
}
#endif
}
- return copy_to_user(res, &t, sizeof(struct ppp_stats));
+ if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT;
+ return 0;
}
int
isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
{
- int error;
+ int error=0;
char *r;
int len;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -1873,7 +1876,7 @@ isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
case SIOCGPPPVER:
r = (char *) ifr->ifr_ifru.ifru_data;
len = strlen(PPP_VERSION) + 1;
- error = copy_to_user(r, PPP_VERSION, len);
+ if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
break;
case SIOCGPPPSTATS:
error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
diff --git a/drivers/isdn/isdn_x25iface.c b/drivers/isdn/isdn_x25iface.c
index c7471d361..2ae21fcf3 100644
--- a/drivers/isdn/isdn_x25iface.c
+++ b/drivers/isdn/isdn_x25iface.c
@@ -65,7 +65,7 @@ static struct concap_proto_ops ix25_pops = {
&isdn_x25iface_disconn_ind
};
-/* error message helper fuction */
+/* error message helper function */
static void illegal_state_warn( unsigned state, unsigned char firstbyte)
{
printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"