File Index
Files and directories
Sign in
FILE

rnpgbe_mbx_fw.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mucse/rnpgbe/rnpgbe_mbx_fw.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright(c) 2020 - 2025 Mucse Corporation. */
  3
  4#include <linux/if_ether.h>
  5#include <linux/bitfield.h>
  6
  7#include "rnpgbe.h"
  8#include "rnpgbe_mbx.h"
  9#include "rnpgbe_mbx_fw.h"
 10
 11/**
 12 * mucse_fw_send_cmd_wait_resp - Send cmd req and wait for response
 13 * @hw: pointer to the HW structure
 14 * @req: pointer to the cmd req structure
 15 * @reply: pointer to the fw reply structure
 16 *
 17 * mucse_fw_send_cmd_wait_resp sends req to pf-fw mailbox and wait
 18 * reply from fw.
 19 *
 20 * Return: 0 on success, negative errno on failure
 21 **/
 22static int mucse_fw_send_cmd_wait_resp(struct mucse_hw *hw,
 23				       struct mbx_fw_cmd_req *req,
 24				       struct mbx_fw_cmd_reply *reply)
 25{
 26	int len = le16_to_cpu(req->datalen);
 27	int retry_cnt = 3;
 28	int err;
 29
 30	mutex_lock(&hw->mbx.lock);
 31	err = mucse_write_and_wait_ack_mbx(hw, (u32 *)req, len);
 32	if (err)
 33		goto out;
 34	do {
 35		err = mucse_poll_and_read_mbx(hw, (u32 *)reply,
 36					      sizeof(*reply));
 37		if (err)
 38			goto out;
 39		/* mucse_write_and_wait_ack_mbx return 0 means fw has
 40		 * received request, wait for the expect opcode
 41		 * reply with 'retry_cnt' times.
 42		 */
 43	} while (--retry_cnt >= 0 && reply->opcode != req->opcode);
 44out:
 45	mutex_unlock(&hw->mbx.lock);
 46	if (!err && retry_cnt < 0)
 47		return -ETIMEDOUT;
 48	if (!err && reply->error_code)
 49		return -EIO;
 50
 51	return err;
 52}
 53
 54/**
 55 * mucse_mbx_get_info - Get hw info from fw
 56 * @hw: pointer to the HW structure
 57 *
 58 * mucse_mbx_get_info tries to get hw info from hw.
 59 *
 60 * Return: 0 on success, negative errno on failure
 61 **/
 62static int mucse_mbx_get_info(struct mucse_hw *hw)
 63{
 64	struct mbx_fw_cmd_req req = {
 65		.datalen = cpu_to_le16(MUCSE_MBX_REQ_HDR_LEN),
 66		.opcode  = cpu_to_le16(GET_HW_INFO),
 67	};
 68	struct mbx_fw_cmd_reply reply = {};
 69	int err;
 70
 71	err = mucse_fw_send_cmd_wait_resp(hw, &req, &reply);
 72	if (!err)
 73		hw->pfvfnum = FIELD_GET(GENMASK_U16(7, 0),
 74					le16_to_cpu(reply.hw_info.pfnum));
 75
 76	return err;
 77}
 78
 79/**
 80 * mucse_mbx_sync_fw - Try to sync with fw
 81 * @hw: pointer to the HW structure
 82 *
 83 * mucse_mbx_sync_fw tries to sync with fw. It is only called in
 84 * probe. Nothing (register network) todo if failed.
 85 * Try more times to do sync.
 86 *
 87 * Return: 0 on success, negative errno on failure
 88 **/
 89int mucse_mbx_sync_fw(struct mucse_hw *hw)
 90{
 91	int try_cnt = 3;
 92	int err;
 93
 94	do {
 95		err = mucse_mbx_get_info(hw);
 96	} while (err == -ETIMEDOUT && try_cnt--);
 97
 98	return err;
 99}
100
101/**
102 * mucse_mbx_powerup - Echo fw to powerup
103 * @hw: pointer to the HW structure
104 * @is_powerup: true for powerup, false for powerdown
105 *
106 * mucse_mbx_powerup echo fw to change working frequency
107 * to normal after received true, and reduce working frequency
108 * if false.
109 *
110 * Return: 0 on success, negative errno on failure
111 **/
112int mucse_mbx_powerup(struct mucse_hw *hw, bool is_powerup)
113{
114	struct mbx_fw_cmd_req req = {
115		.datalen = cpu_to_le16(sizeof(req.powerup) +
116				       MUCSE_MBX_REQ_HDR_LEN),
117		.opcode  = cpu_to_le16(POWER_UP),
118		.powerup = {
119			/* fw needs this to reply correct cmd */
120			.version = cpu_to_le32(GENMASK_U32(31, 0)),
121			.status  = cpu_to_le32(is_powerup ? 1 : 0),
122		},
123	};
124	int len, err;
125
126	len = le16_to_cpu(req.datalen);
127	mutex_lock(&hw->mbx.lock);
128	err = mucse_write_and_wait_ack_mbx(hw, (u32 *)&req, len);
129	mutex_unlock(&hw->mbx.lock);
130
131	return err;
132}
133
134/**
135 * mucse_mbx_reset_hw - Posts a mbx req to reset hw
136 * @hw: pointer to the HW structure
137 *
138 * mucse_mbx_reset_hw posts a mbx req to firmware to reset hw.
139 * We use mucse_fw_send_cmd_wait_resp to wait hw reset ok.
140 *
141 * Return: 0 on success, negative errno on failure
142 **/
143int mucse_mbx_reset_hw(struct mucse_hw *hw)
144{
145	struct mbx_fw_cmd_req req = {
146		.datalen = cpu_to_le16(MUCSE_MBX_REQ_HDR_LEN),
147		.opcode  = cpu_to_le16(RESET_HW),
148	};
149	struct mbx_fw_cmd_reply reply = {};
150
151	return mucse_fw_send_cmd_wait_resp(hw, &req, &reply);
152}
153
154/**
155 * mucse_mbx_get_macaddr - Posts a mbx req to request macaddr
156 * @hw: pointer to the HW structure
157 * @pfvfnum: index of pf/vf num
158 * @mac_addr: pointer to store mac_addr
159 * @port: port index
160 *
161 * mucse_mbx_get_macaddr posts a mbx req to firmware to get mac_addr.
162 *
163 * Return: 0 on success, negative errno on failure
164 **/
165int mucse_mbx_get_macaddr(struct mucse_hw *hw, int pfvfnum,
166			  u8 *mac_addr,
167			  int port)
168{
169	struct mbx_fw_cmd_req req = {
170		.datalen      = cpu_to_le16(sizeof(req.get_mac_addr) +
171					    MUCSE_MBX_REQ_HDR_LEN),
172		.opcode       = cpu_to_le16(GET_MAC_ADDRESS),
173		.get_mac_addr = {
174			.port_mask = cpu_to_le32(BIT(port)),
175			.pfvf_num  = cpu_to_le32(pfvfnum),
176		},
177	};
178	struct mbx_fw_cmd_reply reply = {};
179	int err;
180
181	err = mucse_fw_send_cmd_wait_resp(hw, &req, &reply);
182	if (err)
183		return err;
184
185	if (le32_to_cpu(reply.mac_addr.ports) & BIT(port))
186		memcpy(mac_addr, reply.mac_addr.addrs[port].mac, ETH_ALEN);
187	else
188		return -ENODATA;
189
190	return 0;
191}
~/ Read-only file preview.