Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Benjamin Herrenschmidt
Hi Matt !

The IBM PowerStation is a machine similar in design to our JS21 blades,
which uses an HT2000 bridge with it's dual 5780 TG3's.

I started investigating recently a problem where with recent kernels,
the machine will appear to freeze every second or two for a second
or two. The freeze would affect pretty much everything.

We noticed that it disappears when downing eth0, and finally bisected
it down to commit 7c5026aa9b81dd45df8d3f4e0be73e485976a8b6 Add link
state reporting to UMP firmware.

I don't know yet for sure what happens, but a quick look at the commit
seems to show that the driver synchronously spin-waits for up to 2.5ms
with a lock held multiple times from a timer interrupt. I don't know
yet if that's where the problem comes from, or if it's an issue with
the FW going nuts and the chip hogging the machine's bus or whatever
else, I'll have to do some more experiments on monday, but in any case,
that spin is really not nice.

The relevant pieces of lspci and dmesg are:

0001:00:01.0 PCI bridge: Broadcom HT2000 PCI-X bridge (rev b0)
0001:00:02.0 PCI bridge: Broadcom HT2000 PCI-X bridge (rev b0)
0001:00:03.0 PCI bridge: Broadcom HT2000 PCI-Express bridge (rev b0)
0001:00:04.0 PCI bridge: Broadcom HT2000 PCI-Express bridge (rev b0)
0001:00:05.0 PCI bridge: Broadcom HT2000 PCI-Express bridge (rev b0)
0001:00:06.0 PCI bridge: Broadcom HT2000 PCI-Express bridge (rev b0)
0001:02:04.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5780 
Gigabit Ethernet (rev 10)
0001:02:04.1 Ethernet controller: Broadcom Corporation NetXtreme BCM5780 
Gigabit Ethernet (rev 10)

tg3.c:v3.91 (April 18, 2008)
tg3 0001:02:04.0: enabling device (0140 - 0142)
eth0: Tigon3 [partno(BCM95780) rev 8100 PHY(5780)] (PCIX:133MHz:64-bit) 
10/100/1000Base-T Ethernet 00:14:5e:9e:01:82
eth0: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[1] WireSpeed[1] TSOcap[1]
eth0: dma_rwctrl[76144000] dma_mask[40-bit]
tg3 0001:02:04.1: enabling device (0140 - 0142)
eth1: Tigon3 [partno(BCM95780) rev 8100 PHY(5780)] (PCIX:133MHz:64-bit) 
10/100/1000Base-T Ethernet 00:14:5e:9e:01:83
eth1: RXcsums[1] LinkChgREG[0] MIirq[0] ASF[0] WireSpeed[1] TSOcap[1]
eth1: dma_rwctrl[76144000] dma_mask[40-bit]

Any help sorting that out would be much appreciated !

Cheers,
Ben.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Segher Boessenkool

I don't know yet for sure what happens, but a quick look at the commit
seems to show that the driver synchronously spin-waits for up to 2.5ms


That's what the comment says, but the code says 2.5 _seconds_:

+   /* Wait for up to 2.5 milliseconds */
+   for (i = 0; i  25; i++) {
+   if (!(tr32(GRC_RX_CPU_EVENT)  GRC_RX_CPU_DRIVER_EVENT))
+   break;
+   udelay(10);
+   }

(not that milliseconds wouldn't be bad already...)


Segher

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Benjamin Herrenschmidt
On Fri, 2008-08-08 at 10:58 +0200, Segher Boessenkool wrote:
  I don't know yet for sure what happens, but a quick look at the commit
  seems to show that the driver synchronously spin-waits for up to 2.5ms
 
 That's what the comment says, but the code says 2.5 _seconds_:
 
 +   /* Wait for up to 2.5 milliseconds */
 +   for (i = 0; i  25; i++) {
 +   if (!(tr32(GRC_RX_CPU_EVENT)  GRC_RX_CPU_DRIVER_EVENT))
 +   break;
 +   udelay(10);
 +   }
 
 (not that milliseconds wouldn't be bad already...)

Right, indeed. I think we have a good candidate for the problem :-) I'll
verify that on monday. Now, that leads to two questions:

 - What such a synchronous and potentially horribly slow code is
going in a locked section or a timer interrupts ? Ie, the link
watch should probably move to a workqueue if that is to remain,
or the code turned into a state machine that periodically check for
events, or whatever is more sane than the above.

 - The code should at least display some error and do something sane in
case of timeout such as disabling the new UMP feature instead of
repeatedly looping ...

 - If this is indeed our problem (timing out in the code above), why is
our firmware not emitting the requested event - maybe the PowerStations
need a tg3 firmware update.

Matt, what's your take on this ?

Cheers,
Ben.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Arnd Bergmann
On Friday 08 August 2008, Segher Boessenkool wrote:
  I don't know yet for sure what happens, but a quick look at the commit
  seems to show that the driver synchronously spin-waits for up to 2.5ms
 
 That's what the comment says, but the code says 2.5 _seconds_:
 
 +       /* Wait for up to 2.5 milliseconds */
 +       for (i = 0; i  25; i++) {
 +               if (!(tr32(GRC_RX_CPU_EVENT)  GRC_RX_CPU_DRIVER_EVENT))
 +                       break;
 +               udelay(10);
 +       }
 
 (not that milliseconds wouldn't be bad already...)

It can potentially be even much longer, because each udelay will wait
for *more* than 10 microseconds, and tr32() is an mmio read that takes
additional time, possibly in the order of microseconds as well.

The correct way to implement a timeout like this would be to use
time_before() in the condition, aside from better not doing a busy-loop
in the first place.

Arnd 
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH] Re: Level IRQ handling on Xilinx INTC with ARCH=powerpc

2008-08-08 Thread Sergey Temerkhanov
I've prepared the patch to fix the problem being discussed. It adds a field 
flags to struct irq_chip. If IRQ_CHIP_UNMASK_ACK is set in this field, 
acknowledge is performed before unmasking.

The patch is against 2.6.26
diff -r 6b0915754563 arch/powerpc/sysdev/xilinx_intc.c
--- a/arch/powerpc/sysdev/xilinx_intc.c	Mon Jul 28 19:59:22 2008 +0400
+++ b/arch/powerpc/sysdev/xilinx_intc.c	Fri Aug 08 13:13:52 2008 +0400
@@ -73,6 +73,7 @@
 	.mask = xilinx_intc_mask,
 	.unmask = xilinx_intc_unmask,
 	.ack = xilinx_intc_ack,
+	.flags = IRQ_CHIP_UNMASK_ACK,
 };
 
 /*
@@ -107,8 +108,8 @@
 	}
 	regs = ioremap(res.start, 32);
 
-	printk(KERN_INFO Xilinx intc at 0x%08LX mapped to 0x%p\n,
-		res.start, regs);
+	printk(KERN_INFO Xilinx intc at 0x%p mapped to 0x%p\n,
+		(void *)res.start, regs);
 
 	/* Setup interrupt controller */
 	out_be32(regs + XINTC_IER, 0); /* disable all irqs */
diff -r 6b0915754563 include/linux/irq.h
--- a/include/linux/irq.h	Mon Jul 28 19:59:22 2008 +0400
+++ b/include/linux/irq.h	Fri Aug 08 13:13:52 2008 +0400
@@ -114,6 +114,9 @@
 	int		(*retrigger)(unsigned int irq);
 	int		(*set_type)(unsigned int irq, unsigned int flow_type);
 	int		(*set_wake)(unsigned int irq, unsigned int on);
+
+	unsigned int	flags;
+#define IRQ_CHIP_UNMASK_ACK	0x0001
 
 	/* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
diff -r 6b0915754563 kernel/irq/chip.c
--- a/kernel/irq/chip.c	Mon Jul 28 19:59:22 2008 +0400
+++ b/kernel/irq/chip.c	Fri Aug 08 13:13:52 2008 +0400
@@ -377,8 +377,12 @@
 
 	spin_lock(desc-lock);
 	desc-status = ~IRQ_INPROGRESS;
-	if (!(desc-status  IRQ_DISABLED)  desc-chip-unmask)
-		desc-chip-unmask(irq);
+	if (!(desc-status  IRQ_DISABLED)) {
+		if (desc-chip-flags  IRQ_CHIP_UNMASK_ACK)
+			desc-chip-ack(irq);
+		if (desc-chip-unmask)
+			desc-chip-unmask(irq);
+	}
 out_unlock:
 	spin_unlock(desc-lock);
 }
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

[PATCH] watchdog: delete unused driver mpc8xx_wdt.c

2008-08-08 Thread Jochen Friedrich
The watchdog driver mpc8xx_wdt.c was a device interface to
arch/ppc/syslib/m8xx_wdt.c for MPC8xx hardware. Now that ARCH=ppc is
gone, this driver is of no more use. For ARCH=powerpc, MPC8xx hardware
is supported by mpc8xxx_wdt.c.

Signed-off-by: Jochen Friedrich [EMAIL PROTECTED]
Acked-by: Vitaly Bordug [EMAIL PROTECTED]
---
 drivers/watchdog/Kconfig  |4 -
 drivers/watchdog/Makefile |1 -
 drivers/watchdog/mpc8xx_wdt.c |  170 -
 3 files changed, 0 insertions(+), 175 deletions(-)
 delete mode 100644 drivers/watchdog/mpc8xx_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 32b9fe1..46e763c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -691,10 +691,6 @@ config MPC5200_WDT
tristate MPC5200 Watchdog Timer
depends on PPC_MPC52xx

-config 8xx_WDT
-   tristate MPC8xx Watchdog Timer
-   depends on 8xx
-
 config 8xxx_WDT
tristate MPC8xxx Platform Watchdog Timer
depends on PPC_8xx || PPC_83xx || PPC_86xx
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 049c918..6c20717 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -101,7 +101,6 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 # PARISC Architecture

 # POWERPC Architecture
-obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
 obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o
 obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o
 obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c
deleted file mode 100644
index 1336425..000
--- a/drivers/watchdog/mpc8xx_wdt.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * mpc8xx_wdt.c - MPC8xx watchdog userspace interface
- *
- * Author: Florian Schirmer [EMAIL PROTECTED]
- *
- * 2002 (c) Florian Schirmer [EMAIL PROTECTED] This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed as is without any warranty of any kind, whether express
- * or implied.
- */
-
-#include linux/fs.h
-#include linux/init.h
-#include linux/kernel.h
-#include linux/miscdevice.h
-#include linux/module.h
-#include linux/watchdog.h
-#include asm/8xx_immap.h
-#include linux/uaccess.h
-#include linux/io.h
-#include syslib/m8xx_wdt.h
-
-static unsigned long wdt_opened;
-static int wdt_status;
-static spinlock_t wdt_lock;
-
-static void mpc8xx_wdt_handler_disable(void)
-{
-   volatile uint __iomem *piscr;
-   piscr = (uint *)((immap_t *)IMAP_ADDR)-im_sit.sit_piscr;
-
-   if (!m8xx_has_internal_rtc)
-   m8xx_wdt_stop_timer();
-   else
-   out_be32(piscr, in_be32(piscr)  ~(PISCR_PIE | PISCR_PTE));
-   printk(KERN_NOTICE mpc8xx_wdt: keep-alive handler deactivated\n);
-}
-
-static void mpc8xx_wdt_handler_enable(void)
-{
-   volatile uint __iomem *piscr;
-   piscr = (uint *)((immap_t *)IMAP_ADDR)-im_sit.sit_piscr;
-
-   if (!m8xx_has_internal_rtc)
-   m8xx_wdt_install_timer();
-   else
-   out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE);
-   printk(KERN_NOTICE mpc8xx_wdt: keep-alive handler activated\n);
-}
-
-static int mpc8xx_wdt_open(struct inode *inode, struct file *file)
-{
-   if (test_and_set_bit(0, wdt_opened))
-   return -EBUSY;
-   m8xx_wdt_reset();
-   mpc8xx_wdt_handler_disable();
-   return nonseekable_open(inode, file);
-}
-
-static int mpc8xx_wdt_release(struct inode *inode, struct file *file)
-{
-   m8xx_wdt_reset();
-#if !defined(CONFIG_WATCHDOG_NOWAYOUT)
-   mpc8xx_wdt_handler_enable();
-#endif
-   clear_bit(0, wdt_opened);
-   return 0;
-}
-
-static ssize_t mpc8xx_wdt_write(struct file *file, const char *data,
-   size_t len, loff_t *ppos)
-{
-   if (len) {
-   spin_lock(wdt_lock);
-   m8xx_wdt_reset();
-   spin_unlock(wdt_lock);
-   }
-   return len;
-}
-
-static long mpc8xx_wdt_ioctl(struct file *file,
-   unsigned int cmd, unsigned long arg)
-{
-   int timeout;
-   static struct watchdog_info info = {
-   .options = WDIOF_KEEPALIVEPING,
-   .firmware_version = 0,
-   .identity = MPC8xx watchdog,
-   };
-
-   switch (cmd) {
-   case WDIOC_GETSUPPORT:
-   if (copy_to_user((void *)arg, info, sizeof(info)))
-   return -EFAULT;
-   break;
-
-   case WDIOC_GETSTATUS:
-   case WDIOC_GETBOOTSTATUS:
-   if (put_user(wdt_status, (int *)arg))
-   return -EFAULT;
-   wdt_status = ~WDIOF_KEEPALIVEPING;
-   break;
-
-   case WDIOC_GETTEMP:
-   return -EOPNOTSUPP;
-
-   case WDIOC_SETOPTIONS:
-   return -EOPNOTSUPP;
-
-   case WDIOC_KEEPALIVE:
-   spin_lock(wdt_lock);
-   m8xx_wdt_reset();
-   

Re: [PATCH 2/2] Cell OProfile: SPU mutex lock fix, version 4

2008-08-08 Thread Arnd Bergmann
On Friday 01 August 2008, Carl Love wrote:
 If an error occurs on opcontrol start, the event and per cpu buffers 
 are released.  If later opcontrol shutdown is called then the free
 function will be called again to free buffers that no longer 
 exist.  This results in a kernel oops.  The following changes
 prevent the call to delete buffers that don't exist.
 
 Signed-off-by: Carl Love [EMAIL PROTECTED]
 

vfree(NULL) is defined to be legal, so you don't need to check the
argument for being non-NULL, just set it to NULL after the free.

Arnd 
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[2.6 patch] cleanup powerpc/include/asm/ide.h

2008-08-08 Thread Adrian Bunk
This patch removes code that became unused through IDE changes and the 
arch/ppc/ removal.

Signed-off-by: Adrian Bunk [EMAIL PROTECTED]

---

 arch/powerpc/include/asm/ide.h |   43 -
 1 file changed, 1 insertion(+), 42 deletions(-)

363979e32b08c578431a1773e7b885698feb30aa 
diff --git a/arch/powerpc/include/asm/ide.h b/arch/powerpc/include/asm/ide.h
index 048480e..da01b20 100644
--- a/arch/powerpc/include/asm/ide.h
+++ b/arch/powerpc/include/asm/ide.h
@@ -6,12 +6,7 @@
 #ifndef _ASM_POWERPC_IDE_H
 #define _ASM_POWERPC_IDE_H
 
-#ifdef __KERNEL__
-
-#ifndef __powerpc64__
-#include linux/sched.h
-#include asm/mpc8xx.h
-#endif
+#include linux/compiler.h
 #include asm/io.h
 
 #define __ide_mm_insw(p, a, c) readsw((void __iomem *)(p), (a), (c))
@@ -19,40 +14,4 @@
 #define __ide_mm_outsw(p, a, c)writesw((void __iomem *)(p), (a), (c))
 #define __ide_mm_outsl(p, a, c)writesl((void __iomem *)(p), (a), (c))
 
-#ifndef  __powerpc64__
-#include linux/ioport.h
-
-/* FIXME: use ide_platform host driver */
-static __inline__ int ide_default_irq(unsigned long base)
-{
-#ifdef CONFIG_PPLUS
-   switch (base) {
-   case 0x1f0: return 14;
-   case 0x170: return 15;
-   }
-#endif
-   return 0;
-}
-
-/* FIXME: use ide_platform host driver */
-static __inline__ unsigned long ide_default_io_base(int index)
-{
-#ifdef CONFIG_PPLUS
-   switch (index) {
-   case 0: return 0x1f0;
-   case 1: return 0x170;
-   }
-#endif
-   return 0;
-}
-
-#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
-#define IDE_ARCH_ACK_INTR  1
-#define ide_ack_intr(hwif) ((hwif)-ack_intr ? (hwif)-ack_intr(hwif) : 1)
-#endif
-
-#endif /* __powerpc64__ */
-
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_POWERPC_IDE_H */

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 1/2] Cell OProfile: SPU mutex lock fix, version 4

2008-08-08 Thread Arnd Bergmann
On Friday 01 August 2008, Carl Love wrote:
 The issue is the SPU code is not holding the kernel mutex lock while
 adding samples to the kernel buffer.

Thanks for your patch, and sorry for not replying earlier.
It looks good from a functionality perspective, I just have
some style comments left that I hope we can address quickly.

Since this is still a bug fix (though a rather large one), I
guess we can should get it into 2.6.27-rc3.

Arnd 

 Index: Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_task_sync.c
 ===
 --- Cell_kernel_6_26_2008.orig/arch/powerpc/oprofile/cell/spu_task_sync.c
 +++ Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_task_sync.c
 @@ -35,7 +35,106 @@ static DEFINE_SPINLOCK(buffer_lock);
  static DEFINE_SPINLOCK(cache_lock);
  static int num_spu_nodes;
  int spu_prof_num_nodes;
 -int last_guard_val[MAX_NUMNODES * 8];
 +int last_guard_val[MAX_NUMNODES * SPUS_PER_NODE];
 +static int spu_ctx_sw_seen[MAX_NUMNODES * SPUS_PER_NODE];
 +static int sync_start_registered;
 +static int delayed_work_init;

You don't need the delayed_work_init variable. Just initialize
the work queue in your init function to be sure it's always
right.

I think you should also try to remove sync_start_registered,
these global state variables can easily get annoying when you
try to change something.
AFAICT, spu_sync_stop does not get called unless spu_sync_start
was successful, so the sync_start_registered variable is
redundant.

 +static int oprofile_spu_buff_create(void)
 +{
 + int spu;
 +
 + max_spu_buff = oprofile_get_cpu_buffer_size();
 +
 + for (spu = 0; spu  num_spu_nodes; spu++) {
 + /* create circular buffers to store the data in.
 +  * use locks to manage accessing the buffers
 +  */
 + spu_buff.index[spu].head = 0;
 + spu_buff.index[spu].tail = 0;
 +
 + /*
 +  * Create a buffer for each SPU.  Can't reliably
 +  * create a single buffer for all spus due to not
 +  * enough contiguous kernel memory.
 +  */
 +
 + spu_buff.buff[spu] = kzalloc((max_spu_buff
 +   * sizeof(unsigned long)),
 +  GFP_KERNEL);
 +
 + if (!spu_buff.buff[spu]) {
 + printk(KERN_ERR SPU_PROF: 
 +%s, line %d:  oprofile_spu_buff_create  \
 +failed to allocate spu buffer %d.\n,
 +__FUNCTION__, __LINE__, spu);

The formatting of the printk line is a little unconventional. You certainly
don't need the '\' at the end of the line.
Also, please don't use __FUNCTION__ in new code, but instead of the
standard c99 __func__ symbol. The __LINE__ macro is fine.

 +
 + /* release the spu buffers that have been allocated */
 + while (spu = 0) {
 + if (spu_buff.buff[spu]) {
 + kfree(spu_buff.buff[spu]);
 + spu_buff.buff[spu] = 0;
 + }
 + spu--;
 + }
 + return 1;
 + }
 + }
 + return 0;
 +}

The convention for a function would be to return -ENOMEM here instead
of 1.

  /* The main purpose of this function is to synchronize
   * OProfile with SPUFS by registering to be notified of
   * SPU task switches.
 @@ -372,30 +521,50 @@ static int number_of_online_nodes(void)
   */
  int spu_sync_start(void)
  {
 - int k;
 + int spu;
   int ret = SKIP_GENERIC_SYNC;
   int register_ret;
   unsigned long flags = 0;
  
   spu_prof_num_nodes = number_of_online_nodes();
   num_spu_nodes = spu_prof_num_nodes * 8;
 + delayed_work_init = 0;
 +
 + /* create buffer for storing the SPU data to put in
 +  * the kernel buffer.
 +  */
 + if (oprofile_spu_buff_create()) {
 + ret = -ENOMEM;
 + sync_start_registered = 0;
 + goto out;
 + }

consequently, this becomes

ret = oprofile_spu_buff_create();
if (ret)
goto out;
  

 -out:
 +
 + /* remove scheduled work queue item rather then waiting
 +  * for every queued entry to execute.  Then flush pending
 +  * system wide buffer to event buffer.  Only try to
 +  * remove if it was scheduled.  Get kernel errors otherwise.
 +  */
 + if (delayed_work_init)
 + cancel_delayed_work(spu_work);
 +
 + for (k = 0; k  num_spu_nodes; k++) {
 + spu_ctx_sw_seen[k] = 0;
 +
 + /* spu_sys_buff will be null if there was a problem
 +  * allocating the buffer.  Only delete if it exists.
 +  */
 +
 + if (spu_buff.buff[k]) {
 + kfree(spu_buff.buff[k]);
 +  

[PATCH 0/3] Patches to support QE USB Host Controller

2008-08-08 Thread Anton Vorontsov
Hi all,

Most patches that were needed to support QE USB Host were merged during
2.6.27 merge window, and only three more patches left over. Here they
are.

David, could you bear with gpio_to_chip() exported function, just as
a stopgap for a proper api?

Thanks,

-- 
Anton Vorontsov
email: [EMAIL PROTECTED]
irc://irc.freenode.net/bd2
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 1/3] gpiolib: make gpio_to_chip() public

2008-08-08 Thread Anton Vorontsov
We'll need this function to write platform-specific hooks to deal
with pin's dedicated functions. Quite obviously this will work only
for the platforms with 1-to-1 GPIO to PIN mapping.

This is stopgap solution till we think out and implement a proper
api (pinlib?).

Signed-off-by: Anton Vorontsov [EMAIL PROTECTED]
---
 drivers/gpio/gpiolib.c |3 ++-
 include/asm-generic/gpio.h |1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 8d29405..9536fa8 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -81,10 +81,11 @@ static void gpio_ensure_requested(struct gpio_desc *desc)
 }
 
 /* caller holds gpio_lock *OR* gpio is marked as requested */
-static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
+struct gpio_chip *gpio_to_chip(unsigned gpio)
 {
return gpio_desc[gpio].chip;
 }
+EXPORT_SYMBOL_GPL(gpio_to_chip);
 
 /* dynamic allocation of GPIOs, e.g. on a hotplugged device */
 static int gpiochip_find_base(int ngpio)
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 0f99ad3..d70ee45 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -81,6 +81,7 @@ struct gpio_chip {
unsignedexported:1;
 };
 
+extern struct gpio_chip *gpio_to_chip(unsigned gpio);
 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
unsigned offset);
 extern int __must_check gpiochip_reserve(int start, int ngpio);
-- 
1.5.5.4

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[PATCH 2/3] powerpc/qe: new call to revert a gpio to a dedicated function

2008-08-08 Thread Anton Vorontsov
qe_gpio_set_dedicated() is a platform specific function, which is used
to revert a pin to a dedicated function. Caller should have already
obtained the gpio via gpio_request().

This is needed to support Freescale USB Host Controller.

Signed-off-by: Anton Vorontsov [EMAIL PROTECTED]
---
 arch/powerpc/include/asm/qe.h |1 +
 arch/powerpc/sysdev/qe_lib/gpio.c |   46 +
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/qe.h b/arch/powerpc/include/asm/qe.h
index edee15d..c5c92d9 100644
--- a/arch/powerpc/include/asm/qe.h
+++ b/arch/powerpc/include/asm/qe.h
@@ -111,6 +111,7 @@ extern void __par_io_config_pin(struct qe_pio_regs __iomem 
*par_io, u8 pin,
 extern int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
 int assignment, int has_irq);
 extern int par_io_data_set(u8 port, u8 pin, u8 val);
+int qe_gpio_set_dedicated(unsigned int gpio);
 
 /* QE internal API */
 int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input);
diff --git a/arch/powerpc/sysdev/qe_lib/gpio.c 
b/arch/powerpc/sysdev/qe_lib/gpio.c
index 8e5a0bc..bd7278f 100644
--- a/arch/powerpc/sysdev/qe_lib/gpio.c
+++ b/arch/powerpc/sysdev/qe_lib/gpio.c
@@ -26,6 +26,9 @@ struct qe_gpio_chip {
 
/* shadowed data register to clear/set bits safely */
u32 cpdata;
+
+   /* saved_regs used to restore dedicated functions */
+   struct qe_pio_regs saved_regs;
 };
 
 static inline struct qe_gpio_chip *
@@ -40,6 +43,12 @@ static void qe_gpio_save_regs(struct of_mm_gpio_chip *mm_gc)
struct qe_pio_regs __iomem *regs = mm_gc-regs;
 
qe_gc-cpdata = in_be32(regs-cpdata);
+   qe_gc-saved_regs.cpdata = qe_gc-cpdata;
+   qe_gc-saved_regs.cpdir1 = in_be32(regs-cpdir1);
+   qe_gc-saved_regs.cpdir2 = in_be32(regs-cpdir2);
+   qe_gc-saved_regs.cppar1 = in_be32(regs-cppar1);
+   qe_gc-saved_regs.cppar2 = in_be32(regs-cppar2);
+   qe_gc-saved_regs.cpodr = in_be32(regs-cpodr);
 }
 
 static int qe_gpio_get(struct gpio_chip *gc, unsigned int gpio)
@@ -103,6 +112,43 @@ static int qe_gpio_dir_out(struct gpio_chip *gc, unsigned 
int gpio, int val)
return 0;
 }
 
+int qe_gpio_set_dedicated(unsigned int gpio)
+{
+   struct gpio_chip *gc = gpio_to_chip(gpio);
+   struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+   struct qe_gpio_chip *qe_gc = to_qe_gpio_chip(mm_gc);
+   struct qe_pio_regs __iomem *regs = mm_gc-regs;
+   struct qe_pio_regs *sregs = qe_gc-saved_regs;
+   u8 pin = gpio - gc-base;
+   u32 mask1 = 1  (QE_PIO_PINS - (pin + 1));
+   u32 mask2 = 0x3  (QE_PIO_PINS - (pin % (QE_PIO_PINS / 2) + 1) * 2);
+   bool second_reg = pin  (QE_PIO_PINS / 2) - 1;
+   unsigned long flags;
+
+   spin_lock_irqsave(qe_gc-lock, flags);
+
+   if (second_reg) {
+   clrsetbits_be32(regs-cpdir2, mask2, sregs-cpdir2  mask2);
+   clrsetbits_be32(regs-cppar2, mask2, sregs-cppar2  mask2);
+   } else {
+   clrsetbits_be32(regs-cpdir1, mask2, sregs-cpdir1  mask2);
+   clrsetbits_be32(regs-cppar1, mask2, sregs-cppar1  mask2);
+   }
+
+   if (sregs-cpdata  mask1)
+   qe_gc-cpdata |= mask1;
+   else
+   qe_gc-cpdata = ~mask1;
+
+   out_be32(regs-cpdata, qe_gc-cpdata);
+   clrsetbits_be32(regs-cpodr, mask1, sregs-cpodr  mask1);
+
+   spin_unlock_irqrestore(qe_gc-lock, flags);
+
+   return 0;
+}
+EXPORT_SYMBOL(qe_gpio_set_dedicated);
+
 static int __init qe_add_gpiochips(void)
 {
struct device_node *np;
-- 
1.5.5.4

___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [2.6 patch] cleanup powerpc/include/asm/ide.h

2008-08-08 Thread Bartlomiej Zolnierkiewicz
On Friday 08 August 2008, Adrian Bunk wrote:
 This patch removes code that became unused through IDE changes and the 
 arch/ppc/ removal.
 
 Signed-off-by: Adrian Bunk [EMAIL PROTECTED]

applied
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


[12/17] powerpc: use bcd2bin/bin2bcd

2008-08-08 Thread Adrian Bunk
This patch changes powerpc to use the new bcd2bin/bin2bcd functions 
instead of the obsolete BCD_TO_BIN/BIN_TO_BCD macros.

Signed-off-by: Adrian Bunk [EMAIL PROTECTED]

---

 arch/powerpc/platforms/chrp/time.c  |   24 
 arch/powerpc/platforms/iseries/mf.c |   26 +-
 arch/powerpc/platforms/maple/time.c |   24 
 3 files changed, 37 insertions(+), 37 deletions(-)

e6d9f2f91ed9e6b761aba2754ec5339b4c76beed 
diff --git a/arch/powerpc/platforms/chrp/time.c 
b/arch/powerpc/platforms/chrp/time.c
index 96d1e4b..054dfe5 100644
--- a/arch/powerpc/platforms/chrp/time.c
+++ b/arch/powerpc/platforms/chrp/time.c
@@ -94,12 +94,12 @@ int chrp_set_rtc_time(struct rtc_time *tmarg)
chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), 
RTC_FREQ_SELECT);
 
if (!(save_control  RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-   BIN_TO_BCD(tm.tm_sec);
-   BIN_TO_BCD(tm.tm_min);
-   BIN_TO_BCD(tm.tm_hour);
-   BIN_TO_BCD(tm.tm_mon);
-   BIN_TO_BCD(tm.tm_mday);
-   BIN_TO_BCD(tm.tm_year);
+   tm.tm_sec = bin2bcd(tm.tm_sec);
+   tm.tm_min = bin2bcd(tm.tm_min);
+   tm.tm_hour = bin2bcd(tm.tm_hour);
+   tm.tm_mon = bin2bcd(tm.tm_mon);
+   tm.tm_mday = bin2bcd(tm.tm_mday);
+   tm.tm_year = bin2bcd(tm.tm_year);
}
chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
@@ -136,12 +136,12 @@ void chrp_get_rtc_time(struct rtc_time *tm)
} while (sec != chrp_cmos_clock_read(RTC_SECONDS));
 
if (!(chrp_cmos_clock_read(RTC_CONTROL)  RTC_DM_BINARY) || 
RTC_ALWAYS_BCD) {
-   BCD_TO_BIN(sec);
-   BCD_TO_BIN(min);
-   BCD_TO_BIN(hour);
-   BCD_TO_BIN(day);
-   BCD_TO_BIN(mon);
-   BCD_TO_BIN(year);
+   sec = bcd2bin(sec);
+   min = bcd2bin(min);
+   hour = bcd2bin(hour);
+   day = bcd2bin(day);
+   mon = bcd2bin(mon);
+   year = bcd2bin(year);
}
if (year  70)
year += 100;
diff --git a/arch/powerpc/platforms/iseries/mf.c 
b/arch/powerpc/platforms/iseries/mf.c
index 1dc7295..8dfc78e 100644
--- a/arch/powerpc/platforms/iseries/mf.c
+++ b/arch/powerpc/platforms/iseries/mf.c
@@ -722,13 +722,13 @@ static int mf_set_rtc(struct rtc_time *tm)
day = tm-tm_mday;
mon = tm-tm_mon + 1;
 
-   BIN_TO_BCD(sec);
-   BIN_TO_BCD(min);
-   BIN_TO_BCD(hour);
-   BIN_TO_BCD(mon);
-   BIN_TO_BCD(day);
-   BIN_TO_BCD(y1);
-   BIN_TO_BCD(y2);
+   sec = bin2bcd(sec);
+   min = bin2bcd(min);
+   hour = bin2bcd(hour);
+   mon = bin2bcd(mon);
+   day = bin2bcd(day);
+   y1 = bin2bcd(y1);
+   y2 = bin2bcd(y2);
 
memset(ce_time, 0, sizeof(ce_time));
ce_time[3] = 0x41;
@@ -777,12 +777,12 @@ static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time 
*tm)
u8 day = ce_msg[10];
u8 mon = ce_msg[11];
 
-   BCD_TO_BIN(sec);
-   BCD_TO_BIN(min);
-   BCD_TO_BIN(hour);
-   BCD_TO_BIN(day);
-   BCD_TO_BIN(mon);
-   BCD_TO_BIN(year);
+   sec = bcd2bin(sec);
+   min = bcd2bin(min);
+   hour = bcd2bin(hour);
+   day = bcd2bin(day);
+   mon = bcd2bin(mon);
+   year = bcd2bin(year);
 
if (year = 69)
year += 100;
diff --git a/arch/powerpc/platforms/maple/time.c 
b/arch/powerpc/platforms/maple/time.c
index 53bca13..eac569d 100644
--- a/arch/powerpc/platforms/maple/time.c
+++ b/arch/powerpc/platforms/maple/time.c
@@ -68,12 +68,12 @@ void maple_get_rtc_time(struct rtc_time *tm)
 
if (!(maple_clock_read(RTC_CONTROL)  RTC_DM_BINARY)
|| RTC_ALWAYS_BCD) {
-   BCD_TO_BIN(tm-tm_sec);
-   BCD_TO_BIN(tm-tm_min);
-   BCD_TO_BIN(tm-tm_hour);
-   BCD_TO_BIN(tm-tm_mday);
-   BCD_TO_BIN(tm-tm_mon);
-   BCD_TO_BIN(tm-tm_year);
+   tm-tm_sec = bcd2bin(tm-tm_sec);
+   tm-tm_min = bcd2bin(tm-tm_min);
+   tm-tm_hour = bcd2bin(tm-tm_hour);
+   tm-tm_mday = bcd2bin(tm-tm_mday);
+   tm-tm_mon = bcd2bin(tm-tm_mon);
+   tm-tm_year = bcd2bin(tm-tm_year);
  }
if ((tm-tm_year + 1900)  1970)
tm-tm_year += 100;
@@ -104,12 +104,12 @@ int maple_set_rtc_time(struct rtc_time *tm)
year = tm-tm_year;
 
if (!(save_control  RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-   BIN_TO_BCD(sec);
-   BIN_TO_BCD(min);
-   BIN_TO_BCD(hour);
-   BIN_TO_BCD(mon);
-   BIN_TO_BCD(mday);
-   BIN_TO_BCD(year);
+

Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Matt Carlson
On Fri, Aug 08, 2008 at 07:18:31PM +1000, Benjamin Herrenschmidt wrote:
 On Fri, 2008-08-08 at 10:58 +0200, Segher Boessenkool wrote:
   I don't know yet for sure what happens, but a quick look at the commit
   seems to show that the driver synchronously spin-waits for up to 2.5ms
  
  That's what the comment says, but the code says 2.5 _seconds_:
  
  +   /* Wait for up to 2.5 milliseconds */
  +   for (i = 0; i  25; i++) {
  +   if (!(tr32(GRC_RX_CPU_EVENT)  GRC_RX_CPU_DRIVER_EVENT))
  +   break;
  +   udelay(10);
  +   }
  
  (not that milliseconds wouldn't be bad already...)
 
 Right, indeed. I think we have a good candidate for the problem :-) I'll
 verify that on monday. Now, that leads to two questions:
 
  - What such a synchronous and potentially horribly slow code is
 going in a locked section or a timer interrupts ? Ie, the link
 watch should probably move to a workqueue if that is to remain,
 or the code turned into a state machine that periodically check for
 events, or whatever is more sane than the above.
 
  - The code should at least display some error and do something sane in
 case of timeout such as disabling the new UMP feature instead of
 repeatedly looping ...
 
  - If this is indeed our problem (timing out in the code above), why is
 our firmware not emitting the requested event - maybe the PowerStations
 need a tg3 firmware update.
 
 Matt, what's your take on this ?

Segher is right.  The code should be 2.5 milliseconds but is actually
much longer.  This fix is actually already in my patch queue and needs
to be sent upstream.

We really shouldn't be displaying any error messages in the event of a
timeout though.  Earlier versions of the UMP firmware did not support
the link update interface.  The best thing the driver can do for all
cases is give the firmware a chance to service the event but continue
as if the event were serviced if it did not get an explicit ACK.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Michael Chan

On Fri, 2008-08-08 at 11:43 -0700, Matthew Carlson wrote:
 Segher is right.  The code should be 2.5 milliseconds but is actually
 much longer.  This fix is actually already in my patch queue and needs
 to be sent upstream.
 

Matt, I think we can optimize this a little more.  The heart beat event
is sent every second and the link event is sent whenever the link
changes.  the spin wait is only needed in rare cases when the link event
is closer than 2.5 msec from the heart beat event.

We can save the jiffies time stamp right after sending each event.  Next
time we need to send a heart beat or a link event, we check the jiffies
with the stored time stamp.  If they are less than 2.5 msec apart and we
haven't received the ACK from the previous event yet, we just wait up to
the remainder.  It should be very rare that we have to wait.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Nathan Lynch
Benjamin Herrenschmidt wrote:
 On Fri, 2008-08-08 at 10:58 +0200, Segher Boessenkool wrote:
   I don't know yet for sure what happens, but a quick look at the commit
   seems to show that the driver synchronously spin-waits for up to 2.5ms
  
  That's what the comment says, but the code says 2.5 _seconds_:
  
  +   /* Wait for up to 2.5 milliseconds */
  +   for (i = 0; i  25; i++) {
  +   if (!(tr32(GRC_RX_CPU_EVENT)  GRC_RX_CPU_DRIVER_EVENT))
  +   break;
  +   udelay(10);
  +   }
  
  (not that milliseconds wouldn't be bad already...)
 
 Right, indeed. I think we have a good candidate for the problem :-)

I put a printk in tg3_wait_for_event_ack and I can confirm that it's
timing out frequently (every few seconds) on my system.  Changing the
number of loop iterations to 250 alleviates the problem.
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Benjamin Herrenschmidt
On Fri, 2008-08-08 at 11:43 -0700, Matt Carlson wrote:
 
 Segher is right.  The code should be 2.5 milliseconds but is actually
 much longer.  This fix is actually already in my patch queue and needs
 to be sent upstream.
 
 We really shouldn't be displaying any error messages in the event of a
 timeout though.  Earlier versions of the UMP firmware did not support
 the link update interface.  The best thing the driver can do for all
 cases is give the firmware a chance to service the event but continue
 as if the event were serviced if it did not get an explicit ACK.

But that means that the driver will continuously spin 2.5ms every
timer tick or so ? Or do I miss something ? Could it be possible to
count timeouts and if after N attempts at an ack, they all timed out,
disable the feature completely ?

Or is there a way to test the version of the firmware ?

In any case, the fix should go into -stable as the problem is hurting
2.6.26. Also, should we consider updating the tg3 firmware on those
machines ?

Ben.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 1/2] Cell OProfile: SPU mutex lock fix, version 4

2008-08-08 Thread Carl Love

On Fri, 2008-08-08 at 18:08 +0200, Arnd Bergmann wrote:
 On Friday 01 August 2008, Carl Love wrote:
  The issue is the SPU code is not holding the kernel mutex lock while
  adding samples to the kernel buffer.
 
 Thanks for your patch, and sorry for not replying earlier.
 It looks good from a functionality perspective, I just have
 some style comments left that I hope we can address quickly.
 
 Since this is still a bug fix (though a rather large one), I
 guess we can should get it into 2.6.27-rc3.
 
   Arnd 
 
  Index: Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_task_sync.c
  ===
  --- Cell_kernel_6_26_2008.orig/arch/powerpc/oprofile/cell/spu_task_sync.c
  +++ Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_task_sync.c
  @@ -35,7 +35,106 @@ static DEFINE_SPINLOCK(buffer_lock);
   static DEFINE_SPINLOCK(cache_lock);
   static int num_spu_nodes;
   int spu_prof_num_nodes;
  -int last_guard_val[MAX_NUMNODES * 8];
  +int last_guard_val[MAX_NUMNODES * SPUS_PER_NODE];
  +static int spu_ctx_sw_seen[MAX_NUMNODES * SPUS_PER_NODE];
  +static int sync_start_registered;
  +static int delayed_work_init;
 
 You don't need the delayed_work_init variable. Just initialize
 the work queue in your init function to be sure it's always
 right.
 
 I think you should also try to remove sync_start_registered,
 these global state variables can easily get annoying when you
 try to change something.
 AFAICT, spu_sync_stop does not get called unless spu_sync_start
 was successful, so the sync_start_registered variable is
 redundant.
 


I was able to remove the delayed_work_init variable with a little code
restructuring.  

I worked on the sync_start_registered variable.  I had put it in because
I thought that the call to spu_switch_event_unregister() call for a non
registered event was giving me a kernel error.  I retested this and it
does look like it is OK.  So it looks safe to remove the
sync_start_registered variable.  

The rest of your comments were fairly easy to address.


  +static int oprofile_spu_buff_create(void)
  +{
  +   int spu;
  +
  +   max_spu_buff = oprofile_get_cpu_buffer_size();
  +
  +   for (spu = 0; spu  num_spu_nodes; spu++) {
  +   /* create circular buffers to store the data in.
  +* use locks to manage accessing the buffers
  +*/
  +   spu_buff.index[spu].head = 0;
  +   spu_buff.index[spu].tail = 0;
  +
  +   /*
  +* Create a buffer for each SPU.  Can't reliably
  +* create a single buffer for all spus due to not
  +* enough contiguous kernel memory.
  +*/
  +
  +   spu_buff.buff[spu] = kzalloc((max_spu_buff
  + * sizeof(unsigned long)),
  +GFP_KERNEL);
  +
  +   if (!spu_buff.buff[spu]) {
  +   printk(KERN_ERR SPU_PROF: 
  +  %s, line %d:  oprofile_spu_buff_create  \
  +  failed to allocate spu buffer %d.\n,
  +  __FUNCTION__, __LINE__, spu);
 
 The formatting of the printk line is a little unconventional. You certainly
 don't need the '\' at the end of the line.
 Also, please don't use __FUNCTION__ in new code, but instead of the
 standard c99 __func__ symbol. The __LINE__ macro is fine.
 
  +
  +   /* release the spu buffers that have been allocated */
  +   while (spu = 0) {
  +   if (spu_buff.buff[spu]) {
  +   kfree(spu_buff.buff[spu]);
  +   spu_buff.buff[spu] = 0;
  +   }
  +   spu--;
  +   }
  +   return 1;
  +   }
  +   }
  +   return 0;
  +}
 
 The convention for a function would be to return -ENOMEM here instead
 of 1.
 
   /* The main purpose of this function is to synchronize
* OProfile with SPUFS by registering to be notified of
* SPU task switches.
  @@ -372,30 +521,50 @@ static int number_of_online_nodes(void)
*/
   int spu_sync_start(void)
   {
  -   int k;
  +   int spu;
  int ret = SKIP_GENERIC_SYNC;
  int register_ret;
  unsigned long flags = 0;
   
  spu_prof_num_nodes = number_of_online_nodes();
  num_spu_nodes = spu_prof_num_nodes * 8;
  +   delayed_work_init = 0;
  +
  +   /* create buffer for storing the SPU data to put in
  +* the kernel buffer.
  +*/
  +   if (oprofile_spu_buff_create()) {
  +   ret = -ENOMEM;
  +   sync_start_registered = 0;
  +   goto out;
  +   }
 
 consequently, this becomes
 
   ret = oprofile_spu_buff_create();
   if (ret)
   goto out;
   
 
  -out:
  +
  +   /* remove scheduled work queue item rather then waiting
  +* for every queued entry to execute.  Then flush pending
  +* system wide buffer to 

Re: [PATCH 1/2] Repost Cell OProfile: SPU mutex lock fix, version 4

2008-08-08 Thread Carl Love
Version 4 of the SPU mutex lock fix.

Updated to address Arnd's comments.

The issue is the SPU code is not holding the kernel mutex lock while
adding samples to the kernel buffer.

This patch creates per SPU buffers to hold the data.  Data
is added to the buffers from in interrupt context.  The data
is periodically pushed to the kernel buffer via a new Oprofile
function oprofile_put_buff(). The oprofile_put_buff() function
is called via a work queue enabling the funtion to acquire the
mutex lock.  

The existing user controls for adjusting the per CPU buffer 
size is used to control the size of the per SPU buffers.  
Similarly, overflows of the SPU buffers are reported by 
incrementing the per CPU buffer stats.  This eliminates the 
need to have architecture specific controls for the per SPU 
buffers which is not acceptable to the OProfile user tool
maintainer.

The export of the oprofile add_event_entry() is removed as it 
is no longer needed given this patch.
 
Note, this patch has not addressed the issue of indexing arrays
by the spu number.  This still needs to be fixed as the spu
numbering is not guarenteed to be 0 to max_num_spus-1.

Signed-off-by: Carl Love [EMAIL PROTECTED]
Signed-off-by: Maynard Johnson   [EMAIL PROTECTED]


Index: Cell_kernel_6_26_2008/drivers/oprofile/cpu_buffer.c
===
--- Cell_kernel_6_26_2008.orig/drivers/oprofile/cpu_buffer.c
+++ Cell_kernel_6_26_2008/drivers/oprofile/cpu_buffer.c
@@ -37,11 +37,24 @@ static int work_enabled;
 void free_cpu_buffers(void)
 {
int i;
- 
+
for_each_online_cpu(i)
vfree(per_cpu(cpu_buffer, i).buffer);
 }
 
+unsigned long oprofile_get_cpu_buffer_size(void)
+{
+   return fs_cpu_buffer_size;
+}
+
+void oprofile_cpu_buffer_inc_smpl_lost(void)
+{
+   struct oprofile_cpu_buffer *cpu_buf
+   = __get_cpu_var(cpu_buffer);
+
+   cpu_buf-sample_lost_overflow++;
+}
+
 int alloc_cpu_buffers(void)
 {
int i;
Index: Cell_kernel_6_26_2008/include/linux/oprofile.h
===
--- Cell_kernel_6_26_2008.orig/include/linux/oprofile.h
+++ Cell_kernel_6_26_2008/include/linux/oprofile.h
@@ -84,13 +84,6 @@ int oprofile_arch_init(struct oprofile_o
 void oprofile_arch_exit(void);
 
 /**
- * Add data to the event buffer.
- * The data passed is free-form, but typically consists of
- * file offsets, dcookies, context information, and ESCAPE codes.
- */
-void add_event_entry(unsigned long data);
-
-/**
  * Add a sample. This may be called from any context. Pass
  * smp_processor_id() as cpu.
  */
@@ -160,5 +153,14 @@ int oprofilefs_ulong_from_user(unsigned 
 
 /** lock for read/write safety */
 extern spinlock_t oprofilefs_lock;
+
+/**
+ * Add the contents of a circular buffer to the event buffer.
+ */
+void oprofile_put_buff(unsigned long *buf,unsigned int start,
+   unsigned int stop, unsigned int max);
+
+unsigned long oprofile_get_cpu_buffer_size(void);
+void oprofile_cpu_buffer_inc_smpl_lost(void);
  
 #endif /* OPROFILE_H */
Index: Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_profiler.c
===
--- Cell_kernel_6_26_2008.orig/arch/powerpc/oprofile/cell/spu_profiler.c
+++ Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_profiler.c
@@ -23,12 +23,11 @@
 
 static u32 *samples;
 
-static int spu_prof_running;
+int spu_prof_running;
 static unsigned int profiling_interval;
 
 #define NUM_SPU_BITS_TRBUF 16
 #define SPUS_PER_TB_ENTRY   4
-#define SPUS_PER_NODE   8
 
 #define SPU_PC_MASK 0x
 
@@ -208,6 +207,7 @@ int start_spu_profiling(unsigned int cyc
 
spu_prof_running = 1;
hrtimer_start(timer, kt, HRTIMER_MODE_REL);
+   schedule_delayed_work(spu_work, DEFAULT_TIMER_EXPIRE);
 
return 0;
 }
Index: Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_task_sync.c
===
--- Cell_kernel_6_26_2008.orig/arch/powerpc/oprofile/cell/spu_task_sync.c
+++ Cell_kernel_6_26_2008/arch/powerpc/oprofile/cell/spu_task_sync.c
@@ -35,7 +35,102 @@ static DEFINE_SPINLOCK(buffer_lock);
 static DEFINE_SPINLOCK(cache_lock);
 static int num_spu_nodes;
 int spu_prof_num_nodes;
-int last_guard_val[MAX_NUMNODES * 8];
+
+struct spu_buffer spu_buff[MAX_NUMNODES * SPUS_PER_NODE];
+struct delayed_work spu_work;
+static unsigned max_spu_buff;
+
+static void spu_buff_add(unsigned long int value, int spu)
+{
+   /* spu buff is a circular buffer.  Add entries to the
+* head.  Head is the index to store the next value.
+* The buffer is full when there is one available entry
+* in the queue, i.e. head and tail can't be equal.
+* That way we can tell the difference between the
+* buffer being full versus empty.
+*
+*  ASSUPTION: the buffer_lock is held when this function
+*   

Re: [PATCH 2/2] Repost Cell OProfile: SPU mutex lock fix, version 4

2008-08-08 Thread Carl Love
Updated to address Arnd's comments.

If an error occurs on opcontrol start, the event and per cpu buffers 
are released.  If later opcontrol shutdown is called then the free
function will be called again to free buffers that no longer 
exist.  This results in a kernel oops.  The following changes
prevent the call to delete buffers that don't exist.

Signed-off-by: Carl Love [EMAIL PROTECTED]

Index: Cell_kernel_6_26_2008/drivers/oprofile/cpu_buffer.c
===
--- Cell_kernel_6_26_2008.orig/drivers/oprofile/cpu_buffer.c
+++ Cell_kernel_6_26_2008/drivers/oprofile/cpu_buffer.c
@@ -38,8 +38,10 @@ void free_cpu_buffers(void)
 {
int i;
 
-   for_each_online_cpu(i)
+   for_each_online_cpu(i) {
vfree(per_cpu(cpu_buffer, i).buffer);
+   per_cpu(cpu_buffer, i).buffer = NULL;
+   }
 }
 
 unsigned long oprofile_get_cpu_buffer_size(void)
Index: Cell_kernel_6_26_2008/drivers/oprofile/event_buffer.c
===
--- Cell_kernel_6_26_2008.orig/drivers/oprofile/event_buffer.c
+++ Cell_kernel_6_26_2008/drivers/oprofile/event_buffer.c
@@ -93,6 +93,8 @@ out:
 void free_event_buffer(void)
 {
vfree(event_buffer);
+
+   event_buffer = NULL;
 }
 
  


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: [PATCH 0/3] Patches to support QE USB Host Controller

2008-08-08 Thread Greg KH
On Fri, Aug 08, 2008 at 08:17:17PM +0400, Anton Vorontsov wrote:
 Hi all,
 
 Most patches that were needed to support QE USB Host were merged during
 2.6.27 merge window, and only three more patches left over. Here they
 are.
 
 David, could you bear with gpio_to_chip() exported function, just as
 a stopgap for a proper api?

I'll hold off on the 3rd patch until david takes the first two.

thanks,

greg k-h
___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev


Re: Strange tg3 regression with UMP fw. link reporting

2008-08-08 Thread Michael Chan

On Fri, 2008-08-08 at 15:05 -0700, Benjamin Herrenschmidt wrote:
 On Fri, 2008-08-08 at 11:43 -0700, Matt Carlson wrote:
  We really shouldn't be displaying any error messages in the event of a
  timeout though.  Earlier versions of the UMP firmware did not support
  the link update interface.  The best thing the driver can do for all
  cases is give the firmware a chance to service the event but continue
  as if the event were serviced if it did not get an explicit ACK.
 
 But that means that the driver will continuously spin 2.5ms every
 timer tick or so ? Or do I miss something ? Could it be possible to
 count timeouts and if after N attempts at an ack, they all timed out,
 disable the feature completely ?

Please see my other email.  Matt and I will fix it in a way to minimize
the spin as much as possible regardless of firmware version.

 
 Or is there a way to test the version of the firmware ?
 
 In any case, the fix should go into -stable as the problem is hurting
 2.6.26. Also, should we consider updating the tg3 firmware on those
 machines ?
 

Right, we'll take care of -stable as well.  Thanks.


___
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev