summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-08-05 20:13:21 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-05 20:13:21 -0700
commit47ec5303d73ea344e84f46660fff693c57641386 (patch)
treea2252debab749de29620c43285295d60c4741119 /drivers/net/ethernet/mellanox/mlxsw/spectrum.c
parent8186749621ed6b8fc42644c399e8c755a2b6f630 (diff)
parentc1055b76ad00aed0e8b79417080f212d736246b6 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from David Miller: 1) Support 6Ghz band in ath11k driver, from Rajkumar Manoharan. 2) Support UDP segmentation in code TSO code, from Eric Dumazet. 3) Allow flashing different flash images in cxgb4 driver, from Vishal Kulkarni. 4) Add drop frames counter and flow status to tc flower offloading, from Po Liu. 5) Support n-tuple filters in cxgb4, from Vishal Kulkarni. 6) Various new indirect call avoidance, from Eric Dumazet and Brian Vazquez. 7) Fix BPF verifier failures on 32-bit pointer arithmetic, from Yonghong Song. 8) Support querying and setting hardware address of a port function via devlink, use this in mlx5, from Parav Pandit. 9) Support hw ipsec offload on bonding slaves, from Jarod Wilson. 10) Switch qca8k driver over to phylink, from Jonathan McDowell. 11) In bpftool, show list of processes holding BPF FD references to maps, programs, links, and btf objects. From Andrii Nakryiko. 12) Several conversions over to generic power management, from Vaibhav Gupta. 13) Add support for SO_KEEPALIVE et al. to bpf_setsockopt(), from Dmitry Yakunin. 14) Various https url conversions, from Alexander A. Klimov. 15) Timestamping and PHC support for mscc PHY driver, from Antoine Tenart. 16) Support bpf iterating over tcp and udp sockets, from Yonghong Song. 17) Support 5GBASE-T i40e NICs, from Aleksandr Loktionov. 18) Add kTLS RX HW offload support to mlx5e, from Tariq Toukan. 19) Fix the ->ndo_start_xmit() return type to be netdev_tx_t in several drivers. From Luc Van Oostenryck. 20) XDP support for xen-netfront, from Denis Kirjanov. 21) Support receive buffer autotuning in MPTCP, from Florian Westphal. 22) Support EF100 chip in sfc driver, from Edward Cree. 23) Add XDP support to mvpp2 driver, from Matteo Croce. 24) Support MPTCP in sock_diag, from Paolo Abeni. 25) Commonize UDP tunnel offloading code by creating udp_tunnel_nic infrastructure, from Jakub Kicinski. 26) Several pci_ --> dma_ API conversions, from Christophe JAILLET. 27) Add FLOW_ACTION_POLICE support to mlxsw, from Ido Schimmel. 28) Add SK_LOOKUP bpf program type, from Jakub Sitnicki. 29) Refactor a lot of networking socket option handling code in order to avoid set_fs() calls, from Christoph Hellwig. 30) Add rfc4884 support to icmp code, from Willem de Bruijn. 31) Support TBF offload in dpaa2-eth driver, from Ioana Ciornei. 32) Support XDP_REDIRECT in qede driver, from Alexander Lobakin. 33) Support PCI relaxed ordering in mlx5 driver, from Aya Levin. 34) Support TCP syncookies in MPTCP, from Flowian Westphal. 35) Fix several tricky cases of PMTU handling wrt. briding, from Stefano Brivio. * git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2056 commits) net: thunderx: initialize VF's mailbox mutex before first usage usb: hso: remove bogus check for EINPROGRESS usb: hso: no complaint about kmalloc failure hso: fix bailout in error case of probe ip_tunnel_core: Fix build for archs without _HAVE_ARCH_IPV6_CSUM selftests/net: relax cpu affinity requirement in msg_zerocopy test mptcp: be careful on subflow creation selftests: rtnetlink: make kci_test_encap() return sub-test result selftests: rtnetlink: correct the final return value for the test net: dsa: sja1105: use detected device id instead of DT one on mismatch tipc: set ub->ifindex for local ipv6 address ipv6: add ipv6_dev_find() net: openvswitch: silence suspicious RCU usage warning Revert "vxlan: fix tos value before xmit" ptp: only allow phase values lower than 1 period farsync: switch from 'pci_' to 'dma_' API wan: wanxl: switch from 'pci_' to 'dma_' API hv_netvsc: do not use VF device if link is down dpaa2-eth: Fix passing zero to 'PTR_ERR' warning net: macb: Properly handle phylink on at91sam9x ...
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/spectrum.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c1680
1 files changed, 76 insertions, 1604 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 029ea344ad65..fdf9aa8314b2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -45,8 +45,8 @@
#include "../mlxfw/mlxfw.h"
#define MLXSW_SP1_FWREV_MAJOR 13
-#define MLXSW_SP1_FWREV_MINOR 2000
-#define MLXSW_SP1_FWREV_SUBMINOR 2714
+#define MLXSW_SP1_FWREV_MINOR 2007
+#define MLXSW_SP1_FWREV_SUBMINOR 1168
#define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702
static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
@@ -62,8 +62,8 @@ static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
"." __stringify(MLXSW_SP1_FWREV_SUBMINOR) ".mfa2"
#define MLXSW_SP2_FWREV_MAJOR 29
-#define MLXSW_SP2_FWREV_MINOR 2000
-#define MLXSW_SP2_FWREV_SUBMINOR 2714
+#define MLXSW_SP2_FWREV_MINOR 2007
+#define MLXSW_SP2_FWREV_SUBMINOR 1168
static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = {
.major = MLXSW_SP2_FWREV_MAJOR,
@@ -76,10 +76,24 @@ static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = {
"." __stringify(MLXSW_SP2_FWREV_MINOR) \
"." __stringify(MLXSW_SP2_FWREV_SUBMINOR) ".mfa2"
+#define MLXSW_SP3_FWREV_MAJOR 30
+#define MLXSW_SP3_FWREV_MINOR 2007
+#define MLXSW_SP3_FWREV_SUBMINOR 1168
+
+static const struct mlxsw_fw_rev mlxsw_sp3_fw_rev = {
+ .major = MLXSW_SP3_FWREV_MAJOR,
+ .minor = MLXSW_SP3_FWREV_MINOR,
+ .subminor = MLXSW_SP3_FWREV_SUBMINOR,
+};
+
+#define MLXSW_SP3_FW_FILENAME \
+ "mellanox/mlxsw_spectrum3-" __stringify(MLXSW_SP3_FWREV_MAJOR) \
+ "." __stringify(MLXSW_SP3_FWREV_MINOR) \
+ "." __stringify(MLXSW_SP3_FWREV_SUBMINOR) ".mfa2"
+
static const char mlxsw_sp1_driver_name[] = "mlxsw_spectrum";
static const char mlxsw_sp2_driver_name[] = "mlxsw_spectrum2";
static const char mlxsw_sp3_driver_name[] = "mlxsw_spectrum3";
-static const char mlxsw_sp_driver_version[] = "1.0";
static const unsigned char mlxsw_sp1_mac_mask[ETH_ALEN] = {
0xff, 0xff, 0xff, 0xff, 0xfc, 0x00
@@ -161,43 +175,6 @@ struct mlxsw_sp_mlxfw_dev {
struct mlxsw_sp *mlxsw_sp;
};
-struct mlxsw_sp_ptp_ops {
- struct mlxsw_sp_ptp_clock *
- (*clock_init)(struct mlxsw_sp *mlxsw_sp, struct device *dev);
- void (*clock_fini)(struct mlxsw_sp_ptp_clock *clock);
-
- struct mlxsw_sp_ptp_state *(*init)(struct mlxsw_sp *mlxsw_sp);
- void (*fini)(struct mlxsw_sp_ptp_state *ptp_state);
-
- /* Notify a driver that a packet that might be PTP was received. Driver
- * is responsible for freeing the passed-in SKB.
- */
- void (*receive)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
- u8 local_port);
-
- /* Notify a driver that a timestamped packet was transmitted. Driver
- * is responsible for freeing the passed-in SKB.
- */
- void (*transmitted)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
- u8 local_port);
-
- int (*hwtstamp_get)(struct mlxsw_sp_port *mlxsw_sp_port,
- struct hwtstamp_config *config);
- int (*hwtstamp_set)(struct mlxsw_sp_port *mlxsw_sp_port,
- struct hwtstamp_config *config);
- void (*shaper_work)(struct work_struct *work);
- int (*get_ts_info)(struct mlxsw_sp *mlxsw_sp,
- struct ethtool_ts_info *info);
- int (*get_stats_count)(void);
- void (*get_stats_strings)(u8 **p);
- void (*get_stats)(struct mlxsw_sp_port *mlxsw_sp_port,
- u64 *data, int data_index);
-};
-
-struct mlxsw_sp_span_ops {
- u32 (*buffsize_get)(int mtu, u32 speed);
-};
-
static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
u16 component_index, u32 *p_max_size,
u8 *p_align_bits, u16 *p_max_write_size)
@@ -580,8 +557,8 @@ static int mlxsw_sp_base_mac_get(struct mlxsw_sp *mlxsw_sp)
return 0;
}
-static int mlxsw_sp_port_admin_status_set(struct mlxsw_sp_port *mlxsw_sp_port,
- bool is_up)
+int mlxsw_sp_port_admin_status_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ bool is_up)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
char paos_pl[MLXSW_REG_PAOS_LEN];
@@ -995,8 +972,8 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
}
-static int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port,
- int mtu, bool pause_en)
+int mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port,
+ int mtu, bool pause_en)
{
u8 def_prio_tc[IEEE_8021QAZ_MAX_TCS] = {0};
bool dcb_en = !!mlxsw_sp_port->dcb.ets;
@@ -1088,8 +1065,8 @@ static int mlxsw_sp_port_get_offload_stats(int attr_id, const struct net_device
return -EINVAL;
}
-static int mlxsw_sp_port_get_stats_raw(struct net_device *dev, int grp,
- int prio, char *ppcnt_pl)
+int mlxsw_sp_port_get_stats_raw(struct net_device *dev, int grp,
+ int prio, char *ppcnt_pl)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
@@ -1352,6 +1329,21 @@ static int mlxsw_sp_port_kill_vid(struct net_device *dev,
return 0;
}
+static int mlxsw_sp_setup_tc_block(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct flow_block_offload *f)
+{
+ switch (f->binder_type) {
+ case FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS:
+ return mlxsw_sp_setup_tc_block_clsact(mlxsw_sp_port, f, true);
+ case FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS:
+ return mlxsw_sp_setup_tc_block_clsact(mlxsw_sp_port, f, false);
+ case FLOW_BLOCK_BINDER_TYPE_RED_EARLY_DROP:
+ return mlxsw_sp_setup_tc_block_qevent_early_drop(mlxsw_sp_port, f);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static int mlxsw_sp_setup_tc(struct net_device *dev, enum tc_setup_type type,
void *type_data)
{
@@ -1547,1500 +1539,6 @@ static const struct net_device_ops mlxsw_sp_port_netdev_ops = {
.ndo_do_ioctl = mlxsw_sp_port_ioctl,
};
-static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
- struct ethtool_drvinfo *drvinfo)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-
- strlcpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind,
- sizeof(drvinfo->driver));
- strlcpy(drvinfo->version, mlxsw_sp_driver_version,
- sizeof(drvinfo->version));
- snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
- "%d.%d.%d",
- mlxsw_sp->bus_info->fw_rev.major,
- mlxsw_sp->bus_info->fw_rev.minor,
- mlxsw_sp->bus_info->fw_rev.subminor);
- strlcpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name,
- sizeof(drvinfo->bus_info));
-}
-
-static void mlxsw_sp_port_get_pauseparam(struct net_device *dev,
- struct ethtool_pauseparam *pause)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-
- pause->rx_pause = mlxsw_sp_port->link.rx_pause;
- pause->tx_pause = mlxsw_sp_port->link.tx_pause;
-}
-
-static int mlxsw_sp_port_pause_set(struct mlxsw_sp_port *mlxsw_sp_port,
- struct ethtool_pauseparam *pause)
-{
- char pfcc_pl[MLXSW_REG_PFCC_LEN];
-
- mlxsw_reg_pfcc_pack(pfcc_pl, mlxsw_sp_port->local_port);
- mlxsw_reg_pfcc_pprx_set(pfcc_pl, pause->rx_pause);
- mlxsw_reg_pfcc_pptx_set(pfcc_pl, pause->tx_pause);
-
- return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pfcc),
- pfcc_pl);
-}
-
-static int mlxsw_sp_port_set_pauseparam(struct net_device *dev,
- struct ethtool_pauseparam *pause)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- bool pause_en = pause->tx_pause || pause->rx_pause;
- int err;
-
- if (mlxsw_sp_port->dcb.pfc && mlxsw_sp_port->dcb.pfc->pfc_en) {
- netdev_err(dev, "PFC already enabled on port\n");
- return -EINVAL;
- }
-
- if (pause->autoneg) {
- netdev_err(dev, "PAUSE frames autonegotiation isn't supported\n");
- return -EINVAL;
- }
-
- err = mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en);
- if (err) {
- netdev_err(dev, "Failed to configure port's headroom\n");
- return err;
- }
-
- err = mlxsw_sp_port_pause_set(mlxsw_sp_port, pause);
- if (err) {
- netdev_err(dev, "Failed to set PAUSE parameters\n");
- goto err_port_pause_configure;
- }
-
- mlxsw_sp_port->link.rx_pause = pause->rx_pause;
- mlxsw_sp_port->link.tx_pause = pause->tx_pause;
-
- return 0;
-
-err_port_pause_configure:
- pause_en = mlxsw_sp_port_is_pause_en(mlxsw_sp_port);
- mlxsw_sp_port_headroom_set(mlxsw_sp_port, dev->mtu, pause_en);
- return err;
-}
-
-struct mlxsw_sp_port_hw_stats {
- char str[ETH_GSTRING_LEN];
- u64 (*getter)(const char *payload);
- bool cells_bytes;
-};
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
- {
- .str = "a_frames_transmitted_ok",
- .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get,
- },
- {
- .str = "a_frames_received_ok",
- .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get,
- },
- {
- .str = "a_frame_check_sequence_errors",
- .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get,
- },
- {
- .str = "a_alignment_errors",
- .getter = mlxsw_reg_ppcnt_a_alignment_errors_get,
- },
- {
- .str = "a_octets_transmitted_ok",
- .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get,
- },
- {
- .str = "a_octets_received_ok",
- .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get,
- },
- {
- .str = "a_multicast_frames_xmitted_ok",
- .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get,
- },
- {
- .str = "a_broadcast_frames_xmitted_ok",
- .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get,
- },
- {
- .str = "a_multicast_frames_received_ok",
- .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get,
- },
- {
- .str = "a_broadcast_frames_received_ok",
- .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get,
- },
- {
- .str = "a_in_range_length_errors",
- .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get,
- },
- {
- .str = "a_out_of_range_length_field",
- .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get,
- },
- {
- .str = "a_frame_too_long_errors",
- .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get,
- },
- {
- .str = "a_symbol_error_during_carrier",
- .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get,
- },
- {
- .str = "a_mac_control_frames_transmitted",
- .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get,
- },
- {
- .str = "a_mac_control_frames_received",
- .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get,
- },
- {
- .str = "a_unsupported_opcodes_received",
- .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get,
- },
- {
- .str = "a_pause_mac_ctrl_frames_received",
- .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get,
- },
- {
- .str = "a_pause_mac_ctrl_frames_xmitted",
- .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2863_stats[] = {
- {
- .str = "if_in_discards",
- .getter = mlxsw_reg_ppcnt_if_in_discards_get,
- },
- {
- .str = "if_out_discards",
- .getter = mlxsw_reg_ppcnt_if_out_discards_get,
- },
- {
- .str = "if_out_errors",
- .getter = mlxsw_reg_ppcnt_if_out_errors_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN \
- ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2863_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2819_stats[] = {
- {
- .str = "ether_stats_undersize_pkts",
- .getter = mlxsw_reg_ppcnt_ether_stats_undersize_pkts_get,
- },
- {
- .str = "ether_stats_oversize_pkts",
- .getter = mlxsw_reg_ppcnt_ether_stats_oversize_pkts_get,
- },
- {
- .str = "ether_stats_fragments",
- .getter = mlxsw_reg_ppcnt_ether_stats_fragments_get,
- },
- {
- .str = "ether_pkts64octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts64octets_get,
- },
- {
- .str = "ether_pkts65to127octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts65to127octets_get,
- },
- {
- .str = "ether_pkts128to255octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts128to255octets_get,
- },
- {
- .str = "ether_pkts256to511octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts256to511octets_get,
- },
- {
- .str = "ether_pkts512to1023octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts512to1023octets_get,
- },
- {
- .str = "ether_pkts1024to1518octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts1024to1518octets_get,
- },
- {
- .str = "ether_pkts1519to2047octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts1519to2047octets_get,
- },
- {
- .str = "ether_pkts2048to4095octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts2048to4095octets_get,
- },
- {
- .str = "ether_pkts4096to8191octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts4096to8191octets_get,
- },
- {
- .str = "ether_pkts8192to10239octets",
- .getter = mlxsw_reg_ppcnt_ether_stats_pkts8192to10239octets_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN \
- ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2819_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_3635_stats[] = {
- {
- .str = "dot3stats_fcs_errors",
- .getter = mlxsw_reg_ppcnt_dot3stats_fcs_errors_get,
- },
- {
- .str = "dot3stats_symbol_errors",
- .getter = mlxsw_reg_ppcnt_dot3stats_symbol_errors_get,
- },
- {
- .str = "dot3control_in_unknown_opcodes",
- .getter = mlxsw_reg_ppcnt_dot3control_in_unknown_opcodes_get,
- },
- {
- .str = "dot3in_pause_frames",
- .getter = mlxsw_reg_ppcnt_dot3in_pause_frames_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN \
- ARRAY_SIZE(mlxsw_sp_port_hw_rfc_3635_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_ext_stats[] = {
- {
- .str = "ecn_marked",
- .getter = mlxsw_reg_ppcnt_ecn_marked_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_EXT_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_ext_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_discard_stats[] = {
- {
- .str = "discard_ingress_general",
- .getter = mlxsw_reg_ppcnt_ingress_general_get,
- },
- {
- .str = "discard_ingress_policy_engine",
- .getter = mlxsw_reg_ppcnt_ingress_policy_engine_get,
- },
- {
- .str = "discard_ingress_vlan_membership",
- .getter = mlxsw_reg_ppcnt_ingress_vlan_membership_get,
- },
- {
- .str = "discard_ingress_tag_frame_type",
- .getter = mlxsw_reg_ppcnt_ingress_tag_frame_type_get,
- },
- {
- .str = "discard_egress_vlan_membership",
- .getter = mlxsw_reg_ppcnt_egress_vlan_membership_get,
- },
- {
- .str = "discard_loopback_filter",
- .getter = mlxsw_reg_ppcnt_loopback_filter_get,
- },
- {
- .str = "discard_egress_general",
- .getter = mlxsw_reg_ppcnt_egress_general_get,
- },
- {
- .str = "discard_egress_hoq",
- .getter = mlxsw_reg_ppcnt_egress_hoq_get,
- },
- {
- .str = "discard_egress_policy_engine",
- .getter = mlxsw_reg_ppcnt_egress_policy_engine_get,
- },
- {
- .str = "discard_ingress_tx_link_down",
- .getter = mlxsw_reg_ppcnt_ingress_tx_link_down_get,
- },
- {
- .str = "discard_egress_stp_filter",
- .getter = mlxsw_reg_ppcnt_egress_stp_filter_get,
- },
- {
- .str = "discard_egress_sll",
- .getter = mlxsw_reg_ppcnt_egress_sll_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_DISCARD_STATS_LEN \
- ARRAY_SIZE(mlxsw_sp_port_hw_discard_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = {
- {
- .str = "rx_octets_prio",
- .getter = mlxsw_reg_ppcnt_rx_octets_get,
- },
- {
- .str = "rx_frames_prio",
- .getter = mlxsw_reg_ppcnt_rx_frames_get,
- },
- {
- .str = "tx_octets_prio",
- .getter = mlxsw_reg_ppcnt_tx_octets_get,
- },
- {
- .str = "tx_frames_prio",
- .getter = mlxsw_reg_ppcnt_tx_frames_get,
- },
- {
- .str = "rx_pause_prio",
- .getter = mlxsw_reg_ppcnt_rx_pause_get,
- },
- {
- .str = "rx_pause_duration_prio",
- .getter = mlxsw_reg_ppcnt_rx_pause_duration_get,
- },
- {
- .str = "tx_pause_prio",
- .getter = mlxsw_reg_ppcnt_tx_pause_get,
- },
- {
- .str = "tx_pause_duration_prio",
- .getter = mlxsw_reg_ppcnt_tx_pause_duration_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
-
-static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = {
- {
- .str = "tc_transmit_queue_tc",
- .getter = mlxsw_reg_ppcnt_tc_transmit_queue_get,
- .cells_bytes = true,
- },
- {
- .str = "tc_no_buffer_discard_uc_tc",
- .getter = mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get,
- },
-};
-
-#define MLXSW_SP_PORT_HW_TC_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_tc_stats)
-
-#define MLXSW_SP_PORT_ETHTOOL_STATS_LEN (MLXSW_SP_PORT_HW_STATS_LEN + \
- MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \
- MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \
- MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \
- MLXSW_SP_PORT_HW_EXT_STATS_LEN + \
- MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \
- (MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \
- IEEE_8021QAZ_MAX_TCS) + \
- (MLXSW_SP_PORT_HW_TC_STATS_LEN * \
- TC_MAX_QUEUE))
-
-static void mlxsw_sp_port_get_prio_strings(u8 **p, int prio)
-{
- int i;
-
- for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) {
- snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
- mlxsw_sp_port_hw_prio_stats[i].str, prio);
- *p += ETH_GSTRING_LEN;
- }
-}
-
-static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
-{
- int i;
-
- for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) {
- snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
- mlxsw_sp_port_hw_tc_stats[i].str, tc);
- *p += ETH_GSTRING_LEN;
- }
-}
-
-static void mlxsw_sp_port_get_strings(struct net_device *dev,
- u32 stringset, u8 *data)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- u8 *p = data;
- int i;
-
- switch (stringset) {
- case ETH_SS_STATS:
- for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) {
- memcpy(p, mlxsw_sp_port_hw_stats[i].str,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
-
- for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; i++) {
- memcpy(p, mlxsw_sp_port_hw_rfc_2863_stats[i].str,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
-
- for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; i++) {
- memcpy(p, mlxsw_sp_port_hw_rfc_2819_stats[i].str,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
-
- for (i = 0; i < MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; i++) {
- memcpy(p, mlxsw_sp_port_hw_rfc_3635_stats[i].str,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
-
- for (i = 0; i < MLXSW_SP_PORT_HW_EXT_STATS_LEN; i++) {
- memcpy(p, mlxsw_sp_port_hw_ext_stats[i].str,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
-
- for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) {
- memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- }
-
- for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
- mlxsw_sp_port_get_prio_strings(&p, i);
-
- for (i = 0; i < TC_MAX_QUEUE; i++)
- mlxsw_sp_port_get_tc_strings(&p, i);
-
- mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_strings(&p);
- break;
- }
-}
-
-static int mlxsw_sp_port_set_phys_id(struct net_device *dev,
- enum ethtool_phys_id_state state)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- char mlcr_pl[MLXSW_REG_MLCR_LEN];
- bool active;
-
- switch (state) {
- case ETHTOOL_ID_ACTIVE:
- active = true;
- break;
- case ETHTOOL_ID_INACTIVE:
- active = false;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- mlxsw_reg_mlcr_pack(mlcr_pl, mlxsw_sp_port->local_port, active);
- return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mlcr), mlcr_pl);
-}
-
-static int
-mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats,
- int *p_len, enum mlxsw_reg_ppcnt_grp grp)
-{
- switch (grp) {
- case MLXSW_REG_PPCNT_IEEE_8023_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_stats;
- *p_len = MLXSW_SP_PORT_HW_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_RFC_2863_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_rfc_2863_stats;
- *p_len = MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_RFC_2819_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_rfc_2819_stats;
- *p_len = MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_RFC_3635_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats;
- *p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_EXT_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_ext_stats;
- *p_len = MLXSW_SP_PORT_HW_EXT_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_DISCARD_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_discard_stats;
- *p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_PRIO_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_prio_stats;
- *p_len = MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
- break;
- case MLXSW_REG_PPCNT_TC_CNT:
- *p_hw_stats = mlxsw_sp_port_hw_tc_stats;
- *p_len = MLXSW_SP_PORT_HW_TC_STATS_LEN;
- break;
- default:
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static void __mlxsw_sp_port_get_stats(struct net_device *dev,
- enum mlxsw_reg_ppcnt_grp grp, int prio,
- u64 *data, int data_index)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- struct mlxsw_sp_port_hw_stats *hw_stats;
- char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
- int i, len;
- int err;
-
- err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp);
- if (err)
- return;
- mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl);
- for (i = 0; i < len; i++) {
- data[data_index + i] = hw_stats[i].getter(ppcnt_pl);
- if (!hw_stats[i].cells_bytes)
- continue;
- data[data_index + i] = mlxsw_sp_cells_bytes(mlxsw_sp,
- data[data_index + i]);
- }
-}
-
-static void mlxsw_sp_port_get_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- int i, data_index = 0;
-
- /* IEEE 802.3 Counters */
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 0,
- data, data_index);
- data_index = MLXSW_SP_PORT_HW_STATS_LEN;
-
- /* RFC 2863 Counters */
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2863_CNT, 0,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
-
- /* RFC 2819 Counters */
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2819_CNT, 0,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
-
- /* RFC 3635 Counters */
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_3635_CNT, 0,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
-
- /* Extended Counters */
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_EXT_CNT, 0,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_EXT_STATS_LEN;
-
- /* Discard Counters */
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
-
- /* Per-Priority Counters */
- for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_PRIO_CNT, i,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
- }
-
- /* Per-TC Counters */
- for (i = 0; i < TC_MAX_QUEUE; i++) {
- __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_TC_CNT, i,
- data, data_index);
- data_index += MLXSW_SP_PORT_HW_TC_STATS_LEN;
- }
-
- /* PTP counters */
- mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats(mlxsw_sp_port,
- data, data_index);
- data_index += mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
-}
-
-static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
-
- switch (sset) {
- case ETH_SS_STATS:
- return MLXSW_SP_PORT_ETHTOOL_STATS_LEN +
- mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
- default:
- return -EOPNOTSUPP;
- }
-}
-
-struct mlxsw_sp1_port_link_mode {
- enum ethtool_link_mode_bit_indices mask_ethtool;
- u32 mask;
- u32 speed;
-};
-
-static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
- .mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
- .speed = SPEED_100,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
- MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
- .mask_ethtool = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
- .speed = SPEED_1000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_T,
- .mask_ethtool = ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- .speed = SPEED_10000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
- .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
- .speed = SPEED_10000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
- .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
- .speed = SPEED_10000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_20GBASE_KR2,
- .mask_ethtool = ETHTOOL_LINK_MODE_20000baseKR2_Full_BIT,
- .speed = SPEED_20000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
- .mask_ethtool = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
- .speed = SPEED_40000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
- .mask_ethtool = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
- .speed = SPEED_40000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
- .mask_ethtool = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
- .speed = SPEED_40000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
- .mask_ethtool = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
- .speed = SPEED_40000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR,
- .mask_ethtool = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
- .speed = SPEED_25000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR,
- .mask_ethtool = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
- .speed = SPEED_25000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
- .mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
- .speed = SPEED_25000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
- .mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
- .speed = SPEED_50000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
- .mask_ethtool = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
- .speed = SPEED_50000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2,
- .mask_ethtool = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
- .speed = SPEED_50000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
- .mask_ethtool = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
- .speed = SPEED_100000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4,
- .mask_ethtool = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
- .speed = SPEED_100000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
- .mask_ethtool = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
- .speed = SPEED_100000,
- },
- {
- .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
- .mask_ethtool = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
- .speed = SPEED_100000,
- },
-};
-
-#define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
-
-static void
-mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
- u32 ptys_eth_proto,
- struct ethtool_link_ksettings *cmd)
-{
- if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
- MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
- MLXSW_REG_PTYS_ETH_SPEED_SGMII))
- ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
-
- if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
- MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
- MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
- MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
- MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
- ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
-}
-
-static void
-mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
- u8 width, unsigned long *mode)
-{
- int i;
-
- for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
- if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
- __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
- mode);
- }
-}
-
-static u32
-mlxsw_sp1_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
-{
- int i;
-
- for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
- if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
- return mlxsw_sp1_port_link_mode[i].speed;
- }
-
- return SPEED_UNKNOWN;
-}
-
-static void
-mlxsw_sp1_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
- u32 ptys_eth_proto,
- struct ethtool_link_ksettings *cmd)
-{
- cmd->base.speed = SPEED_UNKNOWN;
- cmd->base.duplex = DUPLEX_UNKNOWN;
-
- if (!carrier_ok)
- return;
-
- cmd->base.speed = mlxsw_sp1_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
- if (cmd->base.speed != SPEED_UNKNOWN)
- cmd->base.duplex = DUPLEX_FULL;
-}
-
-static u32
-mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
- const struct ethtool_link_ksettings *cmd)
-{
- u32 ptys_proto = 0;
- int i;
-
- for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
- if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
- cmd->link_modes.advertising))
- ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
- }
- return ptys_proto;
-}
-
-static u32 mlxsw_sp1_to_ptys_speed(struct mlxsw_sp *mlxsw_sp, u8 width,
- u32 speed)
-{
- u32 ptys_proto = 0;
- int i;
-
- for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
- if (speed == mlxsw_sp1_port_link_mode[i].speed)
- ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
- }
- return ptys_proto;
-}
-
-static void
-mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
- u8 local_port, u32 proto_admin, bool autoneg)
-{
- mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg);
-}
-
-static void
-mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
- u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
- u32 *p_eth_proto_oper)
-{
- mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin,
- p_eth_proto_oper);
-}
-
-static const struct mlxsw_sp_port_type_speed_ops
-mlxsw_sp1_port_type_speed_ops = {
- .from_ptys_supported_port = mlxsw_sp1_from_ptys_supported_port,
- .from_ptys_link = mlxsw_sp1_from_ptys_link,
- .from_ptys_speed = mlxsw_sp1_from_ptys_speed,
- .from_ptys_speed_duplex = mlxsw_sp1_from_ptys_speed_duplex,
- .to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link,
- .to_ptys_speed = mlxsw_sp1_to_ptys_speed,
- .reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack,
- .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack,
-};
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_sgmii_100m[] = {
- ETHTOOL_LINK_MODE_100baseT_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = {
- ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
- ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii[] = {
- ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_5gbase_r[] = {
- ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = {
- ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
- ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
- ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
- ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
- ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
- ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = {
- ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
- ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
- ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
- ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = {
- ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
- ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
- ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = {
- ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
- ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
- ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = {
- ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
- ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
- ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
- ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
- ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = {
- ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = {
- ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
- ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
- ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
- ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
- ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
- ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
- ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
-
-static const enum ethtool_link_mode_bit_indices
-mlxsw_sp2_mask_ethtool_400gaui_8[] = {
- ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
- ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
- ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
- ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
- ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
-};
-
-#define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \
- ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_8)
-
-#define MLXSW_SP_PORT_MASK_WIDTH_1X BIT(0)
-#define MLXSW_SP_PORT_MASK_WIDTH_2X BIT(1)
-#define MLXSW_SP_PORT_MASK_WIDTH_4X BIT(2)
-#define MLXSW_SP_PORT_MASK_WIDTH_8X BIT(3)
-
-static u8 mlxsw_sp_port_mask_width_get(u8 width)
-{
- switch (width) {
- case 1:
- return MLXSW_SP_PORT_MASK_WIDTH_1X;
- case 2:
- return MLXSW_SP_PORT_MASK_WIDTH_2X;
- case 4:
- return MLXSW_SP_PORT_MASK_WIDTH_4X;
- case 8:
- return MLXSW_SP_PORT_MASK_WIDTH_8X;
- default:
- WARN_ON_ONCE(1);
- return 0;
- }
-}
-
-struct mlxsw_sp2_port_link_mode {
- const enum ethtool_link_mode_bit_indices *mask_ethtool;
- int m_ethtool_len;
- u32 mask;
- u32 speed;
- u8 mask_width;
-};
-
-static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_sgmii_100m,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
- MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_100,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_1000base_x_sgmii,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
- MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_1000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_2_5GBASE_X_2_5GMII,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_2_5gbase_x_2_5gmii,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_2_5GBASE_X_2_5GMII_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
- MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_2500,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_5gbase_r,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
- MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_5000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
- MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_10000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_40000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
- MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_25000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_2X |
- MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_50000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_1X,
- .speed = SPEED_50000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_100000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_2X,
- .speed = SPEED_100000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_4X |
- MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_200000,
- },
- {
- .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8,
- .mask_ethtool = mlxsw_sp2_mask_ethtool_400gaui_8,
- .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN,
- .mask_width = MLXSW_SP_PORT_MASK_WIDTH_8X,
- .speed = SPEED_400000,
- },
-};
-
-#define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
-
-static void
-mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
- u32 ptys_eth_proto,
- struct ethtool_link_ksettings *cmd)
-{
- ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
- ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
-}
-
-static void
-mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
- unsigned long *mode)
-{
- int i;
-
- for (i = 0; i < link_mode->m_ethtool_len; i++)
- __set_bit(link_mode->mask_ethtool[i], mode);
-}
-
-static void
-mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
- u8 width, unsigned long *mode)
-{
- u8 mask_width = mlxsw_sp_port_mask_width_get(width);
- int i;
-
- for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
- if ((ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) &&
- (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
- mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
- mode);
- }
-}
-
-static u32
-mlxsw_sp2_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
-{
- int i;
-
- for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
- if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
- return mlxsw_sp2_port_link_mode[i].speed;
- }
-
- return SPEED_UNKNOWN;
-}
-
-static void
-mlxsw_sp2_from_ptys_speed_duplex(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
- u32 ptys_eth_proto,
- struct ethtool_link_ksettings *cmd)
-{
- cmd->base.speed = SPEED_UNKNOWN;
- cmd->base.duplex = DUPLEX_UNKNOWN;
-
- if (!carrier_ok)
- return;
-
- cmd->base.speed = mlxsw_sp2_from_ptys_speed(mlxsw_sp, ptys_eth_proto);
- if (cmd->base.speed != SPEED_UNKNOWN)
- cmd->base.duplex = DUPLEX_FULL;
-}
-
-static bool
-mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
- const unsigned long *mode)
-{
- int cnt = 0;
- int i;
-
- for (i = 0; i < link_mode->m_ethtool_len; i++) {
- if (test_bit(link_mode->mask_ethtool[i], mode))
- cnt++;
- }
-
- return cnt == link_mode->m_ethtool_len;
-}
-
-static u32
-mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, u8 width,
- const struct ethtool_link_ksettings *cmd)
-{
- u8 mask_width = mlxsw_sp_port_mask_width_get(width);
- u32 ptys_proto = 0;
- int i;
-
- for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
- if ((mask_width & mlxsw_sp2_port_link_mode[i].mask_width) &&
- mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
- cmd->link_modes.advertising))
- ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
- }
- return ptys_proto;
-}
-
-static u32 mlxsw_sp2_to_ptys_speed(struct mlxsw_sp *mlxsw_sp,
- u8 width, u32 speed)
-{
- u8 mask_width = mlxsw_sp_port_mask_width_get(width);
- u32 ptys_proto = 0;
- int i;
-
- for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
- if ((speed == mlxsw_sp2_port_link_mode[i].speed) &&
- (mask_width & mlxsw_sp2_port_link_mode[i].mask_width))
- ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
- }
- return ptys_proto;
-}
-
-static void
-mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
- u8 local_port, u32 proto_admin,
- bool autoneg)
-{
- mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg);
-}
-
-static void
-mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
- u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
- u32 *p_eth_proto_oper)
-{
- mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap,
- p_eth_proto_admin, p_eth_proto_oper);
-}
-
-static const struct mlxsw_sp_port_type_speed_ops
-mlxsw_sp2_port_type_speed_ops = {
- .from_ptys_supported_port = mlxsw_sp2_from_ptys_supported_port,
- .from_ptys_link = mlxsw_sp2_from_ptys_link,
- .from_ptys_speed = mlxsw_sp2_from_ptys_speed,
- .from_ptys_speed_duplex = mlxsw_sp2_from_ptys_speed_duplex,
- .to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link,
- .to_ptys_speed = mlxsw_sp2_to_ptys_speed,
- .reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack,
- .reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack,
-};
-
-static void
-mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
- u8 width, struct ethtool_link_ksettings *cmd)
-{
- const struct mlxsw_sp_port_type_speed_ops *ops;
-
- ops = mlxsw_sp->port_type_speed_ops;
-
- ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
- ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
- ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
-
- ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd);
- ops->from_ptys_link(mlxsw_sp, eth_proto_cap, width,
- cmd->link_modes.supported);
-}
-
-static void
-mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
- u32 eth_proto_admin, bool autoneg, u8 width,
- struct ethtool_link_ksettings *cmd)
-{
- const struct mlxsw_sp_port_type_speed_ops *ops;
-
- ops = mlxsw_sp->port_type_speed_ops;
-
- if (!autoneg)
- return;
-
- ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
- ops->from_ptys_link(mlxsw_sp, eth_proto_admin, width,
- cmd->link_modes.advertising);
-}
-
-static u8
-mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)
-{
- switch (connector_type) {
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR:
- return PORT_OTHER;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE:
- return PORT_NONE;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP:
- return PORT_TP;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI:
- return PORT_AUI;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC:
- return PORT_BNC;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII:
- return PORT_MII;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE:
- return PORT_FIBRE;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA:
- return PORT_DA;
- case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER:
- return PORT_OTHER;
- default:
- WARN_ON_ONCE(1);
- return PORT_OTHER;
- }
-}
-
-static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
- struct ethtool_link_ksettings *cmd)
-{
- u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- const struct mlxsw_sp_port_type_speed_ops *ops;
- char ptys_pl[MLXSW_REG_PTYS_LEN];
- u8 connector_type;
- bool autoneg;
- int err;
-
- ops = mlxsw_sp->port_type_speed_ops;
-
- autoneg = mlxsw_sp_port->link.autoneg;
- ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
- 0, false);
- err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
- if (err)
- return err;
- ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
- &eth_proto_admin, &eth_proto_oper);
-
- mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap,
- mlxsw_sp_port->mapping.width, cmd);
-
- mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg,
- mlxsw_sp_port->mapping.width, cmd);
-
- cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
- connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
- cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
- ops->from_ptys_speed_duplex(mlxsw_sp, netif_carrier_ok(dev),
- eth_proto_oper, cmd);
-
- return 0;
-}
-
-static int
-mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
- const struct ethtool_link_ksettings *cmd)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- const struct mlxsw_sp_port_type_speed_ops *ops;
- char ptys_pl[MLXSW_REG_PTYS_LEN];
- u32 eth_proto_cap, eth_proto_new;
- bool autoneg;
- int err;
-
- ops = mlxsw_sp->port_type_speed_ops;
-
- ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
- 0, false);
- err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
- if (err)
- return err;
- ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap, NULL, NULL);
-
- autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
- eth_proto_new = autoneg ?
- ops->to_ptys_advert_link(mlxsw_sp, mlxsw_sp_port->mapping.width,
- cmd) :
- ops->to_ptys_speed(mlxsw_sp, mlxsw_sp_port->mapping.width,
- cmd->base.speed);
-
- eth_proto_new = eth_proto_new & eth_proto_cap;
- if (!eth_proto_new) {
- netdev_err(dev, "No supported speed requested\n");
- return -EINVAL;
- }
-
- ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
- eth_proto_new, autoneg);
- err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
- if (err)
- return err;
-
- mlxsw_sp_port->link.autoneg = autoneg;
-
- if (!netif_running(dev))
- return 0;
-
- mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
- mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
-
- return 0;
-}
-
-static int mlxsw_sp_get_module_info(struct net_device *netdev,
- struct ethtool_modinfo *modinfo)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- int err;
-
- err = mlxsw_env_get_module_info(mlxsw_sp->core,
- mlxsw_sp_port->mapping.module,
- modinfo);
-
- return err;
-}
-
-static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
- struct ethtool_eeprom *ee,
- u8 *data)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
- int err;
-
- err = mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core,
- mlxsw_sp_port->mapping.module, ee,
- data);
-
- return err;
-}
-
-static int
-mlxsw_sp_get_ts_info(struct net_device *netdev, struct ethtool_ts_info *info)
-{
- struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
- struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-
- return mlxsw_sp->ptp_ops->get_ts_info(mlxsw_sp, info);
-}
-
-static const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
- .get_drvinfo = mlxsw_sp_port_get_drvinfo,
- .get_link = ethtool_op_get_link,
- .get_pauseparam = mlxsw_sp_port_get_pauseparam,
- .set_pauseparam = mlxsw_sp_port_set_pauseparam,
- .get_strings = mlxsw_sp_port_get_strings,
- .set_phys_id = mlxsw_sp_port_set_phys_id,
- .get_ethtool_stats = mlxsw_sp_port_get_stats,
- .get_sset_count = mlxsw_sp_port_get_sset_count,
- .get_link_ksettings = mlxsw_sp_port_get_link_ksettings,
- .set_link_ksettings = mlxsw_sp_port_set_link_ksettings,
- .get_module_info = mlxsw_sp_get_module_info,
- .get_module_eeprom = mlxsw_sp_get_module_eeprom,
- .get_ts_info = mlxsw_sp_get_ts_info,
-};
-
static int
mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
{
@@ -3246,12 +1744,16 @@ static int mlxsw_sp_port_create(struct mlxsw_sp *mlxsw_sp, u8 local_port,
struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
bool split = !!split_base_local_port;
struct mlxsw_sp_port *mlxsw_sp_port;
+ u32 lanes = port_mapping->width;
struct net_device *dev;
+ bool splittable;
int err;
+ splittable = lanes > 1 && !split;
err = mlxsw_core_port_init(mlxsw_sp->core, local_port,
port_mapping->module + 1, split,
- port_mapping->lane / port_mapping->width,
+ port_mapping->lane / lanes,
+ splittable, lanes,
mlxsw_sp->base_mac,
sizeof(mlxsw_sp->base_mac));
if (err) {
@@ -3745,13 +2247,6 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
return -EINVAL;
}
- /* Split ports cannot be split. */
- if (mlxsw_sp_port->split) {
- netdev_err(mlxsw_sp_port->dev, "Port cannot be split further\n");
- NL_SET_ERR_MSG_MOD(extack, "Port cannot be split further");
- return -EINVAL;
- }
-
max_width = mlxsw_core_module_max_width(mlxsw_core,
mlxsw_sp_port->mapping.module);
if (max_width < 0) {
@@ -3760,19 +2255,13 @@ static int mlxsw_sp_port_split(struct mlxsw_core *mlxsw_core, u8 local_port,
return max_width;
}
- /* Split port with non-max and 1 module width cannot be split. */
- if (mlxsw_sp_port->mapping.width != max_width || max_width == 1) {
+ /* Split port with non-max cannot be split. */
+ if (mlxsw_sp_port->mapping.width != max_width) {
netdev_err(mlxsw_sp_port->dev, "Port cannot be split\n");
NL_SET_ERR_MSG_MOD(extack, "Port cannot be split");
return -EINVAL;
}
- if (count == 1 || !is_power_of_2(count) || count > max_width) {
- netdev_err(mlxsw_sp_port->dev, "Invalid split count\n");
- NL_SET_ERR_MSG_MOD(extack, "Invalid split count");
- return -EINVAL;
- }
-
offset = mlxsw_sp_local_ports_offset(mlxsw_core, count, max_width);
if (offset < 0) {
netdev_err(mlxsw_sp_port->dev, "Cannot obtain local port offset\n");
@@ -4334,52 +2823,6 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
.get_stats = mlxsw_sp2_get_stats,
};
-static u32 mlxsw_sp1_span_buffsize_get(int mtu, u32 speed)
-{
- return mtu * 5 / 2;
-}
-
-static const struct mlxsw_sp_span_ops mlxsw_sp1_span_ops = {
- .buffsize_get = mlxsw_sp1_span_buffsize_get,
-};
-
-#define MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR 38
-#define MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR 50
-
-static u32 __mlxsw_sp_span_buffsize_get(int mtu, u32 speed, u32 buffer_factor)
-{
- return 3 * mtu + buffer_factor * speed / 1000;
-}
-
-static u32 mlxsw_sp2_span_buffsize_get(int mtu, u32 speed)
-{
- int factor = MLXSW_SP2_SPAN_EG_MIRROR_BUFFER_FACTOR;
-
- return __mlxsw_sp_span_buffsize_get(mtu, speed, factor);
-}
-
-static const struct mlxsw_sp_span_ops mlxsw_sp2_span_ops = {
- .buffsize_get = mlxsw_sp2_span_buffsize_get,
-};
-
-static u32 mlxsw_sp3_span_buffsize_get(int mtu, u32 speed)
-{
- int factor = MLXSW_SP3_SPAN_EG_MIRROR_BUFFER_FACTOR;
-
- return __mlxsw_sp_span_buffsize_get(mtu, speed, factor);
-}
-
-static const struct mlxsw_sp_span_ops mlxsw_sp3_span_ops = {
- .buffsize_get = mlxsw_sp3_span_buffsize_get,
-};
-
-u32 mlxsw_sp_span_buffsize_get(struct mlxsw_sp *mlxsw_sp, int mtu, u32 speed)
-{
- u32 buffsize = mlxsw_sp->span_ops->buffsize_get(speed, mtu);
-
- return mlxsw_sp_bytes_cells(mlxsw_sp, buffsize) + 1;
-}
-
static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
unsigned long event, void *ptr);
@@ -4417,6 +2860,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_fids_init;
}
+ err = mlxsw_sp_policers_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize policers\n");
+ goto err_policers_init;
+ }
+
err = mlxsw_sp_traps_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to set traps\n");
@@ -4576,6 +3025,8 @@ err_buffers_init:
err_devlink_traps_init:
mlxsw_sp_traps_fini(mlxsw_sp);
err_traps_init:
+ mlxsw_sp_policers_fini(mlxsw_sp);
+err_policers_init:
mlxsw_sp_fids_fini(mlxsw_sp);
err_fids_init:
mlxsw_sp_kvdl_fini(mlxsw_sp);
@@ -4594,6 +3045,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->afa_ops = &mlxsw_sp1_act_afa_ops;
mlxsw_sp->afk_ops = &mlxsw_sp1_afk_ops;
mlxsw_sp->mr_tcam_ops = &mlxsw_sp1_mr_tcam_ops;
+ mlxsw_sp->acl_rulei_ops = &mlxsw_sp1_acl_rulei_ops;
mlxsw_sp->acl_tcam_ops = &mlxsw_sp1_acl_tcam_ops;
mlxsw_sp->nve_ops_arr = mlxsw_sp1_nve_ops_arr;
mlxsw_sp->mac_mask = mlxsw_sp1_mac_mask;
@@ -4602,6 +3054,8 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->port_type_speed_ops = &mlxsw_sp1_port_type_speed_ops;
mlxsw_sp->ptp_ops = &mlxsw_sp1_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp1_span_ops;
+ mlxsw_sp->policer_core_ops = &mlxsw_sp1_policer_core_ops;
+ mlxsw_sp->trap_ops = &mlxsw_sp1_trap_ops;
mlxsw_sp->listeners = mlxsw_sp1_listener;
mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
@@ -4621,6 +3075,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
+ mlxsw_sp->acl_rulei_ops = &mlxsw_sp2_acl_rulei_ops;
mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
@@ -4629,6 +3084,8 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp2_span_ops;
+ mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
+ mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
@@ -4640,10 +3097,13 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
{
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+ mlxsw_sp->req_rev = &mlxsw_sp3_fw_rev;
+ mlxsw_sp->fw_filename = MLXSW_SP3_FW_FILENAME;
mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
+ mlxsw_sp->acl_rulei_ops = &mlxsw_sp2_acl_rulei_ops;
mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
@@ -4652,6 +3112,8 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp3_span_ops;
+ mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
+ mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
@@ -4681,6 +3143,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_buffers_fini(mlxsw_sp);
mlxsw_sp_devlink_traps_fini(mlxsw_sp);
mlxsw_sp_traps_fini(mlxsw_sp);
+ mlxsw_sp_policers_fini(mlxsw_sp);
mlxsw_sp_fids_fini(mlxsw_sp);
mlxsw_sp_kvdl_fini(mlxsw_sp);
}
@@ -4892,6 +3355,10 @@ static int mlxsw_sp1_resources_register(struct mlxsw_core *mlxsw_core)
if (err)
goto err_resources_counter_register;
+ err = mlxsw_sp_policer_resources_register(mlxsw_core);
+ if (err)
+ goto err_resources_counter_register;
+
return 0;
err_resources_counter_register:
@@ -4916,6 +3383,10 @@ static int mlxsw_sp2_resources_register(struct mlxsw_core *mlxsw_core)
if (err)
goto err_resources_counter_register;
+ err = mlxsw_sp_policer_resources_register(mlxsw_core);
+ if (err)
+ goto err_resources_counter_register;
+
return 0;
err_resources_counter_register:
@@ -6330,3 +4801,4 @@ MODULE_DEVICE_TABLE(pci, mlxsw_sp2_pci_id_table);
MODULE_DEVICE_TABLE(pci, mlxsw_sp3_pci_id_table);
MODULE_FIRMWARE(MLXSW_SP1_FW_FILENAME);
MODULE_FIRMWARE(MLXSW_SP2_FW_FILENAME);
+MODULE_FIRMWARE(MLXSW_SP3_FW_FILENAME);