summaryrefslogtreecommitdiff
path: root/drivers/s390/cio
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/qdio.h2
-rw-r--r--drivers/s390/cio/qdio_main.c8
-rw-r--r--drivers/s390/cio/qdio_setup.c1
3 files changed, 10 insertions, 1 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index 9b6ea3ca3ece..a77aa9109cfd 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -249,6 +249,8 @@ struct qdio_output_q {
int use_enh_siga;
/* timer to check for more outbound work */
struct timer_list timer;
+ /* used SBALs before tasklet schedule */
+ int scan_threshold;
};
/*
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 6621de94f3ad..4c0109900c74 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -1492,7 +1492,13 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags,
qperf_inc(q, fast_requeue);
out:
- tasklet_schedule(&q->tasklet);
+ /* in case of SIGA errors we must process the error immediately */
+ if (used >= q->u.out.scan_threshold || rc)
+ tasklet_schedule(&q->tasklet);
+ else
+ /* free the SBALs in case of no further traffic */
+ if (!timer_pending(&q->u.out.timer))
+ mod_timer(&q->u.out.timer, jiffies + HZ);
return rc;
}
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index a13cf7ec64b2..635f35dc8466 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -178,6 +178,7 @@ static void setup_queues(struct qdio_irq *irq_ptr,
setup_queues_misc(q, irq_ptr, qdio_init->output_handler, i);
q->is_input_q = 0;
+ q->u.out.scan_threshold = qdio_init->scan_threshold;
setup_storage_lists(q, irq_ptr, output_sbal_array, i);
output_sbal_array += QDIO_MAX_BUFFERS_PER_Q;