s390/qeth: enhance TSO control sequence
authorJulian Wiedmann <jwi@linux.ibm.com>
Fri, 12 Oct 2018 15:27:13 +0000 (17:27 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 12 Oct 2018 18:27:00 +0000 (11:27 -0700)
TSO6 requires the full programming sequence, and not just a simple
START command. This implements the additional ENABLE command, and adds
some sanity checks that were missing for the START command.

Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_mpc.h

index 92e539d..ab022b6 100644 (file)
@@ -5394,6 +5394,21 @@ static int qeth_setassparms_inspect_rc(struct qeth_ipa_cmd *cmd)
        return cmd->hdr.return_code;
 }
 
+static int qeth_setassparms_get_caps_cb(struct qeth_card *card,
+                                       struct qeth_reply *reply,
+                                       unsigned long data)
+{
+       struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+       struct qeth_ipa_caps *caps = reply->param;
+
+       if (qeth_setassparms_inspect_rc(cmd))
+               return 0;
+
+       caps->supported = cmd->data.setassparms.data.caps.supported;
+       caps->enabled = cmd->data.setassparms.data.caps.enabled;
+       return 0;
+}
+
 int qeth_setassparms_cb(struct qeth_card *card,
                        struct qeth_reply *reply, unsigned long data)
 {
@@ -6396,6 +6411,20 @@ static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype,
        return rc ? -EIO : 0;
 }
 
+static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply,
+                            unsigned long data)
+{
+       struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
+       struct qeth_tso_start_data *tso_data = reply->param;
+
+       if (qeth_setassparms_inspect_rc(cmd))
+               return 0;
+
+       tso_data->mss = cmd->data.setassparms.data.tso.mss;
+       tso_data->supported = cmd->data.setassparms.data.tso.supported;
+       return 0;
+}
+
 static int qeth_set_tso_off(struct qeth_card *card,
                            enum qeth_prot_versions prot)
 {
@@ -6406,8 +6435,52 @@ static int qeth_set_tso_off(struct qeth_card *card,
 static int qeth_set_tso_on(struct qeth_card *card,
                           enum qeth_prot_versions prot)
 {
-       return qeth_send_simple_setassparms_prot(card, IPA_OUTBOUND_TSO,
-                                                IPA_CMD_ASS_START, 0, prot);
+       struct qeth_tso_start_data tso_data;
+       struct qeth_cmd_buffer *iob;
+       struct qeth_ipa_caps caps;
+       int rc;
+
+       iob = qeth_get_setassparms_cmd(card, IPA_OUTBOUND_TSO,
+                                      IPA_CMD_ASS_START, 0, prot);
+       if (!iob)
+               return -ENOMEM;
+
+       rc = qeth_send_setassparms(card, iob, 0, 0 /* unused */,
+                                  qeth_start_tso_cb, &tso_data);
+       if (rc)
+               return rc;
+
+       if (!tso_data.mss || !(tso_data.supported & QETH_IPA_LARGE_SEND_TCP)) {
+               qeth_set_tso_off(card, prot);
+               return -EOPNOTSUPP;
+       }
+
+       iob = qeth_get_setassparms_cmd(card, IPA_OUTBOUND_TSO,
+                                      IPA_CMD_ASS_ENABLE, sizeof(caps), prot);
+       if (!iob) {
+               qeth_set_tso_off(card, prot);
+               return -ENOMEM;
+       }
+
+       /* enable TSO capability */
+       caps.supported = 0;
+       caps.enabled = QETH_IPA_LARGE_SEND_TCP;
+       rc = qeth_send_setassparms(card, iob, sizeof(caps), (long) &caps,
+                                  qeth_setassparms_get_caps_cb, &caps);
+       if (rc) {
+               qeth_set_tso_off(card, prot);
+               return rc;
+       }
+
+       if (!qeth_ipa_caps_supported(&caps, QETH_IPA_LARGE_SEND_TCP) ||
+           !qeth_ipa_caps_enabled(&caps, QETH_IPA_LARGE_SEND_TCP)) {
+               qeth_set_tso_off(card, prot);
+               return -EOPNOTSUPP;
+       }
+
+       dev_info(&card->gdev->dev, "TSOv%u enabled (MSS: %u)\n", prot,
+                tso_data.mss);
+       return 0;
 }
 
 static int qeth_set_ipa_tso(struct qeth_card *card, bool on,
index aa5de1f..e850904 100644 (file)
@@ -56,6 +56,21 @@ static inline bool qeth_intparm_is_iob(unsigned long intparm)
 #define IPA_CMD_INITIATOR_OSA_REPLY   0x81
 #define IPA_CMD_PRIM_VERSION_NO 0x01
 
+struct qeth_ipa_caps {
+       u32 supported;
+       u32 enabled;
+};
+
+static inline bool qeth_ipa_caps_supported(struct qeth_ipa_caps *caps, u32 mask)
+{
+       return (caps->supported & mask) == mask;
+}
+
+static inline bool qeth_ipa_caps_enabled(struct qeth_ipa_caps *caps, u32 mask)
+{
+       return (caps->enabled & mask) == mask;
+}
+
 enum qeth_card_types {
        QETH_CARD_TYPE_OSD     = 1,
        QETH_CARD_TYPE_IQD     = 5,
@@ -405,14 +420,25 @@ struct qeth_checksum_cmd {
        __u32 enabled;
 } __packed;
 
+enum qeth_ipa_large_send_caps {
+       QETH_IPA_LARGE_SEND_TCP         = 0x00000001,
+};
+
+struct qeth_tso_start_data {
+       u32 mss;
+       u32 supported;
+};
+
 /* SETASSPARMS IPA Command: */
 struct qeth_ipacmd_setassparms {
        struct qeth_ipacmd_setassparms_hdr hdr;
        union {
                __u32 flags_32bit;
+               struct qeth_ipa_caps caps;
                struct qeth_checksum_cmd chksum;
                struct qeth_arp_cache_entry add_arp_entry;
                struct qeth_arp_query_data query_arp;
+               struct qeth_tso_start_data tso;
                __u8 ip[16];
        } data;
 } __attribute__ ((packed));