|
@@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count)
|
|
|
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;
|
|
|
|
|
|
/* special handling for no target buffer empty */
|
|
@@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count)
|
|
|
DBF_ERROR("F14:%2x F15:%2x",
|
|
|
q->sbal[q->first_to_check]->element[14].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)
|
|
@@ -506,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
|
|
|
account_sbals(q, count);
|
|
|
break;
|
|
|
case SLSB_P_INPUT_ERROR:
|
|
|
- announce_buffer_error(q, count);
|
|
|
- /* process the buffer, the upper layer will take care of it */
|
|
|
+ process_buffer_error(q, count);
|
|
|
q->first_to_check = add_buf(q->first_to_check, count);
|
|
|
atomic_sub(count, &q->nr_buf_used);
|
|
|
if (q->irq_ptr->perf_stat_enabled)
|
|
@@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
|
|
|
account_sbals(q, count);
|
|
|
break;
|
|
|
case SLSB_P_OUTPUT_ERROR:
|
|
|
- announce_buffer_error(q, count);
|
|
|
- /* process the buffer, the upper layer will take care of it */
|
|
|
+ process_buffer_error(q, count);
|
|
|
q->first_to_check = add_buf(q->first_to_check, count);
|
|
|
atomic_sub(count, &q->nr_buf_used);
|
|
|
if (q->irq_ptr->perf_stat_enabled)
|