Thomas Bogendoerfer 8c58df
From: Julian Wiedmann <jwi@linux.vnet.ibm.com>
Thomas Bogendoerfer 8c58df
Date: Tue, 6 Jun 2017 14:33:50 +0200
Thomas Bogendoerfer 8c58df
Subject: s390/qeth: do early device setup for z/VM IQD NICs
Thomas Bogendoerfer 8c58df
Patch-mainline: v4.13-rc1
Thomas Bogendoerfer 8c58df
Git-commit: c70eb09dc210b8d6fdd4a93d5bc25d85133fb9d2
Thomas Bogendoerfer 8c58df
References: bsc#1061024 FATE#323301
Thomas Bogendoerfer 8c58df
Thomas Bogendoerfer 8c58df
qeth currently supports early setup for OSM and OSN devices.
Thomas Bogendoerfer 8c58df
This patch adds early setup support for z/VM HiperSockets,
Thomas Bogendoerfer 8c58df
since they can only be coupled to L3 networks.
Thomas Bogendoerfer 8c58df
Thomas Bogendoerfer 8c58df
Based on an initial version by Dmitriy Lakhvich.
Thomas Bogendoerfer 8c58df
Thomas Bogendoerfer 8c58df
Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com>
Thomas Bogendoerfer 8c58df
Signed-off-by: David S. Miller <davem@davemloft.net>
Thomas Bogendoerfer 8c58df
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer 8c58df
---
Thomas Bogendoerfer 8c58df
 drivers/s390/net/qeth_core.h      |    2 +
Thomas Bogendoerfer 8c58df
 drivers/s390/net/qeth_core_main.c |   44 +++++++++++++++++++++++++++++---------
Thomas Bogendoerfer 8c58df
 drivers/s390/net/qeth_core_sys.c  |    2 -
Thomas Bogendoerfer 8c58df
 3 files changed, 37 insertions(+), 11 deletions(-)
Thomas Bogendoerfer 8c58df
Thomas Bogendoerfer 8c58df
--- a/drivers/s390/net/qeth_core.h
Thomas Bogendoerfer 8c58df
+++ b/drivers/s390/net/qeth_core.h
Thomas Bogendoerfer 8c58df
@@ -659,6 +659,7 @@ struct qeth_card_info {
Thomas Bogendoerfer 8c58df
 	int max_mtu;
Thomas Bogendoerfer 8c58df
 	int broadcast_capable;
Thomas Bogendoerfer 8c58df
 	int unique_id;
Thomas Bogendoerfer 8c58df
+	bool layer_enforced;
Thomas Bogendoerfer 8c58df
 	struct qeth_card_blkt blkt;
Thomas Bogendoerfer 8c58df
 	enum qeth_ipa_promisc_modes promisc_mode;
Thomas Bogendoerfer 8c58df
 	__u32 diagass_support;
Thomas Bogendoerfer 8c58df
@@ -696,6 +697,7 @@ struct qeth_osn_info {
Thomas Bogendoerfer 8c58df
 };
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
 enum qeth_discipline_id {
Thomas Bogendoerfer 8c58df
+	QETH_DISCIPLINE_UNDETERMINED = -1,
Thomas Bogendoerfer 8c58df
 	QETH_DISCIPLINE_LAYER3 = 0,
Thomas Bogendoerfer 8c58df
 	QETH_DISCIPLINE_LAYER2 = 1,
Thomas Bogendoerfer 8c58df
 };
Thomas Bogendoerfer 8c58df
--- a/drivers/s390/net/qeth_core_main.c
Thomas Bogendoerfer 8c58df
+++ b/drivers/s390/net/qeth_core_main.c
Thomas Bogendoerfer 8c58df
@@ -1723,6 +1723,25 @@ static void qeth_configure_unitaddr(stru
Thomas Bogendoerfer 8c58df
 			       (prcd[0x11] == _ascebc['M']));
Thomas Bogendoerfer 8c58df
 }
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
+/* Determine whether the device requires a specific layer discipline */
Thomas Bogendoerfer 8c58df
+static enum qeth_discipline_id qeth_enforce_discipline(struct qeth_card *card)
Thomas Bogendoerfer 8c58df
+{
Thomas Bogendoerfer 8c58df
+	if (card->info.type == QETH_CARD_TYPE_OSM ||
Thomas Bogendoerfer 8c58df
+	    card->info.type == QETH_CARD_TYPE_OSN) {
Thomas Bogendoerfer 8c58df
+		QETH_DBF_TEXT(SETUP, 3, "force l2");
Thomas Bogendoerfer 8c58df
+		return QETH_DISCIPLINE_LAYER2;
Thomas Bogendoerfer 8c58df
+	}
Thomas Bogendoerfer 8c58df
+
Thomas Bogendoerfer 8c58df
+	/* virtual HiperSocket is L3 only: */
Thomas Bogendoerfer 8c58df
+	if (card->info.guestlan && card->info.type == QETH_CARD_TYPE_IQD) {
Thomas Bogendoerfer 8c58df
+		QETH_DBF_TEXT(SETUP, 3, "force l3");
Thomas Bogendoerfer 8c58df
+		return QETH_DISCIPLINE_LAYER3;
Thomas Bogendoerfer 8c58df
+	}
Thomas Bogendoerfer 8c58df
+
Thomas Bogendoerfer 8c58df
+	QETH_DBF_TEXT(SETUP, 3, "force no");
Thomas Bogendoerfer 8c58df
+	return QETH_DISCIPLINE_UNDETERMINED;
Thomas Bogendoerfer 8c58df
+}
Thomas Bogendoerfer 8c58df
+
Thomas Bogendoerfer 8c58df
 static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd)
Thomas Bogendoerfer 8c58df
 {
Thomas Bogendoerfer 8c58df
 	QETH_DBF_TEXT(SETUP, 2, "cfgblkt");
Thomas Bogendoerfer 8c58df
@@ -5485,6 +5504,7 @@ int qeth_core_load_discipline(struct qet
Thomas Bogendoerfer 8c58df
 		enum qeth_discipline_id discipline)
Thomas Bogendoerfer 8c58df
 {
Thomas Bogendoerfer 8c58df
 	int rc = 0;
Thomas Bogendoerfer 8c58df
+
Thomas Bogendoerfer 8c58df
 	mutex_lock(&qeth_mod_mutex);
Thomas Bogendoerfer 8c58df
 	switch (discipline) {
Thomas Bogendoerfer 8c58df
 	case QETH_DISCIPLINE_LAYER3:
Thomas Bogendoerfer 8c58df
@@ -5495,7 +5515,10 @@ int qeth_core_load_discipline(struct qet
Thomas Bogendoerfer 8c58df
 		card->discipline = try_then_request_module(
Thomas Bogendoerfer 8c58df
 			symbol_get(qeth_l2_discipline), "qeth_l2");
Thomas Bogendoerfer 8c58df
 		break;
Thomas Bogendoerfer 8c58df
+	default:
Thomas Bogendoerfer 8c58df
+		break;
Thomas Bogendoerfer 8c58df
 	}
Thomas Bogendoerfer 8c58df
+
Thomas Bogendoerfer 8c58df
 	if (!card->discipline) {
Thomas Bogendoerfer 8c58df
 		dev_err(&card->gdev->dev, "There is no kernel module to "
Thomas Bogendoerfer 8c58df
 			"support discipline %d\n", discipline);
Thomas Bogendoerfer 8c58df
@@ -5598,6 +5621,7 @@ static int qeth_core_probe_device(struct
Thomas Bogendoerfer 8c58df
 	struct qeth_card *card;
Thomas Bogendoerfer 8c58df
 	struct device *dev;
Thomas Bogendoerfer 8c58df
 	int rc;
Thomas Bogendoerfer 8c58df
+	enum qeth_discipline_id enforced_disc;
Thomas Bogendoerfer 8c58df
 	unsigned long flags;
Thomas Bogendoerfer 8c58df
 	char dbf_name[DBF_NAME_LEN];
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
@@ -5645,10 +5669,15 @@ static int qeth_core_probe_device(struct
Thomas Bogendoerfer 8c58df
 		goto err_card;
Thomas Bogendoerfer 8c58df
 	}
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
-	switch (card->info.type) {
Thomas Bogendoerfer 8c58df
-	case QETH_CARD_TYPE_OSN:
Thomas Bogendoerfer 8c58df
-	case QETH_CARD_TYPE_OSM:
Thomas Bogendoerfer 8c58df
-		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
Thomas Bogendoerfer 8c58df
+	qeth_determine_capabilities(card);
Thomas Bogendoerfer 8c58df
+	enforced_disc = qeth_enforce_discipline(card);
Thomas Bogendoerfer 8c58df
+	switch (enforced_disc) {
Thomas Bogendoerfer 8c58df
+	case QETH_DISCIPLINE_UNDETERMINED:
Thomas Bogendoerfer 8c58df
+		gdev->dev.type = &qeth_generic_devtype;
Thomas Bogendoerfer 8c58df
+		break;
Thomas Bogendoerfer 8c58df
+	default:
Thomas Bogendoerfer 8c58df
+		card->info.layer_enforced = true;
Thomas Bogendoerfer 8c58df
+		rc = qeth_core_load_discipline(card, enforced_disc);
Thomas Bogendoerfer 8c58df
 		if (rc)
Thomas Bogendoerfer 8c58df
 			goto err_card;
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
@@ -5659,16 +5688,11 @@ static int qeth_core_probe_device(struct
Thomas Bogendoerfer 8c58df
 		if (rc)
Thomas Bogendoerfer 8c58df
 			goto err_disc;
Thomas Bogendoerfer 8c58df
 		break;
Thomas Bogendoerfer 8c58df
-	default:
Thomas Bogendoerfer 8c58df
-		gdev->dev.type = &qeth_generic_devtype;
Thomas Bogendoerfer 8c58df
-		break;
Thomas Bogendoerfer 8c58df
 	}
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
 	write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
Thomas Bogendoerfer 8c58df
 	list_add_tail(&card->list, &qeth_core_card_list.list);
Thomas Bogendoerfer 8c58df
 	write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
Thomas Bogendoerfer 8c58df
-
Thomas Bogendoerfer 8c58df
-	qeth_determine_capabilities(card);
Thomas Bogendoerfer 8c58df
 	return 0;
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
 err_disc:
Thomas Bogendoerfer 8c58df
@@ -5705,7 +5729,7 @@ static int qeth_core_set_online(struct c
Thomas Bogendoerfer 8c58df
 {
Thomas Bogendoerfer 8c58df
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
Thomas Bogendoerfer 8c58df
 	int rc = 0;
Thomas Bogendoerfer 8c58df
-	int def_discipline;
Thomas Bogendoerfer 8c58df
+	enum qeth_discipline_id def_discipline;
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
 	if (!card->discipline) {
Thomas Bogendoerfer 8c58df
 		if (card->info.type == QETH_CARD_TYPE_IQD)
Thomas Bogendoerfer 8c58df
--- a/drivers/s390/net/qeth_core_sys.c
Thomas Bogendoerfer 8c58df
+++ b/drivers/s390/net/qeth_core_sys.c
Thomas Bogendoerfer 8c58df
@@ -413,7 +413,7 @@ static ssize_t qeth_dev_layer2_store(str
Thomas Bogendoerfer 8c58df
 
Thomas Bogendoerfer 8c58df
 	if (card->options.layer2 == newdis)
Thomas Bogendoerfer 8c58df
 		goto out;
Thomas Bogendoerfer 8c58df
-	if (card->info.type == QETH_CARD_TYPE_OSM) {
Thomas Bogendoerfer 8c58df
+	if (card->info.layer_enforced) {
Thomas Bogendoerfer 8c58df
 		/* fixed layer, can't switch */
Thomas Bogendoerfer 8c58df
 		rc = -EOPNOTSUPP;
Thomas Bogendoerfer 8c58df
 		goto out;