Re: [PATCH 4/5] checks: Add infrastructure for setting bus type of nodes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Tue, Jan 31, 2017 at 11:26:34AM +1100, David Gibson wrote:
> On Tue, Jan 24, 2017 at 11:45:33AM -0600, Rob Herring wrote:
> > In preparation to support bus specific checks, add the necessary
> > infrastructure to determine and set the bus type for nodes.
> > 
> > Signed-off-by: Rob Herring <robh@xxxxxxxxxx>
> > ---
> >  checks.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
> >  dtc.h    | 11 +++++++++++
> >  2 files changed, 62 insertions(+)

[...]

> > +static void check_bus_bridge(struct check *c, struct dt_info *dti,
> > +			     struct node *node)
> > +{
> > +	struct bus_type *bt;
> > +
> > +	if (!node->bus_type)
> > +		return;
> > +
> > +	bt = node->bus_type;
> > +	if (bt->check_bridge)
> > +		bt->check_bridge(c, dti, node);
> > +}
> > +WARNING(bus_bridge, check_bus_bridge, NULL);
> 
> Hrm.  So, we have a double multiplex here, and I'm not sure that it's
> necessary.  First the table of checks themselves, then the table of
> bus types.  Could we eliminate that simply by having each bus type
> implement a check function which tests for that bus type then,
> performans any checks for the bridge then sets the bus_type field.
> 
> It would mean that if there are multiple bus-specific things we want
> to check about the bridge, we could put them into separate checks.
> That might be clearer in some cases, and it means our existing
> messages can show something informative via the check name which
> failed, rather than just saying "(bus_bridge)" for anything wrong with
> any bus bridge.
> 
> We could still use the bus_type field for "semi-generic" checks like
> validating unit names that are the same in outline between different
> buses, but differ in details.

Something like this what you have in mind? If we have additional checks 
to add, we can just use the existing prerq functionality.

8<--------------------------------------------------------------------------
>From 5cea821e6078f84eaae5af317651a4a696d1f0f7 Mon Sep 17 00:00:00 2001
From: Rob Herring <robh@xxxxxxxxxx>
Date: Wed, 1 Feb 2017 15:43:32 -0600
Subject: [PATCH v2] checks: Add bus checks for PCI buses

Add PCI bridge and device node checks. We identify PCI bridges with
'device_type = "pci"' as only PCI bridges should set that property. For
bridges, check that ranges is present and #address-cells and

For devices, the primary check is the reg property and the unit address.
Device unit addresses are in the form DD or DD,F where DD is the
device 0-0x1f and F is the function 0-7.

Signed-off-by: Rob Herring <robh@xxxxxxxxxx>
---
 checks.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dtc.h    |  4 +++-
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/checks.c b/checks.c
index 225ace39c698..b727c49d457c 100644
--- a/checks.c
+++ b/checks.c
@@ -702,6 +702,77 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
 }
 WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
 
+static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
+{
+	struct property *prop;
+
+	prop = get_property(node, "device_type");
+	if (!prop || strcmp(prop->val.val, "pci"))
+		return;
+
+	node->bus_type = PCI_BUS_TYPE;
+
+	prop = get_property(node, "ranges");
+	if (!prop) {
+		FAIL(c, "Node %s missing ranges for PCI bridge (or not a bridge)",
+			     node->fullpath);
+		return;
+	}
+
+	if (node_addr_cells(node) != 3)
+		FAIL(c, "Node %s incorrect #address-cells for PCI bridge",
+			     node->fullpath);
+	if (node_size_cells(node) != 2)
+		FAIL(c, "Node %s incorrect #size-cells for PCI bridge",
+			     node->fullpath);
+}
+WARNING(pci_bridge, check_pci_bridge, NULL, &device_type_is_string,&addr_size_cells);
+
+static void check_pci_device(struct check *c, struct dt_info *dti, struct node *node)
+{
+	struct property *prop;
+	const char *unitname = get_unitname(node);
+	char unit_addr[5];
+	unsigned int dev, func, reg;
+
+	if (!node->parent || (node->parent->bus_type != PCI_BUS_TYPE))
+		return;
+
+	prop = get_property(node, "reg");
+	if (!prop)
+		return;
+
+	reg = fdt32_to_cpu(*((cell_t *)prop->val.val));
+
+	dev = (reg & 0xf800) >> 11;
+	func = (reg & 0x700) >> 8;
+
+	if (reg & 0xff000000)
+		FAIL(c, "Node %s PCI reg address is not configuration space",
+			     node->fullpath);
+
+	if (dev > 0x1f)
+		FAIL(c, "Node %s PCI device number out of range",
+			     node->fullpath);
+	if (func > 7)
+		FAIL(c, "Node %s PCI function number out of range",
+		     node->fullpath);
+
+	if (func == 0) {
+		snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
+		if (!strcmp(unitname, unit_addr))
+			return;
+	}
+
+	snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
+	if (!strcmp(unitname, unit_addr))
+		return;
+
+	FAIL(c, "Node %s PCI unit address format error, expected \"%s\"",
+	     node->fullpath, unit_addr);
+}
+WARNING(pci_device, check_pci_device, NULL, &reg_format);
+
 /*
  * Style checks
  */
@@ -775,6 +846,9 @@ static struct check *check_table[] = {
 	&unit_address_vs_reg,
 	&unit_address_format,
 
+	&pci_bridge,
+	&pci_device,
+
 	&avoid_default_addr_size,
 	&obsolete_chosen_interrupt_controller,
 
diff --git a/dtc.h b/dtc.h
index c6f125c68ba8..03c249c65101 100644
--- a/dtc.h
+++ b/dtc.h
@@ -146,6 +146,8 @@ struct property {
 	struct label *labels;
 };
 
+#define PCI_BUS_TYPE	1
+
 struct node {
 	bool deleted;
 	char *name;
@@ -159,7 +161,7 @@ struct node {
 	int basenamelen;
 
 	cell_t phandle;
-	int addr_cells, size_cells;
+	int addr_cells, size_cells, bus_type;
 
 	struct label *labels;
 };
-- 
2.10.1
--
To unsubscribe from this list: send the line "unsubscribe devicetree-compiler" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux