public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: PATCH 2.4.0.10: Update hotplug
  2000-11-02  8:05 PATCH 2.4.0.10: Update hotplug Jeff Garzik
@ 2000-11-02  8:01 ` David S. Miller
  2000-11-04  7:49 ` PATCH 2.4.0.10 v2: " Jeff Garzik
  1 sibling, 0 replies; 6+ messages in thread
From: David S. Miller @ 2000-11-02  8:01 UTC (permalink / raw)
  To: jgarzik; +Cc: linux-kernel, torvalds, dhinds, randy.dunlap, mj

   Date: 	Thu, 02 Nov 2000 03:05:45 -0500
   From: Jeff Garzik <jgarzik@mandrakesoft.com>

   DaveM - netdevice.h seems like the best place to include businfo.h.
   Since it doesn't include anything but linux/types.h, that should
   eliminate any worry about a nightmare of nested includes...

Ok.

Later,
David S. Miller
davem@redhat.com
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* PATCH 2.4.0.10: Update hotplug
@ 2000-11-02  8:05 Jeff Garzik
  2000-11-02  8:01 ` David S. Miller
  2000-11-04  7:49 ` PATCH 2.4.0.10 v2: " Jeff Garzik
  0 siblings, 2 replies; 6+ messages in thread
From: Jeff Garzik @ 2000-11-02  8:05 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Linus Torvalds, David S. Miller, David Hinds, randy.dunlap, mj

[-- Attachment #1: Type: text/plain, Size: 1429 bytes --]

Note - this is just an RFC patch, do not apply.  It compiles, but is not
tested.

Attached is a patch against 2.4.0-test10 which updates the kernel's
hotplug capabilities per recent discussions (both public and private).

Major changes:
* pci: Execute /sbin/hotplug for each hotplug device insertion or
removal
* net: Export network device hardware info to userspace as
/proc/net/if/$IF/businfo
* net: Execute /sbin/network for each net device register/unregister

Minor changes:
* kbuild: CONFIG_HOTPLUG now requires CONFIG_KMOD
* epic100: demonstration of how a net device exports its bus info
* procfs: add standard method of exporting bus info to userspace. 
Currently ISA, PCI, and SBUS are supported.
* pci: support businfo
* sparc: support businfo
* usb: update /sbin/hotplug execution to pass event type (verb) as
standardized cmd line arg

DaveM - netdevice.h seems like the best place to include businfo.h. 
Since it doesn't include anything but linux/types.h, that should
eliminate any worry about a nightmare of nested includes...

Note - the patch to include/linux/pci.h will go away, that is a remnant
of an earlier change.  But it is included as you may need it to compile.

-- 
Jeff Garzik             | "Mind if I drive?"  -Sam
Building 1024           | "Not if you don't mind me clawing at the
MandrakeSoft            |  dash and shrieking like a cheerleader."
                        |                     -Max

[-- Attachment #2: hotplug-2.4.0.10.patch --]
[-- Type: text/plain, Size: 27712 bytes --]

Index: linux_2_4/Documentation/00-INDEX
diff -u linux_2_4/Documentation/00-INDEX:1.1.1.1 linux_2_4/Documentation/00-INDEX:1.1.1.1.34.1
--- linux_2_4/Documentation/00-INDEX:1.1.1.1	Sun Oct 22 12:47:49 2000
+++ linux_2_4/Documentation/00-INDEX	Wed Nov  1 22:50:19 2000
@@ -53,6 +53,8 @@
 	- notes about the floppy tape device driver
 hayes-esp.txt
 	- info on using the Hayes ESP serial driver.
+hotplug.txt
+	- kernel hotplug support
 i386/
 	- directory with info about Linux on the intel ix86 architecture.
 ide.txt
Index: linux_2_4/Documentation/hotplug.txt
diff -u /dev/null linux_2_4/Documentation/hotplug.txt:1.1.2.1
--- /dev/null	Wed Nov  1 23:27:35 2000
+++ linux_2_4/Documentation/hotplug.txt	Wed Nov  1 22:50:19 2000
@@ -0,0 +1,111 @@
+
+Hot-Plug Devices, the Kernel, and You!
+
+
+Introduction
+============
+Kernel version 2.4.0 and later includes native support for hotpluggable
+devices.  This text documents that support.
+
+FIXME: turn this random collection of notes into a real document
+
+Supported hot-plug buses:  CardBus (in the PCI subsystem), USB.
+
+Hot-plug code is conditionally included when CONFIG_HOTPLUG is enabled
+in 'make config'.  CONFIG_HOTPLUG now requires CONFIG_KMOD, so it is
+automatically defined when CONFIG_HOTPLUG is enabled.
+
+
+/sbin/network
+=============
+When network devices (interfaces) are added or removed, /sbin/network
+is executed by the kernel.  The usage of /sbin/network is as follows:
+
+	/sbin/network [netdev-event] [interface]
+
+[netdev-event] - any one of the follow one-word ASCII strings:
+
+	register	- New device [interface] was just added
+	unregister	- Device [interface] was just removed
+
+/sbin/network is executed by the kernel when all such events occur --
+after bootup.  Register and un-register events which occur during
+bootup, including initcalls, do not cause /sbin/network to be executed.
+
+The return value of /sbin/network is ignored by the kernel, and the
+file does not have to exist.  No errors or warnings will be issued
+by the kernel is /sbin/network execution fails in any way.
+
+
+/sbin/hotplug
+=============
+When hotpluggable hardware devices are added or removed, /sbin/hotplug
+is executed by the kernel.  The usage of /sbin/hotplug is as follows:
+
+	/sbin/hotplug [bus] [event]
+
+[bus] - The bus on which the hotpluggable event occurred.  Supported
+bus types are:
+
+	usb	- USB
+	pci	- PCI-compatible hot-plug:  CardBus
+
+[event] - Type of hot-plug event
+
+	add	- Device insertion
+	del	- Device removal
+
+In addition to the standard arguments passed to /sbin/hotplug as
+described above, each bus has its own set of environment variables
+which are passed to the program.
+
+hotplug pci env vars
+--------------------
+HOME=/
+	Hardcoded value.
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+	Hardcoded value.
+PCI_ID=$VENDOR:$DEVICE
+	$VENDOR	- 16-bit PCI device vendor id, in hexidecimal
+	$DEVICE	- 16-bit PCI device id, in hexidecimal
+PCI_SUBSYS_ID=$VENDOR:$DEVICE
+	$VENDOR	- 16-bit PCI device subsystem vendor id, in hexidecimal
+	$DEVICE	- 16-bit PCI device subsystem device id, in hexidecimal
+PCI_BUS_ID=$BUS:$SLOT:$FUNC
+	$BUS	- PCI bus number, in decimal
+	$SLOT	- PCI device slot, decoded from devfn, in decimal
+	$FUNC	- PCI device function, decoded from devfn, in decimal
+
+
+hotplug usb env vars
+--------------------
+HOME=/
+	Hardcoded value.
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+	Hardcoded value.
+DEBUG=kernel
+	Hardcoded value.  Only present if USB is in debug mode
+DEVFS=/proc/bus/usb
+	Hardcoded value.  Only present if CONFIG_USB_DEVICEFS is set.
+DEVICE=/proc/bus/usb/$BUS/$DEVICE
+	Indicates the assigned USB device node for the USB device.
+	Only present if CONFIG_USB_DEVICEFS is set.
+	$BUS	- USB bus number
+	$DEVICE	- USB device number
+PRODUCT=$VENDOR/$PRODUCT/$DEVICE
+	USB device identification info.
+	$VENDOR	- USB vendor id, in hexadecimal
+	$PRODUCT- USB product ID, in hexadecimal
+	$DEVICE	- Binary-coded decimal device number
+TYPE=$CLASS/$SUB/$PROTO
+	Only present if device class is non-zero.
+	$CLASS	- USB device class.
+	$SUB	- USB device sub-class.
+	$PROTO	- USB device protocol number.
+INTERFACE=$CLASS/$SUB/$PROTO
+	Only present if device class is zero.
+	Only the first interface (interface 0) is presented.
+	$CLASS	- USB interface 0 class.
+	$SUB	- USB interface 0 sub-class.
+	$PROTO	- USB interface 0 protocol number.
+
Index: linux_2_4/Documentation/networking/00-INDEX
diff -u linux_2_4/Documentation/networking/00-INDEX:1.1.1.1 linux_2_4/Documentation/networking/00-INDEX:1.1.1.1.34.1
--- linux_2_4/Documentation/networking/00-INDEX:1.1.1.1	Sun Oct 22 12:48:03 2000
+++ linux_2_4/Documentation/networking/00-INDEX	Wed Nov  1 23:04:19 2000
@@ -58,6 +58,8 @@
 	- info and "insmod" parameters for all network driver modules.
 policy-routing.txt
 	- IP policy-based routing
+proc-net-if.txt
+	- Description of /proc/net/if/* contents
 pt.txt
 	- the Gracilis Packetwin AX.25 device driver
 routing.txt
Index: linux_2_4/Documentation/networking/proc-net-if.txt
diff -u /dev/null linux_2_4/Documentation/networking/proc-net-if.txt:1.1.2.1
--- /dev/null	Wed Nov  1 23:27:36 2000
+++ linux_2_4/Documentation/networking/proc-net-if.txt	Wed Nov  1 23:04:19 2000
@@ -0,0 +1,20 @@
+Contents of /proc/net/if/*:
+
+/proc/net/if is a container for per-interface procfs information.
+Each interface has its own directory, which contains the following
+pseudo-files:
+
+businfo
+	- Outputs a bus-specific string describing the hardware device
+	which owns this network interface.  Zero bytes are output if
+	no hardware info is associated with the network device.
+
+Examples:
+
+	$ cat /proc/net/if/eth0/businfo
+	PCI bus 0 devfn 0
+	$
+
+	$ cat /proc/net/if/lo/businfo
+	$
+
Index: linux_2_4/arch/alpha/config.in
diff -u linux_2_4/arch/alpha/config.in:1.1.1.7 linux_2_4/arch/alpha/config.in:1.1.1.7.10.1
--- linux_2_4/arch/alpha/config.in:1.1.1.7	Sun Oct 22 16:26:26 2000
+++ linux_2_4/arch/alpha/config.in	Wed Nov  1 22:50:19 2000
@@ -222,6 +222,9 @@
  
 if [ "$CONFIG_HOTPLUG" = "y" ] ; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/arm/config.in
diff -u linux_2_4/arch/arm/config.in:1.1.1.8 linux_2_4/arch/arm/config.in:1.1.1.8.16.1
--- linux_2_4/arch/arm/config.in:1.1.1.8	Sun Oct 22 15:34:31 2000
+++ linux_2_4/arch/arm/config.in	Wed Nov  1 22:50:19 2000
@@ -242,6 +242,9 @@
 bool 'Support hot-pluggable devices' CONFIG_HOTPLUG
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/i386/config.in
diff -u linux_2_4/arch/i386/config.in:1.1.1.7 linux_2_4/arch/i386/config.in:1.1.1.7.10.2
--- linux_2_4/arch/i386/config.in:1.1.1.7	Sun Oct 22 16:26:14 2000
+++ linux_2_4/arch/i386/config.in	Wed Nov  1 22:50:19 2000
@@ -202,6 +202,9 @@
 
 if [ "$CONFIG_HOTPLUG" = "y" ] ; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/ia64/config.in
diff -u linux_2_4/arch/ia64/config.in:1.1.1.8 linux_2_4/arch/ia64/config.in:1.1.1.8.14.1
--- linux_2_4/arch/ia64/config.in:1.1.1.8	Sun Oct 22 15:53:47 2000
+++ linux_2_4/arch/ia64/config.in	Wed Nov  1 22:50:19 2000
@@ -98,6 +98,9 @@
 bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/mips/config.in
diff -u linux_2_4/arch/mips/config.in:1.1.1.7 linux_2_4/arch/mips/config.in:1.1.1.7.18.1
--- linux_2_4/arch/mips/config.in:1.1.1.7	Sun Oct 22 15:03:27 2000
+++ linux_2_4/arch/mips/config.in	Wed Nov  1 22:50:19 2000
@@ -181,6 +181,9 @@
 
 if [ "$CONFIG_HOTPLUG" = "y" ] ; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/mips64/config.in
diff -u linux_2_4/arch/mips64/config.in:1.1.1.7 linux_2_4/arch/mips64/config.in:1.1.1.7.18.1
--- linux_2_4/arch/mips64/config.in:1.1.1.7	Sun Oct 22 15:04:47 2000
+++ linux_2_4/arch/mips64/config.in	Wed Nov  1 22:50:19 2000
@@ -93,6 +93,9 @@
 
 if [ "$CONFIG_HOTPLUG" = "y" ] ; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/ppc/config.in
diff -u linux_2_4/arch/ppc/config.in:1.1.1.8 linux_2_4/arch/ppc/config.in:1.1.1.8.10.1
--- linux_2_4/arch/ppc/config.in:1.1.1.8	Sun Oct 22 16:26:54 2000
+++ linux_2_4/arch/ppc/config.in	Wed Nov  1 22:50:19 2000
@@ -132,6 +132,9 @@
 
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/arch/sh/config.in
diff -u linux_2_4/arch/sh/config.in:1.1.1.7 linux_2_4/arch/sh/config.in:1.1.1.7.18.1
--- linux_2_4/arch/sh/config.in:1.1.1.7	Sun Oct 22 15:04:35 2000
+++ linux_2_4/arch/sh/config.in	Wed Nov  1 22:50:19 2000
@@ -100,6 +100,9 @@
 
 if [ "$CONFIG_HOTPLUG" = "y" ] ; then
    source drivers/pcmcia/Config.in
+   if [ "$CONFIG_KMOD" != "y" ] ; then
+      define_bool CONFIG_KMOD y
+   fi
 else
    define_bool CONFIG_PCMCIA n
 fi
Index: linux_2_4/drivers/net/epic100.c
diff -u linux_2_4/drivers/net/epic100.c:1.1.1.6 linux_2_4/drivers/net/epic100.c:1.1.1.6.18.2
--- linux_2_4/drivers/net/epic100.c:1.1.1.6	Sun Oct 22 14:55:54 2000
+++ linux_2_4/drivers/net/epic100.c	Wed Nov  1 22:50:19 2000
@@ -491,6 +491,10 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
 
+	dev->bus_info.u.pci.pdev = pdev;
+	wmb();
+	dev->bus_info.bus_type = BUSINFO_PCI;
+
 	return 0;
 
 #ifndef USE_IO_OPS
Index: linux_2_4/drivers/pci/pci.c
diff -u linux_2_4/drivers/pci/pci.c:1.1.1.6 linux_2_4/drivers/pci/pci.c:1.1.1.6.6.2
--- linux_2_4/drivers/pci/pci.c:1.1.1.6	Fri Oct 27 00:45:05 2000
+++ linux_2_4/drivers/pci/pci.c	Wed Nov  1 22:50:19 2000
@@ -20,6 +20,8 @@
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
+#include <linux/businfo.h>
+#include <linux/kmod.h>		/* for hotplug_path */
 
 #include <asm/page.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
@@ -343,6 +345,41 @@
 
 #ifdef CONFIG_HOTPLUG
 
+static void
+run_sbin_hotplug(struct pci_dev *pdev, int insert)
+{
+	char *argv[4], *envp[6];
+	char id[32], sub_id[32], bus_id[32];
+	int i;
+
+	if (!hotplug_path[0])
+		return;
+
+	sprintf(id, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device);
+	sprintf(sub_id, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device);
+	sprintf(bus_id, "PCI_BUS_ID=%d:%d:%d", pdev->bus->number,
+		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+	i = 0;
+	argv[i++] = hotplug_path;
+	argv[i++] = "pci";
+	argv[i++] = insert ? "add" : "del";
+	argv[i] = 0;
+
+	i = 0;
+	/* minimal command environment */
+	envp[i++] = "HOME=/";
+	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	
+	/* other stuff we want to pass to /sbin/hotplug */
+	envp[i++] = id;
+	envp[i++] = sub_id;
+	envp[i++] = bus_id;
+	envp[i] = 0;
+
+	call_usermodehelper (argv [0], argv, envp);
+}
+
 void
 pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
 {
@@ -358,9 +395,13 @@
 		if (drv->remove && pci_announce_device(drv, dev))
 			break;
 	}
+
+	/* notify userspace of new hotplug device */
+	run_sbin_hotplug(dev, 1);
 }
 
-static void pci_free_resources(struct pci_dev *dev)
+static void
+pci_free_resources(struct pci_dev *dev)
 {
 	int i;
 
@@ -385,6 +426,9 @@
 #ifdef CONFIG_PROC_FS
 	pci_proc_detach_device(dev);
 #endif
+
+	/* notify userspace of hotplug device removal */
+	run_sbin_hotplug(dev, 0);
 }
 
 #endif
@@ -1097,6 +1141,23 @@
 }
 #endif
 
+/*
+ * format for ASCII PCI device identifiers:
+ *	PCI bus A devfn B
+ * where "A" is the PCI bus number, and "B" is the
+ * encoded slot/device-function number as found in the
+ * PCI device's devfn configuration register.
+ */
+void sprintf_pci_businfo (char *buf, struct bus_info *bi)
+{
+	if (!bi->u.pci.pdev)
+		buf[0] = 0;
+	else
+		sprintf (buf, "PCI bus %d devfn %d",
+			 bi->u.pci.pdev->bus->number,
+			 bi->u.pci.pdev->devfn);
+}
+
 void __init pci_init(void)
 {
 	struct pci_dev *dev;
@@ -1175,4 +1236,3 @@
 
 EXPORT_SYMBOL(isa_dma_bridge_buggy);
 EXPORT_SYMBOL(pci_pci_problems);
-
Index: linux_2_4/drivers/sbus/sbus.c
diff -u linux_2_4/drivers/sbus/sbus.c:1.1.1.1 linux_2_4/drivers/sbus/sbus.c:1.1.1.1.34.1
--- linux_2_4/drivers/sbus/sbus.c:1.1.1.1	Sun Oct 22 12:44:03 2000
+++ linux_2_4/drivers/sbus/sbus.c	Wed Nov  1 22:50:19 2000
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/businfo.h>
 
 #include <asm/system.h>
 #include <asm/sbus.h>
@@ -546,4 +547,23 @@
 		clock_probe();
 	}
 #endif
+}
+
+
+/*
+ * format for ASCII SBUS device identifiers:
+ *	SBUS bus A dev B slot C
+ * A - OBP node of SBUS
+ * B - OBP node of this device
+ * C - SBUS slot number
+ */
+void sprintf_sbus_businfo (char *buf, struct bus_info *bi)
+{
+	if (!bi->u.sbus.bus || !bi->u.sbus.dev)
+		buf[0] = 0;
+	else
+		sprintf (buf, "SBUS bus %d dev %d slot %d",
+			 bi->u.sbus.bus->prom_node,
+			 bi->u.sbus.dev->prom_node,
+			 bi->u.sbus.dev->slot);
 }


Index: linux_2_4/drivers/usb/usb.c
diff -u linux_2_4/drivers/usb/usb.c:1.1.1.12 linux_2_4/drivers/usb/usb.c:1.1.1.12.2.2
--- linux_2_4/drivers/usb/usb.c:1.1.1.12	Tue Oct 31 13:28:21 2000
+++ linux_2_4/drivers/usb/usb.c	Wed Nov  1 22:54:06 2000
@@ -574,7 +574,7 @@
 }
 
 
-#if	defined(CONFIG_KMOD) && defined(CONFIG_HOTPLUG)
+#ifdef CONFIG_HOTPLUG
 
 /*
  * USB hotplugging invokes what /proc/sys/kernel/hotplug says
@@ -639,9 +639,9 @@
  * cases, we know no other thread can recycle our address, since we must
  * already have been serialized enough to prevent that.
  */
-static void call_policy (char *verb, struct usb_device *dev)
+static void call_policy (struct usb_device *dev, int insert)
 {
-	char *argv [3], **envp, *buf, *scratch;
+	char *argv [4], *envp[8], *buf, *scratch;
 	int i = 0, value;
 
 	if (!hotplug_path [0])
@@ -652,27 +652,24 @@
 	}
 	if (!current->fs->root) {
 		/* statically linked USB is initted rather early */
-		dbg ("call_policy %s, num %d -- no FS yet", verb, dev->devnum);
+		dbg ("call_policy %s, num %d -- no FS yet",
+		     insert ? "add" : "del", dev->devnum);
 		return;
 	}
 	if (dev->devnum < 0) {
 		dbg ("device already deleted ??");
 		return;
 	}
-	if (!(envp = (char **) kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
-		dbg ("enomem");
-		return;
-	}
 	if (!(buf = kmalloc (256, GFP_KERNEL))) {
-		kfree (envp);
 		dbg ("enomem2");
 		return;
 	}
 
-	/* only one standardized param to hotplug command: type */
+	/* args: /sbin/hotplug [bus type] [add/del] */
 	argv [0] = hotplug_path;
 	argv [1] = "usb";
-	argv [2] = 0;
+	argv [2] = insert ? "add" : "del";
+	argv [3] = 0;
 
 	/* minimal command environment */
 	envp [i++] = "HOME=/";
@@ -687,10 +684,6 @@
 	 */
 	scratch = buf;
 
-	/* action:  add, remove */
-	envp [i++] = scratch;
-	scratch += sprintf (scratch, "ACTION=%s", verb) + 1;
-
 #ifdef	CONFIG_USB_DEVICEFS
 	/* If this is available, userspace programs can directly read
 	 * all the device descriptors we don't tell them about.  Or
@@ -742,7 +735,6 @@
 	dbg ("kusbd: %s %s %d", argv [0], verb, dev->devnum);
 	value = call_usermodehelper (argv [0], argv, envp);
 	kfree (buf);
-	kfree (envp);
 	if (value != 0)
 		dbg ("kusbd policy returned 0x%x", value);
 }
@@ -750,10 +742,10 @@
 #else
 
 static inline void
-call_policy (char *verb, struct usb_device *dev)
+call_policy (struct usb_device *dev, int insert)
 { } 
 
-#endif	/* KMOD && HOTPLUG */
+#endif /* CONFIG_HOTPLUG */
 
 
 /*
@@ -1520,7 +1512,7 @@
 	}
 
 	/* Let policy agent unload modules etc */
-	call_policy ("remove", dev);
+	call_policy (dev, 0);
 
 	/* Free the device number and remove the /proc/bus/usb entry */
 	if (dev->devnum > 0) {
@@ -2037,7 +2029,7 @@
 	usb_find_drivers(dev);
 
 	/* userspace may load modules and/or configure further */
-	call_policy ("add", dev);
+	call_policy (dev, 1);
 
 	return 0;
 }

Index: linux_2_4/fs/proc/Makefile
diff -u linux_2_4/fs/proc/Makefile:1.1.1.1 linux_2_4/fs/proc/Makefile:1.1.1.1.34.1
--- linux_2_4/fs/proc/Makefile:1.1.1.1	Sun Oct 22 12:35:07 2000
+++ linux_2_4/fs/proc/Makefile	Tue Oct 31 14:43:34 2000
@@ -9,7 +9,8 @@
 
 O_TARGET := proc.o
 O_OBJS   := inode.o root.o base.o generic.o array.o \
-		kmsg.o proc_tty.o proc_misc.o kcore.o
+		kmsg.o proc_tty.o proc_misc.o kcore.o \
+		businfo.o
 OX_OBJS  := procfs_syms.o
 M_OBJS   := 
 
Index: linux_2_4/fs/proc/businfo.c
diff -u /dev/null linux_2_4/fs/proc/businfo.c:1.1.6.2
--- /dev/null	Wed Nov  1 23:28:22 2000
+++ linux_2_4/fs/proc/businfo.c	Wed Nov  1 22:50:19 2000
@@ -0,0 +1,116 @@
+/*
+ * kernel/businfo.c
+ * Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/businfo.h>
+
+
+extern void sprintf_pci_businfo (char *buf, struct bus_info *bi);
+extern void sprintf_sbus_businfo (char *buf, struct bus_info *bi);
+
+
+#ifdef CONFIG_PROC_FS
+
+
+/* normally we put sprintf_$bus_businfo in a bus-specific module.  However there
+ * is no drivers/isa, so as a special case we put the following function here.
+ */
+#ifdef CONFIG_ISA
+/*
+ * format for ASCII ISA device identifiers:
+ *	ISA mem A irq B dma C port D
+ * A - An occupied 24-bit ISA memory area, in hexidecimal, or zero.
+ * B - An assigned irq number, in decimal, or zero.
+ * C - An assigned dma channel number, in decimal, or zero.
+ * D - The base of an I/O port range (as used with inb/outb),
+ *     in hexidecimal, or zero.
+ */
+static void sprintf_isa_businfo (char *buf, struct bus_info *bi)
+{
+	if (!bi->u.isa.mem && !bi->u.isa.irq &&
+	    !bi->u.isa.dma && !bi->u.isa.port)
+		buf[0] = 0;
+	else
+		sprintf (buf, "ISA mem %X irq %d dma %d port %X",
+			 bi->u.isa.mem,
+			 bi->u.isa.irq,
+			 bi->u.isa.dma,
+			 bi->u.isa.port);
+}
+#endif /* CONFIG_ISA */
+
+
+/* rule for userspace users: zero output is a valid return,
+ * which implies the bus info is unknown or unavailable
+ */
+int businfo_read_proc (char *buf, char **start, off_t fpos,
+		       int length, int *eof, struct bus_info *bi)
+{
+	size_t len;
+
+	switch (bi->bus_type) {
+#ifdef CONFIG_ISA
+	case BUSINFO_ISA:
+		sprintf_isa_businfo (buf, bi);
+		break;
+#endif
+
+#ifdef CONFIG_PCI
+	case BUSINFO_PCI:
+		sprintf_pci_businfo (buf, bi);
+		break;
+#endif
+
+#ifdef CONFIG_SBUS
+	case BUSINFO_SBUS:
+		sprintf_sbus_businfo (buf, bi);
+		break;
+#endif
+
+	default:
+		buf[0] = 0;
+		break;
+	}
+
+	len = strlen (buf);
+
+	if (fpos >= len) {
+		*start = buf;
+		*eof = 1;
+		return 0;
+	}
+
+	*start = buf + fpos;
+        if ((len -= fpos) > length)
+                return length;
+        *eof = 1;
+        return len;
+}
+
+
+#else /* CONFIG_PROC_FS */
+
+
+int businfo_read_proc (char *buf, char **start, off_t fpos,
+		       int length, int *eof, struct bus_info *bi)
+{
+	*eof = 1;
+	return 0;
+}
+
+
+#endif /* CONFIG_PROC_FS */
+
+EXPORT_SYMBOL(businfo_read_proc);
Index: linux_2_4/include/linux/businfo.h
diff -u /dev/null linux_2_4/include/linux/businfo.h:1.1.6.2
--- /dev/null	Wed Nov  1 23:28:35 2000
+++ linux_2_4/include/linux/businfo.h	Wed Nov  1 22:50:19 2000
@@ -0,0 +1,64 @@
+/*
+ * include/linux/businfo.h
+ * Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __LINUX_BUSINFO_H__
+#define __LINUX_BUSINFO_H__
+
+
+/* this is the only include allowed */
+#include <linux/types.h>
+
+
+enum {
+	BUSINFO_NULL = 0,	/* unknown or error */
+	BUSINFO_ISA,
+	BUSINFO_PCI,
+	BUSINFO_SBUS,
+};
+
+
+struct isa_bus_info {
+	u32 mem;		/* 24-bit, most significant 8 bits ignored */
+	u8 irq;
+	u8 dma;
+	u16 port;
+};
+
+
+struct pci_dev;
+struct pci_bus_info {
+	struct pci_dev *pdev;
+};
+
+
+struct sbus_bus;
+struct sbus_dev;
+struct sbus_bus_info {
+	struct sbus_bus *bus;
+	struct sbus_dev *dev;
+};
+
+
+struct bus_info {
+	unsigned int bus_type;
+	union {
+		struct isa_bus_info isa;
+		struct pci_bus_info pci;
+		struct sbus_bus_info sbus;
+	} u;
+};
+
+
+
+extern int businfo_read_proc (char *buf, char **start, off_t fpos,
+			      int length, int *eof, struct bus_info *bi);
+
+#endif /* __LINUX_BUSINFO_H__ */
Index: linux_2_4/include/linux/netdevice.h
diff -u linux_2_4/include/linux/netdevice.h:1.1.1.8 linux_2_4/include/linux/netdevice.h:1.1.1.8.2.2
--- linux_2_4/include/linux/netdevice.h:1.1.1.8	Tue Oct 31 13:19:43 2000
+++ linux_2_4/include/linux/netdevice.h	Wed Nov  1 22:50:19 2000
@@ -28,6 +28,7 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
+#include <linux/businfo.h>
 
 #include <asm/atomic.h>
 #include <asm/cache.h>
@@ -261,6 +262,9 @@
 	int			(*init)(struct net_device *dev);
 
 	/* ------- Fields preinitialized in Space.c finish here ------- */
+
+	/* Hardware bus identity, exported to userspace */
+	struct bus_info		bus_info;
 
 	struct net_device	*next_sched;
 
Index: linux_2_4/include/linux/pci.h
diff -u linux_2_4/include/linux/pci.h:1.1.1.2 linux_2_4/include/linux/pci.h:1.1.1.2.18.2
--- linux_2_4/include/linux/pci.h:1.1.1.2	Sun Oct 22 14:52:55 2000
+++ linux_2_4/include/linux/pci.h	Wed Nov  1 22:50:19 2000
@@ -286,6 +286,7 @@
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+#include <linux/businfo.h>
 
 /* This defines the direction arg to the DMA mapping routines. */
 #define PCI_DMA_BIDIRECTIONAL	0
 		    int (*)(struct pci_dev *, u8, u8));
+
 
 /* New-style probing supporting hot-pluggable devices */
 int pci_register_driver(struct pci_driver *);
Index: linux_2_4/init/main.c
diff -u linux_2_4/init/main.c:1.1.1.10 linux_2_4/init/main.c:1.1.1.10.6.1
--- linux_2_4/init/main.c:1.1.1.10	Fri Oct 27 00:37:39 2000
+++ linux_2_4/init/main.c	Wed Nov  1 22:50:19 2000
@@ -95,6 +95,7 @@
 extern void signals_init(void);
 extern void bdev_init(void);
 extern int init_pcmcia_ds(void);
+extern void net_notifier_init(void);
 
 extern void free_initmem(void);
 extern void filesystem_setup(void);
@@ -710,6 +711,13 @@
 #ifdef CONFIG_PCMCIA
 	init_pcmcia_ds();		/* Do this last */
 #endif
+
+	/* do this after other 'do this last' stuff, because we want
+	 * to minimize spurious executions of /sbin/network
+	 * during boot-up
+	 */
+	net_notifier_init();
+
 	/* Mount the root filesystem.. */
 	mount_root();
 
Index: linux_2_4/net/core/dev.c
diff -u linux_2_4/net/core/dev.c:1.1.1.8 linux_2_4/net/core/dev.c:1.1.1.8.4.2
--- linux_2_4/net/core/dev.c:1.1.1.8	Mon Oct 30 11:39:10 2000
+++ linux_2_4/net/core/dev.c	Wed Nov  1 22:50:19 2000
@@ -2253,6 +2253,23 @@
 	}
 }
 
+/**
+ *	netdev_proc_businfo	- output bus identity for a network device
+ *
+ *	This function is static inline because using its address in
+ *	create_proc_read_entry() call below forces it un-inlined...
+ *	Except for the !CONFIG_PROC_FS case, when it goes away completely.
+ *	XXX unverified...
+ */
+static inline int netdev_proc_businfo (char *buf, char **start, off_t fpos,
+				       int length, int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	return businfo_read_proc(buf, start, fpos, length, eof, &dev->bus_info);
+}
+
+
 static int dev_boot_phase = 1;
 
 /**
@@ -2276,9 +2293,8 @@
 int register_netdevice(struct net_device *dev)
 {
 	struct net_device *d, **dp;
-#ifdef CONFIG_NET_DIVERT
 	int ret;
-#endif
+	char businfo_fn[32];
 
 	spin_lock_init(&dev->queue_lock);
 	spin_lock_init(&dev->xmit_lock);
@@ -2331,9 +2347,16 @@
 
 	dev->iflink = -1;
 
+	/* register /proc/net/if/???/businfo */
+	/* we purposefully ignore create_proc_read_entry failure */
+	sprintf(businfo_fn, "net/if/%s/businfo", dev->name);
+	create_proc_read_entry(businfo_fn, 0, NULL, netdev_proc_businfo, dev);
+
 	/* Init, if this function is available */
-	if (dev->init && dev->init(dev) != 0)
-		return -EIO;
+	if (dev->init && dev->init(dev) != 0) {
+		ret = -EIO;
+		goto err_out;
+	}
 
 	dev->ifindex = dev_new_index();
 	if (dev->iflink == -1)
@@ -2342,7 +2365,8 @@
 	/* Check for existence, and append to tail of chain */
 	for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
 		if (d == dev || strcmp(d->name, dev->name) == 0) {
-			return -EEXIST;
+			ret = -EEXIST;
+			goto err_out;
 		}
 	}
 	/*
@@ -2371,13 +2395,17 @@
 #ifdef CONFIG_NET_DIVERT
 	ret = alloc_divert_blk(dev);
 	if (ret)
-		return ret;
+		goto err_out;
 #endif /* CONFIG_NET_DIVERT */
 	
 	/* Notify protocols, that a new device appeared. */
 	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
 
 	return 0;
+
+err_out:
+	remove_proc_entry(businfo_fn, NULL);
+	return ret;
 }
 
 /**
@@ -2423,6 +2451,7 @@
 
 int unregister_netdevice(struct net_device *dev)
 {
+	char businfo_fn[32];
 	unsigned long now, warning_time;
 	struct net_device *d, **dp;
 
@@ -2469,6 +2498,10 @@
 	if (dev->uninit)
 		dev->uninit(dev);
 
+	/* eliminate our /proc/net/if/???/businfo inode */
+	sprintf(businfo_fn, "net/if/%s/businfo", dev->name);
+	remove_proc_entry(businfo_fn, NULL);
+
 	/* Notifier chain MUST detach us from master device. */
 	BUG_TRAP(dev->master==NULL);
 
@@ -2687,4 +2720,64 @@
 	net_device_init();
 
 	return 0;
+}
+
+
+/* Notify userspace when a netdevice event occurs,
+ * by running /sbin/network [event] [interface]
+ * 'event' - an ASCII string indicating the type of event
+ * 'interface' - an ASCII string naming the interface on which
+ *	the event occurred.
+ * Currently reported events are listed in netdev_event_names[].
+ */
+
+/* /sbin/network ONLY executes for events named here */
+static char *netdev_event_names[] = {
+	[NETDEV_REGISTER]	= "register",
+	[NETDEV_UNREGISTER]	= "unregister",
+};
+
+/* FIXME: make this changeable like hotplug_path */
+char sbin_network_path[256] = "/sbin/network";
+
+static int run_sbin_network(struct notifier_block *this,
+			    unsigned long event, void *ptr)
+{
+	struct net_device *dev = (struct net_device *) ptr;
+	char *argv[4], *envp[3];
+	int i = 0;
+
+	if ((event >= ARRAY_SIZE(netdev_event_names)) ||
+	    !netdev_event_names[event])
+		return NOTIFY_DONE;
+
+	argv[0] = sbin_network_path;
+	argv[1] = netdev_event_names[event];
+	argv[2] = dev->name;
+	argv[3] = 0;
+	
+	/* minimal command environment */
+	envp [i++] = "HOME=/";
+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	envp [i] = 0;
+	
+	call_usermodehelper (argv [0], argv, envp);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sbin_network = {
+	notifier_call: run_sbin_network,
+};
+
+/*
+ * called from init/main.c, -after- all the initcalls are complete.
+ * Registers a hook that calls /sbin/network on every netdev
+ * addition and removal.
+ */
+void __init net_notifier_init (void)
+{
+	if (register_netdevice_notifier(&sbin_network))
+		printk (KERN_WARNING "unable to register netdev notifier\n"
+			KERN_WARNING "/sbin/network will not be run.\n");
 }

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH 2.4.0.10: Update hotplug
@ 2000-11-02 23:51 David Brownell
  2000-11-03  0:38 ` Jeff Garzik
  0 siblings, 1 reply; 6+ messages in thread
From: David Brownell @ 2000-11-02 23:51 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-kernel

I'm glad to see the CardBus/PCI and network hotplug
support start happening!

Would you motivate two changes I noticed?

    - Changing /sbin/hotplug invocations ... now it can
      only support "add" and "del" events.  (USB now
      uses "add" and "remove", though "remove" doesn't
      try to do anything yet.)

      This removes the intended flexibility whereby
      different subsystems (such as networking) can
      define their own events.

    - "/sbin/hotplug net ..." replaced by "/sbin/network",
      with two custom event types.

The original intent of /sbin/hotplug was to centralize all
the hotplug-related dispatching, addressing both the module
selection/loading problem and device config/setup aspects
of device setup.

By creating another hotplug command (/sbin/network) you're
starting down what seems a slippery slope, where there's
no longer a single dispatch point to enable/disable or
to debug from.  Why discard the, err, "conceptual unity"
of one access point for usermode hotplug policy agents?

- Dave



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH 2.4.0.10: Update hotplug
  2000-11-02 23:51 PATCH 2.4.0.10: " David Brownell
@ 2000-11-03  0:38 ` Jeff Garzik
  2000-11-03  4:35   ` David Brownell
  0 siblings, 1 reply; 6+ messages in thread
From: Jeff Garzik @ 2000-11-03  0:38 UTC (permalink / raw)
  To: David Brownell; +Cc: linux-kernel

David Brownell wrote:
>     - Changing /sbin/hotplug invocations ... now it can
>       only support "add" and "del" events.  (USB now
>       uses "add" and "remove", though "remove" doesn't
>       try to do anything yet.)
> 
>       This removes the intended flexibility whereby
>       different subsystems (such as networking) can
>       define their own events.

Wrong.  Different subsystems -do- define their own events.  However,
different subsystems should use the same verbs for the same actions.  We
need consistency where possible.


>     - "/sbin/hotplug net ..." replaced by "/sbin/network",
>       with two custom event types.

Hotplug device insertion and network interface addition/removal are two
fundamentally different things.  Further, my code purposefully does not
wrap CONFIG_HOTPLUG around the /sbin/network code, because /sbin/network
has utility outside the domain of hotplug.

	Jeff


-- 
Jeff Garzik             | Dinner is ready when
Building 1024           | the smoke alarm goes off.
MandrakeSoft            |	-/usr/games/fortune
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH 2.4.0.10: Update hotplug
  2000-11-03  0:38 ` Jeff Garzik
@ 2000-11-03  4:35   ` David Brownell
  0 siblings, 0 replies; 6+ messages in thread
From: David Brownell @ 2000-11-03  4:35 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-kernel

> >     - Changing /sbin/hotplug invocations ... now it can
> >       only support "add" and "del" events.  (USB now
> >       uses "add" and "remove", though "remove" doesn't
> >       try to do anything yet.)
> > 
> >       This removes the intended flexibility whereby
> >       different subsystems (such as networking) can
> >       define their own events.
> 
> Wrong.  Different subsystems -do- define their own events. 

I can't read your documentation that way, and you changed
some code that currently passes arbitrary event names into
code that passes magic numbers (0/1 for add/del).


>     However,
> different subsystems should use the same verbs for the same actions.
> We need consistency where possible.

So why change how it's _already_ being done?  And why change
the current policy about the use of /sbin/hotplug parameters?
(Described in kmod.c and the link from HOTPLUG config help.)

It's not that change is bad, but without motivation this one
seems to be gratuitous.  Why impose conversion costs, then?


> >     - "/sbin/hotplug net ..." replaced by "/sbin/network",
> >       with two custom event types.
> 
> Hotplug device insertion and network interface addition/removal are two
> fundamentally different things. 

No, they're the same thing at different levels.  It's telling
a subsystem to react to some entity that wasn't there before,
or which is going away:  hot plugging and unplugging.

You can easily see this by considering what happens when you
connect a USB network adapter.  (Similarly for a Cardbus one.)
Two invocations are needed:

    - From the USB subsystem:  "/sbin/hotplug usb add" tells
      usermode USB tools about the new USB device entity.

      At this level, tools know they _may_ need to choose and
      load a (network) driver; or, it might be in the kernel
      already, needing special setup (maybe load microcode
      or start a special service).  In this case, the driver
      creates a new network interface entity.

    - From the network subsystem:  "/sbin/hotplug net add"
      tells usermode networking tools about the new interface.

      At this level, tools know they may need to activate an
      existing configuration ("ifup eth0") or perhaps alert
      a sysadmin to create a new config.

They're just different subsystems; the "new thing!" alert is
the same event role in both cases.  No matter that the "thing"
differs (USB device vs. network interface) and that the event
receiver differs (USB tools vs. network tools).

If there is going to be any abstraction at all, it's got to be
blind to those particular details ... else every new subsystem
and device type will get new hotplug commands in /sbin and in
/proc/sys/kernel, with eventual chaos.


>     Further, my code purposefully does not
> wrap CONFIG_HOTPLUG around the /sbin/network code,

As we discussed separately, the CONFIG_{HOTPLUG,KMOD} coupling
there isn't quite separable because of how kmod works today.

You'll need CONFIG_HOTPLUG and CONFIG_KMOD unless you shift
some of the guts of kmod; which should happen, but maybe now
isn't the right time for that.


>     because /sbin/network
> has utility outside the domain of hotplug.

Again, not according to the documentation you included; but
then, it doesn't really talk about /sbin/network except to
say that it's used to report additions/removals.  Which is
what /sbin/hotplug was defined to handle ... :-)

- Dave





-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* PATCH 2.4.0.10 v2: Update hotplug
  2000-11-02  8:05 PATCH 2.4.0.10: Update hotplug Jeff Garzik
  2000-11-02  8:01 ` David S. Miller
@ 2000-11-04  7:49 ` Jeff Garzik
  1 sibling, 0 replies; 6+ messages in thread
From: Jeff Garzik @ 2000-11-04  7:49 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Linus Torvalds, David S. Miller, David Hinds, randy.dunlap, mj,
	David Brownell

[-- Attachment #1: Type: text/plain, Size: 1142 bytes --]

Attached is a revised "hotplug update" patch, against 2.4.0-test10. 
It's looking close to submit-able now.

General change description is the same as the first patch, which can be
found at
http://boudicca.tux.org/hypermail/linux-kernel/this-week/0785.html

Changes since the first patch:
* CONFIG_HOTPLUG and CONFIG_KMOD are now totally independent.  It was an
incestuous relationship anyway.
* exec_usermodehelper and call_usermodehelper are now unconditionally
present
* new file Documentation/networking/netdevices.txt describes
/sbin/network usage, and netdevice locking
* usb supports ACTION=$verb again, for compatibility with existing
implementation
* don't use magic numbers for 'insert' value in code, use TRUE/FALSE
* ditch the sbus slot number
* use '/' separate in PCI environment variables, for consistency with
USB
* eliminate EXPORT_SYMBOL(hotplug_path), modules don't need it
* constify netdev_event_name[] array

Now, time to track down that elusive thing called sleep... :)

-- 
Jeff Garzik             | Dinner is ready when
Building 1024           | the smoke alarm goes off.
MandrakeSoft            |	-/usr/games/fortune

[-- Attachment #2: hotplug-2.4.0.10-2.patch --]
[-- Type: text/plain, Size: 28351 bytes --]

Index: linux_2_4/Documentation/00-INDEX
diff -u linux_2_4/Documentation/00-INDEX:1.1.1.1 linux_2_4/Documentation/00-INDEX:1.1.1.1.34.1
--- linux_2_4/Documentation/00-INDEX:1.1.1.1	Sun Oct 22 12:47:49 2000
+++ linux_2_4/Documentation/00-INDEX	Wed Nov  1 22:50:19 2000
@@ -53,6 +53,8 @@
 	- notes about the floppy tape device driver
 hayes-esp.txt
 	- info on using the Hayes ESP serial driver.
+hotplug.txt
+	- kernel hotplug support
 i386/
 	- directory with info about Linux on the intel ix86 architecture.
 ide.txt
Index: linux_2_4/Documentation/hotplug.txt
diff -u /dev/null linux_2_4/Documentation/hotplug.txt:1.1.2.2
--- /dev/null	Fri Nov  3 23:12:53 2000
+++ linux_2_4/Documentation/hotplug.txt	Fri Nov  3 23:12:03 2000
@@ -0,0 +1,92 @@
+
+Hot-Plug Devices, the Kernel, and You!
+
+
+Introduction
+============
+Kernel version 2.4.0 and later includes native support for hotpluggable
+devices.  This text documents that support.
+
+FIXME: turn this random collection of notes into a real document
+
+Supported hot-plug buses:  CardBus (in the PCI subsystem), USB.
+
+Hot-plug code is conditionally included when CONFIG_HOTPLUG is enabled
+in 'make config'.  CONFIG_HOTPLUG now requires CONFIG_KMOD, so it is
+automatically defined when CONFIG_HOTPLUG is enabled.
+
+
+/sbin/hotplug
+=============
+When hotpluggable hardware devices are added or removed, /sbin/hotplug
+is executed by the kernel.  The usage of /sbin/hotplug is as follows:
+
+	/sbin/hotplug [bus] [event]
+
+[bus] - The bus on which the hotpluggable event occurred.  Supported
+bus types are:
+
+	usb	- USB
+	pci	- PCI-compatible hot-plug:  CardBus
+
+[event] - Type of hot-plug event
+
+	add	- Device insertion
+	del	- Device removal
+
+In addition to the standard arguments passed to /sbin/hotplug as
+described above, each bus has its own set of environment variables
+which are passed to the program.
+
+hotplug pci env vars
+--------------------
+HOME=/
+	Hardcoded value.
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+	Hardcoded value.
+PCI_CLASS=$CLASS
+	$CLASS - PCI device class, in hexidecimal
+PCI_ID=$VENDOR/$DEVICE
+	$VENDOR	- 16-bit PCI device vendor id, in hexidecimal
+	$DEVICE	- 16-bit PCI device id, in hexidecimal
+PCI_SUBSYS_ID=$VENDOR/$DEVICE
+	$VENDOR	- 16-bit PCI device subsystem vendor id, in hexidecimal
+	$DEVICE	- 16-bit PCI device subsystem device id, in hexidecimal
+PCI_BUS_ID=$BUS/$SLOT/$FUNC
+	$BUS	- PCI bus number, in decimal
+	$SLOT	- PCI device slot, decoded from devfn, in decimal
+	$FUNC	- PCI device function, decoded from devfn, in decimal
+
+
+hotplug usb env vars
+--------------------
+HOME=/
+	Hardcoded value.
+PATH=/sbin:/bin:/usr/sbin:/usr/bin
+	Hardcoded value.
+DEBUG=kernel
+	Hardcoded value.  Only present if USB is in debug mode
+DEVFS=/proc/bus/usb
+	Hardcoded value.  Only present if CONFIG_USB_DEVICEFS is set.
+DEVICE=/proc/bus/usb/$BUS/$DEVICE
+	Indicates the assigned USB device node for the USB device.
+	Only present if CONFIG_USB_DEVICEFS is set.
+	$BUS	- USB bus number
+	$DEVICE	- USB device number
+PRODUCT=$VENDOR/$PRODUCT/$DEVICE
+	USB device identification info.
+	$VENDOR	- USB vendor id, in hexadecimal
+	$PRODUCT- USB product ID, in hexadecimal
+	$DEVICE	- Binary-coded decimal device number
+TYPE=$CLASS/$SUB/$PROTO
+	Only present if device class is non-zero.
+	$CLASS	- USB device class.
+	$SUB	- USB device sub-class.
+	$PROTO	- USB device protocol number.
+INTERFACE=$CLASS/$SUB/$PROTO
+	Only present if device class is zero.
+	Only the first interface (interface 0) is presented.
+	$CLASS	- USB interface 0 class.
+	$SUB	- USB interface 0 sub-class.
+	$PROTO	- USB interface 0 protocol number.
+
Index: linux_2_4/Documentation/networking/00-INDEX
diff -u linux_2_4/Documentation/networking/00-INDEX:1.1.1.1 linux_2_4/Documentation/networking/00-INDEX:1.1.1.1.34.2
--- linux_2_4/Documentation/networking/00-INDEX:1.1.1.1	Sun Oct 22 12:48:03 2000
+++ linux_2_4/Documentation/networking/00-INDEX	Fri Nov  3 23:12:03 2000
@@ -54,10 +54,14 @@
 	- Behaviour of cards under Multicast
 ncsa-telnet
 	- notes on how NCSA telnet (DOS) breaks with MTU discovery enabled.
+netdevices.txt
+	- notes on developing and using network devices
 net-modules.txt
 	- info and "insmod" parameters for all network driver modules.
 policy-routing.txt
 	- IP policy-based routing
+proc-net-if.txt
+	- Description of /proc/net/if/* contents
 pt.txt
 	- the Gracilis Packetwin AX.25 device driver
 routing.txt
Index: linux_2_4/Documentation/networking/netdevices.txt
diff -u /dev/null linux_2_4/Documentation/networking/netdevices.txt:1.1.2.1
--- /dev/null	Fri Nov  3 23:12:55 2000
+++ linux_2_4/Documentation/networking/netdevices.txt	Fri Nov  3 23:12:03 2000
@@ -0,0 +1,69 @@
+
+Network Devices, the Kernel, and You!
+
+
+Introduction
+============
+The following is a random collection of documentation regarding
+network devices.
+
+
+/sbin/network
+=============
+When network devices (interfaces) are added or removed, /sbin/network
+is executed by the kernel.  The usage of /sbin/network is as follows:
+
+	/sbin/network [netdev-event] [interface]
+
+[netdev-event] - any one of the follow one-word ASCII strings:
+
+	register	- New device [interface] was just added
+	unregister	- Device [interface] was just removed
+
+/sbin/network is executed by the kernel when all such events occur --
+after bootup.  Register and un-register events which occur during
+bootup, including initcalls, do not cause /sbin/network to be executed.
+
+The return value of /sbin/network is ignored by the kernel, and the
+file does not have to exist.  No errors or warnings will be issued
+by the kernel is /sbin/network execution fails in any way.
+
+Developers can change the events which cause /sbin/network to be
+executed in net/core/dev.c, netdev_event_names[] array.
+
+
+struct net_device synchronization rules
+=======================================
+dev->open:
+	Locking: Inside rtnl_lock() semaphore.
+	Sleeping: OK
+
+dev->stop:
+	Locking: Inside rtnl_lock() semaphore.
+	Sleeping: OK
+
+dev->do_ioctl:
+	Locking: Inside rtnl_lock() semaphore.
+	Sleeping: OK
+
+dev->get_stats:
+	Locking: Inside dev_base_lock spinlock.
+	Sleeping: NO
+
+dev->hard_start_xmit:
+	Locking: Inside dev->xmit_lock spinlock.
+	Sleeping: NO[1]
+
+dev->tx_timeout:
+	Locking: Inside dev->xmit_lock spinlock.
+	Sleeping: NO[1]
+
+dev->set_multicast_list:
+	Locking: Inside dev->xmit_lock spinlock.
+	Sleeping: NO[1]
+
+
+NOTE [1]: On principle, you should not sleep when a spinlock is held.
+However, since this spinlock is per-net-device, we only block ourselves
+if we sleep, so the effect is mitigated.
+
Index: linux_2_4/Documentation/networking/proc-net-if.txt
diff -u /dev/null linux_2_4/Documentation/networking/proc-net-if.txt:1.1.2.1
--- /dev/null	Fri Nov  3 23:12:55 2000
+++ linux_2_4/Documentation/networking/proc-net-if.txt	Wed Nov  1 23:04:19 2000
@@ -0,0 +1,20 @@
+Contents of /proc/net/if/*:
+
+/proc/net/if is a container for per-interface procfs information.
+Each interface has its own directory, which contains the following
+pseudo-files:
+
+businfo
+	- Outputs a bus-specific string describing the hardware device
+	which owns this network interface.  Zero bytes are output if
+	no hardware info is associated with the network device.
+
+Examples:
+
+	$ cat /proc/net/if/eth0/businfo
+	PCI bus 0 devfn 0
+	$
+
+	$ cat /proc/net/if/lo/businfo
+	$
+
Index: linux_2_4/drivers/net/epic100.c
diff -u linux_2_4/drivers/net/epic100.c:1.1.1.6 linux_2_4/drivers/net/epic100.c:1.1.1.6.18.2
--- linux_2_4/drivers/net/epic100.c:1.1.1.6	Sun Oct 22 14:55:54 2000
+++ linux_2_4/drivers/net/epic100.c	Wed Nov  1 22:50:19 2000
@@ -491,6 +491,10 @@
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->tx_timeout = &epic_tx_timeout;
 
+	dev->bus_info.u.pci.pdev = pdev;
+	wmb();
+	dev->bus_info.bus_type = BUSINFO_PCI;
+
 	return 0;
 
 #ifndef USE_IO_OPS
Index: linux_2_4/drivers/pci/pci.c
diff -u linux_2_4/drivers/pci/pci.c:1.1.1.6 linux_2_4/drivers/pci/pci.c:1.1.1.6.6.3
--- linux_2_4/drivers/pci/pci.c:1.1.1.6	Fri Oct 27 00:45:05 2000
+++ linux_2_4/drivers/pci/pci.c	Fri Nov  3 23:12:03 2000
@@ -20,6 +20,8 @@
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
+#include <linux/businfo.h>
+#include <linux/kmod.h>		/* for hotplug_path */
 
 #include <asm/page.h>
 #include <asm/dma.h>	/* isa_dma_bridge_buggy */
@@ -343,6 +345,47 @@
 
 #ifdef CONFIG_HOTPLUG
 
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+static void
+run_sbin_hotplug(struct pci_dev *pdev, int insert)
+{
+	char *argv[4], *envp[6];
+	char id[32], sub_id[32], bus_id[32], class_id[32];
+	int i;
+
+	if (!hotplug_path[0])
+		return;
+
+	sprintf(class_id, "PCI_CLASS=%X", pdev->class >> 8);
+	sprintf(id, "PCI_ID=%X/%X", pdev->vendor, pdev->device);
+	sprintf(sub_id, "PCI_SUBSYS_ID=%X/%X", pdev->subsystem_vendor, pdev->subsystem_device);
+	sprintf(bus_id, "PCI_BUS_ID=%d/%d/%d", pdev->bus->number,
+		PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
+
+	i = 0;
+	argv[i++] = hotplug_path;
+	argv[i++] = "pci";
+	argv[i++] = insert ? "add" : "del";
+	argv[i] = 0;
+
+	i = 0;
+	/* minimal command environment */
+	envp[i++] = "HOME=/";
+	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	
+	/* other stuff we want to pass to /sbin/hotplug */
+	envp[i++] = id;
+	envp[i++] = sub_id;
+	envp[i++] = bus_id;
+	envp[i] = 0;
+
+	call_usermodehelper (argv [0], argv, envp);
+}
+
 void
 pci_insert_device(struct pci_dev *dev, struct pci_bus *bus)
 {
@@ -358,9 +401,13 @@
 		if (drv->remove && pci_announce_device(drv, dev))
 			break;
 	}
+
+	/* notify userspace of new hotplug device */
+	run_sbin_hotplug(dev, TRUE);
 }
 
-static void pci_free_resources(struct pci_dev *dev)
+static void
+pci_free_resources(struct pci_dev *dev)
 {
 	int i;
 
@@ -385,6 +432,9 @@
 #ifdef CONFIG_PROC_FS
 	pci_proc_detach_device(dev);
 #endif
+
+	/* notify userspace of hotplug device removal */
+	run_sbin_hotplug(dev, FALSE);
 }
 
 #endif
@@ -1096,6 +1146,24 @@
 	return 0;
 }
 #endif
+
+/*
+ * format for ASCII PCI device identifiers:
+ *	PCI bus A slot B func C
+ * A - PCI device's bus number
+ * B - PCI device's slot number
+ * C - PCI device function's function number
+ */
+void sprintf_pci_businfo (char *buf, struct bus_info *bi)
+{
+	if (!bi->u.pci.pdev)
+		buf[0] = 0;
+	else
+		sprintf (buf, "PCI bus %d slot %d func %d",
+			 bi->u.pci.pdev->bus->number,
+			 PCI_SLOT(bi->u.pci.pdev->devfn),
+			 PCI_FUNC(bi->u.pci.pdev->devfn));
+}
 
 void __init pci_init(void)
 {
Index: linux_2_4/drivers/sbus/sbus.c
diff -u linux_2_4/drivers/sbus/sbus.c:1.1.1.1 linux_2_4/drivers/sbus/sbus.c:1.1.1.1.34.2
--- linux_2_4/drivers/sbus/sbus.c:1.1.1.1	Sun Oct 22 12:44:03 2000
+++ linux_2_4/drivers/sbus/sbus.c	Fri Nov  3 23:12:03 2000
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/businfo.h>
 
 #include <asm/system.h>
 #include <asm/sbus.h>
@@ -546,4 +547,21 @@
 		clock_probe();
 	}
 #endif
+}
+
+
+/*
+ * format for ASCII SBUS device identifiers:
+ *	SBUS bus A dev B
+ * A - OBP node of SBUS
+ * B - OBP node of this device
+ */
+void sprintf_sbus_businfo (char *buf, struct bus_info *bi)
+{
+	if (!bi->u.sbus.bus || !bi->u.sbus.dev)
+		buf[0] = 0;
+	else
+		sprintf (buf, "SBUS bus %d dev %d",
+			 bi->u.sbus.bus->prom_node,
+			 bi->u.sbus.dev->prom_node);
 }
Index: linux_2_4/drivers/usb/usb.c
diff -u linux_2_4/drivers/usb/usb.c:1.1.1.12 linux_2_4/drivers/usb/usb.c:1.1.1.12.2.3
--- linux_2_4/drivers/usb/usb.c:1.1.1.12	Tue Oct 31 13:28:21 2000
+++ linux_2_4/drivers/usb/usb.c	Fri Nov  3 23:12:04 2000
@@ -574,7 +574,7 @@
 }
 
 
-#if	defined(CONFIG_KMOD) && defined(CONFIG_HOTPLUG)
+#ifdef CONFIG_HOTPLUG
 
 /*
  * USB hotplugging invokes what /proc/sys/kernel/hotplug says
@@ -623,6 +623,13 @@
 	return retval;
 }
 
+
+/* defined for users of call_policy() */
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
 /*
  * This invokes a user mode policy agent, typically helping to load driver
  * or other modules, configure the device, or both.
@@ -639,9 +646,9 @@
  * cases, we know no other thread can recycle our address, since we must
  * already have been serialized enough to prevent that.
  */
-static void call_policy (char *verb, struct usb_device *dev)
+static void call_policy (struct usb_device *dev, int insert)
 {
-	char *argv [3], **envp, *buf, *scratch;
+	char *argv [4], *envp[8], *buf, *scratch;
 	int i = 0, value;
 
 	if (!hotplug_path [0])
@@ -652,27 +659,24 @@
 	}
 	if (!current->fs->root) {
 		/* statically linked USB is initted rather early */
-		dbg ("call_policy %s, num %d -- no FS yet", verb, dev->devnum);
+		dbg ("call_policy %s, num %d -- no FS yet",
+		     insert ? "add" : "del", dev->devnum);
 		return;
 	}
 	if (dev->devnum < 0) {
 		dbg ("device already deleted ??");
 		return;
 	}
-	if (!(envp = (char **) kmalloc (20 * sizeof (char *), GFP_KERNEL))) {
-		dbg ("enomem");
-		return;
-	}
 	if (!(buf = kmalloc (256, GFP_KERNEL))) {
-		kfree (envp);
 		dbg ("enomem2");
 		return;
 	}
 
-	/* only one standardized param to hotplug command: type */
+	/* args: /sbin/hotplug [bus type] [add/del] */
 	argv [0] = hotplug_path;
 	argv [1] = "usb";
-	argv [2] = 0;
+	argv [2] = insert ? "add" : "del";
+	argv [3] = 0;
 
 	/* minimal command environment */
 	envp [i++] = "HOME=/";
@@ -689,7 +693,7 @@
 
 	/* action:  add, remove */
 	envp [i++] = scratch;
-	scratch += sprintf (scratch, "ACTION=%s", verb) + 1;
+	scratch += sprintf (scratch, "ACTION=%s", insert ? "add" : "remove") + 1;
 
 #ifdef	CONFIG_USB_DEVICEFS
 	/* If this is available, userspace programs can directly read
@@ -742,7 +746,6 @@
 	dbg ("kusbd: %s %s %d", argv [0], verb, dev->devnum);
 	value = call_usermodehelper (argv [0], argv, envp);
 	kfree (buf);
-	kfree (envp);
 	if (value != 0)
 		dbg ("kusbd policy returned 0x%x", value);
 }
@@ -750,10 +753,10 @@
 #else
 
 static inline void
-call_policy (char *verb, struct usb_device *dev)
+call_policy (struct usb_device *dev, int insert)
 { } 
 
-#endif	/* KMOD && HOTPLUG */
+#endif /* CONFIG_HOTPLUG */
 
 
 /*
@@ -1520,7 +1523,7 @@
 	}
 
 	/* Let policy agent unload modules etc */
-	call_policy ("remove", dev);
+	call_policy (dev, FALSE);
 
 	/* Free the device number and remove the /proc/bus/usb entry */
 	if (dev->devnum > 0) {
@@ -2037,7 +2040,7 @@
 	usb_find_drivers(dev);
 
 	/* userspace may load modules and/or configure further */
-	call_policy ("add", dev);
+	call_policy (dev, TRUE);
 
 	return 0;
 }
Index: linux_2_4/fs/proc/Makefile
diff -u linux_2_4/fs/proc/Makefile:1.1.1.1 linux_2_4/fs/proc/Makefile:1.1.1.1.34.1
--- linux_2_4/fs/proc/Makefile:1.1.1.1	Sun Oct 22 12:35:07 2000
+++ linux_2_4/fs/proc/Makefile	Tue Oct 31 14:43:34 2000
@@ -9,7 +9,8 @@
 
 O_TARGET := proc.o
 O_OBJS   := inode.o root.o base.o generic.o array.o \
-		kmsg.o proc_tty.o proc_misc.o kcore.o
+		kmsg.o proc_tty.o proc_misc.o kcore.o \
+		businfo.o
 OX_OBJS  := procfs_syms.o
 M_OBJS   := 
 
Index: linux_2_4/fs/proc/businfo.c
diff -u /dev/null linux_2_4/fs/proc/businfo.c:1.1.6.2
--- /dev/null	Fri Nov  3 23:13:25 2000
+++ linux_2_4/fs/proc/businfo.c	Wed Nov  1 22:50:19 2000
@@ -0,0 +1,116 @@
+/*
+ * kernel/businfo.c
+ * Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/businfo.h>
+
+
+extern void sprintf_pci_businfo (char *buf, struct bus_info *bi);
+extern void sprintf_sbus_businfo (char *buf, struct bus_info *bi);
+
+
+#ifdef CONFIG_PROC_FS
+
+
+/* normally we put sprintf_$bus_businfo in a bus-specific module.  However there
+ * is no drivers/isa, so as a special case we put the following function here.
+ */
+#ifdef CONFIG_ISA
+/*
+ * format for ASCII ISA device identifiers:
+ *	ISA mem A irq B dma C port D
+ * A - An occupied 24-bit ISA memory area, in hexidecimal, or zero.
+ * B - An assigned irq number, in decimal, or zero.
+ * C - An assigned dma channel number, in decimal, or zero.
+ * D - The base of an I/O port range (as used with inb/outb),
+ *     in hexidecimal, or zero.
+ */
+static void sprintf_isa_businfo (char *buf, struct bus_info *bi)
+{
+	if (!bi->u.isa.mem && !bi->u.isa.irq &&
+	    !bi->u.isa.dma && !bi->u.isa.port)
+		buf[0] = 0;
+	else
+		sprintf (buf, "ISA mem %X irq %d dma %d port %X",
+			 bi->u.isa.mem,
+			 bi->u.isa.irq,
+			 bi->u.isa.dma,
+			 bi->u.isa.port);
+}
+#endif /* CONFIG_ISA */
+
+
+/* rule for userspace users: zero output is a valid return,
+ * which implies the bus info is unknown or unavailable
+ */
+int businfo_read_proc (char *buf, char **start, off_t fpos,
+		       int length, int *eof, struct bus_info *bi)
+{
+	size_t len;
+
+	switch (bi->bus_type) {
+#ifdef CONFIG_ISA
+	case BUSINFO_ISA:
+		sprintf_isa_businfo (buf, bi);
+		break;
+#endif
+
+#ifdef CONFIG_PCI
+	case BUSINFO_PCI:
+		sprintf_pci_businfo (buf, bi);
+		break;
+#endif
+
+#ifdef CONFIG_SBUS
+	case BUSINFO_SBUS:
+		sprintf_sbus_businfo (buf, bi);
+		break;
+#endif
+
+	default:
+		buf[0] = 0;
+		break;
+	}
+
+	len = strlen (buf);
+
+	if (fpos >= len) {
+		*start = buf;
+		*eof = 1;
+		return 0;
+	}
+
+	*start = buf + fpos;
+        if ((len -= fpos) > length)
+                return length;
+        *eof = 1;
+        return len;
+}
+
+
+#else /* CONFIG_PROC_FS */
+
+
+int businfo_read_proc (char *buf, char **start, off_t fpos,
+		       int length, int *eof, struct bus_info *bi)
+{
+	*eof = 1;
+	return 0;
+}
+
+
+#endif /* CONFIG_PROC_FS */
+
+EXPORT_SYMBOL(businfo_read_proc);
Index: linux_2_4/include/linux/businfo.h
diff -u /dev/null linux_2_4/include/linux/businfo.h:1.1.6.2
--- /dev/null	Fri Nov  3 23:13:26 2000
+++ linux_2_4/include/linux/businfo.h	Wed Nov  1 22:50:19 2000
@@ -0,0 +1,64 @@
+/*
+ * include/linux/businfo.h
+ * Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License
+ *	as published by the Free Software Foundation; either version
+ *	2 of the License, or (at your option) any later version.
+ *
+ */
+
+#ifndef __LINUX_BUSINFO_H__
+#define __LINUX_BUSINFO_H__
+
+
+/* this is the only include allowed */
+#include <linux/types.h>
+
+
+enum {
+	BUSINFO_NULL = 0,	/* unknown or error */
+	BUSINFO_ISA,
+	BUSINFO_PCI,
+	BUSINFO_SBUS,
+};
+
+
+struct isa_bus_info {
+	u32 mem;		/* 24-bit, most significant 8 bits ignored */
+	u8 irq;
+	u8 dma;
+	u16 port;
+};
+
+
+struct pci_dev;
+struct pci_bus_info {
+	struct pci_dev *pdev;
+};
+
+
+struct sbus_bus;
+struct sbus_dev;
+struct sbus_bus_info {
+	struct sbus_bus *bus;
+	struct sbus_dev *dev;
+};
+
+
+struct bus_info {
+	unsigned int bus_type;
+	union {
+		struct isa_bus_info isa;
+		struct pci_bus_info pci;
+		struct sbus_bus_info sbus;
+	} u;
+};
+
+
+
+extern int businfo_read_proc (char *buf, char **start, off_t fpos,
+			      int length, int *eof, struct bus_info *bi);
+
+#endif /* __LINUX_BUSINFO_H__ */
Index: linux_2_4/include/linux/netdevice.h
diff -u linux_2_4/include/linux/netdevice.h:1.1.1.8 linux_2_4/include/linux/netdevice.h:1.1.1.8.2.2
--- linux_2_4/include/linux/netdevice.h:1.1.1.8	Tue Oct 31 13:19:43 2000
+++ linux_2_4/include/linux/netdevice.h	Wed Nov  1 22:50:19 2000
@@ -28,6 +28,7 @@
 #include <linux/if.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
+#include <linux/businfo.h>
 
 #include <asm/atomic.h>
 #include <asm/cache.h>
@@ -261,6 +262,9 @@
 	int			(*init)(struct net_device *dev);
 
 	/* ------- Fields preinitialized in Space.c finish here ------- */
+
+	/* Hardware bus identity, exported to userspace */
+	struct bus_info		bus_info;
 
 	struct net_device	*next_sched;
 
Index: linux_2_4/init/main.c
diff -u linux_2_4/init/main.c:1.1.1.10 linux_2_4/init/main.c:1.1.1.10.6.1
--- linux_2_4/init/main.c:1.1.1.10	Fri Oct 27 00:37:39 2000
+++ linux_2_4/init/main.c	Wed Nov  1 22:50:19 2000
@@ -95,6 +95,7 @@
 extern void signals_init(void);
 extern void bdev_init(void);
 extern int init_pcmcia_ds(void);
+extern void net_notifier_init(void);
 
 extern void free_initmem(void);
 extern void filesystem_setup(void);
@@ -710,6 +711,13 @@
 #ifdef CONFIG_PCMCIA
 	init_pcmcia_ds();		/* Do this last */
 #endif
+
+	/* do this after other 'do this last' stuff, because we want
+	 * to minimize spurious executions of /sbin/network
+	 * during boot-up
+	 */
+	net_notifier_init();
+
 	/* Mount the root filesystem.. */
 	mount_root();
 
Index: linux_2_4/kernel/Makefile
diff -u linux_2_4/kernel/Makefile:1.1.1.3 linux_2_4/kernel/Makefile:1.1.1.3.24.2
--- linux_2_4/kernel/Makefile:1.1.1.3	Sun Oct 22 14:00:25 2000
+++ linux_2_4/kernel/Makefile	Fri Nov  3 23:12:04 2000
@@ -12,14 +12,10 @@
 	    module.o exit.o itimer.o info.o time.o softirq.o resource.o \
 	    sysctl.o acct.o capability.o ptrace.o timer.o user.o
 
-OX_OBJS  += signal.o sys.o
+OX_OBJS  += signal.o sys.o kmod.o
 
 ifeq ($(CONFIG_UID16),y)
 O_OBJS += uid16.o
-endif
-
-ifeq ($(CONFIG_KMOD),y)
-O_OBJS += kmod.o
 endif
 
 ifeq ($(CONFIG_MODULES),y)
Index: linux_2_4/kernel/kmod.c
diff -u linux_2_4/kernel/kmod.c:1.1.1.6 linux_2_4/kernel/kmod.c:1.1.1.6.18.1
--- linux_2_4/kernel/kmod.c:1.1.1.6	Sun Oct 22 14:52:47 2000
+++ linux_2_4/kernel/kmod.c	Fri Nov  3 23:12:04 2000
@@ -16,17 +16,13 @@
 #define __KERNEL_SYSCALLS__
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/unistd.h>
 #include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
-/*
-	modprobe_path is set via /proc/sys.
-*/
-char modprobe_path[256] = "/sbin/modprobe";
-
 extern int max_threads;
 
 static inline void
@@ -130,6 +126,13 @@
 	return 0;
 }
 
+#ifdef CONFIG_KMOD
+
+/*
+	modprobe_path is set via /proc/sys.
+*/
+char modprobe_path[256] = "/sbin/modprobe";
+
 static int exec_modprobe(void * module_name)
 {
 	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
@@ -226,6 +229,7 @@
 	}
 	return 0;
 }
+#endif /* CONFIG_KMOD */
 
 
 #ifdef CONFIG_HOTPLUG
@@ -247,6 +251,8 @@
 */
 char hotplug_path[256] = "/sbin/hotplug";
 
+#endif /* CONFIG_HOTPLUG */
+
 
 static int exec_helper (void *arg)
 {
@@ -286,5 +292,10 @@
 	return retval;
 }
 
+EXPORT_SYMBOL(exec_usermodehelper);
+EXPORT_SYMBOL(call_usermodehelper);
+
+#ifdef CONFIG_KMOD
+EXPORT_SYMBOL(request_module);
 #endif
 
Index: linux_2_4/kernel/ksyms.c
diff -u linux_2_4/kernel/ksyms.c:1.1.1.10 linux_2_4/kernel/ksyms.c:1.1.1.10.4.1
--- linux_2_4/kernel/ksyms.c:1.1.1.10	Mon Oct 30 11:37:29 2000
+++ linux_2_4/kernel/ksyms.c	Fri Nov  3 23:12:04 2000
@@ -71,15 +71,6 @@
 #endif
 
 
-#ifdef CONFIG_KMOD
-EXPORT_SYMBOL(request_module);
-EXPORT_SYMBOL(exec_usermodehelper);
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(hotplug_path);
-EXPORT_SYMBOL(call_usermodehelper);
-#endif
-#endif
-
 #ifdef CONFIG_MODULES
 EXPORT_SYMBOL(get_module_symbol);
 EXPORT_SYMBOL(put_module_symbol);
Index: linux_2_4/kernel/sysctl.c
diff -u linux_2_4/kernel/sysctl.c:1.1.1.7 linux_2_4/kernel/sysctl.c:1.1.1.7.2.1
--- linux_2_4/kernel/sysctl.c:1.1.1.7	Tue Oct 31 13:19:30 2000
+++ linux_2_4/kernel/sysctl.c	Fri Nov  3 23:12:04 2000
@@ -54,10 +54,10 @@
 
 #ifdef CONFIG_KMOD
 extern char modprobe_path[];
+#endif
 #ifdef CONFIG_HOTPLUG
 extern char hotplug_path[];
 #endif
-#endif
 #ifdef CONFIG_CHR_DEV_SG
 extern int sg_big_buff;
 #endif
@@ -188,10 +188,10 @@
 #ifdef CONFIG_KMOD
 	{KERN_MODPROBE, "modprobe", &modprobe_path, 256,
 	 0644, NULL, &proc_dostring, &sysctl_string },
+#endif
 #ifdef CONFIG_HOTPLUG
 	{KERN_HOTPLUG, "hotplug", &hotplug_path, 256,
 	 0644, NULL, &proc_dostring, &sysctl_string },
-#endif
 #endif
 #ifdef CONFIG_CHR_DEV_SG
 	{KERN_SG_BIG_BUFF, "sg-big-buff", &sg_big_buff, sizeof (int),
Index: linux_2_4/net/core/dev.c
diff -u linux_2_4/net/core/dev.c:1.1.1.8 linux_2_4/net/core/dev.c:1.1.1.8.4.3
--- linux_2_4/net/core/dev.c:1.1.1.8	Mon Oct 30 11:39:10 2000
+++ linux_2_4/net/core/dev.c	Fri Nov  3 23:12:04 2000
@@ -2253,6 +2253,23 @@
 	}
 }
 
+/**
+ *	netdev_proc_businfo	- output bus identity for a network device
+ *
+ *	This function is static inline because using its address in
+ *	create_proc_read_entry() call below forces it un-inlined...
+ *	Except for the !CONFIG_PROC_FS case, when it goes away completely.
+ *	XXX unverified...
+ */
+static inline int netdev_proc_businfo (char *buf, char **start, off_t fpos,
+				       int length, int *eof, void *data)
+{
+	struct net_device *dev = data;
+	
+	return businfo_read_proc(buf, start, fpos, length, eof, &dev->bus_info);
+}
+
+
 static int dev_boot_phase = 1;
 
 /**
@@ -2276,9 +2293,8 @@
 int register_netdevice(struct net_device *dev)
 {
 	struct net_device *d, **dp;
-#ifdef CONFIG_NET_DIVERT
 	int ret;
-#endif
+	char businfo_fn[32];
 
 	spin_lock_init(&dev->queue_lock);
 	spin_lock_init(&dev->xmit_lock);
@@ -2331,9 +2347,16 @@
 
 	dev->iflink = -1;
 
+	/* register /proc/net/if/???/businfo */
+	/* we purposefully ignore create_proc_read_entry failure */
+	sprintf(businfo_fn, "net/if/%s/businfo", dev->name);
+	create_proc_read_entry(businfo_fn, 0, NULL, netdev_proc_businfo, dev);
+
 	/* Init, if this function is available */
-	if (dev->init && dev->init(dev) != 0)
-		return -EIO;
+	if (dev->init && dev->init(dev) != 0) {
+		ret = -EIO;
+		goto err_out;
+	}
 
 	dev->ifindex = dev_new_index();
 	if (dev->iflink == -1)
@@ -2342,7 +2365,8 @@
 	/* Check for existence, and append to tail of chain */
 	for (dp=&dev_base; (d=*dp) != NULL; dp=&d->next) {
 		if (d == dev || strcmp(d->name, dev->name) == 0) {
-			return -EEXIST;
+			ret = -EEXIST;
+			goto err_out;
 		}
 	}
 	/*
@@ -2371,13 +2395,17 @@
 #ifdef CONFIG_NET_DIVERT
 	ret = alloc_divert_blk(dev);
 	if (ret)
-		return ret;
+		goto err_out;
 #endif /* CONFIG_NET_DIVERT */
 	
 	/* Notify protocols, that a new device appeared. */
 	notifier_call_chain(&netdev_chain, NETDEV_REGISTER, dev);
 
 	return 0;
+
+err_out:
+	remove_proc_entry(businfo_fn, NULL);
+	return ret;
 }
 
 /**
@@ -2423,6 +2451,7 @@
 
 int unregister_netdevice(struct net_device *dev)
 {
+	char businfo_fn[32];
 	unsigned long now, warning_time;
 	struct net_device *d, **dp;
 
@@ -2469,6 +2498,10 @@
 	if (dev->uninit)
 		dev->uninit(dev);
 
+	/* eliminate our /proc/net/if/???/businfo inode */
+	sprintf(businfo_fn, "net/if/%s/businfo", dev->name);
+	remove_proc_entry(businfo_fn, NULL);
+
 	/* Notifier chain MUST detach us from master device. */
 	BUG_TRAP(dev->master==NULL);
 
@@ -2687,4 +2720,64 @@
 	net_device_init();
 
 	return 0;
+}
+
+
+/* Notify userspace when a netdevice event occurs,
+ * by running /sbin/network [event] [interface]
+ * 'event' - an ASCII string indicating the type of event
+ * 'interface' - an ASCII string naming the interface on which
+ *	the event occurred.
+ * Currently reported events are listed in netdev_event_names[].
+ */
+
+/* /sbin/network ONLY executes for events named here */
+static const char *netdev_event_names[] = {
+	[NETDEV_REGISTER]	= "register",
+	[NETDEV_UNREGISTER]	= "unregister",
+};
+
+/* FIXME: make this changeable like hotplug_path */
+char sbin_network_path[256] = "/sbin/network";
+
+static int run_sbin_network(struct notifier_block *this,
+			    unsigned long event, void *ptr)
+{
+	struct net_device *dev = (struct net_device *) ptr;
+	char *argv[4], *envp[3];
+	int i = 0;
+
+	if ((event >= ARRAY_SIZE(netdev_event_names)) ||
+	    !netdev_event_names[event])
+		return NOTIFY_DONE;
+
+	argv[0] = sbin_network_path;
+	argv[1] = netdev_event_names[event];
+	argv[2] = dev->name;
+	argv[3] = 0;
+	
+	/* minimal command environment */
+	envp [i++] = "HOME=/";
+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	envp [i] = 0;
+	
+	call_usermodehelper (argv [0], argv, envp);
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block sbin_network = {
+	notifier_call: run_sbin_network,
+};
+
+/*
+ * called from init/main.c, -after- all the initcalls are complete.
+ * Registers a hook that calls /sbin/network on every netdev
+ * addition and removal.
+ */
+void __init net_notifier_init (void)
+{
+	if (register_netdevice_notifier(&sbin_network))
+		printk (KERN_WARNING "unable to register netdev notifier\n"
+			KERN_WARNING "/sbin/network will not be run.\n");
 }

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2000-11-04  7:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-11-02  8:05 PATCH 2.4.0.10: Update hotplug Jeff Garzik
2000-11-02  8:01 ` David S. Miller
2000-11-04  7:49 ` PATCH 2.4.0.10 v2: " Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2000-11-02 23:51 PATCH 2.4.0.10: " David Brownell
2000-11-03  0:38 ` Jeff Garzik
2000-11-03  4:35   ` David Brownell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox