[S390] qdio enhanced SIGA (iqdio) support.
Klaus-Dieter Wacker [Fri, 10 Oct 2008 19:33:18 +0000 (21:33 +0200)]
Add support for z10 HiperSockets multiwrite SBALs on output
queues. This is used on LPAR with EDDP enabled devices.

Signed-off-by: Klaus-Dieter Wacker <kdwacker@de.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

index 6813772..4734c3f 100644 (file)
@@ -299,7 +299,13 @@ struct qdio_ssqd_desc {
        u8 mbccnt;
        u16 qdioac2;
        u64 sch_token;
-       u64:64;
+       u8 mro;
+       u8 mri;
+       u8:8;
+       u8 sbalic;
+       u16:16;
+       u8:8;
+       u8 mmwc;
 } __attribute__ ((packed));
 
 /* params are: ccw_device, qdio_error, queue_number,
index af86773..e3ea1d5 100644 (file)
@@ -203,6 +203,9 @@ struct qdio_output_q {
        /* PCIs are enabled for the queue */
        int pci_out_enabled;
 
+       /* IQDIO: output multiple buffers (enhanced SIGA) */
+       int use_enh_siga;
+
        /* timer to check for more outbound work */
        struct timer_list timer;
 };
index 719066e..a50682d 100644 (file)
@@ -316,6 +316,9 @@ static inline int qdio_do_siga_output(struct qdio_q *q, unsigned int *busy_bit)
        unsigned int fc = 0;
        unsigned long schid;
 
+       if (q->u.out.use_enh_siga) {
+               fc = 3;
+       }
        if (!is_qebsm(q))
                schid = *((u32 *)&q->irq_ptr->schid);
        else {
@@ -1449,6 +1452,8 @@ int qdio_establish(struct qdio_initialize *init_data)
        }
 
        qdio_setup_ssqd_info(irq_ptr);
+       sprintf(dbf_text, "qDmmwc%2x", irq_ptr->ssqd_desc.mmwc);
+       QDIO_DBF_TEXT2(0, setup, dbf_text);
        sprintf(dbf_text, "qib ac%2x", irq_ptr->qib.ac);
        QDIO_DBF_TEXT2(0, setup, dbf_text);
 
@@ -1621,12 +1626,21 @@ static void handle_outbound(struct qdio_q *q, unsigned int callflags,
                if (multicast_outbound(q))
                        qdio_kick_outbound_q(q);
                else
-                       /*
-                        * One siga-w per buffer required for unicast
-                        * HiperSockets.
-                        */
-                       while (count--)
+                       if ((q->irq_ptr->ssqd_desc.mmwc > 1) &&
+                           (count > 1) &&
+                           (count <= q->irq_ptr->ssqd_desc.mmwc)) {
+                               /* exploit enhanced SIGA */
+                               q->u.out.use_enh_siga = 1;
                                qdio_kick_outbound_q(q);
+                       } else {
+                               /*
+                               * One siga-w per buffer required for unicast
+                               * HiperSockets.
+                               */
+                               q->u.out.use_enh_siga = 0;
+                               while (count--)
+                                       qdio_kick_outbound_q(q);
+                       }
                goto out;
        }