Linux Input/HID development
 help / color / mirror / Atom feed
* Re: [PATCH v5 1/4] resource: Move reparent_resources() to kernel/resource.c and make it public
From: Baoquan He @ 2018-07-04  4:18 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Nicolas Pitre, brijesh.singh-5C7GfCeVMHo, devicetree,
	David Airlie, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w, Max Filippov,
	Paul Mackerras, baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	KY Srinivasan, Frank Rowand, Lorenzo Pieralisi, Stephen Hemminger,
	linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw, Michael Ellerman,
	Patrik Jakobsson, linux-input, Gustavo Padovan, Borislav Petkov,
	Dave Young, Tom Lendacky, Haiyang Zhang, Maarten Lankhorst,
	Josh Triplett
In-Reply-To: <CAHp75VeEjhcYF4Fy4O_srdv_nEGGjGwAHhZufscB_tiLQVQ=FQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On 07/03/18 at 11:57pm, Andy Shevchenko wrote:
> On Tue, Jul 3, 2018 at 5:55 PM, Baoquan He <bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> > On 06/12/18 at 05:24pm, Andy Shevchenko wrote:
> >> On Tue, Jun 12, 2018 at 5:20 PM, Andy Shevchenko
> >> <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> 
> >> > I briefly looked at the code and error codes we have, so, my proposal
> >> > is one of the following
> >>
> >> >  - use -ECANCELED (not the best choice for first occurrence here,
> >> > though I can't find better)
> >>
> >> Actually -ENOTSUPP might suit the first case (although the actual
> >> would be something like -EOVERLAP, which we don't have)
> >
> > Sorry for late reply, and many thanks for your great suggestion.
> >
> 
> > I am fine to use -ENOTSUPP as the first returned value, and -ECANCELED
> > for the 2nd one.
> 
> I have no strong opinion, but I like (slightly better) this approach ^^^

Done, post v6 in this way, many thanks.

> 
> > Or define an enum as you suggested inside the function
> > or in header file.
> 
> >
> > Or use -EBUSY for the first case because existing resource is
> > overlapping but not fully contained by 'res'; and -EINVAL for
> > the 2nd case since didn't find any one resources which is contained by
> > 'res', means we passed in a invalid resource.
> >
> > All is fine to me, I can repost with each of them.
> 
> >> >  - use positive integers (or enum), like
> >> >   #define RES_REPARENTED 0
> >> >   #define RES_OVERLAPPED 1
> >> >   #define RES_NOCONFLICT 2
> 
> -- 
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply

* [PATCH v6 4/4] kexec_file: Load kernel at top of system RAM if required
From: Baoquan He @ 2018-07-04  4:10 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
	nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, josh-iaAMLnmF4UmaiuxdJuQwMA,
	fengguang.wu-ral2JQCrhuEAvxtiuMwx3w, bp-l3A5Bk7waGM,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w
  Cc: brijesh.singh-5C7GfCeVMHo, devicetree-u79uwXL29TY76Z2rM5mHXA,
	airlied-cv59FeDIM0c, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w,
	jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	kys-0li6OtcxBFHby3iVrkZq2A, frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
	lorenzo.pieralisi-5wv7dgnIgG8, sthemmin-0li6OtcxBFHby3iVrkZq2A,
	Baoquan He, linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	patrik.r.jakobsson-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	gustavo-THi1TnShQwVAfugRpC6u6w, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	thomas.lendacky-5C7GfCeVMHo, haiyangz-0li6OtcxBFHby3iVrkZq2A,
	maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA,
	jglisse-H+wXaHxf7aLQT0dZR+AlfA, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, tglx-hfZtesqFncYOwBW4kG4KsQ,
	yinghai-DgEjT+Ai2ygdnm+yROfE0A,
	jonathan.derrick-ral2JQCrhuEAvxtiuMwx3w,
	chris-YvXeqwSYzG2sTnJN9+BGXg, monstr-pSz03upnqPeHXe+LvDLADg,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w,
	devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, davem
In-Reply-To: <20180704041038.8190-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

For kexec_file loading, if kexec_buf.top_down is 'true', the memory which
is used to load kernel/initrd/purgatory is supposed to be allocated from
top to down. This is what we have been doing all along in the old kexec
loading interface and the kexec loading is still default setting in some
distributions. However, the current kexec_file loading interface doesn't
do likt this. The function arch_kexec_walk_mem() it calls ignores checking
kexec_buf.top_down, but calls walk_system_ram_res() directly to go through
all resources of System RAM from bottom to up, to try to find memory region
which can contain the specific kexec buffer, then call locate_mem_hole_callback()
to allocate memory in that found memory region from top to down. This brings
confusion especially when KASLR is widely supported , users have to make clear
why kexec/kdump kernel loading position is different between these two
interfaces in order to exclude unnecessary noises. Hence these two interfaces
need be unified on behaviour.

Here add checking if kexec_buf.top_down is 'true' in arch_kexec_walk_mem(),
if yes, call the newly added walk_system_ram_res_rev() to find memory region
from top to down to load kernel.

Signed-off-by: Baoquan He <bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Eric Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
Cc: Vivek Goyal <vgoyal-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Dave Young <dyoung-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Yinghai Lu <yinghai-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Cc: kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
---
 kernel/kexec_file.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index c6a3b6851372..75226c1d08ce 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -518,6 +518,8 @@ int __weak arch_kexec_walk_mem(struct kexec_buf *kbuf,
 					   IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY,
 					   crashk_res.start, crashk_res.end,
 					   kbuf, func);
+	else if (kbuf->top_down)
+		return walk_system_ram_res_rev(0, ULONG_MAX, kbuf, func);
 	else
 		return walk_system_ram_res(0, ULONG_MAX, kbuf, func);
 }
-- 
2.13.6

^ permalink raw reply related

* [PATCH v6 3/4] resource: add walk_system_ram_res_rev()
From: Baoquan He @ 2018-07-04  4:10 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
	nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, josh-iaAMLnmF4UmaiuxdJuQwMA,
	fengguang.wu-ral2JQCrhuEAvxtiuMwx3w, bp-l3A5Bk7waGM,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w
  Cc: brijesh.singh-5C7GfCeVMHo, devicetree-u79uwXL29TY76Z2rM5mHXA,
	airlied-cv59FeDIM0c, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w,
	jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	kys-0li6OtcxBFHby3iVrkZq2A, frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
	lorenzo.pieralisi-5wv7dgnIgG8, sthemmin-0li6OtcxBFHby3iVrkZq2A,
	Baoquan He, linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	patrik.r.jakobsson-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	gustavo-THi1TnShQwVAfugRpC6u6w, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	thomas.lendacky-5C7GfCeVMHo, haiyangz-0li6OtcxBFHby3iVrkZq2A,
	maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA,
	jglisse-H+wXaHxf7aLQT0dZR+AlfA, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, tglx-hfZtesqFncYOwBW4kG4KsQ,
	yinghai-DgEjT+Ai2ygdnm+yROfE0A,
	jonathan.derrick-ral2JQCrhuEAvxtiuMwx3w,
	chris-YvXeqwSYzG2sTnJN9+BGXg, monstr-pSz03upnqPeHXe+LvDLADg,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w,
	devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, davem
In-Reply-To: <20180704041038.8190-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

This function, being a variant of walk_system_ram_res() introduced in
commit 8c86e70acead ("resource: provide new functions to walk through
resources"), walks through a list of all the resources of System RAM
in reversed order, i.e., from higher to lower.

It will be used in kexec_file code.

Signed-off-by: Baoquan He <bhe@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Wei Yang <richard.weiyang@gmail.com>
---
 include/linux/ioport.h |  3 +++
 kernel/resource.c      | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index b7456ae889dd..066cc263e2cc 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -279,6 +279,9 @@ extern int
 walk_system_ram_res(u64 start, u64 end, void *arg,
 		    int (*func)(struct resource *, void *));
 extern int
+walk_system_ram_res_rev(u64 start, u64 end, void *arg,
+			int (*func)(struct resource *, void *));
+extern int
 walk_iomem_res_desc(unsigned long desc, unsigned long flags, u64 start, u64 end,
 		    void *arg, int (*func)(struct resource *, void *));
 
diff --git a/kernel/resource.c b/kernel/resource.c
index 6d647a3824b1..4c5fbef4ea24 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -23,6 +23,8 @@
 #include <linux/pfn.h>
 #include <linux/mm.h>
 #include <linux/resource_ext.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
 #include <asm/io.h>
 
 
@@ -443,6 +445,44 @@ int walk_system_ram_res(u64 start, u64 end, void *arg,
 }
 
 /*
+ * This function, being a variant of walk_system_ram_res(), calls the @func
+ * callback against all memory ranges of type System RAM which are marked as
+ * IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY in reversed order, i.e., from
+ * higher to lower.
+ */
+int walk_system_ram_res_rev(u64 start, u64 end, void *arg,
+				int (*func)(struct resource *, void *))
+{
+	unsigned long flags;
+	struct resource *res;
+	int ret = -1;
+
+	flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
+
+	read_lock(&resource_lock);
+	list_for_each_entry_reverse(res, &iomem_resource.child, sibling) {
+		if (start >= end)
+			break;
+		if ((res->flags & flags) != flags)
+			continue;
+		if (res->desc != IORES_DESC_NONE)
+			continue;
+		if (res->end < start)
+			break;
+
+		if ((res->end >= start) && (res->start < end)) {
+			ret = (*func)(res, arg);
+			if (ret)
+				break;
+		}
+		end = res->start - 1;
+
+	}
+	read_unlock(&resource_lock);
+	return ret;
+}
+
+/*
  * This function calls the @func callback against all memory ranges, which
  * are ranges marked as IORESOURCE_MEM and IORESOUCE_BUSY.
  */
-- 
2.13.6

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related

* [PATCH v6 2/4] resource: Use list_head to link sibling resource
From: Baoquan He @ 2018-07-04  4:10 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
	nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, josh-iaAMLnmF4UmaiuxdJuQwMA,
	fengguang.wu-ral2JQCrhuEAvxtiuMwx3w, bp-l3A5Bk7waGM,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w
  Cc: brijesh.singh-5C7GfCeVMHo, devicetree-u79uwXL29TY76Z2rM5mHXA,
	airlied-cv59FeDIM0c, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w,
	jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	kys-0li6OtcxBFHby3iVrkZq2A, frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
	lorenzo.pieralisi-5wv7dgnIgG8, sthemmin-0li6OtcxBFHby3iVrkZq2A,
	Baoquan He, linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	patrik.r.jakobsson-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	gustavo-THi1TnShQwVAfugRpC6u6w, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	thomas.lendacky-5C7GfCeVMHo, haiyangz-0li6OtcxBFHby3iVrkZq2A,
	maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA,
	jglisse-H+wXaHxf7aLQT0dZR+AlfA, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, tglx-hfZtesqFncYOwBW4kG4KsQ,
	yinghai-DgEjT+Ai2ygdnm+yROfE0A,
	jonathan.derrick-ral2JQCrhuEAvxtiuMwx3w,
	chris-YvXeqwSYzG2sTnJN9+BGXg, monstr-pSz03upnqPeHXe+LvDLADg,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w,
	devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, davem
In-Reply-To: <20180704041038.8190-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

The struct resource uses singly linked list to link siblings, implemented
by pointer operation. Replace it with list_head for better code readability.

Based on this list_head replacement, it will be very easy to do reverse
iteration on iomem_resource's sibling list in later patch.

Besides, type of member variables of struct resource, sibling and child, are
changed from 'struct resource *' to 'struct list_head'. This brings two
pointers of size increase.

Suggested-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Baoquan He <bhe@redhat.com>
Cc: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Cc: David Airlie <airlied@linux.ie>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Frank Rowand <frowand.list@gmail.com>
Cc: Keith Busch <keith.busch@intel.com>
Cc: Jonathan Derrick <jonathan.derrick@intel.com>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: Borislav Petkov <bp@suse.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
Cc: Wei Yang <richard.weiyang@gmail.com>
Cc: devel@linuxdriverproject.org
Cc: linux-input@vger.kernel.org
Cc: linux-nvdimm@lists.01.org
Cc: devicetree@vger.kernel.org
Cc: linux-pci@vger.kernel.org
---
 arch/arm/plat-samsung/pm-check.c            |   6 +-
 arch/microblaze/pci/pci-common.c            |   4 +-
 arch/powerpc/kernel/pci-common.c            |   4 +-
 arch/sparc/kernel/ioport.c                  |   2 +-
 arch/xtensa/include/asm/pci-bridge.h        |   4 +-
 drivers/eisa/eisa-bus.c                     |   2 +
 drivers/gpu/drm/drm_memory.c                |   3 +-
 drivers/gpu/drm/gma500/gtt.c                |   5 +-
 drivers/hv/vmbus_drv.c                      |  52 +++----
 drivers/input/joystick/iforce/iforce-main.c |   4 +-
 drivers/nvdimm/namespace_devs.c             |   6 +-
 drivers/nvdimm/nd.h                         |   5 +-
 drivers/of/address.c                        |   4 +-
 drivers/parisc/lba_pci.c                    |   4 +-
 drivers/pci/controller/vmd.c                |   8 +-
 drivers/pci/probe.c                         |   2 +
 drivers/pci/setup-bus.c                     |   2 +-
 include/linux/ioport.h                      |  17 ++-
 kernel/resource.c                           | 208 ++++++++++++++--------------
 19 files changed, 175 insertions(+), 167 deletions(-)

diff --git a/arch/arm/plat-samsung/pm-check.c b/arch/arm/plat-samsung/pm-check.c
index cd2c02c68bc3..5494355b1c49 100644
--- a/arch/arm/plat-samsung/pm-check.c
+++ b/arch/arm/plat-samsung/pm-check.c
@@ -46,8 +46,8 @@ typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
 static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
 {
 	while (ptr != NULL) {
-		if (ptr->child != NULL)
-			s3c_pm_run_res(ptr->child, fn, arg);
+		if (!list_empty(&ptr->child))
+			s3c_pm_run_res(resource_first_child(&ptr->child), fn, arg);
 
 		if ((ptr->flags & IORESOURCE_SYSTEM_RAM)
 				== IORESOURCE_SYSTEM_RAM) {
@@ -57,7 +57,7 @@ static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
 			arg = (fn)(ptr, arg);
 		}
 
-		ptr = ptr->sibling;
+		ptr = resource_sibling(ptr);
 	}
 }
 
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 7899bafab064..2bf73e27e231 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -533,7 +533,9 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 			res->flags = range.flags;
 			res->start = range.cpu_addr;
 			res->end = range.cpu_addr + range.size - 1;
-			res->parent = res->child = res->sibling = NULL;
+			res->parent = NULL;
+			INIT_LIST_HEAD(&res->child);
+			INIT_LIST_HEAD(&res->sibling);
 		}
 	}
 
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 926035bb378d..28fbe83c9daf 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -761,7 +761,9 @@ void pci_process_bridge_OF_ranges(struct pci_controller *hose,
 			res->flags = range.flags;
 			res->start = range.cpu_addr;
 			res->end = range.cpu_addr + range.size - 1;
-			res->parent = res->child = res->sibling = NULL;
+			res->parent = NULL;
+			INIT_LIST_HEAD(&res->child);
+			INIT_LIST_HEAD(&res->sibling);
 		}
 	}
 }
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index cca9134cfa7d..99efe4e98b16 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -669,7 +669,7 @@ static int sparc_io_proc_show(struct seq_file *m, void *v)
 	struct resource *root = m->private, *r;
 	const char *nm;
 
-	for (r = root->child; r != NULL; r = r->sibling) {
+	list_for_each_entry(r, &root->child, sibling) {
 		if ((nm = r->name) == NULL) nm = "???";
 		seq_printf(m, "%016llx-%016llx: %s\n",
 				(unsigned long long)r->start,
diff --git a/arch/xtensa/include/asm/pci-bridge.h b/arch/xtensa/include/asm/pci-bridge.h
index 0b68c76ec1e6..f487b06817df 100644
--- a/arch/xtensa/include/asm/pci-bridge.h
+++ b/arch/xtensa/include/asm/pci-bridge.h
@@ -71,8 +71,8 @@ static inline void pcibios_init_resource(struct resource *res,
 	res->flags = flags;
 	res->name = name;
 	res->parent = NULL;
-	res->sibling = NULL;
-	res->child = NULL;
+	INIT_LIST_HEAD(&res->child);
+	INIT_LIST_HEAD(&res->sibling);
 }
 
 
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 1e8062f6dbfc..dba78f75fd06 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -408,6 +408,8 @@ static struct resource eisa_root_res = {
 	.start = 0,
 	.end   = 0xffffffff,
 	.flags = IORESOURCE_IO,
+	.sibling = LIST_HEAD_INIT(eisa_root_res.sibling),
+	.child  = LIST_HEAD_INIT(eisa_root_res.child),
 };
 
 static int eisa_bus_count;
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index d69e4fc1ee77..33baa7fa5e41 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -155,9 +155,8 @@ u64 drm_get_max_iomem(void)
 	struct resource *tmp;
 	resource_size_t max_iomem = 0;
 
-	for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling) {
+	list_for_each_entry(tmp, &iomem_resource.child, sibling)
 		max_iomem = max(max_iomem,  tmp->end);
-	}
 
 	return max_iomem;
 }
diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c
index 3949b0990916..addd3bc009af 100644
--- a/drivers/gpu/drm/gma500/gtt.c
+++ b/drivers/gpu/drm/gma500/gtt.c
@@ -565,7 +565,7 @@ int psb_gtt_init(struct drm_device *dev, int resume)
 int psb_gtt_restore(struct drm_device *dev)
 {
 	struct drm_psb_private *dev_priv = dev->dev_private;
-	struct resource *r = dev_priv->gtt_mem->child;
+	struct resource *r;
 	struct gtt_range *range;
 	unsigned int restored = 0, total = 0, size = 0;
 
@@ -573,14 +573,13 @@ int psb_gtt_restore(struct drm_device *dev)
 	mutex_lock(&dev_priv->gtt_mutex);
 	psb_gtt_init(dev, 1);
 
-	while (r != NULL) {
+	list_for_each_entry(r, &dev_priv->gtt_mem->child, sibling) {
 		range = container_of(r, struct gtt_range, resource);
 		if (range->pages) {
 			psb_gtt_insert(dev, range, 1);
 			size += range->resource.end - range->resource.start;
 			restored++;
 		}
-		r = r->sibling;
 		total++;
 	}
 	mutex_unlock(&dev_priv->gtt_mutex);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index b10fe26c4891..d87ec5a1bc4c 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1412,9 +1412,8 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
 {
 	resource_size_t start = 0;
 	resource_size_t end = 0;
-	struct resource *new_res;
+	struct resource *new_res, *tmp;
 	struct resource **old_res = &hyperv_mmio;
-	struct resource **prev_res = NULL;
 
 	switch (res->type) {
 
@@ -1461,44 +1460,36 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
 	/*
 	 * If two ranges are adjacent, merge them.
 	 */
-	do {
-		if (!*old_res) {
-			*old_res = new_res;
-			break;
-		}
-
-		if (((*old_res)->end + 1) == new_res->start) {
-			(*old_res)->end = new_res->end;
+	if (!*old_res) {
+		*old_res = new_res;
+		return AE_OK;
+	}
+	tmp = *old_res;
+	list_for_each_entry_from(tmp, &tmp->parent->child, sibling) {
+		if ((tmp->end + 1) == new_res->start) {
+			tmp->end = new_res->end;
 			kfree(new_res);
 			break;
 		}
 
-		if ((*old_res)->start == new_res->end + 1) {
-			(*old_res)->start = new_res->start;
+		if (tmp->start == new_res->end + 1) {
+			tmp->start = new_res->start;
 			kfree(new_res);
 			break;
 		}
 
-		if ((*old_res)->start > new_res->end) {
-			new_res->sibling = *old_res;
-			if (prev_res)
-				(*prev_res)->sibling = new_res;
-			*old_res = new_res;
+		if (tmp->start > new_res->end) {
+			list_add(&new_res->sibling, tmp->sibling.prev);
 			break;
 		}
-
-		prev_res = old_res;
-		old_res = &(*old_res)->sibling;
-
-	} while (1);
+	}
 
 	return AE_OK;
 }
 
 static int vmbus_acpi_remove(struct acpi_device *device)
 {
-	struct resource *cur_res;
-	struct resource *next_res;
+	struct resource *res;
 
 	if (hyperv_mmio) {
 		if (fb_mmio) {
@@ -1507,10 +1498,9 @@ static int vmbus_acpi_remove(struct acpi_device *device)
 			fb_mmio = NULL;
 		}
 
-		for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) {
-			next_res = cur_res->sibling;
-			kfree(cur_res);
-		}
+		res = hyperv_mmio;
+		list_for_each_entry_from(res, &res->parent->child, sibling)
+			kfree(res);
 	}
 
 	return 0;
@@ -1596,7 +1586,8 @@ int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
 		}
 	}
 
-	for (iter = hyperv_mmio; iter; iter = iter->sibling) {
+	iter = hyperv_mmio;
+	list_for_each_entry_from(iter, &iter->parent->child, sibling) {
 		if ((iter->start >= max) || (iter->end <= min))
 			continue;
 
@@ -1639,7 +1630,8 @@ void vmbus_free_mmio(resource_size_t start, resource_size_t size)
 	struct resource *iter;
 
 	down(&hyperv_mmio_lock);
-	for (iter = hyperv_mmio; iter; iter = iter->sibling) {
+	iter = hyperv_mmio;
+	list_for_each_entry_from(iter, &iter->parent->child, sibling) {
 		if ((iter->start >= start + size) || (iter->end <= start))
 			continue;
 
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c
index daeeb4c7e3b0..5c0be27b33ff 100644
--- a/drivers/input/joystick/iforce/iforce-main.c
+++ b/drivers/input/joystick/iforce/iforce-main.c
@@ -305,8 +305,8 @@ int iforce_init_device(struct iforce *iforce)
 	iforce->device_memory.end = 200;
 	iforce->device_memory.flags = IORESOURCE_MEM;
 	iforce->device_memory.parent = NULL;
-	iforce->device_memory.child = NULL;
-	iforce->device_memory.sibling = NULL;
+	INIT_LIST_HEAD(&iforce->device_memory.child);
+	INIT_LIST_HEAD(&iforce->device_memory.sibling);
 
 /*
  * Wait until device ready - until it sends its first response.
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 28afdd668905..f53d410d9981 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -637,7 +637,7 @@ static resource_size_t scan_allocate(struct nd_region *nd_region,
  retry:
 	first = 0;
 	for_each_dpa_resource(ndd, res) {
-		struct resource *next = res->sibling, *new_res = NULL;
+		struct resource *next = resource_sibling(res), *new_res = NULL;
 		resource_size_t allocate, available = 0;
 		enum alloc_loc loc = ALLOC_ERR;
 		const char *action;
@@ -763,7 +763,7 @@ static resource_size_t scan_allocate(struct nd_region *nd_region,
 	 * an initial "pmem-reserve pass".  Only do an initial BLK allocation
 	 * when none of the DPA space is reserved.
 	 */
-	if ((is_pmem || !ndd->dpa.child) && n == to_allocate)
+	if ((is_pmem || list_empty(&ndd->dpa.child)) && n == to_allocate)
 		return init_dpa_allocation(label_id, nd_region, nd_mapping, n);
 	return n;
 }
@@ -779,7 +779,7 @@ static int merge_dpa(struct nd_region *nd_region,
  retry:
 	for_each_dpa_resource(ndd, res) {
 		int rc;
-		struct resource *next = res->sibling;
+		struct resource *next = resource_sibling(res);
 		resource_size_t end = res->start + resource_size(res);
 
 		if (!next || strcmp(res->name, label_id->id) != 0
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 32e0364b48b9..da7da15e03e7 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -102,11 +102,10 @@ unsigned sizeof_namespace_label(struct nvdimm_drvdata *ndd);
 		(unsigned long long) (res ? res->start : 0), ##arg)
 
 #define for_each_dpa_resource(ndd, res) \
-	for (res = (ndd)->dpa.child; res; res = res->sibling)
+	list_for_each_entry(res, &(ndd)->dpa.child, sibling)
 
 #define for_each_dpa_resource_safe(ndd, res, next) \
-	for (res = (ndd)->dpa.child, next = res ? res->sibling : NULL; \
-			res; res = next, next = next ? next->sibling : NULL)
+	list_for_each_entry_safe(res, next, &(ndd)->dpa.child, sibling)
 
 struct nd_percpu_lane {
 	int count;
diff --git a/drivers/of/address.c b/drivers/of/address.c
index 53349912ac75..e2e25719ab52 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -330,7 +330,9 @@ int of_pci_range_to_resource(struct of_pci_range *range,
 {
 	int err;
 	res->flags = range->flags;
-	res->parent = res->child = res->sibling = NULL;
+	res->parent = NULL;
+	INIT_LIST_HEAD(&res->child);
+	INIT_LIST_HEAD(&res->sibling);
 	res->name = np->full_name;
 
 	if (res->flags & IORESOURCE_IO) {
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 69bd98421eb1..7482bdfd1959 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -170,8 +170,8 @@ lba_dump_res(struct resource *r, int d)
 	for (i = d; i ; --i) printk(" ");
 	printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r,
 		(long)r->start, (long)r->end, r->flags);
-	lba_dump_res(r->child, d+2);
-	lba_dump_res(r->sibling, d);
+	lba_dump_res(resource_first_child(&r->child), d+2);
+	lba_dump_res(resource_sibling(r), d);
 }
 
 
diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
index 942b64fc7f1f..e3ace20345c7 100644
--- a/drivers/pci/controller/vmd.c
+++ b/drivers/pci/controller/vmd.c
@@ -542,14 +542,14 @@ static struct pci_ops vmd_ops = {
 
 static void vmd_attach_resources(struct vmd_dev *vmd)
 {
-	vmd->dev->resource[VMD_MEMBAR1].child = &vmd->resources[1];
-	vmd->dev->resource[VMD_MEMBAR2].child = &vmd->resources[2];
+	list_add(&vmd->resources[1].sibling, &vmd->dev->resource[VMD_MEMBAR1].child);
+	list_add(&vmd->resources[2].sibling, &vmd->dev->resource[VMD_MEMBAR2].child);
 }
 
 static void vmd_detach_resources(struct vmd_dev *vmd)
 {
-	vmd->dev->resource[VMD_MEMBAR1].child = NULL;
-	vmd->dev->resource[VMD_MEMBAR2].child = NULL;
+	INIT_LIST_HEAD(&vmd->dev->resource[VMD_MEMBAR1].child);
+	INIT_LIST_HEAD(&vmd->dev->resource[VMD_MEMBAR2].child);
 }
 
 /*
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ac876e32de4b..9624dd1dfd49 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -59,6 +59,8 @@ static struct resource *get_pci_domain_busn_res(int domain_nr)
 	r->res.start = 0;
 	r->res.end = 0xff;
 	r->res.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED;
+	INIT_LIST_HEAD(&r->res.child);
+	INIT_LIST_HEAD(&r->res.sibling);
 
 	list_add_tail(&r->list, &pci_domain_busn_res_list);
 
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 79b1824e83b4..8e685af8938d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2107,7 +2107,7 @@ int pci_reassign_bridge_resources(struct pci_dev *bridge, unsigned long type)
 				continue;
 
 			/* Ignore BARs which are still in use */
-			if (res->child)
+			if (!list_empty(&res->child))
 				continue;
 
 			ret = add_to_list(&saved, bridge, res, 0, 0);
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index dfdcd0bfe54e..b7456ae889dd 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -12,6 +12,7 @@
 #ifndef __ASSEMBLY__
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/list.h>
 /*
  * Resources are tree-like, allowing
  * nesting etc..
@@ -22,7 +23,8 @@ struct resource {
 	const char *name;
 	unsigned long flags;
 	unsigned long desc;
-	struct resource *parent, *sibling, *child;
+	struct list_head child, sibling;
+	struct resource *parent;
 };
 
 /*
@@ -216,7 +218,6 @@ static inline bool resource_contains(struct resource *r1, struct resource *r2)
 	return r1->start <= r2->start && r1->end >= r2->end;
 }
 
-
 /* Convenience shorthand with allocation */
 #define request_region(start,n,name)		__request_region(&ioport_resource, (start), (n), (name), 0)
 #define request_muxed_region(start,n,name)	__request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED)
@@ -287,6 +288,18 @@ static inline bool resource_overlaps(struct resource *r1, struct resource *r2)
        return (r1->start <= r2->end && r1->end >= r2->start);
 }
 
+static inline struct resource *resource_sibling(struct resource *res)
+{
+	if (res->parent && !list_is_last(&res->sibling, &res->parent->child))
+		return list_next_entry(res, sibling);
+	return NULL;
+}
+
+static inline struct resource *resource_first_child(struct list_head *head)
+{
+	return list_first_entry_or_null(head, struct resource, sibling);
+}
+
 
 #endif /* __ASSEMBLY__ */
 #endif	/* _LINUX_IOPORT_H */
diff --git a/kernel/resource.c b/kernel/resource.c
index d1cbf4b50e17..6d647a3824b1 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -31,6 +31,8 @@ struct resource ioport_resource = {
 	.start	= 0,
 	.end	= IO_SPACE_LIMIT,
 	.flags	= IORESOURCE_IO,
+	.sibling = LIST_HEAD_INIT(ioport_resource.sibling),
+	.child  = LIST_HEAD_INIT(ioport_resource.child),
 };
 EXPORT_SYMBOL(ioport_resource);
 
@@ -39,6 +41,8 @@ struct resource iomem_resource = {
 	.start	= 0,
 	.end	= -1,
 	.flags	= IORESOURCE_MEM,
+	.sibling = LIST_HEAD_INIT(iomem_resource.sibling),
+	.child  = LIST_HEAD_INIT(iomem_resource.child),
 };
 EXPORT_SYMBOL(iomem_resource);
 
@@ -57,20 +61,20 @@ static DEFINE_RWLOCK(resource_lock);
  * by boot mem after the system is up. So for reusing the resource entry
  * we need to remember the resource.
  */
-static struct resource *bootmem_resource_free;
+static struct list_head bootmem_resource_free = LIST_HEAD_INIT(bootmem_resource_free);
 static DEFINE_SPINLOCK(bootmem_resource_lock);
 
 static struct resource *next_resource(struct resource *p, bool sibling_only)
 {
 	/* Caller wants to traverse through siblings only */
 	if (sibling_only)
-		return p->sibling;
+		return resource_sibling(p);
 
-	if (p->child)
-		return p->child;
-	while (!p->sibling && p->parent)
+	if (!list_empty(&p->child))
+		return resource_first_child(&p->child);
+	while (!resource_sibling(p) && p->parent)
 		p = p->parent;
-	return p->sibling;
+	return resource_sibling(p);
 }
 
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
@@ -90,7 +94,7 @@ static void *r_start(struct seq_file *m, loff_t *pos)
 	struct resource *p = PDE_DATA(file_inode(m->file));
 	loff_t l = 0;
 	read_lock(&resource_lock);
-	for (p = p->child; p && l < *pos; p = r_next(m, p, &l))
+	for (p = resource_first_child(&p->child); p && l < *pos; p = r_next(m, p, &l))
 		;
 	return p;
 }
@@ -153,8 +157,7 @@ static void free_resource(struct resource *res)
 
 	if (!PageSlab(virt_to_head_page(res))) {
 		spin_lock(&bootmem_resource_lock);
-		res->sibling = bootmem_resource_free;
-		bootmem_resource_free = res;
+		list_add(&res->sibling, &bootmem_resource_free);
 		spin_unlock(&bootmem_resource_lock);
 	} else {
 		kfree(res);
@@ -166,10 +169,9 @@ static struct resource *alloc_resource(gfp_t flags)
 	struct resource *res = NULL;
 
 	spin_lock(&bootmem_resource_lock);
-	if (bootmem_resource_free) {
-		res = bootmem_resource_free;
-		bootmem_resource_free = res->sibling;
-	}
+	res = resource_first_child(&bootmem_resource_free);
+	if (res)
+		list_del(&res->sibling);
 	spin_unlock(&bootmem_resource_lock);
 
 	if (res)
@@ -177,6 +179,8 @@ static struct resource *alloc_resource(gfp_t flags)
 	else
 		res = kzalloc(sizeof(struct resource), flags);
 
+	INIT_LIST_HEAD(&res->child);
+	INIT_LIST_HEAD(&res->sibling);
 	return res;
 }
 
@@ -185,7 +189,7 @@ static struct resource * __request_resource(struct resource *root, struct resour
 {
 	resource_size_t start = new->start;
 	resource_size_t end = new->end;
-	struct resource *tmp, **p;
+	struct resource *tmp;
 
 	if (end < start)
 		return root;
@@ -193,64 +197,62 @@ static struct resource * __request_resource(struct resource *root, struct resour
 		return root;
 	if (end > root->end)
 		return root;
-	p = &root->child;
-	for (;;) {
-		tmp = *p;
-		if (!tmp || tmp->start > end) {
-			new->sibling = tmp;
-			*p = new;
+
+	if (list_empty(&root->child)) {
+		list_add(&new->sibling, &root->child);
+		new->parent = root;
+		INIT_LIST_HEAD(&new->child);
+		return NULL;
+	}
+
+	list_for_each_entry(tmp, &root->child, sibling) {
+		if (tmp->start > end) {
+			list_add(&new->sibling, tmp->sibling.prev);
 			new->parent = root;
+			INIT_LIST_HEAD(&new->child);
 			return NULL;
 		}
-		p = &tmp->sibling;
 		if (tmp->end < start)
 			continue;
 		return tmp;
 	}
+
+	list_add_tail(&new->sibling, &root->child);
+	new->parent = root;
+	INIT_LIST_HEAD(&new->child);
+	return NULL;
 }
 
 static int __release_resource(struct resource *old, bool release_child)
 {
-	struct resource *tmp, **p, *chd;
+	struct resource *tmp, *next, *chd;
 
-	p = &old->parent->child;
-	for (;;) {
-		tmp = *p;
-		if (!tmp)
-			break;
+	list_for_each_entry_safe(tmp, next, &old->parent->child, sibling) {
 		if (tmp == old) {
-			if (release_child || !(tmp->child)) {
-				*p = tmp->sibling;
+			if (release_child || list_empty(&tmp->child)) {
+				list_del(&tmp->sibling);
 			} else {
-				for (chd = tmp->child;; chd = chd->sibling) {
+				list_for_each_entry(chd, &tmp->child, sibling)
 					chd->parent = tmp->parent;
-					if (!(chd->sibling))
-						break;
-				}
-				*p = tmp->child;
-				chd->sibling = tmp->sibling;
+				list_splice(&tmp->child, tmp->sibling.prev);
+				list_del(&tmp->sibling);
 			}
+
 			old->parent = NULL;
 			return 0;
 		}
-		p = &tmp->sibling;
 	}
 	return -EINVAL;
 }
 
 static void __release_child_resources(struct resource *r)
 {
-	struct resource *tmp, *p;
+	struct resource *tmp, *next;
 	resource_size_t size;
 
-	p = r->child;
-	r->child = NULL;
-	while (p) {
-		tmp = p;
-		p = p->sibling;
-
+	list_for_each_entry_safe(tmp, next, &r->child, sibling) {
 		tmp->parent = NULL;
-		tmp->sibling = NULL;
+		list_del_init(&tmp->sibling);
 		__release_child_resources(tmp);
 
 		printk(KERN_DEBUG "release child resource %pR\n", tmp);
@@ -259,6 +261,8 @@ static void __release_child_resources(struct resource *r)
 		tmp->start = 0;
 		tmp->end = size - 1;
 	}
+
+	INIT_LIST_HEAD(&tmp->child);
 }
 
 void release_child_resources(struct resource *r)
@@ -343,7 +347,8 @@ static int find_next_iomem_res(struct resource *res, unsigned long desc,
 
 	read_lock(&resource_lock);
 
-	for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) {
+	for (p = resource_first_child(&iomem_resource.child); p;
+			p = next_resource(p, sibling_only)) {
 		if ((p->flags & res->flags) != res->flags)
 			continue;
 		if ((desc != IORES_DESC_NONE) && (desc != p->desc))
@@ -532,7 +537,7 @@ int region_intersects(resource_size_t start, size_t size, unsigned long flags,
 	struct resource *p;
 
 	read_lock(&resource_lock);
-	for (p = iomem_resource.child; p ; p = p->sibling) {
+	list_for_each_entry(p, &iomem_resource.child, sibling) {
 		bool is_type = (((p->flags & flags) == flags) &&
 				((desc == IORES_DESC_NONE) ||
 				 (desc == p->desc)));
@@ -586,7 +591,7 @@ static int __find_resource(struct resource *root, struct resource *old,
 			 resource_size_t  size,
 			 struct resource_constraint *constraint)
 {
-	struct resource *this = root->child;
+	struct resource *this = resource_first_child(&root->child);
 	struct resource tmp = *new, avail, alloc;
 
 	tmp.start = root->start;
@@ -596,7 +601,7 @@ static int __find_resource(struct resource *root, struct resource *old,
 	 */
 	if (this && this->start == root->start) {
 		tmp.start = (this == old) ? old->start : this->end + 1;
-		this = this->sibling;
+		this = resource_sibling(this);
 	}
 	for(;;) {
 		if (this)
@@ -632,7 +637,7 @@ next:		if (!this || this->end == root->end)
 
 		if (this != old)
 			tmp.start = this->end + 1;
-		this = this->sibling;
+		this = resource_sibling(this);
 	}
 	return -EBUSY;
 }
@@ -676,7 +681,7 @@ static int reallocate_resource(struct resource *root, struct resource *old,
 		goto out;
 	}
 
-	if (old->child) {
+	if (!list_empty(&old->child)) {
 		err = -EBUSY;
 		goto out;
 	}
@@ -757,7 +762,7 @@ struct resource *lookup_resource(struct resource *root, resource_size_t start)
 	struct resource *res;
 
 	read_lock(&resource_lock);
-	for (res = root->child; res; res = res->sibling) {
+	list_for_each_entry(res, &root->child, sibling) {
 		if (res->start == start)
 			break;
 	}
@@ -790,32 +795,27 @@ static struct resource * __insert_resource(struct resource *parent, struct resou
 			break;
 	}
 
-	for (next = first; ; next = next->sibling) {
+	for (next = first; ; next = resource_sibling(next)) {
 		/* Partial overlap? Bad, and unfixable */
 		if (next->start < new->start || next->end > new->end)
 			return next;
-		if (!next->sibling)
+		if (!resource_sibling(next))
 			break;
-		if (next->sibling->start > new->end)
+		if (resource_sibling(next)->start > new->end)
 			break;
 	}
-
 	new->parent = parent;
-	new->sibling = next->sibling;
-	new->child = first;
+	list_add(&new->sibling, &next->sibling);
+	INIT_LIST_HEAD(&new->child);
 
-	next->sibling = NULL;
-	for (next = first; next; next = next->sibling)
+	/*
+	 * From first to next, they all fall into new's region, so change them
+	 * as new's children.
+	 */
+	list_cut_position(&new->child, first->sibling.prev, &next->sibling);
+	list_for_each_entry(next, &new->child, sibling)
 		next->parent = new;
 
-	if (parent->child == first) {
-		parent->child = new;
-	} else {
-		next = parent->child;
-		while (next->sibling != first)
-			next = next->sibling;
-		next->sibling = new;
-	}
 	return NULL;
 }
 
@@ -937,19 +937,17 @@ static int __adjust_resource(struct resource *res, resource_size_t start,
 	if ((start < parent->start) || (end > parent->end))
 		goto out;
 
-	if (res->sibling && (res->sibling->start <= end))
+	if (resource_sibling(res) && (resource_sibling(res)->start <= end))
 		goto out;
 
-	tmp = parent->child;
-	if (tmp != res) {
-		while (tmp->sibling != res)
-			tmp = tmp->sibling;
+	if (res->sibling.prev != &parent->child) {
+		tmp = list_prev_entry(res, sibling);
 		if (start <= tmp->end)
 			goto out;
 	}
 
 skip:
-	for (tmp = res->child; tmp; tmp = tmp->sibling)
+	list_for_each_entry(tmp, &res->child, sibling)
 		if ((tmp->start < start) || (tmp->end > end))
 			goto out;
 
@@ -993,28 +991,31 @@ EXPORT_SYMBOL(adjust_resource);
  */
 int reparent_resources(struct resource *parent, struct resource *res)
 {
-	struct resource *p, **pp;
-	struct resource **firstpp = NULL;
+	struct resource *p, *first = NULL;
 
-	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+	list_for_each_entry(p, &parent->child, sibling) {
 		if (p->end < res->start)
 			continue;
 		if (res->end < p->start)
 			break;
 		if (p->start < res->start || p->end > res->end)
 			return -ENOTSUPP;	/* not completely contained */
-		if (firstpp == NULL)
-			firstpp = pp;
+		if (first == NULL)
+			first = p;
 	}
-	if (firstpp == NULL)
+	if (first == NULL)
 		return -ECANCELED; /* didn't find any conflicting entries? */
 	res->parent = parent;
-	res->child = *firstpp;
-	res->sibling = *pp;
-	*firstpp = res;
-	*pp = NULL;
-	for (p = res->child; p != NULL; p = p->sibling) {
-		p->parent = res;
+	list_add(&res->sibling, p->sibling.prev);
+	INIT_LIST_HEAD(&res->child);
+
+	/*
+	 * From first to p's previous sibling, they all fall into
+	 * res's region, change them as res's children.
+	 */
+	list_cut_position(&res->child, first->sibling.prev, res->sibling.prev);
+	list_for_each_entry(p, &res->child, sibling) {
+                p->parent = res;
 		pr_debug("PCI: Reparented %s %pR under %s\n",
 			 p->name, p, res->name);
 	}
@@ -1213,34 +1214,32 @@ EXPORT_SYMBOL(__request_region);
 void __release_region(struct resource *parent, resource_size_t start,
 			resource_size_t n)
 {
-	struct resource **p;
+	struct resource *res;
 	resource_size_t end;
 
-	p = &parent->child;
+	res = resource_first_child(&parent->child);
 	end = start + n - 1;
 
 	write_lock(&resource_lock);
 
 	for (;;) {
-		struct resource *res = *p;
-
 		if (!res)
 			break;
 		if (res->start <= start && res->end >= end) {
 			if (!(res->flags & IORESOURCE_BUSY)) {
-				p = &res->child;
+				res = resource_first_child(&res->child);
 				continue;
 			}
 			if (res->start != start || res->end != end)
 				break;
-			*p = res->sibling;
+			list_del(&res->sibling);
 			write_unlock(&resource_lock);
 			if (res->flags & IORESOURCE_MUXED)
 				wake_up(&muxed_resource_wait);
 			free_resource(res);
 			return;
 		}
-		p = &res->sibling;
+		res = resource_sibling(res);
 	}
 
 	write_unlock(&resource_lock);
@@ -1275,9 +1274,7 @@ EXPORT_SYMBOL(__release_region);
 int release_mem_region_adjustable(struct resource *parent,
 			resource_size_t start, resource_size_t size)
 {
-	struct resource **p;
-	struct resource *res;
-	struct resource *new_res;
+	struct resource *res, *new_res;
 	resource_size_t end;
 	int ret = -EINVAL;
 
@@ -1288,16 +1285,16 @@ int release_mem_region_adjustable(struct resource *parent,
 	/* The alloc_resource() result gets checked later */
 	new_res = alloc_resource(GFP_KERNEL);
 
-	p = &parent->child;
+	res = resource_first_child(&parent->child);
 	write_lock(&resource_lock);
 
-	while ((res = *p)) {
+	while ((res)) {
 		if (res->start >= end)
 			break;
 
 		/* look for the next resource if it does not fit into */
 		if (res->start > start || res->end < end) {
-			p = &res->sibling;
+			res = resource_sibling(res);
 			continue;
 		}
 
@@ -1305,14 +1302,14 @@ int release_mem_region_adjustable(struct resource *parent,
 			break;
 
 		if (!(res->flags & IORESOURCE_BUSY)) {
-			p = &res->child;
+			res = resource_first_child(&res->child);
 			continue;
 		}
 
 		/* found the target resource; let's adjust accordingly */
 		if (res->start == start && res->end == end) {
 			/* free the whole entry */
-			*p = res->sibling;
+			list_del(&res->sibling);
 			free_resource(res);
 			ret = 0;
 		} else if (res->start == start && res->end != end) {
@@ -1335,14 +1332,13 @@ int release_mem_region_adjustable(struct resource *parent,
 			new_res->flags = res->flags;
 			new_res->desc = res->desc;
 			new_res->parent = res->parent;
-			new_res->sibling = res->sibling;
-			new_res->child = NULL;
+			INIT_LIST_HEAD(&new_res->child);
 
 			ret = __adjust_resource(res, res->start,
 						start - res->start);
 			if (ret)
 				break;
-			res->sibling = new_res;
+			list_add(&new_res->sibling, &res->sibling);
 			new_res = NULL;
 		}
 
@@ -1523,7 +1519,7 @@ static int __init reserve_setup(char *str)
 			res->end = io_start + io_num - 1;
 			res->flags |= IORESOURCE_BUSY;
 			res->desc = IORES_DESC_NONE;
-			res->child = NULL;
+			INIT_LIST_HEAD(&res->child);
 			if (request_resource(parent, res) == 0)
 				reserved = x+1;
 		}
@@ -1543,7 +1539,7 @@ int iomem_map_sanity_check(resource_size_t addr, unsigned long size)
 	loff_t l;
 
 	read_lock(&resource_lock);
-	for (p = p->child; p ; p = r_next(NULL, p, &l)) {
+	for (p = resource_first_child(&p->child); p; p = r_next(NULL, p, &l)) {
 		/*
 		 * We can probably skip the resources without
 		 * IORESOURCE_IO attribute?
@@ -1599,7 +1595,7 @@ bool iomem_is_exclusive(u64 addr)
 	addr = addr & PAGE_MASK;
 
 	read_lock(&resource_lock);
-	for (p = p->child; p ; p = r_next(NULL, p, &l)) {
+	for (p = resource_first_child(&p->child); p; p = r_next(NULL, p, &l)) {
 		/*
 		 * We can probably skip the resources without
 		 * IORESOURCE_IO attribute?
-- 
2.13.6

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

^ permalink raw reply related

* [PATCH v6 1/4] resource: Move reparent_resources() to kernel/resource.c and make it public
From: Baoquan He @ 2018-07-04  4:10 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
	nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, josh-iaAMLnmF4UmaiuxdJuQwMA,
	fengguang.wu-ral2JQCrhuEAvxtiuMwx3w, bp-l3A5Bk7waGM,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w
  Cc: brijesh.singh-5C7GfCeVMHo, devicetree-u79uwXL29TY76Z2rM5mHXA,
	airlied-cv59FeDIM0c, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w,
	jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	kys-0li6OtcxBFHby3iVrkZq2A, frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
	lorenzo.pieralisi-5wv7dgnIgG8, sthemmin-0li6OtcxBFHby3iVrkZq2A,
	Baoquan He, linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	patrik.r.jakobsson-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	gustavo-THi1TnShQwVAfugRpC6u6w, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	thomas.lendacky-5C7GfCeVMHo, haiyangz-0li6OtcxBFHby3iVrkZq2A,
	maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA,
	jglisse-H+wXaHxf7aLQT0dZR+AlfA, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, tglx-hfZtesqFncYOwBW4kG4KsQ,
	yinghai-DgEjT+Ai2ygdnm+yROfE0A,
	jonathan.derrick-ral2JQCrhuEAvxtiuMwx3w,
	chris-YvXeqwSYzG2sTnJN9+BGXg, monstr-pSz03upnqPeHXe+LvDLADg,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w,
	devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, davem
In-Reply-To: <20180704041038.8190-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

reparent_resources() is duplicated in arch/microblaze/pci/pci-common.c
and arch/powerpc/kernel/pci-common.c, so move it to kernel/resource.c
so that it's shared.

Signed-off-by: Baoquan He <bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 arch/microblaze/pci/pci-common.c | 37 -------------------------------------
 arch/powerpc/kernel/pci-common.c | 35 -----------------------------------
 include/linux/ioport.h           |  1 +
 kernel/resource.c                | 39 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 40 insertions(+), 72 deletions(-)

diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index f34346d56095..7899bafab064 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -619,43 +619,6 @@ int pcibios_add_device(struct pci_dev *dev)
 EXPORT_SYMBOL(pcibios_add_device);
 
 /*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int __init reparent_resources(struct resource *parent,
-				     struct resource *res)
-{
-	struct resource *p, **pp;
-	struct resource **firstpp = NULL;
-
-	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
-		if (p->end < res->start)
-			continue;
-		if (res->end < p->start)
-			break;
-		if (p->start < res->start || p->end > res->end)
-			return -1;	/* not completely contained */
-		if (firstpp == NULL)
-			firstpp = pp;
-	}
-	if (firstpp == NULL)
-		return -1;	/* didn't find any conflicting entries? */
-	res->parent = parent;
-	res->child = *firstpp;
-	res->sibling = *pp;
-	*firstpp = res;
-	*pp = NULL;
-	for (p = res->child; p != NULL; p = p->sibling) {
-		p->parent = res;
-		pr_debug("PCI: Reparented %s [%llx..%llx] under %s\n",
-			 p->name,
-			 (unsigned long long)p->start,
-			 (unsigned long long)p->end, res->name);
-	}
-	return 0;
-}
-
-/*
  *  Handle resources of PCI devices.  If the world were perfect, we could
  *  just allocate all the resource regions and do nothing more.  It isn't.
  *  On the other hand, we cannot just re-allocate all devices, as it would
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index fe9733ffffaa..926035bb378d 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1088,41 +1088,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
 EXPORT_SYMBOL(pcibios_align_resource);
 
 /*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int reparent_resources(struct resource *parent,
-				     struct resource *res)
-{
-	struct resource *p, **pp;
-	struct resource **firstpp = NULL;
-
-	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
-		if (p->end < res->start)
-			continue;
-		if (res->end < p->start)
-			break;
-		if (p->start < res->start || p->end > res->end)
-			return -1;	/* not completely contained */
-		if (firstpp == NULL)
-			firstpp = pp;
-	}
-	if (firstpp == NULL)
-		return -1;	/* didn't find any conflicting entries? */
-	res->parent = parent;
-	res->child = *firstpp;
-	res->sibling = *pp;
-	*firstpp = res;
-	*pp = NULL;
-	for (p = res->child; p != NULL; p = p->sibling) {
-		p->parent = res;
-		pr_debug("PCI: Reparented %s %pR under %s\n",
-			 p->name, p, res->name);
-	}
-	return 0;
-}
-
-/*
  *  Handle resources of PCI devices.  If the world were perfect, we could
  *  just allocate all the resource regions and do nothing more.  It isn't.
  *  On the other hand, we cannot just re-allocate all devices, as it would
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index da0ebaec25f0..dfdcd0bfe54e 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -192,6 +192,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
 struct resource *lookup_resource(struct resource *root, resource_size_t start);
 int adjust_resource(struct resource *res, resource_size_t start,
 		    resource_size_t size);
+int reparent_resources(struct resource *parent, struct resource *res);
 resource_size_t resource_alignment(struct resource *res);
 static inline resource_size_t resource_size(const struct resource *res)
 {
diff --git a/kernel/resource.c b/kernel/resource.c
index 30e1bc68503b..d1cbf4b50e17 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -983,6 +983,45 @@ int adjust_resource(struct resource *res, resource_size_t start,
 }
 EXPORT_SYMBOL(adjust_resource);
 
+/*
+ * reparent_resources - reparent resource children of parent that res covers
+ * @parent: parent resource descriptor
+ * @res: resource descriptor desired by caller
+ *
+ * Reparent resource children of 'parent' that conflict with 'res'
+ * under 'res', and make 'res' replace those children.
+ */
+int reparent_resources(struct resource *parent, struct resource *res)
+{
+	struct resource *p, **pp;
+	struct resource **firstpp = NULL;
+
+	for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
+		if (p->end < res->start)
+			continue;
+		if (res->end < p->start)
+			break;
+		if (p->start < res->start || p->end > res->end)
+			return -ENOTSUPP;	/* not completely contained */
+		if (firstpp == NULL)
+			firstpp = pp;
+	}
+	if (firstpp == NULL)
+		return -ECANCELED; /* didn't find any conflicting entries? */
+	res->parent = parent;
+	res->child = *firstpp;
+	res->sibling = *pp;
+	*firstpp = res;
+	*pp = NULL;
+	for (p = res->child; p != NULL; p = p->sibling) {
+		p->parent = res;
+		pr_debug("PCI: Reparented %s %pR under %s\n",
+			 p->name, p, res->name);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(reparent_resources);
+
 static void __init __reserve_region_with_split(struct resource *root,
 		resource_size_t start, resource_size_t end,
 		const char *name)
-- 
2.13.6

^ permalink raw reply related

* [PATCH v6 0/4] resource: Use list_head to link sibling resource
From: Baoquan He @ 2018-07-04  4:10 UTC (permalink / raw)
  To: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
	nicolas.pitre-QSEj5FYQhm4dnm+yROfE0A, josh-iaAMLnmF4UmaiuxdJuQwMA,
	fengguang.wu-ral2JQCrhuEAvxtiuMwx3w, bp-l3A5Bk7waGM,
	andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w
  Cc: brijesh.singh-5C7GfCeVMHo, devicetree-u79uwXL29TY76Z2rM5mHXA,
	airlied-cv59FeDIM0c, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w,
	jcmvbkbc-Re5JQEeQqe8AvxtiuMwx3w,
	baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	kys-0li6OtcxBFHby3iVrkZq2A, frowand.list-Re5JQEeQqe8AvxtiuMwx3w,
	lorenzo.pieralisi-5wv7dgnIgG8, sthemmin-0li6OtcxBFHby3iVrkZq2A,
	Baoquan He, linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw,
	patrik.r.jakobsson-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	gustavo-THi1TnShQwVAfugRpC6u6w, dyoung-H+wXaHxf7aLQT0dZR+AlfA,
	thomas.lendacky-5C7GfCeVMHo, haiyangz-0li6OtcxBFHby3iVrkZq2A,
	maarten.lankhorst-VuQAYsv1563Yd54FQh9/CA,
	jglisse-H+wXaHxf7aLQT0dZR+AlfA, seanpaul-F7+t8E8rja9g9hUCZPvPmw,
	bhelgaas-hpIqsD4AKlfQT0dZR+AlfA, tglx-hfZtesqFncYOwBW4kG4KsQ,
	yinghai-DgEjT+Ai2ygdnm+yROfE0A,
	jonathan.derrick-ral2JQCrhuEAvxtiuMwx3w,
	chris-YvXeqwSYzG2sTnJN9+BGXg, monstr-pSz03upnqPeHXe+LvDLADg,
	linux-parisc-u79uwXL29TY76Z2rM5mHXA,
	gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	kexec-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	ebiederm-aS9lmoZGLiVWk0Htik3J/w,
	devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X,
	linuxppc-dev-uLR06cmDAlY/bJ5BZ2RsiQ, davem

This patchset is doing:
1) Replace struct resource's sibling list from singly linked list to
list_head. Clearing out those pointer operation within singly linked
list for better code readability.
2) Based on list_head replacement, add a new function
walk_system_ram_res_rev() which can does reversed iteration on
iomem_resource's siblings.
3) Change kexec_file loading to search system RAM top down for kernel
loadin, using walk_system_ram_res_rev().

Note:
This patchset only passed testing on  x86_64 arch with network
enabling. The thing we need pay attetion to is that a root resource's
child member need be initialized specifically with LIST_HEAD_INIT() if
statically defined or INIT_LIST_HEAD() for dynamically definition. Here
Just like we do for iomem_resource/ioport_resource, or the change in
get_pci_domain_busn_res().

v5:
http://lkml.kernel.org/r/20180612032831.29747-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

v4:
http://lkml.kernel.org/r/20180507063224.24229-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

v3:
http://lkml.kernel.org/r/20180419001848.3041-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

v2:
http://lkml.kernel.org/r/20180408024724.16812-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

v1:
http://lkml.kernel.org/r/20180322033722.9279-1-bhe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

Changelog:
v5->v6:
  Fix code style problems in reparent_resources() and use existing
  error codes, according to Andy's suggestion.

  Fix bugs test robot reported.
  
v4->v5:
  Add new patch 0001 to move duplicated reparent_resources() to
  kernel/resource.c to make it be shared by different ARCH-es.

  Fix several code bugs reported by test robot on ARCH powerpc and
  microblaze.
v3->v4:
  Fix several bugs test robot reported. Rewrite cover letter and patch
  log according to reviewer's comment.

v2->v3:
  Rename resource functions first_child() and sibling() to
  resource_first_chils() and resource_sibling(). Dan suggested this.

  Move resource_first_chils() and resource_sibling() to linux/ioport.h
  and make them as inline function. Rob suggested this. Accordingly add
  linux/list.h including in linux/ioport.h, please help review if this
  bring efficiency degradation or code redundancy.

  The change on struct resource {} bring two pointers of size increase,
  mention this in git log to make it more specifically, Rob suggested
  this.

v1->v2:
  Use list_head instead to link resource siblings. This is suggested by
  Andrew.

  Rewrite walk_system_ram_res_rev() after list_head is taken to link
  resouce siblings.



Baoquan He (4):
  resource: Move reparent_resources() to kernel/resource.c and make it
    public
  resource: Use list_head to link sibling resource
  resource: add walk_system_ram_res_rev()
  kexec_file: Load kernel at top of system RAM if required

 arch/arm/plat-samsung/pm-check.c            |   6 +-
 arch/microblaze/pci/pci-common.c            |  41 +----
 arch/powerpc/kernel/pci-common.c            |  39 +----
 arch/sparc/kernel/ioport.c                  |   2 +-
 arch/xtensa/include/asm/pci-bridge.h        |   4 +-
 drivers/eisa/eisa-bus.c                     |   2 +
 drivers/gpu/drm/drm_memory.c                |   3 +-
 drivers/gpu/drm/gma500/gtt.c                |   5 +-
 drivers/hv/vmbus_drv.c                      |  52 +++---
 drivers/input/joystick/iforce/iforce-main.c |   4 +-
 drivers/nvdimm/namespace_devs.c             |   6 +-
 drivers/nvdimm/nd.h                         |   5 +-
 drivers/of/address.c                        |   4 +-
 drivers/parisc/lba_pci.c                    |   4 +-
 drivers/pci/controller/vmd.c                |   8 +-
 drivers/pci/probe.c                         |   2 +
 drivers/pci/setup-bus.c                     |   2 +-
 include/linux/ioport.h                      |  21 ++-
 kernel/kexec_file.c                         |   2 +
 kernel/resource.c                           | 263 ++++++++++++++++++----------
 20 files changed, 248 insertions(+), 227 deletions(-)

-- 
2.13.6

^ permalink raw reply

* Re: [PATCH v5 1/4] resource: Move reparent_resources() to kernel/resource.c and make it public
From: Andy Shevchenko @ 2018-07-03 20:57 UTC (permalink / raw)
  To: Baoquan He
  Cc: Nicolas Pitre, brijesh.singh, devicetree, David Airlie, linux-pci,
	richard.weiyang, Keith Busch, Max Filippov, Paul Mackerras,
	baiyaowei, Frank Rowand, Dan Williams, Lorenzo Pieralisi,
	Stephen Hemminger, linux-nvdimm, Michael Ellerman,
	Patrik Jakobsson, linux-input, Gustavo Padovan, Borislav Petkov,
	Dave Young, Vivek Goyal, Tom Lendacky, Haiyang Zhang, Maarten
In-Reply-To: <20180703145503.GA1225@MiWiFi-R3L-srv>

On Tue, Jul 3, 2018 at 5:55 PM, Baoquan He <bhe@redhat.com> wrote:
> On 06/12/18 at 05:24pm, Andy Shevchenko wrote:
>> On Tue, Jun 12, 2018 at 5:20 PM, Andy Shevchenko
>> <andy.shevchenko@gmail.com> wrote:

>> > I briefly looked at the code and error codes we have, so, my proposal
>> > is one of the following
>>
>> >  - use -ECANCELED (not the best choice for first occurrence here,
>> > though I can't find better)
>>
>> Actually -ENOTSUPP might suit the first case (although the actual
>> would be something like -EOVERLAP, which we don't have)
>
> Sorry for late reply, and many thanks for your great suggestion.
>

> I am fine to use -ENOTSUPP as the first returned value, and -ECANCELED
> for the 2nd one.

I have no strong opinion, but I like (slightly better) this approach ^^^

> Or define an enum as you suggested inside the function
> or in header file.

>
> Or use -EBUSY for the first case because existing resource is
> overlapping but not fully contained by 'res'; and -EINVAL for
> the 2nd case since didn't find any one resources which is contained by
> 'res', means we passed in a invalid resource.
>
> All is fine to me, I can repost with each of them.

>> >  - use positive integers (or enum), like
>> >   #define RES_REPARENTED 0
>> >   #define RES_OVERLAPPED 1
>> >   #define RES_NOCONFLICT 2

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply

* [PATCH] Input: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2018-07-03 20:35 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, linux-kernel, Gustavo A. R. Silva

In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.

Warning level 2 was used: -Wimplicit-fallthrough=2

Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
 drivers/input/joystick/db9.c          | 5 +++++
 drivers/input/keyboard/adp5589-keys.c | 1 +
 drivers/input/mouse/appletouch.c      | 1 +
 drivers/input/mouse/cyapa_gen5.c      | 1 +
 drivers/input/mouse/cyapa_gen6.c      | 1 +
 drivers/input/mouse/elantech.c        | 2 +-
 drivers/input/mouse/sermouse.c        | 4 +++-
 drivers/input/touchscreen/elo.c       | 1 +
 8 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
index de0dd47..0006da5 100644
--- a/drivers/input/joystick/db9.c
+++ b/drivers/input/joystick/db9.c
@@ -263,6 +263,7 @@ static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char
 			db9_saturn_write_sub(port, type, 3, powered, 0);
 			return data[0] = 0xe3;
 		}
+		/* else: fall through */
 	default:
 		return data[0];
 	}
@@ -282,11 +283,14 @@ static int db9_saturn_report(unsigned char id, unsigned char data[60], struct in
 		switch (data[j]) {
 		case 0x16: /* multi controller (analog 4 axis) */
 			input_report_abs(dev, db9_abs[5], data[j + 6]);
+			/* fall through */
 		case 0x15: /* mission stick (analog 3 axis) */
 			input_report_abs(dev, db9_abs[3], data[j + 4]);
 			input_report_abs(dev, db9_abs[4], data[j + 5]);
+			/* fall through */
 		case 0x13: /* racing controller (analog 1 axis) */
 			input_report_abs(dev, db9_abs[2], data[j + 3]);
+			/* fall through */
 		case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
 		case 0x02: /* digital pad (digital 2 axis + buttons) */
 			input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
@@ -380,6 +384,7 @@ static void db9_timer(struct timer_list *t)
 			input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
 			input_report_abs(dev2, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
 			input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);
+			/* fall through */
 
 		case DB9_MULTI_0802:
 
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index 32d94c6..2835fba 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -885,6 +885,7 @@ static int adp5589_probe(struct i2c_client *client,
 	switch (id->driver_data) {
 	case ADP5585_02:
 		kpad->support_row5 = true;
+		/* fall through */
 	case ADP5585_01:
 		kpad->is_adp5585 = true;
 		kpad->var = &const_adp5585;
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c
index 032d279..0aeed28e8 100644
--- a/drivers/input/mouse/appletouch.c
+++ b/drivers/input/mouse/appletouch.c
@@ -472,6 +472,7 @@ static int atp_status_check(struct urb *urb)
 				dev->info->datalen, dev->urb->actual_length);
 			dev->overflow_warned = true;
 		}
+		/* fall through */
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
diff --git a/drivers/input/mouse/cyapa_gen5.c b/drivers/input/mouse/cyapa_gen5.c
index 5775d40..14239fb 100644
--- a/drivers/input/mouse/cyapa_gen5.c
+++ b/drivers/input/mouse/cyapa_gen5.c
@@ -2554,6 +2554,7 @@ static int cyapa_gen5_do_operational_check(struct cyapa *cyapa)
 		}
 
 		cyapa->state = CYAPA_STATE_GEN5_APP;
+		/* fall through */
 
 	case CYAPA_STATE_GEN5_APP:
 		/*
diff --git a/drivers/input/mouse/cyapa_gen6.c b/drivers/input/mouse/cyapa_gen6.c
index 0163978..c1b524a 100644
--- a/drivers/input/mouse/cyapa_gen6.c
+++ b/drivers/input/mouse/cyapa_gen6.c
@@ -680,6 +680,7 @@ static int cyapa_gen6_operational_check(struct cyapa *cyapa)
 		}
 
 		cyapa->state = CYAPA_STATE_GEN6_APP;
+		/* fall through */
 
 	case CYAPA_STATE_GEN6_APP:
 		/*
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index dd85b16..44f57cf 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -340,7 +340,7 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
 		 */
 		if (packet[3] & 0x80)
 			fingers = 4;
-		/* pass through... */
+		/* fall through */
 	case 1:
 		/*
 		 * byte 1:  .   .   .   .  x11 x10 x9  x8
diff --git a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
index 8df5266..4431057 100644
--- a/drivers/input/mouse/sermouse.c
+++ b/drivers/input/mouse/sermouse.c
@@ -143,7 +143,8 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
 			switch (sermouse->type) {
 
 				case SERIO_MS:
-					 sermouse->type = SERIO_MP;
+					sermouse->type = SERIO_MP;
+					/* fall through */
 
 				case SERIO_MP:
 					if ((data >> 2) & 3) break;	/* M++ Wireless Extension packet. */
@@ -154,6 +155,7 @@ static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
 				case SERIO_MZP:
 				case SERIO_MZPP:
 					input_report_key(dev, BTN_SIDE,   (data >> 5) & 1);
+					/* fall through */
 
 				case SERIO_MZ:
 					input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
index 83433e8..7f2942f 100644
--- a/drivers/input/touchscreen/elo.c
+++ b/drivers/input/touchscreen/elo.c
@@ -352,6 +352,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv)
 
 	case 1: /* 6-byte protocol */
 		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0);
+		/* fall through */
 
 	case 2: /* 4-byte protocol */
 		input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0);
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v5 1/4] resource: Move reparent_resources() to kernel/resource.c and make it public
From: Baoquan He @ 2018-07-03 14:55 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Nicolas Pitre, brijesh.singh-5C7GfCeVMHo, devicetree,
	David Airlie, linux-pci-u79uwXL29TY76Z2rM5mHXA,
	richard.weiyang-Re5JQEeQqe8AvxtiuMwx3w, Max Filippov,
	Paul Mackerras, baiyaowei-0p4V/sDNsUmm0O/7XYngnFaTQe2KTcn/,
	KY Srinivasan, Frank Rowand, Lorenzo Pieralisi, Stephen Hemminger,
	linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw, Michael Ellerman,
	Patrik Jakobsson, linux-input, Gustavo Padovan, Borislav Petkov,
	Dave Young, Tom Lendacky, Haiyang Zhang, Maarten Lankhorst,
	Josh Triplett
In-Reply-To: <CAHp75Vdaqj+n=F7wSB9PFGpf9Ok2XZzKcq_H0DzmtjmN-4UUfw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi Andy,

On 06/12/18 at 05:24pm, Andy Shevchenko wrote:
> On Tue, Jun 12, 2018 at 5:20 PM, Andy Shevchenko
> <andy.shevchenko-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> >> Hmm, I just copied it from arch/powerpc/kernel/pci-common.c. The
> >> function interface expects an integer returned value, not sure what a
> >> real error codes look like, could you give more hints? Will change
> >> accordingly.
> >
> > I briefly looked at the code and error codes we have, so, my proposal
> > is one of the following
> 
> >  - use -ECANCELED (not the best choice for first occurrence here,
> > though I can't find better)
> 
> Actually -ENOTSUPP might suit the first case (although the actual
> would be something like -EOVERLAP, which we don't have)

Sorry for late reply, and many thanks for your great suggestion.

I am fine to use -ENOTSUPP as the first returned value, and -ECANCELED
for the 2nd one. Or define an enum as you suggested inside the function
or in header file.

Or use -EBUSY for the first case because existing resource is
overlapping but not fully contained by 'res'; and -EINVAL for
the 2nd case since didn't find any one resources which is contained by
'res', means we passed in a invalid resource. 

All is fine to me, I can repost with each of them.

Thanks
Baoquan

> 
> >  - use positive integers (or enum), like
> >   #define RES_REPARENTED 0
> >   #define RES_OVERLAPPED 1
> >   #define RES_NOCONFLICT 2
> >
> >
> >>> > +               if (firstpp == NULL)
> >>> > +                       firstpp = pp;
> >>> > +       }
> >>>
> >>> > +       if (firstpp == NULL)
> >>> > +               return -1;      /* didn't find any conflicting entries? */
> >>>
> >>> Ditto.
> >
> > Ditto.
> >
> >>>
> >>> > +}
> >>> > +EXPORT_SYMBOL(reparent_resources);
> >
> > --
> > With Best Regards,
> > Andy Shevchenko
> 
> 
> 
> -- 
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply

* Re: [PATCH 0/3] cast sizeof to int for comparison
From: Dan Carpenter @ 2018-07-03 13:00 UTC (permalink / raw)
  To: Julia Lawall
  Cc: Joe Perches, linux-usb, Chengguang Xu, kernel-janitors,
	linux-kernel, linux-input, linux-media
In-Reply-To: <alpine.DEB.2.20.1807012050530.2494@hadrien>

On Sun, Jul 01, 2018 at 08:51:55PM +0200, Julia Lawall wrote:
> 
> 
> On Sun, 1 Jul 2018, Joe Perches wrote:
> 
> > On Sun, 2018-07-01 at 19:32 +0200, Julia Lawall wrote:
> > > Comparing an int to a size, which is unsigned, causes the int to become
> > > unsigned, giving the wrong result.
> > >
> > > The semantic match that finds this problem is as follows:
> > > (http://coccinelle.lip6.fr/)
> >
> > Great, thanks.
> >
> > But what about the ones in net/smc like:
> >
> > > net/smc/smc_clc.c:
> > >
> > >         len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
> > >                              sizeof(struct smc_clc_msg_decline));
> > >         if (len < sizeof(struct smc_clc_msg_decline))
> >
> > Are those detected by the semantic match and ignored?
> 
> I wasn't sure how to justify that kernel_sendmsg returns a negative value.
> If it is the case, I can send the patch.  I only found this in one file,
> but there were multiple occurrences.
> 

In theory, Smatch is supposed to know return values but kernel_sendmsg()
is too complicated for Smatch.  It's a tricky thing...  That particular
check is correct and deliberate, but there is another check which is
wrong.

net/smc/smc_clc.c
   369          len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
   370                               sizeof(struct smc_clc_msg_decline));
   371          if (len < sizeof(struct smc_clc_msg_decline))
   372                  smc->sk.sk_err = EPROTO;
   373          if (len < 0)
   374                  smc->sk.sk_err = -len;

If it's invalid we set an error code, if it's already an error we
preserve the error code.

   375          return sock_error(&smc->sk);

[ snip ]

   442          /* due to the few bytes needed for clc-handshake this cannot block */
   443          len = kernel_sendmsg(smc->clcsock, &msg, vec, i, plen);
   444          if (len < sizeof(pclc)) {
   445                  if (len >= 0) {
                            ^^^^^^^^
This is always true.

   446                          reason_code = -ENETUNREACH;
   447                          smc->sk.sk_err = -reason_code;
   448                  } else {
   449                          smc->sk.sk_err = smc->clcsock->sk->sk_err;
   450                          reason_code = -smc->sk.sk_err;
   451                  }
   452          }

The other two checks are not type promoted so they also work as
intended.

This is an interesting sort of bug I've written a Smatch script inspired
by your work here.  One for the type promotion and one for the
impossible condition.  I'll let you know how it goes.

regards,
dan carpenter

^ permalink raw reply

* Re: [PATCH] HID: debug: check length before copy_to_user()
From: Jiri Kosina @ 2018-07-03  9:55 UTC (permalink / raw)
  To: Benjamin Tissoires
  Cc: Daniel Rosenberg, open list:HID CORE LAYER, lkml, kernel-team,
	3.8+
In-Reply-To: <CAO-hwJLocBwuS7TGaXW88B-V8xSheATNDuvobv-Vk+hU0hei0A@mail.gmail.com>

On Tue, 3 Jul 2018, Benjamin Tissoires wrote:

> > If our length is greater than the size of the buffer, we
> > overflow the buffer
> >
> > Signed-off-by: Daniel Rosenberg <drosen@google.com>
> > Cc: stable@vger.kernel.org
> > ---
> 
> Looks good:
> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Indeed, thanks a lot for fixing this. Now queued, I'll push it for 4.18.

-- 
Jiri Kosina
SUSE Labs

^ permalink raw reply

* Re: [PATCH v8 1/2] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Enric Balletbo Serra @ 2018-07-03  9:26 UTC (permalink / raw)
  To: matti.vaittinen
  Cc: Michael Turquette, Rob Herring, Mark Rutland, Lee Jones,
	Liam Girdwood, Mark Brown, Matti Vaittinen, Arnd Bergmann,
	Dmitry Torokhov, Sebastian Reichel, chenjh, Andrey Smirnov,
	Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, sboyd, linux-clk, devicetree@vger.kernel.org,
	linux-kernel
In-Reply-To: <18a04e42debb2a23aec855cac3bcf3d6ab6c55fd.1530259815.git.matti.vaittinen@fi.rohmeurope.com>

Hi Matti,

One doubt regarding the probe function and few comments.

Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
dia dv., 29 de juny 2018 a les 11:47:
>
> ROHM BD71837 PMIC MFD driver providing interrupts and support
> for three subsystems:
> - clk
> - Regulators
> - input/power-key
>
> fix too long lines

I guess that this message is not intended to be here.

>
> Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> ---
>  drivers/mfd/Kconfig         |  13 ++
>  drivers/mfd/Makefile        |   1 +
>  drivers/mfd/bd71837.c       | 220 +++++++++++++++++++++++++
>  include/linux/mfd/bd71837.h | 391 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 625 insertions(+)
>  create mode 100644 drivers/mfd/bd71837.c
>  create mode 100644 include/linux/mfd/bd71837.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index b860eb5aa194..d01a279f5e4a 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1787,6 +1787,19 @@ config MFD_STW481X
>           in various ST Microelectronics and ST-Ericsson embedded
>           Nomadik series.
>
> +config MFD_BD71837
> +       tristate "BD71837 Power Management chip"
> +       depends on I2C=y
> +       depends on OF
> +       select REGMAP_I2C
> +       select REGMAP_IRQ
> +       select MFD_CORE
> +       help
> +         Select this option to get support for the ROHM BD71837
> +         Power Management chips. BD71837 is designed to power processors like
> +         NXP i.MX8. It contains 8 BUCK outputs and 7 LDOs, voltage monitoring
> +         and emergency shut down as well as 32,768KHz clock output.
> +
>  config MFD_STM32_LPTIMER
>         tristate "Support for STM32 Low-Power Timer"
>         depends on (ARCH_STM32 && OF) || COMPILE_TEST
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index e9fd20dba18d..09dc9eb3782c 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -227,4 +227,5 @@ obj-$(CONFIG_MFD_STM32_TIMERS)      += stm32-timers.o
>  obj-$(CONFIG_MFD_MXS_LRADC)     += mxs-lradc.o
>  obj-$(CONFIG_MFD_SC27XX_PMIC)  += sprd-sc27xx-spi.o
>  obj-$(CONFIG_RAVE_SP_CORE)     += rave-sp.o
> +obj-$(CONFIG_MFD_BD71837)      += bd71837.o
>
> diff --git a/drivers/mfd/bd71837.c b/drivers/mfd/bd71837.c
> new file mode 100644
> index 000000000000..25f2de2a5bb8
> --- /dev/null
> +++ b/drivers/mfd/bd71837.c
> @@ -0,0 +1,220 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +// Copyright (C) 2018 ROHM Semiconductors
> +// bd71837.c -- ROHM BD71837MWV mfd driver
> +//
> +// Datasheet available from
> +// https://www.rohm.com/datasheet/BD71837MWV/bd71837mwv-e
> +
> +#include <linux/i2c.h>
> +#include <linux/input.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/bd71837.h>
> +#include <linux/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +#include <linux/gpio_keys.h>
> +
> +static struct gpio_keys_button btns[] = {
> +       {
> +               .code = KEY_POWER,
> +               .gpio = -1,
> +               .type = EV_KEY,
> +       }
> +};
> +
> +static struct gpio_keys_platform_data bd718xx_powerkey_data = {
> +       .buttons = &btns[0],
> +       .nbuttons = ARRAY_SIZE(btns),
> +       .name = "bd718xx-pwrkey",
> +};
> +
> +/* bd71837 multi function cells */
> +
> +static struct mfd_cell bd71837_mfd_cells[] = {
> +       {
> +               .name = "bd71837-clk",
> +       }, {
> +               .name = "gpio-keys",
> +               .platform_data = &bd718xx_powerkey_data,
> +               .pdata_size = sizeof(bd718xx_powerkey_data),
> +       }, {
> +               .name = "bd71837-pmic",
> +       }
> +};
> +
> +static const struct regmap_irq bd71837_irqs[] = {
> +       REGMAP_IRQ_REG(BD71837_INT_SWRST, 0, BD71837_INT_SWRST_MASK),
> +       REGMAP_IRQ_REG(BD71837_INT_PWRBTN_S, 0, BD71837_INT_PWRBTN_S_MASK),
> +       REGMAP_IRQ_REG(BD71837_INT_PWRBTN_L, 0, BD71837_INT_PWRBTN_L_MASK),
> +       REGMAP_IRQ_REG(BD71837_INT_PWRBTN, 0, BD71837_INT_PWRBTN_MASK),
> +       REGMAP_IRQ_REG(BD71837_INT_WDOG, 0, BD71837_INT_WDOG_MASK),
> +       REGMAP_IRQ_REG(BD71837_INT_ON_REQ, 0, BD71837_INT_ON_REQ_MASK),
> +       REGMAP_IRQ_REG(BD71837_INT_STBY_REQ, 0, BD71837_INT_STBY_REQ_MASK),
> +};
> +
> +static struct regmap_irq_chip bd71837_irq_chip = {
> +       .name = "bd71837-irq",
> +       .irqs = bd71837_irqs,
> +       .num_irqs = ARRAY_SIZE(bd71837_irqs),
> +       .num_regs = 1,
> +       .irq_reg_stride = 1,
> +       .status_base = BD71837_REG_IRQ,
> +       .mask_base = BD71837_REG_MIRQ,
> +       .ack_base = BD71837_REG_IRQ,
> +       .init_ack_masked = true,
> +       .mask_invert = false,
> +};
> +
> +static const struct regmap_range pmic_status_range = {
> +       .range_min = BD71837_REG_IRQ,
> +       .range_max = BD71837_REG_POW_STATE,
> +};
> +
> +static const struct regmap_access_table volatile_regs = {
> +       .yes_ranges = &pmic_status_range,
> +       .n_yes_ranges = 1,
> +};
> +
> +static const struct regmap_config bd71837_regmap_config = {
> +       .reg_bits = 8,
> +       .val_bits = 8,
> +       .volatile_table = &volatile_regs,
> +       .max_register = BD71837_MAX_REGISTER - 1,
> +       .cache_type = REGCACHE_RBTREE,
> +};
> +
> +static const struct of_device_id bd71837_of_match[] = {
> +       { .compatible = "rohm,bd71837", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(of, bd71837_of_match);
> +
> +static int bd71837_i2c_probe(struct i2c_client *i2c,
> +                           const struct i2c_device_id *id)
> +{
> +       struct bd71837 *bd71837;
> +       struct bd71837_board *board_info;
> +       int ret = -EINVAL;
> +
> +       board_info = dev_get_platdata(&i2c->dev);

Sorry in advance if I am missing something, but isn't this always NULL?

> +
> +       if (!board_info) {

then this check is not required

> +               board_info = devm_kzalloc(&i2c->dev, sizeof(*board_info),
> +                                         GFP_KERNEL);
> +               if (!board_info) {
> +                       ret = -ENOMEM;
> +                       goto err_out;

Now that you use devm calls and you don't need to unwind things I
think is better to use plain returns. So,

return -ENOMEM;

> +               } else if (i2c->irq) {

IMO this else is confusing, also maybe you want to warn about the
missing interrupt.

if (!i2c->irq) {
    dev_err(&i2c->dev, "No IRQ configured!);
    return -EINVAL;
}

> +                       board_info->gpio_intr = i2c->irq;

Is board_info really necessary?

> +               } else {
> +                       ret = -ENOENT;
> +                       goto err_out;
> +               }

and remove the else

> +       }
> +
> +       if (!board_info)
> +               goto err_out;
> +

This is redundant.

> +       bd71837 = devm_kzalloc(&i2c->dev, sizeof(struct bd71837), GFP_KERNEL);
> +       if (bd71837 == NULL)

if (!bd71837)

> +               return -ENOMEM;
> +
> +       i2c_set_clientdata(i2c, bd71837);
> +       bd71837->dev = &i2c->dev;
> +       bd71837->i2c_client = i2c;
> +       bd71837->chip_irq = board_info->gpio_intr;

bd71837->chip_irq = i2c->irq;

> +
> +       bd71837->regmap = devm_regmap_init_i2c(i2c, &bd71837_regmap_config);
> +       if (IS_ERR(bd71837->regmap)) {
> +               ret = PTR_ERR(bd71837->regmap);
> +               dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret);
> +               goto err_out;

    dev_err(bd71837->dev, "regmap initialization failed: %d\n", ret);
    return PTR_ERR(bd71837->regmap);

> +       }
> +
> +       ret = bd71837_reg_read(bd71837, BD71837_REG_REV);
> +       if (ret < 0) {
> +               dev_err(bd71837->dev,
> +                       "%s(): Read BD71837_REG_DEVICE failed!\n", __func__);

__func__ part is redundant.

> +               goto err_out;
return ret;
> +       }
> +
> +       ret = devm_regmap_add_irq_chip(&i2c->dev, bd71837->regmap,
> +                                      bd71837->chip_irq, IRQF_ONESHOT, 0,
> +                                      &bd71837_irq_chip, &bd71837->irq_data);
> +       if (ret < 0) {
> +               dev_err(bd71837->dev, "Failed to add irq_chip %d\n", ret);
> +               goto err_out;
return ret;
> +       }
> +
> +       ret = regmap_update_bits(bd71837->regmap,
> +                                BD71837_REG_PWRONCONFIG0,
> +                                BD718XX_PWRBTN_PRESS_DURATION_MASK,
> +                                BD718XX_PWRBTN_SHORT_PRESS_10MS);
> +       if (ret < 0) {
> +               dev_err(bd71837->dev,
> +                       "Failed to configure button short press timeout %d\n",
> +                        ret);
> +               goto err_out;
return ret;
> +       }
> +       /* According to BD71847 datasheet the HW default for long press
> +        * detection is 10ms. So lets change it to 10 sec so we can actually
> +        * get the short push and allow gracefull shut down
> +        */
> +       ret = regmap_update_bits(bd71837->regmap,
> +                                BD71837_REG_PWRONCONFIG1,
> +                                BD718XX_PWRBTN_PRESS_DURATION_MASK,
> +                                BD718XX_PWRBTN_LONG_PRESS_10S);
> +       if (ret < 0) {
> +               dev_err(bd71837->dev,
> +                       "Failed to configure button long press timeout %d\n",
> +                        ret);
> +               goto err_out;
return ret;
> +       }
> +       btns[0].irq = regmap_irq_get_virq(bd71837->irq_data,
> +                                         BD71837_INT_PWRBTN_S);
> +
> +       if (btns[0].irq < 0) {
> +               ret = btns[0].irq;
> +               goto err_out;
return ret;
> +       }
> +
> +       ret = devm_mfd_add_devices(bd71837->dev, PLATFORM_DEVID_AUTO,
> +                                  bd71837_mfd_cells,
> +                                  ARRAY_SIZE(bd71837_mfd_cells), NULL, 0,
> +                                  regmap_irq_get_domain(bd71837->irq_data));
> +err_out:

Remove the label.

> +
> +       return ret;
> +}
> +
> +static const struct i2c_device_id bd71837_i2c_id[] = {
> +       { .name = "bd71837", },
> +       { }
> +};
> +MODULE_DEVICE_TABLE(i2c, bd71837_i2c_id);
> +
> +static struct i2c_driver bd71837_i2c_driver = {
> +       .driver = {
> +               .name = "bd71837-mfd",
> +               .of_match_table = bd71837_of_match,
> +       },
> +       .probe = bd71837_i2c_probe,
> +       .id_table = bd71837_i2c_id,
> +};
> +
> +static int __init bd71837_i2c_init(void)
> +{
> +       return i2c_add_driver(&bd71837_i2c_driver);
> +}
> +/* init early so consumer devices can complete system boot */
> +subsys_initcall(bd71837_i2c_init);
> +
> +static void __exit bd71837_i2c_exit(void)
> +{
> +       i2c_del_driver(&bd71837_i2c_driver);
> +}
> +module_exit(bd71837_i2c_exit);
> +
> +MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
> +MODULE_DESCRIPTION("BD71837 chip multi-function driver");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/bd71837.h b/include/linux/mfd/bd71837.h
> new file mode 100644
> index 000000000000..10b0dfe90f27
> --- /dev/null
> +++ b/include/linux/mfd/bd71837.h
> @@ -0,0 +1,391 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/* Copyright (C) 2018 ROHM Semiconductors */
> +
> +/*
> + * ROHM BD71837MWV header file
> + */
> +
> +#ifndef __LINUX_MFD_BD71837_H__
> +#define __LINUX_MFD_BD71837_H__
> +
> +#include <linux/regmap.h>
> +
> +enum {
> +       BD71837_BUCK1   =       0,
> +       BD71837_BUCK2,
> +       BD71837_BUCK3,
> +       BD71837_BUCK4,
> +       BD71837_BUCK5,
> +       BD71837_BUCK6,
> +       BD71837_BUCK7,
> +       BD71837_BUCK8,
> +       BD71837_LDO1,
> +       BD71837_LDO2,
> +       BD71837_LDO3,
> +       BD71837_LDO4,
> +       BD71837_LDO5,
> +       BD71837_LDO6,
> +       BD71837_LDO7,
> +       BD71837_REGULATOR_CNT,
> +};
> +
> +#define BD71837_BUCK1_VOLTAGE_NUM      0x40
> +#define BD71837_BUCK2_VOLTAGE_NUM      0x40
> +#define BD71837_BUCK3_VOLTAGE_NUM      0x40
> +#define BD71837_BUCK4_VOLTAGE_NUM      0x40
> +
> +#define BD71837_BUCK5_VOLTAGE_NUM      0x08
> +#define BD71837_BUCK6_VOLTAGE_NUM      0x04
> +#define BD71837_BUCK7_VOLTAGE_NUM      0x08
> +#define BD71837_BUCK8_VOLTAGE_NUM      0x40
> +
> +#define BD71837_LDO1_VOLTAGE_NUM       0x04
> +#define BD71837_LDO2_VOLTAGE_NUM       0x02
> +#define BD71837_LDO3_VOLTAGE_NUM       0x10
> +#define BD71837_LDO4_VOLTAGE_NUM       0x10
> +#define BD71837_LDO5_VOLTAGE_NUM       0x10
> +#define BD71837_LDO6_VOLTAGE_NUM       0x10
> +#define BD71837_LDO7_VOLTAGE_NUM       0x10
> +
> +enum {
> +       BD71837_REG_REV                = 0x00,
> +       BD71837_REG_SWRESET            = 0x01,
> +       BD71837_REG_I2C_DEV            = 0x02,
> +       BD71837_REG_PWRCTRL0           = 0x03,
> +       BD71837_REG_PWRCTRL1           = 0x04,
> +       BD71837_REG_BUCK1_CTRL         = 0x05,
> +       BD71837_REG_BUCK2_CTRL         = 0x06,
> +       BD71837_REG_BUCK3_CTRL         = 0x07,
> +       BD71837_REG_BUCK4_CTRL         = 0x08,
> +       BD71837_REG_BUCK5_CTRL         = 0x09,
> +       BD71837_REG_BUCK6_CTRL         = 0x0A,
> +       BD71837_REG_BUCK7_CTRL         = 0x0B,
> +       BD71837_REG_BUCK8_CTRL         = 0x0C,
> +       BD71837_REG_BUCK1_VOLT_RUN     = 0x0D,
> +       BD71837_REG_BUCK1_VOLT_IDLE    = 0x0E,
> +       BD71837_REG_BUCK1_VOLT_SUSP    = 0x0F,
> +       BD71837_REG_BUCK2_VOLT_RUN     = 0x10,
> +       BD71837_REG_BUCK2_VOLT_IDLE    = 0x11,
> +       BD71837_REG_BUCK3_VOLT_RUN     = 0x12,
> +       BD71837_REG_BUCK4_VOLT_RUN     = 0x13,
> +       BD71837_REG_BUCK5_VOLT         = 0x14,
> +       BD71837_REG_BUCK6_VOLT         = 0x15,
> +       BD71837_REG_BUCK7_VOLT         = 0x16,
> +       BD71837_REG_BUCK8_VOLT         = 0x17,
> +       BD71837_REG_LDO1_VOLT          = 0x18,
> +       BD71837_REG_LDO2_VOLT          = 0x19,
> +       BD71837_REG_LDO3_VOLT          = 0x1A,
> +       BD71837_REG_LDO4_VOLT          = 0x1B,
> +       BD71837_REG_LDO5_VOLT          = 0x1C,
> +       BD71837_REG_LDO6_VOLT          = 0x1D,
> +       BD71837_REG_LDO7_VOLT          = 0x1E,
> +       BD71837_REG_TRANS_COND0        = 0x1F,
> +       BD71837_REG_TRANS_COND1        = 0x20,
> +       BD71837_REG_VRFAULTEN          = 0x21,
> +       BD71837_REG_MVRFLTMASK0        = 0x22,
> +       BD71837_REG_MVRFLTMASK1        = 0x23,
> +       BD71837_REG_MVRFLTMASK2        = 0x24,
> +       BD71837_REG_RCVCFG             = 0x25,
> +       BD71837_REG_RCVNUM             = 0x26,
> +       BD71837_REG_PWRONCONFIG0       = 0x27,
> +       BD71837_REG_PWRONCONFIG1       = 0x28,
> +       BD71837_REG_RESETSRC           = 0x29,
> +       BD71837_REG_MIRQ               = 0x2A,
> +       BD71837_REG_IRQ                = 0x2B,
> +       BD71837_REG_IN_MON             = 0x2C,
> +       BD71837_REG_POW_STATE          = 0x2D,
> +       BD71837_REG_OUT32K             = 0x2E,
> +       BD71837_REG_REGLOCK            = 0x2F,
> +       BD71837_REG_OTPVER             = 0xFF,
> +       BD71837_MAX_REGISTER           = 0x100,
> +};
> +
> +#define REGLOCK_PWRSEQ 0x1
> +#define REGLOCK_VREG   0x10
> +
> +/* Generic BUCK control masks */
> +#define BD71837_BUCK_SEL       0x02
> +#define BD71837_BUCK_EN                0x01
> +#define BD71837_BUCK_RUN_ON    0x04
> +
> +/* Generic LDO masks */
> +#define BD71837_LDO_SEL                0x80
> +#define BD71837_LDO_EN         0x40
> +
> +/* BD71837 BUCK ramp rate CTRL reg bits */
> +#define BUCK_RAMPRATE_MASK     0xC0
> +#define BUCK_RAMPRATE_10P00MV  0x0
> +#define BUCK_RAMPRATE_5P00MV   0x1
> +#define BUCK_RAMPRATE_2P50MV   0x2
> +#define BUCK_RAMPRATE_1P25MV   0x3
> +
> +/* BD71837_REG_BUCK1_VOLT_RUN bits */
> +#define BUCK1_RUN_MASK         0x3F
> +#define BUCK1_RUN_DEFAULT      0x14
> +
> +/* BD71837_REG_BUCK1_VOLT_SUSP bits */
> +#define BUCK1_SUSP_MASK                0x3F
> +#define BUCK1_SUSP_DEFAULT     0x14
> +
> +/* BD71837_REG_BUCK1_VOLT_IDLE bits */
> +#define BUCK1_IDLE_MASK                0x3F
> +#define BUCK1_IDLE_DEFAULT     0x14
> +
> +/* BD71837_REG_BUCK2_VOLT_RUN bits */
> +#define BUCK2_RUN_MASK         0x3F
> +#define BUCK2_RUN_DEFAULT      0x1E
> +
> +/* BD71837_REG_BUCK2_VOLT_IDLE bits */
> +#define BUCK2_IDLE_MASK                0x3F
> +#define BUCK2_IDLE_DEFAULT     0x14
> +
> +/* BD71837_REG_BUCK3_VOLT_RUN bits */
> +#define BUCK3_RUN_MASK         0x3F
> +#define BUCK3_RUN_DEFAULT      0x1E
> +
> +/* BD71837_REG_BUCK4_VOLT_RUN bits */
> +#define BUCK4_RUN_MASK         0x3F
> +#define BUCK4_RUN_DEFAULT      0x1E
> +
> +/* BD71837_REG_BUCK5_VOLT bits */
> +#define BUCK5_MASK             0x07
> +#define BUCK5_DEFAULT          0x02
> +
> +/* BD71837_REG_BUCK6_VOLT bits */
> +#define BUCK6_MASK             0x03
> +#define BUCK6_DEFAULT          0x03
> +
> +/* BD71837_REG_BUCK7_VOLT bits */
> +#define BUCK7_MASK             0x07
> +#define BUCK7_DEFAULT          0x03
> +
> +/* BD71837_REG_BUCK8_VOLT bits */
> +#define BUCK8_MASK             0x3F
> +#define BUCK8_DEFAULT          0x1E
> +
> +/* BD71837_REG_IRQ bits */
> +#define IRQ_SWRST              0x40
> +#define IRQ_PWRON_S            0x20
> +#define IRQ_PWRON_L            0x10
> +#define IRQ_PWRON              0x08
> +#define IRQ_WDOG               0x04
> +#define IRQ_ON_REQ             0x02
> +#define IRQ_STBY_REQ           0x01
> +
> +/* BD71837_REG_OUT32K bits */
> +#define BD71837_OUT32K_EN      0x01
> +
> +/* BD71837 gated clock rate */
> +#define BD71837_CLK_RATE 32768
> +
> +/* BD71837 irqs */
> +enum {
> +       BD71837_INT_STBY_REQ,
> +       BD71837_INT_ON_REQ,
> +       BD71837_INT_WDOG,
> +       BD71837_INT_PWRBTN,
> +       BD71837_INT_PWRBTN_L,
> +       BD71837_INT_PWRBTN_S,
> +       BD71837_INT_SWRST
> +};
> +
> +/* BD71837 interrupt masks */
> +#define BD71837_INT_SWRST_MASK         0x40
> +#define BD71837_INT_PWRBTN_S_MASK      0x20
> +#define BD71837_INT_PWRBTN_L_MASK      0x10
> +#define BD71837_INT_PWRBTN_MASK                0x8
> +#define BD71837_INT_WDOG_MASK          0x4
> +#define BD71837_INT_ON_REQ_MASK                0x2
> +#define BD71837_INT_STBY_REQ_MASK      0x1
> +
> +/* BD71837_REG_LDO1_VOLT bits */
> +#define LDO1_MASK              0x03
> +
> +/* BD71837_REG_LDO1_VOLT bits */
> +#define LDO2_MASK              0x20
> +
> +/* BD71837_REG_LDO3_VOLT bits */
> +#define LDO3_MASK              0x0F
> +
> +/* BD71837_REG_LDO4_VOLT bits */
> +#define LDO4_MASK              0x0F
> +
> +/* BD71837_REG_LDO5_VOLT bits */
> +#define LDO5_MASK              0x0F
> +
> +/* BD71837_REG_LDO6_VOLT bits */
> +#define LDO6_MASK              0x0F
> +
> +/* BD71837_REG_LDO7_VOLT bits */
> +#define LDO7_MASK              0x0F
> +
> +/* Register write induced reset settings */
> +
> +/* Even though the bit zero is not SWRESET type we still want to write zero
> + * to it when changing type. Bit zero is 'SWRESET' trigger bit and if we
> + * write 1 to it we will trigger the action. So always write 0 to it when
> + * changning SWRESET action - no matter what we read from it.
> + */
> +#define BD71837_SWRESET_TYPE_MASK 7
> +#define BD71837_SWRESET_TYPE_DISABLED 0
> +#define BD71837_SWRESET_TYPE_COLD 4
> +#define BD71837_SWRESET_TYPE_WARM 6
> +
> +#define BD71837_SWRESET_RESET_MASK 1
> +#define BD71837_SWRESET_RESET 1
> +
> +/* Poweroff state transition conditions */
> +
> +#define BD718XX_ON_REQ_POWEROFF_MASK 1
> +#define BD718XX_SWRESET_POWEROFF_MASK 2
> +#define BD718XX_WDOG_POWEROFF_MASK 4
> +#define BD718XX_KEY_L_POWEROFF_MASK 8
> +
> +#define BD718XX_POWOFF_TO_SNVS 0
> +#define BD718XX_POWOFF_TO_RDY 0xF
> +
> +#define BD718XX_POWOFF_TIME_MASK 0xF0
> +enum {
> +       BD718XX_POWOFF_TIME_5MS = 0,
> +       BD718XX_POWOFF_TIME_10MS,
> +       BD718XX_POWOFF_TIME_15MS,
> +       BD718XX_POWOFF_TIME_20MS,
> +       BD718XX_POWOFF_TIME_25MS,
> +       BD718XX_POWOFF_TIME_30MS,
> +       BD718XX_POWOFF_TIME_35MS,
> +       BD718XX_POWOFF_TIME_40MS,
> +       BD718XX_POWOFF_TIME_45MS,
> +       BD718XX_POWOFF_TIME_50MS,
> +       BD718XX_POWOFF_TIME_75MS,
> +       BD718XX_POWOFF_TIME_100MS,
> +       BD718XX_POWOFF_TIME_250MS,
> +       BD718XX_POWOFF_TIME_500MS,
> +       BD718XX_POWOFF_TIME_750MS,
> +       BD718XX_POWOFF_TIME_1500MS
> +};
> +
> +/* Poweron sequence state transition conditions */
> +
> +#define BD718XX_RDY_TO_SNVS_MASK 0xF
> +#define BD718XX_SNVS_TO_RUN_MASK 0xF0
> +
> +#define BD718XX_PWR_TRIG_KEY_L 1
> +#define BD718XX_PWR_TRIG_KEY_S 2
> +#define BD718XX_PWR_TRIG_PMIC_ON 4
> +#define BD718XX_PWR_TRIG_VSYS_UVLO 8
> +#define BD718XX_RDY_TO_SNVS_SIFT 0
> +#define BD718XX_SNVS_TO_RUN_SIFT 4
> +
> +
> +#define BD718XX_PWRBTN_PRESS_DURATION_MASK 0xF
> +
> +/* Timeout value for detecting short press */
> +
> +enum {
> +       BD718XX_PWRBTN_SHORT_PRESS_10MS = 0,
> +       BD718XX_PWRBTN_SHORT_PRESS_500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_1000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_1500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_2000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_2500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_3000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_3500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_4000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_4500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_5000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_5500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_6000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_6500MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_7000MS,
> +       BD718XX_PWRBTN_SHORT_PRESS_7500MS
> +};
> +
> +/* Timeout value for detecting LONG press */
> +
> +enum {
> +       BD718XX_PWRBTN_LONG_PRESS_10MS = 0,
> +       BD718XX_PWRBTN_LONG_PRESS_1S,
> +       BD718XX_PWRBTN_LONG_PRESS_2S,
> +       BD718XX_PWRBTN_LONG_PRESS_3S,
> +       BD718XX_PWRBTN_LONG_PRESS_4S,
> +       BD718XX_PWRBTN_LONG_PRESS_5S,
> +       BD718XX_PWRBTN_LONG_PRESS_6S,
> +       BD718XX_PWRBTN_LONG_PRESS_7S,
> +       BD718XX_PWRBTN_LONG_PRESS_8S,
> +       BD718XX_PWRBTN_LONG_PRESS_9S,
> +       BD718XX_PWRBTN_LONG_PRESS_10S,
> +       BD718XX_PWRBTN_LONG_PRESS_11S,
> +       BD718XX_PWRBTN_LONG_PRESS_12S,
> +       BD718XX_PWRBTN_LONG_PRESS_13S,
> +       BD718XX_PWRBTN_LONG_PRESS_14S,
> +       BD718XX_PWRBTN_LONG_PRESS_15S
> +};
> +
> +
> +
> +struct bd71837;
> +struct bd71837_pmic;
> +struct bd71837_clk;
> +struct bd718xx_pwrkey;
> +
> +/*
> + * Board platform data may be used to initialize regulators.
> + */
> +
> +struct bd71837_board {
> +       struct regulator_init_data *init_data[BD71837_REGULATOR_CNT];
> +       int     gpio_intr;
> +};
> +
> +struct bd71837 {
> +       struct device *dev;
> +       struct i2c_client *i2c_client;
> +       struct regmap *regmap;
> +       unsigned long int id;
> +
> +       int chip_irq;
> +       struct regmap_irq_chip_data *irq_data;
> +
> +       struct bd71837_pmic *pmic;
> +       struct bd71837_clk *clk;
> +       struct bd718xx_pwrkey *pwrkey;
> +};
> +
> +/*
> + * bd71837 sub-driver chip access routines
> + */
> +
> +static inline int bd71837_reg_read(struct bd71837 *bd71837, u8 reg)
> +{
> +       int r, val;
> +
> +       r = regmap_read(bd71837->regmap, reg, &val);
> +       if (r < 0)
> +               return r;
> +       return val;
> +}
> +
> +static inline int bd71837_reg_write(struct bd71837 *bd71837, u8 reg,
> +                                   unsigned int val)
> +{
> +       return regmap_write(bd71837->regmap, reg, val);
> +}
> +
> +static inline int bd71837_set_bits(struct bd71837 *bd71837, u8 reg, u8 mask)
> +{
> +       return regmap_update_bits(bd71837->regmap, reg, mask, mask);
> +}
> +
> +static inline int bd71837_clear_bits(struct bd71837 *bd71837, u8 reg,
> +                                    u8 mask)
> +{
> +       return regmap_update_bits(bd71837->regmap, reg, mask, 0);
> +}
> +
> +static inline int bd71837_update_bits(struct bd71837 *bd71837, u8 reg,
> +                                     u8 mask, u8 val)
> +{
> +       return regmap_update_bits(bd71837->regmap, reg, mask, val);
> +}
> +
> +#endif /* __LINUX_MFD_BD71837_H__ */
> --
> 2.14.3
>

^ permalink raw reply

* Re: [PATCH] input: mtk-pmic-keys: Fix probe when no DT node present
From: Lee Jones @ 2018-07-03  9:17 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Matthias Brugger, chen.zhong, linux-input, linux-arm-kernel,
	linux-mediatek, linux-kernel, Matthias Brugger
In-Reply-To: <20180622183114.GA92912@dtor-ws>

On Fri, 22 Jun 2018, Dmitry Torokhov wrote:

> On Fri, Jun 22, 2018 at 01:42:28PM +0200, Matthias Brugger wrote:
> > The drivers gets probed from a mfd devices. So the driver runs
> > probe although no DT node exists. This leads to a NULL pointer
> > dereference in the probe function. Check if a node exists and
> > error out in case none is present.
> 
> Hmm, if a cell specifies of_compatible and no such node is present in DT
> maybe we should bail out in mfd_add_device() instead of pushing the
> check into individual drivers? Something like:
> 
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 94e3f32ce935..36a5fd98000d 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -137,6 +137,18 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
>  }
>  #endif
>  
> +static struct device_node *mfd_get_node_for_cell(struct device *parent,
> +						 const struct mfd_cell *cell)
> +{
> +	struct device_node *np;
> +
> +	for_each_child_of_node(parent->of_node, np)
> +		if (of_device_is_compatible(np, cell->of_compatible))
> +			return np;
> +
> +	return NULL;
> +}
> +
>  static int mfd_add_device(struct device *parent, int id,
>  			  const struct mfd_cell *cell, atomic_t *usage_count,
>  			  struct resource *mem_base,
> @@ -144,7 +156,6 @@ static int mfd_add_device(struct device *parent, int id,
>  {
>  	struct resource *res;
>  	struct platform_device *pdev;
> -	struct device_node *np = NULL;
>  	int ret = -ENOMEM;
>  	int platform_id;
>  	int r;
> @@ -176,11 +187,11 @@ static int mfd_add_device(struct device *parent, int id,
>  		goto fail_res;
>  
>  	if (parent->of_node && cell->of_compatible) {
> -		for_each_child_of_node(parent->of_node, np) {
> -			if (of_device_is_compatible(np, cell->of_compatible)) {
> -				pdev->dev.of_node = np;
> -				break;
> -			}
> +		pdev->dev.of_node = mfd_get_node_for_cell(parent, cell);
> +		if (!pdev->dev.of_node) {
> +			dev_err(parent, "unable to locate node for %s (%s)\n",
> +				cell->name, cell->of_compatible);
> +			goto fail_res;
>  		}
>  	}
>  
> Lee?

This change results the wrong semantics.  MFD overrides Device Tree,
such that if a device is supplied and registered using
mfd_add_device(s) it should be probed.  The only reason we provide a
pointer to the of_node is for the child device to pull properties
from.

If a device should only be probed if an OF node exists, then it should
not be registered at the MFD level.

> > Fixes: 3e9f0b3e2b27 ("input: Add MediaTek PMIC keys support")
> > Signed-off-by: Matthias Brugger <mbrugger@suse.com>
> > ---
> >  drivers/input/keyboard/mtk-pmic-keys.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
> > index 02c67a1749fc..388043e1939c 100644
> > --- a/drivers/input/keyboard/mtk-pmic-keys.c
> > +++ b/drivers/input/keyboard/mtk-pmic-keys.c
> > @@ -257,6 +257,9 @@ static int mtk_pmic_keys_probe(struct platform_device *pdev)
> >  	const struct of_device_id *of_id =
> >  		of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
> >  
> > +	if (of_id == NULL)
> > +		return -ENODEV;
> > +
> >  	keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
> >  	if (!keys)
> >  		return -ENOMEM;
> 
> Thanks.
> 

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH 4/4] HID: multitouch: remove unneeded else conditional cases
From: Benjamin Tissoires @ 2018-07-03  8:17 UTC (permalink / raw)
  To: Joey Pabalinas; +Cc: open list:HID CORE LAYER, lkml, Jiri Kosina, Daniel Martin
In-Reply-To: <d35643165a1d1972fd91e547922697a3c785a413.1530402641.git.joeypabalinas@gmail.com>

On Sun, Jul 1, 2018 at 2:19 AM, Joey Pabalinas <joeypabalinas@gmail.com> wrote:
> Elide lone `else` cases and replace `else if` clauses
> with plain `if` conditionals when they occur immediately
> after return statements.
>
> Signed-off-by: Joey Pabalinas <joeypabalinas@gmail.com>
>

This one looks good.
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Just FYI, I sent out a big refactor of the hid-multitouch code. Jiri
should be still reviewing it, so I am not so sure who will have to
rebase which series on top of the other, but someone between us will
have to do it :)

Cheers,
Benjamin

>  1 file changed, 6 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index 08b50e5908cecdda66..30b1a2c67f39a41325 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -205,12 +205,12 @@ static void mt_post_parse(struct mt_device *td);
>
>  static int cypress_compute_slot(struct mt_device *td)
>  {
>         if (td->curdata.contactid != 0 || td->num_received == 0)
>                 return td->curdata.contactid;
> -       else
> -               return -1;
> +
> +       return -1;
>  }
>
>  static struct mt_class mt_classes[] = {
>         { .name = MT_CLS_DEFAULT,
>                 .quirks = MT_QUIRK_ALWAYS_VALID |
> @@ -803,12 +803,12 @@ static int mt_compute_timestamp(struct mt_device *td, struct hid_field *field,
>         delta *= 100;
>
>         if (jdelta > MAX_TIMESTAMP_INTERVAL)
>                 /* No data received for a while, resync the timestamp. */
>                 return 0;
> -       else
> -               return td->timestamp + delta;
> +
> +       return td->timestamp + delta;
>  }
>
>  static int mt_touch_event(struct hid_device *hid, struct hid_field *field,
>                                 struct hid_usage *usage, __s32 value)
>  {
> @@ -1110,11 +1110,12 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
>          * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
>          * collection, but within the report ID.
>          */
>         if (field->physical == HID_DG_STYLUS)
>                 return 0;
> -       else if ((field->physical == 0) &&
> +
> +       if ((field->physical == 0) &&
>                  (field->report->id != td->mt_report_id) &&
>                  (td->mt_report_id != -1))
>                 return 0;
>
>         if (field->application == HID_DG_TOUCHSCREEN ||
> --
> 2.18.0
>

^ permalink raw reply

* Re: [PATCH 2/4] HID: multitouch: don't check HID_GROUP_MULTITOUCH_WIN_8 for serial protocol
From: Benjamin Tissoires @ 2018-07-03  8:16 UTC (permalink / raw)
  To: Joey Pabalinas; +Cc: open list:HID CORE LAYER, lkml, Jiri Kosina, Daniel Martin
In-Reply-To: <0aaacf083be5b68a830f9e174f9abee3b00c5a51.1530402641.git.joeypabalinas@gmail.com>

On Sun, Jul 1, 2018 at 2:19 AM, Joey Pabalinas <joeypabalinas@gmail.com> wrote:
> The HID_GROUP_MULTITOUCH_WIN_8 group never needs to check for the serial
> protocol, so avoid setting `td->serial_maybe = true;` in order to avoid
> an unnecessary mt_post_parse_default_settings() call
>
> Signed-off-by: Joey Pabalinas <joeypabalinas@gmail.com>
>
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index a793076139d7d0db9b..c0654db0b736543ca0 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -1460,11 +1460,13 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
>         if (!td->fields) {
>                 dev_err(&hdev->dev, "cannot allocate multitouch fields data\n");
>                 return -ENOMEM;
>         }
>
> -       if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID)
> +       if (id->vendor == HID_ANY_ID
> +                       && id->product == HID_ANY_ID
> +                       && id->group != HID_GROUP_MULTITOUCH_WIN_8)

There is a tiny difference between the HID group (this device looks
like it is used as a Win 8 device) and the device class (this is
effectively a Win8 device)

It makes sense to remove this check for Win8 devices, but I don't
think it should be done for all devices.

All in all, it won't change much.

Cheers,
Benjamin

>                 td->serial_maybe = true;
>
>         /* This allows the driver to correctly support devices
>          * that emit events over several HID messages.
>          */
> --
> 2.18.0
>

^ permalink raw reply

* Re: [PATCH 3/4] HID: multitouch: drop reports containing invalid values
From: Benjamin Tissoires @ 2018-07-03  8:13 UTC (permalink / raw)
  To: Joey Pabalinas; +Cc: open list:HID CORE LAYER, lkml, Jiri Kosina, Daniel Martin
In-Reply-To: <29ad484c1b357fd7fd670a6f252d097677b808f8.1530402641.git.joeypabalinas@gmail.com>

Hi Joey,

On Sun, Jul 1, 2018 at 2:19 AM, Joey Pabalinas <joeypabalinas@gmail.com> wrote:
> Avoid processing reports containing invalid values to reduce
> multitouch input stutter.
>
> Signed-off-by: Joey Pabalinas <joeypabalinas@gmail.com>
>
>  1 file changed, 9 insertions(+)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index c0654db0b736543ca0..08b50e5908cecdda66 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -694,10 +694,19 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
>  {
>         if ((td->mtclass.quirks & MT_QUIRK_CONTACT_CNT_ACCURATE) &&
>             td->num_received >= td->num_expected)
>                 return;
>
> +       /* drop invalid values after counting them */
> +       if (td->curdata.x == 0xffff &&
> +                       td->curdata.y == 0xffff &&
> +                       td->curdata.w == 0xffff &&
> +                       td->curdata.h == 0xffff) {

You can't really use plain values like that. There is a tiny chance
these values are valid on an other device.
IIRC, MS spec says that we should ignore out of band values if they
are tagged as such. Such input are tagged with NULL values
(http://www.usb.org/developers/hidpage/HID1_11.pdf page 31) and MS
spec mentioned this.

All in all, if you have this bit set, you need to compare the value
with the logical_max/min for each field.

I never encountered a device that required this, so you are probably
the lucky one :)

Cheers,
Benjamin

> +               td->num_received++;
> +               return;
> +       }
> +
>         if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
>                 int active;
>                 int slotnum = mt_compute_slot(td, input);
>                 struct mt_slot *s = &td->curdata;
>                 struct input_mt *mt = input->mt;
> --
> 2.18.0
>

^ permalink raw reply

* Re: [PATCH v7 1/4] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Enric Balletbo Serra @ 2018-07-03  8:09 UTC (permalink / raw)
  To: Lee Jones
  Cc: matti.vaittinen, Michael Turquette, sboyd, Rob Herring,
	Mark Rutland, Liam Girdwood, Mark Brown, Matti Vaittinen,
	Arnd Bergmann, Dmitry Torokhov, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <20180703065648.GB20176@dell>

Hi,
Missatge de Lee Jones <lee.jones@linaro.org> del dia dt., 3 de jul.
2018 a les 8:56:
>
> On Tue, 26 Jun 2018, Enric Balletbo Serra wrote:
>
> > Hi Matti,
> >
> > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> > dia dt., 26 de juny 2018 a les 14:03:
> > >
> > > Hello Again Eric,
> > >
> > > On Tue, Jun 26, 2018 at 01:40:40PM +0200, Enric Balletbo Serra wrote:
> > > > Hi Matti,
> > > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> > > > dia dt., 26 de juny 2018 a les 13:25:
> > > > > On Tue, Jun 26, 2018 at 11:06:33AM +0200, Enric Balletbo Serra wrote:
> > > > > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> > > > > > dia dt., 19 de juny 2018 a les 12:57:
> > > > >
> > > > > > > +static const struct of_device_id bd71837_of_match[] = {
> > > > > > > +       { .compatible = "rohm,bd71837", .data = (void *)0},
> > > > > > > +       { },
> > > > > >
> > > > > > nit: { /* sentinel */ }
> > > > >
> > > > > I am sorry but I didn't quite get the point here. Could you please
> > > > > explain what did you expect to be added here?
> > > > >
> > > >
> > > > It's a nit but It is a good practice to specify that the last entry is
> > > > a sentinel. Just this.
> > > >
> > > > +static const struct of_device_id bd71837_of_match[] = {
> > > > +       { .compatible = "rohm,bd71837", .data = (void *)0},
> > > > +       { /* sentinel */ }
> > > > +};
> > >
> > > Oh, I see. Finally something I can disagree =) I quickly opened few
> > > random drivers which declare match table. None of them practiced this
> > > good practice. So I guess it is not such a standard after all. And I
> > > guess the meaning of last entry in match table should be quite obvious.
> > > Adding the comment /* sentinel */ sounds like stating the obvious at
> > > best - at worst it gets one just to wonder what the "sentinel" means =)
> > >
> >
> > git grep "/\* sentinel \*/"
> >
> > Anyway, I marked this change as a nit, so you don't need to change. I
> > just commented because at some point I received a "complain" when I
> > didn't add it. But this is up to the maintainer and I am not sure if
> > the "complain" was received in this subsystem :)
>
> Certainly not from me.  I don't agree with the practice.
>
Ok, Removed from my notes.

> I'd like to know who is enforcing this!

I tried to find from where my note comes from but I did not find it.
Anyway, it's clear now that you don't like it, so I'll remove from the
pending patches I have and see if someone complains about it again.

Thanks,
 Enric

>
> --
> Lee Jones [李琼斯]
> Linaro Services Technical Lead
> Linaro.org │ Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH 1/4] HID: multitouch: add MT_QUIRK_NOT_SEEN_MEANS_UP to MT_CLS_WIN_8 quirks
From: Benjamin Tissoires @ 2018-07-03  7:53 UTC (permalink / raw)
  To: Joey Pabalinas; +Cc: open list:HID CORE LAYER, lkml, Jiri Kosina, Daniel Martin
In-Reply-To: <958e450a066289c94ba03429166c972c54be6fb3.1530402641.git.joeypabalinas@gmail.com>

On Sun, Jul 1, 2018 at 2:19 AM, Joey Pabalinas <joeypabalinas@gmail.com> wrote:
> The firmware found in the touch screen of the Surface Pro 3 is slightly
> buggy and occasionally doesn't send lift off reports for contacts; add
> MT_QUIRK_NOT_SEEN_MEANS_UP to .quirks to compensate for the missed
> reports.
>
> Signed-off-by: Joey Pabalinas <joeypabalinas@gmail.com>
>
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
> index 45968f7970f87775fa..a793076139d7d0db9b 100644
> --- a/drivers/hid/hid-multitouch.c
> +++ b/drivers/hid/hid-multitouch.c
> @@ -242,11 +242,12 @@ static struct mt_class mt_classes[] = {
>                 .quirks = MT_QUIRK_ALWAYS_VALID |
>                         MT_QUIRK_IGNORE_DUPLICATES |
>                         MT_QUIRK_HOVERING |
>                         MT_QUIRK_CONTACT_CNT_ACCURATE |
>                         MT_QUIRK_STICKY_FINGERS |
> -                       MT_QUIRK_WIN8_PTP_BUTTONS },
> +                       MT_QUIRK_WIN8_PTP_BUTTONS |
> +                       MT_QUIRK_NOT_SEEN_MEANS_UP },

NACK on this.
If the Surface has a buggy firmware, we should handle it as a special
case, not as a common failure.
Also, I am not sure this quirk is compatible with Win 8 specification.
Last, we now have a timeout for unreleased touches, so I really don't
think you need that in recent kernels.

Cheers,
Benjamin

>         { .name = MT_CLS_EXPORT_ALL_INPUTS,
>                 .quirks = MT_QUIRK_ALWAYS_VALID |
>                         MT_QUIRK_CONTACT_CNT_ACCURATE,
>                 .export_all_inputs = true },
>         { .name = MT_CLS_WIN_8_DUAL,
> --
> 2.18.0
>

^ permalink raw reply

* Re: [PATCH] HID: debug: check length before copy_to_user()
From: Benjamin Tissoires @ 2018-07-03  7:50 UTC (permalink / raw)
  To: Daniel Rosenberg
  Cc: Jiri Kosina, open list:HID CORE LAYER, lkml, kernel-team, 3.8+
In-Reply-To: <20180702235937.111619-1-drosen@google.com>

On Tue, Jul 3, 2018 at 1:59 AM, Daniel Rosenberg <drosen@google.com> wrote:
> If our length is greater than the size of the buffer, we
> overflow the buffer
>
> Signed-off-by: Daniel Rosenberg <drosen@google.com>
> Cc: stable@vger.kernel.org
> ---

Looks good:
Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

Cheers,
Benjamin

>  drivers/hid/hid-debug.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
> index 8469b6964ff64..b48100236df89 100644
> --- a/drivers/hid/hid-debug.c
> +++ b/drivers/hid/hid-debug.c
> @@ -1154,6 +1154,8 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
>                         goto out;
>                 if (list->tail > list->head) {
>                         len = list->tail - list->head;
> +                       if (len > count)
> +                               len = count;
>
>                         if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
>                                 ret = -EFAULT;
> @@ -1163,6 +1165,8 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
>                         list->head += len;
>                 } else {
>                         len = HID_DEBUG_BUFSIZE - list->head;
> +                       if (len > count)
> +                               len = count;
>
>                         if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
>                                 ret = -EFAULT;
> @@ -1170,7 +1174,9 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
>                         }
>                         list->head = 0;
>                         ret += len;
> -                       goto copy_rest;
> +                       count -= len;
> +                       if (count > 0)
> +                               goto copy_rest;
>                 }
>
>         }
> --
> 2.18.0.399.gad0ab374a1-goog
>

^ permalink raw reply

* Re: [PATCH 1/5] m68k/io: Add missing ioremap define guards, fix typo
From: Geert Uytterhoeven @ 2018-07-03  7:41 UTC (permalink / raw)
  To: Greg Ungerer
  Cc: David S. Miller, Dmitry Torokhov, Helge Deller, linux-m68k,
	netdev, linux-input, Linux Kernel Mailing List
In-Reply-To: <1349f685-e4a2-5e04-8227-dd55e11153f6@linux-m68k.org>

Hi Greg,

On Tue, Jul 3, 2018 at 4:13 AM Greg Ungerer <gerg@linux-m68k.org> wrote:
> On 02/07/18 23:35, Geert Uytterhoeven wrote:
> >    - Add missing define guard for ioremap_wt(),
> >    - Fix typo s/ioremap_fillcache/ioremap_fullcache/,
> >    - Add define guard for iounmap() for consistency with other
> >      architectures.
> >
> > Fixes: 9746882f547d2f00 ("m68k: group io mapping definitions and functions")
> > Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
>
> If I build for the m5475evb defconfig then I get warnings like this:
>
>    CC      init/main.o
> In file included from ./include/asm-generic/io.h:19:0,
>                   from ./arch/m68k/include/asm/io_no.h:147,
>                   from ./arch/m68k/include/asm/io.h:3,
>                   from ./include/linux/bio.h:28,
>                   from ./include/linux/blkdev.h:21,
>                   from init/main.c:80:
> ./include/asm-generic/iomap.h:79:0: warning: "ioremap_wt" redefined
>   #define ioremap_wt ioremap_nocache
>   ^
> In file included from ./arch/m68k/include/asm/io_no.h:145:0,
>                   from ./arch/m68k/include/asm/io.h:3,
>                   from ./include/linux/bio.h:28,
>                   from ./include/linux/blkdev.h:21,
>                   from init/main.c:80:
> ./arch/m68k/include/asm/kmap.h:37:0: note: this is the location of the previous definition
>   #define ioremap_wt ioremap_wt
>   ^

Thanks, I did some m68knommu compile tests, but didn't see this warning, which
happens for Coldfire+MMU only.

The issue is that there are two ways to declare an architecture has
ioremap_wt():
  1. By defining ioremap_wt,
  2. By defining ARCH_HAS_IOREMAP_WT.

1 is done in arch/m68k/include/asm/kmap.h.
2 is done in arch/m68k/include/asm/io_mm.h. Moving that to kmap.h fixes
the warning. Will send an update shortly.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v3 24/27] devicetree: fix a series of wrong file references
From: Lee Jones @ 2018-07-03  7:34 UTC (permalink / raw)
  To: Mauro Carvalho Chehab
  Cc: Linux Doc Mailing List, Mauro Carvalho Chehab, linux-kernel,
	Jonathan Corbet, Dmitry Torokhov, Rob Herring, Mark Rutland,
	Maxime Ripard, Chen-Yu Tsai, Zhou Wang, Bjorn Helgaas,
	Xiaowei Song, Binghui Wang, Liam Girdwood, Mark Brown,
	Maxime Coquelin, Alexandre Torgue, linux-input, devicetree,
	linux-arm-kernel
In-Reply-To: <bce1b59268ac2d659fd7cb37f89285ef2acc8316.1528990947.git.mchehab+samsung@kernel.org>

On Thu, 14 Jun 2018, Mauro Carvalho Chehab wrote:

> As files got renamed, their references broke.
> 
> Manually fix a series of broken refs at the DT bindings.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
> ---
>  .../devicetree/bindings/input/rmi4/rmi_2d_sensor.txt |  2 +-
>  Documentation/devicetree/bindings/mfd/sun6i-prcm.txt |  2 +-

Acked-by: Lee Jones <lee.jones@linaro.org>

>  .../devicetree/bindings/pci/hisilicon-pcie.txt       |  2 +-
>  Documentation/devicetree/bindings/pci/kirin-pcie.txt |  2 +-
>  .../devicetree/bindings/pci/pci-keystone.txt         |  4 ++--
>  .../devicetree/bindings/sound/st,stm32-i2s.txt       |  2 +-
>  .../devicetree/bindings/sound/st,stm32-sai.txt       |  2 +-
>  MAINTAINERS                                          | 12 ++++++------
>  8 files changed, 14 insertions(+), 14 deletions(-)

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v7 0/4] mfd/regulator/clk/input: bd71837: ROHM BD71837 PMIC driver
From: Lee Jones @ 2018-07-03  7:02 UTC (permalink / raw)
  To: Matti Vaittinen
  Cc: mturquette, sboyd, robh+dt, mark.rutland, lgirdwood, broonie,
	mazziesaccount, arnd, dmitry.torokhov, sre, chenjh,
	andrew.smirnov, linus.walleij, kstewart, heiko, gregkh, linux-clk,
	devicetree, linux-kernel, linux-input, mikko.mutanen,
	heikki.haikola
In-Reply-To: <20180621103400.GB6076@localhost.localdomain>

On Thu, 21 Jun 2018, Matti Vaittinen wrote:

> On Tue, Jun 19, 2018 at 01:55:31PM +0300, Matti Vaittinen wrote:
> > Patch series adding support for ROHM BD71837 PMIC.
> > 
> What is the preferred way when I send updated patches:
> 
> 1. always resend _all_ unapplied patches even if there is no changes to
>    some of them. (patch-vN mail thread contains _all_ unapplied patches)
> 2. only resend changed patches (patch-vN mail thread contains only
>    patches that were changed from patch-vN-1)
> 
> I have currently used approach 1 - so that no patches would be
> accidentally forgotten - but downside is that people need to check if
> they have already reviewed some of the patches. I'd rather not caused
> any extra work. What is the most convenient way for you guys?

Option 1 is preferred.

Just ensure you apply any tags you have collected so reviewers can see
which patches are pending a review.  It's also a good idea to keep a
succinct change log between the "--" marker and the diff stat where
you can state "v4: No change" or the like.

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v7 1/4] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Lee Jones @ 2018-07-03  6:56 UTC (permalink / raw)
  To: Enric Balletbo Serra
  Cc: matti.vaittinen, Michael Turquette, sboyd, Rob Herring,
	Mark Rutland, Liam Girdwood, Mark Brown, Matti Vaittinen,
	Arnd Bergmann, Dmitry Torokhov, Sebastian Reichel, chenjh,
	Andrey Smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org
In-Reply-To: <CAFqH_52v3-L1xLL12hzyGCbuooX5T52Lm7BXHM3sBX1ERWmhiQ@mail.gmail.com>

On Tue, 26 Jun 2018, Enric Balletbo Serra wrote:

> Hi Matti,
> 
> Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> dia dt., 26 de juny 2018 a les 14:03:
> >
> > Hello Again Eric,
> >
> > On Tue, Jun 26, 2018 at 01:40:40PM +0200, Enric Balletbo Serra wrote:
> > > Hi Matti,
> > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> > > dia dt., 26 de juny 2018 a les 13:25:
> > > > On Tue, Jun 26, 2018 at 11:06:33AM +0200, Enric Balletbo Serra wrote:
> > > > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> > > > > dia dt., 19 de juny 2018 a les 12:57:
> > > >
> > > > > > +static const struct of_device_id bd71837_of_match[] = {
> > > > > > +       { .compatible = "rohm,bd71837", .data = (void *)0},
> > > > > > +       { },
> > > > >
> > > > > nit: { /* sentinel */ }
> > > >
> > > > I am sorry but I didn't quite get the point here. Could you please
> > > > explain what did you expect to be added here?
> > > >
> > >
> > > It's a nit but It is a good practice to specify that the last entry is
> > > a sentinel. Just this.
> > >
> > > +static const struct of_device_id bd71837_of_match[] = {
> > > +       { .compatible = "rohm,bd71837", .data = (void *)0},
> > > +       { /* sentinel */ }
> > > +};
> >
> > Oh, I see. Finally something I can disagree =) I quickly opened few
> > random drivers which declare match table. None of them practiced this
> > good practice. So I guess it is not such a standard after all. And I
> > guess the meaning of last entry in match table should be quite obvious.
> > Adding the comment /* sentinel */ sounds like stating the obvious at
> > best - at worst it gets one just to wonder what the "sentinel" means =)
> >
> 
> git grep "/\* sentinel \*/"
> 
> Anyway, I marked this change as a nit, so you don't need to change. I
> just commented because at some point I received a "complain" when I
> didn't add it. But this is up to the maintainer and I am not sure if
> the "complain" was received in this subsystem :)

Certainly not from me.  I don't agree with the practice.

I'd like to know who is enforcing this!

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH v7 1/4] mfd: bd71837: mfd driver for ROHM BD71837 PMIC
From: Lee Jones @ 2018-07-03  6:53 UTC (permalink / raw)
  To: Enric Balletbo Serra
  Cc: matti.vaittinen, Michael Turquette, sboyd, Rob Herring,
	Mark Rutland, Liam Girdwood, Mark Brown, mazziesaccount,
	Arnd Bergmann, Dmitry Torokhov, Sebastian Reichel, chenjh,
	andrew.smirnov, Linus Walleij, Kate Stewart, Heiko Stübner,
	Greg Kroah-Hartman, linux-clk, devicetree@vger.kernel.org,
	linux-kernel, linux-input
In-Reply-To: <CAFqH_52NERfORwSkBh0stW+mvzRpw0to9CiWPwLB9mFo_TsW_w@mail.gmail.com>

On Tue, 26 Jun 2018, Enric Balletbo Serra wrote:

> Hi Matti,
> Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> dia dt., 26 de juny 2018 a les 13:25:
> >
> > Hello Eric,
> >
> > Thanks for the comments! I'll be addressing these in patch series v8
> > - except the regmap wrapper one which will be taken care of by another
> > patch set.
> >
> > On Tue, Jun 26, 2018 at 11:06:33AM +0200, Enric Balletbo Serra wrote:
> > > Hi Matti,
> > >
> > > Thanks for the patch, a few comments below, some are feedback I
> > > received when I sent some patches to this subsystem.
> > >
> > > Missatge de Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> del
> > > dia dt., 19 de juny 2018 a les 12:57:
> > > >
> > > > ROHM BD71837 PMIC MFD driver providing interrupts and support
> > > > for two subsystems:
> > > > - clk
> > > > - Regulators
> > > >
> > > > Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>
> > > > ---
> > > >  drivers/mfd/Kconfig         |  13 ++
> > > >  drivers/mfd/Makefile        |   1 +
> > > >  drivers/mfd/bd71837.c       | 221 ++++++++++++++++++++++++++
> > > >  include/linux/mfd/bd71837.h | 367 ++++++++++++++++++++++++++++++++++++++++++++
> > > >  4 files changed, 602 insertions(+)
> > > >  create mode 100644 drivers/mfd/bd71837.c
> > > >  create mode 100644 include/linux/mfd/bd71837.h

[...]

> > > > +static const struct of_device_id bd71837_of_match[] = {
> > > > +       { .compatible = "rohm,bd71837", .data = (void *)0},
> > > > +       { },
> > >
> > > nit: { /* sentinel */ }
> >
> > I am sorry but I didn't quite get the point here. Could you please
> > explain what did you expect to be added here?
> >
> 
> It's a nit but It is a good practice to specify that the last entry is
> a sentinel. Just this.
> 
> +static const struct of_device_id bd71837_of_match[] = {
> +       { .compatible = "rohm,bd71837", .data = (void *)0},
> +       { /* sentinel */ }
> +};

I would not say this is "good practice" at all.

We all know what empty brackets mean.  No need for obvious comments.

When authors put this, I let it go because "sentinel" is a cool word -
and nothing more! ;)

-- 
Lee Jones [李琼斯]
Linaro Services Technical Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* Re: [PATCH 0/5] m68k: IO Fixes and Cleanups
From: Greg Ungerer @ 2018-07-03  2:15 UTC (permalink / raw)
  To: Geert Uytterhoeven, David S . Miller, Dmitry Torokhov,
	Helge Deller
  Cc: linux-m68k, netdev, linux-input, linux-kernel
In-Reply-To: <20180702133532.5412-1-geert@linux-m68k.org>

Hi Geert,

On 02/07/18 23:35, Geert Uytterhoeven wrote:
> 	Hi all,
> 
> This patch series contains fixes and cleanups for I/O accessors on m68k
> platforms (with MMU).
> 
> The first patch contains small fixes without any dependencies.
> Patches 2 and 3 make small adjustments to drivers that are dependencies
> for further cleanup.
> Patch 4 and 5 complete the cleanup.
> 
> Given the dependencies, I think it's easiest if the respective
> maintainers would provide their Acked-by, so all patches can go in
> through the m68k tree.
> 
> Thanks for your comments!

I like it alot. If we can just fix up the warnings caused by patch
number 1 I am more than happy to ack.

Regards
Greg


> Geert Uytterhoeven (5):
>    m68k/io: Add missing ioremap define guards, fix typo
>    net: mac8390: Use standard memcpy_{from,to}io()
>    Input: hilkbd - Add casts to HP9000/300 I/O accessors
>    m68k/io: Move mem*io define guards to <asm/kmap.h>
>    m68k/io: Switch mmu variant to <asm-generic/io.h>
> 
>   arch/m68k/include/asm/io.h          |  7 +++++
>   arch/m68k/include/asm/io_mm.h       | 40 +++--------------------------
>   arch/m68k/include/asm/io_no.h       | 12 ---------
>   arch/m68k/include/asm/kmap.h        |  7 ++++-
>   drivers/input/keyboard/hilkbd.c     |  4 +--
>   drivers/net/ethernet/8390/mac8390.c | 20 +++++++--------
>   6 files changed, 28 insertions(+), 62 deletions(-)
> 

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox