LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 04/15] powerpc/boot: add byteswapping routines in oflib
From: Cédric Le Goater @ 2014-04-14  7:47 UTC (permalink / raw)
  To: benh; +Cc: Cédric Le Goater, linuxppc-dev
In-Reply-To: <1395651884.30488.10.camel@pasglop>

Values will need to be byte-swapped when calling prom (big endian) from
a little endian boot wrapper.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 arch/powerpc/boot/of.h        |    3 +++
 arch/powerpc/boot/ofconsole.c |    6 ++++--
 arch/powerpc/boot/oflib.c     |   22 +++++++++++-----------
 3 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index 5da03d9b9463..40d95bf7402b 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -20,4 +20,7 @@ void of_console_init(void);
 
 typedef u32			__be32;
 
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+
 #endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/ofconsole.c b/arch/powerpc/boot/ofconsole.c
index ce0e02424453..8b754702460a 100644
--- a/arch/powerpc/boot/ofconsole.c
+++ b/arch/powerpc/boot/ofconsole.c
@@ -18,7 +18,7 @@
 
 #include "of.h"
 
-static void *of_stdout_handle;
+static unsigned int of_stdout_handle;
 
 static int of_console_open(void)
 {
@@ -27,8 +27,10 @@ static int of_console_open(void)
 	if (((devp = of_finddevice("/chosen")) != NULL)
 	    && (of_getprop(devp, "stdout", &of_stdout_handle,
 			   sizeof(of_stdout_handle))
-		== sizeof(of_stdout_handle)))
+		== sizeof(of_stdout_handle))) {
+		of_stdout_handle = be32_to_cpu(of_stdout_handle);
 		return 0;
+	}
 
 	return -1;
 }
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index 3b0c9458504f..0f72b1a42133 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -42,13 +42,13 @@ int of_call_prom(const char *service, int nargs, int nret, ...)
 	struct prom_args args;
 	va_list list;
 
-	args.service = ADDR(service);
-	args.nargs = nargs;
-	args.nret = nret;
+	args.service = cpu_to_be32(ADDR(service));
+	args.nargs = cpu_to_be32(nargs);
+	args.nret = cpu_to_be32(nret);
 
 	va_start(list, nret);
 	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, prom_arg_t);
+		args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
 	va_end(list);
 
 	for (i = 0; i < nret; i++)
@@ -57,7 +57,7 @@ int of_call_prom(const char *service, int nargs, int nret, ...)
 	if (prom(&args) < 0)
 		return -1;
 
-	return (nret > 0)? args.args[nargs]: 0;
+	return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
 }
 
 static int of_call_prom_ret(const char *service, int nargs, int nret,
@@ -67,13 +67,13 @@ static int of_call_prom_ret(const char *service, int nargs, int nret,
 	struct prom_args args;
 	va_list list;
 
-	args.service = ADDR(service);
-	args.nargs = nargs;
-	args.nret = nret;
+	args.service = cpu_to_be32(ADDR(service));
+	args.nargs = cpu_to_be32(nargs);
+	args.nret = cpu_to_be32(nret);
 
 	va_start(list, rets);
 	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, prom_arg_t);
+		args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
 	va_end(list);
 
 	for (i = 0; i < nret; i++)
@@ -84,9 +84,9 @@ static int of_call_prom_ret(const char *service, int nargs, int nret,
 
 	if (rets != (void *) 0)
 		for (i = 1; i < nret; ++i)
-			rets[i-1] = args.args[nargs+i];
+			rets[i-1] = be32_to_cpu(args.args[nargs+i]);
 
-	return (nret > 0)? args.args[nargs]: 0;
+	return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
 }
 
 /* returns true if s2 is a prefix of s1 */
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v2 03/15] powerpc/boot: use prom_arg_t in oflib
From: Cédric Le Goater @ 2014-04-14  7:47 UTC (permalink / raw)
  To: benh; +Cc: Cédric Le Goater, linuxppc-dev
In-Reply-To: <1395651884.30488.10.camel@pasglop>

This patch updates the wrapper code to converge with the kernel code in
prom_init.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 arch/powerpc/boot/oflib.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index c3288a3446b3..3b0c9458504f 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -16,6 +16,8 @@
 
 #include "of.h"
 
+typedef u32 prom_arg_t;
+
 /* The following structure is used to communicate with open firmware.
  * All arguments in and out are in big endian format. */
 struct prom_args {
@@ -46,7 +48,7 @@ int of_call_prom(const char *service, int nargs, int nret, ...)
 
 	va_start(list, nret);
 	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
+		args.args[i] = va_arg(list, prom_arg_t);
 	va_end(list);
 
 	for (i = 0; i < nret; i++)
@@ -59,7 +61,7 @@ int of_call_prom(const char *service, int nargs, int nret, ...)
 }
 
 static int of_call_prom_ret(const char *service, int nargs, int nret,
-			    unsigned int *rets, ...)
+			    prom_arg_t *rets, ...)
 {
 	int i;
 	struct prom_args args;
@@ -71,7 +73,7 @@ static int of_call_prom_ret(const char *service, int nargs, int nret,
 
 	va_start(list, rets);
 	for (i = 0; i < nargs; i++)
-		args.args[i] = va_arg(list, unsigned int);
+		args.args[i] = va_arg(list, prom_arg_t);
 	va_end(list);
 
 	for (i = 0; i < nret; i++)
@@ -148,7 +150,7 @@ static int check_of_version(void)
 void *of_claim(unsigned long virt, unsigned long size, unsigned long align)
 {
 	int ret;
-	unsigned int result;
+	prom_arg_t result;
 
 	if (need_map < 0)
 		need_map = check_of_version();
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v2 02/15] powerpc/boot: use a common prom_args struct in oflib
From: Cédric Le Goater @ 2014-04-14  7:47 UTC (permalink / raw)
  To: benh; +Cc: Cédric Le Goater, linuxppc-dev
In-Reply-To: <1395651884.30488.10.camel@pasglop>

This patch fixes warnings when the wrapper is compiled in 64bit and
updates the boot wrapper code related to prom to converge with the
kernel code in prom_init. This should make the review of changes easier.

The kernel has a different number of possible arguments (10) when
entering prom. There does not seem to be any good reason to have
12 in the wrapper, so the patch changes this value to args[10] in
the prom_args struct.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 arch/powerpc/boot/of.h    |    2 ++
 arch/powerpc/boot/oflib.c |   29 +++++++++++++++--------------
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/arch/powerpc/boot/of.h b/arch/powerpc/boot/of.h
index e4c68f7391c5..5da03d9b9463 100644
--- a/arch/powerpc/boot/of.h
+++ b/arch/powerpc/boot/of.h
@@ -18,4 +18,6 @@ int of_setprop(const void *phandle, const char *name, const void *buf,
 /* Console functions */
 void of_console_init(void);
 
+typedef u32			__be32;
+
 #endif /* _PPC_BOOT_OF_H_ */
diff --git a/arch/powerpc/boot/oflib.c b/arch/powerpc/boot/oflib.c
index b0ec9cf3eaaf..c3288a3446b3 100644
--- a/arch/powerpc/boot/oflib.c
+++ b/arch/powerpc/boot/oflib.c
@@ -16,6 +16,15 @@
 
 #include "of.h"
 
+/* The following structure is used to communicate with open firmware.
+ * All arguments in and out are in big endian format. */
+struct prom_args {
+	__be32 service;	/* Address of service name string. */
+	__be32 nargs;	/* Number of input arguments. */
+	__be32 nret;	/* Number of output arguments. */
+	__be32 args[10];	/* Input/output arguments. */
+};
+
 static int (*prom) (void *);
 
 void of_init(void *promptr)
@@ -23,18 +32,15 @@ void of_init(void *promptr)
 	prom = (int (*)(void *))promptr;
 }
 
+#define ADDR(x)		(u32)(unsigned long)(x)
+
 int of_call_prom(const char *service, int nargs, int nret, ...)
 {
 	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
+	struct prom_args args;
 	va_list list;
 
-	args.service = service;
+	args.service = ADDR(service);
 	args.nargs = nargs;
 	args.nret = nret;
 
@@ -56,15 +62,10 @@ static int of_call_prom_ret(const char *service, int nargs, int nret,
 			    unsigned int *rets, ...)
 {
 	int i;
-	struct prom_args {
-		const char *service;
-		int nargs;
-		int nret;
-		unsigned int args[12];
-	} args;
+	struct prom_args args;
 	va_list list;
 
-	args.service = service;
+	args.service = ADDR(service);
 	args.nargs = nargs;
 	args.nret = nret;
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v2 00/15] powerpc/boot: 64bit little endian wrapper
From: Cédric Le Goater @ 2014-04-14  7:46 UTC (permalink / raw)
  To: benh; +Cc: Cédric Le Goater, linuxppc-dev
In-Reply-To: <1395651884.30488.10.camel@pasglop>

Hi,

The following patchset adds support for 64bit little endian boot 
wrapper. It is based on original code from Andrew Tauferner. 

The first patches provide fixes for 64bit support. I also changed 
the prom code to make it converge with the prom_init kernel code. 
They have a lot in common and they could probably be merged.

  powerpc/boot: fix do_div for 64bit wrapper
  powerpc/boot: use a common prom_args struct in oflib
  powerpc/boot: use prom_arg_t in oflib
  powerpc/boot: add byteswapping routines in oflib
  powerpc/boot: add PROM_ERROR define in oflib
  powerpc/boot: rework of_claim() to make it 64bit friendly
  powerpc/boot: define typedef ihandle as u32
  powerpc/boot: fix compile warning in 64bit

These are for little endian only:

  powerpc/boot: define byteswapping routines for little endian
  powerpc/boot: add 64bit and little endian support to addnote
  powerpc/boot: add little endian support to elf utils

and finally, these add support for the 64bit little endian boot 
wrapper :

  powerpc/boot: define a routine to enter prom
  powerpc/boot: modify entry point for 64bit
  powerpc/boot: add a global entry point for pseries
  powerpc/boot: add support for 64bit little endian wrapper

Here are some topics to discuss :

  - to compile in 64bit, -m64 is added to the cross32 compiler.    
  - There are still some compile warnings due to 64bit, in addnote 
    and in the device tree library.
  - the wrapper is compiled as a position independent executable. 

This patchset is based on a 3.15-rc1 and was tested on qemu with 
the -kernel option, yaboot and grub for little and big endian 
guests. Tests were also done to check that the PowerVM stack was
not broken by these changes.

It is also available from :

	https://github.com/legoater/linux zimagev2 

Cheers,

C. 

Changes since v1 :

  - Fixed Makefile for platforms generating a zImage.pseries 
  - used PROM_ERROR (-1u) to test return addr when claiming memory
  - removed patch modifying the call to the kernel entry point
  - merged last 3 patches to preserve bisectability 

Cédric Le Goater (15):
  powerpc/boot: fix do_div for 64bit wrapper
  powerpc/boot: use a common prom_args struct in oflib
  powerpc/boot: use prom_arg_t in oflib
  powerpc/boot: add byteswapping routines in oflib
  powerpc/boot: add PROM_ERROR define in oflib
  powerpc/boot: rework of_claim() to make it 64bit friendly
  powerpc/boot: define typedef ihandle as u32
  powerpc/boot: fix compile warning in 64bit
  powerpc/boot: define byteswapping routines for little endian
  powerpc/boot: add 64bit and little endian support to addnote
  powerpc/boot: add little endian support to elf utils
  powerpc/boot: define a routine to enter prom
  powerpc/boot: modify entry point for 64bit
  powerpc/boot: add a global entry point for pseries
  powerpc/boot: add support for 64bit little endian wrapper

 arch/powerpc/boot/Makefile             |   21 +++-
 arch/powerpc/boot/addnote.c            |  128 +++++++++++++++--------
 arch/powerpc/boot/crt0.S               |  180 +++++++++++++++++++++++++++++++-
 arch/powerpc/boot/elf_util.c           |    4 +
 arch/powerpc/boot/of.c                 |    4 +-
 arch/powerpc/boot/of.h                 |   19 +++-
 arch/powerpc/boot/ofconsole.c          |    6 +-
 arch/powerpc/boot/oflib.c              |   92 ++++++++--------
 arch/powerpc/boot/ppc_asm.h            |   12 +++
 arch/powerpc/boot/pseries-head.S       |    8 ++
 arch/powerpc/boot/stdio.c              |   14 +++
 arch/powerpc/boot/swab.h               |   29 +++++
 arch/powerpc/boot/wrapper              |   17 ++-
 arch/powerpc/boot/zImage.lds.S         |   25 ++++-
 arch/powerpc/platforms/Kconfig.cputype |    5 +
 15 files changed, 464 insertions(+), 100 deletions(-)
 create mode 100644 arch/powerpc/boot/pseries-head.S
 create mode 100644 arch/powerpc/boot/swab.h

-- 
1.7.10.4

^ permalink raw reply

* [PATCH v2 01/15] powerpc/boot: fix do_div for 64bit wrapper
From: Cédric Le Goater @ 2014-04-14  7:47 UTC (permalink / raw)
  To: benh; +Cc: Cédric Le Goater, linuxppc-dev
In-Reply-To: <1395651884.30488.10.camel@pasglop>

When the boot wrapper is compiled in 64bit, there is no need to
use __div64_32.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
---
 arch/powerpc/boot/stdio.c |   14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/powerpc/boot/stdio.c b/arch/powerpc/boot/stdio.c
index 5b57800bbc67..a701261b1781 100644
--- a/arch/powerpc/boot/stdio.c
+++ b/arch/powerpc/boot/stdio.c
@@ -21,6 +21,18 @@ size_t strnlen(const char * s, size_t count)
 	return sc - s;
 }
 
+#ifdef __powerpc64__
+
+# define do_div(n, base) ({						\
+	unsigned int __base = (base);					\
+	unsigned int __rem;						\
+	__rem = ((unsigned long long)(n)) % __base;			\
+	(n) = ((unsigned long long)(n)) / __base;			\
+	__rem;								\
+})
+
+#else
+
 extern unsigned int __div64_32(unsigned long long *dividend,
 			       unsigned int divisor);
 
@@ -39,6 +51,8 @@ extern unsigned int __div64_32(unsigned long long *dividend,
 	__rem;								\
  })
 
+#endif /* __powerpc64__ */
+
 static int skip_atoi(const char **s)
 {
 	int i, c;
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/2] PCI/MSI: Phase out pci_enable_msi_block()
From: Alexander Gordeev @ 2014-04-14  7:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-mips, linux-s390, linux-pci, x86, Alexander Gordeev,
	linuxppc-dev
In-Reply-To: <cover.1397458024.git.agordeev@redhat.com>

There are no users of pci_enable_msi_block() function have
left. Obsolete it in favor of pci_enable_msi_range() and
pci_enable_msi_exact() functions.

Up until now, when enabling MSI mode for a device, a single
successful call to arch_msi_check_device() was followed by
a single call to arch_setup_msi_irqs() function.

Yet, if arch_msi_check_device() returned success we should be
able to call arch_setup_msi_irqs() multiple times - while it
returns a number of MSI vectors that could have been allocated
(a third state).

This update makes use of the assumption described above. It
could have broke things had the architectures done any pre-
allocations or switch to some state in a call to function
arch_msi_check_device(). But because arch_msi_check_device()
is expected stateless and MSI resources are allocated in a
follow-up call to arch_setup_msi_irqs() we should be fine.

Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
Cc: linux-mips@linux-mips.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-s390@vger.kernel.org
Cc: x86@kernel.org
Cc: linux-pci@vger.kernel.org
---
 drivers/pci/msi.c   |   79 +++++++++++++++++++++-----------------------------
 include/linux/pci.h |    5 +--
 2 files changed, 34 insertions(+), 50 deletions(-)

diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 955ab79..fc669ab 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -883,50 +883,6 @@ int pci_msi_vec_count(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_msi_vec_count);
 
-/**
- * pci_enable_msi_block - configure device's MSI capability structure
- * @dev: device to configure
- * @nvec: number of interrupts to configure
- *
- * Allocate IRQs for a device with the MSI capability.
- * This function returns a negative errno if an error occurs.  If it
- * is unable to allocate the number of interrupts requested, it returns
- * the number of interrupts it might be able to allocate.  If it successfully
- * allocates at least the number of interrupts requested, it returns 0 and
- * updates the @dev's irq member to the lowest new interrupt number; the
- * other interrupt numbers allocated to this device are consecutive.
- */
-int pci_enable_msi_block(struct pci_dev *dev, int nvec)
-{
-	int status, maxvec;
-
-	if (dev->current_state != PCI_D0)
-		return -EINVAL;
-
-	maxvec = pci_msi_vec_count(dev);
-	if (maxvec < 0)
-		return maxvec;
-	if (nvec > maxvec)
-		return maxvec;
-
-	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
-	if (status)
-		return status;
-
-	WARN_ON(!!dev->msi_enabled);
-
-	/* Check whether driver already requested MSI-X irqs */
-	if (dev->msix_enabled) {
-		dev_info(&dev->dev, "can't enable MSI "
-			 "(MSI-X already enabled)\n");
-		return -EINVAL;
-	}
-
-	status = msi_capability_init(dev, nvec);
-	return status;
-}
-EXPORT_SYMBOL(pci_enable_msi_block);
-
 void pci_msi_shutdown(struct pci_dev *dev)
 {
 	struct msi_desc *desc;
@@ -1132,14 +1088,45 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
  **/
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
 {
-	int nvec = maxvec;
+	int nvec;
 	int rc;
 
+	if (dev->current_state != PCI_D0)
+		return -EINVAL;
+
+	WARN_ON(!!dev->msi_enabled);
+
+	/* Check whether driver already requested MSI-X irqs */
+	if (dev->msix_enabled) {
+		dev_info(&dev->dev,
+			 "can't enable MSI (MSI-X already enabled)\n");
+		return -EINVAL;
+	}
+
 	if (maxvec < minvec)
 		return -ERANGE;
 
+	nvec = pci_msi_vec_count(dev);
+	if (nvec < 0)
+		return nvec;
+	else if (nvec < minvec)
+		return -EINVAL;
+	else if (nvec > maxvec)
+		nvec = maxvec;
+
+	do {
+		rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
+		if (rc < 0) {
+			return rc;
+		} else if (rc > 0) {
+			if (rc < minvec)
+				return -ENOSPC;
+			nvec = rc;
+		}
+	} while (rc);
+
 	do {
-		rc = pci_enable_msi_block(dev, nvec);
+		rc = msi_capability_init(dev, nvec);
 		if (rc < 0) {
 			return rc;
 		} else if (rc > 0) {
diff --git a/include/linux/pci.h b/include/linux/pci.h
index aab57b4..d8104f4 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1158,7 +1158,6 @@ struct msix_entry {
 
 #ifdef CONFIG_PCI_MSI
 int pci_msi_vec_count(struct pci_dev *dev);
-int pci_enable_msi_block(struct pci_dev *dev, int nvec);
 void pci_msi_shutdown(struct pci_dev *dev);
 void pci_disable_msi(struct pci_dev *dev);
 int pci_msix_vec_count(struct pci_dev *dev);
@@ -1188,8 +1187,6 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,
 }
 #else
 static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
-static inline int pci_enable_msi_block(struct pci_dev *dev, int nvec)
-{ return -ENOSYS; }
 static inline void pci_msi_shutdown(struct pci_dev *dev) { }
 static inline void pci_disable_msi(struct pci_dev *dev) { }
 static inline int pci_msix_vec_count(struct pci_dev *dev) { return -ENOSYS; }
@@ -1244,7 +1241,7 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) { }
 static inline void pcie_ecrc_get_policy(char *str) { }
 #endif
 
-#define pci_enable_msi(pdev)	pci_enable_msi_block(pdev, 1)
+#define pci_enable_msi(pdev)	pci_enable_msi_range(pdev, 1, 1)
 
 #ifdef CONFIG_HT_IRQ
 /* The functions a driver should call */
-- 
1.7.7.6

^ permalink raw reply related

* [PATCH 0/2] Phase out pci_enable_msi_block()
From: Alexander Gordeev @ 2014-04-14  7:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-s390, linux-mips, Greg Kroah-Hartman, x86,
	Alexander Gordeev, linux-pci, linuxppc-dev, Frank Haverkamp

Hello,

This series is against 3.15-rc1.

This update obsoletes pci_enable_msi_block() function in
favor of pci_enable_msi_range() and pci_enable_msi_exact().


Cc: Frank Haverkamp <haver@linux.vnet.ibm.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-mips@linux-mips.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-s390@vger.kernel.org
Cc: x86@kernel.org
Cc: linux-pci@vger.kernel.org


Alexander Gordeev (2):
  GenWQE: Use pci_enable_msi_exact() instead of pci_enable_msi_block()
  PCI/MSI: Phase out pci_enable_msi_block()

 drivers/misc/genwqe/card_utils.c |    2 +-
 drivers/pci/msi.c                |   79 ++++++++++++++++----------------------
 include/linux/pci.h              |    5 +--
 3 files changed, 35 insertions(+), 51 deletions(-)

-- 
1.7.7.6

^ permalink raw reply

* Re: Change MINSIGSTKSZ and SIGSTKSIZE
From: Alan Modra @ 2014-04-14  6:53 UTC (permalink / raw)
  To: Haren Myneni; +Cc: linuxppc-dev
In-Reply-To: <1397296795.11946.42.camel@hbabu-laptop>

On Sat, Apr 12, 2014 at 02:59:55AM -0700, Haren Myneni wrote:
> Alan, 
> 	LTP test (signalstack02) is failing.

Ignore the stupid test.  Do *NOT* change the kernel value to match
glibc.  The two sets of constants are independent.

The glibc constants are for user code, to allocate correctly sized
signal stacks for all known kernels.  These constants are therefore
the maximum values needed for known kernels.

The kernel constants are to check that user code is setting up a large
enough signal stack *for that specific kernel, and user binary*.  If
you make the kernel constants match current glibc, then old binaries
that don't use htm or vsx will fail when run on a newer kernel.

Ideally the kernel would detect whether a binary was going to use htm
or vsx and adjust the minimum sizes, but it's a wee bit difficult for
the kernel to know that ahead of time.

> This test expects -ENOMEM from
> kernel when passing less than stack size (passing 4095). MINSIGSTKSZ in
> signal.h (glibc) is changed to 4096 to support VSX changes
> (https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=f7c399cff5bd04ee9dc117fb6b0f39597dc047c6)  We should also change these values in kernel to match with glibc. Any issues? 
> 
> diff --git a/arch/powerpc/include/uapi/asm/signal.h
> b/arch/powerpc/include/uapi/
> index 6c69ee9..18f498e 100644
> --- a/arch/powerpc/include/uapi/asm/signal.h
> +++ b/arch/powerpc/include/uapi/asm/signal.h
> @@ -85,8 +85,8 @@ typedef struct {
>  
>  #define SA_RESTORER    0x04000000U
>  
> -#define MINSIGSTKSZ    2048
> -#define SIGSTKSZ       8192
> +#define MINSIGSTKSZ    4096
> +#define SIGSTKSZ       16384
> 
> Thanks
> Haren

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply

* Re: [PATCH v3] powerpc: kvm: make _PAGE_NUMA take effect
From: Alexander Graf @ 2014-04-14  6:43 UTC (permalink / raw)
  To: Liu ping fan
  Cc: Liu Ping Fan, kvm@vger.kernel.org mailing list, kvm-ppc,
	Paul Mackerras, Aneesh Kumar K.V, linuxppc-dev
In-Reply-To: <CAFgQCTsbr9_Y24upMSuOTqdO-gAVySBxW=o6uK2UKHk9=uQihw@mail.gmail.com>


On 13.04.14 04:27, Liu ping fan wrote:
> On Fri, Apr 11, 2014 at 10:03 PM, Alexander Graf <agraf@suse.de> wrote:
>> On 11.04.2014, at 13:45, Liu Ping Fan <pingfank@linux.vnet.ibm.com> wrote:
>>
>>> When we mark pte with _PAGE_NUMA we already call mmu_notifier_invalidate_range_start
>>> and mmu_notifier_invalidate_range_end, which will mark existing guest hpte
>>> entry as HPTE_V_ABSENT. Now we need to do that when we are inserting new
>>> guest hpte entries.
>> What happens when we don't? Why do we need the check? Why isn't it done implicitly? What happens when we treat a NUMA marked page as non-present? Why does it work out for us?
>>
>> Assume you have no idea what PAGE_NUMA is, but try to figure out what this patch does and whether you need to cherry-pick it into your downstream kernel. The description as is still is not very helpful for that. It doesn't even explain what really changes with this patch applied.
>>
> Yeah.  what about appending the following description?  Can it make
> the context clear?
> "Guest should not setup a hpte for the page whose pte is marked with
> _PAGE_NUMA, so on the host, the numa-fault mechanism can take effect
> to check whether the page is placed correctly or not."

Try to come up with a text that answers the following questions in order:

   - What does _PAGE_NUMA mean?
   - How does page migration with _PAGE_NUMA work?
   -> Why should we not map pages when _PAGE_NUMA is set?
   - Which part of what needs to be done did the previous _PAGE_NUMA 
patch address?
   - What's the situation without this patch?
   - Which scenario does this patch fix?

Once you have a text that answers those, you should have a good patch 
description :).

Alex

^ permalink raw reply

* RE: [PATCH v3] dmaengine: driver support for FSL RaidEngine device.
From: Xuelin Shi @ 2014-04-14  2:48 UTC (permalink / raw)
  To: Dan Williams
  Cc: Harninder Rai, andriy.shevchenko@intel.com, Koul, Vinod,
	Naveen Burmi, dmaengine@vger.kernel.org, linuxppc-dev
In-Reply-To: <CAA9_cme=Bo3tYi0-bNXBRNLZnC-4FZyaSYZ=3iRD_5xfiVX5Mw@mail.gmail.com>

SGkgRGFuLA0KDQpmc2wgZG1hIGRldmljZSBhbmQgZnNsIHJhaWQgZGV2aWNlIGFyZSB0d28gZGlm
ZmVyZW5jdCBkZXZpY2VzIHRoYXQgYm90aCBwcm92aWRlIGFzeW5jX21lbWNweQ0KY2FwYWJpbGl0
eSwgc28gSSB1c2UgIUZTTF9ETUEgdG8gZGlzYWJsZSB0aGUgZnNsIGRtYSBkZXZpY2UuIA0KDQpU
aGF0J3MgdG8gc2F5LCBlaXRoZXIgc2VsZWN0IGZzbGRtYSBkZXZpY2UsIGVpdGhlciBmc2wgcmFp
ZCBkZXZpY2UuDQoNClRoYW5rcywNClh1ZWxpbiBTaGkNCg0KLS0tLS1PcmlnaW5hbCBNZXNzYWdl
LS0tLS0NCkZyb206IGRhbi5qLndpbGxpYW1zQGdtYWlsLmNvbSBbbWFpbHRvOmRhbi5qLndpbGxp
YW1zQGdtYWlsLmNvbV0gT24gQmVoYWxmIE9mIERhbiBXaWxsaWFtcw0KU2VudDogMjAxNMTqNNTC
MTLI1SAxOjQzDQpUbzogU2hpIFh1ZWxpbi1CMjkyMzcNCkNjOiBLb3VsLCBWaW5vZDsgYW5kcml5
LnNoZXZjaGVua29AaW50ZWwuY29tOyBkbWFlbmdpbmVAdmdlci5rZXJuZWwub3JnOyBsaW51eHBw
Yy1kZXY7IFJhaSBIYXJuaW5kZXItQjAxMDQ0OyBCdXJtaSBOYXZlZW4tQjE2NTAyDQpTdWJqZWN0
OiBSZTogW1BBVENIIHYzXSBkbWFlbmdpbmU6IGRyaXZlciBzdXBwb3J0IGZvciBGU0wgUmFpZEVu
Z2luZSBkZXZpY2UuDQoNCkEgZmV3IG1vcmUgY29tbWVudHM6DQoNCk9uIEZyaSwgQXByIDExLCAy
MDE0IGF0IDEyOjQxIEFNLCAgPHh1ZWxpbi5zaGlAZnJlZXNjYWxlLmNvbT4gd3JvdGU6DQo+IEZy
b206IFh1ZWxpbiBTaGkgPHh1ZWxpbi5zaGlAZnJlZXNjYWxlLmNvbT4NCj4NCj4gVGhlIFJhaWRF
bmdpbmUgaXMgYSBuZXcgRlNMIGhhcmR3YXJlIHVzZWQgZm9yIFJhaWQ1LzYgYWNjZXJhdGlvbi4N
Cj4NCj4gVGhpcyBwYXRjaCBlbmFibGVzIHRoZSBSYWlkRW5naW5lIGZ1bmN0aW9uYWxpdHkgYW5k
IHByb3ZpZGVzIGhhcmR3YXJlIA0KPiBvZmZsb2FkaW5nIGNhcGFiaWxpdHkgZm9yIG1lbWNweSwg
eG9yIGFuZCBwcSBjb21wdXRhdGlvbi4NCj4gSXQgd29ya3Mgd2l0aCBhc3luY190eC4NCj4NCj4g
U2lnbmVkLW9mZi1ieTogSGFybmluZGVyIFJhaSA8aGFybmluZGVyLnJhaUBmcmVlc2NhbGUuY29t
Pg0KPiBTaWduZWQtb2ZmLWJ5OiBOYXZlZW4gQnVybWkgPG5hdmVlbmJ1cm1pQGZyZWVzY2FsZS5j
b20+DQo+IFNpZ25lZC1vZmYtYnk6IFh1ZWxpbiBTaGkgPHh1ZWxpbi5zaGlAZnJlZXNjYWxlLmNv
bT4NCj4gLS0tDQo+ICBjaGFuZ2VzIGZvciB2MzoNCj4gICAtIGZpeCBtZW1vcnkgYWxsb2NhdGlv
biBmbGFnIEdGUF94eHggdXNhZ2UuDQo+ICAgLSBhZGQgcmVfanJfaXNzdWVfcGVuZGluZyBjYWxs
IGluIGNsZWFudXAuDQo+ICAgLSByZW1vdmUgdW5uZWNlc3NhcnkgZG1hX3J1bl9kZXBlbmRlbmNp
ZXMoLi4uKS4NCj4gICAtIHVzZSBkbWFfY29va2llX2NvbXBsZXRlKC4uLikgaW5zdGVhZCBvZiBk
aXJlY3QgdXBkYXRpbmcgY29va2llLg0KPg0KPiAgZHJpdmVycy9kbWEvS2NvbmZpZyAgICB8ICAx
MSArDQo+ICBkcml2ZXJzL2RtYS9NYWtlZmlsZSAgIHwgICAxICsNCj4gIGRyaXZlcnMvZG1hL2Zz
bF9yYWlkLmMgfCA4NzggDQo+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysNCj4gIGRyaXZlcnMvZG1hL2ZzbF9yYWlkLmggfCAzMDggKysrKysrKysrKysr
KysrKysNCj4gIDQgZmlsZXMgY2hhbmdlZCwgMTE5OCBpbnNlcnRpb25zKCspDQo+ICBjcmVhdGUg
bW9kZSAxMDA2NDQgZHJpdmVycy9kbWEvZnNsX3JhaWQuYyAgY3JlYXRlIG1vZGUgMTAwNjQ0IA0K
PiBkcml2ZXJzL2RtYS9mc2xfcmFpZC5oDQo+DQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2RtYS9L
Y29uZmlnIGIvZHJpdmVycy9kbWEvS2NvbmZpZyBpbmRleCANCj4gNjA1YjAxNi4uODI5ZjQxYyAx
MDA2NDQNCj4gLS0tIGEvZHJpdmVycy9kbWEvS2NvbmZpZw0KPiArKysgYi9kcml2ZXJzL2RtYS9L
Y29uZmlnDQo+IEBAIC0xMDAsNiArMTAwLDE3IEBAIGNvbmZpZyBGU0xfRE1BDQo+ICAgICAgICAg
ICBFbG9QbHVzIGlzIG9uIG1wYzg1eHggYW5kIG1wYzg2eHggYW5kIFB4eHggcGFydHMsIGFuZCB0
aGUgRWxvMyBpcyBvbg0KPiAgICAgICAgICAgc29tZSBUeHh4IGFuZCBCeHh4IHBhcnRzLg0KPg0K
PiArY29uZmlnIEZTTF9SQUlEDQo+ICsgICAgICAgIHRyaXN0YXRlICJGcmVlc2NhbGUgUkFJRCBl
bmdpbmUgU3VwcG9ydCINCj4gKyAgICAgICAgZGVwZW5kcyBvbiBGU0xfU09DICYmICFGU0xfRE1B
DQoNClRoaXMgd29uJ3Qgd29yayBpbiB0aGUgY2FzZSB3aGVyZSBGU0xfRE1BPW0uDQoNCkluc3Rl
YWQsIEkgdGhpbmsgeW91IHdhbnQgdG8gdXNlICJkZXBlbmRzIG9uICFBU1lOQ19UWF9FTkFCTEVf
Q0hBTk5FTF9TV0lUQ0giIHdoaWNoIGlzIHRoZSBhY3R1YWwgZGVwZW5kZW5jeS4NCg0KPiArICAg
ICAgICBzZWxlY3QgRE1BX0VOR0lORQ0KPiArICAgICAgICBzZWxlY3QgRE1BX0VOR0lORV9SQUlE
DQo+ICsgICAgICAgIC0tLWhlbHAtLS0NCj4gKyAgICAgICAgICBFbmFibGUgc3VwcG9ydCBmb3Ig
RnJlZXNjYWxlIFJBSUQgRW5naW5lLiBSQUlEIEVuZ2luZSBpcw0KPiArICAgICAgICAgIGF2YWls
YWJsZSBvbiBzb21lIFFvcklRIFNvQ3MgKGxpa2UgUDUwMjApLiBJdCBoYXMNCj4gKyAgICAgICAg
ICB0aGUgY2FwYWJpbGl0eSB0byBvZmZsb2FkIG1lbWNweSwgeG9yIGFuZCBwcSBjb21wdXRhdGlv
bg0KPiArICAgICAgICAgZm9yIHJhaWQ1LzYuDQo+ICsNClsuLl0NCj4gZGlmZiAtLWdpdCBhL2Ry
aXZlcnMvZG1hL2ZzbF9yYWlkLmMgYi9kcml2ZXJzL2RtYS9mc2xfcmFpZC5jIG5ldyBmaWxlIA0K
PiBtb2RlIDEwMDY0NCBpbmRleCAwMDAwMDAwLi40YjM4OWIxDQo+IC0tLSAvZGV2L251bGwNCj4g
KysrIGIvZHJpdmVycy9kbWEvZnNsX3JhaWQuYw0KPiBAQCAtMCwwICsxLDg3OCBAQA0KWy4uXQ0K
PiArdm9pZCBmaWxsX2NmZF9mcmFtZShzdHJ1Y3QgY21wbmRfZnJhbWUgKmNmLCB1OCBpbmRleCwN
Cj4gKyAgICAgICAgICAgICAgIHNpemVfdCBsZW5ndGgsIGRtYV9hZGRyX3QgYWRkciwgYm9vbCBm
aW5hbCkgew0KPiArICAgICAgIHUzMiBlZnJsID0gbGVuZ3RoICYgQ0ZfTEVOR1RIX01BU0s7DQo+
ICsgICAgICAgZWZybCB8PSBmaW5hbCA8PCBDRl9GSU5BTF9TSElGVDsNCj4gKyAgICAgICBjZltp
bmRleF0uZWZybDMyID0gZWZybDsNCj4gKyAgICAgICBjZltpbmRleF0uYWRkcl9oaWdoID0gKGFk
ZHIgPj4gMzIpICYgSFdERVNDX0FERFJfSElHSF9NQVNLOw0KDQpVc2UgInVwcGVyXzMyX2JpdHMo
KSIgaGVyZSBvdGhlcndpc2U6DQoNCiAgZHJpdmVycy9kbWEvZnNsX3JhaWQuYzogSW4gZnVuY3Rp
b24gJ2ZpbGxfY2ZkX2ZyYW1lJzoNCiAgZHJpdmVycy9kbWEvZnNsX3JhaWQuYzoyNTg6Mjogd2Fy
bmluZzogcmlnaHQgc2hpZnQgY291bnQgPj0gd2lkdGggb2YgdHlwZQ0KDQo+ICsgICAgICAgY2Zb
aW5kZXhdLmFkZHJfbG93ID0gKHUzMilhZGRyOw0KDQpVc2UgbG93ZXJfMzJfYml0cygpIGhlcmUg
dG8gYmUgc3ltbWV0cmljYWwuDQoNCj4gK30NCj4gKw0KPiArc3RhdGljIHN0cnVjdCBmc2xfcmVf
ZG1hX2FzeW5jX3R4X2Rlc2MgKnJlX2pyX2luaXRfZGVzYyhzdHJ1Y3QgcmVfanIgKmpyLA0KPiAr
ICAgICAgIHN0cnVjdCBmc2xfcmVfZG1hX2FzeW5jX3R4X2Rlc2MgKmRlc2MsIHZvaWQgKmNmLCBk
bWFfYWRkcl90IA0KPiArcGFkZHIpIHsNCj4gKyAgICAgICBkZXNjLT5qciA9IGpyOw0KPiArICAg
ICAgIGRlc2MtPmFzeW5jX3R4LnR4X3N1Ym1pdCA9IHJlX2pyX3R4X3N1Ym1pdDsNCj4gKyAgICAg
ICBkbWFfYXN5bmNfdHhfZGVzY3JpcHRvcl9pbml0KCZkZXNjLT5hc3luY190eCwgJmpyLT5jaGFu
KTsNCj4gKyAgICAgICBJTklUX0xJU1RfSEVBRCgmZGVzYy0+bm9kZSk7DQo+ICsNCj4gKyAgICAg
ICBkZXNjLT5od2Rlc2MuZm10MzIgPSBGUkFNRV9GT1JNQVQgPDwgSFdERVNDX0ZNVF9TSElGVDsN
Cj4gKyAgICAgICBkZXNjLT5od2Rlc2MubGJlYTMyID0gKHBhZGRyID4+IDMyKSAmIEhXREVTQ19B
RERSX0hJR0hfTUFTSzsNCg0KU2FtZSBjb21tZW50L3dhcm5pbmcgYXMgYWJvdmUuLi4NCg0KPiAr
ICAgICAgIGRlc2MtPmh3ZGVzYy5hZGRyX2xvdyA9ICh1MzIpcGFkZHI7DQoNCmRpdHRvLg0KDQoN
Cg==

^ permalink raw reply

* [PATCH 2/2] fsl/mpic_timer: make mpic_timer to support deep sleep feature
From: Dongsheng Wang @ 2014-04-14  2:24 UTC (permalink / raw)
  To: scottwood; +Cc: linuxppc-dev, chenhui.zhao, jason.jin, Wang Dongsheng
In-Reply-To: <1397442250-14886-1-git-send-email-dongsheng.wang@freescale.com>

From: Wang Dongsheng <dongsheng.wang@freescale.com>

At T104x platfrom the timer clock will be changed when system going to
deep sleep. Add suspend function to switch timer time before system
going to deep sleep, and recovery the time after resume from deep sleep.

Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>

diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
index 9d9b062..737a53d 100644
--- a/arch/powerpc/sysdev/mpic_timer.c
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -11,6 +11,7 @@
  * option) any later version.
  */
 
+#include <linux/fsl/fsl_pm.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -18,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
@@ -26,6 +28,7 @@
 #include <sysdev/fsl_soc.h>
 #include <asm/io.h>
 
+#include <asm/mpc85xx.h>
 #include <asm/mpic_timer.h>
 
 #define FSL_GLOBAL_TIMER		0x1
@@ -71,8 +74,10 @@ struct timer_group_priv {
 	struct timer_regs __iomem	*regs;
 	struct mpic_timer		timer[TIMERS_PER_GROUP];
 	struct list_head		node;
+	unsigned long			idle;
 	unsigned int			timerfreq;
-	unsigned int			idle;
+	unsigned int			suspended_timerfreq;
+	unsigned int			resume_timerfreq;
 	unsigned int			flags;
 	spinlock_t			lock;
 	void __iomem			*group_tcr;
@@ -88,6 +93,7 @@ static struct cascade_priv cascade_timer[] = {
 };
 
 static LIST_HEAD(timer_group_list);
+static int switch_freq_flag;
 
 static void convert_ticks_to_time(struct timer_group_priv *priv,
 		const u64 ticks, struct timeval *time)
@@ -423,6 +429,33 @@ struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev,
 }
 EXPORT_SYMBOL(mpic_request_timer);
 
+static void timer_group_get_suspended_freq(struct timer_group_priv *priv)
+{
+	struct device_node *np;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-clockgen-2.0");
+	if (!np) {
+		pr_err("mpic timer: Missing clockgen device node.\n");
+
+		return;
+	}
+
+	of_property_read_u32(np, "clock-frequency", &priv->suspended_timerfreq);
+	of_node_put(np);
+}
+
+static int need_to_switch_freq(void)
+{
+	u32 svr;
+
+	svr = mfspr(SPRN_SVR);
+	if (SVR_SOC_VER(svr) == SVR_T1040 ||
+			SVR_SOC_VER(svr) == SVR_T1042)
+		return 1;
+
+	return 0;
+}
+
 static int timer_group_get_freq(struct device_node *np,
 			struct timer_group_priv *priv)
 {
@@ -437,6 +470,15 @@ static int timer_group_get_freq(struct device_node *np,
 					&priv->timerfreq);
 			of_node_put(dn);
 		}
+
+		/*
+		 * For deep sleep, if system going to deep sleep,
+		 * timer freq will be changed.
+		 */
+		if (need_to_switch_freq()) {
+			timer_group_get_suspended_freq(priv);
+			switch_freq_flag = 1;
+		}
 	}
 
 	if (priv->timerfreq <= 0)
@@ -445,6 +487,7 @@ static int timer_group_get_freq(struct device_node *np,
 	if (priv->flags & FSL_GLOBAL_TIMER) {
 		div = (1 << (MPIC_TIMER_TCR_CLKDIV >> 8)) * 8;
 		priv->timerfreq /= div;
+		priv->suspended_timerfreq /= div;
 	}
 
 	return 0;
@@ -564,14 +607,190 @@ out:
 	kfree(priv);
 }
 
+static void mpic_reset_time(struct mpic_timer *handle, struct timeval *bcr_time,
+				struct timeval *ccr_time)
+{
+	struct timer_group_priv *priv = container_of(handle,
+			struct timer_group_priv, timer[handle->num]);
+
+	u64 ccr_ticks = 0;
+	u64 bcr_ticks = 0;
+
+	/* switch bcr time */
+	convert_time_to_ticks(priv, bcr_time, &bcr_ticks);
+
+	/* switch ccr time */
+	convert_time_to_ticks(priv, ccr_time, &ccr_ticks);
+
+	if (handle->cascade_handle) {
+		u32 tmp_ticks;
+		u32 rem_ticks;
+
+		/* reset ccr ticks to bcr */
+		tmp_ticks = div_u64_rem(ccr_ticks, MAX_TICKS_CASCADE,
+					&rem_ticks);
+		out_be32(&priv->regs[handle->num].gtbcr,
+			tmp_ticks | TIMER_STOP);
+		out_be32(&priv->regs[handle->num - 1].gtbcr, rem_ticks);
+
+		/* start timer */
+		clrbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+
+		/* reset bcr */
+		tmp_ticks = div_u64_rem(bcr_ticks, MAX_TICKS_CASCADE,
+					&rem_ticks);
+		out_be32(&priv->regs[handle->num].gtbcr,
+			tmp_ticks & ~TIMER_STOP);
+		out_be32(&priv->regs[handle->num - 1].gtbcr, rem_ticks);
+	} else {
+		/* reset ccr ticks to bcr */
+		out_be32(&priv->regs[handle->num].gtbcr,
+			ccr_ticks | TIMER_STOP);
+		/* start timer */
+		clrbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+		/* reset bcr */
+		out_be32(&priv->regs[handle->num].gtbcr,
+			bcr_ticks & ~TIMER_STOP);
+	}
+}
+
+static void do_switch_time(struct mpic_timer *handle, unsigned int new_freq)
+{
+	struct timer_group_priv *priv = container_of(handle,
+			struct timer_group_priv, timer[handle->num]);
+	struct timeval ccr_time;
+	struct timeval bcr_time;
+	unsigned int timerfreq;
+	u32 test_stop;
+	u64 ticks;
+
+	test_stop = in_be32(&priv->regs[handle->num].gtbcr);
+	test_stop &= TIMER_STOP;
+	if (test_stop)
+		return;
+
+	/* stop timer, prepare reset time */
+	setbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP);
+
+	/* get bcr time */
+	if (handle->cascade_handle) {
+		u32 tmp_ticks;
+
+		tmp_ticks = in_be32(&priv->regs[handle->num].gtbcr);
+		tmp_ticks &= ~TIMER_STOP;
+		ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE;
+		tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtbcr);
+		ticks += tmp_ticks;
+	} else {
+		ticks = in_be32(&priv->regs[handle->num].gtbcr);
+		ticks &= ~TIMER_STOP;
+	}
+	convert_ticks_to_time(priv, ticks, &bcr_time);
+
+	/* get ccr time */
+	mpic_get_remain_time(handle, &ccr_time);
+
+	/* recalculate timer time */
+	timerfreq = priv->timerfreq;
+	priv->timerfreq = new_freq;
+	mpic_reset_time(handle, &bcr_time, &ccr_time);
+	priv->timerfreq = timerfreq;
+}
+
+static void switch_group_timer(struct timer_group_priv *priv,
+				unsigned int new_freq)
+{
+	int i, num;
+
+	for (i = 0; i < TIMERS_PER_GROUP; i++) {
+		num = TIMERS_PER_GROUP - 1 - i;
+		/* cascade */
+		if ((i + 1) < TIMERS_PER_GROUP &&
+				priv->timer[num].cascade_handle) {
+			do_switch_time(&priv->timer[num], new_freq);
+			i++;
+			continue;
+		}
+
+		if (!test_bit(i, &priv->idle))
+			do_switch_time(&priv->timer[num], new_freq);
+	}
+}
+
+static int mpic_timer_suspend(void)
+{
+	struct timer_group_priv *priv;
+	suspend_state_t pm_state;
+
+	pm_state = pm_suspend_state();
+
+	list_for_each_entry(priv, &timer_group_list, node) {
+		/* timer not be used */
+		if (priv->idle == 0xf)
+			continue;
+
+		switch (pm_state) {
+		case PM_SUSPEND_STANDBY:
+			break;
+		case PM_SUSPEND_MEM:
+			if (!switch_freq_flag)
+				continue;
+
+			if (!priv->suspended_timerfreq) {
+				pr_warn("Mpic timer will not be accurate.\n");
+				continue;
+			}
+
+			/* will switch timers, a set of timer */
+			switch_group_timer(priv, priv->suspended_timerfreq);
+
+			/* Software: switch timerfreq to suspended freq */
+			priv->resume_timerfreq = priv->timerfreq;
+			priv->timerfreq = priv->suspended_timerfreq;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
 static void mpic_timer_resume(void)
 {
 	struct timer_group_priv *priv;
+	suspend_state_t pm_state;
+
+	pm_state = pm_suspend_state();
 
 	list_for_each_entry(priv, &timer_group_list, node) {
 		/* Init FSL timer hardware */
 		if (priv->flags & FSL_GLOBAL_TIMER)
 			setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV);
+
+		/* timer not be used */
+		if (priv->idle == 0xf)
+			continue;
+
+		switch (pm_state) {
+		case PM_SUSPEND_STANDBY:
+			break;
+		case PM_SUSPEND_MEM:
+			if (!switch_freq_flag)
+				continue;
+
+			if (!priv->suspended_timerfreq)
+				continue;
+
+			/* will switch timers, a set of timer */
+			switch_group_timer(priv, priv->resume_timerfreq);
+
+			/* restore timerfreq */
+			priv->timerfreq = priv->resume_timerfreq;
+			break;
+		default:
+			break;
+		}
 	}
 }
 
@@ -581,6 +800,7 @@ static const struct of_device_id mpic_timer_ids[] = {
 };
 
 static struct syscore_ops mpic_timer_syscore_ops = {
+	.suspend = mpic_timer_suspend,
 	.resume = mpic_timer_resume,
 };
 
-- 
1.8.5

^ permalink raw reply related

* [PATCH 1/2] powerpc/mpc85xx: add two functions to get suspend state which is standby or mem
From: Dongsheng Wang @ 2014-04-14  2:24 UTC (permalink / raw)
  To: scottwood; +Cc: linuxppc-dev, chenhui.zhao, jason.jin, Wang Dongsheng

From: Wang Dongsheng <dongsheng.wang@freescale.com>

Add set_pm_suspend_state & pm_suspend_state functions to set/get suspend state.
When system going to sleep, devices can get the system suspend state(STANDBY/MEM)
through pm_suspend_state function and handle different situations.

Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com>

diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index b564b5e..3853d43 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -8,6 +8,7 @@
 
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/suspend.h>
 
 #include <asm/qe.h>
 #include <sysdev/cpm2_pic.h>
@@ -47,6 +48,19 @@ int __init mpc85xx_common_publish_devices(void)
 {
 	return of_platform_bus_probe(NULL, mpc85xx_common_ids, NULL);
 }
+
+static suspend_state_t pm_state;
+
+void set_pm_suspend_state(suspend_state_t state)
+{
+	pm_state = state;
+}
+
+suspend_state_t pm_suspend_state(void)
+{
+	return pm_state;
+}
+
 #ifdef CONFIG_CPM2
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 8cf4aa0..0b34c00 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/export.h>
+#include <linux/fsl/fsl_pm.h>
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -52,12 +53,20 @@ static int pmc_suspend_valid(suspend_state_t state)
 {
 	if (state != PM_SUSPEND_STANDBY)
 		return 0;
+
+	set_pm_suspend_state(state);
 	return 1;
 }
 
+static void pmc_suspend_end(void)
+{
+	set_pm_suspend_state(PM_SUSPEND_ON);
+}
+
 static const struct platform_suspend_ops pmc_suspend_ops = {
 	.valid = pmc_suspend_valid,
 	.enter = pmc_suspend_enter,
+	.end	= pmc_suspend_end,
 };
 
 static int pmc_probe(struct platform_device *ofdev)
@@ -68,6 +77,7 @@ static int pmc_probe(struct platform_device *ofdev)
 
 	pmc_dev = &ofdev->dev;
 	suspend_set_ops(&pmc_suspend_ops);
+	set_pm_suspend_state(PM_SUSPEND_ON);
 	return 0;
 }
 
diff --git a/include/linux/fsl/fsl_pm.h b/include/linux/fsl/fsl_pm.h
new file mode 100644
index 0000000..705ea52
--- /dev/null
+++ b/include/linux/fsl/fsl_pm.h
@@ -0,0 +1,25 @@
+/*
+ * include/linux/fsl/fsl_pm.h
+ *
+ * Definitions for any platform related flags or structures for Freescale
+ * Power Management.
+ *
+ * Author: Wang Dongsheng <dongsheng.wang@freescale.com>
+ *
+ * Copyright 2014 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/suspend.h>
+
+#ifdef CONFIG_FSL_SOC_BOOKE
+extern void set_pm_suspend_state(suspend_state_t state);
+extern suspend_state_t pm_suspend_state(void);
+#else
+static inline void set_pm_suspend_state(suspend_state_t state) { }
+static inline suspend_state_t pm_suspend_state(void) { }
+#endif
-- 
1.8.5

^ permalink raw reply related

* Re: [PATCH v3] powerpc: kvm: make _PAGE_NUMA take effect
From: Liu ping fan @ 2014-04-13  2:27 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Liu Ping Fan, kvm@vger.kernel.org mailing list, kvm-ppc,
	Paul Mackerras, Aneesh Kumar K.V, linuxppc-dev
In-Reply-To: <3DC9A8E1-547C-4660-AB61-BE371DEDA520@suse.de>

On Fri, Apr 11, 2014 at 10:03 PM, Alexander Graf <agraf@suse.de> wrote:
>
> On 11.04.2014, at 13:45, Liu Ping Fan <pingfank@linux.vnet.ibm.com> wrote=
:
>
>> When we mark pte with _PAGE_NUMA we already call mmu_notifier_invalidate=
_range_start
>> and mmu_notifier_invalidate_range_end, which will mark existing guest hp=
te
>> entry as HPTE_V_ABSENT. Now we need to do that when we are inserting new
>> guest hpte entries.
>
> What happens when we don't? Why do we need the check? Why isn't it done i=
mplicitly? What happens when we treat a NUMA marked page as non-present? Wh=
y does it work out for us?
>
> Assume you have no idea what PAGE_NUMA is, but try to figure out what thi=
s patch does and whether you need to cherry-pick it into your downstream ke=
rnel. The description as is still is not very helpful for that. It doesn't =
even explain what really changes with this patch applied.
>
Yeah.  what about appending the following description?  Can it make
the context clear?
"Guest should not setup a hpte for the page whose pte is marked with
_PAGE_NUMA, so on the host, the numa-fault mechanism can take effect
to check whether the page is placed correctly or not."

>>
>> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
>> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
>> ---
>> v3:
>>  rebased onto Alex's tree, branch kvm-ppc-next
>>  substitue commit log with the more clear description in Aneesh's reply =
(thanks, Aneesh)
>> ---
>> arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book=
3s_hv_rm_mmu.c
>> index 1d6c56a..1117525 100644
>> --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
>> +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
>> @@ -234,7 +234,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned lon=
g flags,
>>               pte_size =3D psize;
>>               pte =3D lookup_linux_pte_and_update(pgdir, hva, writing,
>>                                                 &pte_size);
>> -             if (pte_present(pte)) {
>> +             if (pte_present(pte)&&!pte_numa(pte)) {
>
> Spaces missing
>
Will fix,

Thx,
Fan

^ permalink raw reply

* Change MINSIGSTKSZ and SIGSTKSIZE
From: Haren Myneni @ 2014-04-12  9:59 UTC (permalink / raw)
  To: amodra, benh; +Cc: linuxppc-dev

Alan, 
	LTP test (signalstack02) is failing. This test expects -ENOMEM from
kernel when passing less than stack size (passing 4095). MINSIGSTKSZ in
signal.h (glibc) is changed to 4096 to support VSX changes
(https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=f7c399cff5bd04ee9dc117fb6b0f39597dc047c6)  We should also change these values in kernel to match with glibc. Any issues? 

diff --git a/arch/powerpc/include/uapi/asm/signal.h
b/arch/powerpc/include/uapi/
index 6c69ee9..18f498e 100644
--- a/arch/powerpc/include/uapi/asm/signal.h
+++ b/arch/powerpc/include/uapi/asm/signal.h
@@ -85,8 +85,8 @@ typedef struct {
 
 #define SA_RESTORER    0x04000000U
 
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
+#define MINSIGSTKSZ    4096
+#define SIGSTKSZ       16384

Thanks
Haren

^ permalink raw reply related

* [PATCH v2] gpio: ge: Convert to platform driver
From: Alexander Shiyan @ 2014-04-12  5:41 UTC (permalink / raw)
  To: linux-gpio
  Cc: Martyn Welch, Alexandre Courbot, Linus Walleij, linuxppc-dev,
	Alexander Shiyan

This patch converts GE I/O FPGA GPIO driver to platform driver.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
---
 drivers/gpio/gpio-ge.c | 174 +++++++++++++++----------------------------------
 1 file changed, 53 insertions(+), 121 deletions(-)

diff --git a/drivers/gpio/gpio-ge.c b/drivers/gpio/gpio-ge.c
index 7b95a4a..1237a73 100644
--- a/drivers/gpio/gpio-ge.c
+++ b/drivers/gpio/gpio-ge.c
@@ -18,15 +18,9 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/init.h>
 #include <linux/io.h>
-#include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_platform.h>
 #include <linux/of_gpio.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
 #include <linux/module.h>
 
 #define GEF_GPIO_DIRECT		0x00
@@ -39,28 +33,26 @@
 #define GEF_GPIO_OVERRUN	0x1C
 #define GEF_GPIO_MODE		0x20
 
-static void _gef_gpio_set(void __iomem *reg, unsigned int offset, int value)
+static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
+	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 	unsigned int data;
 
-	data = ioread32be(reg);
-	/* value: 0=low; 1=high */
-	if (value & 0x1)
-		data = data | (0x1 << offset);
+	data = ioread32be(mmchip->regs + GEF_GPIO_OUT);
+	if (value)
+		data = data | BIT(offset);
 	else
-		data = data & ~(0x1 << offset);
-
-	iowrite32be(data, reg);
+		data = data & ~BIT(offset);
+	iowrite32be(data, mmchip->regs + GEF_GPIO_OUT);
 }
 
-
 static int gef_gpio_dir_in(struct gpio_chip *chip, unsigned offset)
 {
 	unsigned int data;
 	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 
 	data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
-	data = data | (0x1 << offset);
+	data = data | BIT(offset);
 	iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
 
 	return 0;
@@ -71,11 +63,11 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
 	unsigned int data;
 	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 
-	/* Set direction before switching to input */
-	_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
+	/* Set value before switching to output */
+	gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
 
 	data = ioread32be(mmchip->regs + GEF_GPIO_DIRECT);
-	data = data & ~(0x1 << offset);
+	data = data & ~BIT(offset);
 	iowrite32be(data, mmchip->regs + GEF_GPIO_DIRECT);
 
 	return 0;
@@ -83,116 +75,56 @@ static int gef_gpio_dir_out(struct gpio_chip *chip, unsigned offset, int value)
 
 static int gef_gpio_get(struct gpio_chip *chip, unsigned offset)
 {
-	unsigned int data;
-	int state = 0;
 	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
 
-	data = ioread32be(mmchip->regs + GEF_GPIO_IN);
-	state = (int)((data >> offset) & 0x1);
-
-	return state;
+	return !!(ioread32be(mmchip->regs + GEF_GPIO_IN) & BIT(offset));
 }
 
-static void gef_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct of_mm_gpio_chip *mmchip = to_of_mm_gpio_chip(chip);
-
-	_gef_gpio_set(mmchip->regs + GEF_GPIO_OUT, offset, value);
-}
+static const struct of_device_id gef_gpio_ids[] = {
+	{
+		.compatible	= "gef,sbc610-gpio",
+		.data		= (void *)19,
+	}, {
+		.compatible	= "gef,sbc310-gpio",
+		.data		= (void *)6,
+	}, {
+		.compatible	= "ge,imp3a-gpio",
+		.data		= (void *)16,
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gef_gpio_ids);
 
-static int __init gef_gpio_init(void)
+static int __init gef_gpio_probe(struct platform_device *pdev)
 {
-	struct device_node *np;
-	int retval;
-	struct of_mm_gpio_chip *gef_gpio_chip;
-
-	for_each_compatible_node(np, NULL, "gef,sbc610-gpio") {
-
-		pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
-		/* Allocate chip structure */
-		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-		if (!gef_gpio_chip) {
-			pr_err("%s: Unable to allocate structure\n",
-				np->full_name);
-			continue;
-		}
-
-		/* Setup pointers to chip functions */
-		gef_gpio_chip->gc.of_gpio_n_cells = 2;
-		gef_gpio_chip->gc.ngpio = 19;
-		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-		gef_gpio_chip->gc.get = gef_gpio_get;
-		gef_gpio_chip->gc.set = gef_gpio_set;
-
-		/* This function adds a memory mapped GPIO chip */
-		retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-		if (retval) {
-			kfree(gef_gpio_chip);
-			pr_err("%s: Unable to add GPIO\n", np->full_name);
-		}
-	}
-
-	for_each_compatible_node(np, NULL, "gef,sbc310-gpio") {
-
-		pr_debug("%s: Initialising GEF GPIO\n", np->full_name);
-
-		/* Allocate chip structure */
-		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-		if (!gef_gpio_chip) {
-			pr_err("%s: Unable to allocate structure\n",
-				np->full_name);
-			continue;
-		}
-
-		/* Setup pointers to chip functions */
-		gef_gpio_chip->gc.of_gpio_n_cells = 2;
-		gef_gpio_chip->gc.ngpio = 6;
-		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-		gef_gpio_chip->gc.get = gef_gpio_get;
-		gef_gpio_chip->gc.set = gef_gpio_set;
-
-		/* This function adds a memory mapped GPIO chip */
-		retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-		if (retval) {
-			kfree(gef_gpio_chip);
-			pr_err("%s: Unable to add GPIO\n", np->full_name);
-		}
-	}
-
-	for_each_compatible_node(np, NULL, "ge,imp3a-gpio") {
-
-		pr_debug("%s: Initialising GE GPIO\n", np->full_name);
-
-		/* Allocate chip structure */
-		gef_gpio_chip = kzalloc(sizeof(*gef_gpio_chip), GFP_KERNEL);
-		if (!gef_gpio_chip) {
-			pr_err("%s: Unable to allocate structure\n",
-				np->full_name);
-			continue;
-		}
-
-		/* Setup pointers to chip functions */
-		gef_gpio_chip->gc.of_gpio_n_cells = 2;
-		gef_gpio_chip->gc.ngpio = 16;
-		gef_gpio_chip->gc.direction_input = gef_gpio_dir_in;
-		gef_gpio_chip->gc.direction_output = gef_gpio_dir_out;
-		gef_gpio_chip->gc.get = gef_gpio_get;
-		gef_gpio_chip->gc.set = gef_gpio_set;
-
-		/* This function adds a memory mapped GPIO chip */
-		retval = of_mm_gpiochip_add(np, gef_gpio_chip);
-		if (retval) {
-			kfree(gef_gpio_chip);
-			pr_err("%s: Unable to add GPIO\n", np->full_name);
-		}
-	}
+	const struct of_device_id *of_id =
+		of_match_device(gef_gpio_ids, &pdev->dev);
+	struct of_mm_gpio_chip *mmchip;
+
+	mmchip = devm_kzalloc(&pdev->dev, sizeof(*mmchip), GFP_KERNEL);
+	if (!mmchip)
+		return -ENOMEM;
+
+	/* Setup pointers to chip functions */
+	mmchip->gc.ngpio = (u16)(uintptr_t)of_id->data;
+	mmchip->gc.of_gpio_n_cells = 2;
+	mmchip->gc.direction_input = gef_gpio_dir_in;
+	mmchip->gc.direction_output = gef_gpio_dir_out;
+	mmchip->gc.get = gef_gpio_get;
+	mmchip->gc.set = gef_gpio_set;
+
+	/* This function adds a memory mapped GPIO chip */
+	return of_mm_gpiochip_add(pdev->dev.of_node, mmchip);
+};
 
-	return 0;
+static struct platform_driver gef_gpio_driver = {
+	.driver = {
+		.name		= "gef-gpio",
+		.owner		= THIS_MODULE,
+		.of_match_table	= gef_gpio_ids,
+	},
 };
-arch_initcall(gef_gpio_init);
+module_platform_driver_probe(gef_gpio_driver, gef_gpio_probe);
 
 MODULE_DESCRIPTION("GE I/O FPGA GPIO driver");
 MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
-- 
1.8.3.2

^ permalink raw reply related

* Re: [PATCH v3] dmaengine: driver support for FSL RaidEngine device.
From: Dan Williams @ 2014-04-11 17:45 UTC (permalink / raw)
  To: xuelin.shi
  Cc: Harninder Rai, andriy.shevchenko, Koul, Vinod, Naveen Burmi,
	dmaengine@vger.kernel.org, linuxppc-dev
In-Reply-To: <CAA9_cme=Bo3tYi0-bNXBRNLZnC-4FZyaSYZ=3iRD_5xfiVX5Mw@mail.gmail.com>

On Fri, Apr 11, 2014 at 10:42 AM, Dan Williams <dan.j.williams@intel.com> wrote:
> A few more comments:
>
> On Fri, Apr 11, 2014 at 12:41 AM,  <xuelin.shi@freescale.com> wrote:
>> From: Xuelin Shi <xuelin.shi@freescale.com>
>>
>> The RaidEngine is a new FSL hardware used for Raid5/6 acceration.
>>
>> This patch enables the RaidEngine functionality and provides
>> hardware offloading capability for memcpy, xor and pq computation.
>> It works with async_tx.
>>
>> Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
>> Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
>> Signed-off-by: Xuelin Shi <xuelin.shi@freescale.com>
>> ---
>>  changes for v3:
>>   - fix memory allocation flag GFP_xxx usage.
>>   - add re_jr_issue_pending call in cleanup.
>>   - remove unnecessary dma_run_dependencies(...).
>>   - use dma_cookie_complete(...) instead of direct updating cookie.
>>
>>  drivers/dma/Kconfig    |  11 +
>>  drivers/dma/Makefile   |   1 +
>>  drivers/dma/fsl_raid.c | 878 +++++++++++++++++++++++++++++++++++++++++++++++++
>>  drivers/dma/fsl_raid.h | 308 +++++++++++++++++
>>  4 files changed, 1198 insertions(+)
>>  create mode 100644 drivers/dma/fsl_raid.c
>>  create mode 100644 drivers/dma/fsl_raid.h
>>
>> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
>> index 605b016..829f41c 100644
>> --- a/drivers/dma/Kconfig
>> +++ b/drivers/dma/Kconfig
>> @@ -100,6 +100,17 @@ config FSL_DMA
>>           EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
>>           some Txxx and Bxxx parts.
>>
>> +config FSL_RAID
>> +        tristate "Freescale RAID engine Support"
>> +        depends on FSL_SOC && !FSL_DMA
>
> This won't work in the case where FSL_DMA=m.
>
> Instead, I think you want to use "depends on
> !ASYNC_TX_ENABLE_CHANNEL_SWITCH" which is the actual dependency.
>
>> +        select DMA_ENGINE
>> +        select DMA_ENGINE_RAID
>> +        ---help---
>> +          Enable support for Freescale RAID Engine. RAID Engine is
>> +          available on some QorIQ SoCs (like P5020). It has
>> +          the capability to offload memcpy, xor and pq computation
>> +         for raid5/6.
>> +
> [..]
>> diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
>> new file mode 100644
>> index 0000000..4b389b1
>> --- /dev/null
>> +++ b/drivers/dma/fsl_raid.c
>> @@ -0,0 +1,878 @@
> [..]
>> +void fill_cfd_frame(struct cmpnd_frame *cf, u8 index,
>> +               size_t length, dma_addr_t addr, bool final)
>> +{
>> +       u32 efrl = length & CF_LENGTH_MASK;
>> +       efrl |= final << CF_FINAL_SHIFT;
>> +       cf[index].efrl32 = efrl;
>> +       cf[index].addr_high = (addr >> 32) & HWDESC_ADDR_HIGH_MASK;
>
> Use "upper_32_bits()" here otherwise:
>
>   drivers/dma/fsl_raid.c: In function 'fill_cfd_frame':
>   drivers/dma/fsl_raid.c:258:2: warning: right shift count >= width of type
>
>> +       cf[index].addr_low = (u32)addr;
>
> Use lower_32_bits() here to be symmetrical.
>
>> +}
>> +
>> +static struct fsl_re_dma_async_tx_desc *re_jr_init_desc(struct re_jr *jr,
>> +       struct fsl_re_dma_async_tx_desc *desc, void *cf, dma_addr_t paddr)
>> +{
>> +       desc->jr = jr;
>> +       desc->async_tx.tx_submit = re_jr_tx_submit;
>> +       dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
>> +       INIT_LIST_HEAD(&desc->node);
>> +
>> +       desc->hwdesc.fmt32 = FRAME_FORMAT << HWDESC_FMT_SHIFT;
>> +       desc->hwdesc.lbea32 = (paddr >> 32) & HWDESC_ADDR_HIGH_MASK;
>
> Same comment/warning as above...
>
>> +       desc->hwdesc.addr_low = (u32)paddr;
>
> ditto.

Oh, and be mindful of checkpatch output:

ERROR: trailing whitespace
#35: FILE: drivers/dma/Kconfig:106:
+        select DMA_ENGINE $

ERROR: trailing whitespace
#42: FILE: drivers/dma/Kconfig:113:
+ $

total: 2 errors, 0 warnings, 1207 lines checked

^ permalink raw reply

* Re: [PATCH v3] dmaengine: driver support for FSL RaidEngine device.
From: Dan Williams @ 2014-04-11 17:42 UTC (permalink / raw)
  To: xuelin.shi
  Cc: Harninder Rai, andriy.shevchenko, Koul, Vinod, Naveen Burmi,
	dmaengine@vger.kernel.org, linuxppc-dev
In-Reply-To: <1397202086-22489-1-git-send-email-xuelin.shi@freescale.com>

A few more comments:

On Fri, Apr 11, 2014 at 12:41 AM,  <xuelin.shi@freescale.com> wrote:
> From: Xuelin Shi <xuelin.shi@freescale.com>
>
> The RaidEngine is a new FSL hardware used for Raid5/6 acceration.
>
> This patch enables the RaidEngine functionality and provides
> hardware offloading capability for memcpy, xor and pq computation.
> It works with async_tx.
>
> Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
> Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
> Signed-off-by: Xuelin Shi <xuelin.shi@freescale.com>
> ---
>  changes for v3:
>   - fix memory allocation flag GFP_xxx usage.
>   - add re_jr_issue_pending call in cleanup.
>   - remove unnecessary dma_run_dependencies(...).
>   - use dma_cookie_complete(...) instead of direct updating cookie.
>
>  drivers/dma/Kconfig    |  11 +
>  drivers/dma/Makefile   |   1 +
>  drivers/dma/fsl_raid.c | 878 +++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/dma/fsl_raid.h | 308 +++++++++++++++++
>  4 files changed, 1198 insertions(+)
>  create mode 100644 drivers/dma/fsl_raid.c
>  create mode 100644 drivers/dma/fsl_raid.h
>
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> index 605b016..829f41c 100644
> --- a/drivers/dma/Kconfig
> +++ b/drivers/dma/Kconfig
> @@ -100,6 +100,17 @@ config FSL_DMA
>           EloPlus is on mpc85xx and mpc86xx and Pxxx parts, and the Elo3 is on
>           some Txxx and Bxxx parts.
>
> +config FSL_RAID
> +        tristate "Freescale RAID engine Support"
> +        depends on FSL_SOC && !FSL_DMA

This won't work in the case where FSL_DMA=m.

Instead, I think you want to use "depends on
!ASYNC_TX_ENABLE_CHANNEL_SWITCH" which is the actual dependency.

> +        select DMA_ENGINE
> +        select DMA_ENGINE_RAID
> +        ---help---
> +          Enable support for Freescale RAID Engine. RAID Engine is
> +          available on some QorIQ SoCs (like P5020). It has
> +          the capability to offload memcpy, xor and pq computation
> +         for raid5/6.
> +
[..]
> diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
> new file mode 100644
> index 0000000..4b389b1
> --- /dev/null
> +++ b/drivers/dma/fsl_raid.c
> @@ -0,0 +1,878 @@
[..]
> +void fill_cfd_frame(struct cmpnd_frame *cf, u8 index,
> +               size_t length, dma_addr_t addr, bool final)
> +{
> +       u32 efrl = length & CF_LENGTH_MASK;
> +       efrl |= final << CF_FINAL_SHIFT;
> +       cf[index].efrl32 = efrl;
> +       cf[index].addr_high = (addr >> 32) & HWDESC_ADDR_HIGH_MASK;

Use "upper_32_bits()" here otherwise:

  drivers/dma/fsl_raid.c: In function 'fill_cfd_frame':
  drivers/dma/fsl_raid.c:258:2: warning: right shift count >= width of type

> +       cf[index].addr_low = (u32)addr;

Use lower_32_bits() here to be symmetrical.

> +}
> +
> +static struct fsl_re_dma_async_tx_desc *re_jr_init_desc(struct re_jr *jr,
> +       struct fsl_re_dma_async_tx_desc *desc, void *cf, dma_addr_t paddr)
> +{
> +       desc->jr = jr;
> +       desc->async_tx.tx_submit = re_jr_tx_submit;
> +       dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
> +       INIT_LIST_HEAD(&desc->node);
> +
> +       desc->hwdesc.fmt32 = FRAME_FORMAT << HWDESC_FMT_SHIFT;
> +       desc->hwdesc.lbea32 = (paddr >> 32) & HWDESC_ADDR_HIGH_MASK;

Same comment/warning as above...

> +       desc->hwdesc.addr_low = (u32)paddr;

ditto.

^ permalink raw reply

* [PATCH] ASoC: fsl_sai: Fix incorrect condition check in trigger()
From: Nicolin Chen @ 2014-04-11 14:10 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, Li.Xiubo, linuxppc-dev, linux-kernel, timur

Patch ASoC: fsl_sai: Fix buggy configurations in trigger() doesn't entirely
fix the condition: FRDE of the current substream direction is being cleared
while the code is still using the non-updated one.

Thus this patch fixes this issue by checking the opposite one's FRDE alone
since the current one's is absolutely disabled.

Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
---
 sound/soc/fsl/fsl_sai.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 9858d42..1716a41 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -343,7 +343,8 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
 		regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx),
 				   FSL_SAI_CSR_xIE_MASK, 0);
 
-		if (!(tcsr & FSL_SAI_CSR_FRDE || rcsr & FSL_SAI_CSR_FRDE)) {
+		/* Check if the opposite FRDE is also disabled */
+		if (!(tx ? rcsr & FSL_SAI_CSR_FRDE : tcsr & FSL_SAI_CSR_FRDE)) {
 			regmap_update_bits(sai->regmap, FSL_SAI_TCSR,
 					   FSL_SAI_CSR_TERE, 0);
 			regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
-- 
1.8.4

^ permalink raw reply related

* Re: [PATCH v3] powerpc: kvm: make _PAGE_NUMA take effect
From: Alexander Graf @ 2014-04-11 14:03 UTC (permalink / raw)
  To: Liu Ping Fan; +Cc: kvm, kvm-ppc, Paul Mackerras, Aneesh Kumar K.V, linuxppc-dev
In-Reply-To: <1397216707-12795-1-git-send-email-pingfank@linux.vnet.ibm.com>


On 11.04.2014, at 13:45, Liu Ping Fan <pingfank@linux.vnet.ibm.com> =
wrote:

> When we mark pte with _PAGE_NUMA we already call =
mmu_notifier_invalidate_range_start
> and mmu_notifier_invalidate_range_end, which will mark existing guest =
hpte
> entry as HPTE_V_ABSENT. Now we need to do that when we are inserting =
new
> guest hpte entries.

What happens when we don't? Why do we need the check? Why isn't it done =
implicitly? What happens when we treat a NUMA marked page as =
non-present? Why does it work out for us?

Assume you have no idea what PAGE_NUMA is, but try to figure out what =
this patch does and whether you need to cherry-pick it into your =
downstream kernel. The description as is still is not very helpful for =
that. It doesn't even explain what really changes with this patch =
applied.

>=20
> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
> Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> v3:
>  rebased onto Alex's tree, branch kvm-ppc-next
>  substitue commit log with the more clear description in Aneesh's =
reply (thanks, Aneesh)
> ---
> arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>=20
> diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c =
b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
> index 1d6c56a..1117525 100644
> --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
> +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
> @@ -234,7 +234,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned =
long flags,
> 		pte_size =3D psize;
> 		pte =3D lookup_linux_pte_and_update(pgdir, hva, writing,
> 						  &pte_size);
> -		if (pte_present(pte)) {
> +		if (pte_present(pte)&&!pte_numa(pte)) {

Spaces missing


Alex

^ permalink raw reply

* [PATCH v3] powerpc: kvm: make _PAGE_NUMA take effect
From: Liu Ping Fan @ 2014-04-11 11:45 UTC (permalink / raw)
  To: linuxppc-dev, kvm-ppc
  Cc: Paul Mackerras, Alexander Graf, kvm, Aneesh Kumar K.V

When we mark pte with _PAGE_NUMA we already call mmu_notifier_invalidate_range_start
and mmu_notifier_invalidate_range_end, which will mark existing guest hpte
entry as HPTE_V_ABSENT. Now we need to do that when we are inserting new
guest hpte entries.

Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
v3:
  rebased onto Alex's tree, branch kvm-ppc-next
  substitue commit log with the more clear description in Aneesh's reply (thanks, Aneesh)
---
 arch/powerpc/kvm/book3s_hv_rm_mmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 1d6c56a..1117525 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -234,7 +234,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags,
 		pte_size = psize;
 		pte = lookup_linux_pte_and_update(pgdir, hva, writing,
 						  &pte_size);
-		if (pte_present(pte)) {
+		if (pte_present(pte)&&!pte_numa(pte)) {
 			if (writing && !pte_write(pte))
 				/* make the actual HPTE be read-only */
 				ptel = hpte_make_readonly(ptel);
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH 3/3] ppc/kvm: Clear the runlatch bit of a vcpu before napping
From: Preeti U Murthy @ 2014-04-11 10:32 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, linux-kernel, srivatsa.bhat
In-Reply-To: <20140411103030.27683.2107.stgit@preeti.in.ibm.com>

When the guest cedes the vcpu or the vcpu has no guest to
run it naps. Clear the runlatch bit of the vcpu before
napping to indicate an idle cpu.

Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---

 arch/powerpc/kvm/book3s_hv_rmhandlers.S |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index b254075..b031f93 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -315,6 +315,11 @@ kvm_no_guest:
 	li	r0, KVM_HWTHREAD_IN_NAP
 	stb	r0, HSTATE_HWTHREAD_STATE(r13)
 kvm_do_nap:
+	/* Clear the runlatch bit before napping */
+	mfspr	r2, SPRN_CTRLF
+	clrrdi	r2, r2, 1
+	mtspr	SPRN_CTRLT, r2
+
 	li	r3, LPCR_PECE0
 	mfspr	r4, SPRN_LPCR
 	rlwimi	r4, r3, 0, LPCR_PECE0 | LPCR_PECE1
@@ -2005,8 +2010,13 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
 
 	/*
 	 * Take a nap until a decrementer or external or doobell interrupt
-	 * occurs, with PECE1, PECE0 and PECEDP set in LPCR
+	 * occurs, with PECE1, PECE0 and PECEDP set in LPCR. Also clear the
+	 * runlatch bit before napping.
 	 */
+	mfspr	r2, SPRN_CTRLF
+	clrrdi	r2, r2, 1
+	mtspr	SPRN_CTRLT, r2
+
 	li	r0,1
 	stb	r0,HSTATE_HWTHREAD_REQ(r13)
 	mfspr	r5,SPRN_LPCR

^ permalink raw reply related

* [PATCH 2/3] ppc/kvm: Set the runlatch bit of a CPU just before starting guest
From: Preeti U Murthy @ 2014-04-11 10:31 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, linux-kernel, srivatsa.bhat
In-Reply-To: <20140411103030.27683.2107.stgit@preeti.in.ibm.com>

The secondary threads in the core are kept offline before launching guests
in kvm on powerpc: "371fefd6f2dc4666:KVM: PPC: Allow book3s_hv guests to use
SMT processor modes."

Hence their runlatch bits are cleared. When the secondary threads are called
in to start a guest, their runlatch bits need to be set to indicate that they
are busy. The primary thread has its runlatch bit set though, but there is no
harm in setting this bit once again. Hence set the runlatch bit for all
threads before they start guest.

Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---

 arch/powerpc/kvm/book3s_hv_rmhandlers.S |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index ffbb871..b254075 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -242,6 +242,12 @@ kvm_novcpu_exit:
  */
 	.globl	kvm_start_guest
 kvm_start_guest:
+
+	/* Set runlatch bit the minute you wake up from nap */
+	mfspr	r1, SPRN_CTRLF
+	ori 	r1, r1, 1
+	mtspr	SPRN_CTRLT, r1
+
 	ld	r2,PACATOC(r13)
 
 	li	r0,KVM_HWTHREAD_IN_KVM

^ permalink raw reply related

* [PATCH 1/3] ppc/powernv: Set the runlatch bits correctly for offline cpus
From: Preeti U Murthy @ 2014-04-11 10:31 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, linux-kernel, srivatsa.bhat
In-Reply-To: <20140411103030.27683.2107.stgit@preeti.in.ibm.com>

Up until now we have been setting the runlatch bits for a busy CPU and
clearing it when a CPU enters idle state. The runlatch bit has thus
been consistent with the utilization of a CPU as long as the CPU is online.

However when a CPU is hotplugged out the runlatch bit is not cleared. It
needs to be cleared to indicate an unused CPU. Hence this patch has the
runlatch bit cleared for an offline CPU just before entering an idle state
and sets it immediately after it exits the idle state.

Signed-off-by: Preeti U Murthy <preeti@linux.vnet.ibm.com>
Acked-by: Paul Mackerras <paulus@samba.org>
Reviewed-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---

 arch/powerpc/platforms/powernv/smp.c |    3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c
index 908672b..bf5fcd4 100644
--- a/arch/powerpc/platforms/powernv/smp.c
+++ b/arch/powerpc/platforms/powernv/smp.c
@@ -30,6 +30,7 @@
 #include <asm/cputhreads.h>
 #include <asm/xics.h>
 #include <asm/opal.h>
+#include <asm/runlatch.h>
 
 #include "powernv.h"
 
@@ -156,7 +157,9 @@ static void pnv_smp_cpu_kill_self(void)
 	 */
 	mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
 	while (!generic_check_cpu_restart(cpu)) {
+		ppc64_runlatch_off();
 		power7_nap();
+		ppc64_runlatch_on();
 		if (!generic_check_cpu_restart(cpu)) {
 			DBG("CPU%d Unexpected exit while offline !\n", cpu);
 			/* We may be getting an IPI, so we re-enable

^ permalink raw reply related

* [PATCH 0/3] ppc:Set runlatch bits correctly for offline threads and vcpus
From: Preeti U Murthy @ 2014-04-11 10:31 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: paulus, linux-kernel, srivatsa.bhat

The runlatch bits with their value indicated by CTRL_RUNLATCH are set and
cleared in the SPRN_CTRL registers to indicate a busy and idle cpu
respectively. This is currently being done in the cpuidle path of the host.
But needs to be taken care of in hotplug and kvm scenarios. This patchset
is aimed at ensuring that the runlatch bits are consisten with the
utilization of a CPU under all circumstances.
---

Preeti U Murthy (3):
      ppc/powernv: Set the runlatch bits correctly for offline cpus
      ppc/kvm: Set the runlatch bit of a CPU just before starting guest
      ppc/kvm: Clear the runlatch bit of a vcpu before napping


 arch/powerpc/kvm/book3s_hv_rmhandlers.S |   18 +++++++++++++++++-
 arch/powerpc/platforms/powernv/smp.c    |    3 +++
 2 files changed, 20 insertions(+), 1 deletion(-)

-- 

^ permalink raw reply

* [PATCH] ASoC: fsl_sai: Use FSL_SAI_xXR() and regmap_update_bits() to simplify code
From: Nicolin Chen @ 2014-04-11 10:30 UTC (permalink / raw)
  To: broonie; +Cc: alsa-devel, Li.Xiubo, linuxppc-dev, linux-kernel, timur

By doing this, the driver can drop around 50 lines and become neater.

Signed-off-by: Nicolin Chen <Guangyu.Chen@freescale.com>
---
 sound/soc/fsl/fsl_sai.c | 101 ++++++++++++------------------------------------
 1 file changed, 25 insertions(+), 76 deletions(-)

diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 5fff2e1..9858d42 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -93,16 +93,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
 		int clk_id, unsigned int freq, int fsl_dir)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 val_cr2, reg_cr2;
-
-	if (fsl_dir == FSL_FMT_TRANSMITTER)
-		reg_cr2 = FSL_SAI_TCR2;
-	else
-		reg_cr2 = FSL_SAI_RCR2;
-
-	regmap_read(sai->regmap, reg_cr2, &val_cr2);
-
-	val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
+	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
+	u32 val_cr2 = 0;
 
 	switch (clk_id) {
 	case FSL_SAI_CLK_BUS:
@@ -121,7 +113,8 @@ static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
 		return -EINVAL;
 	}
 
-	regmap_write(sai->regmap, reg_cr2, val_cr2);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+			   FSL_SAI_CR2_MSEL_MASK, val_cr2);
 
 	return 0;
 }
@@ -153,22 +146,10 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 				unsigned int fmt, int fsl_dir)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 val_cr2, val_cr4, reg_cr2, reg_cr4;
-
-	if (fsl_dir == FSL_FMT_TRANSMITTER) {
-		reg_cr2 = FSL_SAI_TCR2;
-		reg_cr4 = FSL_SAI_TCR4;
-	} else {
-		reg_cr2 = FSL_SAI_RCR2;
-		reg_cr4 = FSL_SAI_RCR4;
-	}
+	bool tx = fsl_dir == FSL_FMT_TRANSMITTER;
+	u32 val_cr2 = 0, val_cr4 = 0;
 
-	regmap_read(sai->regmap, reg_cr2, &val_cr2);
-	regmap_read(sai->regmap, reg_cr4, &val_cr4);
-
-	if (sai->big_endian_data)
-		val_cr4 &= ~FSL_SAI_CR4_MF;
-	else
+	if (!sai->big_endian_data)
 		val_cr4 |= FSL_SAI_CR4_MF;
 
 	/* DAI mode */
@@ -189,7 +170,6 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		 * frame sync asserts with the first bit of the frame.
 		 */
 		val_cr2 |= FSL_SAI_CR2_BCP;
-		val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
 		/*
@@ -199,7 +179,6 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		 * data word.
 		 */
 		val_cr2 |= FSL_SAI_CR2_BCP;
-		val_cr4 &= ~FSL_SAI_CR4_FSP;
 		val_cr4 |= FSL_SAI_CR4_FSE;
 		sai->is_dsp_mode = true;
 		break;
@@ -209,7 +188,6 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		 * frame sync asserts with the first bit of the frame.
 		 */
 		val_cr2 |= FSL_SAI_CR2_BCP;
-		val_cr4 &= ~(FSL_SAI_CR4_FSE | FSL_SAI_CR4_FSP);
 		sai->is_dsp_mode = true;
 		break;
 	case SND_SOC_DAIFMT_RIGHT_J:
@@ -247,23 +225,22 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
 		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFM:
-		val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
-		val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
 		break;
 	case SND_SOC_DAIFMT_CBS_CFM:
 		val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
-		val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
 		break;
 	case SND_SOC_DAIFMT_CBM_CFS:
-		val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
 		val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	regmap_write(sai->regmap, reg_cr2, val_cr2);
-	regmap_write(sai->regmap, reg_cr4, val_cr4);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx),
+			   FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+			   FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
+			   FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
 
 	return 0;
 }
@@ -290,29 +267,10 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	unsigned int channels = params_channels(params);
 	u32 word_width = snd_pcm_format_width(params_format(params));
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		reg_cr4 = FSL_SAI_TCR4;
-		reg_cr5 = FSL_SAI_TCR5;
-		reg_mr = FSL_SAI_TMR;
-	} else {
-		reg_cr4 = FSL_SAI_RCR4;
-		reg_cr5 = FSL_SAI_RCR5;
-		reg_mr = FSL_SAI_RMR;
-	}
-
-	regmap_read(sai->regmap, reg_cr4, &val_cr4);
-	regmap_read(sai->regmap, reg_cr4, &val_cr5);
-
-	val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
-	val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
-
-	val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
-	val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
-	val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
+	u32 val_cr4 = 0, val_cr5 = 0;
 
 	if (!sai->is_dsp_mode)
 		val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
@@ -320,18 +278,20 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
 	val_cr5 |= FSL_SAI_CR5_WNW(word_width);
 	val_cr5 |= FSL_SAI_CR5_W0W(word_width);
 
-	val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
 	if (sai->big_endian_data)
 		val_cr5 |= FSL_SAI_CR5_FBT(0);
 	else
 		val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
 
 	val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
-	val_mr = ~0UL - ((1 << channels) - 1);
 
-	regmap_write(sai->regmap, reg_cr4, val_cr4);
-	regmap_write(sai->regmap, reg_cr5, val_cr5);
-	regmap_write(sai->regmap, reg_mr, val_mr);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx),
+			   FSL_SAI_CR4_SYWD_MASK | FSL_SAI_CR4_FRSZ_MASK,
+			   val_cr4);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR5(tx),
+			   FSL_SAI_CR5_WNW_MASK | FSL_SAI_CR5_W0W_MASK |
+			   FSL_SAI_CR5_FBT_MASK, val_cr5);
+	regmap_write(sai->regmap, FSL_SAI_xMR(tx), ~0UL - ((1 << channels) - 1));
 
 	return 0;
 }
@@ -401,8 +361,8 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 	struct device *dev = &sai->pdev->dev;
-	u32 reg;
 	int ret;
 
 	ret = clk_prepare_enable(sai->bus_clk);
@@ -411,12 +371,7 @@ static int fsl_sai_startup(struct snd_pcm_substream *substream,
 		return ret;
 	}
 
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		reg = FSL_SAI_TCR3;
-	else
-		reg = FSL_SAI_RCR3;
-
-	regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE,
 			   FSL_SAI_CR3_TRCE);
 
 	return 0;
@@ -426,15 +381,9 @@ static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
 		struct snd_soc_dai *cpu_dai)
 {
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
-	u32 reg;
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		reg = FSL_SAI_TCR3;
-	else
-		reg = FSL_SAI_RCR3;
+	bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
 
-	regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
-			   ~FSL_SAI_CR3_TRCE);
+	regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx), FSL_SAI_CR3_TRCE, 0);
 
 	clk_disable_unprepare(sai->bus_clk);
 }
-- 
1.8.4

^ permalink raw reply related


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