All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] qeth: autodetect layer2/3 of z/VM VSWITCH/GUESTLAN
@ 2016-06-22 16:07 Lakhvich Dmitriy
  0 siblings, 0 replies; only message in thread
From: Lakhvich Dmitriy @ 2016-06-22 16:07 UTC (permalink / raw)
  To: linux-s390

From: Lakhvich Dmitriy <LDmitriy@ru.ibm.com>

If the NIC belongs to a z/VM VSWITCH/GUESTLAN, detect in which layer
the VSWITCH/GUESTLAN is configured with CP command, and enforce this
layer on the net device.

Signed-off-by: Lakhvich Dmitriy <ldmitriy@ru.ibm.com>
Reviewed-by: Eugene Crosser <Eugene.Crosser@ru.ibm.com>
Reviewed-by: Ursula Braun <ursula.braun@de.ibm.com>
Reviewed-by: Thomas Richter <tmricht@linux.vnet.ibm.com>
---
 drivers/s390/net/qeth_core_main.c | 104 +++++++++++++++++++++++++++++++++++---
 drivers/s390/net/qeth_core_sys.c  |   6 +++
 2 files changed, 102 insertions(+), 8 deletions(-)

diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 10b3a59..72799df 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -27,6 +27,7 @@
 #include <asm/io.h>
 #include <asm/sysinfo.h>
 #include <asm/compat.h>
+#include <asm/cpcmd.h>
 
 #include "qeth_core.h"
 
@@ -1724,6 +1725,87 @@ static void qeth_configure_unitaddr(struct qeth_card *card, char *prcd)
 			       (prcd[0x11] == _ascebc['M']));
 }
 
+/* Define which line discipline is enforced by the underlying hardware,
+* or not enforced.
+*/
+enum qeth_disc_enforcement {
+	ENFORCE_NONE = -1,
+	ENFORCE_L2 = QETH_DISCIPLINE_LAYER2,
+	ENFORCE_L3 = QETH_DISCIPLINE_LAYER3,
+};
+
+enum qeth_disc_enforcement
+qeth_detect_enforced_discipline(struct qeth_card *card)
+{
+	char cmd[128];
+	char response[200];
+	char *vswitch_or_lan, *ownerid, *vswitch_name;
+	char *token_stop;
+	char *is_ethernet;
+	struct ccw_dev_id id;
+	int is_guestlan = 0;
+	enum qeth_disc_enforcement rc = ENFORCE_NONE;
+
+	if (card->info.type == QETH_CARD_TYPE_IQD)
+		return ENFORCE_L3;
+
+	memset(cmd, 0, sizeof(cmd));
+	ccw_device_get_id(CARD_RDEV(card), &id);
+	snprintf(cmd, sizeof(cmd),
+		    "QUERY VIRTUAL NIC %04x", id.devno);
+
+	memset(response, 0, sizeof(response));
+	cpcmd(cmd, response,
+		   sizeof(response) - 1, NULL);
+
+	/* Response format:
+	 * Adapter xxxx.Pxx Type: QDIO      Name: Name      Devices: 3
+	 * MAC: xx-xx-xx-xx-xx-xx         VSWITCH: OWNER VSWITCHNAME
+	 */
+	vswitch_or_lan = strstr(response, "VSWITCH:");
+	if (!vswitch_or_lan) {
+		vswitch_or_lan = strstr(response, "LAN:");
+		if (!vswitch_or_lan)
+			goto out;
+		is_guestlan = 1;
+	}
+
+	ownerid = skip_spaces(strchr(vswitch_or_lan, ' '));
+	if (!ownerid)
+		goto out;
+
+	vswitch_name = strim(strchr(ownerid, ' '));
+	if (!vswitch_name)
+		goto out;
+
+	/* Attempt to parse correctly the situation
+	* when cp output format changed and some information
+	* is added after the name of lan/vswitch.
+	*/
+	token_stop = strchr(vswitch_name, '\n');
+	if (token_stop)
+		*token_stop = '\0';
+
+	if (!*vswitch_name)
+		goto out;
+
+	memset(cmd, 0, sizeof(cmd));
+	snprintf(cmd, sizeof(cmd), "QUERY %s %s",
+		 is_guestlan ? "LAN" : "VSWITCH", vswitch_name);
+
+	memset(response, 0, sizeof(response));
+	cpcmd(cmd, response,
+		   sizeof(response) - 1, NULL);
+	is_ethernet = strstr(response, "ETHERNET");
+	if (is_ethernet)
+		rc = ENFORCE_L2;
+	else
+		rc = ENFORCE_L3;
+
+out:
+	return rc;
+}
+
 static void qeth_configure_blkt_default(struct qeth_card *card, char *prcd)
 {
 	QETH_DBF_TEXT(SETUP, 2, "cfgblkt");
@@ -5543,6 +5625,7 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 	struct qeth_card *card;
 	struct device *dev;
 	int rc;
+	enum qeth_disc_enforcement enforced;
 	unsigned long flags;
 	char dbf_name[DBF_NAME_LEN];
 
@@ -5590,31 +5673,36 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
 		goto err_card;
 	}
 
+	qeth_determine_capabilities(card);
+
 	if (card->info.type == QETH_CARD_TYPE_OSN)
 		gdev->dev.type = &qeth_osn_devtype;
 	else
 		gdev->dev.type = &qeth_generic_devtype;
 
-	switch (card->info.type) {
-	case QETH_CARD_TYPE_OSN:
-	case QETH_CARD_TYPE_OSM:
+	if ((card->info.type == QETH_CARD_TYPE_OSN) ||
+	    (card->info.type == QETH_CARD_TYPE_OSM)) {
 		rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
 		if (rc)
 			goto err_card;
+
 		rc = card->discipline->setup(card->gdev);
 		if (rc)
 			goto err_disc;
-	case QETH_CARD_TYPE_OSD:
-	case QETH_CARD_TYPE_OSX:
-	default:
-		break;
+
+	} else if (card->info.guestlan) {
+		enforced = qeth_detect_enforced_discipline(card);
+		if (enforced != ENFORCE_NONE) {
+			rc = qeth_core_load_discipline(card, enforced);
+			if (rc)
+				goto err_card;
+		}
 	}
 
 	write_lock_irqsave(&qeth_core_card_list.rwlock, flags);
 	list_add_tail(&card->list, &qeth_core_card_list.list);
 	write_unlock_irqrestore(&qeth_core_card_list.rwlock, flags);
 
-	qeth_determine_capabilities(card);
 	return 0;
 
 err_disc:
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index 75b29fd2..31cde3f 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -411,6 +411,12 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 		goto out;
 	}
 
+	if (card->info.guestlan &&
+	    card->options.layer2 != -1) {
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
+
 	if (card->options.layer2 == newdis)
 		goto out;
 	else {
-- 
2.5.0

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2016-06-22 16:07 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-22 16:07 [PATCH] qeth: autodetect layer2/3 of z/VM VSWITCH/GUESTLAN Lakhvich Dmitriy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.