diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2008-12-25 07:38:47 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2008-12-25 07:38:59 -0500 |
commit | 50f769df1c4bea766c4eb927eae35728fb93e305 (patch) | |
tree | c86228e6965de0ea84bddc2104d7dfa339e2a187 /drivers/s390/cio/qdio.h | |
parent | 22f9934767f49012ffbae753b28b8055bd28348f (diff) |
[S390] qdio: improve inbound buffer acknowledgement
- Use automatic acknowledgement of incoming buffers in QEBSM mode
- Move ACK for non-QEBSM mode always to the newest buffer to prevent
a race with qdio_stop_polling
- Remove the polling spinlock, the upper layer drivers return new buffers
in the same code path and could not run in parallel
- Don't flood the error log in case of no-target-buffer-empty
- In handle_inbound we check if we would overwrite an ACK'ed buffer, if so
advance the pointer to the oldest ACK'ed buffer so we don't overwrite an
empty buffer in qdio_stop_polling
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/qdio.h')
-rw-r--r-- | drivers/s390/cio/qdio.h | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 7b50882577d5..c60f2566d28c 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -112,12 +112,12 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue, | |||
112 | } | 112 | } |
113 | 113 | ||
114 | static inline int do_eqbs(u64 token, unsigned char *state, int queue, | 114 | static inline int do_eqbs(u64 token, unsigned char *state, int queue, |
115 | int *start, int *count) | 115 | int *start, int *count, int ack) |
116 | { | 116 | { |
117 | register unsigned long _ccq asm ("0") = *count; | 117 | register unsigned long _ccq asm ("0") = *count; |
118 | register unsigned long _token asm ("1") = token; | 118 | register unsigned long _token asm ("1") = token; |
119 | unsigned long _queuestart = ((unsigned long)queue << 32) | *start; | 119 | unsigned long _queuestart = ((unsigned long)queue << 32) | *start; |
120 | unsigned long _state = 0; | 120 | unsigned long _state = (unsigned long)ack << 63; |
121 | 121 | ||
122 | asm volatile( | 122 | asm volatile( |
123 | " .insn rrf,0xB99c0000,%1,%2,0,0" | 123 | " .insn rrf,0xB99c0000,%1,%2,0,0" |
@@ -134,7 +134,7 @@ static inline int do_eqbs(u64 token, unsigned char *state, int queue, | |||
134 | static inline int do_sqbs(u64 token, unsigned char state, int queue, | 134 | static inline int do_sqbs(u64 token, unsigned char state, int queue, |
135 | int *start, int *count) { return 0; } | 135 | int *start, int *count) { return 0; } |
136 | static inline int do_eqbs(u64 token, unsigned char *state, int queue, | 136 | static inline int do_eqbs(u64 token, unsigned char *state, int queue, |
137 | int *start, int *count) { return 0; } | 137 | int *start, int *count, int ack) { return 0; } |
138 | #endif /* CONFIG_64BIT */ | 138 | #endif /* CONFIG_64BIT */ |
139 | 139 | ||
140 | struct qdio_irq; | 140 | struct qdio_irq; |
@@ -187,11 +187,11 @@ struct qdio_input_q { | |||
187 | /* input buffer acknowledgement flag */ | 187 | /* input buffer acknowledgement flag */ |
188 | int polling; | 188 | int polling; |
189 | 189 | ||
190 | /* how much sbals are acknowledged with qebsm */ | ||
191 | int ack_count; | ||
192 | |||
190 | /* last time of noticing incoming data */ | 193 | /* last time of noticing incoming data */ |
191 | u64 timestamp; | 194 | u64 timestamp; |
192 | |||
193 | /* lock for clearing the acknowledgement */ | ||
194 | spinlock_t lock; | ||
195 | }; | 195 | }; |
196 | 196 | ||
197 | struct qdio_output_q { | 197 | struct qdio_output_q { |
@@ -351,10 +351,13 @@ static inline unsigned long long get_usecs(void) | |||
351 | ((bufnr + 1) & QDIO_MAX_BUFFERS_MASK) | 351 | ((bufnr + 1) & QDIO_MAX_BUFFERS_MASK) |
352 | #define add_buf(bufnr, inc) \ | 352 | #define add_buf(bufnr, inc) \ |
353 | ((bufnr + inc) & QDIO_MAX_BUFFERS_MASK) | 353 | ((bufnr + inc) & QDIO_MAX_BUFFERS_MASK) |
354 | #define sub_buf(bufnr, dec) \ | ||
355 | ((bufnr - dec) & QDIO_MAX_BUFFERS_MASK) | ||
354 | 356 | ||
355 | /* prototypes for thin interrupt */ | 357 | /* prototypes for thin interrupt */ |
356 | void qdio_sync_after_thinint(struct qdio_q *q); | 358 | void qdio_sync_after_thinint(struct qdio_q *q); |
357 | int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state); | 359 | int get_buf_state(struct qdio_q *q, unsigned int bufnr, unsigned char *state, |
360 | int auto_ack); | ||
358 | void qdio_check_outbound_after_thinint(struct qdio_q *q); | 361 | void qdio_check_outbound_after_thinint(struct qdio_q *q); |
359 | int qdio_inbound_q_moved(struct qdio_q *q); | 362 | int qdio_inbound_q_moved(struct qdio_q *q); |
360 | void qdio_kick_inbound_handler(struct qdio_q *q); | 363 | void qdio_kick_inbound_handler(struct qdio_q *q); |
@@ -388,6 +391,8 @@ int qdio_setup_irq(struct qdio_initialize *init_data); | |||
388 | void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, | 391 | void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, |
389 | struct ccw_device *cdev); | 392 | struct ccw_device *cdev); |
390 | void qdio_release_memory(struct qdio_irq *irq_ptr); | 393 | void qdio_release_memory(struct qdio_irq *irq_ptr); |
394 | int qdio_setup_create_sysfs(struct ccw_device *cdev); | ||
395 | void qdio_setup_destroy_sysfs(struct ccw_device *cdev); | ||
391 | int qdio_setup_init(void); | 396 | int qdio_setup_init(void); |
392 | void qdio_setup_exit(void); | 397 | void qdio_setup_exit(void); |
393 | 398 | ||