Commit c70d82e9 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Vasily Gorbik

s390/qdio: add IRQ reduction for error SBALs

SBALs in PRIMED or ERROR state represent new work on the Input Queue.
But while inbound_primed() does all sorts of ACK management for new
PRIMED work, the same handling is currently missing for ERROR work.
In particular the path for ERROR work doesn't clear up _old_ ACKs.

Treat ERROR work the same as PRIMED work, but consider that the QEBSM
auto-ACK feature doesn't apply here. So we need to set the ACK manually,
as if it was a non-QEBSM device.

Note that this doesn't aspire to actually improve performance, the main
goal is to just unify the code paths and have consistent behaviour.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 1db85d0e
...@@ -438,15 +438,12 @@ static void process_buffer_error(struct qdio_q *q, unsigned int start, ...@@ -438,15 +438,12 @@ static void process_buffer_error(struct qdio_q *q, unsigned int start,
q->sbal[start]->element[15].sflags); q->sbal[start]->element[15].sflags);
} }
static inline void inbound_primed(struct qdio_q *q, unsigned int start, static inline void inbound_handle_work(struct qdio_q *q, unsigned int start,
int count) int count, bool auto_ack)
{ {
int new; int new;
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim:%1d %02x", q->nr, count); if (auto_ack) {
/* for QEBSM the ACK was already set by EQBS */
if (is_qebsm(q)) {
if (!q->u.in.ack_count) { if (!q->u.in.ack_count) {
q->u.in.ack_count = count; q->u.in.ack_count = count;
q->u.in.ack_start = start; q->u.in.ack_start = start;
...@@ -507,19 +504,21 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start) ...@@ -507,19 +504,21 @@ static int get_inbound_buffer_frontier(struct qdio_q *q, unsigned int start)
switch (state) { switch (state) {
case SLSB_P_INPUT_PRIMED: case SLSB_P_INPUT_PRIMED:
inbound_primed(q, start, count); DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim:%1d %02x", q->nr,
count);
inbound_handle_work(q, start, count, is_qebsm(q));
if (atomic_sub_return(count, &q->nr_buf_used) == 0) if (atomic_sub_return(count, &q->nr_buf_used) == 0)
qperf_inc(q, inbound_queue_full); qperf_inc(q, inbound_queue_full);
if (q->irq_ptr->perf_stat_enabled) if (q->irq_ptr->perf_stat_enabled)
account_sbals(q, count); account_sbals(q, count);
return count; return count;
case SLSB_P_INPUT_ERROR: case SLSB_P_INPUT_ERROR:
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in err:%1d %02x", q->nr,
count);
process_buffer_error(q, start, count); process_buffer_error(q, start, count);
/* inbound_handle_work(q, start, count, false);
* Interrupts may be avoided as long as the error is present
* so change the buffer state immediately to avoid starvation.
*/
set_buf_states(q, start, SLSB_P_INPUT_NOT_INIT, count);
if (atomic_sub_return(count, &q->nr_buf_used) == 0) if (atomic_sub_return(count, &q->nr_buf_used) == 0)
qperf_inc(q, inbound_queue_full); qperf_inc(q, inbound_queue_full);
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