LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] ps3: remove driver_data direct access of struct device
From: Geoff Levand @ 2009-05-11 21:07 UTC (permalink / raw)
  To: Roel Kluin; +Cc: Geert.Uytterhoeven, linuxppc-dev, cbe-oss-dev, lkml
In-Reply-To: <4A087DB9.50305@gmail.com>

Hi Roel,

On 05/11/2009 12:34 PM, Roel Kluin wrote:
> To avoid direct access to the driver_data pointer in struct device, the
> functions dev_get_drvdata() and dev_set_drvdata() should be used.
> 
> Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
> ---
> Please review. especially note that I removed a
> kfree(dev->sbd.core.driver_data);
> Is that correct?

Comment below.

>  arch/powerpc/include/asm/ps3.h |    4 ++--
>  drivers/char/ps3flash.c        |   11 +++++------
>  drivers/scsi/ps3rom.c          |   10 +++++-----
>  drivers/video/ps3fb.c          |    6 +++---
>  4 files changed, 15 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h
> index cdb6fd8..a55717e 100644
> --- a/arch/powerpc/include/asm/ps3.h
> +++ b/arch/powerpc/include/asm/ps3.h
> @@ -421,12 +421,12 @@ static inline struct ps3_system_bus_driver *
>  static inline void ps3_system_bus_set_driver_data(
>  	struct ps3_system_bus_device *dev, void *data)
>  {
> -	dev->core.driver_data = data;
> +	dev_set_drvdata(&dev->core, data);
>  }
>  static inline void *ps3_system_bus_get_driver_data(
>  	struct ps3_system_bus_device *dev)
>  {
> -	return dev->core.driver_data;
> +	return dev_get_drvdata(&dev->core);
>  }
>  
>  /* These two need global scope for get_dma_ops(). */
> diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
> index afbe456..6083032 100644
> --- a/drivers/char/ps3flash.c
> +++ b/drivers/char/ps3flash.c
> @@ -108,7 +108,7 @@ static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
>  			     loff_t *pos)
>  {
>  	struct ps3_storage_device *dev = ps3flash_dev;
> -	struct ps3flash_private *priv = dev->sbd.core.driver_data;
> +	struct ps3flash_private *priv = dev_get_drvdata(&dev->sbd.core);

These should all be using ps3_system_bus_get_driver_data() and
ps3_system_bus_set_driver_data():

  struct ps3flash_private *priv = ps3_system_bus_get_driver_data(&dev->sbd)

> @@ -404,8 +404,7 @@ static int ps3flash_remove(struct ps3_system_bus_device *_dev)
>  
>  	misc_deregister(&ps3flash_misc);
>  	ps3stor_teardown(dev);
> -	kfree(dev->sbd.core.driver_data);
> -	dev->sbd.core.driver_data = NULL;
> +	dev_set_drvdata(&dev->sbd.core, NULL);

It seems that will result in a memory leak.  Why did you
think the kfree() should be removed?

Won't this work?

	kfree(ps3_system_bus_get_driver_data(&dev->sbd));
	ps3_system_bus_set_driver_data(&dev->sbd, NULL);

>  	ps3flash_dev = NULL;
>  	return 0;
>  }

-Geoff

^ permalink raw reply

* [RFC] Hardware Breakpoint interfaces implementation for PPC64
From: K.Prasad @ 2009-05-11 20:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Benjamin Herrenschmidt, paulus

Hi PPC Dev folks,
	Please find a patch below that implements the proposed Hardware
Breakpoint interfaces for PPC64 architecture.

As a brief introduction, the proposed Hardware Breakpoint
infrastructure provides generic in-kernel interfaces to which users
from kernel- and user-space can request for breakpoint registers. An
ftrace plugin that can trace accesses to data variables is also part
of the generic HW Breakpoint interface patchset. The latest submission
for this patchset along with an x86 implementation can be found here:
http://lkml.org/lkml/2009/5/11/159.

The following are the salient features of the PPC64 patch.

- Arch-specific definitions for kernel and user-space requests are
  defined in arch/powerpc/kernel/hw_breakpoint.c
- Ptrace is converted to use the HW Breakpoint interfaces
- The ftrace plugin called ksym_tracer is tested to work fine. For
  instance when tracing pid_max kernel variable, the following was
  obtained as output

# cat trace
# tracer: ksym_tracer
#
#       TASK-PID      CPU#      Symbol         Type    Function         
#          |           |          |              |         |            
bash            4502  3   pid_max               RW  .do_proc_dointvec_minmax_conv+0x78/0x10c
bash            4502  3   pid_max               RW  .do_proc_dointvec_minmax_conv+0xa0/0x10c
bash            4502  3   pid_max               RW  .alloc_pid+0x8c/0x4a4

There are however a few limitations/caveats of the patch as identified
below:

- The patch is currently implemented only for PPC64 architecture. Other
  architectures (especially Book-E implementations are expected to
  happen in due course).

- HW Breakpoints over data addresses through Xmon (using "bd" command)
  and the proposed HW Breakpoint interfaces can now operate in a
  mutually exclusive manner. Xmon's integration is pending and is
  dependant on successful triggering of breakpoints through "bd<ops>".
  (Note: On a Power5 machine running 2.6.29, Xmon could not trigger HW
  Breakpoints when tested).

Kindly let me know your comments.

Thanks,
K.Prasad


Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
---
 arch/powerpc/Kconfig                     |    1 
 arch/powerpc/include/asm/hw_breakpoint.h |   52 +++++
 arch/powerpc/include/asm/processor.h     |    1 
 arch/powerpc/include/asm/reg.h           |    2 
 arch/powerpc/include/asm/thread_info.h   |    2 
 arch/powerpc/kernel/Makefile             |    2 
 arch/powerpc/kernel/hw_breakpoint.c      |  271 +++++++++++++++++++++++++++++++
 arch/powerpc/kernel/process.c            |   18 ++
 arch/powerpc/kernel/ptrace.c             |   48 +++++
 arch/powerpc/mm/fault.c                  |   14 -
 samples/hw_breakpoint/data_breakpoint.c  |    4 
 12 files changed, 423 insertions(+), 9 deletions(-)

Index: linux-2.6-tip.hbkpt/arch/powerpc/Kconfig
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/Kconfig
+++ linux-2.6-tip.hbkpt/arch/powerpc/Kconfig
@@ -125,6 +125,7 @@ config PPC
 	select USE_GENERIC_SMP_HELPERS if SMP
 	select HAVE_OPROFILE
 	select HAVE_SYSCALL_WRAPPERS if PPC64
+	select HAVE_HW_BREAKPOINT if PPC64
 
 config EARLY_PRINTK
 	bool
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/Makefile
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/Makefile
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/Makefile
@@ -33,7 +33,7 @@ obj-$(CONFIG_PPC64)		+= setup_64.o sys_p
 				   signal_64.o ptrace32.o \
 				   paca.o cpu_setup_ppc970.o \
 				   cpu_setup_pa6t.o \
-				   firmware.o nvram_64.o
+				   firmware.o nvram_64.o hw_breakpoint.o
 obj64-$(CONFIG_RELOCATABLE)	+= reloc_64.o
 obj-$(CONFIG_PPC64)		+= vdso64/
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/hw_breakpoint.c
===================================================================
--- /dev/null
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/hw_breakpoint.c
@@ -0,0 +1,271 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) 2009 IBM Corporation
+ */
+
+/*
+ * HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,
+ * using the CPU's debug registers.
+ */
+
+#include <linux/notifier.h>
+#include <linux/kallsyms.h>
+#include <linux/kprobes.h>
+#include <linux/percpu.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+
+#include <asm/hw_breakpoint.h>
+#include <asm/processor.h>
+#include <asm/sstep.h>
+
+/* Store the kernel-space breakpoint address value */
+static unsigned long kdabr;
+
+/*
+ * Temporarily stores address for DABR before it is written by the
+ * single-step handler routine
+ */
+static DEFINE_PER_CPU(unsigned long, dabr_data);
+
+void arch_update_kernel_hw_breakpoint(void *unused)
+{
+	struct hw_breakpoint *bp;
+
+	/* Check if there is nothing to update */
+	if (hbp_kernel_pos == HB_NUM)
+		return;
+	bp = hbp_kernel[hbp_kernel_pos];
+	if (bp == NULL)
+		kdabr = 0;
+	else
+		kdabr = bp->info.address | bp->info.type | DABR_TRANSLATION;
+	set_dabr(kdabr);
+}
+
+/*
+ * Install the thread breakpoints in their debug registers.
+ */
+void arch_install_thread_hw_breakpoint(struct task_struct *tsk)
+{
+	set_dabr(tsk->thread.dabr);
+}
+
+/*
+ * Install the debug register values for just the kernel, no thread.
+ */
+void arch_uninstall_thread_hw_breakpoint()
+{
+	set_dabr(0);
+}
+
+/*
+ * Check for virtual address in user space.
+ */
+int arch_check_va_in_userspace(unsigned long va, u8 hbp_len)
+{
+	return (va <= TASK_SIZE - HW_BREAKPOINT_LEN);
+}
+
+/*
+ * Check for virtual address in kernel space.
+ */
+int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
+{
+	return (va >= TASK_SIZE) && ((va + HW_BREAKPOINT_LEN - 1) >= TASK_SIZE);
+}
+
+/*
+ * Store a breakpoint's encoded address, length, and type.
+ */
+int arch_store_info(struct hw_breakpoint *bp)
+{
+	/*
+	 * User-space requests will always have the address field populated
+	 * For kernel-addresses, either the address or symbol name can be
+	 * specified.
+	 */
+	if (bp->info.name)
+		bp->info.address = (unsigned long)
+					kallsyms_lookup_name(bp->info.name);
+	if (bp->info.address)
+		return 0;
+	return -EINVAL;
+}
+
+/*
+ * Validate the arch-specific HW Breakpoint register settings
+ */
+int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
+						struct task_struct *tsk)
+{
+	int ret = -EINVAL;
+
+	if (!bp)
+		return ret;
+
+	switch (bp->info.type) {
+	case DABR_DATA_READ:
+		break;
+	case DABR_DATA_WRITE:
+		break;
+	case DABR_DATA_RW:
+		break;
+	default:
+		return ret;
+	}
+
+	if (bp->triggered)
+		ret = arch_store_info(bp);
+
+	/* Check for double word alignment - 8 bytes */
+	if (bp->info.address & HW_BREAKPOINT_ALIGN)
+		return -EINVAL;
+	return ret;
+}
+
+void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk)
+{
+	struct thread_struct *thread = &(tsk->thread);
+	struct hw_breakpoint *bp = thread->hbp[0];
+
+	if (bp)
+		thread->dabr = bp->info.address	| bp->info.type |
+				DABR_TRANSLATION;
+	else
+		thread->dabr = 0;
+}
+
+void arch_flush_thread_hw_breakpoint(struct task_struct *tsk)
+{
+	struct thread_struct *thread = &(tsk->thread);
+
+	thread->dabr = 0;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_handler(struct die_args *args)
+{
+	int rc = NOTIFY_STOP;
+	struct hw_breakpoint *bp;
+	struct pt_regs *regs = args->regs;
+	unsigned long dar;
+	int cpu, stepped, is_kernel;
+
+	/* Disable breakpoints during exception handling */
+	set_dabr(0);
+
+	dar = regs->dar & (~HW_BREAKPOINT_ALIGN);
+	is_kernel = (dar >= TASK_SIZE) ? 1 : 0;
+
+	if (is_kernel)
+		bp = hbp_kernel[0];
+	else {
+		bp = current->thread.hbp[0];
+		/* Lazy debug register switching */
+		if (!bp)
+			return rc;
+		rc = NOTIFY_DONE;
+	}
+
+	(bp->triggered)(bp, regs);
+
+	cpu = get_cpu();
+	if (is_kernel)
+		per_cpu(dabr_data, cpu) = kdabr;
+	else
+		per_cpu(dabr_data, cpu) = current->thread.dabr;
+
+	stepped = emulate_step(regs, regs->nip);
+	/*
+	 * Single-step the causative instruction manually if
+	 * emulate_step() could not execute it
+	 */
+	if (stepped == 0) {
+		regs->msr |= MSR_SE;
+		goto out;
+	}
+
+	set_dabr(per_cpu(dabr_data, cpu));
+out:
+	/* Enable pre-emption only if single-stepping is finished */
+	if (stepped)
+		put_cpu_no_resched();
+	return rc;
+}
+
+/*
+ * Handle single-step exceptions following a DABR hit.
+ */
+int __kprobes single_step_dabr_instruction(struct die_args *args)
+{
+	struct pt_regs *regs = args->regs;
+	int cpu = get_cpu();
+	int ret = NOTIFY_DONE;
+	siginfo_t info;
+	unsigned long this_dabr_data = per_cpu(dabr_data, cpu);
+
+	/*
+	 * Check if we are single-stepping as a result of a
+	 * previous HW Breakpoint exception
+	 */
+	if (this_dabr_data == 0)
+		goto out;
+
+	regs->msr &= ~MSR_SE;
+	/* Deliver signal to user-space */
+	if (this_dabr_data < TASK_SIZE) {
+		info.si_signo = SIGTRAP;
+		info.si_errno = 0;
+		info.si_code = TRAP_HWBKPT;
+		info.si_addr = (void __user *)(per_cpu(dabr_data, cpu));
+		force_sig_info(SIGTRAP, &info, current);
+	}
+
+	set_dabr(this_dabr_data);
+	per_cpu(dabr_data, cpu) = 0;
+	ret = NOTIFY_STOP;
+	put_cpu_no_resched();
+
+out:
+	put_cpu_no_resched();
+	return ret;
+}
+
+/*
+ * Handle debug exception notifications.
+ */
+int __kprobes hw_breakpoint_exceptions_notify(
+		struct notifier_block *unused, unsigned long val, void *data)
+{
+	int ret = NOTIFY_DONE;
+
+	switch (val) {
+	case DIE_DABR_MATCH:
+		ret = hw_breakpoint_handler(data);
+		break;
+	case DIE_SSTEP:
+		ret = single_step_dabr_instruction(data);
+		break;
+	}
+
+	return ret;
+}
Index: linux-2.6-tip.hbkpt/arch/powerpc/include/asm/hw_breakpoint.h
===================================================================
--- /dev/null
+++ linux-2.6-tip.hbkpt/arch/powerpc/include/asm/hw_breakpoint.h
@@ -0,0 +1,52 @@
+#ifndef	_PPC64_HW_BREAKPOINT_H
+#define	_PPC64_HW_BREAKPOINT_H
+
+#ifdef	__KERNEL__
+#define	__ARCH_HW_BREAKPOINT_H
+
+struct arch_hw_breakpoint {
+	char		*name; /* Contains name of the symbol to set bkpt */
+	unsigned long	address;
+	u8		type;
+};
+
+#include <linux/kdebug.h>
+#include <asm/reg.h>
+#include <asm-generic/hw_breakpoint.h>
+
+#define HW_BREAKPOINT_READ DABR_DATA_READ
+#define HW_BREAKPOINT_WRITE DABR_DATA_WRITE
+#define HW_BREAKPOINT_RW DABR_DATA_RW
+
+#define HW_BREAKPOINT_ALIGN 0x7
+#define HW_BREAKPOINT_LEN 4
+
+extern struct hw_breakpoint *hbp_kernel[HB_NUM];
+extern unsigned int hbp_user_refcount[HB_NUM];
+
+/*
+ * Ptrace support: breakpoint trigger routine.
+ */
+extern int __modify_user_hw_breakpoint(int pos, struct task_struct *tsk,
+			struct hw_breakpoint *bp);
+
+extern void arch_install_thread_hw_breakpoint(struct task_struct *tsk);
+extern void arch_uninstall_thread_hw_breakpoint(void);
+extern int arch_check_va_in_userspace(unsigned long va, u8 hbp_len);
+extern int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len);
+extern int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
+						struct task_struct *tsk);
+extern void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk);
+extern void arch_flush_thread_hw_breakpoint(struct task_struct *tsk);
+extern void arch_update_kernel_hw_breakpoint(void *);
+extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused,
+				     unsigned long val, void *data);
+
+extern void flush_thread_hw_breakpoint(struct task_struct *tsk);
+extern int copy_thread_hw_breakpoint(struct task_struct *tsk,
+		struct task_struct *child, unsigned long clone_flags);
+extern void switch_to_thread_hw_breakpoint(struct task_struct *tsk);
+
+#endif	/* __KERNEL__ */
+#endif	/* _PPC64_HW_BREAKPOINT_H */
+
Index: linux-2.6-tip.hbkpt/arch/powerpc/include/asm/processor.h
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/include/asm/processor.h
+++ linux-2.6-tip.hbkpt/arch/powerpc/include/asm/processor.h
@@ -177,6 +177,7 @@ struct thread_struct {
 #ifdef CONFIG_PPC64
 	unsigned long	start_tb;	/* Start purr when proc switched in */
 	unsigned long	accum_tb;	/* Total accumilated purr for process */
+	struct hw_breakpoint *hbp[HB_NUM];
 #endif
 	unsigned long	dabr;		/* Data address breakpoint register */
 #ifdef CONFIG_ALTIVEC
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/ptrace.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
@@ -37,6 +37,9 @@
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
+#ifdef CONFIG_PPC64
+#include <asm/hw_breakpoint.h>
+#endif
 
 /*
  * does not yet catch signals sent when the child dies.
@@ -735,9 +738,22 @@ void user_disable_single_step(struct tas
 	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
 }
 
+static void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
+{
+	/*
+	 * The SIGTRAP signal is generated automatically for us in do_dabr().
+	 * We don't have to do anything here
+	 */
+}
+
 int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 			       unsigned long data)
 {
+#ifdef CONFIG_PPC64
+	struct thread_struct *thread = &(task->thread);
+	struct hw_breakpoint *bp;
+	int ret;
+#endif
 	/* For ppc64 we support one DABR and no IABR's at the moment (ppc64).
 	 *  For embedded processors we support one DAC and no IAC's at the
 	 *  moment.
@@ -767,6 +783,38 @@ int ptrace_set_debugreg(struct task_stru
 	if (data && !(data & DABR_TRANSLATION))
 		return -EIO;
 
+#ifdef CONFIG_PPC64
+	bp = thread->hbp[0];
+	if ((data & ~0x7UL) == 0) {
+		if (bp) {
+			unregister_user_hw_breakpoint(task, bp);
+			kfree(bp);
+			thread->hbp[0] = NULL;
+		}
+		return 0;
+	}
+
+	if (bp) {
+		bp->info.type = data & 0x3UL;
+		task->thread.dabr = bp->info.address =
+						(data & ~HW_BREAKPOINT_ALIGN);
+		return __modify_user_hw_breakpoint(0, task, bp);
+	}
+	bp = kzalloc(sizeof(struct hw_breakpoint), GFP_KERNEL);
+	if (!bp)
+		return -ENOMEM;
+
+	/* Store the type of breakpoint */
+	bp->info.type = data & 0x3UL;
+	bp->triggered = ptrace_triggered;
+	task->thread.dabr = bp->info.address = (data & ~HW_BREAKPOINT_ALIGN);
+
+	ret = register_user_hw_breakpoint(task, bp);
+	if (ret)
+		return ret;
+	set_tsk_thread_flag(task, TIF_DEBUG);
+#endif /* CONFIG_PPC64 */
+
 	/* Move contents to the DABR register */
 	task->thread.dabr = data;
 
Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/process.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/process.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/process.c
@@ -50,6 +50,7 @@
 #include <asm/syscalls.h>
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
+#include <asm/hw_breakpoint.h>
 #endif
 #include <linux/kprobes.h>
 #include <linux/kdebug.h>
@@ -254,8 +255,10 @@ void do_dabr(struct pt_regs *regs, unsig
 			11, SIGSEGV) == NOTIFY_STOP)
 		return;
 
+#ifndef CONFIG_PPC64
 	if (debugger_dabr_match(regs))
 		return;
+#endif
 
 	/* Clear the DAC and struct entries.  One shot trigger */
 #if defined(CONFIG_BOOKE)
@@ -372,8 +375,13 @@ struct task_struct *__switch_to(struct t
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC64
+		if (unlikely(test_tsk_thread_flag(new, TIF_DEBUG)))
+			switch_to_thread_hw_breakpoint(new);
+#else
 	if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
 		set_dabr(new->thread.dabr);
+#endif /* CONFIG_PPC64 */
 
 #if defined(CONFIG_BOOKE)
 	/* If new thread DAC (HW breakpoint) is the same then leave it */
@@ -550,6 +558,10 @@ void show_regs(struct pt_regs * regs)
 void exit_thread(void)
 {
 	discard_lazy_cpu_state();
+#ifdef CONFIG_PPC64
+	if (unlikely(test_tsk_thread_flag(current, TIF_DEBUG)))
+		flush_thread_hw_breakpoint(current);
+#endif /* CONFIG_PPC64 */
 }
 
 void flush_thread(void)
@@ -605,6 +617,9 @@ int copy_thread(unsigned long clone_flag
 	struct pt_regs *childregs, *kregs;
 	extern void ret_from_fork(void);
 	unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+#ifdef CONFIG_PPC64
+	struct task_struct *tsk = current;
+#endif
 
 	CHECK_FULL_REGS(regs);
 	/* Copy registers */
@@ -672,6 +687,9 @@ int copy_thread(unsigned long clone_flag
 	 * function.
  	 */
 	kregs->nip = *((unsigned long *)ret_from_fork);
+
+	if (unlikely(test_tsk_thread_flag(tsk, TIF_DEBUG)))
+		copy_thread_hw_breakpoint(tsk, p, clone_flags);
 #else
 	kregs->nip = (unsigned long)ret_from_fork;
 #endif
Index: linux-2.6-tip.hbkpt/samples/hw_breakpoint/data_breakpoint.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/samples/hw_breakpoint/data_breakpoint.c
+++ linux-2.6-tip.hbkpt/samples/hw_breakpoint/data_breakpoint.c
@@ -54,6 +54,10 @@ static int __init hw_break_module_init(v
 	sample_hbp.info.type = HW_BREAKPOINT_WRITE;
 	sample_hbp.info.len = HW_BREAKPOINT_LEN_4;
 #endif /* CONFIG_X86 */
+#ifdef CONFIG_PPC64
+	sample_hbp.info.name = ksym_name;
+	sample_hbp.info.type = DABR_DATA_WRITE;
+#endif /* CONFIG_PPC64 */
 
 	sample_hbp.triggered = (void *)sample_hbp_handler;
 
Index: linux-2.6-tip.hbkpt/arch/powerpc/include/asm/thread_info.h
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/include/asm/thread_info.h
+++ linux-2.6-tip.hbkpt/arch/powerpc/include/asm/thread_info.h
@@ -114,6 +114,7 @@ static inline struct thread_info *curren
 #define TIF_FREEZE		14	/* Freezing for suspend */
 #define TIF_RUNLATCH		15	/* Is the runlatch enabled? */
 #define TIF_ABI_PENDING		16	/* 32/64 bit switch needed */
+#define TIF_DEBUG		17	/* uses debug registers */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -132,6 +133,7 @@ static inline struct thread_info *curren
 #define _TIF_FREEZE		(1<<TIF_FREEZE)
 #define _TIF_RUNLATCH		(1<<TIF_RUNLATCH)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
+#define _TIF_DEBUG		(1<<TIF_DEBUG)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 #define _TIF_USER_WORK_MASK	(_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
Index: linux-2.6-tip.hbkpt/arch/powerpc/include/asm/reg.h
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/include/asm/reg.h
+++ linux-2.6-tip.hbkpt/arch/powerpc/include/asm/reg.h
@@ -184,9 +184,11 @@
 #define   CTRL_TE	0x00c00000	/* thread enable */
 #define   CTRL_RUNLATCH	0x1
 #define SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
+#define   HB_NUM	1	/* Number of physical HW breakpoint registers */
 #define   DABR_TRANSLATION	(1UL << 2)
 #define   DABR_DATA_WRITE	(1UL << 1)
 #define   DABR_DATA_READ	(1UL << 0)
+#define   DABR_DATA_RW		(3UL << 0)
 #define SPRN_DABR2	0x13D	/* e300 */
 #define SPRN_DABRX	0x3F7	/* Data Address Breakpoint Register Extension */
 #define   DABRX_USER	(1UL << 0)
Index: linux-2.6-tip.hbkpt/arch/powerpc/mm/fault.c
===================================================================
--- linux-2.6-tip.hbkpt.orig/arch/powerpc/mm/fault.c
+++ linux-2.6-tip.hbkpt/arch/powerpc/mm/fault.c
@@ -137,6 +137,12 @@ int __kprobes do_page_fault(struct pt_re
 		error_code &= 0x48200000;
 	else
 		is_write = error_code & DSISR_ISSTORE;
+
+	if (error_code & DSISR_DABRMATCH) {
+		/* DABR match */
+		do_dabr(regs, address, error_code);
+		return 0;
+	}
 #else
 	is_write = error_code & ESR_DST;
 #endif /* CONFIG_4xx || CONFIG_BOOKE */
@@ -151,14 +157,6 @@ int __kprobes do_page_fault(struct pt_re
 	if (!user_mode(regs) && (address >= TASK_SIZE))
 		return SIGSEGV;
 
-#if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE))
-  	if (error_code & DSISR_DABRMATCH) {
-		/* DABR match */
-		do_dabr(regs, address, error_code);
-		return 0;
-	}
-#endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
-
 	if (in_atomic() || mm == NULL) {
 		if (!user_mode(regs))
 			return SIGSEGV;

^ permalink raw reply

* [PATCH] aoa: remove driver_data direct access of struct device
From: Roel Kluin @ 2009-05-11 19:54 UTC (permalink / raw)
  To: johannes; +Cc: linuxppc-dev, alsa-devel, lkml

To avoid direct access to the driver_data pointer in struct device, the
functions dev_get_drvdata() and dev_set_drvdata() should be used.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index fbf5c93..586965f 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -1037,7 +1037,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 	}
 	ldev->selfptr_headphone.ptr = ldev;
 	ldev->selfptr_lineout.ptr = ldev;
-	sdev->ofdev.dev.driver_data = ldev;
+	dev_set_drvdata(&sdev->ofdev.dev, ldev);
 	list_add(&ldev->list, &layouts_list);
 	layouts_list_items++;
 
@@ -1081,7 +1081,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 
 static int aoa_fabric_layout_remove(struct soundbus_dev *sdev)
 {
-	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+	struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev);
 	int i;
 
 	for (i=0; i<MAX_CODECS_PER_BUS; i++) {
@@ -1114,7 +1114,7 @@ static int aoa_fabric_layout_remove(struct soundbus_dev *sdev)
 #ifdef CONFIG_PM
 static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state)
 {
-	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+	struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev);
 
 	if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
 		ldev->gpio.methods->all_amps_off(&ldev->gpio);
@@ -1124,7 +1124,7 @@ static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t sta
 
 static int aoa_fabric_layout_resume(struct soundbus_dev *sdev)
 {
-	struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
+	struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev);
 
 	if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
 		ldev->gpio.methods->all_amps_restore(&ldev->gpio);
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/core.c
index 418c84c..4e3b819 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/core.c
@@ -358,14 +358,14 @@ static int i2sbus_probe(struct macio_dev* dev, const struct of_device_id *match)
 		return -ENODEV;
 	}
 
-	dev->ofdev.dev.driver_data = control;
+	dev_set_drvdata(&dev->ofdev.dev, control);
 
 	return 0;
 }
 
 static int i2sbus_remove(struct macio_dev* dev)
 {
-	struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
 	struct i2sbus_dev *i2sdev, *tmp;
 
 	list_for_each_entry_safe(i2sdev, tmp, &control->list, item)
@@ -377,7 +377,7 @@ static int i2sbus_remove(struct macio_dev* dev)
 #ifdef CONFIG_PM
 static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
 {
-	struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
 	struct codec_info_item *cii;
 	struct i2sbus_dev* i2sdev;
 	int err, ret = 0;
@@ -407,7 +407,7 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
 
 static int i2sbus_resume(struct macio_dev* dev)
 {
-	struct i2sbus_control *control = dev->ofdev.dev.driver_data;
+	struct i2sbus_control *control = dev_get_drvdata(&dev->ofdev.dev);
 	struct codec_info_item *cii;
 	struct i2sbus_dev* i2sdev;
 	int err, ret = 0;

^ permalink raw reply related

* Re: [PATCH] fix sata_sil compilation on non-DMI platforms
From: Alan Cox @ 2009-05-11 18:44 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: linux-ide, Konstantinos Margaritis, linuxppc-dev,
	Lennert Buytenhek, Lennart Sorensen, rmk
In-Reply-To: <4A086A76.3090008@garzik.org>

> Ideally the DMI subsystem should be provided wrappers for platforms 
> without DMI, rendering patches like this unnecessary.

Interesting question - is the PPC OpenFirmware machine information
mappable onto the DMI space ? or the various static bits of name
information in the various ARM and the like machine descriptions.

If not which bits are similar enough we could replace dmi at the high
level with an abstract interface for system/vendor/... that was ?

(

^ permalink raw reply

* [PATCH] ps3: remove driver_data direct access of struct device
From: Roel Kluin @ 2009-05-11 19:34 UTC (permalink / raw)
  To: geoffrey.levand, Geert.Uytterhoeven; +Cc: linuxppc-dev, cbe-oss-dev, lkml

To avoid direct access to the driver_data pointer in struct device, the
functions dev_get_drvdata() and dev_set_drvdata() should be used.

Signed-off-by: Roel Kluin <roel.kluin@gmail.com>
---
Please review. especially note that I removed a

kfree(dev->sbd.core.driver_data);

Is that correct?

 arch/powerpc/include/asm/ps3.h |    4 ++--
 drivers/char/ps3flash.c        |   11 +++++------
 drivers/scsi/ps3rom.c          |   10 +++++-----
 drivers/video/ps3fb.c          |    6 +++---
 4 files changed, 15 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h
index cdb6fd8..a55717e 100644
--- a/arch/powerpc/include/asm/ps3.h
+++ b/arch/powerpc/include/asm/ps3.h
@@ -421,12 +421,12 @@ static inline struct ps3_system_bus_driver *
 static inline void ps3_system_bus_set_driver_data(
 	struct ps3_system_bus_device *dev, void *data)
 {
-	dev->core.driver_data = data;
+	dev_set_drvdata(&dev->core, data);
 }
 static inline void *ps3_system_bus_get_driver_data(
 	struct ps3_system_bus_device *dev)
 {
-	return dev->core.driver_data;
+	return dev_get_drvdata(&dev->core);
 }
 
 /* These two need global scope for get_dma_ops(). */
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index afbe456..6083032 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -108,7 +108,7 @@ static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
 			     loff_t *pos)
 {
 	struct ps3_storage_device *dev = ps3flash_dev;
-	struct ps3flash_private *priv = dev->sbd.core.driver_data;
+	struct ps3flash_private *priv = dev_get_drvdata(&dev->sbd.core);
 	u64 size, start_sector, end_sector, offset;
 	ssize_t sectors_read;
 	size_t remaining, n;
@@ -173,7 +173,7 @@ static ssize_t ps3flash_write(struct file *file, const char __user *buf,
 			      size_t count, loff_t *pos)
 {
 	struct ps3_storage_device *dev = ps3flash_dev;
-	struct ps3flash_private *priv = dev->sbd.core.driver_data;
+	struct ps3flash_private *priv = dev_get_drvdata(&dev->sbd.core);
 	u64 size, chunk_sectors, start_write_sector, end_write_sector,
 	    end_read_sector, start_read_sector, head, tail, offset;
 	ssize_t res;
@@ -366,7 +366,7 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
 		goto fail;
 	}
 
-	dev->sbd.core.driver_data = priv;
+	dev_set_drvdata(&dev->sbd.core, priv);
 	mutex_init(&priv->mutex);
 
 	dev->bounce_size = ps3flash_bounce_buffer.size;
@@ -392,7 +392,7 @@ fail_teardown:
 	ps3stor_teardown(dev);
 fail_free_priv:
 	kfree(priv);
-	dev->sbd.core.driver_data = NULL;
+	dev_set_drvdata(&dev->sbd.core, NULL);
 fail:
 	ps3flash_dev = NULL;
 	return error;
@@ -404,8 +404,7 @@ static int ps3flash_remove(struct ps3_system_bus_device *_dev)
 
 	misc_deregister(&ps3flash_misc);
 	ps3stor_teardown(dev);
-	kfree(dev->sbd.core.driver_data);
-	dev->sbd.core.driver_data = NULL;
+	dev_set_drvdata(&dev->sbd.core, NULL);
 	ps3flash_dev = NULL;
 	return 0;
 }
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index ca0dd33..f2f840a 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -299,7 +299,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data)
 		return IRQ_HANDLED;
 	}
 
-	host = dev->sbd.core.driver_data;
+	host = dev_get_drvdata(&dev->sbd.core);
 	priv = shost_priv(host);
 	cmd = priv->curr_cmd;
 
@@ -387,7 +387,7 @@ static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
 	}
 
 	priv = shost_priv(host);
-	dev->sbd.core.driver_data = host;
+	dev_set_drvdata(&dev->sbd.core, host);
 	priv->dev = dev;
 
 	/* One device/LUN per SCSI bus */
@@ -407,7 +407,7 @@ static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
 
 fail_host_put:
 	scsi_host_put(host);
-	dev->sbd.core.driver_data = NULL;
+	dev_set_drvdata(&dev->sbd.core, NULL);
 fail_teardown:
 	ps3stor_teardown(dev);
 fail_free_bounce:
@@ -418,12 +418,12 @@ fail_free_bounce:
 static int ps3rom_remove(struct ps3_system_bus_device *_dev)
 {
 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
-	struct Scsi_Host *host = dev->sbd.core.driver_data;
+	struct Scsi_Host *host = dev_get_drvdata(&dev->sbd.core);
 
 	scsi_remove_host(host);
 	ps3stor_teardown(dev);
 	scsi_host_put(host);
-	dev->sbd.core.driver_data = NULL;
+	dev_set_drvdata(&dev->sbd.core, NULL);
 	kfree(dev->bounce_buf);
 	return 0;
 }
diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c
index e00c1df..55f4250 100644
--- a/drivers/video/ps3fb.c
+++ b/drivers/video/ps3fb.c
@@ -1210,7 +1210,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev)
 	if (retval < 0)
 		goto err_fb_dealloc;
 
-	dev->core.driver_data = info;
+	dev_set_drvdata(&dev->core, info);
 
 	dev_info(info->device, "%s %s, using %u KiB of video memory\n",
 		 dev_driver_string(info->dev), dev_name(info->dev),
@@ -1248,7 +1248,7 @@ err:
 static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 {
 	int status;
-	struct fb_info *info = dev->core.driver_data;
+	struct fb_info *info = dev_get_drvdata(&dev->core);
 
 	dev_dbg(&dev->core, " -> %s:%d\n", __func__, __LINE__);
 
@@ -1268,7 +1268,7 @@ static int ps3fb_shutdown(struct ps3_system_bus_device *dev)
 		unregister_framebuffer(info);
 		fb_dealloc_cmap(&info->cmap);
 		framebuffer_release(info);
-		info = dev->core.driver_data = NULL;
+		info = dev_set_drvdata(&dev->core, NULL);
 	}
 	iounmap((u8 __force __iomem *)ps3fb.dinfo);
 

^ permalink raw reply related

* Re: question about softirqs
From: Chris Friesen @ 2009-05-11 18:25 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev, paulus
In-Reply-To: <20090508.234815.127227651.davem@davemloft.net>

David Miller wrote:

> You know, for networking over loopback (one of the only real cases
> that even matters, if we get a hard interrupt then the return from
> that would process any softints), we probably make out just fine
> anyways.  As long as we hit a local_bh_enable() (and in the return
> path from device transmit that's exceedingly likely as all of the
> networking locking is BH safe) we'll run the softints from that and
> thus long before we get to syscall return.

What about the issue I raised earlier?  (I don't think you were copied
at that point.)

Suppose I have a SCHED_FIFO task spinning on recvmsg() with MSG_DONTWAIT
set (and maybe doing other stuff if there are no messages). In this
case, schedule() would re-run the spinning task rather than running
ksoftirqd. This could prevent any incoming packets from actually being
sent up the stack until we get a real hardware interrupt--which could be
a whole jiffy if interrupt mitigation is enabled in the net device.
(And maybe longer if NOHZ is enabled.)

Chris

^ permalink raw reply

* Re: [PATCH 1/3 v3] Added support for Designware SATA controller driver
From: Jeff Garzik @ 2009-05-11 18:23 UTC (permalink / raw)
  To: Feng Kan; +Cc: Mark Miesfeld, linuxppc-dev, linux-ide
In-Reply-To: <1241632174-2570-1-git-send-email-fkan@amcc.com>

Feng Kan wrote:
> Signed-off-by: Feng Kan <fkan@amcc.com>
> Signed-off-by: Mark Miesfeld <miesfeld@gmail.com>
> ---
>  drivers/ata/Kconfig    |   10 +
>  drivers/ata/Makefile   |    1 +
>  drivers/ata/sata_dwc.c | 2053 ++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 2064 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/ata/sata_dwc.c
> 
> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> index 0bcf264..c3d0b24 100644
> --- a/drivers/ata/Kconfig
> +++ b/drivers/ata/Kconfig
> @@ -72,6 +72,16 @@ config SATA_FSL
>  
>  	  If unsure, say N.
>  
> +config SATA_DWC
> +	tristate "DesignWare Cores SATA support"
> + 	depends on 460EX
> +	help
> +	  This option enables support for the Synopsys DesignWare Cores SATA
> +	  controller.
> +	  It can be found on the AMCC 460EX.
> +
> +	  If unsure, say N.
> +
>  config ATA_SFF
>  	bool "ATA SFF support"
>  	default y
> diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
> index 7f1ecf9..3d41fc7 100644
> --- a/drivers/ata/Makefile
> +++ b/drivers/ata/Makefile
> @@ -18,6 +18,7 @@ obj-$(CONFIG_SATA_MV)		+= sata_mv.o
>  obj-$(CONFIG_SATA_INIC162X)	+= sata_inic162x.o
>  obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
>  obj-$(CONFIG_SATA_FSL)		+= sata_fsl.o
> +obj-$(CONFIG_SATA_DWC)          += sata_dwc.o
>  
>  obj-$(CONFIG_PATA_ALI)		+= pata_ali.o
>  obj-$(CONFIG_PATA_AMD)		+= pata_amd.o
> diff --git a/drivers/ata/sata_dwc.c b/drivers/ata/sata_dwc.c
> new file mode 100644
> index 0000000..672f91f
> --- /dev/null
> +++ b/drivers/ata/sata_dwc.c
> @@ -0,0 +1,2053 @@
> +/*
> + * drivers/ata/sata_dwc.c
> + *
> + * Synopsys DesignWare Cores (DWC) SATA host driver
> + *
> + * Author: Mark Miesfeld <mmiesfeld@amcc.com>
> + *
> + * Ported from 2.6.19.2 to 2.6.25/26 by Stefan Roese <sr@denx.de>
> + * Copyright 2008 DENX Software Engineering
> + *
> + * Based on versions provided by AMCC and Synopsys which are:
> + *          Copyright 2006 Applied Micro Circuits Corporation
> + *          COPYRIGHT (C) 2005  SYNOPSYS, INC.  ALL RIGHTS RESERVED
> + *
> + * This program is free software; you can redistribute  it and/or modify it
> + * under  the terms of  the GNU General  Public License as published by the
> + * Free Software Foundation;  either version 2 of the  License, or (at your
> + * option) any later version.
> + *
> + */
> +#ifdef CONFIG_SATA_DWC_DEBUG
> +#define DEBUG
> +#endif
> +
> +#ifdef CONFIG_SATA_DWC_VDEBUG
> +#define VERBOSE_DEBUG
> +#define DEBUG_NCQ
> +#endif
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/device.h>
> +#include <linux/platform_device.h>
> +#include <linux/libata.h>
> +
> +#include <scsi/scsi_host.h>
> +#include <scsi/scsi_cmnd.h>
> +
> +#define DRV_NAME        "sata-dwc"
> +#define DRV_VERSION     "1.0"
> +
> +/* SATA DMA driver Globals */
> +#define DMA_NUM_CHANS			1
> +#define DMA_NUM_CHAN_REGS		8
> +
> +/* SATA DMA Register definitions */
> +#define AHB_DMA_BRST_DFLT		64	/* 16 data items burst length */
> +
> +struct dmareg {
> +	u32 low;		/* Low bits 0-31 */
> +	u32 high;		/* High bits 32-63 */
> +};
> +
> +/* DMA Per Channel registers */
> +
> +struct dma_chan_regs {
> +	struct dmareg sar;	/* Source Address */
> +	struct dmareg dar;	/* Destination address */
> +	struct dmareg llp;	/* Linked List Pointer */
> +	struct dmareg ctl;	/* Control */
> +	struct dmareg sstat;	/* Source Status not implemented in core */
> +	struct dmareg dstat;	/* Destination Status not implemented in core */
> +	struct dmareg sstatar;	/* Source Status Address not impl in core */
> +	struct dmareg dstatar;	/* Destination Status Address not implemented */
> +	struct dmareg cfg;	/* Config */
> +	struct dmareg sgr;	/* Source Gather */
> +	struct dmareg dsr;	/* Destination Scatter */
> +};
> +
> +/* Generic Interrupt Registers */
> +struct dma_interrupt_regs {
> +	struct dmareg tfr;	/* Transfer Interrupt */
> +	struct dmareg block;	/* Block Interrupt */
> +	struct dmareg srctran;	/* Source Transfer Interrupt */
> +	struct dmareg dsttran;	/* Dest Transfer Interrupt */
> +	struct dmareg error;	/* Error */
> +};
> +
> +struct ahb_dma_regs {
> +	struct dma_chan_regs	chan_regs[DMA_NUM_CHAN_REGS];
> +	struct dma_interrupt_regs interrupt_raw;	/* Raw Interrupt */
> +	struct dma_interrupt_regs interrupt_status;	/* Interrupt Status */
> +	struct dma_interrupt_regs interrupt_mask;	/* Interrupt Mask */
> +	struct dma_interrupt_regs interrupt_clear;	/* Interrupt Clear */
> +	struct dmareg		statusInt;		/* Interrupt combined */
> +	struct dmareg		rq_srcreg;		/* Src Trans Req */
> +	struct dmareg		rq_dstreg;		/* Dst Trans Req */
> +	struct dmareg		rq_sgl_srcreg;		/* Sngl Src Trans Req */
> +	struct dmareg		rq_sgl_dstreg;		/* Sngl Dst Trans Req */
> +	struct dmareg		rq_lst_srcreg;		/* Last Src Trans Req */
> +	struct dmareg		rq_lst_dstreg;		/* Last Dst Trans Req */
> +	struct dmareg		dma_cfg;		/* DMA Config */
> +	struct dmareg		dma_chan_en;		/* DMA Channel Enable */
> +	struct dmareg		dma_id;			/* DMA ID */
> +	struct dmareg		dma_test;		/* DMA Test */
> +	struct dmareg		res1;			/* reserved */
> +	struct dmareg		res2;			/* reserved */
> +
> +	/* DMA Comp Params
> +	 * Param 6 = dma_param[0], Param 5 = dma_param[1],
> +	 * Param 4 = dma_param[2] ...
> +	 */
> +	struct dmareg		dma_params[6];
> +};
> +
> +/* Data structure for linked list item */
> +struct lli {
> +	u32		sar;		/* Source Address */
> +	u32		dar;		/* Destination address */
> +	u32		llp;		/* Linked List Pointer */
> +	struct dmareg	ctl;		/* Control */
> +	struct dmareg	dstat;		/* Destination Status */
> +};
> +
> +#define SATA_DWC_DMAC_LLI_SZ		(sizeof(struct lli))
> +#define SATA_DWC_DMAC_LLI_NUM		256
> +#define SATA_DWC_DMAC_TWIDTH_BYTES	4
> +#define SATA_DWC_DMAC_LLI_TBL_SZ	\
> +	(SATA_DWC_DMAC_LLI_SZ * SATA_DWC_DMAC_LLI_NUM)
> +#define SATA_DWC_DMAC_CTRL_TSIZE_MAX	\
> +	(0x00000800 * SATA_DWC_DMAC_TWIDTH_BYTES)
> +
> +/* DMA Register Operation Bits */
> +#define DMA_EN			0x00000001		/* Enable AHB DMA */
> +#define DMA_CHANNEL(ch)		(0x00000001 << (ch))	/* Select channel */
> +#define DMA_ENABLE_CHAN(ch)	((0x00000001 << (ch)) |			\
> +				 ((0x000000001 << (ch)) << 8))
> +#define DMA_DISABLE_CHAN(ch)	(0x00000000 | ((0x000000001 << (ch)) << 8))
> +
> +/* Channel Control Register */
> +#define DMA_CTL_BLK_TS(size)	((size) & 0x000000FFF)	/* Blk Transfer size */
> +#define DMA_CTL_LLP_SRCEN	0x10000000	/* Blk chain enable Src */
> +#define DMA_CTL_LLP_DSTEN	0x08000000	/* Blk chain enable Dst */
> +/*
> + * This define is used to set block chaining disabled in the control low
> + * register.  It is already in little endian format so it can be &'d dirctly.
> + * It is essentially: cpu_to_le32(~(DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN))
> + */
> +#define DMA_CTL_LLP_DISABLE_LE32 0xffffffe7
> +#define DMA_CTL_SMS(num)	((num & 0x3) << 25)	/*Src Master Select*/
> +#define DMA_CTL_DMS(num)	((num & 0x3) << 23)	/*Dst Master Select*/
> +#define DMA_CTL_TTFC(type)	((type & 0x7) << 20)	/*Type&Flow cntr*/
> +#define DMA_CTL_TTFC_P2M_DMAC	0x00000002		/*Per mem,DMAC cntr*/
> +#define DMA_CTL_TTFC_M2P_PER	0x00000003		/*Mem per,peri cntr*/
> +#define DMA_CTL_SRC_MSIZE(size)	((size & 0x7) << 14)	/*Src Burst Len*/
> +#define DMA_CTL_DST_MSIZE(size)	((size & 0x7) << 11)	/*Dst Burst Len*/
> +#define DMA_CTL_SINC_INC	0x00000000		/*Src addr incr*/
> +#define DMA_CTL_SINC_DEC	0x00000200
> +#define DMA_CTL_SINC_NOCHANGE	0x00000400
> +#define DMA_CTL_DINC_INC	0x00000000		/*Dst addr incr*/
> +#define DMA_CTL_DINC_DEC	0x00000080
> +#define DMA_CTL_DINC_NOCHANGE	0x00000100
> +#define DMA_CTL_SRC_TRWID(size)	((size & 0x7) << 4)	/*Src Trnsfr Width*/
> +#define DMA_CTL_DST_TRWID(size)	((size & 0x7) << 1)	/*Dst Trnsfr Width*/
> +#define DMA_CTL_INT_EN		0x00000001		/*Interrupt Enable*/
> +
> +/* Channel Configuration Register high bits */
> +#define DMA_CFG_FCMOD_REQ	0x00000001		/*Flow cntrl req*/
> +#define DMA_CFG_PROTCTL		(0x00000003 << 2)	/*Protection cntrl*/
> +
> +/* Channel Configuration Register low bits */
> +#define DMA_CFG_RELD_DST	0x80000000		/*Reload Dst/Src Addr*/
> +#define DMA_CFG_RELD_SRC	0x40000000
> +#define DMA_CFG_HS_SELSRC	0x00000800		/*SW hndshk Src/Dst*/
> +#define DMA_CFG_HS_SELDST	0x00000400
> +#define DMA_CFG_FIFOEMPTY       (0x00000001 << 9)	/*FIFO Empty bit*/
> +
> +/* Assign hardware handshaking interface (x) to dst / sre peripheral */
> +#define DMA_CFG_HW_HS_DEST(int_num)	((int_num & 0xF) << 11)
> +#define DMA_CFG_HW_HS_SRC(int_num)	((int_num & 0xF) << 7)
> +
> +/* Channel Linked List Pointer Register */
> +#define DMA_LLP_LMS(addr, master)	(((addr) & 0xfffffffc) | (master))
> +#define DMA_LLP_AHBMASTER1		0	/* List Master Select */
> +#define DMA_LLP_AHBMASTER2		1
> +
> +#define SATA_DWC_MAX_PORTS	1
> +
> +#define SATA_DWC_SCR_OFFSET	0x24
> +#define SATA_DWC_REG_OFFSET	0x64

Use 'enum' rather than pre-processor #defines, for creating constants, 
as we do in the rest of libata.  This gives more debugger and compiler 
symbol visibility, and makes pre-processed source much easier to read.


> +/* DWC SATA Registers */
> +struct sata_dwc_regs {
> +	u32 fptagr;		/* 1st party DMA tag */
> +	u32 fpbor;		/* 1st party DMA buffer offset */
> +	u32 fptcr;		/* 1st party DMA Xfr count */
> +	u32 dmacr;		/* DMA Control */
> +	u32 dbtsr;		/* DMA Burst Transac size */
> +	u32 intpr;		/* Interrupt Pending */
> +	u32 intmr;		/* Interrupt Mask */
> +	u32 errmr;		/* Error Mask */
> +	u32 llcr;		/* Link Layer Control */
> +	u32 phycr;		/* PHY Control */
> +	u32 physr;		/* PHY Status */
> +	u32 rxbistpd;		/* Recvd BIST pattern def register */
> +	u32 rxbistpd1;		/* Recvd BIST data dword1 */
> +	u32 rxbistpd2;		/* Recvd BIST pattern data dword2 */
> +	u32 txbistpd;		/* Trans BIST pattern def register */
> +	u32 txbistpd1;		/* Trans BIST data dword1 */
> +	u32 txbistpd2;		/* Trans BIST data dword2 */
> +	u32 bistcr;		/* BIST Control Register */
> +	u32 bistfctr;		/* BIST FIS Count Register */
> +	u32 bistsr;		/* BIST Status Register */
> +	u32 bistdecr;		/* BIST Dword Error count register */
> +	u32 res[15];		/* Reserved locations */
> +	u32 testr;		/* Test Register */
> +	u32 versionr;		/* Version Register */
> +	u32 idr;		/* ID Register */
> +	u32 unimpl[192];	/* Unimplemented */
> +	u32 dmadr[256];	/* FIFO Locations in DMA Mode */
> +};
> +
> +#define SCR_SCONTROL_DET_ENABLE		0x00000001
> +#define SCR_SSTATUS_DET_PRESENT		0x00000001
> +#define SCR_SERROR_DIAG_X		0x04000000
> +
> +/* DWC SATA Register Operations */
> +#define	SATA_DWC_TXFIFO_DEPTH		0x01FF
> +#define	SATA_DWC_RXFIFO_DEPTH		0x01FF
> +
> +#define SATA_DWC_DMACR_TMOD_TXCHEN	0x00000004
> +#define	SATA_DWC_DMACR_TXCHEN		(0x00000001 | \
> +						SATA_DWC_DMACR_TMOD_TXCHEN)
> +#define	SATA_DWC_DMACR_RXCHEN		(0x00000002 | \
> +						SATA_DWC_DMACR_TMOD_TXCHEN)
> +#define SATA_DWC_DMACR_TX_CLEAR(v)	(((v) & ~SATA_DWC_DMACR_TXCHEN) | \
> +						SATA_DWC_DMACR_TMOD_TXCHEN)
> +#define SATA_DWC_DMACR_RX_CLEAR(v)	(((v) & ~SATA_DWC_DMACR_RXCHEN) | \
> +						SATA_DWC_DMACR_TMOD_TXCHEN)
> +#define SATA_DWC_DMACR_TXRXCH_CLEAR	SATA_DWC_DMACR_TMOD_TXCHEN
> +
> +#define SATA_DWC_DBTSR_MWR(size)	((size/4) & \
> +						SATA_DWC_TXFIFO_DEPTH)
> +#define SATA_DWC_DBTSR_MRD(size)	(((size/4) & \
> +						SATA_DWC_RXFIFO_DEPTH) << 16)
> +#define	SATA_DWC_INTPR_DMAT		0x00000001
> +#define SATA_DWC_INTPR_NEWFP		0x00000002
> +#define SATA_DWC_INTPR_PMABRT		0x00000004
> +#define SATA_DWC_INTPR_ERR		0x00000008
> +#define SATA_DWC_INTPR_NEWBIST		0x00000010
> +#define SATA_DWC_INTPR_IPF		0x10000000
> +#define	SATA_DWC_INTMR_DMATM		0x00000001
> +#define SATA_DWC_INTMR_NEWFPM		0x00000002
> +#define SATA_DWC_INTMR_PMABRTM		0x00000004
> +#define SATA_DWC_INTMR_ERRM		0x00000008
> +#define SATA_DWC_INTMR_NEWBISTM		0x00000010
> +#define SATA_DWC_LLCR_SCRAMEN		0x00000001
> +#define SATA_DWC_LLCR_DESCRAMEN		0x00000002
> +#define SATA_DWC_LLCR_RPDEN		0x00000004

ditto


> +struct sata_dwc_device {
> +	struct device		*dev;		/* generic device struct */
> +	struct ata_probe_ent	*pe;		/* ptr to probe-ent */
> +	struct ata_host		*host;
> +	u8			*reg_base;
> +	struct sata_dwc_regs	*sata_dwc_regs;	/* DW Synopsys SATA specific */
> +	int			irq_dma;
> +};

I think this is missing __iomem notations and 'sparse' checks 
(Documentation/sparse.txt)


> + */
> +static u32 sata_dwc_sactive_issued;	/* issued queued ops */
> +static u32 sata_dwc_sactive_queued;	/* queued ops */
> +static struct ahb_dma_regs *sata_dma_regs;
> +static u32 dma_interrupt_count;
> +static void *scr_addr_sstatus;
> +static struct device *dwc_dev;

create a host-private struct, do not use global variables.

Global variables are discouraged because they create a barrier to 
supporting multiple controller instances in a single driver -- and also 
because people look at existing driver code for examples, and this 
creates a poor example


> +static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag);
> +static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
> +				u32 check_status);
> +static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status);
> +static void sata_dwc_port_stop(struct ata_port *ap);
> +static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag);
> +
> +static int dma_dwc_init(struct sata_dwc_device *hsdev, struct resource *res,
> +			int irq);
> +static void dma_dwc_exit(struct sata_dwc_device *hsdev);
> +static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
> +			      struct lli *lli, dma_addr_t dma_lli,
> +			      void __iomem *addr, int dir);
> +static void dma_dwc_xfer_start(int dma_ch);
> +static void dma_dwc_terminate_dma(int dma_ch);
> +
> +static const char *dir_2_txt(enum dma_data_direction dir)
> +{
> +	switch (dir) {
> +	case DMA_BIDIRECTIONAL:
> +		return "bi";
> +	case DMA_FROM_DEVICE:
> +		return "from";
> +	case DMA_TO_DEVICE:
> +		return "to";
> +	case DMA_NONE:
> +		return "none";
> +	default:
> +		return "err";
> +	}
> +}
> +
> +static const char *prot_2_txt(enum ata_tf_protocols protocol)
> +{
> +	switch (protocol) {
> +	case ATA_PROT_UNKNOWN:
> +		return "unknown";
> +	case ATA_PROT_NODATA:
> +		return "nodata";
> +	case ATA_PROT_PIO:
> +		return "pio";
> +	case ATA_PROT_DMA:
> +		return "dma";
> +	case ATA_PROT_NCQ:
> +		return "ncq";
> +	case ATAPI_PROT_PIO:
> +		return "atapi pio";
> +	case ATAPI_PROT_NODATA:
> +		return "atapi nodata";
> +	case ATAPI_PROT_DMA:
> +		return "atapi dma";
> +	default:
> +		return "err";
> +	}
> +}
> +
> +inline const char *ata_cmd_2_txt(const struct ata_taskfile *tf)
> +{
> +	switch (tf->command) {
> +	case ATA_CMD_CHK_POWER:
> +		return "ATA_CMD_CHK_POWER";
> +	case ATA_CMD_EDD:
> +		return "ATA_CMD_EDD";
> +	case ATA_CMD_FLUSH:
> +		return "ATA_CMD_FLUSH";
> +	case ATA_CMD_FLUSH_EXT:
> +		return "ATA_CMD_FLUSH_EXT";
> +	case ATA_CMD_ID_ATA:
> +		return "ATA_CMD_ID_ATA";
> +	case ATA_CMD_ID_ATAPI:
> +		return "ATA_CMD_ID_ATAPI";
> +	case ATA_CMD_FPDMA_READ:
> +		return "ATA_CMD_FPDMA_READ";
> +	case ATA_CMD_FPDMA_WRITE:
> +		return "ATA_CMD_FPDMA_WRITE";
> +	case ATA_CMD_READ:
> +		return "ATA_CMD_READ";
> +	case ATA_CMD_READ_EXT:
> +		return "ATA_CMD_READ_EXT";
> +	case ATA_CMD_WRITE:
> +		return "ATA_CMD_WRITE";
> +	case ATA_CMD_WRITE_EXT:
> +		return "ATA_CMD_WRITE_EXT";
> +	case ATA_CMD_PIO_READ:
> +		return "ATA_CMD_PIO_READ";
> +	case ATA_CMD_PIO_READ_EXT:
> +		return "ATA_CMD_PIO_READ_EXT";
> +	case ATA_CMD_PIO_WRITE:
> +		return "ATA_CMD_PIO_WRITE";
> +	case ATA_CMD_PIO_WRITE_EXT:
> +		return "ATA_CMD_PIO_WRITE_EXT";
> +	case ATA_CMD_SET_FEATURES:
> +		return "ATA_CMD_SET_FEATURES";
> +	case ATA_CMD_PACKET:
> +		return "ATA_CMD_PACKET";
> +	default:
> +		return "ATA_CMD_???";

libata already has debugging facilties.  we don't need this generic dump 
stuff in a specific driver.


> +static void sata_dwc_tf_dump(struct ata_taskfile *tf)
> +{
> +	dev_vdbg(dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx"
> +			"device: %x\n", tf->command, prot_2_txt(tf->protocol),
> +			tf->flags, tf->device);
> +	dev_vdbg(dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam:"
> +			"0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal,
> +			tf->lbam, tf->lbah);
> +	dev_vdbg(dwc_dev, "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x "
> +			"hob_lbam: 0x%x hob_lbah: 0x%x\n", tf->hob_feature,
> +			tf->hob_nsect, tf->hob_lbal, tf->hob_lbam,
> +			tf->hob_lbah);

ditto


> + * Function: get_burst_length_encode
> + * arguments: datalength: length in bytes of data
> + * returns value to be programmed in register corrresponding to data length
> + * This value is effectively the log(base 2) of the length
> + */
> +static inline int get_burst_length_encode(int datalength)
> +{
> +	int items = datalength >> 2;	/* div by 4 to get lword count */
> +
> +	if (items >= 64)
> +		return 5;
> +
> +	if (items >= 32)
> +		return 4;
> +
> +	if (items >= 16)
> +		return 3;
> +
> +	if (items >= 8)
> +		return 2;
> +
> +	if (items >= 4)
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static inline void clear_chan_interrupts(int c)
> +{
> +	out_le32(&(sata_dma_regs->interrupt_clear.tfr.low), DMA_CHANNEL(c));
> +	out_le32(&(sata_dma_regs->interrupt_clear.block.low), DMA_CHANNEL(c));
> +	out_le32(&(sata_dma_regs->interrupt_clear.srctran.low), DMA_CHANNEL(c));
> +	out_le32(&(sata_dma_regs->interrupt_clear.dsttran.low), DMA_CHANNEL(c));
> +	out_le32(&(sata_dma_regs->interrupt_clear.error.low), DMA_CHANNEL(c));
> +}
> +
> +/*
> + * Function: dma_request_channel
> + * arguments: None
> + * returns channel number if available else -1
> + * This function assigns the next available DMA channel from the list to the
> + * requester
> + */
> +static int dma_request_channel(void)
> +{
> +	int i;
> +	struct ahb_dma_regs *pdma;
> +
> +	pdma = sata_dma_regs;
> +	for (i = 0; i < DMA_NUM_CHANS; i++) {
> +		if (!(in_le32(&(pdma->dma_chan_en.low)) & DMA_CHANNEL(i)))
> +			return i;
> +	}
> +
> +	dev_err(dwc_dev, "%s NO channel chan_en: 0x%08x\n", __func__,
> +		in_le32(&(pdma->dma_chan_en.low)));
> +
> +	return -1;
> +}
> +
> +/*
> + * Function: dma_dwc_interrupt
> + * arguments: irq, dev_id, pt_regs
> + * returns channel number if available else -1
> + * Interrupt Handler for DW AHB SATA DMA
> + */
> +static irqreturn_t dma_dwc_interrupt(int irq, void *hsdev_instance)
> +{
> +	int chan;
> +	u32 tfr_reg, err_reg;
> +	unsigned long flags;
> +	struct sata_dwc_device *hsdev =
> +		(struct sata_dwc_device *)hsdev_instance;
> +	struct ata_host *host = (struct ata_host *)hsdev->host;
> +	struct ata_port *ap;
> +	struct sata_dwc_device_port *hsdevp;
> +	u8 tag = 0;
> +	unsigned int port = 0;
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +
> +	ap = host->ports[port];
> +	hsdevp = HSDEVP_FROM_AP(ap);
> +	tag = ap->link.active_tag;
> +
> +	tfr_reg = in_le32(&(sata_dma_regs->interrupt_status.tfr.low));
> +	err_reg = in_le32(&(sata_dma_regs->interrupt_status.error.low));
> +
> +	dev_dbg(ap->dev, "eot=0x%08x err=0x%08x pending=%d active port=%d\n",
> +		tfr_reg, err_reg, hsdevp->dma_pending[tag], port);
> +
> +	for (chan = 0; chan < DMA_NUM_CHANS; chan++) {
> +		/* Check for end-of-transfer interrupt. */
> +		if (tfr_reg & DMA_CHANNEL(chan)) {
> +			/* 
> +			 *Each DMA command produces 2 interrupts.  Only
> +			 * complete the command after both interrupts have been
> +			 * seen. (See sata_dwc_isr())
> +			 */
> +			dma_interrupt_count++;
> +
> +			sata_dwc_clear_dmacr(hsdevp, tag);
> +
> +			if (hsdevp->dma_pending[tag] == 0) {
> +				dev_err(ap->dev, "DMA not pending eot=0x%08x "
> +					"err=0x%08x tag=0x%02x pending=%d\n",
> +					tfr_reg, err_reg, tag,
> +					hsdevp->dma_pending[tag]);
> +			}
> +
> +			if ((dma_interrupt_count % 2) == 0)
> +				sata_dwc_dma_xfer_complete(ap, 1);
> +
> +			/* Clear the interrupt */
> +			out_le32(&(sata_dma_regs->interrupt_clear.tfr.low),
> +				 DMA_CHANNEL(chan));
> +		}
> +
> +		/* Check for error interrupt. */
> +		if (err_reg & DMA_CHANNEL(chan)) {
> +			/* TODO Need error handler ! */
> +			dev_err(ap->dev, "error interrupt err_reg=0x%08x\n",
> +					err_reg);
> +
> +			/* Clear the interrupt. */
> +			out_le32(&(sata_dma_regs->interrupt_clear.error.low),
> +				 DMA_CHANNEL(chan));
> +		}
> +	}
> +
> +	spin_unlock_irqrestore(&host->lock, flags);


spin_lock_irqsave() is most likely expensive overkill.  Use spin_lock() 
unless you have concrete justification for something else.


> +/*
> + * Function: dma_request_interrupts
> + * arguments: hsdev
> + * returns status
> + * This function registers ISR for a particular DMA channel interrupt
> + */
> +static int dma_request_interrupts(struct sata_dwc_device *hsdev, int irq)
> +{
> +	int retval = 0;
> +	int chan;
> +
> +	for (chan = 0; chan < DMA_NUM_CHANS; chan++) {
> +		/* Unmask error interrupt */
> +		out_le32(&sata_dma_regs->interrupt_mask.error.low,
> +			 DMA_ENABLE_CHAN(chan));
> +
> +		/* Unmask end-of-transfer interrupt */
> +		out_le32(&sata_dma_regs->interrupt_mask.tfr.low,
> +			 DMA_ENABLE_CHAN(chan));
> +	}
> +
> +	retval = request_irq(irq, dma_dwc_interrupt, 0, "SATA DMA", hsdev);
> +	if (retval) {
> +		dev_err(dwc_dev, "%s: could not get IRQ %d\n", __func__, irq);
> +		return -ENODEV;
> +	}
> +
> +	/* Mark this interrupt as requested */
> +	hsdev->irq_dma = irq;
> +
> +	return 0;
> +}
> +
> +/*
> + * Function: map_sg_to_lli
> + * arguments: sg: scatter/gather list(sg)
> + *	      num_elems: no of elements in sg list
> + *	      dma_lli: LLI table
> + *	      dest: destination address
> + *	      read: whether the transfer is read or write
> + * returns array of AHB DMA Linked List Items
> + * This function creates a list of LLIs for DMA Xfr and returns the number
> + * of elements in the DMA linked list.
> + *
> + * Note that the Synopsis driver has a comment proposing that better performance
> + * is possible by only enabling interrupts on the last item in the linked list.
> + * However, it seems that could be a problem if an error happened on one of the
> + * first items.  The transfer would halt, but no error interrupt would occur.
> + *
> + * Currently this function sets interrupts enabled for each linked list item:
> + * DMA_CTL_INT_EN.
> + */
> +static int map_sg_to_lli(struct scatterlist *sg, int num_elems, struct lli *lli,
> +			 dma_addr_t dma_lli, void __iomem *dmadr_addr, int dir)
> +{
> +	int i, idx = 0;
> +	int fis_len = 0;
> +	dma_addr_t next_llp;
> +	int bl;
> +	unsigned int dma_ts = 0;
> +
> +	dev_dbg(dwc_dev, "%s: sg=%p nelem=%d lli=%p dma_lli=0x%08x "
> +		"dmadr=0x%08x\n", __func__, sg, num_elems, lli, (u32)dma_lli,
> +		(u32)dmadr_addr);
> +
> +	bl = get_burst_length_encode(AHB_DMA_BRST_DFLT);
> +
> +	for (i = 0; i < num_elems; i++, sg++) {
> +		u32 addr, offset;
> +		u32 sg_len, len;
> +
> +		addr = (u32) sg_dma_address(sg);
> +		sg_len = sg_dma_len(sg);
> +
> +		dev_dbg(dwc_dev, "%s: elem=%d sg_addr=0x%x sg_len=%d\n",
> +			__func__, i, addr, sg_len);
> +
> +		while (sg_len) {
> +
> +			if (idx >= SATA_DWC_DMAC_LLI_NUM) {
> +				/* The LLI table is not large enough. */
> +				dev_err(dwc_dev, "LLI table overrun (idx=%d)\n",
> +						idx);
> +				break;
> +			}
> +			len = (sg_len > SATA_DWC_DMAC_CTRL_TSIZE_MAX) ?
> +				SATA_DWC_DMAC_CTRL_TSIZE_MAX : sg_len;
> +
> +			offset = addr & 0xffff;
> +			if ((offset + sg_len) > 0x10000)
> +				len = 0x10000 - offset;
> +
> +			/*
> +			 * Make sure a LLI block is not created that will span a
> +			 * 8K max FIS boundary.  If the block spans such a FIS
> +			 * boundary, there is a chance that a DMA burst will
> +			 * cross that boundary -- this results in an error in
> +			 * the host controller.
> +			 */
> +			if (fis_len + len > 8192) {
> +				dev_dbg(dwc_dev, "SPLITTING: fis_len=%d(0x%x) "
> +					"len=%d(0x%x)\n", fis_len, fis_len,
> +					len, len);
> +				len = 8192 - fis_len;
> +				fis_len = 0;
> +			} else {
> +				fis_len += len;
> +			}
> +			if (fis_len == 8192)
> +				fis_len = 0;
> +
> +			/*
> +			 * Set DMA addresses and lower half of control register
> +			 * based on direction.
> +			 */
> +			if (dir == DMA_FROM_DEVICE) {
> +				lli[idx].dar = cpu_to_le32(addr);
> +				lli[idx].sar = cpu_to_le32((u32)dmadr_addr);
> +
> +				lli[idx].ctl.low = cpu_to_le32(
> +					DMA_CTL_TTFC(DMA_CTL_TTFC_P2M_DMAC) |
> +					DMA_CTL_SMS(0) |
> +					DMA_CTL_DMS(1) |
> +					DMA_CTL_SRC_MSIZE(bl) |
> +					DMA_CTL_DST_MSIZE(bl) |
> +					DMA_CTL_SINC_NOCHANGE |
> +					DMA_CTL_SRC_TRWID(2) |
> +					DMA_CTL_DST_TRWID(2) |
> +					DMA_CTL_INT_EN |
> +					DMA_CTL_LLP_SRCEN |
> +					DMA_CTL_LLP_DSTEN);
> +			} else {	/* DMA_TO_DEVICE */
> +				lli[idx].sar = cpu_to_le32(addr);
> +				lli[idx].dar = cpu_to_le32((u32)dmadr_addr);
> +
> +				lli[idx].ctl.low = cpu_to_le32(
> +					DMA_CTL_TTFC(DMA_CTL_TTFC_M2P_PER) |
> +					DMA_CTL_SMS(1) |
> +					DMA_CTL_DMS(0) |
> +					DMA_CTL_SRC_MSIZE(bl) |
> +					DMA_CTL_DST_MSIZE(bl) |
> +					DMA_CTL_DINC_NOCHANGE |
> +					DMA_CTL_SRC_TRWID(2) |
> +					DMA_CTL_DST_TRWID(2) |
> +					DMA_CTL_INT_EN |
> +					DMA_CTL_LLP_SRCEN |
> +					DMA_CTL_LLP_DSTEN);
> +			}
> +
> +			dev_dbg(dwc_dev, "%s setting ctl.high len: 0x%08x val: "
> +					"0x%08x\n", __func__, len,
> +					DMA_CTL_BLK_TS(len / 4));
> +
> +			/* Program the LLI CTL high register */
> +			dma_ts = DMA_CTL_BLK_TS(len / 4);
> +			lli[idx].ctl.high = cpu_to_le32(dma_ts);
> +
> +			/* 
> +			 *Program the next pointer.  The next pointer must be
> +			 * the physical address, not the virtual address.
> +			 */
> +			next_llp = (dma_lli + ((idx + 1) * sizeof(struct lli)));
> +
> +			/* The last 2 bits encode the list master select. */
> +			next_llp = DMA_LLP_LMS(next_llp, DMA_LLP_AHBMASTER2);
> +
> +			lli[idx].llp = cpu_to_le32(next_llp);
> +
> +			idx++;
> +			sg_len -= len;
> +			addr += len;
> +		}
> +	}
> +
> +	/*
> +	 * The last next ptr has to be zero and the last control low register
> +	 * has to have LLP_SRC_EN and LLP_DST_EN (linked list pointer source
> +	 * and destination enable) set back to 0 (disabled.)  This is what tells
> +	 * the core that this is the last item in the linked list.
> +	 */
> +	if (idx) {
> +		lli[idx-1].llp = 0x00000000;
> +		lli[idx-1].ctl.low &= DMA_CTL_LLP_DISABLE_LE32;
> +
> +		/* Flush cache to memory */
> +		dma_cache_sync(NULL, lli, (sizeof(struct lli) * idx),
> +			       DMA_BIDIRECTIONAL);
> +	}
> +
> +	return idx;
> +}
> +
> +/*
> + * Function: dma_dwc_xfer_start
> + * arguments: Channel number
> + * Return : None
> + * Enables the DMA channel
> + */
> +static void dma_dwc_xfer_start(int dma_ch)
> +{
> +	/* Enable the DMA channel */
> +	out_le32(&(sata_dma_regs->dma_chan_en.low),
> +		 in_le32(&(sata_dma_regs->dma_chan_en.low)) |
> +		 DMA_ENABLE_CHAN(dma_ch));
> +}
> +
> +static int dma_dwc_channel_enabled(int ch)
> +{
> +	if (in_le32(&(sata_dma_regs->dma_chan_en.low)) & DMA_CHANNEL(ch))
> +		return 1;
> +
> +	return 0;
> +}
> +
> +static void dma_dwc_terminate_dma(int dma_ch)
> +{
> +	int enabled = dma_dwc_channel_enabled(dma_ch);
> +
> +	dev_info(dwc_dev, "%s terminate DMA on channel=%d enabled=%d\n",
> +		 __func__, dma_ch, enabled);
> +
> +	if (enabled)  {
> +		out_le32(&(sata_dma_regs->dma_chan_en.low),
> +			 DMA_DISABLE_CHAN(dma_ch));
> +
> +		do {
> +			enabled = dma_dwc_channel_enabled(dma_ch);
> +		} while (enabled);
> +	}
> +}
> +
> +static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
> +			      struct lli *lli, dma_addr_t dma_lli,
> +			      void __iomem *addr, int dir)
> +{
> +	int dma_ch;
> +	int num_lli;
> +
> +	/* Acquire DMA channel */
> +	dma_ch = dma_request_channel();
> +	if (dma_ch == -1) {
> +		dev_err(dwc_dev, "%s: dma channel unavailable\n", __func__);
> +		return -EAGAIN;
> +	}
> +
> +	/* Convert SG list to linked list of items (LLIs) for AHB DMA */
> +	num_lli = map_sg_to_lli(sg, num_elems, lli, dma_lli, addr, dir);
> +
> +	dev_dbg(dwc_dev, "%s sg: 0x%p, count: %d lli: %p dma_lli: 0x%0xlx addr:"
> +		" %p lli count: %d\n", __func__, sg, num_elems, lli,
> +		(u32)dma_lli, addr, num_lli);
> +
> +	/* Clear channel interrupts */
> +	clear_chan_interrupts(dma_ch);
> +
> +	/* Program the CFG register. */
> +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.high),
> +		 DMA_CFG_PROTCTL | DMA_CFG_FCMOD_REQ);
> +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].cfg.low), 0);
> +
> +	/* Program the address of the linked list */
> +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].llp.low),
> +		 DMA_LLP_LMS(dma_lli, DMA_LLP_AHBMASTER2));
> +
> +	/* Program the CTL register with src enable / dst enable */
> +	out_le32(&(sata_dma_regs->chan_regs[dma_ch].ctl.low),
> +		 DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN);
> +
> +	return 0;
> +}
> +

add this is inside a spinlock, at all times, I hope?


> +static void dma_dwc_exit(struct sata_dwc_device *hsdev)
> +{
> +	dev_dbg(dwc_dev, "%s:\n", __func__);
> +	if (sata_dma_regs)
> +		iounmap(sata_dma_regs);
> +
> +	if (hsdev->irq_dma)
> +		free_irq(hsdev->irq_dma, hsdev);
> +}
> +
> +/*
> + * Function: dma_dwc_init
> + * arguments: hsdev
> + * returns status
> + * This function initializes the SATA DMA driver
> + */
> +static int dma_dwc_init(struct sata_dwc_device *hsdev, struct resource *res,
> +			int irq)
> +{
> +	int err;
> +
> +	sata_dma_regs = ioremap(res->start, res->end - res->start + 1);
> +	if (!sata_dma_regs) {
> +		dev_err(dwc_dev, "%s: ioremap failed\n", __func__);
> +		err = -ENODEV;
> +		goto error_out;
> +	}
> +
> +	err = dma_request_interrupts(hsdev, irq);
> +	if (err) {
> +		dev_err(dwc_dev, "%s: dma_request_interrupts returns %d\n",
> +			__func__, err);
> +		goto error_out;
> +	}
> +
> +	/* Enabe DMA */
> +	out_le32(&(sata_dma_regs->dma_cfg.low), DMA_EN);
> +
> +	dev_notice(dwc_dev, "DMA initialized\n");
> +	dev_dbg(dwc_dev, "SATA DMA registers=0x%p\n", sata_dma_regs);
> +
> +	return 0;
> +
> +error_out:
> +	dma_dwc_exit(hsdev);
> +
> +	return err;
> +}
> +
> +static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val)
> +{
> +	if (scr > SCR_NOTIFICATION) {
> +		dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n",
> +				__func__, scr);
> +		return -EINVAL;
> +	}
> +
> +	*val = in_le32((void *)link->ap->ioaddr.scr_addr + (scr * 4));
> +	dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
> +		__func__, link->ap->print_id, scr, *val);
> +
> +	return 0;
> +}
> +
> +static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val)
> +{
> +	dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n",
> +		__func__, link->ap->print_id, scr, val);
> +	if (scr > SCR_NOTIFICATION) {
> +		dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n",
> +				__func__, scr);
> +		return -EINVAL;
> +	}
> +	out_le32((void *)link->ap->ioaddr.scr_addr + (scr * 4), val);
> +
> +	return 0;
> +}
> +
> +static inline u32 core_scr_read(unsigned int scr)
> +{
> +	return in_le32((void __iomem *)scr_addr_sstatus + (scr * 4));
> +}
> +
> +static inline void core_scr_write(unsigned int scr, u32 val)
> +{
> +	out_le32((void __iomem *)scr_addr_sstatus + (scr * 4), val);
> +}
> +
> +static inline void clear_serror(void)
> +{
> +	out_le32((void __iomem *)scr_addr_sstatus + 4,
> +		 in_le32((void __iomem *)scr_addr_sstatus + 4));
> +}

adding __iomem casts indicates you are _missing_ iomem casts elsewhere



> +static inline void clear_intpr(struct sata_dwc_device *hsdev)
> +{
> +	out_le32(&hsdev->sata_dwc_regs->intpr,
> +		 in_le32(&hsdev->sata_dwc_regs->intpr));
> +}
> +
> +static inline void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
> +{
> +	out_le32(&hsdev->sata_dwc_regs->intpr,
> +		 in_le32(&hsdev->sata_dwc_regs->intpr));
> +}
> +
> +static inline void disable_err_irq(struct sata_dwc_device *hsdev)
> +{
> +	out_le32(&hsdev->sata_dwc_regs->intmr,
> +		 in_le32(&hsdev->sata_dwc_regs->intmr) & ~SATA_DWC_INTMR_ERRM);
> +	out_le32(&hsdev->sata_dwc_regs->errmr, ~SATA_DWC_SERROR_ERR_BITS);
> +}
> +
> +static inline void enable_err_irq(struct sata_dwc_device *hsdev)
> +{
> +	out_le32(&hsdev->sata_dwc_regs->intmr,
> +		 in_le32(&hsdev->sata_dwc_regs->intmr) | SATA_DWC_INTMR_ERRM);
> +	out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
> +}
> +
> +static inline u32 qcmd_tag_to_mask(u8 tag)
> +{
> +	return 0x00000001 << (tag & 0x1f);
> +}
> +
> +/* See ahci.c */
> +static void sata_dwc_error_intr(struct ata_port *ap,
> +				struct sata_dwc_device *hsdev, uint intpr)
> +{
> +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
> +	struct ata_eh_info *ehi = &ap->link.eh_info;
> +	unsigned int err_mask = 0, action = 0;
> +	struct ata_queued_cmd *qc;
> +	u32 serror;
> +	u8 status, tag;
> +	u32 err_reg;
> +
> +	ata_ehi_clear_desc(ehi);
> +
> +	serror = core_scr_read(SCR_ERROR);
> +	status = ap->ops->sff_check_status(ap);
> +
> +	err_reg = in_le32(&(sata_dma_regs->interrupt_status.error.low));
> +	tag = ap->link.active_tag;
> +
> +	dev_err(ap->dev, "%s SCR_ERROR=0x%08x intpr=0x%08x status=0x%08x "
> +		"dma_intp=%d pending=%d issued=%d dma_err_status=0x%08x\n",
> +		__func__, serror, intpr, status, dma_interrupt_count,
> +		hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag], err_reg);
> +
> +	/* Clear error register and interrupt bit */
> +	clear_serror();
> +	clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR);
> +
> +	/* This is the only error happening now. */
> +	/* TODO check for exact error */
> +	err_mask |= AC_ERR_HOST_BUS;
> +	action |= ATA_EH_RESET;
> +
> +	/* Pass this on to EH */
> +	ehi->serror |= serror;
> +	ehi->action |= action;
> +
> +	qc = ata_qc_from_tag(ap, tag);
> +	if (qc)
> +		qc->err_mask |= err_mask;
> +	else
> +		ehi->err_mask |= err_mask;
> +
> +	ata_port_abort(ap);
> +
> +	/*
> +	  if (irq_stat & PORT_IRQ_FREEZE)
> +	  ata_port_freeze(ap);
> +	  else
> +	  ata_port_abort(ap);
> +	*/
> +}
> +
> +/*
> + * Function : sata_dwc_isr
> + * arguments : irq, void *dev_instance, struct pt_regs *regs
> + * Return value : irqreturn_t - status of IRQ
> + * This Interrupt handler called via port ops registered function.
> + * .irq_handler = sata_dwc_isr
> + */
> +static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
> +{
> +	struct ata_host *host = (struct ata_host *)dev_instance;
> +	struct sata_dwc_device *hsdev = HSDEV_FROM_HOST(host);
> +	struct ata_port *ap;
> +	struct ata_queued_cmd *qc;
> +	unsigned long flags;
> +	u8 status, tag;
> +	int handled, num_processed, port = 0;
> +	uint intpr, sactive, sactive2, tag_mask;
> +	struct sata_dwc_device_port *hsdevp;
> +
> +	spin_lock_irqsave(&host->lock, flags);
> +
> +	/* Read the interrupt register */
> +	intpr = in_le32(&hsdev->sata_dwc_regs->intpr);
> +
> +	ap = host->ports[port];
> +	hsdevp = HSDEVP_FROM_AP(ap);
> +
> +	dev_dbg(ap->dev, "%s intpr=0x%08x active_tag=%d\n", __func__, intpr,
> +		ap->link.active_tag);
> +
> +	/* Check for error interrupt */
> +	if (intpr & SATA_DWC_INTPR_ERR) {
> +		sata_dwc_error_intr(ap, hsdev, intpr);
> +		handled = 1;
> +		goto done_irqrestore;
> +	}
> +
> +	/* Check for DMA SETUP FIS (FP DMA) interrupt */
> +	if (intpr & SATA_DWC_INTPR_NEWFP) {
> +		clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP);
> +
> +		tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr));
> +		dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag);
> +		if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND)
> +			dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag);
> +
> +		sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag);
> +
> +		qc = ata_qc_from_tag(ap, tag);
> +		/* 
> +		 * Start FP DMA for NCQ command.  At this point the tag is the
> +		 * active tag.  It is the tag that matches the command about to
> +		 * be completed.
> +		 */
> +		qc->ap->link.active_tag = tag;
> +		sata_dwc_bmdma_start_by_tag(qc, tag);
> +
> +		handled = 1;
> +		goto done_irqrestore;
> +	}
> +
> +	sactive = core_scr_read(SCR_ACTIVE);
> +	tag_mask = (sata_dwc_sactive_issued | sactive) ^ sactive;
> +
> +	/* If no sactive issued and tag_mask is zero then this is not NCQ */
> +	if (sata_dwc_sactive_issued == 0 && tag_mask == 0) {
> +		tag = 0;
> +		qc = ata_qc_from_tag(ap, tag);
> +
> +		/* DEV interrupt w/ no active qc? */
> +		if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
> +			dev_err(ap->dev, "%s intr with no active qc qc=%p\n",
> +				__func__, qc);
> +			ata_sff_check_status(ap);
> +			handled = 1;
> +			goto done_irqrestore;
> +		}
> +
> +		status = ap->ops->sff_check_status(ap);
> +
> +		qc->ap->link.active_tag = tag;
> +		hsdevp->cmd_issued[tag] = SATA_DWC_CMD_ISSUED_NOT;
> +
> +		if (status & ATA_ERR) {
> +			dev_dbg(ap->dev, "interrupt ATA_ERR (0x%x)\n", status);
> +			sata_dwc_qc_complete(ap, qc, 1);
> +			handled = 1;
> +			goto done_irqrestore;
> +		}
> +
> +		dev_dbg(ap->dev, "%s non-NCQ cmd interrupt, protocol: %s\n",
> +			__func__, prot_2_txt(qc->tf.protocol));
> +drv_still_busy:
> +		if (ata_is_dma(qc->tf.protocol)) {
> +			int dma_flag = hsdevp->dma_pending[tag];
> +			/* 
> +			 * Each DMA transaction produces 2 interrupts.  The DMAC
> +			 * transfer complete interrupt and the SATA controller
> +			 * operation done interrupt. The command should be
> +			 * completed only after both interrupts are seen.
> +			 */
> +			dma_interrupt_count++;
> +			if (dma_flag == SATA_DWC_DMA_PEND_NONE) {
> +				dev_err(ap->dev, "%s: DMA not pending "
> +					"intpr=0x%08x status=0x%08x pend=%d\n",
> +					__func__, intpr, status, dma_flag);
> +			}
> +
> +			if ((dma_interrupt_count % 2) == 0)
> +				sata_dwc_dma_xfer_complete(ap, 1);
> +		} else {
> +			if (unlikely(sata_dwc_qc_complete(ap, qc, 1)))
> +				goto drv_still_busy;
> +		}
> +
> +		handled = 1;
> +		goto done_irqrestore;
> +	}
> +
> +	/*
> +	 * This is a NCQ command.  At this point we need to figure out for which
> +	 * tags we have gotten a completion interrupt.  One interrupt may serve
> +	 * as completion for more than one operation when commands are queued
> +	 * (NCQ).  We need to process each completed command.
> +	 */
> +
> +process_cmd:  /* process completed commands */
> +	sactive = core_scr_read(SCR_ACTIVE);
> +	tag_mask = (sata_dwc_sactive_issued | sactive) ^ sactive;
> +
> +	if (sactive != 0 || sata_dwc_sactive_issued > 1 || tag_mask > 1) {
> +		dev_dbg(ap->dev, "%s NCQ: sactive=0x%08x  sactive_issued=0x%08x"
> +			" tag_mask=0x%08x\n", __func__, sactive,
> +			sata_dwc_sactive_issued, tag_mask);
> +	}
> +
> +	if ((tag_mask | sata_dwc_sactive_issued) != sata_dwc_sactive_issued) {
> +		dev_warn(ap->dev, "Bad tag mask?  sactive=0x%08x "
> +			 "sata_dwc_sactive_issued=0x%08x  tag_mask=0x%08x\n",
> +			 sactive, sata_dwc_sactive_issued, tag_mask);
> +	}
> +
> +	/* read just to clear ... not bad if currently still busy */
> +	status = ap->ops->sff_check_status(ap);
> +	dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
> +
> +	tag = 0;
> +	num_processed = 0;
> +	while (tag_mask) {
> +		num_processed++;
> +		while (!(tag_mask & 0x00000001)) {
> +			tag++;
> +			tag_mask <<= 1;
> +		}
> +		tag_mask &= (~0x00000001);
> +		qc = ata_qc_from_tag(ap, tag);
> +
> +		/* To be picked up by completion functions */
> +		qc->ap->link.active_tag = tag;
> +		hsdevp->cmd_issued[tag] = SATA_DWC_CMD_ISSUED_NOT;
> +
> +		/* Let libata/scsi layers handle error */
> +		if (status & ATA_ERR) {
> +			dev_dbg(ap->dev, "%s ATA_ERR (0x%x)\n",
> +					 __func__, status);
> +
> +			sata_dwc_qc_complete(ap, qc, 1);
> +			handled = 1;
> +			goto done_irqrestore;
> +		}
> +
> +		/* Process completed command */
> +		dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__,
> +			prot_2_txt(qc->tf.protocol));
> +		if (ata_is_dma(qc->tf.protocol)) {
> +			dma_interrupt_count++;
> +			if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PEND_NONE)
> +				dev_warn(ap->dev,
> +					"%s: DMA not pending?\n", __func__);
> +			if ((dma_interrupt_count % 2) == 0)
> +				sata_dwc_dma_xfer_complete(ap, 1);
> +		} else {
> +			if (unlikely(sata_dwc_qc_complete(ap, qc, 1)))
> +				goto still_busy;
> +		}
> +		continue;
> +
> +still_busy:
> +		ap->stats.idle_irq++;
> +		dev_warn(ap->dev, "STILL BUSY IRQ ata%d: irq trap\n",
> +				ap->print_id);
> +	} /* while tag_mask */
> +
> +	/*
> +	 * Check to see if any commands completed while we were processing our
> +	 * initial set of completed commands (reading of status clears
> +	 * interrupts, so we might miss a completed command interrupt if one
> +	 * came in while we were processing:
> +	 * we read status as part of processing a completed command).
> +	 */
> +	sactive2 = core_scr_read(SCR_ACTIVE);
> +	if (sactive2 != sactive) {
> +		dev_dbg(ap->dev, "More finished - sactive=0x%x sactive2=0x%x\n",
> +			sactive, sactive2);
> +		goto process_cmd;
> +	}
> +	handled = 1;
> +
> +done_irqrestore:
> +	spin_unlock_irqrestore(&host->lock, flags);
> +	return IRQ_RETVAL(handled);

1) it is completely silly to have a function this large.  break it up 
into multiple, smaller functions.

2) same comment as above -- spin_lock_irqsave() is both expensive and 
probably wrong, for this irq handler


> +static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag)
> +{
> +	struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp);
> +
> +	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PEND_RX) {
> +		out_le32(&(hsdev->sata_dwc_regs->dmacr),
> +			 SATA_DWC_DMACR_RX_CLEAR(
> +				 in_le32(&(hsdev->sata_dwc_regs->dmacr))));
> +	} else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PEND_TX) {
> +		out_le32(&(hsdev->sata_dwc_regs->dmacr),
> +			 SATA_DWC_DMACR_TX_CLEAR(
> +				 in_le32(&(hsdev->sata_dwc_regs->dmacr))));
> +	} else {
> +		/* 
> +		 * This should not happen, it indicates the driver is out of
> +		 * sync.  If it does happen, clear dmacr anyway.
> +		 */
> +		dev_err(dwc_dev, "%s DMA protocol RX and TX DMA not pending "
> +			"tag=0x%02x pending=%d dmacr: 0x%08x\n",
> +			__func__, tag, hsdevp->dma_pending[tag],
> +			in_le32(&(hsdev->sata_dwc_regs->dmacr)));
> +		out_le32(&(hsdev->sata_dwc_regs->dmacr),
> +				SATA_DWC_DMACR_TXRXCH_CLEAR);
> +	}
> +}
> +
> +static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status)
> +{
> +	struct ata_queued_cmd *qc;
> +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
> +	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
> +	u8 tag = 0;
> +
> +	tag = ap->link.active_tag;
> +	qc = ata_qc_from_tag(ap, tag);
> +
> +#ifdef DEBUG_NCQ
> +	if (tag > 0) {
> +		dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s "
> +			 "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command,
> +			 dir_2_txt(qc->dma_dir), prot_2_txt(qc->tf.protocol),
> +			 in_le32(&(hsdev->sata_dwc_regs->dmacr)));
> +	}
> +#endif
> +
> +	if (ata_is_dma(qc->tf.protocol)) {
> +		if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PEND_NONE) {
> +			dev_err(ap->dev, "%s DMA protocol RX and TX DMA not "
> +				"pending dmacr: 0x%08x\n", __func__,
> +				in_le32(&(hsdev->sata_dwc_regs->dmacr)));
> +		}
> +
> +		hsdevp->dma_pending[tag] = SATA_DWC_DMA_PEND_NONE;
> +		sata_dwc_qc_complete(ap, qc, check_status);
> +		ap->link.active_tag = ATA_TAG_POISON;
> +	} else {
> +		sata_dwc_qc_complete(ap, qc, check_status);
> +	}
> +}
> +
> +static int sata_dwc_qc_complete(struct ata_port *ap, struct ata_queued_cmd *qc,
> +				u32 check_status)
> +{
> +	u8 status = 0;
> +	int i = 0;
> +	u32 mask = 0x0;
> +	u8 tag = qc->tag;
> +	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
> +	u32 serror;
> +
> +	dev_dbg(ap->dev, "%s checkstatus? %x\n", __func__, check_status);
> +
> +	if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PEND_TX)
> +		dev_err(ap->dev, "TX DMA PENDING\n");
> +	else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PEND_RX)
> +		dev_err(ap->dev, "RX DMA PENDING\n");
> +
> +	if (check_status) {
> +		i = 0;
> +		do {
> +			/* check main status, clearing INTRQ */
> +			status = ap->ops->sff_check_status(ap);
> +			if (status & ATA_BUSY) {
> +				dev_dbg(ap->dev, "STATUS BUSY (0x%02x) [%d]\n",
> +						status, i);
> +			}
> +			if (++i > 10)
> +				break;
> +		} while (status & ATA_BUSY);
> +
> +		status = ap->ops->sff_check_status(ap);
> +		if (unlikely(status & ATA_BUSY))
> +			dev_err(ap->dev, "QC complete cmd=0x%02x STATUS BUSY "
> +				"(0x%02x) [%d]\n", qc->tf.command, status, i);
> +		serror = core_scr_read(SCR_ERROR);
> +		if (serror & SATA_DWC_SERROR_ERR_BITS)
> +			dev_err(ap->dev, "****** SERROR=0x%08x ******\n",
> +				serror);
> +	}

it is both silly and expensive to call a hook from your own driver. 
just call the function directly!


> +	dev_dbg(ap->dev, "QC complete cmd=0x%02x status=0x%02x ata%u: "
> +		"protocol=%d\n", qc->tf.command, status, ap->print_id,
> +		qc->tf.protocol);
> +
> +	/* clear active bit */
> +	mask = (~(qcmd_tag_to_mask(tag)));
> +	sata_dwc_sactive_queued = sata_dwc_sactive_queued & mask;
> +	sata_dwc_sactive_issued = sata_dwc_sactive_issued & mask;
> +
> +	/* Complete taskfile transaction (does not read SCR registers) */
> +	ata_qc_complete(qc);
> +
> +	return 0;
> +}
> +
> +static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev)
> +{
> +	/* Enable selective interrupts by setting the interrupt mask register */
> +	out_le32(&hsdev->sata_dwc_regs->intmr,
> +		 SATA_DWC_INTMR_ERRM |
> +		 SATA_DWC_INTMR_NEWFPM |
> +		 SATA_DWC_INTMR_PMABRTM |
> +		 SATA_DWC_INTMR_DMATM);
> +
> +	/* 
> +	 * Unmask the error bits that should trigger an error interrupt by
> +	 * setting the error mask register.
> +	 */
> +	out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS);
> +
> +	dev_dbg(dwc_dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", __func__,
> +		in_le32(&hsdev->sata_dwc_regs->intmr),
> +		in_le32(&hsdev->sata_dwc_regs->errmr));
> +}
> +
> +static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base)
> +{
> +	port->cmd_addr = (void *)base + 0x00;
> +	port->data_addr = (void *)base + 0x00;
> +
> +	port->error_addr = (void *)base + 0x04;
> +	port->feature_addr = (void *)base + 0x04;
> +
> +	port->nsect_addr = (void *)base + 0x08;
> +
> +	port->lbal_addr = (void *)base + 0x0c;
> +	port->lbam_addr = (void *)base + 0x10;
> +	port->lbah_addr = (void *)base + 0x14;
> +
> +	port->device_addr = (void *)base + 0x18;
> +	port->command_addr = (void *)base + 0x1c;
> +	port->status_addr = (void *)base + 0x1c;
> +
> +	port->altstatus_addr = (void *)base + 0x20;
> +	port->ctl_addr = (void *)base + 0x20;

casts indicate a C typing bug

^ permalink raw reply

* Re: device trees.
From: Grant Likely @ 2009-05-11 17:47 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: linuxppc-dev
In-Reply-To: <4A085612.9050602@dlasys.net>

On Mon, May 11, 2009 at 10:45 AM, David H. Lynch Jr. <dhlii@dlasys.net> wro=
te:
> Grant Likely wrote:
>>
>>> =A0 =A0We are very actively headed in the opposite direction. It is my/=
our
>>> intention to have a single linux executable that works accross
>>> =A0 =A0everyone of our cards and everyone of our bitfiles.
>>>
>>
>> That is the direction we are already going in. =A0U-Boot supports this.
>> In fact, I can build a single kernel image which will boot on all of
>> my MPC5200 boards, and my MPC83xx boards. =A0Similarly, if I have u-boot
>> running on a Virtex board, I can build a single image which will boot
>> all of them if the correct .dtb is passed to it.
>>
> =A0 =A0I was not aware that u-boot was currently doing that, but I was
> aware that was possible.
> =A0 =A0It is the most useful alternative to simple image.
> =A0 =A0I was not specifically trying to criticize simple image.
> =A0 =A0My problem is not with specific means of handling device trees.
> =A0 =A0It is that it is a one size fits all solution, and it is not
> sufficiently flexible for that.

What do you mean by "one size fits all solution?"

The kernel doesn't care where the device tree comes from.  All it
cares about is that by the time the kernel is started the device tree
must be fully formed and populated.  It can be completely pre-canned
(like simpleImage), it can be modified by firmware (like u-boot), or
it can be generated from scratch (like with real OpenFirmware).  There
is lots of flexibility on how to handle it.

>> You *could* generate the device tree dynamically, but I think that is
>> a path of diminishing returns considering that generating a .dts at
>> the same time as bitstream creation time is cheap and it is small. =A0At
>> one time Steven Neuendorffer was playing with a scheme to preload a
>> section of BRAM with a gzipped .dtb so that the correct device tree is
>> always present. =A0I really liked the idea, and I'd like to try to
>> pursue it.
>>
> =A0 =A0I would prefer not to waste bram by filling it with a device tree.
> =A0 =A0The best alternative to creating the device tree dynamically would
> be to
> =A0 =A0append the devicetree to the bitimage in a way the boot loader cou=
ld
> always find it.

That sounds like a good solution to me.

As for using up BRAM, a gzipped dtb image is smaller than 2k and it
can be reclaimed for other uses after the kernel has booted.  That may
not help your situation, but for my use cases the tradeoff works.

> =A0 =A0Regardless it still makes my point. =A0The problem with devicetree=
s as
> they are is that they handle probably 98% of all cases well.
> =A0 =A0The remaining 2% are a mess.

No it isn't.  It is expected that firmware will fixup the device tree
data with board specific values.  This is intentional.  The device
tree is simply the bearer.  It makes no determination about where the
data comes from.

> =A0 =A0lots of .dtb files lying arround is only a better solution than
> simpleimage.
> =A0 =A0I will guarantee that unless they are welded together the wrong
> device tree will get used with the wrong bit file.

I agree.

> =A0 =A0Inevitably I will make that mistake myself occasionally and waste
> hours or possibly days trying to debug it.
> =A0 =A0And if I will do it rarely clients will do it frequently.
>
> =A0 =A0In my expereince if you create a situation where confusion can exi=
st
> it will.
>
> =A0 =A0It is also my expereince that time spend coding a solution to a
> common client problem is well spent.
> =A0 =A0If it takes me a week to work out dynamically creating a device
> tree, that ill likely save many weeks of
> =A0 =A0support headaches.

Again, it doesn't sound like you want dynamic *creation* of device
trees.  It sounds like you want a reliable way to make sure the
bitstream is welded together with the correct dtb, preferably within
the Xilinx toolchain.

> =A0 =A0Even if I do not end up creating the device tree dynamically, I am
> likely to end up at a minimum doing some validation on it.
> =A0 =A0i.e. once the bitfile is loaded scanning the device tree and probi=
ng
> to ascertain that the hardware that I am supposed to expect
> =A0 =A0it really present.

If you like.

> =A0 =A0ultimately devicetrees are supposed to be a database not a black b=
ox.

I don't understand what you mean by this statement.

> =A0 =A0Anyway, all I was looking for was a leg up on figuring out how to =
do
> what I want with them. Rather than starting from scratch.
> =A0 =A0I am not looking to be convinced that I am approaching this all wr=
ong.
> =A0 =A0If you are happy with what you have - great. I am not.
> =A0 =A0While I was not looking to restart a great debate over device tree=
s
> - I do not actually think they are a bad idea.

I still don't understand what you're worried about starting an arguing
about.  Pretty much any of the PowerPC maintainers can point at warts
and problems in the current handling of device trees.  I'm not
particularly happy with simpleImage (and I wrote it), but it takes
time and effort to write something more capable.

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

^ permalink raw reply

* Re: [PowerPC] Next May 8 boot failure: OOPS during ibmveth moduleinit
From: Sachin Sant @ 2009-05-11 17:07 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: linuxppc-dev, netdev, linux-next, David Miller, sfr
In-Reply-To: <20090508223332.GA4881@psychotron.englab.brq.redhat.com>

Jiri Pirko wrote:
> Fri, May 08, 2009 at 09:57:22PM CEST, davem@davemloft.net wrote:
>   
>> From: Sachin Sant <sachinp@in.ibm.com>
>> Date: Fri, 08 May 2009 18:22:48 +0530
>>
>>     
>>> Todays Next failed to boot on a Power6 JS22 blade with following oops.
>>>       
>> Jiri, I suspect this might be your address list changes.
>>
>> Although that's just a guess.  But please take a look.
>>     
>
> Hmm, only thing I see might cause the problem would be if calling __hw_addr_add
> in dev_addr_init fails, then dev->dev_addr would contain zeroes (which looks
> this is not the case). But in this case the oops would appear earlier (in
> ibmveth_probe dev_addr memcpy).
>
> Will do the patch which checks the result to behave correctly in case of oom
> but this imho this wouldn't help. Strange, I will dig into this more tomorrow.
>   
I can recreate this problem with today's Next release as well. Let me 
know if you want me to try
out any thing to debug this problem.

Thanks
-Sachin

-- 

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

^ permalink raw reply

* Re: device trees.
From: David H. Lynch Jr. @ 2009-05-11 16:54 UTC (permalink / raw)
  To: Timur Tabi; +Cc: linuxppc-dev
In-Reply-To: <ed82fe3e0905110758l59ee1c94nffbfa50280851613@mail.gmail.com>

Timur Tabi wrote:
> On Mon, May 11, 2009 at 1:32 AM, David H. Lynch Jr. <dhlii@dlasys.net> wrote:
>
> So all you need to do is have your boot loader create a device tree
> from scratch.  If you're using U-Boot, then you can already do this by
> making the appropriate libfdt calls.  Otherwise, you should probably
> add libfdt to your boot loader.
>   
    As I mentioned before, we do nto use u-boot. I am not looking to
start a debate on it either, but it does not meet a number of our needs,
    and would require significant architectural changes to do so. The
difference between it and devicetrees is that u-boot is avaiable to us
if we want, I did port u-boot to our hardware at one point and it did
everything it promised, but u-boot is optional, device trees are not.
    I do not have to re-architect u-boot to fit into 16k of bram, or
load bit files or .....
     If I want to move past 2.6.26 I have to not only use device trees
but actually make them work in a way that will function as we need with
our systems.
    It is likely I will use libdft as a starting point, but I can not
see it as more than a short term solution. libdft is orders of magnitude
large than our entire monitor, and it is a toolkit rather than the whole
solution.


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.627.3770 	       dhlii@dlasys.net 	  http://www.dlasys.net
fax: 1.253.369.9244 			           Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein

^ permalink raw reply

* Re: Next May 11 : BUG during scsi initialization
From: Sachin Sant @ 2009-05-11 16:59 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Nick Piggin, Stephen Rothwell, linux-scsi, chinang.ma,
	linuxppc-dev, Pekka Enberg, linux-next
In-Reply-To: <20090511162511.GG8112@parisc-linux.org>

Matthew Wilcox wrote:
> On Mon, May 11, 2009 at 09:49:55PM +0530, Sachin Sant wrote:
>   
>> Yeah so the problem seems to be with SLQB. I was able to boot Next 11 with
>> SLUB on the same machine.
>>     
>
> Is it 100% reproducable with SLQB?  Our errors were fairly hard to tickle
> on demand.
>
>   
Yes. I am able to recreate this during every single reboot. I just 
tested few older next
releases (May 6th, 7th and 8th)as well and was able to recreate this 
issue with every release.

Thanks
-Sachin

-- 

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

^ permalink raw reply

* Re: device trees.
From: David H. Lynch Jr. @ 2009-05-11 16:58 UTC (permalink / raw)
  To: Stephen Neuendorffer; +Cc: linuxppc-dev
In-Reply-To: <20090511155232.A30671B6005D@mail89-va3.bigfish.com>

Stephen Neuendorffer wrote:
>> You *could* generate the device tree dynamically, but I think that is
>> a path of diminishing returns considering that generating a .dts at
>> the same time as bitstream creation time is cheap and it is small.  At
>> one time Steven Neuendorffer was playing with a scheme to preload a
>> section of BRAM with a gzipped .dtb so that the correct device tree is
>> always present.  I really liked the idea, and I'd like to try to
>> pursue it.
>>     
Thanks and I will look at it.
But if you want my .02, append the .dtb to the bit file in some fashion
that it can easily be located.
We already use all the bram we are willing to steal from clients (16k)
for our monitor/boot loader.

>
> In fact, the code to do this should still be floating around
> git.xilinx.com, although someone would likely have to bring it up to the
> current kernel versions.
> My intention was to treat it as two independent configuration options:
>
> 1) .dtb location is in BRAM
> 2) .dtb is passed compressed (regardless of location)
>
> Steve
>
> This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
>
>
>   


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.627.3770 	       dhlii@dlasys.net 	  http://www.dlasys.net
fax: 1.253.369.9244 			           Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein

^ permalink raw reply

* Re: device trees.
From: David H. Lynch Jr. @ 2009-05-11 16:45 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40905110651r1c18b78bpe8ffebe041726695@mail.gmail.com>

Grant Likely wrote:
>   
>>    We are very actively headed in the opposite direction. It is my/our
>> intention to have a single linux executable that works accross
>>    everyone of our cards and everyone of our bitfiles.
>>     
>
> That is the direction we are already going in.  U-Boot supports this.
> In fact, I can build a single kernel image which will boot on all of
> my MPC5200 boards, and my MPC83xx boards.  Similarly, if I have u-boot
> running on a Virtex board, I can build a single image which will boot
> all of them if the correct .dtb is passed to it.
>   
    I was not aware that u-boot was currently doing that, but I was
aware that was possible.
    It is the most useful alternative to simple image.
    I was not specifically trying to criticize simple image.
    My problem is not with specific means of handling device trees.
    It is that it is a one size fits all solution, and it is not
sufficiently flexible for that.


> You *could* generate the device tree dynamically, but I think that is
> a path of diminishing returns considering that generating a .dts at
> the same time as bitstream creation time is cheap and it is small.  At
> one time Steven Neuendorffer was playing with a scheme to preload a
> section of BRAM with a gzipped .dtb so that the correct device tree is
> always present.  I really liked the idea, and I'd like to try to
> pursue it.
>   
    I would prefer not to waste bram by filling it with a device tree.
    The best alternative to creating the device tree dynamically would
be to
    append the devicetree to the bitimage in a way the boot loader could
always find it.

    But ultimately the problem still exists.

    Device trees are the ONLY legitimate way to pass information post
2.6.26.
    That means that if there is a single peice of dynamic information
that needs to be passed to linux,
    at a minimum the device tree must be edited.
    It is my understanding that u-boot already does some of this to
manage command lines, and maybe a few other items.

    Regardless it still makes my point.  The problem with devicetrees as
they are is that they handle probably 98% of all cases well.
    The remaining 2% are a mess.

    lots of .dtb files lying arround is only a better solution than
simpleimage.
    I will guarantee that unless they are welded together the wrong
device tree will get used with the wrong bit file.
    Inevitably I will make that mistake myself occasionally and waste
hours or possibly days trying to debug it.
    And if I will do it rarely clients will do it frequently.

    In my expereince if you create a situation where confusion can exist
it will.

    It is also my expereince that time spend coding a solution to a
common client problem is well spent.
    If it takes me a week to work out dynamically creating a device
tree, that ill likely save many weeks of
    support headaches.

    Even if I do not end up creating the device tree dynamically, I am
likely to end up at a minimum doing some validation on it.
    i.e. once the bitfile is loaded scanning the device tree and probing
to ascertain that the hardware that I am supposed to expect
    it really present.

    ultimately devicetrees are supposed to be a database not a black box.

    Anyway, all I was looking for was a leg up on figuring out how to do
what I want with them. Rather than starting from scratch.
    I am not looking to be convinced that I am approaching this all wrong.
    If you are happy with what you have - great. I am not.
    While I was not looking to restart a great debate over device trees
- I do not actually think they are a bad idea.
   

> g.
>
>   


-- 
Dave Lynch 					  	    DLA Systems
Software Development:  				         Embedded Linux
717.627.3770 	       dhlii@dlasys.net 	  http://www.dlasys.net
fax: 1.253.369.9244 			           Cell: 1.717.587.7774
Over 25 years' experience in platforms, languages, and technologies too numerous to list.

"Any intelligent fool can make things bigger and more complex... It takes a touch of genius - and a lot of courage to move in the opposite direction."
Albert Einstein

^ permalink raw reply

* Re: Next May 11 : BUG during scsi initialization
From: Matthew Wilcox @ 2009-05-11 16:25 UTC (permalink / raw)
  To: Sachin Sant
  Cc: Nick Piggin, Stephen Rothwell, linux-scsi, chinang.ma,
	linuxppc-dev, Pekka Enberg, linux-next
In-Reply-To: <4A08502B.9040001@in.ibm.com>

On Mon, May 11, 2009 at 09:49:55PM +0530, Sachin Sant wrote:
> Yeah so the problem seems to be with SLQB. I was able to boot Next 11 with
> SLUB on the same machine.

Is it 100% reproducable with SLQB?  Our errors were fairly hard to tickle
on demand.

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply

* Re: Next May 11 : BUG during scsi initialization
From: Sachin Sant @ 2009-05-11 16:19 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Nick Piggin, Stephen Rothwell, linux-scsi, linuxppc-dev,
	Pekka Enberg, linux-next
In-Reply-To: <20090511122135.GC8112@parisc-linux.org>

Matthew Wilcox wrote:
>> Default one. SLQB
>>
>> CONFIG_SLQB_ALLOCATOR=y
>> CONFIG_SLQB=y
>>
>> Page size is 64K with Config DEBUG_PAGEALLOC set.
>>
>> CONFIG_PPC_HAS_HASH_64K=y
>> CONFIG_PPC_64K_PAGES=y
>> CONFIG_DEBUG_PAGEALLOC=y
>>     
>
> Hm.  We've seen some similar problems at Intel while doing database
> performance tests with SLQB.  Any ideas, Nick?
>   
Yeah so the problem seems to be with SLQB. I was able to boot Next 11 with
SLUB on the same machine.

Thanks
-Sachin

-- 

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

^ permalink raw reply

* RE: device trees.
From: Stephen Neuendorffer @ 2009-05-11 15:52 UTC (permalink / raw)
  To: Grant Likely, David H. Lynch Jr.; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40905110651r1c18b78bpe8ffebe041726695@mail.gmail.com>


> You *could* generate the device tree dynamically, but I think that is
> a path of diminishing returns considering that generating a .dts at
> the same time as bitstream creation time is cheap and it is small.  At
> one time Steven Neuendorffer was playing with a scheme to preload a
> section of BRAM with a gzipped .dtb so that the correct device tree is
> always present.  I really liked the idea, and I'd like to try to
> pursue it.

In fact, the code to do this should still be floating around
git.xilinx.com, although someone would likely have to bring it up to the
current kernel versions.
My intention was to treat it as two independent configuration options:

1) .dtb location is in BRAM
2) .dtb is passed compressed (regardless of location)

Steve

This email and any attachments are intended for the sole use of the named r=
ecipient(s) and contain(s) confidential information that may be proprietary=
, privileged or copyrighted under applicable law. If you are not the intend=
ed recipient, do not read, copy, or forward this email message or any attac=
hments. Delete this email message and any attachments immediately.

^ permalink raw reply

* Re: device trees.
From: Timur Tabi @ 2009-05-11 14:58 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: linuxppc-dev
In-Reply-To: <4A07C664.6040609@dlasys.net>

On Mon, May 11, 2009 at 1:32 AM, David H. Lynch Jr. <dhlii@dlasys.net> wrot=
e:
> =A0 =A0We are very actively headed in the opposite direction. It is my/ou=
r
> intention to have a single linux executable that works accross
> =A0 =A0everyone of our cards and everyone of our bitfiles.

This is the same direction that "we" are headed in as well.  For a
given core, it is more or less possible to generate one kernel that
works on any number of  SOCs and boards that use that core.  The only
difference is which device tree it is given.

So all you need to do is have your boot loader create a device tree
from scratch.  If you're using U-Boot, then you can already do this by
making the appropriate libfdt calls.  Otherwise, you should probably
add libfdt to your boot loader.

--=20
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: device trees.
From: Grant Likely @ 2009-05-11 13:51 UTC (permalink / raw)
  To: David H. Lynch Jr.; +Cc: linuxppc-dev
In-Reply-To: <4A07C664.6040609@dlasys.net>

On Mon, May 11, 2009 at 12:32 AM, David H. Lynch Jr. <dhlii@dlasys.net> wro=
te:
> =A0 =A0But partial reconfiguration is not the only way to encounter a
> dynamic environment.
> =A0 =A0A typical pico system has multiple bit files and multiple
> executables stored in its flash file system.
> =A0 =A0Power up and soft resets might each run through a different sequen=
ce
> of bit files and executables.
>
> =A0 =A0My issue is that post 2.6.26 unless I can dynamically create the
> device tree inside our monitor/bootloader
> =A0 =A0we must at minimum have a different device tree for each bitfile,

This is true

> or worse if we wrap the device tree into the executable,
>    a different linux executable for each bit file.

As you say, this is undesirable.  simpleImage does this, but it it
intended for the least common denominator case where there is no
firmware support at all available and the kernel needs to be
completely contained.  simpleImage is not intended to be the ideal.

> =A0 =A0We are very actively headed in the opposite direction. It is my/ou=
r
> intention to have a single linux executable that works accross
> =A0 =A0everyone of our cards and everyone of our bitfiles.

That is the direction we are already going in.  U-Boot supports this.
In fact, I can build a single kernel image which will boot on all of
my MPC5200 boards, and my MPC83xx boards.  Similarly, if I have u-boot
running on a Virtex board, I can build a single image which will boot
all of them if the correct .dtb is passed to it.

You *could* generate the device tree dynamically, but I think that is
a path of diminishing returns considering that generating a .dts at
the same time as bitstream creation time is cheap and it is small.  At
one time Steven Neuendorffer was playing with a scheme to preload a
section of BRAM with a gzipped .dtb so that the correct device tree is
always present.  I really liked the idea, and I'd like to try to
pursue it.

g.

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

^ permalink raw reply

* some questions about the implementation of oprofile of mpc8560 in linux kernel source code
From: 0x0000 @ 2009-05-11 12:36 UTC (permalink / raw)
  To: linuxppc-dev

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

Dear All,

I am a user of oprofile. When I use oprofile, I find some problems. Could you please help me? 

I have some questions about the open source code of the implementation of oprofile in linux 
kernel 2.6.26, which is presented op_model_fsl_emb.c, and the path in linux kernel source 
tree is arch/powerpc/oprofile/op_model_fsl_emb.c. 

To present this question more clearly, It needs the following steps: 

1> I give some cpu event and its counter values, which finally will call the function fsl_emb_reg_setup 

2> I execute setup, which finally will call the function fsl_emb_cpu_setup 

3> I execute start, which finally will call the function fsl_emb_start 

4> After calling start, the MPC8560 CPU will continuing increasing the PMCn value until its value reach 
0x80000000. Basing on what metioned in E500CORERM.pdf, this value should cause a exception, and 
should goto the interrupt routine:fsl_emb_handle_interrupt. 
But in fact, It never goto this interrupt routine! It always cause a reboot without any information! 

But while we using MPC7450 CPU, this situation never happened, it works well. 


Basing on the information metioned above, my questions are: 
1> Is there any bug in op_model_fsl_emb.c and its related source code? 
2> If possible, could you please tell me what the reason it is? And How to use op_model_fsl_emb.c correctly? 


Any feedback is appreciated! 

Thanks & regards 
Jike

2009-05-11 



0x0000 

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

^ permalink raw reply

* Re: [PATCH 2/2] x86-64: seccomp: fix 32/64 syscall hole
From: Pavel Machek @ 2009-05-10  5:37 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-mips, linuxppc-dev, x86, linux-kernel, stable, sparclinux,
	Markus Gutschke (?????????), Nicholas Miell, Linus Torvalds,
	Andrew Morton, Roland McGrath
In-Reply-To: <20090507101129.GB5978@elte.hu>

On Thu 2009-05-07 12:11:29, Ingo Molnar wrote:
> 
> * Nicholas Miell <nmiell@comcast.net> wrote:
> 
> > On Wed, 2009-05-06 at 15:21 -0700, Markus Gutschke (?????????) wrote:
> > > On Wed, May 6, 2009 at 15:13, Ingo Molnar <mingo@elte.hu> wrote:
> > > > doing a (per arch) bitmap of harmless syscalls and replacing the
> > > > mode1_syscalls[] check with that in kernel/seccomp.c would be a
> > > > pretty reasonable extension. (.config controllable perhaps, for
> > > > old-style-seccomp)
> > > >
> > > > It would probably be faster than the current loop over
> > > > mode1_syscalls[] as well.
> > > 
> > > This would be a great option to improve performance of our sandbox. I
> > > can detect the availability of the new kernel API dynamically, and
> > > then not intercept the bulk of the system calls. This would allow the
> > > sandbox to work both with existing and with newer kernels.
> > > 
> > > We'll post a kernel patch for discussion in the next few days,
> > > 
> > 
> > I suspect the correct thing to do would be to leave seccomp mode 1 
> > alone and introduce a mode 2 with a less restricted set of system 
> > calls -- the interface was designed to be extended in this way, 
> > after all.
> 
> Yes, that is what i alluded to above via the '.config controllable' 
> aspect.
> 
> Mode 2 could be implemented like this: extend prctl_set_seccomp() 
> with a bitmap pointer, and copy it to a per task seccomp context 
> structure.
> 
> a bitmap for 300 syscalls takes only about 40 bytes.
> 
> Please take care to implement nesting properly: if a seccomp context 
> does a seccomp call (which mode 2 could allow), then the resulting 
> bitmap should be the logical-AND of the parent and child bitmaps. 
> There's no reason why seccomp couldnt be used in hiearachy of 
> sandboxes, in a gradually less permissive fashion.

I don't think seccomp nesting (at kernel level) has any value.

First, syscalls are wrong level of abstraction for sandboxing. There
are multiple ways to read from file, for example.

If you wanted to do hierarchical sandboxes, asking your monitor to
restrict your seccomp mask would seem like a way to go...
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* Re: Next May 11 : BUG during scsi initialization
From: Matthew Wilcox @ 2009-05-11 12:21 UTC (permalink / raw)
  To: Sachin Sant
  Cc: Nick Piggin, Stephen Rothwell, linux-scsi, linuxppc-dev,
	Pekka Enberg, linux-next
In-Reply-To: <4A081437.7000409@in.ibm.com>

On Mon, May 11, 2009 at 05:34:07PM +0530, Sachin Sant wrote:
> Matthew Wilcox wrote:
>> On Mon, May 11, 2009 at 05:16:10PM +0530, Sachin Sant wrote:
>>   
>>> Today's Next tree failed to boot on a Power6 box with following BUG :
>>
>> This doesn't actually appear to be a SCSI bug ... it looks like SCSI tried
>> to allocate memory and things went wrong in the memory allocator:
>>
>> [c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
>> [c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
>> [c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
>> [c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
>> [c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]
>>
>> Which memory allocator did you have selected (SLAB, SLUB, SLOB, SLQB)?
>>   
> Default one. SLQB
>
> CONFIG_SLQB_ALLOCATOR=y
> CONFIG_SLQB=y
>
> Page size is 64K with Config DEBUG_PAGEALLOC set.
>
> CONFIG_PPC_HAS_HASH_64K=y
> CONFIG_PPC_64K_PAGES=y
> CONFIG_DEBUG_PAGEALLOC=y

Hm.  We've seen some similar problems at Intel while doing database
performance tests with SLQB.  Any ideas, Nick?

-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply

* Re: Next May 11 : BUG during scsi initialization
From: Sachin Sant @ 2009-05-11 12:04 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Stephen Rothwell, Pekka Enberg, linux-next, linux-scsi,
	linuxppc-dev
In-Reply-To: <20090511115233.GB8112@parisc-linux.org>

Matthew Wilcox wrote:
> On Mon, May 11, 2009 at 05:16:10PM +0530, Sachin Sant wrote:
>   
>> Today's Next tree failed to boot on a Power6 box with following BUG :
>>     
>
> This doesn't actually appear to be a SCSI bug ... it looks like SCSI tried
> to allocate memory and things went wrong in the memory allocator:
>
> [c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
> [c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
> [c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
> [c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
> [c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]
>
> Which memory allocator did you have selected (SLAB, SLUB, SLOB, SLQB)?
>   
Default one. SLQB

CONFIG_SLQB_ALLOCATOR=y
CONFIG_SLQB=y

Page size is 64K with Config DEBUG_PAGEALLOC set.

CONFIG_PPC_HAS_HASH_64K=y
CONFIG_PPC_64K_PAGES=y
CONFIG_DEBUG_PAGEALLOC=y

Thanks
-Sachin


-- 

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

^ permalink raw reply

* Re: Next May 11 : BUG during scsi initialization
From: Matthew Wilcox @ 2009-05-11 11:52 UTC (permalink / raw)
  To: Sachin Sant; +Cc: Stephen Rothwell, linux-next, linux-scsi, linuxppc-dev
In-Reply-To: <4A081002.4050802@in.ibm.com>

On Mon, May 11, 2009 at 05:16:10PM +0530, Sachin Sant wrote:
> Today's Next tree failed to boot on a Power6 box with following BUG :

This doesn't actually appear to be a SCSI bug ... it looks like SCSI tried
to allocate memory and things went wrong in the memory allocator:

[c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
[c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
[c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
[c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
[c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]

Which memory allocator did you have selected (SLAB, SLUB, SLOB, SLQB)?

> BUG: spinlock bad magic on CPU#1, modprobe/63
> Unable to handle kernel paging request for data at address 0xffffc994838
> Faulting instruction address: 0xc00000000035f5a8
> Oops: Kernel access of bad area, sig: 11 [#1]
> SMP NR_CPUS=1024 DEBUG_PAGEALLOC NUMA pSeries
> Modules linked in: scsi_mod(+)
> NIP: c00000000035f5a8 LR: c00000000035f58c CTR: 0000000000136f8c
> REGS: c0000000c7d03500 TRAP: 0300   Not tainted  (2.6.30-rc5-autotest-next-20090511)
> MSR: 8000000000009032 <EE,ME,IR,DR>  CR: 28222484  XER: 0000000f
> DAR: 00000ffffc994838, DSISR: 0000000040000000
> TASK = c0000000c7cf0a80[63] 'modprobe' THREAD: c0000000c7d00000 CPU: 1
> GPR00: c00000000035f58c c0000000c7d03780 c000000000aaeed8 
> 0000000000000031 GPR04: 0000000000000000 00000000585cf4e0 
> 0000000000673580 80000000565a6cc0 GPR08: 0000000000000000 
> c0000000009ebf50 0000000000000000 c0000000009ebf38 GPR12: 
> 0000000028222482 c000000000b82600 0000000000000000 0000000000000000  
> GPR16: 0000000000000000 0000000000000000 0000000000000000 
> 0000000000000000 GPR20: 0000000000000018 ffffffffffffffff 
> c0000000009bbe40 0000000000000010 GPR24: 0000000000210d00 
> c0000000c6caff80 c0000000dfc732a0 c000000000f61380 GPR28: 
> c0000000007c8350 c0000000008a4280 c000000000a2f928 00000ffffc994550 NIP 
> [c00000000035f5a8] .spin_bug+0x90/0xd4
> LR [c00000000035f58c] .spin_bug+0x74/0xd4
> Call Trace:
> [c0000000c7d03780] [c00000000035f58c] .spin_bug+0x74/0xd4 (unreliable)
> [c0000000c7d03810] [c00000000035f890] ._raw_spin_lock+0x48/0x184
> [c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
> [c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
> [c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
> [c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
> [c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]
> [c0000000c7d03c20] [d000000000ea13c8] .init_scsi+0x1c/0xe8 [scsi_mod]
> [c0000000c7d03ca0] [c0000000000092c0] .do_one_initcall+0x80/0x19c
> [c0000000c7d03d90] [c0000000000c0540] .SyS_init_module+0xe0/0x244
> [c0000000c7d03e30] [c000000000008534] syscall_exit+0x0/0x40
> Instruction dump:
> 7f84e378 e87e8020 38c604d0 e8e902ea 4827fced 60000000 2fbf0000 80bd0004  
> 409e0010 e8de8028 38e0ffff 4800000c <e8ff02ea> 38df04d0 7fa4eb78 811d0008 
> ---[ end trace f725820a6fa9dbb7 ]---
> /init: line 21:    63 Segmentation fault      modprobe $file
>
> I have attached the dmesg log here. Let me know if any other information  
> is required.
>
> Thanks
> -Sachin
>
> -- 
>
> ---------------------------------
> Sachin Sant
> IBM Linux Technology Center
> India Systems and Technology Labs
> Bangalore, India
> ---------------------------------
>

> Using 007bc904 bytes for initrd buffer
> Please wait, loading kernel...
> Allocated 01100000 bytes for kernel @ 02300000
>    Elf64 kernel loaded...
> Loading ramdisk...
> ramdisk loaded 007bc904 @ 03400000
> OF stdout device is: /vdevice/vty@30000000
> Preparing to boot Linux version 2.6.30-rc5-autotest-next-20090511 (root@mpower6lp5) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #1 SMP Mon May 11 16:01:58 IST 2009
> Calling ibm,client-architecture... done
> command line: root=/dev/sda3 sysrq=1 insmod=sym53c8xx insmod=ipr crashkernel=512M-:256M IDENT=1242039097 
> memory layout at init:
>   alloc_bottom : 0000000003bc0000
>   alloc_top    : 0000000008000000
>   alloc_top_hi : 0000000008000000
>   rmo_top      : 0000000008000000
>   ram_top      : 0000000008000000
> instantiating rtas at 0x00000000074e0000... done
> boot cpu hw idx 0000000000000000
> copying OF device tree...
> Building dt strings...
> Building dt structure...
> Device tree strings 0x0000000003bd0000 -> 0x0000000003bd15c2
> Device tree struct  0x0000000003be0000 -> 0x0000000003c00000
> Calling quiesce...
> returning from prom_init
> Crash kernel location must be 0x2000000
> Reserving 256MB of memory at 32MB for crashkernel (System RAM: 4096MB)
> Phyp-dump disabled at boot time
> Using pSeries machine description
> Using 1TB segments
> Found initrd at 0xc000000003400000:0xc000000003bbc904
> console [udbg0] enabled
> Partition configured for 2 cpus.
> CPU maps initialized for 2 threads per core
> Starting Linux PPC64 #1 SMP Mon May 11 16:01:58 IST 2009
> -----------------------------------------------------
> ppc64_pft_size                = 0x1a
> physicalMemorySize            = 0x100000000
> htab_hash_mask                = 0x7ffff
> -----------------------------------------------------
> Initializing cgroup subsys cpuset
> Initializing cgroup subsys cpu
> Linux version 2.6.30-rc5-autotest-next-20090511 (root@mpower6lp5) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #1 SMP Mon May 11 16:01:58 IST 2009
> [boot]0012 Setup Arch
> EEH: No capable adapters found
> PPC64 nvram contains 15360 bytes
> Zone PFN ranges:
>   DMA      0x00000000 -> 0x00010000
>   Normal   0x00010000 -> 0x00010000
> Movable zone start PFN for each node
> early_node_map[2] active PFN ranges
>     2: 0x00000000 -> 0x0000e000
>     3: 0x0000e000 -> 0x00010000
> Could not find start_pfn for node 0
> [boot]0015 Setup Done
> Built 3 zonelists in Node order, mobility grouping on.  Total pages: 65472
> Policy zone: DMA
> Kernel command line: root=/dev/sda3 sysrq=1 insmod=sym53c8xx insmod=ipr crashkernel=512M-:256M IDENT=1242039097 
> Experimental hierarchical RCU implementation.
> RCU-based detection of stalled CPUs is enabled.
> Experimental hierarchical RCU init done.
> NR_IRQS:512
> [boot]0020 XICS Init
> [boot]0021 XICS Done
> PID hash table entries: 4096 (order: 12, 32768 bytes)
> clocksource: timebase mult[7d0000] shift[22] registered
> Console: colour dummy device 80x25
> console handover: boot [udbg0] -> real [hvc0]
> allocated 2621440 bytes of page_cgroup
> please try cgroup_disable=memory option if you don't want
> freeing bootmem node 2
> freeing bootmem node 3
> Memory: 3881920k/4194304k available (8896k kernel code, 312384k reserved, 2048k data, 4287k bss, 448k init)
> Calibrating delay loop... 1022.36 BogoMIPS (lpj=5111808)
> Security Framework initialized
> SELinux:  Disabled at boot.
> Dentry cache hash table entries: 524288 (order: 6, 4194304 bytes)
> Inode-cache hash table entries: 262144 (order: 5, 2097152 bytes)
> Mount-cache hash table entries: 4096
> Initializing cgroup subsys ns
> Initializing cgroup subsys cpuacct
> Initializing cgroup subsys memory
> Initializing cgroup subsys devices
> Initializing cgroup subsys freezer
> Processor 1 found.
> Brought up 2 CPUs
> net_namespace: 1936 bytes
> NET: Registered protocol family 16
> IBM eBus Device Driver
> PCI: Probing PCI hardware
> bio: create slab <bio-0> at 0
> usbcore: registered new interface driver usbfs
> usbcore: registered new interface driver hub
> usbcore: registered new device driver usb
> Failed to register trace events module notifier
> NET: Registered protocol family 2
> IP route cache hash table entries: 32768 (order: 2, 262144 bytes)
> TCP established hash table entries: 131072 (order: 5, 2097152 bytes)
> TCP bind hash table entries: 65536 (order: 5, 2097152 bytes)
> TCP: Hash tables configured (established 131072 bind 65536)
> TCP reno registered
> NET: Registered protocol family 1
> Unpacking initramfs...
> IOMMU table initialized, virtual merging enabled
> audit: initializing netlink socket (disabled)
> type=2000 audit(1242039145.533:1): initialized
> Kprobe smoke test started
> Kprobe smoke test passed successfully
> HugeTLB registered 16 MB page size, pre-allocated 0 pages
> HugeTLB registered 16 GB page size, pre-allocated 0 pages
> VFS: Disk quotas dquot_6.5.2
> Dquot-cache hash table entries: 8192 (order 0, 65536 bytes)
> Btrfs loaded
> msgmni has been set to 7580
> alg: No test for stdrng (krng)
> Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
> io scheduler noop registered
> io scheduler anticipatory registered
> io scheduler deadline registered
> io scheduler cfq registered (default)
> pci_hotplug: PCI Hot Plug PCI Core version: 0.5
> rpaphp: RPA HOT Plug PCI Controller Driver version: 0.1
> Generic RTC Driver v1.07
> Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
> pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)
> input: Macintosh mouse button emulation as /devices/virtual/input/input0
> Uniform Multi-Platform E-IDE driver
> ide-gd driver 1.18
> IBM eHEA ethernet device driver (Release EHEA_0101)
> ehea: eth0: Jumbo frames are disabled
> ehea: eth0 -> logical port id #2
> ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
> ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
> mice: PS/2 mouse device common for all mice
> EDAC MC: Ver: 2.1.0 May 11 2009
> usbcore: registered new interface driver hiddev
> usbcore: registered new interface driver usbhid
> usbhid: v2.6:USB HID core driver
> TCP cubic registered
> NET: Registered protocol family 15
> registered taskstats version 1
> Freeing unused kernel memory: 448k freed
> doing fast boot
> SysRq : Changing Loglevel
> Loglevel set to 1
> BUG: spinlock bad magic on CPU#1, modprobe/63
> Unable to handle kernel paging request for data at address 0xffffc994838
> Faulting instruction address: 0xc00000000035f5a8
> Oops: Kernel access of bad area, sig: 11 [#1]
> SMP NR_CPUS=1024 DEBUG_PAGEALLOC NUMA pSeries
> Modules linked in: scsi_mod(+)
> NIP: c00000000035f5a8 LR: c00000000035f58c CTR: 0000000000136f8c
> REGS: c0000000c7d03500 TRAP: 0300   Not tainted  (2.6.30-rc5-autotest-next-20090511)
> MSR: 8000000000009032 <EE,ME,IR,DR>  CR: 28222484  XER: 0000000f
> DAR: 00000ffffc994838, DSISR: 0000000040000000
> TASK = c0000000c7cf0a80[63] 'modprobe' THREAD: c0000000c7d00000 CPU: 1
> GPR00: c00000000035f58c c0000000c7d03780 c000000000aaeed8 0000000000000031 
> GPR04: 0000000000000000 00000000585cf4e0 0000000000673580 80000000565a6cc0 
> GPR08: 0000000000000000 c0000000009ebf50 0000000000000000 c0000000009ebf38 
> GPR12: 0000000028222482 c000000000b82600 0000000000000000 0000000000000000 
> GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
> GPR20: 0000000000000018 ffffffffffffffff c0000000009bbe40 0000000000000010 
> GPR24: 0000000000210d00 c0000000c6caff80 c0000000dfc732a0 c000000000f61380 
> GPR28: c0000000007c8350 c0000000008a4280 c000000000a2f928 00000ffffc994550 
> NIP [c00000000035f5a8] .spin_bug+0x90/0xd4
> LR [c00000000035f58c] .spin_bug+0x74/0xd4
> Call Trace:
> [c0000000c7d03780] [c00000000035f58c] .spin_bug+0x74/0xd4 (unreliable)
> [c0000000c7d03810] [c00000000035f890] ._raw_spin_lock+0x48/0x184
> [c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
> [c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
> [c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
> [c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
> [c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]
> [c0000000c7d03c20] [d000000000ea13c8] .init_scsi+0x1c/0xe8 [scsi_mod]
> [c0000000c7d03ca0] [c0000000000092c0] .do_one_initcall+0x80/0x19c
> [c0000000c7d03d90] [c0000000000c0540] .SyS_init_module+0xe0/0x244
> [c0000000c7d03e30] [c000000000008534] syscall_exit+0x0/0x40
> Instruction dump:
> 7f84e378 e87e8020 38c604d0 e8e902ea 4827fced 60000000 2fbf0000 80bd0004 
> 409e0010 e8de8028 38e0ffff 4800000c <e8ff02ea> 38df04d0 7fa4eb78 811d0008 
> ---[ end trace f725820a6fa9dbb7 ]---
> /init: line 21:    63 Segmentation fault      modprobe $file
> Creating device nodes with udev
> udevd version 128 started
> 
> 
> After the udevadm settle timeout, the events queue contains:
> 
> 632: /devices/vio/30000007
> 
> 
> Boot logging started on /dev/hvc0(/dev/console) at Mon May 11 10:52:56 2009
> 
> 
> After the udevadm settle timeout, the events queue contains:
> 
> 632: /devices/vio/30000007
> 
> 
> 
> 
> After the udevadm settle timeout, the events queue contains:
> 
> 632: /devices/vio/30000007
> 
> 
> 
> 
> After the udevadm settle timeout, the events queue contains:
> 
> 632: /devices/vio/30000007
> 
> 
> Waiting for device /dev/sda3 to appear: ..............................Could not find /dev/sda3.
> Want me to fall back to /dev/sda3? (Y/n) 
> 


-- 
Matthew Wilcox				Intel Open Source Technology Centre
"Bill, look, we understand that you're interested in selling us this
operating system, but compare it to ours.  We can't possibly take such
a retrograde step."

^ permalink raw reply

* Next May 11 : BUG during scsi initialization
From: Sachin Sant @ 2009-05-11 11:46 UTC (permalink / raw)
  Cc: Stephen Rothwell, linux-next, linux-scsi, linuxppc-dev
In-Reply-To: <20090511161442.3e9d9cb9.sfr@canb.auug.org.au>

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

Today's Next tree failed to boot on a Power6 box with following BUG :

BUG: spinlock bad magic on CPU#1, modprobe/63
Unable to handle kernel paging request for data at address 0xffffc994838
Faulting instruction address: 0xc00000000035f5a8
Oops: Kernel access of bad area, sig: 11 [#1]
SMP NR_CPUS=1024 DEBUG_PAGEALLOC NUMA pSeries
Modules linked in: scsi_mod(+)
NIP: c00000000035f5a8 LR: c00000000035f58c CTR: 0000000000136f8c
REGS: c0000000c7d03500 TRAP: 0300   Not tainted  (2.6.30-rc5-autotest-next-20090511)
MSR: 8000000000009032 <EE,ME,IR,DR>  CR: 28222484  XER: 0000000f
DAR: 00000ffffc994838, DSISR: 0000000040000000
TASK = c0000000c7cf0a80[63] 'modprobe' THREAD: c0000000c7d00000 CPU: 1
GPR00: c00000000035f58c c0000000c7d03780 c000000000aaeed8 0000000000000031 
GPR04: 0000000000000000 00000000585cf4e0 0000000000673580 80000000565a6cc0 
GPR08: 0000000000000000 c0000000009ebf50 0000000000000000 c0000000009ebf38 
GPR12: 0000000028222482 c000000000b82600 0000000000000000 0000000000000000 
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
GPR20: 0000000000000018 ffffffffffffffff c0000000009bbe40 0000000000000010 
GPR24: 0000000000210d00 c0000000c6caff80 c0000000dfc732a0 c000000000f61380 
GPR28: c0000000007c8350 c0000000008a4280 c000000000a2f928 00000ffffc994550 
NIP [c00000000035f5a8] .spin_bug+0x90/0xd4
LR [c00000000035f58c] .spin_bug+0x74/0xd4
Call Trace:
[c0000000c7d03780] [c00000000035f58c] .spin_bug+0x74/0xd4 (unreliable)
[c0000000c7d03810] [c00000000035f890] ._raw_spin_lock+0x48/0x184
[c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
[c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
[c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
[c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
[c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]
[c0000000c7d03c20] [d000000000ea13c8] .init_scsi+0x1c/0xe8 [scsi_mod]
[c0000000c7d03ca0] [c0000000000092c0] .do_one_initcall+0x80/0x19c
[c0000000c7d03d90] [c0000000000c0540] .SyS_init_module+0xe0/0x244
[c0000000c7d03e30] [c000000000008534] syscall_exit+0x0/0x40
Instruction dump:
7f84e378 e87e8020 38c604d0 e8e902ea 4827fced 60000000 2fbf0000 80bd0004 
409e0010 e8de8028 38e0ffff 4800000c <e8ff02ea> 38df04d0 7fa4eb78 811d0008 
---[ end trace f725820a6fa9dbb7 ]---
/init: line 21:    63 Segmentation fault      modprobe $file

I have attached the dmesg log here. Let me know if any other information 
is required.

Thanks
-Sachin

-- 

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


[-- Attachment #2: next11-boot --]
[-- Type: text/plain, Size: 9024 bytes --]

Using 007bc904 bytes for initrd buffer
Please wait, loading kernel...
Allocated 01100000 bytes for kernel @ 02300000
   Elf64 kernel loaded...
Loading ramdisk...
ramdisk loaded 007bc904 @ 03400000
OF stdout device is: /vdevice/vty@30000000
Preparing to boot Linux version 2.6.30-rc5-autotest-next-20090511 (root@mpower6lp5) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #1 SMP Mon May 11 16:01:58 IST 2009
Calling ibm,client-architecture... done
command line: root=/dev/sda3 sysrq=1 insmod=sym53c8xx insmod=ipr crashkernel=512M-:256M IDENT=1242039097 
memory layout at init:
  alloc_bottom : 0000000003bc0000
  alloc_top    : 0000000008000000
  alloc_top_hi : 0000000008000000
  rmo_top      : 0000000008000000
  ram_top      : 0000000008000000
instantiating rtas at 0x00000000074e0000... done
boot cpu hw idx 0000000000000000
copying OF device tree...
Building dt strings...
Building dt structure...
Device tree strings 0x0000000003bd0000 -> 0x0000000003bd15c2
Device tree struct  0x0000000003be0000 -> 0x0000000003c00000
Calling quiesce...
returning from prom_init
Crash kernel location must be 0x2000000
Reserving 256MB of memory at 32MB for crashkernel (System RAM: 4096MB)
Phyp-dump disabled at boot time
Using pSeries machine description
Using 1TB segments
Found initrd at 0xc000000003400000:0xc000000003bbc904
console [udbg0] enabled
Partition configured for 2 cpus.
CPU maps initialized for 2 threads per core
Starting Linux PPC64 #1 SMP Mon May 11 16:01:58 IST 2009
-----------------------------------------------------
ppc64_pft_size                = 0x1a
physicalMemorySize            = 0x100000000
htab_hash_mask                = 0x7ffff
-----------------------------------------------------
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 2.6.30-rc5-autotest-next-20090511 (root@mpower6lp5) (gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux) ) #1 SMP Mon May 11 16:01:58 IST 2009
[boot]0012 Setup Arch
EEH: No capable adapters found
PPC64 nvram contains 15360 bytes
Zone PFN ranges:
  DMA      0x00000000 -> 0x00010000
  Normal   0x00010000 -> 0x00010000
Movable zone start PFN for each node
early_node_map[2] active PFN ranges
    2: 0x00000000 -> 0x0000e000
    3: 0x0000e000 -> 0x00010000
Could not find start_pfn for node 0
[boot]0015 Setup Done
Built 3 zonelists in Node order, mobility grouping on.  Total pages: 65472
Policy zone: DMA
Kernel command line: root=/dev/sda3 sysrq=1 insmod=sym53c8xx insmod=ipr crashkernel=512M-:256M IDENT=1242039097 
Experimental hierarchical RCU implementation.
RCU-based detection of stalled CPUs is enabled.
Experimental hierarchical RCU init done.
NR_IRQS:512
[boot]0020 XICS Init
[boot]0021 XICS Done
PID hash table entries: 4096 (order: 12, 32768 bytes)
clocksource: timebase mult[7d0000] shift[22] registered
Console: colour dummy device 80x25
console handover: boot [udbg0] -> real [hvc0]
allocated 2621440 bytes of page_cgroup
please try cgroup_disable=memory option if you don't want
freeing bootmem node 2
freeing bootmem node 3
Memory: 3881920k/4194304k available (8896k kernel code, 312384k reserved, 2048k data, 4287k bss, 448k init)
Calibrating delay loop... 1022.36 BogoMIPS (lpj=5111808)
Security Framework initialized
SELinux:  Disabled at boot.
Dentry cache hash table entries: 524288 (order: 6, 4194304 bytes)
Inode-cache hash table entries: 262144 (order: 5, 2097152 bytes)
Mount-cache hash table entries: 4096
Initializing cgroup subsys ns
Initializing cgroup subsys cpuacct
Initializing cgroup subsys memory
Initializing cgroup subsys devices
Initializing cgroup subsys freezer
Processor 1 found.
Brought up 2 CPUs
net_namespace: 1936 bytes
NET: Registered protocol family 16
IBM eBus Device Driver
PCI: Probing PCI hardware
bio: create slab <bio-0> at 0
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Failed to register trace events module notifier
NET: Registered protocol family 2
IP route cache hash table entries: 32768 (order: 2, 262144 bytes)
TCP established hash table entries: 131072 (order: 5, 2097152 bytes)
TCP bind hash table entries: 65536 (order: 5, 2097152 bytes)
TCP: Hash tables configured (established 131072 bind 65536)
TCP reno registered
NET: Registered protocol family 1
Unpacking initramfs...
IOMMU table initialized, virtual merging enabled
audit: initializing netlink socket (disabled)
type=2000 audit(1242039145.533:1): initialized
Kprobe smoke test started
Kprobe smoke test passed successfully
HugeTLB registered 16 MB page size, pre-allocated 0 pages
HugeTLB registered 16 GB page size, pre-allocated 0 pages
VFS: Disk quotas dquot_6.5.2
Dquot-cache hash table entries: 8192 (order 0, 65536 bytes)
Btrfs loaded
msgmni has been set to 7580
alg: No test for stdrng (krng)
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered (default)
pci_hotplug: PCI Hot Plug PCI Core version: 0.5
rpaphp: RPA HOT Plug PCI Controller Driver version: 0.1
Generic RTC Driver v1.07
Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
pmac_zilog: 0.6 (Benjamin Herrenschmidt <benh@kernel.crashing.org>)
input: Macintosh mouse button emulation as /devices/virtual/input/input0
Uniform Multi-Platform E-IDE driver
ide-gd driver 1.18
IBM eHEA ethernet device driver (Release EHEA_0101)
ehea: eth0: Jumbo frames are disabled
ehea: eth0 -> logical port id #2
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
mice: PS/2 mouse device common for all mice
EDAC MC: Ver: 2.1.0 May 11 2009
usbcore: registered new interface driver hiddev
usbcore: registered new interface driver usbhid
usbhid: v2.6:USB HID core driver
TCP cubic registered
NET: Registered protocol family 15
registered taskstats version 1
Freeing unused kernel memory: 448k freed
doing fast boot
SysRq : Changing Loglevel
Loglevel set to 1
BUG: spinlock bad magic on CPU#1, modprobe/63
Unable to handle kernel paging request for data at address 0xffffc994838
Faulting instruction address: 0xc00000000035f5a8
Oops: Kernel access of bad area, sig: 11 [#1]
SMP NR_CPUS=1024 DEBUG_PAGEALLOC NUMA pSeries
Modules linked in: scsi_mod(+)
NIP: c00000000035f5a8 LR: c00000000035f58c CTR: 0000000000136f8c
REGS: c0000000c7d03500 TRAP: 0300   Not tainted  (2.6.30-rc5-autotest-next-20090511)
MSR: 8000000000009032 <EE,ME,IR,DR>  CR: 28222484  XER: 0000000f
DAR: 00000ffffc994838, DSISR: 0000000040000000
TASK = c0000000c7cf0a80[63] 'modprobe' THREAD: c0000000c7d00000 CPU: 1
GPR00: c00000000035f58c c0000000c7d03780 c000000000aaeed8 0000000000000031 
GPR04: 0000000000000000 00000000585cf4e0 0000000000673580 80000000565a6cc0 
GPR08: 0000000000000000 c0000000009ebf50 0000000000000000 c0000000009ebf38 
GPR12: 0000000028222482 c000000000b82600 0000000000000000 0000000000000000 
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000 
GPR20: 0000000000000018 ffffffffffffffff c0000000009bbe40 0000000000000010 
GPR24: 0000000000210d00 c0000000c6caff80 c0000000dfc732a0 c000000000f61380 
GPR28: c0000000007c8350 c0000000008a4280 c000000000a2f928 00000ffffc994550 
NIP [c00000000035f5a8] .spin_bug+0x90/0xd4
LR [c00000000035f58c] .spin_bug+0x74/0xd4
Call Trace:
[c0000000c7d03780] [c00000000035f58c] .spin_bug+0x74/0xd4 (unreliable)
[c0000000c7d03810] [c00000000035f890] ._raw_spin_lock+0x48/0x184
[c0000000c7d038b0] [c0000000005d67d8] ._spin_lock+0x10/0x24
[c0000000c7d03920] [c00000000013fbdc] .__slab_alloc_page+0x344/0x3cc
[c0000000c7d039e0] [c000000000141168] .kmem_cache_alloc+0x13c/0x21c
[c0000000c7d03aa0] [c000000000141b04] .kmem_cache_create+0x294/0x2a8
[c0000000c7d03b90] [d000000000ea14cc] .scsi_init_queue+0x38/0x170 [scsi_mod]
[c0000000c7d03c20] [d000000000ea13c8] .init_scsi+0x1c/0xe8 [scsi_mod]
[c0000000c7d03ca0] [c0000000000092c0] .do_one_initcall+0x80/0x19c
[c0000000c7d03d90] [c0000000000c0540] .SyS_init_module+0xe0/0x244
[c0000000c7d03e30] [c000000000008534] syscall_exit+0x0/0x40
Instruction dump:
7f84e378 e87e8020 38c604d0 e8e902ea 4827fced 60000000 2fbf0000 80bd0004 
409e0010 e8de8028 38e0ffff 4800000c <e8ff02ea> 38df04d0 7fa4eb78 811d0008 
---[ end trace f725820a6fa9dbb7 ]---
/init: line 21:    63 Segmentation fault      modprobe $file
Creating device nodes with udev
udevd version 128 started


After the udevadm settle timeout, the events queue contains:

632: /devices/vio/30000007


Boot logging started on /dev/hvc0(/dev/console) at Mon May 11 10:52:56 2009


After the udevadm settle timeout, the events queue contains:

632: /devices/vio/30000007




After the udevadm settle timeout, the events queue contains:

632: /devices/vio/30000007




After the udevadm settle timeout, the events queue contains:

632: /devices/vio/30000007


Waiting for device /dev/sda3 to appear: ..............................Could not find /dev/sda3.
Want me to fall back to /dev/sda3? (Y/n) 


^ permalink raw reply

* Re: [PATCH 08/15] powerpc/cell: Extract duplicated IOPTE_* to <asm/iommu.h>
From: Geert Uytterhoeven @ 2009-05-11  7:24 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linux-fbdev-devel, Arnd Bergmann, linux-kernel, linuxppc-dev,
	cbe-oss-dev
In-Reply-To: <20090510190825.GB23659@lst.de>

On Sun, 10 May 2009, Christoph Hellwig wrote:
> On Fri, May 08, 2009 at 04:01:17PM +0200, Geert Uytterhoeven wrote:
> > +/* Cell page table entries */
> > +#define IOPTE_PP_W		0x8000000000000000ul /* protection: write */
> > +#define IOPTE_PP_R		0x4000000000000000ul /* protection: read */
> > +#define IOPTE_M			0x2000000000000000ul /* coherency required */
> > +#define IOPTE_SO_R		0x1000000000000000ul /* ordering: writes */
> > +#define IOPTE_SO_RW             0x1800000000000000ul /* ordering: r & w */
> > +#define IOPTE_RPN_Mask		0x07fffffffffff000ul /* RPN */
> > +#define IOPTE_H			0x0000000000000800ul /* cache hint */
> > +#define IOPTE_IOID_Mask		0x00000000000007fful /* ioid */
> 
> If this is in a global header it should probably have a CELL_ prefix.

Fair enough; I'll use CBE_, as that's shorter and used for the other
definitions in arch/powerpc/include/asm/cell-*.h, too.

With kind regards,

Geert Uytterhoeven
Software Architect
Techsoft Centre

Technology and Software Centre Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium

Phone:    +32 (0)2 700 8453
Fax:      +32 (0)2 700 8622
E-mail:   Geert.Uytterhoeven@sonycom.com
Internet: http://www.sony-europe.com/

A division of Sony Europe (Belgium) N.V.
VAT BE 0413.825.160 · RPR Brussels
Fortis · BIC GEBABEBB · IBAN BE41293037680010

^ permalink raw reply


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