Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Jul 2017 10:19:38 -0700
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-drivers@freebsd.org
Cc:        Krishna Yenduri <kyenduri@brkt.com>
Subject:   Re: ACPI mediated Hotplug?
Message-ID:  <3585281.TQq0CdjIrL@ralph.baldwin.cx>
In-Reply-To: <3DDBEFB3-AB51-4AD2-845D-A8B81ECB417A@brkt.com>
References:  <3DDBEFB3-AB51-4AD2-845D-A8B81ECB417A@brkt.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Monday, May 22, 2017 11:12:43 AM Krishna Yenduri wrote:
> Hi Folks,
> 
>  I have a AWS instance (m4.large) running FreeBSD 11.0-STABLE-amd64-2017-04-20.
>  The system came up with a primary interface ixv0. Per pciconf -
> 
>  ixv0@pci0:0:3:0:       class=0x020000 card=0x00000000 chip=0x10ed8086 rev=0x01 hdr=0x00
>     vendor     = 'Intel Corporation'
>     device     = '82599 Ethernet Controller Virtual Function'
>     class      = network
>     subclass   = ethernet
> 
> 
>  I attached another network interface while the system is up. But, it does
>  not show up in the pciconf -l output. Doing
>         # devctl rescan pci0
>  causes it to appear.
> 
>  I want to make the interface appear automatically rather
>  than having to run the devctl command. BTW, this works on Linux.
>  Is there a way to use the ACPI framework in FreeBSD so
>  that the Hotplug happens automatically?
> 
>  DTracing shows that adding a new interface triggers calls to
>  AcpiEvSciXruptHandler and AcpiEvAsynchExecuteGpeMethod.
>  Is it safe to add a hook in to pci_rescan_method() from these
>  routines? Any pointers to the ACPI<->FreeBSD kernel interface
>  are much appreciated.

It is possible to support HotPlug via ACPI, however it is a bit more involved
than that.  There are ACPI methods for handling hotplug that are generic to
ACPI (not PCI specific) which on some systems handle PCI hotplug.  I believe
there is a section discussing it in the ACPI spec.  More details are present in
the "Device Insertion, Removal, and Status Objects" section of the "Device
Configuration" section of the ACPI spec (at least as of 6.1).  You might be
able to make this work by installing a notify handler in the ACPI PCI bus
driver (sys/dev/acpica/acpi_pci.c) and triggering a rescan in response to
notifications with a value of 0.  Something like this perhaps (untested):

Index: acpi_pci.c
===================================================================
--- acpi_pci.c	(revision 321295)
+++ acpi_pci.c	(working copy)
@@ -71,9 +71,11 @@ CTASSERT(ACPI_STATE_D2 == PCI_POWERSTATE_D2);
 CTASSERT(ACPI_STATE_D3 == PCI_POWERSTATE_D3);
 
 static struct pci_devinfo *acpi_pci_alloc_devinfo(device_t dev);
+static int	acpi_pci_attach(device_t dev);
 static void	acpi_pci_child_deleted(device_t dev, device_t child);
 static int	acpi_pci_child_location_str_method(device_t cbdev,
 		    device_t child, char *buf, size_t buflen);
+static int	acpi_pci_detach(device_t dev);
 static int	acpi_pci_probe(device_t dev);
 static int	acpi_pci_read_ivar(device_t dev, device_t child, int which,
 		    uintptr_t *result);
@@ -89,6 +91,8 @@ static bus_dma_tag_t acpi_pci_get_dma_tag(device_t
 static device_method_t acpi_pci_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		acpi_pci_probe),
+	DEVMETHOD(device_attach,	acpi_pci_attach),
+	DEVMETHOD(device_detach,	acpi_pci_detach),
 
 	/* Bus interface */
 	DEVMETHOD(bus_read_ivar,	acpi_pci_read_ivar),
@@ -326,6 +330,45 @@ acpi_pci_probe(device_t dev)
 	return (BUS_PROBE_DEFAULT);
 }
 
+static void
+acpi_pcib_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context)
+{
+	device_t dev;
+
+	dev = context;
+
+	switch (notify) {
+	case ACPI_NOTIFY_BUS_CHECK:
+		BUS_RESCAN(dev);
+		break;
+	default:
+		device_printf(dev, "unknown notify %#x\n", notify);
+		break;
+	}
+}
+
+static int
+acpi_pci_attach(device_t dev)
+{
+	int error;
+
+	error = pci_attach(dev);
+	if (error)
+		return (error);
+	AcpiInstallNotifyHandler(acpi_get_handle(dev), ACPI_DEVICE_NOTIFY,
+	    acpi_pci_notify_handler, dev);
+	return (0);
+}
+
+static int
+acpi_pci_detach(device_t dev)
+{
+
+	AcpiRemoveNotifyHandler(acpi_get_handle(dev), ACPI_DEVICE_NOTIFY,
+				acpi_pci_notify_handler);
+	return (pci_detach(dev));
+}
+
 #ifdef ACPI_DMAR
 bus_dma_tag_t dmar_get_dma_tag(device_t dev, device_t child);
 static bus_dma_tag_t



-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3585281.TQq0CdjIrL>