Commit 7c20f6c1 authored by Daniel Golle's avatar Daniel Golle Committed by Jakub Kicinski
Browse files

net: dsa: mxl862xx: use RST_DATA to skip writing zero words



Issue the firmware's RST_DATA command before writing data payloads that
contain many zero words. RST_DATA zeroes both the firmware's internal
buffer and the MMD data registers in a single command, allowing the
driver to skip individual MDIO writes for zero-valued words. This
reduces bus traffic for the common case where API structs have many
unused or default-zero fields.

The optimization is applied when at least 5 zero words are found in the
payload, roughly the break-even point against the cost of the extra
RST_DATA command round-trip.

Signed-off-by: default avatarDaniel Golle <daniel@makrotopia.org>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/d10bd6ad5df062d0da342c3e0d330550b3d2432b.1774185953.git.daniel@makrotopia.org


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a319d0c8
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -283,6 +283,17 @@ static int mxl862xx_get_data(struct mxl862xx_priv *priv, u16 words)
				  MXL862XX_MMD_REG_DATA_MAX_SIZE * sizeof(u16));
}

static int mxl862xx_rst_data(struct mxl862xx_priv *priv)
{
	return mxl862xx_issue_cmd(priv, MMD_API_RST_DATA, 0);
}

/* Minimum number of zero words in the data payload before issuing a
 * RST_DATA command is worthwhile.  RST_DATA costs one full command
 * round-trip (~5 MDIO transactions), so the threshold must offset that.
 */
#define RST_DATA_THRESHOLD	5

static int mxl862xx_send_cmd(struct mxl862xx_priv *priv, u16 cmd, u16 size,
			     bool quiet)
{
@@ -318,6 +329,8 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data,
		      u16 size, bool read, bool quiet)
{
	__le16 *data = _data;
	bool use_rst = false;
	unsigned int zeros;
	int ret, cmd_ret;
	u16 max, crc, i;

@@ -331,6 +344,24 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data,
	if (ret < 0)
		goto out;

	/* If the data contains enough zero words, issue RST_DATA to zero
	 * both the firmware buffer and MMD registers, then skip writing
	 * zero words individually.
	 */
	for (i = 0, zeros = 0; i < size / 2 && zeros < RST_DATA_THRESHOLD; i++)
		if (!data[i])
			zeros++;

	if (zeros < RST_DATA_THRESHOLD && (size & 1) && !*(u8 *)&data[i])
		zeros++;

	if (zeros >= RST_DATA_THRESHOLD) {
		ret = mxl862xx_rst_data(priv);
		if (ret < 0)
			goto out;
		use_rst = true;
	}

	/* Compute CRC-16 over the data payload; written as an extra word
	 * after the data so the firmware can verify the transfer.
	 */
@@ -367,6 +398,13 @@ int mxl862xx_api_wrap(struct mxl862xx_priv *priv, u16 cmd, void *_data,
			val = le16_to_cpu(data[i]);
		}

		/* After RST_DATA, skip zero data words as the registers
		 * already contain zeros, but never skip the CRC word at the
		 * final word.
		 */
		if (use_rst && i < max && val == 0)
			continue;

		ret = mxl862xx_reg_write(priv,
					 MXL862XX_MMD_REG_DATA_FIRST + off,
					 val);