Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4666d7fb authored by Julian Wiedmann's avatar Julian Wiedmann Committed by David S. Miller
Browse files

s390/qeth: enhance TSO control sequence



TSO6 requires the full programming sequence, and not just a simple
START command. This implements the additional ENABLE command, and adds
some sanity checks that were missing for the START command.

Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1f83b817
Loading
Loading
Loading
Loading
+75 −2
Original line number Diff line number Diff line
@@ -5394,6 +5394,21 @@ static int qeth_setassparms_inspect_rc(struct qeth_ipa_cmd *cmd)
	return cmd->hdr.return_code;
}

static int qeth_setassparms_get_caps_cb(struct qeth_card *card,
					struct qeth_reply *reply,
					unsigned long data)
{
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
	struct qeth_ipa_caps *caps = reply->param;

	if (qeth_setassparms_inspect_rc(cmd))
		return 0;

	caps->supported = cmd->data.setassparms.data.caps.supported;
	caps->enabled = cmd->data.setassparms.data.caps.enabled;
	return 0;
}

int qeth_setassparms_cb(struct qeth_card *card,
			struct qeth_reply *reply, unsigned long data)
{
@@ -6396,6 +6411,20 @@ static int qeth_set_ipa_csum(struct qeth_card *card, bool on, int cstype,
	return rc ? -EIO : 0;
}

static int qeth_start_tso_cb(struct qeth_card *card, struct qeth_reply *reply,
			     unsigned long data)
{
	struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *) data;
	struct qeth_tso_start_data *tso_data = reply->param;

	if (qeth_setassparms_inspect_rc(cmd))
		return 0;

	tso_data->mss = cmd->data.setassparms.data.tso.mss;
	tso_data->supported = cmd->data.setassparms.data.tso.supported;
	return 0;
}

static int qeth_set_tso_off(struct qeth_card *card,
			    enum qeth_prot_versions prot)
{
@@ -6406,8 +6435,52 @@ static int qeth_set_tso_off(struct qeth_card *card,
static int qeth_set_tso_on(struct qeth_card *card,
			   enum qeth_prot_versions prot)
{
	return qeth_send_simple_setassparms_prot(card, IPA_OUTBOUND_TSO,
	struct qeth_tso_start_data tso_data;
	struct qeth_cmd_buffer *iob;
	struct qeth_ipa_caps caps;
	int rc;

	iob = qeth_get_setassparms_cmd(card, IPA_OUTBOUND_TSO,
				       IPA_CMD_ASS_START, 0, prot);
	if (!iob)
		return -ENOMEM;

	rc = qeth_send_setassparms(card, iob, 0, 0 /* unused */,
				   qeth_start_tso_cb, &tso_data);
	if (rc)
		return rc;

	if (!tso_data.mss || !(tso_data.supported & QETH_IPA_LARGE_SEND_TCP)) {
		qeth_set_tso_off(card, prot);
		return -EOPNOTSUPP;
	}

	iob = qeth_get_setassparms_cmd(card, IPA_OUTBOUND_TSO,
				       IPA_CMD_ASS_ENABLE, sizeof(caps), prot);
	if (!iob) {
		qeth_set_tso_off(card, prot);
		return -ENOMEM;
	}

	/* enable TSO capability */
	caps.supported = 0;
	caps.enabled = QETH_IPA_LARGE_SEND_TCP;
	rc = qeth_send_setassparms(card, iob, sizeof(caps), (long) &caps,
				   qeth_setassparms_get_caps_cb, &caps);
	if (rc) {
		qeth_set_tso_off(card, prot);
		return rc;
	}

	if (!qeth_ipa_caps_supported(&caps, QETH_IPA_LARGE_SEND_TCP) ||
	    !qeth_ipa_caps_enabled(&caps, QETH_IPA_LARGE_SEND_TCP)) {
		qeth_set_tso_off(card, prot);
		return -EOPNOTSUPP;
	}

	dev_info(&card->gdev->dev, "TSOv%u enabled (MSS: %u)\n", prot,
		 tso_data.mss);
	return 0;
}

static int qeth_set_ipa_tso(struct qeth_card *card, bool on,
+26 −0
Original line number Diff line number Diff line
@@ -56,6 +56,21 @@ static inline bool qeth_intparm_is_iob(unsigned long intparm)
#define IPA_CMD_INITIATOR_OSA_REPLY   0x81
#define IPA_CMD_PRIM_VERSION_NO 0x01

struct qeth_ipa_caps {
	u32 supported;
	u32 enabled;
};

static inline bool qeth_ipa_caps_supported(struct qeth_ipa_caps *caps, u32 mask)
{
	return (caps->supported & mask) == mask;
}

static inline bool qeth_ipa_caps_enabled(struct qeth_ipa_caps *caps, u32 mask)
{
	return (caps->enabled & mask) == mask;
}

enum qeth_card_types {
	QETH_CARD_TYPE_OSD     = 1,
	QETH_CARD_TYPE_IQD     = 5,
@@ -405,14 +420,25 @@ struct qeth_checksum_cmd {
	__u32 enabled;
} __packed;

enum qeth_ipa_large_send_caps {
	QETH_IPA_LARGE_SEND_TCP		= 0x00000001,
};

struct qeth_tso_start_data {
	u32 mss;
	u32 supported;
};

/* SETASSPARMS IPA Command: */
struct qeth_ipacmd_setassparms {
	struct qeth_ipacmd_setassparms_hdr hdr;
	union {
		__u32 flags_32bit;
		struct qeth_ipa_caps caps;
		struct qeth_checksum_cmd chksum;
		struct qeth_arp_cache_entry add_arp_entry;
		struct qeth_arp_query_data query_arp;
		struct qeth_tso_start_data tso;
		__u8 ip[16];
	} data;
} __attribute__ ((packed));