LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 13/13] vfio: powerpc/spapr: Enable Dynamic DMA windows
From: Alexey Kardashevskiy @ 2014-10-10 18:33 UTC (permalink / raw)
  To: Alex Williamson; +Cc: linuxppc-dev, Gavin Shan, kvm, linux-kernel
In-Reply-To: <1411509370.24563.35.camel@ul30vt.home>

On 09/23/2014 11:56 PM, Alex Williamson wrote:
> On Tue, 2014-09-23 at 13:01 +1000, Alexey Kardashevskiy wrote:
>> This defines and implements VFIO IOMMU API which lets the userspace
>> create and remove DMA windows.
>>
>> This updates VFIO_IOMMU_SPAPR_TCE_GET_INFO to return the number of
>> available windows and page mask.
>>
>> This adds VFIO_IOMMU_SPAPR_TCE_CREATE and VFIO_IOMMU_SPAPR_TCE_REMOVE
>> to allow the user space to create and remove window(s).
>>
>> The VFIO IOMMU driver does basic sanity checks and calls corresponding
>> SPAPR TCE functions. At the moment only IODA2 (POWER8 PCI host bridge)
>> implements them.
>>
>> This advertises VFIO_IOMMU_SPAPR_TCE_FLAG_DDW capability via
>> VFIO_IOMMU_SPAPR_TCE_GET_INFO.
>>
>> This calls platform DDW reset() callback when IOMMU is being disabled
>> to reset the DMA configuration to its original state.
>>
>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>> ---
>>  drivers/vfio/vfio_iommu_spapr_tce.c | 135 ++++++++++++++++++++++++++++++++++--
>>  include/uapi/linux/vfio.h           |  25 ++++++-
>>  2 files changed, 153 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
>> index 0dccbc4..b518891 100644
>> --- a/drivers/vfio/vfio_iommu_spapr_tce.c
>> +++ b/drivers/vfio/vfio_iommu_spapr_tce.c
>> @@ -190,18 +190,25 @@ static void tce_iommu_disable(struct tce_container *container)
>>  
>>  	container->enabled = false;
>>  
>> -	if (!container->grp || !current->mm)
>> +	if (!container->grp)
>>  		return;
>>  
>>  	data = iommu_group_get_iommudata(container->grp);
>>  	if (!data || !data->iommu_owner || !data->ops->get_table)
>>  		return;
>>  
>> -	tbl = data->ops->get_table(data, 0);
>> -	if (!tbl)
>> -		return;
>> +	if (current->mm) {
>> +		tbl = data->ops->get_table(data, 0);
>> +		if (tbl)
>> +			decrement_locked_vm(tbl);
>>  
>> -	decrement_locked_vm(tbl);
>> +		tbl = data->ops->get_table(data, 1);
>> +		if (tbl)
>> +			decrement_locked_vm(tbl);
>> +	}
>> +
>> +	if (data->ops->reset)
>> +		data->ops->reset(data);
>>  }
>>  
>>  static void *tce_iommu_open(unsigned long arg)
>> @@ -243,7 +250,7 @@ static long tce_iommu_ioctl(void *iommu_data,
>>  				 unsigned int cmd, unsigned long arg)
>>  {
>>  	struct tce_container *container = iommu_data;
>> -	unsigned long minsz;
>> +	unsigned long minsz, ddwsz;
>>  	long ret;
>>  
>>  	switch (cmd) {
>> @@ -288,6 +295,28 @@ static long tce_iommu_ioctl(void *iommu_data,
>>  		info.dma32_window_size = tbl->it_size << tbl->it_page_shift;
>>  		info.flags = 0;
>>  
>> +		ddwsz = offsetofend(struct vfio_iommu_spapr_tce_info,
>> +				page_size_mask);
>> +
>> +		if (info.argsz == ddwsz) {
> 
>> =
> 
>> +			if (data->ops->query && data->ops->create &&
>> +					data->ops->remove) {
>> +				info.flags |= VFIO_IOMMU_SPAPR_TCE_FLAG_DDW;
> 
> I think you want to set this flag regardless of whether the user has
> provided space for it.  A valid use model is to call with the minimum
> size and look at the flags to determine if it needs to be called again
> with a larger size.
> 
>> +
>> +				ret = data->ops->query(data,
>> +						&info.current_windows,
>> +						&info.windows_available,
>> +						&info.page_size_mask);
>> +				if (ret)
>> +					return ret;
>> +			} else {
>> +				info.current_windows = 0;
>> +				info.windows_available = 0;
>> +				info.page_size_mask = 0;
>> +			}
>> +			minsz = ddwsz;
> 
> It's not really any longer the min size, is it?
> 
>> +		}
>> +
>>  		if (copy_to_user((void __user *)arg, &info, minsz))
>>  			return -EFAULT;
>>  
>> @@ -412,12 +441,106 @@ static long tce_iommu_ioctl(void *iommu_data,
>>  		tce_iommu_disable(container);
>>  		mutex_unlock(&container->lock);
>>  		return 0;
>> +
>>  	case VFIO_EEH_PE_OP:
>>  		if (!container->grp)
>>  			return -ENODEV;
>>  
>>  		return vfio_spapr_iommu_eeh_ioctl(container->grp,
>>  						  cmd, arg);
>> +
>> +	case VFIO_IOMMU_SPAPR_TCE_CREATE: {
>> +		struct vfio_iommu_spapr_tce_create create;
>> +		struct spapr_tce_iommu_group *data;
>> +		struct iommu_table *tbl;
>> +
>> +		if (WARN_ON(!container->grp))
> 
> redux previous comment on this warning
> 
>> +			return -ENXIO;
>> +
>> +		data = iommu_group_get_iommudata(container->grp);
>> +
>> +		minsz = offsetofend(struct vfio_iommu_spapr_tce_create,
>> +				start_addr);
>> +
>> +		if (copy_from_user(&create, (void __user *)arg, minsz))
>> +			return -EFAULT;
>> +
>> +		if (create.argsz < minsz)
>> +			return -EINVAL;
>> +
>> +		if (create.flags)
>> +			return -EINVAL;
>> +
>> +		if (!data->ops->create || !data->iommu_owner)
>> +			return -ENOSYS;
>> +
>> +		BUG_ON(!data || !data->ops || !data->ops->remove);
> 
> Little late for this test since we'll oops on the previous test.  Why is
> this a BUG_ON?  A user could exploit this on a system with only a
> partial set of callbacks.
> 
>> +
>> +		ret = data->ops->create(data, create.page_shift,
>> +				create.window_shift, &tbl);
>> +		if (ret)
>> +			return ret;
>> +
>> +		ret = try_increment_locked_vm(tbl);
>> +		if (ret) {
>> +			data->ops->remove(data, tbl);
>> +			return ret;
>> +		}
>> +
>> +		create.start_addr = tbl->it_offset << tbl->it_page_shift;
>> +
>> +		if (copy_to_user((void __user *)arg, &create, minsz)) {
>> +			data->ops->remove(data, tbl);
>> +			decrement_locked_vm(tbl);
>> +			return -EFAULT;
>> +		}
>> +		mutex_lock(&container->lock);
>> +		++container->windows_num;
>> +		mutex_unlock(&container->lock);
>> +
>> +		return ret;
>> +	}
>> +	case VFIO_IOMMU_SPAPR_TCE_REMOVE: {
>> +		struct vfio_iommu_spapr_tce_remove remove;
>> +		struct spapr_tce_iommu_group *data;
>> +		struct iommu_table *tbl;
>> +
>> +		if (WARN_ON(!container->grp))
>> +			return -ENXIO;
>> +
>> +		data = iommu_group_get_iommudata(container->grp);
>> +
>> +		minsz = offsetofend(struct vfio_iommu_spapr_tce_remove,
>> +				start_addr);
>> +
>> +		if (copy_from_user(&remove, (void __user *)arg, minsz))
>> +			return -EFAULT;
>> +
>> +		if (remove.argsz < minsz)
>> +			return -EINVAL;
>> +
>> +		if (remove.flags)
>> +			return -EINVAL;
>> +
>> +		if (!data->ops->remove || !data->iommu_owner)
> 
> On this one we don't both to get data/data->ops.  Is there also an
> exploit where the user can call these CREATE/REMOVE interfaces even
> though INFO doesn't expose them if only a partial set of callbacks are
> present?

		if (!data || !data->ops || !data->ops->remove || !data->iommu_owner)

should do it, right?
And I am not going to add create() without remove(), may be it is worth
adding a compile time check for that.


> 
>> +			return -ENOSYS;
>> +
>> +		tbl = spapr_tce_find_table(container, data, remove.start_addr);
> 
> What happens if this returns the 0 index rather than the expected 1
> index table?  Why doesn't this call ops->find_table()?

Why ops->find_table()? They are different (->find_table() searches for the
window by number, spapr_tce_find_table() searches by address), I do not
understand this comment.

And removing window#0 is supported.


> 
>> +		if (!tbl)
>> +			return -EINVAL;
>> +
>> +		ret = data->ops->remove(data, tbl);
>> +		if (ret)
>> +			return ret;
>> +
>> +		decrement_locked_vm(tbl);
>> +
>> +		mutex_lock(&container->lock);
>> +		--container->windows_num;
>> +		mutex_unlock(&container->lock);
>> +
>> +		return 0;
>> +	}
>>  	}
>>  
>>  	return -ENOTTY;
>> diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
>> index 6612974..e71a6ef 100644
>> --- a/include/uapi/linux/vfio.h
>> +++ b/include/uapi/linux/vfio.h
>> @@ -451,9 +451,13 @@ struct vfio_iommu_type1_dma_unmap {
>>   */
>>  struct vfio_iommu_spapr_tce_info {
>>  	__u32 argsz;
>> -	__u32 flags;			/* reserved for future use */
>> +	__u32 flags;
>> +#define VFIO_IOMMU_SPAPR_TCE_FLAG_DDW	1 /* Support dynamic windows */
>>  	__u32 dma32_window_start;	/* 32 bit window start (bytes) */
>>  	__u32 dma32_window_size;	/* 32 bit window size (bytes) */
>> +	__u32 current_windows;
>> +	__u32 windows_available;
>> +	__u32 page_size_mask;
>>  };
>>  
>>  #define VFIO_IOMMU_SPAPR_TCE_GET_INFO	_IO(VFIO_TYPE, VFIO_BASE + 12)
>> @@ -489,6 +493,25 @@ struct vfio_eeh_pe_op {
>>  
>>  #define VFIO_EEH_PE_OP			_IO(VFIO_TYPE, VFIO_BASE + 21)
>>  
>> +struct vfio_iommu_spapr_tce_create {
>> +	__u32 argsz;
>> +	__u32 flags;
>> +	/* in */
>> +	__u32 page_shift;
>> +	__u32 window_shift;
>> +	/* out */
>> +	__u64 start_addr;
>> +};
>> +#define VFIO_IOMMU_SPAPR_TCE_CREATE	_IO(VFIO_TYPE, VFIO_BASE + 18)
>> +
>> +struct vfio_iommu_spapr_tce_remove {
>> +	__u32 argsz;
>> +	__u32 flags;
>> +	/* in */
>> +	__u64 start_addr;
>> +};
>> +#define VFIO_IOMMU_SPAPR_TCE_REMOVE	_IO(VFIO_TYPE, VFIO_BASE + 19)
>> +
> 
> Zero comments, no good.

Right. I'll fix it. Thanks for the review.


> 
>>  /* ***************************************************************** */
>>  
>>  #endif /* _UAPIVFIO_H */
> 
> 
> 


-- 
Alexey

^ permalink raw reply

* Re: [PATCH 3/3] ls1021a-twr/qe: add qe node to ls1-twr
From: Scott Wood @ 2014-10-10 18:08 UTC (permalink / raw)
  To: Zhao Qiang; +Cc: devicetree, R63061, linuxppc-dev, linux-arm-kernel, B07421
In-Reply-To: <1412923798-9757-1-git-send-email-B45475@freescale.com>

On Fri, 2014-10-10 at 14:49 +0800, Zhao Qiang wrote:
> add qe node to ls1021atwr fdt.
> 
> Signed-off-by: Zhao Qiang <B45475@freescale.com>
> ---
>  arch/arm/boot/dts/ls1021a-twr.dts | 24 +++++++++++++++
>  arch/arm/boot/dts/ls1021a.dtsi    | 64 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 88 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
> index a52be7b..415387f 100755
> --- a/arch/arm/boot/dts/ls1021a-twr.dts
> +++ b/arch/arm/boot/dts/ls1021a-twr.dts
> @@ -164,6 +164,30 @@
>  	};
>  };
>  
> +&uqe {
> +	tdma: ucc@2000 {
> +		compatible = "fsl,ucc-tdm";

Binding?

> +		rx-clock-name = "clk8";
> +		tx-clock-name = "clk9";
> +		fsl,rx-sync-clock = "rsync_pin";
> +		fsl,tx-sync-clock = "tsync_pin";
> +		fsl,tx-timeslot = <0xfffffffe>;
> +		fsl,rx-timeslot = <0xfffffffe>;
> +		fsl,tdm-framer-type = "e1";
> +		fsl,tdm-mode = "normal";
> +		fsl,tdm-id = <0>;
> +		fsl,siram-entry-id = <0>;
> +	};
> +
> +	serial: ucc@2200 {
> +		device_type = "serial";
> +		compatible = "ucc_uart";
> +		port-number = <1>;
> +		rx-clock-name = "brg2";
> +		tx-clock-name = "brg2";
> +	};

Binding for ucc_uart?  Why device_type?

> +};
> +
>  &pwm6 {
>  	status = "okay";
>  };
> diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
> index 80747dc..3f2ab89 100644
> --- a/arch/arm/boot/dts/ls1021a.dtsi
> +++ b/arch/arm/boot/dts/ls1021a.dtsi
> @@ -314,6 +314,70 @@
>  			status = "disabled";
>  		};
>  
> +		uqe: uqe@2400000 {

How does "uqe" differ from "qe"?

-Scott

^ permalink raw reply

* Re: [PATCH 1/3] qe-uart: modify qe-uart to adapt both powerpc and arm
From: Scott Wood @ 2014-10-10 18:05 UTC (permalink / raw)
  To: Zhao Qiang
  Cc: B07421, timur, linux-serial, R63061, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1412923663-4374-1-git-send-email-B45475@freescale.com>

On Fri, 2014-10-10 at 14:47 +0800, Zhao Qiang wrote:
> qe has been supported by arm board ls1021, qe-uart need
> to be supported by ls1021.
> modify the code to make qe-uart can work on both powerpc
> and ls1021.
> 
> Signed-off-by: Zhao Qiang <B45475@freescale.com>
> ---
>  arch/arm/include/asm/delay.h  |  16 ++++
>  arch/arm/include/asm/io.h     |  28 +++++++
>  arch/arm/include/asm/irq.h    |   2 +
>  arch/arm/kernel/irq.c         |   7 ++
>  drivers/soc/qe/Kconfig        |   1 -
>  drivers/soc/qe/qe.c           |  63 ++++++++-------
>  drivers/soc/qe/qe_common.c    |   2 +-
>  drivers/soc/qe/qe_ic.c        |   7 +-
>  drivers/soc/qe/qe_io.c        |  53 ++++++-------
>  drivers/soc/qe/ucc_slow.c     |  40 +++++-----
>  drivers/tty/serial/ucc_uart.c | 176 +++++++++++++++++++++---------------------
>  include/linux/fsl/qe.h        |  21 +++++
>  12 files changed, 245 insertions(+), 171 deletions(-)

This patch obviously depends on the patches to relocate QE support, but
there's no mention of that dependency above.

There are many changes in here that ought to be separate patches with
separate justification.

Also, some of the QE changes seem to be reasonable cleanup, but not
related to making the code work on ARM.

> diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h
> index dff714d..a932f99 100644
> --- a/arch/arm/include/asm/delay.h
> +++ b/arch/arm/include/asm/delay.h
> @@ -57,6 +57,22 @@ extern void __bad_udelay(void);
>  			__const_udelay((n) * UDELAY_MULT)) :		\
>  	  __udelay(n))
>  
> +#define spin_event_timeout(condition, timeout, delay)                          \
> +({                                                                             \
> +	typeof(condition) __ret;                                               \
> +	int i = 0;							       \
> +	while (!(__ret = (condition)) && (i++ < timeout)) {		       \
> +		if (delay)                                                     \
> +			udelay(delay);                                         \
> +		else                                                           \
> +			cpu_relax();					       \
> +		udelay(1);						       \
> +	}								       \

This will delay too long if "delay" is used.

How about:

	delay = delay ? delay : 1;			\
	while (!(__ret = (condition))) {		\
		if (i < timeout)			\
			break;				\
		i += delay;				\
		udelay(delay);				\
	}						\

Also, once the dependency on timebase is removed, how about making this
generic rather than just PPC+ARM?

> +	if (!__ret)                                                            \
> +		__ret = (condition);                                           \
> +	__ret;		                                                       \

Timur, do you remember why that final "if (!__ret) __ret = (condition);"
is needed?

> +})
> +
>  /* Loop-based definitions for assembly code. */
>  extern void __loop_delay(unsigned long loops);
>  extern void __loop_udelay(unsigned long usecs);
> diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
> index d070741..4bec694 100644
> --- a/arch/arm/include/asm/io.h
> +++ b/arch/arm/include/asm/io.h
> @@ -206,6 +206,34 @@ extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
>  #endif
>  #endif
>  
> +/* access ports */
> +#define setbits32(_addr, _v) iowrite32be(ioread32be(_addr) |  (_v), (_addr))
> +#define clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr))
> +
> +#define setbits16(_addr, _v) iowrite16be(ioread16be(_addr) |  (_v), (_addr))
> +#define clrbits16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr))
> +
> +#define setbits8(_addr, _v) iowrite8(ioread8(_addr) |  (_v), (_addr))
> +#define clrbits8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr))

This should also be a separate patch, though I don't think implicit big
endian is going to fly in arch/arm (it was a mistake in arch/powerpc).
Rename to setbits_be32 etc as is used in U-Boot.

> +/* Clear and set bits in one shot.  These macros can be used to clear and
> + * set multiple bits in a register using a single read-modify-write.  These
> + * macros can also be used to set a multiple-bit bit pattern using a mask,
> + * by specifying the mask in the 'clear' parameter and the new bit pattern
> + * in the 'set' parameter.
> + */
> +
> +#define clrsetbits_be32(addr, clear, set) \
> +	iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr))
> +#define clrsetbits_le32(addr, clear, set) \
> +	iowrite32le((ioread32le(addr) & ~(clear)) | (set), (addr))
> +#define clrsetbits_be16(addr, clear, set) \
> +	iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr))
> +#define clrsetbits_le16(addr, clear, set) \
> +	iowrite16le((ioread16le(addr) & ~(clear)) | (set), (addr))
> +#define clrsetbits_8(addr, clear, set) \
> +	iowrite8((ioread8(addr) & ~(clear)) | (set), (addr))
> +
>  /*
>   *  IO port access primitives
>   *  -------------------------
> diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
> index 53c15de..4358904 100644
> --- a/arch/arm/include/asm/irq.h
> +++ b/arch/arm/include/asm/irq.h
> @@ -30,6 +30,8 @@ extern void asm_do_IRQ(unsigned int, struct pt_regs *);
>  void handle_IRQ(unsigned int, struct pt_regs *);
>  void init_IRQ(void);
>  
> +extern irq_hw_number_t virq_to_hw(unsigned int virq);
> +
>  #ifdef CONFIG_MULTI_IRQ_HANDLER
>  extern void (*handle_arch_irq)(struct pt_regs *);
>  extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
> diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
> index 9723d17..afa204a 100644
> --- a/arch/arm/kernel/irq.c
> +++ b/arch/arm/kernel/irq.c
> @@ -121,6 +121,13 @@ void __init init_IRQ(void)
>  		machine_desc->init_irq();
>  }
>  
> +irq_hw_number_t virq_to_hw(unsigned int virq)
> +{
> +	struct irq_data *irq_data = irq_get_irq_data(virq);
> +	return WARN_ON(!irq_data) ? 0 : irq_data->hwirq;
> +}
> +EXPORT_SYMBOL_GPL(virq_to_hw);

Can this be moved to generic code?  Or just open-coded in the caller?

>  #ifdef CONFIG_MULTI_IRQ_HANDLER
>  void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
>  {
> diff --git a/drivers/soc/qe/Kconfig b/drivers/soc/qe/Kconfig
> index 49118e1..43b984b 100644
> --- a/drivers/soc/qe/Kconfig
> +++ b/drivers/soc/qe/Kconfig
> @@ -4,7 +4,6 @@
>  
>  config QUICC_ENGINE
>  	bool "Freescale QUICC Engine (QE) Support"
> -	depends on FSL_SOC && (PPC32 || PPC64)

Are you sure there are no build dependencies?  What about OF?

> diff --git a/include/linux/fsl/qe.h b/include/linux/fsl/qe.h
> index 5a6a647..ef4422c 100644
> --- a/include/linux/fsl/qe.h
> +++ b/include/linux/fsl/qe.h
> @@ -306,6 +306,27 @@ struct qe_bd {
>  #define BD_STATUS_MASK	0xffff0000
>  #define BD_LENGTH_MASK	0x0000ffff
>  
> +/* Buffer descriptor control/status used by serial
> + */
> +
> +#define BD_SC_EMPTY	(0x8000)	/* Receive is empty */
> +#define BD_SC_READY	(0x8000)	/* Transmit is ready */
> +#define BD_SC_WRAP	(0x2000)	/* Last buffer descriptor */
> +#define BD_SC_INTRPT	(0x1000)	/* Interrupt on change */
> +#define BD_SC_LAST	(0x0800)	/* Last buffer in frame */
> +#define BD_SC_TC	(0x0400)	/* Transmit CRC */
> +#define BD_SC_CM	(0x0200)	/* Continuous mode */
> +#define BD_SC_ID	(0x0100)	/* Rec'd too many idles */
> +#define BD_SC_P		(0x0100)	/* xmt preamble */
> +#define BD_SC_BR	(0x0020)	/* Break received */
> +#define BD_SC_FR	(0x0010)	/* Framing error */
> +#define BD_SC_PR	(0x0008)	/* Parity error */
> +#define BD_SC_NAK	(0x0004)	/* NAK - did not respond */
> +#define BD_SC_OV	(0x0002)	/* Overrun */
> +#define BD_SC_UN	(0x0002)	/* Underrun */
> +#define BD_SC_CD	(0x0001)	/* */
> +#define BD_SC_CL	(0x0001)	/* Collision */

Please move this rather than copying it.

-Scott

^ permalink raw reply

* Re: [PATCH 2/3] qe: run qe_init and qe_ic_init
From: Scott Wood @ 2014-10-10 17:34 UTC (permalink / raw)
  To: Zhao Qiang; +Cc: B07421, R63061, linuxppc-dev, linux-kernel
In-Reply-To: <1412923725-9611-1-git-send-email-B45475@freescale.com>

On Fri, 2014-10-10 at 14:48 +0800, Zhao Qiang wrote:
> qe and qe_ic need to be initialized before the
> qe app drivers, using subsys_initcall to run
> qe_init and qe_ic_init
> 
> Signed-off-by: Zhao Qiang <B45475@freescale.com>
> ---
>  drivers/soc/qe/qe.c    | 15 +++++++++++++++
>  drivers/soc/qe/qe_ic.c | 15 +++++++++++++++
>  2 files changed, 30 insertions(+)
> 
> diff --git a/drivers/soc/qe/qe.c b/drivers/soc/qe/qe.c
> index 2aaa5b2..bfea0f8 100644
> --- a/drivers/soc/qe/qe.c
> +++ b/drivers/soc/qe/qe.c
> @@ -683,6 +683,21 @@ unsigned int qe_get_num_of_snums(void)
>  }
>  EXPORT_SYMBOL(qe_get_num_of_snums);
>  
> +static int __init qe_init(void)
> +{
> +	struct device_node *np;
> +
> +	np = of_find_compatible_node(NULL, NULL, "fsl,qe");
> +	if (!np) {
> +		pr_err("%s: Could not find Quicc Engine node\n", __func__);
> +		return -ENODEV;
> +	}
> +	qe_reset();
> +	of_node_put(np);
> +	return 0;
> +}
> +subsys_initcall(qe_init);

It is not an error to enable QE support on hardware that doesn't have
QE.  Please remove the pr_err().

> +
>  #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
>  static int qe_resume(struct platform_device *ofdev)
>  {
> diff --git a/drivers/soc/qe/qe_ic.c b/drivers/soc/qe/qe_ic.c
> index cc1b8d5..11fe98c 100644
> --- a/drivers/soc/qe/qe_ic.c
> +++ b/drivers/soc/qe/qe_ic.c
> @@ -34,6 +34,7 @@
>  #include <linux/fsl/qe_ic.h>
>  
>  #include "qe_ic.h"
> +#include "../../irqchip/irqchip.h"

What do you need from here, and can it be moved to include/linux/...?
 
The only thing I see defined in irqchip.h is IRQCHIP_DECLARE, and you
don't use that in this patch...

-Scott

>  static DEFINE_RAW_SPINLOCK(qe_ic_lock);
>  
> @@ -501,4 +502,18 @@ static int __init init_qe_ic_sysfs(void)
>  	return 0;
>  }
>  
> +static int __init qeic_of_init(void)
> +{
> +	struct device_node *np;
> +
> +	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
> +	if (np) {
> +		qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
> +			   qe_ic_cascade_high_mpic);
> +		of_node_put(np);
> +	}
> +	return 0;
> +}
> +subsys_initcall(qeic_of_init);
> +
>  subsys_initcall(init_qe_ic_sysfs);

^ permalink raw reply

* Re: [PATCH 08/44] kernel: Move pm_power_off to common code
From: Guenter Roeck @ 2014-10-10 16:53 UTC (permalink / raw)
  To: Pavel Machek
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, Steven Miao,
	linux-xtensa, Boris Ostrovsky, Catalin Marinas, Will Deacon,
	David Howells, Max Filippov, Paul Mackerras, Ralf Baechle,
	H. Peter Anvin, Guan Xuetao, Thomas Gleixner, Lennox Wu,
	Hans-Christian Egtvedt, devel, linux-s390, Jesper Nilsson, lguest,
	Russell King, linux-c6x-dev, Len Brown, David S. Miller,
	linux-hexagon, Hirokazu Takata, linux-sh, James E.J. Bottomley,
	linux-acpi, Ingo Molnar, Geert Uytterhoeven, Mark Salter,
	xen-devel, Matt Turner, Chen Liqin, Jonas Bonn,
	Haavard Skinnemoen, devicetree, James Hogan,
	user-mode-linux-devel, linux-pm, Aurelien Jacquiot,
	Heiko Carstens, Jeff Dike, adi-buildroot-devel, Chris Metcalf,
	Konrad Rzeszutek Wilk, Mikael Starvik, Richard Weinberger,
	linux-m68k, linux-am33-list, Ivan Kokshaysky, linux-tegra,
	openipmi-developer, linux-metag, linux-arm-kernel,
	Richard Henderson, Chris Zankel, Michal Simek, Tony Luck,
	linux-parisc, linux-cris-kernel, Vineet Gupta, Rafael J. Wysocki,
	linux-kernel, Fenghua Yu, Richard Kuo, David Vrabel, linux-alpha,
	Martin Schwidefsky, Koichi Yasutake, linuxppc-dev, Helge Deller
In-Reply-To: <20141009202419.GA16885@amd>

On 10/09/2014 01:24 PM, Pavel Machek wrote:
> Hi!
>
>>>> @@ -184,6 +179,8 @@ machine_halt(void)
>>>>   void
>>>>   machine_power_off(void)
>>>>   {
>>>> +	do_kernel_poweroff();
>>>> +
>>>
>>> poweroff -> power_off for consistency.
>>>
>> Dunno; matter of personal preference. I started with that, but ultimately went
>> with poweroff to distinguish poweroff handler functions from existing code,
>> specifically kernel_power_off().
>
> That works for you, but once it is merged, it is ugly/confusing typo.
> 									Pavel
>

Ok, no problem, I'll change it.

Guenter

^ permalink raw reply

* [PATCH v3] powerpc/numa: add ability to disable and debug topology updates
From: Nishanth Aravamudan @ 2014-10-10 16:04 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Nathan Fontenot, Paul Mackerras, linuxppc-dev
In-Reply-To: <20141010042816.A75841400EA@ozlabs.org>

On 10.10.2014 [15:28:16 +1100], Michael Ellerman wrote:
> On Thu, 2014-09-10 at 23:42:15 UTC, Nishanth Aravamudan wrote:
> > We have hit a few customer issues with the topology update code (VPHN
> > and PRRN). It would be nice to be able to debug the notifications coming
> > from the hypervisor in both cases to the LPAR, as well as to disable
> > responding to the notifications at boot-time, to narrow down the source
> > of the problems. Add a basic level of such functionality, similar to the
> > numa= command-line parameter. We already have a toggle in
> > /proc/powerpc/topology_updates that allows run-time enabling/disabling,
> > so the updates can be started at run-time if desired. But the bugs we've
> > run into have occured during boot or very shortly after coming to login,
> > and have resulted in a broken NUMA topology.
> 
> Thanks Nish, a couple of minor nits.

Thanks for the review, fixed.

<snip>

> > +static int __init early_topology_updates(char *p)
> > +{
> > +	if (!p)
> > +		return 0;
> > +
> > +	if (strstr(p, "off")) {
> 
> You're better off using strcmp. Using strstr() is nice if you need to support
> multiple values, but it's sloppy otherwise. This will match "offset",
> "smirnoff" etc.

I feel like this is the Linux-equivalent of "You just got iced!"

<snip>

We have hit a few customer issues with the topology update code (VPHN
and PRRN). It would be nice to be able to debug the notifications coming
from the hypervisor in both cases to the LPAR, as well as to disable
responding to the notifications at boot-time, to narrow down the source
of the problems. Add a basic level of such functionality, similar to the
numa= command-line parameter. We already have a toggle in
/proc/powerpc/topology_updates that allows run-time enabling/disabling,
so the updates can be started at run-time if desired. But the bugs we've
run into have occured during boot or very shortly after coming to login,
and have resulted in a broken NUMA topology.

Signed-off-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
---
v1 -> v2:
 Updated commit message to answer some of mpe's reviews.
 Switched to pr_fmt based debugging, which removes the need for the
   debug flag.
 Be a little less verbose in the debugging, as it was duplicating
   information.
v2 -> v3:
 Move pr_fmt define to the right spot.
 Make topology_updates_enabled bool.
 Use strcmp instead of strstr for topology_updates= parsing.
 Add a missing newline.

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d9a452e8fb9b..35a46b8240ad 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3388,6 +3388,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			e.g. base its process migration decisions on it.
 			Default is on.
 
+	topology_updates= [KNL, PPC, NUMA]
+			Format: {off}
+			Specify if the kernel should ignore (off)
+			topology updates sent by the hypervisor to this
+			LPAR.
+
 	tp720=		[HW,PS2]
 
 	tpm_suspend_pcr=[HW,TPM]
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e28c21ba862d..6fde1d4351e6 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -8,6 +8,8 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
+#define pr_fmt(fmt) "numa: " fmt
+
 #include <linux/threads.h>
 #include <linux/bootmem.h>
 #include <linux/init.h>
@@ -1160,6 +1162,22 @@ static int __init early_numa(char *p)
 }
 early_param("numa", early_numa);
 
+static bool topology_updates_enabled = true;
+
+static int __init early_topology_updates(char *p)
+{
+	if (!p)
+		return 0;
+
+	if (!strcmp(p, "off")) {
+		pr_info("Disabling topology updates\n");
+		topology_updates_enabled = false;
+	}
+
+	return 0;
+}
+early_param("topology_updates", early_topology_updates);
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Find the node associated with a hot added memory section for
@@ -1546,6 +1564,9 @@ int arch_update_cpu_topology(void)
 	struct device *dev;
 	int weight, new_nid, i = 0;
 
+	if (!prrn_enabled && !vphn_enabled)
+		return 0;
+
 	weight = cpumask_weight(&cpu_associativity_changes_mask);
 	if (!weight)
 		return 0;
@@ -1599,6 +1620,15 @@ int arch_update_cpu_topology(void)
 		cpu = cpu_last_thread_sibling(cpu);
 	}
 
+	pr_debug("Topology update for the following CPUs:\n");
+	if (cpumask_weight(&updated_cpus)) {
+		for (ud = &updates[0]; ud; ud = ud->next) {
+			pr_debug("cpu %d moving from node %d "
+					  "to %d\n", ud->cpu,
+					  ud->old_nid, ud->new_nid);
+		}
+	}
+
 	/*
 	 * In cases where we have nothing to update (because the updates list
 	 * is too short or because the new topology is same as the old one),
@@ -1807,7 +1837,10 @@ static const struct file_operations topology_ops = {
 
 static int topology_update_init(void)
 {
-	start_topology_update();
+	/* Do not poll for changes if disabled at boot */
+	if (topology_updates_enabled)
+		start_topology_update();
+
 	if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
 		return -ENOMEM;
 

^ permalink raw reply related

* [PATCH v2] powerpc/powernv: Fallback to old HMI handling behavior for old firmware
From: Mahesh J Salgaonkar @ 2014-10-10 15:58 UTC (permalink / raw)
  To: Michael Ellerman, linuxppc-dev, Benjamin Herrenschmidt; +Cc: Paul Mackerras

From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>

Recently we moved HMI handling into Linux kernel instead of taking
HMI directly in OPAL. This new change is dependent on new OPAL call
for HMI recovery which was introduced in newer firmware. While this new
change works fine with latest OPAL firmware, we broke the HMI handling
if we run newer kernel on old OPAL firmware that results in system hang.

This patch fixes this issue by falling back to old HMI behavior on older
OPAL firmware.

This patch introduces a check for opal token OPAL_HANDLE_HMI to see
if we are running on newer firmware or old firmware. On newer firmware
this check would return OPAL_TOKEN_PRESENT, otherwise we are running on
old firmware and fallback to old HMI behavior.

Old firmware: POWER8 System Firmware Release as of today <= SV810_087
Action: Let OPAL handle HMIs

Newer firmware: in development/yet to be released.
Action: Let Linux host handle HMIs.

This patch depends on opal check token patch posted at ppc-devel
https://lists.ozlabs.org/pipermail/linuxppc-dev/2014-August/120224.html

Signed-off-by: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/opal.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index b44eec3..f172c15 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -194,6 +194,29 @@ static int __init opal_register_exception_handlers(void)
 	 * fwnmi area at 0x7000 to provide the glue space to OPAL
 	 */
 	glue = 0x7000;
+
+	/*
+	 * Check if we are running on newer firmware that exports
+	 * OPAL_HANDLE_HMI token. If yes, then don't ask opal to patch
+	 * HMI interrupt and we catch it directly in Linux kernel.
+	 *
+	 * For older firmware (i.e currently released POWER8 System Firmware
+	 * as of today <= SV810_087), we fallback to old behavior and let OPAL
+	 * to patch the HMI vector and handle it inside OPAL firmware.
+	 *
+	 * For newer firmware (in development/yet to be released) we will
+	 * start catching/handling HMI directly in Linux kernel.
+	 */
+	if (!opal_check_token(OPAL_HANDLE_HMI)) {
+		/* We are on old firmware. fallback to old behavior. */
+		pr_info("%s: Old firmware detected, let OPAL handle HMIs.\n",
+			"opal");
+		opal_register_exception_handler(
+				OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
+				0, glue);
+		glue += 128;
+	}
+
 	opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
 #endif
 

^ permalink raw reply related

* [PATCHv5] clk: ppc-corenet: rename to qoriq and add CLK_OF_DECLARE support
From: Jingchang Lu @ 2014-10-10  9:14 UTC (permalink / raw)
  To: mturquette
  Cc: scottwood, linuxppc-dev, linux-kernel, linux-arm-kernel,
	Jingchang Lu

The IP is shared by PPC and ARM, this renames it to qoriq for better
represention, and this also adds the CLK_OF_DECLARE support for being
initialized by of_clk_init() on ARM.

Signed-off-by: Jingchang Lu <jingchang.lu@freescale.com>
---
changes in v5:
 update drivers/cpufreq/Kconfig.powerpc to slect the renamed config option.

changes in v4:
 remove "corenet" literals omitted in v3 remove.

changes in v3:
 generate the patch with -M -C option

changes in v2:
 rename the driver name to ppc-qoriq.c for shared on PPC and ARM.

 drivers/clk/Kconfig                            | 10 ++++-----
 drivers/clk/Makefile                           |  2 +-
 drivers/clk/{clk-ppc-corenet.c => clk-qoriq.c} | 29 +++++++++++++++-----------
 drivers/cpufreq/Kconfig.powerpc                |  2 +-
 4 files changed, 24 insertions(+), 19 deletions(-)
 rename drivers/clk/{clk-ppc-corenet.c => clk-qoriq.c} (89%)

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 455fd17..4706a9f 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -101,12 +101,12 @@ config COMMON_CLK_AXI_CLKGEN
 	  Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
 	  FPGAs. It is commonly used in Analog Devices' reference designs.
 
-config CLK_PPC_CORENET
-	bool "Clock driver for PowerPC corenet platforms"
-	depends on PPC_E500MC && OF
+config CLK_QORIQ
+	bool "Clock driver for Freescale QorIQ platforms"
+	depends on (PPC_E500MC || ARM) && OF
 	---help---
-	  This adds the clock driver support for Freescale PowerPC corenet
-	  platforms using common clock framework.
+	  This adds the clock driver support for Freescale QorIQ platforms
+	  using common clock framework.
 
 config COMMON_CLK_XGENE
 	bool "Clock driver for APM XGene SoC"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index d5fba5b..4ff94cd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -30,7 +30,7 @@ obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
 obj-$(CONFIG_COMMON_CLK_PALMAS)		+= clk-palmas.o
-obj-$(CONFIG_CLK_PPC_CORENET)		+= clk-ppc-corenet.o
+obj-$(CONFIG_CLK_QORIQ)			+= clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)		+= clk-rk808.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)	+= clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SI5351)		+= clk-si5351.o
diff --git a/drivers/clk/clk-ppc-corenet.c b/drivers/clk/clk-qoriq.c
similarity index 89%
rename from drivers/clk/clk-ppc-corenet.c
rename to drivers/clk/clk-qoriq.c
index 8e58edf..48cb923 100644
--- a/drivers/clk/clk-ppc-corenet.c
+++ b/drivers/clk/clk-qoriq.c
@@ -5,7 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * clock driver for Freescale PowerPC corenet SoCs.
+ * clock driver for Freescale QorIQ SoCs.
  */
 #include <linux/clk-provider.h>
 #include <linux/io.h>
@@ -155,7 +155,7 @@ static void __init core_pll_init(struct device_node *np)
 
 	base = of_iomap(np, 0);
 	if (!base) {
-		pr_err("clk-ppc: iomap error\n");
+		pr_err("clk-qoriq: iomap error\n");
 		return;
 	}
 
@@ -252,7 +252,7 @@ static void __init sysclk_init(struct device_node *node)
 	u32 rate;
 
 	if (!np) {
-		pr_err("ppc-clk: could not get parent node\n");
+		pr_err("qoriq-clk: could not get parent node\n");
 		return;
 	}
 
@@ -278,30 +278,35 @@ static const struct of_device_id clk_match[] __initconst = {
 	{}
 };
 
-static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
+static int __init qoriq_clk_probe(struct platform_device *pdev)
 {
 	of_clk_init(clk_match);
 
 	return 0;
 }
 
-static const struct of_device_id ppc_clk_ids[] __initconst = {
+static const struct of_device_id qoriq_clk_ids[] __initconst = {
 	{ .compatible = "fsl,qoriq-clockgen-1.0", },
 	{ .compatible = "fsl,qoriq-clockgen-2.0", },
 	{}
 };
 
-static struct platform_driver ppc_corenet_clk_driver __initdata = {
+static struct platform_driver qoriq_clk_driver __initdata = {
 	.driver = {
-		.name = "ppc_corenet_clock",
+		.name = "qoriq_clock",
 		.owner = THIS_MODULE,
-		.of_match_table = ppc_clk_ids,
+		.of_match_table = qoriq_clk_ids,
 	},
-	.probe = ppc_corenet_clk_probe,
+	.probe = qoriq_clk_probe,
 };
 
-static int __init ppc_corenet_clk_init(void)
+static int __init qoriq_clk_init(void)
 {
-	return platform_driver_register(&ppc_corenet_clk_driver);
+	return platform_driver_register(&qoriq_clk_driver);
 }
-subsys_initcall(ppc_corenet_clk_init);
+subsys_initcall(qoriq_clk_init);
+
+CLK_OF_DECLARE(qoriq_core_pll_v1, "fsl,qoriq-core-pll-1.0", core_pll_init);
+CLK_OF_DECLARE(qoriq_core_pll_v2, "fsl,qoriq-core-pll-2.0", core_pll_init);
+CLK_OF_DECLARE(qoriq_core_mux_v1, "fsl,qoriq-core-mux-1.0", core_mux_init);
+CLK_OF_DECLARE(qoriq_core_mux_v2, "fsl,qoriq-core-mux-2.0", core_mux_init);
diff --git a/drivers/cpufreq/Kconfig.powerpc b/drivers/cpufreq/Kconfig.powerpc
index 72564b7..7ea2441 100644
--- a/drivers/cpufreq/Kconfig.powerpc
+++ b/drivers/cpufreq/Kconfig.powerpc
@@ -26,7 +26,7 @@ config CPU_FREQ_MAPLE
 config PPC_CORENET_CPUFREQ
 	tristate "CPU frequency scaling driver for Freescale E500MC SoCs"
 	depends on PPC_E500MC && OF && COMMON_CLK
-	select CLK_PPC_CORENET
+	select CLK_QORIQ
 	help
 	  This adds the CPUFreq driver support for Freescale e500mc,
 	  e5500 and e6500 series SoCs which are capable of changing
-- 
1.8.0

^ permalink raw reply related

* Re: [PATCH tty-next 14/22] tty: Remove tty_wait_until_sent_from_close()
From: One Thousand Gnomes @ 2014-10-10  8:58 UTC (permalink / raw)
  To: Peter Hurley
  Cc: Karsten Keil, Arnd Bergmann, Greg Kroah-Hartman,
	linux-kernel@vger.kernel.org, David Laight,
	linux-serial@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <5434B5D3.4060308@hurleysoftware.com>

> The point being that holding the tty lock across the _entire_ close
> is equivalent to the current outcome, regardless of O_NONBLOCK.
> 
> I'm reluctant to start returning EGAIN for non-blocking tty opens
> because no tty driver does that now, and I don't think userspace will
> deal well with new return codes from tty opens.

I do not know about the non blocking case mattering. The blocking open
does need to wait, when I broke that case before I broke the console
login drivers (mingetty).

Returning EAGAIN would also only work if poll/select did the right thing.
Currently Linux can't support a System5 style ttymon process because of
this limitation, which means, for example, that systemd can't implement a
single thread to manage all console prompts/setup

Alan

^ permalink raw reply

* Re: [PATCH 2/2] powerpc/msi: Use WARN_ON() in msi bitmap selftests
From: Laurentiu Tudor @ 2014-10-10  8:11 UTC (permalink / raw)
  To: linuxppc-dev, mpe
In-Reply-To: <1412928265-21991-2-git-send-email-mpe@ellerman.id.au>

Hi Michael,

Comment inline.

On 10/10/2014 11:04 AM, Michael Ellerman wrote:
> As demonstrated in the previous commit, the failure message from the msi
> bitmap selftests is a bit subtle, it's easy to miss a failure in a busy
> boot log.
> 
> So drop our check() macro and use WARN_ON() instead. This necessitates
> inverting all the conditions as well.
> 
> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> ---
>  arch/powerpc/sysdev/msi_bitmap.c | 54 ++++++++++++++++++----------------------

[snip]

>  
>  	/* Free most of them for the alignment tests */
>  	msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
>  
>  	/* Check we get a naturally aligned offset */
>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
> -	check(rc >= 0 && rc % 2 == 0);
> +	WARN_ON(rc < 0 && rc % 2 != 0);

Here and below, shouldn't these be:

	WARN_ON(rc < 0 || rc % 2 != 0);

?

>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
> -	check(rc >= 0 && rc % 4 == 0);
> +	WARN_ON(rc < 0 && rc % 4 != 0);
>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
> -	check(rc >= 0 && rc % 8 == 0);
> +	WARN_ON(rc < 0 && rc % 8 != 0);
>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
> -	check(rc >= 0 && rc % 16 == 0);
> +	WARN_ON(rc < 0 && rc % 16 != 0);
>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
> -	check(rc >= 0 && rc % 4 == 0);
> +	WARN_ON(rc < 0 && rc % 4 != 0);
>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
> -	check(rc >= 0 && rc % 8 == 0);
> +	WARN_ON(rc < 0 && rc % 8 != 0);
>  	rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
> -	check(rc >= 0 && rc % 128 == 0);
> +	WARN_ON(rc < 0 && rc % 128 != 0);
>  
>  	msi_bitmap_free(&bmp);
>  
> -	/* Clients may check bitmap == NULL for "not-allocated" */
> -	check(bmp.bitmap == NULL);
> +	/* Clients may WARN_ON bitmap == NULL for "not-allocated" */
> +	WARN_ON(bmp.bitmap != NULL);
>  
>  	kfree(bmp.bitmap);
>  }
> @@ -229,14 +224,13 @@ static void __init test_of_node(void)
>  	of_node_init(&of_node);
>  	of_node.full_name = node_name;
>  
> -	check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
> +	WARN_ON(msi_bitmap_alloc(&bmp, size, &of_node));
>  
>  	/* No msi-available-ranges, so expect > 0 */
> -	check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
> +	WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
>  
>  	/* Should all still be free */
> -	check(0 == bitmap_find_free_region(bmp.bitmap, size,
> -					   get_count_order(size)));
> +	WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
>  	bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
>  
>  	/* Now create a fake msi-available-ranges property */
> @@ -250,11 +244,11 @@ static void __init test_of_node(void)
>  	of_node.properties = &prop;
>  
>  	/* msi-available-ranges, so expect == 0 */
> -	check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0);
> +	WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp));
>  
>  	/* Check we got the expected result */
> -	check(0 == bitmap_parselist(expected_str, expected, size));
> -	check(bitmap_equal(expected, bmp.bitmap, size));
> +	WARN_ON(bitmap_parselist(expected_str, expected, size));
> +	WARN_ON(!bitmap_equal(expected, bmp.bitmap, size));
>  
>  	msi_bitmap_free(&bmp);
>  	kfree(bmp.bitmap);
> 

---
Best Regards, Laurentiu

^ permalink raw reply

* Re: [v2] powerpc/vphn: fix endian issue in NUMA device node code
From: Greg Kurz @ 2014-10-10  8:20 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Nishanth Aravamudan, linuxppc-dev
In-Reply-To: <20141007092823.7994A1400BE@ozlabs.org>

On Tue,  7 Oct 2014 20:28:23 +1100 (EST)
Michael Ellerman <mpe@ellerman.id.au> wrote:

> On Fri, 2014-03-10 at 09:13:17 UTC, Greg Kurz wrote:
> > The associativity domain numbers are obtained from the hypervisor through
> > registers and written into memory by the guest: the packed array passed to
> > vphn_unpack_associativity() is then native-endian, unlike what was assumed
> > in the following commit:
> > 
> > This patch does two things:
> > - extract values from the packed array with shifts, in order to be endian
> >   neutral
> > - convert the resulting values to be32 as expected
> > 
> > Suggested-by: Anton Blanchard <anton@samba.org>
> > Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
> > Reviewed-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
> > Tested-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>
> 
> 
> Hi Greg,
> 
> I'm a bit dense, it's after 8pm, but this seems like it's more complicated than
> it needs to be?
> 
> We get six 64-bit registers back from the hypervisor, they're cpu endian
> obviously, and each is defined to consist of four 2 byte fields.
> 
> So to unpack them, can't we just iterate over those six 64-bit values, which if
> we load them as 64-bit values will be back in cpu endian?
> 
> cheers
> 

First, I was sure I had Cc'd Benjamin... sorry for this omission :)

Hi Michael,

Do you mean something like the following ?

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index b835bf0..fbe5a8b 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1421,8 +1421,11 @@ static long hcall_vphn(unsigned long cpu, __be32 *associativity)
        long retbuf[PLPAR_HCALL9_BUFSIZE] = {0};
        u64 flags = 1;
        int hwcpu = get_hard_smp_processor_id(cpu);
+       int i;
 
        rc = plpar_hcall9(H_HOME_NODE_ASSOCIATIVITY, retbuf, flags, hwcpu);
+       for (i = 0; i < 6; i++)
+               retbuf[i] = cpu_to_be64(retbuf[i]);
        vphn_unpack_associativity(retbuf, associativity);
 
        return rc;

Sure it also works and is a lot simplier... but it adds an extra loop. Also,
if the 3 first elements of the array contain 12 VPHN_FIELD_MSB fields, then
we don't even need to swap the remaining elements: only the parsing code
knows.

On the other hand, I understand this is not a hot path... so what should we
do ?

Cheers.

--
Greg

^ permalink raw reply related

* [PATCH 2/2] powerpc/msi: Use WARN_ON() in msi bitmap selftests
From: Michael Ellerman @ 2014-10-10  8:04 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1412928265-21991-1-git-send-email-mpe@ellerman.id.au>

As demonstrated in the previous commit, the failure message from the msi
bitmap selftests is a bit subtle, it's easy to miss a failure in a busy
boot log.

So drop our check() macro and use WARN_ON() instead. This necessitates
inverting all the conditions as well.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/sysdev/msi_bitmap.c | 54 ++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 8155d93dee1d..73b64c73505b 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -145,69 +145,64 @@ void msi_bitmap_free(struct msi_bitmap *bmp)
 
 #ifdef CONFIG_MSI_BITMAP_SELFTEST
 
-#define check(x)	\
-	if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__);
-
 static void __init test_basics(void)
 {
 	struct msi_bitmap bmp;
 	int rc, i, size = 512;
 
 	/* Can't allocate a bitmap of 0 irqs */
-	check(msi_bitmap_alloc(&bmp, 0, NULL) != 0);
+	WARN_ON(msi_bitmap_alloc(&bmp, 0, NULL) == 0);
 
 	/* of_node may be NULL */
-	check(0 == msi_bitmap_alloc(&bmp, size, NULL));
+	WARN_ON(msi_bitmap_alloc(&bmp, size, NULL));
 
 	/* Should all be free by default */
-	check(0 == bitmap_find_free_region(bmp.bitmap, size,
-					   get_count_order(size)));
+	WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
 	bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
 	/* With no node, there's no msi-available-ranges, so expect > 0 */
-	check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+	WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
 
 	/* Should all still be free */
-	check(0 == bitmap_find_free_region(bmp.bitmap, size,
-					   get_count_order(size)));
+	WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
 	bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
 	/* Check we can fill it up and then no more */
 	for (i = 0; i < size; i++)
-		check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
+		WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
 
-	check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0);
+	WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0);
 
 	/* Should all be allocated */
-	check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0);
+	WARN_ON(bitmap_find_free_region(bmp.bitmap, size, 0) >= 0);
 
 	/* And if we free one we can then allocate another */
 	msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2);
+	WARN_ON(msi_bitmap_alloc_hwirqs(&bmp, 1) != size / 2);
 
 	/* Free most of them for the alignment tests */
 	msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
 
 	/* Check we get a naturally aligned offset */
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
-	check(rc >= 0 && rc % 2 == 0);
+	WARN_ON(rc < 0 && rc % 2 != 0);
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
-	check(rc >= 0 && rc % 4 == 0);
+	WARN_ON(rc < 0 && rc % 4 != 0);
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
-	check(rc >= 0 && rc % 8 == 0);
+	WARN_ON(rc < 0 && rc % 8 != 0);
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
-	check(rc >= 0 && rc % 16 == 0);
+	WARN_ON(rc < 0 && rc % 16 != 0);
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
-	check(rc >= 0 && rc % 4 == 0);
+	WARN_ON(rc < 0 && rc % 4 != 0);
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
-	check(rc >= 0 && rc % 8 == 0);
+	WARN_ON(rc < 0 && rc % 8 != 0);
 	rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
-	check(rc >= 0 && rc % 128 == 0);
+	WARN_ON(rc < 0 && rc % 128 != 0);
 
 	msi_bitmap_free(&bmp);
 
-	/* Clients may check bitmap == NULL for "not-allocated" */
-	check(bmp.bitmap == NULL);
+	/* Clients may WARN_ON bitmap == NULL for "not-allocated" */
+	WARN_ON(bmp.bitmap != NULL);
 
 	kfree(bmp.bitmap);
 }
@@ -229,14 +224,13 @@ static void __init test_of_node(void)
 	of_node_init(&of_node);
 	of_node.full_name = node_name;
 
-	check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
+	WARN_ON(msi_bitmap_alloc(&bmp, size, &of_node));
 
 	/* No msi-available-ranges, so expect > 0 */
-	check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0);
+	WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp) <= 0);
 
 	/* Should all still be free */
-	check(0 == bitmap_find_free_region(bmp.bitmap, size,
-					   get_count_order(size)));
+	WARN_ON(bitmap_find_free_region(bmp.bitmap, size, get_count_order(size)));
 	bitmap_release_region(bmp.bitmap, 0, get_count_order(size));
 
 	/* Now create a fake msi-available-ranges property */
@@ -250,11 +244,11 @@ static void __init test_of_node(void)
 	of_node.properties = &prop;
 
 	/* msi-available-ranges, so expect == 0 */
-	check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0);
+	WARN_ON(msi_bitmap_reserve_dt_hwirqs(&bmp));
 
 	/* Check we got the expected result */
-	check(0 == bitmap_parselist(expected_str, expected, size));
-	check(bitmap_equal(expected, bmp.bitmap, size));
+	WARN_ON(bitmap_parselist(expected_str, expected, size));
+	WARN_ON(!bitmap_equal(expected, bmp.bitmap, size));
 
 	msi_bitmap_free(&bmp);
 	kfree(bmp.bitmap);
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/2] powerpc/msi: Fix the msi bitmap alignment tests
From: Michael Ellerman @ 2014-10-10  8:04 UTC (permalink / raw)
  To: linuxppc-dev

When we added the alignment tests recently we failed to check they were
actually passing - oops.

They weren't passing, because the bitmap was full. We should also be a
bit more careful when checking the return code, a negative error return
could by divisible by our alignment value.

Fixes: b0345bbc6d09 ("powerpc/msi: Improve IRQ bitmap allocator")
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
---
 arch/powerpc/sysdev/msi_bitmap.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 0c75214b6f92..8155d93dee1d 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -151,7 +151,7 @@ void msi_bitmap_free(struct msi_bitmap *bmp)
 static void __init test_basics(void)
 {
 	struct msi_bitmap bmp;
-	int i, size = 512;
+	int rc, i, size = 512;
 
 	/* Can't allocate a bitmap of 0 irqs */
 	check(msi_bitmap_alloc(&bmp, 0, NULL) != 0);
@@ -185,14 +185,24 @@ static void __init test_basics(void)
 	msi_bitmap_free_hwirqs(&bmp, size / 2, 1);
 	check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2);
 
+	/* Free most of them for the alignment tests */
+	msi_bitmap_free_hwirqs(&bmp, 3, size - 3);
+
 	/* Check we get a naturally aligned offset */
-	check(msi_bitmap_alloc_hwirqs(&bmp, 2) % 2 == 0);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 4) % 4 == 0);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 8) % 8 == 0);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 9) % 16 == 0);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 3) % 4 == 0);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 7) % 8 == 0);
-	check(msi_bitmap_alloc_hwirqs(&bmp, 121) % 128 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 2);
+	check(rc >= 0 && rc % 2 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 4);
+	check(rc >= 0 && rc % 4 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 8);
+	check(rc >= 0 && rc % 8 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 9);
+	check(rc >= 0 && rc % 16 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 3);
+	check(rc >= 0 && rc % 4 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 7);
+	check(rc >= 0 && rc % 8 == 0);
+	rc = msi_bitmap_alloc_hwirqs(&bmp, 121);
+	check(rc >= 0 && rc % 128 == 0);
 
 	msi_bitmap_free(&bmp);
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH 1/3] qe-uart: modify qe-uart to adapt both powerpc and arm
From: Zhao Qiang @ 2014-10-10  6:47 UTC (permalink / raw)
  To: linuxppc-dev, linux-arm-kernel, linux-serial, B07421; +Cc: Zhao Qiang, R63061

qe has been supported by arm board ls1021, qe-uart need
to be supported by ls1021.
modify the code to make qe-uart can work on both powerpc
and ls1021.

Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
 arch/arm/include/asm/delay.h  |  16 ++++
 arch/arm/include/asm/io.h     |  28 +++++++
 arch/arm/include/asm/irq.h    |   2 +
 arch/arm/kernel/irq.c         |   7 ++
 drivers/soc/qe/Kconfig        |   1 -
 drivers/soc/qe/qe.c           |  63 ++++++++-------
 drivers/soc/qe/qe_common.c    |   2 +-
 drivers/soc/qe/qe_ic.c        |   7 +-
 drivers/soc/qe/qe_io.c        |  53 ++++++-------
 drivers/soc/qe/ucc_slow.c     |  40 +++++-----
 drivers/tty/serial/ucc_uart.c | 176 +++++++++++++++++++++---------------------
 include/linux/fsl/qe.h        |  21 +++++
 12 files changed, 245 insertions(+), 171 deletions(-)

diff --git a/arch/arm/include/asm/delay.h b/arch/arm/include/asm/delay.h
index dff714d..a932f99 100644
--- a/arch/arm/include/asm/delay.h
+++ b/arch/arm/include/asm/delay.h
@@ -57,6 +57,22 @@ extern void __bad_udelay(void);
 			__const_udelay((n) * UDELAY_MULT)) :		\
 	  __udelay(n))
 
+#define spin_event_timeout(condition, timeout, delay)                          \
+({                                                                             \
+	typeof(condition) __ret;                                               \
+	int i = 0;							       \
+	while (!(__ret = (condition)) && (i++ < timeout)) {		       \
+		if (delay)                                                     \
+			udelay(delay);                                         \
+		else                                                           \
+			cpu_relax();					       \
+		udelay(1);						       \
+	}								       \
+	if (!__ret)                                                            \
+		__ret = (condition);                                           \
+	__ret;		                                                       \
+})
+
 /* Loop-based definitions for assembly code. */
 extern void __loop_delay(unsigned long loops);
 extern void __loop_udelay(unsigned long usecs);
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index d070741..4bec694 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -206,6 +206,34 @@ extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
 #endif
 #endif
 
+/* access ports */
+#define setbits32(_addr, _v) iowrite32be(ioread32be(_addr) |  (_v), (_addr))
+#define clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr))
+
+#define setbits16(_addr, _v) iowrite16be(ioread16be(_addr) |  (_v), (_addr))
+#define clrbits16(_addr, _v) iowrite16be(ioread16be(_addr) & ~(_v), (_addr))
+
+#define setbits8(_addr, _v) iowrite8(ioread8(_addr) |  (_v), (_addr))
+#define clrbits8(_addr, _v) iowrite8(ioread8(_addr) & ~(_v), (_addr))
+
+/* Clear and set bits in one shot.  These macros can be used to clear and
+ * set multiple bits in a register using a single read-modify-write.  These
+ * macros can also be used to set a multiple-bit bit pattern using a mask,
+ * by specifying the mask in the 'clear' parameter and the new bit pattern
+ * in the 'set' parameter.
+ */
+
+#define clrsetbits_be32(addr, clear, set) \
+	iowrite32be((ioread32be(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_le32(addr, clear, set) \
+	iowrite32le((ioread32le(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_be16(addr, clear, set) \
+	iowrite16be((ioread16be(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_le16(addr, clear, set) \
+	iowrite16le((ioread16le(addr) & ~(clear)) | (set), (addr))
+#define clrsetbits_8(addr, clear, set) \
+	iowrite8((ioread8(addr) & ~(clear)) | (set), (addr))
+
 /*
  *  IO port access primitives
  *  -------------------------
diff --git a/arch/arm/include/asm/irq.h b/arch/arm/include/asm/irq.h
index 53c15de..4358904 100644
--- a/arch/arm/include/asm/irq.h
+++ b/arch/arm/include/asm/irq.h
@@ -30,6 +30,8 @@ extern void asm_do_IRQ(unsigned int, struct pt_regs *);
 void handle_IRQ(unsigned int, struct pt_regs *);
 void init_IRQ(void);
 
+extern irq_hw_number_t virq_to_hw(unsigned int virq);
+
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 extern void (*handle_arch_irq)(struct pt_regs *);
 extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 9723d17..afa204a 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -121,6 +121,13 @@ void __init init_IRQ(void)
 		machine_desc->init_irq();
 }
 
+irq_hw_number_t virq_to_hw(unsigned int virq)
+{
+	struct irq_data *irq_data = irq_get_irq_data(virq);
+	return WARN_ON(!irq_data) ? 0 : irq_data->hwirq;
+}
+EXPORT_SYMBOL_GPL(virq_to_hw);
+
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
 {
diff --git a/drivers/soc/qe/Kconfig b/drivers/soc/qe/Kconfig
index 49118e1..43b984b 100644
--- a/drivers/soc/qe/Kconfig
+++ b/drivers/soc/qe/Kconfig
@@ -4,7 +4,6 @@
 
 config QUICC_ENGINE
 	bool "Freescale QUICC Engine (QE) Support"
-	depends on FSL_SOC && (PPC32 || PPC64)
 	select LIB_RHEAP
 	select CRC32
 	---help---
diff --git a/drivers/soc/qe/qe.c b/drivers/soc/qe/qe.c
index e0926f5..2aaa5b2 100644
--- a/drivers/soc/qe/qe.c
+++ b/drivers/soc/qe/qe.c
@@ -74,8 +74,8 @@ static phys_addr_t qebase = -1;
 phys_addr_t get_qe_base(void)
 {
 	struct device_node *qe;
-	int size;
-	const u32 *prop;
+	int ret;
+	struct resource res;
 
 	if (qebase != -1)
 		return qebase;
@@ -87,9 +87,9 @@ phys_addr_t get_qe_base(void)
 			return qebase;
 	}
 
-	prop = of_get_property(qe, "reg", &size);
-	if (prop && size >= sizeof(*prop))
-		qebase = of_translate_address(qe, prop);
+	ret = of_address_to_resource(qe, 0, &res);
+	if (!ret)
+		qebase = res.start;
 	of_node_put(qe);
 
 	return qebase;
@@ -121,7 +121,7 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
 
 	spin_lock_irqsave(&qe_lock, flags);
 	if (cmd == QE_RESET) {
-		out_be32(&qe_immr->cp.cecr, (u32) (cmd | QE_CR_FLG));
+		iowrite32be((u32) (cmd | QE_CR_FLG), &qe_immr->cp.cecr);
 	} else {
 		if (cmd == QE_ASSIGN_PAGE) {
 			/* Here device is the SNUM, not sub-block */
@@ -138,15 +138,14 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input)
 				mcn_shift = QE_CR_MCN_NORMAL_SHIFT;
 		}
 
-		out_be32(&qe_immr->cp.cecdr, cmd_input);
-		out_be32(&qe_immr->cp.cecr,
-			 (cmd | QE_CR_FLG | ((u32) device << dev_shift) | (u32)
-			  mcn_protocol << mcn_shift));
+		iowrite32be(cmd_input, &qe_immr->cp.cecdr);
+		iowrite32be((cmd | QE_CR_FLG | ((u32) device << dev_shift) |
+			    (u32)mcn_protocol << mcn_shift), &qe_immr->cp.cecr);
 	}
 
 	/* wait for the QE_CR_FLG to clear */
-	ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0,
-			   100, 0);
+	ret = spin_event_timeout((ioread32be(&qe_immr->cp.cecr)
+				& QE_CR_FLG) == 0, 100, 0);
 	/* On timeout (e.g. failure), the expression will be false (ret == 0),
 	   otherwise it will be true (ret == 1). */
 	spin_unlock_irqrestore(&qe_lock, flags);
@@ -170,8 +169,8 @@ static unsigned int brg_clk;
 unsigned int qe_get_brg_clk(void)
 {
 	struct device_node *qe;
-	int size;
-	const u32 *prop;
+	u32 val;
+	int ret;
 
 	if (brg_clk)
 		return brg_clk;
@@ -183,9 +182,9 @@ unsigned int qe_get_brg_clk(void)
 			return brg_clk;
 	}
 
-	prop = of_get_property(qe, "brg-frequency", &size);
-	if (prop && size == sizeof(*prop))
-		brg_clk = *prop;
+	ret = of_property_read_u32_index(qe, "brg-frequency", 0, &val);
+	if (!ret)
+		brg_clk = val;
 
 	of_node_put(qe);
 
@@ -225,7 +224,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
 	tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
 		QE_BRGC_ENABLE | div16;
 
-	out_be32(&qe_immr->brg.brgc[brg - QE_BRG1], tempval);
+	iowrite32be(tempval, &qe_immr->brg.brgc[brg - QE_BRG1]);
 
 	return 0;
 }
@@ -365,9 +364,9 @@ static int qe_sdma_init(void)
 			return -ENOMEM;
 	}
 
-	out_be32(&sdma->sdebcr, (u32) sdma_buf_offset & QE_SDEBCR_BA_MASK);
-	out_be32(&sdma->sdmr, (QE_SDMR_GLB_1_MSK |
-			       (0x1 << QE_SDMR_CEN_SHIFT)));
+	iowrite32be((u32) sdma_buf_offset & QE_SDEBCR_BA_MASK, &sdma->sdebcr);
+	iowrite32be((QE_SDMR_GLB_1_MSK | (0x1 << QE_SDMR_CEN_SHIFT)),
+		   &sdma->sdmr);
 
 	return 0;
 }
@@ -403,14 +402,14 @@ static void qe_upload_microcode(const void *base,
 		pr_info("qe-FM: uploading microcode '%s'\n", ucode->id);
 
 	/* Use auto-increment */
-	out_be32(&qe_immr->iram.iadd, be32_to_cpu(ucode->iram_offset) |
-		QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR);
+	iowrite32be(be32_to_cpu(ucode->iram_offset) | QE_IRAM_IADD_AIE |
+		   QE_IRAM_IADD_BADDR, &qe_immr->iram.iadd);
 
 	for (i = 0; i < be32_to_cpu(ucode->count); i++)
-		out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
+		iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata);
 
 	/* Set I-RAM Ready Register */
-	out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
+	iowrite32be(be32_to_cpu(QE_IRAM_READY), &qe_immr->iram.iready);
 }
 
 /*
@@ -528,11 +527,11 @@ int qe_upload_firmware(const struct qe_firmware *firmware)
 			u32 trap = be32_to_cpu(ucode->traps[j]);
 
 			if (trap)
-				out_be32(&qe_immr->rsp[i].tibcr[j], trap);
+				iowrite32be(trap, &qe_immr->rsp[i].tibcr[j]);
 		}
 
 		/* Enable traps */
-		out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
+		iowrite32be(be32_to_cpu(ucode->eccr), &qe_immr->rsp[i].eccr);
 	}
 
 	qe_firmware_uploaded = 1;
@@ -651,9 +650,9 @@ EXPORT_SYMBOL(qe_get_num_of_risc);
 unsigned int qe_get_num_of_snums(void)
 {
 	struct device_node *qe;
-	int size;
 	unsigned int num_of_snums;
-	const u32 *prop;
+	u32 val;
+	int ret;
 
 	num_of_snums = 28; /* The default number of snum for threads is 28 */
 	qe = of_find_compatible_node(NULL, NULL, "fsl,qe");
@@ -667,9 +666,9 @@ unsigned int qe_get_num_of_snums(void)
 			return num_of_snums;
 	}
 
-	prop = of_get_property(qe, "fsl,qe-num-snums", &size);
-	if (prop && size == sizeof(*prop)) {
-		num_of_snums = *prop;
+	ret = of_property_read_u32_index(qe, "fsl,qe-num-snums", 0, &val);
+	if (!ret) {
+		num_of_snums = val;
 		if ((num_of_snums < 28) || (num_of_snums > QE_NUM_OF_SNUM)) {
 			/* No QE ever has fewer than 28 SNUMs */
 			pr_err("QE: number of snum is invalid\n");
diff --git a/drivers/soc/qe/qe_common.c b/drivers/soc/qe/qe_common.c
index e7fdd02..1c7afbb 100644
--- a/drivers/soc/qe/qe_common.c
+++ b/drivers/soc/qe/qe_common.c
@@ -68,7 +68,7 @@ int qe_muram_init(void)
 		}
 	}
 
-	muram_pbase = of_translate_address(np, zero);
+	muram_pbase = (phys_addr_t)of_translate_address(np, zero);
 	if (muram_pbase == (phys_addr_t)OF_BAD_ADDR) {
 		pr_err("Cannot translate zero through CPM muram node");
 		ret = -ENODEV;
diff --git a/drivers/soc/qe/qe_ic.c b/drivers/soc/qe/qe_ic.c
index 1968f22..cc1b8d5 100644
--- a/drivers/soc/qe/qe_ic.c
+++ b/drivers/soc/qe/qe_ic.c
@@ -16,7 +16,10 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/irqdomain.h>
 #include <linux/errno.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/stddef.h>
@@ -177,13 +180,13 @@ static struct qe_ic_info qe_ic_info[] = {
 
 static inline u32 qe_ic_read(__be32  __iomem *base, unsigned int reg)
 {
-	return in_be32(base + (reg >> 2));
+	return ioread32be(base + (reg >> 2));
 }
 
 static inline void qe_ic_write(__be32  __iomem *base, unsigned int reg,
 			       u32 value)
 {
-	out_be32(base + (reg >> 2), value);
+	iowrite32be(value, base + (reg >> 2));
 }
 
 static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
diff --git a/drivers/soc/qe/qe_io.c b/drivers/soc/qe/qe_io.c
index 939e903..7f40d3c 100644
--- a/drivers/soc/qe/qe_io.c
+++ b/drivers/soc/qe/qe_io.c
@@ -24,7 +24,6 @@
 #include <linux/io.h>
 #include <linux/fsl/qe.h>
 #include <asm/prom.h>
-#include <sysdev/fsl_soc.h>
 
 #undef DEBUG
 
@@ -62,16 +61,16 @@ void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
 	pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
 
 	/* Set open drain, if required */
-	tmp_val = in_be32(&par_io->cpodr);
+	tmp_val = ioread32be(&par_io->cpodr);
 	if (open_drain)
-		out_be32(&par_io->cpodr, pin_mask1bit | tmp_val);
+		iowrite32be(pin_mask1bit | tmp_val, &par_io->cpodr);
 	else
-		out_be32(&par_io->cpodr, ~pin_mask1bit & tmp_val);
+		iowrite32be(~pin_mask1bit & tmp_val, &par_io->cpodr);
 
 	/* define direction */
 	tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
-		in_be32(&par_io->cpdir2) :
-		in_be32(&par_io->cpdir1);
+		ioread32be(&par_io->cpdir2) :
+		ioread32be(&par_io->cpdir1);
 
 	/* get all bits mask for 2 bit per port */
 	pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
@@ -83,34 +82,30 @@ void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
 
 	/* clear and set 2 bits mask */
 	if (pin > (QE_PIO_PINS / 2) - 1) {
-		out_be32(&par_io->cpdir2,
-			 ~pin_mask2bits & tmp_val);
+		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cpdir2);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io->cpdir2, new_mask2bits | tmp_val);
+		iowrite32be(new_mask2bits | tmp_val, &par_io->cpdir2);
 	} else {
-		out_be32(&par_io->cpdir1,
-			 ~pin_mask2bits & tmp_val);
+		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cpdir1);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io->cpdir1, new_mask2bits | tmp_val);
+		iowrite32be(new_mask2bits | tmp_val, &par_io->cpdir1);
 	}
 	/* define pin assignment */
 	tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
-		in_be32(&par_io->cppar2) :
-		in_be32(&par_io->cppar1);
+		ioread32be(&par_io->cppar2) :
+		ioread32be(&par_io->cppar1);
 
 	new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
 			(pin % (QE_PIO_PINS / 2) + 1) * 2));
 	/* clear and set 2 bits mask */
 	if (pin > (QE_PIO_PINS / 2) - 1) {
-		out_be32(&par_io->cppar2,
-			 ~pin_mask2bits & tmp_val);
+		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cppar2);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io->cppar2, new_mask2bits | tmp_val);
+		iowrite32be(new_mask2bits | tmp_val, &par_io->cppar2);
 	} else {
-		out_be32(&par_io->cppar1,
-			 ~pin_mask2bits & tmp_val);
+		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cppar1);
 		tmp_val &= ~pin_mask2bits;
-		out_be32(&par_io->cppar1, new_mask2bits | tmp_val);
+		iowrite32be(new_mask2bits | tmp_val, &par_io->cppar1);
 	}
 }
 EXPORT_SYMBOL(__par_io_config_pin);
@@ -138,12 +133,12 @@ int par_io_data_set(u8 port, u8 pin, u8 val)
 	/* calculate pin location */
 	pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
 
-	tmp_val = in_be32(&par_io[port].cpdata);
+	tmp_val = ioread32be(&par_io[port].cpdata);
 
 	if (val == 0)		/* clear */
-		out_be32(&par_io[port].cpdata, ~pin_mask & tmp_val);
+		iowrite32be(~pin_mask & tmp_val, &par_io[port].cpdata);
 	else			/* set */
-		out_be32(&par_io[port].cpdata, pin_mask | tmp_val);
+		iowrite32be(pin_mask | tmp_val, &par_io[port].cpdata);
 
 	return 0;
 }
@@ -200,17 +195,17 @@ static void dump_par_io(void)
 	pr_info("%s: par_io=%p\n", __func__, par_io);
 	for (i = 0; i < num_par_io_ports; i++) {
 		pr_info("	cpodr[%u]=%08x\n", i,
-			in_be32(&par_io[i].cpodr));
+			ioread32be(&par_io[i].cpodr));
 		pr_info("	cpdata[%u]=%08x\n", i,
-			in_be32(&par_io[i].cpdata));
+			ioread32be(&par_io[i].cpdata));
 		pr_info("	cpdir1[%u]=%08x\n", i,
-			in_be32(&par_io[i].cpdir1));
+			ioread32be(&par_io[i].cpdir1));
 		pr_info("	cpdir2[%u]=%08x\n", i,
-			in_be32(&par_io[i].cpdir2));
+			ioread32be(&par_io[i].cpdir2));
 		pr_info("	cppar1[%u]=%08x\n", i,
-			in_be32(&par_io[i].cppar1));
+			ioread32be(&par_io[i].cppar1));
 		pr_info("	cppar2[%u]=%08x\n", i,
-			in_be32(&par_io[i].cppar2));
+			ioread32be(&par_io[i].cppar2));
 	}
 }
 EXPORT_SYMBOL(dump_par_io);
diff --git a/drivers/soc/qe/ucc_slow.c b/drivers/soc/qe/ucc_slow.c
index d023f19..edb1b2e 100644
--- a/drivers/soc/qe/ucc_slow.c
+++ b/drivers/soc/qe/ucc_slow.c
@@ -46,7 +46,7 @@ EXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock);
 
 void ucc_slow_poll_transmitter_now(struct ucc_slow_private *uccs)
 {
-	out_be16(&uccs->us_regs->utodr, UCC_SLOW_TOD);
+	iowrite16be(UCC_SLOW_TOD, &uccs->us_regs->utodr);
 }
 
 void ucc_slow_graceful_stop_tx(struct ucc_slow_private *uccs)
@@ -88,7 +88,7 @@ void ucc_slow_enable(struct ucc_slow_private *uccs, enum comm_dir mode)
 	us_regs = uccs->us_regs;
 
 	/* Enable reception and/or transmission on this UCC. */
-	gumr_l = in_be32(&us_regs->gumr_l);
+	gumr_l = ioread32be(&us_regs->gumr_l);
 	if (mode & COMM_DIR_TX) {
 		gumr_l |= UCC_SLOW_GUMR_L_ENT;
 		uccs->enabled_tx = 1;
@@ -97,7 +97,7 @@ void ucc_slow_enable(struct ucc_slow_private *uccs, enum comm_dir mode)
 		gumr_l |= UCC_SLOW_GUMR_L_ENR;
 		uccs->enabled_rx = 1;
 	}
-	out_be32(&us_regs->gumr_l, gumr_l);
+	iowrite32be(gumr_l, &us_regs->gumr_l);
 }
 EXPORT_SYMBOL(ucc_slow_enable);
 
@@ -109,7 +109,7 @@ void ucc_slow_disable(struct ucc_slow_private *uccs, enum comm_dir mode)
 	us_regs = uccs->us_regs;
 
 	/* Disable reception and/or transmission on this UCC. */
-	gumr_l = in_be32(&us_regs->gumr_l);
+	gumr_l = ioread32be(&us_regs->gumr_l);
 	if (mode & COMM_DIR_TX) {
 		gumr_l &= ~UCC_SLOW_GUMR_L_ENT;
 		uccs->enabled_tx = 0;
@@ -118,7 +118,7 @@ void ucc_slow_disable(struct ucc_slow_private *uccs, enum comm_dir mode)
 		gumr_l &= ~UCC_SLOW_GUMR_L_ENR;
 		uccs->enabled_rx = 0;
 	}
-	out_be32(&us_regs->gumr_l, gumr_l);
+	iowrite32be(gumr_l, &us_regs->gumr_l);
 }
 EXPORT_SYMBOL(ucc_slow_disable);
 
@@ -209,7 +209,7 @@ int ucc_slow_init(struct ucc_slow_info *us_info,
 		return ret;
 	}
 
-	out_be16(&uccs->us_pram->mrblr, us_info->max_rx_buf_length);
+	iowrite16be(us_info->max_rx_buf_length, &uccs->us_pram->mrblr);
 
 	INIT_LIST_HEAD(&uccs->confQ);
 
@@ -239,27 +239,27 @@ int ucc_slow_init(struct ucc_slow_info *us_info,
 	bd = uccs->confBd = uccs->tx_bd = qe_muram_addr(uccs->tx_base_offset);
 	for (i = 0; i < us_info->tx_bd_ring_len - 1; i++) {
 		/* clear bd buffer */
-		out_be32(&bd->buf, 0);
+		iowrite32be(0, &bd->buf);
 		/* set bd status and length */
-		out_be32((u32 *) bd, 0);
+		iowrite32be(0, (u32 *) bd);
 		bd++;
 	}
 	/* for last BD set Wrap bit */
-	out_be32(&bd->buf, 0);
-	out_be32((u32 *) bd, cpu_to_be32(T_W));
+	iowrite32be(0, &bd->buf);
+	iowrite32be(T_W, (u32 *) bd);
 
 	/* Init Rx bds */
 	bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
 	for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
 		/* set bd status and length */
-		out_be32((u32 *)bd, 0);
+		iowrite32be(0, (u32 *)bd);
 		/* clear bd buffer */
-		out_be32(&bd->buf, 0);
+		iowrite32be(0, &bd->buf);
 		bd++;
 	}
 	/* for last BD set Wrap bit */
-	out_be32((u32 *)bd, cpu_to_be32(R_W));
-	out_be32(&bd->buf, 0);
+	iowrite32be(R_W, (u32 *)bd);
+	iowrite32be(0, &bd->buf);
 
 	/* Set GUMR (For more details see the hardware spec.). */
 	/* gumr_h */
@@ -280,7 +280,7 @@ int ucc_slow_init(struct ucc_slow_info *us_info,
 		gumr |= UCC_SLOW_GUMR_H_TXSY;
 	if (us_info->rtsm)
 		gumr |= UCC_SLOW_GUMR_H_RTSM;
-	out_be32(&us_regs->gumr_h, gumr);
+	iowrite32be(gumr, &us_regs->gumr_h);
 
 	/* gumr_l */
 	gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |
@@ -293,7 +293,7 @@ int ucc_slow_init(struct ucc_slow_info *us_info,
 		gumr |= UCC_SLOW_GUMR_L_TINV;
 	if (us_info->tend)
 		gumr |= UCC_SLOW_GUMR_L_TEND;
-	out_be32(&us_regs->gumr_l, gumr);
+	iowrite32be(gumr, &us_regs->gumr_l);
 
 	/* Function code registers */
 
@@ -303,8 +303,8 @@ int ucc_slow_init(struct ucc_slow_info *us_info,
 	uccs->us_pram->rbmr = UCC_BMR_BO_BE;
 
 	/* rbase, tbase are offsets from MURAM base */
-	out_be16(&uccs->us_pram->rbase, uccs->rx_base_offset);
-	out_be16(&uccs->us_pram->tbase, uccs->tx_base_offset);
+	iowrite16be(uccs->rx_base_offset, &uccs->us_pram->rbase);
+	iowrite16be(uccs->tx_base_offset, &uccs->us_pram->tbase);
 
 	/* Mux clocking */
 	/* Grant Support */
@@ -334,14 +334,14 @@ int ucc_slow_init(struct ucc_slow_info *us_info,
 	}
 
 	/* Set interrupt mask register at UCC level. */
-	out_be16(&us_regs->uccm, us_info->uccm_mask);
+	iowrite16be(us_info->uccm_mask, &us_regs->uccm);
 
 	/* First, clear anything pending at UCC level,
 	 * otherwise, old garbage may come through
 	 * as soon as the dam is opened. */
 
 	/* Writing '1' clears */
-	out_be16(&us_regs->ucce, 0xffff);
+	iowrite16be(0xffff, &us_regs->ucce);
 
 	/* Issue QE Init command */
 	if (us_info->init_tx && us_info->init_rx)
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 4718ebe..2c9a87c 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -26,13 +26,13 @@
 #include <linux/tty_flip.h>
 #include <linux/io.h>
 #include <linux/of_platform.h>
+#include <linux/of_irq.h>
 #include <linux/dma-mapping.h>
 
 #include <linux/fs_uart_pd.h>
 #include <linux/fsl/ucc_slow.h>
 
 #include <linux/firmware.h>
-#include <asm/reg.h>
 
 /*
  * The GUMR flag for Soft UART.  This would normally be defined in qe.h,
@@ -257,11 +257,11 @@ static unsigned int qe_uart_tx_empty(struct uart_port *port)
 	struct qe_bd *bdp = qe_port->tx_bd_base;
 
 	while (1) {
-		if (in_be16(&bdp->status) & BD_SC_READY)
+		if (ioread16be(&bdp->status) & BD_SC_READY)
 			/* This BD is not done, so return "not done" */
 			return 0;
 
-		if (in_be16(&bdp->status) & BD_SC_WRAP)
+		if (ioread16be(&bdp->status) & BD_SC_WRAP)
 			/*
 			 * This BD is done and it's the last one, so return
 			 * "done"
@@ -339,13 +339,13 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
 		/* Pick next descriptor and fill from buffer */
 		bdp = qe_port->tx_cur;
 
-		p = qe2cpu_addr(bdp->buf, qe_port);
+		p = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port);
 
 		*p++ = port->x_char;
-		out_be16(&bdp->length, 1);
+		iowrite16be(1, &bdp->length);
 		setbits16(&bdp->status, BD_SC_READY);
 		/* Get next BD. */
-		if (in_be16(&bdp->status) & BD_SC_WRAP)
+		if (ioread16be(&bdp->status) & BD_SC_WRAP)
 			bdp = qe_port->tx_bd_base;
 		else
 			bdp++;
@@ -364,10 +364,10 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
 	/* Pick next descriptor and fill from buffer */
 	bdp = qe_port->tx_cur;
 
-	while (!(in_be16(&bdp->status) & BD_SC_READY) &&
+	while (!(ioread16be(&bdp->status) & BD_SC_READY) &&
 	       (xmit->tail != xmit->head)) {
 		count = 0;
-		p = qe2cpu_addr(bdp->buf, qe_port);
+		p = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port);
 		while (count < qe_port->tx_fifosize) {
 			*p++ = xmit->buf[xmit->tail];
 			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -377,11 +377,11 @@ static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
 				break;
 		}
 
-		out_be16(&bdp->length, count);
+		iowrite16be(count, &bdp->length);
 		setbits16(&bdp->status, BD_SC_READY);
 
 		/* Get next BD. */
-		if (in_be16(&bdp->status) & BD_SC_WRAP)
+		if (ioread16be(&bdp->status) & BD_SC_WRAP)
 			bdp = qe_port->tx_bd_base;
 		else
 			bdp++;
@@ -414,7 +414,7 @@ static void qe_uart_start_tx(struct uart_port *port)
 		container_of(port, struct uart_qe_port, port);
 
 	/* If we currently are transmitting, then just return */
-	if (in_be16(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX)
+	if (ioread16be(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX)
 		return;
 
 	/* Otherwise, pump the port and start transmission */
@@ -479,14 +479,14 @@ static void qe_uart_int_rx(struct uart_qe_port *qe_port)
 	 */
 	bdp = qe_port->rx_cur;
 	while (1) {
-		status = in_be16(&bdp->status);
+		status = ioread16be(&bdp->status);
 
 		/* If this one is empty, then we assume we've read them all */
 		if (status & BD_SC_EMPTY)
 			break;
 
 		/* get number of characters, and check space in RX buffer */
-		i = in_be16(&bdp->length);
+		i = ioread16be(&bdp->length);
 
 		/* If we don't have enough room in RX buffer for the entire BD,
 		 * then we try later, which will be the next RX interrupt.
@@ -497,7 +497,7 @@ static void qe_uart_int_rx(struct uart_qe_port *qe_port)
 		}
 
 		/* get pointer */
-		cp = qe2cpu_addr(bdp->buf, qe_port);
+		cp = qe2cpu_addr(be32_to_cpu(bdp->buf), qe_port);
 
 		/* loop through the buffer */
 		while (i-- > 0) {
@@ -519,7 +519,7 @@ error_return:
 		/* This BD is ready to be used again. Clear status. get next */
 		clrsetbits_be16(&bdp->status, BD_SC_BR | BD_SC_FR | BD_SC_PR |
 			BD_SC_OV | BD_SC_ID, BD_SC_EMPTY);
-		if (in_be16(&bdp->status) & BD_SC_WRAP)
+		if (ioread16be(&bdp->status) & BD_SC_WRAP)
 			bdp = qe_port->rx_bd_base;
 		else
 			bdp++;
@@ -578,8 +578,8 @@ static irqreturn_t qe_uart_int(int irq, void *data)
 	u16 events;
 
 	/* Clear the interrupts */
-	events = in_be16(&uccp->ucce);
-	out_be16(&uccp->ucce, events);
+	events = ioread16be(&uccp->ucce);
+	iowrite16be(events, &uccp->ucce);
 
 	if (events & UCC_UART_UCCE_BRKE)
 		uart_handle_break(&qe_port->port);
@@ -610,17 +610,17 @@ static void qe_uart_initbd(struct uart_qe_port *qe_port)
 	bdp = qe_port->rx_bd_base;
 	qe_port->rx_cur = qe_port->rx_bd_base;
 	for (i = 0; i < (qe_port->rx_nrfifos - 1); i++) {
-		out_be16(&bdp->status, BD_SC_EMPTY | BD_SC_INTRPT);
-		out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
-		out_be16(&bdp->length, 0);
+		iowrite16be(BD_SC_EMPTY | BD_SC_INTRPT, &bdp->status);
+		iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf);
+		iowrite16be(0, &bdp->length);
 		bd_virt += qe_port->rx_fifosize;
 		bdp++;
 	}
 
 	/* */
-	out_be16(&bdp->status, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
-	out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
-	out_be16(&bdp->length, 0);
+	iowrite16be(BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT, &bdp->status);
+	iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf);
+	iowrite16be(0, &bdp->length);
 
 	/* Set the physical address of the host memory
 	 * buffers in the buffer descriptors, and the
@@ -631,9 +631,9 @@ static void qe_uart_initbd(struct uart_qe_port *qe_port)
 	qe_port->tx_cur = qe_port->tx_bd_base;
 	bdp = qe_port->tx_bd_base;
 	for (i = 0; i < (qe_port->tx_nrfifos - 1); i++) {
-		out_be16(&bdp->status, BD_SC_INTRPT);
-		out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
-		out_be16(&bdp->length, 0);
+		iowrite16be(BD_SC_INTRPT, &bdp->status);
+		iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf);
+		iowrite16be(0, &bdp->length);
 		bd_virt += qe_port->tx_fifosize;
 		bdp++;
 	}
@@ -643,9 +643,9 @@ static void qe_uart_initbd(struct uart_qe_port *qe_port)
 	setbits16(&qe_port->tx_cur->status, BD_SC_P);
 #endif
 
-	out_be16(&bdp->status, BD_SC_WRAP | BD_SC_INTRPT);
-	out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
-	out_be16(&bdp->length, 0);
+	iowrite16be(BD_SC_WRAP | BD_SC_INTRPT, &bdp->status);
+	iowrite32be(cpu2qe_addr(bd_virt, qe_port), &bdp->buf);
+	iowrite16be(0, &bdp->length);
 }
 
 /*
@@ -667,21 +667,21 @@ static void qe_uart_init_ucc(struct uart_qe_port *qe_port)
 	ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
 
 	/* Program the UCC UART parameter RAM */
-	out_8(&uccup->common.rbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
-	out_8(&uccup->common.tbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
-	out_be16(&uccup->common.mrblr, qe_port->rx_fifosize);
-	out_be16(&uccup->maxidl, 0x10);
-	out_be16(&uccup->brkcr, 1);
-	out_be16(&uccup->parec, 0);
-	out_be16(&uccup->frmec, 0);
-	out_be16(&uccup->nosec, 0);
-	out_be16(&uccup->brkec, 0);
-	out_be16(&uccup->uaddr[0], 0);
-	out_be16(&uccup->uaddr[1], 0);
-	out_be16(&uccup->toseq, 0);
+	iowrite8(UCC_BMR_GBL | UCC_BMR_BO_BE, &uccup->common.rbmr);
+	iowrite8(UCC_BMR_GBL | UCC_BMR_BO_BE, &uccup->common.tbmr);
+	iowrite16be(qe_port->rx_fifosize, &uccup->common.mrblr);
+	iowrite16be(0x10, &uccup->maxidl);
+	iowrite16be(1, &uccup->brkcr);
+	iowrite16be(0, &uccup->parec);
+	iowrite16be(0, &uccup->frmec);
+	iowrite16be(0, &uccup->nosec);
+	iowrite16be(0, &uccup->brkec);
+	iowrite16be(0, &uccup->uaddr[0]);
+	iowrite16be(0, &uccup->uaddr[1]);
+	iowrite16be(0, &uccup->toseq);
 	for (i = 0; i < 8; i++)
-		out_be16(&uccup->cchars[i], 0xC000);
-	out_be16(&uccup->rccm, 0xc0ff);
+		iowrite16be(0xC000, &uccup->cchars[i]);
+	iowrite16be(0xc0ff, &uccup->rccm);
 
 	/* Configure the GUMR registers for UART */
 	if (soft_uart) {
@@ -715,30 +715,30 @@ static void qe_uart_init_ucc(struct uart_qe_port *qe_port)
 #endif
 
 	/* Disable rx interrupts  and clear all pending events.  */
-	out_be16(&uccp->uccm, 0);
-	out_be16(&uccp->ucce, 0xffff);
-	out_be16(&uccp->udsr, 0x7e7e);
+	iowrite16be(0, &uccp->uccm);
+	iowrite16be(0xffff, &uccp->ucce);
+	iowrite16be(0x7e7e, &uccp->udsr);
 
 	/* Initialize UPSMR */
-	out_be16(&uccp->upsmr, 0);
+	iowrite16be(0, &uccp->upsmr);
 
 	if (soft_uart) {
-		out_be16(&uccup->supsmr, 0x30);
-		out_be16(&uccup->res92, 0);
-		out_be32(&uccup->rx_state, 0);
-		out_be32(&uccup->rx_cnt, 0);
-		out_8(&uccup->rx_bitmark, 0);
-		out_8(&uccup->rx_length, 10);
-		out_be32(&uccup->dump_ptr, 0x4000);
-		out_8(&uccup->rx_temp_dlst_qe, 0);
-		out_be32(&uccup->rx_frame_rem, 0);
-		out_8(&uccup->rx_frame_rem_size, 0);
+		iowrite16be(0x30, &uccup->supsmr);
+		iowrite16be(0, &uccup->res92);
+		iowrite32be(0, &uccup->rx_state);
+		iowrite32be(0, &uccup->rx_cnt);
+		iowrite8(0, &uccup->rx_bitmark);
+		iowrite8(10, &uccup->rx_length);
+		iowrite32be(0x4000, &uccup->dump_ptr);
+		iowrite8(0, &uccup->rx_temp_dlst_qe);
+		iowrite32be(0, &uccup->rx_frame_rem);
+		iowrite8(0, &uccup->rx_frame_rem_size);
 		/* Soft-UART requires TX to be 1X */
-		out_8(&uccup->tx_mode,
-			UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1);
-		out_be16(&uccup->tx_state, 0);
-		out_8(&uccup->resD4, 0);
-		out_be16(&uccup->resD5, 0);
+		iowrite8(UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1,
+			 &uccup->tx_mode);
+		iowrite16be(0, &uccup->tx_state);
+		iowrite8(0, &uccup->resD4);
+		iowrite16be(0, &uccup->resD5);
 
 		/* Set UART mode.
 		 * Enable receive and transmit.
@@ -866,9 +866,9 @@ static void qe_uart_set_termios(struct uart_port *port,
 	struct ucc_slow __iomem *uccp = qe_port->uccp;
 	unsigned int baud;
 	unsigned long flags;
-	u16 upsmr = in_be16(&uccp->upsmr);
+	u16 upsmr = ioread16be(&uccp->upsmr);
 	struct ucc_uart_pram __iomem *uccup = qe_port->uccup;
-	u16 supsmr = in_be16(&uccup->supsmr);
+	u16 supsmr = ioread16be(&uccup->supsmr);
 	u8 char_length = 2; /* 1 + CL + PEN + 1 + SL */
 
 	/* Character length programmed into the mode register is the
@@ -966,10 +966,10 @@ static void qe_uart_set_termios(struct uart_port *port,
 	/* Update the per-port timeout. */
 	uart_update_timeout(port, termios->c_cflag, baud);
 
-	out_be16(&uccp->upsmr, upsmr);
+	iowrite16be(upsmr, &uccp->upsmr);
 	if (soft_uart) {
-		out_be16(&uccup->supsmr, supsmr);
-		out_8(&uccup->rx_length, char_length);
+		iowrite16be(supsmr, &uccup->supsmr);
+		iowrite8(char_length, &uccup->rx_length);
 
 		/* Soft-UART requires a 1X multiplier for TX */
 		qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
@@ -1139,7 +1139,9 @@ static unsigned int soc_info(unsigned int *rev_h, unsigned int *rev_l)
 {
 	struct device_node *np;
 	const char *soc_string;
+#ifdef CONFIG_PPC_85xx
 	unsigned int svr;
+#endif
 	unsigned int soc;
 
 	/* Find the CPU node */
@@ -1156,10 +1158,12 @@ static unsigned int soc_info(unsigned int *rev_h, unsigned int *rev_l)
 	if ((sscanf(soc_string, "PowerPC,%u", &soc) != 1) || !soc)
 		return 0;
 
+#ifdef CONFIG_PPC_85xx
 	/* Get the revision from the SVR */
 	svr = mfspr(SPRN_SVR);
 	*rev_h = (svr >> 4) & 0xf;
 	*rev_l = svr & 0xf;
+#endif
 
 	return soc;
 }
@@ -1202,7 +1206,7 @@ static void uart_firmware_cont(const struct firmware *fw, void *context)
 static int ucc_uart_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
-	const unsigned int *iprop;      /* Integer OF properties */
+	u32 val;
 	const char *sprop;      /* String OF properties */
 	struct uart_qe_port *qe_port = NULL;
 	struct resource res;
@@ -1285,10 +1289,10 @@ static int ucc_uart_probe(struct platform_device *ofdev)
 
 	/* Get the UCC number (device ID) */
 	/* UCCs are numbered 1-7 */
-	iprop = of_get_property(np, "cell-index", NULL);
-	if (!iprop) {
-		iprop = of_get_property(np, "device-id", NULL);
-		if (!iprop) {
+	ret = of_property_read_u32_index(np, "cell-index", 0, &val);
+	if (ret) {
+		ret = of_property_read_u32_index(np, "device-id", 0, &val);
+		if (ret) {
 			dev_err(&ofdev->dev, "UCC is unspecified in "
 				"device tree\n");
 			ret = -EINVAL;
@@ -1296,12 +1300,12 @@ static int ucc_uart_probe(struct platform_device *ofdev)
 		}
 	}
 
-	if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
-		dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop);
+	if ((val < 1) || (val > UCC_MAX_NUM)) {
+		dev_err(&ofdev->dev, "no support for UCC%u\n", val);
 		ret = -ENODEV;
 		goto out_free;
 	}
-	qe_port->ucc_num = *iprop - 1;
+	qe_port->ucc_num = val - 1;
 
 	/*
 	 * In the future, we should not require the BRG to be specified in the
@@ -1345,13 +1349,13 @@ static int ucc_uart_probe(struct platform_device *ofdev)
 	}
 
 	/* Get the port number, numbered 0-3 */
-	iprop = of_get_property(np, "port-number", NULL);
-	if (!iprop) {
+	ret = of_property_read_u32_index(np, "port-number", 0, &val);
+	if (ret) {
 		dev_err(&ofdev->dev, "missing port-number in device tree\n");
 		ret = -EINVAL;
 		goto out_free;
 	}
-	qe_port->port.line = *iprop;
+	qe_port->port.line = val;
 	if (qe_port->port.line >= UCC_MAX_UART) {
 		dev_err(&ofdev->dev, "port-number must be 0-%u\n",
 			UCC_MAX_UART - 1);
@@ -1381,31 +1385,31 @@ static int ucc_uart_probe(struct platform_device *ofdev)
 		}
 	}
 
-	iprop = of_get_property(np, "brg-frequency", NULL);
-	if (!iprop) {
+	ret = of_property_read_u32_index(np, "brg-frequency", 0, &val);
+	if (ret) {
 		dev_err(&ofdev->dev,
 		       "missing brg-frequency in device tree\n");
 		ret = -EINVAL;
 		goto out_np;
 	}
 
-	if (*iprop)
-		qe_port->port.uartclk = *iprop;
+	if (val)
+		qe_port->port.uartclk = val;
 	else {
 		/*
 		 * Older versions of U-Boot do not initialize the brg-frequency
 		 * property, so in this case we assume the BRG frequency is
 		 * half the QE bus frequency.
 		 */
-		iprop = of_get_property(np, "bus-frequency", NULL);
-		if (!iprop) {
+		ret = of_property_read_u32_index(np, "bus-frequency", 0, &val);
+		if (ret) {
 			dev_err(&ofdev->dev,
 				"missing QE bus-frequency in device tree\n");
 			ret = -EINVAL;
 			goto out_np;
 		}
-		if (*iprop)
-			qe_port->port.uartclk = *iprop / 2;
+		if (val)
+			qe_port->port.uartclk = val / 2;
 		else {
 			dev_err(&ofdev->dev,
 				"invalid QE bus-frequency in device tree\n");
diff --git a/include/linux/fsl/qe.h b/include/linux/fsl/qe.h
index 5a6a647..ef4422c 100644
--- a/include/linux/fsl/qe.h
+++ b/include/linux/fsl/qe.h
@@ -306,6 +306,27 @@ struct qe_bd {
 #define BD_STATUS_MASK	0xffff0000
 #define BD_LENGTH_MASK	0x0000ffff
 
+/* Buffer descriptor control/status used by serial
+ */
+
+#define BD_SC_EMPTY	(0x8000)	/* Receive is empty */
+#define BD_SC_READY	(0x8000)	/* Transmit is ready */
+#define BD_SC_WRAP	(0x2000)	/* Last buffer descriptor */
+#define BD_SC_INTRPT	(0x1000)	/* Interrupt on change */
+#define BD_SC_LAST	(0x0800)	/* Last buffer in frame */
+#define BD_SC_TC	(0x0400)	/* Transmit CRC */
+#define BD_SC_CM	(0x0200)	/* Continuous mode */
+#define BD_SC_ID	(0x0100)	/* Rec'd too many idles */
+#define BD_SC_P		(0x0100)	/* xmt preamble */
+#define BD_SC_BR	(0x0020)	/* Break received */
+#define BD_SC_FR	(0x0010)	/* Framing error */
+#define BD_SC_PR	(0x0008)	/* Parity error */
+#define BD_SC_NAK	(0x0004)	/* NAK - did not respond */
+#define BD_SC_OV	(0x0002)	/* Overrun */
+#define BD_SC_UN	(0x0002)	/* Underrun */
+#define BD_SC_CD	(0x0001)	/* */
+#define BD_SC_CL	(0x0001)	/* Collision */
+
 /* Alignment */
 #define QE_INTR_TABLE_ALIGN	16	/* ??? */
 #define QE_ALIGNMENT_OF_BD	8
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH 3/3] ls1021a-twr/qe: add qe node to ls1-twr
From: Zhao Qiang @ 2014-10-10  6:49 UTC (permalink / raw)
  To: linuxppc-dev, linux-arm-kernel, devicetree, B07421; +Cc: Zhao Qiang, R63061

add qe node to ls1021atwr fdt.

Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
 arch/arm/boot/dts/ls1021a-twr.dts | 24 +++++++++++++++
 arch/arm/boot/dts/ls1021a.dtsi    | 64 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+)

diff --git a/arch/arm/boot/dts/ls1021a-twr.dts b/arch/arm/boot/dts/ls1021a-twr.dts
index a52be7b..415387f 100755
--- a/arch/arm/boot/dts/ls1021a-twr.dts
+++ b/arch/arm/boot/dts/ls1021a-twr.dts
@@ -164,6 +164,30 @@
 	};
 };
 
+&uqe {
+	tdma: ucc@2000 {
+		compatible = "fsl,ucc-tdm";
+		rx-clock-name = "clk8";
+		tx-clock-name = "clk9";
+		fsl,rx-sync-clock = "rsync_pin";
+		fsl,tx-sync-clock = "tsync_pin";
+		fsl,tx-timeslot = <0xfffffffe>;
+		fsl,rx-timeslot = <0xfffffffe>;
+		fsl,tdm-framer-type = "e1";
+		fsl,tdm-mode = "normal";
+		fsl,tdm-id = <0>;
+		fsl,siram-entry-id = <0>;
+	};
+
+	serial: ucc@2200 {
+		device_type = "serial";
+		compatible = "ucc_uart";
+		port-number = <1>;
+		rx-clock-name = "brg2";
+		tx-clock-name = "brg2";
+	};
+};
+
 &pwm6 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/ls1021a.dtsi b/arch/arm/boot/dts/ls1021a.dtsi
index 80747dc..3f2ab89 100644
--- a/arch/arm/boot/dts/ls1021a.dtsi
+++ b/arch/arm/boot/dts/ls1021a.dtsi
@@ -314,6 +314,70 @@
 			status = "disabled";
 		};
 
+		uqe: uqe@2400000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			device_type = "qe";
+			compatible = "fsl,qe", "simple-bus";
+			ranges = <0x0 0x0 0x2400000 0x40000>;
+			reg = <0x0 0x2400000 0x0 0x480>;
+			brg-frequency = <100000000>;
+			bus-frequency = <200000000>;
+
+			fsl,qe-num-riscs = <1>;
+			fsl,qe-num-snums = <28>;
+
+			qeic: qeic@80 {
+				compatible = "fsl,qe-ic";
+				reg = <0x80 0x80>;
+				#address-cells = <0>;
+				interrupt-controller;
+				#interrupt-cells = <1>;
+				interrupts = <0 109 0x04 0 109 0x04>;
+			};
+
+			si1: si@700 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "fsl,qe-si";
+				reg = <0x700 0x80>;
+			};
+
+			siram1: siram@1000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,qe-siram";
+				reg = <0x1000 0x800>;
+			};
+
+			ucc@2000 {
+				cell-index = <1>;
+				reg = <0x2000 0x200>;
+				interrupts = <32>;
+				interrupt-parent = <&qeic>;
+			};
+
+			ucc@2200 {
+				cell-index = <3>;
+				reg = <0x2200 0x200>;
+				interrupts = <34>;
+				interrupt-parent = <&qeic>;
+			};
+
+			muram@10000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "fsl,qe-muram", "fsl,cpm-muram";
+				ranges = <0x0 0x10000 0x6000>;
+
+				data-only@0 {
+					compatible = "fsl,qe-muram-data",
+					"fsl,cpm-muram-data";
+					reg = <0x0 0x6000>;
+				};
+			};
+		};
+
 		lpuart0: serial@2950000 {
 			compatible = "fsl,ls1021a-lpuart";
 			reg = <0x0 0x2950000 0x0 0x1000>;
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* [PATCH 2/3] qe: run qe_init and qe_ic_init
From: Zhao Qiang @ 2014-10-10  6:48 UTC (permalink / raw)
  To: linuxppc-dev, linux-kernel, B07421; +Cc: Zhao Qiang, R63061

qe and qe_ic need to be initialized before the
qe app drivers, using subsys_initcall to run
qe_init and qe_ic_init

Signed-off-by: Zhao Qiang <B45475@freescale.com>
---
 drivers/soc/qe/qe.c    | 15 +++++++++++++++
 drivers/soc/qe/qe_ic.c | 15 +++++++++++++++
 2 files changed, 30 insertions(+)

diff --git a/drivers/soc/qe/qe.c b/drivers/soc/qe/qe.c
index 2aaa5b2..bfea0f8 100644
--- a/drivers/soc/qe/qe.c
+++ b/drivers/soc/qe/qe.c
@@ -683,6 +683,21 @@ unsigned int qe_get_num_of_snums(void)
 }
 EXPORT_SYMBOL(qe_get_num_of_snums);
 
+static int __init qe_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe");
+	if (!np) {
+		pr_err("%s: Could not find Quicc Engine node\n", __func__);
+		return -ENODEV;
+	}
+	qe_reset();
+	of_node_put(np);
+	return 0;
+}
+subsys_initcall(qe_init);
+
 #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx)
 static int qe_resume(struct platform_device *ofdev)
 {
diff --git a/drivers/soc/qe/qe_ic.c b/drivers/soc/qe/qe_ic.c
index cc1b8d5..11fe98c 100644
--- a/drivers/soc/qe/qe_ic.c
+++ b/drivers/soc/qe/qe_ic.c
@@ -34,6 +34,7 @@
 #include <linux/fsl/qe_ic.h>
 
 #include "qe_ic.h"
+#include "../../irqchip/irqchip.h"
 
 static DEFINE_RAW_SPINLOCK(qe_ic_lock);
 
@@ -501,4 +502,18 @@ static int __init init_qe_ic_sysfs(void)
 	return 0;
 }
 
+static int __init qeic_of_init(void)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
+	if (np) {
+		qe_ic_init(np, 0, qe_ic_cascade_low_mpic,
+			   qe_ic_cascade_high_mpic);
+		of_node_put(np);
+	}
+	return 0;
+}
+subsys_initcall(qeic_of_init);
+
 subsys_initcall(init_qe_ic_sysfs);
-- 
2.1.0.27.g96db324

^ permalink raw reply related

* Re: powerpc/powernv: Fallback to old HMI handling behavior for old firmware
From: Michael Ellerman @ 2014-10-10  6:23 UTC (permalink / raw)
  To: Mahesh Salgaonkar, linuxppc-dev, Benjamin Herrenschmidt; +Cc: Paul Mackerras
In-Reply-To: <20141006093358.1828.36741.stgit@mars>

On Mon, 2014-06-10 at 09:34:19 UTC, Mahesh Salgaonkar wrote:
> From: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com>

Hi Mahesh,

> Recently we moved HMI handling into Linux kernel instead of taking
> HMI directly in OPAL. This new change is dependent on new OPAL call
> for HMI recovery which was introduced in newer firmware. While this new
> change works fine with latest OPAL firmware, we broke the HMI handling
> if we run newer kernel on old OPAL firmware that results in system hang.
> 
> This patch fixes this issue by falling back to old HMI behavior on older
> OPAL firmware.

It sounds like "older" firmware is actually "the currently released firmware".
The "newer" firmware is still in development, is that right?

If so please update the comment and changelog to better reflect that.

> diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
> index b44eec3..2768cd3 100644
> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -194,6 +194,24 @@ static int __init opal_register_exception_handlers(void)
>  	 * fwnmi area at 0x7000 to provide the glue space to OPAL
>  	 */
>  	glue = 0x7000;
> +
> +	/* Check if we are running on newer firmware that exports

Please format your long comments like:

/*
 * Check if we are ..
 */

I know some of our code uses the other style but this is the commonly accepted
style.

> +	 * OPAL_HANDLE_HMI token. If yes, then don't ask opal to patch
> +	 * HMI interrupt and we catch it directly in Linux kernel.
> +	 *
> +	 * For older firmware we will fallback to old behavior and
> +	 * let OPAL patch the HMI vector and handle it inside OPAL
> +	 * firmware.
> +	 */
> +	if (opal_check_token(OPAL_HANDLE_HMI) != OPAL_TOKEN_PRESENT) {

OPAL_TOKEN_PRESENT was dropped from the API. Just use:

	if (!opal_check_token(OPAL_HANDLE_HMI)) {

> +		/* We are on old firmware. fallback to old behavior. */
> +		pr_info("%s: Falling back to old HMI handling behavior.\n",
> +			__func__);

Please just use "opal: " rather than __func__.

And rather than the user having to know what the old vs new behaviour is, can
you make it explicit in the message, eg:

"opal: Old firmware detected, letting OPAL handle HMIs."

> +		opal_register_exception_handler(
> +				OPAL_HYPERVISOR_MAINTENANCE_HANDLER,
> +				0, glue);
> +		glue += 128;
> +	}

Newline here please.

>  	opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue);
>  #endif


cheers

^ permalink raw reply

* [PATCH] powerpc: Wire up sys_bpf() syscall
From: Pranith Kumar @ 2014-10-10  5:53 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
	Anton Blanchard, David Herrmann, Andrew Morton, Fabian Frederick,
	open list:LINUX FOR POWERPC..., open list

This patch wires up the new syscall sys_bpf() on powerpc.

Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
---
 arch/powerpc/include/asm/systbl.h      | 1 +
 arch/powerpc/include/asm/unistd.h      | 2 +-
 arch/powerpc/include/uapi/asm/unistd.h | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h
index 7d8a600..ce9577d 100644
--- a/arch/powerpc/include/asm/systbl.h
+++ b/arch/powerpc/include/asm/systbl.h
@@ -365,3 +365,4 @@ SYSCALL_SPU(renameat2)
 SYSCALL_SPU(seccomp)
 SYSCALL_SPU(getrandom)
 SYSCALL_SPU(memfd_create)
+SYSCALL_SPU(bpf)
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h
index 4e9af3f..e0da021 100644
--- a/arch/powerpc/include/asm/unistd.h
+++ b/arch/powerpc/include/asm/unistd.h
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls		361
+#define __NR_syscalls		362
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff --git a/arch/powerpc/include/uapi/asm/unistd.h b/arch/powerpc/include/uapi/asm/unistd.h
index 0688fc0..f55351f 100644
--- a/arch/powerpc/include/uapi/asm/unistd.h
+++ b/arch/powerpc/include/uapi/asm/unistd.h
@@ -383,5 +383,6 @@
 #define __NR_seccomp		358
 #define __NR_getrandom		359
 #define __NR_memfd_create	360
+#define __NR_bpf		361
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
-- 
2.1.0

^ permalink raw reply related

* [PATCH] powerpc: Fix Text randomization
From: Vineeth Vijayan @ 2014-10-10  5:45 UTC (permalink / raw)
  To: benh, linuxppc-dev, linux-kernel; +Cc: Vineeth Vijayan

Right now there is no way to disable TEXT randomization on a PPC32
machine. text randomization happens even in the case of "echo 0 >
/proc/sys/kernel/randomize_va_space"

This happens due to the incorrect definition of ELF_ET_DYN_BASE at
arch/powerpc/include/asm/elf.h

Signed-off-by: Vineeth Vijayan <vvijayan@mvista.com>
---
Test details:

#include <stdio.h>

int main(int argc,char *argv)
{
        printf("main = %p\n",main);
        return 0;
}

Compile the same as position-independent executable

Results without Patch:

p5040ds:~# gcc test.c -o test -fPIE -pie
p5040ds:~# echo 2 > /proc/sys/kernel/randomize_va_space 
p5040ds:~# ./test 
main = 0xb7e9681c
p5040ds:~# ./test 
main = 0xb7aba81c
p5040ds:~# ./test 
main = 0xb7fac81c
p5040ds:~# ./test 
main = 0xb7f4c81c
p5040ds:~# echo 0 > /proc/sys/kernel/randomize_va_space                                                                                                                                              
p5040ds:~# ./test 
main = 0x2010281c
p5040ds:~# ./test 
main = 0x2018d81c
p5040ds:~# ./test 
main = 0x206a981c
p5040ds:~# ./test 
main = 0x2036681c


Results with Patch:

p5040ds:~# gcc test.c -o test -fPIE -pie
p5040ds:~# 
p5040ds:~# echo 2 > /proc/sys/kernel/randomize_va_space 
p5040ds:~# 
p5040ds:~# ./test 
main = 0xb78a581c
p5040ds:~# ./test 
main = 0xb792c81c
p5040ds:~# ./test 
main = 0xb79de81c
p5040ds:~# ./test 
main = 0xb78ae81c
p5040ds:~# echo 0 > /proc/sys/kernel/randomize_va_space                                                                                                                                              
p5040ds:~# 
p5040ds:~# ./test 
main = 0x2000081c
p5040ds:~# ./test 
main = 0x2000081c
p5040ds:~# ./test 
main = 0x2000081c
p5040ds:~# ./test 
main = 0x2000081c


 arch/powerpc/Kconfig           |    1 +
 arch/powerpc/include/asm/elf.h |    2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4bc7b62..f99ddae 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -88,6 +88,7 @@ config PPC
 	select ARCH_MIGHT_HAVE_PC_PARPORT
 	select ARCH_MIGHT_HAVE_PC_SERIO
 	select BINFMT_ELF
+	select ARCH_BINFMT_ELF_RANDOMIZE_PIE
 	select OF
 	select OF_EARLY_FLATTREE
 	select OF_RESERVED_MEM
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h
index 888d8f3..162813b 100644
--- a/arch/powerpc/include/asm/elf.h
+++ b/arch/powerpc/include/asm/elf.h
@@ -29,7 +29,7 @@
    that it will "exec", and that there is sufficient room for the brk.  */
 
 extern unsigned long randomize_et_dyn(unsigned long base);
-#define ELF_ET_DYN_BASE		(randomize_et_dyn(0x20000000))
+#define ELF_ET_DYN_BASE		(0x20000000)
 
 #define ELF_CORE_EFLAGS (is_elf2_task() ? 2 : 0)
 
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH] net: fs_enet: error: 'SCCE_ENET_TXF' undeclared
From: David Miller @ 2014-10-10  4:51 UTC (permalink / raw)
  To: christophe.leroy; +Cc: netdev, linuxppc-dev, linux-kernel, vbordug
In-Reply-To: <20141009145443.74AD61AB275@localhost.localdomain>

From: Christophe Leroy <christophe.leroy@c-s.fr>
Date: Thu,  9 Oct 2014 16:54:43 +0200 (CEST)

> [linux-devel:devel-hourly-2014100909 3763/3915] drivers/net/ethernet/freescale/fs_enet/mac-scc.c:119:32: error: 'SCCE_ENET_TXF' undeclared
> 
> Due to patch d43a396 net: fs_enet: Add NAPI TX, it appears that some target
> compilations are broken.
> This is due to the fact that unlike the FEC, the SCC and FCC don't have a TXF
> event (complete Frame transmitted) but only TXB (buffer transmitted).
> 
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>

Applied, thanks.

^ permalink raw reply

* Re: [v2] powerpc/numa: add ability to disable and debug topology updates
From: Michael Ellerman @ 2014-10-10  4:28 UTC (permalink / raw)
  To: Nishanth Aravamudan; +Cc: Nathan Fontenot, Paul Mackerras, linuxppc-dev
In-Reply-To: <20141009234215.GC30604@linux.vnet.ibm.com>

On Thu, 2014-09-10 at 23:42:15 UTC, Nishanth Aravamudan wrote:
> We have hit a few customer issues with the topology update code (VPHN
> and PRRN). It would be nice to be able to debug the notifications coming
> from the hypervisor in both cases to the LPAR, as well as to disable
> responding to the notifications at boot-time, to narrow down the source
> of the problems. Add a basic level of such functionality, similar to the
> numa= command-line parameter. We already have a toggle in
> /proc/powerpc/topology_updates that allows run-time enabling/disabling,
> so the updates can be started at run-time if desired. But the bugs we've
> run into have occured during boot or very shortly after coming to login,
> and have resulted in a broken NUMA topology.

Thanks Nish, a couple of minor nits.

> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
> index e28c21ba862d..ad240a41d3e4 100644
> --- a/arch/powerpc/mm/numa.c
> +++ b/arch/powerpc/mm/numa.c
> @@ -45,6 +45,7 @@ static char *cmdline __initdata;
>  
>  static int numa_debug;
>  #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
> +#define pr_fmt(fmt) "numa: " fmt

This needs to come before printk.h to take effect, typically it goes before all
headers.

> @@ -1160,6 +1161,22 @@ static int __init early_numa(char *p)
>  }
>  early_param("numa", early_numa);
>  
> +static int topology_updates_enabled = 1;

bool ?

> +static int __init early_topology_updates(char *p)
> +{
> +	if (!p)
> +		return 0;
> +
> +	if (strstr(p, "off")) {

You're better off using strcmp. Using strstr() is nice if you need to support
multiple values, but it's sloppy otherwise. This will match "offset",
"smirnoff" etc.

> @@ -1807,7 +1836,9 @@ static const struct file_operations topology_ops = {
>  
>  static int topology_update_init(void)
>  {
> -	start_topology_update();
> +	/* Do not poll for changes if disabled at boot */
> +	if (topology_updates_enabled)
> +		start_topology_update();

Newline please!

>  	if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
>  		return -ENOMEM;

cheers

^ permalink raw reply

* [PATCH v2] powerpc/numa: add ability to disable and debug topology updates
From: Nishanth Aravamudan @ 2014-10-09 23:42 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Nathan Fontenot, Paul Mackerras, linuxppc-dev

We have hit a few customer issues with the topology update code (VPHN
and PRRN). It would be nice to be able to debug the notifications coming
from the hypervisor in both cases to the LPAR, as well as to disable
responding to the notifications at boot-time, to narrow down the source
of the problems. Add a basic level of such functionality, similar to the
numa= command-line parameter. We already have a toggle in
/proc/powerpc/topology_updates that allows run-time enabling/disabling,
so the updates can be started at run-time if desired. But the bugs we've
run into have occured during boot or very shortly after coming to login,
and have resulted in a broken NUMA topology.

Signed-off-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>

---
v1 -> v2:
 Updated commit message to answer some of mpe's reviews.
 Switched to pr_fmt based debugging, which removes the need for the
   debug flag.
 Be a little less verbose in the debugging, as it was duplicating
   information.

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d9a452e8fb9b..35a46b8240ad 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -3388,6 +3388,12 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			e.g. base its process migration decisions on it.
 			Default is on.
 
+	topology_updates= [KNL, PPC, NUMA]
+			Format: {off}
+			Specify if the kernel should ignore (off)
+			topology updates sent by the hypervisor to this
+			LPAR.
+
 	tp720=		[HW,PS2]
 
 	tpm_suspend_pcr=[HW,TPM]
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index e28c21ba862d..ad240a41d3e4 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -45,6 +45,7 @@ static char *cmdline __initdata;
 
 static int numa_debug;
 #define dbg(args...) if (numa_debug) { printk(KERN_INFO args); }
+#define pr_fmt(fmt) "numa: " fmt
 
 int numa_cpu_lookup_table[NR_CPUS];
 cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
@@ -1160,6 +1161,22 @@ static int __init early_numa(char *p)
 }
 early_param("numa", early_numa);
 
+static int topology_updates_enabled = 1;
+
+static int __init early_topology_updates(char *p)
+{
+	if (!p)
+		return 0;
+
+	if (strstr(p, "off")) {
+		pr_info("Disabling topology updates\n");
+		topology_updates_enabled = 0;
+	}
+
+	return 0;
+}
+early_param("topology_updates", early_topology_updates);
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 /*
  * Find the node associated with a hot added memory section for
@@ -1546,6 +1563,9 @@ int arch_update_cpu_topology(void)
 	struct device *dev;
 	int weight, new_nid, i = 0;
 
+	if (!prrn_enabled && !vphn_enabled)
+		return 0;
+
 	weight = cpumask_weight(&cpu_associativity_changes_mask);
 	if (!weight)
 		return 0;
@@ -1599,6 +1619,15 @@ int arch_update_cpu_topology(void)
 		cpu = cpu_last_thread_sibling(cpu);
 	}
 
+	pr_debug("Topology update for the following CPUs:\n");
+	if (cpumask_weight(&updated_cpus)) {
+		for (ud = &updates[0]; ud; ud = ud->next) {
+			pr_debug("cpu %d moving from node %d "
+					  "to %d\n", ud->cpu,
+					  ud->old_nid, ud->new_nid);
+		}
+	}
+
 	/*
 	 * In cases where we have nothing to update (because the updates list
 	 * is too short or because the new topology is same as the old one),
@@ -1807,7 +1836,9 @@ static const struct file_operations topology_ops = {
 
 static int topology_update_init(void)
 {
-	start_topology_update();
+	/* Do not poll for changes if disabled at boot */
+	if (topology_updates_enabled)
+		start_topology_update();
 	if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
 		return -ENOMEM;
 

^ permalink raw reply related

* [PATCH] powerpc/numa: check error return from proc_create
From: Nishanth Aravamudan @ 2014-10-09 23:41 UTC (permalink / raw)
  To: Michael Ellerman; +Cc: Nathan Fontenot, Paul Mackerras, linuxppc-dev

proc_create can fail, we should check the return value and pass up the
failure.

Suggested-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Nishanth Aravamudan <nacc@linux.vnet.ibm.com>

diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index d7737a542fd7..e28c21ba862d 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1808,7 +1808,8 @@ static const struct file_operations topology_ops = {
 static int topology_update_init(void)
 {
 	start_topology_update();
-	proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops);
+	if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
+		return -ENOMEM;
 
 	return 0;
 }

^ permalink raw reply related

* Re: [PATCH 08/44] kernel: Move pm_power_off to common code
From: Pavel Machek @ 2014-10-09 20:24 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: linux-m32r-ja, linux-mips, linux-efi, linux-ia64, Steven Miao,
	linux-xtensa, Boris Ostrovsky, Catalin Marinas, Will Deacon,
	David Howells, Max Filippov, Paul Mackerras, Ralf Baechle,
	H. Peter Anvin, Guan Xuetao, Thomas Gleixner, Lennox Wu,
	Hans-Christian Egtvedt, devel, linux-s390, Jesper Nilsson, lguest,
	Russell King, linux-c6x-dev, Len Brown, David S. Miller,
	linux-hexagon, Hirokazu Takata, linux-sh, James E.J. Bottomley,
	linux-acpi, Ingo Molnar, Geert Uytterhoeven, Mark Salter,
	xen-devel, Matt Turner, Chen Liqin, Jonas Bonn,
	Haavard Skinnemoen, devicetree, James Hogan,
	user-mode-linux-devel, linux-pm, Aurelien Jacquiot,
	Heiko Carstens, Jeff Dike, adi-buildroot-devel, Chris Metcalf,
	Konrad Rzeszutek Wilk, Mikael Starvik, Richard Weinberger,
	linux-m68k, linux-am33-list, Ivan Kokshaysky, linux-tegra,
	openipmi-developer, linux-metag, linux-arm-kernel,
	Richard Henderson, Chris Zankel, Michal Simek, Tony Luck,
	linux-parisc, linux-cris-kernel, Vineet Gupta, Rafael J. Wysocki,
	linux-kernel, Fenghua Yu, Richard Kuo, David Vrabel, linux-alpha,
	Martin Schwidefsky, Koichi Yasutake, linuxppc-dev, Helge Deller
In-Reply-To: <54368A30.9070101@roeck-us.net>

Hi!

> >>@@ -184,6 +179,8 @@ machine_halt(void)
> >>  void
> >>  machine_power_off(void)
> >>  {
> >>+	do_kernel_poweroff();
> >>+
> >
> >poweroff -> power_off for consistency.
> >
> Dunno; matter of personal preference. I started with that, but ultimately went
> with poweroff to distinguish poweroff handler functions from existing code,
> specifically kernel_power_off().

That works for you, but once it is merged, it is ugly/confusing typo.
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: [PATCH 12/44] mfd: ab8500-sysctrl: Register with kernel poweroff handler
From: Guenter Roeck @ 2014-10-09 15:54 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-m32r-ja@ml.linux-m32r.org, linux-mips@linux-mips.org,
	linux-m68k@vger.kernel.org, linux-efi@vger.kernel.org,
	linux-ia64@vger.kernel.org, linux-sh@vger.kernel.org,
	Catalin Marinas, Linus Walleij, devicetree@vger.kernel.org,
	devel@driverdev.osuosl.org, linux-s390@vger.kernel.org,
	lguest@lists.ozlabs.org, linux-c6x-dev@linux-c6x.org,
	linux-hexagon@vger.kernel.org, linux-acpi@vger.kernel.org,
	xen-devel@lists.xenproject.org, linux-xtensa@linux-xtensa.org,
	user-mode-linux-devel@lists.sourceforge.net,
	linux-pm@vger.kernel.org,
	adi-buildroot-devel@lists.sourceforge.net,
	linux-am33-list@redhat.com, linux-tegra@vger.kernel.org,
	openipmi-developer@lists.sourceforge.net,
	linux-metag@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	Samuel Ortiz, linux-cris-kernel@axis.com,
	linux-parisc@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-alpha@vger.kernel.org, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <20141009104927.GN20647@lee--X1>

On Thu, Oct 09, 2014 at 11:49:27AM +0100, Lee Jones wrote:
> On Thu, 09 Oct 2014, Catalin Marinas wrote:
> 
> > On Tue, Oct 07, 2014 at 09:00:48AM +0100, Lee Jones wrote:
> > > On Mon, 06 Oct 2014, Guenter Roeck wrote:
> > > > --- a/drivers/mfd/ab8500-sysctrl.c
> > > > +++ b/drivers/mfd/ab8500-sysctrl.c
> > > > @@ -6,6 +6,7 @@
> > > 
> > > [...]
> > > 
> > > > +static int ab8500_power_off(struct notifier_block *this, unsigned long unused1,
> > > > +			    void *unused2)
> > > >  {
> > > >  	sigset_t old;
> > > >  	sigset_t all;
> > > > @@ -34,11 +36,6 @@ static void ab8500_power_off(void)
> > > >  	struct power_supply *psy;
> > > >  	int ret;
> > > >  
> > > > -	if (sysctrl_dev == NULL) {
> > > > -		pr_err("%s: sysctrl not initialized\n", __func__);
> > > > -		return;
> > > > -	}
> > > 
> > > Can you explain the purpose of this change please?
> > 
> > I guess it's because the sysctrl_dev is already initialised when
> > registering the power_off handler, so there isn't a way to call the
> > above function with a NULL sysctrl_dev. Probably even with the original
> > code you didn't need this check (after some race fix in
> > ab8500_sysctrl_remove but races is one of the things Guenter's patches
> > try to address).
> 
> Sounds reasonable, although I think this change should be part of
> another patch.
> 
Turns out the options are to either drop the check or to use the device
managed function to register the poweroff handler. I decided to keep
the check and use the device managed function.

Guenter

^ permalink raw reply


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