diff options
author | Jan Glauber <jang@linux.vnet.ibm.com> | 2009-03-26 10:24:29 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 10:24:21 -0400 |
commit | e85dea0e415617b5c5627f38c71b33fbc7f94a85 (patch) | |
tree | 59400d25cb978f66e3b2906dbed01813b617e0ba /drivers/s390 | |
parent | 3fdf1e18cbc7c58f2d5604315ddae3596725bc6a (diff) |
[S390] qdio: seperate last move index and polling index
The index value that indicated that the input queue moved was also used to
store the index of the first acknowledged buffer. For non-qebsm only the
newest buffer is acknowledged which may be different from the last move index
so two seperate values are needed to track the input queue.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/qdio.h | 5 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_debug.c | 3 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 38 |
3 files changed, 23 insertions, 23 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 42f2b09631b6..57807f5ffe84 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -186,6 +186,9 @@ struct qdio_input_q { | |||
186 | /* input buffer acknowledgement flag */ | 186 | /* input buffer acknowledgement flag */ |
187 | int polling; | 187 | int polling; |
188 | 188 | ||
189 | /* first ACK'ed buffer */ | ||
190 | int ack_start; | ||
191 | |||
189 | /* how much sbals are acknowledged with qebsm */ | 192 | /* how much sbals are acknowledged with qebsm */ |
190 | int ack_count; | 193 | int ack_count; |
191 | 194 | ||
@@ -234,7 +237,7 @@ struct qdio_q { | |||
234 | int first_to_check; | 237 | int first_to_check; |
235 | 238 | ||
236 | /* first_to_check of the last time */ | 239 | /* first_to_check of the last time */ |
237 | int last_move_ftc; | 240 | int last_move; |
238 | 241 | ||
239 | /* beginning position for calling the program */ | 242 | /* beginning position for calling the program */ |
240 | int first_to_kick; | 243 | int first_to_kick; |
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index da7afb04e71f..e3434b34f86c 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c | |||
@@ -63,8 +63,9 @@ static int qstat_show(struct seq_file *m, void *v) | |||
63 | seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); | 63 | seq_printf(m, "device state indicator: %d\n", *(u32 *)q->irq_ptr->dsci); |
64 | seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); | 64 | seq_printf(m, "nr_used: %d\n", atomic_read(&q->nr_buf_used)); |
65 | seq_printf(m, "ftc: %d\n", q->first_to_check); | 65 | seq_printf(m, "ftc: %d\n", q->first_to_check); |
66 | seq_printf(m, "last_move_ftc: %d\n", q->last_move_ftc); | 66 | seq_printf(m, "last_move: %d\n", q->last_move); |
67 | seq_printf(m, "polling: %d\n", q->u.in.polling); | 67 | seq_printf(m, "polling: %d\n", q->u.in.polling); |
68 | seq_printf(m, "ack start: %d\n", q->u.in.ack_start); | ||
68 | seq_printf(m, "ack count: %d\n", q->u.in.ack_count); | 69 | seq_printf(m, "ack count: %d\n", q->u.in.ack_count); |
69 | seq_printf(m, "slsb buffer states:\n"); | 70 | seq_printf(m, "slsb buffer states:\n"); |
70 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); | 71 | seq_printf(m, "|0 |8 |16 |24 |32 |40 |48 |56 63|\n"); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 61ba765936a6..31b9318149ba 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -380,11 +380,11 @@ inline void qdio_stop_polling(struct qdio_q *q) | |||
380 | 380 | ||
381 | /* show the card that we are not polling anymore */ | 381 | /* show the card that we are not polling anymore */ |
382 | if (is_qebsm(q)) { | 382 | if (is_qebsm(q)) { |
383 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, | 383 | set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, |
384 | q->u.in.ack_count); | 384 | q->u.in.ack_count); |
385 | q->u.in.ack_count = 0; | 385 | q->u.in.ack_count = 0; |
386 | } else | 386 | } else |
387 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | 387 | set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); |
388 | } | 388 | } |
389 | 389 | ||
390 | static void announce_buffer_error(struct qdio_q *q, int count) | 390 | static void announce_buffer_error(struct qdio_q *q, int count) |
@@ -419,15 +419,15 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
419 | if (!q->u.in.polling) { | 419 | if (!q->u.in.polling) { |
420 | q->u.in.polling = 1; | 420 | q->u.in.polling = 1; |
421 | q->u.in.ack_count = count; | 421 | q->u.in.ack_count = count; |
422 | q->last_move_ftc = q->first_to_check; | 422 | q->u.in.ack_start = q->first_to_check; |
423 | return; | 423 | return; |
424 | } | 424 | } |
425 | 425 | ||
426 | /* delete the previous ACK's */ | 426 | /* delete the previous ACK's */ |
427 | set_buf_states(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT, | 427 | set_buf_states(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT, |
428 | q->u.in.ack_count); | 428 | q->u.in.ack_count); |
429 | q->u.in.ack_count = count; | 429 | q->u.in.ack_count = count; |
430 | q->last_move_ftc = q->first_to_check; | 430 | q->u.in.ack_start = q->first_to_check; |
431 | return; | 431 | return; |
432 | } | 432 | } |
433 | 433 | ||
@@ -439,18 +439,13 @@ static inline void inbound_primed(struct qdio_q *q, int count) | |||
439 | if (q->u.in.polling) { | 439 | if (q->u.in.polling) { |
440 | /* reset the previous ACK but first set the new one */ | 440 | /* reset the previous ACK but first set the new one */ |
441 | set_buf_state(q, new, SLSB_P_INPUT_ACK); | 441 | set_buf_state(q, new, SLSB_P_INPUT_ACK); |
442 | set_buf_state(q, q->last_move_ftc, SLSB_P_INPUT_NOT_INIT); | 442 | set_buf_state(q, q->u.in.ack_start, SLSB_P_INPUT_NOT_INIT); |
443 | } else { | 443 | } else { |
444 | q->u.in.polling = 1; | 444 | q->u.in.polling = 1; |
445 | set_buf_state(q, new, SLSB_P_INPUT_ACK); | 445 | set_buf_state(q, new, SLSB_P_INPUT_ACK); |
446 | } | 446 | } |
447 | 447 | ||
448 | /* | 448 | q->u.in.ack_start = new; |
449 | * last_move_ftc points to the ACK'ed buffer and not to the last turns | ||
450 | * first_to_check like for qebsm. Since it is only used to check if | ||
451 | * the queue front moved in qdio_inbound_q_done this is not a problem. | ||
452 | */ | ||
453 | q->last_move_ftc = new; | ||
454 | count--; | 449 | count--; |
455 | if (!count) | 450 | if (!count) |
456 | return; | 451 | return; |
@@ -527,7 +522,8 @@ int qdio_inbound_q_moved(struct qdio_q *q) | |||
527 | 522 | ||
528 | bufnr = get_inbound_buffer_frontier(q); | 523 | bufnr = get_inbound_buffer_frontier(q); |
529 | 524 | ||
530 | if ((bufnr != q->last_move_ftc) || q->qdio_error) { | 525 | if ((bufnr != q->last_move) || q->qdio_error) { |
526 | q->last_move = bufnr; | ||
531 | if (!need_siga_sync(q) && !pci_out_supported(q)) | 527 | if (!need_siga_sync(q) && !pci_out_supported(q)) |
532 | q->u.in.timestamp = get_usecs(); | 528 | q->u.in.timestamp = get_usecs(); |
533 | 529 | ||
@@ -702,8 +698,8 @@ static inline int qdio_outbound_q_moved(struct qdio_q *q) | |||
702 | 698 | ||
703 | bufnr = get_outbound_buffer_frontier(q); | 699 | bufnr = get_outbound_buffer_frontier(q); |
704 | 700 | ||
705 | if ((bufnr != q->last_move_ftc) || q->qdio_error) { | 701 | if ((bufnr != q->last_move) || q->qdio_error) { |
706 | q->last_move_ftc = bufnr; | 702 | q->last_move = bufnr; |
707 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); | 703 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out moved:%1d", q->nr); |
708 | return 1; | 704 | return 1; |
709 | } else | 705 | } else |
@@ -748,7 +744,7 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) | |||
748 | int start, end, count; | 744 | int start, end, count; |
749 | 745 | ||
750 | start = q->first_to_kick; | 746 | start = q->first_to_kick; |
751 | end = q->last_move_ftc; | 747 | end = q->last_move; |
752 | if (end >= start) | 748 | if (end >= start) |
753 | count = end - start; | 749 | count = end - start; |
754 | else | 750 | else |
@@ -764,7 +760,7 @@ static void qdio_kick_outbound_handler(struct qdio_q *q) | |||
764 | q->irq_ptr->int_parm); | 760 | q->irq_ptr->int_parm); |
765 | 761 | ||
766 | /* for the next time: */ | 762 | /* for the next time: */ |
767 | q->first_to_kick = q->last_move_ftc; | 763 | q->first_to_kick = q->last_move; |
768 | q->qdio_error = 0; | 764 | q->qdio_error = 0; |
769 | } | 765 | } |
770 | 766 | ||
@@ -1475,18 +1471,18 @@ static void handle_inbound(struct qdio_q *q, unsigned int callflags, | |||
1475 | q->u.in.polling = 0; | 1471 | q->u.in.polling = 0; |
1476 | q->u.in.ack_count = 0; | 1472 | q->u.in.ack_count = 0; |
1477 | goto set; | 1473 | goto set; |
1478 | } else if (buf_in_between(q->last_move_ftc, bufnr, count)) { | 1474 | } else if (buf_in_between(q->u.in.ack_start, bufnr, count)) { |
1479 | if (is_qebsm(q)) { | 1475 | if (is_qebsm(q)) { |
1480 | /* partial overwrite, just update last_move_ftc */ | 1476 | /* partial overwrite, just update ack_start */ |
1481 | diff = add_buf(bufnr, count); | 1477 | diff = add_buf(bufnr, count); |
1482 | diff = sub_buf(diff, q->last_move_ftc); | 1478 | diff = sub_buf(diff, q->u.in.ack_start); |
1483 | q->u.in.ack_count -= diff; | 1479 | q->u.in.ack_count -= diff; |
1484 | if (q->u.in.ack_count <= 0) { | 1480 | if (q->u.in.ack_count <= 0) { |
1485 | q->u.in.polling = 0; | 1481 | q->u.in.polling = 0; |
1486 | q->u.in.ack_count = 0; | 1482 | q->u.in.ack_count = 0; |
1487 | goto set; | 1483 | goto set; |
1488 | } | 1484 | } |
1489 | q->last_move_ftc = add_buf(q->last_move_ftc, diff); | 1485 | q->u.in.ack_start = add_buf(q->u.in.ack_start, diff); |
1490 | } | 1486 | } |
1491 | else | 1487 | else |
1492 | /* the only ACK will be deleted, so stop polling */ | 1488 | /* the only ACK will be deleted, so stop polling */ |