Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Jan 2018 17:09:12 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r327835 - in head/sys: arm/arm arm64/arm64 conf dev/acpica
Message-ID:  <201801111709.w0BH9CrD027510@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Thu Jan 11 17:09:12 2018
New Revision: 327835
URL: https://svnweb.freebsd.org/changeset/base/327835

Log:
  Add the start of INTRNG support for ACPI.
  
  This adds a new acpi_bus interface with a map_intr method. This is similar
  to the Open Firmware map_intr method and allows us to create the needed
  mapping from ACPI space to INTRNG space.
  
  Obtained from:	ABT Systems Ltd
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D8617

Added:
  head/sys/dev/acpica/acpi_bus_if.m   (contents, props changed)
Modified:
  head/sys/arm/arm/generic_timer.c
  head/sys/arm64/arm64/nexus.c
  head/sys/conf/files.arm64
  head/sys/dev/acpica/acpi.c
  head/sys/dev/acpica/acpi_resource.c
  head/sys/dev/acpica/acpivar.h

Modified: head/sys/arm/arm/generic_timer.c
==============================================================================
--- head/sys/arm/arm/generic_timer.c	Thu Jan 11 16:50:03 2018	(r327834)
+++ head/sys/arm/arm/generic_timer.c	Thu Jan 11 17:09:12 2018	(r327835)
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
 #ifdef DEV_ACPI
 #include <contrib/dev/acpica/include/acpi.h>
 #include <dev/acpica/acpivar.h>
+#include "acpi_bus_if.h"
 #endif
 
 #define	GT_CTRL_ENABLE		(1 << 0)
@@ -313,6 +314,15 @@ arm_tmr_fdt_probe(device_t dev)
 
 #ifdef DEV_ACPI
 static void
+arm_tmr_acpi_add_irq(device_t parent, device_t dev, int rid, u_int irq)
+{
+
+	irq = ACPI_BUS_MAP_INTR(parent, dev, irq,
+		INTR_TRIGGER_LEVEL, INTR_POLARITY_HIGH);
+	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, rid, irq, 1);
+}
+
+static void
 arm_tmr_acpi_identify(driver_t *driver, device_t parent)
 {
 	ACPI_TABLE_GTDT *gtdt;
@@ -336,12 +346,9 @@ arm_tmr_acpi_identify(driver_t *driver, device_t paren
 		goto out;
 	}
 
-	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 0,
-	    gtdt->SecureEl1Interrupt, 1);
-	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 1,
-	    gtdt->NonSecureEl1Interrupt, 1);
-	BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, 2,
-	    gtdt->VirtualTimerInterrupt, 1);
+	arm_tmr_acpi_add_irq(parent, dev, 0, gtdt->SecureEl1Interrupt);
+	arm_tmr_acpi_add_irq(parent, dev, 1, gtdt->NonSecureEl1Interrupt);
+	arm_tmr_acpi_add_irq(parent, dev, 2, gtdt->VirtualTimerInterrupt);
 
 out:
 	acpi_unmap_table(gtdt);

Modified: head/sys/arm64/arm64/nexus.c
==============================================================================
--- head/sys/arm64/arm64/nexus.c	Thu Jan 11 16:50:03 2018	(r327834)
+++ head/sys/arm64/arm64/nexus.c	Thu Jan 11 17:09:12 2018	(r327835)
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
 #ifdef DEV_ACPI
 #include <contrib/dev/acpica/include/acpi.h>
 #include <dev/acpica/acpivar.h>
+#include "acpi_bus_if.h"
 #endif
 
 extern struct bus_space memmap_bus;
@@ -460,11 +461,16 @@ nexus_ofw_map_intr(device_t dev, device_t child, phand
 #endif
 
 #ifdef DEV_ACPI
+static int nexus_acpi_map_intr(device_t dev, device_t child, u_int irq, int trig, int pol);
+
 static device_method_t nexus_acpi_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		nexus_acpi_probe),
 	DEVMETHOD(device_attach,	nexus_acpi_attach),
 
+	/* ACPI interface */
+	DEVMETHOD(acpi_bus_map_intr,	nexus_acpi_map_intr),
+
 	DEVMETHOD_END,
 };
 
@@ -494,5 +500,31 @@ nexus_acpi_attach(device_t dev)
 
 	nexus_add_child(dev, 10, "acpi", 0);
 	return (nexus_attach(dev));
+}
+
+static int
+nexus_acpi_map_intr(device_t dev, device_t child, u_int irq, int trig, int pol)
+{
+	struct intr_map_data_acpi *acpi_data;
+	size_t len;
+
+	len = sizeof(*acpi_data);
+	acpi_data = (struct intr_map_data_acpi *)intr_alloc_map_data(
+	    INTR_MAP_DATA_ACPI, len, M_WAITOK | M_ZERO);
+	acpi_data->irq = irq;
+	acpi_data->pol = pol;
+	acpi_data->trig = trig;
+
+	/*
+	 * TODO: This will only handle a single interrupt controller.
+	 * ACPI will map multiple controllers into a single virtual IRQ
+	 * space. Each controller has a System Vector Base to hold the
+	 * first irq it handles in this space. As such the correct way
+	 * to handle interrupts with ACPI is to search through the
+	 * controllers for the largest base value that is no larger than
+	 * the IRQ value.
+	 */
+	irq = intr_map_irq(NULL, 0, (struct intr_map_data *)acpi_data);
+	return (irq);
 }
 #endif

Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64	Thu Jan 11 16:50:03 2018	(r327834)
+++ head/sys/conf/files.arm64	Thu Jan 11 17:09:12 2018	(r327835)
@@ -167,6 +167,7 @@ armv8_crypto_wrap.o		optional	armv8crypto		\
 	clean		"armv8_crypto_wrap.o"
 crypto/blowfish/bf_enc.c	optional	crypto | ipsec | ipsec_support
 crypto/des/des_enc.c		optional	crypto | ipsec | ipsec_support | netsmb
+dev/acpica/acpi_bus_if.m	optional	acpi
 dev/acpica/acpi_if.m		optional	acpi
 dev/ahci/ahci_generic.c		optional	ahci
 dev/axgbe/if_axgbe.c		optional	axgbe

Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c	Thu Jan 11 16:50:03 2018	(r327834)
+++ head/sys/dev/acpica/acpi.c	Thu Jan 11 17:09:12 2018	(r327835)
@@ -1358,7 +1358,9 @@ static struct resource *
 acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
 {
+#ifndef INTRNG
     ACPI_RESOURCE ares;
+#endif
     struct acpi_device *ad;
     struct resource_list_entry *rle;
     struct resource_list *rl;
@@ -1385,6 +1387,7 @@ acpi_alloc_resource(device_t bus, device_t child, int 
 		resource_list_add(rl, type, *rid, start, end, count);
 	res = resource_list_alloc(rl, bus, child, type, rid, start, end, count,
 	    flags);
+#ifndef INTRNG
 	if (res != NULL && type == SYS_RES_IRQ) {
 	    /*
 	     * Since bus_config_intr() takes immediate effect, we cannot
@@ -1397,6 +1400,7 @@ acpi_alloc_resource(device_t bus, device_t child, int 
 	    if (ACPI_SUCCESS(acpi_lookup_irq_resource(child, *rid, res, &ares)))
 		acpi_config_intr(child, &ares);
 	}
+#endif
 
 	/*
 	 * If this is an allocation of the "default" range for a given

Added: head/sys/dev/acpica/acpi_bus_if.m
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/acpica/acpi_bus_if.m	Thu Jan 11 17:09:12 2018	(r327835)
@@ -0,0 +1,67 @@
+#-
+# Copyright (c) 2016 The FreeBSD Foundation
+# All rights reserved.
+#
+# This software was developed by Andrew Turner under
+# sponsorship from the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+INTERFACE acpi_bus;
+
+CODE {
+	static acpi_bus_map_intr_t acpi_bus_default_map_intr;
+
+	int
+	acpi_bus_default_map_intr(device_t bus, device_t dev, u_int irq,
+	    int trig, int pol)
+	{
+		device_t parent;
+
+		/* Pass up the hierarchy */
+		parent = device_get_parent(bus);
+		if (parent != NULL)
+			return (ACPI_BUS_MAP_INTR(parent, dev, irq, trig, pol));
+
+		panic("Unable to map interrupt %u", irq);
+	}
+};
+
+# Map an interrupt from ACPI space to the FreeBSD IRQ space. Note that
+# both of these may be different than the pysical interrupt space as this
+# may be local to each interrupt controller.
+#
+# This method also associates interrupt metadata with the interrupt,
+# removing the need for a post hoc configure step.
+METHOD int map_intr {
+	device_t bus;
+	device_t dev;
+	u_int irq;
+	int trig;
+	int pol;
+} DEFAULT acpi_bus_default_map_intr;

Modified: head/sys/dev/acpica/acpi_resource.c
==============================================================================
--- head/sys/dev/acpica/acpi_resource.c	Thu Jan 11 16:50:03 2018	(r327834)
+++ head/sys/dev/acpica/acpi_resource.c	Thu Jan 11 17:09:12 2018	(r327835)
@@ -45,6 +45,10 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/acpica/acpivar.h>
 
+#ifdef INTRNG
+#include "acpi_bus_if.h"
+#endif
+
 /* Hooks for the ACPI CA debugging infrastructure */
 #define _COMPONENT	ACPI_BUS
 ACPI_MODULE_NAME("RESOURCE")
@@ -556,6 +560,7 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t 
     int trig, int pol)
 {
     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
+    rman_res_t intr;
 
     if (cp == NULL || irq == NULL)
 	return;
@@ -564,7 +569,14 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t 
     if (count != 1)
 	return;
 
-    bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
+#ifdef INTRNG
+    intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
+	(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
+	(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
+#else
+    intr = *irq;
+#endif
+    bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
 }
 
 static void
@@ -572,6 +584,7 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint
     int trig, int pol)
 {
     struct acpi_res_context	*cp = (struct acpi_res_context *)context;
+    rman_res_t intr;
 
     if (cp == NULL || irq == NULL)
 	return;
@@ -580,7 +593,14 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint
     if (count != 1)
 	return;
 
-    bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
+#ifdef INTRNG
+    intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
+	(trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
+	(pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
+#else
+    intr = *irq;
+#endif
+    bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
 }
 
 static void

Modified: head/sys/dev/acpica/acpivar.h
==============================================================================
--- head/sys/dev/acpica/acpivar.h	Thu Jan 11 16:50:03 2018	(r327834)
+++ head/sys/dev/acpica/acpivar.h	Thu Jan 11 17:09:12 2018	(r327835)
@@ -36,6 +36,9 @@
 #include "acpi_if.h"
 #include "bus_if.h"
 #include <sys/eventhandler.h>
+#ifdef INTRNG
+#include <sys/intr.h>
+#endif
 #include <sys/ktr.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
@@ -90,6 +93,16 @@ struct acpi_device {
     /* Resources */
     struct resource_list	ad_rl;
 };
+
+#ifdef INTRNG
+struct intr_map_data_acpi {
+	struct intr_map_data	hdr;
+	u_int			irq;
+	u_int			pol;
+	u_int			trig;
+};
+
+#endif
 
 /* Track device (/dev/{apm,apmctl} and /dev/acpi) notification status. */
 struct apm_clone_data {



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