[S390] cio: change misleading console logic
[safe/jmp/linux-2.6] / drivers / s390 / cio / qdio.h
index 6b8aa6a..ff7748a 100644 (file)
@@ -1,70 +1,28 @@
+/*
+ * linux/drivers/s390/cio/qdio.h
+ *
+ * Copyright 2000,2009 IBM Corp.
+ * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
+ *           Jan Glauber <jang@linux.vnet.ibm.com>
+ */
 #ifndef _CIO_QDIO_H
 #define _CIO_QDIO_H
 
 #include <asm/page.h>
+#include <asm/schid.h>
+#include <asm/debug.h>
+#include "chsc.h"
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
-
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_VERBOSE_LEVEL 9
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_VERBOSE_LEVEL 5
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_USE_PROCESSING_STATE
-
-#ifdef CONFIG_QDIO_PERF_STATS
-#define QDIO_PERFORMANCE_STATS
-#endif /* CONFIG_QDIO_PERF_STATS */
-
-#define QDIO_MINIMAL_BH_RELIEF_TIME 16
-#define QDIO_TIMER_POLL_VALUE 1
-#define IQDIO_TIMER_POLL_VALUE 1
+#define QDIO_BUSY_BIT_PATIENCE         100     /* 100 microseconds */
+#define QDIO_INPUT_THRESHOLD           500     /* 500 microseconds */
 
 /*
- * unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as
- * we never know, whether we'll get initiative again, e.g. to give the
- * transmit skb's back to the stack, however the stack may be waiting for
- * them... therefore we define 4 as threshold to start polling (which
- * will stop as soon as the asynchronous queue catches up)
- * btw, this only applies to the asynchronous HiperSockets queue
+ * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait
+ * till next initiative to give transmitted skbs back to the stack is too long.
+ * Therefore polling is started in case of multicast queue is filled more
+ * than 50 percent.
  */
-#define IQDIO_FILL_LEVEL_TO_POLL 4
-
-#define TIQDIO_THININT_ISC 3
-#define TIQDIO_DELAY_TARGET 0
-#define QDIO_BUSY_BIT_PATIENCE 100 /* in microsecs */
-#define QDIO_BUSY_BIT_GIVE_UP 10000000 /* 10 seconds */
-#define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */
-#define IQDIO_GLOBAL_LAPS_INT 1 /* don't global summary */
-#define IQDIO_LOCAL_LAPS 4
-#define IQDIO_LOCAL_LAPS_INT 1
-#define IQDIO_GLOBAL_SUMMARY_CC_MASK 2
-/*#define IQDIO_IQDC_INT_PARM 0x1234*/
-
-#define QDIO_Q_LAPS 5
-
-#define QDIO_STORAGE_KEY PAGE_DEFAULT_KEY
-
-#define L2_CACHELINE_SIZE 256
-#define INDICATORS_PER_CACHELINE (L2_CACHELINE_SIZE/sizeof(__u32))
-
-#define QDIO_PERF "qdio_perf"
-
-/* must be a power of 2 */
-/*#define QDIO_STATS_NUMBER 4
-
-#define QDIO_STATS_CLASSES 2
-#define QDIO_STATS_COUNT_NEEDED 2*/
-
-#define QDIO_NO_USE_COUNT_TIMEOUT (1*HZ) /* wait for 1 sec on each q before
-                                           exiting without having use_count
-                                           of the queue to 0 */
-
-#define QDIO_ESTABLISH_TIMEOUT (1*HZ)
-#define QDIO_ACTIVATE_TIMEOUT ((5*HZ)>>10)
-#define QDIO_CLEANUP_CLEAR_TIMEOUT (20*HZ)
-#define QDIO_CLEANUP_HALT_TIMEOUT (10*HZ)
+#define QDIO_IQDIO_POLL_LVL            65      /* HS multicast queue */
 
 enum qdio_irq_states {
        QDIO_IRQ_STATE_INACTIVE,
@@ -76,575 +34,357 @@ enum qdio_irq_states {
        NR_QDIO_IRQ_STATES,
 };
 
-/* used as intparm in do_IO: */
-#define QDIO_DOING_SENSEID 0
-#define QDIO_DOING_ESTABLISH 1
-#define QDIO_DOING_ACTIVATE 2
-#define QDIO_DOING_CLEANUP 3
-
-/************************* DEBUG FACILITY STUFF *********************/
-
-#define QDIO_DBF_HEX(ex,name,level,addr,len) \
-       do { \
-       if (ex) \
-               debug_exception(qdio_dbf_##name,level,(void*)(addr),len); \
-       else \
-               debug_event(qdio_dbf_##name,level,(void*)(addr),len); \
-       } while (0)
-#define QDIO_DBF_TEXT(ex,name,level,text) \
-       do { \
-       if (ex) \
-               debug_text_exception(qdio_dbf_##name,level,text); \
-       else \
-               debug_text_event(qdio_dbf_##name,level,text); \
-       } while (0)
-
-
-#define QDIO_DBF_HEX0(ex,name,addr,len) QDIO_DBF_HEX(ex,name,0,addr,len)
-#define QDIO_DBF_HEX1(ex,name,addr,len) QDIO_DBF_HEX(ex,name,1,addr,len)
-#define QDIO_DBF_HEX2(ex,name,addr,len) QDIO_DBF_HEX(ex,name,2,addr,len)
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_HEX3(ex,name,addr,len) QDIO_DBF_HEX(ex,name,3,addr,len)
-#define QDIO_DBF_HEX4(ex,name,addr,len) QDIO_DBF_HEX(ex,name,4,addr,len)
-#define QDIO_DBF_HEX5(ex,name,addr,len) QDIO_DBF_HEX(ex,name,5,addr,len)
-#define QDIO_DBF_HEX6(ex,name,addr,len) QDIO_DBF_HEX(ex,name,6,addr,len)
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_HEX3(ex,name,addr,len) do {} while (0)
-#define QDIO_DBF_HEX4(ex,name,addr,len) do {} while (0)
-#define QDIO_DBF_HEX5(ex,name,addr,len) do {} while (0)
-#define QDIO_DBF_HEX6(ex,name,addr,len) do {} while (0)
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_DBF_TEXT0(ex,name,text) QDIO_DBF_TEXT(ex,name,0,text)
-#define QDIO_DBF_TEXT1(ex,name,text) QDIO_DBF_TEXT(ex,name,1,text)
-#define QDIO_DBF_TEXT2(ex,name,text) QDIO_DBF_TEXT(ex,name,2,text)
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_TEXT3(ex,name,text) QDIO_DBF_TEXT(ex,name,3,text)
-#define QDIO_DBF_TEXT4(ex,name,text) QDIO_DBF_TEXT(ex,name,4,text)
-#define QDIO_DBF_TEXT5(ex,name,text) QDIO_DBF_TEXT(ex,name,5,text)
-#define QDIO_DBF_TEXT6(ex,name,text) QDIO_DBF_TEXT(ex,name,6,text)
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_TEXT3(ex,name,text) do {} while (0)
-#define QDIO_DBF_TEXT4(ex,name,text) do {} while (0)
-#define QDIO_DBF_TEXT5(ex,name,text) do {} while (0)
-#define QDIO_DBF_TEXT6(ex,name,text) do {} while (0)
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_DBF_SETUP_NAME "qdio_setup"
-#define QDIO_DBF_SETUP_LEN 8
-#define QDIO_DBF_SETUP_PAGES 4
-#define QDIO_DBF_SETUP_NR_AREAS 1
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_SETUP_LEVEL 6
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_SETUP_LEVEL 2
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_DBF_SBAL_NAME "qdio_labs" /* sbal */
-#define QDIO_DBF_SBAL_LEN 256
-#define QDIO_DBF_SBAL_PAGES 4
-#define QDIO_DBF_SBAL_NR_AREAS 2
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_SBAL_LEVEL 6
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_SBAL_LEVEL 2
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_DBF_TRACE_NAME "qdio_trace"
-#define QDIO_DBF_TRACE_LEN 8
-#define QDIO_DBF_TRACE_NR_AREAS 2
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_TRACE_PAGES 16
-#define QDIO_DBF_TRACE_LEVEL 4 /* -------- could be even more verbose here */
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_TRACE_PAGES 4
-#define QDIO_DBF_TRACE_LEVEL 2
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_DBF_SENSE_NAME "qdio_sense"
-#define QDIO_DBF_SENSE_LEN 64
-#define QDIO_DBF_SENSE_PAGES 2
-#define QDIO_DBF_SENSE_NR_AREAS 1
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_SENSE_LEVEL 6
-#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_SENSE_LEVEL 2
-#endif /* CONFIG_QDIO_DEBUG */
-
-#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_TRACE_QTYPE QDIO_ZFCP_QFMT
-
-#define QDIO_DBF_SLSB_OUT_NAME "qdio_slsb_out"
-#define QDIO_DBF_SLSB_OUT_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_OUT_PAGES 256
-#define QDIO_DBF_SLSB_OUT_NR_AREAS 1
-#define QDIO_DBF_SLSB_OUT_LEVEL 6
-
-#define QDIO_DBF_SLSB_IN_NAME "qdio_slsb_in"
-#define QDIO_DBF_SLSB_IN_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_IN_PAGES 256
-#define QDIO_DBF_SLSB_IN_NR_AREAS 1
-#define QDIO_DBF_SLSB_IN_LEVEL 6
-#endif /* CONFIG_QDIO_DEBUG */
-
-#define QDIO_PRINTK_HEADER QDIO_NAME ": "
-
-#if QDIO_VERBOSE_LEVEL>8
-#define QDIO_PRINT_STUPID(x...) printk( KERN_DEBUG QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_STUPID(x...)
-#endif
-
-#if QDIO_VERBOSE_LEVEL>7
-#define QDIO_PRINT_ALL(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_ALL(x...)
-#endif
-
-#if QDIO_VERBOSE_LEVEL>6
-#define QDIO_PRINT_INFO(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_INFO(x...)
-#endif
-
-#if QDIO_VERBOSE_LEVEL>5
-#define QDIO_PRINT_WARN(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_WARN(x...)
-#endif
-
-#if QDIO_VERBOSE_LEVEL>4
-#define QDIO_PRINT_ERR(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_ERR(x...)
-#endif
+/* used as intparm in do_IO */
+#define QDIO_DOING_ESTABLISH   1
+#define QDIO_DOING_ACTIVATE    2
+#define QDIO_DOING_CLEANUP     3
+
+#define SLSB_STATE_NOT_INIT    0x0
+#define SLSB_STATE_EMPTY       0x1
+#define SLSB_STATE_PRIMED      0x2
+#define SLSB_STATE_HALTED      0xe
+#define SLSB_STATE_ERROR       0xf
+#define SLSB_TYPE_INPUT                0x0
+#define SLSB_TYPE_OUTPUT       0x20
+#define SLSB_OWNER_PROG                0x80
+#define SLSB_OWNER_CU          0x40
+
+#define SLSB_P_INPUT_NOT_INIT  \
+       (SLSB_OWNER_PROG | SLSB_TYPE_INPUT | SLSB_STATE_NOT_INIT)  /* 0x80 */
+#define SLSB_P_INPUT_ACK       \
+       (SLSB_OWNER_PROG | SLSB_TYPE_INPUT | SLSB_STATE_EMPTY)     /* 0x81 */
+#define SLSB_CU_INPUT_EMPTY    \
+       (SLSB_OWNER_CU | SLSB_TYPE_INPUT | SLSB_STATE_EMPTY)       /* 0x41 */
+#define SLSB_P_INPUT_PRIMED    \
+       (SLSB_OWNER_PROG | SLSB_TYPE_INPUT | SLSB_STATE_PRIMED)    /* 0x82 */
+#define SLSB_P_INPUT_HALTED    \
+       (SLSB_OWNER_PROG | SLSB_TYPE_INPUT | SLSB_STATE_HALTED)    /* 0x8e */
+#define SLSB_P_INPUT_ERROR     \
+       (SLSB_OWNER_PROG | SLSB_TYPE_INPUT | SLSB_STATE_ERROR)     /* 0x8f */
+#define SLSB_P_OUTPUT_NOT_INIT \
+       (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_NOT_INIT) /* 0xa0 */
+#define SLSB_P_OUTPUT_EMPTY    \
+       (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_EMPTY)    /* 0xa1 */
+#define SLSB_CU_OUTPUT_PRIMED  \
+       (SLSB_OWNER_CU | SLSB_TYPE_OUTPUT | SLSB_STATE_PRIMED)     /* 0x62 */
+#define SLSB_P_OUTPUT_HALTED   \
+       (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_HALTED)   /* 0xae */
+#define SLSB_P_OUTPUT_ERROR    \
+       (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_ERROR)    /* 0xaf */
+
+#define SLSB_ERROR_DURING_LOOKUP  0xff
+
+/* additional CIWs returned by extended Sense-ID */
+#define CIW_TYPE_EQUEUE                        0x3 /* establish QDIO queues */
+#define CIW_TYPE_AQUEUE                        0x4 /* activate QDIO queues */
 
-#if QDIO_VERBOSE_LEVEL>3
-#define QDIO_PRINT_CRIT(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_CRIT(x...)
-#endif
-
-#if QDIO_VERBOSE_LEVEL>2
-#define QDIO_PRINT_ALERT(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_ALERT(x...)
-#endif
-
-#if QDIO_VERBOSE_LEVEL>1
-#define QDIO_PRINT_EMERG(x...) printk( QDIO_PRINTK_HEADER x)
-#else
-#define QDIO_PRINT_EMERG(x...)
-#endif
-
-#define HEXDUMP16(importance,header,ptr) \
-QDIO_PRINT_##importance(header "%02x %02x %02x %02x  " \
-                       "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-                       "%02x %02x %02x %02x\n",*(((char*)ptr)), \
-                       *(((char*)ptr)+1),*(((char*)ptr)+2), \
-                       *(((char*)ptr)+3),*(((char*)ptr)+4), \
-                       *(((char*)ptr)+5),*(((char*)ptr)+6), \
-                       *(((char*)ptr)+7),*(((char*)ptr)+8), \
-                       *(((char*)ptr)+9),*(((char*)ptr)+10), \
-                       *(((char*)ptr)+11),*(((char*)ptr)+12), \
-                       *(((char*)ptr)+13),*(((char*)ptr)+14), \
-                       *(((char*)ptr)+15)); \
-QDIO_PRINT_##importance(header "%02x %02x %02x %02x  %02x %02x %02x %02x  " \
-                       "%02x %02x %02x %02x  %02x %02x %02x %02x\n", \
-                       *(((char*)ptr)+16),*(((char*)ptr)+17), \
-                       *(((char*)ptr)+18),*(((char*)ptr)+19), \
-                       *(((char*)ptr)+20),*(((char*)ptr)+21), \
-                       *(((char*)ptr)+22),*(((char*)ptr)+23), \
-                       *(((char*)ptr)+24),*(((char*)ptr)+25), \
-                       *(((char*)ptr)+26),*(((char*)ptr)+27), \
-                       *(((char*)ptr)+28),*(((char*)ptr)+29), \
-                       *(((char*)ptr)+30),*(((char*)ptr)+31));
-
-/****************** END OF DEBUG FACILITY STUFF *********************/
-
-/*
- * Some instructions as assembly
- */
-extern __inline__ int 
-do_siga_sync(unsigned int irq, unsigned int mask1, unsigned int mask2)
-{
-       int cc;
-
-#ifndef CONFIG_ARCH_S390X
-       asm volatile (
-               "lhi    0,2     \n\t"
-               "lr     1,%1    \n\t"
-               "lr     2,%2    \n\t"
-               "lr     3,%3    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               : "=d" (cc)
-               : "d" (0x10000|irq), "d" (mask1), "d" (mask2)
-               : "cc", "0", "1", "2", "3"
-               );
-#else /* CONFIG_ARCH_S390X */
-       asm volatile (
-               "lghi   0,2     \n\t"
-               "llgfr  1,%1    \n\t"
-               "llgfr  2,%2    \n\t"
-               "llgfr  3,%3    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               : "=d" (cc)
-               : "d" (0x10000|irq), "d" (mask1), "d" (mask2)
-               : "cc", "0", "1", "2", "3"
-               );
-#endif /* CONFIG_ARCH_S390X */
-       return cc;
-}
-
-extern __inline__ int
-do_siga_input(unsigned int irq, unsigned int mask)
+/* flags for st qdio sch data */
+#define CHSC_FLAG_QDIO_CAPABILITY      0x80
+#define CHSC_FLAG_VALIDITY             0x40
+
+/* qdio adapter-characteristics-1 flag */
+#define AC1_SIGA_INPUT_NEEDED          0x40    /* process input queues */
+#define AC1_SIGA_OUTPUT_NEEDED         0x20    /* process output queues */
+#define AC1_SIGA_SYNC_NEEDED           0x10    /* ask hypervisor to sync */
+#define AC1_AUTOMATIC_SYNC_ON_THININT  0x08    /* set by hypervisor */
+#define AC1_AUTOMATIC_SYNC_ON_OUT_PCI  0x04    /* set by hypervisor */
+#define AC1_SC_QEBSM_AVAILABLE         0x02    /* available for subchannel */
+#define AC1_SC_QEBSM_ENABLED           0x01    /* enabled for subchannel */
+
+#ifdef CONFIG_64BIT
+static inline int do_sqbs(u64 token, unsigned char state, int queue,
+                         int *start, int *count)
 {
-       int cc;
-
-#ifndef CONFIG_ARCH_S390X
-       asm volatile (
-               "lhi    0,1     \n\t"
-               "lr     1,%1    \n\t"
-               "lr     2,%2    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               : "=d" (cc)
-               : "d" (0x10000|irq), "d" (mask)
-               : "cc", "0", "1", "2", "memory"
-               );
-#else /* CONFIG_ARCH_S390X */
-       asm volatile (
-               "lghi   0,1     \n\t"
-               "llgfr  1,%1    \n\t"
-               "llgfr  2,%2    \n\t"
-               "siga   0       \n\t"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               : "=d" (cc)
-               : "d" (0x10000|irq), "d" (mask)
-               : "cc", "0", "1", "2", "memory"
-               );
-#endif /* CONFIG_ARCH_S390X */
-       
-       return cc;
+       register unsigned long _ccq asm ("0") = *count;
+       register unsigned long _token asm ("1") = token;
+       unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+
+       asm volatile(
+               "       .insn   rsy,0xeb000000008A,%1,0,0(%2)"
+               : "+d" (_ccq), "+d" (_queuestart)
+               : "d" ((unsigned long)state), "d" (_token)
+               : "memory", "cc");
+       *count = _ccq & 0xff;
+       *start = _queuestart & 0xff;
+
+       return (_ccq >> 32) & 0xff;
 }
 
-extern __inline__ int
-do_siga_output(unsigned long irq, unsigned long mask, __u32 *bb)
+static inline int do_eqbs(u64 token, unsigned char *state, int queue,
+                         int *start, int *count, int ack)
 {
-       int cc;
-       __u32 busy_bit;
-
-#ifndef CONFIG_ARCH_S390X
-       asm volatile (
-               "lhi    0,0     \n\t"
-               "lr     1,%2    \n\t"
-               "lr     2,%3    \n\t"
-               "siga   0       \n\t"
-               "0:"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               "srl    0,31    \n\t"
-               "lr     %1,0    \n\t"
-               "1:     \n\t"
-               ".section .fixup,\"ax\"\n\t"
-               "2:     \n\t"
-               "lhi    %0,%4   \n\t"
-               "bras   1,3f    \n\t"
-               ".long 1b       \n\t"
-               "3:     \n\t"
-               "l      1,0(1)  \n\t"
-               "br     1       \n\t"
-               ".previous      \n\t"
-               ".section __ex_table,\"a\"\n\t"
-               ".align 4       \n\t"
-               ".long  0b,2b   \n\t"
-               ".previous      \n\t"
-               : "=d" (cc), "=d" (busy_bit)
-               : "d" (0x10000|irq), "d" (mask),
-               "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
-               : "cc", "0", "1", "2", "memory"
-               );
-#else /* CONFIG_ARCH_S390X */
-       asm volatile (
-               "lghi   0,0     \n\t"
-               "llgfr  1,%2    \n\t"
-               "llgfr  2,%3    \n\t"
-               "siga   0       \n\t"
-               "0:"
-               "ipm    %0      \n\t"
-               "srl    %0,28   \n\t"
-               "srl    0,31    \n\t"
-               "llgfr  %1,0    \n\t"
-               "1:     \n\t"
-               ".section .fixup,\"ax\"\n\t"
-               "lghi   %0,%4   \n\t"
-               "jg     1b      \n\t"
-               ".previous\n\t"
-               ".section __ex_table,\"a\"\n\t"
-               ".align 8       \n\t"
-               ".quad  0b,1b   \n\t"
-               ".previous      \n\t"
-               : "=d" (cc), "=d" (busy_bit)
-               : "d" (0x10000|irq), "d" (mask),
-               "i" (QDIO_SIGA_ERROR_ACCESS_EXCEPTION)
-               : "cc", "0", "1", "2", "memory"
-               );
-#endif /* CONFIG_ARCH_S390X */
-       
-       (*bb) = busy_bit;
-       return cc;
+       register unsigned long _ccq asm ("0") = *count;
+       register unsigned long _token asm ("1") = token;
+       unsigned long _queuestart = ((unsigned long)queue << 32) | *start;
+       unsigned long _state = (unsigned long)ack << 63;
+
+       asm volatile(
+               "       .insn   rrf,0xB99c0000,%1,%2,0,0"
+               : "+d" (_ccq), "+d" (_queuestart), "+d" (_state)
+               : "d" (_token)
+               : "memory", "cc");
+       *count = _ccq & 0xff;
+       *start = _queuestart & 0xff;
+       *state = _state & 0xff;
+
+       return (_ccq >> 32) & 0xff;
 }
+#else
+static inline int do_sqbs(u64 token, unsigned char state, int queue,
+                         int *start, int *count) { return 0; }
+static inline int do_eqbs(u64 token, unsigned char *state, int queue,
+                         int *start, int *count, int ack) { return 0; }
+#endif /* CONFIG_64BIT */
+
+struct qdio_irq;
+
+struct siga_flag {
+       u8 input:1;
+       u8 output:1;
+       u8 sync:1;
+       u8 no_sync_ti:1;
+       u8 no_sync_out_ti:1;
+       u8 no_sync_out_pci:1;
+       u8:2;
+} __attribute__ ((packed));
+
+struct chsc_ssqd_area {
+       struct chsc_header request;
+       u16:10;
+       u8 ssid:2;
+       u8 fmt:4;
+       u16 first_sch;
+       u16:16;
+       u16 last_sch;
+       u32:32;
+       struct chsc_header response;
+       u32:32;
+       struct qdio_ssqd_desc qdio_ssqd;
+} __attribute__ ((packed));
+
+struct scssc_area {
+       struct chsc_header request;
+       u16 operation_code;
+       u16:16;
+       u32:32;
+       u32:32;
+       u64 summary_indicator_addr;
+       u64 subchannel_indicator_addr;
+       u32 ks:4;
+       u32 kc:4;
+       u32:21;
+       u32 isc:3;
+       u32 word_with_d_bit;
+       u32:32;
+       struct subchannel_id schid;
+       u32 reserved[1004];
+       struct chsc_header response;
+       u32:32;
+} __attribute__ ((packed));
+
+struct qdio_input_q {
+       /* input buffer acknowledgement flag */
+       int polling;
+
+       /* first ACK'ed buffer */
+       int ack_start;
+
+       /* how much sbals are acknowledged with qebsm */
+       int ack_count;
+
+       /* last time of noticing incoming data */
+       u64 timestamp;
+};
 
-extern __inline__ unsigned long
-do_clear_global_summary(void)
-{
-
-       unsigned long time;
-
-#ifndef CONFIG_ARCH_S390X
-       asm volatile (
-               "lhi    1,3     \n\t"
-               ".insn  rre,0xb2650000,2,0      \n\t"
-               "lr     %0,3    \n\t"
-               : "=d" (time) : : "cc", "1", "2", "3"
-               );
-#else /* CONFIG_ARCH_S390X */
-       asm volatile (
-               "lghi   1,3     \n\t"
-               ".insn  rre,0xb2650000,2,0      \n\t"
-               "lgr    %0,3    \n\t"
-               : "=d" (time) : : "cc", "1", "2", "3"
-               );
-#endif /* CONFIG_ARCH_S390X */
-       
-       return time;
-}
-       
-/*
- * QDIO device commands returned by extended Sense-ID
- */
-#define DEFAULT_ESTABLISH_QS_CMD 0x1b
-#define DEFAULT_ESTABLISH_QS_COUNT 0x1000
-#define DEFAULT_ACTIVATE_QS_CMD 0x1f
-#define DEFAULT_ACTIVATE_QS_COUNT 0
+struct qdio_output_q {
+       /* PCIs are enabled for the queue */
+       int pci_out_enabled;
 
-/*
- * additional CIWs returned by extended Sense-ID
- */
-#define CIW_TYPE_EQUEUE 0x3       /* establish QDIO queues */
-#define CIW_TYPE_AQUEUE 0x4       /* activate QDIO queues */
+       /* IQDIO: output multiple buffers (enhanced SIGA) */
+       int use_enh_siga;
 
-#define QDIO_CHSC_RESPONSE_CODE_OK 1
-/* flags for st qdio sch data */
-#define CHSC_FLAG_QDIO_CAPABILITY 0x80
-#define CHSC_FLAG_VALIDITY 0x40
-
-#define CHSC_FLAG_SIGA_INPUT_NECESSARY 0x40
-#define CHSC_FLAG_SIGA_OUTPUT_NECESSARY 0x20
-#define CHSC_FLAG_SIGA_SYNC_NECESSARY 0x10
-#define CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS 0x08
-#define CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS 0x04
-
-#ifdef QDIO_PERFORMANCE_STATS
-struct qdio_perf_stats {
-       unsigned int tl_runs;
-
-       unsigned int siga_outs;
-       unsigned int siga_ins;
-       unsigned int siga_syncs;
-       unsigned int pcis;
-       unsigned int thinints;
-       unsigned int fast_reqs;
-
-       __u64 start_time_outbound;
-       unsigned int outbound_cnt;
-       unsigned int outbound_time;
-       __u64 start_time_inbound;
-       unsigned int inbound_cnt;
-       unsigned int inbound_time;
+       /* timer to check for more outbound work */
+       struct timer_list timer;
 };
-#endif /* QDIO_PERFORMANCE_STATS */
-
-#define atomic_swap(a,b) xchg((int*)a.counter,b)
-
-/* unlikely as the later the better */
-#define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q)
-#define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \
-       qdio_siga_sync(q,~0U,~0U)
-#define SYNC_MEMORY_ALL_OUTB if (unlikely(q->siga_sync)) \
-       qdio_siga_sync(q,~0U,0)
-
-#define NOW qdio_get_micros()
-#define SAVE_TIMESTAMP(q) q->timing.last_transfer_time=NOW
-#define GET_SAVED_TIMESTAMP(q) (q->timing.last_transfer_time)
-#define SAVE_FRONTIER(q,val) q->last_move_ftc=val
-#define GET_SAVED_FRONTIER(q) (q->last_move_ftc)
-
-#define MY_MODULE_STRING(x) #x
-
-#ifdef CONFIG_ARCH_S390X
-#define QDIO_GET_ADDR(x) ((__u32)(unsigned long)x)
-#else /* CONFIG_ARCH_S390X */
-#define QDIO_GET_ADDR(x) ((__u32)(long)x)
-#endif /* CONFIG_ARCH_S390X */
-
-#ifdef CONFIG_QDIO_DEBUG
-#define set_slsb(x,y) \
-  if(q->queue_type==QDIO_TRACE_QTYPE) { \
-        if(q->is_input_q) { \
-            QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } else { \
-            QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } \
-  } \
-  qdio_set_slsb(x,y); \
-  if(q->queue_type==QDIO_TRACE_QTYPE) { \
-        if(q->is_input_q) { \
-            QDIO_DBF_HEX2(0,slsb_in,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } else { \
-            QDIO_DBF_HEX2(0,slsb_out,&q->slsb,QDIO_MAX_BUFFERS_PER_Q); \
-        } \
-  }
-#else /* CONFIG_QDIO_DEBUG */
-#define set_slsb(x,y) qdio_set_slsb(x,y)
-#endif /* CONFIG_QDIO_DEBUG */
 
 struct qdio_q {
-       volatile struct slsb slsb;
+       struct slsb slsb;
+       union {
+               struct qdio_input_q in;
+               struct qdio_output_q out;
+       } u;
 
-       char unused[QDIO_MAX_BUFFERS_PER_Q];
+       /* queue number */
+       int nr;
 
-       __u32 * volatile dev_st_chg_ind;
+       /* bitmask of queue number */
+       int mask;
 
+       /* input or output queue */
        int is_input_q;
-       int irq;
-       struct ccw_device *cdev;
 
-       unsigned int is_iqdio_q;
-       unsigned int is_thinint_q;
-
-       /* bit 0 means queue 0, bit 1 means queue 1, ... */
-       unsigned int mask;
-       unsigned int q_no;
+       /* list of thinint input queues */
+       struct list_head entry;
 
+       /* upper-layer program handler */
        qdio_handler_t (*handler);
 
-       /* points to the next buffer to be checked for having
-        * been processed by the card (outbound)
-        * or to the next buffer the program should check for (inbound) */
-       volatile int first_to_check;
-       /* and the last time it was: */
-       volatile int last_move_ftc;
-
-       atomic_t number_of_buffers_used;
-       atomic_t polling;
-
-       unsigned int siga_in;
-       unsigned int siga_out;
-       unsigned int siga_sync;
-       unsigned int siga_sync_done_on_thinints;
-       unsigned int siga_sync_done_on_outb_tis;
-       unsigned int hydra_gives_outbound_pcis;
+       /*
+        * inbound: next buffer the program should check for
+        * outbound: next buffer to check for having been processed
+        * by the card
+        */
+       int first_to_check;
 
-       /* used to save beginning position when calling dd_handlers */
-       int first_element_to_kick;
+       /* first_to_check of the last time */
+       int last_move;
 
-       atomic_t use_count;
-       atomic_t is_in_shutdown;
+       /* beginning position for calling the program */
+       int first_to_kick;
 
-       void *irq_ptr;
+       /* number of buffers in use by the adapter */
+       atomic_t nr_buf_used;
 
-#ifdef QDIO_USE_TIMERS_FOR_POLLING
-       struct timer_list timer;
-       atomic_t timer_already_set;
-       spinlock_t timer_lock;
-#else /* QDIO_USE_TIMERS_FOR_POLLING */
+       struct qdio_irq *irq_ptr;
+       struct dentry *debugfs_q;
        struct tasklet_struct tasklet;
-#endif /* QDIO_USE_TIMERS_FOR_POLLING */
 
-       enum qdio_irq_states state;
-
-       /* used to store the error condition during a data transfer */
+       /* error condition during a data transfer */
        unsigned int qdio_error;
-       unsigned int siga_error;
-       unsigned int error_status_flags;
-
-       /* list of interesting queues */
-       volatile struct qdio_q *list_next;
-       volatile struct qdio_q *list_prev;
 
        struct sl *sl;
-       volatile struct sbal *sbal[QDIO_MAX_BUFFERS_PER_Q];
-
-       struct qdio_buffer *qdio_buffers[QDIO_MAX_BUFFERS_PER_Q];
-
-       unsigned long int_parm;
-
-       /*struct {
-               int in_bh_check_limit;
-               int threshold;
-       } threshold_classes[QDIO_STATS_CLASSES];*/
-
-       struct {
-               /* inbound: the time to stop polling
-                  outbound: the time to kick peer */
-               int threshold; /* the real value */
-
-               /* outbound: last time of do_QDIO
-                  inbound: last time of noticing incoming data */
-               /*__u64 last_transfer_times[QDIO_STATS_NUMBER];
-               int last_transfer_index; */
-
-               __u64 last_transfer_time;
-               __u64 busy_start;
-       } timing;
-       atomic_t busy_siga_counter;
-        unsigned int queue_type;
-
-       /* leave this member at the end. won't be cleared in qdio_fill_qs */
-       struct slib *slib; /* a page is allocated under this pointer,
-                             sl points into this page, offset PAGE_SIZE/2
-                             (after slib) */
+       struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
+
+       /*
+        * Warning: Leave this member at the end so it won't be cleared in
+        * qdio_fill_qs. A page is allocated under this pointer and used for
+        * slib and sl. slib is 2048 bytes big and sl points to offset
+        * PAGE_SIZE / 2.
+        */
+       struct slib *slib;
 } __attribute__ ((aligned(256)));
 
 struct qdio_irq {
-       __u32 * volatile dev_st_chg_ind;
+       struct qib qib;
+       u32 *dsci;              /* address of device state change indicator */
+       struct ccw_device *cdev;
+       struct dentry *debugfs_dev;
 
        unsigned long int_parm;
-       int irq;
-
-       unsigned int is_iqdio_irq;
-       unsigned int is_thinint_irq;
-       unsigned int hydra_gives_outbound_pcis;
-       unsigned int sync_done_on_outb_pcis;
+       struct subchannel_id schid;
+       unsigned long sch_token;        /* QEBSM facility */
 
        enum qdio_irq_states state;
 
-       unsigned int no_input_qs;
-       unsigned int no_output_qs;
+       struct siga_flag siga_flag;     /* siga sync information from qdioac */
 
-       unsigned char qdioac;
+       int nr_input_qs;
+       int nr_output_qs;
 
        struct ccw1 ccw;
-
        struct ciw equeue;
        struct ciw aqueue;
 
-       struct qib qib;
-       
-       void (*original_int_handler) (struct ccw_device *,
-                                     unsigned long, struct irb *);
+       struct qdio_ssqd_desc ssqd_desc;
+
+       void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
 
-       /* leave these four members together at the end. won't be cleared in qdio_fill_irq */
+       /*
+        * Warning: Leave these members together at the end so they won't be
+        * cleared in qdio_setup_irq.
+        */
        struct qdr *qdr;
+       unsigned long chsc_page;
+
        struct qdio_q *input_qs[QDIO_MAX_QUEUES_PER_IRQ];
        struct qdio_q *output_qs[QDIO_MAX_QUEUES_PER_IRQ];
-       struct semaphore setting_up_sema;
+
+       debug_info_t *debug_area;
+       struct mutex setup_mutex;
 };
-#endif
+
+/* helper functions */
+#define queue_type(q)  q->irq_ptr->qib.qfmt
+#define SCH_NO(q)      (q->irq_ptr->schid.sch_no)
+
+#define is_thinint_irq(irq) \
+       (irq->qib.qfmt == QDIO_IQDIO_QFMT || \
+        css_general_characteristics.aif_osa)
+
+/* the highest iqdio queue is used for multicast */
+static inline int multicast_outbound(struct qdio_q *q)
+{
+       return (q->irq_ptr->nr_output_qs > 1) &&
+              (q->nr == q->irq_ptr->nr_output_qs - 1);
+}
+
+static inline unsigned long long get_usecs(void)
+{
+       return monotonic_clock() >> 12;
+}
+
+#define pci_out_supported(q) \
+       (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED)
+#define is_qebsm(q)                    (q->irq_ptr->sch_token != 0)
+
+#define need_siga_sync_thinint(q)      (!q->irq_ptr->siga_flag.no_sync_ti)
+#define need_siga_sync_out_thinint(q)  (!q->irq_ptr->siga_flag.no_sync_out_ti)
+#define need_siga_in(q)                        (q->irq_ptr->siga_flag.input)
+#define need_siga_out(q)               (q->irq_ptr->siga_flag.output)
+#define need_siga_sync(q)              (q->irq_ptr->siga_flag.sync)
+#define siga_syncs_out_pci(q)          (q->irq_ptr->siga_flag.no_sync_out_pci)
+
+#define for_each_input_queue(irq_ptr, q, i)    \
+       for (i = 0, q = irq_ptr->input_qs[0];   \
+               i < irq_ptr->nr_input_qs;       \
+               q = irq_ptr->input_qs[++i])
+#define for_each_output_queue(irq_ptr, q, i)   \
+       for (i = 0, q = irq_ptr->output_qs[0];  \
+               i < irq_ptr->nr_output_qs;      \
+               q = irq_ptr->output_qs[++i])
+
+#define prev_buf(bufnr)        \
+       ((bufnr + QDIO_MAX_BUFFERS_MASK) & QDIO_MAX_BUFFERS_MASK)
+#define next_buf(bufnr)        \
+       ((bufnr + 1) & QDIO_MAX_BUFFERS_MASK)
+#define add_buf(bufnr, inc) \
+       ((bufnr + inc) & QDIO_MAX_BUFFERS_MASK)
+#define sub_buf(bufnr, dec) \
+       ((bufnr - dec) & QDIO_MAX_BUFFERS_MASK)
+
+/* prototypes for thin interrupt */
+void qdio_setup_thinint(struct qdio_irq *irq_ptr);
+int qdio_establish_thinint(struct qdio_irq *irq_ptr);
+void qdio_shutdown_thinint(struct qdio_irq *irq_ptr);
+void tiqdio_add_input_queues(struct qdio_irq *irq_ptr);
+void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr);
+void tiqdio_inbound_processing(unsigned long q);
+int tiqdio_allocate_memory(void);
+void tiqdio_free_memory(void);
+int tiqdio_register_thinints(void);
+void tiqdio_unregister_thinints(void);
+
+/* prototypes for setup */
+void qdio_inbound_processing(unsigned long data);
+void qdio_outbound_processing(unsigned long data);
+void qdio_outbound_timer(unsigned long data);
+void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm,
+                     struct irb *irb);
+int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs,
+                    int nr_output_qs);
+void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr);
+int qdio_setup_get_ssqd(struct qdio_irq *irq_ptr,
+                       struct subchannel_id *schid,
+                       struct qdio_ssqd_desc *data);
+int qdio_setup_irq(struct qdio_initialize *init_data);
+void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
+                               struct ccw_device *cdev);
+void qdio_release_memory(struct qdio_irq *irq_ptr);
+int qdio_setup_create_sysfs(struct ccw_device *cdev);
+void qdio_setup_destroy_sysfs(struct ccw_device *cdev);
+int qdio_setup_init(void);
+void qdio_setup_exit(void);
+
+int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
+                       unsigned char *state);
+#endif /* _CIO_QDIO_H */