[PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support

Dong Yibo posted 15 patches 2 months, 2 weeks ago
There is a newer version of this series
[PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support
Posted by Dong Yibo 2 months, 2 weeks ago
Initialize get hw capability from mbx_fw ops.

Signed-off-by: Dong Yibo <dong100@mucse.com>
---
 drivers/net/ethernet/mucse/rnpgbe/Makefile    |   3 +-
 drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h    |   8 +
 .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c   |   8 +
 .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 140 +++++
 .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 568 ++++++++++++++++++
 5 files changed, 726 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
 create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h

diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ethernet/mucse/rnpgbe/Makefile
index 41177103b50c..fd455cb111a9 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/Makefile
+++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile
@@ -7,4 +7,5 @@
 obj-$(CONFIG_MGBE) += rnpgbe.o
 rnpgbe-objs := rnpgbe_main.o \
 	       rnpgbe_chip.o \
-	       rnpgbe_mbx.o
+	       rnpgbe_mbx.o \
+	       rnpgbe_mbx_fw.o
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
index 46e2bb2fe71e..4514bc1223c1 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
@@ -154,6 +154,14 @@ struct mucse_hw {
 	u16 vendor_id;
 	u16 subsystem_device_id;
 	u16 subsystem_vendor_id;
+	u32 wol;
+	u32 wol_en;
+	u32 fw_version;
+	u32 axi_mhz;
+	u32 bd_uid;
+	int ncsi_en;
+	int force_en;
+	int force_cap;
 	int max_vfs;
 	int max_vfs_noari;
 	enum rnpgbe_hw_type hw_type;
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
index 1e8360cae560..aeb560145c47 100644
--- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
@@ -9,6 +9,7 @@
 #include <linux/etherdevice.h>
 
 #include "rnpgbe.h"
+#include "rnpgbe_mbx_fw.h"
 
 char rnpgbe_driver_name[] = "rnpgbe";
 static const struct rnpgbe_info *rnpgbe_info_tbl[] = {
@@ -116,6 +117,13 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev,
 	ii->get_invariants(hw);
 	hw->mbx.ops.init_params(hw);
 
+	err = mucse_mbx_get_capability(hw);
+	if (err) {
+		dev_err(&pdev->dev,
+			"mucse_mbx_get_capability failed!\n");
+		goto err_free_net;
+	}
+
 	return 0;
 
 err_free_net:
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
new file mode 100644
index 000000000000..1674229fcd43
--- /dev/null
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2020 - 2025 Mucse Corporation. */
+
+#include <linux/pci.h>
+
+#include "rnpgbe_mbx_fw.h"
+
+/**
+ * mucse_fw_send_cmd_wait - Send cmd req and wait for response
+ * @hw: Pointer to the HW structure
+ * @req: Pointer to the cmd req structure
+ * @reply: Pointer to the fw reply structure
+ *
+ * mucse_fw_send_cmd_wait sends req to pf-fw mailbox and wait
+ * reply from fw.
+ *
+ * @return: 0 on success, negative on failure
+ **/
+static int mucse_fw_send_cmd_wait(struct mucse_hw *hw,
+				  struct mbx_fw_cmd_req *req,
+				  struct mbx_fw_cmd_reply *reply)
+{
+	int len = le32_to_cpu(req->datalen) + MBX_REQ_HDR_LEN;
+	int retry_cnt = 3;
+	int err;
+
+	err = mutex_lock_interruptible(&hw->mbx.lock);
+	if (err)
+		return err;
+
+	err = hw->mbx.ops.write_posted(hw, (u32 *)req,
+				       L_WD(len),
+				       MBX_FW);
+	if (err) {
+		mutex_unlock(&hw->mbx.lock);
+		return err;
+	}
+
+retry:
+	retry_cnt--;
+	if (retry_cnt < 0)
+		return -EIO;
+
+	err = hw->mbx.ops.read_posted(hw, (u32 *)reply,
+				      L_WD(sizeof(*reply)),
+				      MBX_FW);
+	if (err) {
+		mutex_unlock(&hw->mbx.lock);
+		return err;
+	}
+
+	if (reply->opcode != req->opcode)
+		goto retry;
+
+	mutex_unlock(&hw->mbx.lock);
+
+	if (reply->error_code)
+		return -EIO;
+
+	return 0;
+}
+
+/**
+ * mucse_fw_get_capability - Get hw abilities from fw
+ * @hw: Pointer to the HW structure
+ * @abil: Pointer to the hw_abilities structure
+ *
+ * mucse_fw_get_capability tries to get hw abilities from
+ * hw.
+ *
+ * @return: 0 on success, negative on failure
+ **/
+static int mucse_fw_get_capability(struct mucse_hw *hw,
+				   struct hw_abilities *abil)
+{
+	struct mbx_fw_cmd_reply reply;
+	struct mbx_fw_cmd_req req;
+	int err = 0;
+
+	memset(&req, 0, sizeof(req));
+	memset(&reply, 0, sizeof(reply));
+	build_phy_abalities_req(&req, &req);
+	err = mucse_fw_send_cmd_wait(hw, &req, &reply);
+	if (err == 0)
+		memcpy(abil, &reply.hw_abilities, sizeof(*abil));
+
+	return err;
+}
+
+/**
+ * mucse_mbx_get_capability - Get hw abilities from fw
+ * @hw: Pointer to the HW structure
+ *
+ * mucse_mbx_get_capability tries to some capabities from
+ * hw. Many retrys will do if it is failed.
+ *
+ * @return: 0 on success, negative on failure
+ **/
+int mucse_mbx_get_capability(struct mucse_hw *hw)
+{
+	struct hw_abilities ability;
+	int try_cnt = 3;
+	int err = 0;
+
+	memset(&ability, 0, sizeof(ability));
+
+	while (try_cnt--) {
+		err = mucse_fw_get_capability(hw, &ability);
+		if (err == 0) {
+			u16 nic_mode = le16_to_cpu(ability.nic_mode);
+			u32 wol = le32_to_cpu(ability.wol_status);
+
+			hw->ncsi_en = (nic_mode & 0x4) ? 1 : 0;
+			hw->pfvfnum = le16_to_cpu(ability.pfnum);
+			hw->fw_version = le32_to_cpu(ability.fw_version);
+			hw->axi_mhz = le32_to_cpu(ability.axi_mhz);
+			hw->bd_uid = le32_to_cpu(ability.bd_uid);
+
+			if (hw->fw_version >= 0x0001012C) {
+				/* this version can get wol_en from hw */
+				hw->wol = wol & 0xff;
+				hw->wol_en = wol & 0x100;
+			} else {
+				/* other version only pf0 or ncsi can wol */
+				hw->wol = wol & 0xff;
+				if (hw->ncsi_en || !hw->pfvfnum)
+					hw->wol_en = 1;
+			}
+			/* 0.1.5.0 can get force status from fw */
+			if (hw->fw_version >= 0x00010500) {
+				ability_update_host_endian(&ability);
+				hw->force_en = ability.e_host.force_down_en;
+				hw->force_cap = 1;
+			}
+			return 0;
+		}
+	}
+
+	return err;
+}
diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
new file mode 100644
index 000000000000..a24c5d4e0075
--- /dev/null
+++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
@@ -0,0 +1,568 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2020 - 2025 Mucse Corporation. */
+
+#ifndef _RNPGBE_MBX_FW_H
+#define _RNPGBE_MBX_FW_H
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+
+#include "rnpgbe.h"
+
+#define MBX_REQ_HDR_LEN 24
+#define L_WD(x) ((x) / 4)
+
+struct mbx_fw_cmd_reply;
+typedef void (*cookie_cb)(struct mbx_fw_cmd_reply *reply, void *priv);
+
+struct mbx_req_cookie {
+	int magic;
+#define COOKIE_MAGIC 0xCE
+	cookie_cb cb;
+	int timeout_jiffes;
+	int errcode;
+	wait_queue_head_t wait;
+	int done;
+	int priv_len;
+	char priv[];
+};
+
+enum MUCSE_FW_CMD {
+	GET_VERSION = 0x0001,
+	READ_REG = 0xFF03,
+	WRITE_REG = 0xFF04,
+	MODIFY_REG = 0xFF07,
+	IFUP_DOWN = 0x0800,
+	SEND_TO_PF = 0x0801,
+	SEND_TO_VF = 0x0802,
+	DRIVER_INSMOD = 0x0803,
+	SYSTEM_SUSPUSE = 0x0804,
+	SYSTEM_FORCE = 0x0805,
+	GET_PHY_ABALITY = 0x0601,
+	GET_MAC_ADDRES = 0x0602,
+	RESET_PHY = 0x0603,
+	LED_SET = 0x0604,
+	GET_LINK_STATUS = 0x0607,
+	LINK_STATUS_EVENT = 0x0608,
+	SET_LANE_FUN = 0x0609,
+	GET_LANE_STATUS = 0x0610,
+	SFP_SPEED_CHANGED_EVENT = 0x0611,
+	SET_EVENT_MASK = 0x0613,
+	SET_LOOPBACK_MODE = 0x0618,
+	SET_PHY_REG = 0x0628,
+	GET_PHY_REG = 0x0629,
+	PHY_LINK_SET = 0x0630,
+	GET_PHY_STATISTICS = 0x0631,
+	PHY_PAUSE_SET = 0x0632,
+	PHY_PAUSE_GET = 0x0633,
+	PHY_EEE_SET = 0x0636,
+	PHY_EEE_GET = 0x0637,
+	SFP_MODULE_READ = 0x0900,
+	SFP_MODULE_WRITE = 0x0901,
+	FW_UPDATE = 0x0700,
+	FW_MAINTAIN = 0x0701,
+	FW_UPDATE_GBE = 0x0702,
+	WOL_EN = 0x0910,
+	GET_DUMP = 0x0a00,
+	SET_DUMP = 0x0a10,
+	GET_TEMP = 0x0a11,
+	SET_WOL = 0x0a12,
+	SET_TEST_MODE = 0x0a13,
+	SHOW_TX_STAMP = 0x0a14,
+	LLDP_TX_CTRL = 0x0a15,
+};
+
+struct hw_abilities {
+	u8 link_stat;
+	u8 lane_mask;
+	__le32 speed;
+	__le16 phy_type;
+	__le16 nic_mode;
+	__le16 pfnum;
+	__le32 fw_version;
+	__le32 axi_mhz;
+	union {
+		u8 port_id[4];
+		__le32 port_ids;
+	};
+	__le32 bd_uid;
+	__le32 phy_id;
+	__le32 wol_status;
+	union {
+		__le32 ext_ability;
+		struct {
+			__le32 valid : 1; /* 0 */
+			__le32 wol_en : 1; /* 1 */
+			__le32 pci_preset_runtime_en : 1; /* 2 */
+			__le32 smbus_en : 1; /* 3 */
+			__le32 ncsi_en : 1; /* 4 */
+			__le32 rpu_en : 1; /* 5 */
+			__le32 v2 : 1; /* 6 */
+			__le32 pxe_en : 1; /* 7 */
+			__le32 mctp_en : 1; /* 8 */
+			__le32 yt8614 : 1; /* 9 */
+			__le32 pci_ext_reset : 1; /* 10 */
+			__le32 rpu_availble : 1; /* 11 */
+			__le32 fw_lldp_ability : 1; /* 12 */
+			__le32 lldp_enabled : 1; /* 13 */
+			__le32 only_1g : 1; /* 14 */
+			__le32 force_down_en: 1; /* 15 */
+		} e;
+		struct {
+			u32 valid : 1; /* 0 */
+			u32 wol_en : 1; /* 1 */
+			u32 pci_preset_runtime_en : 1; /* 2 */
+			u32 smbus_en : 1; /* 3 */
+			u32 ncsi_en : 1; /* 4 */
+			u32 rpu_en : 1; /* 5 */
+			u32 v2 : 1; /* 6 */
+			u32 pxe_en : 1; /* 7 */
+			u32 mctp_en : 1; /* 8 */
+			u32 yt8614 : 1; /* 9 */
+			u32 pci_ext_reset : 1; /* 10 */
+			u32 rpu_availble : 1; /* 11 */
+			u32 fw_lldp_ability : 1; /* 12 */
+			u32 lldp_enabled : 1; /* 13 */
+			u32 only_1g : 1; /* 14 */
+			u32 force_down_en: 1; /* 15 */
+		} e_host;
+	};
+} __packed;
+
+static inline void ability_update_host_endian(struct hw_abilities *abi)
+{
+	u32 host_val = le32_to_cpu(abi->ext_ability);
+
+	abi->e_host = *(typeof(abi->e_host) *)&host_val;
+}
+
+struct phy_pause_data {
+	u32 pause_mode;
+};
+
+struct lane_stat_data {
+	u8 nr_lane;
+	u8 pci_gen : 4;
+	u8 pci_lanes : 4;
+	u8 pma_type;
+	u8 phy_type;
+	__le16 linkup : 1;
+	__le16 duplex : 1;
+	__le16 autoneg : 1;
+	__le16 fec : 1;
+	__le16 an : 1;
+	__le16 link_traing : 1;
+	__le16 media_availble : 1;
+	__le16 is_sgmii : 1;
+	__le16 link_fault : 4;
+#define LINK_LINK_FAULT BIT(0)
+#define LINK_TX_FAULT BIT(1)
+#define LINK_RX_FAULT BIT(2)
+#define LINK_REMOTE_FAULT BIT(3)
+	__le16 is_backplane : 1;
+	__le16 tp_mdx : 2;
+	union {
+		u8 phy_addr;
+		struct {
+			u8 mod_abs : 1;
+			u8 fault : 1;
+			u8 tx_dis : 1;
+			u8 los : 1;
+		} sfp;
+	};
+	u8 sfp_connector;
+	__le32 speed;
+	__le32 si_main;
+	__le32 si_pre;
+	__le32 si_post;
+	__le32 si_tx_boost;
+	__le32 supported_link;
+	__le32 phy_id;
+	__le32 advertised_link;
+} __packed;
+
+struct yt_phy_statistics {
+	__le32 pkg_ib_valid; /* rx crc good and length 64-1518 */
+	__le32 pkg_ib_os_good; /* rx crc good and length >1518 */
+	__le32 pkg_ib_us_good; /* rx crc good and length <64 */
+	__le16 pkg_ib_err; /* rx crc wrong and length 64-1518 */
+	__le16 pkg_ib_os_bad; /* rx crc wrong and length >1518 */
+	__le16 pkg_ib_frag; /* rx crc wrong and length <64 */
+	__le16 pkg_ib_nosfd; /* rx sfd missed */
+	__le32 pkg_ob_valid; /* tx crc good and length 64-1518 */
+	__le32 pkg_ob_os_good; /* tx crc good and length >1518 */
+	__le32 pkg_ob_us_good; /* tx crc good and length <64 */
+	__le16 pkg_ob_err; /* tx crc wrong and length 64-1518 */
+	__le16 pkg_ob_os_bad; /* tx crc wrong and length >1518 */
+	__le16 pkg_ob_frag; /* tx crc wrong and length <64 */
+	__le16 pkg_ob_nosfd; /* tx sfd missed */
+} __packed;
+
+struct phy_statistics {
+	union {
+		struct yt_phy_statistics yt;
+	};
+} __packed;
+
+struct port_stat {
+	u8 phyid;
+	u8 duplex : 1;
+	u8 autoneg : 1;
+	u8 fec : 1;
+	__le16 speed;
+	union {
+		__le16 stat;
+		struct {
+			__le16 pause : 4;
+			__le16 local_eee : 3;
+			__le16 partner_eee : 3;
+			__le16 tp_mdx : 2;
+			__le16 lldp_status : 1;
+			__le16 revs : 3;
+		} v;
+		struct {
+			u16 pause : 4;
+			u16 local_eee : 3;
+			u16 partner_eee : 3;
+			u16 tp_mdx : 2;
+			u16 lldp_status : 1;
+			u16 revs : 3;
+		} v_host;
+	};
+} __packed;
+
+#define FLAGS_DD BIT(0) /* driver clear 0, FW must set 1 */
+/* driver clear 0, FW must set only if it reporting an error */
+#define FLAGS_ERR BIT(2)
+
+/* req is little endian. bigendian should be conserened */
+struct mbx_fw_cmd_req {
+	__le16 flags; /* 0-1 */
+	__le16 opcode; /* 2-3 enum GENERIC_CMD */
+	__le16 datalen; /* 4-5 */
+	__le16 ret_value; /* 6-7 */
+	union {
+		struct {
+			__le32 cookie_lo; /* 8-11 */
+			__le32 cookie_hi; /* 12-15 */
+		};
+
+		void *cookie;
+	};
+	__le32 reply_lo; /* 16-19 5dw */
+	__le32 reply_hi; /* 20-23 */
+	union {
+		u8 data[32];
+		struct {
+			__le32 addr;
+			__le32 bytes;
+		} r_reg;
+
+		struct {
+			__le32 addr;
+			__le32 bytes;
+			__le32 data[4];
+		} w_reg;
+
+		struct {
+			__le32 lanes;
+		} ptp;
+
+		struct {
+			__le32 lane;
+			__le32 up;
+		} ifup;
+
+		struct {
+			__le32 sec;
+			__le32 nanosec;
+
+		} tstamps;
+
+		struct {
+			__le32 lane;
+			__le32 status;
+		} ifinsmod;
+
+		struct {
+			__le32 lane;
+			__le32 status;
+		} ifforce;
+
+		struct {
+			__le32 lane;
+			__le32 status;
+		} ifsuspuse;
+
+		struct {
+			__le32 nr_lane;
+		} get_lane_st;
+
+		struct {
+			__le32 nr_lane;
+			__le32 func;
+#define LANE_FUN_AN 0
+#define LANE_FUN_LINK_TRAING 1
+#define LANE_FUN_FEC 2
+#define LANE_FUN_SI 3
+#define LANE_FUN_SFP_TX_DISABLE 4
+#define LANE_FUN_PCI_LANE 5
+#define LANE_FUN_PRBS 6
+#define LANE_FUN_SPEED_CHANGE 7
+			__le32 value0;
+			__le32 value1;
+			__le32 value2;
+			__le32 value3;
+		} set_lane_fun;
+
+		struct {
+			__le32 flag;
+			__le32 nr_lane;
+		} set_dump;
+
+		struct {
+			__le32 lane;
+			__le32 enable;
+		} wol;
+
+		struct {
+			__le32 lane;
+			__le32 mode;
+		} gephy_test;
+
+		struct {
+			__le32 lane;
+			__le32 op;
+			__le32 enable;
+			__le32 inteval;
+		} lldp_tx;
+
+		struct {
+			__le32 bytes;
+			__le32 nr_lane;
+			__le32 bin_offset;
+			__le32 no_use;
+		} get_dump;
+
+		struct {
+			__le32 nr_lane;
+			__le32 value;
+#define LED_IDENTIFY_INACTIVE 0
+#define LED_IDENTIFY_ACTIVE 1
+#define LED_IDENTIFY_ON 2
+#define LED_IDENTIFY_OFF 3
+		} led_set;
+
+		struct {
+			__le32 addr;
+			__le32 data;
+			__le32 mask;
+		} modify_reg;
+
+		struct {
+			__le32 adv_speed_mask;
+			__le32 autoneg;
+			__le32 speed;
+			__le32 duplex;
+			__le32 nr_lane;
+			__le32 tp_mdix_ctrl;
+		} phy_link_set;
+
+		struct {
+			__le32 pause_mode;
+			__le32 nr_lane;
+		} phy_pause_set;
+
+		struct {
+			__le32 pause_mode;
+			__le32 nr_lane;
+		} phy_pause_get;
+
+		struct {
+			__le32 local_eee;
+			__le32 tx_lpi_timer;
+			__le32 nr_lane;
+		} phy_eee_set;
+
+		struct {
+			__le32 nr_lane;
+			__le32 sfp_adr; /* 0xa0 or 0xa2 */
+			__le32 reg;
+			__le32 cnt;
+		} sfp_read;
+
+		struct {
+			__le32 nr_lane;
+			__le32 sfp_adr; /* 0xa0 or 0xa2 */
+			__le32 reg;
+			__le32 val;
+		} sfp_write;
+
+		struct {
+			__le32 nr_lane; /* 0-3 */
+		} get_linkstat;
+
+		struct {
+			__le16 changed_lanes;
+			__le16 lane_status;
+			__le32 port_st_magic;
+#define SPEED_VALID_MAGIC 0xa4a6a8a9
+			struct port_stat st[4];
+		} link_stat; /* FW->RC */
+
+		struct {
+			__le16 enable_stat;
+			__le16 event_mask;
+		} stat_event_mask;
+
+		struct {
+			__le32 cmd;
+			__le32 arg0;
+			__le32 req_bytes;
+			__le32 reply_bytes;
+			__le32 ddr_lo;
+			__le32 ddr_hi;
+		} maintain;
+
+		struct { /* set phy register */
+			u8 phy_interface;
+			union {
+				u8 page_num;
+				u8 external_phy_addr;
+			};
+			__le32 phy_reg_addr;
+			__le32 phy_w_data;
+			__le32 reg_addr;
+			__le32 w_data;
+			/* 1 = ignore page_num, use last QSFP */
+			u8 recall_qsfp_page : 1;
+			/* page value */
+			/* 0 = use page_num for QSFP */
+			u8 nr_lane;
+		} set_phy_reg;
+
+		struct {
+			__le32 lane_mask;
+			__le32 pfvf_num;
+		} get_mac_addr;
+
+		struct {
+			u8 phy_interface;
+			union {
+				u8 page_num;
+				u8 external_phy_addr;
+			};
+			__le32 phy_reg_addr;
+			u8 nr_lane;
+		} get_phy_reg;
+
+		struct {
+			__le32 nr_lane;
+		} phy_statistics;
+
+		struct {
+			u8 paration;
+			__le32 bytes;
+			__le32 bin_phy_lo;
+			__le32 bin_phy_hi;
+		} fw_update;
+	};
+} __packed;
+
+#define EEE_1000BT BIT(2)
+#define EEE_100BT BIT(1)
+
+struct rnpgbe_eee_cap {
+	__le32 local_capability;
+	__le32 local_eee;
+	__le32 partner_eee;
+};
+
+/* firmware -> driver */
+struct mbx_fw_cmd_reply {
+	/* fw must set: DD, CMP, Error(if error), copy value */
+	__le16 flags;
+	/* from command: LB,RD,VFC,BUF,SI,EI,FE */
+	__le16 opcode; /* 2-3: copy from req */
+	__le16 error_code; /* 4-5: 0 if no error */
+	__le16 datalen; /* 6-7: */
+	union {
+		struct {
+			__le32 cookie_lo; /* 8-11: */
+			__le32 cookie_hi; /* 12-15: */
+		};
+		void *cookie;
+	};
+	/* ===== data ==== [16-64] */
+	union {
+		u8 data[40];
+
+		struct version {
+			__le32 major;
+			__le32 sub;
+			__le32 modify;
+		} version;
+
+		struct {
+			__le32 value[4];
+		} r_reg;
+
+		struct {
+			__le32 new_value;
+		} modify_reg;
+
+		struct get_temp {
+			__le32 temp;
+			__le32 volatage;
+		} get_temp;
+
+		struct {
+#define MBX_SFP_READ_MAX_CNT 32
+			u8 value[MBX_SFP_READ_MAX_CNT];
+		} sfp_read;
+
+		struct mac_addr {
+			__le32 lanes;
+			struct _addr {
+				/*
+				 * for macaddr:01:02:03:04:05:06
+				 * mac-hi=0x01020304 mac-lo=0x05060000
+				 */
+				u8 mac[8];
+			} addrs[4];
+		} mac_addr;
+
+		struct get_dump_reply {
+			__le32 flags;
+			__le32 version;
+			__le32 bytes;
+			__le32 data[4];
+		} get_dump;
+
+		struct get_lldp_reply {
+			__le32 value;
+			__le32 inteval;
+		} get_lldp;
+
+		struct rnpgbe_eee_cap phy_eee_abilities;
+		struct lane_stat_data lanestat;
+		struct hw_abilities hw_abilities;
+		struct phy_statistics phy_statistics;
+	};
+} __packed;
+
+static inline void build_phy_abalities_req(struct mbx_fw_cmd_req *req,
+					   void *cookie)
+{
+	req->flags = 0;
+	req->opcode = cpu_to_le32(GET_PHY_ABALITY);
+	req->datalen = 0;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->cookie = cookie;
+}
+
+int mucse_mbx_get_capability(struct mucse_hw *hw);
+
+#endif /* _RNPGBE_MBX_FW_H */
-- 
2.25.1
Re: [PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support
Posted by Simon Horman 2 months, 2 weeks ago
On Mon, Jul 21, 2025 at 07:32:27PM +0800, Dong Yibo wrote:
> Initialize get hw capability from mbx_fw ops.
> 
> Signed-off-by: Dong Yibo <dong100@mucse.com>

...

> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h

...

> +struct hw_abilities {
> +	u8 link_stat;
> +	u8 lane_mask;
> +	__le32 speed;
> +	__le16 phy_type;
> +	__le16 nic_mode;
> +	__le16 pfnum;
> +	__le32 fw_version;
> +	__le32 axi_mhz;
> +	union {
> +		u8 port_id[4];
> +		__le32 port_ids;
> +	};
> +	__le32 bd_uid;
> +	__le32 phy_id;
> +	__le32 wol_status;
> +	union {
> +		__le32 ext_ability;
> +		struct {
> +			__le32 valid : 1; /* 0 */
> +			__le32 wol_en : 1; /* 1 */
> +			__le32 pci_preset_runtime_en : 1; /* 2 */
> +			__le32 smbus_en : 1; /* 3 */
> +			__le32 ncsi_en : 1; /* 4 */
> +			__le32 rpu_en : 1; /* 5 */
> +			__le32 v2 : 1; /* 6 */
> +			__le32 pxe_en : 1; /* 7 */
> +			__le32 mctp_en : 1; /* 8 */
> +			__le32 yt8614 : 1; /* 9 */
> +			__le32 pci_ext_reset : 1; /* 10 */
> +			__le32 rpu_availble : 1; /* 11 */
> +			__le32 fw_lldp_ability : 1; /* 12 */
> +			__le32 lldp_enabled : 1; /* 13 */
> +			__le32 only_1g : 1; /* 14 */
> +			__le32 force_down_en: 1; /* 15 */
> +		} e;

I am not sure how __le32 bitfields work on big endian hosts. Do they?

I would suggest using some combination of BIT/GENMASK,
FIELD_PREP/FIELT_GET, and le32_from_cpu/cpu_from_le32 instead.

Flagged by Sparse.

> +		struct {
> +			u32 valid : 1; /* 0 */
> +			u32 wol_en : 1; /* 1 */
> +			u32 pci_preset_runtime_en : 1; /* 2 */
> +			u32 smbus_en : 1; /* 3 */
> +			u32 ncsi_en : 1; /* 4 */
> +			u32 rpu_en : 1; /* 5 */
> +			u32 v2 : 1; /* 6 */
> +			u32 pxe_en : 1; /* 7 */
> +			u32 mctp_en : 1; /* 8 */
> +			u32 yt8614 : 1; /* 9 */
> +			u32 pci_ext_reset : 1; /* 10 */
> +			u32 rpu_availble : 1; /* 11 */
> +			u32 fw_lldp_ability : 1; /* 12 */
> +			u32 lldp_enabled : 1; /* 13 */
> +			u32 only_1g : 1; /* 14 */
> +			u32 force_down_en: 1; /* 15 */
> +		} e_host;
> +	};
> +} __packed;

...

> +/* req is little endian. bigendian should be conserened */
> +struct mbx_fw_cmd_req {

...

> +		struct {
> +			__le32 lane;
> +			__le32 op;
> +			__le32 enable;
> +			__le32 inteval;

interval

Flagged by checkpatch.pl --codespell

...

> +/* firmware -> driver */
> +struct mbx_fw_cmd_reply {
> +	/* fw must set: DD, CMP, Error(if error), copy value */
> +	__le16 flags;
> +	/* from command: LB,RD,VFC,BUF,SI,EI,FE */
> +	__le16 opcode; /* 2-3: copy from req */
> +	__le16 error_code; /* 4-5: 0 if no error */
> +	__le16 datalen; /* 6-7: */
> +	union {
> +		struct {
> +			__le32 cookie_lo; /* 8-11: */
> +			__le32 cookie_hi; /* 12-15: */
> +		};
> +		void *cookie;
> +	};
> +	/* ===== data ==== [16-64] */
> +	union {
> +		u8 data[40];
> +
> +		struct version {
> +			__le32 major;
> +			__le32 sub;
> +			__le32 modify;
> +		} version;
> +
> +		struct {
> +			__le32 value[4];
> +		} r_reg;
> +
> +		struct {
> +			__le32 new_value;
> +		} modify_reg;
> +
> +		struct get_temp {
> +			__le32 temp;
> +			__le32 volatage;

voltage

> +		} get_temp;
> +
> +		struct {
> +#define MBX_SFP_READ_MAX_CNT 32
> +			u8 value[MBX_SFP_READ_MAX_CNT];
> +		} sfp_read;
> +
> +		struct mac_addr {
> +			__le32 lanes;
> +			struct _addr {
> +				/*
> +				 * for macaddr:01:02:03:04:05:06
> +				 * mac-hi=0x01020304 mac-lo=0x05060000
> +				 */
> +				u8 mac[8];
> +			} addrs[4];
> +		} mac_addr;
> +
> +		struct get_dump_reply {
> +			__le32 flags;
> +			__le32 version;
> +			__le32 bytes;
> +			__le32 data[4];
> +		} get_dump;
> +
> +		struct get_lldp_reply {
> +			__le32 value;
> +			__le32 inteval;

interval

> +		} get_lldp;
> +
> +		struct rnpgbe_eee_cap phy_eee_abilities;
> +		struct lane_stat_data lanestat;
> +		struct hw_abilities hw_abilities;
> +		struct phy_statistics phy_statistics;
> +	};
> +} __packed;

...
Re: [PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support
Posted by Yibo Dong 2 months, 2 weeks ago
On Tue, Jul 22, 2025 at 02:19:11PM +0100, Simon Horman wrote:
> On Mon, Jul 21, 2025 at 07:32:27PM +0800, Dong Yibo wrote:
> > Initialize get hw capability from mbx_fw ops.
> > 
> > Signed-off-by: Dong Yibo <dong100@mucse.com>
> 
> ...
> 
> > diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> 
> ...
> 
> > +struct hw_abilities {
> > +	u8 link_stat;
> > +	u8 lane_mask;
> > +	__le32 speed;
> > +	__le16 phy_type;
> > +	__le16 nic_mode;
> > +	__le16 pfnum;
> > +	__le32 fw_version;
> > +	__le32 axi_mhz;
> > +	union {
> > +		u8 port_id[4];
> > +		__le32 port_ids;
> > +	};
> > +	__le32 bd_uid;
> > +	__le32 phy_id;
> > +	__le32 wol_status;
> > +	union {
> > +		__le32 ext_ability;
> > +		struct {
> > +			__le32 valid : 1; /* 0 */
> > +			__le32 wol_en : 1; /* 1 */
> > +			__le32 pci_preset_runtime_en : 1; /* 2 */
> > +			__le32 smbus_en : 1; /* 3 */
> > +			__le32 ncsi_en : 1; /* 4 */
> > +			__le32 rpu_en : 1; /* 5 */
> > +			__le32 v2 : 1; /* 6 */
> > +			__le32 pxe_en : 1; /* 7 */
> > +			__le32 mctp_en : 1; /* 8 */
> > +			__le32 yt8614 : 1; /* 9 */
> > +			__le32 pci_ext_reset : 1; /* 10 */
> > +			__le32 rpu_availble : 1; /* 11 */
> > +			__le32 fw_lldp_ability : 1; /* 12 */
> > +			__le32 lldp_enabled : 1; /* 13 */
> > +			__le32 only_1g : 1; /* 14 */
> > +			__le32 force_down_en: 1; /* 15 */
> > +		} e;
> 
> I am not sure how __le32 bitfields work on big endian hosts. Do they?
> 
> I would suggest using some combination of BIT/GENMASK,
> FIELD_PREP/FIELT_GET, and le32_from_cpu/cpu_from_le32 instead.
> 
> Flagged by Sparse.
> 

You are right, '__le32 bitfields' is error. I will fix it. 

> > +		struct {
> > +			u32 valid : 1; /* 0 */
> > +			u32 wol_en : 1; /* 1 */
> > +			u32 pci_preset_runtime_en : 1; /* 2 */
> > +			u32 smbus_en : 1; /* 3 */
> > +			u32 ncsi_en : 1; /* 4 */
> > +			u32 rpu_en : 1; /* 5 */
> > +			u32 v2 : 1; /* 6 */
> > +			u32 pxe_en : 1; /* 7 */
> > +			u32 mctp_en : 1; /* 8 */
> > +			u32 yt8614 : 1; /* 9 */
> > +			u32 pci_ext_reset : 1; /* 10 */
> > +			u32 rpu_availble : 1; /* 11 */
> > +			u32 fw_lldp_ability : 1; /* 12 */
> > +			u32 lldp_enabled : 1; /* 13 */
> > +			u32 only_1g : 1; /* 14 */
> > +			u32 force_down_en: 1; /* 15 */
> > +		} e_host;
> > +	};
> > +} __packed;
> 
> ...
> 
> > +/* req is little endian. bigendian should be conserened */
> > +struct mbx_fw_cmd_req {
> 
> ...
> 
> > +		struct {
> > +			__le32 lane;
> > +			__le32 op;
> > +			__le32 enable;
> > +			__le32 inteval;
> 
> interval
> 
> Flagged by checkpatch.pl --codespell
> 
> ...
> 

Got it, I will also use checkpatch.pl to check other patches.

> > +/* firmware -> driver */
> > +struct mbx_fw_cmd_reply {
> > +	/* fw must set: DD, CMP, Error(if error), copy value */
> > +	__le16 flags;
> > +	/* from command: LB,RD,VFC,BUF,SI,EI,FE */
> > +	__le16 opcode; /* 2-3: copy from req */
> > +	__le16 error_code; /* 4-5: 0 if no error */
> > +	__le16 datalen; /* 6-7: */
> > +	union {
> > +		struct {
> > +			__le32 cookie_lo; /* 8-11: */
> > +			__le32 cookie_hi; /* 12-15: */
> > +		};
> > +		void *cookie;
> > +	};
> > +	/* ===== data ==== [16-64] */
> > +	union {
> > +		u8 data[40];
> > +
> > +		struct version {
> > +			__le32 major;
> > +			__le32 sub;
> > +			__le32 modify;
> > +		} version;
> > +
> > +		struct {
> > +			__le32 value[4];
> > +		} r_reg;
> > +
> > +		struct {
> > +			__le32 new_value;
> > +		} modify_reg;
> > +
> > +		struct get_temp {
> > +			__le32 temp;
> > +			__le32 volatage;
> 
> voltage
> 

Got it, I will fix this.

> > +		} get_temp;
> > +
> > +		struct {
> > +#define MBX_SFP_READ_MAX_CNT 32
> > +			u8 value[MBX_SFP_READ_MAX_CNT];
> > +		} sfp_read;
> > +
> > +		struct mac_addr {
> > +			__le32 lanes;
> > +			struct _addr {
> > +				/*
> > +				 * for macaddr:01:02:03:04:05:06
> > +				 * mac-hi=0x01020304 mac-lo=0x05060000
> > +				 */
> > +				u8 mac[8];
> > +			} addrs[4];
> > +		} mac_addr;
> > +
> > +		struct get_dump_reply {
> > +			__le32 flags;
> > +			__le32 version;
> > +			__le32 bytes;
> > +			__le32 data[4];
> > +		} get_dump;
> > +
> > +		struct get_lldp_reply {
> > +			__le32 value;
> > +			__le32 inteval;
> 
> interval
> 

Got it, I will fix this.

> > +		} get_lldp;
> > +
> > +		struct rnpgbe_eee_cap phy_eee_abilities;
> > +		struct lane_stat_data lanestat;
> > +		struct hw_abilities hw_abilities;
> > +		struct phy_statistics phy_statistics;
> > +	};
> > +} __packed;
> 
> ...
> 

Thanks for your feedback.
Re: [PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support
Posted by Brett Creeley 2 months, 2 weeks ago

On 7/21/2025 4:32 AM, Dong Yibo wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> Initialize get hw capability from mbx_fw ops.
> 
> Signed-off-by: Dong Yibo <dong100@mucse.com>
> ---
>   drivers/net/ethernet/mucse/rnpgbe/Makefile    |   3 +-
>   drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h    |   8 +
>   .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c   |   8 +
>   .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 140 +++++
>   .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 568 ++++++++++++++++++
>   5 files changed, 726 insertions(+), 1 deletion(-)
>   create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
>   create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> 
> diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ethernet/mucse/rnpgbe/Makefile
> index 41177103b50c..fd455cb111a9 100644
> --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile
> +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile
> @@ -7,4 +7,5 @@
>   obj-$(CONFIG_MGBE) += rnpgbe.o
>   rnpgbe-objs := rnpgbe_main.o \
>                 rnpgbe_chip.o \
> -              rnpgbe_mbx.o
> +              rnpgbe_mbx.o \
> +              rnpgbe_mbx_fw.o
> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
> index 46e2bb2fe71e..4514bc1223c1 100644
> --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
> @@ -154,6 +154,14 @@ struct mucse_hw {
>          u16 vendor_id;
>          u16 subsystem_device_id;
>          u16 subsystem_vendor_id;
> +       u32 wol;
> +       u32 wol_en;
> +       u32 fw_version;
> +       u32 axi_mhz;
> +       u32 bd_uid;
> +       int ncsi_en;
> +       int force_en;
> +       int force_cap;
>          int max_vfs;
>          int max_vfs_noari;
>          enum rnpgbe_hw_type hw_type;
> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> index 1e8360cae560..aeb560145c47 100644
> --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> @@ -9,6 +9,7 @@
>   #include <linux/etherdevice.h>
> 
>   #include "rnpgbe.h"
> +#include "rnpgbe_mbx_fw.h"
> 
>   char rnpgbe_driver_name[] = "rnpgbe";
>   static const struct rnpgbe_info *rnpgbe_info_tbl[] = {
> @@ -116,6 +117,13 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev,
>          ii->get_invariants(hw);
>          hw->mbx.ops.init_params(hw);
> 
> +       err = mucse_mbx_get_capability(hw);
> +       if (err) {
> +               dev_err(&pdev->dev,
> +                       "mucse_mbx_get_capability failed!\n");
> +               goto err_free_net;
> +       }

Do you want to know what the "err" value was? Should that be included in 
the error message?

> +
>          return 0;
> 
>   err_free_net:
> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
> new file mode 100644
> index 000000000000..1674229fcd43
> --- /dev/null
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
> @@ -0,0 +1,140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright(c) 2020 - 2025 Mucse Corporation. */
> +
> +#include <linux/pci.h>
> +
> +#include "rnpgbe_mbx_fw.h"
> +
> +/**
> + * mucse_fw_send_cmd_wait - Send cmd req and wait for response
> + * @hw: Pointer to the HW structure
> + * @req: Pointer to the cmd req structure
> + * @reply: Pointer to the fw reply structure
> + *
> + * mucse_fw_send_cmd_wait sends req to pf-fw mailbox and wait
> + * reply from fw.
> + *
> + * @return: 0 on success, negative on failure
> + **/
> +static int mucse_fw_send_cmd_wait(struct mucse_hw *hw,
> +                                 struct mbx_fw_cmd_req *req,
> +                                 struct mbx_fw_cmd_reply *reply)
> +{
> +       int len = le32_to_cpu(req->datalen) + MBX_REQ_HDR_LEN;
> +       int retry_cnt = 3;
> +       int err;
> +
> +       err = mutex_lock_interruptible(&hw->mbx.lock);
> +       if (err)
> +               return err;
> +
> +       err = hw->mbx.ops.write_posted(hw, (u32 *)req,
> +                                      L_WD(len),
> +                                      MBX_FW);
> +       if (err) {
> +               mutex_unlock(&hw->mbx.lock);
> +               return err;
> +       }
> +
> +retry:
> +       retry_cnt--;
> +       if (retry_cnt < 0)
> +               return -EIO;

You aren't releasing the lock here, was that intentional?  Also, would 
-ETIMEDOUT make more sense?

> +
> +       err = hw->mbx.ops.read_posted(hw, (u32 *)reply,
> +                                     L_WD(sizeof(*reply)),
> +                                     MBX_FW);
> +       if (err) {
> +               mutex_unlock(&hw->mbx.lock);
> +               return err;
> +       }
> +
> +       if (reply->opcode != req->opcode)
> +               goto retry;

It seems like this block could be achieved with some sort of loop 
condition instead of a goto retry. Something like:

do {
} while (--retry_cnt >= 0 && reply->opcode != req->opcode);

mutex_unlock();

if (retry_cnt < 0)
	return -ETIMEDOUT;

if (reply->error_code)
	return -EIO;

return 0;
> +
> +       mutex_unlock(&hw->mbx.lock);
> +
> +       if (reply->error_code)
> +               return -EIO;

Do you want to lose the "error_code" here?

> +
> +       return 0;
> +}
> +
> +/**
> + * mucse_fw_get_capability - Get hw abilities from fw
> + * @hw: Pointer to the HW structure
> + * @abil: Pointer to the hw_abilities structure
> + *
> + * mucse_fw_get_capability tries to get hw abilities from
> + * hw.
> + *
> + * @return: 0 on success, negative on failure
> + **/
> +static int mucse_fw_get_capability(struct mucse_hw *hw,
> +                                  struct hw_abilities *abil)
> +{
> +       struct mbx_fw_cmd_reply reply;
> +       struct mbx_fw_cmd_req req;
> +       int err = 0;

Nit, you don't need to initialize this because it will always be set 
when calling mucse_fw_send_cmd_wait().

> +
> +       memset(&req, 0, sizeof(req));
> +       memset(&reply, 0, sizeof(reply));
> +       build_phy_abalities_req(&req, &req);
> +       err = mucse_fw_send_cmd_wait(hw, &req, &reply);
> +       if (err == 0)

Nit, but typically just "if (!err)" is used.

> +               memcpy(abil, &reply.hw_abilities, sizeof(*abil));
> +
> +       return err;
> +}
> +
> +/**
> + * mucse_mbx_get_capability - Get hw abilities from fw
> + * @hw: Pointer to the HW structure
> + *
> + * mucse_mbx_get_capability tries to some capabities from
> + * hw. Many retrys will do if it is failed.
> + *
> + * @return: 0 on success, negative on failure
> + **/
> +int mucse_mbx_get_capability(struct mucse_hw *hw)
> +{
> +       struct hw_abilities ability;
> +       int try_cnt = 3;
> +       int err = 0;

Don't initialize err as it's always set before being used. Please look 
through all your patches and apply this same comment/thought process 
before reposting.

> +
> +       memset(&ability, 0, sizeof(ability));
> +
> +       while (try_cnt--) {
> +               err = mucse_fw_get_capability(hw, &ability);
> +               if (err == 0) {

Typically the following is done to reduce indentation.

while (condition) {
	err = func();
         if (err)
		continue;

	/* handle non-err case */
         return 0;
}

return err;
> +                       u16 nic_mode = le16_to_cpu(ability.nic_mode);
> +                       u32 wol = le32_to_cpu(ability.wol_status);
> +
> +                       hw->ncsi_en = (nic_mode & 0x4) ? 1 : 0;
> +                       hw->pfvfnum = le16_to_cpu(ability.pfnum);
> +                       hw->fw_version = le32_to_cpu(ability.fw_version);
> +                       hw->axi_mhz = le32_to_cpu(ability.axi_mhz);
> +                       hw->bd_uid = le32_to_cpu(ability.bd_uid);
> +
> +                       if (hw->fw_version >= 0x0001012C) {
> +                               /* this version can get wol_en from hw */
> +                               hw->wol = wol & 0xff;
> +                               hw->wol_en = wol & 0x100;
> +                       } else {
> +                               /* other version only pf0 or ncsi can wol */
> +                               hw->wol = wol & 0xff;
> +                               if (hw->ncsi_en || !hw->pfvfnum)
> +                                       hw->wol_en = 1;
> +                       }
> +                       /* 0.1.5.0 can get force status from fw */
> +                       if (hw->fw_version >= 0x00010500) {
> +                               ability_update_host_endian(&ability);
> +                               hw->force_en = ability.e_host.force_down_en;
> +                               hw->force_cap = 1;
> +                       }
> +                       return 0;
> +               }
> +       }
> +
> +       return err;
> +}
> diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> new file mode 100644
> index 000000000000..a24c5d4e0075
> --- /dev/null
> +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> @@ -0,0 +1,568 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright(c) 2020 - 2025 Mucse Corporation. */
> +
> +#ifndef _RNPGBE_MBX_FW_H
> +#define _RNPGBE_MBX_FW_H
> +
> +#include <linux/types.h>
> +#include <linux/errno.h>
> +#include <linux/wait.h>
> +
> +#include "rnpgbe.h"
> +
> +#define MBX_REQ_HDR_LEN 24
> +#define L_WD(x) ((x) / 4)
> +
> +struct mbx_fw_cmd_reply;
> +typedef void (*cookie_cb)(struct mbx_fw_cmd_reply *reply, void *priv);
> +
> +struct mbx_req_cookie {
> +       int magic;
> +#define COOKIE_MAGIC 0xCE
> +       cookie_cb cb;
> +       int timeout_jiffes;
> +       int errcode;
> +       wait_queue_head_t wait;
> +       int done;
> +       int priv_len;
> +       char priv[];
> +};
> +
> +enum MUCSE_FW_CMD {
> +       GET_VERSION = 0x0001,
> +       READ_REG = 0xFF03,
> +       WRITE_REG = 0xFF04,
> +       MODIFY_REG = 0xFF07,
> +       IFUP_DOWN = 0x0800,
> +       SEND_TO_PF = 0x0801,
> +       SEND_TO_VF = 0x0802,
> +       DRIVER_INSMOD = 0x0803,
> +       SYSTEM_SUSPUSE = 0x0804,
> +       SYSTEM_FORCE = 0x0805,
> +       GET_PHY_ABALITY = 0x0601,
> +       GET_MAC_ADDRES = 0x0602,
> +       RESET_PHY = 0x0603,
> +       LED_SET = 0x0604,
> +       GET_LINK_STATUS = 0x0607,
> +       LINK_STATUS_EVENT = 0x0608,
> +       SET_LANE_FUN = 0x0609,
> +       GET_LANE_STATUS = 0x0610,
> +       SFP_SPEED_CHANGED_EVENT = 0x0611,
> +       SET_EVENT_MASK = 0x0613,
> +       SET_LOOPBACK_MODE = 0x0618,
> +       SET_PHY_REG = 0x0628,
> +       GET_PHY_REG = 0x0629,
> +       PHY_LINK_SET = 0x0630,
> +       GET_PHY_STATISTICS = 0x0631,
> +       PHY_PAUSE_SET = 0x0632,
> +       PHY_PAUSE_GET = 0x0633,
> +       PHY_EEE_SET = 0x0636,
> +       PHY_EEE_GET = 0x0637,
> +       SFP_MODULE_READ = 0x0900,
> +       SFP_MODULE_WRITE = 0x0901,
> +       FW_UPDATE = 0x0700,
> +       FW_MAINTAIN = 0x0701,
> +       FW_UPDATE_GBE = 0x0702,
> +       WOL_EN = 0x0910,
> +       GET_DUMP = 0x0a00,
> +       SET_DUMP = 0x0a10,
> +       GET_TEMP = 0x0a11,
> +       SET_WOL = 0x0a12,
> +       SET_TEST_MODE = 0x0a13,
> +       SHOW_TX_STAMP = 0x0a14,
> +       LLDP_TX_CTRL = 0x0a15,
> +};
> +
> +struct hw_abilities {
> +       u8 link_stat;
> +       u8 lane_mask;
> +       __le32 speed;
> +       __le16 phy_type;
> +       __le16 nic_mode;
> +       __le16 pfnum;
> +       __le32 fw_version;
> +       __le32 axi_mhz;
> +       union {
> +               u8 port_id[4];
> +               __le32 port_ids;
> +       };
> +       __le32 bd_uid;
> +       __le32 phy_id;
> +       __le32 wol_status;
> +       union {
> +               __le32 ext_ability;
> +               struct {
> +                       __le32 valid : 1; /* 0 */
> +                       __le32 wol_en : 1; /* 1 */
> +                       __le32 pci_preset_runtime_en : 1; /* 2 */
> +                       __le32 smbus_en : 1; /* 3 */
> +                       __le32 ncsi_en : 1; /* 4 */
> +                       __le32 rpu_en : 1; /* 5 */
> +                       __le32 v2 : 1; /* 6 */
> +                       __le32 pxe_en : 1; /* 7 */
> +                       __le32 mctp_en : 1; /* 8 */
> +                       __le32 yt8614 : 1; /* 9 */
> +                       __le32 pci_ext_reset : 1; /* 10 */
> +                       __le32 rpu_availble : 1; /* 11 */
> +                       __le32 fw_lldp_ability : 1; /* 12 */
> +                       __le32 lldp_enabled : 1; /* 13 */
> +                       __le32 only_1g : 1; /* 14 */
> +                       __le32 force_down_en: 1; /* 15 */
> +               } e;
> +               struct {
> +                       u32 valid : 1; /* 0 */
> +                       u32 wol_en : 1; /* 1 */
> +                       u32 pci_preset_runtime_en : 1; /* 2 */
> +                       u32 smbus_en : 1; /* 3 */
> +                       u32 ncsi_en : 1; /* 4 */
> +                       u32 rpu_en : 1; /* 5 */
> +                       u32 v2 : 1; /* 6 */
> +                       u32 pxe_en : 1; /* 7 */
> +                       u32 mctp_en : 1; /* 8 */
> +                       u32 yt8614 : 1; /* 9 */
> +                       u32 pci_ext_reset : 1; /* 10 */
> +                       u32 rpu_availble : 1; /* 11 */
> +                       u32 fw_lldp_ability : 1; /* 12 */
> +                       u32 lldp_enabled : 1; /* 13 */
> +                       u32 only_1g : 1; /* 14 */
> +                       u32 force_down_en: 1; /* 15 */
> +               } e_host;

Do the /* <bit_#> */ comments provide any value here?

> +       };
> +} __packed;
> +
> +static inline void ability_update_host_endian(struct hw_abilities *abi)
> +{
> +       u32 host_val = le32_to_cpu(abi->ext_ability);
> +
> +       abi->e_host = *(typeof(abi->e_host) *)&host_val;
> +}
> +
> +struct phy_pause_data {
> +       u32 pause_mode;
> +};
> +
> +struct lane_stat_data {
> +       u8 nr_lane;
> +       u8 pci_gen : 4;
> +       u8 pci_lanes : 4;
> +       u8 pma_type;
> +       u8 phy_type;
> +       __le16 linkup : 1;
> +       __le16 duplex : 1;
> +       __le16 autoneg : 1;
> +       __le16 fec : 1;
> +       __le16 an : 1;
> +       __le16 link_traing : 1;
> +       __le16 media_availble : 1;
> +       __le16 is_sgmii : 1;
> +       __le16 link_fault : 4;
> +#define LINK_LINK_FAULT BIT(0)
> +#define LINK_TX_FAULT BIT(1)
> +#define LINK_RX_FAULT BIT(2)
> +#define LINK_REMOTE_FAULT BIT(3)
> +       __le16 is_backplane : 1;
> +       __le16 tp_mdx : 2;
> +       union {
> +               u8 phy_addr;
> +               struct {
> +                       u8 mod_abs : 1;
> +                       u8 fault : 1;
> +                       u8 tx_dis : 1;
> +                       u8 los : 1;
> +               } sfp;
> +       };
> +       u8 sfp_connector;
> +       __le32 speed;
> +       __le32 si_main;
> +       __le32 si_pre;
> +       __le32 si_post;
> +       __le32 si_tx_boost;
> +       __le32 supported_link;
> +       __le32 phy_id;
> +       __le32 advertised_link;
> +} __packed;
> +
> +struct yt_phy_statistics {
> +       __le32 pkg_ib_valid; /* rx crc good and length 64-1518 */
> +       __le32 pkg_ib_os_good; /* rx crc good and length >1518 */
> +       __le32 pkg_ib_us_good; /* rx crc good and length <64 */
> +       __le16 pkg_ib_err; /* rx crc wrong and length 64-1518 */
> +       __le16 pkg_ib_os_bad; /* rx crc wrong and length >1518 */
> +       __le16 pkg_ib_frag; /* rx crc wrong and length <64 */
> +       __le16 pkg_ib_nosfd; /* rx sfd missed */
> +       __le32 pkg_ob_valid; /* tx crc good and length 64-1518 */
> +       __le32 pkg_ob_os_good; /* tx crc good and length >1518 */
> +       __le32 pkg_ob_us_good; /* tx crc good and length <64 */
> +       __le16 pkg_ob_err; /* tx crc wrong and length 64-1518 */
> +       __le16 pkg_ob_os_bad; /* tx crc wrong and length >1518 */
> +       __le16 pkg_ob_frag; /* tx crc wrong and length <64 */
> +       __le16 pkg_ob_nosfd; /* tx sfd missed */
> +} __packed;
> +
> +struct phy_statistics {
> +       union {
> +               struct yt_phy_statistics yt;
> +       };
> +} __packed;
> +
> +struct port_stat {
> +       u8 phyid;
> +       u8 duplex : 1;
> +       u8 autoneg : 1;
> +       u8 fec : 1;
> +       __le16 speed;
> +       union {
> +               __le16 stat;
> +               struct {
> +                       __le16 pause : 4;
> +                       __le16 local_eee : 3;
> +                       __le16 partner_eee : 3;
> +                       __le16 tp_mdx : 2;
> +                       __le16 lldp_status : 1;
> +                       __le16 revs : 3;
> +               } v;
> +               struct {
> +                       u16 pause : 4;
> +                       u16 local_eee : 3;
> +                       u16 partner_eee : 3;
> +                       u16 tp_mdx : 2;
> +                       u16 lldp_status : 1;
> +                       u16 revs : 3;
> +               } v_host;
> +       };
> +} __packed;
> +
> +#define FLAGS_DD BIT(0) /* driver clear 0, FW must set 1 */
> +/* driver clear 0, FW must set only if it reporting an error */
> +#define FLAGS_ERR BIT(2)
> +
> +/* req is little endian. bigendian should be conserened */

Some typos here. Please fix.

> +struct mbx_fw_cmd_req {
> +       __le16 flags; /* 0-1 */
> +       __le16 opcode; /* 2-3 enum GENERIC_CMD */
> +       __le16 datalen; /* 4-5 */
> +       __le16 ret_value; /* 6-7 */
> +       union {
> +               struct {
> +                       __le32 cookie_lo; /* 8-11 */
> +                       __le32 cookie_hi; /* 12-15 */
> +               };
> +
> +               void *cookie;
> +       };
> +       __le32 reply_lo; /* 16-19 5dw */
> +       __le32 reply_hi; /* 20-23 */
> +       union {
> +               u8 data[32];
> +               struct {
> +                       __le32 addr;
> +                       __le32 bytes;
> +               } r_reg;
> +
> +               struct {
> +                       __le32 addr;
> +                       __le32 bytes;
> +                       __le32 data[4];
> +               } w_reg;
> +
> +               struct {
> +                       __le32 lanes;
> +               } ptp;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 up;
> +               } ifup;
> +
> +               struct {
> +                       __le32 sec;
> +                       __le32 nanosec;
> +
> +               } tstamps;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 status;
> +               } ifinsmod;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 status;
> +               } ifforce;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 status;
> +               } ifsuspuse;
> +
> +               struct {
> +                       __le32 nr_lane;
> +               } get_lane_st;
> +
> +               struct {
> +                       __le32 nr_lane;
> +                       __le32 func;
> +#define LANE_FUN_AN 0
> +#define LANE_FUN_LINK_TRAING 1
> +#define LANE_FUN_FEC 2
> +#define LANE_FUN_SI 3
> +#define LANE_FUN_SFP_TX_DISABLE 4
> +#define LANE_FUN_PCI_LANE 5
> +#define LANE_FUN_PRBS 6
> +#define LANE_FUN_SPEED_CHANGE 7
> +                       __le32 value0;
> +                       __le32 value1;
> +                       __le32 value2;
> +                       __le32 value3;
> +               } set_lane_fun;
> +
> +               struct {
> +                       __le32 flag;
> +                       __le32 nr_lane;
> +               } set_dump;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 enable;
> +               } wol;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 mode;
> +               } gephy_test;
> +
> +               struct {
> +                       __le32 lane;
> +                       __le32 op;
> +                       __le32 enable;
> +                       __le32 inteval;
> +               } lldp_tx;
> +
> +               struct {
> +                       __le32 bytes;
> +                       __le32 nr_lane;
> +                       __le32 bin_offset;
> +                       __le32 no_use;
> +               } get_dump;
> +
> +               struct {
> +                       __le32 nr_lane;
> +                       __le32 value;
> +#define LED_IDENTIFY_INACTIVE 0
> +#define LED_IDENTIFY_ACTIVE 1
> +#define LED_IDENTIFY_ON 2
> +#define LED_IDENTIFY_OFF 3
> +               } led_set;
> +
> +               struct {
> +                       __le32 addr;
> +                       __le32 data;
> +                       __le32 mask;
> +               } modify_reg;
> +
> +               struct {
> +                       __le32 adv_speed_mask;
> +                       __le32 autoneg;
> +                       __le32 speed;
> +                       __le32 duplex;
> +                       __le32 nr_lane;
> +                       __le32 tp_mdix_ctrl;
> +               } phy_link_set;
> +
> +               struct {
> +                       __le32 pause_mode;
> +                       __le32 nr_lane;
> +               } phy_pause_set;
> +
> +               struct {
> +                       __le32 pause_mode;
> +                       __le32 nr_lane;
> +               } phy_pause_get;
> +
> +               struct {
> +                       __le32 local_eee;
> +                       __le32 tx_lpi_timer;
> +                       __le32 nr_lane;
> +               } phy_eee_set;
> +
> +               struct {
> +                       __le32 nr_lane;
> +                       __le32 sfp_adr; /* 0xa0 or 0xa2 */
> +                       __le32 reg;
> +                       __le32 cnt;
> +               } sfp_read;
> +
> +               struct {
> +                       __le32 nr_lane;
> +                       __le32 sfp_adr; /* 0xa0 or 0xa2 */
> +                       __le32 reg;
> +                       __le32 val;
> +               } sfp_write;
> +
> +               struct {
> +                       __le32 nr_lane; /* 0-3 */
> +               } get_linkstat;
> +
> +               struct {
> +                       __le16 changed_lanes;
> +                       __le16 lane_status;
> +                       __le32 port_st_magic;
> +#define SPEED_VALID_MAGIC 0xa4a6a8a9
> +                       struct port_stat st[4];
> +               } link_stat; /* FW->RC */
> +
> +               struct {
> +                       __le16 enable_stat;
> +                       __le16 event_mask;
> +               } stat_event_mask;
> +
> +               struct {
> +                       __le32 cmd;
> +                       __le32 arg0;
> +                       __le32 req_bytes;
> +                       __le32 reply_bytes;
> +                       __le32 ddr_lo;
> +                       __le32 ddr_hi;
> +               } maintain;
> +
> +               struct { /* set phy register */
> +                       u8 phy_interface;
> +                       union {
> +                               u8 page_num;
> +                               u8 external_phy_addr;
> +                       };
> +                       __le32 phy_reg_addr;
> +                       __le32 phy_w_data;
> +                       __le32 reg_addr;
> +                       __le32 w_data;
> +                       /* 1 = ignore page_num, use last QSFP */
> +                       u8 recall_qsfp_page : 1;
> +                       /* page value */
> +                       /* 0 = use page_num for QSFP */
> +                       u8 nr_lane;
> +               } set_phy_reg;
> +
> +               struct {
> +                       __le32 lane_mask;
> +                       __le32 pfvf_num;
> +               } get_mac_addr;
> +
> +               struct {
> +                       u8 phy_interface;
> +                       union {
> +                               u8 page_num;
> +                               u8 external_phy_addr;
> +                       };
> +                       __le32 phy_reg_addr;
> +                       u8 nr_lane;
> +               } get_phy_reg;
> +
> +               struct {
> +                       __le32 nr_lane;
> +               } phy_statistics;
> +
> +               struct {
> +                       u8 paration;
> +                       __le32 bytes;
> +                       __le32 bin_phy_lo;
> +                       __le32 bin_phy_hi;
> +               } fw_update;
> +       };
> +} __packed;
> +
> +#define EEE_1000BT BIT(2)
> +#define EEE_100BT BIT(1)
> +
> +struct rnpgbe_eee_cap {
> +       __le32 local_capability;
> +       __le32 local_eee;
> +       __le32 partner_eee;
> +};
> +
> +/* firmware -> driver */
> +struct mbx_fw_cmd_reply {
> +       /* fw must set: DD, CMP, Error(if error), copy value */
> +       __le16 flags;
> +       /* from command: LB,RD,VFC,BUF,SI,EI,FE */
> +       __le16 opcode; /* 2-3: copy from req */
> +       __le16 error_code; /* 4-5: 0 if no error */
> +       __le16 datalen; /* 6-7: */
> +       union {
> +               struct {
> +                       __le32 cookie_lo; /* 8-11: */
> +                       __le32 cookie_hi; /* 12-15: */
> +               };
> +               void *cookie;
> +       };
> +       /* ===== data ==== [16-64] */
> +       union {
> +               u8 data[40];
> +
> +               struct version {
> +                       __le32 major;
> +                       __le32 sub;
> +                       __le32 modify;
> +               } version;
> +
> +               struct {
> +                       __le32 value[4];
> +               } r_reg;
> +
> +               struct {
> +                       __le32 new_value;
> +               } modify_reg;
> +
> +               struct get_temp {
> +                       __le32 temp;
> +                       __le32 volatage;
> +               } get_temp;
> +
> +               struct {
> +#define MBX_SFP_READ_MAX_CNT 32
> +                       u8 value[MBX_SFP_READ_MAX_CNT];
> +               } sfp_read;
> +
> +               struct mac_addr {
> +                       __le32 lanes;
> +                       struct _addr {
> +                               /*
> +                                * for macaddr:01:02:03:04:05:06
> +                                * mac-hi=0x01020304 mac-lo=0x05060000
> +                                */
> +                               u8 mac[8];
> +                       } addrs[4];
> +               } mac_addr;
> +
> +               struct get_dump_reply {
> +                       __le32 flags;
> +                       __le32 version;
> +                       __le32 bytes;
> +                       __le32 data[4];
> +               } get_dump;
> +
> +               struct get_lldp_reply {
> +                       __le32 value;
> +                       __le32 inteval;
> +               } get_lldp;
> +
> +               struct rnpgbe_eee_cap phy_eee_abilities;
> +               struct lane_stat_data lanestat;
> +               struct hw_abilities hw_abilities;
> +               struct phy_statistics phy_statistics;
> +       };
> +} __packed;
> +
> +static inline void build_phy_abalities_req(struct mbx_fw_cmd_req *req,
> +                                          void *cookie)
> +{
> +       req->flags = 0;
> +       req->opcode = cpu_to_le32(GET_PHY_ABALITY);
> +       req->datalen = 0;
> +       req->reply_lo = 0;
> +       req->reply_hi = 0;
> +       req->cookie = cookie;
> +}
> +
> +int mucse_mbx_get_capability(struct mucse_hw *hw);
> +
> +#endif /* _RNPGBE_MBX_FW_H */
> --
> 2.25.1
> 
>
Re: [PATCH v2 04/15] net: rnpgbe: Add get_capability mbx_fw ops support
Posted by Yibo Dong 2 months, 2 weeks ago
On Mon, Jul 21, 2025 at 03:08:22PM -0700, Brett Creeley wrote:
> On 7/21/2025 4:32 AM, Dong Yibo wrote:
> > Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> > 
> > 
> > Initialize get hw capability from mbx_fw ops.
> > 
> > Signed-off-by: Dong Yibo <dong100@mucse.com>
> > ---
> >   drivers/net/ethernet/mucse/rnpgbe/Makefile    |   3 +-
> >   drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h    |   8 +
> >   .../net/ethernet/mucse/rnpgbe/rnpgbe_main.c   |   8 +
> >   .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c | 140 +++++
> >   .../net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h | 568 ++++++++++++++++++
> >   5 files changed, 726 insertions(+), 1 deletion(-)
> >   create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
> >   create mode 100644 drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> > 
> > diff --git a/drivers/net/ethernet/mucse/rnpgbe/Makefile b/drivers/net/ethernet/mucse/rnpgbe/Makefile
> > index 41177103b50c..fd455cb111a9 100644
> > --- a/drivers/net/ethernet/mucse/rnpgbe/Makefile
> > +++ b/drivers/net/ethernet/mucse/rnpgbe/Makefile
> > @@ -7,4 +7,5 @@
> >   obj-$(CONFIG_MGBE) += rnpgbe.o
> >   rnpgbe-objs := rnpgbe_main.o \
> >                 rnpgbe_chip.o \
> > -              rnpgbe_mbx.o
> > +              rnpgbe_mbx.o \
> > +              rnpgbe_mbx_fw.o
> > diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
> > index 46e2bb2fe71e..4514bc1223c1 100644
> > --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
> > +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe.h
> > @@ -154,6 +154,14 @@ struct mucse_hw {
> >          u16 vendor_id;
> >          u16 subsystem_device_id;
> >          u16 subsystem_vendor_id;
> > +       u32 wol;
> > +       u32 wol_en;
> > +       u32 fw_version;
> > +       u32 axi_mhz;
> > +       u32 bd_uid;
> > +       int ncsi_en;
> > +       int force_en;
> > +       int force_cap;
> >          int max_vfs;
> >          int max_vfs_noari;
> >          enum rnpgbe_hw_type hw_type;
> > diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> > index 1e8360cae560..aeb560145c47 100644
> > --- a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> > +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_main.c
> > @@ -9,6 +9,7 @@
> >   #include <linux/etherdevice.h>
> > 
> >   #include "rnpgbe.h"
> > +#include "rnpgbe_mbx_fw.h"
> > 
> >   char rnpgbe_driver_name[] = "rnpgbe";
> >   static const struct rnpgbe_info *rnpgbe_info_tbl[] = {
> > @@ -116,6 +117,13 @@ static int rnpgbe_add_adapter(struct pci_dev *pdev,
> >          ii->get_invariants(hw);
> >          hw->mbx.ops.init_params(hw);
> > 
> > +       err = mucse_mbx_get_capability(hw);
> > +       if (err) {
> > +               dev_err(&pdev->dev,
> > +                       "mucse_mbx_get_capability failed!\n");
> > +               goto err_free_net;
> > +       }
> 
> Do you want to know what the "err" value was? Should that be included in the
> error message?
> 

Yes, i waant it, I should add err in the dev_err. Thank you for your suggestion.

> > +
> >          return 0;
> > 
> >   err_free_net:
> > diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
> > new file mode 100644
> > index 000000000000..1674229fcd43
> > --- /dev/null
> > +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c
> > @@ -0,0 +1,140 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright(c) 2020 - 2025 Mucse Corporation. */
> > +
> > +#include <linux/pci.h>
> > +
> > +#include "rnpgbe_mbx_fw.h"
> > +
> > +/**
> > + * mucse_fw_send_cmd_wait - Send cmd req and wait for response
> > + * @hw: Pointer to the HW structure
> > + * @req: Pointer to the cmd req structure
> > + * @reply: Pointer to the fw reply structure
> > + *
> > + * mucse_fw_send_cmd_wait sends req to pf-fw mailbox and wait
> > + * reply from fw.
> > + *
> > + * @return: 0 on success, negative on failure
> > + **/
> > +static int mucse_fw_send_cmd_wait(struct mucse_hw *hw,
> > +                                 struct mbx_fw_cmd_req *req,
> > +                                 struct mbx_fw_cmd_reply *reply)
> > +{
> > +       int len = le32_to_cpu(req->datalen) + MBX_REQ_HDR_LEN;
> > +       int retry_cnt = 3;
> > +       int err;
> > +
> > +       err = mutex_lock_interruptible(&hw->mbx.lock);
> > +       if (err)
> > +               return err;
> > +
> > +       err = hw->mbx.ops.write_posted(hw, (u32 *)req,
> > +                                      L_WD(len),
> > +                                      MBX_FW);
> > +       if (err) {
> > +               mutex_unlock(&hw->mbx.lock);
> > +               return err;
> > +       }
> > +
> > +retry:
> > +       retry_cnt--;
> > +       if (retry_cnt < 0)
> > +               return -EIO;
> 
> You aren't releasing the lock here, was that intentional?  Also, would
> -ETIMEDOUT make more sense?
> 

Yes, I missed releasing the lock. I will fix it.
-ETIMEDOUT is more sense, I will improve it.

> > +
> > +       err = hw->mbx.ops.read_posted(hw, (u32 *)reply,
> > +                                     L_WD(sizeof(*reply)),
> > +                                     MBX_FW);
> > +       if (err) {
> > +               mutex_unlock(&hw->mbx.lock);
> > +               return err;
> > +       }
> > +
> > +       if (reply->opcode != req->opcode)
> > +               goto retry;
> 
> It seems like this block could be achieved with some sort of loop condition
> instead of a goto retry. Something like:
> 
> do {
> } while (--retry_cnt >= 0 && reply->opcode != req->opcode);
> 
> mutex_unlock();
> 
> if (retry_cnt < 0)
> 	return -ETIMEDOUT;
> 
> if (reply->error_code)
> 	return -EIO;
> 
> return 0;

Got it, I will improve it.

> > +
> > +       mutex_unlock(&hw->mbx.lock);
> > +
> > +       if (reply->error_code)
> > +               return -EIO;
> 
> Do you want to lose the "error_code" here?
> 

reply->erro_code is not linux error code.
It is used only between fw and driver:
0     -- no err
not 0 -- err
So, I turn it into a linux/POSIX error here.

> > +
> > +       return 0;
> > +}
> > +
> > +/**
> > + * mucse_fw_get_capability - Get hw abilities from fw
> > + * @hw: Pointer to the HW structure
> > + * @abil: Pointer to the hw_abilities structure
> > + *
> > + * mucse_fw_get_capability tries to get hw abilities from
> > + * hw.
> > + *
> > + * @return: 0 on success, negative on failure
> > + **/
> > +static int mucse_fw_get_capability(struct mucse_hw *hw,
> > +                                  struct hw_abilities *abil)
> > +{
> > +       struct mbx_fw_cmd_reply reply;
> > +       struct mbx_fw_cmd_req req;
> > +       int err = 0;
> 
> Nit, you don't need to initialize this because it will always be set when
> calling mucse_fw_send_cmd_wait().
> 

Got it, I will improve it.

> > +
> > +       memset(&req, 0, sizeof(req));
> > +       memset(&reply, 0, sizeof(reply));
> > +       build_phy_abalities_req(&req, &req);
> > +       err = mucse_fw_send_cmd_wait(hw, &req, &reply);
> > +       if (err == 0)
> 
> Nit, but typically just "if (!err)" is used.
> 

Got it, I will improve it.

> > +               memcpy(abil, &reply.hw_abilities, sizeof(*abil));
> > +
> > +       return err;
> > +}
> > +
> > +/**
> > + * mucse_mbx_get_capability - Get hw abilities from fw
> > + * @hw: Pointer to the HW structure
> > + *
> > + * mucse_mbx_get_capability tries to some capabities from
> > + * hw. Many retrys will do if it is failed.
> > + *
> > + * @return: 0 on success, negative on failure
> > + **/
> > +int mucse_mbx_get_capability(struct mucse_hw *hw)
> > +{
> > +       struct hw_abilities ability;
> > +       int try_cnt = 3;
> > +       int err = 0;
> 
> Don't initialize err as it's always set before being used. Please look
> through all your patches and apply this same comment/thought process before
> reposting.
> 

Got it, I will check it for the reset of patches in the next version.

> > +
> > +       memset(&ability, 0, sizeof(ability));
> > +
> > +       while (try_cnt--) {
> > +               err = mucse_fw_get_capability(hw, &ability);
> > +               if (err == 0) {
> 
> Typically the following is done to reduce indentation.
> 
> while (condition) {
> 	err = func();
>         if (err)
> 		continue;
> 
> 	/* handle non-err case */
>         return 0;
> }
> 
> return err;

Got it, I will fix it.

> > +                       u16 nic_mode = le16_to_cpu(ability.nic_mode);
> > +                       u32 wol = le32_to_cpu(ability.wol_status);
> > +
> > +                       hw->ncsi_en = (nic_mode & 0x4) ? 1 : 0;
> > +                       hw->pfvfnum = le16_to_cpu(ability.pfnum);
> > +                       hw->fw_version = le32_to_cpu(ability.fw_version);
> > +                       hw->axi_mhz = le32_to_cpu(ability.axi_mhz);
> > +                       hw->bd_uid = le32_to_cpu(ability.bd_uid);
> > +
> > +                       if (hw->fw_version >= 0x0001012C) {
> > +                               /* this version can get wol_en from hw */
> > +                               hw->wol = wol & 0xff;
> > +                               hw->wol_en = wol & 0x100;
> > +                       } else {
> > +                               /* other version only pf0 or ncsi can wol */
> > +                               hw->wol = wol & 0xff;
> > +                               if (hw->ncsi_en || !hw->pfvfnum)
> > +                                       hw->wol_en = 1;
> > +                       }
> > +                       /* 0.1.5.0 can get force status from fw */
> > +                       if (hw->fw_version >= 0x00010500) {
> > +                               ability_update_host_endian(&ability);
> > +                               hw->force_en = ability.e_host.force_down_en;
> > +                               hw->force_cap = 1;
> > +                       }
> > +                       return 0;
> > +               }
> > +       }
> > +
> > +       return err;
> > +}
> > diff --git a/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> > new file mode 100644
> > index 000000000000..a24c5d4e0075
> > --- /dev/null
> > +++ b/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.h
> > @@ -0,0 +1,568 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Copyright(c) 2020 - 2025 Mucse Corporation. */
> > +
> > +#ifndef _RNPGBE_MBX_FW_H
> > +#define _RNPGBE_MBX_FW_H
> > +
> > +#include <linux/types.h>
> > +#include <linux/errno.h>
> > +#include <linux/wait.h>
> > +
> > +#include "rnpgbe.h"
> > +
> > +#define MBX_REQ_HDR_LEN 24
> > +#define L_WD(x) ((x) / 4)
> > +
> > +struct mbx_fw_cmd_reply;
> > +typedef void (*cookie_cb)(struct mbx_fw_cmd_reply *reply, void *priv);
> > +
> > +struct mbx_req_cookie {
> > +       int magic;
> > +#define COOKIE_MAGIC 0xCE
> > +       cookie_cb cb;
> > +       int timeout_jiffes;
> > +       int errcode;
> > +       wait_queue_head_t wait;
> > +       int done;
> > +       int priv_len;
> > +       char priv[];
> > +};
> > +
> > +enum MUCSE_FW_CMD {
> > +       GET_VERSION = 0x0001,
> > +       READ_REG = 0xFF03,
> > +       WRITE_REG = 0xFF04,
> > +       MODIFY_REG = 0xFF07,
> > +       IFUP_DOWN = 0x0800,
> > +       SEND_TO_PF = 0x0801,
> > +       SEND_TO_VF = 0x0802,
> > +       DRIVER_INSMOD = 0x0803,
> > +       SYSTEM_SUSPUSE = 0x0804,
> > +       SYSTEM_FORCE = 0x0805,
> > +       GET_PHY_ABALITY = 0x0601,
> > +       GET_MAC_ADDRES = 0x0602,
> > +       RESET_PHY = 0x0603,
> > +       LED_SET = 0x0604,
> > +       GET_LINK_STATUS = 0x0607,
> > +       LINK_STATUS_EVENT = 0x0608,
> > +       SET_LANE_FUN = 0x0609,
> > +       GET_LANE_STATUS = 0x0610,
> > +       SFP_SPEED_CHANGED_EVENT = 0x0611,
> > +       SET_EVENT_MASK = 0x0613,
> > +       SET_LOOPBACK_MODE = 0x0618,
> > +       SET_PHY_REG = 0x0628,
> > +       GET_PHY_REG = 0x0629,
> > +       PHY_LINK_SET = 0x0630,
> > +       GET_PHY_STATISTICS = 0x0631,
> > +       PHY_PAUSE_SET = 0x0632,
> > +       PHY_PAUSE_GET = 0x0633,
> > +       PHY_EEE_SET = 0x0636,
> > +       PHY_EEE_GET = 0x0637,
> > +       SFP_MODULE_READ = 0x0900,
> > +       SFP_MODULE_WRITE = 0x0901,
> > +       FW_UPDATE = 0x0700,
> > +       FW_MAINTAIN = 0x0701,
> > +       FW_UPDATE_GBE = 0x0702,
> > +       WOL_EN = 0x0910,
> > +       GET_DUMP = 0x0a00,
> > +       SET_DUMP = 0x0a10,
> > +       GET_TEMP = 0x0a11,
> > +       SET_WOL = 0x0a12,
> > +       SET_TEST_MODE = 0x0a13,
> > +       SHOW_TX_STAMP = 0x0a14,
> > +       LLDP_TX_CTRL = 0x0a15,
> > +};
> > +
> > +struct hw_abilities {
> > +       u8 link_stat;
> > +       u8 lane_mask;
> > +       __le32 speed;
> > +       __le16 phy_type;
> > +       __le16 nic_mode;
> > +       __le16 pfnum;
> > +       __le32 fw_version;
> > +       __le32 axi_mhz;
> > +       union {
> > +               u8 port_id[4];
> > +               __le32 port_ids;
> > +       };
> > +       __le32 bd_uid;
> > +       __le32 phy_id;
> > +       __le32 wol_status;
> > +       union {
> > +               __le32 ext_ability;
> > +               struct {
> > +                       __le32 valid : 1; /* 0 */
> > +                       __le32 wol_en : 1; /* 1 */
> > +                       __le32 pci_preset_runtime_en : 1; /* 2 */
> > +                       __le32 smbus_en : 1; /* 3 */
> > +                       __le32 ncsi_en : 1; /* 4 */
> > +                       __le32 rpu_en : 1; /* 5 */
> > +                       __le32 v2 : 1; /* 6 */
> > +                       __le32 pxe_en : 1; /* 7 */
> > +                       __le32 mctp_en : 1; /* 8 */
> > +                       __le32 yt8614 : 1; /* 9 */
> > +                       __le32 pci_ext_reset : 1; /* 10 */
> > +                       __le32 rpu_availble : 1; /* 11 */
> > +                       __le32 fw_lldp_ability : 1; /* 12 */
> > +                       __le32 lldp_enabled : 1; /* 13 */
> > +                       __le32 only_1g : 1; /* 14 */
> > +                       __le32 force_down_en: 1; /* 15 */
> > +               } e;
> > +               struct {
> > +                       u32 valid : 1; /* 0 */
> > +                       u32 wol_en : 1; /* 1 */
> > +                       u32 pci_preset_runtime_en : 1; /* 2 */
> > +                       u32 smbus_en : 1; /* 3 */
> > +                       u32 ncsi_en : 1; /* 4 */
> > +                       u32 rpu_en : 1; /* 5 */
> > +                       u32 v2 : 1; /* 6 */
> > +                       u32 pxe_en : 1; /* 7 */
> > +                       u32 mctp_en : 1; /* 8 */
> > +                       u32 yt8614 : 1; /* 9 */
> > +                       u32 pci_ext_reset : 1; /* 10 */
> > +                       u32 rpu_availble : 1; /* 11 */
> > +                       u32 fw_lldp_ability : 1; /* 12 */
> > +                       u32 lldp_enabled : 1; /* 13 */
> > +                       u32 only_1g : 1; /* 14 */
> > +                       u32 force_down_en: 1; /* 15 */
> > +               } e_host;
> 
> Do the /* <bit_#> */ comments provide any value here?
> 

Got it. I should remove no value comments like this.

> > +       };
> > +} __packed;
> > +
> > +static inline void ability_update_host_endian(struct hw_abilities *abi)
> > +{
> > +       u32 host_val = le32_to_cpu(abi->ext_ability);
> > +
> > +       abi->e_host = *(typeof(abi->e_host) *)&host_val;
> > +}
> > +
> > +struct phy_pause_data {
> > +       u32 pause_mode;
> > +};
> > +
> > +struct lane_stat_data {
> > +       u8 nr_lane;
> > +       u8 pci_gen : 4;
> > +       u8 pci_lanes : 4;
> > +       u8 pma_type;
> > +       u8 phy_type;
> > +       __le16 linkup : 1;
> > +       __le16 duplex : 1;
> > +       __le16 autoneg : 1;
> > +       __le16 fec : 1;
> > +       __le16 an : 1;
> > +       __le16 link_traing : 1;
> > +       __le16 media_availble : 1;
> > +       __le16 is_sgmii : 1;
> > +       __le16 link_fault : 4;
> > +#define LINK_LINK_FAULT BIT(0)
> > +#define LINK_TX_FAULT BIT(1)
> > +#define LINK_RX_FAULT BIT(2)
> > +#define LINK_REMOTE_FAULT BIT(3)
> > +       __le16 is_backplane : 1;
> > +       __le16 tp_mdx : 2;
> > +       union {
> > +               u8 phy_addr;
> > +               struct {
> > +                       u8 mod_abs : 1;
> > +                       u8 fault : 1;
> > +                       u8 tx_dis : 1;
> > +                       u8 los : 1;
> > +               } sfp;
> > +       };
> > +       u8 sfp_connector;
> > +       __le32 speed;
> > +       __le32 si_main;
> > +       __le32 si_pre;
> > +       __le32 si_post;
> > +       __le32 si_tx_boost;
> > +       __le32 supported_link;
> > +       __le32 phy_id;
> > +       __le32 advertised_link;
> > +} __packed;
> > +
> > +struct yt_phy_statistics {
> > +       __le32 pkg_ib_valid; /* rx crc good and length 64-1518 */
> > +       __le32 pkg_ib_os_good; /* rx crc good and length >1518 */
> > +       __le32 pkg_ib_us_good; /* rx crc good and length <64 */
> > +       __le16 pkg_ib_err; /* rx crc wrong and length 64-1518 */
> > +       __le16 pkg_ib_os_bad; /* rx crc wrong and length >1518 */
> > +       __le16 pkg_ib_frag; /* rx crc wrong and length <64 */
> > +       __le16 pkg_ib_nosfd; /* rx sfd missed */
> > +       __le32 pkg_ob_valid; /* tx crc good and length 64-1518 */
> > +       __le32 pkg_ob_os_good; /* tx crc good and length >1518 */
> > +       __le32 pkg_ob_us_good; /* tx crc good and length <64 */
> > +       __le16 pkg_ob_err; /* tx crc wrong and length 64-1518 */
> > +       __le16 pkg_ob_os_bad; /* tx crc wrong and length >1518 */
> > +       __le16 pkg_ob_frag; /* tx crc wrong and length <64 */
> > +       __le16 pkg_ob_nosfd; /* tx sfd missed */
> > +} __packed;
> > +
> > +struct phy_statistics {
> > +       union {
> > +               struct yt_phy_statistics yt;
> > +       };
> > +} __packed;
> > +
> > +struct port_stat {
> > +       u8 phyid;
> > +       u8 duplex : 1;
> > +       u8 autoneg : 1;
> > +       u8 fec : 1;
> > +       __le16 speed;
> > +       union {
> > +               __le16 stat;
> > +               struct {
> > +                       __le16 pause : 4;
> > +                       __le16 local_eee : 3;
> > +                       __le16 partner_eee : 3;
> > +                       __le16 tp_mdx : 2;
> > +                       __le16 lldp_status : 1;
> > +                       __le16 revs : 3;
> > +               } v;
> > +               struct {
> > +                       u16 pause : 4;
> > +                       u16 local_eee : 3;
> > +                       u16 partner_eee : 3;
> > +                       u16 tp_mdx : 2;
> > +                       u16 lldp_status : 1;
> > +                       u16 revs : 3;
> > +               } v_host;
> > +       };
> > +} __packed;
> > +
> > +#define FLAGS_DD BIT(0) /* driver clear 0, FW must set 1 */
> > +/* driver clear 0, FW must set only if it reporting an error */
> > +#define FLAGS_ERR BIT(2)
> > +
> > +/* req is little endian. bigendian should be conserened */
> 
> Some typos here. Please fix.
> 

Got it, I will fix them.

> > +struct mbx_fw_cmd_req {
> > +       __le16 flags; /* 0-1 */
> > +       __le16 opcode; /* 2-3 enum GENERIC_CMD */
> > +       __le16 datalen; /* 4-5 */
> > +       __le16 ret_value; /* 6-7 */
> > +       union {
> > +               struct {
> > +                       __le32 cookie_lo; /* 8-11 */
> > +                       __le32 cookie_hi; /* 12-15 */
> > +               };
> > +
> > +               void *cookie;
> > +       };
> > +       __le32 reply_lo; /* 16-19 5dw */
> > +       __le32 reply_hi; /* 20-23 */
> > +       union {
> > +               u8 data[32];
> > +               struct {
> > +                       __le32 addr;
> > +                       __le32 bytes;
> > +               } r_reg;
> > +
> > +               struct {
> > +                       __le32 addr;
> > +                       __le32 bytes;
> > +                       __le32 data[4];
> > +               } w_reg;
> > +
> > +               struct {
> > +                       __le32 lanes;
> > +               } ptp;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 up;
> > +               } ifup;
> > +
> > +               struct {
> > +                       __le32 sec;
> > +                       __le32 nanosec;
> > +
> > +               } tstamps;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 status;
> > +               } ifinsmod;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 status;
> > +               } ifforce;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 status;
> > +               } ifsuspuse;
> > +
> > +               struct {
> > +                       __le32 nr_lane;
> > +               } get_lane_st;
> > +
> > +               struct {
> > +                       __le32 nr_lane;
> > +                       __le32 func;
> > +#define LANE_FUN_AN 0
> > +#define LANE_FUN_LINK_TRAING 1
> > +#define LANE_FUN_FEC 2
> > +#define LANE_FUN_SI 3
> > +#define LANE_FUN_SFP_TX_DISABLE 4
> > +#define LANE_FUN_PCI_LANE 5
> > +#define LANE_FUN_PRBS 6
> > +#define LANE_FUN_SPEED_CHANGE 7
> > +                       __le32 value0;
> > +                       __le32 value1;
> > +                       __le32 value2;
> > +                       __le32 value3;
> > +               } set_lane_fun;
> > +
> > +               struct {
> > +                       __le32 flag;
> > +                       __le32 nr_lane;
> > +               } set_dump;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 enable;
> > +               } wol;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 mode;
> > +               } gephy_test;
> > +
> > +               struct {
> > +                       __le32 lane;
> > +                       __le32 op;
> > +                       __le32 enable;
> > +                       __le32 inteval;
> > +               } lldp_tx;
> > +
> > +               struct {
> > +                       __le32 bytes;
> > +                       __le32 nr_lane;
> > +                       __le32 bin_offset;
> > +                       __le32 no_use;
> > +               } get_dump;
> > +
> > +               struct {
> > +                       __le32 nr_lane;
> > +                       __le32 value;
> > +#define LED_IDENTIFY_INACTIVE 0
> > +#define LED_IDENTIFY_ACTIVE 1
> > +#define LED_IDENTIFY_ON 2
> > +#define LED_IDENTIFY_OFF 3
> > +               } led_set;
> > +
> > +               struct {
> > +                       __le32 addr;
> > +                       __le32 data;
> > +                       __le32 mask;
> > +               } modify_reg;
> > +
> > +               struct {
> > +                       __le32 adv_speed_mask;
> > +                       __le32 autoneg;
> > +                       __le32 speed;
> > +                       __le32 duplex;
> > +                       __le32 nr_lane;
> > +                       __le32 tp_mdix_ctrl;
> > +               } phy_link_set;
> > +
> > +               struct {
> > +                       __le32 pause_mode;
> > +                       __le32 nr_lane;
> > +               } phy_pause_set;
> > +
> > +               struct {
> > +                       __le32 pause_mode;
> > +                       __le32 nr_lane;
> > +               } phy_pause_get;
> > +
> > +               struct {
> > +                       __le32 local_eee;
> > +                       __le32 tx_lpi_timer;
> > +                       __le32 nr_lane;
> > +               } phy_eee_set;
> > +
> > +               struct {
> > +                       __le32 nr_lane;
> > +                       __le32 sfp_adr; /* 0xa0 or 0xa2 */
> > +                       __le32 reg;
> > +                       __le32 cnt;
> > +               } sfp_read;
> > +
> > +               struct {
> > +                       __le32 nr_lane;
> > +                       __le32 sfp_adr; /* 0xa0 or 0xa2 */
> > +                       __le32 reg;
> > +                       __le32 val;
> > +               } sfp_write;
> > +
> > +               struct {
> > +                       __le32 nr_lane; /* 0-3 */
> > +               } get_linkstat;
> > +
> > +               struct {
> > +                       __le16 changed_lanes;
> > +                       __le16 lane_status;
> > +                       __le32 port_st_magic;
> > +#define SPEED_VALID_MAGIC 0xa4a6a8a9
> > +                       struct port_stat st[4];
> > +               } link_stat; /* FW->RC */
> > +
> > +               struct {
> > +                       __le16 enable_stat;
> > +                       __le16 event_mask;
> > +               } stat_event_mask;
> > +
> > +               struct {
> > +                       __le32 cmd;
> > +                       __le32 arg0;
> > +                       __le32 req_bytes;
> > +                       __le32 reply_bytes;
> > +                       __le32 ddr_lo;
> > +                       __le32 ddr_hi;
> > +               } maintain;
> > +
> > +               struct { /* set phy register */
> > +                       u8 phy_interface;
> > +                       union {
> > +                               u8 page_num;
> > +                               u8 external_phy_addr;
> > +                       };
> > +                       __le32 phy_reg_addr;
> > +                       __le32 phy_w_data;
> > +                       __le32 reg_addr;
> > +                       __le32 w_data;
> > +                       /* 1 = ignore page_num, use last QSFP */
> > +                       u8 recall_qsfp_page : 1;
> > +                       /* page value */
> > +                       /* 0 = use page_num for QSFP */
> > +                       u8 nr_lane;
> > +               } set_phy_reg;
> > +
> > +               struct {
> > +                       __le32 lane_mask;
> > +                       __le32 pfvf_num;
> > +               } get_mac_addr;
> > +
> > +               struct {
> > +                       u8 phy_interface;
> > +                       union {
> > +                               u8 page_num;
> > +                               u8 external_phy_addr;
> > +                       };
> > +                       __le32 phy_reg_addr;
> > +                       u8 nr_lane;
> > +               } get_phy_reg;
> > +
> > +               struct {
> > +                       __le32 nr_lane;
> > +               } phy_statistics;
> > +
> > +               struct {
> > +                       u8 paration;
> > +                       __le32 bytes;
> > +                       __le32 bin_phy_lo;
> > +                       __le32 bin_phy_hi;
> > +               } fw_update;
> > +       };
> > +} __packed;
> > +
> > +#define EEE_1000BT BIT(2)
> > +#define EEE_100BT BIT(1)
> > +
> > +struct rnpgbe_eee_cap {
> > +       __le32 local_capability;
> > +       __le32 local_eee;
> > +       __le32 partner_eee;
> > +};
> > +
> > +/* firmware -> driver */
> > +struct mbx_fw_cmd_reply {
> > +       /* fw must set: DD, CMP, Error(if error), copy value */
> > +       __le16 flags;
> > +       /* from command: LB,RD,VFC,BUF,SI,EI,FE */
> > +       __le16 opcode; /* 2-3: copy from req */
> > +       __le16 error_code; /* 4-5: 0 if no error */
> > +       __le16 datalen; /* 6-7: */
> > +       union {
> > +               struct {
> > +                       __le32 cookie_lo; /* 8-11: */
> > +                       __le32 cookie_hi; /* 12-15: */
> > +               };
> > +               void *cookie;
> > +       };
> > +       /* ===== data ==== [16-64] */
> > +       union {
> > +               u8 data[40];
> > +
> > +               struct version {
> > +                       __le32 major;
> > +                       __le32 sub;
> > +                       __le32 modify;
> > +               } version;
> > +
> > +               struct {
> > +                       __le32 value[4];
> > +               } r_reg;
> > +
> > +               struct {
> > +                       __le32 new_value;
> > +               } modify_reg;
> > +
> > +               struct get_temp {
> > +                       __le32 temp;
> > +                       __le32 volatage;
> > +               } get_temp;
> > +
> > +               struct {
> > +#define MBX_SFP_READ_MAX_CNT 32
> > +                       u8 value[MBX_SFP_READ_MAX_CNT];
> > +               } sfp_read;
> > +
> > +               struct mac_addr {
> > +                       __le32 lanes;
> > +                       struct _addr {
> > +                               /*
> > +                                * for macaddr:01:02:03:04:05:06
> > +                                * mac-hi=0x01020304 mac-lo=0x05060000
> > +                                */
> > +                               u8 mac[8];
> > +                       } addrs[4];
> > +               } mac_addr;
> > +
> > +               struct get_dump_reply {
> > +                       __le32 flags;
> > +                       __le32 version;
> > +                       __le32 bytes;
> > +                       __le32 data[4];
> > +               } get_dump;
> > +
> > +               struct get_lldp_reply {
> > +                       __le32 value;
> > +                       __le32 inteval;
> > +               } get_lldp;
> > +
> > +               struct rnpgbe_eee_cap phy_eee_abilities;
> > +               struct lane_stat_data lanestat;
> > +               struct hw_abilities hw_abilities;
> > +               struct phy_statistics phy_statistics;
> > +       };
> > +} __packed;
> > +
> > +static inline void build_phy_abalities_req(struct mbx_fw_cmd_req *req,
> > +                                          void *cookie)
> > +{
> > +       req->flags = 0;
> > +       req->opcode = cpu_to_le32(GET_PHY_ABALITY);
> > +       req->datalen = 0;
> > +       req->reply_lo = 0;
> > +       req->reply_hi = 0;
> > +       req->cookie = cookie;
> > +}
> > +
> > +int mucse_mbx_get_capability(struct mucse_hw *hw);
> > +
> > +#endif /* _RNPGBE_MBX_FW_H */
> > --
> > 2.25.1
> > 
> > 
> 
> 

Thanks for your feedback.