s390/qeth: fix SETIP command handling
authorJulian Wiedmann <jwi@linux.vnet.ibm.com>
Fri, 9 Feb 2018 10:03:50 +0000 (11:03 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Mar 2018 06:41:18 +0000 (22:41 -0800)
[ Upstream commit 1c5b2216fbb973a9410e0b06389740b5c1289171 ]

send_control_data() applies some special handling to SETIP v4 IPA
commands. But current code parses *all* command types for the SETIP
command code. Limit the command code check to IPA commands.

Fixes: 5b54e16f1a54 ("qeth: do not spin for SETIP ip assist command")
Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c

index 22b0704..6b1e835 100644 (file)
@@ -580,6 +580,11 @@ struct qeth_cmd_buffer {
        void (*callback) (struct qeth_channel *, struct qeth_cmd_buffer *);
 };
 
+static inline struct qeth_ipa_cmd *__ipa_cmd(struct qeth_cmd_buffer *iob)
+{
+       return (struct qeth_ipa_cmd *)(iob->data + IPA_PDU_HEADER_SIZE);
+}
+
 /**
  * definition of a qeth channel, used for read and write
  */
index 7c7a244..b60e81d 100644 (file)
@@ -2073,7 +2073,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        unsigned long flags;
        struct qeth_reply *reply = NULL;
        unsigned long timeout, event_timeout;
-       struct qeth_ipa_cmd *cmd;
+       struct qeth_ipa_cmd *cmd = NULL;
 
        QETH_CARD_TEXT(card, 2, "sendctl");
 
@@ -2100,10 +2100,13 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        while (atomic_cmpxchg(&card->write.irq_pending, 0, 1)) ;
        qeth_prepare_control_data(card, len, iob);
 
-       if (IS_IPA(iob->data))
+       if (IS_IPA(iob->data)) {
+               cmd = __ipa_cmd(iob);
                event_timeout = QETH_IPA_TIMEOUT;
-       else
+       } else {
                event_timeout = QETH_TIMEOUT;
+       }
+
        timeout = jiffies + event_timeout;
 
        QETH_CARD_TEXT(card, 6, "noirqpnd");
@@ -2128,9 +2131,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,
 
        /* we have only one long running ipassist, since we can ensure
           process context of this command we can sleep */
-       cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-       if ((cmd->hdr.command == IPA_CMD_SETIP) &&
-           (cmd->hdr.prot_version == QETH_PROT_IPV4)) {
+       if (cmd && cmd->hdr.command == IPA_CMD_SETIP &&
+           cmd->hdr.prot_version == QETH_PROT_IPV4) {
                if (!wait_event_timeout(reply->wait_q,
                    atomic_read(&reply->received), event_timeout))
                        goto time_err;