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

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

Merge branch 'mlxsw-dcb'



Jiri Pirko says:

====================
mlxsw: Introduce support for Data Center Bridging

Ido says:

This patchset introduces support for Quality of Service (QoS) as part of the
IEEE Data Center Bridiging (DCB) standards.

Patches 1-9 do the required device initialization. Specifically, patches 1-6
initialize the ports' headroom buffers, which are used at ingress to store
incoming packets while they go through the switch's pipeline. Patches 7-9
complete them by initializing the egress scheduling.

The pipeline mentioned above determines the packet's egress port(s) and
traffic class. Ideally, once out of the pipeline the packet moves to the
switch's shared buffer (to be introduced in Jiri's patchset, currently
default values are used) and scheduled for transmission according to its
traffic class. The egress scheduling is configured according to the 802.1Qaz
standard, which is part of the DCB infrastructure supported by Linux. This
is introduced in patches 10-12.

Even after going through the pipeline packets are not always eligible to
enter the shared buffer. This is determined by the amount of available space
and the quotas associated with the packet. However, if flow control is
enabled and the packet is associated with the lossless flow, then it will
stay in the headroom and won't be discarded. This is introduced in patches
13-17.

Please check individual commit messages for more info, as I tried to keep
them pretty detailed.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 92b6d35f d81a6bdb
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -50,3 +50,11 @@ config MLXSW_SPECTRUM

	  To compile this driver as a module, choose M here: the
	  module will be called mlxsw_spectrum.

config MLXSW_SPECTRUM_DCB
	bool "Data Center Bridging (DCB) support"
	depends on MLXSW_SPECTRUM && DCB
	default y
	---help---
	  Say Y here if you want to use Data Center Bridging (DCB) in the
	  driver.
+1 −0
Original line number Diff line number Diff line
@@ -8,3 +8,4 @@ mlxsw_switchx2-objs := switchx2.o
obj-$(CONFIG_MLXSW_SPECTRUM)	+= mlxsw_spectrum.o
mlxsw_spectrum-objs		:= spectrum.o spectrum_buffers.o \
				   spectrum_switchdev.o
mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB)	+= spectrum_dcb.o
+503 −4
Original line number Diff line number Diff line
@@ -1805,6 +1805,184 @@ static inline void mlxsw_reg_spvmlr_pack(char *payload, u8 local_port,
	}
}

/* QTCT - QoS Switch Traffic Class Table
 * -------------------------------------
 * Configures the mapping between the packet switch priority and the
 * traffic class on the transmit port.
 */
#define MLXSW_REG_QTCT_ID 0x400A
#define MLXSW_REG_QTCT_LEN 0x08

static const struct mlxsw_reg_info mlxsw_reg_qtct = {
	.id = MLXSW_REG_QTCT_ID,
	.len = MLXSW_REG_QTCT_LEN,
};

/* reg_qtct_local_port
 * Local port number.
 * Access: Index
 *
 * Note: CPU port is not supported.
 */
MLXSW_ITEM32(reg, qtct, local_port, 0x00, 16, 8);

/* reg_qtct_sub_port
 * Virtual port within the physical port.
 * Should be set to 0 when virtual ports are not enabled on the port.
 * Access: Index
 */
MLXSW_ITEM32(reg, qtct, sub_port, 0x00, 8, 8);

/* reg_qtct_switch_prio
 * Switch priority.
 * Access: Index
 */
MLXSW_ITEM32(reg, qtct, switch_prio, 0x00, 0, 4);

/* reg_qtct_tclass
 * Traffic class.
 * Default values:
 * switch_prio 0 : tclass 1
 * switch_prio 1 : tclass 0
 * switch_prio i : tclass i, for i > 1
 * Access: RW
 */
MLXSW_ITEM32(reg, qtct, tclass, 0x04, 0, 4);

static inline void mlxsw_reg_qtct_pack(char *payload, u8 local_port,
				       u8 switch_prio, u8 tclass)
{
	MLXSW_REG_ZERO(qtct, payload);
	mlxsw_reg_qtct_local_port_set(payload, local_port);
	mlxsw_reg_qtct_switch_prio_set(payload, switch_prio);
	mlxsw_reg_qtct_tclass_set(payload, tclass);
}

/* QEEC - QoS ETS Element Configuration Register
 * ---------------------------------------------
 * Configures the ETS elements.
 */
#define MLXSW_REG_QEEC_ID 0x400D
#define MLXSW_REG_QEEC_LEN 0x1C

static const struct mlxsw_reg_info mlxsw_reg_qeec = {
	.id = MLXSW_REG_QEEC_ID,
	.len = MLXSW_REG_QEEC_LEN,
};

/* reg_qeec_local_port
 * Local port number.
 * Access: Index
 *
 * Note: CPU port is supported.
 */
MLXSW_ITEM32(reg, qeec, local_port, 0x00, 16, 8);

enum mlxsw_reg_qeec_hr {
	MLXSW_REG_QEEC_HIERARCY_PORT,
	MLXSW_REG_QEEC_HIERARCY_GROUP,
	MLXSW_REG_QEEC_HIERARCY_SUBGROUP,
	MLXSW_REG_QEEC_HIERARCY_TC,
};

/* reg_qeec_element_hierarchy
 * 0 - Port
 * 1 - Group
 * 2 - Subgroup
 * 3 - Traffic Class
 * Access: Index
 */
MLXSW_ITEM32(reg, qeec, element_hierarchy, 0x04, 16, 4);

/* reg_qeec_element_index
 * The index of the element in the hierarchy.
 * Access: Index
 */
MLXSW_ITEM32(reg, qeec, element_index, 0x04, 0, 8);

/* reg_qeec_next_element_index
 * The index of the next (lower) element in the hierarchy.
 * Access: RW
 *
 * Note: Reserved for element_hierarchy 0.
 */
MLXSW_ITEM32(reg, qeec, next_element_index, 0x08, 0, 8);

enum {
	MLXSW_REG_QEEC_BYTES_MODE,
	MLXSW_REG_QEEC_PACKETS_MODE,
};

/* reg_qeec_pb
 * Packets or bytes mode.
 * 0 - Bytes mode
 * 1 - Packets mode
 * Access: RW
 *
 * Note: Used for max shaper configuration. For Spectrum, packets mode
 * is supported only for traffic classes of CPU port.
 */
MLXSW_ITEM32(reg, qeec, pb, 0x0C, 28, 1);

/* reg_qeec_mase
 * Max shaper configuration enable. Enables configuration of the max
 * shaper on this ETS element.
 * 0 - Disable
 * 1 - Enable
 * Access: RW
 */
MLXSW_ITEM32(reg, qeec, mase, 0x10, 31, 1);

/* A large max rate will disable the max shaper. */
#define MLXSW_REG_QEEC_MAS_DIS	200000000	/* Kbps */

/* reg_qeec_max_shaper_rate
 * Max shaper information rate.
 * For CPU port, can only be configured for port hierarchy.
 * When in bytes mode, value is specified in units of 1000bps.
 * Access: RW
 */
MLXSW_ITEM32(reg, qeec, max_shaper_rate, 0x10, 0, 28);

/* reg_qeec_de
 * DWRR configuration enable. Enables configuration of the dwrr and
 * dwrr_weight.
 * 0 - Disable
 * 1 - Enable
 * Access: RW
 */
MLXSW_ITEM32(reg, qeec, de, 0x18, 31, 1);

/* reg_qeec_dwrr
 * Transmission selection algorithm to use on the link going down from
 * the ETS element.
 * 0 - Strict priority
 * 1 - DWRR
 * Access: RW
 */
MLXSW_ITEM32(reg, qeec, dwrr, 0x18, 15, 1);

/* reg_qeec_dwrr_weight
 * DWRR weight on the link going down from the ETS element. The
 * percentage of bandwidth guaranteed to an ETS element within
 * its hierarchy. The sum of all weights across all ETS elements
 * within one hierarchy should be equal to 100. Reserved when
 * transmission selection algorithm is strict priority.
 * Access: RW
 */
MLXSW_ITEM32(reg, qeec, dwrr_weight, 0x18, 0, 8);

static inline void mlxsw_reg_qeec_pack(char *payload, u8 local_port,
				       enum mlxsw_reg_qeec_hr hr, u8 index,
				       u8 next_index)
{
	MLXSW_REG_ZERO(qeec, payload);
	mlxsw_reg_qeec_local_port_set(payload, local_port);
	mlxsw_reg_qeec_element_hierarchy_set(payload, hr);
	mlxsw_reg_qeec_element_index_set(payload, index);
	mlxsw_reg_qeec_next_element_index_set(payload, next_index);
}

/* PMLP - Ports Module to Local Port Register
 * ------------------------------------------
 * Configures the assignment of modules to local ports.
@@ -2141,6 +2319,145 @@ static inline void mlxsw_reg_paos_pack(char *payload, u8 local_port,
	mlxsw_reg_paos_e_set(payload, 1);
}

/* PFCC - Ports Flow Control Configuration Register
 * ------------------------------------------------
 * Configures and retrieves the per port flow control configuration.
 */
#define MLXSW_REG_PFCC_ID 0x5007
#define MLXSW_REG_PFCC_LEN 0x20

static const struct mlxsw_reg_info mlxsw_reg_pfcc = {
	.id = MLXSW_REG_PFCC_ID,
	.len = MLXSW_REG_PFCC_LEN,
};

/* reg_pfcc_local_port
 * Local port number.
 * Access: Index
 */
MLXSW_ITEM32(reg, pfcc, local_port, 0x00, 16, 8);

/* reg_pfcc_pnat
 * Port number access type. Determines the way local_port is interpreted:
 * 0 - Local port number.
 * 1 - IB / label port number.
 * Access: Index
 */
MLXSW_ITEM32(reg, pfcc, pnat, 0x00, 14, 2);

/* reg_pfcc_shl_cap
 * Send to higher layers capabilities:
 * 0 - No capability of sending Pause and PFC frames to higher layers.
 * 1 - Device has capability of sending Pause and PFC frames to higher
 *     layers.
 * Access: RO
 */
MLXSW_ITEM32(reg, pfcc, shl_cap, 0x00, 1, 1);

/* reg_pfcc_shl_opr
 * Send to higher layers operation:
 * 0 - Pause and PFC frames are handled by the port (default).
 * 1 - Pause and PFC frames are handled by the port and also sent to
 *     higher layers. Only valid if shl_cap = 1.
 * Access: RW
 */
MLXSW_ITEM32(reg, pfcc, shl_opr, 0x00, 0, 1);

/* reg_pfcc_ppan
 * Pause policy auto negotiation.
 * 0 - Disabled. Generate / ignore Pause frames based on pptx / pprtx.
 * 1 - Enabled. When auto-negotiation is performed, set the Pause policy
 *     based on the auto-negotiation resolution.
 * Access: RW
 *
 * Note: The auto-negotiation advertisement is set according to pptx and
 * pprtx. When PFC is set on Tx / Rx, ppan must be set to 0.
 */
MLXSW_ITEM32(reg, pfcc, ppan, 0x04, 28, 4);

/* reg_pfcc_prio_mask_tx
 * Bit per priority indicating if Tx flow control policy should be
 * updated based on bit pfctx.
 * Access: WO
 */
MLXSW_ITEM32(reg, pfcc, prio_mask_tx, 0x04, 16, 8);

/* reg_pfcc_prio_mask_rx
 * Bit per priority indicating if Rx flow control policy should be
 * updated based on bit pfcrx.
 * Access: WO
 */
MLXSW_ITEM32(reg, pfcc, prio_mask_rx, 0x04, 0, 8);

/* reg_pfcc_pptx
 * Admin Pause policy on Tx.
 * 0 - Never generate Pause frames (default).
 * 1 - Generate Pause frames according to Rx buffer threshold.
 * Access: RW
 */
MLXSW_ITEM32(reg, pfcc, pptx, 0x08, 31, 1);

/* reg_pfcc_aptx
 * Active (operational) Pause policy on Tx.
 * 0 - Never generate Pause frames.
 * 1 - Generate Pause frames according to Rx buffer threshold.
 * Access: RO
 */
MLXSW_ITEM32(reg, pfcc, aptx, 0x08, 30, 1);

/* reg_pfcc_pfctx
 * Priority based flow control policy on Tx[7:0]. Per-priority bit mask:
 * 0 - Never generate priority Pause frames on the specified priority
 *     (default).
 * 1 - Generate priority Pause frames according to Rx buffer threshold on
 *     the specified priority.
 * Access: RW
 *
 * Note: pfctx and pptx must be mutually exclusive.
 */
MLXSW_ITEM32(reg, pfcc, pfctx, 0x08, 16, 8);

/* reg_pfcc_pprx
 * Admin Pause policy on Rx.
 * 0 - Ignore received Pause frames (default).
 * 1 - Respect received Pause frames.
 * Access: RW
 */
MLXSW_ITEM32(reg, pfcc, pprx, 0x0C, 31, 1);

/* reg_pfcc_aprx
 * Active (operational) Pause policy on Rx.
 * 0 - Ignore received Pause frames.
 * 1 - Respect received Pause frames.
 * Access: RO
 */
MLXSW_ITEM32(reg, pfcc, aprx, 0x0C, 30, 1);

/* reg_pfcc_pfcrx
 * Priority based flow control policy on Rx[7:0]. Per-priority bit mask:
 * 0 - Ignore incoming priority Pause frames on the specified priority
 *     (default).
 * 1 - Respect incoming priority Pause frames on the specified priority.
 * Access: RW
 */
MLXSW_ITEM32(reg, pfcc, pfcrx, 0x0C, 16, 8);

#define MLXSW_REG_PFCC_ALL_PRIO 0xFF

static inline void mlxsw_reg_pfcc_prio_pack(char *payload, u8 pfc_en)
{
	mlxsw_reg_pfcc_prio_mask_tx_set(payload, MLXSW_REG_PFCC_ALL_PRIO);
	mlxsw_reg_pfcc_prio_mask_rx_set(payload, MLXSW_REG_PFCC_ALL_PRIO);
	mlxsw_reg_pfcc_pfctx_set(payload, pfc_en);
	mlxsw_reg_pfcc_pfcrx_set(payload, pfc_en);
}

static inline void mlxsw_reg_pfcc_pack(char *payload, u8 local_port)
{
	MLXSW_REG_ZERO(pfcc, payload);
	mlxsw_reg_pfcc_local_port_set(payload, local_port);
}

/* PPCNT - Ports Performance Counters Register
 * -------------------------------------------
 * The PPCNT register retrieves per port performance counters.
@@ -2180,6 +2497,11 @@ MLXSW_ITEM32(reg, ppcnt, local_port, 0x00, 16, 8);
 */
MLXSW_ITEM32(reg, ppcnt, pnat, 0x00, 14, 2);

enum mlxsw_reg_ppcnt_grp {
	MLXSW_REG_PPCNT_IEEE_8023_CNT = 0x0,
	MLXSW_REG_PPCNT_PRIO_CNT = 0x10,
};

/* reg_ppcnt_grp
 * Performance counter group.
 * Group 63 indicates all groups. Only valid on Set() operation with
@@ -2215,6 +2537,8 @@ MLXSW_ITEM32(reg, ppcnt, clr, 0x04, 31, 1);
 */
MLXSW_ITEM32(reg, ppcnt, prio_tc, 0x04, 0, 5);

/* Ethernet IEEE 802.3 Counter Group */

/* reg_ppcnt_a_frames_transmitted_ok
 * Access: RO
 */
@@ -2329,15 +2653,145 @@ MLXSW_ITEM64(reg, ppcnt, a_pause_mac_ctrl_frames_received,
MLXSW_ITEM64(reg, ppcnt, a_pause_mac_ctrl_frames_transmitted,
	     0x08 + 0x90, 0, 64);

static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port)
/* Ethernet Per Priority Group Counters */

/* reg_ppcnt_rx_octets
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, rx_octets, 0x08 + 0x00, 0, 64);

/* reg_ppcnt_rx_frames
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, rx_frames, 0x08 + 0x20, 0, 64);

/* reg_ppcnt_tx_octets
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, tx_octets, 0x08 + 0x28, 0, 64);

/* reg_ppcnt_tx_frames
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, tx_frames, 0x08 + 0x48, 0, 64);

/* reg_ppcnt_rx_pause
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, rx_pause, 0x08 + 0x50, 0, 64);

/* reg_ppcnt_rx_pause_duration
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, rx_pause_duration, 0x08 + 0x58, 0, 64);

/* reg_ppcnt_tx_pause
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, tx_pause, 0x08 + 0x60, 0, 64);

/* reg_ppcnt_tx_pause_duration
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, tx_pause_duration, 0x08 + 0x68, 0, 64);

/* reg_ppcnt_rx_pause_transition
 * Access: RO
 */
MLXSW_ITEM64(reg, ppcnt, tx_pause_transition, 0x08 + 0x70, 0, 64);

static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port,
					enum mlxsw_reg_ppcnt_grp grp,
					u8 prio_tc)
{
	MLXSW_REG_ZERO(ppcnt, payload);
	mlxsw_reg_ppcnt_swid_set(payload, 0);
	mlxsw_reg_ppcnt_local_port_set(payload, local_port);
	mlxsw_reg_ppcnt_pnat_set(payload, 0);
	mlxsw_reg_ppcnt_grp_set(payload, 0);
	mlxsw_reg_ppcnt_grp_set(payload, grp);
	mlxsw_reg_ppcnt_clr_set(payload, 0);
	mlxsw_reg_ppcnt_prio_tc_set(payload, 0);
	mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc);
}

/* PPTB - Port Prio To Buffer Register
 * -----------------------------------
 * Configures the switch priority to buffer table.
 */
#define MLXSW_REG_PPTB_ID 0x500B
#define MLXSW_REG_PPTB_LEN 0x0C

static const struct mlxsw_reg_info mlxsw_reg_pptb = {
	.id = MLXSW_REG_PPTB_ID,
	.len = MLXSW_REG_PPTB_LEN,
};

enum {
	MLXSW_REG_PPTB_MM_UM,
	MLXSW_REG_PPTB_MM_UNICAST,
	MLXSW_REG_PPTB_MM_MULTICAST,
};

/* reg_pptb_mm
 * Mapping mode.
 * 0 - Map both unicast and multicast packets to the same buffer.
 * 1 - Map only unicast packets.
 * 2 - Map only multicast packets.
 * Access: Index
 *
 * Note: SwitchX-2 only supports the first option.
 */
MLXSW_ITEM32(reg, pptb, mm, 0x00, 28, 2);

/* reg_pptb_local_port
 * Local port number.
 * Access: Index
 */
MLXSW_ITEM32(reg, pptb, local_port, 0x00, 16, 8);

/* reg_pptb_um
 * Enables the update of the untagged_buf field.
 * Access: RW
 */
MLXSW_ITEM32(reg, pptb, um, 0x00, 8, 1);

/* reg_pptb_pm
 * Enables the update of the prio_to_buff field.
 * Bit <i> is a flag for updating the mapping for switch priority <i>.
 * Access: RW
 */
MLXSW_ITEM32(reg, pptb, pm, 0x00, 0, 8);

/* reg_pptb_prio_to_buff
 * Mapping of switch priority <i> to one of the allocated receive port
 * buffers.
 * Access: RW
 */
MLXSW_ITEM_BIT_ARRAY(reg, pptb, prio_to_buff, 0x04, 0x04, 4);

/* reg_pptb_pm_msb
 * Enables the update of the prio_to_buff field.
 * Bit <i> is a flag for updating the mapping for switch priority <i+8>.
 * Access: RW
 */
MLXSW_ITEM32(reg, pptb, pm_msb, 0x08, 24, 8);

/* reg_pptb_untagged_buff
 * Mapping of untagged frames to one of the allocated receive port buffers.
 * Access: RW
 *
 * Note: In SwitchX-2 this field must be mapped to buffer 8. Reserved for
 * Spectrum, as it maps untagged packets based on the default switch priority.
 */
MLXSW_ITEM32(reg, pptb, untagged_buff, 0x08, 0, 4);

#define MLXSW_REG_PPTB_ALL_PRIO 0xFF

static inline void mlxsw_reg_pptb_pack(char *payload, u8 local_port)
{
	MLXSW_REG_ZERO(pptb, payload);
	mlxsw_reg_pptb_mm_set(payload, MLXSW_REG_PPTB_MM_UM);
	mlxsw_reg_pptb_local_port_set(payload, local_port);
	mlxsw_reg_pptb_pm_set(payload, MLXSW_REG_PPTB_ALL_PRIO);
}

/* PBMC - Port Buffer Management Control Register
@@ -2346,7 +2800,7 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u8 local_port)
 * allocation for different Prios, and the Pause threshold management.
 */
#define MLXSW_REG_PBMC_ID 0x500C
#define MLXSW_REG_PBMC_LEN 0x68
#define MLXSW_REG_PBMC_LEN 0x6C

static const struct mlxsw_reg_info mlxsw_reg_pbmc = {
	.id = MLXSW_REG_PBMC_ID,
@@ -2374,6 +2828,8 @@ MLXSW_ITEM32(reg, pbmc, xoff_timer_value, 0x04, 16, 16);
 */
MLXSW_ITEM32(reg, pbmc, xoff_refresh, 0x04, 0, 16);

#define MLXSW_REG_PBMC_PORT_SHARED_BUF_IDX 11

/* reg_pbmc_buf_lossy
 * The field indicates if the buffer is lossy.
 * 0 - Lossless
@@ -2398,6 +2854,30 @@ MLXSW_ITEM32_INDEXED(reg, pbmc, buf_epsb, 0x0C, 24, 1, 0x08, 0x00, false);
 */
MLXSW_ITEM32_INDEXED(reg, pbmc, buf_size, 0x0C, 0, 16, 0x08, 0x00, false);

/* reg_pbmc_buf_xoff_threshold
 * Once the amount of data in the buffer goes above this value, device
 * starts sending PFC frames for all priorities associated with the
 * buffer. Units are represented in cells. Reserved in case of lossy
 * buffer.
 * Access: RW
 *
 * Note: In Spectrum, reserved for buffer[9].
 */
MLXSW_ITEM32_INDEXED(reg, pbmc, buf_xoff_threshold, 0x0C, 16, 16,
		     0x08, 0x04, false);

/* reg_pbmc_buf_xon_threshold
 * When the amount of data in the buffer goes below this value, device
 * stops sending PFC frames for the priorities associated with the
 * buffer. Units are represented in cells. Reserved in case of lossy
 * buffer.
 * Access: RW
 *
 * Note: In Spectrum, reserved for buffer[9].
 */
MLXSW_ITEM32_INDEXED(reg, pbmc, buf_xon_threshold, 0x0C, 0, 16,
		     0x08, 0x04, false);

static inline void mlxsw_reg_pbmc_pack(char *payload, u8 local_port,
				       u16 xoff_timer_value, u16 xoff_refresh)
{
@@ -2416,6 +2896,17 @@ static inline void mlxsw_reg_pbmc_lossy_buffer_pack(char *payload,
	mlxsw_reg_pbmc_buf_size_set(payload, buf_index, size);
}

static inline void mlxsw_reg_pbmc_lossless_buffer_pack(char *payload,
						       int buf_index, u16 size,
						       u16 threshold)
{
	mlxsw_reg_pbmc_buf_lossy_set(payload, buf_index, 0);
	mlxsw_reg_pbmc_buf_epsb_set(payload, buf_index, 0);
	mlxsw_reg_pbmc_buf_size_set(payload, buf_index, size);
	mlxsw_reg_pbmc_buf_xoff_threshold_set(payload, buf_index, threshold);
	mlxsw_reg_pbmc_buf_xon_threshold_set(payload, buf_index, threshold);
}

/* PSPA - Port Switch Partition Allocation
 * ---------------------------------------
 * Controls the association of a port with a switch partition and enables
@@ -3283,6 +3774,10 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id)
		return "SFMR";
	case MLXSW_REG_SPVMLR_ID:
		return "SPVMLR";
	case MLXSW_REG_QTCT_ID:
		return "QTCT";
	case MLXSW_REG_QEEC_ID:
		return "QEEC";
	case MLXSW_REG_PMLP_ID:
		return "PMLP";
	case MLXSW_REG_PMTU_ID:
@@ -3293,8 +3788,12 @@ static inline const char *mlxsw_reg_id_str(u16 reg_id)
		return "PPAD";
	case MLXSW_REG_PAOS_ID:
		return "PAOS";
	case MLXSW_REG_PFCC_ID:
		return "PFCC";
	case MLXSW_REG_PPCNT_ID:
		return "PPCNT";
	case MLXSW_REG_PPTB_ID:
		return "PPTB";
	case MLXSW_REG_PBMC_ID:
		return "PBMC";
	case MLXSW_REG_PSPA_ID:
+261 −2

File changed.

Preview size limit exceeded, changes collapsed.

+61 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include <linux/bitops.h>
#include <linux/if_vlan.h>
#include <linux/list.h>
#include <linux/dcbnl.h>
#include <net/switchdev.h>
#include <net/devlink.h>

@@ -62,6 +63,23 @@

#define MLXSW_SP_PORT_BASE_SPEED 25000	/* Mb/s */

#define MLXSW_SP_BYTES_PER_CELL 96

#define MLXSW_SP_BYTES_TO_CELLS(b) DIV_ROUND_UP(b, MLXSW_SP_BYTES_PER_CELL)

/* Maximum delay buffer needed in case of PAUSE frames, in cells.
 * Assumes 100m cable and maximum MTU.
 */
#define MLXSW_SP_PAUSE_DELAY 612

#define MLXSW_SP_CELL_FACTOR 2	/* 2 * cell_size / (IPG + cell_size + 1) */

static inline u16 mlxsw_sp_pfc_delay_get(int mtu, u16 delay)
{
	delay = MLXSW_SP_BYTES_TO_CELLS(DIV_ROUND_UP(delay, BITS_PER_BYTE));
	return MLXSW_SP_CELL_FACTOR * delay + MLXSW_SP_BYTES_TO_CELLS(mtu);
}

struct mlxsw_sp_port;

struct mlxsw_sp_upper {
@@ -166,6 +184,15 @@ struct mlxsw_sp_port {
		struct mlxsw_sp_vfid *vfid;
		u16 vid;
	} vport;
	struct {
		u8 tx_pause:1,
		   rx_pause:1;
	} link;
	struct {
		struct ieee_ets *ets;
		struct ieee_maxrate *maxrate;
		struct ieee_pfc *pfc;
	} dcb;
	/* 802.1Q bridge VLANs */
	unsigned long *active_vlans;
	unsigned long *untagged_vlans;
@@ -174,6 +201,12 @@ struct mlxsw_sp_port {
	struct devlink_port devlink_port;
};

static inline bool
mlxsw_sp_port_is_pause_en(const struct mlxsw_sp_port *mlxsw_sp_port)
{
	return mlxsw_sp_port->link.tx_pause || mlxsw_sp_port->link.rx_pause;
}

static inline struct mlxsw_sp_port *
mlxsw_sp_port_lagged_get(struct mlxsw_sp *mlxsw_sp, u16 lag_id, u8 port_index)
{
@@ -265,5 +298,33 @@ int mlxsw_sp_vport_flood_set(struct mlxsw_sp_port *mlxsw_sp_vport, u16 vfid,
			     bool set, bool only_uc);
void mlxsw_sp_port_active_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port);
int mlxsw_sp_port_pvid_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 vid);
int mlxsw_sp_port_ets_set(struct mlxsw_sp_port *mlxsw_sp_port,
			  enum mlxsw_reg_qeec_hr hr, u8 index, u8 next_index,
			  bool dwrr, u8 dwrr_weight);
int mlxsw_sp_port_prio_tc_set(struct mlxsw_sp_port *mlxsw_sp_port,
			      u8 switch_prio, u8 tclass);
int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
				 u8 *prio_tc, bool pause_en,
				 struct ieee_pfc *my_pfc);
int mlxsw_sp_port_ets_maxrate_set(struct mlxsw_sp_port *mlxsw_sp_port,
				  enum mlxsw_reg_qeec_hr hr, u8 index,
				  u8 next_index, u32 maxrate);

#ifdef CONFIG_MLXSW_SPECTRUM_DCB

int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port);
void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port);

#else

static inline int mlxsw_sp_port_dcb_init(struct mlxsw_sp_port *mlxsw_sp_port)
{
	return 0;
}

static inline void mlxsw_sp_port_dcb_fini(struct mlxsw_sp_port *mlxsw_sp_port)
{}

#endif

#endif
Loading