Re: Why is arch/s390/crypto/Kconfig sourced when building for another arch ?

2007-03-30 Thread Jan Glauber
Hi Thomas,

 with 2.6.20.4 it works great, but when switching to 2.6.21-rcX it breaks 
 with this:
 
 drivers/crypto/Kconfig:55: can't open file arch/s390/crypto/Kconfig

arch/s390/crypto/Kconfig is included there since that is the right place
for the config options to show up.

 I tried to fix drivers/crypto/Kconfig by changing the code to:
 
 if S390
 source arch/s390/crypto/Kconfig
 endif
 
 but it still gets sourced...

You would need something like:

source arch/s390/crypto/Kconfig
depends on S390

But that is not implemented and I doubt it will since deleting parts of
the kernel tree is not something that is required to work.

Jan

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


Re: Why is arch/s390/crypto/Kconfig sourced when building for another arch ?

2007-03-30 Thread Jan Glauber
On Fri, 2007-03-30 at 05:55 -0400, Robert P. J. Day wrote:
   i'm betting the S390 folks would *really* hate that idea but, if you
 look closely, the generic Kconfig file *already* has some
 arch-dependent content:
 
 ...
 config CRYPTO_DEV_PADLOCK
 tristate Support for VIA PadLock ACE
 depends on X86_32 -
 ...

Yes, but the padlock driver is located under drivers/crypto. The s390
crypto stuff is not. It is under arch/s390/crypto, thats why the Kconfig
file is there...

Both solutions (the current and your proposed) are somehow ugly. 
I don't care too much, where the Kconfig entries are, as long as it
works. So if you're interested in changing it go forward and post a
patch...

Jan

   i think it's a matter of deciding how to be consistent.  either you
 allow individual architectures to define their own additional Kconfig
 files or you don't.  mixing the two approaches is a recipe for
 confusion.
 
 rday
 
 

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


Re: Module init call vs symbols exporting race?

2007-11-12 Thread Jan Glauber
On Sat, 2007-11-10 at 18:27 +1100, Rusty Russell wrote:
 We fail rather than sleep in the dependency isn't ready case.  Partially 
 because it's not happened before, but partially because we risk nasty loops.

If we fail since we have to in the dependency isn't ready case then
the warning seems quite useless. I'll send a patch in a seperate mail
to remove the warning.

-jang

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


[PATCH] module loader should not complain about unknown symbol

2007-11-12 Thread Jan Glauber
If module A depends on module B and module B has not yet finished its
init() the module loader may print a warning about an unknown symbol.

This happens if module B is still in state MODULE_STATE_COMING,
as module A runs into resolve_symbol() for a symbol from module B.
resolve_symbol() return 0 in that case and causes the warning.

---
Signed-off-by: Jan Glauber [EMAIL PROTECTED]

Index: linux-2.6/kernel/module.c
===
--- linux-2.6.orig/kernel/module.c  2007-11-12 13:53:44.0 +
+++ linux-2.6/kernel/module.c   2007-11-12 13:54:33.0 +
@@ -1411,8 +1411,8 @@
if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
break;
 
-   printk(KERN_WARNING %s: Unknown symbol %s\n,
-  mod-name, strtab + sym[i].st_name);
+   DEBUGP(%s: Unknown symbol %s\n, mod-name,
+  strtab + sym[i].st_name);
ret = -ENOENT;
break;

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


Re: [PATCH] module loader should not complain about unknown symbol

2007-11-14 Thread Jan Glauber
On Tue, 2007-11-13 at 13:52 +1100, Rusty Russell wrote: 
 On Tuesday 13 November 2007 09:23:12 Rusty Russell wrote:
  Better might be to put in a waitqueue and wake it up whenever a module is
  deleted or changes status.  Then use_module() can wait if
  strong_try_module_get() returns -EBUSY (up to 30 seconds, then print a
  warning and fail).
 
 And here it is.  Does it work for you Jan?

No, it hangs at boot time after starting udev. All CPUs are in
cpu_idle(). Unfortunately I've had no time for further debugging and
I'll be offline for the next 10 days...

-jang

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


[RFC PATCH 0/2] use virtual time for CFS on s390

2007-10-23 Thread Jan Glauber
Hi Ingo,

an outcome from the previous discussion about a virtual sched_clock() on s390
was that scheduler_tick() should also be called based on virtual time.
The second patch changes the scheduler_tick() call to only happen after a tick
passed for the virtual cpu.

The patches cause nothing obvious to break, numbers from top look sane but 
I've seen something strange...

For a simple make -j6 workload top reports processes very often to be in 
state defunct. Thats' not terribly wrong since this can happens also 
without the patches but I wonder if this indicates that the scheduler behaves
badly and does less often schedule the parent processes that gathers the 
waiting zombie processes?

Are there any indicators in the sched_debug output that I could look for?

Jan

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


[RFC PATCH 1/2] virtual sched_clock() for s390

2007-10-23 Thread Jan Glauber
From: Jan Glauber [EMAIL PROTECTED] 
From: Christian Borntraeger [EMAIL PROTECTED] 

This patch introduces a cpu time clock for s390 (only ticking if
the virtual cpu is running) and bases the s390 implementation of
sched_clock() on it.

The time slice length on a virtual cpu can be anything between the
calculated time slice and zero. In reality this doesn't seem to be
problem, since the scheduler is fair enough to not let a single
process starve but the current implementation can lead to inefficient
short time slices.

By providing a 'virtual' sched_clock() we improve the scheduler
fairness, regardless of scheduling decisions from the hypervisor.
We also lay a foundation to base process accouting on virtual cpu
time without CONFIG_VIRT_CPU_ACCOUNTING.

Signed-off-by: Jan Glauber [EMAIL PROTECTED]
Signed-off-by: Christian Borntraeger [EMAIL PROTECTED]
CC: Martin Schwidefsky [EMAIL PROTECTED]

---
 arch/s390/kernel/time.c  |   30 +--
 arch/s390/kernel/vtime.c |   52 ---
 include/asm-s390/timer.h |2 +
 3 files changed, 70 insertions(+), 14 deletions(-)

Index: linux-2.6/arch/s390/kernel/time.c
===
--- linux-2.6.orig/arch/s390/kernel/time.c
+++ linux-2.6/arch/s390/kernel/time.c
@@ -62,21 +62,27 @@ static u64 jiffies_timer_cc;
 static u64 xtime_cc;
 
 /*
- * Scheduler clock - returns current time in nanosec units.
+ * Monotonic_clock - returns # of nanoseconds passed since time_init()
  */
-unsigned long long sched_clock(void)
+unsigned long long monotonic_clock(void)
 {
-   return ((get_clock() - jiffies_timer_cc) * 125)  9;
+   return ((get_clock() - jiffies_timer_cc)  9) * 125;
 }
+EXPORT_SYMBOL(monotonic_clock);
 
 /*
- * Monotonic_clock - returns # of nanoseconds passed since time_init()
+ * Scheduler clock - returns current time in nanosec units.
+ * Now based on virtual cpu time to only account time the guest
+ * was actually running.
  */
-unsigned long long monotonic_clock(void)
+unsigned long long sched_clock(void)
 {
-   return sched_clock();
+#ifdef CONFIG_VIRT_TIMER
+   return s390_cpu_clock();
+#else
+   return monotonic_clock();
+#endif
 }
-EXPORT_SYMBOL(monotonic_clock);
 
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
 {
@@ -348,13 +354,15 @@ void __init time_init(void)
/* Enable TOD clock interrupts on the boot cpu. */
init_cpu_timer();
 
-#ifdef CONFIG_NO_IDLE_HZ
-   nohz_init();
-#endif
-
+   /* The virtual timer must be ready on the first tick, therefore,
+  The vtime notifier callback must be registered first */
 #ifdef CONFIG_VIRT_TIMER
vtime_init();
 #endif
+
+#ifdef CONFIG_NO_IDLE_HZ
+   nohz_init();
+#endif
 }
 
 /*
Index: linux-2.6/arch/s390/kernel/vtime.c
===
--- linux-2.6.orig/arch/s390/kernel/vtime.c
+++ linux-2.6/arch/s390/kernel/vtime.c
@@ -3,8 +3,9 @@
  *Virtual cpu timer based timer functions.
  *
  *  S390 version
- *Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *Copyright 2004,2007 IBM Corp.
  *Author(s): Jan Glauber [EMAIL PROTECTED]
+ *   Christian Borntraeger [EMAIL PROTECTED]
  */
 
 #include linux/module.h
@@ -26,6 +27,44 @@
 
 static ext_int_info_t ext_int_info_timer;
 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+static DEFINE_PER_CPU(struct vtimer_list, cpu_clock_timer);
+
+/*
+ * read the remaining time of a virtual timer running on the current cpu
+ */
+static unsigned long long read_cpu_timer(struct vtimer_list *timer)
+{
+   struct vtimer_queue *vt_list;
+   unsigned long flags;
+   __u64 done;
+
+   local_irq_save(flags);
+
+   BUG_ON(timer-cpu != smp_processor_id());
+
+   vt_list = per_cpu(virt_cpu_timer, timer-cpu);
+   asm volatile (STPT %0 : =m (done));
+
+   done = timer-expires - vt_list-offset - (vt_list-to_expire - done);
+   local_irq_restore(flags);
+   return done;
+}
+
+/*
+ * Cpu clock, returns cpu time in nanosec units.
+ * Must be called with preemption disabled.
+ */
+unsigned long long s390_cpu_clock(void)
+{
+   __u64 remaining = read_cpu_timer(__get_cpu_var(cpu_clock_timer));
+   return ((VTIMER_MAX_SLICE - remaining)  9) * 125;
+}
+
+/* expire after 142 years ... */
+static void cpu_clock_timer_callback(unsigned long data)
+{
+   BUG();
+}
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -148,7 +187,7 @@ static void start_cpu_timer(void)
vt_list = __get_cpu_var(virt_cpu_timer);
 
/* CPU timer interrupt is pending, don't reprogramm it */
-   if (vt_list-idle  1LL63)
+   if ((s64) vt_list-idle  0)
return;
 
if (!list_empty(vt_list-list))
@@ -174,7 +213,7 @@ static void stop_cpu_timer(void)
 * If the CPU timer is negative we don't reprogramm
 * it because we will get instantly an interrupt

[RFC PATCH 2/2] base scheduler_tick() on virtual time

2007-10-23 Thread Jan Glauber
Make the scheduler_tick() dependent on the s390 cpu timer so it gets only 
called after
a virtual cpu has completed a tick. Together with the virtual sched_clock() 
this 
should make the scheduler decisions for s390 based on virtual time.

Signed-off-by: Jan Glauber [EMAIL PROTECTED]
Signed-off-by: Martin Schwidefsky [EMAIL PROTECTED]

---
 arch/s390/kernel/time.c|4 
 arch/s390/kernel/vtime.c   |7 ++-
 include/asm-s390/lowcore.h |8 ++--
 include/asm-s390/timer.h   |4 
 4 files changed, 16 insertions(+), 7 deletions(-)

Index: linux-2.6/include/asm-s390/timer.h
===
--- linux-2.6.orig/include/asm-s390/timer.h
+++ linux-2.6/include/asm-s390/timer.h
@@ -14,6 +14,10 @@
 
 #include linux/timer.h
 
+/* change this if you have some constant time drift */
+#define USECS_PER_JIFFY ((unsigned long) 100/HZ)
+#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY  12)
+
 #define VTIMER_MAX_SLICE (0x7000LL)
 
 struct vtimer_list {
Index: linux-2.6/include/asm-s390/lowcore.h
===
--- linux-2.6.orig/include/asm-s390/lowcore.h
+++ linux-2.6/include/asm-s390/lowcore.h
@@ -83,6 +83,7 @@
 #define __LC_JIFFY_TIMER   0xC80
 #define __LC_CURRENT   0xC90
 #define __LC_INT_CLOCK 0xC98
+#define __LC_VIRT_TICK 0xCA0
 #else /* __s390x__ */
 #define __LC_IRB   0x210
 #define __LC_SYNC_ENTER_TIMER  0x250
@@ -106,6 +107,7 @@
 #define __LC_JIFFY_TIMER   0xDC0
 #define __LC_CURRENT   0xDD8
 #define __LC_INT_CLOCK 0xDE8
+#define __LC_VIRT_TICK 0xDF0
 #endif /* __s390x__ */
 

@@ -282,7 +284,8 @@ struct _lowcore
__u32current_task; /* 0xc90 */
__u32softirq_pending;  /* 0xc94 */
__u64int_clock;/* 0xc98 */
-__u8 pad11[0xe00-0xca0];   /* 0xca0 */
+   __u64virt_tick;/* 0xca0 */
+   __u8 pad11[0xe00-0xca8];   /* 0xca8 */
 
 /* 0xe00 is used as indicator for dump tools */
 /* whether the kernel died with panic() or not */
@@ -374,7 +377,8 @@ struct _lowcore
__u64current_task; /* 0xdd8 */
__u64softirq_pending;  /* 0xde0 */
__u64int_clock;/* 0xde8 */
-__u8 pad12[0xe00-0xdf0];   /* 0xdf0 */
+   __u64virt_tick;/* 0xdf0 */
+   __u8 pad12[0xe00-0xdf8];   /* 0xdf8 */
 
 /* 0xe00 is used as indicator for dump tools */
 /* whether the kernel died with panic() or not */
Index: linux-2.6/arch/s390/kernel/time.c
===
--- linux-2.6.orig/arch/s390/kernel/time.c
+++ linux-2.6/arch/s390/kernel/time.c
@@ -40,10 +40,6 @@
 #include asm/timer.h
 #include asm/etr.h
 
-/* change this if you have some constant time drift */
-#define USECS_PER_JIFFY ((unsigned long) 100/HZ)
-#define CLK_TICKS_PER_JIFFY ((unsigned long) USECS_PER_JIFFY  12)
-
 /* The value of the TOD clock for 1.1.1970. */
 #define TOD_UNIX_EPOCH 0x7d91048bca00ULL
 
Index: linux-2.6/arch/s390/kernel/vtime.c
===
--- linux-2.6.orig/arch/s390/kernel/vtime.c
+++ linux-2.6/arch/s390/kernel/vtime.c
@@ -85,6 +85,7 @@ void account_tick_vtime(struct task_stru
=m (S390_lowcore.last_update_clock) );
S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock;
+   S390_lowcore.virt_tick += timer - S390_lowcore.last_update_timer;
 
cputime = S390_lowcore.user_timer  12;
rcu_user_flag = cputime != 0;
@@ -107,7 +108,11 @@ void account_tick_vtime(struct task_stru
run_local_timers();
if (rcu_pending(smp_processor_id()))
rcu_check_callbacks(smp_processor_id(), rcu_user_flag);
-   scheduler_tick();
+
+   while (S390_lowcore.virt_tick = CLK_TICKS_PER_JIFFY) {
+   S390_lowcore.virt_tick -= CLK_TICKS_PER_JIFFY;
+   scheduler_tick();
+   }
run_posix_cpu_timers(tsk);
 }
 


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


[RFC PATCH 03/10] s390/bitops: find leftmost bit instruction support

2012-11-14 Thread Jan Glauber
The flogr instruction scans a bitmap starting from the leftmost bit.
Implement support for these bitops. This could be useful to scan
bitmaps like an interrupt vector set by the hardware starting
at the leftmost bit.

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/bitops.h | 81 ++
 1 file changed, 81 insertions(+)

diff --git a/arch/s390/include/asm/bitops.h b/arch/s390/include/asm/bitops.h
index 6f57389..1542293 100644
--- a/arch/s390/include/asm/bitops.h
+++ b/arch/s390/include/asm/bitops.h
@@ -640,6 +640,87 @@ static inline unsigned long find_first_bit(const unsigned 
long * addr,
 }
 #define find_first_bit find_first_bit
 
+/*
+ * Big endian variant whichs starts bit counting from left using
+ * the flogr (find leftmost one) instruction.
+ */
+static inline unsigned long __flo_word(unsigned long nr, unsigned long val)
+{
+   register unsigned long bit asm(2) = val;
+   register unsigned long out asm(3);
+
+   asm volatile (
+  .insn   rre,0xb983,%[bit],%[bit]\n
+   : [bit] +d (bit), [out] =d (out) : : cc);
+   return nr + bit;
+}
+
+/*
+ * 64 bit special left bitops format:
+ * order in memory:
+ *00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
+ *10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
+ *20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
+ *30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
+ * after that follows the next long with bit numbers
+ *40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
+ *50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
+ *60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
+ *70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
+ * The reason for this bit ordering is the fact that
+ * the hardware sets bits in a bitmap starting at bit 0
+ * and we don't want to scan the bitmap from the 'wrong
+ * end'.
+ */
+static inline unsigned long find_first_bit_left(const unsigned long *addr,
+   unsigned long size)
+{
+   unsigned long bytes, bits;
+
+   if (!size)
+   return 0;
+   bytes = __ffs_word_loop(addr, size);
+   bits = __flo_word(bytes * 8, __load_ulong_be(addr, bytes));
+   return (bits  size) ? bits : size;
+}
+
+static inline int find_next_bit_left(const unsigned long *addr,
+unsigned long size,
+unsigned long offset)
+{
+   const unsigned long *p;
+   unsigned long bit, set;
+
+   if (offset = size)
+   return size;
+   bit = offset  (__BITOPS_WORDSIZE - 1);
+   offset -= bit;
+   size -= offset;
+   p = addr + offset / __BITOPS_WORDSIZE;
+   if (bit) {
+   set = __flo_word(0, *p  (~0UL  bit));
+   if (set = size)
+   return size + offset;
+   if (set  __BITOPS_WORDSIZE)
+   return set + offset;
+   offset += __BITOPS_WORDSIZE;
+   size -= __BITOPS_WORDSIZE;
+   p++;
+   }
+   return offset + find_first_bit_left(p, size);
+}
+
+#define for_each_set_bit_left(bit, addr, size) \
+   for ((bit) = find_first_bit_left((addr), (size));   \
+(bit)  (size);\
+(bit) = find_next_bit_left((addr), (size), (bit) + 1))
+
+/* same as for_each_set_bit() but use bit as value to start with */
+#define for_each_set_bit_left_cont(bit, addr, size)\
+   for ((bit) = find_next_bit_left((addr), (size), (bit)); \
+(bit)  (size);\
+(bit) = find_next_bit_left((addr), (size), (bit) + 1))
+
 /**
  * find_next_zero_bit - find the first zero bit in a memory region
  * @addr: The address to base the search on
-- 
1.7.12.4

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


[RFC PATCH 10/10] vga: compile fix, disable vga for s390

2012-11-14 Thread Jan Glauber
Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 drivers/gpu/vga/Kconfig | 2 +-
 include/video/vga.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index f348388..29437ea 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -1,7 +1,7 @@
 config VGA_ARB
bool VGA Arbitration if EXPERT
default y
-   depends on PCI
+   depends on (PCI  !S390)
help
  Some legacy VGA devices implemented on PCI typically have the same
  hard-decoded addresses as they did on ISA. When multiple PCI devices
diff --git a/include/video/vga.h b/include/video/vga.h
index cac567f..7978d31 100644
--- a/include/video/vga.h
+++ b/include/video/vga.h
@@ -19,7 +19,9 @@
 
 #include linux/types.h
 #include asm/io.h
+#ifndef __s390x__
 #include asm/vga.h
+#endif
 #include asm/byteorder.h
 
 
-- 
1.7.12.4

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


[RFC PATCH 09/10] s390/pci: add PCI Kconfig options

2012-11-14 Thread Jan Glauber
Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/Kconfig | 56 +--
 1 file changed, 50 insertions(+), 6 deletions(-)

diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index 5dba755..e3dd4aec 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -34,12 +34,6 @@ config GENERIC_BUG
 config GENERIC_BUG_RELATIVE_POINTERS
def_bool y
 
-config NO_IOMEM
-   def_bool y
-
-config NO_DMA
-   def_bool y
-
 config ARCH_DMA_ADDR_T_64BIT
def_bool 64BIT
 
@@ -58,6 +52,12 @@ config KEXEC
 config AUDIT_ARCH
def_bool y
 
+config NO_IOPORT
+   def_bool y
+
+config PCI_QUIRKS
+   def_bool n
+
 config S390
def_bool y
select USE_GENERIC_SMP_HELPERS if SMP
@@ -423,6 +423,50 @@ config QDIO
 
  If unsure, say Y.
 
+menuconfig PCI
+   bool PCI support 
+   default y
+   depends on 64BIT 
+   select ARCH_SUPPORTS_MSI
+   select PCI_MSI
+   help
+ Enable PCI support.
+
+if PCI
+
+config PCI_NR_FUNCTIONS
+   int Maximum number of PCI functions (1-4096)
+   range 1 4096
+   default 64
+   help
+ This allows you to specify the maximum number of PCI functions which
+ this kernel will support.
+
+source drivers/pci/Kconfig
+source drivers/pci/pcie/Kconfig
+source drivers/pci/hotplug/Kconfig
+
+endif  # PCI
+
+config PCI_DOMAINS
+   def_bool PCI
+
+config HAS_IOMEM
+   def_bool PCI
+
+config IOMMU_HELPER
+   def_bool PCI
+
+config HAS_DMA
+   def_bool PCI
+   select HAVE_DMA_API_DEBUG
+
+config NEED_SG_DMA_LENGTH
+   def_bool PCI
+
+config HAVE_DMA_ATTRS
+   def_bool PCI
+
 config CHSC_SCH
def_tristate m
prompt Support for CHSC subchannels
-- 
1.7.12.4

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


[RFC PATCH 02/10] s390/pci: CLP interface

2012-11-14 Thread Jan Glauber
CLP instructions are used to query the firmware about detected PCI
functions, the attributes of those functions and to enable or disable
a PCI function. The CLP interface is the equivalent to a PCI bus scan.

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/clp.h |  28 
 arch/s390/include/asm/pci.h |   7 +
 arch/s390/include/asm/pci_clp.h | 182 +++
 arch/s390/pci/Makefile  |   2 +-
 arch/s390/pci/pci.c |  28 
 arch/s390/pci/pci_clp.c | 317 
 6 files changed, 563 insertions(+), 1 deletion(-)
 create mode 100644 arch/s390/include/asm/clp.h
 create mode 100644 arch/s390/include/asm/pci_clp.h
 create mode 100644 arch/s390/pci/pci_clp.c

diff --git a/arch/s390/include/asm/clp.h b/arch/s390/include/asm/clp.h
new file mode 100644
index 000..6c3aecc
--- /dev/null
+++ b/arch/s390/include/asm/clp.h
@@ -0,0 +1,28 @@
+#ifndef _ASM_S390_CLP_H
+#define _ASM_S390_CLP_H
+
+/* CLP common request  response block size */
+#define CLP_BLK_SIZE   (PAGE_SIZE * 2)
+
+struct clp_req_hdr {
+   u16 len;
+   u16 cmd;
+} __packed;
+
+struct clp_rsp_hdr {
+   u16 len;
+   u16 rsp;
+} __packed;
+
+/* CLP Response Codes */
+#define CLP_RC_OK  0x0010  /* Command request successfully 
*/
+#define CLP_RC_CMD 0x0020  /* Command code not recognized 
*/
+#define CLP_RC_PERM0x0030  /* Command not authorized */
+#define CLP_RC_FMT 0x0040  /* Invalid command request 
format */
+#define CLP_RC_LEN 0x0050  /* Invalid command request 
length */
+#define CLP_RC_8K  0x0060  /* Command requires 8K LPCB */
+#define CLP_RC_RESNOT0 0x0070  /* Reserved field not zero */
+#define CLP_RC_NODATA  0x0080  /* No data available */
+#define CLP_RC_FC_UNKNOWN  0x0100  /* Function code not recognized 
*/
+
+#endif
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 5e286ce..079b7e2 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -8,6 +8,7 @@
 
 #include asm-generic/pci.h
 #include asm-generic/pci-dma-compat.h
+#include asm/pci_clp.h
 
 #define PCIBIOS_MIN_IO 0x1000
 #define PCIBIOS_MIN_MEM0x1000
@@ -76,6 +77,12 @@ void zpci_stop_device(struct zpci_dev *);
 void zpci_free_device(struct zpci_dev *);
 int zpci_scan_device(struct zpci_dev *);
 
+/* CLP */
+int clp_find_pci_devices(void);
+int clp_add_pci_device(u32, u32, int);
+int clp_enable_fh(struct zpci_dev *, u8);
+int clp_disable_fh(struct zpci_dev *);
+
 /* Helpers */
 struct zpci_dev *get_zdev(struct pci_dev *);
 struct zpci_dev *get_zdev_by_fid(u32);
diff --git a/arch/s390/include/asm/pci_clp.h b/arch/s390/include/asm/pci_clp.h
new file mode 100644
index 000..e97163e
--- /dev/null
+++ b/arch/s390/include/asm/pci_clp.h
@@ -0,0 +1,182 @@
+#ifndef _ASM_S390_PCI_CLP_H
+#define _ASM_S390_PCI_CLP_H
+
+#include asm/clp.h
+
+/*
+ * Call Logical Processor - Command Codes
+ */
+#define CLP_LIST_PCI   0x0002
+#define CLP_QUERY_PCI_FN   0x0003
+#define CLP_QUERY_PCI_FNGRP0x0004
+#define CLP_SET_PCI_FN 0x0005
+
+/* PCI function handle list entry */
+struct clp_fh_list_entry {
+   u16 device_id;
+   u16 vendor_id;
+   u32 config_state :  1;
+   u32  : 31;
+   u32 fid;/* PCI function id */
+   u32 fh; /* PCI function handle */
+} __packed;
+
+#define CLP_RC_SETPCIFN_FH 0x0101  /* Invalid PCI fn handle */
+#define CLP_RC_SETPCIFN_FHOP   0x0102  /* Fn handle not valid for op */
+#define CLP_RC_SETPCIFN_DMAAS  0x0103  /* Invalid DMA addr space */
+#define CLP_RC_SETPCIFN_RES0x0104  /* Insufficient resources */
+#define CLP_RC_SETPCIFN_ALRDY  0x0105  /* Fn already in requested state */
+#define CLP_RC_SETPCIFN_ERR0x0106  /* Fn in permanent error state */
+#define CLP_RC_SETPCIFN_RECPND 0x0107  /* Error recovery pending */
+#define CLP_RC_SETPCIFN_BUSY   0x0108  /* Fn busy */
+#define CLP_RC_LISTPCI_BADRT   0x010a  /* Resume token not recognized */
+#define CLP_RC_QUERYPCIFG_PFGID0x010b  /* Unrecognized PFGID */
+
+/* request or response block header length */
+#define LIST_PCI_HDR_LEN   32
+
+/* Number of function handles fitting in response block */
+#define CLP_FH_LIST_NR_ENTRIES \
+   ((CLP_BLK_SIZE - 2 * LIST_PCI_HDR_LEN)  \
+   / sizeof(struct clp_fh_list_entry))
+
+#define CLP_SET_ENABLE_PCI_FN  0   /* Yes, 0 enables it */
+#define CLP_SET_DISABLE_PCI_FN 1   /* Yes, 1 disables it */
+
+#define CLP_UTIL_STR_LEN   64
+
+/* List PCI functions request */
+struct clp_req_list_pci {
+   struct clp_req_hdr hdr;
+   u32 fmt :  4;   /* cmd request block format */
+   u32 : 28;
+   u64 reserved1

[RFC PATCH 08/10] s390/pci: s390 specific PCI sysfs attributes

2012-11-14 Thread Jan Glauber
Add some s390 specific sysfs attributes to the PCI device directory.
The following attributes are introduced:
- function_id (PCI function ID)
- function_handle (PCI function handle)
- pchid (PCI channel ID)
- pfgid (PCI function group ID aka PCI root complex)

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/pci.h |  4 +++
 arch/s390/pci/Makefile  |  2 +-
 arch/s390/pci/pci.c |  6 
 arch/s390/pci/pci_sysfs.c   | 86 +
 4 files changed, 97 insertions(+), 1 deletion(-)
 create mode 100644 arch/s390/pci/pci_sysfs.c

diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 739d9f1..39057e4 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -141,6 +141,10 @@ struct zpci_dev *get_zdev(struct pci_dev *);
 struct zpci_dev *get_zdev_by_fid(u32);
 bool zpci_fid_present(u32);
 
+/* sysfs */
+int zpci_sysfs_add_device(struct device *);
+void zpci_sysfs_remove_device(struct device *);
+
 /* DMA */
 int zpci_dma_init(void);
 void zpci_dma_exit(void);
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
index 7e36f42..ab0827b 100644
--- a/arch/s390/pci/Makefile
+++ b/arch/s390/pci/Makefile
@@ -3,4 +3,4 @@
 #
 
 obj-$(CONFIG_PCI)  += pci.o pci_dma.o pci_clp.o pci_msi.o \
-  pci_event.o
+  pci_sysfs.o pci_event.o
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index c523594..0723b10 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -628,6 +628,7 @@ static void zpci_remove_device(struct pci_dev *pdev)
dev_info(pdev-dev, Removing device %u\n, zdev-domain);
zdev-state = ZPCI_FN_STATE_CONFIGURED;
zpci_dma_exit_device(zdev);
+   zpci_sysfs_remove_device(pdev-dev);
zpci_unmap_resources(pdev);
list_del(zdev-entry); /* can be called from init */
zdev-pdev = NULL;
@@ -676,6 +677,11 @@ void pcibios_disable_device(struct pci_dev *pdev)
pdev-sysdata = NULL;
 }
 
+int pcibios_add_platform_entries(struct pci_dev *pdev)
+{
+   return zpci_sysfs_add_device(pdev-dev);
+}
+
 int zpci_request_irq(unsigned int irq, irq_handler_t handler, void *data)
 {
int msi_nr = irq_to_msi_nr(irq);
diff --git a/arch/s390/pci/pci_sysfs.c b/arch/s390/pci/pci_sysfs.c
new file mode 100644
index 000..a42cce6
--- /dev/null
+++ b/arch/s390/pci/pci_sysfs.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright IBM Corp. 2012
+ *
+ * Author(s):
+ *   Jan Glauber j...@linux.vnet.ibm.com
+ */
+
+#define COMPONENT zPCI
+#define pr_fmt(fmt) COMPONENT :  fmt
+
+#include linux/kernel.h
+#include linux/stat.h
+#include linux/pci.h
+
+static ssize_t show_fid(struct device *dev, struct device_attribute *attr,
+   char *buf)
+{
+   struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, 
dev));
+
+   sprintf(buf, 0x%08x\n, zdev-fid);
+   return strlen(buf);
+}
+static DEVICE_ATTR(function_id, S_IRUGO, show_fid, NULL);
+
+static ssize_t show_fh(struct device *dev, struct device_attribute *attr,
+  char *buf)
+{
+   struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, 
dev));
+
+   sprintf(buf, 0x%08x\n, zdev-fh);
+   return strlen(buf);
+}
+static DEVICE_ATTR(function_handle, S_IRUGO, show_fh, NULL);
+
+static ssize_t show_pchid(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+   struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, 
dev));
+
+   sprintf(buf, 0x%04x\n, zdev-pchid);
+   return strlen(buf);
+}
+static DEVICE_ATTR(pchid, S_IRUGO, show_pchid, NULL);
+
+static ssize_t show_pfgid(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+   struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, 
dev));
+
+   sprintf(buf, 0x%02x\n, zdev-pfgid);
+   return strlen(buf);
+}
+static DEVICE_ATTR(pfgid, S_IRUGO, show_pfgid, NULL);
+
+static struct device_attribute *zpci_dev_attrs[] = {
+   dev_attr_function_id,
+   dev_attr_function_handle,
+   dev_attr_pchid,
+   dev_attr_pfgid,
+   NULL,
+};
+
+int zpci_sysfs_add_device(struct device *dev)
+{
+   int i, rc = 0;
+
+   for (i = 0; zpci_dev_attrs[i]; i++) {
+   rc = device_create_file(dev, zpci_dev_attrs[i]);
+   if (rc)
+   goto error;
+   }
+   return 0;
+
+error:
+   while (--i = 0)
+   device_remove_file(dev, zpci_dev_attrs[i]);
+   return rc;
+}
+
+void zpci_sysfs_remove_device(struct device *dev)
+{
+   int i;
+
+   for (i = 0; zpci_dev_attrs[i]; i++)
+   device_remove_file(dev, zpci_dev_attrs[i]);
+}
-- 
1.7.12.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please

[RFC PATCH 07/10] s390/pci: PCI hotplug support via SCLP

2012-11-14 Thread Jan Glauber
Add SCLP PCI configure/deconfigure and implement a PCI hotplug
controller (s390_pci_hpc). The hotplug controller creates a slot
for every PCI function in stand-by or configured state. The PCI
functions are named after the PCI function ID (fid). By writing to
the power attribute in /sys/bus/pci/slots/fid/power the PCI function
is moved to stand-by or configured state. If moved to the configured
state the device is automatically scanned by the s390 PCI layer.

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/pci.h|  11 ++
 arch/s390/include/asm/sclp.h   |   2 +
 arch/s390/pci/pci.c|   9 ++
 drivers/pci/hotplug/Kconfig|  11 ++
 drivers/pci/hotplug/Makefile   |   1 +
 drivers/pci/hotplug/s390_pci_hpc.c | 252 +
 drivers/s390/char/sclp.h   |   3 +-
 drivers/s390/char/sclp_cmd.c   |  64 +-
 8 files changed, 351 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pci/hotplug/s390_pci_hpc.c

diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 3dc2cb6..739d9f1 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -95,6 +95,11 @@ struct zpci_dev {
enum pci_bus_speed max_bus_speed;
 };
 
+struct pci_hp_callback_ops {
+   int (*create_slot)  (struct zpci_dev *zdev);
+   void (*remove_slot) (struct zpci_dev *zdev);
+};
+
 static inline bool zdev_enabled(struct zpci_dev *zdev)
 {
return (zdev-fh  (1UL  31)) ? true : false;
@@ -140,4 +145,10 @@ bool zpci_fid_present(u32);
 int zpci_dma_init(void);
 void zpci_dma_exit(void);
 
+/* Hotplug */
+extern struct mutex zpci_list_lock;
+extern struct list_head zpci_list;
+extern struct pci_hp_callback_ops hotplug_ops;
+extern unsigned int pci_probe;
+
 #endif
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index e62a555..8337886 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -55,5 +55,7 @@ int sclp_chp_read_info(struct sclp_chp_info *info);
 void sclp_get_ipl_info(struct sclp_ipl_info *info);
 bool sclp_has_linemode(void);
 bool sclp_has_vt220(void);
+int sclp_pci_configure(u32 fid);
+int sclp_pci_deconfigure(u32 fid);
 
 #endif /* _ASM_S390_SCLP_H */
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 5a2ef9e..c523594 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -47,7 +47,12 @@
 
 /* list of all detected zpci devices */
 LIST_HEAD(zpci_list);
+EXPORT_SYMBOL_GPL(zpci_list);
 DEFINE_MUTEX(zpci_list_lock);
+EXPORT_SYMBOL_GPL(zpci_list_lock);
+
+struct pci_hp_callback_ops hotplug_ops;
+EXPORT_SYMBOL_GPL(hotplug_ops);
 
 static DECLARE_BITMAP(zpci_domain, ZPCI_NR_DEVICES);
 static DEFINE_SPINLOCK(zpci_domain_lock);
@@ -935,6 +940,8 @@ int zpci_create_device(struct zpci_dev *zdev)
 
mutex_lock(zpci_list_lock);
list_add_tail(zdev-entry, zpci_list);
+   if (hotplug_ops.create_slot)
+   hotplug_ops.create_slot(zdev);
mutex_unlock(zpci_list_lock);
 
if (zdev-state == ZPCI_FN_STATE_STANDBY)
@@ -948,6 +955,8 @@ int zpci_create_device(struct zpci_dev *zdev)
 out_start:
mutex_lock(zpci_list_lock);
list_del(zdev-entry);
+   if (hotplug_ops.remove_slot)
+   hotplug_ops.remove_slot(zdev);
mutex_unlock(zpci_list_lock);
 out_bus:
zpci_free_domain(zdev);
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index b0e46de..0594c4a 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -151,4 +151,15 @@ config HOTPLUG_PCI_SGI
 
  When in doubt, say N.
 
+config HOTPLUG_PCI_S390
+   tristate System z PCI Hotplug Support
+   depends on S390  64BIT
+   help
+ Say Y here if you want to use the System z PCI Hotplug
+ driver for PCI devices. Without this driver it is not
+  possible to access stand-by PCI functions nor to deconfigure
+  PCI functions.
+
+ When in doubt, say Y.
+
 endif # HOTPLUG_PCI
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index c459cd4..47ec8c8 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
 obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR)+= rpadlpar_io.o
 obj-$(CONFIG_HOTPLUG_PCI_SGI)  += sgi_hotplug.o
 obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
+obj-$(CONFIG_HOTPLUG_PCI_S390) += s390_pci_hpc.o
 
 # acpiphp_ibm extends acpiphp, so should be linked afterwards.
 
diff --git a/drivers/pci/hotplug/s390_pci_hpc.c 
b/drivers/pci/hotplug/s390_pci_hpc.c
new file mode 100644
index 000..d4de895
--- /dev/null
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -0,0 +1,252 @@
+/*
+ * PCI Hot Plug Controller Driver for System z
+ *
+ * Copyright 2012 IBM Corp.
+ *
+ * Author(s):
+ *   Jan Glauber j...@linux.vnet.ibm.com
+ */
+
+#define COMPONENT zPCI hpc
+#define pr_fmt(fmt

[RFC PATCH 06/10] s390/pci: CHSC PCI support for error and availability events

2012-11-14 Thread Jan Glauber
Add CHSC store-event-information support for PCI (notfication type 2)
and report error and availability events to the PCI architecture layer.

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/pci.h |   4 ++
 arch/s390/pci/Makefile  |   3 +-
 arch/s390/pci/pci_event.c   |  93 ++
 drivers/s390/cio/chsc.c | 156 +++-
 4 files changed, 211 insertions(+), 45 deletions(-)
 create mode 100644 arch/s390/pci/pci_event.c

diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index ca48caf..3dc2cb6 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -127,6 +127,10 @@ void zpci_teardown_msi_irq(struct zpci_dev *, struct 
msi_desc *);
 int zpci_msihash_init(void);
 void zpci_msihash_exit(void);
 
+/* Error handling and recovery */
+void zpci_event_error(void *);
+void zpci_event_availability(void *);
+
 /* Helpers */
 struct zpci_dev *get_zdev(struct pci_dev *);
 struct zpci_dev *get_zdev_by_fid(u32);
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile
index 4590596..7e36f42 100644
--- a/arch/s390/pci/Makefile
+++ b/arch/s390/pci/Makefile
@@ -2,4 +2,5 @@
 # Makefile for the s390 PCI subsystem.
 #
 
-obj-$(CONFIG_PCI)  += pci.o pci_dma.o pci_clp.o pci_msi.o
+obj-$(CONFIG_PCI)  += pci.o pci_dma.o pci_clp.o pci_msi.o \
+  pci_event.o
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
new file mode 100644
index 000..dbed8cd
--- /dev/null
+++ b/arch/s390/pci/pci_event.c
@@ -0,0 +1,93 @@
+/*
+ *  Copyright IBM Corp. 2012
+ *
+ *  Author(s):
+ *Jan Glauber j...@linux.vnet.ibm.com
+ */
+
+#define COMPONENT zPCI
+#define pr_fmt(fmt) COMPONENT :  fmt
+
+#include linux/kernel.h
+#include linux/pci.h
+
+/* Content Code Description for PCI Function Error */
+struct zpci_ccdf_err {
+   u32 reserved1;
+   u32 fh; /* function handle */
+   u32 fid;/* function id */
+   u32 ett :  4;   /* expected table type */
+   u32 mvn : 12;   /* MSI vector number */
+   u32 dmaas   :  8;   /* DMA address space */
+   u32 :  6;
+   u32 q   :  1;   /* event qualifier */
+   u32 rw  :  1;   /* read/write */
+   u64 faddr;  /* failing address */
+   u32 reserved3;
+   u16 reserved4;
+   u16 pec;/* PCI event code */
+} __packed;
+
+/* Content Code Description for PCI Function Availability */
+struct zpci_ccdf_avail {
+   u32 reserved1;
+   u32 fh; /* function handle */
+   u32 fid;/* function id */
+   u32 reserved2;
+   u32 reserved3;
+   u32 reserved4;
+   u32 reserved5;
+   u16 reserved6;
+   u16 pec;/* PCI event code */
+} __packed;
+
+static void zpci_event_log_err(struct zpci_ccdf_err *ccdf)
+{
+   struct zpci_dev *zdev = get_zdev_by_fid(ccdf-fid);
+
+   dev_err(zdev-pdev-dev, event code: 0x%x\n, ccdf-pec);
+}
+
+static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf)
+{
+   struct zpci_dev *zdev = get_zdev_by_fid(ccdf-fid);
+
+   pr_err(%s%s: availability event: fh: 0x%x  fid: 0x%x  event code: 0x%x 
 reason:,
+   (zdev) ? dev_driver_string(zdev-pdev-dev) : ?,
+   (zdev) ? dev_name(zdev-pdev-dev) : ?,
+   ccdf-fh, ccdf-fid, ccdf-pec);
+   print_hex_dump(KERN_CONT, ccdf, DUMP_PREFIX_OFFSET,
+  16, 1, ccdf, sizeof(*ccdf), false);
+
+   switch (ccdf-pec) {
+   case 0x0301:
+   zpci_enable_device(zdev);
+   break;
+   case 0x0302:
+   clp_add_pci_device(ccdf-fid, ccdf-fh, 0);
+   break;
+   case 0x0306:
+   clp_find_pci_devices();
+   break;
+   default:
+   break;
+   }
+}
+
+void zpci_event_error(void *data)
+{
+   struct zpci_ccdf_err *ccdf = data;
+   struct zpci_dev *zdev;
+
+   zpci_event_log_err(ccdf);
+   zdev = get_zdev_by_fid(ccdf-fid);
+   if (!zdev) {
+   pr_err(Error event for unknown fid: %x, ccdf-fid);
+   return;
+   }
+}
+
+void zpci_event_availability(void *data)
+{
+   zpci_event_log_avail(data);
+}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 4d51a7c..68e80e2 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -1,7 +1,7 @@
 /*
  *   S/390 common I/O routines -- channel subsystem call
  *
- *Copyright IBM Corp. 1999, 2010
+ *Copyright IBM Corp. 1999,2012
  *Author(s): Ingo Adlung (adl...@de.ibm.com)
  *  Cornelia Huck (cornelia.h...@de.ibm.com)
  *  Arnd Bergmann (ar...@de.ibm.com)
@@ -14,6 +14,7 @@
 #include linux/slab.h
 #include linux/init.h
 #include linux/device.h

[RFC PATCH 04/10] s390/pci: PCI adapter interrupts for MSI/MSI-X

2012-11-14 Thread Jan Glauber
Support PCI adapter interrupts using the Single-IRQ-mode. Single-IRQ-mode
disables an adapter IRQ automatically after delivering it until the SIC
instruction enables it again. This is used to reduce the number of IRQs
for streaming workloads.

Up to 64 MSI handlers can be registered per PCI function.
A hash table is used to map interrupt numbers to MSI descriptors.
The interrupt vector is scanned using the flogr instruction.
Only MSI/MSI-X interrupts are supported, no legacy INTs.

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/hw_irq.h |  22 ++
 arch/s390/include/asm/irq.h|  12 ++
 arch/s390/include/asm/isc.h|   1 +
 arch/s390/include/asm/pci.h|  27 +++
 arch/s390/kernel/irq.c |   2 +
 arch/s390/pci/Makefile |   2 +-
 arch/s390/pci/pci.c| 464 -
 arch/s390/pci/pci_clp.c|   3 +
 arch/s390/pci/pci_msi.c| 141 +
 drivers/pci/msi.c  |  10 +-
 include/linux/irq.h|  10 +-
 11 files changed, 685 insertions(+), 9 deletions(-)
 create mode 100644 arch/s390/include/asm/hw_irq.h
 create mode 100644 arch/s390/pci/pci_msi.c

diff --git a/arch/s390/include/asm/hw_irq.h b/arch/s390/include/asm/hw_irq.h
new file mode 100644
index 000..7e3d258
--- /dev/null
+++ b/arch/s390/include/asm/hw_irq.h
@@ -0,0 +1,22 @@
+#ifndef _HW_IRQ_H
+#define _HW_IRQ_H
+
+#include linux/msi.h
+#include linux/pci.h
+
+static inline struct msi_desc *irq_get_msi_desc(unsigned int irq)
+{
+   return __irq_get_msi_desc(irq);
+}
+
+/* Must be called with msi map lock held */
+static inline int irq_set_msi_desc(unsigned int irq, struct msi_desc *msi)
+{
+   if (!msi)
+   return -EINVAL;
+
+   msi-irq = irq;
+   return 0;
+}
+
+#endif
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index 6703dd9..e6972f8 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -33,6 +33,8 @@ enum interruption_class {
IOINT_APB,
IOINT_ADM,
IOINT_CSC,
+   IOINT_PCI,
+   IOINT_MSI,
NMI_NMI,
NR_IRQS,
 };
@@ -51,4 +53,14 @@ void service_subclass_irq_unregister(void);
 void measurement_alert_subclass_register(void);
 void measurement_alert_subclass_unregister(void);
 
+#ifdef CONFIG_LOCKDEP
+#  define disable_irq_nosync_lockdep(irq)  disable_irq_nosync(irq)
+#  define disable_irq_nosync_lockdep_irqsave(irq, flags) \
+   disable_irq_nosync(irq)
+#  define disable_irq_lockdep(irq) disable_irq(irq)
+#  define enable_irq_lockdep(irq)  enable_irq(irq)
+#  define enable_irq_lockdep_irqrestore(irq, flags) \
+   enable_irq(irq)
+#endif
+
 #endif /* _ASM_IRQ_H */
diff --git a/arch/s390/include/asm/isc.h b/arch/s390/include/asm/isc.h
index 5ae6064..68d7d68 100644
--- a/arch/s390/include/asm/isc.h
+++ b/arch/s390/include/asm/isc.h
@@ -18,6 +18,7 @@
 #define CHSC_SCH_ISC 7 /* CHSC subchannels */
 /* Adapter interrupts. */
 #define QDIO_AIRQ_ISC IO_SCH_ISC   /* I/O subchannel in qdio mode */
+#define PCI_ISC 2  /* PCI I/O subchannels */
 #define AP_ISC 6   /* adjunct processor (crypto) devices */
 
 /* Functions for registration of I/O interruption subclasses */
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 079b7e2..a9aadeb 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -20,6 +20,10 @@ void pci_iounmap(struct pci_dev *, void __iomem *);
 int pci_domain_nr(struct pci_bus *);
 int pci_proc_domain(struct pci_bus *);
 
+/* MSI arch hooks */
+#define arch_setup_msi_irqsarch_setup_msi_irqs
+#define arch_teardown_msi_irqs arch_teardown_msi_irqs
+
 #define ZPCI_BUS_NR0   /* default bus number */
 #define ZPCI_DEVFN 0   /* default device number */
 
@@ -29,6 +33,15 @@ int pci_proc_domain(struct pci_bus *);
 #define ZPCI_FC_BLOCKED0x20
 #define ZPCI_FC_DMA_ENABLED0x10
 
+struct msi_map {
+   unsigned long irq;
+   struct msi_desc *msi;
+   struct hlist_node msi_chain;
+};
+
+#define ZPCI_NR_MSI_VECS   64
+#define ZPCI_MSI_MASK  (ZPCI_NR_MSI_VECS - 1)
+
 enum zpci_state {
ZPCI_FN_STATE_RESERVED,
ZPCI_FN_STATE_STANDBY,
@@ -56,6 +69,12 @@ struct zpci_dev {
u8  pfgid;  /* function group ID */
u16 domain;
 
+   /* IRQ stuff */
+   u64 msi_addr;   /* MSI address */
+   struct zdev_irq_map *irq_map;
+   struct msi_map *msi_map[ZPCI_NR_MSI_VECS];
+   unsigned intaisb;   /* number of the summary bit */
+
struct zpci_bar_struct bars[PCI_BAR_COUNT];
 
enum pci_bus_speed max_bus_speed;
@@ -83,6 +102,14 @@ int clp_add_pci_device(u32, u32, int);
 int

[RFC PATCH 05/10] s390/pci: DMA support

2012-11-14 Thread Jan Glauber
Add DMA IOMMU support using 4K page table entries. Implement dma_map_ops.

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/include/asm/dma-mapping.h |  76 ++
 arch/s390/include/asm/dma.h |  19 +-
 arch/s390/include/asm/pci.h |  21 ++
 arch/s390/include/asm/pci_dma.h | 196 ++
 arch/s390/pci/Makefile  |   2 +-
 arch/s390/pci/pci.c |  36 +++
 arch/s390/pci/pci_clp.c |   4 +
 arch/s390/pci/pci_dma.c | 505 
 8 files changed, 848 insertions(+), 11 deletions(-)
 create mode 100644 arch/s390/include/asm/dma-mapping.h
 create mode 100644 arch/s390/include/asm/pci_dma.h
 create mode 100644 arch/s390/pci/pci_dma.c

diff --git a/arch/s390/include/asm/dma-mapping.h 
b/arch/s390/include/asm/dma-mapping.h
new file mode 100644
index 000..aab2158
--- /dev/null
+++ b/arch/s390/include/asm/dma-mapping.h
@@ -0,0 +1,76 @@
+#ifndef _ASM_S390_DMA_MAPPING_H
+#define _ASM_S390_DMA_MAPPING_H
+
+#include linux/kernel.h
+#include linux/types.h
+#include linux/mm.h
+#include linux/scatterlist.h
+#include linux/dma-attrs.h
+#include linux/dma-debug.h
+#include linux/io.h
+
+#define DMA_ERROR_CODE  (~(dma_addr_t) 0x0)
+
+extern struct dma_map_ops s390_dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+   return s390_dma_ops;
+}
+
+extern int dma_set_mask(struct device *dev, u64 mask);
+extern int dma_is_consistent(struct device *dev, dma_addr_t dma_handle);
+extern void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+  enum dma_data_direction direction);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+#include asm-generic/dma-mapping-common.h
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+   struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+   if (dma_ops-dma_supported == NULL)
+   return 1;
+   return dma_ops-dma_supported(dev, mask);
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t 
size)
+{
+   if (!dev-dma_mask)
+   return 0;
+   return addr + size - 1 = *dev-dma_mask;
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+   struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+   if (dma_ops-mapping_error)
+   return dma_ops-mapping_error(dev, dma_addr);
+   return (dma_addr == 0UL);
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+  dma_addr_t *dma_handle, gfp_t flag)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   void *ret;
+
+   ret = ops-alloc(dev, size, dma_handle, flag, NULL);
+   debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+   return ret;
+}
+
+static inline void dma_free_coherent(struct device *dev, size_t size,
+void *cpu_addr, dma_addr_t dma_handle)
+{
+   struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+   dma_ops-free(dev, size, cpu_addr, dma_handle, NULL);
+   debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#endif /* _ASM_S390_DMA_MAPPING_H */
diff --git a/arch/s390/include/asm/dma.h b/arch/s390/include/asm/dma.h
index 6fb6de4..de015d8 100644
--- a/arch/s390/include/asm/dma.h
+++ b/arch/s390/include/asm/dma.h
@@ -1,14 +1,13 @@
-/*
- *  S390 version
- */
-
-#ifndef _ASM_DMA_H
-#define _ASM_DMA_H
+#ifndef _ASM_S390_DMA_H
+#define _ASM_S390_DMA_H
 
-#include asm/io.h/* need byte IO */
+#include asm/io.h
 
+/*
+ * MAX_DMA_ADDRESS is ambiguous because on s390 its completely unrelated
+ * to DMA. It _is_ used for the s390 memory zone split at 2GB caused
+ * by the 31 bit heritage.
+ */
 #define MAX_DMA_ADDRESS 0x8000
 
-#define free_dma(x)do { } while (0)
-
-#endif /* _ASM_DMA_H */
+#endif /* _ASM_S390_DMA_H */
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index a9aadeb..ca48caf 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -75,8 +75,23 @@ struct zpci_dev {
struct msi_map *msi_map[ZPCI_NR_MSI_VECS];
unsigned intaisb;   /* number of the summary bit */
 
+   /* DMA stuff */
+   unsigned long   *dma_table;
+   spinlock_t  dma_table_lock;
+   int tlb_refresh;
+
+   spinlock_t  iommu_bitmap_lock;
+   unsigned long   *iommu_bitmap;
+   unsigned long   iommu_size;
+   unsigned long   iommu_pages;
+   unsigned intnext_bit;
+
struct zpci_bar_struct bars[PCI_BAR_COUNT];
 
+   u64 start_dma;  /* Start of available DMA addresses */
+   u64 end_dma;/* End of available DMA addresses */
+   u64 dma_mask;   /* DMA address space mask */
+
enum

[RFC PATCH 00/10] s390/pci: PCI support on System z

2012-11-14 Thread Jan Glauber
Hi,

this patchset based on 3.7-rc4 aims at adding PCI(e) support to the
System z (s390) architecture. PCI is currently not available on s390,
so this is early prototype code.

I'm posting in the hope to get some feedback and direction on the more humble
aspects of it.

Patches 01-05 are only split to ease the review, they belong functional
together and don't make much sense without each other.

PCI on the mainframe differs in some aspects from PCI on other platforms. 

The most notable difference is the use of instructions for memory
mapped IO. So on s390 the BAR spaces cannot be mapped to memory. To access 
the BAR spaces privileged instructions must be used (how that will be
addressed for user-space is not part of this patchset). See patch 01 for how
the read/write pci primitives are mapped to the s390 instructions.

Another difference is that the addresses of BARs from two different PCI
functions may be identical. That means we can't distinguish from an iomem
address which PCI device the address belongs to. Therefore s390 needs a
custom implementation of pci_iomap to remap iomem addresses using the bar
and device information provided by pci_iomap.

Device naming - the topology on System z is that every PCI function is attached
directly to a PCI root complex. Therefore we decided to use a domain number per
function and leave the bus, slot and function 0.

Next one - IRQs. s390 will use its existing adapter interrupt infrastructure
to deliver MSI/MSI-X interrupts. Legacy INTs are _not_ supported at all. 
The only thing that s390 needs is to close the gap between adapter interrupts
and MSI, in other words to locate a struct msi_desc from an IRQ number.
For that I've implemented a simple hash, see patch 04.

Then there is Kconfig, see patch 09, which gives s390 a bunch of options that
we would rather avoid. Like VGA support, sound subsystem, etc. I do not have a
solution how to disable these subsystems. We would like to limit the subsystems
that become available on s390 because the usable PCI hardware will be limited
to a small number of hand-picked and supported PCI cards.

There are several options I can imagine:

a) Don't disable anything - that would result in lots of drivers builtable on
   s390 that are not supported and weird error reports

b) Introduce negative options for whole subsystems like we have already with
   NO_IOPORT, so maybe NO_USB, NO_SOUND, ...

c) Introduce a special CONFIG_PCI_S390 and add that explicitely to all
   subsystems that we want to enable on s390

None of the above looks like the obvious winner to me.


Hope to get some feedback,
TIA, Jan

Jan Glauber (10):
  s390/pci: base support
  s390/pci: CLP interface
  s390/bitops: find leftmost bit instruction support
  s390/pci: PCI adapter interrupts for MSI/MSI-X
  s390/pci: DMA support
  s390/pci: CHSC PCI support for error and availability events
  s390/pci: PCI hotplug support via SCLP
  s390/pci: s390 specific PCI sysfs attributes
  s390/pci: add PCI Kconfig options
  vga: compile fix, disable vga for s390

 arch/s390/Kbuild|1 +
 arch/s390/Kconfig   |   56 +-
 arch/s390/include/asm/bitops.h  |   81 +++
 arch/s390/include/asm/clp.h |   28 +
 arch/s390/include/asm/dma-mapping.h |   76 +++
 arch/s390/include/asm/dma.h |   19 +-
 arch/s390/include/asm/hw_irq.h  |   22 +
 arch/s390/include/asm/io.h  |   55 +-
 arch/s390/include/asm/irq.h |   12 +
 arch/s390/include/asm/isc.h |1 +
 arch/s390/include/asm/pci.h |  156 -
 arch/s390/include/asm/pci_clp.h |  182 ++
 arch/s390/include/asm/pci_dma.h |  196 +++
 arch/s390/include/asm/pci_insn.h|  280 +
 arch/s390/include/asm/pci_io.h  |  194 +++
 arch/s390/include/asm/sclp.h|2 +
 arch/s390/kernel/dis.c  |   15 +
 arch/s390/kernel/irq.c  |2 +
 arch/s390/pci/Makefile  |6 +
 arch/s390/pci/pci.c | 1098 +++
 arch/s390/pci/pci_clp.c |  324 +++
 arch/s390/pci/pci_dma.c |  505 
 arch/s390/pci/pci_event.c   |   93 +++
 arch/s390/pci/pci_msi.c |  141 +
 arch/s390/pci/pci_sysfs.c   |   86 +++
 drivers/gpu/vga/Kconfig |2 +-
 drivers/pci/hotplug/Kconfig |   11 +
 drivers/pci/hotplug/Makefile|1 +
 drivers/pci/hotplug/s390_pci_hpc.c  |  252 
 drivers/pci/msi.c   |   10 +-
 drivers/s390/char/sclp.h|3 +-
 drivers/s390/char/sclp_cmd.c|   64 +-
 drivers/s390/cio/chsc.c |  156 +++--
 include/asm-generic/io.h|   21 +-
 include/linux/irq.h |   10 +-
 include/video/vga.h |2 +
 36 files changed, 4084 insertions(+), 79 deletions(-)
 create mode 100644 arch/s390/include/asm/clp.h
 create mode 100644 arch/s390/include/asm/dma-mapping.h
 create mode

[RFC PATCH 01/10] s390/pci: base support

2012-11-14 Thread Jan Glauber
Add PCI support for s390, (only 64 bit mode is supported by hardware):
- PCI facility tests
- PCI instructions: pcilg, pcistg, pcistb, stpcifc, mpcifc, rpcit
- map readb/w/l/q and writeb/w/l/q to pcilg and pcistg instructions
- pci_iomap implementation
- memcpy_fromio/toio
- pci_root_ops using special pcilg/pcistg
- device, bus and domain allocation

Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
---
 arch/s390/Kbuild |   1 +
 arch/s390/include/asm/io.h   |  55 +++-
 arch/s390/include/asm/pci.h  |  82 +-
 arch/s390/include/asm/pci_insn.h | 280 
 arch/s390/include/asm/pci_io.h   | 194 ++
 arch/s390/kernel/dis.c   |  15 ++
 arch/s390/pci/Makefile   |   5 +
 arch/s390/pci/pci.c  | 557 +++
 include/asm-generic/io.h |  21 +-
 9 files changed, 1201 insertions(+), 9 deletions(-)
 create mode 100644 arch/s390/include/asm/pci_insn.h
 create mode 100644 arch/s390/include/asm/pci_io.h
 create mode 100644 arch/s390/pci/Makefile
 create mode 100644 arch/s390/pci/pci.c

diff --git a/arch/s390/Kbuild b/arch/s390/Kbuild
index cc45d25..647c3ec 100644
--- a/arch/s390/Kbuild
+++ b/arch/s390/Kbuild
@@ -6,3 +6,4 @@ obj-$(CONFIG_S390_HYPFS_FS) += hypfs/
 obj-$(CONFIG_APPLDATA_BASE)+= appldata/
 obj-$(CONFIG_MATHEMU)  += math-emu/
 obj-y  += net/
+obj-$(CONFIG_PCI)  += pci/
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index 559e921..5f3766b 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -9,9 +9,9 @@
 #ifndef _S390_IO_H
 #define _S390_IO_H
 
+#include linux/kernel.h
 #include asm/page.h
-
-#define IO_SPACE_LIMIT 0x
+#include asm/pci_io.h
 
 /*
  * Change virtual addresses to physical addresses and vv.
@@ -24,10 +24,11 @@ static inline unsigned long virt_to_phys(volatile void * 
address)
   lra %0,0(%1)\n
   jz  0f\n
   la  %0,0\n
- 0:
+0:
 : =a (real_address) : a (address) : cc);
-return real_address;
+   return real_address;
 }
+#define virt_to_phys virt_to_phys
 
 static inline void * phys_to_virt(unsigned long address)
 {
@@ -42,4 +43,50 @@ void unxlate_dev_mem_ptr(unsigned long phys, void *addr);
  */
 #define xlate_dev_kmem_ptr(p)  p
 
+#define IO_SPACE_LIMIT 0
+
+#ifdef CONFIG_PCI
+
+#define ioremap_nocache(addr, size)ioremap(addr, size)
+#define ioremap_wc ioremap_nocache
+
+/* TODO: s390 cannot support io_remap_pfn_range... */
+#define io_remap_pfn_range(vma, vaddr, pfn, size, prot)\
+   remap_pfn_range(vma, vaddr, pfn, size, prot)
+
+static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
+{
+   return (void __iomem *) offset;
+}
+
+static inline void iounmap(volatile void __iomem *addr)
+{
+}
+
+/*
+ * s390 needs a private implementation of pci_iomap since ioremap with its
+ * offset parameter isn't sufficient. That's because BAR spaces are not
+ * disjunctive on s390 so we need the bar parameter of pci_iomap to find
+ * the corresponding device and create the mapping cookie.
+ */
+#define pci_iomap pci_iomap
+#define pci_iounmap pci_iounmap
+
+#define memcpy_fromio(dst, src, count) zpci_memcpy_fromio(dst, src, count)
+#define memcpy_toio(dst, src, count)   zpci_memcpy_toio(dst, src, count)
+#define memset_io(dst, val, count) zpci_memset_io(dst, val, count)
+
+#define __raw_readbzpci_read_u8
+#define __raw_readwzpci_read_u16
+#define __raw_readlzpci_read_u32
+#define __raw_readqzpci_read_u64
+#define __raw_writeb   zpci_write_u8
+#define __raw_writew   zpci_write_u16
+#define __raw_writel   zpci_write_u32
+#define __raw_writeq   zpci_write_u64
+
+#endif /* CONFIG_PCI */
+
+#include asm-generic/io.h
+
 #endif
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h
index 42a145c..5e286ce 100644
--- a/arch/s390/include/asm/pci.h
+++ b/arch/s390/include/asm/pci.h
@@ -1,10 +1,84 @@
 #ifndef __ASM_S390_PCI_H
 #define __ASM_S390_PCI_H
 
-/* S/390 systems don't have a PCI bus. This file is just here because some 
stupid .c code
- * includes it even if CONFIG_PCI is not set.
- */
+/* must be set before including asm-generic/pci.h */
 #define PCI_DMA_BUS_IS_PHYS (0)
+/* must be set before including pci_clp.h */
+#define PCI_BAR_COUNT  6
 
-#endif /* __ASM_S390_PCI_H */
+#include asm-generic/pci.h
+#include asm-generic/pci-dma-compat.h
 
+#define PCIBIOS_MIN_IO 0x1000
+#define PCIBIOS_MIN_MEM0x1000
+
+#define pcibios_assign_all_busses()(0)
+
+void __iomem *pci_iomap(struct pci_dev *, int, unsigned long);
+void pci_iounmap(struct pci_dev *, void __iomem *);
+int pci_domain_nr(struct pci_bus *);
+int pci_proc_domain(struct pci_bus *);
+
+#define ZPCI_BUS_NR0   /* default bus number */
+#define

Re: [PATCH] virtual sched_clock() for s390

2007-07-23 Thread Jan Glauber
On Fri, 2007-07-20 at 09:22 +0200, Ingo Molnar wrote:
 * Paul Mackerras [EMAIL PROTECTED] wrote:
  As with s390, 64-bit PowerPC also uses CONFIG_VIRT_CPU_ACCOUNTING. 
  That affects how tsk-utime and tsk-stime are accumulated (we call 
  account_user_time and account_system_time directly rather than calling 
  update_process_times) as well as the system hardirq/softirq time, idle 
  time, and stolen time.
 
 tsk-utime and tsk-stime is only used for a single purpose: to 
 determine the 'split' factor of how to split up the precise total time 
 between user and system time.
 
  When you say precise task statistics for /proc, where are they 
  accumulated?  I don't see any changes to the way that tsk-utime and 
  ctime are computed.
 
 we now use p-se.sum_exec_runtime that measures (in nanoseconds) the 
 precise amount of time spent executing (sum of system and user time) - 
 and -stime and -utime is used to determine the 'split'. [this allows 
 us to gather -stime and -utime via low-resolution sampling, while 
 keeping the 'total' precise. Accounting at every system entry point 
 would be quite expensive on most platforms.]

Using se.sum_exec_runtime to generate -utime and -stime breaks
the process accounting we have on s390 (and probably on PowerPC too).
With CONFIG_VIRT_CPU_ACCOUNTING we already have precise values in
-utime and -stime. Can we make the calculation of the CFS-based time
values conditional by CONFIG_VIRT_CPU_ACCOUNTING?

Jan

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

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


Re: [RFC][PATCH] Pseudo-random number generator

2007-01-16 Thread Jan Glauber
On Tue, 2006-12-05 at 14:07 +0100, Jan Glauber wrote:
 Yes, if an attacker knows the initial clock value a brute-force attack
 would be feasible to predict the output. But I don't know if the
 hardware completely relies on the clock values or if there is any
 internal state which is not visible by an attacker. I will try to find
 out more details...

OK, after some research I got a new proposal. What the hardware does 
internally is just a Triple-DES operation with 3 different keys.

That means with my old implementation the input for a TDES operation is
the buffer full of timestamps. If an attacker can guess the first timestamp
he knows the entire input, since the timestamp loop indeed produces 
timestamps with a constant offset. Therefore I'd like to replace the
timestamp loop with only a single timestamp, which has the following
advantages:

- it is as safe as the loop (since the additional timestamps contain very
  low entropy)
- its faster, since we don't have to overwrite the entire buffer
- the one timestamp still guarantees unique, non-repeating output values

Even if an attacker knows the input buffer for the next operation
(known-plaintext attack) it turns out that currently this attack is not
feasible against TDES. Therefore, as long as the key is not compromised
there is no way to guess the next output from the generator.

Jan

--
 arch/s390/crypto/Makefile   |1 
 arch/s390/crypto/crypt_s390.h   |3 
 arch/s390/crypto/crypt_s390_query.c |2 
 arch/s390/crypto/prng.c |  209 
 arch/s390/defconfig |1 
 drivers/s390/Kconfig|7 +
 6 files changed, 222 insertions(+), 1 deletion(-)

diff -urNp linux-2.6.orig/arch/s390/crypto/Makefile 
linux-2.6/arch/s390/crypto/Makefile
--- linux-2.6.orig/arch/s390/crypto/Makefile2006-11-17 10:26:35.0 
+0100
+++ linux-2.6/arch/s390/crypto/Makefile 2007-01-16 13:03:12.0 +0100
@@ -6,5 +6,6 @@ obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s
 obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
 obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
 obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
+obj-$(CONFIG_S390_PRNG) += prng.o
 
 obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o
diff -urNp linux-2.6.orig/arch/s390/crypto/crypt_s390.h 
linux-2.6/arch/s390/crypto/crypt_s390.h
--- linux-2.6.orig/arch/s390/crypto/crypt_s390.h2006-11-17 
10:26:35.0 +0100
+++ linux-2.6/arch/s390/crypto/crypt_s390.h 2007-01-16 13:03:12.0 
+0100
@@ -68,6 +68,7 @@ enum crypt_s390_kmc_func {
KMC_AES_192_DECRYPT  = CRYPT_S390_KMC | 0x13 | 0x80,
KMC_AES_256_ENCRYPT  = CRYPT_S390_KMC | 0x14,
KMC_AES_256_DECRYPT  = CRYPT_S390_KMC | 0x14 | 0x80,
+   KMC_PRNG = CRYPT_S390_KMC | 0x43,
 };
 
 /* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
@@ -147,7 +148,7 @@ crypt_s390_km(long func, void* param, u8
  * @param src: address of source memory area
  * @param src_len: length of src operand in bytes
  * @returns  zero for failure, 0 for the query func, number of processed bytes
- * for encryption/decryption funcs
+ * for encryption/decryption funcs
  */
 static inline int
 crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
diff -urNp linux-2.6.orig/arch/s390/crypto/crypt_s390_query.c 
linux-2.6/arch/s390/crypto/crypt_s390_query.c
--- linux-2.6.orig/arch/s390/crypto/crypt_s390_query.c  2006-11-17 
10:26:35.0 +0100
+++ linux-2.6/arch/s390/crypto/crypt_s390_query.c   2007-01-16 
13:03:12.0 +0100
@@ -54,6 +54,8 @@ static void query_available_functions(vo
crypt_s390_func_available(KMC_AES_192_ENCRYPT));
printk(KERN_INFO KMC_AES_256: %d\n,
crypt_s390_func_available(KMC_AES_256_ENCRYPT));
+   printk(KERN_INFO KMC_PRNG: %d\n,
+   crypt_s390_func_available(KMC_PRNG));
 
/* query available KIMD functions */
printk(KERN_INFO KIMD_QUERY: %d\n,
diff -urNp linux-2.6.orig/arch/s390/crypto/prng.c 
linux-2.6/arch/s390/crypto/prng.c
--- linux-2.6.orig/arch/s390/crypto/prng.c  1970-01-01 01:00:00.0 
+0100
+++ linux-2.6/arch/s390/crypto/prng.c   2007-01-16 13:04:45.0 +0100
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2006 IBM Corporation
+ * Author(s): Jan Glauber [EMAIL PROTECTED]
+ * Driver for the s390 pseudo random number generator
+ */
+#include linux/fs.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/miscdevice.h
+#include linux/module.h
+#include linux/moduleparam.h
+#include linux/random.h
+#include asm/debug.h
+#include asm/uaccess.h
+
+#include crypt_s390.h
+
+MODULE_LICENSE(GPL);
+MODULE_AUTHOR(Jan Glauber [EMAIL PROTECTED]);
+MODULE_DESCRIPTION(s390 PRNG interface);
+
+static int prng_chunk_size = 256;
+module_param(prng_chunk_size, int, 0);
+MODULE_PARM_DESC(prng_chunk_size, PRNG read chunk size in bytes);
+
+static int prng_entropy_limit = 4096;
+module_param

Re: [RFC][PATCH] Pseudo-random number generator

2006-12-07 Thread Jan Glauber
On Thu, 2006-12-07 at 16:06 +0100, Arnd Bergmann wrote:
 On Friday 01 December 2006 14:19, Jan Glauber wrote:
  I've chosen the char driver since it allows the user to decide which 
  pseudo-random
  numbers he wants to use. That means there is a new interface for the s390
  PRNG, called /dev/prandom.
  
  I would like to know if there are any objections, especially with the 
  chosen device
  name.
 
 This may be a stupid question, but what is it _good_ for? My understanding is
 that the crypt_s390_kmc() opcodes work in user mode as well as kernel mode, so
 you should not need a character device at all, but maybe just a small tool
 that spits prandom data to stdout.

Hm, why is /dev/urandom implemented in the kernel?

It could be done completely in user-space (like libica already does)
but I think having a device node where you can read from is the simplest
implementation. Also, if we can solve the security flaw we could use it
as replacement for /dev/urandom.

Jan

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


Re: [RFC][PATCH] Pseudo-random number generator

2006-12-08 Thread Jan Glauber
On Thu, 2006-12-07 at 19:43 +0100, Arnd Bergmann wrote:
 On Thursday 07 December 2006 16:19, Jan Glauber wrote:
  Hm, why is /dev/urandom implemented in the kernel?
  
  It could be done completely in user-space (like libica already does)
  but I think having a device node where you can read from is the simplest
  implementation. Also, if we can solve the security flaw we could use it
  as replacement for /dev/urandom.
 
 urandom is more useful, because can't be implemented in user space at
 all. /dev/urandom will use the real randomness from the kernel as a seed
 without depleting the entropy pool. How does your /dev/prandom device
 compare to /dev/urandom performance-wise? If it can be made to use
 the same input data and it turns out to be significantly faster, I can
 see some use for it.

The performance of the PRNG without constantly adding entropy is up tp
factor 40 faster than /dev/urandom ;- , depending on the block size of
the read.

With the current patch it performs not so well because of the STCKE loop
before every KMC. I think about removing them and changing the
periodically seed to use get_random_bytes instead.

Jan

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


[RFC][PATCH] Pseudo-random number generator

2006-12-01 Thread Jan Glauber
New s390 machines have hardware support for the generation of pseudo-random
numbers. This patch implements a simple char driver that exports this numbers
to user-space. Other possible implementations would have been:

* using the new hwrandom number generator API
PRO: reuse of an existing interface
CON: this API is for truly random data, not for pseudo-random numbers

* merging the s390 PRNG with the random pool implementation
PRO: no new interface, random numbers can be read through /dev/urandom
CON: complex implementation, could only use traditional /dev/urandom algorithm
 or hardware-accelerated implementation

I've chosen the char driver since it allows the user to decide which 
pseudo-random
numbers he wants to use. That means there is a new interface for the s390
PRNG, called /dev/prandom.

I would like to know if there are any objections, especially with the chosen 
device
name.

Jan

---
 arch/s390/crypto/Makefile   |1 
 arch/s390/crypto/crypt_s390.h   |3 
 arch/s390/crypto/crypt_s390_query.c |2 
 arch/s390/crypto/prng.c |  206 
 arch/s390/defconfig |1 
 drivers/s390/Kconfig|7 +
 include/asm-s390/timex.h|   12 ++
 7 files changed, 231 insertions(+), 1 deletion(-)

diff -urNp linux-2.5/arch/s390/crypto/Makefile 
linux-2.5_prng/arch/s390/crypto/Makefile
--- linux-2.5/arch/s390/crypto/Makefile 2005-12-06 16:11:12.0 +0100
+++ linux-2.5_prng/arch/s390/crypto/Makefile2006-12-01 13:04:27.0 
+0100
@@ -6,5 +6,6 @@ obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s
 obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
 obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
 obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
+obj-$(CONFIG_S390_PRNG) += prng.o
 
 obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o
diff -urNp linux-2.5/arch/s390/crypto/crypt_s390.h 
linux-2.5_prng/arch/s390/crypto/crypt_s390.h
--- linux-2.5/arch/s390/crypto/crypt_s390.h 2006-12-01 12:54:23.0 
+0100
+++ linux-2.5_prng/arch/s390/crypto/crypt_s390.h2006-12-01 
13:05:26.0 +0100
@@ -68,6 +68,7 @@ enum crypt_s390_kmc_func {
KMC_AES_192_DECRYPT  = CRYPT_S390_KMC | 0x13 | 0x80,
KMC_AES_256_ENCRYPT  = CRYPT_S390_KMC | 0x14,
KMC_AES_256_DECRYPT  = CRYPT_S390_KMC | 0x14 | 0x80,
+   KMC_PRNG = CRYPT_S390_KMC | 0x43,
 };
 
 /* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
@@ -147,7 +148,7 @@ crypt_s390_km(long func, void* param, u8
  * @param src: address of source memory area
  * @param src_len: length of src operand in bytes
  * @returns  zero for failure, 0 for the query func, number of processed bytes
- * for encryption/decryption funcs
+ * for encryption/decryption funcs
  */
 static inline int
 crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
diff -urNp linux-2.5/arch/s390/crypto/crypt_s390_query.c 
linux-2.5_prng/arch/s390/crypto/crypt_s390_query.c
--- linux-2.5/arch/s390/crypto/crypt_s390_query.c   2006-06-19 
14:01:10.0 +0200
+++ linux-2.5_prng/arch/s390/crypto/crypt_s390_query.c  2006-12-01 
13:05:46.0 +0100
@@ -54,6 +54,8 @@ static void query_available_functions(vo
crypt_s390_func_available(KMC_AES_192_ENCRYPT));
printk(KERN_INFO KMC_AES_256: %d\n,
crypt_s390_func_available(KMC_AES_256_ENCRYPT));
+   printk(KERN_INFO KMC_PRNG: %d\n,
+   crypt_s390_func_available(KMC_PRNG));
 
/* query available KIMD functions */
printk(KERN_INFO KIMD_QUERY: %d\n,
diff -urNp linux-2.5/arch/s390/crypto/prng.c 
linux-2.5_prng/arch/s390/crypto/prng.c
--- linux-2.5/arch/s390/crypto/prng.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.5_prng/arch/s390/crypto/prng.c  2006-12-01 13:06:50.0 
+0100
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2006 IBM Corporation
+ * Author(s): Jan Glauber [EMAIL PROTECTED]
+ * Driver for the s390 pseudo random number generator
+ */
+#include linux/fs.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/miscdevice.h
+#include linux/module.h
+#include linux/moduleparam.h
+#include linux/random.h
+#include asm/debug.h
+#include asm/uaccess.h
+
+#include crypt_s390.h
+
+MODULE_LICENSE(GPL);
+MODULE_AUTHOR(Jan Glauber [EMAIL PROTECTED]);
+MODULE_DESCRIPTION(s390 PRNG interface);
+
+static int prng_chunk_size = 32;
+module_param(prng_chunk_size, int, 0);
+MODULE_PARM_DESC(prng_chunk_size, PRNG read chunk size in bytes);
+
+static int prng_entropy_limit = 4096;
+module_param(prng_entropy_limit, int, 0);
+MODULE_PARM_DESC(prng_entropy_limit, PRNG add entropy after that much bytes 
were produced);
+
+/*
+ * Any one who considers arithmetical methods of producing random digits is,
+ * of course, in a state of sin. -- John von Neumann
+ */
+
+struct s390_prng_data {
+   unsigned long count; /* how many bytes were produced */
+   char *buf;
+};
+
+struct

Re: [RFC][PATCH] Pseudo-random number generator

2006-12-01 Thread Jan Glauber
On Fri, 2006-12-01 at 13:39 +, Alan wrote:
  * merging the s390 PRNG with the random pool implementation
  PRO: no new interface, random numbers can be read through /dev/urandom
  CON: complex implementation, could only use traditional /dev/urandom 
  algorithm
   or hardware-accelerated implementation
 
 Also PRO: Can be verified by non-IBM people, high resistance if there is
 a flaw (accidental or US government 8)) in the 390 hardware.

No, the interesting stuff is done internally in the hardware, we cannot
see it with both implementations.

  I've chosen the char driver since it allows the user to decide which 
  pseudo-random
  numbers he wants to use. That means there is a new interface for the s390
  PRNG, called /dev/prandom.
 
 And people can pipe this into the urandom layer if they wish.

Yes, a user can just symlink urandom to prandom and will have a faster
generator.

  +/* copied from libica, use a non-zero initial parameter block */
  +unsigned char parm_block[32] = {
  +0x0F,0x2B,0x8E,0x63,0x8C,0x8E,0xD2,0x52,0x64,0xB7,0xA0,0x7B,0x75,0x28,0xB8,0xF4,
  +0x75,0x5F,0xD2,0xA6,0x8D,0x97,0x11,0xFF,0x49,0xD8,0x23,0xF3,0x7E,0x21,0xEC,0xA0,
  +};
  +
 
 Global variables called p and parm_block. Plus parm_block appears to
 be const

Argh. I'll make them static.

 Also your register the misc device before allocating the buffer so it can
 be opened in theory before the alloc is done and crash.

Fixed. The misc_register is now done at the very end.

thanks,
Jan

---
 arch/s390/crypto/Makefile   |1 
 arch/s390/crypto/crypt_s390.h   |3 
 arch/s390/crypto/crypt_s390_query.c |2 
 arch/s390/crypto/prng.c |  203 
 arch/s390/defconfig |1 
 drivers/s390/Kconfig|7 +
 include/asm-s390/timex.h|   12 ++
 7 files changed, 228 insertions(+), 1 deletion(-)

diff -urNp linux-2.5/arch/s390/crypto/Makefile 
linux-2.5_prng/arch/s390/crypto/Makefile
--- linux-2.5/arch/s390/crypto/Makefile 2006-12-01 15:40:54.0 +0100
+++ linux-2.5_prng/arch/s390/crypto/Makefile2006-11-30 18:30:23.0 
+0100
@@ -6,5 +6,6 @@ obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s
 obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
 obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
 obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
+obj-$(CONFIG_S390_PRNG) += prng.o
 
 obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o
diff -urNp linux-2.5/arch/s390/crypto/crypt_s390.h 
linux-2.5_prng/arch/s390/crypto/crypt_s390.h
--- linux-2.5/arch/s390/crypto/crypt_s390.h 2006-12-01 15:40:54.0 
+0100
+++ linux-2.5_prng/arch/s390/crypto/crypt_s390.h2006-12-01 
15:38:00.0 +0100
@@ -68,6 +68,7 @@ enum crypt_s390_kmc_func {
KMC_AES_192_DECRYPT  = CRYPT_S390_KMC | 0x13 | 0x80,
KMC_AES_256_ENCRYPT  = CRYPT_S390_KMC | 0x14,
KMC_AES_256_DECRYPT  = CRYPT_S390_KMC | 0x14 | 0x80,
+   KMC_PRNG = CRYPT_S390_KMC | 0x43,
 };
 
 /* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
@@ -147,7 +148,7 @@ crypt_s390_km(long func, void* param, u8
  * @param src: address of source memory area
  * @param src_len: length of src operand in bytes
  * @returns  zero for failure, 0 for the query func, number of processed bytes
- * for encryption/decryption funcs
+ * for encryption/decryption funcs
  */
 static inline int
 crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len)
diff -urNp linux-2.5/arch/s390/crypto/crypt_s390_query.c 
linux-2.5_prng/arch/s390/crypto/crypt_s390_query.c
--- linux-2.5/arch/s390/crypto/crypt_s390_query.c   2006-12-01 
15:40:54.0 +0100
+++ linux-2.5_prng/arch/s390/crypto/crypt_s390_query.c  2006-12-01 
15:37:27.0 +0100
@@ -54,6 +54,8 @@ static void query_available_functions(vo
crypt_s390_func_available(KMC_AES_192_ENCRYPT));
printk(KERN_INFO KMC_AES_256: %d\n,
crypt_s390_func_available(KMC_AES_256_ENCRYPT));
+   printk(KERN_INFO KMC_PRNG: %d\n,
+   crypt_s390_func_available(KMC_PRNG));
 
/* query available KIMD functions */
printk(KERN_INFO KIMD_QUERY: %d\n,
diff -urNp linux-2.5/arch/s390/crypto/prng.c 
linux-2.5_prng/arch/s390/crypto/prng.c
--- linux-2.5/arch/s390/crypto/prng.c   1970-01-01 01:00:00.0 +0100
+++ linux-2.5_prng/arch/s390/crypto/prng.c  2006-12-01 16:14:22.0 
+0100
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2006 IBM Corporation
+ * Author(s): Jan Glauber [EMAIL PROTECTED]
+ * Driver for the s390 pseudo random number generator
+ */
+#include linux/fs.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/miscdevice.h
+#include linux/module.h
+#include linux/moduleparam.h
+#include linux/random.h
+#include asm/debug.h
+#include asm/uaccess.h
+
+#include crypt_s390.h
+
+MODULE_LICENSE(GPL);
+MODULE_AUTHOR(Jan Glauber [EMAIL PROTECTED]);
+MODULE_DESCRIPTION(s390 PRNG interface);
+
+static int

Re: [RFC][PATCH] Pseudo-random number generator

2006-12-05 Thread Jan Glauber
On Mon, 2006-12-04 at 11:15 -0500, [EMAIL PROTECTED] wrote:
 On Fri, 01 Dec 2006 14:19:15 +0100, Jan Glauber said:
  New s390 machines have hardware support for the generation of pseudo-random
  numbers. This patch implements a simple char driver that exports this 
  numbers
  to user-space. Other possible implementations would have been:
 
  +   for (i = 0; i  16; i++) {
  +   entropy[0] = get_clock();
  +   entropy[1] = get_clock();
  +   entropy[2] = get_clock();
  +   entropy[3] = get_clock();
 
 By the time this loop completes, we'll have done 64 get_clock() - and if an
 attacker has a good estimate of what the system clock has in it, they'll be
 able to guess all 64 values, since each pass through the loop will have fairly
 predictable timing.  So as a result, the pseudo-random stream will be a *lot*
 less random than one would hope for...

I completely agree. Filling the input buffer with timestamps looks quite
uncomfortable but was exactly what the hardware specification suggested.

At least for the initialisation of the PRNG I preferred get_random_bytes()
over get_clock to get a good initial seed. But get_random_bytes cannot
be used during normal operation since the PRNG read should not block.

  +   /*
  +* It shouldn't weaken the quality of the random numbers
  +* passing the full 16 bytes from STCKE to the generator.
  +*/
 
 As long as you realize that probably 12 or 13 or even more of those 16 bytes
 are likely predictable (depending exactly how fast the hardware clock ticks),
 and as a result the output stream will also be predictable.

Yes, if an attacker knows the initial clock value a brute-force attack
would be feasible to predict the output. But I don't know if the
hardware completely relies on the clock values or if there is any
internal state which is not visible by an attacker. I will try to find
out more details...

Jan


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


Re: [patch] i386/x86_64: smp_call_function locking inconsistency

2007-02-09 Thread Jan Glauber
On Fri, 2007-02-09 at 09:42 +0100, Heiko Carstens wrote:
 I just want to avoid that s390 has different semantics for
 smp_call_functiom*() than any other architecture. But then again it
 will probably not hurt since we allow more.
 Another thing that comes into my mind is smp_call_function together
 with cpu hotplug. Who is responsible that preemption and with that
 cpu hotplug is disabled?
 Is it the caller or smp_call_function itself?

I think the caller must disable preemption since smp_call_function()
means do something on all but the current cpu. If the preempt_disable
would happen only in smp_call_function() it could already be running on
a different cpu, which is not what the caller wants.

If preemption must be disabled before smp_call_function() we should have
the same semantics for all smp_call_function_* variants.

Jan

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


Re: Module init call vs symbols exporting race?

2007-11-07 Thread Jan Glauber
Hi Rusty,

I've seen a symbol-resolving race on s390. The qeth module uses symbols
from qdio and although the loading order seems correct and the qdio
symbols should be available the following error appears:

qdio: loading QDIO base support version 2
qeth: Unknown symbol qdio_synchronize
qeth: Unknown symbol do_QDIO
qeth: Unknown symbol qdio_initialize
qeth: Unknown symbol qdio_cleanup
qeth: Unknown symbol qdio_activate
qeth: Unknown symbol qdio_synchronize
qeth: Unknown symbol do_QDIO
qeth: Unknown symbol qdio_initialize
qeth: Unknown symbol qdio_cleanup
qeth: Unknown symbol qdio_activate
qeth: loading qeth S/390 OSA-Express driver
qeth: Device 0.0.f5f0/0.0.f5f1/0.0.f5f2 is a OSD Express card (level: 087a) 
with link type OSD_1000 (portname: OSAPORT)
qeth: Hardware IP fragmentation not supported on eth0
qeth: VLAN enabled 
qeth: Multicast enabled
qeth: IPV6 enabled 
qeth: Broadcast enabled 
qeth: Using SW checksumming on eth0.
qeth: Outbound TSO enabled

After that both drivers work fine but I'm curious why this happens.
Cheers,
Jan


On Tue, 2007-11-06 at 23:41 +1100, Rusty Russell wrote:
 On Tuesday 06 November 2007 20:20:58 Pavel Emelyanov wrote:
  Hi.
 
  I looked at the sys_init_module() and found that the -init callback
  for the module is called without the module_mutex held and *after*
  the module's symbols are exported. Doesn't this create the race when
  loading two modules in parallel? Like this.
 
 Hi Pavel,
 
   In a word, no.  See strong_try_module_get().
 
 Cheers,
 Rusty.
 -
 To unsubscribe from this list: send the line unsubscribe linux-kernel in
 the body of a message to [EMAIL PROTECTED]
 More majordomo info at  http://vger.kernel.org/majordomo-info.html
 Please read the FAQ at  http://www.tux.org/lkml/

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


Re: Module init call vs symbols exporting race?

2007-11-09 Thread Jan Glauber
On Thu, 2007-11-08 at 13:10 +1100, Rusty Russell wrote:
 On Wednesday 07 November 2007 21:01:30 Jan Glauber wrote:
  Hi Rusty,
 
  I've seen a symbol-resolving race on s390. The qeth module uses symbols
  from qdio and although the loading order seems correct and the qdio
  symbols should be available the following error appears:
 
  qdio: loading QDIO base support version 2
  qeth: Unknown symbol qdio_synchronize
 
 Looks like qdio does something which triggers qeth to load, but of course 
 qdio 
 isn't finished initializing yet so its symbols aren't available.
 
 It's not obvious what's triggering the load, but you could probably find it 
 by 
 using printk's through qdio.c's init_QDIO().

Digging through the module loader I found what triggers the error...

CPU0 (sys_init_module for qdio) CPU1 (sys_init_module for qeth)

mutex_lock()
- load_module()
 mod-state = COMING
mutex_unlock()
mutex_lock()
init()...takes some timeload_module()
- resolve_symbols()
   - use_module()
  - stong_try_module_get() 
bails out
 because state == COMING
- simplify_symbols() complains 
with the warning

mutex_lock()
mod-state = LIVE
mutex_unlock()

So is it correct that sys_init_module() is called for qeth even if qdio is
not yet in MODULE_STATE_LIVE?

-jang

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


man page for s390_runtime_instr syscall

2012-12-10 Thread Jan Glauber
Hi Michael,

I've written a man page for the s390_runtime_instr syscall which was merged 
with 3.7 (e4b8b3f). Now the question is if you would like to include it in the 
man-pages although it is completely s390 specific and wont be available on any 
other arch? Or should it go into a different package?

thanks, Jan
--

--- /dev/null   2012-12-04 10:52:46.657720288 +0100
+++ s390_runtime_instr.22012-10-09 13:55:39.0 +0200
@@ -0,0 +1,73 @@
+.\ Copyright IBM Corp. 2012
+.\ Author: Jan Glauber j...@linux.vnet.ibm.com
+.\
+.TH S390_RUNTIME_INSTR 2 2012-10-09 Linux Programmer's Manual
+.SH NAME
+s390_runtime_instr \- enable/disable s390 CPU runtime instrumentation
+.SH SYNOPSIS
+.nf
+.B #include asm/runtime_instr.h
+
+.BI int s390_runtime_instr(int  command , int  signum );
+.fi
+
+.SH DESCRIPTION
+The
+.BR s390_runtime_instr ()
+system call starts or stops CPU runtime instrumentation for the current thread.
+
+The
+.IR command
+argument controls whether runtime instumentation is started
+( 1 ) or stopped ( 2 ) for the current thread.
+
+The
+.IR signum
+argument specifies the number of a real-time signal. The
+real-time signal is sent to the thread if the runtime instrumentation
+buffer is full or if the runtime-instrumentation-halted interrupt
+occured.
+
+.SH RETURN VALUE
+On success
+.BR s390_runtime_instr ()
+returns 0 and enables the thread for
+runtime instrumentation by assigning the thread a default runtime
+instrumentation control block. The caller can then read and modify the
+control block and start the runtime instrumentation. On error, -1 is
+returned and
+.IR errno
+is set to one of the error codes listed below.
+
+.SH ERRORS
+.TP
+.B EOPNOTSUPP
+The runtime instrumentation facility is not available.
+.TP
+.B EINVAL
+The value specified in
+.IR command
+is not a valid command or the value specified in
+.IR signum
+is not a real-time signal number.
+.TP
+.B ENOMEM
+Allocating memory for the runtime instrumentation control block
+failed.
+
+.SH VERSIONS
+This system call is available since Linux 3.7.
+
+.SH CONFORMING TO
+This system call
+is only available on the s390 architecture. The runtime instrumentation 
facility is available
+beginning with System z EC12.
+
+.SH NOTES
+Glibc does not provide a wrapper for this system call, use
+.BR syscall (2)
+to call it.
+
+.SH SEE ALSO
+.BR signal (7),
+.BR syscall (2)

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


Re: [RFC PATCH 01/10] s390/pci: base support

2012-12-13 Thread Jan Glauber
On Mon, 2012-12-10 at 14:14 -0700, Bjorn Helgaas wrote:
 On Wed, Nov 14, 2012 at 2:41 AM, Jan Glauber j...@linux.vnet.ibm.com wrote:
  Add PCI support for s390, (only 64 bit mode is supported by hardware):
  - PCI facility tests
  - PCI instructions: pcilg, pcistg, pcistb, stpcifc, mpcifc, rpcit
  - map readb/w/l/q and writeb/w/l/q to pcilg and pcistg instructions
  - pci_iomap implementation
  - memcpy_fromio/toio
  - pci_root_ops using special pcilg/pcistg
  - device, bus and domain allocation
 
  Signed-off-by: Jan Glauber j...@linux.vnet.ibm.com
 
 I think these patches are in -next already, so I just have some
 general comments  questions.

Yes, since the feedback was manageable we decided to give the patches
some exposure in -next and if no one complains we'll just go for the
next merge window. BTW, Sebastian  Gerald (on CC:) will continue the
work on the PCI code.

 My overall impression is that these are exceptionally well done.
 They're easy to read, well organized, and well documented.  It's a
 refreshing change from a lot of the stuff that's posted.

Thanks Björn!

 As with other arches that run on top of hypervisors, you have
 arch-specific code that enumerates PCI devices using hypervisor calls,
 and you hook into the PCI core at a lower level than
 pci_scan_root_bus().  That is, you call pci_create_root_bus(),
 pci_scan_single_device(), pci_bus_add_devices(), etc., directly from
 the arch code.  This is the typical approach, but it does make more
 dependencies between the arch code and the PCI core than I'd like.
 
 Did you consider hiding any of the hypervisor details behind the PCI
 config accessor interface?  If that could be done, the overall
 structure might be more similar to other architectures.

You mean pci_root_ops? I'm not sure I understand how that can be used
to hide hipervisor details. One reason why we use the lower level
functions is that we need to create the root bus (and its resources)
much earlier then the pci_dev. For instance pci_hp_register wants a
pci_bus to create the PCI slot and the slot can exist without a pci_dev.

 The current config accessors only work for dev/fn 00.0 (they fail when
 devfn != ZPCI_DEVFN).  Why is that?  It looks like it precludes
 multi-function devices and basically prevents you from building an
 arbitrary PCI hierarchy.

Our hypervisor does not support multi-function devices. In fact the
hypervisor will limit the reported PCI devices to a hand-picked
selection so we can be sure that there will be no unsupported devices.
The PCI hierarchy is hidden by the hipervisor. We only use the PCI
domain number, bus and devfn are always zero. So it looks like every
function is directly attached to a PCI root complex.

That was the reason for the sanity check, but thinking about it I could
remove it since although we don't support multi-function devices I
think the s390 code should be more agnostic to these limitations.

 zpci_map_resources() is very unusual.  The struct pci_dev resource[]
 table normally contains CPU physical addresses, but
 zpci_map_resources() fills it with virtual addresses.  I suspect this
 has something to do with the BAR spaces are not disjunctive on s390
 comment.  It almost sounds like that's describing host bridges where
 the PCI bus address is not equal to the CPU physical address -- in
 that case, device A and device B may have the same values in their
 BARs, but they can still be distinct if they're under host bridges
 that apply different CPU-to-bus address translations.

Yeah, you've found it... I've had 3 or 4 tries on different
implementations but all failed. If we use the resources as they are we
cannot map them to the instructions (and ioremap does not help because
there we cannot find out which device the resource belongs to). If we
change the BARs on the card MMIO stops to work. I don't know about host
bridges - if we would use a host bridge at which point in the
translation process would it kick in?

Jan

 Bjorn
 



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


Re: man page for s390_runtime_instr syscall

2012-12-17 Thread Jan Glauber
On Sat, 2012-12-15 at 19:38 +0100, Michael Kerrisk (man-pages) wrote:
 Thanks for this page. The man-pages package is the right place for it,
 but a few things need fixing. Could you see below and resubmit please?

I've addressed all of your comments but for the example. We could add
the example later when the official documentation is released which
did not yet happen.

thanks, Jan

--- /dev/null   2012-12-17 11:58:11.967183723 +0100
+++ s390_runtime_instr.22012-12-17 12:55:20.942872393 +0100
@@ -0,0 +1,91 @@
+.\ Copyright IBM Corp. 2012
+.\ Author: Jan Glauber j...@linux.vnet.ibm.com
+.\ Copyright (c) 2012, IBM Corp.
+.\
+.\ This is free documentation; 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.
+.\
+.\ The GNU General Public License's references to object code
+.\ and executables are to be interpreted as the output of any
+.\ document formatting or typesetting system, including
+.\ intermediate and printed output.
+.\
+.\ This manual 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 manual; if not, see
+.\ http://www.gnu.org/licenses/.
+.TH S390_RUNTIME_INSTR 2 2012-12-17 Linux Programmer's Manual
+.SH NAME
+s390_runtime_instr \- enable/disable s390 CPU runtime instrumentation
+.SH SYNOPSIS
+.nf
+.B #include asm/runtime_instr.h
+
+.BI int s390_runtime_instr(int  command , int  signum );
+.fi
+
+.SH DESCRIPTION
+The
+.BR s390_runtime_instr ()
+system call starts or stops CPU runtime instrumentation for the current thread.
+
+The
+.IR command
+argument controls whether runtime instrumentation is started
+( 1 ) or stopped ( 2 ) for the current thread.
+
+The
+.IR signum
+argument specifies the number of a real-time signal.
+The real-time signal is sent to the thread if the runtime instrumentation
+buffer is full or if the runtime-instrumentation-halted interrupt
+occurred.
+
+.SH RETURN VALUE
+On success
+.BR s390_runtime_instr ()
+returns 0 and enables the thread for
+runtime instrumentation by assigning the thread a default runtime
+instrumentation control block.
+The caller can then read and modify the control block and start the runtime
+instrumentation.
+On error, -1 is returned and
+.IR errno
+is set to one of the error codes listed below.
+
+.SH ERRORS
+.TP
+.B EOPNOTSUPP
+The runtime instrumentation facility is not available.
+.TP
+.B EINVAL
+The value specified in
+.IR command
+is not a valid command or the value specified in
+.IR signum
+is not a real-time signal number.
+.TP
+.B ENOMEM
+Allocating memory for the runtime instrumentation control block failed.
+
+.SH VERSIONS
+This system call is available since Linux 3.7.
+
+.SH CONFORMING TO
+This Linux-specific system call is only available on the s390 architecture.
+The runtime instrumentation facility is available beginning with System z EC12.
+
+.SH NOTES
+Glibc does not provide a wrapper for this system call, use
+.BR syscall (2)
+to call it.
+
+.SH SEE ALSO
+.BR syscall (2),
+.BR signal (7)



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


[PATCH] virtual sched_clock() for s390

2007-07-19 Thread Jan Glauber
This patch introduces a cpu time clock for s390 (only ticking
if the virtual cpu is running) and bases the s390 implementation
of sched_clock() on it.

The times lice length on a virtual cpu can be anything
between the calculated time slice and zero. In reality
this doesn't seem to be problem, since the scheduler is fair
enough to not let a single process starve but the current
implementation can lead to inefficient short time slices.

By providing a 'virtual' sched_clock() we guarantee that a
process can get its time slice regardless of scheduling
decisions from the hypervisor.

Patch applies to 2.6.22 git and works fine with CFS.

Jan

--
 arch/s390/kernel/time.c  |   18 --
 arch/s390/kernel/vtime.c |   45 +
 include/asm-s390/timer.h |2 ++
 3 files changed, 59 insertions(+), 6 deletions(-)

--- ./include/asm-s390/timer.h.cpu_clock2007-07-18 13:43:53.0 
+0200
+++ ./include/asm-s390/timer.h  2007-07-18 20:41:13.0 +0200
@@ -48,6 +48,8 @@
 extern void init_cpu_vtimer(void);
 extern void vtime_init(void);
 
+extern unsigned long long cpu_clock(void);
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_S390_TIMER_H */
--- ./arch/s390/kernel/time.c.cpu_clock 2007-07-18 13:43:35.0 +0200
+++ ./arch/s390/kernel/time.c   2007-07-18 21:01:07.0 +0200
@@ -62,21 +62,27 @@
 static u64 xtime_cc;
 
 /*
- * Scheduler clock - returns current time in nanosec units.
+ * Monotonic_clock - returns # of nanoseconds passed since time_init()
  */
-unsigned long long sched_clock(void)
+unsigned long long monotonic_clock(void)
 {
return ((get_clock() - jiffies_timer_cc) * 125)  9;
 }
+EXPORT_SYMBOL(monotonic_clock);
 
 /*
- * Monotonic_clock - returns # of nanoseconds passed since time_init()
+ * Scheduler clock - returns current time in nanosec units.
+ * Now based on virtual cpu time to only account time the guest
+ * was actually running.
  */
-unsigned long long monotonic_clock(void)
+unsigned long long sched_clock(void)
 {
-   return sched_clock();
+#ifdef CONFIG_VIRT_TIMER
+   return cpu_clock();
+#else
+   return monotonic_clock();
+#endif
 }
-EXPORT_SYMBOL(monotonic_clock);
 
 void tod_to_timeval(__u64 todval, struct timespec *xtime)
 {
--- ./arch/s390/kernel/vtime.c.cpu_clock2007-07-18 13:43:44.0 
+0200
+++ ./arch/s390/kernel/vtime.c  2007-07-18 20:52:14.0 +0200
@@ -26,6 +26,44 @@
 
 static ext_int_info_t ext_int_info_timer;
 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+static DEFINE_PER_CPU(struct vtimer_list, cpu_clock_timer);
+
+/*
+ * read the remaining time of a virtual timer running on the current cpu
+ */
+static unsigned long long read_cpu_timer(struct vtimer_list *timer)
+{
+   struct vtimer_queue *vt_list;
+   unsigned long flags;
+   __u64 done;
+
+   local_irq_save(flags);
+   local_irq_disable();
+
+   BUG_ON(timer-cpu != smp_processor_id());
+
+   vt_list = per_cpu(virt_cpu_timer, timer-cpu);
+   asm volatile (STPT %0 : =m (done));
+
+   done = vt_list-to_expire + vt_list-offset - done;
+   local_irq_restore(flags);
+   return done;
+}
+
+/*
+ * Cpu clock, returns cpu time in nanosec units.
+ * Must be called with preemption disabled.
+ */
+unsigned long long cpu_clock(void)
+{
+   return ((read_cpu_timer(__get_cpu_var(cpu_clock_timer)) * 125)  9);
+}
+
+/* expire after 142 years ... */
+static void cpu_clock_timer_callback(unsigned long data)
+{
+   BUG();
+}
 
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 /*
@@ -522,6 +560,7 @@
 void init_cpu_vtimer(void)
 {
struct vtimer_queue *vt_list;
+   struct vtimer_list *timer;
 
/* kick the virtual timer */
S390_lowcore.exit_timer = VTIMER_MAX_SLICE;
@@ -539,6 +578,12 @@
vt_list-offset = 0;
vt_list-idle = 0;
 
+   /* add dummy timers needed for cpu_clock */
+   timer = __get_cpu_var(cpu_clock_timer);
+   init_virt_timer(timer);
+   timer-expires = VTIMER_MAX_SLICE;
+   timer-function = cpu_clock_timer_callback;
+   add_virt_timer(timer);
 }
 
 static int vtimer_idle_notify(struct notifier_block *self,


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


Re: [PATCH] virtual sched_clock() for s390

2007-07-19 Thread Jan Glauber
On Thu, 2007-07-19 at 18:00 +0200, Ingo Molnar wrote:
 * Jeremy Fitzhardinge [EMAIL PROTECTED] wrote:
 
/*
   - * Monotonic_clock - returns # of nanoseconds passed since time_init()
   + * Scheduler clock - returns current time in nanosec units.
   + * Now based on virtual cpu time to only account time the guest
   + * was actually running.
  
  Runn*ing*?  Does it include time the VCPU spends idle/blocked?  If 
  not, then the scheduler won't be able to tell how long a process has 
  been asleep.  Maybe this doesn't matter (I had this problem in a 
  version of Xen's sched_clock, and I can't say I saw an ill effects 
  from it).

No, it does not include idle time, if we're going idle the cpu timer
gets stopped.

 CFS does measure time elapsed across task-sleep periods (and does 
 something similar to what the old scheduler's 'sleep average' 
 interactivity mechanism did), but that mechanism measures time spent 
 running during sleep, not time spent idling.
 
 still, CFS needs time measurement across idle periods as well, for 
 another purpose: to be able to do precise task statistics for /proc. 
 (for top, ps, etc.) So it's still true that sched_clock() should include 
 idle periods too.

I'm not sure, s390 already has an implemetation for precise accounting
in the architecture code, does CFS also improve accounting data? 

Jan

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


Re: [PATCH] virtual sched_clock() for s390

2007-07-19 Thread Jan Glauber
On Thu, 2007-07-19 at 21:38 +0200, Ingo Molnar wrote: 
 * Jan Glauber [EMAIL PROTECTED] wrote:
 
   still, CFS needs time measurement across idle periods as well, for 
   another purpose: to be able to do precise task statistics for /proc. 
   (for top, ps, etc.) So it's still true that sched_clock() should 
   include idle periods too.
  
  I'm not sure, s390 already has an implemetation for precise accounting 
  in the architecture code, does CFS also improve accounting data?
 
 what kind of precise accounting does s390 have in the architecture code? 
 CFS changes task (and load) accounting to be sched_clock() driven in 
 essence.

s390 has per-process accounting that is aware of virtual cpu time, implemented 
in
arch/s390/kernel/time.c: account_ticks() and arch/s390/kernel/vtime.c:
account_*_vtime(). Timestamps are taken in entry.S for system calls, interrupts
and other system entries and are accounted later, we don't call 
update_process_times().

Jan

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

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


Ambigiuous thread stack annotation in /proc/pid/[s]maps

2013-06-26 Thread Jan Glauber
Commit b764375 added annotations of thread stacks. This annotation can be
wrong depending on the memory layout of a task (will probably only happen
under 32 bit).

If a large allocation happens before the creation of a thread you can get:

root@box:~# cat /proc/2032/maps 
08048000-08049000 r-xp  08:01 3407931/root/pt
08049000-0804a000 r--p  08:01 3407931/root/pt
0804a000-0804b000 rw-p 1000 08:01 3407931/root/pt
093b8000-093d9000 rw-p  00:00 0  [heap]
363fe000-363ff000 ---p  00:00 0 
363ff000-b6c0 rw-p  00:00 0  [stack:2036]
b6c0-b6c21000 rw-p  00:00 0 
b6c21000-b6d0 ---p  00:00 0 
b6d31000-b6d32000 ---p  00:00 0 
b6d32000-b7534000 rw-p  00:00 0  [stack:2033]
b7534000-b76d7000 r-xp  08:01 3145793
/lib/i386-linux-gnu/libc-2.15.so
b76d7000-b76d9000 r--p 001a3000 08:01 3145793
/lib/i386-linux-gnu/libc-2.15.so
b76d9000-b76da000 rw-p 001a5000 08:01 3145793
/lib/i386-linux-gnu/libc-2.15.so
b76da000-b76dd000 rw-p  00:00 0 
b76dd000-b76f4000 r-xp  08:01 3149883
/lib/i386-linux-gnu/libpthread-2.15.so
b76f4000-b76f5000 r--p 00016000 08:01 3149883
/lib/i386-linux-gnu/libpthread-2.15.so
b76f5000-b76f6000 rw-p 00017000 08:01 3149883
/lib/i386-linux-gnu/libpthread-2.15.so
b76f6000-b76f8000 rw-p  00:00 0 
b7707000-b770b000 rw-p  00:00 0 
b770b000-b770c000 r-xp  00:00 0  [vdso]
b770c000-b772c000 r-xp  08:01 3149887/lib/i386-linux-gnu/ld-2.15.so
b772c000-b772d000 r--p 0001f000 08:01 3149887/lib/i386-linux-gnu/ld-2.15.so
b772d000-b772e000 rw-p 0002 08:01 3149887/lib/i386-linux-gnu/ld-2.15.so
bfb15000-bfb36000 rw-p  00:00 0  [stack]

Now the stack for thread 2036 is amazingly large for a pthread. Actually it is
the result of:
1. malloc(2048 * 1024 * 1024)
2. pthread_create (with attr=NULL)

My theory is that this can happen anytime because a thread stack is just created
with mmap (MAP_PRIVATE | MAP_ANONYMOUS). The 1. malloc also resulted in a mmap 
(libc fallback on brk failure) with the same flags (MAP_PRIVATE | 
MAP_ANONYMOUS).

The kernel does not care about thread stacks and tries to merge vma's which 
seems
to happen here and which is correct from the kernel POV.

Any ideas how that can be fixed? The only solution that comes to my mind
is to prevent merging vma's that are used for thread stacks. There is already a
flag (MAP_STACK) which is set by the libc for mmap'ing thread stacks but the
kernel currently does not care. If the kernel gets an mmap request with
MAP_STACK set we could mark the VMA and avoid merging it with others.

Unfortunately there seems to be no bit left in the vm_flags to store the
MAP_STACK information...

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


[PATCH] net: use SYSCALL_DEFINEx for sys_recv

2014-04-15 Thread Jan Glauber
Make sys_recv a first class citizen by using the SYSCALL_DEFINEx
macro. Besides being cleaner this will also generate meta data
for the system call so tracing tools like ftrace or LTTng can
resolve this system call.

Signed-off-by: Jan Glauber jan.glau...@gmail.com
---
 net/socket.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index a19ae19..d258945 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1879,8 +1879,8 @@ out:
  * Receive a datagram from a socket.
  */
 
-asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size,
-unsigned int flags)
+SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size,
+   unsigned int, flags)
 {
return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL);
 }
-- 
1.7.9.5

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


Re: Ambigiuous thread stack annotation in /proc/pid/[s]maps

2013-06-27 Thread Jan Glauber
On Wed, Jun 26, 2013 at 10:05:41PM +0530, Siddhesh Poyarekar wrote:
 On 26 June 2013 17:13, Jan Glauber jan.glau...@gmail.com wrote:
  Any ideas how that can be fixed? The only solution that comes to my mind
  is to prevent merging vma's that are used for thread stacks. There is 
  already a
  flag (MAP_STACK) which is set by the libc for mmap'ing thread stacks but the
  kernel currently does not care. If the kernel gets an mmap request with
  MAP_STACK set we could mark the VMA and avoid merging it with others.
 
  Unfortunately there seems to be no bit left in the vm_flags to store the
  MAP_STACK information...
 
 The annotations essentially point out that the vma contains the stack
 and not that the vma *is* the stack.  We'd get similar output with

But isn't that confusing to the user? At least it is to me. Imagine someone
who uses the maps or smaps output to determine the size of code, data and
stack of a process. Maybe it would be better to not print the stack:tid data
at all if the kernel cannot distinguish the vma's?
Is that behaviour documented anywhere?

 makecontext/getcontext, where the stack may just be a portion of
 memory in another vma.  I don't remember if I had explicitly mentioned
 that during the original discussion.

Never seen that makecontext stuff before. Do you have an example output how
the maps would look like if that is used?

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


Re: Ambigiuous thread stack annotation in /proc/pid/[s]maps

2013-07-02 Thread Jan Glauber
On Thu, Jun 27, 2013 at 10:00:51PM +0530, Siddhesh Poyarekar wrote:
 On 27 June 2013 21:32, Jan Glauber jan.glau...@gmail.com wrote:
  But isn't that confusing to the user? At least it is to me. Imagine someone
  who uses the maps or smaps output to determine the size of code, data and
  stack of a process. Maybe it would be better to not print the stack:tid data
  at all if the kernel cannot distinguish the vma's?
  Is that behaviour documented anywhere?
 
 I'm afraid the documentation update I made to proc.txt did not mention
 this.  In fact I went through the discussion thread and I don't think
 I or anyone mentioned this in the thread either.  I think I assumed
 back then that this was accepted since there was a point made that
 vmas used by makecontext/swapcontext should also get marked correctly
 with [stack].
 
 However, I agree that you have a point about it being misleading.
 Avoiding a vma merge is a possible solution, but we don't have flags
 available any more to do that.  I'll try to think of another way.  In
 the mean time I could add a note to the proc.txt documentation and
 even adjust the language.  Would that be good enough or do you think
 the patch should be reverted until I or someone else comes up with a
 better solution?

I think we should try to solve the problem first. If it turns out that
it is not possible to prevent these vma merges than we should document it.
Removing the annotation would IMHO be bad since it is really useful
information to the user.

Can anyone from the mm folks comment on the vm_flags situation (CC-ing 
linux-mm) ?
Would it be possible to re-use one of the defined flags? Or should we come up 
with a
crude hack?
 
  Never seen that makecontext stuff before. Do you have an example output how
  the maps would look like if that is used?
 
 This is a sample program I cribbed from the makecontext man page and
 modified slightly.  The stack is in the data area in this example.
 There could be a case of a stack being with the main program stack or
 even in the heap.
 
 #include ucontext.h
 #include stdio.h
 #include stdlib.h
 
 static ucontext_t uctx_main, uctx_func1, uctx_func2;
 
 #define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
 
 static char func1_stack[16384];
 static char func2_stack[16384];
 
 static void func1(void)
 {
 printf(func1: started\n);
 printf(func1: swapcontext(uctx_func1, uctx_func2)\n);
 if (swapcontext(uctx_func1, uctx_func2) == -1)
 handle_error(swapcontext);
 
 sleep (1);
 printf(func1: returning\n);
 }
 
 static void func2(void)
 {
 printf(func2: started\n);
 printf(func2: swapcontext(uctx_func2, uctx_func1)\n);
 if (swapcontext(uctx_func2, uctx_func1) == -1)
 handle_error(swapcontext);
 sleep (1);
 printf(func2: returning\n);
 }
 
 int main(int argc, char *argv[])
 {
 if (getcontext(uctx_func1) == -1)
 handle_error(getcontext);
 uctx_func1.uc_stack.ss_sp = func1_stack;
 uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
 uctx_func1.uc_link = uctx_main;
 makecontext(uctx_func1, func1, 0);
 
 if (getcontext(uctx_func2) == -1)
 handle_error(getcontext);
 uctx_func2.uc_stack.ss_sp = func2_stack;
 uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
 /* Successor context is f1(), unless argc  1 */
 uctx_func2.uc_link = (argc  1) ? NULL : uctx_func1;
 makecontext(uctx_func2, func2, 0);
 
 printf(main: swapcontext(uctx_main, uctx_func2)\n);
 if (swapcontext(uctx_main, uctx_func2) == -1)
 handle_error(swapcontext);
 
 printf(main: exiting\n);
 exit(EXIT_SUCCESS);
 }
 
 
 $./a.out
 $ cat /proc/$(pgrep a.out)/maps
 
 0040-00401000 r-xp  fd:00 1704114
   /tmp/a.out
 00601000-00602000 rw-p 1000 fd:00 1704114
   /tmp/a.out
 00602000-0060a000 rw-p  00:00 0
   [stack:7352]
 7fac662d2000-7fac6647e000 r-xp  fd:00 524922
   /usr/lib64/libc-2.15.so
 7fac6647e000-7fac6667e000 ---p 001ac000 fd:00 524922
   /usr/lib64/libc-2.15.so
 7fac6667e000-7fac66682000 r--p 001ac000 fd:00 524922
   /usr/lib64/libc-2.15.so
 7fac66682000-7fac66684000 rw-p 001b fd:00 524922
   /usr/lib64/libc-2.15.so
 7fac66684000-7fac66689000 rw-p  00:00 0
 7fac66689000-7fac666a9000 r-xp  fd:00 524913
   /usr/lib64/ld-2.15.so
 7fac6688f000-7fac66892000 rw-p  00:00 0
 7fac668a6000-7fac668a8000 rw-p  00:00 0
 7fac668a8000-7fac668a9000 r--p 0001f000 fd:00 524913
   /usr/lib64/ld-2.15.so
 7fac668a9000-7fac668aa000 rw-p 0002 fd:00 524913
   /usr/lib64/ld-2.15.so
 7fac668aa000-7fac668ab000 rw-p  00:00 0
 7fff5b8a8000-7fff5b8ca000 rw-p  00:00 0
 7fff5b9fe000-7fff5ba0 r-xp  00:00 0  
 [vdso]
 ff60-ff601000 r-xp  00:00 0
   [vsyscall

[PATCH 3/3] i2c: octeon: Avoid printk after too long SMBUS message

2016-06-08 Thread Jan Glauber
Remove the warning about a too long SMBUS message because
the ipmi_ssif driver triggers this warning too frequently so it
spams the message log.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 8ade7fb..83fd6d8 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -975,12 +975,8 @@ restart:
 
data[i] = octeon_i2c_data_read(i2c);
if (recv_len && i == 0) {
-   if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) {
-   dev_err(i2c->dev,
-   "%s: read len > I2C_SMBUS_BLOCK_MAX 
%d\n",
-   __func__, data[i]);
+   if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
return -EPROTO;
-   }
length += data[i];
}
 
-- 
2.9.0.rc0.21.g322



[PATCH 0/3] Bug fixes for octeon driver

2016-06-08 Thread Jan Glauber
Testing ipmi_ssif on ThunderX several bugs were found that also
apply to the Octeon i2c driver changes coming with 4.7.

I'll need to rebase the pending ThunderX driver series after this
fixes which I'll do shortly.

Please consider for 4.7.

thanks,
Jan

Jan Glauber (3):
  i2c: octeon: Missing AAK flag in case of I2C_M_RECV_LEN
  i2c: octeon: Add retry logic after receiving STAT_RXADDR_NAK
  i2c: octeon: Avoid printk after too long SMBUS message

 drivers/i2c/busses/i2c-octeon.c | 45 -
 1 file changed, 31 insertions(+), 14 deletions(-)

-- 
2.9.0.rc0.21.g322



[PATCH 1/3] i2c: octeon: Missing AAK flag in case of I2C_M_RECV_LEN

2016-06-08 Thread Jan Glauber
During receive the controller requires the AAK flag for all
bytes but the final one. This was wrong in case of I2C_M_RECV_LEN,
where the decision if the final byte is to be transmitted
happened before adding the additional received length byte.

Set the AAK flag if additional bytes are to be received.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index aa5f01e..1922e4a 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -934,8 +934,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int 
target,
return result;
 
for (i = 0; i < length; i++) {
-   /* for the last byte TWSI_CTL_AAK must not be set */
-   if (i + 1 == length)
+   /*
+* For the last byte to receive TWSI_CTL_AAK must not be set.
+*
+* A special case is I2C_M_RECV_LEN where we don't know the
+* additional length yet. If recv_len is set we assume we're
+* not reading the final byte and therefore need to set
+* TWSI_CTL_AAK.
+*/
+   if ((i + 1 == length) && !(recv_len && i == 0))
final_read = true;
 
/* clear iflg to allow next event */
-- 
2.9.0.rc0.21.g322



[PATCH 2/3] i2c: octeon: Add retry logic after receiving STAT_RXADDR_NAK

2016-06-08 Thread Jan Glauber
The controller specification states that when receiving STAT_RXADDR_NAK
the START should be sent again. Retry several times before finally
failing with -ENXIO.

Without this change the IPMI SSIF driver fails executing several commands
like 'ipmitool fru' on ThunderX.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 28 +---
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 1922e4a..8ade7fb 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -880,6 +880,10 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int 
target,
 {
int i, result;
 
+   result = octeon_i2c_start(i2c);
+   if (result)
+   return result;
+
octeon_i2c_data_write(i2c, target << 1);
octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 
@@ -918,9 +922,14 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int 
target,
 static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
   u8 *data, u16 *rlength, bool recv_len)
 {
-   int i, result, length = *rlength;
+   int i, result, length = *rlength, retries = 10;
bool final_read = false;
 
+restart:
+   result = octeon_i2c_start(i2c);
+   if (result)
+   return result;
+
octeon_i2c_data_write(i2c, (target << 1) | 1);
octeon_i2c_ctl_write(i2c, TWSI_CTL_ENAB);
 
@@ -930,8 +939,17 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int 
target,
 
/* address OK ? */
result = octeon_i2c_check_status(i2c, false);
-   if (result)
-   return result;
+   if (result) {
+   /*
+* According to controller specification on STAT_RXADDR_NAK
+* the START should be repeated so retry several times before
+* giving up with -ENXIO.
+*/
+   if (result == -ENXIO && --retries > 0)
+   goto restart;
+   else
+   return result;
+   }
 
for (i = 0; i < length; i++) {
/*
@@ -1019,10 +1037,6 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, 
struct i2c_msg *msgs,
break;
}
 
-   ret = octeon_i2c_start(i2c);
-   if (ret)
-   return ret;
-
if (pmsg->flags & I2C_M_RD)
ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
  >len, pmsg->flags & 
I2C_M_RECV_LEN);
-- 
2.9.0.rc0.21.g322



Re: [PATCH 2/3] i2c: octeon: Add retry logic after receiving STAT_RXADDR_NAK

2016-06-14 Thread Jan Glauber
On Thu, Jun 09, 2016 at 10:11:51PM +0200, Wolfram Sang wrote:
> On Wed, Jun 08, 2016 at 08:51:18AM +0200, Jan Glauber wrote:
> > The controller specification states that when receiving STAT_RXADDR_NAK
> > the START should be sent again. Retry several times before finally
> > failing with -ENXIO.
> > 
> > Without this change the IPMI SSIF driver fails executing several commands
> > like 'ipmitool fru' on ThunderX.
> 
> Huh? Looks wrong to me. I'd say the client driver needs to retry. Only
> that one knows if retrying is appropriate or a waste of time.
> 

I've been debugging this and it turned out that there was an related issue with
the clock setting. With that corrected this patch is not needed anymore,
so you can drop it.

I still see a huge number of RXADDR_NAK's after START but the ipmi_ssif
driver retry logic seems to deal with that.

thanks,
Jan


[PATCH v10 7/8] i2c: cavium: Use booleon values for booleon variables

2016-06-15 Thread Jan Glauber
Initialize booleon values with true instead of 1.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-cavium.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-cavium.c b/drivers/i2c/busses/i2c-cavium.c
index 56b23c2..3a581c9 100644
--- a/drivers/i2c/busses/i2c-cavium.c
+++ b/drivers/i2c/busses/i2c-cavium.c
@@ -63,7 +63,7 @@ static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, 
bool *first)
 static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
long time_left;
-   bool first = 1;
+   bool first = true;
 
/*
 * Some chip revisions don't assert the irq in the interrupt
@@ -176,7 +176,7 @@ static void octeon_i2c_hlc_disable(struct octeon_i2c *i2c)
  */
 static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
-   bool first = 1;
+   bool first = true;
int time_left;
 
/*
-- 
1.9.1



[PATCH v10 2/8] i2c: octeon: Split the driver into two parts

2016-06-15 Thread Jan Glauber
Move common functionality into a separate file in preparation of the
re-use from the ThunderX i2c driver.

Functions are slightly re-ordered but no other changes are included.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/Makefile  |   3 +-
 drivers/i2c/busses/i2c-cavium.c  | 810 +
 drivers/i2c/busses/i2c-cavium.h  | 197 +++
 drivers/i2c/busses/i2c-octeon-core.c | 973 +--
 4 files changed, 1010 insertions(+), 973 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-cavium.c
 create mode 100644 drivers/i2c/busses/i2c-cavium.h

diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 3405286..282f781 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -91,7 +91,8 @@ obj-$(CONFIG_I2C_UNIPHIER)+= i2c-uniphier.o
 obj-$(CONFIG_I2C_UNIPHIER_F)   += i2c-uniphier-f.o
 obj-$(CONFIG_I2C_VERSATILE)+= i2c-versatile.o
 obj-$(CONFIG_I2C_WMT)  += i2c-wmt.o
-obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon-core.o
+i2c-octeon-objs := i2c-cavium.o i2c-octeon-core.o
+obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)   += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
diff --git a/drivers/i2c/busses/i2c-cavium.c b/drivers/i2c/busses/i2c-cavium.c
new file mode 100644
index 000..3e4dd64
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cavium.c
@@ -0,0 +1,810 @@
+/*
+ * (C) Copyright 2009-2010
+ * Nokia Siemens Networks, michael.lawnick@nsn.com
+ *
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
+ *
+ * This file contains the shared part of the driver for the i2c adapter in
+ * Cavium Networks' OCTEON processors and ThunderX SOCs.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "i2c-cavium.h"
+
+/* interrupt service routine */
+irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
+{
+   struct octeon_i2c *i2c = dev_id;
+
+   i2c->int_disable(i2c);
+   wake_up(>queue);
+
+   return IRQ_HANDLED;
+}
+
+static bool octeon_i2c_test_iflg(struct octeon_i2c *i2c)
+{
+   return (octeon_i2c_ctl_read(i2c) & TWSI_CTL_IFLG);
+}
+
+static bool octeon_i2c_test_ready(struct octeon_i2c *i2c, bool *first)
+{
+   if (octeon_i2c_test_iflg(i2c))
+   return true;
+
+   if (*first) {
+   *first = false;
+   return false;
+   }
+
+   /*
+* IRQ has signaled an event but IFLG hasn't changed.
+* Sleep and retry once.
+*/
+   usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
+   return octeon_i2c_test_iflg(i2c);
+}
+
+/**
+ * octeon_i2c_wait - wait for the IFLG to be set
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_wait(struct octeon_i2c *i2c)
+{
+   long time_left;
+   bool first = 1;
+
+   /*
+* Some chip revisions don't assert the irq in the interrupt
+* controller. So we must poll for the IFLG change.
+*/
+   if (i2c->broken_irq_mode) {
+   u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+   while (!octeon_i2c_test_iflg(i2c) &&
+  time_before64(get_jiffies_64(), end))
+   usleep_range(I2C_OCTEON_EVENT_WAIT / 2, 
I2C_OCTEON_EVENT_WAIT);
+
+   return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
+   }
+
+   i2c->int_enable(i2c);
+   time_left = wait_event_timeout(i2c->queue, octeon_i2c_test_ready(i2c, 
),
+  i2c->adap.timeout);
+   i2c->int_disable(i2c);
+
+   if (i2c->broken_irq_check && !time_left &&
+   octeon_i2c_test_iflg(i2c)) {
+   dev_err(i2c->dev, "broken irq connection detected, switching to 
polling mode.\n");
+   i2c->broken_irq_mode = true;
+   return 0;
+   }
+
+   if (!time_left)
+   return -ETIMEDOUT;
+
+   return 0;
+}
+
+static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c)
+{
+   return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0;
+}
+
+static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first)
+{
+   /* check if valid bit is cleared */
+   if (octeon_i2c_hlc_test_valid(i2c))
+   return true;
+
+   if (*first) {
+   *first = false;
+   return false;
+   }
+
+   /*
+* IRQ has signaled an event but valid bit isn't cleared.
+* Sleep and retry once.
+*/
+   usleep_range(I2C_OCTEON_EVENT_WAIT, 2 * I2C_OCTEON_EVENT_WAIT);
+  

[PATCH v10 3/8] i2c: thunderx: Add i2c driver for ThunderX SOC

2016-06-15 Thread Jan Glauber
The ThunderX SOC uses the same i2c block as the Octeon SOC.
The main difference is that on ThunderX the device is a PCI device
so device probing is done via PCI, interrupts are MSI-X. The
clock rates can be set via device tree or ACPI.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/Kconfig |  10 ++
 drivers/i2c/busses/Makefile|   2 +
 drivers/i2c/busses/i2c-cavium.h|  16 ++-
 drivers/i2c/busses/i2c-thunderx-core.c | 250 +
 4 files changed, 275 insertions(+), 3 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-thunderx-core.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index f167021..0c17d7c 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -953,6 +953,16 @@ config I2C_OCTEON
  This driver can also be built as a module.  If so, the module
  will be called i2c-octeon.
 
+config I2C_THUNDERX
+   tristate "Cavium ThunderX I2C bus support"
+   depends on 64BIT && PCI && !CAVIUM_OCTEON_SOC
+   help
+ Say yes if you want to support the I2C serial bus on Cavium
+ ThunderX SOC.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-thunderx.
+
 config I2C_XILINX
tristate "Xilinx I2C Controller"
depends on HAS_IOMEM
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 282f781..a32ff14 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -93,6 +93,8 @@ obj-$(CONFIG_I2C_VERSATILE)   += i2c-versatile.o
 obj-$(CONFIG_I2C_WMT)  += i2c-wmt.o
 i2c-octeon-objs := i2c-cavium.o i2c-octeon-core.o
 obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon.o
+i2c-thunderx-objs := i2c-cavium.o i2c-thunderx-core.o
+obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o
 obj-$(CONFIG_I2C_XILINX)   += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
diff --git a/drivers/i2c/busses/i2c-cavium.h b/drivers/i2c/busses/i2c-cavium.h
index 81c6a81..33c7e1f 100644
--- a/drivers/i2c/busses/i2c-cavium.h
+++ b/drivers/i2c/busses/i2c-cavium.h
@@ -8,9 +8,15 @@
 #include 
 
 /* Register offsets */
-#define SW_TWSI0x00
-#define TWSI_INT   0x10
-#define SW_TWSI_EXT0x18
+#if IS_ENABLED(CONFIG_I2C_THUNDERX)
+   #define SW_TWSI 0x1000
+   #define TWSI_INT0x1010
+   #define SW_TWSI_EXT 0x1018
+#else
+   #define SW_TWSI 0x00
+   #define TWSI_INT0x10
+   #define SW_TWSI_EXT 0x18
+#endif
 
 /* Controller command patterns */
 #define SW_TWSI_V  BIT_ULL(63) /* Valid bit */
@@ -94,6 +100,7 @@
 struct octeon_i2c {
wait_queue_head_t queue;
struct i2c_adapter adap;
+   struct clk *clk;
int irq;
int hlc_irq;/* For cn7890 only */
u32 twsi_freq;
@@ -109,6 +116,9 @@ struct octeon_i2c {
void (*hlc_int_disable)(struct octeon_i2c *);
atomic_t int_enable_cnt;
atomic_t hlc_int_enable_cnt;
+#if IS_ENABLED(CONFIG_I2C_THUNDERX)
+   struct msix_entry i2c_msix;
+#endif
 };
 
 static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
diff --git a/drivers/i2c/busses/i2c-thunderx-core.c 
b/drivers/i2c/busses/i2c-thunderx-core.c
new file mode 100644
index 000..6b830b5
--- /dev/null
+++ b/drivers/i2c/busses/i2c-thunderx-core.c
@@ -0,0 +1,250 @@
+/*
+ * Cavium ThunderX i2c driver.
+ *
+ * Copyright (C) 2015,2016 Cavium Inc.
+ * Authors: Fred Martin <fmar...@caviumnetworks.com>
+ * Jan Glauber <jglau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "i2c-cavium.h"
+
+#define DRV_NAME "i2c-thunderx"
+
+#define PCI_CFG_REG_BAR_NUM0
+#define PCI_DEVICE_ID_THUNDER_TWSI 0xa012
+
+#define SYS_FREQ_DEFAULT   7
+
+#define TWSI_INT_ENA_W1C   0x1028
+#define TWSI_INT_ENA_W1S   0x1030
+
+/*
+ * Enable the CORE interrupt.
+ * The interrupt will be asserted when there is non-STAT_IDLE state in the
+ * SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void thunder_i2c_int_enable(struct octeon_i2c *i2c)
+{
+   octeon_i2c_writeq_flush(TWSI_INT_CORE_INT,
+   i2c->twsi_base + TWSI_INT_ENA_W1S);
+}
+
+/*
+ * Disable the CORE interrupt.
+ */
+static void thunder_i2c_int_disable(struct octeon_i2c *i2c)
+{
+   octeon_i2c_writeq_flush(TWSI_INT_CORE_INT,
+   i2c->twsi_base + TWSI_INT_ENA_W1C);
+}
+
+static void thunder_i2c_hlc_int_enable(struct octeon_i2c *i2c)
+{
+   octeon_i2c_writeq_flush(TWSI_INT_ST_INT | TWSI_INT_TS_INT,
+   i2c->twsi_base + TWSI

[PATCH v10 4/8] i2c: thunderx: Add SMBUS alert support

2016-06-15 Thread Jan Glauber
Add SMBUS alert interrupt support. For now only device tree is
supported for specifying the alert. In case of ACPI an error
is returned.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-cavium.h|  6 
 drivers/i2c/busses/i2c-thunderx-core.c | 51 ++
 2 files changed, 57 insertions(+)

diff --git a/drivers/i2c/busses/i2c-cavium.h b/drivers/i2c/busses/i2c-cavium.h
index 33c7e1f..9c128c1 100644
--- a/drivers/i2c/busses/i2c-cavium.h
+++ b/drivers/i2c/busses/i2c-cavium.h
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -119,6 +120,11 @@ struct octeon_i2c {
 #if IS_ENABLED(CONFIG_I2C_THUNDERX)
struct msix_entry i2c_msix;
 #endif
+
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+   struct i2c_smbus_alert_setup alert_data;
+   struct i2c_client *ara;
+#endif
 };
 
 static inline void octeon_i2c_writeq_flush(u64 val, void __iomem *addr)
diff --git a/drivers/i2c/busses/i2c-thunderx-core.c 
b/drivers/i2c/busses/i2c-thunderx-core.c
index 6b830b5..d68ce08 100644
--- a/drivers/i2c/busses/i2c-thunderx-core.c
+++ b/drivers/i2c/busses/i2c-thunderx-core.c
@@ -10,9 +10,11 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "i2c-cavium.h"
@@ -106,6 +108,51 @@ static void thunder_i2c_clock_disable(struct device *dev, 
struct clk *clk)
devm_clk_put(dev, clk);
 }
 
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+static int thunder_i2c_smbus_setup_of(struct octeon_i2c *i2c,
+ struct device_node *node)
+{
+   u32 type;
+
+   if (!node)
+   return -EINVAL;
+
+   i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
+   if (!i2c->alert_data.irq)
+   return -EINVAL;
+
+   type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
+   i2c->alert_data.alert_edge_triggered =
+   (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
+
+   i2c->ara = i2c_setup_smbus_alert(>adap, >alert_data);
+   if (!i2c->ara)
+   return -ENODEV;
+   return 0;
+}
+#endif
+
+static int thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
+  struct device_node *node)
+{
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+   /* TODO: ACPI support */
+   if (!acpi_disabled)
+   return -EOPNOTSUPP;
+
+   return thunder_i2c_smbus_setup_of(i2c, node);
+#endif
+   return 0;
+}
+
+static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
+{
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+   if (i2c->ara)
+   i2c_unregister_device(i2c->ara);
+#endif
+}
+
 static int thunder_i2c_probe_pci(struct pci_dev *pdev,
 const struct pci_device_id *ent)
 {
@@ -189,6 +236,9 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
goto out_irq;
}
 
+   ret = thunder_i2c_smbus_setup(i2c, pdev->dev.of_node);
+   if (ret < 0)
+   dev_info(dev, "SMBUS alert not active on this bus\n");
dev_info(i2c->dev, "probed\n");
return 0;
 
@@ -219,6 +269,7 @@ static void thunder_i2c_remove_pci(struct pci_dev *pdev)
 
dev = i2c->dev;
thunder_i2c_clock_disable(dev, i2c->clk);
+   thunder_i2c_smbus_remove(i2c);
i2c_del_adapter(>adap);
devm_free_irq(dev, i2c->i2c_msix.vector, i2c);
pci_disable_msix(pdev);
-- 
1.9.1



[PATCH v10 0/8] i2c-octeon and i2c-thunderx driver

2016-06-15 Thread Jan Glauber
Hi Wolfram,

I'm reposting the rebased ThunderX i2c driver series.
Patches are on-top of 4.7-rc3.

Changes to v9:
- rebased on top of upstreamed octeon i2c fixes
- reduced default sclk to 700Mhz

Changes to v8:
- Use device property for clock-frequency setting in thunderx,
  get rid of of_find_node_by_name
- Simplify adap.name by using device name
- SMBUS ACPI handling
- Re-phrase SMBUS error/not-specified message

Thanks,
Jan

-

Jan Glauber (8):
  i2c: octeon: Rename driver to prepare for split
  i2c: octeon: Split the driver into two parts
  i2c: thunderx: Add i2c driver for ThunderX SOC
  i2c: thunderx: Add SMBUS alert support
  i2c: octeon,thunderx: Move register offsets to struct
  i2c: octeon: Sort include files alphabetically
  i2c: cavium: Use booleon values for booleon variables
  i2c: octeon: thunderx: Add MAINTAINERS entry

 MAINTAINERS   |   25 +-
 drivers/i2c/busses/Kconfig|   10 +
 drivers/i2c/busses/Makefile   |3 +
 drivers/i2c/busses/{i2c-octeon.c => i2c-cavium.c} | 1039 ++---
 drivers/i2c/busses/i2c-cavium.h   |  214 +
 drivers/i2c/busses/i2c-octeon-core.c  |  288 ++
 drivers/i2c/busses/i2c-thunderx-core.c|  305 ++
 7 files changed, 1134 insertions(+), 750 deletions(-)
 rename drivers/i2c/busses/{i2c-octeon.c => i2c-cavium.c} (57%)
 create mode 100644 drivers/i2c/busses/i2c-cavium.h
 create mode 100644 drivers/i2c/busses/i2c-octeon-core.c
 create mode 100644 drivers/i2c/busses/i2c-thunderx-core.c

-- 
1.9.1



[PATCH v10 1/8] i2c: octeon: Rename driver to prepare for split

2016-06-15 Thread Jan Glauber
This is an intermediate commit in preparation of the driver split.
The module rename in this commit will be reverted in the next patch,
this is just done to make the series bisectible.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/Makefile| 2 +-
 drivers/i2c/busses/{i2c-octeon.c => i2c-octeon-core.c} | 0
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename drivers/i2c/busses/{i2c-octeon.c => i2c-octeon-core.c} (100%)

diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 37f2819..3405286 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -91,7 +91,7 @@ obj-$(CONFIG_I2C_UNIPHIER)+= i2c-uniphier.o
 obj-$(CONFIG_I2C_UNIPHIER_F)   += i2c-uniphier-f.o
 obj-$(CONFIG_I2C_VERSATILE)+= i2c-versatile.o
 obj-$(CONFIG_I2C_WMT)  += i2c-wmt.o
-obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon.o
+obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon-core.o
 obj-$(CONFIG_I2C_XILINX)   += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
diff --git a/drivers/i2c/busses/i2c-octeon.c 
b/drivers/i2c/busses/i2c-octeon-core.c
similarity index 100%
rename from drivers/i2c/busses/i2c-octeon.c
rename to drivers/i2c/busses/i2c-octeon-core.c
-- 
1.9.1



[PATCH v10 6/8] i2c: octeon: Sort include files alphabetically

2016-06-15 Thread Jan Glauber
Sort include files alphabetically to reduce probability of merge
conflicts.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon-core.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon-core.c 
b/drivers/i2c/busses/i2c-octeon-core.c
index 038007d..ce535fa 100644
--- a/drivers/i2c/busses/i2c-octeon-core.c
+++ b/drivers/i2c/busses/i2c-octeon-core.c
@@ -12,16 +12,16 @@
  */
 
 #include 
-#include 
+#include 
+#include 
 #include 
+#include 
 #include 
 #include 
-#include 
+#include 
+#include 
 #include 
 #include 
-#include 
-#include 
-#include 
 
 #include 
 #include "i2c-cavium.h"
-- 
1.9.1



[PATCH v10 5/8] i2c: octeon,thunderx: Move register offsets to struct

2016-06-15 Thread Jan Glauber
The register offsets are different between Octeon and ThunderX so move
them into the algorithm struct and get rid of the define.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-cavium.c| 28 +--
 drivers/i2c/busses/i2c-cavium.h| 35 +-
 drivers/i2c/busses/i2c-octeon-core.c   |  4 
 drivers/i2c/busses/i2c-thunderx-core.c |  4 
 4 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/drivers/i2c/busses/i2c-cavium.c b/drivers/i2c/busses/i2c-cavium.c
index 3e4dd64..56b23c2 100644
--- a/drivers/i2c/busses/i2c-cavium.c
+++ b/drivers/i2c/busses/i2c-cavium.c
@@ -99,7 +99,7 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 
 static bool octeon_i2c_hlc_test_valid(struct octeon_i2c *i2c)
 {
-   return (__raw_readq(i2c->twsi_base + SW_TWSI) & SW_TWSI_V) == 0;
+   return (__raw_readq(i2c->twsi_base + SW_TWSI(i2c)) & SW_TWSI_V) == 0;
 }
 
 static bool octeon_i2c_hlc_test_ready(struct octeon_i2c *i2c, bool *first)
@@ -446,12 +446,12 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
else
cmd |= SW_TWSI_OP_7;
 
-   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
goto err;
 
-   cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+   cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
if ((cmd & SW_TWSI_R) == 0)
return -EAGAIN;
 
@@ -459,7 +459,7 @@ static int octeon_i2c_hlc_read(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
 
if (msgs[0].len > 4) {
-   cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
+   cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT(i2c));
for (i = 0; i  < msgs[0].len - 4 && i < 4; i++, j--)
msgs[0].buf[j] = (cmd >> (8 * i)) & 0xff;
}
@@ -496,15 +496,15 @@ static int octeon_i2c_hlc_write(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
 
for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
ext |= (u64)msgs[0].buf[j] << (8 * i);
-   octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
+   octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c));
}
 
-   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
goto err;
 
-   cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+   cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
if ((cmd & SW_TWSI_R) == 0)
return -EAGAIN;
 
@@ -539,19 +539,19 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c 
*i2c, struct i2c_msg *msgs
cmd |= SW_TWSI_EIA;
ext = (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
cmd |= (u64)msgs[0].buf[1] << SW_TWSI_IA_SHIFT;
-   octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
+   octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c));
} else {
cmd |= (u64)msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
}
 
octeon_i2c_hlc_int_clear(i2c);
-   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI(i2c));
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
goto err;
 
-   cmd = __raw_readq(i2c->twsi_base + SW_TWSI);
+   cmd = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
if ((cmd & SW_TWSI_R) == 0)
return -EAGAIN;
 
@@ -559,7 +559,7 @@ static int octeon_i2c_hlc_comp_read(struct octeon_i2c *i2c, 
struct i2c_msg *msgs
msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
 
if (msgs[1].len > 4) {
-   cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT);
+   cmd = __raw_readq(i2c->twsi_base + SW_TWSI_EXT(i2c));
for (i = 0; i  < msgs[1].len - 4 && i < 4; i++, j--)
msgs[1].buf[j] = (cmd >> (8 * i)) & 0xff;
}
@@ -606,16 +606,16 @@ static int octeon_i2c_hlc_comp_write(struct octeon_i2c 
*i2c, struct i2c_msg *msg
set_ext = true;
}
if (set_ext)
-   octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT);
+   octeon_i2c_writeq_flush(ext, i2c->twsi_base + SW_TWSI_EXT(i2c));
 
octeon_i2c_hlc_int_clear(i2c);
-   octeon_i2c_writeq_flush(cmd, i2c->twsi_base + SW_TWSI);
+   octeon_i2c_writeq_flush(cmd, i2c->twsi_

[PATCH v10 8/8] i2c: octeon: thunderx: Add MAINTAINERS entry

2016-06-15 Thread Jan Glauber
The i2c Octeon and ThunderX drivers are maintained by Cavium.
While at it fix the whitespace errors of the next entry.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <david.da...@cavium.com>
---
 MAINTAINERS | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 16700e4..ff8075a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2827,15 +2827,24 @@ S:  Maintained
 F: drivers/iio/light/cm*
 F: Documentation/devicetree/bindings/i2c/trivial-devices.txt
 
+CAVIUM I2C DRIVER
+M: Jan Glauber <jglau...@cavium.com>
+M: David Daney <david.da...@cavium.com>
+W: http://www.cavium.com
+S: Supported
+F: drivers/i2c/busses/i2c-cavium*
+F: drivers/i2c/busses/i2c-octeon*
+F: drivers/i2c/busses/i2c-thunderx*
+
 CAVIUM LIQUIDIO NETWORK DRIVER
-M: Derek Chickles <derek.chick...@caviumnetworks.com>
-M: Satanand Burla <satananda.bu...@caviumnetworks.com>
-M: Felix Manlunas <felix.manlu...@caviumnetworks.com>
-M: Raghu Vatsavayi <raghu.vatsav...@caviumnetworks.com>
-L: net...@vger.kernel.org
-W: http://www.cavium.com
-S: Supported
-F: drivers/net/ethernet/cavium/liquidio/
+M: Derek Chickles <derek.chick...@caviumnetworks.com>
+M: Satanand Burla <satananda.bu...@caviumnetworks.com>
+M: Felix Manlunas <felix.manlu...@caviumnetworks.com>
+M: Raghu Vatsavayi <raghu.vatsav...@caviumnetworks.com>
+L: net...@vger.kernel.org
+W: http://www.cavium.com
+S: Supported
+F: drivers/net/ethernet/cavium/liquidio/
 
 CC2520 IEEE-802.15.4 RADIO DRIVER
 M: Varka Bhadram <varkabhad...@gmail.com>
-- 
1.9.1



[RFC PATCH 1/7] arm64/perf: Basic uncore counter support for Cavium ThunderX

2016-02-12 Thread Jan Glauber
Provide uncore facilities for non-CPU performance counter units.
Based on Intel/AMD uncore pmu support.

The uncore PMUs can be found under /sys/bus/event_source/devices.
All counters are exported via sysfs in the corresponding events
files under the PMU directory so the perf tool can list the event names.

There are 2 points that are special in this implementation:

1) The PMU detection solely relies on PCI device detection. If a
   matching PCI device is found the PMU is created. The code can deal
   with multiple units of the same type, e.g. more than one memory
   controller.

2) Counters are summarized across the different units of the same type,
   e.g. L2C TAD 0..7 is presented as a single counter (adding the
   values from TAD 0 to 7). Although losing the ability to read a
   single value the merged values are easier to use and yield
   enough information.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/Makefile   |   1 +
 arch/arm64/kernel/uncore/Makefile|   1 +
 arch/arm64/kernel/uncore/uncore_cavium.c | 210 +++
 arch/arm64/kernel/uncore/uncore_cavium.h |  73 +++
 4 files changed, 285 insertions(+)
 create mode 100644 arch/arm64/kernel/uncore/Makefile
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium.h

diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 83cd7e6..c2d2810 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -42,6 +42,7 @@ arm64-obj-$(CONFIG_PCI)   += pci.o
 arm64-obj-$(CONFIG_ARMV8_DEPRECATED)   += armv8_deprecated.o
 arm64-obj-$(CONFIG_ACPI)   += acpi.o
 arm64-obj-$(CONFIG_PARAVIRT)   += paravirt.o
+arm64-obj-$(CONFIG_ARCH_THUNDER)   += uncore/
 
 obj-y  += $(arm64-obj-y) vdso/
 obj-m  += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
new file mode 100644
index 000..b9c72c2
--- /dev/null
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
new file mode 100644
index 000..0cfcc83
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -0,0 +1,210 @@
+/*
+ * Cavium Thunder uncore PMU support. Derived from Intel and AMD uncore code.
+ *
+ * Copyright (C) 2015,2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+int thunder_uncore_version;
+
+struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event)
+{
+   return NULL;
+}
+
+void thunder_uncore_read(struct perf_event *event)
+{
+   struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+   struct hw_perf_event *hwc = >hw;
+   u64 prev, new = 0;
+   s64 delta;
+   int i;
+
+   /*
+* since we do not enable counter overflow interrupts,
+* we do not have to worry about prev_count changing on us
+*/
+
+   prev = local64_read(>prev_count);
+
+   /* read counter values from all units */
+   for (i = 0; i < uncore->nr_units; i++)
+   new += readq(map_offset(hwc->event_base, uncore, i));
+
+   local64_set(>prev_count, new);
+   delta = new - prev;
+   local64_add(delta, >count);
+}
+
+void thunder_uncore_del(struct perf_event *event, int flags)
+{
+   struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+   struct hw_perf_event *hwc = >hw;
+   int i;
+
+   event->pmu->stop(event, PERF_EF_UPDATE);
+
+   for (i = 0; i < uncore->num_counters; i++) {
+   if (cmpxchg(>events[i], event, NULL) == event)
+   break;
+   }
+   hwc->idx = -1;
+}
+
+int thunder_uncore_event_init(struct perf_event *event)
+{
+   struct hw_perf_event *hwc = >hw;
+   struct thunder_uncore *uncore;
+
+   if (event->attr.type != event->pmu->type)
+   return -ENOENT;
+
+   /* we do not support sampling */
+   if (is_sampling_event(event))
+   return -EINVAL;
+
+   /* counters do not have these bits */
+   if (event->attr.exclude_user||
+   event->attr.exclude_kernel  ||
+   event->attr.exclude_host||
+   event->attr.exclude_guest   ||
+   event->attr.exclude_hv  ||
+   event->attr.exclude_idle)
+   return -EINVAL;
+
+   /* and we do not enable counter overflow interrupts */
+
+   uncore = event_to_thunder_uncore(event);
+   if (!uncore)
+   return -ENODEV;
+   if (!uncore->event_valid(event->a

[RFC PATCH 5/7] arm64/perf: Cavium ThunderX OCX LNE uncore support

2016-02-12 Thread Jan Glauber
Support counters for the CCPI Interface controller (OCX) lanes.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/uncore/Makefile|   3 +-
 arch/arm64/kernel/uncore/uncore_cavium.c |   3 +
 arch/arm64/kernel/uncore/uncore_cavium.h |   4 +
 arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c | 270 +++
 4 files changed, 279 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c

diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
index 81479e8..da39f452 100644
--- a/arch/arm64/kernel/uncore/Makefile
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o  \
  uncore_cavium_l2c_tad.o   \
  uncore_cavium_l2c_cbc.o   \
- uncore_cavium_lmc.o
+ uncore_cavium_lmc.o   \
+ uncore_cavium_ocx_lne.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
index a972418..f2fbdea 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.c
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -28,6 +28,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct 
perf_event *event)
return thunder_uncore_l2c_cbc;
else if (event->pmu->type == thunder_lmc_pmu.type)
return thunder_uncore_lmc;
+   else if (event->pmu->type == thunder_ocx_lne_pmu.type)
+   return thunder_uncore_ocx_lne;
else
return NULL;
 }
@@ -215,6 +217,7 @@ static int __init thunder_uncore_init(void)
thunder_uncore_l2c_tad_setup();
thunder_uncore_l2c_cbc_setup();
thunder_uncore_lmc_setup();
+   thunder_uncore_ocx_lne_setup();
return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.h 
b/arch/arm64/kernel/uncore/uncore_cavium.h
index 6e3beba..b9bcb42 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.h
+++ b/arch/arm64/kernel/uncore/uncore_cavium.h
@@ -16,6 +16,7 @@ enum uncore_type {
L2C_TAD_TYPE,
L2C_CBC_TYPE,
LMC_TYPE,
+   OCX_LNE_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -64,9 +65,11 @@ extern struct attribute_group thunder_uncore_attr_group;
 extern struct thunder_uncore *thunder_uncore_l2c_tad;
 extern struct thunder_uncore *thunder_uncore_l2c_cbc;
 extern struct thunder_uncore *thunder_uncore_lmc;
+extern struct thunder_uncore *thunder_uncore_ocx_lne;
 extern struct pmu thunder_l2c_tad_pmu;
 extern struct pmu thunder_l2c_cbc_pmu;
 extern struct pmu thunder_lmc_pmu;
+extern struct pmu thunder_ocx_lne_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -83,3 +86,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
 int thunder_uncore_lmc_setup(void);
+int thunder_uncore_ocx_lne_setup(void);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c 
b/arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c
new file mode 100644
index 000..c2981b9
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c
@@ -0,0 +1,270 @@
+/*
+ * Cavium Thunder uncore PMU support, OCX LNE counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_OCX
+#define PCI_DEVICE_ID_THUNDER_OCX  0xa013
+#endif
+
+#define OCX_LNE_NR_COUNTERS15
+#define OCX_LNE_NR_UNITS   24
+#define OCX_LNE_UNIT_OFFSET0x100
+#define OCX_LNE_CONTROL_OFFSET 0x8000
+#define OCX_LNE_COUNTER_OFFSET 0x40
+
+#define OCX_LNE_STAT_DISABLE   0
+#define OCX_LNE_STAT_ENABLE1
+
+/* OCX LNE event list */
+#define OCX_LNE_EVENT_STAT00   0x00
+#define OCX_LNE_EVENT_STAT01   0x01
+#define OCX_LNE_EVENT_STAT02   0x02
+#define OCX_LNE_EVENT_STAT03   0x03
+#define OCX_LNE_EVENT_STAT04   0x04
+#define OCX_LNE_EVENT_STAT05   0x05
+#define OCX_LNE_EVENT_STAT06   0x06
+#define OCX_LNE_EVENT_STAT07   0x07
+#define OCX_LNE_EVENT_STAT08   0x08
+#define OCX_LNE_EVENT_STAT09   0x09
+#define OCX_LNE_EVENT_STAT10   0x0a
+#define OCX_LNE_EVENT_STAT11   0x0b
+#define OCX_LNE_EVENT_STAT12   0x0c
+#define OCX_LNE_EVENT_STAT13   0x0d
+#define OCX_LNE_EVENT_STAT14   0x0e
+
+struct thunder_uncore *thunder_uncore_ocx_

[RFC PATCH 4/7] arm64/perf: Cavium ThunderX LMC uncore support

2016-02-12 Thread Jan Glauber
Support counters on the DRAM controllers.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/uncore/Makefile|   3 +-
 arch/arm64/kernel/uncore/uncore_cavium.c |   3 +
 arch/arm64/kernel/uncore/uncore_cavium.h |   4 +
 arch/arm64/kernel/uncore/uncore_cavium_lmc.c | 201 +++
 4 files changed, 210 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_lmc.c

diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
index d52ecc9..81479e8 100644
--- a/arch/arm64/kernel/uncore/Makefile
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o  \
  uncore_cavium_l2c_tad.o   \
- uncore_cavium_l2c_cbc.o
+ uncore_cavium_l2c_cbc.o   \
+ uncore_cavium_lmc.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
index 0304c60..a972418 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.c
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -26,6 +26,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct 
perf_event *event)
return thunder_uncore_l2c_tad;
else if (event->pmu->type == thunder_l2c_cbc_pmu.type)
return thunder_uncore_l2c_cbc;
+   else if (event->pmu->type == thunder_lmc_pmu.type)
+   return thunder_uncore_lmc;
else
return NULL;
 }
@@ -212,6 +214,7 @@ static int __init thunder_uncore_init(void)
 
thunder_uncore_l2c_tad_setup();
thunder_uncore_l2c_cbc_setup();
+   thunder_uncore_lmc_setup();
return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.h 
b/arch/arm64/kernel/uncore/uncore_cavium.h
index 74f44d7..6e3beba 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.h
+++ b/arch/arm64/kernel/uncore/uncore_cavium.h
@@ -15,6 +15,7 @@
 enum uncore_type {
L2C_TAD_TYPE,
L2C_CBC_TYPE,
+   LMC_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -62,8 +63,10 @@ static inline void __iomem *map_offset(unsigned long addr,
 extern struct attribute_group thunder_uncore_attr_group;
 extern struct thunder_uncore *thunder_uncore_l2c_tad;
 extern struct thunder_uncore *thunder_uncore_l2c_cbc;
+extern struct thunder_uncore *thunder_uncore_lmc;
 extern struct pmu thunder_l2c_tad_pmu;
 extern struct pmu thunder_l2c_cbc_pmu;
+extern struct pmu thunder_lmc_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -79,3 +82,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
 
 int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
+int thunder_uncore_lmc_setup(void);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium_lmc.c 
b/arch/arm64/kernel/uncore/uncore_cavium_lmc.c
new file mode 100644
index 000..9667819
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium_lmc.c
@@ -0,0 +1,201 @@
+/*
+ * Cavium Thunder uncore PMU support, LMC counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_LMC
+#define PCI_DEVICE_ID_THUNDER_LMC  0xa022
+#endif
+
+#define LMC_NR_COUNTERS3
+#define LMC_PASS2_NR_COUNTERS  5
+#define LMC_MAX_NR_COUNTERSLMC_PASS2_NR_COUNTERS
+
+/* LMC event list */
+#define LMC_EVENT_IFB_CNT  0
+#define LMC_EVENT_OPS_CNT  1
+#define LMC_EVENT_DCLK_CNT 2
+
+/* pass 2 added counters */
+#define LMC_EVENT_BANK_CONFLICT1   3
+#define LMC_EVENT_BANK_CONFLICT2   4
+
+#define LMC_COUNTER_START  LMC_EVENT_IFB_CNT
+#define LMC_COUNTER_END(LMC_EVENT_BANK_CONFLICT2 + 8)
+
+struct thunder_uncore *thunder_uncore_lmc;
+
+int lmc_events[LMC_MAX_NR_COUNTERS] = { 0x1d0, 0x1d8, 0x1e0, 0x360, 0x368 };
+
+static void thunder_uncore_start(struct perf_event *event, int flags)
+{
+   struct hw_perf_event *hwc = >hw;
+
+   hwc->state = 0;
+   perf_event_update_userpage(event);
+}
+
+static void thunder_uncore_stop(struct perf_event *event, int flags)
+{
+   struct hw_perf_event *hwc = >hw;
+
+   if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+   thunder_uncore_read(event);
+   hwc->state |= PERF_HES_UPTODATE;
+   }
+}
+
+static int thunder_uncore_add(struct perf_event *event, int flags)
+{
+   struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+   struct hw_perf_event *hwc = >hw;
+   int i;
+
+   WARN_ON_ONCE(!uncore);
+
+   /* are we already assigned

[RFC PATCH 2/7] arm64/perf: Cavium ThunderX L2C TAD uncore support

2016-02-12 Thread Jan Glauber
Support counters of the L2 Cache tag and data units.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/uncore/Makefile|   3 +-
 arch/arm64/kernel/uncore/uncore_cavium.c |   6 +-
 arch/arm64/kernel/uncore/uncore_cavium.h |   6 +-
 arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c | 600 +++
 4 files changed, 612 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c

diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
index b9c72c2..6a16caf 100644
--- a/arch/arm64/kernel/uncore/Makefile
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -1 +1,2 @@
-obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o
+obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o  \
+ uncore_cavium_l2c_tad.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
index 0cfcc83..b625caf 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.c
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -22,7 +22,10 @@ int thunder_uncore_version;
 
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event)
 {
-   return NULL;
+   if (event->pmu->type == thunder_l2c_tad_pmu.type)
+   return thunder_uncore_l2c_tad;
+   else
+   return NULL;
 }
 
 void thunder_uncore_read(struct perf_event *event)
@@ -205,6 +208,7 @@ static int __init thunder_uncore_init(void)
thunder_uncore_version = 1;
pr_info("PMU version: %d\n", thunder_uncore_version);
 
+   thunder_uncore_l2c_tad_setup();
return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.h 
b/arch/arm64/kernel/uncore/uncore_cavium.h
index acd121d..90e6a2d 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.h
+++ b/arch/arm64/kernel/uncore/uncore_cavium.h
@@ -13,7 +13,7 @@
 #define pr_fmt(fmt) "thunderx_uncore: " fmt
 
 enum uncore_type {
-   NOP_TYPE,
+   L2C_TAD_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -59,6 +59,8 @@ static inline void __iomem *map_offset(unsigned long addr,
 }
 
 extern struct attribute_group thunder_uncore_attr_group;
+extern struct thunder_uncore *thunder_uncore_l2c_tad;
+extern struct pmu thunder_l2c_tad_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -71,3 +73,5 @@ int thunder_uncore_setup(struct thunder_uncore *uncore, int 
id,
 ssize_t thunder_events_sysfs_show(struct device *dev,
  struct device_attribute *attr,
  char *page);
+
+int thunder_uncore_l2c_tad_setup(void);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c 
b/arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c
new file mode 100644
index 000..bf45b4a
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c
@@ -0,0 +1,600 @@
+/*
+ * Cavium Thunder uncore PMU support, L2C TAD counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_L2C_TAD
+#define PCI_DEVICE_ID_THUNDER_L2C_TAD  0xa02e
+#endif
+
+#define L2C_TAD_NR_COUNTERS 4
+#define L2C_TAD_CONTROL_OFFSET 0x1
+#define L2C_TAD_COUNTER_OFFSET 0x100
+
+/* L2C TAD event list */
+#define L2C_TAD_EVENTS_DISABLED0x00
+
+#define L2C_TAD_EVENT_L2T_HIT  0x01
+#define L2C_TAD_EVENT_L2T_MISS 0x02
+#define L2C_TAD_EVENT_L2T_NOALLOC  0x03
+#define L2C_TAD_EVENT_L2_VIC   0x04
+#define L2C_TAD_EVENT_SC_FAIL  0x05
+#define L2C_TAD_EVENT_SC_PASS  0x06
+#define L2C_TAD_EVENT_LFB_OCC  0x07
+#define L2C_TAD_EVENT_WAIT_LFB 0x08
+#define L2C_TAD_EVENT_WAIT_VAB 0x09
+
+#define L2C_TAD_EVENT_RTG_HIT  0x41
+#define L2C_TAD_EVENT_RTG_MISS 0x42
+#define L2C_TAD_EVENT_L2_RTG_VIC   0x44
+#define L2C_TAD_EVENT_L2_OPEN_OCI  0x48
+
+#define L2C_TAD_EVENT_QD0_IDX  0x80
+#define L2C_TAD_EVENT_QD0_RDAT 0x81
+#define L2C_TAD_EVENT_QD0_BNKS 0x82
+#define L2C_TAD_EVENT_QD0_WDAT 0x83
+
+#define L2C_TAD_EVENT_QD1_IDX  0x90
+#define L2C_TAD_EVENT_QD1_RDAT 0x91
+#define L2C_TAD_EVENT_QD1_BNKS 0x92
+#define L2C_TAD_EVENT_QD1_WDAT 0x93
+
+#define L2C_TAD_EVENT_QD2_IDX  0xa0
+#define L2C_TAD_EVENT_QD2_RDAT 0xa1
+#define L2C_TAD_EVENT_QD2_BNKS 0xa2
+#define L2C_TAD_EVENT_QD2_WDAT 0xa3
+
+#define L2C_TAD_EVENT_QD3_IDX  0xb0
+#define L2C_TAD_EVENT_QD3_RDAT 0xb1
+#define L2C_TAD_EVENT_QD3_BNKS 0xb2
+#define L2C_TAD_EVENT_QD3_WDAT 0xb3
+
+#define L2C_TAD_EVENT_QD4_IDX  0xc0
+#define L2C_TAD_EVENT_QD4_R

[RFC PATCH 3/7] arm64/perf: Cavium ThunderX L2C CBC uncore support

2016-02-12 Thread Jan Glauber
Support counters of the L2 cache crossbar connect.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/uncore/Makefile|   3 +-
 arch/arm64/kernel/uncore/uncore_cavium.c |   3 +
 arch/arm64/kernel/uncore/uncore_cavium.h |   4 +
 arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c | 239 +++
 4 files changed, 248 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c

diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
index 6a16caf..d52ecc9 100644
--- a/arch/arm64/kernel/uncore/Makefile
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o  \
- uncore_cavium_l2c_tad.o
+ uncore_cavium_l2c_tad.o   \
+ uncore_cavium_l2c_cbc.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
index b625caf..0304c60 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.c
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -24,6 +24,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct 
perf_event *event)
 {
if (event->pmu->type == thunder_l2c_tad_pmu.type)
return thunder_uncore_l2c_tad;
+   else if (event->pmu->type == thunder_l2c_cbc_pmu.type)
+   return thunder_uncore_l2c_cbc;
else
return NULL;
 }
@@ -209,6 +211,7 @@ static int __init thunder_uncore_init(void)
pr_info("PMU version: %d\n", thunder_uncore_version);
 
thunder_uncore_l2c_tad_setup();
+   thunder_uncore_l2c_cbc_setup();
return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.h 
b/arch/arm64/kernel/uncore/uncore_cavium.h
index 90e6a2d..74f44d7 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.h
+++ b/arch/arm64/kernel/uncore/uncore_cavium.h
@@ -14,6 +14,7 @@
 
 enum uncore_type {
L2C_TAD_TYPE,
+   L2C_CBC_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -60,7 +61,9 @@ static inline void __iomem *map_offset(unsigned long addr,
 
 extern struct attribute_group thunder_uncore_attr_group;
 extern struct thunder_uncore *thunder_uncore_l2c_tad;
+extern struct thunder_uncore *thunder_uncore_l2c_cbc;
 extern struct pmu thunder_l2c_tad_pmu;
+extern struct pmu thunder_l2c_cbc_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -75,3 +78,4 @@ ssize_t thunder_events_sysfs_show(struct device *dev,
  char *page);
 
 int thunder_uncore_l2c_tad_setup(void);
+int thunder_uncore_l2c_cbc_setup(void);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c 
b/arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c
new file mode 100644
index 000..f1ba9be
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c
@@ -0,0 +1,239 @@
+/*
+ * Cavium Thunder uncore PMU support, L2C CBC counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_L2C_CBC
+#define PCI_DEVICE_ID_THUNDER_L2C_CBC  0xa02f
+#endif
+
+#define L2C_CBC_NR_COUNTERS 16
+
+/* L2C CBC event list */
+#define L2C_CBC_EVENT_XMC0 0x00
+#define L2C_CBC_EVENT_XMD0 0x01
+#define L2C_CBC_EVENT_RSC0 0x02
+#define L2C_CBC_EVENT_RSD0 0x03
+#define L2C_CBC_EVENT_INV0 0x04
+#define L2C_CBC_EVENT_IOC0 0x05
+#define L2C_CBC_EVENT_IOR0 0x06
+
+#define L2C_CBC_EVENT_XMC1 0x08/* 0x40 */
+#define L2C_CBC_EVENT_XMD1 0x09
+#define L2C_CBC_EVENT_RSC1 0x0a
+#define L2C_CBC_EVENT_RSD1 0x0b
+#define L2C_CBC_EVENT_INV1 0x0c
+
+#define L2C_CBC_EVENT_XMC2 0x10/* 0x80 */
+#define L2C_CBC_EVENT_XMD2 0x11
+#define L2C_CBC_EVENT_RSC2 0x12
+#define L2C_CBC_EVENT_RSD2 0x13
+
+struct thunder_uncore *thunder_uncore_l2c_cbc;
+
+int l2c_cbc_events[L2C_CBC_NR_COUNTERS] = {
+   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+   0x08, 0x09, 0x0a, 0x0b, 0x0c,
+   0x10, 0x11, 0x12, 0x13
+};
+
+static void thunder_uncore_start(struct perf_event *event, int flags)
+{
+   struct thunder_uncore *uncore = event_to_thunder_uncore(event);
+   struct hw_perf_event *hwc = >hw;
+   u64 prev;
+   int i;
+
+   /* restore counter value divided by units into all counters */
+   if (flags & PERF_EF_RELOAD) {
+   prev = local64_read(>prev_count);
+   prev = prev / uncore->nr_units;
+   for (i = 0; i < uncore->nr_units; i++)
+   writeq(prev, map_offs

[RFC PATCH 7/7] arm64/perf: Cavium ThunderX OCX TLK uncore support

2016-02-12 Thread Jan Glauber
Support for the OCX transmit link counters.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/uncore/Makefile|   3 +-
 arch/arm64/kernel/uncore/uncore_cavium.c |   3 +
 arch/arm64/kernel/uncore/uncore_cavium.h |   4 +
 arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c | 366 +++
 4 files changed, 375 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c

diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
index 752af39..a267800 100644
--- a/arch/arm64/kernel/uncore/Makefile
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o   \
  uncore_cavium_l2c_cbc.o   \
  uncore_cavium_lmc.o   \
  uncore_cavium_ocx_lne.o   \
- uncore_cavium_ocx_frc.o
+ uncore_cavium_ocx_frc.o   \
+ uncore_cavium_ocx_tlk.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
index 9fed1d6..e2edb7a4 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.c
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -32,6 +32,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct 
perf_event *event)
return thunder_uncore_ocx_lne;
else if (event->pmu->type == thunder_ocx_frc_pmu.type)
return thunder_uncore_ocx_frc;
+   else if (event->pmu->type == thunder_ocx_tlk_pmu.type)
+   return thunder_uncore_ocx_tlk;
else
return NULL;
 }
@@ -221,6 +223,7 @@ static int __init thunder_uncore_init(void)
thunder_uncore_lmc_setup();
thunder_uncore_ocx_lne_setup();
thunder_uncore_ocx_frc_setup();
+   thunder_uncore_ocx_tlk_setup();
return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.h 
b/arch/arm64/kernel/uncore/uncore_cavium.h
index 07bd4f4..f312d41 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.h
+++ b/arch/arm64/kernel/uncore/uncore_cavium.h
@@ -18,6 +18,7 @@ enum uncore_type {
LMC_TYPE,
OCX_LNE_TYPE,
OCX_FRC_TYPE,
+   OCX_TLK_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -68,11 +69,13 @@ extern struct thunder_uncore *thunder_uncore_l2c_cbc;
 extern struct thunder_uncore *thunder_uncore_lmc;
 extern struct thunder_uncore *thunder_uncore_ocx_lne;
 extern struct thunder_uncore *thunder_uncore_ocx_frc;
+extern struct thunder_uncore *thunder_uncore_ocx_tlk;
 extern struct pmu thunder_l2c_tad_pmu;
 extern struct pmu thunder_l2c_cbc_pmu;
 extern struct pmu thunder_lmc_pmu;
 extern struct pmu thunder_ocx_lne_pmu;
 extern struct pmu thunder_ocx_frc_pmu;
+extern struct pmu thunder_ocx_tlk_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -91,3 +94,4 @@ int thunder_uncore_l2c_cbc_setup(void);
 int thunder_uncore_lmc_setup(void);
 int thunder_uncore_ocx_lne_setup(void);
 int thunder_uncore_ocx_frc_setup(void);
+int thunder_uncore_ocx_tlk_setup(void);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c 
b/arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c
new file mode 100644
index 000..71ef3ae
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c
@@ -0,0 +1,366 @@
+/*
+ * Cavium Thunder uncore PMU support, OCX TLK counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_OCX
+#define PCI_DEVICE_ID_THUNDER_OCX  0xa013
+#endif
+
+#define OCX_TLK_NR_UNITS   3
+#define OCX_TLK_UNIT_OFFSET0x2000
+#define OCX_TLK_CONTROL_OFFSET 0x10040
+#define OCX_TLK_COUNTER_OFFSET 0x10400
+
+#define OCX_TLK_STAT_DISABLE   0
+#define OCX_TLK_STAT_ENABLE1
+
+/* OCX TLK event list */
+#define OCX_TLK_EVENT_STAT_IDLE_CNT0x00
+#define OCX_TLK_EVENT_STAT_DATA_CNT0x01
+#define OCX_TLK_EVENT_STAT_SYNC_CNT0x02
+#define OCX_TLK_EVENT_STAT_RETRY_CNT   0x03
+#define OCX_TLK_EVENT_STAT_ERR_CNT 0x04
+
+#define OCX_TLK_EVENT_STAT_MAT0_CNT0x08
+#define OCX_TLK_EVENT_STAT_MAT1_CNT0x09
+#define OCX_TLK_EVENT_STAT_MAT2_CNT0x0a
+#define OCX_TLK_EVENT_STAT_MAT3_CNT0x0b
+
+#define OCX_TLK_EVENT_STAT_VC0_CMD 0x10
+#define OCX_TLK_EVENT_STAT_VC1_CMD 0x11
+#define OCX_TLK_EVENT_STAT_VC2_CMD 0x12
+#define OCX_TLK_EVENT_STAT_VC3_CMD 0x13
+#define OCX_TLK_EVENT_STAT_VC4_CMD 0x14
+#define OCX_TLK_EVENT_STAT_V

[RFC PATCH 6/7] arm64/perf: Cavium ThunderX OCX FRC uncore support

2016-02-12 Thread Jan Glauber
Support for the OCX alignment counters.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/uncore/Makefile|   3 +-
 arch/arm64/kernel/uncore/uncore_cavium.c |   3 +
 arch/arm64/kernel/uncore/uncore_cavium.h |   4 +
 arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c | 248 +++
 4 files changed, 257 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c

diff --git a/arch/arm64/kernel/uncore/Makefile 
b/arch/arm64/kernel/uncore/Makefile
index da39f452..752af39 100644
--- a/arch/arm64/kernel/uncore/Makefile
+++ b/arch/arm64/kernel/uncore/Makefile
@@ -2,4 +2,5 @@ obj-$(CONFIG_ARCH_THUNDER) += uncore_cavium.o   \
  uncore_cavium_l2c_tad.o   \
  uncore_cavium_l2c_cbc.o   \
  uncore_cavium_lmc.o   \
- uncore_cavium_ocx_lne.o
+ uncore_cavium_ocx_lne.o   \
+ uncore_cavium_ocx_frc.o
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.c 
b/arch/arm64/kernel/uncore/uncore_cavium.c
index f2fbdea..9fed1d6 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.c
+++ b/arch/arm64/kernel/uncore/uncore_cavium.c
@@ -30,6 +30,8 @@ struct thunder_uncore *event_to_thunder_uncore(struct 
perf_event *event)
return thunder_uncore_lmc;
else if (event->pmu->type == thunder_ocx_lne_pmu.type)
return thunder_uncore_ocx_lne;
+   else if (event->pmu->type == thunder_ocx_frc_pmu.type)
+   return thunder_uncore_ocx_frc;
else
return NULL;
 }
@@ -218,6 +220,7 @@ static int __init thunder_uncore_init(void)
thunder_uncore_l2c_cbc_setup();
thunder_uncore_lmc_setup();
thunder_uncore_ocx_lne_setup();
+   thunder_uncore_ocx_frc_setup();
return 0;
 }
 late_initcall(thunder_uncore_init);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium.h 
b/arch/arm64/kernel/uncore/uncore_cavium.h
index b9bcb42..07bd4f4 100644
--- a/arch/arm64/kernel/uncore/uncore_cavium.h
+++ b/arch/arm64/kernel/uncore/uncore_cavium.h
@@ -17,6 +17,7 @@ enum uncore_type {
L2C_CBC_TYPE,
LMC_TYPE,
OCX_LNE_TYPE,
+   OCX_FRC_TYPE,
 };
 
 extern int thunder_uncore_version;
@@ -66,10 +67,12 @@ extern struct thunder_uncore *thunder_uncore_l2c_tad;
 extern struct thunder_uncore *thunder_uncore_l2c_cbc;
 extern struct thunder_uncore *thunder_uncore_lmc;
 extern struct thunder_uncore *thunder_uncore_ocx_lne;
+extern struct thunder_uncore *thunder_uncore_ocx_frc;
 extern struct pmu thunder_l2c_tad_pmu;
 extern struct pmu thunder_l2c_cbc_pmu;
 extern struct pmu thunder_lmc_pmu;
 extern struct pmu thunder_ocx_lne_pmu;
+extern struct pmu thunder_ocx_frc_pmu;
 
 /* Prototypes */
 struct thunder_uncore *event_to_thunder_uncore(struct perf_event *event);
@@ -87,3 +90,4 @@ int thunder_uncore_l2c_tad_setup(void);
 int thunder_uncore_l2c_cbc_setup(void);
 int thunder_uncore_lmc_setup(void);
 int thunder_uncore_ocx_lne_setup(void);
+int thunder_uncore_ocx_frc_setup(void);
diff --git a/arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c 
b/arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c
new file mode 100644
index 000..7f62019
--- /dev/null
+++ b/arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c
@@ -0,0 +1,248 @@
+/*
+ * Cavium Thunder uncore PMU support, OCX FRC counters.
+ *
+ * Copyright 2016 Cavium Inc.
+ * Author: Jan Glauber <jan.glau...@cavium.com>
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "uncore_cavium.h"
+
+#ifndef PCI_DEVICE_ID_THUNDER_OCX
+#define PCI_DEVICE_ID_THUNDER_OCX  0xa013
+#endif
+
+#define OCX_FRC_NR_COUNTERS4
+#define OCX_FRC_NR_UNITS   6
+#define OCX_FRC_UNIT_OFFSET0x8
+#define OCX_FRC_COUNTER_OFFSET 0xfa00
+#define OCX_FRC_CONTROL_OFFSET 0xff00
+#define OCX_FRC_COUNTER_INC0x80
+#define OCX_FRC_EVENT_MASK 0x1f
+#define OCX_FRC_STAT_CONTROL_BIT   37
+
+/* OCX FRC event list */
+#define OCX_FRC_EVENT_STAT00x0
+#define OCX_FRC_EVENT_STAT10x1
+#define OCX_FRC_EVENT_STAT20x2
+#define OCX_FRC_EVENT_STAT30x3
+
+struct thunder_uncore *thunder_uncore_ocx_frc;
+
+static inline void __iomem *map_offset_ocx_frc(unsigned long addr,
+   struct thunder_uncore *uncore, int unit)
+{
+   return (void __iomem *) (addr +
+uncore->pdevs[0].map +
+unit * OCX_FRC_UNIT_OFFSET);
+}
+
+/*
+ * Summarize counters across all FRC's. Different from the other uncore
+ * PMUs because all FRC's are on one PCI device.
+ */
+static vo

[RFC PATCH 0/7] Cavium ThunderX uncore PMU support

2016-02-12 Thread Jan Glauber
Hi,

this patch series provides access to various counters on the ThunderX SOC.

For details of the implementation see patch #1.

Patches #2-7 add ther various ThunderX specific PMUs.

I did not want to put these file into arch/arm64/kernel so I added a
"uncore" directory. Maybe this should be put somewhere under drivers/
instead.

Feedback welcome!

Jan


Jan Glauber (7):
  arm64/perf: Basic uncore counter support for Cavium ThunderX
  arm64/perf: Cavium ThunderX L2C TAD uncore support
  arm64/perf: Cavium ThunderX L2C CBC uncore support
  arm64/perf: Cavium ThunderX LMC uncore support
  arm64/perf: Cavium ThunderX OCX LNE uncore support
  arm64/perf: Cavium ThunderX OCX FRC uncore support
  arm64/perf: Cavium ThunderX OCX TLK uncore support

 arch/arm64/kernel/Makefile   |   1 +
 arch/arm64/kernel/uncore/Makefile|   7 +
 arch/arm64/kernel/uncore/uncore_cavium.c | 229 +
 arch/arm64/kernel/uncore/uncore_cavium.h |  97 
 arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c | 239 +
 arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c | 600 +++
 arch/arm64/kernel/uncore/uncore_cavium_lmc.c | 201 
 arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c | 248 ++
 arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c | 270 ++
 arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c | 366 ++
 10 files changed, 2258 insertions(+)
 create mode 100644 arch/arm64/kernel/uncore/Makefile
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium.h
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_l2c_cbc.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_l2c_tad.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_lmc.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_ocx_frc.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_ocx_lne.c
 create mode 100644 arch/arm64/kernel/uncore/uncore_cavium_ocx_tlk.c

-- 
1.9.1



Re: [PATCH v3 0/5] Cavium ThunderX PMU support

2016-02-11 Thread Jan Glauber
On Wed, Feb 03, 2016 at 06:11:55PM +0100, Jan Glauber wrote:
> Hi,
> 
> I'm reposting the whole series just in case my previous attempt to
> repost only the broken patch was confusing. Patches are based on
> 4.5-rc2.

Can I get a review for these patches?

thanks,
Jan

> Patches 1-3 add support for ThunderX specific PMU events.
> 
> Patch 4 changes the cycle counter to overflow on 64 bit but tries to minimize
> code changes. Without this change perf does not work at all on ThunderX.
> 
> Patch 5 extends the event mask according to ARMv8.1 and also affects arm32.
> 
> Changes to v2:
> - fixed arm compile errors
> 
> Changes to v1:
> - renamed thunderx dt pmu binding to thunder
> 
> --Jan
> 
> Jan Glauber (5):
>   arm64/perf: Rename Cortex A57 events
>   arm64/perf: Add Cavium ThunderX PMU support
>   arm64: dts: Add Cavium ThunderX specific PMU
>   arm64/perf: Enable PMCR long cycle counter bit
>   arm64/perf: Extend event mask for ARMv8.1
> 
>  Documentation/devicetree/bindings/arm/pmu.txt |   1 +
>  arch/arm/kernel/perf_event_v6.c   |   6 +-
>  arch/arm/kernel/perf_event_v7.c   |  29 --
>  arch/arm/kernel/perf_event_xscale.c   |   4 +-
>  arch/arm64/boot/dts/cavium/thunder-88xx.dtsi  |   5 +
>  arch/arm64/kernel/perf_event.c| 145 
> --
>  drivers/perf/arm_pmu.c|   5 +-
>  include/linux/perf/arm_pmu.h  |   4 +-
>  8 files changed, 151 insertions(+), 48 deletions(-)
> 
> -- 
> 1.9.1


Re: [PATCH v2 5/5] arm64/perf: Extend event mask for ARMv8.1

2016-01-29 Thread Jan Glauber
On Fri, Jan 29, 2016 at 01:33:35AM +0800, kbuild test robot wrote:
> Hi Jan,
> 
> [auto build test ERROR on robh/for-next]
> [also build test ERROR on v4.5-rc1 next-20160128]
> [cannot apply to tip/perf/core]
> [if your patch is applied to the wrong git tree, please drop us a note to 
> help improving the system]
> 
> url:
> https://github.com/0day-ci/linux/commits/Jan-Glauber/Cavium-ThunderX-PMU-support/20160128-225855
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux for-next
> config: arm-corgi_defconfig (attached as .config)
> reproduce:
> wget 
> https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross
>  -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=arm 
> 
> All errors (new ones prefixed by >>):
> 
>arch/arm/kernel/perf_event_xscale.c: In function 'xscale_map_event':
> >> arch/arm/kernel/perf_event_xscale.c:360:9: error: too many arguments to 
> >> function 'armpmu_map_event'
>  return armpmu_map_event(event, _perf_map,
> ^

I forgot the arm32 parts of this patch. I'll resend this patch only, the
other patches don't touch arm32.

--Jan


[PATCH v2 5/5] arm64/perf: Extend event mask for ARMv8.1

2016-01-29 Thread Jan Glauber
ARMv8.1 increases the PMU event number space. Detect the
presence of this PMUv3 type and extend the event mask.

The event mask is moved to struct arm_pmu so different event masks
can exist, depending on the PMU type.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm/kernel/perf_event_v6.c |  6 --
 arch/arm/kernel/perf_event_v7.c | 29 +++--
 arch/arm/kernel/perf_event_xscale.c |  4 +++-
 arch/arm64/kernel/perf_event.c  | 33 +++--
 drivers/perf/arm_pmu.c  |  5 +++--
 include/linux/perf/arm_pmu.h|  4 ++--
 6 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index 09413e7..d6769f5 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -481,7 +481,7 @@ static void armv6mpcore_pmu_disable_event(struct perf_event 
*event)
 static int armv6_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map,
-   _perf_cache_map, 0xFF);
+   _perf_cache_map);
 }
 
 static void armv6pmu_init(struct arm_pmu *cpu_pmu)
@@ -494,6 +494,7 @@ static void armv6pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->get_event_idx  = armv6pmu_get_event_idx;
cpu_pmu->start  = armv6pmu_start;
cpu_pmu->stop   = armv6pmu_stop;
+   cpu_pmu->event_mask = 0xFF;
cpu_pmu->map_event  = armv6_map_event;
cpu_pmu->num_events = 3;
cpu_pmu->max_period = (1LLU << 32) - 1;
@@ -531,7 +532,7 @@ static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
 static int armv6mpcore_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map,
-   _perf_cache_map, 0xFF);
+   _perf_cache_map);
 }
 
 static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
@@ -545,6 +546,7 @@ static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->get_event_idx  = armv6pmu_get_event_idx;
cpu_pmu->start  = armv6pmu_start;
cpu_pmu->stop   = armv6pmu_stop;
+   cpu_pmu->event_mask = 0xFF;
cpu_pmu->map_event  = armv6mpcore_map_event;
cpu_pmu->num_events = 3;
cpu_pmu->max_period = (1LLU << 32) - 1;
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4152158..8aab098 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1042,7 +1042,7 @@ static int armv7pmu_get_event_idx(struct pmu_hw_events 
*cpuc,
int idx;
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = >hw;
-   unsigned long evtype = hwc->config_base & ARMV7_EVTYPE_EVENT;
+   unsigned long evtype = hwc->config_base & cpu_pmu->event_mask;
 
/* Always place a cycle counter into the cycle counter. */
if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
@@ -1109,55 +1109,55 @@ static void armv7pmu_reset(void *info)
 static int armv7_a8_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a8_perf_map,
-   _a8_perf_cache_map, 0xFF);
+   _a8_perf_cache_map);
 }
 
 static int armv7_a9_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a9_perf_map,
-   _a9_perf_cache_map, 0xFF);
+   _a9_perf_cache_map);
 }
 
 static int armv7_a5_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a5_perf_map,
-   _a5_perf_cache_map, 0xFF);
+   _a5_perf_cache_map);
 }
 
 static int armv7_a15_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a15_perf_map,
-   _a15_perf_cache_map, 0xFF);
+   _a15_perf_cache_map);
 }
 
 static int armv7_a7_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a7_perf_map,
-   _a7_perf_cache_map, 0xFF);
+   _a7_perf_cache_map);
 }
 
 static int armv7_a12_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a12_perf_map,
-   _a12_perf_cache_map, 0xFF);
+   _a12_perf_cache_map);
 }
 
 static int krait_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map,
-   _perf_cache_map, 0xF);
+   _perf_cache_map);
 }
 
 static int krait_map_event_no_branch(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map_no_branch,
-   _perf_cache_map, 0xF);
+

[PATCH v3 0/5] Cavium ThunderX PMU support

2016-02-03 Thread Jan Glauber
Hi,

I'm reposting the whole series just in case my previous attempt to
repost only the broken patch was confusing. Patches are based on
4.5-rc2.

Patches 1-3 add support for ThunderX specific PMU events.

Patch 4 changes the cycle counter to overflow on 64 bit but tries to minimize
code changes. Without this change perf does not work at all on ThunderX.

Patch 5 extends the event mask according to ARMv8.1 and also affects arm32.

Changes to v2:
- fixed arm compile errors

Changes to v1:
- renamed thunderx dt pmu binding to thunder

--Jan

Jan Glauber (5):
  arm64/perf: Rename Cortex A57 events
  arm64/perf: Add Cavium ThunderX PMU support
  arm64: dts: Add Cavium ThunderX specific PMU
  arm64/perf: Enable PMCR long cycle counter bit
  arm64/perf: Extend event mask for ARMv8.1

 Documentation/devicetree/bindings/arm/pmu.txt |   1 +
 arch/arm/kernel/perf_event_v6.c   |   6 +-
 arch/arm/kernel/perf_event_v7.c   |  29 --
 arch/arm/kernel/perf_event_xscale.c   |   4 +-
 arch/arm64/boot/dts/cavium/thunder-88xx.dtsi  |   5 +
 arch/arm64/kernel/perf_event.c| 145 --
 drivers/perf/arm_pmu.c|   5 +-
 include/linux/perf/arm_pmu.h  |   4 +-
 8 files changed, 151 insertions(+), 48 deletions(-)

-- 
1.9.1



[PATCH v3 2/5] arm64/perf: Add Cavium ThunderX PMU support

2016-02-03 Thread Jan Glauber
Support PMU events on Caviums ThunderX SOC. ThunderX supports
some additional counters compared to the default ARMv8 PMUv3:

- branch instructions counter
- stall frontend & backend counters
- L1 dcache load & store counters
- L1 icache counters
- iTLB & dTLB counters
- L1 dcache & icache prefetch counters

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 69 +-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 32fe656..c038e4e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -94,10 +94,19 @@
 #define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_ST0x43
 #define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD 0x4C
 #define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST 0x4D
+#define ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_LD 0x4E
+#define ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_ST 0x4F
 
 /* ARMv8 Cortex-A53 specific event types. */
 #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL0xC2
 
+/* ARMv8 Cavium Thunder specific event types. */
+#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST0xE9
+#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS0xEA
+#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS  0xEB
+#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS0xEC
+#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS  0xED
+
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
@@ -131,6 +140,18 @@ static const unsigned 
armv8_a57_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BUS_CYCLES]  = 
ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
 };
 
+static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = {
+   PERF_MAP_ALL_UNSUPPORTED,
+   [PERF_COUNT_HW_CPU_CYCLES]  = 
ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
+   [PERF_COUNT_HW_INSTRUCTIONS]= 
ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+   [PERF_COUNT_HW_CACHE_REFERENCES]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+   [PERF_COUNT_HW_CACHE_MISSES]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+   [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE,
+   [PERF_COUNT_HW_BRANCH_MISSES]   = 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+   [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 
ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
+   [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = 
ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
+};
+
 static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]

[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
@@ -193,6 +214,36 @@ static const unsigned 
armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
+static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+  [PERF_COUNT_HW_CACHE_OP_MAX]
+  
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+   PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+   [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_LD,
+   [C(L1D)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_LD,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_ST,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST,
+   [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = 
ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS,
+   [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = 
ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS,
+
+   [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
+   [C(L1I)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
+   [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = 
ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS,
+   [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = 
ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS,
+
+   [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_LD,
+   [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD,
+   [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_ST,
+   [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST,
+
+   [C(ITLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+
+   [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+   [C(BPU)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+   [C(BPU)][C(OP_W

[PATCH v3 4/5] arm64/perf: Enable PMCR long cycle counter bit

2016-02-03 Thread Jan Glauber
With the long cycle counter bit (LC) disabled the cycle counter is not
working on ThunderX SOC (ThunderX only implements Aarch64).
Also, according to documentation LC == 0 is deprecated.

To keep the code simple the patch does not introduce 64 bit wide counter
functions. Instead writing the cycle counter always sets the upper
32 bits so overflow interrupts are generated as before.

Original patch from Andrew Pinksi <andrew.pin...@caviumnetworks.com>

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index c038e4e..5e4275e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -405,6 +405,7 @@ static const struct attribute_group 
*armv8_pmuv3_attr_groups[] = {
 #define ARMV8_PMCR_D   (1 << 3) /* CCNT counts every 64th cpu cycle */
 #define ARMV8_PMCR_X   (1 << 4) /* Export to ETM */
 #define ARMV8_PMCR_DP  (1 << 5) /* Disable CCNT if non-invasive debug*/
+#define ARMV8_PMCR_LC  (1 << 6) /* Overflow on 64 bit cycle counter */
 #defineARMV8_PMCR_N_SHIFT  11   /* Number of counters 
supported */
 #defineARMV8_PMCR_N_MASK   0x1f
 #defineARMV8_PMCR_MASK 0x3f /* Mask for writable bits */
@@ -494,9 +495,16 @@ static inline void armv8pmu_write_counter(struct 
perf_event *event, u32 value)
if (!armv8pmu_counter_valid(cpu_pmu, idx))
pr_err("CPU%u writing wrong counter %d\n",
smp_processor_id(), idx);
-   else if (idx == ARMV8_IDX_CYCLE_COUNTER)
-   asm volatile("msr pmccntr_el0, %0" :: "r" (value));
-   else if (armv8pmu_select_counter(idx) == idx)
+   else if (idx == ARMV8_IDX_CYCLE_COUNTER) {
+   /*
+* Set the upper 32bits as this is a 64bit counter but we only
+* count using the lower 32bits and we want an interrupt when
+* it overflows.
+*/
+   u64 value64 = 0xULL | value;
+
+   asm volatile("msr pmccntr_el0, %0" :: "r" (value64));
+   } else if (armv8pmu_select_counter(idx) == idx)
asm volatile("msr pmxevcntr_el0, %0" :: "r" (value));
 }
 
@@ -768,8 +776,11 @@ static void armv8pmu_reset(void *info)
armv8pmu_disable_intens(idx);
}
 
-   /* Initialize & Reset PMNC: C and P bits. */
-   armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C);
+   /*
+* Initialize & Reset PMNC. Request overflow on 64 bit but
+* cheat in armv8pmu_write_counter().
+*/
+   armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C | ARMV8_PMCR_LC);
 }
 
 static int armv8_pmuv3_map_event(struct perf_event *event)
-- 
1.9.1



[PATCH v3 1/5] arm64/perf: Rename Cortex A57 events

2016-02-03 Thread Jan Glauber
The implemented Cortex A57 events are not A57 specific.
They are recommended by ARM and can be found on other
ARMv8 SOCs like Cavium ThunderX too. Therefore move
these events to the common PMUv3 table.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index f7ab14c..32fe656 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -87,17 +87,17 @@
 #define ARMV8_PMUV3_PERFCTR_L2D_TLB0x2F
 #define ARMV8_PMUV3_PERFCTR_L21_TLB0x30
 
+/* Recommended events. */
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_LD0x40
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_ST0x41
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_LD0x42
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_ST0x43
+#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD 0x4C
+#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST 0x4D
+
 /* ARMv8 Cortex-A53 specific event types. */
 #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL0xC2
 
-/* ARMv8 Cortex-A57 and Cortex-A72 specific event types. */
-#define ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_LD  0x40
-#define ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_ST  0x41
-#define ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_LD  0x42
-#define ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_ST  0x43
-#define ARMV8_A57_PERFCTR_DTLB_REFILL_LD   0x4c
-#define ARMV8_A57_PERFCTR_DTLB_REFILL_ST   0x4d
-
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
@@ -174,16 +174,16 @@ static const unsigned 
armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  [PERF_COUNT_HW_CACHE_RESULT_MAX] 
= {
PERF_CACHE_MAP_ALL_UNSUPPORTED,
 
-   [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_LD,
-   [C(L1D)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_LD,
-   [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_ST,
-   [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_ST,
+   [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_LD,
+   [C(L1D)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_LD,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_ST,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_ST,
 
[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
[C(L1I)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
 
-   [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_A57_PERFCTR_DTLB_REFILL_LD,
-   [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = 
ARMV8_A57_PERFCTR_DTLB_REFILL_ST,
+   [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD,
+   [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST,
 
[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
 
-- 
1.9.1



[PATCH v3 5/5] arm64/perf: Extend event mask for ARMv8.1

2016-02-03 Thread Jan Glauber
ARMv8.1 increases the PMU event number space. Detect the
presence of this PMUv3 type and extend the event mask.

The event mask is moved to struct arm_pmu so different event masks
can exist, depending on the PMU type.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm/kernel/perf_event_v6.c |  6 --
 arch/arm/kernel/perf_event_v7.c | 29 +++--
 arch/arm/kernel/perf_event_xscale.c |  4 +++-
 arch/arm64/kernel/perf_event.c  | 33 +++--
 drivers/perf/arm_pmu.c  |  5 +++--
 include/linux/perf/arm_pmu.h|  4 ++--
 6 files changed, 50 insertions(+), 31 deletions(-)

diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index 09413e7..d6769f5 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -481,7 +481,7 @@ static void armv6mpcore_pmu_disable_event(struct perf_event 
*event)
 static int armv6_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map,
-   _perf_cache_map, 0xFF);
+   _perf_cache_map);
 }
 
 static void armv6pmu_init(struct arm_pmu *cpu_pmu)
@@ -494,6 +494,7 @@ static void armv6pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->get_event_idx  = armv6pmu_get_event_idx;
cpu_pmu->start  = armv6pmu_start;
cpu_pmu->stop   = armv6pmu_stop;
+   cpu_pmu->event_mask = 0xFF;
cpu_pmu->map_event  = armv6_map_event;
cpu_pmu->num_events = 3;
cpu_pmu->max_period = (1LLU << 32) - 1;
@@ -531,7 +532,7 @@ static int armv6_1176_pmu_init(struct arm_pmu *cpu_pmu)
 static int armv6mpcore_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map,
-   _perf_cache_map, 0xFF);
+   _perf_cache_map);
 }
 
 static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
@@ -545,6 +546,7 @@ static int armv6mpcore_pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->get_event_idx  = armv6pmu_get_event_idx;
cpu_pmu->start  = armv6pmu_start;
cpu_pmu->stop   = armv6pmu_stop;
+   cpu_pmu->event_mask = 0xFF;
cpu_pmu->map_event  = armv6mpcore_map_event;
cpu_pmu->num_events = 3;
cpu_pmu->max_period = (1LLU << 32) - 1;
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4152158..8aab098 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1042,7 +1042,7 @@ static int armv7pmu_get_event_idx(struct pmu_hw_events 
*cpuc,
int idx;
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = >hw;
-   unsigned long evtype = hwc->config_base & ARMV7_EVTYPE_EVENT;
+   unsigned long evtype = hwc->config_base & cpu_pmu->event_mask;
 
/* Always place a cycle counter into the cycle counter. */
if (evtype == ARMV7_PERFCTR_CPU_CYCLES) {
@@ -1109,55 +1109,55 @@ static void armv7pmu_reset(void *info)
 static int armv7_a8_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a8_perf_map,
-   _a8_perf_cache_map, 0xFF);
+   _a8_perf_cache_map);
 }
 
 static int armv7_a9_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a9_perf_map,
-   _a9_perf_cache_map, 0xFF);
+   _a9_perf_cache_map);
 }
 
 static int armv7_a5_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a5_perf_map,
-   _a5_perf_cache_map, 0xFF);
+   _a5_perf_cache_map);
 }
 
 static int armv7_a15_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a15_perf_map,
-   _a15_perf_cache_map, 0xFF);
+   _a15_perf_cache_map);
 }
 
 static int armv7_a7_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a7_perf_map,
-   _a7_perf_cache_map, 0xFF);
+   _a7_perf_cache_map);
 }
 
 static int armv7_a12_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a12_perf_map,
-   _a12_perf_cache_map, 0xFF);
+   _a12_perf_cache_map);
 }
 
 static int krait_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map,
-   _perf_cache_map, 0xF);
+   _perf_cache_map);
 }
 
 static int krait_map_event_no_branch(struct perf_event *event)
 {
return armpmu_map_event(event, _perf_map_no_branch,
-   _perf_cache_map, 0xF);
+

[PATCH v3 3/5] arm64: dts: Add Cavium ThunderX specific PMU

2016-02-03 Thread Jan Glauber
Add a compatible string for the Cavium ThunderX PMU.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 Documentation/devicetree/bindings/arm/pmu.txt | 1 +
 arch/arm64/boot/dts/cavium/thunder-88xx.dtsi  | 5 +
 2 files changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/pmu.txt 
b/Documentation/devicetree/bindings/arm/pmu.txt
index 5651883..d3999a1 100644
--- a/Documentation/devicetree/bindings/arm/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -25,6 +25,7 @@ Required properties:
"qcom,scorpion-pmu"
"qcom,scorpion-mp-pmu"
"qcom,krait-pmu"
+   "cavium,thunder-pmu"
 - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a 
per-cpu
interrupt (PPI) then 1 interrupt should be specified.
 
diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi 
b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
index 9cb7cf9..2eb9b22 100644
--- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
+++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
@@ -360,6 +360,11 @@
 <1 10 0xff01>;
};
 
+   pmu {
+   compatible = "cavium,thunder-pmu", "arm,armv8-pmuv3";
+   interrupts = <1 7 4>;
+   };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
-- 
1.9.1



[PATCH v2 4/5] arm64/perf: Enable PMCR long cycle counter bit

2016-01-28 Thread Jan Glauber
With the long cycle counter bit (LC) disabled the cycle counter is not
working on ThunderX SOC (ThunderX only implements Aarch64).
Also, according to documentation LC == 0 is deprecated.

To keep the code simple the patch does not introduce 64 bit wide counter
functions. Instead writing the cycle counter always sets the upper
32 bits so overflow interrupts are generated as before.

Original patch from Andrew Pinksi <andrew.pin...@caviumnetworks.com>

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index c038e4e..5e4275e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -405,6 +405,7 @@ static const struct attribute_group 
*armv8_pmuv3_attr_groups[] = {
 #define ARMV8_PMCR_D   (1 << 3) /* CCNT counts every 64th cpu cycle */
 #define ARMV8_PMCR_X   (1 << 4) /* Export to ETM */
 #define ARMV8_PMCR_DP  (1 << 5) /* Disable CCNT if non-invasive debug*/
+#define ARMV8_PMCR_LC  (1 << 6) /* Overflow on 64 bit cycle counter */
 #defineARMV8_PMCR_N_SHIFT  11   /* Number of counters 
supported */
 #defineARMV8_PMCR_N_MASK   0x1f
 #defineARMV8_PMCR_MASK 0x3f /* Mask for writable bits */
@@ -494,9 +495,16 @@ static inline void armv8pmu_write_counter(struct 
perf_event *event, u32 value)
if (!armv8pmu_counter_valid(cpu_pmu, idx))
pr_err("CPU%u writing wrong counter %d\n",
smp_processor_id(), idx);
-   else if (idx == ARMV8_IDX_CYCLE_COUNTER)
-   asm volatile("msr pmccntr_el0, %0" :: "r" (value));
-   else if (armv8pmu_select_counter(idx) == idx)
+   else if (idx == ARMV8_IDX_CYCLE_COUNTER) {
+   /*
+* Set the upper 32bits as this is a 64bit counter but we only
+* count using the lower 32bits and we want an interrupt when
+* it overflows.
+*/
+   u64 value64 = 0xULL | value;
+
+   asm volatile("msr pmccntr_el0, %0" :: "r" (value64));
+   } else if (armv8pmu_select_counter(idx) == idx)
asm volatile("msr pmxevcntr_el0, %0" :: "r" (value));
 }
 
@@ -768,8 +776,11 @@ static void armv8pmu_reset(void *info)
armv8pmu_disable_intens(idx);
}
 
-   /* Initialize & Reset PMNC: C and P bits. */
-   armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C);
+   /*
+* Initialize & Reset PMNC. Request overflow on 64 bit but
+* cheat in armv8pmu_write_counter().
+*/
+   armv8pmu_pmcr_write(ARMV8_PMCR_P | ARMV8_PMCR_C | ARMV8_PMCR_LC);
 }
 
 static int armv8_pmuv3_map_event(struct perf_event *event)
-- 
1.9.1



[PATCH v2 1/5] arm64/perf: Rename Cortex A57 events

2016-01-28 Thread Jan Glauber
The implemented Cortex A57 events are not A57 specific.
They are recommended by ARM and can be found on other
ARMv8 SOCs like Cavium ThunderX too. Therefore move
these events to the common PMUv3 table.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 28 ++--
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index f7ab14c..32fe656 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -87,17 +87,17 @@
 #define ARMV8_PMUV3_PERFCTR_L2D_TLB0x2F
 #define ARMV8_PMUV3_PERFCTR_L21_TLB0x30
 
+/* Recommended events. */
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_LD0x40
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_ST0x41
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_LD0x42
+#define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_ST0x43
+#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD 0x4C
+#define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST 0x4D
+
 /* ARMv8 Cortex-A53 specific event types. */
 #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL0xC2
 
-/* ARMv8 Cortex-A57 and Cortex-A72 specific event types. */
-#define ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_LD  0x40
-#define ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_ST  0x41
-#define ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_LD  0x42
-#define ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_ST  0x43
-#define ARMV8_A57_PERFCTR_DTLB_REFILL_LD   0x4c
-#define ARMV8_A57_PERFCTR_DTLB_REFILL_ST   0x4d
-
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
@@ -174,16 +174,16 @@ static const unsigned 
armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
  [PERF_COUNT_HW_CACHE_RESULT_MAX] 
= {
PERF_CACHE_MAP_ALL_UNSUPPORTED,
 
-   [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_LD,
-   [C(L1D)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_LD,
-   [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_A57_PERFCTR_L1_DCACHE_ACCESS_ST,
-   [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_A57_PERFCTR_L1_DCACHE_REFILL_ST,
+   [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_LD,
+   [C(L1D)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_LD,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_ST,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_ST,
 
[C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
[C(L1I)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
 
-   [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_A57_PERFCTR_DTLB_REFILL_LD,
-   [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = 
ARMV8_A57_PERFCTR_DTLB_REFILL_ST,
+   [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD,
+   [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST,
 
[C(ITLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
 
-- 
1.9.1



[PATCH v2 5/5] arm64/perf: Extend event mask for ARMv8.1

2016-01-28 Thread Jan Glauber
ARMv8.1 increases the PMU event number space. Detect the
presence of this PMUv3 type and extend the event mask.

The event mask is moved to struct arm_pmu so different event masks
can exist, depending on the PMU type.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 33 +++--
 drivers/perf/arm_pmu.c |  5 +++--
 include/linux/perf/arm_pmu.h   |  4 ++--
 3 files changed, 24 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 5e4275e..78b24cb 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -419,7 +419,7 @@ static const struct attribute_group 
*armv8_pmuv3_attr_groups[] = {
 /*
  * PMXEVTYPER: Event selection reg
  */
-#defineARMV8_EVTYPE_MASK   0xc80003ff  /* Mask for writable 
bits */
+#defineARMV8_EVTYPE_FLT_MASK   0xc800  /* Writable filter bits 
*/
 #defineARMV8_EVTYPE_EVENT  0x3ff   /* Mask for EVENT bits 
*/
 
 /*
@@ -510,10 +510,8 @@ static inline void armv8pmu_write_counter(struct 
perf_event *event, u32 value)
 
 static inline void armv8pmu_write_evtype(int idx, u32 val)
 {
-   if (armv8pmu_select_counter(idx) == idx) {
-   val &= ARMV8_EVTYPE_MASK;
+   if (armv8pmu_select_counter(idx) == idx)
asm volatile("msr pmxevtyper_el0, %0" :: "r" (val));
-   }
 }
 
 static inline int armv8pmu_enable_counter(int idx)
@@ -570,6 +568,7 @@ static void armv8pmu_enable_event(struct perf_event *event)
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
struct pmu_hw_events *events = this_cpu_ptr(cpu_pmu->hw_events);
int idx = hwc->idx;
+   u32 val;
 
/*
 * Enable counter and interrupt, and set the counter to count
@@ -585,7 +584,8 @@ static void armv8pmu_enable_event(struct perf_event *event)
/*
 * Set event (if destined for PMNx counters).
 */
-   armv8pmu_write_evtype(idx, hwc->config_base);
+   val = hwc->config_base & (ARMV8_EVTYPE_FLT_MASK | cpu_pmu->event_mask);
+   armv8pmu_write_evtype(idx, val);
 
/*
 * Enable interrupt for this counter
@@ -716,7 +716,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events 
*cpuc,
int idx;
struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu);
struct hw_perf_event *hwc = >hw;
-   unsigned long evtype = hwc->config_base & ARMV8_EVTYPE_EVENT;
+   unsigned long evtype = hwc->config_base & cpu_pmu->event_mask;
 
/* Always place a cycle counter into the cycle counter. */
if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
@@ -786,29 +786,25 @@ static void armv8pmu_reset(void *info)
 static int armv8_pmuv3_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _pmuv3_perf_map,
-   _pmuv3_perf_cache_map,
-   ARMV8_EVTYPE_EVENT);
+   _pmuv3_perf_cache_map);
 }
 
 static int armv8_a53_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a53_perf_map,
-   _a53_perf_cache_map,
-   ARMV8_EVTYPE_EVENT);
+   _a53_perf_cache_map);
 }
 
 static int armv8_a57_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _a57_perf_map,
-   _a57_perf_cache_map,
-   ARMV8_EVTYPE_EVENT);
+   _a57_perf_cache_map);
 }
 
 static int armv8_thunder_map_event(struct perf_event *event)
 {
return armpmu_map_event(event, _thunder_perf_map,
-   _thunder_perf_cache_map,
-   ARMV8_EVTYPE_EVENT);
+   _thunder_perf_cache_map);
 }
 
 static void armv8pmu_read_num_pmnc_events(void *info)
@@ -831,6 +827,8 @@ static int armv8pmu_probe_num_events(struct arm_pmu 
*arm_pmu)
 
 static void armv8_pmu_init(struct arm_pmu *cpu_pmu)
 {
+   u64 id;
+
cpu_pmu->handle_irq = armv8pmu_handle_irq,
cpu_pmu->enable = armv8pmu_enable_event,
cpu_pmu->disable= armv8pmu_disable_event,
@@ -842,6 +840,13 @@ static void armv8_pmu_init(struct arm_pmu *cpu_pmu)
cpu_pmu->reset  = armv8pmu_reset,
cpu_pmu->max_period = (1LLU << 32) - 1,
cpu_pmu->set_event_filter   = armv8pmu_set_event_filter;
+
+   /* detect ARMv8.1 PMUv3 with extended event mask */
+   id = read_cpuid(ID_AA64DFR0_EL1);
+   if (((id >> 8) & 0xf) == 4)
+   cpu_pmu->event_mask = 0x;   /* ARMv8.1 extended events */
+   else
+   cpu_pmu->event_mask = ARMV8_EVTYPE_EVENT;
 }
 
 static int armv8_pmuv

[PATCH v2 2/5] arm64/perf: Add Cavium ThunderX PMU support

2016-01-28 Thread Jan Glauber
Support PMU events on Caviums ThunderX SOC. ThunderX supports
some additional counters compared to the default ARMv8 PMUv3:

- branch instructions counter
- stall frontend & backend counters
- L1 dcache load & store counters
- L1 icache counters
- iTLB & dTLB counters
- L1 dcache & icache prefetch counters

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 arch/arm64/kernel/perf_event.c | 69 +-
 1 file changed, 68 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 32fe656..c038e4e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -94,10 +94,19 @@
 #define ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_ST0x43
 #define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD 0x4C
 #define ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST 0x4D
+#define ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_LD 0x4E
+#define ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_ST 0x4F
 
 /* ARMv8 Cortex-A53 specific event types. */
 #define ARMV8_A53_PERFCTR_PREFETCH_LINEFILL0xC2
 
+/* ARMv8 Cavium Thunder specific event types. */
+#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST0xE9
+#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS0xEA
+#define ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS  0xEB
+#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS0xEC
+#define ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS  0xED
+
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
PERF_MAP_ALL_UNSUPPORTED,
@@ -131,6 +140,18 @@ static const unsigned 
armv8_a57_perf_map[PERF_COUNT_HW_MAX] = {
[PERF_COUNT_HW_BUS_CYCLES]  = 
ARMV8_PMUV3_PERFCTR_BUS_CYCLES,
 };
 
+static const unsigned armv8_thunder_perf_map[PERF_COUNT_HW_MAX] = {
+   PERF_MAP_ALL_UNSUPPORTED,
+   [PERF_COUNT_HW_CPU_CYCLES]  = 
ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
+   [PERF_COUNT_HW_INSTRUCTIONS]= 
ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
+   [PERF_COUNT_HW_CACHE_REFERENCES]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
+   [PERF_COUNT_HW_CACHE_MISSES]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
+   [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = ARMV8_PMUV3_PERFCTR_PC_WRITE,
+   [PERF_COUNT_HW_BRANCH_MISSES]   = 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+   [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 
ARMV8_PMUV3_PERFCTR_STALL_FRONTEND,
+   [PERF_COUNT_HW_STALLED_CYCLES_BACKEND]  = 
ARMV8_PMUV3_PERFCTR_STALL_BACKEND,
+};
+
 static const unsigned armv8_pmuv3_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]

[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
@@ -193,6 +214,36 @@ static const unsigned 
armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
[C(BPU)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
 };
 
+static const unsigned armv8_thunder_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
+  [PERF_COUNT_HW_CACHE_OP_MAX]
+  
[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+   PERF_CACHE_MAP_ALL_UNSUPPORTED,
+
+   [C(L1D)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_LD,
+   [C(L1D)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL_LD,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS_ST,
+   [C(L1D)][C(OP_WRITE)][C(RESULT_MISS)]   = 
ARMV8_THUNDER_PERFCTR_L1_DCACHE_MISS_ST,
+   [C(L1D)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = 
ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_ACCESS,
+   [C(L1D)][C(OP_PREFETCH)][C(RESULT_MISS)] = 
ARMV8_THUNDER_PERFCTR_L1_DCACHE_PREF_MISS,
+
+   [C(L1I)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_ACCESS,
+   [C(L1I)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_L1_ICACHE_REFILL,
+   [C(L1I)][C(OP_PREFETCH)][C(RESULT_ACCESS)] = 
ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_ACCESS,
+   [C(L1I)][C(OP_PREFETCH)][C(RESULT_MISS)] = 
ARMV8_THUNDER_PERFCTR_L1_ICACHE_PREF_MISS,
+
+   [C(DTLB)][C(OP_READ)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_LD,
+   [C(DTLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_LD,
+   [C(DTLB)][C(OP_WRITE)][C(RESULT_ACCESS)] = 
ARMV8_PMUV3_PERFCTR_DTLB_ACCESS_ST,
+   [C(DTLB)][C(OP_WRITE)][C(RESULT_MISS)]  = 
ARMV8_PMUV3_PERFCTR_DTLB_REFILL_ST,
+
+   [C(ITLB)][C(OP_READ)][C(RESULT_MISS)]   = 
ARMV8_PMUV3_PERFCTR_ITLB_REFILL,
+
+   [C(BPU)][C(OP_READ)][C(RESULT_ACCESS)]  = 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_PRED,
+   [C(BPU)][C(OP_READ)][C(RESULT_MISS)]= 
ARMV8_PMUV3_PERFCTR_PC_BRANCH_MIS_PRED,
+   [C(BPU)][C(OP_W

[PATCH v2 0/5] Cavium ThunderX PMU support

2016-01-28 Thread Jan Glauber
Hi Mark & Will,

I'm resending the arm64 PMU patches. The only difference to the first
version is that I dropped the x on thunder in order to be consistent
with the existing device tree name.

Thanks,
Jan

Jan Glauber (5):
  arm64/perf: Rename Cortex A57 events
  arm64/perf: Add Cavium ThunderX PMU support
  arm64: dts: Add Cavium ThunderX specific PMU
  arm64/perf: Enable PMCR long cycle counter bit
  arm64/perf: Extend event mask for ARMv8.1

 Documentation/devicetree/bindings/arm/pmu.txt |   1 +
 arch/arm64/boot/dts/cavium/thunder-88xx.dtsi  |   5 +
 arch/arm64/kernel/perf_event.c| 145 --
 drivers/perf/arm_pmu.c|   5 +-
 include/linux/perf/arm_pmu.h  |   4 +-
 5 files changed, 125 insertions(+), 35 deletions(-)

-- 
1.9.1



[PATCH v2 3/5] arm64: dts: Add Cavium ThunderX specific PMU

2016-01-28 Thread Jan Glauber
Add a compatible string for the Cavium ThunderX PMU.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 Documentation/devicetree/bindings/arm/pmu.txt | 1 +
 arch/arm64/boot/dts/cavium/thunder-88xx.dtsi  | 5 +
 2 files changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/pmu.txt 
b/Documentation/devicetree/bindings/arm/pmu.txt
index 5651883..d3999a1 100644
--- a/Documentation/devicetree/bindings/arm/pmu.txt
+++ b/Documentation/devicetree/bindings/arm/pmu.txt
@@ -25,6 +25,7 @@ Required properties:
"qcom,scorpion-pmu"
"qcom,scorpion-mp-pmu"
"qcom,krait-pmu"
+   "cavium,thunder-pmu"
 - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a 
per-cpu
interrupt (PPI) then 1 interrupt should be specified.
 
diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi 
b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
index 9cb7cf9..2eb9b22 100644
--- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
+++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
@@ -360,6 +360,11 @@
 <1 10 0xff01>;
};
 
+   pmu {
+   compatible = "cavium,thunder-pmu", "arm,armv8-pmuv3";
+   interrupts = <1 7 4>;
+   };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
-- 
1.9.1



[RFC PATCH 1/2] i2c: Split i2c-octeon driver and add ThunderX support

2016-02-24 Thread Jan Glauber
The ThunderX SOC uses the same i2c block as the Octeon SOC.
The main difference is that on ThunderX the device is a PCI device
so device probing is done via PCI.

Split the current Octeon driver into an Octeon and a common part
and add the ThunderX support.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/Kconfig |   10 +
 drivers/i2c/busses/Makefile|3 +
 drivers/i2c/busses/i2c-cavium.c|  828 +
 drivers/i2c/busses/i2c-cavium.h|  187 +
 drivers/i2c/busses/i2c-octeon-core.c   |  302 
 drivers/i2c/busses/i2c-octeon.c| 1283 
 drivers/i2c/busses/i2c-thunderx-core.c |  263 +++
 7 files changed, 1593 insertions(+), 1283 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-cavium.c
 create mode 100644 drivers/i2c/busses/i2c-cavium.h
 create mode 100644 drivers/i2c/busses/i2c-octeon-core.c
 delete mode 100644 drivers/i2c/busses/i2c-octeon.c
 create mode 100644 drivers/i2c/busses/i2c-thunderx-core.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 7b0aa82..97614b3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -952,6 +952,16 @@ config I2C_OCTEON
  This driver can also be built as a module.  If so, the module
  will be called i2c-octeon.
 
+config I2C_THUNDERX
+   tristate "Cavium ThunderX I2C bus support"
+   depends on 64BIT && PCI
+   help
+ Say yes if you want to support the I2C serial bus on Cavium
+ ThunderX SOC.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-thunderx.
+
 config I2C_XILINX
tristate "Xilinx I2C Controller"
depends on HAS_IOMEM
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 37f2819..a32ff14 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -91,7 +91,10 @@ obj-$(CONFIG_I2C_UNIPHIER)   += i2c-uniphier.o
 obj-$(CONFIG_I2C_UNIPHIER_F)   += i2c-uniphier-f.o
 obj-$(CONFIG_I2C_VERSATILE)+= i2c-versatile.o
 obj-$(CONFIG_I2C_WMT)  += i2c-wmt.o
+i2c-octeon-objs := i2c-cavium.o i2c-octeon-core.o
 obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon.o
+i2c-thunderx-objs := i2c-cavium.o i2c-thunderx-core.o
+obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o
 obj-$(CONFIG_I2C_XILINX)   += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
diff --git a/drivers/i2c/busses/i2c-cavium.c b/drivers/i2c/busses/i2c-cavium.c
new file mode 100644
index 000..93d8c0f
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cavium.c
@@ -0,0 +1,828 @@
+/*
+ * (C) Copyright 2009-2010
+ * Nokia Siemens Networks, michael.lawnick@nsn.com
+ *
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
+ *
+ * This file contains the shared part of the driver for the i2c adapter in
+ * Cavium Networks' OCTEON processors and ThunderX SOCs.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "i2c-cavium.h"
+
+static int reset_how;
+
+/*
+ * On some hardware IFLG is not visible in TWSI_CTL until after low-level IRQ,
+ * so re-sample CTL a short time later to avoid stalls.
+ */
+static int irq_early_us = 80;
+module_param(irq_early_us, int, 0644);
+MODULE_PARM_DESC(irq_early_us, "Re-poll for IFLG after IRQ (us)");
+
+static void octeon_i2c_disable_hlc(struct octeon_i2c *i2c)
+{
+   if (!i2c->hlc_enabled)
+   return;
+
+   i2c->hlc_enabled = false;
+   octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+}
+
+/* interrupt service routine */
+irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
+{
+   struct octeon_i2c *i2c = dev_id;
+
+   i2c->int_dis(i2c);
+   wake_up(>queue);
+
+   return IRQ_HANDLED;
+}
+
+/*
+ * Wait-helper which addresses the delayed-IFLAG problem by re-polling for
+ * missing TWSI_CTL[IFLG] a few us later, when irq has signalled an event,
+ * but none found. Skip this re-poll on the first (non-wakeup) call.
+ */
+static int poll_iflg(struct octeon_i2c *i2c, int *first_p)
+{
+   int iflg = octeon_i2c_test_iflg(i2c);
+
+   if (iflg)
+   return 1;
+   if (*first_p)
+   *first_p = 0;
+   else {
+   usleep_range(irq_early_us, 2 * irq_early_us);
+   iflg = octeon_i2c_test_iflg(i2c);
+   }
+   return iflg;
+}
+
+/**
+ * octeon_i2c_wait - wait for the IFLG to be set
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_wait(struct octeon_i2c *i2c)

[RFC PATCH 0/2] ThunderX i2c driver

2016-02-24 Thread Jan Glauber
Hi,

these two patches add support for the Cavium ThunderX SOC.
The patches are on-top of the previous i2c-octeon series.

Please review, feedback welcome!

Jan



Jan Glauber (2):
  i2c: Split i2c-octeon driver and add ThunderX support
  i2c: thunderx: Add smbus support

 drivers/i2c/busses/Kconfig |   10 +
 drivers/i2c/busses/Makefile|3 +
 drivers/i2c/busses/i2c-cavium.c|  828 +
 drivers/i2c/busses/i2c-cavium.h|  191 +
 drivers/i2c/busses/i2c-octeon-core.c   |  302 
 drivers/i2c/busses/i2c-octeon.c| 1283 
 drivers/i2c/busses/i2c-thunderx-core.c |  294 
 7 files changed, 1628 insertions(+), 1283 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-cavium.c
 create mode 100644 drivers/i2c/busses/i2c-cavium.h
 create mode 100644 drivers/i2c/busses/i2c-octeon-core.c
 delete mode 100644 drivers/i2c/busses/i2c-octeon.c
 create mode 100644 drivers/i2c/busses/i2c-thunderx-core.c

-- 
1.9.1



[RFC PATCH 2/2] i2c: thunderx: Add smbus support

2016-02-24 Thread Jan Glauber
Add smbus alert interrupt support.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-cavium.h|  4 
 drivers/i2c/busses/i2c-thunderx-core.c | 31 +++
 2 files changed, 35 insertions(+)

diff --git a/drivers/i2c/busses/i2c-cavium.h b/drivers/i2c/busses/i2c-cavium.h
index db80c0f..8357997 100644
--- a/drivers/i2c/busses/i2c-cavium.h
+++ b/drivers/i2c/busses/i2c-cavium.h
@@ -119,6 +119,10 @@ struct octeon_i2c {
 #ifdef CONFIG_ARCH_THUNDER
struct msix_entry   i2c_msix;
 #endif
+#ifdef CONFIG_I2C_SMBUS
+   struct i2c_smbus_alert_setup alert_data;
+   struct i2c_client   *ara;
+#endif
 };
 
 static inline void writeqflush(u64 val, void __iomem *addr)
diff --git a/drivers/i2c/busses/i2c-thunderx-core.c 
b/drivers/i2c/busses/i2c-thunderx-core.c
index 0a95891..396c8bc 100644
--- a/drivers/i2c/busses/i2c-thunderx-core.c
+++ b/drivers/i2c/busses/i2c-thunderx-core.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,34 @@ static void thunder_i2c_clock_disable(struct device *dev, 
struct clk *clk)
devm_clk_put(dev, clk);
 }
 
+static void thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
+  struct device_node *node)
+{
+#ifdef CONFIG_I2C_SMBUS
+   u32 type;
+
+   i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
+   if (!i2c->alert_data.irq)
+   return;
+
+   type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
+   i2c->alert_data.alert_edge_triggered =
+   (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
+
+   i2c->ara = i2c_setup_smbus_alert(>adap, >alert_data);
+   if (!i2c->ara)
+   dev_err(dev, "Failed to setup smbalert\n");
+#endif
+}
+
+static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
+{
+#ifdef CONFIG_I2C_SMBUS
+   if (i2c->ara)
+   i2c_unregister_device(i2c->ara);
+#endif
+}
+
 static void thunder_i2c_set_name(struct pci_dev *pdev, struct octeon_i2c *i2c,
 char *name)
 {
@@ -202,6 +231,7 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
goto out_irq;
}
 
+   thunder_i2c_smbus_setup(i2c, node);
dev_info(i2c->dev, "probed\n");
return 0;
 
@@ -232,6 +262,7 @@ static void thunder_i2c_remove_pci(struct pci_dev *pdev)
 
dev = i2c->dev;
thunder_i2c_clock_disable(dev, i2c->clk);
+   thunder_i2c_smbus_remove(i2c);
i2c_del_adapter(>adap);
devm_free_irq(dev, i2c->i2c_msix.vector, i2c);
pci_disable_msix(pdev);
-- 
1.9.1



Re: [PATCH v4 4/5] arm64/perf: Enable PMCR long cycle counter bit

2016-02-22 Thread Jan Glauber
On Thu, Feb 18, 2016 at 05:34:28PM +, Will Deacon wrote:
> On Thu, Feb 18, 2016 at 05:50:13PM +0100, Jan Glauber wrote:
> > With the long cycle counter bit (LC) disabled the cycle counter is not
> > working on ThunderX SOC (ThunderX only implements Aarch64).
> > Also, according to documentation LC == 0 is deprecated.
> > 
> > To keep the code simple the patch does not introduce 64 bit wide counter
> > functions. Instead writing the cycle counter always sets the upper
> > 32 bits so overflow interrupts are generated as before.
> > 
> > Original patch from Andrew Pinksi <andrew.pin...@caviumnetworks.com>
> 
> What does this mean? Do we need Andrew's S-o-B, or is this a fresh patch?

Hi Will,

Please let me know if I should repost or not, FWIW I got Andrew's S-o-B on the
patch.

Thanks, Jan

> Will


Re: [PATCH v4 3/5] arm64: dts: Add Cavium ThunderX specific PMU

2016-02-22 Thread Jan Glauber
On Thu, Feb 18, 2016 at 05:32:48PM +, Will Deacon wrote:
> On Thu, Feb 18, 2016 at 05:50:12PM +0100, Jan Glauber wrote:
> > Add a compatible string for the Cavium ThunderX PMU.
> 
> Stupid question, but is "thunder" the name of the CPU or the SoC or ...?
> 
> Whatever we use to describe the PMU, should probably also identify the
> CPU uniquely.

The CPU is currently:

compatible = "cavium,thunder", "arm,armv8";

We clearly need better names in case of a subsequent CPU, but for now
I think we should stick to the existing name.

Jan

> Will
> 
> > Signed-off-by: Jan Glauber <jglau...@cavium.com>
> > ---
> >  Documentation/devicetree/bindings/arm/pmu.txt | 1 +
> >  arch/arm64/boot/dts/cavium/thunder-88xx.dtsi  | 5 +
> >  2 files changed, 6 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/arm/pmu.txt 
> > b/Documentation/devicetree/bindings/arm/pmu.txt
> > index 5651883..d3999a1 100644
> > --- a/Documentation/devicetree/bindings/arm/pmu.txt
> > +++ b/Documentation/devicetree/bindings/arm/pmu.txt
> > @@ -25,6 +25,7 @@ Required properties:
> > "qcom,scorpion-pmu"
> > "qcom,scorpion-mp-pmu"
> > "qcom,krait-pmu"
> > +   "cavium,thunder-pmu"
> >  - interrupts : 1 combined interrupt or 1 per core. If the interrupt is a 
> > per-cpu
> > interrupt (PPI) then 1 interrupt should be specified.
> >  
> > diff --git a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi 
> > b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
> > index 9cb7cf9..2eb9b22 100644
> > --- a/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
> > +++ b/arch/arm64/boot/dts/cavium/thunder-88xx.dtsi
> > @@ -360,6 +360,11 @@
> >  <1 10 0xff01>;
> > };
> >  
> > +   pmu {
> > +   compatible = "cavium,thunder-pmu", "arm,armv8-pmuv3";
> > +   interrupts = <1 7 4>;
> > +   };
> > +
> > soc {
> > compatible = "simple-bus";
> > #address-cells = <2>;
> > -- 
> > 1.9.1
> > 


[Resend PATCH 03/10] i2c-octeon: Enable high-level controller and improve on bus contention

2016-02-29 Thread Jan Glauber
From: David Daney <dda...@caviumnetworks.com>

Use High Level Controller when possible.

i2c-octeon was reacting badly to bus contention: when in
direct-access mode (for transfers > 8 bytes, which cannot use the
high-level controller) some !ACK or arbitration-loss states were
not causing the current transfer to be aborted, and the bus released.

There's one place in i2c protocol that !ACK is an acceptable
response: in the final byte of a read cycle.  In this case the
destination is not saying that the transfer failed, just that it
doesn't want more data.

This enables correct behavior of ACK on final byte of non-final read
msgs too.

Signed-off-by: David Daney <dda...@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 583 ++--
 1 file changed, 504 insertions(+), 79 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index fa4d439..d48456a 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -113,8 +113,15 @@ struct octeon_i2c {
int sys_freq;
void __iomem*twsi_base;
struct device   *dev;
+   boolhlc_enabled;
 };
 
+static int reset_how;
+
+static int timeout = 2;
+module_param(timeout, int, 0444);
+MODULE_PARM_DESC(timeout, "Low-level device timeout (ms)");
+
 /**
  * octeon_i2c_write_sw - write an I2C core register
  * @i2c: The struct octeon_i2c
@@ -123,7 +130,7 @@ struct octeon_i2c {
  *
  * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
  */
-static void octeon_i2c_write_sw(struct octeon_i2c *i2c, u64 eop_reg, u8 data)
+static void octeon_i2c_write_sw(struct octeon_i2c *i2c, u64 eop_reg, u32 data)
 {
u64 tmp;
 
@@ -165,7 +172,7 @@ static u64 octeon_i2c_read_sw64(struct octeon_i2c *i2c, u64 
eop_reg)
  */
 static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)
 {
-   return octeon_i2c_read_sw64(i2c, eop_reg);
+   return (u8) octeon_i2c_read_sw64(i2c, eop_reg);
 }
 
 /**
@@ -198,6 +205,15 @@ static void octeon_i2c_int_disable(struct octeon_i2c *i2c)
octeon_i2c_write_int(i2c, TS_INT | ST_INT);
 }
 
+static void octeon_i2c_disable_hlc(struct octeon_i2c *i2c)
+{
+   if (!i2c->hlc_enabled)
+   return;
+
+   i2c->hlc_enabled = false;
+   octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+}
+
 /**
  * bitbang_unblock - unblock the bus
  * @i2c: The struct octeon_i2c
@@ -207,13 +223,18 @@ static void octeon_i2c_int_disable(struct octeon_i2c *i2c)
  */
 static void bitbang_unblock(struct octeon_i2c *i2c)
 {
-   int i;
+   int state, i;
 
+   octeon_i2c_disable_hlc(i2c);
dev_dbg(i2c->dev, "%s\n", __func__);
 
+   /* cycle 8+1 clocks with SDA high */
for (i = 0; i < 9; i++) {
octeon_i2c_write_int(i2c, 0);
udelay(5);
+   state = __raw_readq(i2c->twsi_base + TWSI_INT);
+   if (state & (SDA | SCL))
+   break;
octeon_i2c_write_int(i2c, SCL_OVR);
udelay(5);
}
@@ -236,10 +257,14 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
return IRQ_HANDLED;
 }
 
+static u64 octeon_i2c_read_ctl(struct octeon_i2c *i2c)
+{
+   return octeon_i2c_read_sw64(i2c, SW_TWSI_EOP_TWSI_CTL);
+}
+
 static int octeon_i2c_test_iflg(struct octeon_i2c *i2c)
 {
-   return (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_CTL)
-   & TWSI_CTL_IFLG) != 0;
+   return (octeon_i2c_read_ctl(i2c) & TWSI_CTL_IFLG) != 0;
 }
 
 /**
@@ -263,76 +288,208 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
return 0;
 }
 
-/* send STOP to the bus */
-static void octeon_i2c_stop(struct octeon_i2c *i2c)
+/*
+ * Cleanup low-level state & enable high-level.
+ *
+ * Returns -EAGAIN if low-level state could not be cleaned
+ */
+static int octeon_i2c_enable_hlc(struct octeon_i2c *i2c)
 {
-   u8 data;
+   int try = 0, ret = 0;
+   u64 val;
+
+   if (i2c->hlc_enabled)
+   return 0;
+   else
+   i2c->hlc_enabled = true;
+
+   while (1) {
+   val = octeon_i2c_read_ctl(i2c) & (TWSI_CTL_STA | TWSI_CTL_STP);
+   if (!val)
+   break;
+
+   /* clear _IFLG event */
+   if (val & TWSI_CTL_IFLG)
+   octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL,
+   TWSI_CTL_ENAB);
+
+   if (try++ > 100) {
+   pr_err("%s: giving up\n", __func__);
+   ret = -EAGAIN;
+   break;
+   }
+
+   /* spin until any start/stop has finished */
+   udelay(10);
+   }
 
octe

[Resend PATCH 10/10] i2c: thunderx: add smbus support

2016-02-29 Thread Jan Glauber
Add smbus alert interrupt support.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-cavium.h|  4 
 drivers/i2c/busses/i2c-thunderx-core.c | 31 +++
 2 files changed, 35 insertions(+)

diff --git a/drivers/i2c/busses/i2c-cavium.h b/drivers/i2c/busses/i2c-cavium.h
index db80c0f..8357997 100644
--- a/drivers/i2c/busses/i2c-cavium.h
+++ b/drivers/i2c/busses/i2c-cavium.h
@@ -119,6 +119,10 @@ struct octeon_i2c {
 #ifdef CONFIG_ARCH_THUNDER
struct msix_entry   i2c_msix;
 #endif
+#ifdef CONFIG_I2C_SMBUS
+   struct i2c_smbus_alert_setup alert_data;
+   struct i2c_client   *ara;
+#endif
 };
 
 static inline void writeqflush(u64 val, void __iomem *addr)
diff --git a/drivers/i2c/busses/i2c-thunderx-core.c 
b/drivers/i2c/busses/i2c-thunderx-core.c
index 0a95891..396c8bc 100644
--- a/drivers/i2c/busses/i2c-thunderx-core.c
+++ b/drivers/i2c/busses/i2c-thunderx-core.c
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -104,6 +105,34 @@ static void thunder_i2c_clock_disable(struct device *dev, 
struct clk *clk)
devm_clk_put(dev, clk);
 }
 
+static void thunder_i2c_smbus_setup(struct octeon_i2c *i2c,
+  struct device_node *node)
+{
+#ifdef CONFIG_I2C_SMBUS
+   u32 type;
+
+   i2c->alert_data.irq = irq_of_parse_and_map(node, 0);
+   if (!i2c->alert_data.irq)
+   return;
+
+   type = irqd_get_trigger_type(irq_get_irq_data(i2c->alert_data.irq));
+   i2c->alert_data.alert_edge_triggered =
+   (type & IRQ_TYPE_LEVEL_MASK) ? 1 : 0;
+
+   i2c->ara = i2c_setup_smbus_alert(>adap, >alert_data);
+   if (!i2c->ara)
+   dev_err(dev, "Failed to setup smbalert\n");
+#endif
+}
+
+static void thunder_i2c_smbus_remove(struct octeon_i2c *i2c)
+{
+#ifdef CONFIG_I2C_SMBUS
+   if (i2c->ara)
+   i2c_unregister_device(i2c->ara);
+#endif
+}
+
 static void thunder_i2c_set_name(struct pci_dev *pdev, struct octeon_i2c *i2c,
 char *name)
 {
@@ -202,6 +231,7 @@ static int thunder_i2c_probe_pci(struct pci_dev *pdev,
goto out_irq;
}
 
+   thunder_i2c_smbus_setup(i2c, node);
dev_info(i2c->dev, "probed\n");
return 0;
 
@@ -232,6 +262,7 @@ static void thunder_i2c_remove_pci(struct pci_dev *pdev)
 
dev = i2c->dev;
thunder_i2c_clock_disable(dev, i2c->clk);
+   thunder_i2c_smbus_remove(i2c);
i2c_del_adapter(>adap);
devm_free_irq(dev, i2c->i2c_msix.vector, i2c);
pci_disable_msix(pdev);
-- 
1.9.1



[Resend PATCH 05/10] i2c-octeon: Add support for cn78XX chips

2016-02-29 Thread Jan Glauber
From: David Daney <dda...@caviumnetworks.com>

cn78XX has a different interrupt architecture, so we have to manage
the interrupts differently.

Signed-off-by: David Daney <dda...@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 156 ++--
 1 file changed, 136 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index d48456a..0b28d8c 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -109,11 +110,18 @@ struct octeon_i2c {
wait_queue_head_t   queue;
struct i2c_adapter  adap;
int irq;
+   int hlc_irq;/* For cn7890 only */
u32 twsi_freq;
int sys_freq;
void __iomem*twsi_base;
struct device   *dev;
boolhlc_enabled;
+   void(*int_en)   (struct octeon_i2c *);
+   void(*int_dis)  (struct octeon_i2c *);
+   void(*hlc_int_en)   (struct octeon_i2c *);
+   void(*hlc_int_dis)  (struct octeon_i2c *);
+   atomic_tint_en_cnt;
+   atomic_thlc_int_en_cnt;
 };
 
 static int reset_how;
@@ -215,6 +223,58 @@ static void octeon_i2c_disable_hlc(struct octeon_i2c *i2c)
 }
 
 /**
+ * octeon_i2c_int_enable78 - enable the CORE interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in the
+ * SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_int_enable78(struct octeon_i2c *i2c)
+{
+   atomic_inc_return(>int_en_cnt);
+   enable_irq(i2c->irq);
+}
+
+static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq)
+{
+   int count;
+
+   /*
+* The interrupt can be disabled in two places, but we only
+* want to make the disable_irq_nosync() call once, so keep
+* track with the atomic variable.
+*/
+   count = atomic_dec_if_positive(cnt);
+   if (count >= 0)
+   disable_irq_nosync(irq);
+}
+
+/* disable the CORE interrupt */
+static void octeon_i2c_int_disable78(struct octeon_i2c *i2c)
+{
+   __octeon_i2c_irq_disable(>int_en_cnt, i2c->irq);
+}
+
+/**
+ * octeon_i2c_hlc_int_enable78 - enable the ST interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in
+ * the SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c)
+{
+   atomic_inc_return(>hlc_int_en_cnt);
+   enable_irq(i2c->hlc_irq);
+}
+
+/* disable the ST interrupt */
+static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c)
+{
+   __octeon_i2c_irq_disable(>hlc_int_en_cnt, i2c->hlc_irq);
+}
+
+/**
  * bitbang_unblock - unblock the bus
  * @i2c: The struct octeon_i2c
  *
@@ -251,7 +311,18 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
 {
struct octeon_i2c *i2c = dev_id;
 
-   octeon_i2c_int_disable(i2c);
+   i2c->int_dis(i2c);
+   wake_up(>queue);
+
+   return IRQ_HANDLED;
+}
+
+/* interrupt service routine */
+static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id)
+{
+   struct octeon_i2c *i2c = dev_id;
+
+   i2c->hlc_int_dis(i2c);
wake_up(>queue);
 
return IRQ_HANDLED;
@@ -277,10 +348,10 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
long result;
 
-   octeon_i2c_int_enable(i2c);
+   i2c->int_en(i2c);
result = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c),
i2c->adap.timeout);
-   octeon_i2c_int_disable(i2c);
+   i2c->int_dis(i2c);
if (!result) {
dev_dbg(i2c->dev, "%s: timeout\n", __func__);
return -ETIMEDOUT;
@@ -300,8 +371,8 @@ static int octeon_i2c_enable_hlc(struct octeon_i2c *i2c)
 
if (i2c->hlc_enabled)
return 0;
-   else
-   i2c->hlc_enabled = true;
+
+   i2c->hlc_enabled = true;
 
while (1) {
val = octeon_i2c_read_ctl(i2c) & (TWSI_CTL_STA | TWSI_CTL_STP);
@@ -635,11 +706,10 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
int result;
 
-   octeon_i2c_hlc_int_enable(i2c);
+   i2c->hlc_int_en(i2c);
result = wait_event_interruptible_timeout(i2c->queue,
- 
octeon_i2c_hlc_test_ready(i2c),
- i2c->adap.timeout);
-   octeon_i2c_int_disable(i2c);
+   octeon_i2c_hlc_test_ready(i2c), i2c->

[Resend PATCH 07/10] i2c-octeon: Faster operation when IFLG signals late

2016-02-29 Thread Jan Glauber
From: Peter Swain <psw...@cavium.com>

Some versions can deliver low-level twsi irq before twsi_ctl.iflg
is set, leading to timeout-driven i/o.
When an irq signals event, but woken task does not see the expected
twsi_ctl.iflg, re-check about 80uS later.

EEPROM reads on 100kHz i2c now measure ~5.2kB/s, about 1/2 what's
achievable, and much better than the worst-case 100 bytes/sec before.

Signed-off-by: Peter Swain <psw...@cavium.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-octeon.c | 31 ++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index bb15a9c..e3552e5 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -130,6 +130,14 @@ static int timeout = 2;
 module_param(timeout, int, 0444);
 MODULE_PARM_DESC(timeout, "Low-level device timeout (ms)");
 
+/*
+ * On some hardware IFLG is not visible in TWSI_CTL until after low-level IRQ,
+ * so re-sample CTL a short time later to avoid stalls.
+ */
+static int irq_early_us = 80;
+module_param(irq_early_us, int, 0644);
+MODULE_PARM_DESC(irq_early_us, "Re-poll for IFLG after IRQ (us)");
+
 static void writeqflush(u64 val, void __iomem *addr)
 {
__raw_writeq(val, addr);
@@ -343,6 +351,26 @@ static int octeon_i2c_test_iflg(struct octeon_i2c *i2c)
return (octeon_i2c_read_ctl(i2c) & TWSI_CTL_IFLG) != 0;
 }
 
+/*
+ * Wait-helper which addresses the delayed-IFLAG problem by re-polling for
+ * missing TWSI_CTL[IFLG] a few us later, when irq has signalled an event,
+ * but none found. Skip this re-poll on the first (non-wakeup) call.
+ */
+static int poll_iflg(struct octeon_i2c *i2c, int *first_p)
+{
+   int iflg = octeon_i2c_test_iflg(i2c);
+
+   if (iflg)
+   return 1;
+   if (*first_p)
+   *first_p = 0;
+   else {
+   usleep_range(irq_early_us, 2 * irq_early_us);
+   iflg = octeon_i2c_test_iflg(i2c);
+   }
+   return iflg;
+}
+
 /**
  * octeon_i2c_wait - wait for the IFLG to be set
  * @i2c: The struct octeon_i2c
@@ -351,10 +379,11 @@ static int octeon_i2c_test_iflg(struct octeon_i2c *i2c)
  */
 static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
+   int first = 1;
long result;
 
i2c->int_en(i2c);
-   result = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c),
+   result = wait_event_timeout(i2c->queue, poll_iflg(i2c, ),
i2c->adap.timeout);
i2c->int_dis(i2c);
if (!result) {
-- 
1.9.1



[Resend PATCH 00/10] i2c-octeon and i2c-thunderx drivers

2016-02-29 Thread Jan Glauber
I'm resending both patch series as one since the thunderx driver
depends on the octeon driver patches. Also (subtly) dropping the RFC
in the hope of getting the patches reviewed.

This series for the Octeon i2c driver is an attempt to upstream some
bug fixes and features that accumulated for some time. I tried to
split the cleanup from the other patches and updated the patch
descriptions according to my humble i2c knowledge.

Patches are on top of 4.5-rc6 and were tested on OCTEON, OCTEON-78
and ThunderX.

Jan

--

David Daney (4):
  i2c-octeon: Support I2C_M_RECV_LEN
  i2c-octeon: Enable high-level controller and improve on bus contention
  i2c-octeon: Add support for cn78XX chips
  i2c-octeon: Add workaround for chips with broken irqs

Jan Glauber (4):
  i2c-octeon: Cleanup i2c-octeon driver
  dt-bindings: i2c: add Octeon cn78xx TWSI
  i2c: split i2c-octeon driver and add ThunderX support
  i2c: thunderx: add smbus support

Peter Swain (2):
  i2c-octeon: Flush TWSI writes with readback
  i2c-octeon: Faster operation when IFLG signals late

 .../devicetree/bindings/i2c/i2c-octeon.txt |   6 +
 drivers/i2c/busses/Kconfig |  10 +
 drivers/i2c/busses/Makefile|   3 +
 drivers/i2c/busses/i2c-cavium.c| 828 +
 drivers/i2c/busses/i2c-cavium.h| 191 +
 drivers/i2c/busses/i2c-octeon-core.c   | 302 
 drivers/i2c/busses/i2c-octeon.c| 633 
 drivers/i2c/busses/i2c-thunderx-core.c | 294 
 8 files changed, 1634 insertions(+), 633 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-cavium.c
 create mode 100644 drivers/i2c/busses/i2c-cavium.h
 create mode 100644 drivers/i2c/busses/i2c-octeon-core.c
 delete mode 100644 drivers/i2c/busses/i2c-octeon.c
 create mode 100644 drivers/i2c/busses/i2c-thunderx-core.c

-- 
1.9.1



[Resend PATCH 06/10] i2c-octeon: Flush TWSI writes with readback

2016-02-29 Thread Jan Glauber
From: Peter Swain <psw...@cavium.com>

Signed-off-by: Peter Swain <psw...@cavium.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-octeon.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 0b28d8c..bb15a9c 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -130,6 +130,12 @@ static int timeout = 2;
 module_param(timeout, int, 0444);
 MODULE_PARM_DESC(timeout, "Low-level device timeout (ms)");
 
+static void writeqflush(u64 val, void __iomem *addr)
+{
+   __raw_writeq(val, addr);
+   __raw_readq(addr);  /* wait for write to land */
+}
+
 /**
  * octeon_i2c_write_sw - write an I2C core register
  * @i2c: The struct octeon_i2c
@@ -190,8 +196,7 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 
eop_reg)
  */
 static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
 {
-   __raw_writeq(data, i2c->twsi_base + TWSI_INT);
-   __raw_readq(i2c->twsi_base + TWSI_INT);
+   writeqflush(data, i2c->twsi_base + TWSI_INT);
 }
 
 /**
@@ -797,10 +802,10 @@ static int octeon_i2c_simple_write(struct octeon_i2c 
*i2c, struct i2c_msg *msgs)
 
for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
ext |= (u64) msgs[0].buf[j] << (8 * i);
-   __raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+   writeqflush(ext, i2c->twsi_base + SW_TWSI_EXT);
}
 
-   __raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+   writeqflush(cmd, i2c->twsi_base + SW_TWSI);
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
@@ -846,7 +851,7 @@ static int octeon_i2c_ia_read(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
cmd |= (u64) msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
 
octeon_i2c_hlc_int_clear(i2c);
-   __raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+   writeqflush(cmd, i2c->twsi_base + SW_TWSI);
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
@@ -906,10 +911,10 @@ static int octeon_i2c_ia_write(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
set_ext = true;
}
if (set_ext)
-   __raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+   writeqflush(ext, i2c->twsi_base + SW_TWSI_EXT);
 
octeon_i2c_hlc_int_clear(i2c);
-   __raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+   writeqflush(cmd, i2c->twsi_base + SW_TWSI);
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
-- 
1.9.1



[Resend PATCH 04/10] dt-bindings: i2c: add Octeon cn78xx TWSI

2016-02-29 Thread Jan Glauber
Add compatible string for Cavium Octeon cn78XX SOCs TWSI.

Cc: Rob Herring <robh...@kernel.org>
Cc: Pawel Moll <pawel.m...@arm.com>
Cc: Mark Rutland <mark.rutl...@arm.com>
Cc: Ian Campbell <ijc+devicet...@hellion.org.uk>
Cc: Kumar Gala <ga...@codeaurora.org>

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 Documentation/devicetree/bindings/i2c/i2c-octeon.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt 
b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
index dced82e..872d485 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
@@ -4,6 +4,12 @@
 
   Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
 
+  or
+
+  compatible: "cavium,octeon-7890-twsi"
+
+  Compatibility with cn78XX SOCs.
+
 - reg: The base address of the TWSI/I2C bus controller register bank.
 
 - #address-cells: Must be <1>.
-- 
1.9.1



[Resend PATCH 08/10] i2c-octeon: Add workaround for chips with broken irqs

2016-02-29 Thread Jan Glauber
From: David Daney <dda...@caviumnetworks.com>

CN3860 does not interrupt the CPU when the i2c status changes.  If
we get a timeout, and see the status has in fact changed, we know we
have this problem, and drop back to polling.

Signed-off-by: David Daney <dda...@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 46 +
 1 file changed, 46 insertions(+)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index e3552e5..3c2f848 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -115,6 +115,7 @@ struct octeon_i2c {
int sys_freq;
void __iomem*twsi_base;
struct device   *dev;
+   int broken_irq_mode;
boolhlc_enabled;
void(*int_en)   (struct octeon_i2c *);
void(*int_dis)  (struct octeon_i2c *);
@@ -382,10 +383,33 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
int first = 1;
long result;
 
+   if (i2c->broken_irq_mode) {
+   /*
+* Some chip revisions seem to not assert the irq in
+* the interrupt controller.  So we must poll for the
+* IFLG change.
+*/
+   u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+   while (!octeon_i2c_test_iflg(i2c) &&
+  time_before64(get_jiffies_64(), end))
+   udelay(50);
+
+   return octeon_i2c_test_iflg(i2c) ? 0 : -ETIMEDOUT;
+   }
+
i2c->int_en(i2c);
result = wait_event_timeout(i2c->queue, poll_iflg(i2c, ),
i2c->adap.timeout);
i2c->int_dis(i2c);
+
+   if (result <= 0 && OCTEON_IS_MODEL(OCTEON_CN38XX) &&
+   octeon_i2c_test_iflg(i2c)) {
+   dev_err(i2c->dev,
+   "broken irq connection detected, switching to polling 
mode.\n");
+   i2c->broken_irq_mode = 1;
+   return 0;
+   }
if (!result) {
dev_dbg(i2c->dev, "%s: timeout\n", __func__);
return -ETIMEDOUT;
@@ -740,6 +764,21 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
int result;
 
+   if (i2c->broken_irq_mode) {
+   /*
+* Some cn38xx boards did not assert the irq in
+* the interrupt controller.  So we must poll for the
+* IFLG change.
+*/
+   u64 end = get_jiffies_64() + i2c->adap.timeout;
+
+   while (!octeon_i2c_hlc_test_ready(i2c) &&
+  time_before64(get_jiffies_64(), end))
+   udelay(50);
+
+   return octeon_i2c_hlc_test_ready(i2c) ? 0 : -ETIMEDOUT;
+   }
+
i2c->hlc_int_en(i2c);
result = wait_event_interruptible_timeout(i2c->queue,
octeon_i2c_hlc_test_ready(i2c), i2c->adap.timeout);
@@ -747,6 +786,13 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
if (!result)
octeon_i2c_hlc_int_clear(i2c);
 
+   if (result <= 0 && OCTEON_IS_MODEL(OCTEON_CN38XX) &&
+   octeon_i2c_hlc_test_ready(i2c)) {
+   dev_err(i2c->dev, "broken irq connection detected, switching to 
polling mode.\n");
+   i2c->broken_irq_mode = 1;
+   return 0;
+   }
+
if (result < 0) {
dev_dbg(i2c->dev, "%s: wait interrupted\n", __func__);
return result;
-- 
1.9.1



[Resend PATCH 01/10] i2c-octeon: Cleanup i2c-octeon driver

2016-02-29 Thread Jan Glauber
Cleanup only without functional change.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-octeon.c | 442 +---
 1 file changed, 230 insertions(+), 212 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 32914ab..1f14094 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -2,7 +2,7 @@
  * (C) Copyright 2009-2010
  * Nokia Siemens Networks, michael.lawnick@nsn.com
  *
- * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
  *
  * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
  *
@@ -24,99 +24,154 @@
 
 #include 
 
-#define DRV_NAME "i2c-octeon"
+#define DRV_NAME   "i2c-octeon"
 
-/* The previous out-of-tree version was implicitly version 1.0. */
-#define DRV_VERSION"2.0"
+/* Register offsets */
+#define SW_TWSI0x00
+#define TWSI_INT   0x10
+#define SW_TWSI_EXT0x18
 
-/* register offsets */
-#define SW_TWSI 0x00
-#define TWSI_INT 0x10
+#define INT_ENA_ST 0x1
+#define INT_ENA_TS 0x2
+#define INT_ENA_CORE   0x4
 
 /* Controller command patterns */
-#define SW_TWSI_V   0x8000ull
-#define SW_TWSI_EOP_TWSI_DATA   0x0C01ull
-#define SW_TWSI_EOP_TWSI_CTL0x0C02ull
-#define SW_TWSI_EOP_TWSI_CLKCTL 0x0C03ull
-#define SW_TWSI_EOP_TWSI_STAT   0x0C03ull
-#define SW_TWSI_EOP_TWSI_RST0x0C07ull
-#define SW_TWSI_OP_TWSI_CLK 0x0800ull
-#define SW_TWSI_R   0x0100ull
+#define SW_TWSI_V  (1ULL << 63)
+#define SW_TWSI_EIA(1ULL << 61)
+#define SW_TWSI_R  (1ULL << 56)
+#define SW_TWSI_SOVR   (1ULL << 55)
+#define SW_TWSI_OP_7   (0ULL << 57)
+#define SW_TWSI_OP_7_IA(1ULL << 57)
+#define SW_TWSI_OP_10  (2ULL << 57)
+#define SW_TWSI_OP_10_IA   (3ULL << 57)
+#define SW_TWSI_OP_TWSI_CLK(1ULL << 59)
+#define SW_TWSI_SIZE_SHIFT 52
+#define SW_TWSI_A_SHIFT40
+#define SW_TWSI_IA_SHIFT   32
+#define SW_TWSI_EOP_TWSI_DATA  0x0C01ULL
+#define SW_TWSI_EOP_TWSI_CTL   0x0C02ULL
+#define SW_TWSI_EOP_TWSI_CLKCTL0x0C03ULL
+#define SW_TWSI_EOP_TWSI_STAT  0x0C03ULL
+#define SW_TWSI_EOP_TWSI_RST   0x0C07ULL
 
 /* Controller command and status bits */
-#define TWSI_CTL_CE   0x80
-#define TWSI_CTL_ENAB 0x40
-#define TWSI_CTL_STA  0x20
-#define TWSI_CTL_STP  0x10
-#define TWSI_CTL_IFLG 0x08
-#define TWSI_CTL_AAK  0x04
+#define TWSI_CTL_CE0x80/* High level controller enable */
+#define TWSI_CTL_ENAB  0x40/* Bus enable */
+#define TWSI_CTL_STA   0x20/* Master-mode start, HW clears when 
done */
+#define TWSI_CTL_STP   0x10/* Master-mode stop, HW clears when 
done */
+#define TWSI_CTL_IFLG  0x08/* HW event, SW writes 0 to ACK */
+#define TWSI_CTL_AAK   0x04/* Assert ACK */
 
 /* Some status values */
-#define STAT_START  0x08
-#define STAT_RSTART 0x10
-#define STAT_TXADDR_ACK 0x18
-#define STAT_TXDATA_ACK 0x28
-#define STAT_RXADDR_ACK 0x40
-#define STAT_RXDATA_ACK 0x50
-#define STAT_IDLE   0xF8
+#define STAT_ERROR 0x00
+#define STAT_START 0x08
+#define STAT_RSTART0x10
+#define STAT_TXADDR_ACK0x18
+#define STAT_TXADDR_NAK0x20
+#define STAT_TXDATA_ACK0x28
+#define STAT_TXDATA_NAK0x30
+#define STAT_LOST_ARB_38   0x38
+#define STAT_RXADDR_ACK0x40
+#define STAT_RXADDR_NAK0x48
+#define STAT_RXDATA_ACK0x50
+#define STAT_RXDATA_NAK0x58
+#define STAT_SLAVE_60  0x60
+#define STAT_LOST_ARB_68   0x68
+#define STAT_SLAVE_70  0x70
+#define STAT_LOST_ARB_78   0x78
+#define STAT_SLAVE_80  0x80
+#define STAT_SLAVE_88  0x88
+#define STAT_GENDATA_ACK   0x90
+#define STAT_GENDATA_NAK   0x98
+#define STAT_SLAVE_A0  0xA0
+#define STAT_SLAVE_A8  0xA8
+#define STAT_LOST_ARB_B0   0xB0
+#define STAT_SLAVE_LOST0xB8
+#define STAT_SLAVE_NAK 0xC0
+#define STAT_SLAVE_ACK 0xC8
+#define STAT_AD2W_ACK  0xD0
+#define STAT_AD2W_NAK  0xD8
+#define STAT_IDLE  0xF8
+
+/* TWSI_INT values */
+#define ST_INT 0x01
+#define TS_INT 0x02
+#define CORE_INT   0x04
+#define ST_EN  0x10
+#define TS_EN  0x20
+#define CORE_EN0x40
+#define

[Resend PATCH 02/10] i2c-octeon: Support I2C_M_RECV_LEN

2016-02-29 Thread Jan Glauber
From: David Daney <dda...@caviumnetworks.com>

If I2C_M_RECV_LEN is set consider the length byte.

Signed-off-by: David Daney <dda...@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 1f14094..fa4d439 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -392,13 +392,14 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int 
target,
  * @target: Target address
  * @data: Pointer to the location to store the data
  * @rlength: Length of the data
+ * @recv_len: flag for length byte
  *
  * The address is sent over the bus, then the data is read.
  *
  * Returns 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_read(struct octeon_i2c *i2c, int target, u8 *data,
-  u16 *rlength)
+  u16 *rlength, bool recv_len)
 {
int length = *rlength;
int i, result;
@@ -438,6 +439,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int 
target, u8 *data,
return result;
 
data[i] = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_DATA);
+   if (recv_len && i == 0) {
+   if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) {
+   dev_err(i2c->dev,
+   "%s: read len > I2C_SMBUS_BLOCK_MAX 
%d\n",
+   __func__, data[i]);
+   return -EIO;
+   }
+   length += data[i];
+   }
}
*rlength = length;
return 0;
@@ -466,7 +476,8 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct 
i2c_msg *msgs,
 pmsg->len, pmsg->addr, i + 1, num);
if (pmsg->flags & I2C_M_RD)
ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
- >len);
+ >len,
+ pmsg->flags & I2C_M_RECV_LEN);
else
ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf,
   pmsg->len);
-- 
1.9.1



[Resend PATCH 09/10] i2c: split i2c-octeon driver and add ThunderX support

2016-02-29 Thread Jan Glauber
The ThunderX SOC uses the same i2c block as the Octeon SOC.
The main difference is that on ThunderX the device is a PCI device
so device probing is done via PCI.

Split the current Octeon driver into an Octeon and a common part
and add the ThunderX support.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/Kconfig |   10 +
 drivers/i2c/busses/Makefile|3 +
 drivers/i2c/busses/i2c-cavium.c|  828 +
 drivers/i2c/busses/i2c-cavium.h|  187 +
 drivers/i2c/busses/i2c-octeon-core.c   |  302 
 drivers/i2c/busses/i2c-octeon.c| 1283 
 drivers/i2c/busses/i2c-thunderx-core.c |  263 +++
 7 files changed, 1593 insertions(+), 1283 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-cavium.c
 create mode 100644 drivers/i2c/busses/i2c-cavium.h
 create mode 100644 drivers/i2c/busses/i2c-octeon-core.c
 delete mode 100644 drivers/i2c/busses/i2c-octeon.c
 create mode 100644 drivers/i2c/busses/i2c-thunderx-core.c

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 7b0aa82..97614b3 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -952,6 +952,16 @@ config I2C_OCTEON
  This driver can also be built as a module.  If so, the module
  will be called i2c-octeon.
 
+config I2C_THUNDERX
+   tristate "Cavium ThunderX I2C bus support"
+   depends on 64BIT && PCI
+   help
+ Say yes if you want to support the I2C serial bus on Cavium
+ ThunderX SOC.
+
+ This driver can also be built as a module.  If so, the module
+ will be called i2c-thunderx.
+
 config I2C_XILINX
tristate "Xilinx I2C Controller"
depends on HAS_IOMEM
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 37f2819..a32ff14 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -91,7 +91,10 @@ obj-$(CONFIG_I2C_UNIPHIER)   += i2c-uniphier.o
 obj-$(CONFIG_I2C_UNIPHIER_F)   += i2c-uniphier-f.o
 obj-$(CONFIG_I2C_VERSATILE)+= i2c-versatile.o
 obj-$(CONFIG_I2C_WMT)  += i2c-wmt.o
+i2c-octeon-objs := i2c-cavium.o i2c-octeon-core.o
 obj-$(CONFIG_I2C_OCTEON)   += i2c-octeon.o
+i2c-thunderx-objs := i2c-cavium.o i2c-thunderx-core.o
+obj-$(CONFIG_I2C_THUNDERX) += i2c-thunderx.o
 obj-$(CONFIG_I2C_XILINX)   += i2c-xiic.o
 obj-$(CONFIG_I2C_XLR)  += i2c-xlr.o
 obj-$(CONFIG_I2C_XLP9XX)   += i2c-xlp9xx.o
diff --git a/drivers/i2c/busses/i2c-cavium.c b/drivers/i2c/busses/i2c-cavium.c
new file mode 100644
index 000..93d8c0f
--- /dev/null
+++ b/drivers/i2c/busses/i2c-cavium.c
@@ -0,0 +1,828 @@
+/*
+ * (C) Copyright 2009-2010
+ * Nokia Siemens Networks, michael.lawnick@nsn.com
+ *
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
+ *
+ * This file contains the shared part of the driver for the i2c adapter in
+ * Cavium Networks' OCTEON processors and ThunderX SOCs.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "i2c-cavium.h"
+
+static int reset_how;
+
+/*
+ * On some hardware IFLG is not visible in TWSI_CTL until after low-level IRQ,
+ * so re-sample CTL a short time later to avoid stalls.
+ */
+static int irq_early_us = 80;
+module_param(irq_early_us, int, 0644);
+MODULE_PARM_DESC(irq_early_us, "Re-poll for IFLG after IRQ (us)");
+
+static void octeon_i2c_disable_hlc(struct octeon_i2c *i2c)
+{
+   if (!i2c->hlc_enabled)
+   return;
+
+   i2c->hlc_enabled = false;
+   octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB);
+}
+
+/* interrupt service routine */
+irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
+{
+   struct octeon_i2c *i2c = dev_id;
+
+   i2c->int_dis(i2c);
+   wake_up(>queue);
+
+   return IRQ_HANDLED;
+}
+
+/*
+ * Wait-helper which addresses the delayed-IFLAG problem by re-polling for
+ * missing TWSI_CTL[IFLG] a few us later, when irq has signalled an event,
+ * but none found. Skip this re-poll on the first (non-wakeup) call.
+ */
+static int poll_iflg(struct octeon_i2c *i2c, int *first_p)
+{
+   int iflg = octeon_i2c_test_iflg(i2c);
+
+   if (iflg)
+   return 1;
+   if (*first_p)
+   *first_p = 0;
+   else {
+   usleep_range(irq_early_us, 2 * irq_early_us);
+   iflg = octeon_i2c_test_iflg(i2c);
+   }
+   return iflg;
+}
+
+/**
+ * octeon_i2c_wait - wait for the IFLG to be set
+ * @i2c: The struct octeon_i2c
+ *
+ * Returns 0 on success, otherwise a negative errno.
+ */
+static int octeon_i2c_wait(struct octeon_i2c *i2c)
+{
+   int first = 1;
+   long result;
+
+   if (i2c->broken_irq_mode)

Re: [PATCH v3 5/5] arm64/perf: Extend event mask for ARMv8.1

2016-02-17 Thread Jan Glauber
On Tue, Feb 16, 2016 at 03:12:53PM +, Will Deacon wrote:
> On Tue, Feb 16, 2016 at 09:00:15AM +0100, Jan Glauber wrote:
> > On Mon, Feb 15, 2016 at 08:04:04PM +, Will Deacon wrote:
> > 
> > [...]
> > 
> > > On Wed, Feb 03, 2016 at 06:12:00PM +0100, Jan Glauber wrote:
> > > > +   cpu_pmu->event_mask = 0x;   /* ARMv8.1 extended 
> > > > events */
> > > > +   else
> > > > +   cpu_pmu->event_mask = ARMV8_EVTYPE_EVENT;
> > > 
> > > ... although can't we just update ARMV8_EVTYPE_EVENT to be 0x now?
> > > AFAICT, that just eats into bits that used to be RES0, so we shouldn't
> > > see any problems. That should make your patch *much* simpler!
> > 
> > That would of course be easier, but I just can't assess the implications.
> > 
> > Probably I'm missing something but to me it looks like the event mask is the
> > only verification we do for the user-space selectable events. Is it safe for
> > implementations that only support 0x3ff events to allow access to the
> > whole 0x range? What memory would be accessed for non-existing
> > events?
> 
> Which memory? The worst-case is that we end up writing to some bits in
> a register (e.g. PMXEVTYPER) that are RES0 in ARMv8 afaict.

OK, I see. Than I'm happy to drop 99% of that patch and just increase
the mask.

Jan

> Will


[RFC PATCH 0/8] i2c-octeon update

2016-02-18 Thread Jan Glauber
This series for the Octeon i2c driver is an attempt to upstream some
bug fixes and features that accumulated for some time. I tried to
split the cleanup from the other patches and updated the patch
descriptions according to my humble i2c knowledge.

Patches are on top of 4.5-rc4 and were tested on OCTEON and OCTEON-78.

Jan

--

David Daney (4):
  i2c-octeon: Support I2C_M_RECV_LEN
  i2c-octeon: Enable high-level controller and improve on bus contention
  i2c-octeon: Add support for cn78XX chips
  i2c-octeon: Add workaround for chips with broken irqs

Jan Glauber (2):
  i2c-octeon: Cleanup i2c-octeon driver
  dt-bindings: i2c: add Octeon cn78xx TWSI

Peter Swain (2):
  i2c-octeon: Flush TWSI writes with readback
  i2c-octeon: Faster operation when IFLG signals late

 .../devicetree/bindings/i2c/i2c-octeon.txt |6 +
 drivers/i2c/busses/i2c-octeon.c| 1154 +++-
 2 files changed, 908 insertions(+), 252 deletions(-)

-- 
1.9.1



[RFC PATCH 1/8] i2c-octeon: Cleanup i2c-octeon driver

2016-02-18 Thread Jan Glauber
Cleanup only without functional change.

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-octeon.c | 442 +---
 1 file changed, 230 insertions(+), 212 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 32914ab..1f14094 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -2,7 +2,7 @@
  * (C) Copyright 2009-2010
  * Nokia Siemens Networks, michael.lawnick@nsn.com
  *
- * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.
+ * Portions Copyright (C) 2010 - 2016 Cavium, Inc.
  *
  * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.
  *
@@ -24,99 +24,154 @@
 
 #include 
 
-#define DRV_NAME "i2c-octeon"
+#define DRV_NAME   "i2c-octeon"
 
-/* The previous out-of-tree version was implicitly version 1.0. */
-#define DRV_VERSION"2.0"
+/* Register offsets */
+#define SW_TWSI0x00
+#define TWSI_INT   0x10
+#define SW_TWSI_EXT0x18
 
-/* register offsets */
-#define SW_TWSI 0x00
-#define TWSI_INT 0x10
+#define INT_ENA_ST 0x1
+#define INT_ENA_TS 0x2
+#define INT_ENA_CORE   0x4
 
 /* Controller command patterns */
-#define SW_TWSI_V   0x8000ull
-#define SW_TWSI_EOP_TWSI_DATA   0x0C01ull
-#define SW_TWSI_EOP_TWSI_CTL0x0C02ull
-#define SW_TWSI_EOP_TWSI_CLKCTL 0x0C03ull
-#define SW_TWSI_EOP_TWSI_STAT   0x0C03ull
-#define SW_TWSI_EOP_TWSI_RST0x0C07ull
-#define SW_TWSI_OP_TWSI_CLK 0x0800ull
-#define SW_TWSI_R   0x0100ull
+#define SW_TWSI_V  (1ULL << 63)
+#define SW_TWSI_EIA(1ULL << 61)
+#define SW_TWSI_R  (1ULL << 56)
+#define SW_TWSI_SOVR   (1ULL << 55)
+#define SW_TWSI_OP_7   (0ULL << 57)
+#define SW_TWSI_OP_7_IA(1ULL << 57)
+#define SW_TWSI_OP_10  (2ULL << 57)
+#define SW_TWSI_OP_10_IA   (3ULL << 57)
+#define SW_TWSI_OP_TWSI_CLK(1ULL << 59)
+#define SW_TWSI_SIZE_SHIFT 52
+#define SW_TWSI_A_SHIFT40
+#define SW_TWSI_IA_SHIFT   32
+#define SW_TWSI_EOP_TWSI_DATA  0x0C01ULL
+#define SW_TWSI_EOP_TWSI_CTL   0x0C02ULL
+#define SW_TWSI_EOP_TWSI_CLKCTL0x0C03ULL
+#define SW_TWSI_EOP_TWSI_STAT  0x0C03ULL
+#define SW_TWSI_EOP_TWSI_RST   0x0C07ULL
 
 /* Controller command and status bits */
-#define TWSI_CTL_CE   0x80
-#define TWSI_CTL_ENAB 0x40
-#define TWSI_CTL_STA  0x20
-#define TWSI_CTL_STP  0x10
-#define TWSI_CTL_IFLG 0x08
-#define TWSI_CTL_AAK  0x04
+#define TWSI_CTL_CE0x80/* High level controller enable */
+#define TWSI_CTL_ENAB  0x40/* Bus enable */
+#define TWSI_CTL_STA   0x20/* Master-mode start, HW clears when 
done */
+#define TWSI_CTL_STP   0x10/* Master-mode stop, HW clears when 
done */
+#define TWSI_CTL_IFLG  0x08/* HW event, SW writes 0 to ACK */
+#define TWSI_CTL_AAK   0x04/* Assert ACK */
 
 /* Some status values */
-#define STAT_START  0x08
-#define STAT_RSTART 0x10
-#define STAT_TXADDR_ACK 0x18
-#define STAT_TXDATA_ACK 0x28
-#define STAT_RXADDR_ACK 0x40
-#define STAT_RXDATA_ACK 0x50
-#define STAT_IDLE   0xF8
+#define STAT_ERROR 0x00
+#define STAT_START 0x08
+#define STAT_RSTART0x10
+#define STAT_TXADDR_ACK0x18
+#define STAT_TXADDR_NAK0x20
+#define STAT_TXDATA_ACK0x28
+#define STAT_TXDATA_NAK0x30
+#define STAT_LOST_ARB_38   0x38
+#define STAT_RXADDR_ACK0x40
+#define STAT_RXADDR_NAK0x48
+#define STAT_RXDATA_ACK0x50
+#define STAT_RXDATA_NAK0x58
+#define STAT_SLAVE_60  0x60
+#define STAT_LOST_ARB_68   0x68
+#define STAT_SLAVE_70  0x70
+#define STAT_LOST_ARB_78   0x78
+#define STAT_SLAVE_80  0x80
+#define STAT_SLAVE_88  0x88
+#define STAT_GENDATA_ACK   0x90
+#define STAT_GENDATA_NAK   0x98
+#define STAT_SLAVE_A0  0xA0
+#define STAT_SLAVE_A8  0xA8
+#define STAT_LOST_ARB_B0   0xB0
+#define STAT_SLAVE_LOST0xB8
+#define STAT_SLAVE_NAK 0xC0
+#define STAT_SLAVE_ACK 0xC8
+#define STAT_AD2W_ACK  0xD0
+#define STAT_AD2W_NAK  0xD8
+#define STAT_IDLE  0xF8
+
+/* TWSI_INT values */
+#define ST_INT 0x01
+#define TS_INT 0x02
+#define CORE_INT   0x04
+#define ST_EN  0x10
+#define TS_EN  0x20
+#define CORE_EN0x40
+#define

[RFC PATCH 2/8] i2c-octeon: Support I2C_M_RECV_LEN

2016-02-18 Thread Jan Glauber
From: David Daney <dda...@caviumnetworks.com>

If I2C_M_RECV_LEN is set consider the length byte.

Signed-off-by: David Daney <dda...@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 1f14094..fa4d439 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -392,13 +392,14 @@ static int octeon_i2c_write(struct octeon_i2c *i2c, int 
target,
  * @target: Target address
  * @data: Pointer to the location to store the data
  * @rlength: Length of the data
+ * @recv_len: flag for length byte
  *
  * The address is sent over the bus, then the data is read.
  *
  * Returns 0 on success, otherwise a negative errno.
  */
 static int octeon_i2c_read(struct octeon_i2c *i2c, int target, u8 *data,
-  u16 *rlength)
+  u16 *rlength, bool recv_len)
 {
int length = *rlength;
int i, result;
@@ -438,6 +439,15 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int 
target, u8 *data,
return result;
 
data[i] = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_DATA);
+   if (recv_len && i == 0) {
+   if (data[i] > I2C_SMBUS_BLOCK_MAX + 1) {
+   dev_err(i2c->dev,
+   "%s: read len > I2C_SMBUS_BLOCK_MAX 
%d\n",
+   __func__, data[i]);
+   return -EIO;
+   }
+   length += data[i];
+   }
}
*rlength = length;
return 0;
@@ -466,7 +476,8 @@ static int octeon_i2c_xfer(struct i2c_adapter *adap, struct 
i2c_msg *msgs,
 pmsg->len, pmsg->addr, i + 1, num);
if (pmsg->flags & I2C_M_RD)
ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf,
- >len);
+ >len,
+ pmsg->flags & I2C_M_RECV_LEN);
else
ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf,
   pmsg->len);
-- 
1.9.1



[RFC PATCH 7/8] i2c-octeon: Faster operation when IFLG signals late

2016-02-18 Thread Jan Glauber
From: Peter Swain <psw...@cavium.com>

Some versions can deliver low-level twsi irq before twsi_ctl.iflg
is set, leading to timeout-driven i/o.
When an irq signals event, but woken task does not see the expected
twsi_ctl.iflg, re-check about 80uS later.

EEPROM reads on 100kHz i2c now measure ~5.2kB/s, about 1/2 what's
achievable, and much better than the worst-case 100 bytes/sec before.

Signed-off-by: Peter Swain <psw...@cavium.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-octeon.c | 31 ++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index bb15a9c..e3552e5 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -130,6 +130,14 @@ static int timeout = 2;
 module_param(timeout, int, 0444);
 MODULE_PARM_DESC(timeout, "Low-level device timeout (ms)");
 
+/*
+ * On some hardware IFLG is not visible in TWSI_CTL until after low-level IRQ,
+ * so re-sample CTL a short time later to avoid stalls.
+ */
+static int irq_early_us = 80;
+module_param(irq_early_us, int, 0644);
+MODULE_PARM_DESC(irq_early_us, "Re-poll for IFLG after IRQ (us)");
+
 static void writeqflush(u64 val, void __iomem *addr)
 {
__raw_writeq(val, addr);
@@ -343,6 +351,26 @@ static int octeon_i2c_test_iflg(struct octeon_i2c *i2c)
return (octeon_i2c_read_ctl(i2c) & TWSI_CTL_IFLG) != 0;
 }
 
+/*
+ * Wait-helper which addresses the delayed-IFLAG problem by re-polling for
+ * missing TWSI_CTL[IFLG] a few us later, when irq has signalled an event,
+ * but none found. Skip this re-poll on the first (non-wakeup) call.
+ */
+static int poll_iflg(struct octeon_i2c *i2c, int *first_p)
+{
+   int iflg = octeon_i2c_test_iflg(i2c);
+
+   if (iflg)
+   return 1;
+   if (*first_p)
+   *first_p = 0;
+   else {
+   usleep_range(irq_early_us, 2 * irq_early_us);
+   iflg = octeon_i2c_test_iflg(i2c);
+   }
+   return iflg;
+}
+
 /**
  * octeon_i2c_wait - wait for the IFLG to be set
  * @i2c: The struct octeon_i2c
@@ -351,10 +379,11 @@ static int octeon_i2c_test_iflg(struct octeon_i2c *i2c)
  */
 static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
+   int first = 1;
long result;
 
i2c->int_en(i2c);
-   result = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c),
+   result = wait_event_timeout(i2c->queue, poll_iflg(i2c, ),
i2c->adap.timeout);
i2c->int_dis(i2c);
if (!result) {
-- 
1.9.1



[RFC PATCH 6/8] i2c-octeon: Flush TWSI writes with readback

2016-02-18 Thread Jan Glauber
From: Peter Swain <psw...@cavium.com>

Signed-off-by: Peter Swain <psw...@cavium.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 drivers/i2c/busses/i2c-octeon.c | 19 ---
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index 0b28d8c..bb15a9c 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -130,6 +130,12 @@ static int timeout = 2;
 module_param(timeout, int, 0444);
 MODULE_PARM_DESC(timeout, "Low-level device timeout (ms)");
 
+static void writeqflush(u64 val, void __iomem *addr)
+{
+   __raw_writeq(val, addr);
+   __raw_readq(addr);  /* wait for write to land */
+}
+
 /**
  * octeon_i2c_write_sw - write an I2C core register
  * @i2c: The struct octeon_i2c
@@ -190,8 +196,7 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 
eop_reg)
  */
 static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)
 {
-   __raw_writeq(data, i2c->twsi_base + TWSI_INT);
-   __raw_readq(i2c->twsi_base + TWSI_INT);
+   writeqflush(data, i2c->twsi_base + TWSI_INT);
 }
 
 /**
@@ -797,10 +802,10 @@ static int octeon_i2c_simple_write(struct octeon_i2c 
*i2c, struct i2c_msg *msgs)
 
for (i = 0; i < msgs[0].len - 4 && i < 4; i++, j--)
ext |= (u64) msgs[0].buf[j] << (8 * i);
-   __raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+   writeqflush(ext, i2c->twsi_base + SW_TWSI_EXT);
}
 
-   __raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+   writeqflush(cmd, i2c->twsi_base + SW_TWSI);
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
@@ -846,7 +851,7 @@ static int octeon_i2c_ia_read(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
cmd |= (u64) msgs[0].buf[0] << SW_TWSI_IA_SHIFT;
 
octeon_i2c_hlc_int_clear(i2c);
-   __raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+   writeqflush(cmd, i2c->twsi_base + SW_TWSI);
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
@@ -906,10 +911,10 @@ static int octeon_i2c_ia_write(struct octeon_i2c *i2c, 
struct i2c_msg *msgs)
set_ext = true;
}
if (set_ext)
-   __raw_writeq(ext, i2c->twsi_base + SW_TWSI_EXT);
+   writeqflush(ext, i2c->twsi_base + SW_TWSI_EXT);
 
octeon_i2c_hlc_int_clear(i2c);
-   __raw_writeq(cmd, i2c->twsi_base + SW_TWSI);
+   writeqflush(cmd, i2c->twsi_base + SW_TWSI);
 
ret = octeon_i2c_hlc_wait(i2c);
if (ret)
-- 
1.9.1



[RFC PATCH 4/8] dt-bindings: i2c: add Octeon cn78xx TWSI

2016-02-18 Thread Jan Glauber
Add compatible string for Cavium Octeon cn78XX SOCs TWSI.

Cc: Rob Herring <robh...@kernel.org>
Cc: Pawel Moll <pawel.m...@arm.com>
Cc: Mark Rutland <mark.rutl...@arm.com>
Cc: Ian Campbell <ijc+devicet...@hellion.org.uk>
Cc: Kumar Gala <ga...@codeaurora.org>

Signed-off-by: Jan Glauber <jglau...@cavium.com>
Acked-by: David Daney <dda...@caviumnetworks.com>
---
 Documentation/devicetree/bindings/i2c/i2c-octeon.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt 
b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
index dced82e..872d485 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-octeon.txt
@@ -4,6 +4,12 @@
 
   Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
 
+  or
+
+  compatible: "cavium,octeon-7890-twsi"
+
+  Compatibility with cn78XX SOCs.
+
 - reg: The base address of the TWSI/I2C bus controller register bank.
 
 - #address-cells: Must be <1>.
-- 
1.9.1



[RFC PATCH 5/8] i2c-octeon: Add support for cn78XX chips

2016-02-18 Thread Jan Glauber
From: David Daney <dda...@caviumnetworks.com>

cn78XX has a different interrupt architecture, so we have to manage
the interrupts differently.

Signed-off-by: David Daney <dda...@caviumnetworks.com>
Signed-off-by: Jan Glauber <jglau...@cavium.com>
---
 drivers/i2c/busses/i2c-octeon.c | 156 ++--
 1 file changed, 136 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c
index d48456a..0b28d8c 100644
--- a/drivers/i2c/busses/i2c-octeon.c
+++ b/drivers/i2c/busses/i2c-octeon.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -109,11 +110,18 @@ struct octeon_i2c {
wait_queue_head_t   queue;
struct i2c_adapter  adap;
int irq;
+   int hlc_irq;/* For cn7890 only */
u32 twsi_freq;
int sys_freq;
void __iomem*twsi_base;
struct device   *dev;
boolhlc_enabled;
+   void(*int_en)   (struct octeon_i2c *);
+   void(*int_dis)  (struct octeon_i2c *);
+   void(*hlc_int_en)   (struct octeon_i2c *);
+   void(*hlc_int_dis)  (struct octeon_i2c *);
+   atomic_tint_en_cnt;
+   atomic_thlc_int_en_cnt;
 };
 
 static int reset_how;
@@ -215,6 +223,58 @@ static void octeon_i2c_disable_hlc(struct octeon_i2c *i2c)
 }
 
 /**
+ * octeon_i2c_int_enable78 - enable the CORE interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in the
+ * SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_int_enable78(struct octeon_i2c *i2c)
+{
+   atomic_inc_return(>int_en_cnt);
+   enable_irq(i2c->irq);
+}
+
+static void __octeon_i2c_irq_disable(atomic_t *cnt, int irq)
+{
+   int count;
+
+   /*
+* The interrupt can be disabled in two places, but we only
+* want to make the disable_irq_nosync() call once, so keep
+* track with the atomic variable.
+*/
+   count = atomic_dec_if_positive(cnt);
+   if (count >= 0)
+   disable_irq_nosync(irq);
+}
+
+/* disable the CORE interrupt */
+static void octeon_i2c_int_disable78(struct octeon_i2c *i2c)
+{
+   __octeon_i2c_irq_disable(>int_en_cnt, i2c->irq);
+}
+
+/**
+ * octeon_i2c_hlc_int_enable78 - enable the ST interrupt
+ * @i2c: The struct octeon_i2c
+ *
+ * The interrupt will be asserted when there is non-STAT_IDLE state in
+ * the SW_TWSI_EOP_TWSI_STAT register.
+ */
+static void octeon_i2c_hlc_int_enable78(struct octeon_i2c *i2c)
+{
+   atomic_inc_return(>hlc_int_en_cnt);
+   enable_irq(i2c->hlc_irq);
+}
+
+/* disable the ST interrupt */
+static void octeon_i2c_hlc_int_disable78(struct octeon_i2c *i2c)
+{
+   __octeon_i2c_irq_disable(>hlc_int_en_cnt, i2c->hlc_irq);
+}
+
+/**
  * bitbang_unblock - unblock the bus
  * @i2c: The struct octeon_i2c
  *
@@ -251,7 +311,18 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id)
 {
struct octeon_i2c *i2c = dev_id;
 
-   octeon_i2c_int_disable(i2c);
+   i2c->int_dis(i2c);
+   wake_up(>queue);
+
+   return IRQ_HANDLED;
+}
+
+/* interrupt service routine */
+static irqreturn_t octeon_i2c_hlc_isr78(int irq, void *dev_id)
+{
+   struct octeon_i2c *i2c = dev_id;
+
+   i2c->hlc_int_dis(i2c);
wake_up(>queue);
 
return IRQ_HANDLED;
@@ -277,10 +348,10 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)
 {
long result;
 
-   octeon_i2c_int_enable(i2c);
+   i2c->int_en(i2c);
result = wait_event_timeout(i2c->queue, octeon_i2c_test_iflg(i2c),
i2c->adap.timeout);
-   octeon_i2c_int_disable(i2c);
+   i2c->int_dis(i2c);
if (!result) {
dev_dbg(i2c->dev, "%s: timeout\n", __func__);
return -ETIMEDOUT;
@@ -300,8 +371,8 @@ static int octeon_i2c_enable_hlc(struct octeon_i2c *i2c)
 
if (i2c->hlc_enabled)
return 0;
-   else
-   i2c->hlc_enabled = true;
+
+   i2c->hlc_enabled = true;
 
while (1) {
val = octeon_i2c_read_ctl(i2c) & (TWSI_CTL_STA | TWSI_CTL_STP);
@@ -635,11 +706,10 @@ static int octeon_i2c_hlc_wait(struct octeon_i2c *i2c)
 {
int result;
 
-   octeon_i2c_hlc_int_enable(i2c);
+   i2c->hlc_int_en(i2c);
result = wait_event_interruptible_timeout(i2c->queue,
- 
octeon_i2c_hlc_test_ready(i2c),
- i2c->adap.timeout);
-   octeon_i2c_int_disable(i2c);
+   octeon_i2c_hlc_test_ready(i2c), i2c->

  1   2   3   4   5   6   7   8   9   10   >