diff options
Diffstat (limited to 'drivers/s390/cio/qdio_main.c')
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 648 |
1 files changed, 266 insertions, 382 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 7c8659151993..744f928a59ea 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -74,7 +74,7 @@ static inline int do_siga_input(struct subchannel_id schid, unsigned int mask) | |||
74 | * Note: For IQDC unicast queues only the highest priority queue is processed. | 74 | * Note: For IQDC unicast queues only the highest priority queue is processed. |
75 | */ | 75 | */ |
76 | static inline int do_siga_output(unsigned long schid, unsigned long mask, | 76 | static inline int do_siga_output(unsigned long schid, unsigned long mask, |
77 | u32 *bb, unsigned int fc) | 77 | unsigned int *bb, unsigned int fc) |
78 | { | 78 | { |
79 | register unsigned long __fc asm("0") = fc; | 79 | register unsigned long __fc asm("0") = fc; |
80 | register unsigned long __schid asm("1") = schid; | 80 | register unsigned long __schid asm("1") = schid; |
@@ -95,8 +95,6 @@ static inline int do_siga_output(unsigned long schid, unsigned long mask, | |||
95 | 95 | ||
96 | static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | 96 | static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) |
97 | { | 97 | { |
98 | char dbf_text[15]; | ||
99 | |||
100 | /* all done or next buffer state different */ | 98 | /* all done or next buffer state different */ |
101 | if (ccq == 0 || ccq == 32) | 99 | if (ccq == 0 || ccq == 32) |
102 | return 0; | 100 | return 0; |
@@ -104,8 +102,7 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | |||
104 | if (ccq == 96 || ccq == 97) | 102 | if (ccq == 96 || ccq == 97) |
105 | return 1; | 103 | return 1; |
106 | /* notify devices immediately */ | 104 | /* notify devices immediately */ |
107 | sprintf(dbf_text, "%d", ccq); | 105 | DBF_ERROR("%4x ccq:%3d", SCH_NO(q), ccq); |
108 | QDIO_DBF_TEXT2(1, trace, dbf_text); | ||
109 | return -EIO; | 106 | return -EIO; |
110 | } | 107 | } |
111 | 108 | ||
@@ -115,41 +112,45 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | |||
115 | * @state: state of the extracted buffers | 112 | * @state: state of the extracted buffers |
116 | * @start: buffer number to start at | 113 | * @start: buffer number to start at |
117 | * @count: count of buffers to examine | 114 | * @count: count of buffers to examine |
115 | * @auto_ack: automatically acknowledge buffers | ||
118 | * | 116 | * |
119 | * Returns the number of successfull extracted equal buffer states. | 117 | * Returns the number of successfull extracted equal buffer states. |
120 | * Stops processing if a state is different from the last buffers state. | 118 | * Stops processing if a state is different from the last buffers state. |
121 | */ | 119 | */ |
122 | static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | 120 | static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, |
123 | int start, int count) | 121 | int start, int count, int auto_ack) |
124 | { | 122 | { |
125 | unsigned int ccq = 0; | 123 | unsigned int ccq = 0; |
126 | int tmp_count = count, tmp_start = start; | 124 | int tmp_count = count, tmp_start = start; |
127 | int nr = q->nr; | 125 | int nr = q->nr; |
128 | int rc; | 126 | int rc; |
129 | char dbf_text[15]; | ||
130 | 127 | ||
131 | BUG_ON(!q->irq_ptr->sch_token); | 128 | BUG_ON(!q->irq_ptr->sch_token); |
129 | qdio_perf_stat_inc(&perf_stats.debug_eqbs_all); | ||
132 | 130 | ||
133 | if (!q->is_input_q) | 131 | if (!q->is_input_q) |
134 | nr += q->irq_ptr->nr_input_qs; | 132 | nr += q->irq_ptr->nr_input_qs; |
135 | again: | 133 | again: |
136 | ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count); | 134 | ccq = do_eqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count, |
135 | auto_ack); | ||
137 | rc = qdio_check_ccq(q, ccq); | 136 | rc = qdio_check_ccq(q, ccq); |
138 | 137 | ||
139 | /* At least one buffer was processed, return and extract the remaining | 138 | /* At least one buffer was processed, return and extract the remaining |
140 | * buffers later. | 139 | * buffers later. |
141 | */ | 140 | */ |
142 | if ((ccq == 96) && (count != tmp_count)) | 141 | if ((ccq == 96) && (count != tmp_count)) { |
142 | qdio_perf_stat_inc(&perf_stats.debug_eqbs_incomplete); | ||
143 | return (count - tmp_count); | 143 | return (count - tmp_count); |
144 | } | ||
145 | |||
144 | if (rc == 1) { | 146 | if (rc == 1) { |
145 | QDIO_DBF_TEXT5(1, trace, "eqAGAIN"); | 147 | DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS again:%2d", ccq); |
146 | goto again; | 148 | goto again; |
147 | } | 149 | } |
148 | 150 | ||
149 | if (rc < 0) { | 151 | if (rc < 0) { |
150 | QDIO_DBF_TEXT2(1, trace, "eqberr"); | 152 | DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); |
151 | sprintf(dbf_text, "%2x,%2x,%d,%d", count, tmp_count, ccq, nr); | 153 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); |
152 | QDIO_DBF_TEXT2(1, trace, dbf_text); | ||
153 | q->handler(q->irq_ptr->cdev, | 154 | q->handler(q->irq_ptr->cdev, |
154 | QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 155 | QDIO_ERROR_ACTIVATE_CHECK_CONDITION, |
155 | 0, -1, -1, q->irq_ptr->int_parm); | 156 | 0, -1, -1, q->irq_ptr->int_parm); |
@@ -176,9 +177,12 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start, | |||
176 | int tmp_count = count, tmp_start = start; | 177 | int tmp_count = count, tmp_start = start; |
177 | int nr = q->nr; | 178 | int nr = q->nr; |
178 | int rc; | 179 | int rc; |
179 | char dbf_text[15]; | 180 | |
181 | if (!count) | ||
182 | return 0; | ||
180 | 183 | ||
181 | BUG_ON(!q->irq_ptr->sch_token); | 184 | BUG_ON(!q->irq_ptr->sch_token); |
185 | qdio_perf_stat_inc(&perf_stats.debug_sqbs_all); | ||
182 | 186 | ||
183 | if (!q->is_input_q) | 187 | if (!q->is_input_q) |
184 | nr += q->irq_ptr->nr_input_qs; | 188 | nr += q->irq_ptr->nr_input_qs; |
@@ -186,16 +190,13 @@ again: | |||
186 | ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count); | 190 | ccq = do_sqbs(q->irq_ptr->sch_token, state, nr, &tmp_start, &tmp_count); |
187 | rc = qdio_check_ccq(q, ccq); | 191 | rc = qdio_check_ccq(q, ccq); |
188 | if (rc == 1) { | 192 | if (rc == 1) { |
189 | QDIO_DBF_TEXT5(1, trace, "sqAGAIN"); | 193 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "SQBS again:%2d", ccq); |
194 | qdio_perf_stat_inc(&perf_stats.debug_sqbs_incomplete); | ||
190 | goto again; | 195 | goto again; |
191 | } | 196 | } |
192 | if (rc < 0) { | 197 | if (rc < 0) { |
193 | QDIO_DBF_TEXT3(1, trace, "sqberr"); | 198 | DBF_ERROR("%4x SQBS ERROR", SCH_NO(q)); |
194 | sprintf(dbf_text, "%2x,%2x", count, tmp_count); | 199 | DBF_ERROR("%3d%3d%2d", count, tmp_count, nr); |
195 | QDIO_DBF_TEXT3(1, trace, dbf_text); | ||
196 | sprintf(dbf_text, "%d,%d", ccq, nr); | ||
197 | QDIO_DBF_TEXT3(1, trace, dbf_text); | ||
198 | |||
199 | q->handler(q->irq_ptr->cdev, | 200 | q->handler(q->irq_ptr->cdev, |
200 | QDIO_ERROR_ACTIVATE_CHECK_CONDITION, | 201 | QDIO_ERROR_ACTIVATE_CHECK_CONDITION, |
201 | 0, -1, -1, q->irq_ptr->int_parm); | 202 | 0, -1, -1, q->irq_ptr->int_parm); |
@@ -207,7 +208,8 @@ again: | |||
207 | 208 | ||
208 | /* returns number of examined buffers and their common state in *state */ | 209 | /* returns number of examined buffers and their common state in *state */ |
209 | static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, | 210 | static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, |
210 | unsigned char *state, unsigned int count) | 211 | unsigned char *state, unsigned int count, |
212 | int auto_ack) | ||
211 | { | 213 | { |
212 | unsigned char __state = 0; | 214 | unsigned char __state = 0; |
213 | int i; | 215 | int i; |
@@ -216,7 +218,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, | |||
216 | BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q); | 218 | BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q); |
217 | 219 | ||
218 | if (is_qebsm(q)) | 220 | if (is_qebsm(q)) |
219 | return qdio_do_eqbs(q, state, bufnr, count); | 221 | return qdio_do_eqbs(q, state, bufnr, count, auto_ack); |
220 | 222 | ||
221 | for (i = 0; i < count; i++) { | 223 | for (i = 0; i < count; i++) { |
222 | if (!__state) | 224 | if (!__state) |
@@ -230,9 +232,9 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, | |||
230 | } | 232 | } |
231 | 233 | ||
232 | inline int get_buf_state(struct qdio_q *q, unsigned int bufnr, | 234 | inline int get_buf_state(struct qdio_q *q, unsigned int bufnr, |
233 | unsigned char *state) | 235 | unsigned char *state, int auto_ack) |
234 | { | 236 | { |
235 | return get_buf_states(q, bufnr, state, 1); | 237 | return get_buf_states(q, bufnr, state, 1, auto_ack); |
236 | } | 238 | } |
237 | 239 | ||
238 | /* wrap-around safe setting of slsb states, returns number of changed buffers */ | 240 | /* wrap-around safe setting of slsb states, returns number of changed buffers */ |
@@ -282,14 +284,12 @@ static int qdio_siga_sync(struct qdio_q *q, unsigned int output, | |||
282 | if (!need_siga_sync(q)) | 284 | if (!need_siga_sync(q)) |
283 | return 0; | 285 | return 0; |
284 | 286 | ||
287 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-s:%1d", q->nr); | ||
285 | qdio_perf_stat_inc(&perf_stats.siga_sync); | 288 | qdio_perf_stat_inc(&perf_stats.siga_sync); |
286 | 289 | ||
287 | cc = do_siga_sync(q->irq_ptr->schid, output, input); | 290 | cc = do_siga_sync(q->irq_ptr->schid, output, input); |
288 | if (cc) { | 291 | if (cc) |
289 | QDIO_DBF_TEXT4(0, trace, "sigasync"); | 292 | DBF_ERROR("%4x SIGA-S:%2d", SCH_NO(q), cc); |
290 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
291 | QDIO_DBF_HEX3(0, trace, &cc, sizeof(int *)); | ||
292 | } | ||
293 | return cc; | 293 | return cc; |
294 | } | 294 | } |
295 | 295 | ||
@@ -311,50 +311,37 @@ static inline int qdio_siga_sync_all(struct qdio_q *q) | |||
311 | return qdio_siga_sync(q, ~0U, ~0U); | 311 | return qdio_siga_sync(q, ~0U, ~0U); |
312 | } | 312 | } |
313 | 313 | ||
314 | static inline int qdio_do_siga_output(struct qdio_q *q, unsigned int *busy_bit) | 314 | static int qdio_siga_output(struct qdio_q *q, unsigned int *busy_bit) |
315 | { | 315 | { |
316 | unsigned int fc = 0; | ||
317 | unsigned long schid; | 316 | unsigned long schid; |
317 | unsigned int fc = 0; | ||
318 | u64 start_time = 0; | ||
319 | int cc; | ||
318 | 320 | ||
319 | if (q->u.out.use_enh_siga) { | 321 | if (q->u.out.use_enh_siga) |
320 | fc = 3; | 322 | fc = 3; |
321 | } | 323 | |
322 | if (!is_qebsm(q)) | 324 | if (is_qebsm(q)) { |
323 | schid = *((u32 *)&q->irq_ptr->schid); | ||
324 | else { | ||
325 | schid = q->irq_ptr->sch_token; | 325 | schid = q->irq_ptr->sch_token; |
326 | fc |= 0x80; | 326 | fc |= 0x80; |
327 | } | 327 | } |
328 | return do_siga_output(schid, q->mask, busy_bit, fc); | 328 | else |
329 | } | 329 | schid = *((u32 *)&q->irq_ptr->schid); |
330 | |||
331 | static int qdio_siga_output(struct qdio_q *q) | ||
332 | { | ||
333 | int cc; | ||
334 | u32 busy_bit; | ||
335 | u64 start_time = 0; | ||
336 | char dbf_text[15]; | ||
337 | |||
338 | QDIO_DBF_TEXT5(0, trace, "sigaout"); | ||
339 | QDIO_DBF_HEX5(0, trace, &q, sizeof(void *)); | ||
340 | 330 | ||
341 | qdio_perf_stat_inc(&perf_stats.siga_out); | ||
342 | again: | 331 | again: |
343 | cc = qdio_do_siga_output(q, &busy_bit); | 332 | cc = do_siga_output(schid, q->mask, busy_bit, fc); |
344 | if (queue_type(q) == QDIO_IQDIO_QFMT && cc == 2 && busy_bit) { | ||
345 | sprintf(dbf_text, "bb%4x%2x", q->irq_ptr->schid.sch_no, q->nr); | ||
346 | QDIO_DBF_TEXT3(0, trace, dbf_text); | ||
347 | 333 | ||
348 | if (!start_time) | 334 | /* hipersocket busy condition */ |
335 | if (*busy_bit) { | ||
336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); | ||
337 | |||
338 | if (!start_time) { | ||
349 | start_time = get_usecs(); | 339 | start_time = get_usecs(); |
350 | else if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) | 340 | goto again; |
341 | } | ||
342 | if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) | ||
351 | goto again; | 343 | goto again; |
352 | } | 344 | } |
353 | |||
354 | if (cc == 2 && busy_bit) | ||
355 | cc |= QDIO_ERROR_SIGA_BUSY; | ||
356 | if (cc) | ||
357 | QDIO_DBF_HEX3(0, trace, &cc, sizeof(int *)); | ||
358 | return cc; | 345 | return cc; |
359 | } | 346 | } |
360 | 347 | ||
@@ -362,14 +349,12 @@ static inline int qdio_siga_input(struct qdio_q *q) | |||
362 | { | 349 | { |
363 | int cc; | 350 | int cc; |
364 | 351 | ||
365 | QDIO_DBF_TEXT4(0, trace, "sigain"); | 352 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-r:%1d", q->nr); |
366 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
367 | |||
368 | qdio_perf_stat_inc(&perf_stats.siga_in); | 353 | qdio_perf_stat_inc(&perf_stats.siga_in); |
369 | 354 | ||
370 | cc = do_siga_input(q->irq_ptr->schid, q->mask); | 355 | cc = do_siga_input(q->irq_ptr->schid, q->mask); |
371 | if (cc) | 356 | if (cc) |
372 | QDIO_DBF_HEX3(0, trace, &cc, sizeof(int *)); | 357 | DBF_ERROR("%4x SIGA-R:%2d", SCH_NO(q), cc); |
373 | return cc; | 358 | return cc; |
374 | } | 359 | } |
375 | 360 | ||
@@ -387,35 +372,91 @@ void qdio_sync_after_thinint(struct qdio_q *q) | |||
387 | 372 | ||
388 | inline void qdio_stop_polling(struct qdio_q *q) | 373 | inline void qdio_stop_polling(struct qdio_q *q) |
389 | { | 374 | { |
390 | spin_lock_bh(&q->u.in.lock); | 375 | if (!q->u.in.polling) |
391 | if (!q->u.in.polling) { | ||
392 | spin_unlock_bh(&q->u.in.lock); | ||
393 | return; | 376 | return; |
394 | } | 377 | |
395 | q->u.in.polling = 0; | 378 | q->u.in.polling = 0; |
396 | qdio_perf_stat_inc(&perf_stats.debug_stop_polling); | 379 | qdio_perf_stat_inc(&perf_stats.debug_stop_polling); |
397 | 380 | ||
398 | /* show the card that we are not polling anymore */ | 381 | /* show the card that we are not polling anymore */ |
399 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | 382 | if (is_qebsm(q)) { |
400 | spin_unlock_bh(&q->u.in.lock); | 383 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, |
384 | q->u.in.ack_count); | ||
385 | q->u.in.ack_count = 0; | ||
386 | } else | ||
387 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | ||
401 | } | 388 | } |
402 | 389 | ||
403 | static void announce_buffer_error(struct qdio_q *q) | 390 | static void announce_buffer_error(struct qdio_q *q, int count) |
404 | { | 391 | { |
405 | char dbf_text[15]; | 392 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; |
393 | |||
394 | /* special handling for no target buffer empty */ | ||
395 | if ((!q->is_input_q && | ||
396 | (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { | ||
397 | qdio_perf_stat_inc(&perf_stats.outbound_target_full); | ||
398 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%3d", | ||
399 | q->first_to_check); | ||
400 | return; | ||
401 | } | ||
406 | 402 | ||
407 | if (q->is_input_q) | 403 | DBF_ERROR("%4x BUF ERROR", SCH_NO(q)); |
408 | QDIO_DBF_TEXT3(1, trace, "inperr"); | 404 | DBF_ERROR((q->is_input_q) ? "IN:%2d" : "OUT:%2d", q->nr); |
409 | else | 405 | DBF_ERROR("FTC:%3d C:%3d", q->first_to_check, count); |
410 | QDIO_DBF_TEXT3(0, trace, "outperr"); | 406 | DBF_ERROR("F14:%2x F15:%2x", |
407 | q->sbal[q->first_to_check]->element[14].flags & 0xff, | ||
408 | q->sbal[q->first_to_check]->element[15].flags & 0xff); | ||
409 | } | ||
410 | |||
411 | static inline void inbound_primed(struct qdio_q *q, int count) | ||
412 | { | ||
413 | int new; | ||
414 | |||
415 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %3d", count); | ||
416 | |||
417 | /* for QEBSM the ACK was already set by EQBS */ | ||
418 | if (is_qebsm(q)) { | ||
419 | if (!q->u.in.polling) { | ||
420 | q->u.in.polling = 1; | ||
421 | q->u.in.ack_count = count; | ||
422 | q->last_move_ftc = q->first_to_check; | ||
423 | return; | ||
424 | } | ||
425 | |||
426 | /* delete the previous ACK's */ | ||
427 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, | ||
428 | q->u.in.ack_count); | ||
429 | q->u.in.ack_count = count; | ||
430 | q->last_move_ftc = q->first_to_check; | ||
431 | return; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * ACK the newest buffer. The ACK will be removed in qdio_stop_polling | ||
436 | * or by the next inbound run. | ||
437 | */ | ||
438 | new = add_buf(q->first_to_check, count - 1); | ||
439 | if (q->u.in.polling) { | ||
440 | /* reset the previous ACK but first set the new one */ | ||
441 | set_buf_state(q, new, SLSB_P_INPUT_ACK); | ||
442 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | ||
443 | } | ||
444 | else { | ||
445 | q->u.in.polling = 1; | ||
446 | set_buf_state(q, q->first_to_check, SLSB_P_INPUT_ACK); | ||
447 | } | ||
411 | 448 | ||
412 | sprintf(dbf_text, "%x-%x-%x", q->first_to_check, | 449 | q->last_move_ftc = new; |
413 | q->sbal[q->first_to_check]->element[14].flags, | 450 | count--; |
414 | q->sbal[q->first_to_check]->element[15].flags); | 451 | if (!count) |
415 | QDIO_DBF_TEXT3(1, trace, dbf_text); | 452 | return; |
416 | QDIO_DBF_HEX2(1, trace, q->sbal[q->first_to_check], 256); | ||
417 | 453 | ||
418 | q->qdio_error = QDIO_ERROR_SLSB_STATE; | 454 | /* |
455 | * Need to change all PRIMED buffers to NOT_INIT, otherwise | ||
456 | * we're loosing initiative in the thinint code. | ||
457 | */ | ||
458 | set_buf_states(q, next_buf(q->first_to_check), SLSB_P_INPUT_NOT_INIT, | ||
459 | count); | ||
419 | } | 460 | } |
420 | 461 | ||
421 | static int get_inbound_buffer_frontier(struct qdio_q *q) | 462 | static int get_inbound_buffer_frontier(struct qdio_q *q) |
@@ -424,13 +465,6 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
424 | unsigned char state; | 465 | unsigned char state; |
425 | 466 | ||
426 | /* | 467 | /* |
427 | * If we still poll don't update last_move_ftc, keep the | ||
428 | * previously ACK buffer there. | ||
429 | */ | ||
430 | if (!q->u.in.polling) | ||
431 | q->last_move_ftc = q->first_to_check; | ||
432 | |||
433 | /* | ||
434 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 468 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
435 | * would return 0. | 469 | * would return 0. |
436 | */ | 470 | */ |
@@ -450,34 +484,13 @@ check_next: | |||
450 | if (q->first_to_check == stop) | 484 | if (q->first_to_check == stop) |
451 | goto out; | 485 | goto out; |
452 | 486 | ||
453 | count = get_buf_states(q, q->first_to_check, &state, count); | 487 | count = get_buf_states(q, q->first_to_check, &state, count, 1); |
454 | if (!count) | 488 | if (!count) |
455 | goto out; | 489 | goto out; |
456 | 490 | ||
457 | switch (state) { | 491 | switch (state) { |
458 | case SLSB_P_INPUT_PRIMED: | 492 | case SLSB_P_INPUT_PRIMED: |
459 | QDIO_DBF_TEXT5(0, trace, "inptprim"); | 493 | inbound_primed(q, count); |
460 | |||
461 | /* | ||
462 | * Only ACK the first buffer. The ACK will be removed in | ||
463 | * qdio_stop_polling. | ||
464 | */ | ||
465 | if (q->u.in.polling) | ||
466 | state = SLSB_P_INPUT_NOT_INIT; | ||
467 | else { | ||
468 | q->u.in.polling = 1; | ||
469 | state = SLSB_P_INPUT_ACK; | ||
470 | } | ||
471 | set_buf_state(q, q->first_to_check, state); | ||
472 | |||
473 | /* | ||
474 | * Need to change all PRIMED buffers to NOT_INIT, otherwise | ||
475 | * we're loosing initiative in the thinint code. | ||
476 | */ | ||
477 | if (count > 1) | ||
478 | set_buf_states(q, next_buf(q->first_to_check), | ||
479 | SLSB_P_INPUT_NOT_INIT, count - 1); | ||
480 | |||
481 | /* | 494 | /* |
482 | * No siga-sync needed for non-qebsm here, as the inbound queue | 495 | * No siga-sync needed for non-qebsm here, as the inbound queue |
483 | * will be synced on the next siga-r, resp. | 496 | * will be synced on the next siga-r, resp. |
@@ -487,7 +500,7 @@ check_next: | |||
487 | atomic_sub(count, &q->nr_buf_used); | 500 | atomic_sub(count, &q->nr_buf_used); |
488 | goto check_next; | 501 | goto check_next; |
489 | case SLSB_P_INPUT_ERROR: | 502 | case SLSB_P_INPUT_ERROR: |
490 | announce_buffer_error(q); | 503 | announce_buffer_error(q, count); |
491 | /* process the buffer, the upper layer will take care of it */ | 504 | /* process the buffer, the upper layer will take care of it */ |
492 | q->first_to_check = add_buf(q->first_to_check, count); | 505 | q->first_to_check = add_buf(q->first_to_check, count); |
493 | atomic_sub(count, &q->nr_buf_used); | 506 | atomic_sub(count, &q->nr_buf_used); |
@@ -495,13 +508,12 @@ check_next: | |||
495 | case SLSB_CU_INPUT_EMPTY: | 508 | case SLSB_CU_INPUT_EMPTY: |
496 | case SLSB_P_INPUT_NOT_INIT: | 509 | case SLSB_P_INPUT_NOT_INIT: |
497 | case SLSB_P_INPUT_ACK: | 510 | case SLSB_P_INPUT_ACK: |
498 | QDIO_DBF_TEXT5(0, trace, "inpnipro"); | 511 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in nop"); |
499 | break; | 512 | break; |
500 | default: | 513 | default: |
501 | BUG(); | 514 | BUG(); |
502 | } | 515 | } |
503 | out: | 516 | out: |
504 | QDIO_DBF_HEX4(0, trace, &q->first_to_check, sizeof(int)); | ||
505 | return q->first_to_check; | 517 | return q->first_to_check; |
506 | } | 518 | } |
507 | 519 | ||
@@ -515,8 +527,7 @@ int qdio_inbound_q_moved(struct qdio_q *q) | |||
515 | if (!need_siga_sync(q) && !pci_out_supported(q)) | 527 | if (!need_siga_sync(q) && !pci_out_supported(q)) |
516 | q->u.in.timestamp = get_usecs(); | 528 | q->u.in.timestamp = get_usecs(); |
517 | 529 | ||
518 | QDIO_DBF_TEXT4(0, trace, "inhasmvd"); | 530 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in moved"); |
519 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
520 | return 1; | 531 | return 1; |
521 | } else | 532 | } else |
522 | return 0; | 533 | return 0; |
@@ -524,10 +535,7 @@ int qdio_inbound_q_moved(struct qdio_q *q) | |||
524 | 535 | ||
525 | static int qdio_inbound_q_done(struct qdio_q *q) | 536 | static int qdio_inbound_q_done(struct qdio_q *q) |
526 | { | 537 | { |
527 | unsigned char state; | 538 | unsigned char state = 0; |
528 | #ifdef CONFIG_QDIO_DEBUG | ||
529 | char dbf_text[15]; | ||
530 | #endif | ||
531 | 539 | ||
532 | if (!atomic_read(&q->nr_buf_used)) | 540 | if (!atomic_read(&q->nr_buf_used)) |
533 | return 1; | 541 | return 1; |
@@ -538,7 +546,7 @@ static int qdio_inbound_q_done(struct qdio_q *q) | |||
538 | */ | 546 | */ |
539 | qdio_siga_sync_q(q); | 547 | qdio_siga_sync_q(q); |
540 | 548 | ||
541 | get_buf_state(q, q->first_to_check, &state); | 549 | get_buf_state(q, q->first_to_check, &state, 0); |
542 | if (state == SLSB_P_INPUT_PRIMED) | 550 | if (state == SLSB_P_INPUT_PRIMED) |
543 | /* we got something to do */ | 551 | /* we got something to do */ |
544 | return 0; | 552 | return 0; |
@@ -552,20 +560,12 @@ static int qdio_inbound_q_done(struct qdio_q *q) | |||
552 | * has (probably) not moved (see qdio_inbound_processing). | 560 | * has (probably) not moved (see qdio_inbound_processing). |
553 | */ | 561 | */ |
554 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | 562 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { |
555 | #ifdef CONFIG_QDIO_DEBUG | 563 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%3d", |
556 | QDIO_DBF_TEXT4(0, trace, "inqisdon"); | 564 | q->first_to_check); |
557 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
558 | sprintf(dbf_text, "pf%02x", q->first_to_check); | ||
559 | QDIO_DBF_TEXT4(0, trace, dbf_text); | ||
560 | #endif /* CONFIG_QDIO_DEBUG */ | ||
561 | return 1; | 565 | return 1; |
562 | } else { | 566 | } else { |
563 | #ifdef CONFIG_QDIO_DEBUG | 567 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in notd:%3d", |
564 | QDIO_DBF_TEXT4(0, trace, "inqisntd"); | 568 | q->first_to_check); |
565 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
566 | sprintf(dbf_text, "pf%02x", q->first_to_check); | ||
567 | QDIO_DBF_TEXT4(0, trace, dbf_text); | ||
568 | #endif /* CONFIG_QDIO_DEBUG */ | ||
569 | return 0; | 569 | return 0; |
570 | } | 570 | } |
571 | } | 571 | } |
@@ -573,9 +573,6 @@ static int qdio_inbound_q_done(struct qdio_q *q) | |||
573 | void qdio_kick_inbound_handler(struct qdio_q *q) | 573 | void qdio_kick_inbound_handler(struct qdio_q *q) |
574 | { | 574 | { |
575 | int count, start, end; | 575 | int count, start, end; |
576 | #ifdef CONFIG_QDIO_DEBUG | ||
577 | char dbf_text[15]; | ||
578 | #endif | ||
579 | 576 | ||
580 | qdio_perf_stat_inc(&perf_stats.inbound_handler); | 577 | qdio_perf_stat_inc(&perf_stats.inbound_handler); |
581 | 578 | ||
@@ -586,10 +583,7 @@ void qdio_kick_inbound_handler(struct qdio_q *q) | |||
586 | else | 583 | else |
587 | count = end + QDIO_MAX_BUFFERS_PER_Q - start; | 584 | count = end + QDIO_MAX_BUFFERS_PER_Q - start; |
588 | 585 | ||
589 | #ifdef CONFIG_QDIO_DEBUG | 586 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); |
590 | sprintf(dbf_text, "s=%2xc=%2x", start, count); | ||
591 | QDIO_DBF_TEXT4(0, trace, dbf_text); | ||
592 | #endif /* CONFIG_QDIO_DEBUG */ | ||
593 | 587 | ||
594 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) | 588 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) |
595 | return; | 589 | return; |
@@ -655,14 +649,14 @@ check_next: | |||
655 | if (q->first_to_check == stop) | 649 | if (q->first_to_check == stop) |
656 | return q->first_to_check; | 650 | return q->first_to_check; |
657 | 651 | ||
658 | count = get_buf_states(q, q->first_to_check, &state, count); | 652 | count = get_buf_states(q, q->first_to_check, &state, count, 0); |
659 | if (!count) | 653 | if (!count) |
660 | return q->first_to_check; | 654 | return q->first_to_check; |
661 | 655 | ||
662 | switch (state) { | 656 | switch (state) { |
663 | case SLSB_P_OUTPUT_EMPTY: | 657 | case SLSB_P_OUTPUT_EMPTY: |
664 | /* the adapter got it */ | 658 | /* the adapter got it */ |
665 | QDIO_DBF_TEXT5(0, trace, "outpempt"); | 659 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %3d", q->nr, count); |
666 | 660 | ||
667 | atomic_sub(count, &q->nr_buf_used); | 661 | atomic_sub(count, &q->nr_buf_used); |
668 | q->first_to_check = add_buf(q->first_to_check, count); | 662 | q->first_to_check = add_buf(q->first_to_check, count); |
@@ -674,14 +668,14 @@ check_next: | |||
674 | break; | 668 | break; |
675 | goto check_next; | 669 | goto check_next; |
676 | case SLSB_P_OUTPUT_ERROR: | 670 | case SLSB_P_OUTPUT_ERROR: |
677 | announce_buffer_error(q); | 671 | announce_buffer_error(q, count); |
678 | /* process the buffer, the upper layer will take care of it */ | 672 | /* process the buffer, the upper layer will take care of it */ |
679 | q->first_to_check = add_buf(q->first_to_check, count); | 673 | q->first_to_check = add_buf(q->first_to_check, count); |
680 | atomic_sub(count, &q->nr_buf_used); | 674 | atomic_sub(count, &q->nr_buf_used); |
681 | break; | 675 | break; |
682 | case SLSB_CU_OUTPUT_PRIMED: | 676 | case SLSB_CU_OUTPUT_PRIMED: |
683 | /* the adapter has not fetched the output yet */ | 677 | /* the adapter has not fetched the output yet */ |
684 | QDIO_DBF_TEXT5(0, trace, "outpprim"); | 678 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out primed:%1d", q->nr); |
685 | break; | 679 | break; |
686 | case SLSB_P_OUTPUT_NOT_INIT: | 680 | case SLSB_P_OUTPUT_NOT_INIT: |
687 | case SLSB_P_OUTPUT_HALTED: | 681 | case SLSB_P_OUTPUT_HALTED: |
@@ -706,99 +700,48 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q) | |||
706 | 700 | ||
707 | if ((bufnr != q->last_move_ftc) || q->qdio_error) { | 701 | if ((bufnr != q->last_move_ftc) || q->qdio_error) { |
708 | q->last_move_ftc = bufnr; | 702 | q->last_move_ftc = bufnr; |
709 | QDIO_DBF_TEXT4(0, trace, "oqhasmvd"); | 703 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); |
710 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
711 | return 1; | 704 | return 1; |
712 | } else | 705 | } else |
713 | return 0; | 706 | return 0; |
714 | } | 707 | } |
715 | 708 | ||
716 | /* | ||
717 | * VM could present us cc=2 and busy bit set on SIGA-write | ||
718 | * during reconfiguration of their Guest LAN (only in iqdio mode, | ||
719 | * otherwise qdio is asynchronous and cc=2 and busy bit there will take | ||
720 | * the queues down immediately). | ||
721 | * | ||
722 | * Therefore qdio_siga_output will try for a short time constantly, | ||
723 | * if such a condition occurs. If it doesn't change, it will | ||
724 | * increase the busy_siga_counter and save the timestamp, and | ||
725 | * schedule the queue for later processing. qdio_outbound_processing | ||
726 | * will check out the counter. If non-zero, it will call qdio_kick_outbound_q | ||
727 | * as often as the value of the counter. This will attempt further SIGA | ||
728 | * instructions. For each successful SIGA, the counter is | ||
729 | * decreased, for failing SIGAs the counter remains the same, after | ||
730 | * all. After some time of no movement, qdio_kick_outbound_q will | ||
731 | * finally fail and reflect corresponding error codes to call | ||
732 | * the upper layer module and have it take the queues down. | ||
733 | * | ||
734 | * Note that this is a change from the original HiperSockets design | ||
735 | * (saying cc=2 and busy bit means take the queues down), but in | ||
736 | * these days Guest LAN didn't exist... excessive cc=2 with busy bit | ||
737 | * conditions will still take the queues down, but the threshold is | ||
738 | * higher due to the Guest LAN environment. | ||
739 | * | ||
740 | * Called from outbound tasklet and do_QDIO handler. | ||
741 | */ | ||
742 | static void qdio_kick_outbound_q(struct qdio_q *q) | 709 | static void qdio_kick_outbound_q(struct qdio_q *q) |
743 | { | 710 | { |
744 | int rc; | 711 | unsigned int busy_bit; |
745 | #ifdef CONFIG_QDIO_DEBUG | 712 | int cc; |
746 | char dbf_text[15]; | ||
747 | |||
748 | QDIO_DBF_TEXT5(0, trace, "kickoutq"); | ||
749 | QDIO_DBF_HEX5(0, trace, &q, sizeof(void *)); | ||
750 | #endif /* CONFIG_QDIO_DEBUG */ | ||
751 | 713 | ||
752 | if (!need_siga_out(q)) | 714 | if (!need_siga_out(q)) |
753 | return; | 715 | return; |
754 | 716 | ||
755 | rc = qdio_siga_output(q); | 717 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w:%1d", q->nr); |
756 | switch (rc) { | 718 | qdio_perf_stat_inc(&perf_stats.siga_out); |
719 | |||
720 | cc = qdio_siga_output(q, &busy_bit); | ||
721 | switch (cc) { | ||
757 | case 0: | 722 | case 0: |
758 | /* TODO: improve error handling for CC=0 case */ | ||
759 | #ifdef CONFIG_QDIO_DEBUG | ||
760 | if (q->u.out.timestamp) { | ||
761 | QDIO_DBF_TEXT3(0, trace, "cc2reslv"); | ||
762 | sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, | ||
763 | q->nr, | ||
764 | atomic_read(&q->u.out.busy_siga_counter)); | ||
765 | QDIO_DBF_TEXT3(0, trace, dbf_text); | ||
766 | } | ||
767 | #endif /* CONFIG_QDIO_DEBUG */ | ||
768 | /* went smooth this time, reset timestamp */ | ||
769 | q->u.out.timestamp = 0; | ||
770 | break; | 723 | break; |
771 | /* cc=2 and busy bit */ | 724 | case 2: |
772 | case (2 | QDIO_ERROR_SIGA_BUSY): | 725 | if (busy_bit) { |
773 | atomic_inc(&q->u.out.busy_siga_counter); | 726 | DBF_ERROR("%4x cc2 REP:%1d", SCH_NO(q), q->nr); |
774 | 727 | q->qdio_error = cc | QDIO_ERROR_SIGA_BUSY; | |
775 | /* if the last siga was successful, save timestamp here */ | 728 | } else { |
776 | if (!q->u.out.timestamp) | 729 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "siga-w cc2:%1d", |
777 | q->u.out.timestamp = get_usecs(); | 730 | q->nr); |
778 | 731 | q->qdio_error = cc; | |
779 | /* if we're in time, don't touch qdio_error */ | ||
780 | if (get_usecs() - q->u.out.timestamp < QDIO_BUSY_BIT_GIVE_UP) { | ||
781 | tasklet_schedule(&q->tasklet); | ||
782 | break; | ||
783 | } | 732 | } |
784 | QDIO_DBF_TEXT2(0, trace, "cc2REPRT"); | 733 | break; |
785 | #ifdef CONFIG_QDIO_DEBUG | 734 | case 1: |
786 | sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, q->nr, | 735 | case 3: |
787 | atomic_read(&q->u.out.busy_siga_counter)); | 736 | DBF_ERROR("%4x SIGA-W:%1d", SCH_NO(q), cc); |
788 | QDIO_DBF_TEXT3(0, trace, dbf_text); | 737 | q->qdio_error = cc; |
789 | #endif /* CONFIG_QDIO_DEBUG */ | 738 | break; |
790 | default: | ||
791 | /* for plain cc=1, 2 or 3 */ | ||
792 | q->qdio_error = rc; | ||
793 | } | 739 | } |
794 | } | 740 | } |
795 | 741 | ||
796 | static void qdio_kick_outbound_handler(struct qdio_q *q) | 742 | static void qdio_kick_outbound_handler(struct qdio_q *q) |
797 | { | 743 | { |
798 | int start, end, count; | 744 | int start, end, count; |
799 | #ifdef CONFIG_QDIO_DEBUG | ||
800 | char dbf_text[15]; | ||
801 | #endif | ||
802 | 745 | ||
803 | start = q->first_to_kick; | 746 | start = q->first_to_kick; |
804 | end = q->last_move_ftc; | 747 | end = q->last_move_ftc; |
@@ -807,13 +750,8 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) | |||
807 | else | 750 | else |
808 | count = end + QDIO_MAX_BUFFERS_PER_Q - start; | 751 | count = end + QDIO_MAX_BUFFERS_PER_Q - start; |
809 | 752 | ||
810 | #ifdef CONFIG_QDIO_DEBUG | 753 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kickouth: %1d", q->nr); |
811 | QDIO_DBF_TEXT4(0, trace, "kickouth"); | 754 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); |
812 | QDIO_DBF_HEX4(0, trace, &q, sizeof(void *)); | ||
813 | |||
814 | sprintf(dbf_text, "s=%2xc=%2x", start, count); | ||
815 | QDIO_DBF_TEXT4(0, trace, dbf_text); | ||
816 | #endif /* CONFIG_QDIO_DEBUG */ | ||
817 | 755 | ||
818 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) | 756 | if (unlikely(q->irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)) |
819 | return; | 757 | return; |
@@ -828,22 +766,18 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) | |||
828 | 766 | ||
829 | static void __qdio_outbound_processing(struct qdio_q *q) | 767 | static void __qdio_outbound_processing(struct qdio_q *q) |
830 | { | 768 | { |
831 | int siga_attempts; | 769 | unsigned long flags; |
832 | 770 | ||
833 | qdio_perf_stat_inc(&perf_stats.tasklet_outbound); | 771 | qdio_perf_stat_inc(&perf_stats.tasklet_outbound); |
834 | 772 | spin_lock_irqsave(&q->lock, flags); | |
835 | /* see comment in qdio_kick_outbound_q */ | ||
836 | siga_attempts = atomic_read(&q->u.out.busy_siga_counter); | ||
837 | while (siga_attempts--) { | ||
838 | atomic_dec(&q->u.out.busy_siga_counter); | ||
839 | qdio_kick_outbound_q(q); | ||
840 | } | ||
841 | 773 | ||
842 | BUG_ON(atomic_read(&q->nr_buf_used) < 0); | 774 | BUG_ON(atomic_read(&q->nr_buf_used) < 0); |
843 | 775 | ||
844 | if (qdio_outbound_q_moved(q)) | 776 | if (qdio_outbound_q_moved(q)) |
845 | qdio_kick_outbound_handler(q); | 777 | qdio_kick_outbound_handler(q); |
846 | 778 | ||
779 | spin_unlock_irqrestore(&q->lock, flags); | ||
780 | |||
847 | if (queue_type(q) == QDIO_ZFCP_QFMT) { | 781 | if (queue_type(q) == QDIO_ZFCP_QFMT) { |
848 | if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) | 782 | if (!pci_out_supported(q) && !qdio_outbound_q_done(q)) |
849 | tasklet_schedule(&q->tasklet); | 783 | tasklet_schedule(&q->tasklet); |
@@ -908,27 +842,18 @@ void qdio_check_outbound_after_thinint(struct qdio_q *q) | |||
908 | static inline void qdio_set_state(struct qdio_irq *irq_ptr, | 842 | static inline void qdio_set_state(struct qdio_irq *irq_ptr, |
909 | enum qdio_irq_states state) | 843 | enum qdio_irq_states state) |
910 | { | 844 | { |
911 | #ifdef CONFIG_QDIO_DEBUG | 845 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "newstate: %1d", state); |
912 | char dbf_text[15]; | ||
913 | |||
914 | QDIO_DBF_TEXT5(0, trace, "newstate"); | ||
915 | sprintf(dbf_text, "%4x%4x", irq_ptr->schid.sch_no, state); | ||
916 | QDIO_DBF_TEXT5(0, trace, dbf_text); | ||
917 | #endif /* CONFIG_QDIO_DEBUG */ | ||
918 | 846 | ||
919 | irq_ptr->state = state; | 847 | irq_ptr->state = state; |
920 | mb(); | 848 | mb(); |
921 | } | 849 | } |
922 | 850 | ||
923 | static void qdio_irq_check_sense(struct subchannel_id schid, struct irb *irb) | 851 | static void qdio_irq_check_sense(struct qdio_irq *irq_ptr, struct irb *irb) |
924 | { | 852 | { |
925 | char dbf_text[15]; | ||
926 | |||
927 | if (irb->esw.esw0.erw.cons) { | 853 | if (irb->esw.esw0.erw.cons) { |
928 | sprintf(dbf_text, "sens%4x", schid.sch_no); | 854 | DBF_ERROR("%4x sense:", irq_ptr->schid.sch_no); |
929 | QDIO_DBF_TEXT2(1, trace, dbf_text); | 855 | DBF_ERROR_HEX(irb, 64); |
930 | QDIO_DBF_HEX0(0, trace, irb, 64); | 856 | DBF_ERROR_HEX(irb->ecw, 64); |
931 | QDIO_DBF_HEX0(0, trace, irb->ecw, 64); | ||
932 | } | 857 | } |
933 | } | 858 | } |
934 | 859 | ||
@@ -962,14 +887,10 @@ static void qdio_handle_activate_check(struct ccw_device *cdev, | |||
962 | { | 887 | { |
963 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 888 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
964 | struct qdio_q *q; | 889 | struct qdio_q *q; |
965 | char dbf_text[15]; | ||
966 | 890 | ||
967 | QDIO_DBF_TEXT2(1, trace, "ick2"); | 891 | DBF_ERROR("%4x ACT CHECK", irq_ptr->schid.sch_no); |
968 | sprintf(dbf_text, "%s", dev_name(&cdev->dev)); | 892 | DBF_ERROR("intp :%lx", intparm); |
969 | QDIO_DBF_TEXT2(1, trace, dbf_text); | 893 | DBF_ERROR("ds: %2x cs:%2x", dstat, cstat); |
970 | QDIO_DBF_HEX2(0, trace, &intparm, sizeof(int)); | ||
971 | QDIO_DBF_HEX2(0, trace, &dstat, sizeof(int)); | ||
972 | QDIO_DBF_HEX2(0, trace, &cstat, sizeof(int)); | ||
973 | 894 | ||
974 | if (irq_ptr->nr_input_qs) { | 895 | if (irq_ptr->nr_input_qs) { |
975 | q = irq_ptr->input_qs[0]; | 896 | q = irq_ptr->input_qs[0]; |
@@ -1022,28 +943,29 @@ static void qdio_int_error(struct ccw_device *cdev) | |||
1022 | } | 943 | } |
1023 | 944 | ||
1024 | static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat, | 945 | static int qdio_establish_check_errors(struct ccw_device *cdev, int cstat, |
1025 | int dstat) | 946 | int dstat) |
1026 | { | 947 | { |
1027 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 948 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1028 | 949 | ||
1029 | if (cstat || (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { | 950 | if (cstat || (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END))) { |
1030 | QDIO_DBF_TEXT2(1, setup, "eq:ckcon"); | 951 | DBF_ERROR("EQ:ck con"); |
1031 | goto error; | 952 | goto error; |
1032 | } | 953 | } |
1033 | 954 | ||
1034 | if (!(dstat & DEV_STAT_DEV_END)) { | 955 | if (!(dstat & DEV_STAT_DEV_END)) { |
1035 | QDIO_DBF_TEXT2(1, setup, "eq:no de"); | 956 | DBF_ERROR("EQ:no dev"); |
1036 | goto error; | 957 | goto error; |
1037 | } | 958 | } |
1038 | 959 | ||
1039 | if (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) { | 960 | if (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) { |
1040 | QDIO_DBF_TEXT2(1, setup, "eq:badio"); | 961 | DBF_ERROR("EQ: bad io"); |
1041 | goto error; | 962 | goto error; |
1042 | } | 963 | } |
1043 | return 0; | 964 | return 0; |
1044 | error: | 965 | error: |
1045 | QDIO_DBF_HEX2(0, trace, &cstat, sizeof(int)); | 966 | DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no); |
1046 | QDIO_DBF_HEX2(0, trace, &dstat, sizeof(int)); | 967 | DBF_ERROR("ds: %2x cs:%2x", dstat, cstat); |
968 | |||
1047 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); | 969 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); |
1048 | return 1; | 970 | return 1; |
1049 | } | 971 | } |
@@ -1052,12 +974,8 @@ static void qdio_establish_handle_irq(struct ccw_device *cdev, int cstat, | |||
1052 | int dstat) | 974 | int dstat) |
1053 | { | 975 | { |
1054 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 976 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1055 | char dbf_text[15]; | ||
1056 | |||
1057 | sprintf(dbf_text, "qehi%4x", cdev->private->schid.sch_no); | ||
1058 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1059 | QDIO_DBF_TEXT0(0, trace, dbf_text); | ||
1060 | 977 | ||
978 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq"); | ||
1061 | if (!qdio_establish_check_errors(cdev, cstat, dstat)) | 979 | if (!qdio_establish_check_errors(cdev, cstat, dstat)) |
1062 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED); | 980 | qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED); |
1063 | } | 981 | } |
@@ -1068,25 +986,21 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1068 | { | 986 | { |
1069 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 987 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1070 | int cstat, dstat; | 988 | int cstat, dstat; |
1071 | char dbf_text[15]; | ||
1072 | 989 | ||
1073 | qdio_perf_stat_inc(&perf_stats.qdio_int); | 990 | qdio_perf_stat_inc(&perf_stats.qdio_int); |
1074 | 991 | ||
1075 | if (!intparm || !irq_ptr) { | 992 | if (!intparm || !irq_ptr) { |
1076 | sprintf(dbf_text, "qihd%4x", cdev->private->schid.sch_no); | 993 | DBF_ERROR("qint:%4x", cdev->private->schid.sch_no); |
1077 | QDIO_DBF_TEXT2(1, setup, dbf_text); | ||
1078 | return; | 994 | return; |
1079 | } | 995 | } |
1080 | 996 | ||
1081 | if (IS_ERR(irb)) { | 997 | if (IS_ERR(irb)) { |
1082 | switch (PTR_ERR(irb)) { | 998 | switch (PTR_ERR(irb)) { |
1083 | case -EIO: | 999 | case -EIO: |
1084 | sprintf(dbf_text, "ierr%4x", irq_ptr->schid.sch_no); | 1000 | DBF_ERROR("%4x IO error", irq_ptr->schid.sch_no); |
1085 | QDIO_DBF_TEXT2(1, setup, dbf_text); | ||
1086 | return; | 1001 | return; |
1087 | case -ETIMEDOUT: | 1002 | case -ETIMEDOUT: |
1088 | sprintf(dbf_text, "qtoh%4x", irq_ptr->schid.sch_no); | 1003 | DBF_ERROR("%4x IO timeout", irq_ptr->schid.sch_no); |
1089 | QDIO_DBF_TEXT2(1, setup, dbf_text); | ||
1090 | qdio_int_error(cdev); | 1004 | qdio_int_error(cdev); |
1091 | return; | 1005 | return; |
1092 | default: | 1006 | default: |
@@ -1094,7 +1008,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1094 | return; | 1008 | return; |
1095 | } | 1009 | } |
1096 | } | 1010 | } |
1097 | qdio_irq_check_sense(irq_ptr->schid, irb); | 1011 | qdio_irq_check_sense(irq_ptr, irb); |
1098 | 1012 | ||
1099 | cstat = irb->scsw.cmd.cstat; | 1013 | cstat = irb->scsw.cmd.cstat; |
1100 | dstat = irb->scsw.cmd.dstat; | 1014 | dstat = irb->scsw.cmd.dstat; |
@@ -1129,23 +1043,20 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1129 | /** | 1043 | /** |
1130 | * qdio_get_ssqd_desc - get qdio subchannel description | 1044 | * qdio_get_ssqd_desc - get qdio subchannel description |
1131 | * @cdev: ccw device to get description for | 1045 | * @cdev: ccw device to get description for |
1046 | * @data: where to store the ssqd | ||
1132 | * | 1047 | * |
1133 | * Returns a pointer to the saved qdio subchannel description, | 1048 | * Returns 0 or an error code. The results of the chsc are stored in the |
1134 | * or NULL for not setup qdio devices. | 1049 | * specified structure. |
1135 | */ | 1050 | */ |
1136 | struct qdio_ssqd_desc *qdio_get_ssqd_desc(struct ccw_device *cdev) | 1051 | int qdio_get_ssqd_desc(struct ccw_device *cdev, |
1052 | struct qdio_ssqd_desc *data) | ||
1137 | { | 1053 | { |
1138 | struct qdio_irq *irq_ptr; | ||
1139 | char dbf_text[15]; | ||
1140 | |||
1141 | sprintf(dbf_text, "qssq%4x", cdev->private->schid.sch_no); | ||
1142 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1143 | 1054 | ||
1144 | irq_ptr = cdev->private->qdio_data; | 1055 | if (!cdev || !cdev->private) |
1145 | if (!irq_ptr) | 1056 | return -EINVAL; |
1146 | return NULL; | ||
1147 | 1057 | ||
1148 | return &irq_ptr->ssqd_desc; | 1058 | DBF_EVENT("get ssqd:%4x", cdev->private->schid.sch_no); |
1059 | return qdio_setup_get_ssqd(NULL, &cdev->private->schid, data); | ||
1149 | } | 1060 | } |
1150 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | 1061 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); |
1151 | 1062 | ||
@@ -1159,14 +1070,9 @@ EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | |||
1159 | */ | 1070 | */ |
1160 | int qdio_cleanup(struct ccw_device *cdev, int how) | 1071 | int qdio_cleanup(struct ccw_device *cdev, int how) |
1161 | { | 1072 | { |
1162 | struct qdio_irq *irq_ptr; | 1073 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1163 | char dbf_text[15]; | ||
1164 | int rc; | 1074 | int rc; |
1165 | 1075 | ||
1166 | sprintf(dbf_text, "qcln%4x", cdev->private->schid.sch_no); | ||
1167 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1168 | |||
1169 | irq_ptr = cdev->private->qdio_data; | ||
1170 | if (!irq_ptr) | 1076 | if (!irq_ptr) |
1171 | return -ENODEV; | 1077 | return -ENODEV; |
1172 | 1078 | ||
@@ -1199,18 +1105,15 @@ static void qdio_shutdown_queues(struct ccw_device *cdev) | |||
1199 | */ | 1105 | */ |
1200 | int qdio_shutdown(struct ccw_device *cdev, int how) | 1106 | int qdio_shutdown(struct ccw_device *cdev, int how) |
1201 | { | 1107 | { |
1202 | struct qdio_irq *irq_ptr; | 1108 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1203 | int rc; | 1109 | int rc; |
1204 | unsigned long flags; | 1110 | unsigned long flags; |
1205 | char dbf_text[15]; | ||
1206 | 1111 | ||
1207 | sprintf(dbf_text, "qshu%4x", cdev->private->schid.sch_no); | ||
1208 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1209 | |||
1210 | irq_ptr = cdev->private->qdio_data; | ||
1211 | if (!irq_ptr) | 1112 | if (!irq_ptr) |
1212 | return -ENODEV; | 1113 | return -ENODEV; |
1213 | 1114 | ||
1115 | DBF_EVENT("qshutdown:%4x", cdev->private->schid.sch_no); | ||
1116 | |||
1214 | mutex_lock(&irq_ptr->setup_mutex); | 1117 | mutex_lock(&irq_ptr->setup_mutex); |
1215 | /* | 1118 | /* |
1216 | * Subchannel was already shot down. We cannot prevent being called | 1119 | * Subchannel was already shot down. We cannot prevent being called |
@@ -1234,10 +1137,8 @@ int qdio_shutdown(struct ccw_device *cdev, int how) | |||
1234 | /* default behaviour is halt */ | 1137 | /* default behaviour is halt */ |
1235 | rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP); | 1138 | rc = ccw_device_halt(cdev, QDIO_DOING_CLEANUP); |
1236 | if (rc) { | 1139 | if (rc) { |
1237 | sprintf(dbf_text, "sher%4x", irq_ptr->schid.sch_no); | 1140 | DBF_ERROR("%4x SHUTD ERR", irq_ptr->schid.sch_no); |
1238 | QDIO_DBF_TEXT0(0, setup, dbf_text); | 1141 | DBF_ERROR("rc:%4d", rc); |
1239 | sprintf(dbf_text, "rc=%d", rc); | ||
1240 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1241 | goto no_cleanup; | 1142 | goto no_cleanup; |
1242 | } | 1143 | } |
1243 | 1144 | ||
@@ -1271,17 +1172,18 @@ EXPORT_SYMBOL_GPL(qdio_shutdown); | |||
1271 | */ | 1172 | */ |
1272 | int qdio_free(struct ccw_device *cdev) | 1173 | int qdio_free(struct ccw_device *cdev) |
1273 | { | 1174 | { |
1274 | struct qdio_irq *irq_ptr; | 1175 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
1275 | char dbf_text[15]; | ||
1276 | |||
1277 | sprintf(dbf_text, "qfre%4x", cdev->private->schid.sch_no); | ||
1278 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1279 | 1176 | ||
1280 | irq_ptr = cdev->private->qdio_data; | ||
1281 | if (!irq_ptr) | 1177 | if (!irq_ptr) |
1282 | return -ENODEV; | 1178 | return -ENODEV; |
1283 | 1179 | ||
1180 | DBF_EVENT("qfree:%4x", cdev->private->schid.sch_no); | ||
1284 | mutex_lock(&irq_ptr->setup_mutex); | 1181 | mutex_lock(&irq_ptr->setup_mutex); |
1182 | |||
1183 | if (irq_ptr->debug_area != NULL) { | ||
1184 | debug_unregister(irq_ptr->debug_area); | ||
1185 | irq_ptr->debug_area = NULL; | ||
1186 | } | ||
1285 | cdev->private->qdio_data = NULL; | 1187 | cdev->private->qdio_data = NULL; |
1286 | mutex_unlock(&irq_ptr->setup_mutex); | 1188 | mutex_unlock(&irq_ptr->setup_mutex); |
1287 | 1189 | ||
@@ -1300,10 +1202,6 @@ EXPORT_SYMBOL_GPL(qdio_free); | |||
1300 | int qdio_initialize(struct qdio_initialize *init_data) | 1202 | int qdio_initialize(struct qdio_initialize *init_data) |
1301 | { | 1203 | { |
1302 | int rc; | 1204 | int rc; |
1303 | char dbf_text[15]; | ||
1304 | |||
1305 | sprintf(dbf_text, "qini%4x", init_data->cdev->private->schid.sch_no); | ||
1306 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1307 | 1205 | ||
1308 | rc = qdio_allocate(init_data); | 1206 | rc = qdio_allocate(init_data); |
1309 | if (rc) | 1207 | if (rc) |
@@ -1323,10 +1221,8 @@ EXPORT_SYMBOL_GPL(qdio_initialize); | |||
1323 | int qdio_allocate(struct qdio_initialize *init_data) | 1221 | int qdio_allocate(struct qdio_initialize *init_data) |
1324 | { | 1222 | { |
1325 | struct qdio_irq *irq_ptr; | 1223 | struct qdio_irq *irq_ptr; |
1326 | char dbf_text[15]; | ||
1327 | 1224 | ||
1328 | sprintf(dbf_text, "qalc%4x", init_data->cdev->private->schid.sch_no); | 1225 | DBF_EVENT("qallocate:%4x", init_data->cdev->private->schid.sch_no); |
1329 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1330 | 1226 | ||
1331 | if ((init_data->no_input_qs && !init_data->input_handler) || | 1227 | if ((init_data->no_input_qs && !init_data->input_handler) || |
1332 | (init_data->no_output_qs && !init_data->output_handler)) | 1228 | (init_data->no_output_qs && !init_data->output_handler)) |
@@ -1340,16 +1236,13 @@ int qdio_allocate(struct qdio_initialize *init_data) | |||
1340 | (!init_data->output_sbal_addr_array)) | 1236 | (!init_data->output_sbal_addr_array)) |
1341 | return -EINVAL; | 1237 | return -EINVAL; |
1342 | 1238 | ||
1343 | qdio_allocate_do_dbf(init_data); | ||
1344 | |||
1345 | /* irq_ptr must be in GFP_DMA since it contains ccw1.cda */ | 1239 | /* irq_ptr must be in GFP_DMA since it contains ccw1.cda */ |
1346 | irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | 1240 | irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); |
1347 | if (!irq_ptr) | 1241 | if (!irq_ptr) |
1348 | goto out_err; | 1242 | goto out_err; |
1349 | QDIO_DBF_TEXT0(0, setup, "irq_ptr:"); | ||
1350 | QDIO_DBF_HEX0(0, setup, &irq_ptr, sizeof(void *)); | ||
1351 | 1243 | ||
1352 | mutex_init(&irq_ptr->setup_mutex); | 1244 | mutex_init(&irq_ptr->setup_mutex); |
1245 | qdio_allocate_dbf(init_data, irq_ptr); | ||
1353 | 1246 | ||
1354 | /* | 1247 | /* |
1355 | * Allocate a page for the chsc calls in qdio_establish. | 1248 | * Allocate a page for the chsc calls in qdio_establish. |
@@ -1367,9 +1260,6 @@ int qdio_allocate(struct qdio_initialize *init_data) | |||
1367 | goto out_rel; | 1260 | goto out_rel; |
1368 | WARN_ON((unsigned long)irq_ptr->qdr & 0xfff); | 1261 | WARN_ON((unsigned long)irq_ptr->qdr & 0xfff); |
1369 | 1262 | ||
1370 | QDIO_DBF_TEXT0(0, setup, "qdr:"); | ||
1371 | QDIO_DBF_HEX0(0, setup, &irq_ptr->qdr, sizeof(void *)); | ||
1372 | |||
1373 | if (qdio_allocate_qs(irq_ptr, init_data->no_input_qs, | 1263 | if (qdio_allocate_qs(irq_ptr, init_data->no_input_qs, |
1374 | init_data->no_output_qs)) | 1264 | init_data->no_output_qs)) |
1375 | goto out_rel; | 1265 | goto out_rel; |
@@ -1390,14 +1280,12 @@ EXPORT_SYMBOL_GPL(qdio_allocate); | |||
1390 | */ | 1280 | */ |
1391 | int qdio_establish(struct qdio_initialize *init_data) | 1281 | int qdio_establish(struct qdio_initialize *init_data) |
1392 | { | 1282 | { |
1393 | char dbf_text[20]; | ||
1394 | struct qdio_irq *irq_ptr; | 1283 | struct qdio_irq *irq_ptr; |
1395 | struct ccw_device *cdev = init_data->cdev; | 1284 | struct ccw_device *cdev = init_data->cdev; |
1396 | unsigned long saveflags; | 1285 | unsigned long saveflags; |
1397 | int rc; | 1286 | int rc; |
1398 | 1287 | ||
1399 | sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); | 1288 | DBF_EVENT("qestablish:%4x", cdev->private->schid.sch_no); |
1400 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1401 | 1289 | ||
1402 | irq_ptr = cdev->private->qdio_data; | 1290 | irq_ptr = cdev->private->qdio_data; |
1403 | if (!irq_ptr) | 1291 | if (!irq_ptr) |
@@ -1427,10 +1315,8 @@ int qdio_establish(struct qdio_initialize *init_data) | |||
1427 | 1315 | ||
1428 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0); | 1316 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0); |
1429 | if (rc) { | 1317 | if (rc) { |
1430 | sprintf(dbf_text, "eq:io%4x", irq_ptr->schid.sch_no); | 1318 | DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no); |
1431 | QDIO_DBF_TEXT2(1, setup, dbf_text); | 1319 | DBF_ERROR("rc:%4x", rc); |
1432 | sprintf(dbf_text, "eq:rc%4x", rc); | ||
1433 | QDIO_DBF_TEXT2(1, setup, dbf_text); | ||
1434 | } | 1320 | } |
1435 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags); | 1321 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags); |
1436 | 1322 | ||
@@ -1451,10 +1337,8 @@ int qdio_establish(struct qdio_initialize *init_data) | |||
1451 | } | 1337 | } |
1452 | 1338 | ||
1453 | qdio_setup_ssqd_info(irq_ptr); | 1339 | qdio_setup_ssqd_info(irq_ptr); |
1454 | sprintf(dbf_text, "qDmmwc%2x", irq_ptr->ssqd_desc.mmwc); | 1340 | DBF_EVENT("qDmmwc:%2x", irq_ptr->ssqd_desc.mmwc); |
1455 | QDIO_DBF_TEXT2(0, setup, dbf_text); | 1341 | DBF_EVENT("qib ac:%4x", irq_ptr->qib.ac); |
1456 | sprintf(dbf_text, "qib ac%2x", irq_ptr->qib.ac); | ||
1457 | QDIO_DBF_TEXT2(0, setup, dbf_text); | ||
1458 | 1342 | ||
1459 | /* qebsm is now setup if available, initialize buffer states */ | 1343 | /* qebsm is now setup if available, initialize buffer states */ |
1460 | qdio_init_buf_states(irq_ptr); | 1344 | qdio_init_buf_states(irq_ptr); |
@@ -1475,10 +1359,8 @@ int qdio_activate(struct ccw_device *cdev) | |||
1475 | struct qdio_irq *irq_ptr; | 1359 | struct qdio_irq *irq_ptr; |
1476 | int rc; | 1360 | int rc; |
1477 | unsigned long saveflags; | 1361 | unsigned long saveflags; |
1478 | char dbf_text[20]; | ||
1479 | 1362 | ||
1480 | sprintf(dbf_text, "qact%4x", cdev->private->schid.sch_no); | 1363 | DBF_EVENT("qactivate:%4x", cdev->private->schid.sch_no); |
1481 | QDIO_DBF_TEXT0(0, setup, dbf_text); | ||
1482 | 1364 | ||
1483 | irq_ptr = cdev->private->qdio_data; | 1365 | irq_ptr = cdev->private->qdio_data; |
1484 | if (!irq_ptr) | 1366 | if (!irq_ptr) |
@@ -1504,10 +1386,8 @@ int qdio_activate(struct ccw_device *cdev) | |||
1504 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ACTIVATE, | 1386 | rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ACTIVATE, |
1505 | 0, DOIO_DENY_PREFETCH); | 1387 | 0, DOIO_DENY_PREFETCH); |
1506 | if (rc) { | 1388 | if (rc) { |
1507 | sprintf(dbf_text, "aq:io%4x", irq_ptr->schid.sch_no); | 1389 | DBF_ERROR("%4x act IO ERR", irq_ptr->schid.sch_no); |
1508 | QDIO_DBF_TEXT2(1, setup, dbf_text); | 1390 | DBF_ERROR("rc:%4x", rc); |
1509 | sprintf(dbf_text, "aq:rc%4x", rc); | ||
1510 | QDIO_DBF_TEXT2(1, setup, dbf_text); | ||
1511 | } | 1391 | } |
1512 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags); | 1392 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), saveflags); |
1513 | 1393 | ||
@@ -1565,23 +1445,38 @@ static inline int buf_in_between(int bufnr, int start, int count) | |||
1565 | static void handle_inbound(struct qdio_q *q, unsigned int callflags, | 1445 | static void handle_inbound(struct qdio_q *q, unsigned int callflags, |
1566 | int bufnr, int count) | 1446 | int bufnr, int count) |
1567 | { | 1447 | { |
1568 | unsigned long flags; | 1448 | int used, cc, diff; |
1569 | int used, rc; | ||
1570 | 1449 | ||
1571 | /* | 1450 | if (!q->u.in.polling) |
1572 | * do_QDIO could run in parallel with the queue tasklet so the | 1451 | goto set; |
1573 | * upper-layer programm could empty the ACK'ed buffer here. | 1452 | |
1574 | * If that happens we must clear the polling flag, otherwise | 1453 | /* protect against stop polling setting an ACK for an emptied slsb */ |
1575 | * qdio_stop_polling() could set the buffer to NOT_INIT after | 1454 | if (count == QDIO_MAX_BUFFERS_PER_Q) { |
1576 | * it was set to EMPTY which would kill us. | 1455 | /* overwriting everything, just delete polling status */ |
1577 | */ | 1456 | q->u.in.polling = 0; |
1578 | spin_lock_irqsave(&q->u.in.lock, flags); | 1457 | q->u.in.ack_count = 0; |
1579 | if (q->u.in.polling) | 1458 | goto set; |
1580 | if (buf_in_between(q->last_move_ftc, bufnr, count)) | 1459 | } else if (buf_in_between(q->last_move_ftc, bufnr, count)) { |
1460 | if (is_qebsm(q)) { | ||
1461 | /* partial overwrite, just update last_move_ftc */ | ||
1462 | diff = add_buf(bufnr, count); | ||
1463 | diff = sub_buf(diff, q->last_move_ftc); | ||
1464 | q->u.in.ack_count -= diff; | ||
1465 | if (q->u.in.ack_count <= 0) { | ||
1466 | q->u.in.polling = 0; | ||
1467 | q->u.in.ack_count = 0; | ||
1468 | /* TODO: must we set last_move_ftc to something meaningful? */ | ||
1469 | goto set; | ||
1470 | } | ||
1471 | q->last_move_ftc = add_buf(q->last_move_ftc, diff); | ||
1472 | } | ||
1473 | else | ||
1474 | /* the only ACK will be deleted, so stop polling */ | ||
1581 | q->u.in.polling = 0; | 1475 | q->u.in.polling = 0; |
1476 | } | ||
1582 | 1477 | ||
1478 | set: | ||
1583 | count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count); | 1479 | count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count); |
1584 | spin_unlock_irqrestore(&q->u.in.lock, flags); | ||
1585 | 1480 | ||
1586 | used = atomic_add_return(count, &q->nr_buf_used) - count; | 1481 | used = atomic_add_return(count, &q->nr_buf_used) - count; |
1587 | BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q); | 1482 | BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q); |
@@ -1591,9 +1486,9 @@ static void handle_inbound(struct qdio_q *q, unsigned int callflags, | |||
1591 | return; | 1486 | return; |
1592 | 1487 | ||
1593 | if (need_siga_in(q)) { | 1488 | if (need_siga_in(q)) { |
1594 | rc = qdio_siga_input(q); | 1489 | cc = qdio_siga_input(q); |
1595 | if (rc) | 1490 | if (cc) |
1596 | q->qdio_error = rc; | 1491 | q->qdio_error = cc; |
1597 | } | 1492 | } |
1598 | } | 1493 | } |
1599 | 1494 | ||
@@ -1640,6 +1535,10 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1640 | while (count--) | 1535 | while (count--) |
1641 | qdio_kick_outbound_q(q); | 1536 | qdio_kick_outbound_q(q); |
1642 | } | 1537 | } |
1538 | |||
1539 | /* report CC=2 conditions synchronously */ | ||
1540 | if (q->qdio_error) | ||
1541 | __qdio_outbound_processing(q); | ||
1643 | goto out; | 1542 | goto out; |
1644 | } | 1543 | } |
1645 | 1544 | ||
@@ -1649,11 +1548,11 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
1649 | } | 1548 | } |
1650 | 1549 | ||
1651 | /* try to fast requeue buffers */ | 1550 | /* try to fast requeue buffers */ |
1652 | get_buf_state(q, prev_buf(bufnr), &state); | 1551 | get_buf_state(q, prev_buf(bufnr), &state, 0); |
1653 | if (state != SLSB_CU_OUTPUT_PRIMED) | 1552 | if (state != SLSB_CU_OUTPUT_PRIMED) |
1654 | qdio_kick_outbound_q(q); | 1553 | qdio_kick_outbound_q(q); |
1655 | else { | 1554 | else { |
1656 | QDIO_DBF_TEXT5(0, trace, "fast-req"); | 1555 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req"); |
1657 | qdio_perf_stat_inc(&perf_stats.fast_requeue); | 1556 | qdio_perf_stat_inc(&perf_stats.fast_requeue); |
1658 | } | 1557 | } |
1659 | out: | 1558 | out: |
@@ -1673,12 +1572,6 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1673 | int q_nr, int bufnr, int count) | 1572 | int q_nr, int bufnr, int count) |
1674 | { | 1573 | { |
1675 | struct qdio_irq *irq_ptr; | 1574 | struct qdio_irq *irq_ptr; |
1676 | #ifdef CONFIG_QDIO_DEBUG | ||
1677 | char dbf_text[20]; | ||
1678 | |||
1679 | sprintf(dbf_text, "doQD%4x", cdev->private->schid.sch_no); | ||
1680 | QDIO_DBF_TEXT3(0, trace, dbf_text); | ||
1681 | #endif /* CONFIG_QDIO_DEBUG */ | ||
1682 | 1575 | ||
1683 | if ((bufnr > QDIO_MAX_BUFFERS_PER_Q) || | 1576 | if ((bufnr > QDIO_MAX_BUFFERS_PER_Q) || |
1684 | (count > QDIO_MAX_BUFFERS_PER_Q) || | 1577 | (count > QDIO_MAX_BUFFERS_PER_Q) || |
@@ -1692,33 +1585,24 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, | |||
1692 | if (!irq_ptr) | 1585 | if (!irq_ptr) |
1693 | return -ENODEV; | 1586 | return -ENODEV; |
1694 | 1587 | ||
1695 | #ifdef CONFIG_QDIO_DEBUG | ||
1696 | if (callflags & QDIO_FLAG_SYNC_INPUT) | 1588 | if (callflags & QDIO_FLAG_SYNC_INPUT) |
1697 | QDIO_DBF_HEX3(0, trace, &irq_ptr->input_qs[q_nr], | 1589 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "doQDIO input"); |
1698 | sizeof(void *)); | ||
1699 | else | 1590 | else |
1700 | QDIO_DBF_HEX3(0, trace, &irq_ptr->output_qs[q_nr], | 1591 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "doQDIO output"); |
1701 | sizeof(void *)); | 1592 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "q:%1d flag:%4x", q_nr, callflags); |
1702 | 1593 | DBF_DEV_EVENT(DBF_INFO, irq_ptr, "buf:%2d cnt:%3d", bufnr, count); | |
1703 | sprintf(dbf_text, "flag%04x", callflags); | ||
1704 | QDIO_DBF_TEXT3(0, trace, dbf_text); | ||
1705 | sprintf(dbf_text, "qi%02xct%02x", bufnr, count); | ||
1706 | QDIO_DBF_TEXT3(0, trace, dbf_text); | ||
1707 | #endif /* CONFIG_QDIO_DEBUG */ | ||
1708 | 1594 | ||
1709 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) | 1595 | if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) |
1710 | return -EBUSY; | 1596 | return -EBUSY; |
1711 | 1597 | ||
1712 | if (callflags & QDIO_FLAG_SYNC_INPUT) | 1598 | if (callflags & QDIO_FLAG_SYNC_INPUT) |
1713 | handle_inbound(irq_ptr->input_qs[q_nr], | 1599 | handle_inbound(irq_ptr->input_qs[q_nr], callflags, bufnr, |
1714 | callflags, bufnr, count); | 1600 | count); |
1715 | else if (callflags & QDIO_FLAG_SYNC_OUTPUT) | 1601 | else if (callflags & QDIO_FLAG_SYNC_OUTPUT) |
1716 | handle_outbound(irq_ptr->output_qs[q_nr], | 1602 | handle_outbound(irq_ptr->output_qs[q_nr], callflags, bufnr, |
1717 | callflags, bufnr, count); | 1603 | count); |
1718 | else { | 1604 | else |
1719 | QDIO_DBF_TEXT3(1, trace, "doQD:inv"); | ||
1720 | return -EINVAL; | 1605 | return -EINVAL; |
1721 | } | ||
1722 | return 0; | 1606 | return 0; |
1723 | } | 1607 | } |
1724 | EXPORT_SYMBOL_GPL(do_QDIO); | 1608 | EXPORT_SYMBOL_GPL(do_QDIO); |