18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
28c2ecf20Sopenharmony_ci/* Copyright (c) 2019-2020 Marvell International Ltd. All rights reserved */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
58c2ecf20Sopenharmony_ci#include <linux/ethtool.h>
68c2ecf20Sopenharmony_ci#include <linux/list.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include "prestera.h"
98c2ecf20Sopenharmony_ci#include "prestera_hw.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#define PRESTERA_SWITCH_INIT_TIMEOUT_MS (30 * 1000)
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define PRESTERA_MIN_MTU 64
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cienum prestera_cmd_type_t {
168c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_SWITCH_INIT = 0x1,
178c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_SWITCH_ATTR_SET = 0x2,
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_PORT_ATTR_SET = 0x100,
208c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_PORT_ATTR_GET = 0x101,
218c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_PORT_INFO_GET = 0x110,
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_VLAN_CREATE = 0x200,
248c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_VLAN_DELETE = 0x201,
258c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_VLAN_PORT_SET = 0x202,
268c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_VLAN_PVID_SET = 0x203,
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_FDB_ADD = 0x300,
298c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_FDB_DELETE = 0x301,
308c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_FDB_FLUSH_PORT = 0x310,
318c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN = 0x311,
328c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN = 0x312,
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_BRIDGE_CREATE = 0x400,
358c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_BRIDGE_DELETE = 0x401,
368c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD = 0x402,
378c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE = 0x403,
388c2ecf20Sopenharmony_ci
398c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_RXTX_INIT = 0x800,
408c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_RXTX_PORT_INIT = 0x801,
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_ACK = 0x10000,
458c2ecf20Sopenharmony_ci	PRESTERA_CMD_TYPE_MAX
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cienum {
498c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_ADMIN_STATE = 1,
508c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_MTU = 3,
518c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_MAC = 4,
528c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_SPEED = 5,
538c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE = 6,
548c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
558c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
568c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
578c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY = 10,
588c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_REMOTE_FC = 11,
598c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_LINK_MODE = 12,
608c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_TYPE = 13,
618c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_FEC = 14,
628c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_AUTONEG = 15,
638c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_DUPLEX = 16,
648c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_STATS = 17,
658c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_MDIX = 18,
668c2ecf20Sopenharmony_ci	PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART = 19,
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cienum {
708c2ecf20Sopenharmony_ci	PRESTERA_CMD_SWITCH_ATTR_MAC = 1,
718c2ecf20Sopenharmony_ci	PRESTERA_CMD_SWITCH_ATTR_AGEING = 2,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cienum {
758c2ecf20Sopenharmony_ci	PRESTERA_CMD_ACK_OK,
768c2ecf20Sopenharmony_ci	PRESTERA_CMD_ACK_FAILED,
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	PRESTERA_CMD_ACK_MAX
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cienum {
828c2ecf20Sopenharmony_ci	PRESTERA_PORT_TP_NA,
838c2ecf20Sopenharmony_ci	PRESTERA_PORT_TP_MDI,
848c2ecf20Sopenharmony_ci	PRESTERA_PORT_TP_MDIX,
858c2ecf20Sopenharmony_ci	PRESTERA_PORT_TP_AUTO,
868c2ecf20Sopenharmony_ci};
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_cienum {
898c2ecf20Sopenharmony_ci	PRESTERA_PORT_GOOD_OCTETS_RCV_CNT,
908c2ecf20Sopenharmony_ci	PRESTERA_PORT_BAD_OCTETS_RCV_CNT,
918c2ecf20Sopenharmony_ci	PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT,
928c2ecf20Sopenharmony_ci	PRESTERA_PORT_BRDC_PKTS_RCV_CNT,
938c2ecf20Sopenharmony_ci	PRESTERA_PORT_MC_PKTS_RCV_CNT,
948c2ecf20Sopenharmony_ci	PRESTERA_PORT_PKTS_64L_CNT,
958c2ecf20Sopenharmony_ci	PRESTERA_PORT_PKTS_65TO127L_CNT,
968c2ecf20Sopenharmony_ci	PRESTERA_PORT_PKTS_128TO255L_CNT,
978c2ecf20Sopenharmony_ci	PRESTERA_PORT_PKTS_256TO511L_CNT,
988c2ecf20Sopenharmony_ci	PRESTERA_PORT_PKTS_512TO1023L_CNT,
998c2ecf20Sopenharmony_ci	PRESTERA_PORT_PKTS_1024TOMAXL_CNT,
1008c2ecf20Sopenharmony_ci	PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT,
1018c2ecf20Sopenharmony_ci	PRESTERA_PORT_MC_PKTS_SENT_CNT,
1028c2ecf20Sopenharmony_ci	PRESTERA_PORT_BRDC_PKTS_SENT_CNT,
1038c2ecf20Sopenharmony_ci	PRESTERA_PORT_FC_SENT_CNT,
1048c2ecf20Sopenharmony_ci	PRESTERA_PORT_GOOD_FC_RCV_CNT,
1058c2ecf20Sopenharmony_ci	PRESTERA_PORT_DROP_EVENTS_CNT,
1068c2ecf20Sopenharmony_ci	PRESTERA_PORT_UNDERSIZE_PKTS_CNT,
1078c2ecf20Sopenharmony_ci	PRESTERA_PORT_FRAGMENTS_PKTS_CNT,
1088c2ecf20Sopenharmony_ci	PRESTERA_PORT_OVERSIZE_PKTS_CNT,
1098c2ecf20Sopenharmony_ci	PRESTERA_PORT_JABBER_PKTS_CNT,
1108c2ecf20Sopenharmony_ci	PRESTERA_PORT_MAC_RCV_ERROR_CNT,
1118c2ecf20Sopenharmony_ci	PRESTERA_PORT_BAD_CRC_CNT,
1128c2ecf20Sopenharmony_ci	PRESTERA_PORT_COLLISIONS_CNT,
1138c2ecf20Sopenharmony_ci	PRESTERA_PORT_LATE_COLLISIONS_CNT,
1148c2ecf20Sopenharmony_ci	PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT,
1158c2ecf20Sopenharmony_ci	PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT,
1168c2ecf20Sopenharmony_ci	PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT,
1178c2ecf20Sopenharmony_ci	PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT,
1188c2ecf20Sopenharmony_ci	PRESTERA_PORT_GOOD_OCTETS_SENT_CNT,
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	PRESTERA_PORT_CNT_MAX
1218c2ecf20Sopenharmony_ci};
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cienum {
1248c2ecf20Sopenharmony_ci	PRESTERA_FC_NONE,
1258c2ecf20Sopenharmony_ci	PRESTERA_FC_SYMMETRIC,
1268c2ecf20Sopenharmony_ci	PRESTERA_FC_ASYMMETRIC,
1278c2ecf20Sopenharmony_ci	PRESTERA_FC_SYMM_ASYMM,
1288c2ecf20Sopenharmony_ci};
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_cistruct prestera_fw_event_handler {
1318c2ecf20Sopenharmony_ci	struct list_head list;
1328c2ecf20Sopenharmony_ci	struct rcu_head rcu;
1338c2ecf20Sopenharmony_ci	enum prestera_event_type type;
1348c2ecf20Sopenharmony_ci	prestera_event_cb_t func;
1358c2ecf20Sopenharmony_ci	void *arg;
1368c2ecf20Sopenharmony_ci};
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct prestera_msg_cmd {
1398c2ecf20Sopenharmony_ci	u32 type;
1408c2ecf20Sopenharmony_ci};
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistruct prestera_msg_ret {
1438c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
1448c2ecf20Sopenharmony_ci	u32 status;
1458c2ecf20Sopenharmony_ci};
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistruct prestera_msg_common_req {
1488c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
1498c2ecf20Sopenharmony_ci};
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_cistruct prestera_msg_common_resp {
1528c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ciunion prestera_msg_switch_param {
1568c2ecf20Sopenharmony_ci	u8 mac[ETH_ALEN];
1578c2ecf20Sopenharmony_ci	u32 ageing_timeout_ms;
1588c2ecf20Sopenharmony_ci};
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistruct prestera_msg_switch_attr_req {
1618c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
1628c2ecf20Sopenharmony_ci	u32 attr;
1638c2ecf20Sopenharmony_ci	union prestera_msg_switch_param param;
1648c2ecf20Sopenharmony_ci};
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistruct prestera_msg_switch_init_resp {
1678c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
1688c2ecf20Sopenharmony_ci	u32 port_count;
1698c2ecf20Sopenharmony_ci	u32 mtu_max;
1708c2ecf20Sopenharmony_ci	u8  switch_id;
1718c2ecf20Sopenharmony_ci};
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_cistruct prestera_msg_port_autoneg_param {
1748c2ecf20Sopenharmony_ci	u64 link_mode;
1758c2ecf20Sopenharmony_ci	u8  enable;
1768c2ecf20Sopenharmony_ci	u8  fec;
1778c2ecf20Sopenharmony_ci};
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistruct prestera_msg_port_cap_param {
1808c2ecf20Sopenharmony_ci	u64 link_mode;
1818c2ecf20Sopenharmony_ci	u8  type;
1828c2ecf20Sopenharmony_ci	u8  fec;
1838c2ecf20Sopenharmony_ci	u8  transceiver;
1848c2ecf20Sopenharmony_ci};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistruct prestera_msg_port_mdix_param {
1878c2ecf20Sopenharmony_ci	u8 status;
1888c2ecf20Sopenharmony_ci	u8 admin_mode;
1898c2ecf20Sopenharmony_ci};
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ciunion prestera_msg_port_param {
1928c2ecf20Sopenharmony_ci	u8  admin_state;
1938c2ecf20Sopenharmony_ci	u8  oper_state;
1948c2ecf20Sopenharmony_ci	u32 mtu;
1958c2ecf20Sopenharmony_ci	u8  mac[ETH_ALEN];
1968c2ecf20Sopenharmony_ci	u8  accept_frm_type;
1978c2ecf20Sopenharmony_ci	u32 speed;
1988c2ecf20Sopenharmony_ci	u8 learning;
1998c2ecf20Sopenharmony_ci	u8 flood;
2008c2ecf20Sopenharmony_ci	u32 link_mode;
2018c2ecf20Sopenharmony_ci	u8  type;
2028c2ecf20Sopenharmony_ci	u8  duplex;
2038c2ecf20Sopenharmony_ci	u8  fec;
2048c2ecf20Sopenharmony_ci	u8  fc;
2058c2ecf20Sopenharmony_ci	struct prestera_msg_port_mdix_param mdix;
2068c2ecf20Sopenharmony_ci	struct prestera_msg_port_autoneg_param autoneg;
2078c2ecf20Sopenharmony_ci	struct prestera_msg_port_cap_param cap;
2088c2ecf20Sopenharmony_ci};
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistruct prestera_msg_port_attr_req {
2118c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2128c2ecf20Sopenharmony_ci	u32 attr;
2138c2ecf20Sopenharmony_ci	u32 port;
2148c2ecf20Sopenharmony_ci	u32 dev;
2158c2ecf20Sopenharmony_ci	union prestera_msg_port_param param;
2168c2ecf20Sopenharmony_ci};
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_cistruct prestera_msg_port_attr_resp {
2198c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
2208c2ecf20Sopenharmony_ci	union prestera_msg_port_param param;
2218c2ecf20Sopenharmony_ci};
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_cistruct prestera_msg_port_stats_resp {
2248c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
2258c2ecf20Sopenharmony_ci	u64 stats[PRESTERA_PORT_CNT_MAX];
2268c2ecf20Sopenharmony_ci};
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistruct prestera_msg_port_info_req {
2298c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2308c2ecf20Sopenharmony_ci	u32 port;
2318c2ecf20Sopenharmony_ci};
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cistruct prestera_msg_port_info_resp {
2348c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
2358c2ecf20Sopenharmony_ci	u32 hw_id;
2368c2ecf20Sopenharmony_ci	u32 dev_id;
2378c2ecf20Sopenharmony_ci	u16 fp_id;
2388c2ecf20Sopenharmony_ci};
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_cistruct prestera_msg_vlan_req {
2418c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2428c2ecf20Sopenharmony_ci	u32 port;
2438c2ecf20Sopenharmony_ci	u32 dev;
2448c2ecf20Sopenharmony_ci	u16 vid;
2458c2ecf20Sopenharmony_ci	u8  is_member;
2468c2ecf20Sopenharmony_ci	u8  is_tagged;
2478c2ecf20Sopenharmony_ci};
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistruct prestera_msg_fdb_req {
2508c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2518c2ecf20Sopenharmony_ci	u8 dest_type;
2528c2ecf20Sopenharmony_ci	u32 port;
2538c2ecf20Sopenharmony_ci	u32 dev;
2548c2ecf20Sopenharmony_ci	u8  mac[ETH_ALEN];
2558c2ecf20Sopenharmony_ci	u16 vid;
2568c2ecf20Sopenharmony_ci	u8  dynamic;
2578c2ecf20Sopenharmony_ci	u32 flush_mode;
2588c2ecf20Sopenharmony_ci};
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_cistruct prestera_msg_bridge_req {
2618c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2628c2ecf20Sopenharmony_ci	u32 port;
2638c2ecf20Sopenharmony_ci	u32 dev;
2648c2ecf20Sopenharmony_ci	u16 bridge;
2658c2ecf20Sopenharmony_ci};
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistruct prestera_msg_bridge_resp {
2688c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
2698c2ecf20Sopenharmony_ci	u16 bridge;
2708c2ecf20Sopenharmony_ci};
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistruct prestera_msg_stp_req {
2738c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2748c2ecf20Sopenharmony_ci	u32 port;
2758c2ecf20Sopenharmony_ci	u32 dev;
2768c2ecf20Sopenharmony_ci	u16 vid;
2778c2ecf20Sopenharmony_ci	u8  state;
2788c2ecf20Sopenharmony_ci};
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistruct prestera_msg_rxtx_req {
2818c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2828c2ecf20Sopenharmony_ci	u8 use_sdma;
2838c2ecf20Sopenharmony_ci};
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_cistruct prestera_msg_rxtx_resp {
2868c2ecf20Sopenharmony_ci	struct prestera_msg_ret ret;
2878c2ecf20Sopenharmony_ci	u32 map_addr;
2888c2ecf20Sopenharmony_ci};
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_cistruct prestera_msg_rxtx_port_req {
2918c2ecf20Sopenharmony_ci	struct prestera_msg_cmd cmd;
2928c2ecf20Sopenharmony_ci	u32 port;
2938c2ecf20Sopenharmony_ci	u32 dev;
2948c2ecf20Sopenharmony_ci};
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cistruct prestera_msg_event {
2978c2ecf20Sopenharmony_ci	u16 type;
2988c2ecf20Sopenharmony_ci	u16 id;
2998c2ecf20Sopenharmony_ci};
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ciunion prestera_msg_event_port_param {
3028c2ecf20Sopenharmony_ci	u32 oper_state;
3038c2ecf20Sopenharmony_ci};
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistruct prestera_msg_event_port {
3068c2ecf20Sopenharmony_ci	struct prestera_msg_event id;
3078c2ecf20Sopenharmony_ci	u32 port_id;
3088c2ecf20Sopenharmony_ci	union prestera_msg_event_port_param param;
3098c2ecf20Sopenharmony_ci};
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ciunion prestera_msg_event_fdb_param {
3128c2ecf20Sopenharmony_ci	u8 mac[ETH_ALEN];
3138c2ecf20Sopenharmony_ci};
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistruct prestera_msg_event_fdb {
3168c2ecf20Sopenharmony_ci	struct prestera_msg_event id;
3178c2ecf20Sopenharmony_ci	u8 dest_type;
3188c2ecf20Sopenharmony_ci	u32 port_id;
3198c2ecf20Sopenharmony_ci	u32 vid;
3208c2ecf20Sopenharmony_ci	union prestera_msg_event_fdb_param param;
3218c2ecf20Sopenharmony_ci};
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic int __prestera_cmd_ret(struct prestera_switch *sw,
3248c2ecf20Sopenharmony_ci			      enum prestera_cmd_type_t type,
3258c2ecf20Sopenharmony_ci			      struct prestera_msg_cmd *cmd, size_t clen,
3268c2ecf20Sopenharmony_ci			      struct prestera_msg_ret *ret, size_t rlen,
3278c2ecf20Sopenharmony_ci			      int waitms)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct prestera_device *dev = sw->dev;
3308c2ecf20Sopenharmony_ci	int err;
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	cmd->type = type;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	err = dev->send_req(dev, cmd, clen, ret, rlen, waitms);
3358c2ecf20Sopenharmony_ci	if (err)
3368c2ecf20Sopenharmony_ci		return err;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	if (ret->cmd.type != PRESTERA_CMD_TYPE_ACK)
3398c2ecf20Sopenharmony_ci		return -EBADE;
3408c2ecf20Sopenharmony_ci	if (ret->status != PRESTERA_CMD_ACK_OK)
3418c2ecf20Sopenharmony_ci		return -EINVAL;
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci	return 0;
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic int prestera_cmd_ret(struct prestera_switch *sw,
3478c2ecf20Sopenharmony_ci			    enum prestera_cmd_type_t type,
3488c2ecf20Sopenharmony_ci			    struct prestera_msg_cmd *cmd, size_t clen,
3498c2ecf20Sopenharmony_ci			    struct prestera_msg_ret *ret, size_t rlen)
3508c2ecf20Sopenharmony_ci{
3518c2ecf20Sopenharmony_ci	return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, 0);
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic int prestera_cmd_ret_wait(struct prestera_switch *sw,
3558c2ecf20Sopenharmony_ci				 enum prestera_cmd_type_t type,
3568c2ecf20Sopenharmony_ci				 struct prestera_msg_cmd *cmd, size_t clen,
3578c2ecf20Sopenharmony_ci				 struct prestera_msg_ret *ret, size_t rlen,
3588c2ecf20Sopenharmony_ci				 int waitms)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	return __prestera_cmd_ret(sw, type, cmd, clen, ret, rlen, waitms);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic int prestera_cmd(struct prestera_switch *sw,
3648c2ecf20Sopenharmony_ci			enum prestera_cmd_type_t type,
3658c2ecf20Sopenharmony_ci			struct prestera_msg_cmd *cmd, size_t clen)
3668c2ecf20Sopenharmony_ci{
3678c2ecf20Sopenharmony_ci	struct prestera_msg_common_resp resp;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	return prestera_cmd_ret(sw, type, cmd, clen, &resp.ret, sizeof(resp));
3708c2ecf20Sopenharmony_ci}
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic int prestera_fw_parse_port_evt(void *msg, struct prestera_event *evt)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	struct prestera_msg_event_port *hw_evt = msg;
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	if (evt->id != PRESTERA_PORT_EVENT_STATE_CHANGED)
3778c2ecf20Sopenharmony_ci		return -EINVAL;
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	evt->port_evt.data.oper_state = hw_evt->param.oper_state;
3808c2ecf20Sopenharmony_ci	evt->port_evt.port_id = hw_evt->port_id;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	return 0;
3838c2ecf20Sopenharmony_ci}
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_cistatic int prestera_fw_parse_fdb_evt(void *msg, struct prestera_event *evt)
3868c2ecf20Sopenharmony_ci{
3878c2ecf20Sopenharmony_ci	struct prestera_msg_event_fdb *hw_evt = msg;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci	evt->fdb_evt.port_id = hw_evt->port_id;
3908c2ecf20Sopenharmony_ci	evt->fdb_evt.vid = hw_evt->vid;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	ether_addr_copy(evt->fdb_evt.data.mac, hw_evt->param.mac);
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	return 0;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic struct prestera_fw_evt_parser {
3988c2ecf20Sopenharmony_ci	int (*func)(void *msg, struct prestera_event *evt);
3998c2ecf20Sopenharmony_ci} fw_event_parsers[PRESTERA_EVENT_TYPE_MAX] = {
4008c2ecf20Sopenharmony_ci	[PRESTERA_EVENT_TYPE_PORT] = { .func = prestera_fw_parse_port_evt },
4018c2ecf20Sopenharmony_ci	[PRESTERA_EVENT_TYPE_FDB] = { .func = prestera_fw_parse_fdb_evt },
4028c2ecf20Sopenharmony_ci};
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic struct prestera_fw_event_handler *
4058c2ecf20Sopenharmony_ci__find_event_handler(const struct prestera_switch *sw,
4068c2ecf20Sopenharmony_ci		     enum prestera_event_type type)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	struct prestera_fw_event_handler *eh;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	list_for_each_entry_rcu(eh, &sw->event_handlers, list) {
4118c2ecf20Sopenharmony_ci		if (eh->type == type)
4128c2ecf20Sopenharmony_ci			return eh;
4138c2ecf20Sopenharmony_ci	}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	return NULL;
4168c2ecf20Sopenharmony_ci}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_cistatic int prestera_find_event_handler(const struct prestera_switch *sw,
4198c2ecf20Sopenharmony_ci				       enum prestera_event_type type,
4208c2ecf20Sopenharmony_ci				       struct prestera_fw_event_handler *eh)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	struct prestera_fw_event_handler *tmp;
4238c2ecf20Sopenharmony_ci	int err = 0;
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	rcu_read_lock();
4268c2ecf20Sopenharmony_ci	tmp = __find_event_handler(sw, type);
4278c2ecf20Sopenharmony_ci	if (tmp)
4288c2ecf20Sopenharmony_ci		*eh = *tmp;
4298c2ecf20Sopenharmony_ci	else
4308c2ecf20Sopenharmony_ci		err = -ENOENT;
4318c2ecf20Sopenharmony_ci	rcu_read_unlock();
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	return err;
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_cistatic int prestera_evt_recv(struct prestera_device *dev, void *buf, size_t size)
4378c2ecf20Sopenharmony_ci{
4388c2ecf20Sopenharmony_ci	struct prestera_switch *sw = dev->priv;
4398c2ecf20Sopenharmony_ci	struct prestera_msg_event *msg = buf;
4408c2ecf20Sopenharmony_ci	struct prestera_fw_event_handler eh;
4418c2ecf20Sopenharmony_ci	struct prestera_event evt;
4428c2ecf20Sopenharmony_ci	int err;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (msg->type >= PRESTERA_EVENT_TYPE_MAX)
4458c2ecf20Sopenharmony_ci		return -EINVAL;
4468c2ecf20Sopenharmony_ci	if (!fw_event_parsers[msg->type].func)
4478c2ecf20Sopenharmony_ci		return -ENOENT;
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	err = prestera_find_event_handler(sw, msg->type, &eh);
4508c2ecf20Sopenharmony_ci	if (err)
4518c2ecf20Sopenharmony_ci		return err;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	evt.id = msg->id;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	err = fw_event_parsers[msg->type].func(buf, &evt);
4568c2ecf20Sopenharmony_ci	if (err)
4578c2ecf20Sopenharmony_ci		return err;
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci	eh.func(sw, &evt, eh.arg);
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	return 0;
4628c2ecf20Sopenharmony_ci}
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_cistatic void prestera_pkt_recv(struct prestera_device *dev)
4658c2ecf20Sopenharmony_ci{
4668c2ecf20Sopenharmony_ci	struct prestera_switch *sw = dev->priv;
4678c2ecf20Sopenharmony_ci	struct prestera_fw_event_handler eh;
4688c2ecf20Sopenharmony_ci	struct prestera_event ev;
4698c2ecf20Sopenharmony_ci	int err;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	ev.id = PRESTERA_RXTX_EVENT_RCV_PKT;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	err = prestera_find_event_handler(sw, PRESTERA_EVENT_TYPE_RXTX, &eh);
4748c2ecf20Sopenharmony_ci	if (err)
4758c2ecf20Sopenharmony_ci		return;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	eh.func(sw, &ev, eh.arg);
4788c2ecf20Sopenharmony_ci}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ciint prestera_hw_port_info_get(const struct prestera_port *port,
4818c2ecf20Sopenharmony_ci			      u32 *dev_id, u32 *hw_id, u16 *fp_id)
4828c2ecf20Sopenharmony_ci{
4838c2ecf20Sopenharmony_ci	struct prestera_msg_port_info_req req = {
4848c2ecf20Sopenharmony_ci		.port = port->id,
4858c2ecf20Sopenharmony_ci	};
4868c2ecf20Sopenharmony_ci	struct prestera_msg_port_info_resp resp;
4878c2ecf20Sopenharmony_ci	int err;
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_INFO_GET,
4908c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
4918c2ecf20Sopenharmony_ci	if (err)
4928c2ecf20Sopenharmony_ci		return err;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	*dev_id = resp.dev_id;
4958c2ecf20Sopenharmony_ci	*hw_id = resp.hw_id;
4968c2ecf20Sopenharmony_ci	*fp_id = resp.fp_id;
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	return 0;
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ciint prestera_hw_switch_mac_set(struct prestera_switch *sw, const char *mac)
5028c2ecf20Sopenharmony_ci{
5038c2ecf20Sopenharmony_ci	struct prestera_msg_switch_attr_req req = {
5048c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_SWITCH_ATTR_MAC,
5058c2ecf20Sopenharmony_ci	};
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	ether_addr_copy(req.param.mac, mac);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
5108c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
5118c2ecf20Sopenharmony_ci}
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ciint prestera_hw_switch_init(struct prestera_switch *sw)
5148c2ecf20Sopenharmony_ci{
5158c2ecf20Sopenharmony_ci	struct prestera_msg_switch_init_resp resp;
5168c2ecf20Sopenharmony_ci	struct prestera_msg_common_req req;
5178c2ecf20Sopenharmony_ci	int err;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&sw->event_handlers);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	err = prestera_cmd_ret_wait(sw, PRESTERA_CMD_TYPE_SWITCH_INIT,
5228c2ecf20Sopenharmony_ci				    &req.cmd, sizeof(req),
5238c2ecf20Sopenharmony_ci				    &resp.ret, sizeof(resp),
5248c2ecf20Sopenharmony_ci				    PRESTERA_SWITCH_INIT_TIMEOUT_MS);
5258c2ecf20Sopenharmony_ci	if (err)
5268c2ecf20Sopenharmony_ci		return err;
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	sw->dev->recv_msg = prestera_evt_recv;
5298c2ecf20Sopenharmony_ci	sw->dev->recv_pkt = prestera_pkt_recv;
5308c2ecf20Sopenharmony_ci	sw->port_count = resp.port_count;
5318c2ecf20Sopenharmony_ci	sw->mtu_min = PRESTERA_MIN_MTU;
5328c2ecf20Sopenharmony_ci	sw->mtu_max = resp.mtu_max;
5338c2ecf20Sopenharmony_ci	sw->id = resp.switch_id;
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_ci	return 0;
5368c2ecf20Sopenharmony_ci}
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_civoid prestera_hw_switch_fini(struct prestera_switch *sw)
5398c2ecf20Sopenharmony_ci{
5408c2ecf20Sopenharmony_ci	WARN_ON(!list_empty(&sw->event_handlers));
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ciint prestera_hw_switch_ageing_set(struct prestera_switch *sw, u32 ageing_ms)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct prestera_msg_switch_attr_req req = {
5468c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_SWITCH_ATTR_AGEING,
5478c2ecf20Sopenharmony_ci		.param = {
5488c2ecf20Sopenharmony_ci			.ageing_timeout_ms = ageing_ms,
5498c2ecf20Sopenharmony_ci		},
5508c2ecf20Sopenharmony_ci	};
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	return prestera_cmd(sw, PRESTERA_CMD_TYPE_SWITCH_ATTR_SET,
5538c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
5548c2ecf20Sopenharmony_ci}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ciint prestera_hw_port_state_set(const struct prestera_port *port,
5578c2ecf20Sopenharmony_ci			       bool admin_state)
5588c2ecf20Sopenharmony_ci{
5598c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
5608c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_ADMIN_STATE,
5618c2ecf20Sopenharmony_ci		.port = port->hw_id,
5628c2ecf20Sopenharmony_ci		.dev = port->dev_id,
5638c2ecf20Sopenharmony_ci		.param = {
5648c2ecf20Sopenharmony_ci			.admin_state = admin_state,
5658c2ecf20Sopenharmony_ci		}
5668c2ecf20Sopenharmony_ci	};
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
5698c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
5708c2ecf20Sopenharmony_ci}
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ciint prestera_hw_port_mtu_set(const struct prestera_port *port, u32 mtu)
5738c2ecf20Sopenharmony_ci{
5748c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
5758c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_MTU,
5768c2ecf20Sopenharmony_ci		.port = port->hw_id,
5778c2ecf20Sopenharmony_ci		.dev = port->dev_id,
5788c2ecf20Sopenharmony_ci		.param = {
5798c2ecf20Sopenharmony_ci			.mtu = mtu,
5808c2ecf20Sopenharmony_ci		}
5818c2ecf20Sopenharmony_ci	};
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
5848c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ciint prestera_hw_port_mac_set(const struct prestera_port *port, const char *mac)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
5908c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_MAC,
5918c2ecf20Sopenharmony_ci		.port = port->hw_id,
5928c2ecf20Sopenharmony_ci		.dev = port->dev_id,
5938c2ecf20Sopenharmony_ci	};
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	ether_addr_copy(req.param.mac, mac);
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
5988c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
5998c2ecf20Sopenharmony_ci}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ciint prestera_hw_port_accept_frm_type(struct prestera_port *port,
6028c2ecf20Sopenharmony_ci				     enum prestera_accept_frm_type type)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
6058c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_ACCEPT_FRAME_TYPE,
6068c2ecf20Sopenharmony_ci		.port = port->hw_id,
6078c2ecf20Sopenharmony_ci		.dev = port->dev_id,
6088c2ecf20Sopenharmony_ci		.param = {
6098c2ecf20Sopenharmony_ci			.accept_frm_type = type,
6108c2ecf20Sopenharmony_ci		}
6118c2ecf20Sopenharmony_ci	};
6128c2ecf20Sopenharmony_ci
6138c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
6148c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ciint prestera_hw_port_cap_get(const struct prestera_port *port,
6188c2ecf20Sopenharmony_ci			     struct prestera_port_caps *caps)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
6218c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_CAPABILITY,
6228c2ecf20Sopenharmony_ci		.port = port->hw_id,
6238c2ecf20Sopenharmony_ci		.dev = port->dev_id,
6248c2ecf20Sopenharmony_ci	};
6258c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
6268c2ecf20Sopenharmony_ci	int err;
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
6298c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
6308c2ecf20Sopenharmony_ci	if (err)
6318c2ecf20Sopenharmony_ci		return err;
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	caps->supp_link_modes = resp.param.cap.link_mode;
6348c2ecf20Sopenharmony_ci	caps->transceiver = resp.param.cap.transceiver;
6358c2ecf20Sopenharmony_ci	caps->supp_fec = resp.param.cap.fec;
6368c2ecf20Sopenharmony_ci	caps->type = resp.param.cap.type;
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	return err;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ciint prestera_hw_port_remote_cap_get(const struct prestera_port *port,
6428c2ecf20Sopenharmony_ci				    u64 *link_mode_bitmap)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
6458c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_REMOTE_CAPABILITY,
6468c2ecf20Sopenharmony_ci		.port = port->hw_id,
6478c2ecf20Sopenharmony_ci		.dev = port->dev_id,
6488c2ecf20Sopenharmony_ci	};
6498c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
6508c2ecf20Sopenharmony_ci	int err;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
6538c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
6548c2ecf20Sopenharmony_ci	if (err)
6558c2ecf20Sopenharmony_ci		return err;
6568c2ecf20Sopenharmony_ci
6578c2ecf20Sopenharmony_ci	*link_mode_bitmap = resp.param.cap.link_mode;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	return 0;
6608c2ecf20Sopenharmony_ci}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ciint prestera_hw_port_remote_fc_get(const struct prestera_port *port,
6638c2ecf20Sopenharmony_ci				   bool *pause, bool *asym_pause)
6648c2ecf20Sopenharmony_ci{
6658c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
6668c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_REMOTE_FC,
6678c2ecf20Sopenharmony_ci		.port = port->hw_id,
6688c2ecf20Sopenharmony_ci		.dev = port->dev_id,
6698c2ecf20Sopenharmony_ci	};
6708c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
6718c2ecf20Sopenharmony_ci	int err;
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
6748c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
6758c2ecf20Sopenharmony_ci	if (err)
6768c2ecf20Sopenharmony_ci		return err;
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_ci	switch (resp.param.fc) {
6798c2ecf20Sopenharmony_ci	case PRESTERA_FC_SYMMETRIC:
6808c2ecf20Sopenharmony_ci		*pause = true;
6818c2ecf20Sopenharmony_ci		*asym_pause = false;
6828c2ecf20Sopenharmony_ci		break;
6838c2ecf20Sopenharmony_ci	case PRESTERA_FC_ASYMMETRIC:
6848c2ecf20Sopenharmony_ci		*pause = false;
6858c2ecf20Sopenharmony_ci		*asym_pause = true;
6868c2ecf20Sopenharmony_ci		break;
6878c2ecf20Sopenharmony_ci	case PRESTERA_FC_SYMM_ASYMM:
6888c2ecf20Sopenharmony_ci		*pause = true;
6898c2ecf20Sopenharmony_ci		*asym_pause = true;
6908c2ecf20Sopenharmony_ci		break;
6918c2ecf20Sopenharmony_ci	default:
6928c2ecf20Sopenharmony_ci		*pause = false;
6938c2ecf20Sopenharmony_ci		*asym_pause = false;
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	return 0;
6978c2ecf20Sopenharmony_ci}
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ciint prestera_hw_port_type_get(const struct prestera_port *port, u8 *type)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
7028c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_TYPE,
7038c2ecf20Sopenharmony_ci		.port = port->hw_id,
7048c2ecf20Sopenharmony_ci		.dev = port->dev_id,
7058c2ecf20Sopenharmony_ci	};
7068c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
7078c2ecf20Sopenharmony_ci	int err;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
7108c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
7118c2ecf20Sopenharmony_ci	if (err)
7128c2ecf20Sopenharmony_ci		return err;
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_ci	*type = resp.param.type;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	return 0;
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ciint prestera_hw_port_fec_get(const struct prestera_port *port, u8 *fec)
7208c2ecf20Sopenharmony_ci{
7218c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
7228c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_FEC,
7238c2ecf20Sopenharmony_ci		.port = port->hw_id,
7248c2ecf20Sopenharmony_ci		.dev = port->dev_id,
7258c2ecf20Sopenharmony_ci	};
7268c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
7278c2ecf20Sopenharmony_ci	int err;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
7308c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
7318c2ecf20Sopenharmony_ci	if (err)
7328c2ecf20Sopenharmony_ci		return err;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	*fec = resp.param.fec;
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	return 0;
7378c2ecf20Sopenharmony_ci}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ciint prestera_hw_port_fec_set(const struct prestera_port *port, u8 fec)
7408c2ecf20Sopenharmony_ci{
7418c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
7428c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_FEC,
7438c2ecf20Sopenharmony_ci		.port = port->hw_id,
7448c2ecf20Sopenharmony_ci		.dev = port->dev_id,
7458c2ecf20Sopenharmony_ci		.param = {
7468c2ecf20Sopenharmony_ci			.fec = fec,
7478c2ecf20Sopenharmony_ci		}
7488c2ecf20Sopenharmony_ci	};
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
7518c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_cistatic u8 prestera_hw_mdix_to_eth(u8 mode)
7558c2ecf20Sopenharmony_ci{
7568c2ecf20Sopenharmony_ci	switch (mode) {
7578c2ecf20Sopenharmony_ci	case PRESTERA_PORT_TP_MDI:
7588c2ecf20Sopenharmony_ci		return ETH_TP_MDI;
7598c2ecf20Sopenharmony_ci	case PRESTERA_PORT_TP_MDIX:
7608c2ecf20Sopenharmony_ci		return ETH_TP_MDI_X;
7618c2ecf20Sopenharmony_ci	case PRESTERA_PORT_TP_AUTO:
7628c2ecf20Sopenharmony_ci		return ETH_TP_MDI_AUTO;
7638c2ecf20Sopenharmony_ci	default:
7648c2ecf20Sopenharmony_ci		return ETH_TP_MDI_INVALID;
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_cistatic u8 prestera_hw_mdix_from_eth(u8 mode)
7698c2ecf20Sopenharmony_ci{
7708c2ecf20Sopenharmony_ci	switch (mode) {
7718c2ecf20Sopenharmony_ci	case ETH_TP_MDI:
7728c2ecf20Sopenharmony_ci		return PRESTERA_PORT_TP_MDI;
7738c2ecf20Sopenharmony_ci	case ETH_TP_MDI_X:
7748c2ecf20Sopenharmony_ci		return PRESTERA_PORT_TP_MDIX;
7758c2ecf20Sopenharmony_ci	case ETH_TP_MDI_AUTO:
7768c2ecf20Sopenharmony_ci		return PRESTERA_PORT_TP_AUTO;
7778c2ecf20Sopenharmony_ci	default:
7788c2ecf20Sopenharmony_ci		return PRESTERA_PORT_TP_NA;
7798c2ecf20Sopenharmony_ci	}
7808c2ecf20Sopenharmony_ci}
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ciint prestera_hw_port_mdix_get(const struct prestera_port *port, u8 *status,
7838c2ecf20Sopenharmony_ci			      u8 *admin_mode)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
7868c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_MDIX,
7878c2ecf20Sopenharmony_ci		.port = port->hw_id,
7888c2ecf20Sopenharmony_ci		.dev = port->dev_id,
7898c2ecf20Sopenharmony_ci	};
7908c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
7918c2ecf20Sopenharmony_ci	int err;
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
7948c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
7958c2ecf20Sopenharmony_ci	if (err)
7968c2ecf20Sopenharmony_ci		return err;
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	*status = prestera_hw_mdix_to_eth(resp.param.mdix.status);
7998c2ecf20Sopenharmony_ci	*admin_mode = prestera_hw_mdix_to_eth(resp.param.mdix.admin_mode);
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return 0;
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ciint prestera_hw_port_mdix_set(const struct prestera_port *port, u8 mode)
8058c2ecf20Sopenharmony_ci{
8068c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
8078c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_MDIX,
8088c2ecf20Sopenharmony_ci		.port = port->hw_id,
8098c2ecf20Sopenharmony_ci		.dev = port->dev_id,
8108c2ecf20Sopenharmony_ci	};
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	req.param.mdix.admin_mode = prestera_hw_mdix_from_eth(mode);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
8158c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ciint prestera_hw_port_link_mode_set(const struct prestera_port *port, u32 mode)
8198c2ecf20Sopenharmony_ci{
8208c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
8218c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
8228c2ecf20Sopenharmony_ci		.port = port->hw_id,
8238c2ecf20Sopenharmony_ci		.dev = port->dev_id,
8248c2ecf20Sopenharmony_ci		.param = {
8258c2ecf20Sopenharmony_ci			.link_mode = mode,
8268c2ecf20Sopenharmony_ci		}
8278c2ecf20Sopenharmony_ci	};
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
8308c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
8318c2ecf20Sopenharmony_ci}
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ciint prestera_hw_port_link_mode_get(const struct prestera_port *port, u32 *mode)
8348c2ecf20Sopenharmony_ci{
8358c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
8368c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_LINK_MODE,
8378c2ecf20Sopenharmony_ci		.port = port->hw_id,
8388c2ecf20Sopenharmony_ci		.dev = port->dev_id,
8398c2ecf20Sopenharmony_ci	};
8408c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
8418c2ecf20Sopenharmony_ci	int err;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
8448c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
8458c2ecf20Sopenharmony_ci	if (err)
8468c2ecf20Sopenharmony_ci		return err;
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	*mode = resp.param.link_mode;
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_ci	return 0;
8518c2ecf20Sopenharmony_ci}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ciint prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed)
8548c2ecf20Sopenharmony_ci{
8558c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
8568c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_SPEED,
8578c2ecf20Sopenharmony_ci		.port = port->hw_id,
8588c2ecf20Sopenharmony_ci		.dev = port->dev_id,
8598c2ecf20Sopenharmony_ci	};
8608c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
8618c2ecf20Sopenharmony_ci	int err;
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
8648c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
8658c2ecf20Sopenharmony_ci	if (err)
8668c2ecf20Sopenharmony_ci		return err;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	*speed = resp.param.speed;
8698c2ecf20Sopenharmony_ci
8708c2ecf20Sopenharmony_ci	return 0;
8718c2ecf20Sopenharmony_ci}
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ciint prestera_hw_port_autoneg_set(const struct prestera_port *port,
8748c2ecf20Sopenharmony_ci				 bool autoneg, u64 link_modes, u8 fec)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
8778c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_AUTONEG,
8788c2ecf20Sopenharmony_ci		.port = port->hw_id,
8798c2ecf20Sopenharmony_ci		.dev = port->dev_id,
8808c2ecf20Sopenharmony_ci		.param = {
8818c2ecf20Sopenharmony_ci			.autoneg = {
8828c2ecf20Sopenharmony_ci				.link_mode = link_modes,
8838c2ecf20Sopenharmony_ci				.enable = autoneg,
8848c2ecf20Sopenharmony_ci				.fec = fec,
8858c2ecf20Sopenharmony_ci			}
8868c2ecf20Sopenharmony_ci		}
8878c2ecf20Sopenharmony_ci	};
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
8908c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
8918c2ecf20Sopenharmony_ci}
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ciint prestera_hw_port_autoneg_restart(struct prestera_port *port)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
8968c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_AUTONEG_RESTART,
8978c2ecf20Sopenharmony_ci		.port = port->hw_id,
8988c2ecf20Sopenharmony_ci		.dev = port->dev_id,
8998c2ecf20Sopenharmony_ci	};
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
9028c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
9038c2ecf20Sopenharmony_ci}
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ciint prestera_hw_port_duplex_get(const struct prestera_port *port, u8 *duplex)
9068c2ecf20Sopenharmony_ci{
9078c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
9088c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_DUPLEX,
9098c2ecf20Sopenharmony_ci		.port = port->hw_id,
9108c2ecf20Sopenharmony_ci		.dev = port->dev_id,
9118c2ecf20Sopenharmony_ci	};
9128c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_resp resp;
9138c2ecf20Sopenharmony_ci	int err;
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
9168c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
9178c2ecf20Sopenharmony_ci	if (err)
9188c2ecf20Sopenharmony_ci		return err;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	*duplex = resp.param.duplex;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	return 0;
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_ciint prestera_hw_port_stats_get(const struct prestera_port *port,
9268c2ecf20Sopenharmony_ci			       struct prestera_port_stats *st)
9278c2ecf20Sopenharmony_ci{
9288c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
9298c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_STATS,
9308c2ecf20Sopenharmony_ci		.port = port->hw_id,
9318c2ecf20Sopenharmony_ci		.dev = port->dev_id,
9328c2ecf20Sopenharmony_ci	};
9338c2ecf20Sopenharmony_ci	struct prestera_msg_port_stats_resp resp;
9348c2ecf20Sopenharmony_ci	u64 *hw = resp.stats;
9358c2ecf20Sopenharmony_ci	int err;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_GET,
9388c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
9398c2ecf20Sopenharmony_ci	if (err)
9408c2ecf20Sopenharmony_ci		return err;
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	st->good_octets_received = hw[PRESTERA_PORT_GOOD_OCTETS_RCV_CNT];
9438c2ecf20Sopenharmony_ci	st->bad_octets_received = hw[PRESTERA_PORT_BAD_OCTETS_RCV_CNT];
9448c2ecf20Sopenharmony_ci	st->mac_trans_error = hw[PRESTERA_PORT_MAC_TRANSMIT_ERR_CNT];
9458c2ecf20Sopenharmony_ci	st->broadcast_frames_received = hw[PRESTERA_PORT_BRDC_PKTS_RCV_CNT];
9468c2ecf20Sopenharmony_ci	st->multicast_frames_received = hw[PRESTERA_PORT_MC_PKTS_RCV_CNT];
9478c2ecf20Sopenharmony_ci	st->frames_64_octets = hw[PRESTERA_PORT_PKTS_64L_CNT];
9488c2ecf20Sopenharmony_ci	st->frames_65_to_127_octets = hw[PRESTERA_PORT_PKTS_65TO127L_CNT];
9498c2ecf20Sopenharmony_ci	st->frames_128_to_255_octets = hw[PRESTERA_PORT_PKTS_128TO255L_CNT];
9508c2ecf20Sopenharmony_ci	st->frames_256_to_511_octets = hw[PRESTERA_PORT_PKTS_256TO511L_CNT];
9518c2ecf20Sopenharmony_ci	st->frames_512_to_1023_octets = hw[PRESTERA_PORT_PKTS_512TO1023L_CNT];
9528c2ecf20Sopenharmony_ci	st->frames_1024_to_max_octets = hw[PRESTERA_PORT_PKTS_1024TOMAXL_CNT];
9538c2ecf20Sopenharmony_ci	st->excessive_collision = hw[PRESTERA_PORT_EXCESSIVE_COLLISIONS_CNT];
9548c2ecf20Sopenharmony_ci	st->multicast_frames_sent = hw[PRESTERA_PORT_MC_PKTS_SENT_CNT];
9558c2ecf20Sopenharmony_ci	st->broadcast_frames_sent = hw[PRESTERA_PORT_BRDC_PKTS_SENT_CNT];
9568c2ecf20Sopenharmony_ci	st->fc_sent = hw[PRESTERA_PORT_FC_SENT_CNT];
9578c2ecf20Sopenharmony_ci	st->fc_received = hw[PRESTERA_PORT_GOOD_FC_RCV_CNT];
9588c2ecf20Sopenharmony_ci	st->buffer_overrun = hw[PRESTERA_PORT_DROP_EVENTS_CNT];
9598c2ecf20Sopenharmony_ci	st->undersize = hw[PRESTERA_PORT_UNDERSIZE_PKTS_CNT];
9608c2ecf20Sopenharmony_ci	st->fragments = hw[PRESTERA_PORT_FRAGMENTS_PKTS_CNT];
9618c2ecf20Sopenharmony_ci	st->oversize = hw[PRESTERA_PORT_OVERSIZE_PKTS_CNT];
9628c2ecf20Sopenharmony_ci	st->jabber = hw[PRESTERA_PORT_JABBER_PKTS_CNT];
9638c2ecf20Sopenharmony_ci	st->rx_error_frame_received = hw[PRESTERA_PORT_MAC_RCV_ERROR_CNT];
9648c2ecf20Sopenharmony_ci	st->bad_crc = hw[PRESTERA_PORT_BAD_CRC_CNT];
9658c2ecf20Sopenharmony_ci	st->collisions = hw[PRESTERA_PORT_COLLISIONS_CNT];
9668c2ecf20Sopenharmony_ci	st->late_collision = hw[PRESTERA_PORT_LATE_COLLISIONS_CNT];
9678c2ecf20Sopenharmony_ci	st->unicast_frames_received = hw[PRESTERA_PORT_GOOD_UC_PKTS_RCV_CNT];
9688c2ecf20Sopenharmony_ci	st->unicast_frames_sent = hw[PRESTERA_PORT_GOOD_UC_PKTS_SENT_CNT];
9698c2ecf20Sopenharmony_ci	st->sent_multiple = hw[PRESTERA_PORT_MULTIPLE_PKTS_SENT_CNT];
9708c2ecf20Sopenharmony_ci	st->sent_deferred = hw[PRESTERA_PORT_DEFERRED_PKTS_SENT_CNT];
9718c2ecf20Sopenharmony_ci	st->good_octets_sent = hw[PRESTERA_PORT_GOOD_OCTETS_SENT_CNT];
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	return 0;
9748c2ecf20Sopenharmony_ci}
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ciint prestera_hw_port_learning_set(struct prestera_port *port, bool enable)
9778c2ecf20Sopenharmony_ci{
9788c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
9798c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_LEARNING,
9808c2ecf20Sopenharmony_ci		.port = port->hw_id,
9818c2ecf20Sopenharmony_ci		.dev = port->dev_id,
9828c2ecf20Sopenharmony_ci		.param = {
9838c2ecf20Sopenharmony_ci			.learning = enable,
9848c2ecf20Sopenharmony_ci		}
9858c2ecf20Sopenharmony_ci	};
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
9888c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
9898c2ecf20Sopenharmony_ci}
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ciint prestera_hw_port_flood_set(struct prestera_port *port, bool flood)
9928c2ecf20Sopenharmony_ci{
9938c2ecf20Sopenharmony_ci	struct prestera_msg_port_attr_req req = {
9948c2ecf20Sopenharmony_ci		.attr = PRESTERA_CMD_PORT_ATTR_FLOOD,
9958c2ecf20Sopenharmony_ci		.port = port->hw_id,
9968c2ecf20Sopenharmony_ci		.dev = port->dev_id,
9978c2ecf20Sopenharmony_ci		.param = {
9988c2ecf20Sopenharmony_ci			.flood = flood,
9998c2ecf20Sopenharmony_ci		}
10008c2ecf20Sopenharmony_ci	};
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
10038c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10048c2ecf20Sopenharmony_ci}
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ciint prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
10078c2ecf20Sopenharmony_ci{
10088c2ecf20Sopenharmony_ci	struct prestera_msg_vlan_req req = {
10098c2ecf20Sopenharmony_ci		.vid = vid,
10108c2ecf20Sopenharmony_ci	};
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_CREATE,
10138c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10148c2ecf20Sopenharmony_ci}
10158c2ecf20Sopenharmony_ci
10168c2ecf20Sopenharmony_ciint prestera_hw_vlan_delete(struct prestera_switch *sw, u16 vid)
10178c2ecf20Sopenharmony_ci{
10188c2ecf20Sopenharmony_ci	struct prestera_msg_vlan_req req = {
10198c2ecf20Sopenharmony_ci		.vid = vid,
10208c2ecf20Sopenharmony_ci	};
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	return prestera_cmd(sw, PRESTERA_CMD_TYPE_VLAN_DELETE,
10238c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10248c2ecf20Sopenharmony_ci}
10258c2ecf20Sopenharmony_ci
10268c2ecf20Sopenharmony_ciint prestera_hw_vlan_port_set(struct prestera_port *port, u16 vid,
10278c2ecf20Sopenharmony_ci			      bool is_member, bool untagged)
10288c2ecf20Sopenharmony_ci{
10298c2ecf20Sopenharmony_ci	struct prestera_msg_vlan_req req = {
10308c2ecf20Sopenharmony_ci		.port = port->hw_id,
10318c2ecf20Sopenharmony_ci		.dev = port->dev_id,
10328c2ecf20Sopenharmony_ci		.vid = vid,
10338c2ecf20Sopenharmony_ci		.is_member = is_member,
10348c2ecf20Sopenharmony_ci		.is_tagged = !untagged,
10358c2ecf20Sopenharmony_ci	};
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PORT_SET,
10388c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10398c2ecf20Sopenharmony_ci}
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ciint prestera_hw_vlan_port_vid_set(struct prestera_port *port, u16 vid)
10428c2ecf20Sopenharmony_ci{
10438c2ecf20Sopenharmony_ci	struct prestera_msg_vlan_req req = {
10448c2ecf20Sopenharmony_ci		.port = port->hw_id,
10458c2ecf20Sopenharmony_ci		.dev = port->dev_id,
10468c2ecf20Sopenharmony_ci		.vid = vid,
10478c2ecf20Sopenharmony_ci	};
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_VLAN_PVID_SET,
10508c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10518c2ecf20Sopenharmony_ci}
10528c2ecf20Sopenharmony_ci
10538c2ecf20Sopenharmony_ciint prestera_hw_vlan_port_stp_set(struct prestera_port *port, u16 vid, u8 state)
10548c2ecf20Sopenharmony_ci{
10558c2ecf20Sopenharmony_ci	struct prestera_msg_stp_req req = {
10568c2ecf20Sopenharmony_ci		.port = port->hw_id,
10578c2ecf20Sopenharmony_ci		.dev = port->dev_id,
10588c2ecf20Sopenharmony_ci		.vid = vid,
10598c2ecf20Sopenharmony_ci		.state = state,
10608c2ecf20Sopenharmony_ci	};
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_STP_PORT_SET,
10638c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10648c2ecf20Sopenharmony_ci}
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ciint prestera_hw_fdb_add(struct prestera_port *port, const unsigned char *mac,
10678c2ecf20Sopenharmony_ci			u16 vid, bool dynamic)
10688c2ecf20Sopenharmony_ci{
10698c2ecf20Sopenharmony_ci	struct prestera_msg_fdb_req req = {
10708c2ecf20Sopenharmony_ci		.port = port->hw_id,
10718c2ecf20Sopenharmony_ci		.dev = port->dev_id,
10728c2ecf20Sopenharmony_ci		.vid = vid,
10738c2ecf20Sopenharmony_ci		.dynamic = dynamic,
10748c2ecf20Sopenharmony_ci	};
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_ci	ether_addr_copy(req.mac, mac);
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_ADD,
10798c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10808c2ecf20Sopenharmony_ci}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ciint prestera_hw_fdb_del(struct prestera_port *port, const unsigned char *mac,
10838c2ecf20Sopenharmony_ci			u16 vid)
10848c2ecf20Sopenharmony_ci{
10858c2ecf20Sopenharmony_ci	struct prestera_msg_fdb_req req = {
10868c2ecf20Sopenharmony_ci		.port = port->hw_id,
10878c2ecf20Sopenharmony_ci		.dev = port->dev_id,
10888c2ecf20Sopenharmony_ci		.vid = vid,
10898c2ecf20Sopenharmony_ci	};
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	ether_addr_copy(req.mac, mac);
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_DELETE,
10948c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
10958c2ecf20Sopenharmony_ci}
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_ciint prestera_hw_fdb_flush_port(struct prestera_port *port, u32 mode)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	struct prestera_msg_fdb_req req = {
11008c2ecf20Sopenharmony_ci		.port = port->hw_id,
11018c2ecf20Sopenharmony_ci		.dev = port->dev_id,
11028c2ecf20Sopenharmony_ci		.flush_mode = mode,
11038c2ecf20Sopenharmony_ci	};
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT,
11068c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ciint prestera_hw_fdb_flush_vlan(struct prestera_switch *sw, u16 vid, u32 mode)
11108c2ecf20Sopenharmony_ci{
11118c2ecf20Sopenharmony_ci	struct prestera_msg_fdb_req req = {
11128c2ecf20Sopenharmony_ci		.vid = vid,
11138c2ecf20Sopenharmony_ci		.flush_mode = mode,
11148c2ecf20Sopenharmony_ci	};
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	return prestera_cmd(sw, PRESTERA_CMD_TYPE_FDB_FLUSH_VLAN,
11178c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
11188c2ecf20Sopenharmony_ci}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ciint prestera_hw_fdb_flush_port_vlan(struct prestera_port *port, u16 vid,
11218c2ecf20Sopenharmony_ci				    u32 mode)
11228c2ecf20Sopenharmony_ci{
11238c2ecf20Sopenharmony_ci	struct prestera_msg_fdb_req req = {
11248c2ecf20Sopenharmony_ci		.port = port->hw_id,
11258c2ecf20Sopenharmony_ci		.dev = port->dev_id,
11268c2ecf20Sopenharmony_ci		.vid = vid,
11278c2ecf20Sopenharmony_ci		.flush_mode = mode,
11288c2ecf20Sopenharmony_ci	};
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_FDB_FLUSH_PORT_VLAN,
11318c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
11328c2ecf20Sopenharmony_ci}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ciint prestera_hw_bridge_create(struct prestera_switch *sw, u16 *bridge_id)
11358c2ecf20Sopenharmony_ci{
11368c2ecf20Sopenharmony_ci	struct prestera_msg_bridge_resp resp;
11378c2ecf20Sopenharmony_ci	struct prestera_msg_bridge_req req;
11388c2ecf20Sopenharmony_ci	int err;
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_BRIDGE_CREATE,
11418c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req),
11428c2ecf20Sopenharmony_ci			       &resp.ret, sizeof(resp));
11438c2ecf20Sopenharmony_ci	if (err)
11448c2ecf20Sopenharmony_ci		return err;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	*bridge_id = resp.bridge;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	return 0;
11498c2ecf20Sopenharmony_ci}
11508c2ecf20Sopenharmony_ci
11518c2ecf20Sopenharmony_ciint prestera_hw_bridge_delete(struct prestera_switch *sw, u16 bridge_id)
11528c2ecf20Sopenharmony_ci{
11538c2ecf20Sopenharmony_ci	struct prestera_msg_bridge_req req = {
11548c2ecf20Sopenharmony_ci		.bridge = bridge_id,
11558c2ecf20Sopenharmony_ci	};
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	return prestera_cmd(sw, PRESTERA_CMD_TYPE_BRIDGE_DELETE,
11588c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ciint prestera_hw_bridge_port_add(struct prestera_port *port, u16 bridge_id)
11628c2ecf20Sopenharmony_ci{
11638c2ecf20Sopenharmony_ci	struct prestera_msg_bridge_req req = {
11648c2ecf20Sopenharmony_ci		.bridge = bridge_id,
11658c2ecf20Sopenharmony_ci		.port = port->hw_id,
11668c2ecf20Sopenharmony_ci		.dev = port->dev_id,
11678c2ecf20Sopenharmony_ci	};
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_ADD,
11708c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
11718c2ecf20Sopenharmony_ci}
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_ciint prestera_hw_bridge_port_delete(struct prestera_port *port, u16 bridge_id)
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	struct prestera_msg_bridge_req req = {
11768c2ecf20Sopenharmony_ci		.bridge = bridge_id,
11778c2ecf20Sopenharmony_ci		.port = port->hw_id,
11788c2ecf20Sopenharmony_ci		.dev = port->dev_id,
11798c2ecf20Sopenharmony_ci	};
11808c2ecf20Sopenharmony_ci
11818c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_BRIDGE_PORT_DELETE,
11828c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_ciint prestera_hw_rxtx_init(struct prestera_switch *sw,
11868c2ecf20Sopenharmony_ci			  struct prestera_rxtx_params *params)
11878c2ecf20Sopenharmony_ci{
11888c2ecf20Sopenharmony_ci	struct prestera_msg_rxtx_resp resp;
11898c2ecf20Sopenharmony_ci	struct prestera_msg_rxtx_req req;
11908c2ecf20Sopenharmony_ci	int err;
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_ci	req.use_sdma = params->use_sdma;
11938c2ecf20Sopenharmony_ci
11948c2ecf20Sopenharmony_ci	err = prestera_cmd_ret(sw, PRESTERA_CMD_TYPE_RXTX_INIT,
11958c2ecf20Sopenharmony_ci			       &req.cmd, sizeof(req), &resp.ret, sizeof(resp));
11968c2ecf20Sopenharmony_ci	if (err)
11978c2ecf20Sopenharmony_ci		return err;
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_ci	params->map_addr = resp.map_addr;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci	return 0;
12028c2ecf20Sopenharmony_ci}
12038c2ecf20Sopenharmony_ci
12048c2ecf20Sopenharmony_ciint prestera_hw_rxtx_port_init(struct prestera_port *port)
12058c2ecf20Sopenharmony_ci{
12068c2ecf20Sopenharmony_ci	struct prestera_msg_rxtx_port_req req = {
12078c2ecf20Sopenharmony_ci		.port = port->hw_id,
12088c2ecf20Sopenharmony_ci		.dev = port->dev_id,
12098c2ecf20Sopenharmony_ci	};
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_RXTX_PORT_INIT,
12128c2ecf20Sopenharmony_ci			    &req.cmd, sizeof(req));
12138c2ecf20Sopenharmony_ci}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ciint prestera_hw_event_handler_register(struct prestera_switch *sw,
12168c2ecf20Sopenharmony_ci				       enum prestera_event_type type,
12178c2ecf20Sopenharmony_ci				       prestera_event_cb_t fn,
12188c2ecf20Sopenharmony_ci				       void *arg)
12198c2ecf20Sopenharmony_ci{
12208c2ecf20Sopenharmony_ci	struct prestera_fw_event_handler *eh;
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	eh = __find_event_handler(sw, type);
12238c2ecf20Sopenharmony_ci	if (eh)
12248c2ecf20Sopenharmony_ci		return -EEXIST;
12258c2ecf20Sopenharmony_ci
12268c2ecf20Sopenharmony_ci	eh = kmalloc(sizeof(*eh), GFP_KERNEL);
12278c2ecf20Sopenharmony_ci	if (!eh)
12288c2ecf20Sopenharmony_ci		return -ENOMEM;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	eh->type = type;
12318c2ecf20Sopenharmony_ci	eh->func = fn;
12328c2ecf20Sopenharmony_ci	eh->arg = arg;
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&eh->list);
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	list_add_rcu(&eh->list, &sw->event_handlers);
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	return 0;
12398c2ecf20Sopenharmony_ci}
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_civoid prestera_hw_event_handler_unregister(struct prestera_switch *sw,
12428c2ecf20Sopenharmony_ci					  enum prestera_event_type type,
12438c2ecf20Sopenharmony_ci					  prestera_event_cb_t fn)
12448c2ecf20Sopenharmony_ci{
12458c2ecf20Sopenharmony_ci	struct prestera_fw_event_handler *eh;
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_ci	eh = __find_event_handler(sw, type);
12488c2ecf20Sopenharmony_ci	if (!eh)
12498c2ecf20Sopenharmony_ci		return;
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	list_del_rcu(&eh->list);
12528c2ecf20Sopenharmony_ci	kfree_rcu(eh, rcu);
12538c2ecf20Sopenharmony_ci}
1254