svn commit: r301451 - in head/sys: kern sys

Svatopluk Kraus skra at FreeBSD.org
Sun Jun 5 16:07:59 UTC 2016


Author: skra
Date: Sun Jun  5 16:07:57 2016
New Revision: 301451
URL: https://svnweb.freebsd.org/changeset/base/301451

Log:
  (1) Add a new bus method to get a mapping data for an interrupt.
  
  BUS_MAP_INTR() is used to get an interrupt mapping data according
  to provided hints. The hints could be modified afterwards, but only
  if mapping data was allocated. This method is intended to be called
  before BUS_ALLOC_RESOURCE().
  
  An interrupt mapping data describes an interrupt - hardware number,
  type, configuration, cpu binding, and whatever is needed to setup it.
  
  (2) Introduce a method which allows storing of an additional data
  in struct resource to be available for bus drivers. This method is
  convenient in two ways:
   - there is no need to rework existing bus drivers as they can simply
     be extended to provide an additional data,
   - there is no need to modify any existing bus methods as struct
     resource is already passed to them as argument and thus stored data
     is simply accessible by other bus drivers.
  For now, implement this method only for INTRNG.
  
  This is motivated by needs of modern SOCs where hardware initialization
  is not straightforward and resources descriptions are complex, opaque
  for everyone but provider, and may vary from SOC to SOC. Typical
  situation is that one bus driver can fetch a resource description for
  its child device, but it's opaque for this driver. Another bus driver
  knows a provider for this kind of resource and can pass this resource
  description to it. In fact, something like device IVARS would be
  perfect for that if implemented generally enough. Unfortunatelly, IVARS
  are usable only by their owners now. Only owner knows its IVARS layout,
  thus other bus drivers are not able to use them.
  
  Differential Revision:	https://reviews.freebsd.org/D6632

Modified:
  head/sys/kern/bus_if.m
  head/sys/kern/subr_bus.c
  head/sys/kern/subr_intr.c
  head/sys/sys/bus.h
  head/sys/sys/intr.h

Modified: head/sys/kern/bus_if.m
==============================================================================
--- head/sys/kern/bus_if.m	Sun Jun  5 15:57:32 2016	(r301450)
+++ head/sys/kern/bus_if.m	Sun Jun  5 16:07:57 2016	(r301451)
@@ -418,6 +418,35 @@ METHOD int release_resource {
 };
 
 /**
+ * @brief Map an interrupt
+ *
+ * This method is used to get an interrupt mapping data according to provided
+ * hints. The hints could be modified afterwards, but only if mapping data was
+ * allocated. This method is intended to be called before BUS_ALLOC_RESOURCE().
+ *
+ * @param _dev		the parent device of @p _child
+ * @param _child	the device which is requesting an allocation
+ * @param _rid		a pointer to the resource identifier
+ * @param _start	a pointer to the hint at the start of the resource
+ *			range - pass @c 0 for any start address
+ * @param _end		a pointer to the hint at the end of the resource
+ *			range - pass @c ~0 for any end address
+ * @param _count	a pointer to the hint at the size of resource
+ *			range required - pass @c 1 for any size
+ * @param _imd		a pointer to the interrupt mapping data which was
+ *			allocated
+ */
+METHOD int map_intr {
+	device_t	_dev;
+	device_t	_child;
+	int		*_rid;
+	rman_res_t	*_start;
+	rman_res_t	*_end;
+	rman_res_t	*_count;
+	struct intr_map_data **_imd;
+} DEFAULT bus_generic_map_intr;
+
+/**
  * @brief Install an interrupt handler
  *
  * This method is used to associate an interrupt handler function with

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c	Sun Jun  5 15:57:32 2016	(r301450)
+++ head/sys/kern/subr_bus.c	Sun Jun  5 16:07:57 2016	(r301451)
@@ -3951,6 +3951,23 @@ bus_generic_new_pass(device_t dev)
 }
 
 /**
+ * @brief Helper function for implementing BUS_MAP_INTR().
+ *
+ * This simple implementation of BUS_MAP_INTR() simply calls the
+ * BUS_MAP_INTR() method of the parent of @p dev.
+ */
+int
+bus_generic_map_intr(device_t dev, device_t child, int *rid, rman_res_t *start,
+    rman_res_t *end, rman_res_t *count, struct intr_map_data **imd)
+{
+	/* Propagate up the bus hierarchy until someone handles it. */
+	if (dev->parent)
+		return (BUS_MAP_INTR(dev->parent, child, rid, start, end, count,
+		    imd));
+	return (EINVAL);
+}
+
+/**
  * @brief Helper function for implementing BUS_SETUP_INTR().
  *
  * This simple implementation of BUS_SETUP_INTR() simply calls the
@@ -4405,6 +4422,41 @@ bus_release_resources(device_t dev, cons
 		}
 }
 
+#ifdef INTRNG
+/**
+ * @internal
+ *
+ * This can be converted to bus method later. (XXX)
+ */
+static struct intr_map_data *
+bus_extend_resource(device_t dev, int type, int *rid, rman_res_t *start,
+    rman_res_t *end, rman_res_t *count)
+{
+	struct intr_map_data *imd;
+	struct resource_list *rl;
+	int rv;
+
+	if (dev->parent == NULL)
+		return (NULL);
+	if (type != SYS_RES_IRQ)
+		return (NULL);
+
+	if (!RMAN_IS_DEFAULT_RANGE(*start, *end))
+		return (NULL);
+	rl = BUS_GET_RESOURCE_LIST(dev->parent, dev);
+	if (rl != NULL) {
+		if (resource_list_find(rl, type, *rid) != NULL)
+			return (NULL);
+	}
+	rv = BUS_MAP_INTR(dev->parent, dev, rid, start, end, count, &imd);
+	if (rv != 0)
+		return (NULL);
+	if (rl != NULL)
+		resource_list_add(rl, type, *rid, *start, *end, *count);
+	return (imd);
+}
+#endif
+
 /**
  * @brief Wrapper function for BUS_ALLOC_RESOURCE().
  *
@@ -4412,13 +4464,31 @@ bus_release_resources(device_t dev, cons
  * parent of @p dev.
  */
 struct resource *
-bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start, rman_res_t end,
-    rman_res_t count, u_int flags)
+bus_alloc_resource(device_t dev, int type, int *rid, rman_res_t start,
+    rman_res_t end, rman_res_t count, u_int flags)
 {
+	struct resource *res;
+#ifdef INTRNG
+	struct intr_map_data *imd;
+#endif
+
 	if (dev->parent == NULL)
 		return (NULL);
-	return (BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
-	    count, flags));
+
+#ifdef INTRNG
+	imd = bus_extend_resource(dev, type, rid, &start, &end, &count);
+#endif
+	res = BUS_ALLOC_RESOURCE(dev->parent, dev, type, rid, start, end,
+	    count, flags);
+#ifdef INTRNG
+	if (imd != NULL) {
+		if (res != NULL && rman_get_virtual(res) == NULL)
+			rman_set_virtual(res, imd);
+		else
+			imd->destruct(imd);
+	}
+#endif
+	return (res);
 }
 
 /**
@@ -4503,9 +4573,23 @@ bus_unmap_resource(device_t dev, int typ
 int
 bus_release_resource(device_t dev, int type, int rid, struct resource *r)
 {
+	int rv;
+#ifdef INTRNG
+	struct intr_map_data *imd;
+#endif
+
 	if (dev->parent == NULL)
 		return (EINVAL);
-	return (BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r));
+
+#ifdef INTRNG
+	imd = (type == SYS_RES_IRQ) ? rman_get_virtual(r) : NULL;
+#endif
+	rv = BUS_RELEASE_RESOURCE(dev->parent, dev, type, rid, r);
+#ifdef INTRNG
+	if (imd != NULL)
+		imd->destruct(imd);
+#endif
+	return (rv);
 }
 
 /**

Modified: head/sys/kern/subr_intr.c
==============================================================================
--- head/sys/kern/subr_intr.c	Sun Jun  5 15:57:32 2016	(r301450)
+++ head/sys/kern/subr_intr.c	Sun Jun  5 16:07:57 2016	(r301451)
@@ -560,7 +560,6 @@ intr_ddata_alloc(u_int extsize)
 	mtx_unlock(&isrc_table_lock);
 
 	ddata->idd_data = (struct intr_map_data *)((uintptr_t)ddata + size);
-	ddata->idd_data->size = extsize;
 	return (ddata);
 }
 

Modified: head/sys/sys/bus.h
==============================================================================
--- head/sys/sys/bus.h	Sun Jun  5 15:57:32 2016	(r301450)
+++ head/sys/sys/bus.h	Sun Jun  5 16:07:57 2016	(r301451)
@@ -272,6 +272,17 @@ enum intr_polarity {
 	INTR_POLARITY_LOW = 2
 };
 
+enum intr_map_data_type {
+	INTR_MAP_DATA_ACPI,
+	INTR_MAP_DATA_FDT,
+	INTR_MAP_DATA_GPIO,
+};
+
+struct intr_map_data {
+	enum intr_map_data_type	type;
+	void (*destruct)(struct intr_map_data *);
+};
+
 /**
  * CPU sets supported by bus_get_cpus().  Note that not all sets may be
  * supported for a given device.  If a request is not supported by a
@@ -448,6 +459,9 @@ int	bus_generic_release_resource(device_
 				     int type, int rid, struct resource *r);
 int	bus_generic_resume(device_t dev);
 int	bus_generic_resume_child(device_t dev, device_t child);
+int	bus_generic_map_intr(device_t dev, device_t child, int *rid,
+			      rman_res_t *start, rman_res_t *end,
+			      rman_res_t *count, struct intr_map_data **imd);
 int	bus_generic_setup_intr(device_t dev, device_t child,
 			       struct resource *irq, int flags,
 			       driver_filter_t *filter, driver_intr_t *intr, 

Modified: head/sys/sys/intr.h
==============================================================================
--- head/sys/sys/intr.h	Sun Jun  5 15:57:32 2016	(r301450)
+++ head/sys/sys/intr.h	Sun Jun  5 16:07:57 2016	(r301451)
@@ -34,17 +34,6 @@
 
 #define	INTR_IRQ_INVALID	0xFFFFFFFF
 
-enum intr_map_data_type {
-	INTR_MAP_DATA_ACPI,
-	INTR_MAP_DATA_FDT,
-	INTR_MAP_DATA_GPIO,
-};
-
-struct intr_map_data {
-	enum intr_map_data_type	type;
-	size_t			size;
-};
-
 #ifdef DEV_ACPI
 struct intr_map_data_acpi {
 	struct intr_map_data	hdr;


More information about the svn-src-all mailing list