Commit bffbbd2d authored by Jan Glauber's avatar Jan Glauber Committed by Martin Schwidefsky

[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: default avatarJan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent e4c031b4
...@@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count) ...@@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count)
q->q_stats.nr_sbals[pos]++; q->q_stats.nr_sbals[pos]++;
} }
static void announce_buffer_error(struct qdio_q *q, int count) static void process_buffer_error(struct qdio_q *q, int count)
{ {
unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
SLSB_P_OUTPUT_NOT_INIT;
q->qdio_error |= QDIO_ERROR_SLSB_STATE; q->qdio_error |= QDIO_ERROR_SLSB_STATE;
/* special handling for no target buffer empty */ /* special handling for no target buffer empty */
...@@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count) ...@@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count)
DBF_ERROR("F14:%2x F15:%2x", DBF_ERROR("F14:%2x F15:%2x",
q->sbal[q->first_to_check]->element[14].flags & 0xff, q->sbal[q->first_to_check]->element[14].flags & 0xff,
q->sbal[q->first_to_check]->element[15].flags & 0xff); q->sbal[q->first_to_check]->element[15].flags & 0xff);
/*
* Interrupts may be avoided as long as the error is present
* so change the buffer state immediately to avoid starvation.
*/
set_buf_states(q, q->first_to_check, state, count);
} }
static inline void inbound_primed(struct qdio_q *q, int count) 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,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
account_sbals(q, count); account_sbals(q, count);
break; break;
case SLSB_P_INPUT_ERROR: case SLSB_P_INPUT_ERROR:
announce_buffer_error(q, count); process_buffer_error(q, count);
/* process the buffer, the upper layer will take care of it */
q->first_to_check = add_buf(q->first_to_check, count); q->first_to_check = add_buf(q->first_to_check, count);
atomic_sub(count, &q->nr_buf_used); atomic_sub(count, &q->nr_buf_used);
if (q->irq_ptr->perf_stat_enabled) if (q->irq_ptr->perf_stat_enabled)
...@@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) ...@@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
account_sbals(q, count); account_sbals(q, count);
break; break;
case SLSB_P_OUTPUT_ERROR: case SLSB_P_OUTPUT_ERROR:
announce_buffer_error(q, count); process_buffer_error(q, count);
/* process the buffer, the upper layer will take care of it */
q->first_to_check = add_buf(q->first_to_check, count); q->first_to_check = add_buf(q->first_to_check, count);
atomic_sub(count, &q->nr_buf_used); atomic_sub(count, &q->nr_buf_used);
if (q->irq_ptr->perf_stat_enabled) if (q->irq_ptr->perf_stat_enabled)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment