diff options
Diffstat (limited to 'drivers/s390/cio/qdio.h')
-rw-r--r-- | drivers/s390/cio/qdio.h | 85 |
1 files changed, 54 insertions, 31 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 44f2f6a97f3..9a5283e16e3 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -210,16 +210,25 @@ struct qdio_dev_perf_stat { unsigned int sqbs_partial; }; +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,16 +269,32 @@ 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 @@ -341,9 +353,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) |