	** DYNAMIC SLIP DEVICES **

	This diff is against Linux-1.3.8. (prev.version was for 1.2.8)

	The system comes up with 0 devices allocated, but when one
	is called for, it is allocated out from memory pool, and linked
	into the device structures.

	When the usage of the device finishes, it is removed from
	the device pool.

	To avoid running out of memory when something goes amok,
	drivers/net/slip.h defines  SL_NRUNIT as 256, which SHOULD
	be enough for everybody -- there can't be more than SL_NRUNIT
	active SLIPs at any time.

	Do know that this device needs a TTY/PTY port on which to
	operate, and if you do not have enough TTYs/PTYs to have
	even 256 SLIP-lines, you do not need to increase that limit.

	With MODULE you can use   insmod  to set   slip_maxdev=1024
	or whatever else you want in case the 256 is not enough (or
	you think it is too much..)

	The MODULE -code is NOT tested.  (However the changes are
	trivial, thus my confidence is high..)


	/Matti Aarnio	<mea@utu.fi>


diff -u -r linux-1308virgin/arch/alpha/config.in linux/arch/alpha/config.in
--- linux-1308virgin/arch/alpha/config.in	Thu Jul  6 13:22:04 1995
+++ linux/arch/alpha/config.in	Wed Jul 12 10:47:54 1995
@@ -122,7 +122,6 @@
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
 if [ "$CONFIG_PPP" = "y" ]; then
diff -u -r linux-1308virgin/arch/i386/config.in linux/arch/i386/config.in
--- linux-1308virgin/arch/i386/config.in	Thu Jul  6 18:34:23 1995
+++ linux/arch/i386/config.in	Wed Jul 12 10:48:20 1995
@@ -131,7 +131,6 @@
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
 if [ "$CONFIG_PPP" = "y" ]; then
diff -u -r linux-1308virgin/arch/mips/config.in linux/arch/mips/config.in
--- linux-1308virgin/arch/mips/config.in	Thu Jun 29 10:37:08 1995
+++ linux/arch/mips/config.in	Wed Jul 12 10:47:40 1995
@@ -108,7 +108,6 @@
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
diff -u -r linux-1308virgin/arch/sparc/config.in linux/arch/sparc/config.in
--- linux-1308virgin/arch/sparc/config.in	Mon Jun 12 03:58:31 1995
+++ linux/arch/sparc/config.in	Wed Jul 12 10:48:33 1995
@@ -76,7 +76,6 @@
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' SL_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
diff -u -r linux-1308virgin/drivers/net/Space.c linux/drivers/net/Space.c
--- linux-1308virgin/drivers/net/Space.c	Wed Jun 28 18:35:04 1995
+++ linux/drivers/net/Space.c	Wed Jul 12 10:50:23 1995
@@ -237,76 +237,13 @@
 #endif  /* PLIP */
 
 #if defined(SLIP) || defined(CONFIG_SLIP)
-    extern int slip_init(struct device *);
-    
-#ifdef SL_SLIP_LOTS
-
-    static struct device slip15_dev={"sl15",0,0,0,0,15,0,0,0,0,NEXT_DEV,slip_init};
-    static struct device slip14_dev={"sl14",0,0,0,0,14,0,0,0,0,&slip15_dev,slip_init};
-    static struct device slip13_dev={"sl13",0,0,0,0,13,0,0,0,0,&slip14_dev,slip_init};
-    static struct device slip12_dev={"sl12",0,0,0,0,12,0,0,0,0,&slip13_dev,slip_init};
-    static struct device slip11_dev={"sl11",0,0,0,0,11,0,0,0,0,&slip12_dev,slip_init};
-    static struct device slip10_dev={"sl10",0,0,0,0,10,0,0,0,0,&slip11_dev,slip_init};
-    static struct device slip9_dev={"sl9",0,0,0,0,9,0,0,0,0,&slip10_dev,slip_init};
-    static struct device slip8_dev={"sl8",0,0,0,0,8,0,0,0,0,&slip9_dev,slip_init};
-    static struct device slip7_dev={"sl7",0,0,0,0,7,0,0,0,0,&slip8_dev,slip_init};
-    static struct device slip6_dev={"sl6",0,0,0,0,6,0,0,0,0,&slip7_dev,slip_init};
-    static struct device slip5_dev={"sl5",0,0,0,0,5,0,0,0,0,&slip6_dev,slip_init};
-    static struct device slip4_dev={"sl4",0,0,0,0,4,0,0,0,0,&slip5_dev,slip_init};
-#   undef	NEXT_DEV
-#   define	NEXT_DEV	(&slip4_dev)
-#endif	/* SL_SLIP_LOTS */
-    
-    static struct device slip3_dev = {
-	"sl3",			/* Internal SLIP driver, channel 3	*/
-	0x0,			/* recv memory end			*/
-	0x0,			/* recv memory start			*/
-	0x0,			/* memory end				*/
-	0x0,			/* memory start				*/
-	0x3,			/* base I/O address			*/
-	0,			/* IRQ					*/
-	0, 0, 0,		/* flags				*/
-	NEXT_DEV,		/* next device				*/
-	slip_init		/* slip_init should set up the rest	*/
-    };
-    static struct device slip2_dev = {
-	"sl2",			/* Internal SLIP driver, channel 2	*/
-	0x0,			/* recv memory end			*/
-	0x0,			/* recv memory start			*/
-	0x0,			/* memory end				*/
-	0x0,			/* memory start				*/
-	0x2,			/* base I/O address			*/
-	0,			/* IRQ					*/
-	0, 0, 0,		/* flags				*/
-	&slip3_dev,		/* next device				*/
-	slip_init		/* slip_init should set up the rest	*/
-    };
-    static struct device slip1_dev = {
-	"sl1",			/* Internal SLIP driver, channel 1	*/
-	0x0,			/* recv memory end			*/
-	0x0,			/* recv memory start			*/
-	0x0,			/* memory end				*/
-	0x0,			/* memory start				*/
-	0x1,			/* base I/O address			*/
-	0,			/* IRQ					*/
-	0, 0, 0,		/* flags				*/
-	&slip2_dev,		/* next device				*/
-	slip_init		/* slip_init should set up the rest	*/
-    };
-    static struct device slip0_dev = {
-	"sl0",			/* Internal SLIP driver, channel 0	*/
-	0x0,			/* recv memory end			*/
-	0x0,			/* recv memory start			*/
-	0x0,			/* memory end				*/
-	0x0,			/* memory start				*/
-	0x0,			/* base I/O address			*/
-	0,			/* IRQ					*/
-	0, 0, 0,		/* flags				*/
-	&slip1_dev,		/* next device				*/
-	slip_init		/* slip_init should set up the rest	*/
-    };
-#   undef	NEXT_DEV
-#   define	NEXT_DEV	(&slip0_dev)
+	/* To be exact, this node just hooks the initialization
+	   routines to the device structures.			*/
+extern int slip_init_ctrl_dev(struct device *);
+static struct device slip_bootstrap = {
+  "slip_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, slip_init_ctrl_dev, };
+#undef NEXT_DEV
+#define NEXT_DEV (&slip_bootstrap)
 #endif	/* SLIP */
   
 #if defined(CONFIG_PPP)
diff -u -r linux-1308virgin/drivers/net/slip.c linux/drivers/net/slip.c
--- linux-1308virgin/drivers/net/slip.c	Wed Jul  5 13:06:27 1995
+++ linux/drivers/net/slip.c	Wed Jul 12 11:43:33 1995
@@ -36,7 +36,15 @@
  *                                      statistics. Include CSLIP code only
  *                                      if it really needed.
  *		Alan Cox	:	Free slhc buffers in the right place.
- *
+ *		Matti Aarnio	:	Dynamic SLIP devices, with ideas taken
+ *					from Jim Freeman's <jfree@caldera.com>
+ *					dynamic PPP devices.  We do NOT kfree()
+ *					device entries, just reg./unreg. them
+ *					as they are needed.  We kfree() them
+ *					at module cleanup.
+ *					With MODULE-loading ``insmod'', user can
+ *					issue parameter:   slip_maxdev=1024
+ *					(Or how much he/she wants.. Default is 256)
  *
  *
  *	FIXME:	This driver still makes some IP'ish assumptions. It should build cleanly KISS TNC only without
@@ -85,9 +93,15 @@
 #endif
 
 
-static struct slip	sl_ctrl[SL_NRUNIT];
+typedef struct slip_ctrl {
+	char		if_name[8];	/* "sl0\0" .. "sl99999\0"	*/
+	struct slip	ctrl;		/* SLIP things			*/
+	struct device	dev;		/* the device			*/
+} slip_ctrl_t;
+static slip_ctrl_t	**slip_ctrls = NULL;
+int slip_maxdev = SL_NRUNIT;		/* Can be overridden with insmod! */
+
 static struct tty_ldisc	sl_ldisc;
-static int		already = 0;
 
 static int slip_esc(unsigned char *p, unsigned char *d, int len);
 static void slip_unesc(struct slip *sl, unsigned char c);
@@ -101,15 +115,67 @@
 static inline struct slip *
 sl_alloc(void)
 {
-	struct slip *sl;
+	slip_ctrl_t *slp;
 	int i;
 
-	for (i = 0; i < SL_NRUNIT; i++) {
-		sl = &sl_ctrl[i];
-		if (!set_bit(SLF_INUSE, &sl->flags)) {
-			return sl;
-		}
+	if (slip_ctrls == NULL) return NULL;	/* Master array missing ! */
+
+	for (i = 0; i < slip_maxdev; i++) {
+	  slp = slip_ctrls[i];
+	  /* Not allocated ? */
+	  if (slp == NULL)
+	    break;
+	  /* Not in use ? */
+	  if (!set_bit(SLF_INUSE, &slp->ctrl.flags))
+	    break;
+	}
+	/* SLP is set.. */
+
+	/* Sorry, too many, all slots in use */
+	if (i >= slip_maxdev) return NULL;
+
+	/* If no channels are available, allocate one */
+	if (!slp &&
+	    (slip_ctrls[i] = (slip_ctrl_t *)kmalloc(sizeof(slip_ctrl_t),
+						    GFP_KERNEL)) != NULL) {
+	  slp = slip_ctrls[i];
+	  memset(slp, 0, sizeof(slip_ctrl_t));
+
+	  /* Initialize channel control data */
+	  set_bit(SLF_INUSE, &slp->ctrl.flags);
+	  slp->ctrl.tty         = NULL;
+	  sprintf(slp->if_name, "sl%d", i);
+	  slp->dev.name         = slp->if_name;
+	  slp->dev.base_addr    = i;
+	  slp->dev.priv         = (void*)&(slp->ctrl);
+	  slp->dev.next         = NULL;
+	  slp->dev.init         = slip_init;
+/* printk(KERN_INFO "slip: kmalloc()ed SLIP control node for line %s\n",
+   slp->if_name); */
+	}
+	if (slp != NULL) {
+
+	  /* register device so that it can be ifconfig'ed       */
+	  /* slip_init() will be called as a side-effect         */
+	  /* SIDE-EFFECT WARNING: slip_init() CLEARS slp->ctrl ! */
+
+	  if (register_netdev(&(slp->dev)) == 0) {
+	    /* (Re-)Set the INUSE bit.   Very Important! */
+	    set_bit(SLF_INUSE, &slp->ctrl.flags);
+	    slp->ctrl.dev = &(slp->dev);
+	    slp->dev.priv = (void*)&(slp->ctrl);
+
+/* printk(KERN_INFO "slip: linked in netdev %s for active use\n",
+   slp->if_name); */
+
+	    return (&(slp->ctrl));
+
+	  } else {
+	    clear_bit(SLF_INUSE,&(slp->ctrl.flags));
+	    printk("sl_alloc() - register_netdev() failure.\n");
+	  }
 	}
+
 	return NULL;
 }
 
@@ -149,9 +215,9 @@
 	}
 }
 
-/* MTU has been changed by the IP layer. Unfortunately we are not told about this, but
-   we spot it ourselves and fix things up. We could be in an upcall from the tty
-   driver, or in an ip packet queue. */
+/* MTU has been changed by the IP layer. Unfortunately we are not told
+   about this, but we spot it ourselves and fix things up. We could be
+   in an upcall from the tty driver, or in an ip packet queue. */
 
 static void sl_changedmtu(struct slip *sl)
 {
@@ -417,7 +483,7 @@
 static int
 sl_xmit(struct sk_buff *skb, struct device *dev)
 {
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 
 	if (!dev->start)  {
 		printk("%s: xmit call when iface is down\n", dev->name);
@@ -472,7 +538,7 @@
 {
 #ifdef CONFIG_AX25
 #ifdef CONFIG_INET
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 
 	if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25))  {
 		return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
@@ -490,7 +556,7 @@
 {
 #ifdef CONFIG_AX25
 #ifdef CONFIG_INET
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 
 	if ((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) {
 		return ax25_rebuild_header(buff, dev, raddr, skb);
@@ -505,7 +571,7 @@
 static int
 sl_open(struct device *dev)
 {
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 	unsigned long len;
 
 	if (sl->tty == NULL) {
@@ -589,7 +655,7 @@
 static int
 sl_close(struct device *dev)
 {
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 
 	if (sl->tty == NULL) {
 		return -EBUSY;
@@ -728,6 +794,7 @@
 	tty->disc_data = 0;
 	sl->tty = NULL;
 	sl_free(sl);
+	unregister_netdev(sl->dev);
 #ifdef MODULE
 	MOD_DEC_USE_COUNT;
 #endif
@@ -738,7 +805,7 @@
 sl_get_stats(struct device *dev)
 {
 	static struct enet_statistics stats;
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 #ifdef SL_INCLUDE_CSLIP
 	struct slcompress *comp;
 #endif
@@ -947,7 +1014,7 @@
 
 int sl_get_ax25_mode(struct device *dev)
 {
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 
 	return sl->mode & SL_MODE_AX25VC;
 }
@@ -1048,17 +1115,82 @@
 
 static int sl_open_dev(struct device *dev)
 {
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 	if(sl->tty==NULL)
 		return -ENODEV;
 	return 0;
 }
 
+/* Initialize SLIP control device -- register SLIP line discipline */
+#ifdef MODULE
+static int slip_init_ctrl_dev()
+#else	/* !MODULE */
+int
+slip_init_ctrl_dev(struct device *dummy)
+#endif	/* !MODULE */
+{
+	int status;
+
+	if (slip_maxdev < 4) slip_maxdev = 4; /* Sanity */
+
+	printk("SLIP: version %s (dynamic channels, max=%d)"
+#ifdef CONFIG_SLIP_MODE_SLIP6
+	       " (6 bit encapsulation enabled)"
+#endif
+	       "\n",
+	       SLIP_VERSION, slip_maxdev );
+#if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
+	printk("CSLIP: code copyright 1989 Regents of the University of California\n");
+#endif
+#ifdef CONFIG_AX25
+	printk("AX25: KISS encapsulation enabled\n");
+#endif
+
+	slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL);
+	if (slip_ctrls == NULL) {
+	  printk("SLIP: Can't allocate slip_ctrls[] array!  Uaargh! (-> No SLIP available)\n");
+	  return -ENOMEM;
+	}
+	
+	/* Clear the pointer array, we allocate devices when we need them */
+	memset(slip_ctrls, 0, sizeof(void*)*slip_maxdev); /* Pointers */
+
+	/* Fill in our line protocol discipline, and register it */
+	memset(&sl_ldisc, 0, sizeof(sl_ldisc));
+	sl_ldisc.magic  = TTY_LDISC_MAGIC;
+	sl_ldisc.flags  = 0;
+	sl_ldisc.open   = slip_open;
+	sl_ldisc.close  = slip_close;
+	sl_ldisc.read   = NULL;
+	sl_ldisc.write  = NULL;
+	sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
+				   unsigned int, unsigned long)) slip_ioctl;
+	sl_ldisc.select = NULL;
+	sl_ldisc.receive_buf = slip_receive_buf;
+	sl_ldisc.receive_room = slip_receive_room;
+	sl_ldisc.write_wakeup = slip_write_wakeup;
+	if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
+	  printk("SLIP: can't register line discipline (err = %d)\n", status);
+	}
+
+
+	/* If not loadable module, a bootstrap Space.c slip_proto dev
+	 *  now needs to be unregistered.
+	 */
+#ifndef MODULE
+	printk("SLIP: Unregistering bootstrap device "
+	       "'slip_proto' - slip OK\n");
+	unregister_netdev(dummy);
+#endif
+	return status;
+      }
+
+
 /* Initialize the SLIP driver.  Called by DDI. */
 int
 slip_init(struct device *dev)
 {
-	struct slip *sl = &sl_ctrl[dev->base_addr];
+	struct slip *sl = (struct slip*)(dev->priv);
 	int i;
 #ifdef CONFIG_AX25
 	static char ax25_bcast[AX25_ADDR_LEN] =
@@ -1067,39 +1199,8 @@
 		{'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
 #endif
 
-	if (already++ == 0) {
-		printk("SLIP: version %s (%d channels) %s\n",
-		       SLIP_VERSION, SL_NRUNIT,
-#ifdef CONFIG_SLIP_MODE_SLIP6
-		       "(6 bit encapsulation enabled)"
-#else
-		       ""
-#endif
-		       );
-#if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
-		printk("CSLIP: code copyright 1989 Regents of the University of California\n");
-#endif
-#ifdef CONFIG_AX25
-		printk("AX25: KISS encapsulation enabled\n");
-#endif
-		/* Fill in our LDISC request block. */
-		memset(&sl_ldisc, 0, sizeof(sl_ldisc));
-		sl_ldisc.magic	= TTY_LDISC_MAGIC;
-		sl_ldisc.flags	= 0;
-		sl_ldisc.open	= slip_open;
-		sl_ldisc.close	= slip_close;
-		sl_ldisc.read	= NULL;
-		sl_ldisc.write	= NULL;
-		sl_ldisc.ioctl	= (int (*)(struct tty_struct *, struct file *,
-					   unsigned int, unsigned long)) slip_ioctl;
-		sl_ldisc.select = NULL;
-		sl_ldisc.receive_buf = slip_receive_buf;
-		sl_ldisc.receive_room = slip_receive_room;
-		sl_ldisc.write_wakeup = slip_write_wakeup;
-		if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
-			printk("SLIP: can't register line discipline (err = %d)\n", i);
-		}
-	}
+	if (sl == NULL)		/* Allocation failed ?? */
+	  return -ENODEV;
 
 	/* Set up the "SLIP Control Block". (And clear statistics) */
 	
@@ -1148,47 +1249,10 @@
 #ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 
-static struct device dev_slip[SL_NRUNIT] =  {
-	{
-		"sl0",		/* slip */
-		0, 0, 0, 0,	/* memory */
-		0, 0,		/* base, irq */
-		0, 0, 0, NULL, slip_init,
-	},
-	{ "sl1" , 0, 0, 0, 0,  1, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl2" , 0, 0, 0, 0,  2, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl3" , 0, 0, 0, 0,  3, 0, 0, 0, 0, NULL, slip_init },
-#ifdef SL_SLIP_LOTS
-	{ "sl4" , 0, 0, 0, 0,  4, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl5" , 0, 0, 0, 0,  5, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl6" , 0, 0, 0, 0,  6, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl7" , 0, 0, 0, 0,  7, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl8" , 0, 0, 0, 0,  8, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl9" , 0, 0, 0, 0,  9, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl10", 0, 0, 0, 0, 10, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl11", 0, 0, 0, 0, 11, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl12", 0, 0, 0, 0, 12, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl13", 0, 0, 0, 0, 13, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl14", 0, 0, 0, 0, 14, 0, 0, 0, 0, NULL, slip_init },
-	{ "sl15", 0, 0, 0, 0, 15, 0, 0, 0, 0, NULL, slip_init },
-#endif /* SL_SLIP_LOTS */
-};
-
 int
 init_module(void)
 {
-	int err;
-	int i;
-
-	for (i = 0; i < SL_NRUNIT; i++)  {
-		if ((err = register_netdev(&dev_slip[i])))  {
-			if (err == -EEXIST)  {
-				printk("SLIP: devices already present. Module not loaded.\n");
-			}
-			return err;
-		}
-	}
-	return 0;
+	return slip_init_ctrl_dev();
 }
 
 void
@@ -1200,12 +1264,18 @@
 		printk("SLIP: device busy, remove delayed\n");
 		return;
 	}
-	for (i = 0; i < SL_NRUNIT; i++)  {
-		unregister_netdev(&dev_slip[i]);
+	if (slip_ctrls != NULL) {
+	  for (i = 0; i < slip_maxdev; i++)  {
+	    if (slip_ctrls[i] != NULL) {
+	      unregister_netdev(&(slip_ctrls[i]->dev));
+	      kfree(slip_ctrls[i]);
+	    }
+	  }
+	  kfree(slip_ctrls);
+	  slip_ctrls = NULL;
 	}
 	if ((i = tty_register_ldisc(N_SLIP, NULL)))  {
-		printk("SLIP: can't unregister line discipline (err = %d)\n", i);
+	  printk("SLIP: can't unregister line discipline (err = %d)\n", i);
 	}
-	already = 0;
 }
 #endif /* MODULE */
diff -u -r linux-1308virgin/drivers/net/slip.h linux/drivers/net/slip.h
--- linux-1308virgin/drivers/net/slip.h	Tue Jun  6 11:22:10 1995
+++ linux/drivers/net/slip.h	Wed Jul 12 11:33:07 1995
@@ -31,11 +31,9 @@
 #endif
 
 /* SLIP configuration. */
-#ifndef SL_SLIP_LOTS
-#define SL_NRUNIT	4		/* number of SLIP channels	*/
-#else
-#define SL_NRUNIT	16
-#endif
+#define SL_NRUNIT	256		/* MAX number of SLIP channels;
+					   This can be overridden with
+					   insmod -oslip_maxdev=nnn	*/
 #define SL_MTU		296		/* 296; I am used to 600- FvK	*/
 
 /* SLIP protocol characters. */
