qdio: support asynchronous delivery of storage blocks
[pandora-kernel.git] / drivers / s390 / cio / qdio.h
index 0f4ef87..2b21f65 100644 (file)
@@ -14,6 +14,8 @@
 #include "chsc.h"
 
 #define QDIO_BUSY_BIT_PATIENCE         (100 << 12)     /* 100 microseconds */
+#define QDIO_BUSY_BIT_RETRY_DELAY      10              /* 10 milliseconds */
+#define QDIO_BUSY_BIT_RETRIES          1000            /* = 10s retry time */
 #define QDIO_INPUT_THRESHOLD           (500 << 12)     /* 500 microseconds */
 
 /*
@@ -42,6 +44,7 @@ enum qdio_irq_states {
 #define SLSB_STATE_NOT_INIT    0x0
 #define SLSB_STATE_EMPTY       0x1
 #define SLSB_STATE_PRIMED      0x2
+#define SLSB_STATE_PENDING     0x3
 #define SLSB_STATE_HALTED      0xe
 #define SLSB_STATE_ERROR       0xf
 #define SLSB_TYPE_INPUT                0x0
@@ -65,6 +68,8 @@ enum qdio_irq_states {
        (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_P_OUTPUT_PENDING \
+       (SLSB_OWNER_PROG | SLSB_TYPE_OUTPUT | SLSB_STATE_PENDING)  /* 0xa3 */
 #define SLSB_CU_OUTPUT_PRIMED  \
        (SLSB_OWNER_CU | SLSB_TYPE_OUTPUT | SLSB_STATE_PRIMED)     /* 0x62 */
 #define SLSB_P_OUTPUT_HALTED   \
@@ -91,6 +96,13 @@ enum qdio_irq_states {
 #define AC1_SC_QEBSM_AVAILABLE         0x02    /* available for subchannel */
 #define AC1_SC_QEBSM_ENABLED           0x01    /* enabled for subchannel */
 
+/* SIGA flags */
+#define QDIO_SIGA_WRITE                0x00
+#define QDIO_SIGA_READ         0x01
+#define QDIO_SIGA_SYNC         0x02
+#define QDIO_SIGA_WRITEQ       0x04
+#define QDIO_SIGA_QEBSM_FLAG   0x80
+
 #ifdef CONFIG_64BIT
 static inline int do_sqbs(u64 token, unsigned char state, int queue,
                          int *start, int *count)
@@ -142,10 +154,9 @@ 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;
+       u8 sync_after_ai:1;
+       u8 sync_out_after_pci:1;
+       u8:3;
 } __attribute__ ((packed));
 
 struct chsc_ssqd_area {
@@ -202,6 +213,7 @@ struct qdio_dev_perf_stat {
        unsigned int inbound_queue_full;
        unsigned int outbound_call;
        unsigned int outbound_handler;
+       unsigned int outbound_queue_full;
        unsigned int fast_requeue;
        unsigned int target_full;
        unsigned int eqbs;
@@ -245,10 +257,16 @@ 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;
+       /* cq: use asynchronous output buffers */
+       int use_cq;
+       /* cq: aobs used for particual SBAL */
+       struct qaob **aobs;
+       /* cq: sbal state related to asynchronous operation */
+       struct qdio_outbuf_state *sbal_state;
        /* timer to check for more outbound work */
        struct timer_list timer;
+       /* used SBALs before tasklet schedule */
+       int scan_threshold;
 };
 
 /*
@@ -383,12 +401,13 @@ static inline int multicast_outbound(struct qdio_q *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 need_siga_sync(q)              (unlikely(q->irq_ptr->siga_flag.sync))
+#define need_siga_sync_after_ai(q)     \
+       (unlikely(q->irq_ptr->siga_flag.sync_after_ai))
+#define need_siga_sync_out_after_pci(q)        \
+       (unlikely(q->irq_ptr->siga_flag.sync_out_after_pci))
 
 #define for_each_input_queue(irq_ptr, q, i)    \
        for (i = 0, q = irq_ptr->input_qs[0];   \
@@ -423,9 +442,20 @@ struct indicator_t {
 
 extern struct indicator_t *q_indicators;
 
-static inline int shared_ind(struct qdio_irq *irq_ptr)
+static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq)
+{
+       return irq->nr_input_qs > 1;
+}
+
+static inline int references_shared_dsci(struct qdio_irq *irq)
 {
-       return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+       return irq->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
+}
+
+static inline int shared_ind(struct qdio_q *q)
+{
+       struct qdio_irq *i = q->irq_ptr;
+       return references_shared_dsci(i) || has_multiple_inq_on_dsci(i);
 }
 
 /* prototypes for thin interrupt */
@@ -440,6 +470,7 @@ 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);
@@ -460,6 +491,9 @@ 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 qdio_enable_async_operation(struct qdio_output_q *q);
+void qdio_disable_async_operation(struct qdio_output_q *q);
+struct qaob *qdio_allocate_aob(void);
 
 int debug_get_buf_state(struct qdio_q *q, unsigned int bufnr,
                        unsigned char *state);