All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] KVM: x86: do not go through vcpu in __get_kvmclock_ns
From: Paolo Bonzini @ 2016-11-14 17:51 UTC (permalink / raw)
  To: linux-kernel, kvm; +Cc: rkrcmar, mtosatti

Going through the first VCPU is wrong if you follow a KVM_SET_CLOCK with
a KVM_GET_CLOCK immediately after, without letting the VCPU run and
call kvm_guest_time_update.

To fix this, compute the kvmclock value ourselves, using the master
clock (tsc, nsec) pair as the base and the host CPU frequency as
the scale.

Reported-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/kvm/x86.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 1ba08278a9a9..c4b07d6f7bf1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1620,6 +1620,11 @@ static bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
 
 	return do_monotonic_boot(kernel_ns, cycle_now) == VCLOCK_TSC;
 }
+#else
+static inline bool kvm_get_time_and_clockread(s64 *kernel_ns, cycle_t *cycle_now)
+{
+	return false;
+}
 #endif
 
 /*
@@ -1724,18 +1729,18 @@ static void kvm_gen_update_masterclock(struct kvm *kvm)
 
 static u64 __get_kvmclock_ns(struct kvm *kvm)
 {
-	struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, 0);
 	struct kvm_arch *ka = &kvm->arch;
-	s64 ns;
+	struct pvclock_vcpu_time_info hv_clock;
 
-	if (vcpu->arch.hv_clock.flags & PVCLOCK_TSC_STABLE_BIT) {
-		u64 tsc = kvm_read_l1_tsc(vcpu, rdtsc());
-		ns = __pvclock_read_cycles(&vcpu->arch.hv_clock, tsc);
-	} else {
-		ns = ktime_get_boot_ns() + ka->kvmclock_offset;
-	}
+	if (!ka->use_master_clock)
+		return ktime_get_boot_ns() + ka->kvmclock_offset;
 
-	return ns;
+	hv_clock.tsc_timestamp = ka->master_cycle_now;
+	hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
+	kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL,
+			   &hv_clock.tsc_shift,
+			   &hv_clock.tsc_to_system_mul);
+	return __pvclock_read_cycles(&hv_clock, rdtsc());
 }
 
 u64 get_kvmclock_ns(struct kvm *kvm)
-- 
1.8.3.1

^ permalink raw reply related

* Re: [Intel-gfx] [PATCH 0/5] Handle Link Training Failure during modeset
From: Manasi Navare @ 2016-11-14 17:51 UTC (permalink / raw)
  To: Cheng, Tony
  Cc: intel-gfx@lists.freedesktop.org, Peres, Martin,
	dri-devel@lists.freedesktop.org, Deucher, Alexander
In-Reply-To: <MWHPR12MB14062D185A126F777DF3A93E98BC0@MWHPR12MB1406.namprd12.prod.outlook.com>

Yes driver can chose to have the pre train for kernel hiding unsupported mode, that is completely still possible for the amd driver and it would never use the link_status connector property and no interaction with userspace.
Could you please give your ACKs for the patches if you are okay with this porposal?

Regards
Manasi



On Mon, Nov 14, 2016 at 02:45:55PM +0000, Cheng, Tony wrote:
> I see.  As long as amd can still just have kernel hiding unsupported mode by doing a pre-train I am okay with the proposal.  Just to caution you the link training fallback we implemented on windows in old dal architecture is very painful to get right.  Windows 7, 8.1 and 10 all behave differently.  Not all apps handles mode change failure gracefully and worse case we get stuck in infinite mode set.  This is why for future generations asic on windows we are also going to just hide unsupported mode by doing pre-train.
> 
> -----Original Message-----
> From: Daniel Vetter [mailto:daniel.vetter@ffwll.ch] On Behalf Of Daniel Vetter
> Sent: Monday, November 14, 2016 3:04 AM
> To: Manasi Navare <manasi.d.navare@intel.com>
> Cc: Cheng, Tony <Tony.Cheng@amd.com>; intel-gfx@lists.freedesktop.org; Peres, Martin <martin.peres@intel.com>; dri-devel@lists.freedesktop.org; Deucher, Alexander <Alexander.Deucher@amd.com>; Wentland, Harry <Harry.Wentland@amd.com>
> Subject: Re: [Intel-gfx] [PATCH 0/5] Handle Link Training Failure during modeset
> 
> On Sun, Nov 13, 2016 at 11:43:01PM -0800, Manasi Navare wrote:
> > On Fri, Nov 11, 2016 at 07:42:16PM +0000, Cheng, Tony wrote:
> > > In case of link training failure and requiring user space to set a lower mode, would full mode set address it?  How do we make user mode select lower resolution?
> > > 
> > > For example 4k@60Hz monitor, and link training at 4 lane HBR2 fails and fallback to 4 lanes HBR, 4k@60 is no longer doable.  I would think preventing user mode from seeing 4K@60Hz from the start is a easier and more robust solution and requiring user mode to have logic to decide how to fallback.
> > >
> > 
> > Hi Tony,
> > 
> > So in case of link training failure, we first call mode_valid that 
> > will use the lower link rate/lane count values based on the link 
> > training fallback to validate the modes and prune the modes that are 
> > higher than the available link. After this is done, then we send the uevent to userspace indicating that link status is BAD and it will redo a probe and trigger a modeset for next possible lower resolution.
> 
> Just in case it's not clear: This entire discussion here is only about the userspace-visible abi changes. And I think for the worst-case we need something like this (and Harry at least said on irc that on other os you do something similar already). It of course does not preclude at all that you do additional link-training/probe on initial hotplug. That part is entirely up to drivers (and we might get there on some platforms, but on others it's a real pain to get a link up&running unfortunately for training, since we need to steal a crtc and do a full modeset).
> -Daniel
> 
> > 
> > Manasi
> > 
> >  
> > > -----Original Message-----
> > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > Sent: Friday, November 11, 2016 11:44 AM
> > > To: Cheng, Tony <Tony.Cheng@amd.com>
> > > Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; 'Jani Nikula' 
> > > <jani.nikula@linux.intel.com>; Manasi Navare 
> > > <manasi.d.navare@intel.com>; dri-devel@lists.freedesktop.org; 
> > > intel-gfx@lists.freedesktop.org; Wentland, Harry 
> > > <Harry.Wentland@amd.com>; Peres, Martin <martin.peres@intel.com>
> > > Subject: Re: [Intel-gfx] [PATCH 0/5] Handle Link Training Failure 
> > > during modeset
> > > 
> > > On Fri, Nov 11, 2016 at 04:21:58PM +0000, Cheng, Tony wrote:
> > > > For HDMI, you can yank the cable, plug back in, HDMI will light up without user mode or kernel mode doing anything.
> > > > 
> > > > For DP this is not possible, someone will have to retrain the link when plugging back in or DP will not light up.  We see that on Ubuntu if someone unplug display and plug it back into same connector, we do not get KMS so in this case.  It appears there is some optimizations somewhere in user mode stack which I am not familiar with yet.  dal added workaround to retrain the link to light it back up (after the test training at end of detection).
> > > 
> > > The link should get retrained as the driver should check the link state on HPD and retrain if it's not good. At least that's what we do in i915. Of course if it's not the same display that got plugged back, the retraining might fail. The new property can help with that case as userspace would then attempt a full modeset after the failed link training.
> > > 
> > > > 
> > > > >From user mode perspective I think it make sense to keep CRTC running, so vblank is still going so UMD isn't impacted.   As regard to connector and encoder does it matter if kernel mode change state without user mode knowing?  It seems to me those are more informational to UMD as UMD doesn't act on them.
> > > > 
> > > > windows does not know link state and all link management is hidden behind kernel driver.   
> > > 
> > > If the user visible state doesn't change in any way, then the kernel could try to manage it all internally.
> > > 
> > > > 
> > > > -----Original Message-----
> > > > From: Ville Syrjälä [mailto:ville.syrjala@linux.intel.com]
> > > > Sent: Friday, November 11, 2016 9:05 AM
> > > > To: Cheng, Tony <Tony.Cheng@amd.com>
> > > > Cc: Deucher, Alexander <Alexander.Deucher@amd.com>; 'Jani Nikula' 
> > > > <jani.nikula@linux.intel.com>; Manasi Navare 
> > > > <manasi.d.navare@intel.com>; dri-devel@lists.freedesktop.org; 
> > > > intel-gfx@lists.freedesktop.org; Wentland, Harry 
> > > > <Harry.Wentland@amd.com>; Peres, Martin <martin.peres@intel.com>
> > > > Subject: Re: [Intel-gfx] [PATCH 0/5] Handle Link Training Failure 
> > > > during modeset
> > > > 
> > > > On Thu, Nov 10, 2016 at 06:51:40PM +0000, Cheng, Tony wrote:
> > > > > Amdgpu dal implementation will do a test link training at end of detection to verify we can achieve the capability reported in DPCD.  We then report mode base on result of test training.
> > > > > 
> > > > > AMD hardware (at least the generations supported by amdgpu) is able to link train without timing being setup (DP encoder and CRTC is decoupled).  Do we have limitation from other vendors where you need timing to be there before you can link train?
> > > > 
> > > > I can't recall the specifics for all of our supported platforms, but at least I have the recollection that it would be the case yes.
> > > > 
> > > > The other problem wiyh this apporach is that even if you don't need the crtc, you still need the link itself. What happens if the link is still active since userspace just didn't bother to shut it down when the cable was yanked? Can you keep the crtc going but stop it from feeding the link in a way that userspace won't be able to notice? The kms design has always been pretty much that policy is in userspace, and thus the kernel shouldn't shut down crtcs unless explicitly asked to do so.
> > > > 
> > > > > 
> > > > > We can also past DP1.2 link layer compliance with this approach.
> > > > > 
> > > > > -----Original Message-----
> > > > > From: Deucher, Alexander
> > > > > Sent: Thursday, November 10, 2016 1:43 PM
> > > > > To: 'Jani Nikula' <jani.nikula@linux.intel.com>; Manasi Navare 
> > > > > <manasi.d.navare@intel.com>; dri-devel@lists.freedesktop.org; 
> > > > > intel-gfx@lists.freedesktop.org; Wentland, Harry 
> > > > > <Harry.Wentland@amd.com>; Cheng, Tony <Tony.Cheng@amd.com>
> > > > > Cc: Dave Airlie <airlied@gmail.com>; Peres, Martin 
> > > > > <martin.peres@intel.com>
> > > > > Subject: RE: [Intel-gfx] [PATCH 0/5] Handle Link Training 
> > > > > Failure during modeset
> > > > > 
> > > > > Adding Harry and Tony from our display team to review.
> > > > > 
> > > > > > -----Original Message-----
> > > > > > From: Jani Nikula [mailto:jani.nikula@linux.intel.com]
> > > > > > Sent: Thursday, November 10, 2016 1:20 PM
> > > > > > To: Manasi Navare; dri-devel@lists.freedesktop.org; intel- 
> > > > > > gfx@lists.freedesktop.org
> > > > > > Cc: Dave Airlie; Peres, Martin; Deucher, Alexander
> > > > > > Subject: Re: [Intel-gfx] [PATCH 0/5] Handle Link Training 
> > > > > > Failure during modeset
> > > > > > 
> > > > > > On Thu, 10 Nov 2016, Manasi Navare <manasi.d.navare@intel.com> wrote:
> > > > > > > Link training failure is handled by lowering the link rate 
> > > > > > > first until it reaches the minimum and keeping the lane 
> > > > > > > count maximum and then lowering the lane count until it 
> > > > > > > reaches minimim. These fallback values are saved and hotplug 
> > > > > > > uevent is sent to the userspace after setting the connector link status property to BAD.
> > > > > > > Userspace should triiger another modeset on a uevent and if 
> > > > > > > link status property is BAD. This will retrain the link at fallback values.
> > > > > > > This is repeated until the link is successfully trained.
> > > > > > >
> > > > > > > This has been validated to pass DP compliance.
> > > > > > 
> > > > > > This cover letter and the commit messages do a good job of 
> > > > > > explaining what the patches do. However, you're lacking the 
> > > > > > crucial information of
> > > > > > *why* we need userspace cooperation to handle link training 
> > > > > > failures on DP mode setting, and *why* a new connector 
> > > > > > property is a good solution for this.
> > > > > > 
> > > > > > Here goes, including some alternative approaches we've 
> > > > > > considered (and even tried):
> > > > > > 
> > > > > > At the time userspace does setcrtc, we've already promised the 
> > > > > > mode would work. The promise is based on the theoretical 
> > > > > > capabilities of the link, but it's possible we can't reach 
> > > > > > this in practice. The DP spec describes how the link should be 
> > > > > > reduced, but we can't reduce the link below the requirements of the mode. Black screen follows.
> > > > > > 
> > > > > > One idea would be to have setcrtc return a failure. However, 
> > > > > > it is my understanding that it already should not fail as the 
> > > > > > atomic checks have passed [citation needed]. It would also 
> > > > > > conflict with the idea of making setcrtc asynchronous in the 
> > > > > > future, returning before the actual mode setting and link training.
> > > > > > 
> > > > > > Another idea is to train the link "upfront" at hotplug time, 
> > > > > > before pruning the mode list, so that we can do the pruning 
> > > > > > based on practical not theoretical capabilities. However, the 
> > > > > > changes for link training are pretty drastic, all for the sake 
> > > > > > of error handling and DP compliance, when the most common 
> > > > > > happy day scenario is the current approach of link training at 
> > > > > > mode setting time, using the optimal parameters for the mode. 
> > > > > > It is also not certain all hardware could do this without the 
> > > > > > pipe on; not even all our hardware can do this. Some of this can be solved, but not trivially.
> > > > > > 
> > > > > > Both of the above ideas also fail to address link degradation
> > > > > > *during* operation.
> > > > > > 
> > > > > > So the idea presented in these patches is to do this in a way 
> > > > > > that
> > > > > > a) changes the current happy day scenario as little as 
> > > > > > possible, to avoid regressions, b) can be implemented the same 
> > > > > > way by all drm drivers, c) is still opt-in for the drivers and 
> > > > > > userspace, and opting out doesn't regress the user experience, 
> > > > > > d) doesn't prevent drivers from implementing better or 
> > > > > > alternate approaches, possibly without userspace involvement. And, of course, handles all the issues presented.
> > > > > > 
> > > > > > The solution is to add a "link status" connector property. In 
> > > > > > the usual happy day scenario, this is always "good". If 
> > > > > > something fails during or after a mode set, the kernel driver 
> > > > > > can set the link status to "bad", prune the mode list based on 
> > > > > > new information as necessary, and send a hotplug uevent for 
> > > > > > userspace to have it re-check the valid modes through 
> > > > > > getconnector, and try again. If the theoretical capabilities of the link can't be reached, the mode list is trimmed based on that.
> > > > > > 
> > > > > > If the userspace is not aware of the property, the user 
> > > > > > experience is the same as it currently is. If the userspace is 
> > > > > > aware of the property, it has a chance to improve user 
> > > > > > experience. If a drm driver does not modify the property (it 
> > > > > > stays "good"), the user experience is the same as it currently 
> > > > > > is. A drm driver can also choose to try to handle more of the 
> > > > > > failures in kernel, hardware not limiting, or it can choose to involve userspace more. Up to the drivers.
> > > > > > 
> > > > > > The reason for adding the property is to handle link training 
> > > > > > failures, but it is not limited to DP or link training. For 
> > > > > > example, if we implement asynchronous setcrtc, we can use this 
> > > > > > to report any failures in that.
> > > > > > 
> > > > > > Finally, while DP CTS compliance is advertized (which is 
> > > > > > great, and could be made to work similarly for all drm 
> > > > > > drivers), this can be used for the more important goal of 
> > > > > > improving user experience on link training failures, by avoiding black screens.
> > > > > > 
> > > > > > 
> > > > > > BR,
> > > > > > Jani.
> > > > > > 
> > > > > > 
> > > > > > >
> > > > > > > Manasi Navare (5):
> > > > > > >   drm: Add a new connector property for link status
> > > > > > >   drm/i915: Set link status property for DP connector
> > > > > > >   drm/i915: Update CRTC state if connector link status 
> > > > > > > property changed
> > > > > >     ^^^^^^^^
> > > > > > 
> > > > > > This is really drm, not i915.
> > > > > > 
> > > > > > 
> > > > > > >   drm/i915: Find fallback link rate/lane count
> > > > > > >   drm/i915: Implement Link Rate fallback on Link training 
> > > > > > > failure
> > > > > > >
> > > > > > >  drivers/gpu/drm/drm_atomic_helper.c           |   7 ++
> > > > > > >  drivers/gpu/drm/drm_connector.c               |  17 ++++
> > > > > > >  drivers/gpu/drm/i915/intel_ddi.c              |  21 +++-
> > > > > > >  drivers/gpu/drm/i915/intel_dp.c               | 138
> > > > > > +++++++++++++++++++++++++-
> > > > > > >  drivers/gpu/drm/i915/intel_dp_link_training.c |  12 ++-
> > > > > > >  drivers/gpu/drm/i915/intel_drv.h              |  12 ++-
> > > > > > >  include/drm/drm_connector.h                   |   7 +-
> > > > > > >  include/drm/drm_crtc.h                        |   5 +
> > > > > > >  include/uapi/drm/drm_mode.h                   |   4 +
> > > > > > >  9 files changed, 214 insertions(+), 9 deletions(-)
> > > > > > 
> > > > > > --
> > > > > > Jani Nikula, Intel Open Source Technology Center
> > > > > _______________________________________________
> > > > > Intel-gfx mailing list
> > > > > Intel-gfx@lists.freedesktop.org
> > > > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> > > > 
> > > > --
> > > > Ville Syrjälä
> > > > Intel OTC
> > > 
> > > --
> > > Ville Syrjälä
> > > Intel OTC
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [U-Boot] [PATCH v2 1/3] SECURE_BOOT: Enable chain of trust on LS1046A platform
From: york sun @ 2016-11-14 17:51 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <1477513031-29292-2-git-send-email-sumit.garg@nxp.com>

On 10/26/2016 03:47 AM, Sumit Garg wrote:
> Define bootscript and its header addresses for QSPI target. Also
> define PPA header address to enable PPA validation.
>
> Signed-off-by: Vinitha Pillai <vinitha.pillai@nxp.com>
> Signed-off-by: Sumit Garg <sumit.garg@nxp.com>
> ---
>
> Changes in v2:
> Split patches logically from 2 to 3.
>
>  arch/arm/include/asm/arch-fsl-layerscape/config.h |  2 +-
>  arch/arm/include/asm/fsl_secure_boot.h            | 37 ++++++++++++++++-------
>  2 files changed, 27 insertions(+), 12 deletions(-)
>
> diff --git a/arch/arm/include/asm/arch-fsl-layerscape/config.h b/arch/arm/include/asm/arch-fsl-layerscape/config.h
> index 4201e0f..11a62e8 100644
> --- a/arch/arm/include/asm/arch-fsl-layerscape/config.h
> +++ b/arch/arm/include/asm/arch-fsl-layerscape/config.h
> @@ -196,7 +196,7 @@
>
>  #define CONFIG_SYS_FSL_IFC_BE
>  #define CONFIG_SYS_FSL_SFP_VER_3_2
> -#define CONFIG_SYS_FSL_SNVS_LE
> +#define CONFIG_SYS_FSL_SEC_MON_BE
>  #define CONFIG_SYS_FSL_SFP_BE
>  #define CONFIG_SYS_FSL_SRK_LE
>  #define CONFIG_KEY_REVOCATION
> diff --git a/arch/arm/include/asm/fsl_secure_boot.h b/arch/arm/include/asm/fsl_secure_boot.h
> index 4525287..933e09c 100644
> --- a/arch/arm/include/asm/fsl_secure_boot.h
> +++ b/arch/arm/include/asm/fsl_secure_boot.h
> @@ -45,7 +45,8 @@
>  #define CONFIG_CMD_HASH
>  #define CONFIG_KEY_REVOCATION
>  #ifndef CONFIG_SYS_RAMBOOT
> -/* The key used for verification of next level images
> +/*
> + * The key used for verification of next level images
>   * is picked up from an Extension Table which has
>   * been verified by the ISBC (Internal Secure boot Code)
>   * in boot ROM of the SoC.
> @@ -59,9 +60,10 @@
>
>  #endif
>
> -#if defined(CONFIG_LS1043A) || defined(CONFIG_LS2080A)
> -/* For LS1043 (ARMv8), ESBC image Address in Header is 64 bit
> - * Similiarly for LS2080
> +#if defined(CONFIG_FSL_LAYERSCAPE)
> +/*
> + * For fsl layerscape based platforms, ESBC image Address in Header
> + * is 64 bit.
>   */
>  #define CONFIG_ESBC_ADDR_64BIT
>  #endif
> @@ -78,13 +80,16 @@
>  	"setenv hwconfig \'fsl_ddr:ctlr_intlv=null,bank_intlv=null\';"
>  #endif
>
> -/* Copying Bootscript and Header to DDR from NOR for LS2 and for rest, from
> - * Non-XIP Memory (Nand/SD)*/
> +/*
> + * Copying Bootscript and Header to DDR from NOR for LS2 and for rest, from
> + * Non-XIP Memory (Nand/SD)
> + */
>  #if defined(CONFIG_SYS_RAMBOOT) || defined(CONFIG_LS2080A) || \
>  	defined(CONFIG_SD_BOOT)
>  #define CONFIG_BOOTSCRIPT_COPY_RAM
>  #endif
> -/* The address needs to be modified according to NOR, NAND, SD and
> +/*
> + * The address needs to be modified according to NOR, NAND, SD and
>   * DDR memory map
>   */
>  #ifdef CONFIG_LS2080A
> @@ -96,19 +101,26 @@
>  #define CONFIG_BS_SIZE			0x00001000
>  #else
>  #ifdef CONFIG_SD_BOOT
> -/* For SD boot address and size are assigned in terms of sector
> +/*
> + * For SD boot address and size are assigned in terms of sector
>   * offset and no. of sectors respectively.
>   */
>  #define CONFIG_BS_HDR_ADDR_DEVICE	0x00000800
>  #define CONFIG_BS_ADDR_DEVICE		0x00000840
>  #define CONFIG_BS_HDR_SIZE		0x00000010
>  #define CONFIG_BS_SIZE			0x00000008
> -#else
> +/* ifdef CONFIG_SD_BOOT */

This comment confuses me. The code below is for QSPI_BOOT obviously.

> +#elif defined(CONFIG_QSPI_BOOT)
> +#define CONFIG_BS_HDR_ADDR_DEVICE	0x40780000
> +#define CONFIG_BS_ADDR_DEVICE		0x40800000
> +#define CONFIG_BS_HDR_SIZE		0x00002000
> +#define CONFIG_BS_SIZE			0x00001000
> +#else /* elif defined(CONFIG_QSPI_BOOT) */

The code below is not for QSPI_BOOT. Confusing comment.

>  #define CONFIG_BS_HDR_ADDR_DEVICE	0x600a0000
>  #define CONFIG_BS_ADDR_DEVICE		0x60060000
>  #define CONFIG_BS_HDR_SIZE		0x00002000
>  #define CONFIG_BS_SIZE			0x00001000
> -#endif /* #ifdef CONFIG_SD_BOOT */
> +#endif /* Default NOR Boot */

I guess the above is for normal NOR boot. The comment should be moved 
above the block.

>  #define CONFIG_BS_HDR_ADDR_RAM		0x81000000
>  #define CONFIG_BS_ADDR_RAM		0x81020000
>  #endif
> @@ -125,12 +137,15 @@
>  #ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP
>  #ifdef CONFIG_LS1043A
>  #define CONFIG_SYS_LS_PPA_ESBC_ADDR	0x600c0000
> +#elif defined(CONFIG_LS1046A)
> +#define CONFIG_SYS_LS_PPA_ESBC_ADDR     0x40740000
>  #endif
>  #else
>  #error "No CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
>  #endif /* ifdef CONFIG_SYS_LS_PPA_FW_IN_XIP */
>
> -/* Define the key hash here if SRK used for signing PPA image is
> +/*
> + * Define the key hash here if SRK used for signing PPA image is
>   * different from SRK hash put in SFP used for U-Boot.
>   * Example
>   * #define CONFIG_PPA_KEY_HASH \
>

It would be better to separate the cosmetic change from the code change.

York

^ permalink raw reply

* Re: [PATCH 4/6] drm/irq: Unexport drm_vblank_count
From: Philipp Zabel @ 2016-11-14 17:51 UTC (permalink / raw)
  To: Daniel Vetter; +Cc: Daniel Vetter, DRI Development
In-Reply-To: <20161114090255.31595-4-daniel.vetter@ffwll.ch>

Am Montag, den 14.11.2016, 10:02 +0100 schrieb Daniel Vetter:
> No one outside of drm_irq.c should ever need this. The correct way to
> implement get_vblank_count for hw lacking a vblank counter is
> drm_vblank_no_hw_counter. Fix this up in mtk, which is the only
> offender left over.
> 
> Cc: CK Hu <ck.hu@mediatek.com>
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>

Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

> ---
>  drivers/gpu/drm/drm_irq.c              | 37 +++++++++-------------------------
>  drivers/gpu/drm/mediatek/mtk_drm_drv.c |  2 +-
>  2 files changed, 11 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
> index 2fb5861b04b7..1681e919b866 100644
> --- a/drivers/gpu/drm/drm_irq.c
> +++ b/drivers/gpu/drm/drm_irq.c
> @@ -234,6 +234,16 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
>  	store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
>  }
>  
> +static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
> +{
> +	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +
> +	if (WARN_ON(pipe >= dev->num_crtcs))
> +		return 0;
> +
> +	return vblank->count;
> +}
> +
>  /**
>   * drm_accurate_vblank_count - retrieve the master vblank counter
>   * @crtc: which counter to retrieve
> @@ -888,31 +898,6 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
>  }
>  
>  /**
> - * drm_vblank_count - retrieve "cooked" vblank counter value
> - * @dev: DRM device
> - * @pipe: index of CRTC for which to retrieve the counter
> - *
> - * Fetches the "cooked" vblank count value that represents the number of
> - * vblank events since the system was booted, including lost events due to
> - * modesetting activity.
> - *
> - * This is the legacy version of drm_crtc_vblank_count().
> - *
> - * Returns:
> - * The software vblank counter.
> - */
> -u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
> -{
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> -
> -	if (WARN_ON(pipe >= dev->num_crtcs))
> -		return 0;
> -
> -	return vblank->count;
> -}
> -EXPORT_SYMBOL(drm_vblank_count);
> -
> -/**
>   * drm_crtc_vblank_count - retrieve "cooked" vblank counter value
>   * @crtc: which counter to retrieve
>   *
> @@ -920,8 +905,6 @@ EXPORT_SYMBOL(drm_vblank_count);
>   * vblank events since the system was booted, including lost events due to
>   * modesetting activity.
>   *
> - * This is the native KMS version of drm_vblank_count().
> - *
>   * Returns:
>   * The software vblank counter.
>   */
> diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> index d90152e85ed0..4b7fe7eaec01 100644
> --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
> @@ -256,7 +256,7 @@ static struct drm_driver mtk_drm_driver = {
>  	.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME |
>  			   DRIVER_ATOMIC,
>  
> -	.get_vblank_counter = drm_vblank_count,
> +	.get_vblank_counter = drm_vblank_no_hw_counter,
>  	.enable_vblank = mtk_drm_crtc_enable_vblank,
>  	.disable_vblank = mtk_drm_crtc_disable_vblank,
>  


_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH v2 1/2] mfd: pm8xxx: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Lee Jones
  Cc: bjorn.andersson, Rob Herring, Andy Gross, devicetree,
	linux-kernel, linux-arm-msm, linux-soc, linux-arm-kernel,
	Srinivas Kandagatla

This patch adds support to PM8821 PMIC and interrupt support.
PM8821 is companion device that supplements primary PMIC PM8921 IC.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Changes from v1:
	- Removed unnessary locking spotted by Bjorn
	- updated register naming to reflect PM8821
	- lot of cleanups suggested by Bjorn
	- rebased on top of Linus Walleij's pm8xxx namespace
	 cleanup patch. 

 .../devicetree/bindings/mfd/qcom-pm8xxx.txt        |   1 +
 drivers/mfd/qcom-pm8xxx.c                          | 247 ++++++++++++++++++++-
 2 files changed, 238 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
index 37a088f..8f1b4ec 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
@@ -11,6 +11,7 @@ voltages and other various functionality to Qualcomm SoCs.
 	Definition: must be one of:
 		    "qcom,pm8058"
 		    "qcom,pm8921"
+		    "qcom,pm8821"
 
 - #address-cells:
 	Usage: required
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c
index 7f9620e..dc347d3 100644
--- a/drivers/mfd/qcom-pm8xxx.c
+++ b/drivers/mfd/qcom-pm8xxx.c
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/ssbi.h>
 #include <linux/regmap.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/core.h>
 
@@ -39,6 +40,20 @@
 #define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
 #define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
 
+#define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
+#define	PM8821_SSBI_REG(m, b, offset) \
+			((m == 0) ? \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
+#define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
+#define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
+#define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
+#define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
+
+#define	PM8821_BLOCKS_PER_MASTER	7
+
 #define	PM_IRQF_LVL_SEL			0x01	/* level select */
 #define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
 #define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
@@ -54,6 +69,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define PM8XXX_NR_IRQS		256
+#define PM8821_NR_IRQS		112
 
 struct pm_irq_chip {
 	struct regmap		*regmap;
@@ -65,6 +81,12 @@ struct pm_irq_chip {
 	u8			config[0];
 };
 
+struct pm_irq_data {
+	int num_irqs;
+	const struct irq_domain_ops  *irq_domain_ops;
+	void (*irq_handler)(struct irq_desc *desc);
+};
+
 static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
 				 unsigned int *ip)
 {
@@ -182,6 +204,84 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(irq_chip, desc);
 }
 
+static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
+				     int master, int block)
+{
+	int pmirq, irq, i, ret;
+	unsigned int bits;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
+	if (ret) {
+		pr_err("Failed reading %d block ret=%d", block, ret);
+		return;
+	}
+	if (!bits) {
+		pr_err("block bit set in master but no irqs: %d", block);
+		return;
+	}
+
+	/* Convert block offset to global block number */
+	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & BIT(i)) {
+			pmirq = block * 8 + i;
+			irq = irq_find_mapping(chip->irqdomain, pmirq);
+			generic_handle_irq(irq);
+		}
+	}
+
+}
+
+static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
+					     int master, u8 master_val)
+{
+	int block;
+
+	for (block = 1; block < 8; block++)
+		if (master_val & BIT(block))
+			pm8821_irq_block_handler(chip, master, block);
+
+}
+
+static void pm8821_irq_handler(struct irq_desc *desc)
+{
+	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+	unsigned int master;
+	int ret;
+
+	chained_irq_enter(irq_chip, desc);
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
+	if (ret) {
+		pr_err("Failed to re:Qad master 0 ret=%d\n", ret);
+		return;
+	}
+
+	 /* bits 1 through 7 marks the first 7 blocks in master 0*/
+	if (master & GENMASK(7, 1))
+		pm8821_irq_master_handler(chip, 0, master);
+
+	 /* bit 0 marks if master 1 contains any bits */
+	if (!(master & BIT(0)))
+		goto done;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
+	if (ret) {
+		pr_err("Failed to read master 1 ret=%d\n", ret);
+		return;
+	}
+
+	pm8821_irq_master_handler(chip, 1, master);
+
+done:
+	chained_irq_exit(irq_chip, desc);
+}
+
 static void pm8xxx_irq_mask_ack(struct irq_data *d)
 {
 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
@@ -299,6 +399,110 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
 	.map = pm8xxx_irq_domain_map,
 };
 
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	u8 block, master;
+	int irq_bit, rc;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
+		return;
+	}
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
+								pmirq, rc);
+	}
+
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), ~BIT(irq_bit));
+
+	if (rc)
+		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+}
+
+static int pm8821_irq_get_irqchip_state(struct irq_data *d,
+					enum irqchip_irq_state which,
+					bool *state)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	int rc, pmirq = irqd_to_hwirq(d);
+	u8 block, irq_bit, master;
+	unsigned int bits;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_read(chip->regmap,
+		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
+	if (rc) {
+		pr_err("Failed Reading Status rc=%d\n", rc);
+		return rc;
+	}
+
+	*state = !!(bits & BIT(irq_bit));
+
+	return rc;
+}
+
+static struct irq_chip pm8821_irq_chip = {
+	.name		= "pm8821",
+	.irq_mask_ack	= pm8821_irq_mask_ack,
+	.irq_unmask	= pm8821_irq_unmask,
+	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
+{
+	struct pm_irq_chip *chip = d->host_data;
+
+	irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, chip);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pm8821_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8821_irq_domain_map,
+};
+
 static const struct regmap_config ssbi_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
@@ -308,22 +512,44 @@ static const struct regmap_config ssbi_regmap_config = {
 	.reg_write = ssbi_reg_write
 };
 
+static const struct pm_irq_data pm8xxx_data = {
+	.num_irqs = PM8XXX_NR_IRQS,
+	.irq_domain_ops = &pm8xxx_irq_domain_ops,
+	.irq_handler = pm8xxx_irq_handler,
+};
+
+static const struct pm_irq_data pm8821_data = {
+	.num_irqs = PM8821_NR_IRQS,
+	.irq_domain_ops = &pm8821_irq_domain_ops,
+	.irq_handler = pm8821_irq_handler,
+};
+
 static const struct of_device_id pm8xxx_id_table[] = {
-	{ .compatible = "qcom,pm8018", },
-	{ .compatible = "qcom,pm8058", },
-	{ .compatible = "qcom,pm8921", },
+	{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
+	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
 
 static int pm8xxx_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match;
+	const struct pm_irq_data *data;
 	struct regmap *regmap;
 	int irq, rc;
 	unsigned int val;
 	u32 rev;
 	struct pm_irq_chip *chip;
-	unsigned int nirqs = PM8XXX_NR_IRQS;
+
+	match = of_match_node(pm8xxx_id_table, pdev->dev.of_node);
+	if (!match) {
+		dev_err(&pdev->dev, "No matching driver data found\n");
+		return -EINVAL;
+	}
+
+	data = match->data;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -354,25 +580,26 @@ static int pm8xxx_probe(struct platform_device *pdev)
 	rev |= val << BITS_PER_BYTE;
 
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
-					sizeof(chip->config[0]) * nirqs,
-					GFP_KERNEL);
+			    sizeof(chip->config[0]) * data->num_irqs,
+			    GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
 	platform_set_drvdata(pdev, chip);
 	chip->regmap = regmap;
-	chip->num_irqs = nirqs;
+	chip->num_irqs = data->num_irqs;
 	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
 	spin_lock_init(&chip->pm_irq_lock);
 
-	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
-						&pm8xxx_irq_domain_ops,
+	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+						data->num_irqs,
+						data->irq_domain_ops,
 						chip);
 	if (!chip->irqdomain)
 		return -ENODEV;
 
-	irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
+	irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
 	irq_set_irq_wake(irq, 1);
 
 	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 1/2] mfd: pm8xxx: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds support to PM8821 PMIC and interrupt support.
PM8821 is companion device that supplements primary PMIC PM8921 IC.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Acked-by: Rob Herring <robh@kernel.org>
---
Changes from v1:
	- Removed unnessary locking spotted by Bjorn
	- updated register naming to reflect PM8821
	- lot of cleanups suggested by Bjorn
	- rebased on top of Linus Walleij's pm8xxx namespace
	 cleanup patch. 

 .../devicetree/bindings/mfd/qcom-pm8xxx.txt        |   1 +
 drivers/mfd/qcom-pm8xxx.c                          | 247 ++++++++++++++++++++-
 2 files changed, 238 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
index 37a088f..8f1b4ec 100644
--- a/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom-pm8xxx.txt
@@ -11,6 +11,7 @@ voltages and other various functionality to Qualcomm SoCs.
 	Definition: must be one of:
 		    "qcom,pm8058"
 		    "qcom,pm8921"
+		    "qcom,pm8821"
 
 - #address-cells:
 	Usage: required
diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c
index 7f9620e..dc347d3 100644
--- a/drivers/mfd/qcom-pm8xxx.c
+++ b/drivers/mfd/qcom-pm8xxx.c
@@ -24,6 +24,7 @@
 #include <linux/err.h>
 #include <linux/ssbi.h>
 #include <linux/regmap.h>
+#include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/mfd/core.h>
 
@@ -39,6 +40,20 @@
 #define	SSBI_REG_ADDR_IRQ_CONFIG	(SSBI_REG_ADDR_IRQ_BASE + 7)
 #define	SSBI_REG_ADDR_IRQ_RT_STATUS	(SSBI_REG_ADDR_IRQ_BASE + 8)
 
+#define	PM8821_SSBI_REG_ADDR_IRQ_BASE	0x100
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER0 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0x30)
+#define	PM8821_SSBI_REG_ADDR_IRQ_MASTER1 (PM8821_SSBI_REG_ADDR_IRQ_BASE + 0xb0)
+#define	PM8821_SSBI_REG(m, b, offset) \
+			((m == 0) ? \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER0 + b + offset) : \
+			(PM8821_SSBI_REG_ADDR_IRQ_MASTER1 + b + offset))
+#define	PM8821_SSBI_ADDR_IRQ_ROOT(m, b)		PM8821_SSBI_REG(m, b, 0x0)
+#define	PM8821_SSBI_ADDR_IRQ_CLEAR(m, b)	PM8821_SSBI_REG(m, b, 0x01)
+#define	PM8821_SSBI_ADDR_IRQ_MASK(m, b)		PM8821_SSBI_REG(m, b, 0x08)
+#define	PM8821_SSBI_ADDR_IRQ_RT_STATUS(m, b)	PM8821_SSBI_REG(m, b, 0x0f)
+
+#define	PM8821_BLOCKS_PER_MASTER	7
+
 #define	PM_IRQF_LVL_SEL			0x01	/* level select */
 #define	PM_IRQF_MASK_FE			0x02	/* mask falling edge */
 #define	PM_IRQF_MASK_RE			0x04	/* mask rising edge */
@@ -54,6 +69,7 @@
 #define REG_HWREV_2		0x0E8  /* PMIC4 revision 2 */
 
 #define PM8XXX_NR_IRQS		256
+#define PM8821_NR_IRQS		112
 
 struct pm_irq_chip {
 	struct regmap		*regmap;
@@ -65,6 +81,12 @@ struct pm_irq_chip {
 	u8			config[0];
 };
 
+struct pm_irq_data {
+	int num_irqs;
+	const struct irq_domain_ops  *irq_domain_ops;
+	void (*irq_handler)(struct irq_desc *desc);
+};
+
 static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
 				 unsigned int *ip)
 {
@@ -182,6 +204,84 @@ static void pm8xxx_irq_handler(struct irq_desc *desc)
 	chained_irq_exit(irq_chip, desc);
 }
 
+static void pm8821_irq_block_handler(struct pm_irq_chip *chip,
+				     int master, int block)
+{
+	int pmirq, irq, i, ret;
+	unsigned int bits;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_ADDR_IRQ_ROOT(master, block), &bits);
+	if (ret) {
+		pr_err("Failed reading %d block ret=%d", block, ret);
+		return;
+	}
+	if (!bits) {
+		pr_err("block bit set in master but no irqs: %d", block);
+		return;
+	}
+
+	/* Convert block offset to global block number */
+	block += (master * PM8821_BLOCKS_PER_MASTER) - 1;
+
+	/* Check IRQ bits */
+	for (i = 0; i < 8; i++) {
+		if (bits & BIT(i)) {
+			pmirq = block * 8 + i;
+			irq = irq_find_mapping(chip->irqdomain, pmirq);
+			generic_handle_irq(irq);
+		}
+	}
+
+}
+
+static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip,
+					     int master, u8 master_val)
+{
+	int block;
+
+	for (block = 1; block < 8; block++)
+		if (master_val & BIT(block))
+			pm8821_irq_block_handler(chip, master, block);
+
+}
+
+static void pm8821_irq_handler(struct irq_desc *desc)
+{
+	struct pm_irq_chip *chip = irq_desc_get_handler_data(desc);
+	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
+	unsigned int master;
+	int ret;
+
+	chained_irq_enter(irq_chip, desc);
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master);
+	if (ret) {
+		pr_err("Failed to re:Qad master 0 ret=%d\n", ret);
+		return;
+	}
+
+	 /* bits 1 through 7 marks the first 7 blocks in master 0*/
+	if (master & GENMASK(7, 1))
+		pm8821_irq_master_handler(chip, 0, master);
+
+	 /* bit 0 marks if master 1 contains any bits */
+	if (!(master & BIT(0)))
+		goto done;
+
+	ret = regmap_read(chip->regmap,
+			  PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master);
+	if (ret) {
+		pr_err("Failed to read master 1 ret=%d\n", ret);
+		return;
+	}
+
+	pm8821_irq_master_handler(chip, 1, master);
+
+done:
+	chained_irq_exit(irq_chip, desc);
+}
+
 static void pm8xxx_irq_mask_ack(struct irq_data *d)
 {
 	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
@@ -299,6 +399,110 @@ static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
 	.map = pm8xxx_irq_domain_map,
 };
 
+static void pm8821_irq_mask_ack(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	u8 block, master;
+	int irq_bit, rc;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write mask IRQ:%d rc=%d\n", pmirq, rc);
+		return;
+	}
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_CLEAR(master, block),
+				BIT(irq_bit), BIT(irq_bit));
+
+	if (rc) {
+		pr_err("Failed to read/write IT_CLEAR IRQ:%d rc=%d\n",
+								pmirq, rc);
+	}
+
+}
+
+static void pm8821_irq_unmask(struct irq_data *d)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	unsigned int pmirq = irqd_to_hwirq(d);
+	int irq_bit, rc;
+	u8 block, master;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_update_bits(chip->regmap,
+				PM8821_SSBI_ADDR_IRQ_MASK(master, block),
+				BIT(irq_bit), ~BIT(irq_bit));
+
+	if (rc)
+		pr_err("Failed to read/write unmask IRQ:%d rc=%d\n", pmirq, rc);
+
+}
+
+static int pm8821_irq_get_irqchip_state(struct irq_data *d,
+					enum irqchip_irq_state which,
+					bool *state)
+{
+	struct pm_irq_chip *chip = irq_data_get_irq_chip_data(d);
+	int rc, pmirq = irqd_to_hwirq(d);
+	u8 block, irq_bit, master;
+	unsigned int bits;
+
+	block = pmirq / 8;
+	master = block / PM8821_BLOCKS_PER_MASTER;
+	irq_bit = pmirq % 8;
+	block %= PM8821_BLOCKS_PER_MASTER;
+
+	rc = regmap_read(chip->regmap,
+		PM8821_SSBI_ADDR_IRQ_RT_STATUS(master, block), &bits);
+	if (rc) {
+		pr_err("Failed Reading Status rc=%d\n", rc);
+		return rc;
+	}
+
+	*state = !!(bits & BIT(irq_bit));
+
+	return rc;
+}
+
+static struct irq_chip pm8821_irq_chip = {
+	.name		= "pm8821",
+	.irq_mask_ack	= pm8821_irq_mask_ack,
+	.irq_unmask	= pm8821_irq_unmask,
+	.irq_get_irqchip_state = pm8821_irq_get_irqchip_state,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
+				   irq_hw_number_t hwirq)
+{
+	struct pm_irq_chip *chip = d->host_data;
+
+	irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
+	irq_set_chip_data(irq, chip);
+	irq_set_noprobe(irq);
+
+	return 0;
+}
+
+static const struct irq_domain_ops pm8821_irq_domain_ops = {
+	.xlate = irq_domain_xlate_twocell,
+	.map = pm8821_irq_domain_map,
+};
+
 static const struct regmap_config ssbi_regmap_config = {
 	.reg_bits = 16,
 	.val_bits = 8,
@@ -308,22 +512,44 @@ static const struct regmap_config ssbi_regmap_config = {
 	.reg_write = ssbi_reg_write
 };
 
+static const struct pm_irq_data pm8xxx_data = {
+	.num_irqs = PM8XXX_NR_IRQS,
+	.irq_domain_ops = &pm8xxx_irq_domain_ops,
+	.irq_handler = pm8xxx_irq_handler,
+};
+
+static const struct pm_irq_data pm8821_data = {
+	.num_irqs = PM8821_NR_IRQS,
+	.irq_domain_ops = &pm8821_irq_domain_ops,
+	.irq_handler = pm8821_irq_handler,
+};
+
 static const struct of_device_id pm8xxx_id_table[] = {
-	{ .compatible = "qcom,pm8018", },
-	{ .compatible = "qcom,pm8058", },
-	{ .compatible = "qcom,pm8921", },
+	{ .compatible = "qcom,pm8018", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8058", .data = &pm8xxx_data},
+	{ .compatible = "qcom,pm8821", .data = &pm8821_data},
+	{ .compatible = "qcom,pm8921", .data = &pm8xxx_data},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
 
 static int pm8xxx_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *match;
+	const struct pm_irq_data *data;
 	struct regmap *regmap;
 	int irq, rc;
 	unsigned int val;
 	u32 rev;
 	struct pm_irq_chip *chip;
-	unsigned int nirqs = PM8XXX_NR_IRQS;
+
+	match = of_match_node(pm8xxx_id_table, pdev->dev.of_node);
+	if (!match) {
+		dev_err(&pdev->dev, "No matching driver data found\n");
+		return -EINVAL;
+	}
+
+	data = match->data;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0)
@@ -354,25 +580,26 @@ static int pm8xxx_probe(struct platform_device *pdev)
 	rev |= val << BITS_PER_BYTE;
 
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip) +
-					sizeof(chip->config[0]) * nirqs,
-					GFP_KERNEL);
+			    sizeof(chip->config[0]) * data->num_irqs,
+			    GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
 	platform_set_drvdata(pdev, chip);
 	chip->regmap = regmap;
-	chip->num_irqs = nirqs;
+	chip->num_irqs = data->num_irqs;
 	chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
 	chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
 	spin_lock_init(&chip->pm_irq_lock);
 
-	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, nirqs,
-						&pm8xxx_irq_domain_ops,
+	chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+						data->num_irqs,
+						data->irq_domain_ops,
 						chip);
 	if (!chip->irqdomain)
 		return -ENODEV;
 
-	irq_set_chained_handler_and_data(irq, pm8xxx_irq_handler, chip);
+	irq_set_chained_handler_and_data(irq, data->irq_handler, chip);
 	irq_set_irq_wake(irq, 1);
 
 	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Lee Jones
  Cc: bjorn.andersson, Rob Herring, Andy Gross, devicetree,
	linux-kernel, linux-arm-msm, linux-soc, linux-arm-kernel,
	Srinivas Kandagatla
In-Reply-To: <1479145933-9849-1-git-send-email-srinivas.kandagatla@linaro.org>

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 arch/arm/boot/dts/qcom-apq8064.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 268bd47..c61ba32 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -627,6 +627,33 @@
 			clock-names = "core";
 		};
 
+		ssbi@c00000 {
+			compatible = "qcom,ssbi";
+			reg = <0x00c00000 0x1000>;
+			qcom,controller-type = "pmic-arbiter";
+
+			pm8821: pmic@1 {
+				compatible = "qcom,pm8821";
+				interrupt-parent = <&tlmm_pinmux>;
+				interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+				#interrupt-cells = <2>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pm8821_mpps: mpps@50 {
+					compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
+					reg = <0x50>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>;
+					gpio-controller;
+					#gpio-cells = <2>;
+		                };
+			};
+		};
+
 		qcom,ssbi@500000 {
 			compatible = "qcom,ssbi";
 			reg = <0x00500000 0x1000>;
-- 
2.10.1

^ permalink raw reply related

* [PATCH v2 2/2] ARM: dts: apq8064: add support to pm8821
From: Srinivas Kandagatla @ 2016-11-14 17:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1479145933-9849-1-git-send-email-srinivas.kandagatla@linaro.org>

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
 arch/arm/boot/dts/qcom-apq8064.dtsi | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 268bd47..c61ba32 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -627,6 +627,33 @@
 			clock-names = "core";
 		};
 
+		ssbi at c00000 {
+			compatible = "qcom,ssbi";
+			reg = <0x00c00000 0x1000>;
+			qcom,controller-type = "pmic-arbiter";
+
+			pm8821: pmic at 1 {
+				compatible = "qcom,pm8821";
+				interrupt-parent = <&tlmm_pinmux>;
+				interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
+				#interrupt-cells = <2>;
+				interrupt-controller;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pm8821_mpps: mpps at 50 {
+					compatible = "qcom,pm8821-mpp", "qcom,ssbi-mpp";
+					reg = <0x50>;
+					interrupts = <24 IRQ_TYPE_NONE>,
+						     <25 IRQ_TYPE_NONE>,
+						     <26 IRQ_TYPE_NONE>,
+						     <27 IRQ_TYPE_NONE>;
+					gpio-controller;
+					#gpio-cells = <2>;
+		                };
+			};
+		};
+
 		qcom,ssbi at 500000 {
 			compatible = "qcom,ssbi";
 			reg = <0x00500000 0x1000>;
-- 
2.10.1

^ permalink raw reply related

* [PATCH v3] RFC: pinctrl: bcm2835: switch to GPIOLIB_IRQCHIP
From: Linus Walleij @ 2016-11-14 17:52 UTC (permalink / raw)
  To: Eric Anholt, Stephen Warren, Lee Jones, linux-gpio
  Cc: linux-rpi-kernel, Linus Walleij, Stefan Wahren

It should be possible to use the GPIOLIB_IRQCHIP helper
library with the BCM2835 driver since it is a pretty straight
forward cascaded irqchip.

The only difference from other drivers is that the BCM2835
has several banks for a single gpiochip, and each bank has
a separate IRQ line. Instead of creating one gpiochip per
bank, a single gpiochip covers all banks GPIO lines. This
makes it necessary to resolve the bank ID in the IRQ
handler.

The GPIOLIB_IRQCHIP allows several IRQs to be cascaded off
the same gpiochip by calling gpiochip_set_chained_irqchip()
repeatedly, but we have been a bit short on examples
for how this should be handled in practice, so this is intended
as an example of how this can be achieved.

The old code did not model the chip as a chained interrupt
handler, but this patch also rectifies that situation.

Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Eric Anholt <eric@anholt.net>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v2->v3:
- Rebase on top of the two new patches from the vendor tree.
ChangeLog v1->v2:
- Forgot to convert the driver to chained IRQ handler. Now fixed.

Rpi folks: I have no clue if this works or not, but would be happy
if you could test it to see if IRQs fire as expected and provide
some feedback.
---
 drivers/pinctrl/bcm/Kconfig           |   1 +
 drivers/pinctrl/bcm/pinctrl-bcm2835.c | 140 ++++++++++++++++------------------
 2 files changed, 65 insertions(+), 76 deletions(-)

diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index 63246770bd74..8968dd7aebed 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -20,6 +20,7 @@ config PINCTRL_BCM2835
 	bool
 	select PINMUX
 	select PINCONF
+	select GPIOLIB_IRQCHIP
 
 config PINCTRL_IPROC_GPIO
 	bool "Broadcom iProc GPIO (with PINCONF) driver"
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 6128359d3281..1bb38d0493eb 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -24,11 +24,9 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/gpio/driver.h>
-#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
-#include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
@@ -87,11 +85,6 @@ enum bcm2835_pinconf_pull {
 #define BCM2835_PINCONF_UNPACK_PARAM(_conf_) ((_conf_) >> 16)
 #define BCM2835_PINCONF_UNPACK_ARG(_conf_) ((_conf_) & 0xffff)
 
-struct bcm2835_gpio_irqdata {
-	struct bcm2835_pinctrl *pc;
-	int irqgroup;
-};
-
 struct bcm2835_pinctrl {
 	struct device *dev;
 	void __iomem *base;
@@ -102,16 +95,13 @@ struct bcm2835_pinctrl {
 	unsigned int irq_type[BCM2835_NUM_GPIOS];
 
 	struct pinctrl_dev *pctl_dev;
-	struct irq_domain *irq_domain;
 	struct gpio_chip gpio_chip;
 	struct pinctrl_gpio_range gpio_range;
 
-	struct bcm2835_gpio_irqdata irq_data[BCM2835_NUM_IRQS];
+	int irq_group[BCM2835_NUM_IRQS];
 	spinlock_t irq_lock[BCM2835_NUM_BANKS];
 };
 
-static struct lock_class_key gpio_lock_class;
-
 /* pins are just named GPIO0..GPIO53 */
 #define BCM2835_GPIO_PIN(a) PINCTRL_PIN(a, "gpio" #a)
 static struct pinctrl_pin_desc bcm2835_gpio_pins[] = {
@@ -369,13 +359,6 @@ static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
 	return pinctrl_gpio_direction_output(chip->base + offset);
 }
 
-static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
-
-	return irq_linear_revmap(pc->irq_domain, offset);
-}
-
 static struct gpio_chip bcm2835_gpio_chip = {
 	.label = MODULE_NAME,
 	.owner = THIS_MODULE,
@@ -386,14 +369,13 @@ static struct gpio_chip bcm2835_gpio_chip = {
 	.get_direction = bcm2835_gpio_get_direction,
 	.get = bcm2835_gpio_get,
 	.set = bcm2835_gpio_set,
-	.to_irq = bcm2835_gpio_to_irq,
 	.base = -1,
 	.ngpio = BCM2835_NUM_GPIOS,
 	.can_sleep = false,
 };
 
-static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
-					unsigned int bank, u32 mask)
+static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
+					 unsigned int bank, u32 mask)
 {
 	unsigned long events;
 	unsigned offset;
@@ -405,34 +387,49 @@ static int bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc,
 	events &= pc->enabled_irq_map[bank];
 	for_each_set_bit(offset, &events, 32) {
 		gpio = (32 * bank) + offset;
+		/* FIXME: no clue why the code looks up the type here */
 		type = pc->irq_type[gpio];
 
-		generic_handle_irq(irq_linear_revmap(pc->irq_domain, gpio));
+		generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain,
+						     gpio));
 	}
-
-	return (events != 0);
 }
 
-static irqreturn_t bcm2835_gpio_irq_handler(int irq, void *dev_id)
+static void bcm2835_gpio_irq_handler(struct irq_desc *desc)
 {
-	struct bcm2835_gpio_irqdata *irqdata = dev_id;
-	struct bcm2835_pinctrl *pc = irqdata->pc;
-	int handled = 0;
+	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
+	struct irq_chip *host_chip = irq_desc_get_chip(desc);
+	int irq = irq_desc_get_irq(desc);
+	int group;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pc->irq); i++) {
+		if (pc->irq[i] == irq) {
+			group = pc->irq_group[i];
+			break;
+		}
+	}
+	/* This should not happen, every IRQ has a bank */
+	if (i == ARRAY_SIZE(pc->irq))
+		BUG();
 
-	switch (irqdata->irqgroup) {
+	chained_irq_enter(host_chip, desc);
+
+	switch (group) {
 	case 0: /* IRQ0 covers GPIOs 0-27 */
-		handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
+		bcm2835_gpio_irq_handle_bank(pc, 0, 0x0fffffff);
 		break;
 	case 1: /* IRQ1 covers GPIOs 28-45 */
-		handled = bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000) |
-			  bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
+		bcm2835_gpio_irq_handle_bank(pc, 0, 0xf0000000);
+		bcm2835_gpio_irq_handle_bank(pc, 1, 0x00003fff);
 		break;
 	case 2: /* IRQ2 covers GPIOs 46-53 */
-		handled = bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
+		bcm2835_gpio_irq_handle_bank(pc, 1, 0x003fc000);
 		break;
 	}
 
-	return handled ? IRQ_HANDLED : IRQ_NONE;
+	chained_irq_exit(host_chip, desc);
 }
 
 static inline void __bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
@@ -478,7 +475,8 @@ static void bcm2835_gpio_irq_config(struct bcm2835_pinctrl *pc,
 
 static void bcm2835_gpio_irq_enable(struct irq_data *data)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 	unsigned offset = GPIO_REG_SHIFT(gpio);
 	unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -492,7 +490,8 @@ static void bcm2835_gpio_irq_enable(struct irq_data *data)
 
 static void bcm2835_gpio_irq_disable(struct irq_data *data)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 	unsigned offset = GPIO_REG_SHIFT(gpio);
 	unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -598,7 +597,8 @@ static int __bcm2835_gpio_irq_set_type_enabled(struct bcm2835_pinctrl *pc,
 
 static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 	unsigned offset = GPIO_REG_SHIFT(gpio);
 	unsigned bank = GPIO_REG_OFFSET(gpio);
@@ -624,7 +624,8 @@ static int bcm2835_gpio_irq_set_type(struct irq_data *data, unsigned int type)
 
 static void bcm2835_gpio_irq_ack(struct irq_data *data)
 {
-	struct bcm2835_pinctrl *pc = irq_data_get_irq_chip_data(data);
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
+	struct bcm2835_pinctrl *pc = gpiochip_get_data(chip);
 	unsigned gpio = irqd_to_hwirq(data);
 
 	bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
@@ -667,10 +668,11 @@ static void bcm2835_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
 		unsigned offset)
 {
 	struct bcm2835_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	struct gpio_chip *chip = &pc->gpio_chip;
 	enum bcm2835_fsel fsel = bcm2835_pinctrl_fsel_get(pc, offset);
 	const char *fname = bcm2835_functions[fsel];
 	int value = bcm2835_gpio_get_bit(pc, GPLEV0, offset);
-	int irq = irq_find_mapping(pc->irq_domain, offset);
+	int irq = irq_find_mapping(chip->irqdomain, offset);
 
 	seq_printf(s, "function %s in %s; irq %d (%s)",
 		fname, value ? "hi" : "lo",
@@ -1016,21 +1018,6 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 	pc->gpio_chip.parent = dev;
 	pc->gpio_chip.of_node = np;
 
-	pc->irq_domain = irq_domain_add_linear(np, BCM2835_NUM_GPIOS,
-			&irq_domain_simple_ops, NULL);
-	if (!pc->irq_domain) {
-		dev_err(dev, "could not create IRQ domain\n");
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < BCM2835_NUM_GPIOS; i++) {
-		int irq = irq_create_mapping(pc->irq_domain, i);
-		irq_set_lockdep_class(irq, &gpio_lock_class);
-		irq_set_chip_and_handler(irq, &bcm2835_gpio_irq_chip,
-				handle_level_irq);
-		irq_set_chip_data(irq, pc);
-	}
-
 	for (i = 0; i < BCM2835_NUM_BANKS; i++) {
 		unsigned long events;
 		unsigned offset;
@@ -1051,34 +1038,35 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
 		spin_lock_init(&pc->irq_lock[i]);
 	}
 
-	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
-		int len;
-		char *name;
-		pc->irq[i] = irq_of_parse_and_map(np, i);
-		pc->irq_data[i].pc = pc;
-		pc->irq_data[i].irqgroup = i;
-
-		len = strlen(dev_name(pc->dev)) + 16;
-		name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
-		if (!name)
-			return -ENOMEM;
-		snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
-
-		err = devm_request_irq(dev, pc->irq[i],
-			bcm2835_gpio_irq_handler, IRQF_SHARED,
-			name, &pc->irq_data[i]);
-		if (err) {
-			dev_err(dev, "unable to request IRQ %d\n", pc->irq[i]);
-			return err;
-		}
-	}
-
 	err = gpiochip_add_data(&pc->gpio_chip, pc);
 	if (err) {
 		dev_err(dev, "could not add GPIO chip\n");
 		return err;
 	}
 
+	err = gpiochip_irqchip_add(&pc->gpio_chip, &bcm2835_gpio_irq_chip,
+				   0, handle_level_irq, IRQ_TYPE_NONE);
+	if (err) {
+		dev_info(dev, "could not add irqchip\n");
+		return err;
+	}
+
+	for (i = 0; i < BCM2835_NUM_IRQS; i++) {
+		pc->irq[i] = irq_of_parse_and_map(np, i);
+		pc->irq_group[i] = i;
+		/*
+		 * Use the same handler for all groups: this is necessary
+		 * since we use one gpiochip to cover all lines - the
+		 * irq handler then needs to figure out which group and
+		 * bank that was firing the IRQ and look up the per-group
+		 * and bank data.
+		 */
+		gpiochip_set_chained_irqchip(&pc->gpio_chip,
+					     &bcm2835_gpio_irq_chip,
+					     pc->irq[i],
+					     bcm2835_gpio_irq_handler);
+	}
+
 	pc->pctl_dev = devm_pinctrl_register(dev, &bcm2835_pinctrl_desc, pc);
 	if (IS_ERR(pc->pctl_dev)) {
 		gpiochip_remove(&pc->gpio_chip);
-- 
2.7.4


^ permalink raw reply related

* Re: [PATCH] cpufreq: intel_pstate: fix intel_pstate_use_acpi_profile helper
From: Pandruvada, Srinivas @ 2016-11-14 17:53 UTC (permalink / raw)
  To: arnd@arndb.de, rjw@rjwysocki.net
  Cc: lenb@kernel.org, viresh.kumar@linaro.org, Gasparini, Stephane,
	philippe.longepe@linux.intel.com, linux-pm@vger.kernel.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <1479143663.6544.11.camel@linux.intel.com>

On Mon, 2016-11-14 at 09:14 -0800, Srinivas Pandruvada wrote:
> On Mon, 2016-11-14 at 17:41 +0100, Arnd Bergmann wrote:
> > 
> > The newly added function uses two different prototypes depending
> > on configuration, and one of them does not match the caller:
> > 
> > drivers/cpufreq/intel_pstate.c: In function ‘copy_cpu_funcs’:
> > drivers/cpufreq/intel_pstate.c:1798:2: error: too few arguments to
> > function ‘intel_pstate_use_acpi_profile’
> > 
> > This changes it to look like the other one.
> Sorry about that.

Since this is a compile issue for x86 non ACPI systems, which will be a
problem for git bisect, it is better to resubmit my patch with the fix.

Thanks,
Srinivas

^ permalink raw reply

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Lee Jones, Rob Herring, Andy Gross,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-msm-u79uwXL29TY76Z2rM5mHXA,
	linux-soc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51@linaro.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn

^ permalink raw reply

* [U-Boot] [PATCH v2 2/3] LS1046AQDS: Add NOR Secure Boot Target
From: york sun @ 2016-11-14 17:53 UTC (permalink / raw)
  To: u-boot
In-Reply-To: <1477513031-29292-3-git-send-email-sumit.garg@nxp.com>

On 10/26/2016 03:47 AM, Sumit Garg wrote:
> Add NOR secure boot target. Also enable sec init.
>
> Signed-off-by: Vinitha Pillai <vinitha.pillai@nxp.com>
> Signed-off-by: Sumit Garg <sumit.garg@nxp.com>
> ---
>
> Changes in v2:
> Split patches logically from 2 to 3.
>
>  board/freescale/ls1046aqds/MAINTAINERS   |  4 ++++
>  board/freescale/ls1046aqds/ls1046aqds.c  | 18 ++++++++++++++++++
>  configs/ls1046aqds_SECURE_BOOT_defconfig | 29 +++++++++++++++++++++++++++++
>  3 files changed, 51 insertions(+)
>  create mode 100644 configs/ls1046aqds_SECURE_BOOT_defconfig
>
> diff --git a/board/freescale/ls1046aqds/MAINTAINERS b/board/freescale/ls1046aqds/MAINTAINERS
> index b4549ae..6737d55 100644
> --- a/board/freescale/ls1046aqds/MAINTAINERS
> +++ b/board/freescale/ls1046aqds/MAINTAINERS
> @@ -8,3 +8,7 @@ F:	configs/ls1046aqds_nand_defconfig
>  F:	configs/ls1046aqds_sdcard_ifc_defconfig
>  F:	configs/ls1046aqds_sdcard_qspi_defconfig
>  F:	configs/ls1046aqds_qspi_defconfig
> +
> +M:	Sumit Garg <sumit.garg@nxp.com>
> +S:	Maintained
> +F:	configs/ls1046aqds_SECURE_BOOT_defconfig
> diff --git a/board/freescale/ls1046aqds/ls1046aqds.c b/board/freescale/ls1046aqds/ls1046aqds.c
> index 8c18538..a418590 100644
> --- a/board/freescale/ls1046aqds/ls1046aqds.c
> +++ b/board/freescale/ls1046aqds/ls1046aqds.c
> @@ -20,6 +20,7 @@
>  #include <fsl_csu.h>
>  #include <fsl_esdhc.h>
>  #include <fsl_ifc.h>
> +#include <fsl_sec.h>
>  #include <spl.h>
>
>  #include "../common/vid.h"
> @@ -242,6 +243,23 @@ int board_init(void)
>  	if (adjust_vdd(0))
>  		printf("Warning: Adjusting core voltage failed.\n");
>
> +#ifdef CONFIG_SECURE_BOOT
> +	/* In case of Secure Boot, the IBR configures the SMMU
> +	 * to allow only Secure transactions.
> +	 * SMMU must be reset in bypass mode.
> +	 * Set the ClientPD bit and Clear the USFCFG Bit
> +	 */

Multiple-line comment in wrong format. You just fixed some in your first 
patch.

York

^ permalink raw reply

* Re: [PATCH 1/2] mfd: pm8921: add support to pm8821
From: Bjorn Andersson @ 2016-11-14 17:53 UTC (permalink / raw)
  To: Srinivas Kandagatla
  Cc: Lee Jones, Rob Herring, Andy Gross, devicetree, linux-kernel,
	linux-arm-msm, linux-soc, linux-arm-kernel
In-Reply-To: <852fbb95-852e-0612-77a8-b0b072a68c51@linaro.org>

On Mon 14 Nov 09:33 PST 2016, Srinivas Kandagatla wrote:

[..]
> >>+static int pm8821_irq_block_handler(struct pm_irq_chip *chip,
> >>+				    int master_number, int block)
> >>+{
> >>+	int pmirq, irq, i, ret;
> >>+	unsigned int bits;
> >>+
> >>+	ret = pm8821_read_block_irq(chip, master_number, block, &bits);
> >>+	if (ret) {
> >>+		pr_err("Failed reading %d block ret=%d", block, ret);
> >>+		return ret;
> >>+	}
> >>+	if (!bits) {
> >>+		pr_err("block bit set in master but no irqs: %d", block);
> >>+		return 0;
> >>+	}
> >>+
> >>+	/* Convert block offset to global block number */
> >>+	block += (master_number * PM8821_BLOCKS_PER_MASTER) - 1;
> >
> >So this is block -= 1 for master 0 and block += 6 for master 1, is the
> >latter correct?
> >
> Yes, both of them are correct.
> 
> for master 0 which has block numbers from 1-7 should translate to 0-6 in
> linear space.
> for master 1 which has block numbers from 1-7 should translate to 7-13 in
> linear space.
> 
> so for master0 it is -=1 and and for master1 it is +=6 seems correct.
> 

Ahh, because block is 1-indexed when we enter, so have to switch base
and then calculate the global number, like:

  block = block - 1 + (master * PER_MASTER) + 7

but we cancel out the subtraction. I agree that this looks correct then.

I would prefer less of a mixture between 0-indexing and 1-indexing, but
I don't have any good ideas on how to restructure it to make it better.

Regards,
Bjorn

^ permalink raw reply

* Re: [net] 2ab9fb18c4: kernel BUG at include/linux/skbuff.h:1935!
From: Duyck, Alexander H @ 2016-11-14 17:54 UTC (permalink / raw)
  To: lkp
In-Reply-To: <5828fc09.rTUEnj6qw0eDHzYL%xiaolong.ye@intel.com>

[-- Attachment #1: Type: text/plain, Size: 5871 bytes --]

On Mon, 2016-11-14 at 07:49 +0800, kernel test robot wrote:
> FYI, we noticed the following commit:
> 
> https://github.com/0day-ci/linux Eric-Dumazet/net-__skb_flow_dissect-must-cap-its-return-value/20161110-080839
> commit 2ab9fb18c46b91b16a0f0f329336d3be9fc32deb ("net: __skb_flow_dissect() must cap its return value")
> 
> in testcase: kbuild
> with following parameters:
> 
> 	runtime: 300s
> 	nr_task: 50%
> 	cpufreq_governor: performance
> 
> 
> 
> 
> on test machine: 8 threads Intel(R) Atom(TM) CPU  C2750  @ 2.40GHz with 16G memory
> 
> caused below changes:
> 
> 
> +-------------------------------------------------------+------------+------------+
> > 
> >                                                       | cdb26d3387 | 2ab9fb18c4 |
> +-------------------------------------------------------+------------+------------+
> > 
> > boot_successes                                        | 10         | 3          |
> > boot_failures                                         | 0          | 9          |
> > kernel_BUG_at_include/linux/skbuff.h                  | 0          | 8          |
> > invalid_opcode:#[##]SMP                               | 0          | 8          |
> > RIP:eth_type_trans                                    | 0          | 8          |
> > Kernel_panic-not_syncing:Fatal_exception_in_interrupt | 0          | 5          |
> > WARNING:at_fs/sysfs/dir.c:#sysfs_warn_dup             | 0          | 1          |
> > calltrace:parport_pc_init                             | 0          | 1          |
> > calltrace:SyS_finit_module                            | 0          | 1          |
> > WARNING:at_lib/kobject.c:#kobject_add_internal        | 0          | 1          |
> +-------------------------------------------------------+------------+------------+
> 
> 
> 
> [   20.491020] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [   20.502988] Sending DHCP requests .
> [   20.506729] ------------[ cut here ]------------
> [   20.511369] kernel BUG at include/linux/skbuff.h:1935!
> [   20.517893] invalid opcode: 0000 [#1] SMP
> [   20.521902] Modules linked in:
> [   20.524979] CPU: 4 PID: 0 Comm: swapper/4 Not tainted 4.9.0-rc3-00286-g2ab9fb1 #1
> [   20.532463] Hardware name: Supermicro SYS-5018A-TN4/A1SAi, BIOS 1.1a 08/27/2015
> [   20.539768] task: ffff8804456c2480 task.stack: ffffc90001920000
> [   20.545684] RIP: 0010:[<ffffffff81837b48>]  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.553972] RSP: 0018:ffff88047fd03db8  EFLAGS: 00010297
> [   20.559283] RAX: 0000000000000158 RBX: ffff88047d8ae600 RCX: 0000000000001073
> [   20.566415] RDX: ffff88047bf07dc0 RSI: ffff88047d8a4000 RDI: ffff88047dac0f00
> [   20.573546] RBP: ffff88047fd03e20 R08: ffff88047d8a4000 R09: 0000000000000800
> [   20.580678] R10: ffff88047bf07ec0 R11: ffffea0011f6e400 R12: ffff88047dac0f00
> [   20.587810] R13: ffff880457413000 R14: ffffc90002129000 R15: 000000000000015e
> [   20.594946] FS:  0000000000000000(0000) GS:ffff88047fd00000(0000) knlGS:0000000000000000
> [   20.603032] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   20.608775] CR2: 00007fffadfb4ef0 CR3: 000000047ee07000 CR4: 00000000001006e0
> [   20.615906] Stack:
> [   20.617927]  ffffffff816905a7 ffffea0011f6e400 ffffea0000000008 ffff88047d8ae450
> [   20.625403]  ffff88047d8ae400 0000004000000166 ffffea0011f6e400 0000ffff00000000
> [   20.632873]  0000000000000040 0000000000000000 ffff88047d8ae450 ffff88047d8b1140
> [   20.640352] Call Trace:
> [   20.642805]  <IRQ> 
> [   20.644740]  [<ffffffff816905a7>] ? igb_clean_rx_irq+0x6a7/0x7d0
> [   20.650760]  [<ffffffff81690a52>] igb_poll+0x382/0x700
> [   20.655904]  [<ffffffff8146edd9>] ? timerqueue_add+0x59/0xb0
> [   20.661564]  [<ffffffff8180f2d7>] net_rx_action+0x217/0x360
> [   20.667137]  [<ffffffff81957ef4>] __do_softirq+0x104/0x2ab
> [   20.672624]  [<ffffffff81086961>] irq_exit+0xf1/0x100
> [   20.677673]  [<ffffffff81957c34>] do_IRQ+0x54/0xd0
> [   20.682466]  [<ffffffff81955acc>] common_interrupt+0x8c/0x8c
> [   20.688123]  <EOI> 
> [   20.690054]  [<ffffffff817c1d12>] ? cpuidle_enter_state+0x122/0x2e0
> [   20.696333]  [<ffffffff817c1f07>] cpuidle_enter+0x17/0x20
> [   20.701733]  [<ffffffff810c64c3>] call_cpuidle+0x23/0x40
> [   20.707045]  [<ffffffff810c66f4>] cpu_startup_entry+0x114/0x200
> [   20.712964]  [<ffffffff81051c87>] start_secondary+0x107/0x130
> [   20.718708] Code: 00 04 00 00 c9 c3 48 33 86 70 03 00 00 48 c1 e0 10 48 85 c0 0f b6 87 90 00 00 00 75 28 83 e0 f8 83 c8 01 88 87 90 00 00 00 eb 82 <0f> 0b 0f b6 87 90 00 00 00 83 e0 f8 83 c8 03 88 87 90 00 00 00 
> [   20.738722] RIP  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.744662]  RSP <ffff88047fd03db8>
> [   20.748160] ---[ end trace 153440bf1ca2e6fc ]---
> [   20.748165] ------------[ cut here ]------------
> 
> 
> To reproduce:
> 
>         git clone git://git.kernel.org/pub/scm/linux/kernel/git/wfg/lkp-tests.git
>         cd lkp-tests
>         bin/lkp install job.yaml  # job file is attached in this email
>         bin/lkp run     job.yaml
> 
> 
> 
> Thanks,
> Kernel Test Robot


So I am trying to reproduce this but need some additional data as just
copying the config apparently isn't enough.

I just wanted to confirm.  It looks like you are running serial over
lan over one of the igb ports.  Do I have that right?  I ask because
the igb driver loading in the dmesg log seems to cause a 2.1 second
skip and doesn't display the driver version or any information on the
igb devices.

Another question I had is what versions of gcc are you testing with?  I
see the dmesg for the failing case is using gcc version 6.2.  Are there
any other versions of gcc that are being tested, and if so are they
showing similar failures?

Thanks.

- Alex



^ permalink raw reply

* Re: [net]  2ab9fb18c4: kernel BUG at include/linux/skbuff.h:1935!
From: Duyck, Alexander H @ 2016-11-14 17:54 UTC (permalink / raw)
  To: eric.dumazet@gmail.com, Ye, Xiaolong
  Cc: tom@herbertland.com, ast@kernel.org, willemb@google.com,
	netdev@vger.kernel.org, jojvargh@cisco.com, davem@davemloft.net,
	lkp@01.org, yibyang@cisco.com
In-Reply-To: <5828fc09.rTUEnj6qw0eDHzYL%xiaolong.ye@intel.com>

On Mon, 2016-11-14 at 07:49 +0800, kernel test robot wrote:
> FYI, we noticed the following commit:
> 
> https://github.com/0day-ci/linux Eric-Dumazet/net-__skb_flow_dissect-must-cap-its-return-value/20161110-080839
> commit 2ab9fb18c46b91b16a0f0f329336d3be9fc32deb ("net: __skb_flow_dissect() must cap its return value")
> 
> in testcase: kbuild
> with following parameters:
> 
> 	runtime: 300s
> 	nr_task: 50%
> 	cpufreq_governor: performance
> 
> 
> 
> 
> on test machine: 8 threads Intel(R) Atom(TM) CPU  C2750  @ 2.40GHz with 16G memory
> 
> caused below changes:
> 
> 
> +-------------------------------------------------------+------------+------------+
> > 
> >                                                       | cdb26d3387 | 2ab9fb18c4 |
> +-------------------------------------------------------+------------+------------+
> > 
> > boot_successes                                        | 10         | 3          |
> > boot_failures                                         | 0          | 9          |
> > kernel_BUG_at_include/linux/skbuff.h                  | 0          | 8          |
> > invalid_opcode:#[##]SMP                               | 0          | 8          |
> > RIP:eth_type_trans                                    | 0          | 8          |
> > Kernel_panic-not_syncing:Fatal_exception_in_interrupt | 0          | 5          |
> > WARNING:at_fs/sysfs/dir.c:#sysfs_warn_dup             | 0          | 1          |
> > calltrace:parport_pc_init                             | 0          | 1          |
> > calltrace:SyS_finit_module                            | 0          | 1          |
> > WARNING:at_lib/kobject.c:#kobject_add_internal        | 0          | 1          |
> +-------------------------------------------------------+------------+------------+
> 
> 
> 
> [   20.491020] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
> [   20.502988] Sending DHCP requests .
> [   20.506729] ------------[ cut here ]------------
> [   20.511369] kernel BUG at include/linux/skbuff.h:1935!
> [   20.517893] invalid opcode: 0000 [#1] SMP
> [   20.521902] Modules linked in:
> [   20.524979] CPU: 4 PID: 0 Comm: swapper/4 Not tainted 4.9.0-rc3-00286-g2ab9fb1 #1
> [   20.532463] Hardware name: Supermicro SYS-5018A-TN4/A1SAi, BIOS 1.1a 08/27/2015
> [   20.539768] task: ffff8804456c2480 task.stack: ffffc90001920000
> [   20.545684] RIP: 0010:[<ffffffff81837b48>]  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.553972] RSP: 0018:ffff88047fd03db8  EFLAGS: 00010297
> [   20.559283] RAX: 0000000000000158 RBX: ffff88047d8ae600 RCX: 0000000000001073
> [   20.566415] RDX: ffff88047bf07dc0 RSI: ffff88047d8a4000 RDI: ffff88047dac0f00
> [   20.573546] RBP: ffff88047fd03e20 R08: ffff88047d8a4000 R09: 0000000000000800
> [   20.580678] R10: ffff88047bf07ec0 R11: ffffea0011f6e400 R12: ffff88047dac0f00
> [   20.587810] R13: ffff880457413000 R14: ffffc90002129000 R15: 000000000000015e
> [   20.594946] FS:  0000000000000000(0000) GS:ffff88047fd00000(0000) knlGS:0000000000000000
> [   20.603032] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> [   20.608775] CR2: 00007fffadfb4ef0 CR3: 000000047ee07000 CR4: 00000000001006e0
> [   20.615906] Stack:
> [   20.617927]  ffffffff816905a7 ffffea0011f6e400 ffffea0000000008 ffff88047d8ae450
> [   20.625403]  ffff88047d8ae400 0000004000000166 ffffea0011f6e400 0000ffff00000000
> [   20.632873]  0000000000000040 0000000000000000 ffff88047d8ae450 ffff88047d8b1140
> [   20.640352] Call Trace:
> [   20.642805]  <IRQ> 
> [   20.644740]  [<ffffffff816905a7>] ? igb_clean_rx_irq+0x6a7/0x7d0
> [   20.650760]  [<ffffffff81690a52>] igb_poll+0x382/0x700
> [   20.655904]  [<ffffffff8146edd9>] ? timerqueue_add+0x59/0xb0
> [   20.661564]  [<ffffffff8180f2d7>] net_rx_action+0x217/0x360
> [   20.667137]  [<ffffffff81957ef4>] __do_softirq+0x104/0x2ab
> [   20.672624]  [<ffffffff81086961>] irq_exit+0xf1/0x100
> [   20.677673]  [<ffffffff81957c34>] do_IRQ+0x54/0xd0
> [   20.682466]  [<ffffffff81955acc>] common_interrupt+0x8c/0x8c
> [   20.688123]  <EOI> 
> [   20.690054]  [<ffffffff817c1d12>] ? cpuidle_enter_state+0x122/0x2e0
> [   20.696333]  [<ffffffff817c1f07>] cpuidle_enter+0x17/0x20
> [   20.701733]  [<ffffffff810c64c3>] call_cpuidle+0x23/0x40
> [   20.707045]  [<ffffffff810c66f4>] cpu_startup_entry+0x114/0x200
> [   20.712964]  [<ffffffff81051c87>] start_secondary+0x107/0x130
> [   20.718708] Code: 00 04 00 00 c9 c3 48 33 86 70 03 00 00 48 c1 e0 10 48 85 c0 0f b6 87 90 00 00 00 75 28 83 e0 f8 83 c8 01 88 87 90 00 00 00 eb 82 <0f> 0b 0f b6 87 90 00 00 00 83 e0 f8 83 c8 03 88 87 90 00 00 00 
> [   20.738722] RIP  [<ffffffff81837b48>] eth_type_trans+0xe8/0x140
> [   20.744662]  RSP <ffff88047fd03db8>
> [   20.748160] ---[ end trace 153440bf1ca2e6fc ]---
> [   20.748165] ------------[ cut here ]------------
> 
> 
> To reproduce:
> 
>         git clone git://git.kernel.org/pub/scm/linux/kernel/git/wfg/lkp-tests.git
>         cd lkp-tests
>         bin/lkp install job.yaml  # job file is attached in this email
>         bin/lkp run     job.yaml
> 
> 
> 
> Thanks,
> Kernel Test Robot


So I am trying to reproduce this but need some additional data as just
copying the config apparently isn't enough.

I just wanted to confirm.  It looks like you are running serial over
lan over one of the igb ports.  Do I have that right?  I ask because
the igb driver loading in the dmesg log seems to cause a 2.1 second
skip and doesn't display the driver version or any information on the
igb devices.

Another question I had is what versions of gcc are you testing with?  I
see the dmesg for the failing case is using gcc version 6.2.  Are there
any other versions of gcc that are being tested, and if so are they
showing similar failures?

Thanks.

- Alex



^ permalink raw reply

* [PATCH tip/core/rcu 0/7] Security-related list changes for 4.10
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani

Hello!

This series contains security-related list changes, some of which stems
in part from PaX and Grsecurity work:

1.	Split __list_add() debug checks into a separate functions,
	courtesy of Kees Cook.

2.	Consolidate DEBUG_LIST() for list_add_rcu(), courtesy of Kees Cook.

3.	Split list_del() debug checking into separate function, courtesy
	of Kees Cook.

4.	Provide toggle for BUG() on data corruption, so that people who
	care more about security than uptime can crash their machines
	in the face of list data corruption, courtesy of Kees Cook.

	Note that CHECK_DATA_CORRUPTION() contains unconventional control
	flow, however, this is intended and is used correctly.

5.	Add tests for list corruption, courtesy of Kees Cook.

6.	Fix typo in "select" Kconfig statement in #4 above, courtesy
	of Valentin Rothberg.

7.	Avoid Kconfig warning from CONFIG_DEBUG_LIST from #4 above,
	courtesy of Arnd Bergmann.

							Thanx, Paul

------------------------------------------------------------------------

 drivers/misc/lkdtm.h      |    2 
 drivers/misc/lkdtm_bugs.c |   68 +++++++++++++++++
 drivers/misc/lkdtm_core.c |    2 
 include/linux/bug.h       |   17 ++++
 include/linux/list.h      |   37 ++++++---
 include/linux/rculist.h   |    8 --
 lib/Kconfig.debug         |   14 +++
 lib/list_debug.c          |  177 +++++++++++++++++-----------------------------
 8 files changed, 197 insertions(+), 128 deletions(-)

^ permalink raw reply

* [PATCH 1/2] can: holt_hi311x: document device tree bindings
From: Akshay Bhat @ 2016-11-14 17:55 UTC (permalink / raw)
  To: wg, mkl, robh+dt
  Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
	Akshay Bhat, Akshay Bhat

Document the HOLT HI-311x CAN device tree bindings.

Signed-off-by: Akshay Bhat <nodeax@gmail.com>
---
 .../devicetree/bindings/net/can/holt_hi311x.txt    | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/can/holt_hi311x.txt

diff --git a/Documentation/devicetree/bindings/net/can/holt_hi311x.txt b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
new file mode 100644
index 0000000..23aa94e
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/holt_hi311x.txt
@@ -0,0 +1,24 @@
+* Holt HI-311X stand-alone CAN controller device tree bindings
+
+Required properties:
+ - compatible: Should be one of the following:
+   - "holt,hi3110" for HI-3110
+ - reg: SPI chip select.
+ - clocks: The clock feeding the CAN controller.
+ - interrupt-parent: The parent interrupt controller.
+ - interrupts: Should contain IRQ line for the CAN controller.
+
+Optional properties:
+ - vdd-supply: Regulator that powers the CAN controller.
+ - xceiver-supply: Regulator that powers the CAN transceiver.
+
+Example:
+	can0: can@1 {
+		compatible = "holt,hi3110";
+		reg = <1>;
+		clocks = <&clk32m>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <13 IRQ_TYPE_EDGE_RISING>;
+		vdd-supply = <&reg5v0>;
+		xceiver-supply = <&reg5v0>;
+	};
-- 
2.8.1

^ permalink raw reply related

* [PATCH 2/2] can: spi: hi311x: Add Holt HI-311x CAN driver
From: Akshay Bhat @ 2016-11-14 17:55 UTC (permalink / raw)
  To: wg, mkl, robh+dt
  Cc: mark.rutland, linux-can, netdev, devicetree, linux-kernel,
	Akshay Bhat, Akshay Bhat
In-Reply-To: <1479146144-29143-1-git-send-email-akshay.bhat@timesys.com>

This patch adds support for the Holt HI-311x CAN controller. The HI311x
CAN controller is capable of transmitting and receiving standard data
frames, extended data frames and remote frames. The HI311x interfaces
with the host over SPI.

Datasheet: www.holtic.com/documents/371-hi-3110_v-rev-jpdf.do

Signed-off-by: Akshay Bhat <nodeax@gmail.com>
---
 drivers/net/can/spi/Kconfig  |    6 +
 drivers/net/can/spi/Makefile |    1 +
 drivers/net/can/spi/hi311x.c | 1071 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1078 insertions(+)
 create mode 100644 drivers/net/can/spi/hi311x.c

diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig
index 148cae5..9eb1bb1 100644
--- a/drivers/net/can/spi/Kconfig
+++ b/drivers/net/can/spi/Kconfig
@@ -7,4 +7,10 @@ config CAN_MCP251X
 	---help---
 	  Driver for the Microchip MCP251x SPI CAN controllers.
 
+config CAN_HI311X
+	tristate "Holt HI311x SPI CAN controllers"
+	depends on CAN_DEV && SPI && HAS_DMA
+	---help---
+	  Driver for the Holt HI311x SPI CAN controllers.
+
 endmenu
diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile
index 0e86040..eac7c3a 100644
--- a/drivers/net/can/spi/Makefile
+++ b/drivers/net/can/spi/Makefile
@@ -4,3 +4,4 @@
 
 
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
+obj-$(CONFIG_CAN_HI311X)	+= hi311x.o
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
new file mode 100644
index 0000000..1020166
--- /dev/null
+++ b/drivers/net/can/spi/hi311x.c
@@ -0,0 +1,1071 @@
+/* CAN bus driver for Holt HI3110 CAN Controller with SPI Interface
+ *
+ * Based on Microchip 251x CAN Controller (mcp251x) Linux kernel driver
+ *
+ * Copyright(C) Timesys Corporation 2016
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/can/led.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/freezer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/spi/spi.h>
+#include <linux/uaccess.h>
+
+#define HI3110_MASTER_RESET        0x56
+#define HI3110_READ_CTRL0          0xD2
+#define HI3110_READ_CTRL1          0xD4
+#define HI3110_READ_STATF          0xE2
+#define HI3110_WRITE_CTRL0         0x14
+#define HI3110_WRITE_CTRL1         0x16
+#define HI3110_WRITE_INTE          0x1C
+#define HI3110_WRITE_BTR0          0x18
+#define HI3110_WRITE_BTR1          0x1A
+#define HI3110_READ_BTR0           0xD6
+#define HI3110_READ_BTR1           0xD8
+#define HI3110_READ_INTF           0xDE
+#define HI3110_READ_ERR            0xDC
+#define HI3110_READ_FIFO_WOTIME    0x48
+#define HI3110_WRITE_FIFO          0x12
+#define HI3110_READ_MESSTAT        0xDA
+#define HI3110_READ_TEC            0xEC
+
+#define HI3110_CTRL0_MODE_MASK     (7 << 5)
+#define HI3110_CTRL0_NORMAL_MODE   (0 << 5)
+#define HI3110_CTRL0_LOOPBACK_MODE (1 << 5)
+#define HI3110_CTRL0_MONITOR_MODE  (2 << 5)
+#define HI3110_CTRL0_SLEEP_MODE    (3 << 5)
+#define HI3110_CTRL0_INIT_MODE     (4 << 5)
+
+#define HI3110_CTRL1_TXEN          BIT(7)
+
+#define HI3110_INT_RXTMP           BIT(7)
+#define HI3110_INT_RXFIFO          BIT(6)
+#define HI3110_INT_TXCPLT          BIT(5)
+#define HI3110_INT_BUSERR          BIT(4)
+#define HI3110_INT_MCHG            BIT(3)
+#define HI3110_INT_WAKEUP          BIT(2)
+#define HI3110_INT_F1MESS          BIT(1)
+#define HI3110_INT_F0MESS          BIT(0)
+
+#define HI3110_ERR_BUSOFF          BIT(7)
+#define HI3110_ERR_TXERRP          BIT(6)
+#define HI3110_ERR_RXERRP          BIT(5)
+#define HI3110_ERR_BITERR          BIT(4)
+#define HI3110_ERR_FRMERR          BIT(3)
+#define HI3110_ERR_CRCERR          BIT(2)
+#define HI3110_ERR_ACKERR          BIT(1)
+#define HI3110_ERR_STUFERR         BIT(0)
+#define HI3110_ERR_PROTOCOL_MASK   (0x1F)
+
+#define HI3110_STAT_RXFMTY         BIT(1)
+
+#define HI3110_BTR0_SJW_SHIFT      6
+#define HI3110_BTR0_BRP_SHIFT      0
+
+#define HI3110_BTR1_SAMP_3PERBIT   (1 << 7)
+#define HI3110_BTR1_SAMP_1PERBIT   (0 << 7)
+#define HI3110_BTR1_TSEG2_SHIFT    4
+#define HI3110_BTR1_TSEG1_SHIFT    0
+
+#define HI3110_FIFO_WOTIME_TAG_OFF 0
+#define HI3110_FIFO_WOTIME_ID_OFF  1
+#define HI3110_FIFO_WOTIME_DLC_OFF 5
+#define HI3110_FIFO_WOTIME_DAT_OFF 6
+
+#define HI3110_FIFO_WOTIME_TAG_IDE BIT(7)
+#define HI3110_FIFO_WOTIME_ID_RTR  BIT(0)
+
+#define HI3110_FIFO_TAG_OFF        0
+#define HI3110_FIFO_ID_OFF         1
+#define HI3110_FIFO_STD_DLC_OFF    3
+#define HI3110_FIFO_STD_DATA_OFF   4
+#define HI3110_FIFO_EXT_DLC_OFF    5
+#define HI3110_FIFO_EXT_DATA_OFF   6
+
+#define CAN_FRAME_MAX_DATA_LEN 8
+#define RX_BUF_LEN             15
+#define TX_STD_BUF_LEN         12
+#define TX_EXT_BUF_LEN         14
+#define CAN_FRAME_MAX_BITS     128
+
+#define TX_ECHO_SKB_MAX	1
+
+#define HI3110_OST_DELAY_MS (10)
+
+#define DEVICE_NAME "hi3110"
+
+static int hi3110_enable_dma = 1; /* Enable SPI DMA. Default: 1 (On) */
+module_param(hi3110_enable_dma, int, 0444);
+MODULE_PARM_DESC(hi3110_enable_dma, "Enable SPI DMA. Default: 1 (On)");
+
+static const struct can_bittiming_const hi3110_bittiming_const = {
+	.name = DEVICE_NAME,
+	.tseg1_min = 2,
+	.tseg1_max = 16,
+	.tseg2_min = 2,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 64,
+	.brp_inc = 1,
+};
+
+enum hi3110_model {
+	CAN_HI3110_HI3110	= 0x3110,
+};
+
+struct hi3110_priv {
+	struct can_priv	   can;
+	struct net_device *net;
+	struct spi_device *spi;
+	enum hi3110_model model;
+
+	struct mutex hi3110_lock; /* SPI device lock */
+
+	u8 *spi_tx_buf;
+	u8 *spi_rx_buf;
+	dma_addr_t spi_tx_dma;
+	dma_addr_t spi_rx_dma;
+
+	struct sk_buff *tx_skb;
+	int tx_len;
+
+	struct workqueue_struct *wq;
+	struct work_struct tx_work;
+	struct work_struct restart_work;
+
+	int force_quit;
+	int after_suspend;
+#define AFTER_SUSPEND_UP 1
+#define AFTER_SUSPEND_DOWN 2
+#define AFTER_SUSPEND_POWER 4
+#define AFTER_SUSPEND_RESTART 8
+	int restart_tx;
+	struct regulator *power;
+	struct regulator *transceiver;
+	struct clk *clk;
+};
+
+static void hi3110_clean(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+
+	if (priv->tx_skb || priv->tx_len)
+		net->stats.tx_errors++;
+	if (priv->tx_skb)
+		dev_kfree_skb(priv->tx_skb);
+	if (priv->tx_len)
+		can_free_echo_skb(priv->net, 0);
+	priv->tx_skb = NULL;
+	priv->tx_len = 0;
+}
+
+/* Note about handling of error return of hi3110_spi_trans: accessing
+ * registers via SPI is not really different conceptually than using
+ * normal I/O assembler instructions, although it's much more
+ * complicated from a practical POV. So it's not advisable to always
+ * check the return value of this function. Imagine that every
+ * read{b,l}, write{b,l} and friends would be bracketed in "if ( < 0)
+ * error();", it would be a great mess (well there are some situation
+ * when exception handling C++ like could be useful after all). So we
+ * just check that transfers are OK at the beginning of our
+ * conversation with the chip and to avoid doing really nasty things
+ * (like injecting bogus packets in the network stack).
+ */
+static int hi3110_spi_trans(struct spi_device *spi, int len)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct spi_transfer t = {
+		.tx_buf = priv->spi_tx_buf,
+		.rx_buf = priv->spi_rx_buf,
+		.len = len,
+		.cs_change = 0,
+	};
+	struct spi_message m;
+	int ret;
+
+	spi_message_init(&m);
+
+	if (hi3110_enable_dma) {
+		t.tx_dma = priv->spi_tx_dma;
+		t.rx_dma = priv->spi_rx_dma;
+		m.is_dma_mapped = 1;
+	}
+
+	spi_message_add_tail(&t, &m);
+
+	ret = spi_sync(spi, &m);
+
+	if (ret)
+		dev_err(&spi->dev, "spi transfer failed: ret = %d\n", ret);
+	return ret;
+}
+
+static u8 hi3110_cmd(struct spi_device *spi, uint8_t command)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = command;
+	dev_dbg(&spi->dev, "hi3110_cmd: %02X\n", command);
+
+	return hi3110_spi_trans(spi, 1);
+}
+
+static u8 hi3110_read(struct spi_device *spi, uint8_t command)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	u8 val = 0;
+
+	priv->spi_tx_buf[0] = command;
+	hi3110_spi_trans(spi, 2);
+	val = priv->spi_rx_buf[1];
+	dev_dbg(&spi->dev, "hi3110_read: %02X, %02X\n", command, val);
+
+	return val;
+}
+
+static void hi3110_write(struct spi_device *spi, u8 reg, uint8_t val)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = reg;
+	priv->spi_tx_buf[1] = val;
+	dev_dbg(&spi->dev, "hi3110_write: %02X, %02X\n", reg, val);
+
+	hi3110_spi_trans(spi, 2);
+}
+
+static void hi3110_hw_tx_frame(struct spi_device *spi, u8 *buf, int len)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = HI3110_WRITE_FIFO;
+	memcpy(priv->spi_tx_buf + 1, buf, len);
+	hi3110_spi_trans(spi, len + 1);
+}
+
+static void hi3110_hw_tx(struct spi_device *spi, struct can_frame *frame)
+{
+	u8 buf[TX_EXT_BUF_LEN];
+
+	buf[HI3110_FIFO_TAG_OFF] = 0;
+
+	if (frame->can_id & CAN_EFF_FLAG) {
+		/* Extended frame */
+		buf[HI3110_FIFO_ID_OFF] = (frame->can_id & CAN_EFF_MASK) >> 21;
+		buf[HI3110_FIFO_ID_OFF + 1] =
+			((((frame->can_id & CAN_EFF_MASK) >> 18) & 0x07) << 5) |
+			0x18 | /* Recessive SRR and IDE */
+			(((frame->can_id & CAN_EFF_MASK) >> 15) & 0x07);
+		buf[HI3110_FIFO_ID_OFF + 2] =
+			(frame->can_id & CAN_EFF_MASK) >> 7;
+		buf[HI3110_FIFO_ID_OFF + 3] =
+			((frame->can_id & CAN_EFF_MASK) << 1) |
+			((frame->can_id & CAN_RTR_FLAG) ? 1 : 0);
+
+		buf[HI3110_FIFO_EXT_DLC_OFF] = frame->can_dlc;
+
+		memcpy(buf + HI3110_FIFO_EXT_DATA_OFF,
+		       frame->data, frame->can_dlc);
+
+		hi3110_hw_tx_frame(spi, buf, TX_EXT_BUF_LEN -
+				   (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
+	} else {
+		/* Standard frame */
+		buf[HI3110_FIFO_ID_OFF] =   (frame->can_id & CAN_SFF_MASK) >> 3;
+		buf[HI3110_FIFO_ID_OFF + 1] =
+			((frame->can_id & CAN_SFF_MASK) << 5) |
+			((frame->can_id & CAN_RTR_FLAG) ? (1 << 4) : 0);
+
+		buf[HI3110_FIFO_STD_DLC_OFF] = frame->can_dlc;
+
+		memcpy(buf + HI3110_FIFO_STD_DATA_OFF,
+		       frame->data, frame->can_dlc);
+
+		hi3110_hw_tx_frame(spi, buf, TX_STD_BUF_LEN -
+				   (CAN_FRAME_MAX_DATA_LEN - frame->can_dlc));
+	}
+}
+
+static void hi3110_hw_rx_frame(struct spi_device *spi, u8 *buf)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	priv->spi_tx_buf[0] = HI3110_READ_FIFO_WOTIME;
+	hi3110_spi_trans(spi, RX_BUF_LEN);
+	memcpy(buf, priv->spi_rx_buf + 1, RX_BUF_LEN - 1);
+}
+
+static void hi3110_hw_rx(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct sk_buff *skb;
+	struct can_frame *frame;
+	u8 buf[RX_BUF_LEN - 1];
+
+	skb = alloc_can_skb(priv->net, &frame);
+	if (!skb) {
+		dev_err(&spi->dev, "cannot allocate RX skb\n");
+		priv->net->stats.rx_dropped++;
+		return;
+	}
+
+	hi3110_hw_rx_frame(spi, buf);
+	if (buf[HI3110_FIFO_WOTIME_TAG_OFF] & HI3110_FIFO_WOTIME_TAG_IDE) {
+		/* IDE is recessive (1), indicating extended 29-bit frame */
+		frame->can_id = CAN_EFF_FLAG;
+		frame->can_id |=
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF] << 21) |
+		 (((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5) << 18) |
+		 ((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0x07) << 15) |
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF + 2] << 7) |
+		 (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] >> 1);
+	} else {
+		/* IDE is dominant (0), frame indicating standard 11-bit */
+		frame->can_id =
+			(buf[HI3110_FIFO_WOTIME_ID_OFF] << 3) |
+			((buf[HI3110_FIFO_WOTIME_ID_OFF + 1] & 0xE0) >> 5);
+	}
+
+	if (buf[HI3110_FIFO_WOTIME_ID_OFF + 3] & HI3110_FIFO_WOTIME_ID_RTR) {
+		/* RTR is recessive (1), indicating remote request frame */
+		frame->can_id |= CAN_RTR_FLAG;
+	}
+
+	/* Data length */
+	frame->can_dlc = get_can_dlc(buf[HI3110_FIFO_WOTIME_DLC_OFF] & 0x0F);
+	memcpy(frame->data, buf + HI3110_FIFO_WOTIME_DAT_OFF, frame->can_dlc);
+
+	priv->net->stats.rx_packets++;
+	priv->net->stats.rx_bytes += frame->can_dlc;
+
+	can_led_event(priv->net, CAN_LED_EVENT_RX);
+
+	netif_rx_ni(skb);
+}
+
+static void hi3110_hw_sleep(struct spi_device *spi)
+{
+	hi3110_write(spi, HI3110_WRITE_CTRL0, HI3110_CTRL0_SLEEP_MODE);
+}
+
+static netdev_tx_t hi3110_hard_start_xmit(struct sk_buff *skb,
+					  struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	if (priv->tx_skb || priv->tx_len) {
+		dev_warn(&spi->dev, "hard_xmit called while tx busy\n");
+		return NETDEV_TX_BUSY;
+	}
+
+	if (can_dropped_invalid_skb(net, skb))
+		return NETDEV_TX_OK;
+
+	netif_stop_queue(net);
+	priv->tx_skb = skb;
+	queue_work(priv->wq, &priv->tx_work);
+
+	return NETDEV_TX_OK;
+}
+
+static int hi3110_do_set_mode(struct net_device *net, enum can_mode mode)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+
+	switch (mode) {
+	case CAN_MODE_START:
+		hi3110_clean(net);
+		/* We have to delay work since SPI I/O may sleep */
+		priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		priv->restart_tx = 1;
+		if (priv->can.restart_ms == 0)
+			priv->after_suspend = AFTER_SUSPEND_RESTART;
+		queue_work(priv->wq, &priv->restart_work);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int hi3110_set_normal_mode(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	u8 reg;
+
+	hi3110_write(spi, HI3110_WRITE_INTE, HI3110_INT_BUSERR |
+		     HI3110_INT_RXFIFO | HI3110_INT_TXCPLT);
+
+	/* Enable TX */
+	hi3110_write(spi, HI3110_WRITE_CTRL1, HI3110_CTRL1_TXEN);
+
+	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+		/* Put device into loopback mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_LOOPBACK_MODE);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+		/* Put device into listen-only mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_MONITOR_MODE);
+	} else {
+		/* Put device into normal mode */
+		hi3110_write(spi, HI3110_WRITE_CTRL0,
+			     HI3110_CTRL0_NORMAL_MODE);
+
+		/* Wait for the device to enter normal mode */
+		mdelay(HI3110_OST_DELAY_MS);
+		reg = hi3110_read(spi, HI3110_READ_CTRL0);
+		if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_NORMAL_MODE)
+			return -EBUSY;
+	}
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+	return 0;
+}
+
+static int hi3110_do_set_bittiming(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct can_bittiming *bt = &priv->can.bittiming;
+	struct spi_device *spi = priv->spi;
+
+	hi3110_write(spi, HI3110_WRITE_BTR0,
+		     ((bt->sjw - 1) << HI3110_BTR0_SJW_SHIFT) |
+		     ((bt->brp - 1) << HI3110_BTR0_BRP_SHIFT));
+
+	hi3110_write(spi, HI3110_WRITE_BTR1,
+		     (priv->can.ctrlmode &
+		     CAN_CTRLMODE_3_SAMPLES ?
+		     HI3110_BTR1_SAMP_3PERBIT : HI3110_BTR1_SAMP_1PERBIT) |
+		     ((bt->phase_seg1 + bt->prop_seg - 1)
+		     << HI3110_BTR1_TSEG1_SHIFT) |
+		     ((bt->phase_seg2 - 1) << HI3110_BTR1_TSEG2_SHIFT));
+
+	dev_dbg(&spi->dev, "BT: 0x%02x 0x%02x\n",
+		hi3110_read(spi, HI3110_READ_BTR0),
+		hi3110_read(spi, HI3110_READ_BTR1));
+
+	return 0;
+}
+
+static int hi3110_setup(struct net_device *net, struct hi3110_priv *priv,
+			struct spi_device *spi)
+{
+	hi3110_do_set_bittiming(net);
+	return 0;
+}
+
+static int hi3110_hw_reset(struct spi_device *spi)
+{
+	u8 reg;
+	int ret;
+
+	/* Wait for oscillator startup timer after power up */
+	mdelay(HI3110_OST_DELAY_MS);
+
+	ret = hi3110_cmd(spi, HI3110_MASTER_RESET);
+	if (ret)
+		return ret;
+
+	/* Wait for oscillator startup timer after reset */
+	mdelay(HI3110_OST_DELAY_MS);
+
+	reg = hi3110_read(spi, HI3110_READ_CTRL0);
+	if ((reg & HI3110_CTRL0_MODE_MASK) != HI3110_CTRL0_INIT_MODE)
+		return -ENODEV;
+
+	/* As per the datasheet it appears the error flags are
+	 * not cleared on reset. Explicitly clear them by performing a read
+	 */
+	hi3110_read(spi, HI3110_READ_ERR);
+
+	return 0;
+}
+
+static int hi3110_hw_probe(struct spi_device *spi)
+{
+	u8 statf;
+
+	hi3110_hw_reset(spi);
+
+	/* Confirm correct operation by checking against reset values
+	 * in datasheet
+	 */
+	statf = hi3110_read(spi, HI3110_READ_STATF);
+
+	dev_dbg(&spi->dev, "statf: %02X\n", statf);
+
+	if (statf != 0x82)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int hi3110_power_enable(struct regulator *reg, int enable)
+{
+	if (IS_ERR_OR_NULL(reg))
+		return 0;
+
+	if (enable)
+		return regulator_enable(reg);
+	else
+		return regulator_disable(reg);
+}
+
+static void hi3110_open_clean(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	free_irq(spi->irq, priv);
+	hi3110_hw_sleep(spi);
+	hi3110_power_enable(priv->transceiver, 0);
+	close_candev(net);
+}
+
+static int hi3110_stop(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+
+	close_candev(net);
+
+	priv->force_quit = 1;
+	free_irq(spi->irq, priv);
+	destroy_workqueue(priv->wq);
+	priv->wq = NULL;
+
+	mutex_lock(&priv->hi3110_lock);
+
+	/* Disable transmit, interrupts and clear flags */
+	hi3110_write(spi, HI3110_WRITE_CTRL1, 0x0);
+	hi3110_write(spi, HI3110_WRITE_INTE, 0x0);
+	hi3110_read(spi, HI3110_READ_INTF);
+
+	hi3110_clean(net);
+
+	hi3110_hw_sleep(spi);
+
+	hi3110_power_enable(priv->transceiver, 0);
+
+	priv->can.state = CAN_STATE_STOPPED;
+
+	mutex_unlock(&priv->hi3110_lock);
+
+	can_led_event(net, CAN_LED_EVENT_STOP);
+
+	return 0;
+}
+
+static void hi3110_error_skb(struct net_device *net, int can_id,
+			     int data1, int data2)
+{
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	skb = alloc_can_err_skb(net, &frame);
+	if (skb) {
+		frame->can_id |= can_id;
+		frame->data[1] = data1;
+		frame->data[2] = data2;
+		netif_rx_ni(skb);
+	} else {
+		netdev_err(net, "cannot allocate error skb\n");
+	}
+}
+
+static void hi3110_tx_work_handler(struct work_struct *ws)
+{
+	struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
+						 tx_work);
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+	struct can_frame *frame;
+
+	mutex_lock(&priv->hi3110_lock);
+	if (priv->tx_skb) {
+		if (priv->can.state == CAN_STATE_BUS_OFF) {
+			hi3110_clean(net);
+		} else {
+			frame = (struct can_frame *)priv->tx_skb->data;
+
+			if (frame->can_dlc > CAN_FRAME_MAX_DATA_LEN)
+				frame->can_dlc = CAN_FRAME_MAX_DATA_LEN;
+			hi3110_hw_tx(spi, frame);
+			priv->tx_len = 1 + frame->can_dlc;
+			can_put_echo_skb(priv->tx_skb, net, 0);
+			priv->tx_skb = NULL;
+		}
+	}
+	mutex_unlock(&priv->hi3110_lock);
+}
+
+static void hi3110_restart_work_handler(struct work_struct *ws)
+{
+	struct hi3110_priv *priv = container_of(ws, struct hi3110_priv,
+						 restart_work);
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+
+	mutex_lock(&priv->hi3110_lock);
+	if (priv->after_suspend) {
+		hi3110_hw_reset(spi);
+		hi3110_setup(net, priv, spi);
+		if (priv->after_suspend & AFTER_SUSPEND_RESTART) {
+			hi3110_set_normal_mode(spi);
+		} else if (priv->after_suspend & AFTER_SUSPEND_UP) {
+			netif_device_attach(net);
+			hi3110_clean(net);
+			hi3110_set_normal_mode(spi);
+			netif_wake_queue(net);
+		} else {
+			hi3110_hw_sleep(spi);
+		}
+		priv->after_suspend = 0;
+		priv->force_quit = 0;
+	}
+
+	if (priv->restart_tx) {
+		priv->restart_tx = 0;
+		hi3110_clean(net);
+		netif_wake_queue(net);
+		hi3110_error_skb(net, CAN_ERR_RESTARTED, 0, 0);
+	}
+	mutex_unlock(&priv->hi3110_lock);
+}
+
+static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
+{
+	struct hi3110_priv *priv = dev_id;
+	struct spi_device *spi = priv->spi;
+	struct net_device *net = priv->net;
+
+	mutex_lock(&priv->hi3110_lock);
+
+	while (!priv->force_quit) {
+		enum can_state new_state;
+		u8 intf;
+		u8 eflag;
+		int can_id = 0, data1 = 0, data2 = 0;
+
+		while (!(HI3110_STAT_RXFMTY &
+			hi3110_read(spi, HI3110_READ_STATF))) {
+			hi3110_hw_rx(spi);
+		};
+
+		intf = hi3110_read(spi, HI3110_READ_INTF);
+		eflag = hi3110_read(spi, HI3110_READ_ERR);
+		/* Update can state */
+		if (eflag & HI3110_ERR_BUSOFF) {
+			new_state = CAN_STATE_BUS_OFF;
+			can_id |= CAN_ERR_BUSOFF;
+		} else if (eflag & HI3110_ERR_TXERRP) {
+			new_state = CAN_STATE_ERROR_PASSIVE;
+			can_id |= CAN_ERR_CRTL;
+			data1 |= CAN_ERR_CRTL_TX_PASSIVE;
+		} else if (eflag & HI3110_ERR_RXERRP) {
+			new_state = CAN_STATE_ERROR_PASSIVE;
+			can_id |= CAN_ERR_CRTL;
+			data1 |= CAN_ERR_CRTL_RX_PASSIVE;
+		} else {
+			new_state = CAN_STATE_ERROR_ACTIVE;
+		}
+
+		/* Check for protocol errors */
+		if (eflag & HI3110_ERR_PROTOCOL_MASK) {
+			can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+			priv->can.can_stats.bus_error++;
+			priv->net->stats.rx_errors++;
+			if (eflag & HI3110_ERR_BITERR)
+				data2 |= CAN_ERR_PROT_BIT;
+			else if (eflag & HI3110_ERR_FRMERR)
+				data2 |= CAN_ERR_PROT_FORM;
+			else if (eflag & HI3110_ERR_STUFERR)
+				data2 |= CAN_ERR_PROT_STUFF;
+			else
+				data2 |= CAN_ERR_PROT_UNSPEC;
+		}
+
+		/* Update can state statistics */
+		switch (priv->can.state) {
+		case CAN_STATE_ERROR_ACTIVE:
+			if (new_state >= CAN_STATE_ERROR_WARNING &&
+			    new_state <= CAN_STATE_BUS_OFF)
+				priv->can.can_stats.error_warning++;
+		/* fallthrough */
+		case CAN_STATE_ERROR_WARNING:
+			if (new_state >= CAN_STATE_ERROR_PASSIVE &&
+			    new_state <= CAN_STATE_BUS_OFF)
+				priv->can.can_stats.error_passive++;
+			break;
+		default:
+			break;
+		}
+		priv->can.state = new_state;
+
+		if (intf & HI3110_INT_BUSERR) {
+			/* Note: HI3110 Does report overflow errors */
+			hi3110_error_skb(net, can_id, data1, data2);
+		}
+
+		if (priv->can.state == CAN_STATE_BUS_OFF) {
+			if (priv->can.restart_ms == 0) {
+				priv->force_quit = 1;
+				priv->can.can_stats.bus_off++;
+				can_bus_off(net);
+				hi3110_hw_sleep(spi);
+				break;
+			}
+		}
+
+		if (intf == 0)
+			break;
+
+		if (intf & HI3110_INT_TXCPLT) {
+			net->stats.tx_packets++;
+			net->stats.tx_bytes += priv->tx_len - 1;
+			can_led_event(net, CAN_LED_EVENT_TX);
+			if (priv->tx_len) {
+				can_get_echo_skb(net, 0);
+				priv->tx_len = 0;
+			}
+			netif_wake_queue(net);
+		}
+	}
+	mutex_unlock(&priv->hi3110_lock);
+	return IRQ_HANDLED;
+}
+
+static int hi3110_open(struct net_device *net)
+{
+	struct hi3110_priv *priv = netdev_priv(net);
+	struct spi_device *spi = priv->spi;
+	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING;
+	int ret;
+
+	ret = open_candev(net);
+	if (ret) {
+		dev_err(&spi->dev, "unable to set initial baudrate!\n");
+		return ret;
+	}
+
+	mutex_lock(&priv->hi3110_lock);
+	hi3110_power_enable(priv->transceiver, 1);
+
+	priv->force_quit = 0;
+	priv->tx_skb = NULL;
+	priv->tx_len = 0;
+
+	ret = request_threaded_irq(spi->irq, NULL, hi3110_can_ist,
+				   flags, DEVICE_NAME, priv);
+	if (ret) {
+		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
+		hi3110_power_enable(priv->transceiver, 0);
+		close_candev(net);
+		goto open_unlock;
+	}
+
+	priv->wq = alloc_workqueue("hi3110_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM,
+			   0);
+	INIT_WORK(&priv->tx_work, hi3110_tx_work_handler);
+	INIT_WORK(&priv->restart_work, hi3110_restart_work_handler);
+
+	ret = hi3110_hw_reset(spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	ret = hi3110_setup(net, priv, spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	ret = hi3110_set_normal_mode(spi);
+	if (ret) {
+		hi3110_open_clean(net);
+		goto open_unlock;
+	}
+	can_led_event(net, CAN_LED_EVENT_OPEN);
+	netif_wake_queue(net);
+
+open_unlock:
+	mutex_unlock(&priv->hi3110_lock);
+	return ret;
+}
+
+static const struct net_device_ops hi3110_netdev_ops = {
+	.ndo_open = hi3110_open,
+	.ndo_stop = hi3110_stop,
+	.ndo_start_xmit = hi3110_hard_start_xmit,
+};
+
+static const struct of_device_id hi3110_of_match[] = {
+	{
+		.compatible	= "holt,hi3110",
+		.data		= (void *)CAN_HI3110_HI3110,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, hi3110_of_match);
+
+static const struct spi_device_id hi3110_id_table[] = {
+	{
+		.name		= "hi3110",
+		.driver_data	= (kernel_ulong_t)CAN_HI3110_HI3110,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, hi3110_id_table);
+
+static int hi3110_can_probe(struct spi_device *spi)
+{
+	const struct of_device_id *of_id = of_match_device(hi3110_of_match,
+							   &spi->dev);
+	struct net_device *net;
+	struct hi3110_priv *priv;
+	struct clk *clk;
+	int freq, ret;
+
+	clk = devm_clk_get(&spi->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&spi->dev, "no CAN clock source defined\n");
+		return PTR_ERR(clk);
+	}
+	freq = clk_get_rate(clk);
+
+	/* Sanity check */
+	if (freq > 40000000)
+		return -ERANGE;
+
+	/* Allocate can/net device */
+	net = alloc_candev(sizeof(struct hi3110_priv), TX_ECHO_SKB_MAX);
+	if (!net)
+		return -ENOMEM;
+
+	if (!IS_ERR(clk)) {
+		ret = clk_prepare_enable(clk);
+		if (ret)
+			goto out_free;
+	}
+
+	net->netdev_ops = &hi3110_netdev_ops;
+	net->flags |= IFF_ECHO;
+
+	priv = netdev_priv(net);
+	priv->can.bittiming_const = &hi3110_bittiming_const;
+	priv->can.do_set_mode = hi3110_do_set_mode;
+	priv->can.clock.freq = freq / 2;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
+		CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
+	if (of_id)
+		priv->model = (enum hi3110_model)of_id->data;
+	else
+		priv->model = spi_get_device_id(spi)->driver_data;
+	priv->net = net;
+	priv->clk = clk;
+
+	spi_set_drvdata(spi, priv);
+
+	/* Configure the SPI bus */
+	spi->bits_per_word = 8;
+	ret = spi_setup(spi);
+	if (ret)
+		goto out_clk;
+
+	priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
+	priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
+	if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
+	    (PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
+		ret = -EPROBE_DEFER;
+		goto out_clk;
+	}
+
+	ret = hi3110_power_enable(priv->power, 1);
+	if (ret)
+		goto out_clk;
+
+	priv->spi = spi;
+	mutex_init(&priv->hi3110_lock);
+
+	/* If requested, allocate DMA buffers */
+	if (hi3110_enable_dma) {
+		spi->dev.coherent_dma_mask = ~0;
+
+		/* Minimum coherent DMA allocation is PAGE_SIZE, so allocate
+		 * that much and share it between Tx and Rx DMA buffers.
+		 */
+		priv->spi_tx_buf = dmam_alloc_coherent(&spi->dev,
+						      PAGE_SIZE,
+						      &priv->spi_tx_dma,
+						      GFP_DMA);
+
+		if (priv->spi_tx_buf) {
+			priv->spi_rx_buf = (priv->spi_tx_buf + (PAGE_SIZE / 2));
+			priv->spi_rx_dma = (dma_addr_t)(priv->spi_tx_dma +
+							(PAGE_SIZE / 2));
+		} else {
+			/* Fall back to non-DMA */
+			hi3110_enable_dma = 0;
+		}
+	}
+
+	/* Allocate non-DMA buffers */
+	if (!hi3110_enable_dma) {
+		priv->spi_tx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
+				GFP_KERNEL);
+		if (!priv->spi_tx_buf) {
+			ret = -ENOMEM;
+			goto error_probe;
+		}
+		priv->spi_rx_buf = devm_kzalloc(&spi->dev, RX_BUF_LEN,
+				GFP_KERNEL);
+
+		if (!priv->spi_rx_buf) {
+			ret = -ENOMEM;
+			goto error_probe;
+		}
+	}
+
+	SET_NETDEV_DEV(net, &spi->dev);
+
+	ret = hi3110_hw_probe(spi);
+	if (ret) {
+		if (ret == -ENODEV)
+			dev_err(&spi->dev, "Cannot initialize %x. Wrong wiring?\n",
+				priv->model);
+		goto error_probe;
+	}
+	hi3110_hw_sleep(spi);
+
+	ret = register_candev(net);
+	if (ret)
+		goto error_probe;
+
+	devm_can_led_init(net);
+	netdev_info(net, "%x successfully initialized.\n", priv->model);
+
+	return 0;
+
+error_probe:
+	hi3110_power_enable(priv->power, 0);
+
+out_clk:
+	if (!IS_ERR(clk))
+		clk_disable_unprepare(clk);
+
+out_free:
+	free_candev(net);
+
+	dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
+	return ret;
+}
+
+static int hi3110_can_remove(struct spi_device *spi)
+{
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct net_device *net = priv->net;
+
+	unregister_candev(net);
+
+	hi3110_power_enable(priv->power, 0);
+
+	if (!IS_ERR(priv->clk))
+		clk_disable_unprepare(priv->clk);
+
+	free_candev(net);
+
+	return 0;
+}
+
+static int __maybe_unused hi3110_can_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+	struct net_device *net = priv->net;
+
+	priv->force_quit = 1;
+	disable_irq(spi->irq);
+
+	/* Note: at this point neither IST nor workqueues are running.
+	 * open/stop cannot be called anyway so locking is not needed
+	 */
+	if (netif_running(net)) {
+		netif_device_detach(net);
+
+		hi3110_hw_sleep(spi);
+		hi3110_power_enable(priv->transceiver, 0);
+		priv->after_suspend = AFTER_SUSPEND_UP;
+	} else {
+		priv->after_suspend = AFTER_SUSPEND_DOWN;
+	}
+
+	if (!IS_ERR_OR_NULL(priv->power)) {
+		regulator_disable(priv->power);
+		priv->after_suspend |= AFTER_SUSPEND_POWER;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused hi3110_can_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct hi3110_priv *priv = spi_get_drvdata(spi);
+
+	if (priv->after_suspend & AFTER_SUSPEND_POWER)
+		hi3110_power_enable(priv->power, 1);
+
+	if (priv->after_suspend & AFTER_SUSPEND_UP) {
+		hi3110_power_enable(priv->transceiver, 1);
+		queue_work(priv->wq, &priv->restart_work);
+	} else {
+		priv->after_suspend = 0;
+	}
+
+	priv->force_quit = 0;
+	enable_irq(spi->irq);
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(hi3110_can_pm_ops, hi3110_can_suspend,
+	hi3110_can_resume);
+
+static struct spi_driver hi3110_can_driver = {
+	.driver = {
+		.name = DEVICE_NAME,
+		.of_match_table = hi3110_of_match,
+		.pm = &hi3110_can_pm_ops,
+	},
+	.id_table = hi3110_id_table,
+	.probe = hi3110_can_probe,
+	.remove = hi3110_can_remove,
+};
+
+module_spi_driver(hi3110_can_driver);
+
+MODULE_AUTHOR("Akshay Bhat <akshay.bhat@timesys.com>");
+MODULE_AUTHOR("Casey Fitzpatrick <casey.fitzpatrick@timesys.com>");
+MODULE_DESCRIPTION("Holt HI-3110 CAN driver");
+MODULE_LICENSE("GPL v2");
-- 
2.8.1

^ permalink raw reply related

* [PATCH tip/core/rcu 7/7] bug: Avoid Kconfig warning for BUG_ON_DATA_CORRUPTION
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Arnd Bergmann, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Arnd Bergmann <arnd@arndb.de>

The CONFIG_DEBUG_LIST option is normally meant for kernel developers
rather than production machines and is guarded by CONFIG_DEBUG_KERNEL.

In contrast, the newly added CONFIG_BUG_ON_DATA_CORRUPTION is meant
for security hardening and may be used on systems that intentionally
do not enable CONFIG_DEBUG_KERNEL. In this configuration, we get
a warning from Kconfig about the mismatched dependencies:

warning: (BUG_ON_DATA_CORRUPTION) selects DEBUG_LIST which has unmet direct dependencies (DEBUG_KERNEL)

This annotates the DEBUG_LIST option to be selectable by
BUG_ON_DATA_CORRUPTION when DEBUG_KERNEL is disabled.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Fixes: 40cd725cfc7f ("bug: Provide toggle for BUG on data corruption")
Acked-by: Rik van Riel <riel@redhat.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
 lib/Kconfig.debug | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index afa30fd52583..0c6366b77062 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1214,7 +1214,7 @@ config DEBUG_BUGVERBOSE
 
 config DEBUG_LIST
 	bool "Debug linked list manipulation"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL || BUG_ON_DATA_CORRUPTION
 	help
 	  Enable this to turn on extended checks in the linked-list
 	  walking routines.
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 4/7] bug: Provide toggle for BUG on data corruption
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

The kernel checks for cases of data structure corruption under some
CONFIGs (e.g. CONFIG_DEBUG_LIST). When corruption is detected, some
systems may want to BUG() immediately instead of letting the system run
with known corruption.  Usually these kinds of manipulation primitives can
be used by security flaws to gain arbitrary memory write control. This
provides a new config CONFIG_BUG_ON_DATA_CORRUPTION and a corresponding
macro CHECK_DATA_CORRUPTION for handling these situations. Notably, even
if not BUGing, the kernel should not continue processing the corrupted
structure.

This is inspired by similar hardening by Syed Rameez Mustafa in MSM
kernels, and in PaX and Grsecurity, which is likely in response to earlier
removal of the BUG calls in commit 924d9addb9b1 ("list debugging: use
WARN() instead of BUG()").

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 include/linux/bug.h | 17 ++++++++++++++++
 lib/Kconfig.debug   | 10 ++++++++++
 lib/list_debug.c    | 57 +++++++++++++++++++++--------------------------------
 3 files changed, 49 insertions(+), 35 deletions(-)

diff --git a/include/linux/bug.h b/include/linux/bug.h
index 292d6a10b0c2..baff2e8fc8a8 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -121,4 +121,21 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
 }
 
 #endif	/* CONFIG_GENERIC_BUG */
+
+/*
+ * Since detected data corruption should stop operation on the affected
+ * structures, this returns false if the corruption condition is found.
+ */
+#define CHECK_DATA_CORRUPTION(condition, fmt, ...)			 \
+	do {								 \
+		if (unlikely(condition)) {				 \
+			if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
+				pr_err(fmt, ##__VA_ARGS__);		 \
+				BUG();					 \
+			} else						 \
+				WARN(1, fmt, ##__VA_ARGS__);		 \
+			return false;					 \
+		}							 \
+	} while (0)
+
 #endif	/* _LINUX_BUG_H */
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 33bc56cf60d7..07a6fac930c5 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1960,6 +1960,16 @@ config TEST_STATIC_KEYS
 
 	  If unsure, say N.
 
+config BUG_ON_DATA_CORRUPTION
+	bool "Trigger a BUG when data corruption is detected"
+	select CONFIG_DEBUG_LIST
+	help
+	  Select this option if the kernel should BUG when it encounters
+	  data corruption in kernel memory structures when they get checked
+	  for validity.
+
+	  If unsure, say N.
+
 source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 276565fca2a6..7f7bfa55eb6d 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -20,21 +20,16 @@
 bool __list_add_valid(struct list_head *new, struct list_head *prev,
 		      struct list_head *next)
 {
-	if (unlikely(next->prev != prev)) {
-		WARN(1, "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
-			prev, next->prev, next);
-		return false;
-	}
-	if (unlikely(prev->next != next)) {
-		WARN(1, "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
-			next, prev->next, prev);
-		return false;
-	}
-	if (unlikely(new == prev || new == next)) {
-		WARN(1, "list_add double add: new=%p, prev=%p, next=%p.\n",
-			new, prev, next);
-		return false;
-	}
+	CHECK_DATA_CORRUPTION(next->prev != prev,
+		"list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
+		prev, next->prev, next);
+	CHECK_DATA_CORRUPTION(prev->next != next,
+		"list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
+		next, prev->next, prev);
+	CHECK_DATA_CORRUPTION(new == prev || new == next,
+		"list_add double add: new=%p, prev=%p, next=%p.\n",
+		new, prev, next);
+
 	return true;
 }
 EXPORT_SYMBOL(__list_add_valid);
@@ -46,26 +41,18 @@ bool __list_del_entry_valid(struct list_head *entry)
 	prev = entry->prev;
 	next = entry->next;
 
-	if (unlikely(next == LIST_POISON1)) {
-		WARN(1, "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
-			entry, LIST_POISON1);
-		return false;
-	}
-	if (unlikely(prev == LIST_POISON2)) {
-		WARN(1, "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
-			entry, LIST_POISON2);
-		return false;
-	}
-	if (unlikely(prev->next != entry)) {
-		WARN(1, "list_del corruption. prev->next should be %p, but was %p\n",
-			entry, prev->next);
-		return false;
-	}
-	if (unlikely(next->prev != entry)) {
-		WARN(1, "list_del corruption. next->prev should be %p, but was %p\n",
-			entry, next->prev);
-		return false;
-	}
+	CHECK_DATA_CORRUPTION(next == LIST_POISON1,
+		"list_del corruption, %p->next is LIST_POISON1 (%p)\n",
+		entry, LIST_POISON1);
+	CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
+		"list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
+		entry, LIST_POISON2);
+	CHECK_DATA_CORRUPTION(prev->next != entry,
+		"list_del corruption. prev->next should be %p, but was %p\n",
+		entry, prev->next);
+	CHECK_DATA_CORRUPTION(next->prev != entry,
+		"list_del corruption. next->prev should be %p, but was %p\n",
+		entry, next->prev);
 	return true;
 
 }
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 5/7] lkdtm: Add tests for struct list corruption
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Kees Cook, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Kees Cook <keescook@chromium.org>

When building under CONFIG_DEBUG_LIST, list addition and removal will be
sanity-checked. This validates that the check is working as expected by
setting up classic corruption attacks against list manipulations, available
with the new lkdtm tests CORRUPT_LIST_ADD and CORRUPT_LIST_DEL.

Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Rik van Riel <riel@redhat.com>
---
 drivers/misc/lkdtm.h      |  2 ++
 drivers/misc/lkdtm_bugs.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/misc/lkdtm_core.c |  2 ++
 3 files changed, 72 insertions(+)

diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index fdf954c2107f..cfa1039c62e7 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -21,6 +21,8 @@ void lkdtm_SPINLOCKUP(void);
 void lkdtm_HUNG_TASK(void);
 void lkdtm_ATOMIC_UNDERFLOW(void);
 void lkdtm_ATOMIC_OVERFLOW(void);
+void lkdtm_CORRUPT_LIST_ADD(void);
+void lkdtm_CORRUPT_LIST_DEL(void);
 
 /* lkdtm_heap.c */
 void lkdtm_OVERWRITE_ALLOCATION(void);
diff --git a/drivers/misc/lkdtm_bugs.c b/drivers/misc/lkdtm_bugs.c
index 182ae1894b32..f336206d4b1f 100644
--- a/drivers/misc/lkdtm_bugs.c
+++ b/drivers/misc/lkdtm_bugs.c
@@ -5,8 +5,13 @@
  * test source files.
  */
 #include "lkdtm.h"
+#include <linux/list.h>
 #include <linux/sched.h>
 
+struct lkdtm_list {
+	struct list_head node;
+};
+
 /*
  * Make sure our attempts to over run the kernel stack doesn't trigger
  * a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -146,3 +151,66 @@ void lkdtm_ATOMIC_OVERFLOW(void)
 	pr_info("attempting bad atomic overflow\n");
 	atomic_inc(&over);
 }
+
+void lkdtm_CORRUPT_LIST_ADD(void)
+{
+	/*
+	 * Initially, an empty list via LIST_HEAD:
+	 *	test_head.next = &test_head
+	 *	test_head.prev = &test_head
+	 */
+	LIST_HEAD(test_head);
+	struct lkdtm_list good, bad;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	pr_info("attempting good list addition\n");
+
+	/*
+	 * Adding to the list performs these actions:
+	 *	test_head.next->prev = &good.node
+	 *	good.node.next = test_head.next
+	 *	good.node.prev = test_head
+	 *	test_head.next = good.node
+	 */
+	list_add(&good.node, &test_head);
+
+	pr_info("attempting corrupted list addition\n");
+	/*
+	 * In simulating this "write what where" primitive, the "what" is
+	 * the address of &bad.node, and the "where" is the address held
+	 * by "redirection".
+	 */
+	test_head.next = redirection;
+	list_add(&bad.node, &test_head);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_add() corruption not detected!\n");
+}
+
+void lkdtm_CORRUPT_LIST_DEL(void)
+{
+	LIST_HEAD(test_head);
+	struct lkdtm_list item;
+	void *target[2] = { };
+	void *redirection = &target;
+
+	list_add(&item.node, &test_head);
+
+	pr_info("attempting good list removal\n");
+	list_del(&item.node);
+
+	pr_info("attempting corrupted list removal\n");
+	list_add(&item.node, &test_head);
+
+	/* As with the list_add() test above, this corrupts "next". */
+	item.node.next = redirection;
+	list_del(&item.node);
+
+	if (target[0] == NULL && target[1] == NULL)
+		pr_err("Overwrite did not happen, but no BUG?!\n");
+	else
+		pr_err("list_del() corruption not detected!\n");
+}
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index f9154b8d67f6..7eeb71a75549 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -197,6 +197,8 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(EXCEPTION),
 	CRASHTYPE(LOOP),
 	CRASHTYPE(OVERFLOW),
+	CRASHTYPE(CORRUPT_LIST_ADD),
+	CRASHTYPE(CORRUPT_LIST_DEL),
 	CRASHTYPE(CORRUPT_STACK),
 	CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
 	CRASHTYPE(OVERWRITE_ALLOCATION),
-- 
2.5.2

^ permalink raw reply related

* [PATCH tip/core/rcu 6/7] lib/Kconfig.debug: Fix typo in select statement
From: Paul E. McKenney @ 2016-11-14 17:55 UTC (permalink / raw)
  To: linux-kernel
  Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
	tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
	bobby.prani, Valentin Rothberg, Paul E. McKenney
In-Reply-To: <20161114175500.GA21637@linux.vnet.ibm.com>

From: Valentin Rothberg <valentinrothberg@gmail.com>

Commit 484f29c7430b3 ("bug: Provide toggle for BUG on data corruption")
added a Kconfig select statement on CONFIG_DEBUG_LIST, but the CONFIG_
prefix is only used in Make and C(PP) syntax.  Remove the CONFIG_ prefix
to correctly select the Kconfig option DEBUG_LIST.

Signed-off-by: Valentin Rothberg <valentinrothberg@gmail.com>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Acked-by: Kees Cook <keescook@chromium.org>
---
 lib/Kconfig.debug | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 07a6fac930c5..afa30fd52583 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1962,7 +1962,7 @@ config TEST_STATIC_KEYS
 
 config BUG_ON_DATA_CORRUPTION
 	bool "Trigger a BUG when data corruption is detected"
-	select CONFIG_DEBUG_LIST
+	select DEBUG_LIST
 	help
 	  Select this option if the kernel should BUG when it encounters
 	  data corruption in kernel memory structures when they get checked
-- 
2.5.2

^ permalink raw reply related

* Re: [SPDK] RoCE Version
From: Alex Bowden @ 2016-11-14 17:56 UTC (permalink / raw)
  To: spdk

[-- Attachment #1: Type: text/plain, Size: 723 bytes --]

No. It supports RoCE v1. It supports any RDMA interface that provides a verbs device to the userspace library libibverbs/librdmacm.

On Tue, Nov 8, 2016 at 12:35 PM, Kumaraparameshwaran Rathnavel <krath(a)cloudsimple.com<mailto:krath(a)cloudsimple.com>> wrote:
Hi All,

I think that NVMe userspace target is supported in all RDMA forms. Basically the RoCE version 1 & 2, iWARP. So the config file has Listen RDMA and a IP address. So does this mean that it does not support RoCE version 1? As RoCE version 1 is in Ethernet Layer.

Thanking You,
Param
_______________________________________________
SPDK mailing list
SPDK(a)lists.01.org<mailto:SPDK(a)lists.01.org>
https://lists.01.org/mailman/listinfo/spdk


[-- Attachment #2: attachment.html --]
[-- Type: text/html, Size: 1269 bytes --]

^ permalink raw reply

* [Buildroot] [PATCH] toolchain: Bump ARC tools to arc-2016.09-rc1
From: Vlad Zakharov @ 2016-11-14 17:56 UTC (permalink / raw)
  To: buildroot

As described at:
4520524ba055706236db9f00dd79f1b2e2e87fde
this commit continues a series of updates of ARC tools.
This time we're updating tools to arc-2016.09-rc1.

This update contains a lot of important fixes, e.g. it fixes:
http://autobuild.buildroot.net/results/4c7/4c77f33c842b37bf28cb931edf1b290e1bf4d93c//
http://autobuild.buildroot.net/results/902/902729a0b98675ad803939e3ecdcf230065a6012//
and other failures.

Other important change is that we also update gdb. Now we are
using gdb 7.12.

This version of gdb requires C++ toolchain support so we add
corresponding dependency to gdb Config.in file.

Signed-off-by: Vlad Zakharov <vzakhar@synopsys.com>
---
 package/binutils/Config.in.host                                         | 2 +-
 .../{arc-2016.09-eng015 => arc-2016.09-rc1}/0300-ld-makefile.patch      | 0
 .../0301-check-ldrunpath-length.patch                                   | 0
 .../0500-add-sysroot-fix-from-bug-3049.patch                            | 0
 .../0600-poison-system-directories.patch                                | 0
 package/binutils/binutils.hash                                          | 2 +-
 package/binutils/binutils.mk                                            | 2 +-
 package/gcc/Config.in.host                                              | 2 +-
 .../301-missing-execinfo_h.patch                                        | 0
 .../gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/860-cilk-wchar.patch    | 0
 .../940-uclinux-enable-threads.patch                                    | 0
 package/gcc/gcc.hash                                                    | 2 +-
 package/gdb/Config.in                                                   | 2 ++
 package/gdb/Config.in.host                                              | 2 +-
 package/gdb/gdb.hash                                                    | 2 +-
 15 files changed, 9 insertions(+), 7 deletions(-)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0300-ld-makefile.patch (100%)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0301-check-ldrunpath-length.patch (100%)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0500-add-sysroot-fix-from-bug-3049.patch (100%)
 rename package/binutils/{arc-2016.09-eng015 => arc-2016.09-rc1}/0600-poison-system-directories.patch (100%)
 rename package/gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/301-missing-execinfo_h.patch (100%)
 rename package/gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/860-cilk-wchar.patch (100%)
 rename package/gcc/{arc-2016.09-eng015 => arc-2016.09-rc1}/940-uclinux-enable-threads.patch (100%)

diff --git a/package/binutils/Config.in.host b/package/binutils/Config.in.host
index 3e0c357..af9339e 100644
--- a/package/binutils/Config.in.host
+++ b/package/binutils/Config.in.host
@@ -22,7 +22,7 @@ endchoice
 
 config BR2_BINUTILS_VERSION
 	string
-	default "arc-2016.09-eng015"	if BR2_arc
+	default "arc-2016.09-rc1"	if BR2_arc
 	default "2.25.1"	if BR2_BINUTILS_VERSION_2_25_X
 	default "2.26.1"	if BR2_BINUTILS_VERSION_2_26_X
 	default "2.27"		if BR2_BINUTILS_VERSION_2_27_X
diff --git a/package/binutils/arc-2016.09-eng015/0300-ld-makefile.patch b/package/binutils/arc-2016.09-rc1/0300-ld-makefile.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0300-ld-makefile.patch
rename to package/binutils/arc-2016.09-rc1/0300-ld-makefile.patch
diff --git a/package/binutils/arc-2016.09-eng015/0301-check-ldrunpath-length.patch b/package/binutils/arc-2016.09-rc1/0301-check-ldrunpath-length.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0301-check-ldrunpath-length.patch
rename to package/binutils/arc-2016.09-rc1/0301-check-ldrunpath-length.patch
diff --git a/package/binutils/arc-2016.09-eng015/0500-add-sysroot-fix-from-bug-3049.patch b/package/binutils/arc-2016.09-rc1/0500-add-sysroot-fix-from-bug-3049.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0500-add-sysroot-fix-from-bug-3049.patch
rename to package/binutils/arc-2016.09-rc1/0500-add-sysroot-fix-from-bug-3049.patch
diff --git a/package/binutils/arc-2016.09-eng015/0600-poison-system-directories.patch b/package/binutils/arc-2016.09-rc1/0600-poison-system-directories.patch
similarity index 100%
rename from package/binutils/arc-2016.09-eng015/0600-poison-system-directories.patch
rename to package/binutils/arc-2016.09-rc1/0600-poison-system-directories.patch
diff --git a/package/binutils/binutils.hash b/package/binutils/binutils.hash
index f41b39b..80ac9dd 100644
--- a/package/binutils/binutils.hash
+++ b/package/binutils/binutils.hash
@@ -5,4 +5,4 @@ sha512  9d9165609fd3b0f20d616f9891fc8e2b466eb13e2bfce40125e12427f8f201d20e2b8322
 sha512	cf276f84935312361a2ca077e04d0b469d23a3aed979d8ba5d92ea590904ffb2c2e7ed12cc842822bfc402836be86f479660cef3791aa62f3753d8a1a6f564cb  binutils-2.27.tar.bz2
 
 # Locally calculated (fetched from Github)
-sha512  f8cc7529fbe3cb52b666b92e1353063a8a36ea07fa8c5aa8359252f4222feaed15253b6a137033c74dabc0ae784daf8a7978e69ebdb8bf8cd6b8bb61c84bf181  binutils-arc-2016.09-eng015.tar.gz
+sha512  d0befdeb0a7b76efd1ad655fc062cde2aa67be7b26210c913ab2709e069d815c4ff2863ce7add1f6434da5a2f4faf1ce5a5bc3d0e64f3e04548a7479f24edcbc  binutils-arc-2016.09-rc1.tar.gz
diff --git a/package/binutils/binutils.mk b/package/binutils/binutils.mk
index ca481d2..61486a2 100644
--- a/package/binutils/binutils.mk
+++ b/package/binutils/binutils.mk
@@ -9,7 +9,7 @@
 BINUTILS_VERSION = $(call qstrip,$(BR2_BINUTILS_VERSION))
 ifeq ($(BINUTILS_VERSION),)
 ifeq ($(BR2_arc),y)
-BINUTILS_VERSION = arc-2016.09-eng015
+BINUTILS_VERSION = arc-2016.09-rc1
 else
 BINUTILS_VERSION = 2.25.1
 endif
diff --git a/package/gcc/Config.in.host b/package/gcc/Config.in.host
index 0a63e6a..d10798b 100644
--- a/package/gcc/Config.in.host
+++ b/package/gcc/Config.in.host
@@ -98,7 +98,7 @@ config BR2_GCC_VERSION
 	default "4.9.4"     if BR2_GCC_VERSION_4_9_X
 	default "5.4.0"     if BR2_GCC_VERSION_5_X
 	default "6.2.0"     if BR2_GCC_VERSION_6_X
-	default "arc-2016.09-eng015" if BR2_GCC_VERSION_ARC
+	default "arc-2016.09-rc1" if BR2_GCC_VERSION_ARC
 
 config BR2_EXTRA_GCC_CONFIG_OPTIONS
 	string "Additional gcc options"
diff --git a/package/gcc/arc-2016.09-eng015/301-missing-execinfo_h.patch b/package/gcc/arc-2016.09-rc1/301-missing-execinfo_h.patch
similarity index 100%
rename from package/gcc/arc-2016.09-eng015/301-missing-execinfo_h.patch
rename to package/gcc/arc-2016.09-rc1/301-missing-execinfo_h.patch
diff --git a/package/gcc/arc-2016.09-eng015/860-cilk-wchar.patch b/package/gcc/arc-2016.09-rc1/860-cilk-wchar.patch
similarity index 100%
rename from package/gcc/arc-2016.09-eng015/860-cilk-wchar.patch
rename to package/gcc/arc-2016.09-rc1/860-cilk-wchar.patch
diff --git a/package/gcc/arc-2016.09-eng015/940-uclinux-enable-threads.patch b/package/gcc/arc-2016.09-rc1/940-uclinux-enable-threads.patch
similarity index 100%
rename from package/gcc/arc-2016.09-eng015/940-uclinux-enable-threads.patch
rename to package/gcc/arc-2016.09-rc1/940-uclinux-enable-threads.patch
diff --git a/package/gcc/gcc.hash b/package/gcc/gcc.hash
index ce738ef..e5d96f4 100644
--- a/package/gcc/gcc.hash
+++ b/package/gcc/gcc.hash
@@ -12,4 +12,4 @@ sha512  2941cc950c8f2409a314df497631f9b0266211aa74746c1839c46e04f1c7c299afe2528d
 sha512  1e8b826a3d44b9d5899309894e20c03abeb352bf3d273b8ad63af814c0ee2911f1a83ce1cd4cdd2d1cb0b3e3c34e9b7ae1b2ab83dfc649ee817ab05247c76198  gcc-6.2.0.tar.bz2
 
 # Locally calculated (fetched from Github)
-sha512  9f365452f746ae91875d935c2ec5ed16cd11a2973f69bd23193fec9fc6b557e0dd66bb169e7efb7ec63fd78af36139005abcf5a5a1d89d6f49788b2ed7b334fb  gcc-arc-2016.09-eng015.tar.gz
+sha512  7029d7ae1316b9385880f32283aa6c4979b1257500bb21e3fb234475ecb20082f46b114d8b7022c75a8dcf0c0c7b6b02e9384b49dd3189adc3d454502b8b0c26  gcc-arc-2016.09-rc1.tar.gz
diff --git a/package/gdb/Config.in b/package/gdb/Config.in
index 809e02d..e025fe0 100644
--- a/package/gdb/Config.in
+++ b/package/gdb/Config.in
@@ -11,6 +11,8 @@ config BR2_PACKAGE_GDB
 		(!BR2_PACKAGE_GDB_DEBUGGER && !BR2_TOOLCHAIN_EXTERNAL_GDB_SERVER_COPY)
 	depends on BR2_TOOLCHAIN_HAS_THREADS && BR2_TOOLCHAIN_HAS_THREADS_DEBUG
 	depends on !BR2_nios2 && !BR2_bfin
+	# Since ARC gdb moved to 7.12 toolchain requires C++ support to build gdb.
+	depends on !BR2_arc || BR2_TOOLCHAIN_BUILDROOT_CXX
 	help
 	  GDB, the GNU Project debugger, allows you to see what is
 	  going on `inside' another program while it executes -- or
diff --git a/package/gdb/Config.in.host b/package/gdb/Config.in.host
index a36dc0f..b6eb41f 100644
--- a/package/gdb/Config.in.host
+++ b/package/gdb/Config.in.host
@@ -56,7 +56,7 @@ endif
 config BR2_GDB_VERSION
 	string
 	depends on BR2_PACKAGE_GDB || BR2_PACKAGE_HOST_GDB
-	default "arc-2016.03-gdb" if BR2_arc
+	default "arc-2016.09-rc1-gdb" if BR2_arc
 	default "6be65fb56ea6694a9260733a536a023a1e2d4d57" if BR2_microblaze
 	default "7.9.1"    if BR2_GDB_VERSION_7_9
 	default "7.10.1"   if BR2_GDB_VERSION_7_10 || !BR2_PACKAGE_HOST_GDB
diff --git a/package/gdb/gdb.hash b/package/gdb/gdb.hash
index 611a75c..8c0d51b 100644
--- a/package/gdb/gdb.hash
+++ b/package/gdb/gdb.hash
@@ -5,4 +5,4 @@ sha512  f80ec6c8a0f0b54c8b945666e875809174402b7e121efb378ebac931a91f9a1cc0048568
 
 # Locally calculated (fetched from Github)
 sha512  0a467091d4b01fbecabb4b8da1cb743025c70e7f4874a0b5c8fa2ec623569a39bde6762b91806de0be6e63711aeb6909715cfbe43860de73d8aec6159a9f10a7	gdb-6be65fb56ea6694a9260733a536a023a1e2d4d57.tar.gz
-sha512  1abef1357896c2b57cfa7f7414eedc49d0de26b54321c680c2d027b1a27ec453d421e7f89a5281336047542379fd4820685802059efbd32b87c5ccffbaf2bd16	gdb-arc-2016.03-gdb.tar.gz
+sha512  e6019ac0d6b1354943d3c06c84f353ba49fef105b07c1a04ad90cc5b65f91e38fe6c671e0c34a9541ee282d0f42cf24579c011a0469d19faaa4d00d64a17afe2	gdb-arc-2016.09-rc1-gdb.tar.gz
-- 
2.6.3

^ permalink raw reply related


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.