diff options
Diffstat (limited to 'drivers/s390/cio/qdio_main.c')
| -rw-r--r-- | drivers/s390/cio/qdio_main.c | 181 |
1 files changed, 118 insertions, 63 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index c810214d3d08..0b4c09cf6a47 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -112,12 +112,13 @@ static inline int qdio_check_ccq(struct qdio_q *q, unsigned int ccq) | |||
| 112 | * @state: state of the extracted buffers | 112 | * @state: state of the extracted buffers |
| 113 | * @start: buffer number to start at | 113 | * @start: buffer number to start at |
| 114 | * @count: count of buffers to examine | 114 | * @count: count of buffers to examine |
| 115 | * @auto_ack: automatically acknowledge buffers | ||
| 115 | * | 116 | * |
| 116 | * Returns the number of successfull extracted equal buffer states. | 117 | * Returns the number of successfull extracted equal buffer states. |
| 117 | * 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. |
| 118 | */ | 119 | */ |
| 119 | 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, |
| 120 | int start, int count) | 121 | int start, int count, int auto_ack) |
| 121 | { | 122 | { |
| 122 | unsigned int ccq = 0; | 123 | unsigned int ccq = 0; |
| 123 | int tmp_count = count, tmp_start = start; | 124 | int tmp_count = count, tmp_start = start; |
| @@ -130,7 +131,8 @@ static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, | |||
| 130 | if (!q->is_input_q) | 131 | if (!q->is_input_q) |
| 131 | nr += q->irq_ptr->nr_input_qs; | 132 | nr += q->irq_ptr->nr_input_qs; |
| 132 | again: | 133 | again: |
| 133 | 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); | ||
| 134 | rc = qdio_check_ccq(q, ccq); | 136 | rc = qdio_check_ccq(q, ccq); |
| 135 | 137 | ||
| 136 | /* At least one buffer was processed, return and extract the remaining | 138 | /* At least one buffer was processed, return and extract the remaining |
| @@ -176,6 +178,9 @@ static int qdio_do_sqbs(struct qdio_q *q, unsigned char state, int start, | |||
| 176 | int nr = q->nr; | 178 | int nr = q->nr; |
| 177 | int rc; | 179 | int rc; |
| 178 | 180 | ||
| 181 | if (!count) | ||
| 182 | return 0; | ||
| 183 | |||
| 179 | BUG_ON(!q->irq_ptr->sch_token); | 184 | BUG_ON(!q->irq_ptr->sch_token); |
| 180 | qdio_perf_stat_inc(&perf_stats.debug_sqbs_all); | 185 | qdio_perf_stat_inc(&perf_stats.debug_sqbs_all); |
| 181 | 186 | ||
| @@ -203,7 +208,8 @@ again: | |||
| 203 | 208 | ||
| 204 | /* returns number of examined buffers and their common state in *state */ | 209 | /* returns number of examined buffers and their common state in *state */ |
| 205 | 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, |
| 206 | unsigned char *state, unsigned int count) | 211 | unsigned char *state, unsigned int count, |
| 212 | int auto_ack) | ||
| 207 | { | 213 | { |
| 208 | unsigned char __state = 0; | 214 | unsigned char __state = 0; |
| 209 | int i; | 215 | int i; |
| @@ -212,7 +218,7 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, | |||
| 212 | BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q); | 218 | BUG_ON(count > QDIO_MAX_BUFFERS_PER_Q); |
| 213 | 219 | ||
| 214 | if (is_qebsm(q)) | 220 | if (is_qebsm(q)) |
| 215 | return qdio_do_eqbs(q, state, bufnr, count); | 221 | return qdio_do_eqbs(q, state, bufnr, count, auto_ack); |
| 216 | 222 | ||
| 217 | for (i = 0; i < count; i++) { | 223 | for (i = 0; i < count; i++) { |
| 218 | if (!__state) | 224 | if (!__state) |
| @@ -226,9 +232,9 @@ static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, | |||
| 226 | } | 232 | } |
| 227 | 233 | ||
| 228 | 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, |
| 229 | unsigned char *state) | 235 | unsigned char *state, int auto_ack) |
| 230 | { | 236 | { |
| 231 | return get_buf_states(q, bufnr, state, 1); | 237 | return get_buf_states(q, bufnr, state, 1, auto_ack); |
| 232 | } | 238 | } |
| 233 | 239 | ||
| 234 | /* 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 */ |
| @@ -376,29 +382,91 @@ void qdio_sync_after_thinint(struct qdio_q *q) | |||
| 376 | 382 | ||
| 377 | inline void qdio_stop_polling(struct qdio_q *q) | 383 | inline void qdio_stop_polling(struct qdio_q *q) |
| 378 | { | 384 | { |
| 379 | spin_lock_bh(&q->u.in.lock); | 385 | if (!q->u.in.polling) |
| 380 | if (!q->u.in.polling) { | ||
| 381 | spin_unlock_bh(&q->u.in.lock); | ||
| 382 | return; | 386 | return; |
| 383 | } | 387 | |
| 384 | q->u.in.polling = 0; | 388 | q->u.in.polling = 0; |
| 385 | qdio_perf_stat_inc(&perf_stats.debug_stop_polling); | 389 | qdio_perf_stat_inc(&perf_stats.debug_stop_polling); |
| 386 | 390 | ||
| 387 | /* show the card that we are not polling anymore */ | 391 | /* show the card that we are not polling anymore */ |
| 388 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | 392 | if (is_qebsm(q)) { |
| 389 | spin_unlock_bh(&q->u.in.lock); | 393 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, |
| 394 | q->u.in.ack_count); | ||
| 395 | q->u.in.ack_count = 0; | ||
| 396 | } else | ||
| 397 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | ||
| 390 | } | 398 | } |
| 391 | 399 | ||
| 392 | static void announce_buffer_error(struct qdio_q *q) | 400 | static void announce_buffer_error(struct qdio_q *q, int count) |
| 393 | { | 401 | { |
| 402 | q->qdio_error = QDIO_ERROR_SLSB_STATE; | ||
| 403 | |||
| 404 | /* special handling for no target buffer empty */ | ||
| 405 | if ((!q->is_input_q && | ||
| 406 | (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { | ||
| 407 | qdio_perf_stat_inc(&perf_stats.outbound_target_full); | ||
| 408 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%3d", | ||
| 409 | q->first_to_check); | ||
| 410 | return; | ||
| 411 | } | ||
| 412 | |||
| 394 | DBF_ERROR("%4x BUF ERROR", SCH_NO(q)); | 413 | DBF_ERROR("%4x BUF ERROR", SCH_NO(q)); |
| 395 | DBF_ERROR((q->is_input_q) ? "IN:%2d" : "OUT:%2d", q->nr); | 414 | DBF_ERROR((q->is_input_q) ? "IN:%2d" : "OUT:%2d", q->nr); |
| 396 | DBF_ERROR("FTC:%3d", q->first_to_check); | 415 | DBF_ERROR("FTC:%3d C:%3d", q->first_to_check, count); |
| 397 | DBF_ERROR("F14:%2x F15:%2x", | 416 | DBF_ERROR("F14:%2x F15:%2x", |
| 398 | q->sbal[q->first_to_check]->element[14].flags & 0xff, | 417 | q->sbal[q->first_to_check]->element[14].flags & 0xff, |
| 399 | q->sbal[q->first_to_check]->element[15].flags & 0xff); | 418 | q->sbal[q->first_to_check]->element[15].flags & 0xff); |
| 419 | } | ||
| 400 | 420 | ||
| 401 | q->qdio_error = QDIO_ERROR_SLSB_STATE; | 421 | static inline void inbound_primed(struct qdio_q *q, int count) |
| 422 | { | ||
| 423 | int new; | ||
| 424 | |||
| 425 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %3d", count); | ||
| 426 | |||
| 427 | /* for QEBSM the ACK was already set by EQBS */ | ||
| 428 | if (is_qebsm(q)) { | ||
| 429 | if (!q->u.in.polling) { | ||
| 430 | q->u.in.polling = 1; | ||
| 431 | q->u.in.ack_count = count; | ||
| 432 | q->last_move_ftc = q->first_to_check; | ||
| 433 | return; | ||
| 434 | } | ||
| 435 | |||
| 436 | /* delete the previous ACK's */ | ||
| 437 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, | ||
| 438 | q->u.in.ack_count); | ||
| 439 | q->u.in.ack_count = count; | ||
| 440 | q->last_move_ftc = q->first_to_check; | ||
| 441 | return; | ||
| 442 | } | ||
| 443 | |||
| 444 | /* | ||
| 445 | * ACK the newest buffer. The ACK will be removed in qdio_stop_polling | ||
| 446 | * or by the next inbound run. | ||
| 447 | */ | ||
| 448 | new = add_buf(q->first_to_check, count - 1); | ||
| 449 | if (q->u.in.polling) { | ||
| 450 | /* reset the previous ACK but first set the new one */ | ||
| 451 | set_buf_state(q, new, SLSB_P_INPUT_ACK); | ||
| 452 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | ||
| 453 | } | ||
| 454 | else { | ||
| 455 | q->u.in.polling = 1; | ||
| 456 | set_buf_state(q, q->first_to_check, SLSB_P_INPUT_ACK); | ||
| 457 | } | ||
| 458 | |||
| 459 | q->last_move_ftc = new; | ||
| 460 | count--; | ||
| 461 | if (!count) | ||
| 462 | return; | ||
| 463 | |||
| 464 | /* | ||
| 465 | * Need to change all PRIMED buffers to NOT_INIT, otherwise | ||
| 466 | * we're loosing initiative in the thinint code. | ||
| 467 | */ | ||
| 468 | set_buf_states(q, next_buf(q->first_to_check), SLSB_P_INPUT_NOT_INIT, | ||
| 469 | count); | ||
| 402 | } | 470 | } |
| 403 | 471 | ||
| 404 | static int get_inbound_buffer_frontier(struct qdio_q *q) | 472 | static int get_inbound_buffer_frontier(struct qdio_q *q) |
| @@ -407,13 +475,6 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
| 407 | unsigned char state; | 475 | unsigned char state; |
| 408 | 476 | ||
| 409 | /* | 477 | /* |
| 410 | * If we still poll don't update last_move_ftc, keep the | ||
| 411 | * previously ACK buffer there. | ||
| 412 | */ | ||
| 413 | if (!q->u.in.polling) | ||
| 414 | q->last_move_ftc = q->first_to_check; | ||
| 415 | |||
| 416 | /* | ||
| 417 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved | 478 | * Don't check 128 buffers, as otherwise qdio_inbound_q_moved |
| 418 | * would return 0. | 479 | * would return 0. |
| 419 | */ | 480 | */ |
| @@ -433,34 +494,13 @@ check_next: | |||
| 433 | if (q->first_to_check == stop) | 494 | if (q->first_to_check == stop) |
| 434 | goto out; | 495 | goto out; |
| 435 | 496 | ||
| 436 | count = get_buf_states(q, q->first_to_check, &state, count); | 497 | count = get_buf_states(q, q->first_to_check, &state, count, 1); |
| 437 | if (!count) | 498 | if (!count) |
| 438 | goto out; | 499 | goto out; |
| 439 | 500 | ||
| 440 | switch (state) { | 501 | switch (state) { |
| 441 | case SLSB_P_INPUT_PRIMED: | 502 | case SLSB_P_INPUT_PRIMED: |
| 442 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %3d", count); | 503 | inbound_primed(q, count); |
| 443 | |||
| 444 | /* | ||
| 445 | * Only ACK the first buffer. The ACK will be removed in | ||
| 446 | * qdio_stop_polling. | ||
| 447 | */ | ||
| 448 | if (q->u.in.polling) | ||
| 449 | state = SLSB_P_INPUT_NOT_INIT; | ||
| 450 | else { | ||
| 451 | q->u.in.polling = 1; | ||
| 452 | state = SLSB_P_INPUT_ACK; | ||
| 453 | } | ||
| 454 | set_buf_state(q, q->first_to_check, state); | ||
| 455 | |||
| 456 | /* | ||
| 457 | * Need to change all PRIMED buffers to NOT_INIT, otherwise | ||
| 458 | * we're loosing initiative in the thinint code. | ||
| 459 | */ | ||
| 460 | if (count > 1) | ||
| 461 | set_buf_states(q, next_buf(q->first_to_check), | ||
| 462 | SLSB_P_INPUT_NOT_INIT, count - 1); | ||
| 463 | |||
| 464 | /* | 504 | /* |
| 465 | * No siga-sync needed for non-qebsm here, as the inbound queue | 505 | * No siga-sync needed for non-qebsm here, as the inbound queue |
| 466 | * will be synced on the next siga-r, resp. | 506 | * will be synced on the next siga-r, resp. |
| @@ -470,7 +510,7 @@ check_next: | |||
| 470 | atomic_sub(count, &q->nr_buf_used); | 510 | atomic_sub(count, &q->nr_buf_used); |
| 471 | goto check_next; | 511 | goto check_next; |
| 472 | case SLSB_P_INPUT_ERROR: | 512 | case SLSB_P_INPUT_ERROR: |
| 473 | announce_buffer_error(q); | 513 | announce_buffer_error(q, count); |
| 474 | /* process the buffer, the upper layer will take care of it */ | 514 | /* process the buffer, the upper layer will take care of it */ |
| 475 | q->first_to_check = add_buf(q->first_to_check, count); | 515 | q->first_to_check = add_buf(q->first_to_check, count); |
| 476 | atomic_sub(count, &q->nr_buf_used); | 516 | atomic_sub(count, &q->nr_buf_used); |
| @@ -516,7 +556,7 @@ static int qdio_inbound_q_done(struct qdio_q *q) | |||
| 516 | */ | 556 | */ |
| 517 | qdio_siga_sync_q(q); | 557 | qdio_siga_sync_q(q); |
| 518 | 558 | ||
| 519 | get_buf_state(q, q->first_to_check, &state); | 559 | get_buf_state(q, q->first_to_check, &state, 0); |
| 520 | if (state == SLSB_P_INPUT_PRIMED) | 560 | if (state == SLSB_P_INPUT_PRIMED) |
| 521 | /* we got something to do */ | 561 | /* we got something to do */ |
| 522 | return 0; | 562 | return 0; |
| @@ -619,7 +659,7 @@ check_next: | |||
| 619 | if (q->first_to_check == stop) | 659 | if (q->first_to_check == stop) |
| 620 | return q->first_to_check; | 660 | return q->first_to_check; |
| 621 | 661 | ||
| 622 | count = get_buf_states(q, q->first_to_check, &state, count); | 662 | count = get_buf_states(q, q->first_to_check, &state, count, 0); |
| 623 | if (!count) | 663 | if (!count) |
| 624 | return q->first_to_check; | 664 | return q->first_to_check; |
| 625 | 665 | ||
| @@ -638,7 +678,7 @@ check_next: | |||
| 638 | break; | 678 | break; |
| 639 | goto check_next; | 679 | goto check_next; |
| 640 | case SLSB_P_OUTPUT_ERROR: | 680 | case SLSB_P_OUTPUT_ERROR: |
| 641 | announce_buffer_error(q); | 681 | announce_buffer_error(q, count); |
| 642 | /* process the buffer, the upper layer will take care of it */ | 682 | /* process the buffer, the upper layer will take care of it */ |
| 643 | q->first_to_check = add_buf(q->first_to_check, count); | 683 | q->first_to_check = add_buf(q->first_to_check, count); |
| 644 | atomic_sub(count, &q->nr_buf_used); | 684 | atomic_sub(count, &q->nr_buf_used); |
| @@ -1451,23 +1491,38 @@ static inline int buf_in_between(int bufnr, int start, int count) | |||
| 1451 | static void handle_inbound(struct qdio_q *q, unsigned int callflags, | 1491 | static void handle_inbound(struct qdio_q *q, unsigned int callflags, |
| 1452 | int bufnr, int count) | 1492 | int bufnr, int count) |
| 1453 | { | 1493 | { |
| 1454 | unsigned long flags; | 1494 | int used, rc, diff; |
| 1455 | int used, rc; | ||
| 1456 | 1495 | ||
| 1457 | /* | 1496 | if (!q->u.in.polling) |
| 1458 | * do_QDIO could run in parallel with the queue tasklet so the | 1497 | goto set; |
| 1459 | * upper-layer programm could empty the ACK'ed buffer here. | 1498 | |
| 1460 | * If that happens we must clear the polling flag, otherwise | 1499 | /* protect against stop polling setting an ACK for an emptied slsb */ |
| 1461 | * qdio_stop_polling() could set the buffer to NOT_INIT after | 1500 | if (count == QDIO_MAX_BUFFERS_PER_Q) { |
| 1462 | * it was set to EMPTY which would kill us. | 1501 | /* overwriting everything, just delete polling status */ |
| 1463 | */ | 1502 | q->u.in.polling = 0; |
| 1464 | spin_lock_irqsave(&q->u.in.lock, flags); | 1503 | q->u.in.ack_count = 0; |
| 1465 | if (q->u.in.polling) | 1504 | goto set; |
| 1466 | if (buf_in_between(q->last_move_ftc, bufnr, count)) | 1505 | } else if (buf_in_between(q->last_move_ftc, bufnr, count)) { |
| 1506 | if (is_qebsm(q)) { | ||
| 1507 | /* partial overwrite, just update last_move_ftc */ | ||
| 1508 | diff = add_buf(bufnr, count); | ||
| 1509 | diff = sub_buf(diff, q->last_move_ftc); | ||
| 1510 | q->u.in.ack_count -= diff; | ||
| 1511 | if (q->u.in.ack_count <= 0) { | ||
| 1512 | q->u.in.polling = 0; | ||
| 1513 | q->u.in.ack_count = 0; | ||
| 1514 | /* TODO: must we set last_move_ftc to something meaningful? */ | ||
| 1515 | goto set; | ||
| 1516 | } | ||
| 1517 | q->last_move_ftc = add_buf(q->last_move_ftc, diff); | ||
| 1518 | } | ||
| 1519 | else | ||
| 1520 | /* the only ACK will be deleted, so stop polling */ | ||
| 1467 | q->u.in.polling = 0; | 1521 | q->u.in.polling = 0; |
| 1522 | } | ||
| 1468 | 1523 | ||
| 1524 | set: | ||
| 1469 | count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count); | 1525 | count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count); |
| 1470 | spin_unlock_irqrestore(&q->u.in.lock, flags); | ||
| 1471 | 1526 | ||
| 1472 | used = atomic_add_return(count, &q->nr_buf_used) - count; | 1527 | used = atomic_add_return(count, &q->nr_buf_used) - count; |
| 1473 | BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q); | 1528 | BUG_ON(used + count > QDIO_MAX_BUFFERS_PER_Q); |
| @@ -1535,7 +1590,7 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags, | |||
| 1535 | } | 1590 | } |
| 1536 | 1591 | ||
| 1537 | /* try to fast requeue buffers */ | 1592 | /* try to fast requeue buffers */ |
| 1538 | get_buf_state(q, prev_buf(bufnr), &state); | 1593 | get_buf_state(q, prev_buf(bufnr), &state, 0); |
| 1539 | if (state != SLSB_CU_OUTPUT_PRIMED) | 1594 | if (state != SLSB_CU_OUTPUT_PRIMED) |
| 1540 | qdio_kick_outbound_q(q); | 1595 | qdio_kick_outbound_q(q); |
| 1541 | else { | 1596 | else { |
