git: 1fb99e97e959 - main - bus: Make BUS_TRANSLATE_RESOURCE behave more like other bus methods

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 15 Nov 2021 18:02:56 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=1fb99e97e959a51306fd216a41977079d4689665

commit 1fb99e97e959a51306fd216a41977079d4689665
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-11-15 16:29:49 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-11-15 18:01:30 +0000

    bus: Make BUS_TRANSLATE_RESOURCE behave more like other bus methods
    
    - Return an errno value upon failure, instead of 1.
    - Provide a bus_translate_resource() wrapper.
    - Implement the generic version, which traverses the hierarchy until a
      bus driver with a non-trivial implementation is found, in subr_bus.c
      like other similar default implementations.
    - Make ofw_pcib_translate_resource() return an error if a matching PCI
      address range is not found.
    - Make generic_pcie_translate_resource_common() return an int instead of
      a bool.  Fix up callers.
    
    No functional change intended.
    
    Reviewed by:    imp, jhb
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32855
---
 sys/compat/linuxkpi/common/src/linux_pci.c |  9 +++++---
 sys/dev/ofw/ofw_pcib.c                     |  6 +++---
 sys/dev/pci/pci_host_generic.c             | 19 +++++++++--------
 sys/dev/pci/pci_user.c                     |  2 +-
 sys/kern/bus_if.m                          | 18 ++++------------
 sys/kern/subr_bus.c                        | 33 ++++++++++++++++++++++++++++++
 sys/sys/bus.h                              |  2 ++
 7 files changed, 60 insertions(+), 29 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_pci.c b/sys/compat/linuxkpi/common/src/linux_pci.c
index db94bc08239e..8ec6a5af2140 100644
--- a/sys/compat/linuxkpi/common/src/linux_pci.c
+++ b/sys/compat/linuxkpi/common/src/linux_pci.c
@@ -690,14 +690,17 @@ pci_resource_start(struct pci_dev *pdev, int bar)
 	struct resource_list_entry *rle;
 	rman_res_t newstart;
 	device_t dev;
+	int error;
 
 	if ((rle = linux_pci_get_bar(pdev, bar, true)) == NULL)
 		return (0);
 	dev = pdev->pdrv != NULL && pdev->pdrv->isdrm ?
 	    device_get_parent(pdev->dev.bsddev) : pdev->dev.bsddev;
-	if (BUS_TRANSLATE_RESOURCE(dev, rle->type, rle->start, &newstart)) {
-		device_printf(pdev->dev.bsddev, "translate of %#jx failed\n",
-		    (uintmax_t)rle->start);
+	error = bus_translate_resource(dev, rle->type, rle->start, &newstart);
+	if (error != 0) {
+		device_printf(pdev->dev.bsddev,
+		    "translate of %#jx failed: %d\n",
+		    (uintmax_t)rle->start, error);
 		return (0);
 	}
 	return (newstart);
diff --git a/sys/dev/ofw/ofw_pcib.c b/sys/dev/ofw/ofw_pcib.c
index 1de5a884ebc9..b10feffedf6c 100644
--- a/sys/dev/ofw/ofw_pcib.c
+++ b/sys/dev/ofw/ofw_pcib.c
@@ -511,11 +511,11 @@ ofw_pcib_translate_resource(device_t bus, int type, rman_res_t start,
 
 		if (type == space) {
 			start += (rp->host - rp->pci);
-			break;
+			*newstart = start;
+			return (0);
 		}
 	}
-	*newstart = start;
-	return (0);
+	return (ENOENT);
 }
 
 static int
diff --git a/sys/dev/pci/pci_host_generic.c b/sys/dev/pci/pci_host_generic.c
index 4d7d9f314dce..e1a0a48bad3a 100644
--- a/sys/dev/pci/pci_host_generic.c
+++ b/sys/dev/pci/pci_host_generic.c
@@ -331,7 +331,7 @@ pci_host_generic_core_release_resource(device_t dev, device_t child, int type,
 	return (bus_generic_release_resource(dev, child, type, rid, res));
 }
 
-static bool
+static int
 generic_pcie_translate_resource_common(device_t dev, int type, rman_res_t start,
     rman_res_t end, rman_res_t *new_start, rman_res_t *new_end)
 {
@@ -385,7 +385,7 @@ generic_pcie_translate_resource_common(device_t dev, int type, rman_res_t start,
 		break;
 	}
 
-	return (found);
+	return (found ? 0 : ENOENT);
 }
 
 static int
@@ -394,7 +394,7 @@ generic_pcie_translate_resource(device_t bus, int type,
 {
 	rman_res_t newend; /* unused */
 
-	return (!generic_pcie_translate_resource_common(
+	return (generic_pcie_translate_resource_common(
 	    bus, type, start, 0, newstart, &newend));
 }
 
@@ -422,8 +422,8 @@ pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type,
 		    type, rid, start, end, count, flags));
 
 	/* Translate the address from a PCI address to a physical address */
-	if (!generic_pcie_translate_resource_common(dev, type, start, end, &phys_start,
-	    &phys_end)) {
+	if (generic_pcie_translate_resource_common(dev, type, start, end,
+	    &phys_start, &phys_end) != 0) {
 		device_printf(dev,
 		    "Failed to translate resource %jx-%jx type %x for %s\n",
 		    (uintmax_t)start, (uintmax_t)end, type,
@@ -474,9 +474,12 @@ generic_pcie_activate_resource(device_t dev, device_t child, int type,
 
 	start = rman_get_start(r);
 	end = rman_get_end(r);
-	if (!generic_pcie_translate_resource_common(dev, type, start, end, &start,
-	    &end))
-		return (EINVAL);
+	res = generic_pcie_translate_resource_common(dev, type, start, end,
+	    &start, &end);
+	if (res != 0) {
+		rman_deactivate_resource(r);
+		return (res);
+	}
 	rman_set_start(r, start);
 	rman_set_end(r, end);
 
diff --git a/sys/dev/pci/pci_user.c b/sys/dev/pci/pci_user.c
index 7ebd9b66138c..ce63122128c5 100644
--- a/sys/dev/pci/pci_user.c
+++ b/sys/dev/pci/pci_user.c
@@ -877,7 +877,7 @@ pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm)
 		return (EBUSY); /* XXXKIB enable if _ACTIVATE */
 	if (!PCI_BAR_MEM(pm->pm_value))
 		return (EIO);
-	error = BUS_TRANSLATE_RESOURCE(pcidev, SYS_RES_MEMORY,
+	error = bus_translate_resource(pcidev, SYS_RES_MEMORY,
 	    pm->pm_value & PCIM_BAR_MEM_BASE, &membase);
 	if (error != 0)
 		return (error);
diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m
index 0bd7056019ab..0f673c983d08 100644
--- a/sys/kern/bus_if.m
+++ b/sys/kern/bus_if.m
@@ -77,18 +77,6 @@ CODE {
 		return (0);
 	}
 
-	static int
-	null_translate_resource(device_t bus, int type, rman_res_t start,
-		rman_res_t *newstart)
-	{
-		if (device_get_parent(bus) != NULL)
-			return (BUS_TRANSLATE_RESOURCE(device_get_parent(bus),
-			    type, start, newstart));
-
-		*newstart = start;
-		return (0);
-	}
-
 	static ssize_t
 	null_get_property(device_t dev, device_t child, const char *propname,
 	    void *propvalue, size_t size)
@@ -425,10 +413,12 @@ METHOD int adjust_resource {
 	rman_res_t	_end;
 };
 
-
 /**
  * @brief translate a resource value
  *
+ * Give a bus driver the opportunity to translate resource ranges.  If
+ * successful, the host's view of the resource starting at @p _start is
+ * returned in @p _newstart, otherwise an error is returned.
  *
  * @param _dev		the device associated with the resource
  * @param _type		the type of resource
@@ -440,7 +430,7 @@ METHOD int translate_resource {
 	int		_type;
 	rman_res_t	_start;
 	rman_res_t	*_newstart;
-} DEFAULT null_translate_resource;
+} DEFAULT bus_generic_translate_resource;
 
 /**
  * @brief Release a resource
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index cdbaee9c203e..09072e1a23de 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -4242,6 +4242,24 @@ bus_generic_adjust_resource(device_t dev, device_t child, int type,
 	return (EINVAL);
 }
 
+/*
+ * @brief Helper function for implementing BUS_TRANSLATE_RESOURCE().
+ *
+ * This simple implementation of BUS_TRANSLATE_RESOURCE() simply calls the
+ * BUS_TRANSLATE_RESOURCE() method of the parent of @p dev.  If there is no
+ * parent, no translation happens.
+ */
+int
+bus_generic_translate_resource(device_t dev, int type, rman_res_t start,
+    rman_res_t *newstart)
+{
+	if (dev->parent)
+		return (BUS_TRANSLATE_RESOURCE(dev->parent, type, start,
+		    newstart));
+	*newstart = start;
+	return (0);
+}
+
 /**
  * @brief Helper function for implementing BUS_ALLOC_RESOURCE().
  *
@@ -4672,6 +4690,21 @@ bus_adjust_resource(device_t dev, int type, struct resource *r, rman_res_t start
 	return (BUS_ADJUST_RESOURCE(dev->parent, dev, type, r, start, end));
 }
 
+/**
+ * @brief Wrapper function for BUS_TRANSLATE_RESOURCE().
+ *
+ * This function simply calls the BUS_TRANSLATE_RESOURCE() method of the
+ * parent of @p dev.
+ */
+int
+bus_translate_resource(device_t dev, int type, rman_res_t start,
+    rman_res_t *newstart)
+{
+	if (dev->parent == NULL)
+		return (EINVAL);
+	return (BUS_TRANSLATE_RESOURCE(dev->parent, type, start, newstart));
+}
+
 /**
  * @brief Wrapper function for BUS_ACTIVATE_RESOURCE().
  *
diff --git a/sys/sys/bus.h b/sys/sys/bus.h
index 8544aa32cff8..0942b7246ae4 100644
--- a/sys/sys/bus.h
+++ b/sys/sys/bus.h
@@ -515,6 +515,8 @@ void	bus_release_resources(device_t dev, const struct resource_spec *rs,
 
 int	bus_adjust_resource(device_t child, int type, struct resource *r,
 			    rman_res_t start, rman_res_t end);
+int	bus_translate_resource(device_t child, int type, rman_res_t start,
+			       rman_res_t *newstart);
 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);