Commit f8fdd54e authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'sja1105-fixes'



Vladimir Oltean says:

====================
tc-cbs offload fixes for SJA1105 DSA

Yanan Yang has pointed out to me that certain tc-cbs offloaded
configurations do not appear to do any shaping on the LS1021A-TSN board
(SJA1105T).

This is due to an apparent documentation error that also made its way
into the driver, which patch 1/3 now fixes.

While investigating and then testing, I've found 2 more bugs, which are
patches 2/3 and 3/3.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ca7cfd73 180a7419
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -132,6 +132,8 @@ struct sja1105_info {
	int max_frame_mem;
	int num_ports;
	bool multiple_cascade_ports;
	/* Every {port, TXQ} has its own CBS shaper */
	bool fixed_cbs_mapping;
	enum dsa_tag_protocol tag_proto;
	const struct sja1105_dynamic_table_ops *dyn_ops;
	const struct sja1105_table_ops *static_ops;
+45 −6
Original line number Diff line number Diff line
@@ -2115,11 +2115,36 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
}

#define BYTES_PER_KBIT (1000LL / 8)
/* Port 0 (the uC port) does not have CBS shapers */
#define SJA1110_FIXED_CBS(port, prio) ((((port) - 1) * SJA1105_NUM_TC) + (prio))

static int sja1105_find_cbs_shaper(struct sja1105_private *priv,
				   int port, int prio)
{
	int i;

	if (priv->info->fixed_cbs_mapping) {
		i = SJA1110_FIXED_CBS(port, prio);
		if (i >= 0 && i < priv->info->num_cbs_shapers)
			return i;

		return -1;
	}

	for (i = 0; i < priv->info->num_cbs_shapers; i++)
		if (priv->cbs[i].port == port && priv->cbs[i].prio == prio)
			return i;

	return -1;
}

static int sja1105_find_unused_cbs_shaper(struct sja1105_private *priv)
{
	int i;

	if (priv->info->fixed_cbs_mapping)
		return -1;

	for (i = 0; i < priv->info->num_cbs_shapers; i++)
		if (!priv->cbs[i].idle_slope && !priv->cbs[i].send_slope)
			return i;
@@ -2150,14 +2175,20 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_cbs_entry *cbs;
	s64 port_transmit_rate_kbps;
	int index;

	if (!offload->enable)
		return sja1105_delete_cbs_shaper(priv, port, offload->queue);

	/* The user may be replacing an existing shaper */
	index = sja1105_find_cbs_shaper(priv, port, offload->queue);
	if (index < 0) {
		/* That isn't the case - see if we can allocate a new one */
		index = sja1105_find_unused_cbs_shaper(priv);
		if (index < 0)
			return -ENOSPC;
	}

	cbs = &priv->cbs[index];
	cbs->port = port;
@@ -2167,9 +2198,17 @@ static int sja1105_setup_tc_cbs(struct dsa_switch *ds, int port,
	 */
	cbs->credit_hi = offload->hicredit;
	cbs->credit_lo = abs(offload->locredit);
	/* User space is in kbits/sec, hardware in bytes/sec */
	cbs->idle_slope = offload->idleslope * BYTES_PER_KBIT;
	cbs->send_slope = abs(offload->sendslope * BYTES_PER_KBIT);
	/* User space is in kbits/sec, while the hardware in bytes/sec times
	 * link speed. Since the given offload->sendslope is good only for the
	 * current link speed anyway, and user space is likely to reprogram it
	 * when that changes, don't even bother to track the port's link speed,
	 * but deduce the port transmit rate from idleslope - sendslope.
	 */
	port_transmit_rate_kbps = offload->idleslope - offload->sendslope;
	cbs->idle_slope = div_s64(offload->idleslope * BYTES_PER_KBIT,
				  port_transmit_rate_kbps);
	cbs->send_slope = div_s64(abs(offload->sendslope * BYTES_PER_KBIT),
				  port_transmit_rate_kbps);
	/* Convert the negative values from 64-bit 2's complement
	 * to 32-bit 2's complement (for the case of 0x80000000 whose
	 * negative is still negative).
+4 −0
Original line number Diff line number Diff line
@@ -781,6 +781,7 @@ const struct sja1105_info sja1110a_info = {
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.fixed_cbs_mapping	= true,
	.ptp_ts_bits		= 32,
	.ptpegr_ts_bytes	= 8,
	.max_frame_mem		= SJA1110_MAX_FRAME_MEMORY,
@@ -831,6 +832,7 @@ const struct sja1105_info sja1110b_info = {
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.fixed_cbs_mapping	= true,
	.ptp_ts_bits		= 32,
	.ptpegr_ts_bytes	= 8,
	.max_frame_mem		= SJA1110_MAX_FRAME_MEMORY,
@@ -881,6 +883,7 @@ const struct sja1105_info sja1110c_info = {
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.fixed_cbs_mapping	= true,
	.ptp_ts_bits		= 32,
	.ptpegr_ts_bytes	= 8,
	.max_frame_mem		= SJA1110_MAX_FRAME_MEMORY,
@@ -931,6 +934,7 @@ const struct sja1105_info sja1110d_info = {
	.tag_proto		= DSA_TAG_PROTO_SJA1110,
	.can_limit_mcast_flood	= true,
	.multiple_cascade_ports	= true,
	.fixed_cbs_mapping	= true,
	.ptp_ts_bits		= 32,
	.ptpegr_ts_bytes	= 8,
	.max_frame_mem		= SJA1110_MAX_FRAME_MEMORY,