public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* 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

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