summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wippel <hwippel@linux.vnet.ibm.com>2016-06-16 17:19:01 +0300
committerDavid S. Miller <davem@davemloft.net>2016-06-17 08:16:13 +0300
commit6c7cd7124493de05d01ea53bdbfcf35918dae4c3 (patch)
tree188c731ef8b450eb157f12c90a0b982f3b7d8095
parent9bdc441102f012b70f51e1ca73b603312fff8b5d (diff)
downloadlinux-6c7cd7124493de05d01ea53bdbfcf35918dae4c3.tar.xz
qeth: improve set_features error handling
The function set_features is called to configure network device features on the hardware. If errors occur, the network device features should reflect the changed hardware state and the function should return an error in order to notify the user. In case of an error, the current implementation does not necessarily save the changed hardware state in the network device features before an error is returned. This patch improves error handling by saving features, that could be changed, to the network device features before returning an error. If the device is not running, an additional check in fix_features removes features, that require hardware changes, before they are passed to set_features. Thus, the corresponding check was removed in set_features. Signed-off-by: Hans Wippel <hwippel@linux.vnet.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/s390/net/qeth_core_main.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 19a6ee01bee3..44d32000a09e 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -6125,27 +6125,38 @@ static int qeth_set_ipa_tso(struct qeth_card *card, int on)
int qeth_set_features(struct net_device *dev, netdev_features_t features)
{
struct qeth_card *card = dev->ml_priv;
- netdev_features_t changed = card->dev->features ^ features;
+ netdev_features_t changed = dev->features ^ features;
int rc = 0;
QETH_DBF_TEXT(SETUP, 2, "setfeat");
QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
- if (card->state == CARD_STATE_DOWN ||
- card->state == CARD_STATE_RECOVER)
- return 0;
-
- if ((changed & NETIF_F_IP_CSUM))
+ if ((changed & NETIF_F_IP_CSUM)) {
rc = qeth_set_ipa_csum(card,
features & NETIF_F_IP_CSUM ? 1 : 0,
IPA_OUTBOUND_CHECKSUM);
- if ((changed & NETIF_F_RXCSUM))
- rc |= qeth_set_ipa_csum(card,
+ if (rc)
+ changed ^= NETIF_F_IP_CSUM;
+ }
+ if ((changed & NETIF_F_RXCSUM)) {
+ rc = qeth_set_ipa_csum(card,
features & NETIF_F_RXCSUM ? 1 : 0,
IPA_INBOUND_CHECKSUM);
- if ((changed & NETIF_F_TSO))
- rc |= qeth_set_ipa_tso(card, features & NETIF_F_TSO ? 1 : 0);
- return rc ? -EIO : 0;
+ if (rc)
+ changed ^= NETIF_F_RXCSUM;
+ }
+ if ((changed & NETIF_F_TSO)) {
+ rc = qeth_set_ipa_tso(card, features & NETIF_F_TSO ? 1 : 0);
+ if (rc)
+ changed ^= NETIF_F_TSO;
+ }
+
+ /* everything changed successfully? */
+ if ((dev->features ^ features) == changed)
+ return 0;
+ /* something went wrong. save changed features and return error */
+ dev->features ^= changed;
+ return -EIO;
}
EXPORT_SYMBOL_GPL(qeth_set_features);
@@ -6164,6 +6175,11 @@ netdev_features_t qeth_fix_features(struct net_device *dev,
dev_info(&card->gdev->dev, "Outbound TSO not supported on %s\n",
QETH_CARD_IFNAME(card));
}
+ /* if the card isn't up, remove features that require hw changes */
+ if (card->state == CARD_STATE_DOWN ||
+ card->state == CARD_STATE_RECOVER)
+ features = features & ~(NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
+ NETIF_F_TSO);
QETH_DBF_HEX(SETUP, 2, &features, sizeof(features));
return features;
}