#include <linux/if_ether.h>
#include <linux/bitfield.h>
#include "rnpgbe.h"
#include "rnpgbe_mbx.h"
#include "rnpgbe_mbx_fw.h"
static int mucse_fw_send_cmd_wait_resp(struct mucse_hw *hw,
struct mbx_fw_cmd_req *req,
struct mbx_fw_cmd_reply *reply)
{
int len = le16_to_cpu(req->datalen);
int retry_cnt = 3;
int err;
mutex_lock(&hw->mbx.lock);
err = mucse_write_and_wait_ack_mbx(hw, (u32 *)req, len);
if (err)
goto out;
do {
err = mucse_poll_and_read_mbx(hw, (u32 *)reply,
sizeof(*reply));
if (err)
goto out;
} while (--retry_cnt >= 0 && reply->opcode != req->opcode);
out:
mutex_unlock(&hw->mbx.lock);
if (!err && retry_cnt < 0)
return -ETIMEDOUT;
if (!err && reply->error_code)
return -EIO;
return err;
}
static int mucse_mbx_get_info(struct mucse_hw *hw)
{
struct mbx_fw_cmd_req req = {
.datalen = cpu_to_le16(MUCSE_MBX_REQ_HDR_LEN),
.opcode = cpu_to_le16(GET_HW_INFO),
};
struct mbx_fw_cmd_reply reply = {};
int err;
err = mucse_fw_send_cmd_wait_resp(hw, &req, &reply);
if (!err)
hw->pfvfnum = FIELD_GET(GENMASK_U16(7, 0),
le16_to_cpu(reply.hw_info.pfnum));
return err;
}
int mucse_mbx_sync_fw(struct mucse_hw *hw)
{
int try_cnt = 3;
int err;
do {
err = mucse_mbx_get_info(hw);
} while (err == -ETIMEDOUT && try_cnt--);
return err;
}
int mucse_mbx_powerup(struct mucse_hw *hw, bool is_powerup)
{
struct mbx_fw_cmd_req req = {
.datalen = cpu_to_le16(sizeof(req.powerup) +
MUCSE_MBX_REQ_HDR_LEN),
.opcode = cpu_to_le16(POWER_UP),
.powerup = {
.version = cpu_to_le32(GENMASK_U32(31, 0)),
.status = cpu_to_le32(is_powerup ? 1 : 0),
},
};
int len, err;
len = le16_to_cpu(req.datalen);
mutex_lock(&hw->mbx.lock);
err = mucse_write_and_wait_ack_mbx(hw, (u32 *)&req, len);
mutex_unlock(&hw->mbx.lock);
return err;
}
int mucse_mbx_reset_hw(struct mucse_hw *hw)
{
struct mbx_fw_cmd_req req = {
.datalen = cpu_to_le16(MUCSE_MBX_REQ_HDR_LEN),
.opcode = cpu_to_le16(RESET_HW),
};
struct mbx_fw_cmd_reply reply = {};
return mucse_fw_send_cmd_wait_resp(hw, &req, &reply);
}
int mucse_mbx_get_macaddr(struct mucse_hw *hw, int pfvfnum,
u8 *mac_addr,
int port)
{
struct mbx_fw_cmd_req req = {
.datalen = cpu_to_le16(sizeof(req.get_mac_addr) +
MUCSE_MBX_REQ_HDR_LEN),
.opcode = cpu_to_le16(GET_MAC_ADDRESS),
.get_mac_addr = {
.port_mask = cpu_to_le32(BIT(port)),
.pfvf_num = cpu_to_le32(pfvfnum),
},
};
struct mbx_fw_cmd_reply reply = {};
int err;
err = mucse_fw_send_cmd_wait_resp(hw, &req, &reply);
if (err)
return err;
if (le32_to_cpu(reply.mac_addr.ports) & BIT(port))
memcpy(mac_addr, reply.mac_addr.addrs[port].mac, ETH_ALEN);
else
return -ENODATA;
return 0;
}