diff options
| author | Jan Glauber <jang@linux.vnet.ibm.com> | 2011-04-20 04:15:33 -0400 |
|---|---|---|
| committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2011-04-20 04:15:43 -0400 |
| commit | bffbbd2df4196a73ffdc16709866dd96eb66aad8 (patch) | |
| tree | d62c80319e3b63fc352afda230e618d792b9a5fb | |
| parent | e4c031b4f2515e9531d71c8aa779799231dbcd0c (diff) | |
[S390] qdio: reset error states immediately
The qdio hardware may surpress further interrupts as long as a SBAL is in
the error state. That can lead to unnotified data in the SBALs following
the error state. To prevent this behaviour change the SBAL[s] in error
state immediately to another program owned state so interrupts are again
received for further traffic on the device.
Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
| -rw-r--r-- | drivers/s390/cio/qdio_main.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index c532ba929ccd..e8f267eb8887 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count) | |||
| 407 | q->q_stats.nr_sbals[pos]++; | 407 | q->q_stats.nr_sbals[pos]++; |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | static void announce_buffer_error(struct qdio_q *q, int count) | 410 | static void process_buffer_error(struct qdio_q *q, int count) |
| 411 | { | 411 | { |
| 412 | unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT : | ||
| 413 | SLSB_P_OUTPUT_NOT_INIT; | ||
| 414 | |||
| 412 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; | 415 | q->qdio_error |= QDIO_ERROR_SLSB_STATE; |
| 413 | 416 | ||
| 414 | /* special handling for no target buffer empty */ | 417 | /* special handling for no target buffer empty */ |
| @@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count) | |||
| 426 | DBF_ERROR("F14:%2x F15:%2x", | 429 | DBF_ERROR("F14:%2x F15:%2x", |
| 427 | q->sbal[q->first_to_check]->element[14].flags & 0xff, | 430 | q->sbal[q->first_to_check]->element[14].flags & 0xff, |
| 428 | q->sbal[q->first_to_check]->element[15].flags & 0xff); | 431 | q->sbal[q->first_to_check]->element[15].flags & 0xff); |
| 432 | |||
| 433 | /* | ||
| 434 | * Interrupts may be avoided as long as the error is present | ||
| 435 | * so change the buffer state immediately to avoid starvation. | ||
| 436 | */ | ||
| 437 | set_buf_states(q, q->first_to_check, state, count); | ||
| 429 | } | 438 | } |
| 430 | 439 | ||
| 431 | static inline void inbound_primed(struct qdio_q *q, int count) | 440 | static inline void inbound_primed(struct qdio_q *q, int count) |
| @@ -506,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q) | |||
| 506 | account_sbals(q, count); | 515 | account_sbals(q, count); |
| 507 | break; | 516 | break; |
| 508 | case SLSB_P_INPUT_ERROR: | 517 | case SLSB_P_INPUT_ERROR: |
| 509 | announce_buffer_error(q, count); | 518 | process_buffer_error(q, count); |
| 510 | /* process the buffer, the upper layer will take care of it */ | ||
| 511 | q->first_to_check = add_buf(q->first_to_check, count); | 519 | q->first_to_check = add_buf(q->first_to_check, count); |
| 512 | atomic_sub(count, &q->nr_buf_used); | 520 | atomic_sub(count, &q->nr_buf_used); |
| 513 | if (q->irq_ptr->perf_stat_enabled) | 521 | if (q->irq_ptr->perf_stat_enabled) |
| @@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) | |||
| 677 | account_sbals(q, count); | 685 | account_sbals(q, count); |
| 678 | break; | 686 | break; |
| 679 | case SLSB_P_OUTPUT_ERROR: | 687 | case SLSB_P_OUTPUT_ERROR: |
| 680 | announce_buffer_error(q, count); | 688 | process_buffer_error(q, count); |
| 681 | /* process the buffer, the upper layer will take care of it */ | ||
| 682 | q->first_to_check = add_buf(q->first_to_check, count); | 689 | q->first_to_check = add_buf(q->first_to_check, count); |
| 683 | atomic_sub(count, &q->nr_buf_used); | 690 | atomic_sub(count, &q->nr_buf_used); |
| 684 | if (q->irq_ptr->perf_stat_enabled) | 691 | if (q->irq_ptr->perf_stat_enabled) |
