LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] powerpc: handle VSX alignment faults correctly in little-endian mode
From: Neil Campbell @ 2009-12-14 14:08 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Michael Neuling

This patch fixes the handling of VSX alignment faults in little-endian
mode (the current code assumes the processor is in big-endian mode).

The patch also makes the handlers clear the top 8 bytes of the register
when handling an 8 byte VSX load.

This is based on 2.6.32.

Signed-off-by: Neil Campbell <neilc@linux.vnet.ibm.com>
Cc: <stable@kernel.org>
---
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index a5b632e..f0c624f 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg,
  */
 static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
 		       unsigned int areg, struct pt_regs *regs,
-		       unsigned int flags, unsigned int length)
+		       unsigned int flags, unsigned int length,
+		       unsigned int elsize)
 {
 	char *ptr;
+	unsigned long *lptr;
 	int ret = 0;
+	int sw = 0;
+	int i, j;
 
 	flush_vsx_to_thread(current);
 
@@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
 	else
 		ptr = (char *) &current->thread.vr[reg - 32];
 
-	if (flags & ST)
-		ret = __copy_to_user(addr, ptr, length);
-        else {
-		if (flags & SPLT){
-			ret = __copy_from_user(ptr, addr, length);
-			ptr += length;
+	lptr = (unsigned long *) ptr;
+
+	if (flags & SW)
+		sw = elsize-1;
+
+	for (j = 0; j < length; j += elsize) {
+		for (i = 0; i < elsize; ++i) {
+			if (flags & ST)
+				ret |= __put_user(ptr[i^sw], addr + i);
+			else
+				ret |= __get_user(ptr[i^sw], addr + i);
 		}
-		ret |= __copy_from_user(ptr, addr, length);
+		ptr  += elsize;
+		addr += elsize;
 	}
-	if (flags & U)
-		regs->gpr[areg] = regs->dar;
-	if (ret)
+
+	if (!ret) {
+		if (flags & U)
+			regs->gpr[areg] = regs->dar;
+
+		/* Splat load copies the same data to top and bottom 8 bytes */
+		if (flags & SPLT)
+			lptr[1] = lptr[0];
+		/* For 8 byte loads, zero the top 8 bytes */
+		else if (!(flags & ST) && (8 == length))
+			lptr[1] = 0;
+	} else
 		return -EFAULT;
+
 	return 1;
 }
 #endif
@@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs)
 
 #ifdef CONFIG_VSX
 	if ((instruction & 0xfc00003e) == 0x7c000018) {
-		/* Additional register addressing bit (64 VSX vs 32 FPR/GPR */
+		unsigned int elsize;
+
+		/* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */
 		reg |= (instruction & 0x1) << 5;
 		/* Simple inline decoder instead of a table */
+		/* VSX has only 8 and 16 byte memory accesses */
+		nb = 8;
 		if (instruction & 0x200)
 			nb = 16;
-		else if (instruction & 0x080)
-			nb = 8;
-		else
-			nb = 4;
+
+		/* Vector stores in little-endian mode swap individual
+		   elements, so process them separately */
+		elsize = 4;
+		if (instruction & 0x80)
+			elsize = 8;
+
 		flags = 0;
+		if (regs->msr & MSR_LE)
+			flags |= SW;
 		if (instruction & 0x100)
 			flags |= ST;
 		if (instruction & 0x040)
@@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs)
 			nb = 8;
 		}
 		PPC_WARN_EMULATED(vsx);
-		return emulate_vsx(addr, reg, areg, regs, flags, nb);
+		return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);
 	}
 #endif
 	/* A size of 0 indicates an instruction we don't support, with

^ permalink raw reply related

* Re: [PATCH] powerpc: handle VSX alignment faults correctly in little-endian mode
From: Neil Campbell @ 2009-12-14 14:21 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Michael Neuling
In-Reply-To: <4B2646F9.4000203@linux.vnet.ibm.com>

Neil Campbell wrote:
> This patch fixes the handling of VSX alignment faults in little-endian
> mode (the current code assumes the processor is in big-endian mode).
> 
> The patch also makes the handlers clear the top 8 bytes of the register
> when handling an 8 byte VSX load.

For the interested, here is a test case that demonstrates the problem.

It should compile with something like:

gcc -m64 -Wa,-mregnames -fno-strict-aliasing -mcpu=power7 -mvsx vsx_le.c -o vsx_le

On an unpatched kernel it reports 8 failures for me, the patch fixes all 8 of these.

---

#include <stdio.h>
#include <string.h>

int fails = 0;

#define LOAD_FUNC(name,inst) \
void test_load_##name(char* input, char* output, int le) \
{ \
  int aligned = (0 == ((long)input & 15)); \
  char* alignstr = aligned?"aligned:   ":"unaligned: "; \
  char* modestr = le?"(le)":"(be)"; \
  int i; \
  char dummydata[16] __attribute__((__aligned__(16))) = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; \
 \
  memset(output, 0, 16); \
 \
  asm ( \
      "mr r15, %[address1]\n\t" \
      "mr r16, %[address2]\n\t" \
      "lvx v0, r0, %[address3]\n\t" /* set register to dummy values */ \
      "cmpwi %[le],1 \n\t" \
      "beq "#name"leversion \n\t" \
      #name" vs32, r0, r15\n\t" \
      "b " #name"store\n\t" \
      #name"leversion: \n\t" \
      "li r0, 171\n\t" \
      "li r3, 20\n\t" \
      "li r4, 1\n\t" \
      "sc\n\t" \
      ".long " inst "\n\t" \
      ".long 0xab000038\n\t" /*"li 0, 171\n\t"*/ \
      ".long 0x14006038\n\t" /*"li 3, 20\n\t"*/ \
      ".long 0x00008038\n\t" /*"li 4, 0\n\t"*/ \
      ".long 0x02000044\n\t" /*"sc\n\t"*/ \
      #name"store: \n\t" \
      "stvx v0,r0,r16 \n\t" \
      : \
      : [address1] "b" (input), [address2] "b" (output), [address3] "b" (dummydata), [le] "b" (le) \
      : "vs32", "r0", "r3", "r4", "r9", "r15", "r16", "cc",  "memory"); \
 \
  fprintf(stderr, #name" %s after %s  ", alignstr, modestr); \
  for (i = 0; i < 16; ++i) \
  { \
    fprintf(stderr, " %x ", output[i]); \
  } \
  fprintf(stderr, "\n"); \
} \


#define STORE_FUNC(name,inst) \
void test_store_##name(char* input, char* output, int le) \
{ \
  int aligned = (0 == ((long)output & 15)); \
  char* alignstr = aligned?"aligned:   ":"unaligned: "; \
  char* modestr = le?"(le)":"(be)"; \
  int i; \
 \
  memset(output, 0, 16); \
 \
  asm ( \
      "mr r15, %[address2]\n\t" \
      "lvx v0, r0, %[address1]\n\t" \
      "cmpwi %[le],1 \n\t" \
      "beq "#name"leversion \n\t" \
      #name" vs32, r0, r15\n\t" \
      "b " #name"end\n\t" \
      #name"leversion: \n\t" \
      "li r0, 171\n\t" \
      "li r3, 20\n\t" \
      "li r4, 1\n\t" \
      "sc\n\t" \
      ".long " inst "\n\t" \
      ".long 0xab000038\n\t" /*"li 0, 171\n\t"*/ \
      ".long 0x14006038\n\t" /*"li 3, 20\n\t"*/ \
      ".long 0x00008038\n\t" /*"li 4, 0\n\t"*/ \
      ".long 0x02000044\n\t" /*"sc\n\t"*/ \
      #name"end: \n\t" \
      : \
      : [address1] "b" (input), [address2] "b" (output), [le] "b" (le) \
      : "vs32", "r0", "r3", "r4", "r9", "r15", "cc",  "memory"); \
 \
  fprintf(stderr, #name" %s after %s  ", alignstr, modestr); \
  for (i = 0; i < 16; ++i) \
  { \
    fprintf(stderr, " %x ", output[i]); \
  } \
  fprintf(stderr, "\n"); \
} \

void do_compare(char* buf1, char* buf2)
{
  if(0 == memcmp(buf1,buf2,16))
  {
    fprintf(stderr, "PASS\n");
  }
  else
  {
    fprintf(stderr, "FAIL\n");
    fails++;
  }
}

STORE_FUNC(stxvw4x, "0x197f007c")
STORE_FUNC(stxvd2x, "0x997f007c")
STORE_FUNC(stxsdx, "0x997d007c")

LOAD_FUNC(lxvw4x, "0x197e007c")
LOAD_FUNC(lxvd2x, "0x997e007c")
LOAD_FUNC(lxsdx, "0x997c007c")
LOAD_FUNC(lxvdsx, "0x997a007c")

int main(int argc, char* argv[])
{
  char inbuf[17] __attribute__((__aligned__(16))) = { -1, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
  char alignedinbuf[16] __attribute__((__aligned__(16))) = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf };
  char outbuf[17] __attribute__((__aligned__(16))) = { -1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
  char alignedoutbuf[16] __attribute__((__aligned__(16))) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
  char alignedoutbuf2[16] __attribute__((__aligned__(16))) = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

  test_store_stxvw4x(alignedinbuf, alignedoutbuf, 0);
  test_store_stxvw4x(alignedinbuf, &outbuf[1], 0);
  do_compare(alignedoutbuf, &outbuf[1]);
  test_store_stxvw4x(alignedinbuf, alignedoutbuf, 1);
  test_store_stxvw4x(alignedinbuf, &outbuf[1], 1);
  do_compare(alignedoutbuf, &outbuf[1]);
  fprintf(stderr, "\n");

  test_store_stxvd2x(alignedinbuf, alignedoutbuf, 0);
  test_store_stxvd2x(alignedinbuf, &outbuf[1], 0);
  do_compare(alignedoutbuf, &outbuf[1]);
  test_store_stxvd2x(alignedinbuf, alignedoutbuf, 1);
  test_store_stxvd2x(alignedinbuf, &outbuf[1], 1);
  do_compare(alignedoutbuf, &outbuf[1]);
  fprintf(stderr, "\n");

  test_store_stxsdx(alignedinbuf, alignedoutbuf, 0);
  test_store_stxsdx(alignedinbuf, &outbuf[1], 0);
  do_compare(alignedoutbuf, &outbuf[1]);
  test_store_stxsdx(alignedinbuf, alignedoutbuf, 1);
  test_store_stxsdx(alignedinbuf, &outbuf[1], 1);
  do_compare(alignedoutbuf, &outbuf[1]);
  fprintf(stderr, "\n");

  test_load_lxvw4x(alignedinbuf, alignedoutbuf, 0);
  test_load_lxvw4x(&inbuf[1], alignedoutbuf2, 0);
  do_compare(alignedoutbuf, alignedoutbuf2);
  test_load_lxvw4x(alignedinbuf, alignedoutbuf, 1);
  test_load_lxvw4x(&inbuf[1], alignedoutbuf2, 1);
  do_compare(alignedoutbuf, alignedoutbuf2);
  fprintf(stderr, "\n");

  test_load_lxvd2x(alignedinbuf, alignedoutbuf, 0);
  test_load_lxvd2x(&inbuf[1], alignedoutbuf2, 0);
  do_compare(alignedoutbuf, alignedoutbuf2);
  test_load_lxvd2x(alignedinbuf, alignedoutbuf, 1);
  test_load_lxvd2x(&inbuf[1], alignedoutbuf2, 1);
  do_compare(alignedoutbuf, alignedoutbuf2);
  fprintf(stderr, "\n");

  test_load_lxsdx(alignedinbuf, alignedoutbuf, 0);
  test_load_lxsdx(&inbuf[1], alignedoutbuf2, 0);
  do_compare(alignedoutbuf, alignedoutbuf2);
  test_load_lxsdx(alignedinbuf, alignedoutbuf, 1);
  test_load_lxsdx(&inbuf[1], alignedoutbuf2, 1);
  do_compare(alignedoutbuf, alignedoutbuf2);
  fprintf(stderr, "\n");

  test_load_lxvdsx(alignedinbuf, alignedoutbuf, 0);
  test_load_lxvdsx(&inbuf[1], alignedoutbuf2, 0);
  do_compare(alignedoutbuf, alignedoutbuf2);
  test_load_lxvdsx(alignedinbuf, alignedoutbuf, 1);
  test_load_lxvdsx(&inbuf[1], alignedoutbuf2, 1);
  do_compare(alignedoutbuf, alignedoutbuf2);
  fprintf(stderr, "\n");

  fprintf(stderr, "%d tests failed\n", fails);
  return fails;
}

^ permalink raw reply

* [PATCH v2 0/2] USB: ehci-fsl: Power management support
From: Anton Vorontsov @ 2009-12-14 15:40 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Scott Wood, Jerry Huang, linux-usb, linuxppc-dev

Hi all,

The patches were waiting for commit 2e9d546eda5888962a441da1e96bbf9
("powerpc/fsl: Make fsl_deep_sleep() usable w/ modules and non-83xx
builds") to hit Linus' tree.

Now that the commit is in, I'm resending the series with some
corrections as suggested[1] by Scott Wood.

It might be late for 2.6.33, but I believe that the patches are
actually quite safe.

Thanks!

[1] http://www.mail-archive.com/linuxppc-dev@lists.ozlabs.org/msg37297.html

-- 
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2

^ permalink raw reply

* [PATCH 1/2] USB: ehci-fsl: Fix sparse warnings
From: Anton Vorontsov @ 2009-12-14 15:41 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Scott Wood, Jerry Huang, linux-usb, linuxppc-dev
In-Reply-To: <20091214154025.GA24035@oksana.dev.rtsoft.ru>

This patch fixes following warnings:

ehci-fsl.c:43:5: warning: symbol 'usb_hcd_fsl_probe' was not declared. Should it be static?
ehci-fsl.c:150:6: warning: symbol 'usb_hcd_fsl_remove' was not declared. Should it be static?

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 drivers/usb/host/ehci-fsl.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 9911749..593a7e7 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -40,8 +40,8 @@
  * Allocates basic resources for this USB host controller.
  *
  */
-int usb_hcd_fsl_probe(const struct hc_driver *driver,
-		      struct platform_device *pdev)
+static int usb_hcd_fsl_probe(const struct hc_driver *driver,
+			     struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata;
 	struct usb_hcd *hcd;
@@ -147,7 +147,8 @@ int usb_hcd_fsl_probe(const struct hc_driver *driver,
  * Reverses the effect of usb_hcd_fsl_probe().
  *
  */
-void usb_hcd_fsl_remove(struct usb_hcd *hcd, struct platform_device *pdev)
+static void usb_hcd_fsl_remove(struct usb_hcd *hcd,
+			       struct platform_device *pdev)
 {
 	usb_remove_hcd(hcd);
 	iounmap(hcd->regs);
-- 
1.6.3.3

^ permalink raw reply related

* [PATCH 2/2] USB: ehci-fsl: Add power management support
From: Anton Vorontsov @ 2009-12-14 15:41 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Scott Wood, Jerry Huang, linux-usb, linuxppc-dev
In-Reply-To: <20091214154025.GA24035@oksana.dev.rtsoft.ru>

EHCI FSL controller preserve its state during sleep mode, so nothing
fancy needs to be done.

Though, during 'deep sleep' mode (as found in MPC831x CPUs) the
controller turns off and needs to be reinitialized upon resume.

This patch adds support for hibernation and resuming after deep sleep.
Based on Dave Liu and Jerry Huang's work[1].

[1] http://www.bitshrine.org/gpp/linux-fsl-2.6.24.3-MPC8315ERDB-usb-power-mangement.patch

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 drivers/usb/host/ehci-fsl.c |   90 +++++++++++++++++++++++++++++++++++++++---
 1 files changed, 83 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 593a7e7..0e26aa1 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2005 MontaVista Software
+ * Copyright 2005-2009 MontaVista Software, Inc.
+ * Copyright 2008      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
@@ -17,17 +18,20 @@
  *
  * Ported to 834x by Randy Vinson <rvinson@mvista.com> using code provided
  * by Hunter Wu.
+ * Power Management support by Dave Liu <daveliu@freescale.com>,
+ * Jerry Huang <Chang-Ming.Huang@freescale.com> and
+ * Anton Vorontsov <avorontsov@ru.mvista.com>.
  */
 
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
 #include <linux/platform_device.h>
 #include <linux/fsl_devices.h>
 
 #include "ehci-fsl.h"
 
-/* FIXME: Power Management is un-ported so temporarily disable it */
-#undef CONFIG_PM
-
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -285,10 +289,81 @@ static int ehci_fsl_setup(struct usb_hcd *hcd)
 	return retval;
 }
 
+struct ehci_fsl {
+	struct ehci_hcd	ehci;
+
+#ifdef CONFIG_PM
+	/* Saved USB PHY settings, need to restore after deep sleep. */
+	u32 usb_ctrl;
+#endif
+};
+
+#ifdef CONFIG_PM
+
+static struct ehci_fsl *hcd_to_ehci_fsl(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+
+	return container_of(ehci, struct ehci_fsl, ehci);
+}
+
+static int ehci_fsl_drv_suspend(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+	void __iomem *non_ehci = hcd->regs;
+
+	if (!fsl_deep_sleep())
+		return 0;
+
+	ehci_fsl->usb_ctrl = in_be32(non_ehci + FSL_SOC_USB_CTRL);
+	return 0;
+}
+
+static int ehci_fsl_drv_resume(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+	struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	void __iomem *non_ehci = hcd->regs;
+
+	if (!fsl_deep_sleep())
+		return 0;
+
+	usb_root_hub_lost_power(hcd->self.root_hub);
+
+	/* Restore USB PHY settings and enable the controller. */
+	out_be32(non_ehci + FSL_SOC_USB_CTRL, ehci_fsl->usb_ctrl);
+
+	ehci_reset(ehci);
+	ehci_fsl_reinit(ehci);
+
+	return 0;
+}
+
+static int ehci_fsl_drv_restore(struct device *dev)
+{
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	usb_root_hub_lost_power(hcd->self.root_hub);
+	return 0;
+}
+
+static struct dev_pm_ops ehci_fsl_pm_ops = {
+	.suspend = ehci_fsl_drv_suspend,
+	.resume = ehci_fsl_drv_resume,
+	.restore = ehci_fsl_drv_restore,
+};
+
+#define EHCI_FSL_PM_OPS		(&ehci_fsl_pm_ops)
+#else
+#define EHCI_FSL_PM_OPS		NULL
+#endif /* CONFIG_PM */
+
 static const struct hc_driver ehci_fsl_hc_driver = {
 	.description = hcd_name,
 	.product_desc = "Freescale On-Chip EHCI Host Controller",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
+	.hcd_priv_size = sizeof(struct ehci_fsl),
 
 	/*
 	 * generic hardware linkage
@@ -355,6 +430,7 @@ static struct platform_driver ehci_fsl_driver = {
 	.remove = ehci_fsl_drv_remove,
 	.shutdown = usb_hcd_platform_shutdown,
 	.driver = {
-		   .name = "fsl-ehci",
+		.name = "fsl-ehci",
+		.pm = EHCI_FSL_PM_OPS,
 	},
 };
-- 
1.6.3.3

^ permalink raw reply related

* Re: spi_mpc8xxx.c: chip select polarity problem
From: Torsten Fleischer @ 2009-12-14 16:54 UTC (permalink / raw)
  To: Grant Likely; +Cc: avorontsov, linuxppc-dev
In-Reply-To: <fa686aa40912090946m12fe293cg2efb043cb7a7f573@mail.gmail.com>

On Wed, Dec 9, 2009 at 18:46:51 Grant Likely wrote:
> <to-fleischer@t-online.de> wrote:
> [...]
> > The following patch adds a function to get the active state of the chip
> > select of a SPI device by looking for the 'spi-cs-high' property in the
> > associated device tree node.
> > This function is used by the spi_mpc8xxx driver to set a proper initial
> > value to the associated GPIOs.
> >
> >
> > Signed-off-by: Torsten Fleischer <to-fleischer@t-online.de>
> 
> I like this better.  See comments below.
> 
[...]

Hey Grant,

below there is a new version of the patch containing the modifications
according to your comments.

Thanks for the hints,
Torsten


Signed-off-by: Torsten Fleischer <to-fleischer@t-online.de>
---

diff -ruN linux-2.6.32_orig//drivers/of/of_spi.c linux-2.6.32/drivers/of/of_spi.c
--- linux-2.6.32_orig//drivers/of/of_spi.c	2009-12-03 04:51:21.000000000 +0100
+++ linux-2.6.32/drivers/of/of_spi.c	2009-12-11 17:57:22.016787665 +0100
@@ -12,6 +12,43 @@
 #include <linux/of_spi.h>
 
 /**
+ * of_get_spi_cs_active_state - Gets the chip select's active state of a SPI
+ * child devices.
+ * @np:        parent node of the SPI device nodes
+ * @index:     index/address of the SPI device (refers to the 'reg' property)
+ *
+ * Returns 0 for 'active low' or if the child's node can't be found.
+ * Otherwise it returns 1 ('active high').
+ */
+bool of_get_spi_cs_active_state(struct device_node *np, int index)
+{
+	struct device_node *child;
+	const int *prop;
+	int len;
+	bool active = 0;
+
+	/* search for the matching SPI device */
+	for_each_child_of_node(np, child) {
+		prop = of_get_property(child, "reg", &len);
+		if (!prop || len < sizeof(*prop)) {
+			/* property 'reg' not available (not an error) */
+			continue;
+		}
+
+		if ( *prop == index ) {
+			/* matching device found */
+			if (of_find_property(child, "spi-cs-high", NULL))
+				active = 1;
+			break;
+		}
+	}
+
+	return active;
+}
+EXPORT_SYMBOL(of_get_spi_cs_active_state);
+
+
+/**
  * of_register_spi_devices - Register child devices onto the SPI bus
  * @master:	Pointer to spi_master device
  * @np:		parent node of SPI device nodes
diff -ruN linux-2.6.32_orig//drivers/spi/spi_mpc8xxx.c linux-2.6.32/drivers/spi/spi_mpc8xxx.c
--- linux-2.6.32_orig//drivers/spi/spi_mpc8xxx.c	2009-12-03 04:51:21.000000000 +0100
+++ linux-2.6.32/drivers/spi/spi_mpc8xxx.c	2009-12-11 17:15:47.957379333 +0100
@@ -705,6 +705,7 @@
 	for (; i < ngpios; i++) {
 		int gpio;
 		enum of_gpio_flags flags;
+		bool astate;
 
 		gpio = of_get_gpio_flags(np, i, &flags);
 		if (!gpio_is_valid(gpio)) {
@@ -721,8 +722,18 @@
 		pinfo->gpios[i] = gpio;
 		pinfo->alow_flags[i] = flags & OF_GPIO_ACTIVE_LOW;
 
+		/* get the active state of the SPI device */
+		astate = of_get_spi_cs_active_state(np, i);
+
+		/*
+		 *  alow_flags describe the wiring of the chip select
+		 *  (0 = non-inverted, 1 = inverted); this must be taken into
+		 *  account when setting the GPIO's initial value
+		 *  (see also mpc8xxx_spi_cs_control()); note that astate will
+		 *  be 0 for active low and 1 for active high respectively
+		 */
 		ret = gpio_direction_output(pinfo->gpios[i],
-					    pinfo->alow_flags[i]);
+					    pinfo->alow_flags[i] ^ !astate);
 		if (ret) {
 			dev_err(dev, "can't set output direction for gpio "
 				"#%d: %d\n", i, ret);
diff -ruN linux-2.6.32_orig//include/linux/of_spi.h linux-2.6.32/include/linux/of_spi.h
--- linux-2.6.32_orig//include/linux/of_spi.h	2009-12-03 04:51:21.000000000 +0100
+++ linux-2.6.32/include/linux/of_spi.h	2009-12-11 17:10:21.681380685 +0100
@@ -15,4 +15,7 @@
 extern void of_register_spi_devices(struct spi_master *master,
 				    struct device_node *np);
 
+extern bool of_get_spi_cs_active_state(struct device_node *np,
+					   int index);
+
 #endif /* __LINUX_OF_SPI */

^ permalink raw reply

* Re: [Patch 1/1] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: K.Prasad @ 2009-12-14 18:03 UTC (permalink / raw)
  To: Roland McGrath
  Cc: Michael Neuling, Benjamin Herrenschmidt, Frederic Weisbecker,
	David Gibson, linuxppc-dev, Alan Stern, paulus
In-Reply-To: <20091214005648.82BA31DE@magilla.sf.frob.com>

On Sun, Dec 13, 2009 at 04:56:48PM -0800, Roland McGrath wrote:
> I can't see anything you've done to keep this use of MSR_SE in the
> user-mode register state from interfering with user_enable_single_step().
> It looks to me like you'd swallow the normal step indications.
> 

Yes, it does unset MSR_SE bit in single_step_dabr_instruction()
irrespective of whether it was previously enabled through
user_enable_single_step(). This could be mitigated with the use of a
separate flag which can be used to conditionally unset MSR_SE, however
given further concerns about pre-emption (as expressed by you below),
I'm afraid of substantial revamp of the user-space semantics.

> Likewise I'm not very clear on the interaction with kprobes, kgdb,
> or whatnot for kernel-mode cases.  But I'll leave those concerns to
> others, since I know more about the user-mode situations.
>

Kprobes has been tested to work simultaneously with hw-breakpoints. KGDB
has not been ported yet to use the hw-breakpoint interfaces (KGDB had
issues in it, that prevented it from being tested during our
development...though its maintainer has begun showing interest
recently).

Xmon was (and I believe is still) in a state where data breakpoints did
not work. It needs to be ported too, to benefit from the hw-breakpoint
interfaces.
 
> Back to the user-mode case, is it really reasonable to disable
> preemption in hw_breakpoint_handler and leave it so across returning
> to user mode?  (Is that even possible?  I thought user mode was
> always preemptible.)  That is done very casually with little comment
> in hw_breakpoint_handler and single_step_dabr_instruction, but it
> seems like an extremely deep and magical thing that merits more
> explanation.  I guess the need for it has to do with the per_cpu
> variable you're using, but the whole situation is not very clear on
> first reading.  Even for kernel mode, what does this mean when the
> stepped instruction does a page fault?
> 

I must admit that the issue of pre-emption should have been given more
thought. Suppose there's a stream of user-space instructions "i1, i2, i3,
.....i<n>" and if 'i2' instruction can cause a hw-breakpoint exception,
then there exists a small window between i1 and i2 where pre-emption is
disabled (while a schedule operation could have taken place otherwise).

Disabling pre-emption is necessary to ensure that hw-breakpoints are
enabled immediately after the causative instruction has finished
execution (the control flow may go astray if pre-emption occurs between
i1 and i2). The root cause of this behaviour is a combination of
'trigger-before-execute' behaviour (for data-exceptions) and a desire
for 'continuous' exceptions (as opposed to one-shot behaviour seen in
ptrace). The per-cpu variable 'last_hit_bp' just helps identify a
single-step exception resulting from a hbp_handler vs other sources.

Resorting to one-shot behaviour (which is the easiest workaround
available) will break the desired uniformity in behaviour for
hw-breakpoint interfaces - say every register_user_<> interface must be
accompanied by a unregister_<> interface, etc. Post perf-events'
integration, ensuring a one-shot behaviour might also have its own
bunch of undesirable consequences (such as circular locks), that must be
overcome.

Unless I see a way to re-instate the breakpoints (surviving a
pre-emption), I will send out a new patch that resorts to a one-shot
behaviour for user-space (kernel-space is fine though).

Thank you for the insightful comments!

K.Prasad

^ permalink raw reply

* Re: [Patch 1/1] PPC64-HWBKPT: Implement hw-breakpoints for PPC64
From: Roland McGrath @ 2009-12-14 19:26 UTC (permalink / raw)
  To: prasad
  Cc: Michael Neuling, Benjamin Herrenschmidt, Frederic Weisbecker,
	David Gibson, linuxppc-dev, Alan Stern, paulus
In-Reply-To: <20091214180324.GA18406@in.ibm.com>

> Yes, it does unset MSR_SE bit in single_step_dabr_instruction()
> irrespective of whether it was previously enabled through
> user_enable_single_step(). This could be mitigated with the use of a
> separate flag which can be used to conditionally unset MSR_SE, however
> given further concerns about pre-emption (as expressed by you below),
> I'm afraid of substantial revamp of the user-space semantics.

There is already TIF_SINGLESTEP set by user_enable_single_step.  So for
that aspect, it is probably relatively straightforward to cover that
interaction.  The code has to be pretty exact and will merit some comments
about subtleties, but I suspect the actual new code required will be just a
tiny amount.

> Kprobes has been tested to work simultaneously with hw-breakpoints. KGDB
> has not been ported yet to use the hw-breakpoint interfaces (KGDB had
> issues in it, that prevented it from being tested during our
> development...though its maintainer has begun showing interest
> recently).
> 
> Xmon was (and I believe is still) in a state where data breakpoints did
> not work. It needs to be ported too, to benefit from the hw-breakpoint
> interfaces.

That is not really what I meant at all.  That is good stuff to work out.
But I just meant the interactions with kprobes/kgdb's use of single-stepping,
the direct analogy to the user_enable_single_step issue.

> I must admit that the issue of pre-emption [...]

I understand the reason for using stepping.  (I have advised in the past
that I thought this magical implicit step logic was too hairy to roll in
under the covers and that a low-level facility expressing the different
hardware semantics to a kernel API would be OK.  I do agree with the
motivation of cross-arch uniformity of the semantics.  I don't object to
making it magically right--I just expressed general skepticism/fear about
getting that right so that I didn't want to try writing that magic.  Now
I'm just responding about the particular details I've noticed about that
can of worms.  It's certainly great if you can resolve all that.  But I'll
note that I am still by no means confident that the details I have raised
cover all the worms in that can.)

What remains less than clear is how preemption relates.  For any per-thread
hw_breakpoint, there is no high-level reason to care one way or the other.
The thread, its HW breakpoints, its register state including state of
stepping, are all part of per-thread state and no reason to do any less (or
more) preemption than normally happens.

> Disabling pre-emption is necessary to ensure that hw-breakpoints are
> enabled immediately after the causative instruction has finished
> execution (the control flow may go astray if pre-emption occurs between
> i1 and i2).

I don't understand what "go astray" means here.  The only thing I can think
of is the effect on any per-cpu variables you are using in hw_breakpoint
implementation.


Thanks,
Roland

^ permalink raw reply

* Re: [PATCH] powerpc/mm: fix typo of cpumask_clear_cpu()
From: Benjamin Herrenschmidt @ 2009-12-14 20:18 UTC (permalink / raw)
  To: Li Yang; +Cc: linuxppc-dev
In-Reply-To: <1260795709-16165-1-git-send-email-leoli@freescale.com>

On Mon, 2009-12-14 at 21:01 +0800, Li Yang wrote:
> The function name of cpumask_clear_cpu was not correct.
> 
> Reported-by: Jin Qing <b24347@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> ---
> This also implies that the CONFIG_HOTPLUG_CPU was never tested.
> We are trying to add cpu hotplug for SMP suspend, but seeing the
> following error(on 2.6.31 with context patches applied).
> Any idea or suggestion?

Hotplug hass indeed never been tested on BookE as we lack a platform
that supports it :-)

As you log, it's useless since you haven't compiled verbose BUG info in
your kernel so the message indicating the file/line of the error is
absent.

Ben.

> ------------[ cut here ]------------
> Badness at c00161b0 [verbose debug info unavailable]
> NIP: c00161b0 LR: c0016190 CTR: c0038f7c
> REGS: eec61e10 TRAP: 0700   Not tainted  (2.6.31-00040-g7c92556-dirty)
> MSR: 00021000 <ME,CE>  CR: 22280028  XER: 00000000
> TASK = eec54980[0] 'swapper' THREAD: eec60000 CPU: 1
> GPR00: 00000001 eec61ec0 eec54980 c0562ea0 eecad500 00000000 00000000 00000001
> GPR08: 00eed000 00000000 00000001 eecad67c 00001ca8 00000000 00021000 eec60040
> GPR16: eec54b0c c05208a0 c055fbe8 00000001 ffffffff c0560000 c0562ea0 00000004
> GPR24: eec60000 00000001 00000000 c0562e80 eec60000 c05291f8 eecad500 c05291f8
> NIP [c00161b0] switch_mmu_context+0x54/0x520
> LR [c0016190] switch_mmu_context+0x34/0x520
> Call Trace:
> [eec61ec0] [c00709c8] tick_program_event+0x50/0x60 (unreliable)
> [eec61f20] [c03beb54] schedule+0x2bc/0x7bc
> [eec61fa0] [c0008a8c] cpu_idle+0x160/0x170
> [eec61fc0] [c03c4be0] start_secondary+0x2d0/0x2e8
> [eec61ff0] [c0001c9c] __secondary_start+0x30/0x84
> Instruction dump:
> 543c0024 7ec3b378 833c0008 483ab1bd 813e0184 2f9d0000 39290001 913e0184
> 419e001c 813d0184 7d200034 5400d97e <0f000000> 3929ffff 913d0184 3d20c055
> MMU: More active contexts than CPUs ! (3 vs 2)
> MMU: More active contexts than CPUs ! (3 vs 2)
> 
> 
>  arch/powerpc/mm/mmu_context_nohash.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c
> index be4f34c..1044a63 100644
> --- a/arch/powerpc/mm/mmu_context_nohash.c
> +++ b/arch/powerpc/mm/mmu_context_nohash.c
> @@ -353,7 +353,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self,
>  		read_lock(&tasklist_lock);
>  		for_each_process(p) {
>  			if (p->mm)
> -				cpu_mask_clear_cpu(cpu, mm_cpumask(p->mm));
> +				cpumask_clear_cpu(cpu, mm_cpumask(p->mm));
>  		}
>  		read_unlock(&tasklist_lock);
>  	break;

^ permalink raw reply

* Re: [PATCH] powerpc: handle VSX alignment faults correctly in little-endian mode
From: Michael Neuling @ 2009-12-14 21:05 UTC (permalink / raw)
  To: Neil Campbell; +Cc: linuxppc-dev
In-Reply-To: <4B2646F9.4000203@linux.vnet.ibm.com>

> This patch fixes the handling of VSX alignment faults in little-endian
> mode (the current code assumes the processor is in big-endian mode).
> 
> The patch also makes the handlers clear the top 8 bytes of the register
> when handling an 8 byte VSX load.
> 
> This is based on 2.6.32.
> 
> Signed-off-by: Neil Campbell <neilc@linux.vnet.ibm.com>

Thanks for this Neil!

Acked-by: Michael Neuling <mikey@neuling.org>

> Cc: <stable@kernel.org>
> ---
> diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
> index a5b632e..f0c624f 100644
> --- a/arch/powerpc/kernel/align.c
> +++ b/arch/powerpc/kernel/align.c
> @@ -642,10 +642,14 @@ static int emulate_spe(struct pt_regs *regs, unsigned i
nt reg,
>   */
>  static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
>  		       unsigned int areg, struct pt_regs *regs,
> -		       unsigned int flags, unsigned int length)
> +		       unsigned int flags, unsigned int length,
> +		       unsigned int elsize)
>  {
>  	char *ptr;
> +	unsigned long *lptr;
>  	int ret = 0;
> +	int sw = 0;
> +	int i, j;
>  
>  	flush_vsx_to_thread(current);
>  
> @@ -654,19 +658,35 @@ static int emulate_vsx(unsigned char __user *addr, unsi
gned int reg,
>  	else
>  		ptr = (char *) &current->thread.vr[reg - 32];
>  
> -	if (flags & ST)
> -		ret = __copy_to_user(addr, ptr, length);
> -        else {
> -		if (flags & SPLT){
> -			ret = __copy_from_user(ptr, addr, length);
> -			ptr += length;
> +	lptr = (unsigned long *) ptr;
> +
> +	if (flags & SW)
> +		sw = elsize-1;
> +
> +	for (j = 0; j < length; j += elsize) {
> +		for (i = 0; i < elsize; ++i) {
> +			if (flags & ST)
> +				ret |= __put_user(ptr[i^sw], addr + i);
> +			else
> +				ret |= __get_user(ptr[i^sw], addr + i);
>  		}
> -		ret |= __copy_from_user(ptr, addr, length);
> +		ptr  += elsize;
> +		addr += elsize;
>  	}
> -	if (flags & U)
> -		regs->gpr[areg] = regs->dar;
> -	if (ret)
> +
> +	if (!ret) {
> +		if (flags & U)
> +			regs->gpr[areg] = regs->dar;
> +
> +		/* Splat load copies the same data to top and bottom 8 bytes */
> +		if (flags & SPLT)
> +			lptr[1] = lptr[0];
> +		/* For 8 byte loads, zero the top 8 bytes */
> +		else if (!(flags & ST) && (8 == length))
> +			lptr[1] = 0;
> +	} else
>  		return -EFAULT;
> +
>  	return 1;
>  }
>  #endif
> @@ -767,16 +787,25 @@ int fix_alignment(struct pt_regs *regs)
>  
>  #ifdef CONFIG_VSX
>  	if ((instruction & 0xfc00003e) == 0x7c000018) {
> -		/* Additional register addressing bit (64 VSX vs 32 FPR/GPR */
> +		unsigned int elsize;
> +
> +		/* Additional register addressing bit (64 VSX vs 32 FPR/GPR) */
>  		reg |= (instruction & 0x1) << 5;
>  		/* Simple inline decoder instead of a table */
> +		/* VSX has only 8 and 16 byte memory accesses */
> +		nb = 8;
>  		if (instruction & 0x200)
>  			nb = 16;
> -		else if (instruction & 0x080)
> -			nb = 8;
> -		else
> -			nb = 4;
> +
> +		/* Vector stores in little-endian mode swap individual
> +		   elements, so process them separately */
> +		elsize = 4;
> +		if (instruction & 0x80)
> +			elsize = 8;
> +
>  		flags = 0;
> +		if (regs->msr & MSR_LE)
> +			flags |= SW;
>  		if (instruction & 0x100)
>  			flags |= ST;
>  		if (instruction & 0x040)
> @@ -787,7 +816,7 @@ int fix_alignment(struct pt_regs *regs)
>  			nb = 8;
>  		}
>  		PPC_WARN_EMULATED(vsx);
> -		return emulate_vsx(addr, reg, areg, regs, flags, nb);
> +		return emulate_vsx(addr, reg, areg, regs, flags, nb, elsize);
>  	}
>  #endif
>  	/* A size of 0 indicates an instruction we don't support, with
> 

^ permalink raw reply

* Re: [Next] CPU Hotplug test failures on powerpc
From: Benjamin Herrenschmidt @ 2009-12-14 21:17 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Linux/PPC Development, Ingo Molnar, linux-next, linux-kernel
In-Reply-To: <1260793182.4165.223.camel@twins>

On Mon, 2009-12-14 at 13:19 +0100, Peter Zijlstra wrote:

> > >> cpu 0x0: Vector: 100 (System Reset) at [c00000000c9333d0]
> > >>     pc: c0000000003433d8: .find_next_bit+0x54/0xc4
> > >>     lr: c000000000342f10: .cpumask_next_and+0x4c/0x94
> > >>     sp: c00000000c933650
> > >>    msr: 8000000000089032
> > >>   current = 0xc00000000c173840
> > >>   paca    = 0xc000000000bc2600
> > >>     pid   = 2602, comm = hotplug06.top.s
> > >> enter ? for help
> > >> [link register   ] c000000000342f10 .cpumask_next_and+0x4c/0x94
> > >> [c00000000c933650] c0000000000e9f34 .cpuset_cpus_allowed_locked+0x38/0x74 (unreliable)
> > >> [c00000000c9336e0] c000000000090074 .move_task_off_dead_cpu+0xc4/0x1ac
> > >> [c00000000c9337a0] c0000000005e4e5c .migration_call+0x304/0x830
> > >> [c00000000c933880] c0000000005e0880 .notifier_call_chain+0x68/0xe0
> > >> [c00000000c933920] c00000000012a92c ._cpu_down+0x210/0x34c
> > >> [c00000000c933a90] c00000000012aad8 .cpu_down+0x70/0xa8
> > >> [c00000000c933b20] c000000000525940 .store_online+0x54/0x894
> > >> [c00000000c933bb0] c000000000463430 .sysdev_store+0x3c/0x50
> > >> [c00000000c933c20] c0000000001f8320 .sysfs_write_file+0x124/0x18c
> > >> [c00000000c933ce0] c00000000017edac .vfs_write+0xd4/0x1fc
> > >> [c00000000c933d80] c00000000017efdc .SyS_write+0x58/0xa0
> > >> [c00000000c933e30] c0000000000085b4 syscall_exit+0x0/0x40
> > >> --- Exception: c01 (System Call) at 00000fff9fa8a8f8
> > >> SP (fffe7aef200) is in userspace
> > >> 0:mon> e
> > >> cpu 0x0: Vector: 100 (System Reset) at [c00000000c9333d0]
> > >>     pc: c0000000003433d8: .find_next_bit+0x54/0xc4
> > >>     lr: c000000000342f10: .cpumask_next_and+0x4c/0x94
> > >>     sp: c00000000c933650
> > >>    msr: 8000000000089032
> > >>   current = 0xc00000000c173840
> > >>   paca    = 0xc000000000bc2600
> > >>     pid   = 2602, comm = hotplug06.top.s
> > >>
> 
> OK so how do I read that above thing? What's a System Reset? Is that
> like the x86 triple fault thing?

Nah, it's an NMI that throws you into xmon. Basically, the machine was
hung and Sachin interrupted it with an NMI to see what was going on. The
above is the backtrace. It was at the moment of the NMI inside
find_next_bit() called from cpumask_next_and() etc... 

> >From what I can make of it, its in move_task_off_dead_cpu(), right after
> having called cpuset_cpus_allowed_locked(), doing that cpumask_any_and()
> call.

Yes, it looks like it.

> static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
> {
>         int dest_cpu;
>         const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(dead_cpu));
> 
> again:
>         /* Look for allowed, online CPU in same node. */
>         for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
>                 if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
>                         goto move;
> 
>         /* Any allowed, online CPU? */
>         dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask);
>         if (dest_cpu < nr_cpu_ids)
>                 goto move;
> 
>         /* No more Mr. Nice Guy. */
>         if (dest_cpu >= nr_cpu_ids) {
>                 cpuset_cpus_allowed_locked(p, &p->cpus_allowed);
> ====>           dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed);
> 
>                 /*
>                  * Don't tell them about moving exiting tasks or
>                  * kernel threads (both mm NULL), since they never
>                  * leave kernel.
>                  */
>                 if (p->mm && printk_ratelimit()) {
>                         pr_info("process %d (%s) no longer affine to cpu%d\n",
>                                 task_pid_nr(p), p->comm, dead_cpu);
>                 }
>         }
> 
> move:
>         /* It can have affinity changed while we were choosing. */
>         if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu)))
>                 goto again;
> }
> 
> Both masks, p->cpus_allowed and cpu_active_mask are stable in that p
> won't go away since we hold the tasklist_lock (in migrate_list_tasks),
> and cpu_active_mask is static storage, so WTH is it going funny on?

Sachin, this is 100% reproduceable right ? You should be able to
sprinkle it with some xmon_printf() (rather than printk, just add a
prototype extern void xmon_printf(const char *fmt,...); somewhere, this
has the advantage of being fully synchronous and will print out even if
the printk sem is held.

Cheers,
Ben.

> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply

* [PATCH] powerpc: Fix MSI support on U4 bridge PCIe slot
From: Benjamin Herrenschmidt @ 2009-12-15  1:31 UTC (permalink / raw)
  To: linuxppc-dev

On machines using the Apple U4 bridge (AKA IBM CPC945) PCIe interface such
as the latest generation G5 machines x16 slot or the x16 slot of the
PowerStation, MSIs are currently broken (and will oops when enabling).

This fixes the oops and implements proper support for those. Instead of
using the PCIe <-> HT bridge conversion, on such slots we need to use
a bunch of magic registers in the bridge as the MSI target, encoding
the interrupt number in the low bits of the address itself

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/sysdev/mpic_msi.c   |   11 ++++++++-
 arch/powerpc/sysdev/mpic_u3msi.c |   46 ++++++++++++++++++++++++++++++++-----
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index 1d44eee..0f67cd7 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -39,7 +39,12 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
 
 	pr_debug("mpic: found U3, guessing msi allocator setup\n");
 
-	/* Reserve source numbers we know are reserved in the HW */
+	/* Reserve source numbers we know are reserved in the HW.
+	 *
+	 * This is a bit of a mix of U3 and U4 reserves but that's going
+	 * to work fine, we have plenty enugh numbers left so let's just
+	 * mark anything we don't like reserved.
+	 */
 	for (i = 0;   i < 8;   i++)
 		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
@@ -49,6 +54,10 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
 	for (i = 100; i < 105; i++)
 		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
 
+	for (i = 124; i < mpic->irq_count; i++)
+		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);
+
+
 	np = NULL;
 	while ((np = of_find_all_nodes(np))) {
 		pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c
index d3caf23..bcbfe79 100644
--- a/arch/powerpc/sysdev/mpic_u3msi.c
+++ b/arch/powerpc/sysdev/mpic_u3msi.c
@@ -64,12 +64,12 @@ static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
 	return addr;
 }
 
-static u64 find_ht_magic_addr(struct pci_dev *pdev)
+static u64 find_ht_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
 {
 	struct pci_bus *bus;
 	unsigned int pos;
 
-	for (bus = pdev->bus; bus; bus = bus->parent) {
+	for (bus = pdev->bus; bus && bus->self; bus = bus->parent) {
 		pos = pci_find_ht_capability(bus->self, HT_CAPTYPE_MSI_MAPPING);
 		if (pos)
 			return read_ht_magic_addr(bus->self, pos);
@@ -78,13 +78,41 @@ static u64 find_ht_magic_addr(struct pci_dev *pdev)
 	return 0;
 }
 
+static u64 find_u4_magic_addr(struct pci_dev *pdev, unsigned int hwirq)
+{
+	struct pci_controller *hose = pci_bus_to_host(pdev->bus);
+
+	/* U4 PCIe MSIs need to write to the special register in
+	 * the bridge that generates interrupts. There should be
+	 * theorically a register at 0xf8005000 where you just write
+	 * the MSI number and that triggers the right interrupt, but
+	 * unfortunately, this is busted in HW, the bridge endian swaps
+	 * the value and hits the wrong nibble in the register.
+	 *
+	 * So instead we use another register set which is used normally
+	 * for converting HT interrupts to MPIC interrupts, which decodes
+	 * the interrupt number as part of the low address bits
+	 *
+	 * This will not work if we ever use more than one legacy MSI in
+	 * a block but we never do. For one MSI or multiple MSI-X where
+	 * each interrupt address can be specified separately, it works
+	 * just fine.
+	 */
+	if (of_device_is_compatible(hose->dn, "u4-pcie") ||
+	    of_device_is_compatible(hose->dn, "U4-pcie"))
+		return 0xf8004000 | (hwirq << 4);
+
+	return 0;
+}
+
 static int u3msi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
 {
 	if (type == PCI_CAP_ID_MSIX)
 		pr_debug("u3msi: MSI-X untested, trying anyway.\n");
 
 	/* If we can't find a magic address then MSI ain't gonna work */
-	if (find_ht_magic_addr(pdev) == 0) {
+	if (find_ht_magic_addr(pdev, 0) == 0 &&
+	    find_u4_magic_addr(pdev, 0) == 0) {
 		pr_debug("u3msi: no magic address found for %s\n",
 			 pci_name(pdev));
 		return -ENXIO;
@@ -118,10 +146,6 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 	u64 addr;
 	int hwirq;
 
-	addr = find_ht_magic_addr(pdev);
-	msg.address_lo = addr & 0xFFFFFFFF;
-	msg.address_hi = addr >> 32;
-
 	list_for_each_entry(entry, &pdev->msi_list, list) {
 		hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1);
 		if (hwirq < 0) {
@@ -129,6 +153,12 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 			return hwirq;
 		}
 
+		addr = find_ht_magic_addr(pdev, hwirq);
+		if (addr == 0)
+			addr = find_u4_magic_addr(pdev, hwirq);
+		msg.address_lo = addr & 0xFFFFFFFF;
+		msg.address_hi = addr >> 32;
+
 		virq = irq_create_mapping(msi_mpic->irqhost, hwirq);
 		if (virq == NO_IRQ) {
 			pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq);
@@ -143,6 +173,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
 		pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
 			  virq, hwirq, (unsigned long)addr);
 
+		printk("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
+			  virq, hwirq, (unsigned long)addr);
 		msg.data = hwirq;
 		write_msi_msg(virq, &msg);
 

^ permalink raw reply related

* Re: [PATCH v0] Crypto: Talitos: re-initialize async_tx descriptors
From: Dan Williams @ 2009-12-15  7:29 UTC (permalink / raw)
  To: Vishnu Suresh
  Cc: herbert, B04825, linux-kernel, linux-raid, linuxppc-dev,
	linux-crypto, R58472
In-Reply-To: <1260797602-7476-1-git-send-email-Vishnu@freescale.com>

On Mon, Dec 14, 2009 at 6:33 AM, Vishnu Suresh <Vishnu@freescale.com> wrote=
:
> The async_tx descriptors contains dangling pointers.
> Hence, re-initialize them to NULL before use.
>
> Signed-off-by: Vishnu Suresh <Vishnu@freescale.com>
> ---
> o. Rebased to linux-next as of 20091214
>
> =A0drivers/crypto/talitos.c | =A0 =A03 +++
> =A01 files changed, 3 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
> index 87f06be..9e261c6 100644
> --- a/drivers/crypto/talitos.c
> +++ b/drivers/crypto/talitos.c
> @@ -952,6 +952,9 @@ static struct dma_async_tx_descriptor * talitos_prep_=
dma_xor(
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return NULL;
> =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0dma_async_tx_descriptor_init(&new->async_tx, &xor_chan->co=
mmon);
> + =A0 =A0 =A0 new->async_tx.parent =3D NULL;
> + =A0 =A0 =A0 new->async_tx.next =3D NULL;
> +
>
> =A0 =A0 =A0 =A0desc =3D &new->hwdesc;
> =A0 =A0 =A0 =A0/* Set destination: Last pointer pair */

These two values are owned by the async_tx api, drivers are not
supposed to touch them.  Both iop_adma and the new ppx4xx driver
(which use the async_tx channel switching capability) get away without
touching these fields which makes me suspect there is a
misunderstanding/bug somewhere else in the talitos implementation.
Also that dma_async_tx_descriptor_init() is unexpected in the hot
path, it's only needed at initial descriptor allocation.  End result I
think this driver needs some more time to brew.

--
Dan

^ permalink raw reply

* Re: [Next] CPU Hotplug test failures on powerpc
From: Sachin Sant @ 2009-12-15  9:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Peter Zijlstra
  Cc: Linux/PPC Development, Ingo Molnar, linux-next, linux-kernel
In-Reply-To: <1260825420.2217.40.camel@pasglop>

Benjamin Herrenschmidt wrote:
>> static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p)
>> {
>>         int dest_cpu;
>>         const struct cpumask *nodemask = cpumask_of_node(cpu_to_node(dead_cpu));
>>
>> again:
>>         /* Look for allowed, online CPU in same node. */
>>         for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
>>                 if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
>>                         goto move;
>>
>>         /* Any allowed, online CPU? */
>>         dest_cpu = cpumask_any_and(&p->cpus_allowed, cpu_active_mask);
>>         if (dest_cpu < nr_cpu_ids)
>>                 goto move;
>>
>>         /* No more Mr. Nice Guy. */
>>         if (dest_cpu >= nr_cpu_ids) {
>>                 cpuset_cpus_allowed_locked(p, &p->cpus_allowed);
>> ====>           dest_cpu = cpumask_any_and(cpu_active_mask, &p->cpus_allowed);
>>
>>                 /*
>>                  * Don't tell them about moving exiting tasks or
>>                  * kernel threads (both mm NULL), since they never
>>                  * leave kernel.
>>                  */
>>                 if (p->mm && printk_ratelimit()) {
>>                         pr_info("process %d (%s) no longer affine to cpu%d\n",
>>                                 task_pid_nr(p), p->comm, dead_cpu);
>>                 }
>>         }
>>
>> move:
>>         /* It can have affinity changed while we were choosing. */
>>         if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu)))
>>                 goto again;
>> }
>>
>> Both masks, p->cpus_allowed and cpu_active_mask are stable in that p
>> won't go away since we hold the tasklist_lock (in migrate_list_tasks),
>> and cpu_active_mask is static storage, so WTH is it going funny on?
>>     
I added some debug statements within the above code. 
This is a 2 cpu machine.

XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
XMON dest_cpu = 1024 
XMON dest_cpu = 1024 . dead_cpu = 1
XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
XMON dest_cpu = 1024 
XMON dest_cpu = 1024 . dead_cpu = 1
XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
XMON dest_cpu = 1024 
XMON dest_cpu = 1024 . dead_cpu = 1

Seems to me that the control is stuck in an infinite loop and hence the
machine appears to be in hung state. The dest_cpu value is always 1024
and never changes, which result in an infinite loop.

In working scenario the o/p is something on the following lines

XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
XMON dest_cpu = 0 
XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
XMON dest_cpu = 0 
XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
XMON dest_cpu = 0 

Let me know if i should try to record any specific value ?

Thanks
-Sachin

-- 

---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------

^ permalink raw reply

* Re: [Next] CPU Hotplug test failures on powerpc
From: Peter Zijlstra @ 2009-12-15 10:43 UTC (permalink / raw)
  To: Sachin Sant; +Cc: Ingo Molnar, linux-next, linux-kernel, Linux/PPC Development
In-Reply-To: <4B275A6B.9030200@in.ibm.com>

On Tue, 2009-12-15 at 15:14 +0530, Sachin Sant wrote:
> Benjamin Herrenschmidt wrote:
> >> static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p=
)
> >> {
> >>         int dest_cpu;
> >>         const struct cpumask *nodemask =3D cpumask_of_node(cpu_to_node=
(dead_cpu));
> >>
> >> again:
> >>         /* Look for allowed, online CPU in same node. */
> >>         for_each_cpu_and(dest_cpu, nodemask, cpu_active_mask)
> >>                 if (cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
> >>                         goto move;
> >>
> >>         /* Any allowed, online CPU? */
> >>         dest_cpu =3D cpumask_any_and(&p->cpus_allowed, cpu_active_mask=
);
> >>         if (dest_cpu < nr_cpu_ids)
> >>                 goto move;
> >>
> >>         /* No more Mr. Nice Guy. */
> >>         if (dest_cpu >=3D nr_cpu_ids) {
> >>                 cpuset_cpus_allowed_locked(p, &p->cpus_allowed);
> >> =3D=3D=3D=3D>           dest_cpu =3D cpumask_any_and(cpu_active_mask, =
&p->cpus_allowed);
> >>
> >>                 /*
> >>                  * Don't tell them about moving exiting tasks or
> >>                  * kernel threads (both mm NULL), since they never
> >>                  * leave kernel.
> >>                  */
> >>                 if (p->mm && printk_ratelimit()) {
> >>                         pr_info("process %d (%s) no longer affine to c=
pu%d\n",
> >>                                 task_pid_nr(p), p->comm, dead_cpu);
> >>                 }
> >>         }
> >>
> >> move:
> >>         /* It can have affinity changed while we were choosing. */
> >>         if (unlikely(!__migrate_task_irq(p, dead_cpu, dest_cpu)))
> >>                 goto again;
> >> }
> >>
> >> Both masks, p->cpus_allowed and cpu_active_mask are stable in that p
> >> won't go away since we hold the tasklist_lock (in migrate_list_tasks),
> >> and cpu_active_mask is static storage, so WTH is it going funny on?
> >>    =20
> I added some debug statements within the above code.=20
> This is a 2 cpu machine.
>=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1 . nr_cpu_ids =3D 2
> XMON dest_cpu =3D 1024=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1 . nr_cpu_ids =3D 2
> XMON dest_cpu =3D 1024=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1 . nr_cpu_ids =3D 2
> XMON dest_cpu =3D 1024=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1
>=20
> Seems to me that the control is stuck in an infinite loop and hence the
> machine appears to be in hung state. The dest_cpu value is always 1024
> and never changes, which result in an infinite loop.
>=20
> In working scenario the o/p is something on the following lines
>=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1 . nr_cpu_ids =3D 2
> XMON dest_cpu =3D 0=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1 . nr_cpu_ids =3D 2
> XMON dest_cpu =3D 0=20
> XMON dest_cpu =3D 1024 . dead_cpu =3D 1 . nr_cpu_ids =3D 2
> XMON dest_cpu =3D 0=20
>=20
> Let me know if i should try to record any specific value ?

Could you possibly print the two masks themselves? cpumask_scnprintf()
and friend come in handy for this.

The dest_cpu=3D1024 thing seem to suggest the intersection between
p->cpus_allowed and cpu_active_mask is empty for some reason, even
though we forcefully reset p->cpus_allowed to the full set using
cpuset_cpus_allowed_locked().

/me goes re-read the cpu_active_map code, this really shouldn't happen.

^ permalink raw reply

* Re: [PATCH] PowerPC: const intspec pointers
From: Roman Fietze @ 2009-12-15 10:59 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <fa686aa40912102213m5b2a0092i3c25d73b914ece93@mail.gmail.com>

Hallo Grant,

On Friday 11 December 2009 07:13:45 Grant Likely wrote:

> BTW, if you're interested, there is a driver for the SCLPC FIFO about
> to be merged into 2.6.33.  It's in Ben's tree waiting to be pulled
> into mainline.

I've had a "look" into it. This means I rewrote it in some parts to
get it running.

=46irst I tried to do it in nice little steps, so the git commits are
clean and simple. But with my knowldege about the SCLPC, the code your
old SCLPC test driver and my 2.4.25 FPGA driver using SCLPS and
BestComm, one of the commits just got a big rewrite including fixes
for quite some bugs.

The driver is now running using DMA TX and RX. Without BestComm it's
running partly. I'm really windering if this code ever ran before?
There are some historical or future items in there like measurement of
the times, a list_header maybe for future request queueing, and so on.

If you or Ben are interested in my work I can post the patches
here. Of course just to get some comments, because the driver can't be
ready in the state it is. The commits would go on top of Ben's next
branch.


Roman

=2D-=20
Roman Fietze                Telemotive AG B=FCro M=FChlhausen
Breitwiesen                              73347 M=FChlhausen
Tel.: +49(0)7335/18493-45        http://www.telemotive.de

^ permalink raw reply

* RE: [PATCH v0] Crypto: Talitos: re-initialize async_tx descriptors
From: Suresh Vishnu-B05022 @ 2009-12-15 11:03 UTC (permalink / raw)
  To: Dan Williams
  Cc: herbert, Tabi Timur-B04825, linux-kernel, linux-raid,
	linuxppc-dev, linux-crypto, Li Yang-R58472
In-Reply-To: <e9c3a7c20912142329j6603402ah2963d075419efa1c@mail.gmail.com>

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

> On Mon, Dec 14, 2009 at 6:33 AM, Vishnu Suresh <Vishnu@freescale.com> wrote:
> > The async_tx descriptors contains dangling pointers.
> > Hence, re-initialize them to NULL before use.
> >
> > Signed-off-by: Vishnu Suresh <Vishnu@freescale.com>
> > ---
> > o. Rebased to linux-next as of 20091214
> >
> >  drivers/crypto/talitos.c |    3 +++
> >  1 files changed, 3 insertions(+), 0 deletions(-)
> >
> > diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
> > index 87f06be..9e261c6 100644
> > --- a/drivers/crypto/talitos.c
> > +++ b/drivers/crypto/talitos.c
> > @@ -952,6 +952,9 @@ static struct dma_async_tx_descriptor * talitos_prep_dma_xor(
> >                return NULL;
> >        }
> >        dma_async_tx_descriptor_init(&new->async_tx, &xor_chan->common);
> > +       new->async_tx.parent = NULL;
> > +       new->async_tx.next = NULL;
> > +
> >
> >        desc = &new->hwdesc;
> >        /* Set destination: Last pointer pair */

> These two values are owned by the async_tx api, drivers are not
> supposed to touch them.
I have sent this patch and the similar one for fsldma seperately, 
so that if the changes are needed and can be done in dma_async_tx_descriptor_init(), 
these patches can be ignored.  
> Both iop_adma and the new ppx4xx driver
> (which use the async_tx channel switching capability) get away without
> touching these fields which makes me suspect there is a
> misunderstanding/bug somewhere else in the talitos implementation.

This bug does not occur on all the platforms. The occurrance is random. 
This occurs when a channel switch between two different devices are present. 
This same initialization is required in case of fsldma as well. 
In case of fsldma/talitosXOR, there are two DMA channels (on same device) and single XOR channel (on another device). 

When used without fsldma, this driver works fine.
Does iop_adma and ppx4xx work in similar enviroment?

> > Also that dma_async_tx_descriptor_init() is unexpected in the hot
> > path, it's only needed at initial descriptor allocation.  End result I
> > think this driver needs some more time to brew.



> --
> Dan




[-- Attachment #2: Type: text/html, Size: 3265 bytes --]

^ permalink raw reply

* Re: [v10 PATCH 8/9]: pSeries: implement pSeries processor idle module
From: Arun R Bharadwaj @ 2009-12-15 11:49 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linux-arch, Peter Zijlstra, linux-kernel, linux-acpi,
	Venkatesh Pallipadi, Arun Bharadwaj, Ingo Molnar, linuxppc-dev
In-Reply-To: <1259920852.2076.1274.camel@pasglop>

* Benjamin Herrenschmidt <benh@kernel.crashing.org> [2009-12-04 21:00:52]:

> On Fri, 2009-12-04 at 13:45 +0530, Arun R Bharadwaj wrote:
> 
> > 
> > Hi Ben,
> > 
> > I forgot to attach the patch which enables cpuidle for the rest of the
> > POWER platforms. Attaching it below.
> > 
> > So for these platforms, ppc_md.power_save will be called from from the
> > cpuidle_idle_call idle loop itself. Also, this cpuidle_idle_call is
> > not a pseries specific idle loop. It is a common loop for Intel and
> > PPC which use cpuidle infrastructure.
> 
> Ok, so there was a missing piece in the puzzle ;-)
> 
> I'll review asap.
> 

Hi Ben,

Did you get time to review this?

thanks
arun

> Cheers,
> Ben.
> 
> > arun
> > 
> > 
> > 
> > This patch enables cpuidle for the rest of the POWER platforms like
> > 44x, Cell, Pasemi etc.
> > 
> > Signed-off-by: Arun R Bharadwaj <arun@linux.vnet.ibm.com>
> > ---
> >  arch/powerpc/include/asm/system.h       |    2 ++
> >  arch/powerpc/kernel/idle.c              |   28 ++++++++++++++++++++++++++++
> >  arch/powerpc/kernel/setup_32.c          |    8 ++++++--
> >  arch/powerpc/platforms/44x/idle.c       |    2 ++
> >  arch/powerpc/platforms/cell/pervasive.c |    2 ++
> >  arch/powerpc/platforms/pasemi/idle.c    |    2 ++
> >  arch/powerpc/platforms/ps3/setup.c      |    2 ++
> >  7 files changed, 44 insertions(+), 2 deletions(-)
> > 
> > Index: linux.trees.git/arch/powerpc/include/asm/system.h
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/include/asm/system.h
> > +++ linux.trees.git/arch/powerpc/include/asm/system.h
> > @@ -551,8 +551,10 @@ void cpu_idle_wait(void);
> >  
> >  #ifdef CONFIG_CPU_IDLE
> >  extern void update_smt_snooze_delay(int snooze);
> > +extern void setup_cpuidle_ppc(void);
> >  #else
> >  static inline void update_smt_snooze_delay(int snooze) {}
> > +static inline void setup_cpuidle_ppc(void) {}
> >  #endif
> >  
> >  #endif /* __KERNEL__ */
> > Index: linux.trees.git/arch/powerpc/kernel/idle.c
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/kernel/idle.c
> > +++ linux.trees.git/arch/powerpc/kernel/idle.c
> > @@ -129,6 +129,34 @@ void default_idle(void)
> >  	HMT_very_low();
> >  }
> >  
> > +#ifdef CONFIG_CPU_IDLE
> > +DEFINE_PER_CPU(struct cpuidle_device, ppc_idle_devices);
> > +struct cpuidle_driver cpuidle_ppc_driver = {
> > +	.name =         "cpuidle_ppc",
> > +};
> > +
> > +static void ppc_idle_loop(struct cpuidle_device *dev, struct cpuidle_state *st)
> > +{
> > +	ppc_md.power_save();
> > +}
> > +
> > +void setup_cpuidle_ppc(void)
> > +{
> > +	struct cpuidle_device *dev;
> > +	int cpu;
> > +
> > +	cpuidle_register_driver(&cpuidle_ppc_driver);
> > +
> > +	for_each_online_cpu(cpu) {
> > +		dev = &per_cpu(ppc_idle_devices, cpu);
> > +		dev->cpu = cpu;
> > +		dev->states[0].enter = ppc_idle_loop;
> > +		dev->state_count = 1;
> > +		cpuidle_register_device(dev);
> > +	}
> > +}
> > +#endif
> > +
> >  int powersave_nap;
> >  
> >  #ifdef CONFIG_SYSCTL
> > Index: linux.trees.git/arch/powerpc/kernel/setup_32.c
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/kernel/setup_32.c
> > +++ linux.trees.git/arch/powerpc/kernel/setup_32.c
> > @@ -133,14 +133,18 @@ notrace void __init machine_init(unsigne
> >  
> >  #ifdef CONFIG_6xx
> >  	if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
> > -	    cpu_has_feature(CPU_FTR_CAN_NAP))
> > +	    cpu_has_feature(CPU_FTR_CAN_NAP)) {
> >  		ppc_md.power_save = ppc6xx_idle;
> > +		setup_cpuidle_ppc();
> > +	}
> >  #endif
> >  
> >  #ifdef CONFIG_E500
> >  	if (cpu_has_feature(CPU_FTR_CAN_DOZE) ||
> > -	    cpu_has_feature(CPU_FTR_CAN_NAP))
> > +	    cpu_has_feature(CPU_FTR_CAN_NAP)) {
> >  		ppc_md.power_save = e500_idle;
> > +		setup_cpuidle_ppc();
> > +	}
> >  #endif
> >  	if (ppc_md.progress)
> >  		ppc_md.progress("id mach(): done", 0x200);
> > Index: linux.trees.git/arch/powerpc/platforms/44x/idle.c
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/platforms/44x/idle.c
> > +++ linux.trees.git/arch/powerpc/platforms/44x/idle.c
> > @@ -24,6 +24,7 @@
> >  #include <linux/of.h>
> >  #include <linux/kernel.h>
> >  #include <asm/machdep.h>
> > +#include <asm/system.h>
> >  
> >  static int mode_spin;
> >  
> > @@ -46,6 +47,7 @@ int __init ppc44x_idle_init(void)
> >  		/* If we are not setting spin mode 
> >                     then we set to wait mode */
> >  		ppc_md.power_save = &ppc44x_idle;
> > +		setup_cpuidle_ppc();
> >  	}
> >  
> >  	return 0;
> > Index: linux.trees.git/arch/powerpc/platforms/cell/pervasive.c
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/platforms/cell/pervasive.c
> > +++ linux.trees.git/arch/powerpc/platforms/cell/pervasive.c
> > @@ -35,6 +35,7 @@
> >  #include <asm/pgtable.h>
> >  #include <asm/reg.h>
> >  #include <asm/cell-regs.h>
> > +#include <asm/system.h>
> >  
> >  #include "pervasive.h"
> >  
> > @@ -128,5 +129,6 @@ void __init cbe_pervasive_init(void)
> >  	}
> >  
> >  	ppc_md.power_save = cbe_power_save;
> > +	setup_cpuidle_ppc();
> >  	ppc_md.system_reset_exception = cbe_system_reset_exception;
> >  }
> > Index: linux.trees.git/arch/powerpc/platforms/pasemi/idle.c
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/platforms/pasemi/idle.c
> > +++ linux.trees.git/arch/powerpc/platforms/pasemi/idle.c
> > @@ -27,6 +27,7 @@
> >  #include <asm/machdep.h>
> >  #include <asm/reg.h>
> >  #include <asm/smp.h>
> > +#include <asm/system.h>
> >  
> >  #include "pasemi.h"
> >  
> > @@ -81,6 +82,7 @@ static int __init pasemi_idle_init(void)
> >  
> >  	ppc_md.system_reset_exception = pasemi_system_reset_exception;
> >  	ppc_md.power_save = modes[current_mode].entry;
> > +	setup_cpuidle_ppc();
> >  	printk(KERN_INFO "Using PA6T idle loop (%s)\n", modes[current_mode].name);
> >  
> >  	return 0;
> > Index: linux.trees.git/arch/powerpc/platforms/ps3/setup.c
> > ===================================================================
> > --- linux.trees.git.orig/arch/powerpc/platforms/ps3/setup.c
> > +++ linux.trees.git/arch/powerpc/platforms/ps3/setup.c
> > @@ -33,6 +33,7 @@
> >  #include <asm/prom.h>
> >  #include <asm/lv1call.h>
> >  #include <asm/ps3gpu.h>
> > +#include <asm/system.h>
> >  
> >  #include "platform.h"
> >  
> > @@ -214,6 +215,7 @@ static void __init ps3_setup_arch(void)
> >  	prealloc_ps3flash_bounce_buffer();
> >  
> >  	ppc_md.power_save = ps3_power_save;
> > +	setup_cpuidle_ppc();
> >  	ps3_os_area_init();
> >  
> >  	DBG(" <- %s:%d\n", __func__, __LINE__);
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

^ permalink raw reply

* Re: [Next] CPU Hotplug test failures on powerpc
From: Sachin Sant @ 2009-12-15 13:47 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Ingo Molnar, linux-next, linux-kernel, Linux/PPC Development
In-Reply-To: <1260873827.4165.362.camel@twins>

Peter Zijlstra wrote:
>> I added some debug statements within the above code. 
>> This is a 2 cpu machine.
>>
>> XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
>> XMON dest_cpu = 1024 
>> XMON dest_cpu = 1024 . dead_cpu = 1
>> XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
>> XMON dest_cpu = 1024 
>> XMON dest_cpu = 1024 . dead_cpu = 1
>> XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
>> XMON dest_cpu = 1024 
>> XMON dest_cpu = 1024 . dead_cpu = 1
>>
>> Seems to me that the control is stuck in an infinite loop and hence the
>> machine appears to be in hung state. The dest_cpu value is always 1024
>> and never changes, which result in an infinite loop.
>>
>> In working scenario the o/p is something on the following lines
>>
>> XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
>> XMON dest_cpu = 0 
>> XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
>> XMON dest_cpu = 0 
>> XMON dest_cpu = 1024 . dead_cpu = 1 . nr_cpu_ids = 2
>> XMON dest_cpu = 0 
>>
>> Let me know if i should try to record any specific value ?
>>     
>
> Could you possibly print the two masks themselves? cpumask_scnprintf()
> and friend come in handy for this.
>
> The dest_cpu=1024 thing seem to suggest the intersection between
> p->cpus_allowed and cpu_active_mask is empty for some reason, even
> though we forcefully reset p->cpus_allowed to the full set using
> cpuset_cpus_allowed_locked().
>   
So here is the data related to the two masks.

cpu_active_mask = 00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000
XMON dest_cpu = 1024

while p->cpus_allowed =  00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000001
XMON dest_cpu = 1024

In working scenario the above data looks like

cpu_active_mask = 00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000002
XMON dest_cpu = 1

while p->cpus_allowed =  00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,
00000000,00000000,00000002
XMON dest_cpu = 1


hope i got the data correct.

Thanks
-Sachin


-- 

---------------------------------
Sachin Sant
IBM Linux Technology Center
India Systems and Technology Labs
Bangalore, India
---------------------------------

^ permalink raw reply

* Re: [Next] CPU Hotplug test failures on powerpc
From: Peter Zijlstra @ 2009-12-15 15:03 UTC (permalink / raw)
  To: Sachin Sant; +Cc: Ingo Molnar, linux-next, linux-kernel, Linux/PPC Development
In-Reply-To: <4B279370.5050800@in.ibm.com>


Could you try the below?

---
 init/main.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/init/main.c b/init/main.c
index 4051d75..4be7de2 100644
--- a/init/main.c
+++ b/init/main.c
@@ -369,12 +369,6 @@ static void __init smp_init(void)
 {
 	unsigned int cpu;
=20
-	/*
-	 * Set up the current CPU as possible to migrate to.
-	 * The other ones will be done by cpu_up/cpu_down()
-	 */
-	set_cpu_active(smp_processor_id(), true);
-
 	/* FIXME: This should be done in userspace --RR */
 	for_each_present_cpu(cpu) {
 		if (num_online_cpus() >=3D setup_max_cpus)
@@ -486,6 +480,7 @@ static void __init boot_cpu_init(void)
 	int cpu =3D smp_processor_id();
 	/* Mark the boot cpu "present", "online" etc for SMP and UP case */
 	set_cpu_online(cpu, true);
+	set_cpu_active(cpu, true);
 	set_cpu_present(cpu, true);
 	set_cpu_possible(cpu, true);
 }

^ permalink raw reply related

* Re: [PATCH v0] Crypto: Talitos: re-initialize async_tx descriptors
From: Dan Williams @ 2009-12-15 18:23 UTC (permalink / raw)
  To: Suresh Vishnu-B05022
  Cc: herbert@gondor.apana.org.au, Ira Snyder, Tabi Timur-B04825,
	linux-kernel@vger.kernel.org, linux-raid@vger.kernel.org,
	linuxppc-dev@ozlabs.org, linux-crypto@vger.kernel.org,
	Li Yang-R58472
In-Reply-To: <76952DF81420A349876E087D089DF034562C75@zin33exm21.fsl.freescale.net>

Suresh Vishnu-B05022 wrote:
>  > On Mon, Dec 14, 2009 at 6:33 AM, Vishnu Suresh <Vishnu@freescale.com> 
> wrote:
>  > > The async_tx descriptors contains dangling pointers.
>  > > Hence, re-initialize them to NULL before use.
>  > >
>  > > Signed-off-by: Vishnu Suresh <Vishnu@freescale.com>
>  > > ---
>  > > o. Rebased to linux-next as of 20091214
>  > >
>  > >  drivers/crypto/talitos.c |    3 +++
>  > >  1 files changed, 3 insertions(+), 0 deletions(-)
>  > >
>  > > diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
>  > > index 87f06be..9e261c6 100644
>  > > --- a/drivers/crypto/talitos.c
>  > > +++ b/drivers/crypto/talitos.c
>  > > @@ -952,6 +952,9 @@ static struct dma_async_tx_descriptor * 
> talitos_prep_dma_xor(
>  > >                return NULL;
>  > >        }
>  > >        dma_async_tx_descriptor_init(&new->async_tx, &xor_chan->common);
>  > > +       new->async_tx.parent = NULL;
>  > > +       new->async_tx.next = NULL;
>  > > +
>  > >
>  > >        desc = &new->hwdesc;
>  > >        /* Set destination: Last pointer pair */
> 
>  > These two values are owned by the async_tx api, drivers are not
>  > supposed to touch them.
> I have sent this patch and the similar one for fsldma seperately,
> so that if the changes are needed and can be done in 
> dma_async_tx_descriptor_init(),
> these patches can be ignored. 
>  > Both iop_adma and the new ppx4xx driver
>  > (which use the async_tx channel switching capability) get away without
>  > touching these fields which makes me suspect there is a
>  > misunderstanding/bug somewhere else in the talitos implementation.
> 
> This bug does not occur on all the platforms. The occurrance is random.
> This occurs when a channel switch between two different devices are 
> present.
> This same initialization is required in case of fsldma as well. 
> In case of fsldma/talitosXOR, there are two DMA channels (on same 
> device) and single XOR channel (on another device).
> 
> When used without fsldma, this driver works fine.
> Does iop_adma and ppx4xx work in similar enviroment?

Yes, iop_adma when running on iop3xx hardware has one xor channel and 
two memcpy channels.

The bug may very well be in the fsldma driver, but the workarounds are 
just band aids.  I would be more comfortable with dropping the three 
workaround patches and simply adding "depends on !FSL_DMA" to the 
CRYPTO_DEV_TALITOS option until the true fix can be developed.

--
Dan

^ permalink raw reply

* Re: [PATCH] PowerPC: const intspec pointers
From: Grant Likely @ 2009-12-15 19:50 UTC (permalink / raw)
  To: Roman Fietze; +Cc: linuxppc-dev
In-Reply-To: <200912151159.40628.roman.fietze@telemotive.de>

On Tue, Dec 15, 2009 at 3:59 AM, Roman Fietze
<roman.fietze@telemotive.de> wrote:
> Hallo Grant,
>
> On Friday 11 December 2009 07:13:45 Grant Likely wrote:
>
>> BTW, if you're interested, there is a driver for the SCLPC FIFO about
>> to be merged into 2.6.33. =A0It's in Ben's tree waiting to be pulled
>> into mainline.
>
> I've had a "look" into it. This means I rewrote it in some parts to
> get it running.
>
> First I tried to do it in nice little steps, so the git commits are
> clean and simple. But with my knowldege about the SCLPC, the code your
> old SCLPC test driver and my 2.4.25 FPGA driver using SCLPS and
> BestComm, one of the commits just got a big rewrite including fixes
> for quite some bugs.
>
> The driver is now running using DMA TX and RX. Without BestComm it's
> running partly. I'm really windering if this code ever ran before?
> There are some historical or future items in there like measurement of
> the times, a list_header maybe for future request queueing, and so on

Yes, I'm using the driver in a couple of projects.  It works for me
for both RX and TX (although TX+DMA has been troublesome).  I'll
double check to make sure I've merged all of my patches for the
driver.

The test driver on the other hand is pretty poor code.  Don't expect
much from it other than some hints.  There's a reason I didn't merge
that chunk.

> If you or Ben are interested in my work I can post the patches
> here. Of course just to get some comments, because the driver can't be
> ready in the state it is. The commits would go on top of Ben's next
> branch.

Yes, please post the patches and cc: me.  I'll review, test, and make comme=
nts.

g.

--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* [git pull] Please pull powerpc.git next branch
From: Kumar Gala @ 2009-12-15 20:20 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev

The following changes since
commit e090aa80321b64c3b793f3b047e31ecf1af9538d:
  Benjamin Herrenschmidt (1):
        powerpc: Fix usage of 64-bit instruction in 32-bit altivec code

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/galak/powerpc.git next

Anton Vorontsov (4):
      powerpc/fsl_pci: Fix P2P bridge handling for MPC83xx PCIe controllers
      powerpc/83xx/suspend: Clear deep_sleeping after devices resume
      powerpc/83xx/suspend: Save and restore SICRL, SICRH and SCCR
      powerpc/83xx: Add power management support for MPC8315E-RDB boards

Dmitry Eremin-Solenikov (4):
      powerpc/83xx: mpc8349emitx - add gpio controller declarations
      powerpc/83xx: mpc8349emitx - populate I2C busses in device tree
      powerpc/83xx: mpc8349emitx - add OF descriptions of LocalBus devices
      powerpc/83xx: mpc8349emitx - add leds-gpio binding

Felix Radensky (1):
      powerpc/85xx: Workaround MPC8572/MPC8536 GPIO 1 errata.

Mark Ware (1):
      powerpc/cpm2_pic: Allow correct flow_types for port C interrupts

Peter Korsgaard (1):
      powerpc/gpio: support gpio_to_irq()

Sebastian Andrzej Siewior (1):
      powerpc/fsl: try to explain why the interrupt numbers are off by 16

 Documentation/powerpc/dts-bindings/fsl/mpic.txt |   42 ++++++++++++
 arch/powerpc/boot/dts/mpc8315erdb.dts           |   27 ++++++++
 arch/powerpc/boot/dts/mpc8349emitx.dts          |   82 ++++++++++++++++++++++-
 arch/powerpc/include/asm/gpio.h                 |    5 +-
 arch/powerpc/platforms/83xx/suspend.c           |   52 ++++++++++++++-
 arch/powerpc/sysdev/cpm2_pic.c                  |   28 ++++++--
 arch/powerpc/sysdev/fsl_pci.c                   |    8 ++-
 arch/powerpc/sysdev/mpc8xxx_gpio.c              |   21 ++++++-
 8 files changed, 248 insertions(+), 17 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/fsl/mpic.txt

^ permalink raw reply

* Problem with mini-PCI-E slot on P2020RDB
From: Felix Radensky @ 2009-12-15 21:25 UTC (permalink / raw)
  To: linuxppc-dev@ozlabs.org, Aggrwal Poonam-B10812, Kumar Gala

Hi,

I'm trying to use mini-PCI-E WLAN card on P2020RDB running 2.6.32, but 
so far without success.
ath9k driver identifies the device, I can run ifconfig, iwconfig and 
hostapd on wlan0, but device is not
getting any interrupts,  so I suspect the interrupt configuration is 
wrong. Atheros ath9k driver reports:

phy0: Atheros AR9280 MAC/BB Rev:2 AR5133 RF Rev:d0: mem=0xf1060000, irq=16

The mapping for irq 16 is:

irq: irq 1 on host /soc@ffe00000/pic@40000 mapped to virtual irq 16

According to /proc/interrupts:

          CPU0
 16:          0   OpenPIC   Edge      ath9k

The same problem happens if Atheros card is plugged (with adapter) into 
regular PCI-E slot.

It seems that p2020rdb device tree is missing interrupt-map-mask and 
interrupt-map properties
in PCI-E nodes.

I've tried running kernel from latest FSL BSP for this board (based on 
2.6.32-rc3). The device tree
has the interrupt-map-mask and interrupt-map properties, and interrupt 
mapping is different:

irq: irq 0 on host /soc@ffe00000/pic@40000 mapped to virtual irq 16

In /proc/interrups I see
           CPU0
 16:     100001   OpenPIC   Level     ath9k

However, when ath9k driver is loaded I get this:

irq 16: nobody cared (try booting with the "irqpoll" option)
Call Trace:
[efbefa40] [c00074b0] show_stack+0x4c/0x16c (unreliable)
[efbefa70] [c0073970] __report_bad_irq+0x38/0xd0
[efbefa90] [c0073bd4] note_interrupt+0x1cc/0x22c
[efbefac0] [c00747d0] handle_fasteoi_irq+0xf4/0x128
[efbefae0] [c0004eb8] do_IRQ+0xc8/0xf4
[efbefb00] [c001081c] ret_from_except+0x0/0x18
[efbefbc0] [00000000] (null)
[efbefc10] [c0004d24] do_softirq+0x60/0x64
[efbefc20] [c0044670] irq_exit+0x88/0xa8
[efbefc30] [c0004ebc] do_IRQ+0xcc/0xf4
[efbefc50] [c001081c] ret_from_except+0x0/0x18
[efbefd10] [c00730b4] __setup_irq+0x320/0x39c
[efbefd30] [c0073214] request_threaded_irq+0xe4/0x148
[efbefd60] [f2244218] ath_pci_probe+0x1b0/0x3a4 [ath9k]
[efbefda0] [c01c386c] local_pci_probe+0x24/0x34
[efbefdb0] [c01c3bc0] pci_device_probe+0x84/0xa8
[efbefde0] [c01e86b8] driver_probe_device+0xa8/0x1a8
[efbefe00] [c01e8874] __driver_attach+0xbc/0xc0
[efbefe20] [c01e7d88] bus_for_each_dev+0x70/0xac
[efbefe50] [c01e84d8] driver_attach+0x24/0x34
[efbefe60] [c01e7504] bus_add_driver+0xb8/0x278
[efbefe90] [c01e8bec] driver_register+0x84/0x178
[efbefeb0] [c01c3e6c] __pci_register_driver+0x54/0xe4
[efbefed0] [f2244434] ath_pci_init+0x28/0x38 [ath9k]
[efbefee0] [f215702c] ath9k_init+0x2c/0x100 [ath9k]
[efbefef0] [c0001d34] do_one_initcall+0x3c/0x1e8
[efbeff20] [c006f9f0] sys_init_module+0xf8/0x220
[efbeff40] [c00101c4] ret_from_syscall+0x0/0x3c
handlers:
[<f223badc>] (ath_isr+0x0/0x1b4 [ath9k])
Disabling IRQ #16

Atheros card plugged into regular PCI-E slot  works OK in  FSL BSP.

Any help in resolving this is much appreciated.

Thanks.

Felix.

^ permalink raw reply

* [PATCH] powerpc/85xx: Fix oops during MSI driver probe on MPC85xxMDS boards
From: Anton Vorontsov @ 2009-12-15 22:58 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev

MPC85xx chips report the wrong value in feature reporting register,
and that causes the following oops:

 Unable to handle kernel paging request for data at address 0x00000c00
 Faulting instruction address: 0xc0019294
 Oops: Kernel access of bad area, sig: 11 [#1]
 MPC8569 MDS
 Modules linked in:
 [...]
 NIP [c0019294] mpic_set_irq_type+0x2f0/0x368
 LR [c0019124] mpic_set_irq_type+0x180/0x368
 Call Trace:
 [ef851d60] [c0019124] mpic_set_irq_type+0x180/0x368 (unreliable)
 [ef851d90] [c007958c] __irq_set_trigger+0x44/0xd4
 [ef851db0] [c007b550] set_irq_type+0x40/0x7c
 [ef851dc0] [c0004a60] irq_create_of_mapping+0xb4/0x114
 [ef851df0] [c0004af0] irq_of_parse_and_map+0x30/0x40
 [ef851e20] [c0405678] fsl_of_msi_probe+0x1a0/0x328
 [ef851e60] [c02e6438] of_platform_device_probe+0x5c/0x84
 [...]

This is because mpic_alloc() assigns wrong values to
mpic->isu_{size,shift,mask}, and things eventually break when
_mpic_irq_read() is trying to use them.

This patch fixes the issue by enabling MPIC_BROKEN_FRR_NIRQS quirk.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
 arch/powerpc/platforms/85xx/mpc85xx_mds.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index c5028a2..6491f7c 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -338,7 +338,8 @@ static void __init mpc85xx_mds_pic_init(void)
 	}
 
 	mpic = mpic_alloc(np, r.start,
-			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN,
+			MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN |
+			MPIC_BROKEN_FRR_NIRQS,
 			0, 256, " OpenPIC  ");
 	BUG_ON(mpic == NULL);
 	of_node_put(np);
-- 
1.6.3.3

^ 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