qeth: allow dynamic change of rx checksumming
authorFrank Blaschka <frank.blaschka@de.ibm.com>
Thu, 12 Nov 2009 00:11:45 +0000 (00:11 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Nov 2009 10:42:09 +0000 (02:42 -0800)
Technically there is no need to set the card offline to change
RX checksumming. Get rid of this stupid limitation.

Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/s390/net/qeth_l3.h
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c

index ffa6fe4da26a337c6820827473dc31f56778a85a..321988fa9f7d514cadb0a3be82d7a09227a58b13 100644 (file)
@@ -61,5 +61,6 @@ int qeth_l3_add_rxip(struct qeth_card *, enum qeth_prot_versions, const u8 *);
 void qeth_l3_del_rxip(struct qeth_card *card, enum qeth_prot_versions,
                        const u8 *);
 int qeth_l3_set_large_send(struct qeth_card *, enum qeth_large_send_types);
+int qeth_l3_set_rx_csum(struct qeth_card *, enum qeth_checksum_types);
 
 #endif /* __QETH_L3_H__ */
index 2048b4354216b28609ada1c6cbf7866989838727..fd1b6ed3721f312800b2ec70c2ab6d6ebdcef38e 100644 (file)
@@ -1465,6 +1465,35 @@ static int qeth_l3_send_checksum_command(struct qeth_card *card)
        return 0;
 }
 
+int qeth_l3_set_rx_csum(struct qeth_card *card,
+       enum qeth_checksum_types csum_type)
+{
+       int rc = 0;
+
+       if (card->options.checksum_type == HW_CHECKSUMMING) {
+               if ((csum_type != HW_CHECKSUMMING) &&
+                       (card->state != CARD_STATE_DOWN)) {
+                       rc = qeth_l3_send_simple_setassparms(card,
+                               IPA_INBOUND_CHECKSUM, IPA_CMD_ASS_STOP, 0);
+                       if (rc)
+                               return -EIO;
+               }
+       } else {
+               if (csum_type == HW_CHECKSUMMING) {
+                       if (card->state != CARD_STATE_DOWN) {
+                               if (!qeth_is_supported(card,
+                                   IPA_INBOUND_CHECKSUM))
+                                       return -EPERM;
+                               rc = qeth_l3_send_checksum_command(card);
+                               if (rc)
+                                       return -EIO;
+                       }
+               }
+       }
+       card->options.checksum_type = csum_type;
+       return rc;
+}
+
 static int qeth_l3_start_ipa_checksum(struct qeth_card *card)
 {
        int rc = 0;
@@ -2954,27 +2983,14 @@ static u32 qeth_l3_ethtool_get_rx_csum(struct net_device *dev)
 static int qeth_l3_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
        struct qeth_card *card = dev->ml_priv;
-       enum qeth_card_states old_state;
        enum qeth_checksum_types csum_type;
 
-       if ((card->state != CARD_STATE_UP) &&
-           (card->state != CARD_STATE_DOWN))
-               return -EPERM;
-
        if (data)
                csum_type = HW_CHECKSUMMING;
        else
                csum_type = SW_CHECKSUMMING;
 
-       if (card->options.checksum_type != csum_type) {
-               old_state = card->state;
-               if (card->state == CARD_STATE_UP)
-                       __qeth_l3_set_offline(card->gdev, 1);
-               card->options.checksum_type = csum_type;
-               if (old_state == CARD_STATE_UP)
-                       __qeth_l3_set_online(card->gdev, 1);
-       }
-       return 0;
+       return qeth_l3_set_rx_csum(card, csum_type);
 }
 
 static int qeth_l3_ethtool_set_tso(struct net_device *dev, u32 data)
index 88f200c8ea3c1debd72c7de091e2f81ca2af13e8..3360b0941aa1b411dde221e4e1dc2f8f19f4a6de 100644 (file)
@@ -293,25 +293,26 @@ static ssize_t qeth_l3_dev_checksum_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct qeth_card *card = dev_get_drvdata(dev);
+       enum qeth_checksum_types csum_type;
        char *tmp;
+       int rc;
 
        if (!card)
                return -EINVAL;
 
-       if ((card->state != CARD_STATE_DOWN) &&
-           (card->state != CARD_STATE_RECOVER))
-               return -EPERM;
-
        tmp = strsep((char **) &buf, "\n");
        if (!strcmp(tmp, "sw_checksumming"))
-               card->options.checksum_type = SW_CHECKSUMMING;
+               csum_type = SW_CHECKSUMMING;
        else if (!strcmp(tmp, "hw_checksumming"))
-               card->options.checksum_type = HW_CHECKSUMMING;
+               csum_type = HW_CHECKSUMMING;
        else if (!strcmp(tmp, "no_checksumming"))
-               card->options.checksum_type = NO_CHECKSUMMING;
-       else {
+               csum_type = NO_CHECKSUMMING;
+       else
                return -EINVAL;
-       }
+
+       rc = qeth_l3_set_rx_csum(card, csum_type);
+       if (rc)
+               return rc;
        return count;
 }