aboutsummaryrefslogtreecommitdiff
path: root/drivers/s390/cio/qdio.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/qdio.h')
-rw-r--r--drivers/s390/cio/qdio.h131
1 files changed, 45 insertions, 86 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 0f4ef8769a3..a563e4c0059 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -1,7 +1,5 @@
/*
- * linux/drivers/s390/cio/qdio.h
- *
- * Copyright 2000,2009 IBM Corp.
+ * Copyright IBM Corp. 2000, 2009
* Author(s): Utz Bacher <utz.bacher@de.ibm.com>
* Jan Glauber <jang@linux.vnet.ibm.com>
*/
@@ -14,16 +12,10 @@
#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 */
-/*
- * 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 QDIO_IQDIO_POLL_LVL 65 /* HS multicast queue */
-
enum qdio_irq_states {
QDIO_IRQ_STATE_INACTIVE,
QDIO_IRQ_STATE_ESTABLISHED,
@@ -42,6 +34,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 +58,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 \
@@ -82,14 +77,12 @@ enum qdio_irq_states {
#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 */
+/* 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,
@@ -142,44 +135,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;
-} __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;
+ u8 sync_after_ai:1;
+ u8 sync_out_after_pci:1;
+ u8:3;
} __attribute__ ((packed));
struct qdio_dev_perf_stat {
@@ -202,6 +160,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 +204,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;
};
/*
@@ -281,6 +246,9 @@ struct qdio_q {
/* error condition during a data transfer */
unsigned int qdio_error;
+ /* last scan of the queue */
+ u64 timestamp;
+
struct tasklet_struct tasklet;
struct qdio_queue_perf_stat q_stats;
@@ -383,21 +351,20 @@ 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 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 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; i < irq_ptr->nr_input_qs && \
+ ({ q = irq_ptr->input_qs[i]; 1; }); i++)
+#define for_each_output_queue(irq_ptr, q, i) \
+ for (i = 0; i < irq_ptr->nr_output_qs && \
+ ({ q = irq_ptr->output_qs[i]; 1; }); i++)
#define prev_buf(bufnr) \
((bufnr + QDIO_MAX_BUFFERS_MASK) & QDIO_MAX_BUFFERS_MASK)
@@ -413,20 +380,7 @@ static inline int multicast_outbound(struct qdio_q *q)
#define queue_irqs_disabled(q) \
(test_bit(QDIO_QUEUE_IRQS_DISABLED, &q->u.in.queue_irq_state) != 0)
-#define TIQDIO_SHARED_IND 63
-
-/* device state change indicators */
-struct indicator_t {
- u32 ind; /* u32 because of compare-and-swap performance */
- atomic_t count; /* use count, 0 or 1 for non-shared indicators */
-};
-
-extern struct indicator_t *q_indicators;
-
-static inline int shared_ind(struct qdio_irq *irq_ptr)
-{
- return irq_ptr->dsci == &q_indicators[TIQDIO_SHARED_IND].ind;
-}
+extern u64 last_ai_time;
/* prototypes for thin interrupt */
void qdio_setup_thinint(struct qdio_irq *irq_ptr);
@@ -439,6 +393,8 @@ int tiqdio_allocate_memory(void);
void tiqdio_free_memory(void);
int tiqdio_register_thinints(void);
void tiqdio_unregister_thinints(void);
+void clear_nonshared_ind(struct qdio_irq *);
+int test_nonshared_ind(struct qdio_irq *);
/* prototypes for setup */
void qdio_inbound_processing(unsigned long data);
@@ -460,6 +416,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);