[S390] qdio: outbound tasklet scan threshold
authorJan Glauber <jang@linux.vnet.ibm.com>
Wed, 5 Jan 2011 11:47:50 +0000 (12:47 +0100)
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>
Wed, 5 Jan 2011 11:47:28 +0000 (12:47 +0100)
Introduce a scan treshold for the qdio outbound queues. By setting the
threshold the driver can tell qdio after how much used SBALs qdio
should schedule the outbound tasklet that scans the queue for finished
SBALs. The threshold is specific by the drivers because a
Hipersockets device is much faster in utilizing outbound buffers than a
ZFCP or OSA device.

The default values after how many used SBALs the tasklet should run are:

OSA:          > 31 SBALs
Hipersockets: > 7 SBALs
zfcp:         > 55 SBALs

Signed-off-by: Jan Glauber <jang@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/qdio.h
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c
drivers/s390/net/qeth_core_main.c
drivers/s390/scsi/zfcp_qdio.c

index 46e96bc1f5a155ea988961b0078ecbdc854c973e..350e7ee5952daaa025ed239189a1df2f78f9142d 100644 (file)
@@ -361,6 +361,7 @@ struct qdio_initialize {
        qdio_handler_t *input_handler;
        qdio_handler_t *output_handler;
        void (*queue_start_poll) (struct ccw_device *, int, unsigned long);
+       int scan_threshold;
        unsigned long int_parm;
        void **input_sbal_addr_array;
        void **output_sbal_addr_array;
index 9b6ea3ca3ececdfac9a63b1fc232c28e52764cdd..a77aa9109cfdddd30dd3c0129c38d0bdcb03dec0 100644 (file)
@@ -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;
 };
 
 /*
index 6621de94f3ad86057fd78515b8e07b681d11f9a7..4c0109900c7413d93b7a4a49c3d381e87118a267 100644 (file)
@@ -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;
 }
 
index a13cf7ec64b2b0e0ab558694e4d77e8487a9ab36..635f35dc84662c552b8e489633906692bcad8248 100644 (file)
@@ -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;
 
index e6b2df0e73f56a4b143365be8302875c600c49bc..f65320babf71de9bc394ee2c7c6922d3d69fd415 100644 (file)
@@ -3831,6 +3831,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
        init_data.int_parm               = (unsigned long) card;
        init_data.input_sbal_addr_array  = (void **) in_sbal_ptrs;
        init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
+       init_data.scan_threshold =
+               (card->info.type == QETH_CARD_TYPE_IQD) ? 8 : 32;
 
        if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED,
                QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) {
index a0554beb4179efde170b463689f53b1fbf637290..5ae40ef586a89f6a3204ea54850e5cbbdbadeb8a 100644 (file)
@@ -292,6 +292,8 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
        id->int_parm = (unsigned long) qdio;
        id->input_sbal_addr_array = (void **) (qdio->res_q);
        id->output_sbal_addr_array = (void **) (qdio->req_q);
+       id->scan_threshold =
+               QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
 }
 
 /**