Merge branch 'nfs-for-2.6.35' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / s390 / cio / qdio.h
index 44f2f6a..f0037ee 100644 (file)
@@ -13,8 +13,8 @@
 #include <asm/debug.h>
 #include "chsc.h"
 
-#define QDIO_BUSY_BIT_PATIENCE         100     /* 100 microseconds */
-#define QDIO_INPUT_THRESHOLD           500     /* 500 microseconds */
+#define QDIO_BUSY_BIT_PATIENCE         (100 << 12)     /* 100 microseconds */
+#define QDIO_INPUT_THRESHOLD           (500 << 12)     /* 500 microseconds */
 
 /*
  * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait
@@ -208,18 +208,27 @@ struct qdio_dev_perf_stat {
        unsigned int eqbs_partial;
        unsigned int sqbs;
        unsigned int sqbs_partial;
+} ____cacheline_aligned;
+
+struct qdio_queue_perf_stat {
+       /*
+        * Sorted into order-2 buckets: 1, 2-3, 4-7, ... 64-127, 128.
+        * Since max. 127 SBALs are scanned reuse entry for 128 as queue full
+        * aka 127 SBALs found.
+        */
+       unsigned int nr_sbals[8];
+       unsigned int nr_sbal_error;
+       unsigned int nr_sbal_nop;
+       unsigned int nr_sbal_total;
 };
 
 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;
 };
@@ -227,40 +236,27 @@ struct qdio_input_q {
 struct qdio_output_q {
        /* PCIs are enabled for the queue */
        int pci_out_enabled;
-
        /* IQDIO: output multiple buffers (enhanced SIGA) */
        int use_enh_siga;
-
        /* timer to check for more outbound work */
        struct timer_list timer;
 };
 
+/*
+ * Note on cache alignment: grouped slsb and write mostly data at the beginning
+ * sbal[] is read-only and starts on a new cacheline followed by read mostly.
+ */
 struct qdio_q {
        struct slsb slsb;
+
        union {
                struct qdio_input_q in;
                struct qdio_output_q out;
        } u;
 
-       /* queue number */
-       int nr;
-
-       /* bitmask of queue number */
-       int mask;
-
-       /* input or output queue */
-       int is_input_q;
-
-       /* list of thinint input queues */
-       struct list_head entry;
-
-       /* upper-layer program handler */
-       qdio_handler_t (*handler);
-
        /*
         * inbound: next buffer the program should check for
-        * outbound: next buffer to check for having been processed
-        * by the card
+        * outbound: next buffer to check if adapter processed it
         */
        int first_to_check;
 
@@ -273,21 +269,35 @@ struct qdio_q {
        /* number of buffers in use by the adapter */
        atomic_t nr_buf_used;
 
-       struct qdio_irq *irq_ptr;
-       struct dentry *debugfs_q;
-       struct tasklet_struct tasklet;
-
        /* error condition during a data transfer */
        unsigned int qdio_error;
 
-       struct sl *sl;
-       struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q];
+       struct tasklet_struct tasklet;
+       struct qdio_queue_perf_stat q_stats;
 
+       struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q] ____cacheline_aligned;
+
+       /* queue number */
+       int nr;
+
+       /* bitmask of queue number */
+       int mask;
+
+       /* input or output queue */
+       int is_input_q;
+
+       /* list of thinint input queues */
+       struct list_head entry;
+
+       /* upper-layer program handler */
+       qdio_handler_t (*handler);
+
+       struct dentry *debugfs_q;
+       struct qdio_irq *irq_ptr;
+       struct sl *sl;
        /*
-        * 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.
+        * 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)));
@@ -317,12 +327,8 @@ struct qdio_irq {
        struct qdio_ssqd_desc ssqd_desc;
        void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
 
-       struct qdio_dev_perf_stat perf_stat;
        int perf_stat_enabled;
-       /*
-        * 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;
 
@@ -331,6 +337,7 @@ struct qdio_irq {
 
        debug_info_t *debug_area;
        struct mutex setup_mutex;
+       struct qdio_dev_perf_stat perf_stat;
 };
 
 /* helper functions */
@@ -341,9 +348,20 @@ struct qdio_irq {
        (irq->qib.qfmt == QDIO_IQDIO_QFMT || \
         css_general_characteristics.aif_osa)
 
-#define qperf(qdev,attr)       qdev->perf_stat.attr
-#define qperf_inc(q,attr)      if (q->irq_ptr->perf_stat_enabled) \
-                                       q->irq_ptr->perf_stat.attr++
+#define qperf(__qdev, __attr)  ((__qdev)->perf_stat.(__attr))
+
+#define qperf_inc(__q, __attr)                                         \
+({                                                                     \
+       struct qdio_irq *qdev = (__q)->irq_ptr;                         \
+       if (qdev->perf_stat_enabled)                                    \
+               (qdev->perf_stat.__attr)++;                             \
+})
+
+static inline void account_sbals_error(struct qdio_q *q, int count)
+{
+       q->q_stats.nr_sbal_error += count;
+       q->q_stats.nr_sbal_total += count;
+}
 
 /* the highest iqdio queue is used for multicast */
 static inline int multicast_outbound(struct qdio_q *q)
@@ -352,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q)
               (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)