Commit 12554574 authored by David S. Miller's avatar David S. Miller

Merge branch 'hinic-add-some-error-messages-for-debug'

Luo bin says:

====================
hinic: add some error messages for debug

patch #1: support to handle hw abnormal event
patch #2: improve the error messages when functions return failure and
	  dump relevant registers in some exception handling processes
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents aff75431 90f86b8a
......@@ -98,10 +98,14 @@ struct hinic_dev {
int lb_pkt_len;
u8 *lb_test_rx_buf;
struct devlink *devlink;
bool cable_unplugged;
bool module_unrecognized;
};
struct hinic_devlink_priv {
struct hinic_hwdev *hwdev;
struct devlink_health_reporter *hw_fault_reporter;
struct devlink_health_reporter *fw_fault_reporter;
};
#endif
......@@ -16,9 +16,9 @@
#include <net/devlink.h>
#include <linux/firmware.h>
#include "hinic_dev.h"
#include "hinic_port.h"
#include "hinic_devlink.h"
#include "hinic_hw_dev.h"
static bool check_image_valid(struct hinic_devlink_priv *priv, const u8 *buf,
u32 image_size, struct host_image_st *host_image)
......@@ -317,12 +317,292 @@ void hinic_devlink_free(struct devlink *devlink)
devlink_free(devlink);
}
int hinic_devlink_register(struct devlink *devlink, struct device *dev)
int hinic_devlink_register(struct hinic_devlink_priv *priv, struct device *dev)
{
struct devlink *devlink = priv_to_devlink(priv);
return devlink_register(devlink, dev);
}
void hinic_devlink_unregister(struct devlink *devlink)
void hinic_devlink_unregister(struct hinic_devlink_priv *priv)
{
struct devlink *devlink = priv_to_devlink(priv);
devlink_unregister(devlink);
}
static int chip_fault_show(struct devlink_fmsg *fmsg,
struct hinic_fault_event *event)
{
char fault_level[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = {
"fatal", "reset", "flr", "general", "suggestion"};
char level_str[FAULT_SHOW_STR_LEN + 1] = {0};
u8 level;
int err;
level = event->event.chip.err_level;
if (level < FAULT_LEVEL_MAX)
strncpy(level_str, fault_level[level], strlen(fault_level[level]));
else
strncpy(level_str, "Unknown", strlen("Unknown"));
if (level == FAULT_LEVEL_SERIOUS_FLR) {
err = devlink_fmsg_u32_pair_put(fmsg, "Function level err func_id",
(u32)event->event.chip.func_id);
if (err)
return err;
}
err = devlink_fmsg_u8_pair_put(fmsg, "module_id", event->event.chip.node_id);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "err_type", (u32)event->event.chip.err_type);
if (err)
return err;
err = devlink_fmsg_string_pair_put(fmsg, "err_level", level_str);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "err_csr_addr",
event->event.chip.err_csr_addr);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "err_csr_value",
event->event.chip.err_csr_value);
if (err)
return err;
return 0;
}
static int fault_report_show(struct devlink_fmsg *fmsg,
struct hinic_fault_event *event)
{
char fault_type[FAULT_TYPE_MAX][FAULT_SHOW_STR_LEN + 1] = {
"chip", "ucode", "mem rd timeout", "mem wr timeout",
"reg rd timeout", "reg wr timeout", "phy fault"};
char type_str[FAULT_SHOW_STR_LEN + 1] = {0};
int err;
if (event->type < FAULT_TYPE_MAX)
strncpy(type_str, fault_type[event->type], strlen(fault_type[event->type]));
else
strncpy(type_str, "Unknown", strlen("Unknown"));
err = devlink_fmsg_string_pair_put(fmsg, "Fault type", type_str);
if (err)
return err;
err = devlink_fmsg_binary_pair_put(fmsg, "Fault raw data",
event->event.val, sizeof(event->event.val));
if (err)
return err;
switch (event->type) {
case FAULT_TYPE_CHIP:
err = chip_fault_show(fmsg, event);
if (err)
return err;
break;
case FAULT_TYPE_UCODE:
err = devlink_fmsg_u8_pair_put(fmsg, "Cause_id", event->event.ucode.cause_id);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "core_id", event->event.ucode.core_id);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "c_id", event->event.ucode.c_id);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "epc", event->event.ucode.epc);
if (err)
return err;
break;
case FAULT_TYPE_MEM_RD_TIMEOUT:
case FAULT_TYPE_MEM_WR_TIMEOUT:
err = devlink_fmsg_u32_pair_put(fmsg, "Err_csr_ctrl",
event->event.mem_timeout.err_csr_ctrl);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "err_csr_data",
event->event.mem_timeout.err_csr_data);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "ctrl_tab",
event->event.mem_timeout.ctrl_tab);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "mem_index",
event->event.mem_timeout.mem_index);
if (err)
return err;
break;
case FAULT_TYPE_REG_RD_TIMEOUT:
case FAULT_TYPE_REG_WR_TIMEOUT:
err = devlink_fmsg_u32_pair_put(fmsg, "Err_csr", event->event.reg_timeout.err_csr);
if (err)
return err;
break;
case FAULT_TYPE_PHY_FAULT:
err = devlink_fmsg_u8_pair_put(fmsg, "Op_type", event->event.phy_fault.op_type);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "port_id", event->event.phy_fault.port_id);
if (err)
return err;
err = devlink_fmsg_u8_pair_put(fmsg, "dev_ad", event->event.phy_fault.dev_ad);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "csr_addr", event->event.phy_fault.csr_addr);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "op_data", event->event.phy_fault.op_data);
if (err)
return err;
break;
default:
break;
}
return 0;
}
static int hinic_hw_reporter_dump(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack)
{
if (priv_ctx)
return fault_report_show(fmsg, priv_ctx);
return 0;
}
static int mgmt_watchdog_report_show(struct devlink_fmsg *fmsg,
struct hinic_mgmt_watchdog_info *watchdog_info)
{
int err;
err = devlink_fmsg_u32_pair_put(fmsg, "Mgmt deadloop time_h", watchdog_info->curr_time_h);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "time_l", watchdog_info->curr_time_l);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "task_id", watchdog_info->task_id);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "sp", watchdog_info->sp);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "stack_current_used", watchdog_info->curr_used);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "peak_used", watchdog_info->peak_used);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "\n Overflow_flag", watchdog_info->is_overflow);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "stack_top", watchdog_info->stack_top);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "stack_bottom", watchdog_info->stack_bottom);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "mgmt_pc", watchdog_info->pc);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "lr", watchdog_info->lr);
if (err)
return err;
err = devlink_fmsg_u32_pair_put(fmsg, "cpsr", watchdog_info->cpsr);
if (err)
return err;
err = devlink_fmsg_binary_pair_put(fmsg, "Mgmt register info",
watchdog_info->reg, sizeof(watchdog_info->reg));
if (err)
return err;
err = devlink_fmsg_binary_pair_put(fmsg, "Mgmt dump stack(start from sp)",
watchdog_info->data, sizeof(watchdog_info->data));
if (err)
return err;
return 0;
}
static int hinic_fw_reporter_dump(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, void *priv_ctx,
struct netlink_ext_ack *extack)
{
if (priv_ctx)
return mgmt_watchdog_report_show(fmsg, priv_ctx);
return 0;
}
static const struct devlink_health_reporter_ops hinic_hw_fault_reporter_ops = {
.name = "hw",
.dump = hinic_hw_reporter_dump,
};
static const struct devlink_health_reporter_ops hinic_fw_fault_reporter_ops = {
.name = "fw",
.dump = hinic_fw_reporter_dump,
};
int hinic_health_reporters_create(struct hinic_devlink_priv *priv)
{
struct devlink *devlink = priv_to_devlink(priv);
priv->hw_fault_reporter =
devlink_health_reporter_create(devlink, &hinic_hw_fault_reporter_ops,
0, priv);
if (IS_ERR(priv->hw_fault_reporter)) {
dev_warn(&priv->hwdev->hwif->pdev->dev, "Failed to create hw fault reporter, err: %ld\n",
PTR_ERR(priv->hw_fault_reporter));
return PTR_ERR(priv->hw_fault_reporter);
}
priv->fw_fault_reporter =
devlink_health_reporter_create(devlink, &hinic_fw_fault_reporter_ops,
0, priv);
if (IS_ERR(priv->fw_fault_reporter)) {
dev_warn(&priv->hwdev->hwif->pdev->dev, "Failed to create fw fault reporter, err: %ld\n",
PTR_ERR(priv->fw_fault_reporter));
devlink_health_reporter_destroy(priv->hw_fault_reporter);
priv->hw_fault_reporter = NULL;
return PTR_ERR(priv->fw_fault_reporter);
}
return 0;
}
void hinic_health_reporters_destroy(struct hinic_devlink_priv *priv)
{
if (!IS_ERR_OR_NULL(priv->fw_fault_reporter)) {
devlink_health_reporter_destroy(priv->fw_fault_reporter);
priv->fw_fault_reporter = NULL;
}
if (!IS_ERR_OR_NULL(priv->hw_fault_reporter)) {
devlink_health_reporter_destroy(priv->hw_fault_reporter);
priv->hw_fault_reporter = NULL;
}
}
......@@ -7,6 +7,7 @@
#define __HINIC_DEVLINK_H__
#include <net/devlink.h>
#include "hinic_dev.h"
#define MAX_FW_TYPE_NUM 30
#define HINIC_MAGIC_NUM 0x18221100
......@@ -109,7 +110,10 @@ struct host_image_st {
struct devlink *hinic_devlink_alloc(void);
void hinic_devlink_free(struct devlink *devlink);
int hinic_devlink_register(struct devlink *devlink, struct device *dev);
void hinic_devlink_unregister(struct devlink *devlink);
int hinic_devlink_register(struct hinic_devlink_priv *priv, struct device *dev);
void hinic_devlink_unregister(struct hinic_devlink_priv *priv);
int hinic_health_reporters_create(struct hinic_devlink_priv *priv);
void hinic_health_reporters_destroy(struct hinic_devlink_priv *priv);
#endif /* __HINIC_DEVLINK_H__ */
......@@ -1766,6 +1766,25 @@ static int hinic_get_module_eeprom(struct net_device *netdev,
return 0;
}
static int
hinic_get_link_ext_state(struct net_device *netdev,
struct ethtool_link_ext_state_info *link_ext_state_info)
{
struct hinic_dev *nic_dev = netdev_priv(netdev);
if (netif_carrier_ok(netdev))
return -ENODATA;
if (nic_dev->cable_unplugged)
link_ext_state_info->link_ext_state =
ETHTOOL_LINK_EXT_STATE_NO_CABLE;
else if (nic_dev->module_unrecognized)
link_ext_state_info->link_ext_state =
ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH;
return 0;
}
static const struct ethtool_ops hinic_ethtool_ops = {
.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS |
ETHTOOL_COALESCE_RX_MAX_FRAMES |
......@@ -1776,6 +1795,7 @@ static const struct ethtool_ops hinic_ethtool_ops = {
.set_link_ksettings = hinic_set_link_ksettings,
.get_drvinfo = hinic_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_link_ext_state = hinic_get_link_ext_state,
.get_ringparam = hinic_get_ringparam,
.set_ringparam = hinic_set_ringparam,
.get_coalesce = hinic_get_coalesce,
......
......@@ -112,6 +112,26 @@ static u32 get_hw_cons_idx(struct hinic_api_cmd_chain *chain)
return HINIC_API_CMD_STATUS_GET(val, CONS_IDX);
}
static void dump_api_chain_reg(struct hinic_api_cmd_chain *chain)
{
u32 addr, val;
addr = HINIC_CSR_API_CMD_STATUS_ADDR(chain->chain_type);
val = hinic_hwif_read_reg(chain->hwif, addr);
dev_err(&chain->hwif->pdev->dev, "Chain type: 0x%x, cpld error: 0x%x, check error: 0x%x, current fsm: 0x%x\n",
chain->chain_type, HINIC_API_CMD_STATUS_GET(val, CPLD_ERR),
HINIC_API_CMD_STATUS_GET(val, CHKSUM_ERR),
HINIC_API_CMD_STATUS_GET(val, FSM));
dev_err(&chain->hwif->pdev->dev, "Chain hw current ci: 0x%x\n",
HINIC_API_CMD_STATUS_GET(val, CONS_IDX));
addr = HINIC_CSR_API_CMD_CHAIN_PI_ADDR(chain->chain_type);
val = hinic_hwif_read_reg(chain->hwif, addr);
dev_err(&chain->hwif->pdev->dev, "Chain hw current pi: 0x%x\n", val);
}
/**
* chain_busy - check if the chain is still processing last requests
* @chain: chain to check
......@@ -131,8 +151,10 @@ static int chain_busy(struct hinic_api_cmd_chain *chain)
/* check for a space for a new command */
if (chain->cons_idx == MASKED_IDX(chain, prod_idx + 1)) {
dev_err(&pdev->dev, "API CMD chain %d is busy\n",
chain->chain_type);
dev_err(&pdev->dev, "API CMD chain %d is busy, cons_idx: %d, prod_idx: %d\n",
chain->chain_type, chain->cons_idx,
chain->prod_idx);
dump_api_chain_reg(chain);
return -EBUSY;
}
break;
......@@ -332,6 +354,7 @@ static int wait_for_api_cmd_completion(struct hinic_api_cmd_chain *chain)
err = wait_for_status_poll(chain);
if (err) {
dev_err(&pdev->dev, "API CMD Poll status timeout\n");
dump_api_chain_reg(chain);
break;
}
break;
......
......@@ -103,10 +103,14 @@
HINIC_API_CMD_STATUS_HEADER_##member##_MASK)
#define HINIC_API_CMD_STATUS_CONS_IDX_SHIFT 0
#define HINIC_API_CMD_STATUS_FSM_SHIFT 24
#define HINIC_API_CMD_STATUS_CHKSUM_ERR_SHIFT 28
#define HINIC_API_CMD_STATUS_CPLD_ERR_SHIFT 30
#define HINIC_API_CMD_STATUS_CONS_IDX_MASK 0xFFFFFF
#define HINIC_API_CMD_STATUS_FSM_MASK 0xFU
#define HINIC_API_CMD_STATUS_CHKSUM_ERR_MASK 0x3
#define HINIC_API_CMD_STATUS_CPLD_ERR_MASK 0x1U
#define HINIC_API_CMD_STATUS_GET(val, member) \
(((val) >> HINIC_API_CMD_STATUS_##member##_SHIFT) & \
......
......@@ -401,6 +401,7 @@ static int cmdq_sync_cmd_direct_resp(struct hinic_cmdq *cmdq,
spin_unlock_bh(&cmdq->cmdq_lock);
hinic_dump_ceq_info(cmdq->hwdev);
return -ETIMEDOUT;
}
......@@ -807,6 +808,7 @@ static int init_cmdqs_ctxt(struct hinic_hwdev *hwdev,
cmdq_type = HINIC_CMDQ_SYNC;
for (; cmdq_type < HINIC_MAX_CMDQ_TYPES; cmdq_type++) {
cmdqs->cmdq[cmdq_type].hwdev = hwdev;
err = init_cmdq(&cmdqs->cmdq[cmdq_type],
&cmdqs->saved_wqs[cmdq_type], cmdq_type,
db_area[cmdq_type]);
......
......@@ -130,6 +130,8 @@ struct hinic_cmdq_ctxt {
};
struct hinic_cmdq {
struct hinic_hwdev *hwdev;
struct hinic_wq *wq;
enum hinic_cmdq_type cmdq_type;
......
......@@ -16,8 +16,11 @@
#include <linux/log2.h>
#include <linux/err.h>
#include <linux/netdevice.h>
#include <net/devlink.h>
#include "hinic_devlink.h"
#include "hinic_sriov.h"
#include "hinic_dev.h"
#include "hinic_hw_if.h"
#include "hinic_hw_eqs.h"
#include "hinic_hw_mgmt.h"
......@@ -255,9 +258,9 @@ static int init_fw_ctxt(struct hinic_hwdev *hwdev)
&fw_ctxt, sizeof(fw_ctxt),
&fw_ctxt, &out_size);
if (err || (out_size != sizeof(fw_ctxt)) || fw_ctxt.status) {
dev_err(&pdev->dev, "Failed to init FW ctxt, ret = %d\n",
fw_ctxt.status);
return -EFAULT;
dev_err(&pdev->dev, "Failed to init FW ctxt, err: %d, status: 0x%x, out size: 0x%x\n",
err, fw_ctxt.status, out_size);
return -EIO;
}
return 0;
......@@ -422,9 +425,9 @@ static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
&cmd_base_qpn, sizeof(cmd_base_qpn),
&cmd_base_qpn, &out_size);
if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) {
dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n",
cmd_base_qpn.status);
return -EFAULT;
dev_err(&pdev->dev, "Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x\n",
err, cmd_base_qpn.status, out_size);
return -EIO;
}
*base_qpn = cmd_base_qpn.qpn;
......@@ -621,6 +624,113 @@ static void nic_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in,
nic_cb->cb_state &= ~HINIC_CB_RUNNING;
}
static void hinic_comm_recv_mgmt_self_cmd_reg(struct hinic_pfhwdev *pfhwdev,
u8 cmd,
comm_mgmt_self_msg_proc proc)
{
u8 cmd_idx;
cmd_idx = pfhwdev->proc.cmd_num;
if (cmd_idx >= HINIC_COMM_SELF_CMD_MAX) {
dev_err(&pfhwdev->hwdev.hwif->pdev->dev,
"Register recv mgmt process failed, cmd: 0x%x\n", cmd);
return;
}
pfhwdev->proc.info[cmd_idx].cmd = cmd;
pfhwdev->proc.info[cmd_idx].proc = proc;
pfhwdev->proc.cmd_num++;
}
static void hinic_comm_recv_mgmt_self_cmd_unreg(struct hinic_pfhwdev *pfhwdev,
u8 cmd)
{
u8 cmd_idx;
cmd_idx = pfhwdev->proc.cmd_num;
if (cmd_idx >= HINIC_COMM_SELF_CMD_MAX) {
dev_err(&pfhwdev->hwdev.hwif->pdev->dev, "Unregister recv mgmt process failed, cmd: 0x%x\n",
cmd);
return;
}
for (cmd_idx = 0; cmd_idx < HINIC_COMM_SELF_CMD_MAX; cmd_idx++) {
if (cmd == pfhwdev->proc.info[cmd_idx].cmd) {
pfhwdev->proc.info[cmd_idx].cmd = 0;
pfhwdev->proc.info[cmd_idx].proc = NULL;
pfhwdev->proc.cmd_num--;
}
}
}
static void comm_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size)
{
struct hinic_pfhwdev *pfhwdev = handle;
u8 cmd_idx;
for (cmd_idx = 0; cmd_idx < pfhwdev->proc.cmd_num; cmd_idx++) {
if (cmd == pfhwdev->proc.info[cmd_idx].cmd) {
if (!pfhwdev->proc.info[cmd_idx].proc) {
dev_warn(&pfhwdev->hwdev.hwif->pdev->dev,
"PF recv mgmt comm msg handle null, cmd: 0x%x\n",
cmd);
} else {
pfhwdev->proc.info[cmd_idx].proc
(&pfhwdev->hwdev, buf_in, in_size,
buf_out, out_size);
}
return;
}
}
dev_warn(&pfhwdev->hwdev.hwif->pdev->dev, "Received unknown mgmt cpu event: 0x%x\n",
cmd);
*out_size = 0;
}
/* pf fault report event */
static void pf_fault_event_handler(void *dev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
struct hinic_cmd_fault_event *fault_event = buf_in;
struct hinic_hwdev *hwdev = dev;
if (in_size != sizeof(*fault_event)) {
dev_err(&hwdev->hwif->pdev->dev, "Invalid fault event report, length: %d, should be %zu\n",
in_size, sizeof(*fault_event));
return;
}
if (!hwdev->devlink_dev || IS_ERR_OR_NULL(hwdev->devlink_dev->hw_fault_reporter))
return;
devlink_health_report(hwdev->devlink_dev->hw_fault_reporter,
"HW fatal error reported", &fault_event->event);
}
static void mgmt_watchdog_timeout_event_handler(void *dev,
void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
struct hinic_mgmt_watchdog_info *watchdog_info = buf_in;
struct hinic_hwdev *hwdev = dev;
if (in_size != sizeof(*watchdog_info)) {
dev_err(&hwdev->hwif->pdev->dev, "Invalid mgmt watchdog report, length: %d, should be %zu\n",
in_size, sizeof(*watchdog_info));
return;
}
if (!hwdev->devlink_dev || IS_ERR_OR_NULL(hwdev->devlink_dev->fw_fault_reporter))
return;
devlink_health_report(hwdev->devlink_dev->fw_fault_reporter,
"FW fatal error reported", watchdog_info);
}
/**
* init_pfhwdev - Initialize the extended components of PF
* @pfhwdev: the HW device for PF
......@@ -640,20 +750,37 @@ static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
return err;
}
err = hinic_devlink_register(hwdev->devlink_dev, &pdev->dev);
if (err) {
dev_err(&hwif->pdev->dev, "Failed to register devlink\n");
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
return err;
}
err = hinic_func_to_func_init(hwdev);
if (err) {
dev_err(&hwif->pdev->dev, "Failed to init mailbox\n");
hinic_devlink_unregister(hwdev->devlink_dev);
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
return err;
}
if (!HINIC_IS_VF(hwif))
if (!HINIC_IS_VF(hwif)) {
hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
HINIC_MOD_L2NIC, pfhwdev,
nic_mgmt_msg_handler);
else
hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
pfhwdev, comm_mgmt_msg_handler);
hinic_comm_recv_mgmt_self_cmd_reg(pfhwdev,
HINIC_COMM_CMD_FAULT_REPORT,
pf_fault_event_handler);
hinic_comm_recv_mgmt_self_cmd_reg
(pfhwdev, HINIC_COMM_CMD_WATCHDOG_INFO,
mgmt_watchdog_timeout_event_handler);
} else {
hinic_register_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC,
nic_mgmt_msg_handler);
}
hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE);
......@@ -670,14 +797,23 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT);
if (!HINIC_IS_VF(hwdev->hwif))
if (!HINIC_IS_VF(hwdev->hwif)) {
hinic_comm_recv_mgmt_self_cmd_unreg(pfhwdev,
HINIC_COMM_CMD_WATCHDOG_INFO);
hinic_comm_recv_mgmt_self_cmd_unreg(pfhwdev,
HINIC_COMM_CMD_FAULT_REPORT);
hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
HINIC_MOD_COMM);
hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt,
HINIC_MOD_L2NIC);
else
} else {
hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC);
}
hinic_func_to_func_free(hwdev);
hinic_devlink_unregister(hwdev->devlink_dev);
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
}
......@@ -777,7 +913,7 @@ int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev,
*
* Initialize the NIC HW device and return a pointer to it
**/
struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev, struct devlink *devlink)
{
struct hinic_pfhwdev *pfhwdev;
struct hinic_hwdev *hwdev;
......@@ -802,6 +938,8 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
hwdev = &pfhwdev->hwdev;
hwdev->hwif = hwif;
hwdev->devlink_dev = devlink_priv(devlink);
hwdev->devlink_dev->hwdev = hwdev;
err = init_msix(hwdev);
if (err) {
......
......@@ -10,6 +10,7 @@
#include <linux/pci.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <net/devlink.h>
#include "hinic_hw_if.h"
#include "hinic_hw_eqs.h"
......@@ -164,9 +165,12 @@ enum hinic_ucode_cmd {
#define NIC_RSS_CMD_TEMP_FREE 0x02
enum hinic_mgmt_msg_cmd {
HINIC_MGMT_MSG_CMD_BASE = 160,
HINIC_MGMT_MSG_CMD_BASE = 0xA0,
HINIC_MGMT_MSG_CMD_LINK_STATUS = 160,
HINIC_MGMT_MSG_CMD_LINK_STATUS = 0xA0,
HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT = 0xE5,
HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT = 0xE6,
HINIC_MGMT_MSG_CMD_MAX,
};
......@@ -348,6 +352,7 @@ struct hinic_hwdev {
struct hinic_cap nic_cap;
u8 port_id;
struct hinic_devlink_priv *devlink_dev;
};
struct hinic_nic_cb {
......@@ -359,12 +364,29 @@ struct hinic_nic_cb {
unsigned long cb_state;
};
#define HINIC_COMM_SELF_CMD_MAX 4
typedef void (*comm_mgmt_self_msg_proc)(void *handle, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
struct comm_mgmt_self_msg_sub_info {
u8 cmd;
comm_mgmt_self_msg_proc proc;
};
struct comm_mgmt_self_msg_info {
u8 cmd_num;
struct comm_mgmt_self_msg_sub_info info[HINIC_COMM_SELF_CMD_MAX];
};
struct hinic_pfhwdev {
struct hinic_hwdev hwdev;
struct hinic_pf_to_mgmt pf_to_mgmt;
struct hinic_nic_cb nic_cb[HINIC_MGMT_NUM_MSG_CMD];
struct comm_mgmt_self_msg_info proc;
};
struct hinic_dev_cap {
......@@ -386,6 +408,126 @@ struct hinic_dev_cap {
u8 rsvd3[204];
};
union hinic_fault_hw_mgmt {
u32 val[4];
/* valid only type == FAULT_TYPE_CHIP */
struct {
u8 node_id;
u8 err_level;
u16 err_type;
u32 err_csr_addr;
u32 err_csr_value;
/* func_id valid only if err_level == FAULT_LEVEL_SERIOUS_FLR */
u16 func_id;
u16 rsvd2;
} chip;
/* valid only if type == FAULT_TYPE_UCODE */
struct {
u8 cause_id;
u8 core_id;
u8 c_id;
u8 rsvd3;
u32 epc;
u32 rsvd4;
u32 rsvd5;
} ucode;
/* valid only if type == FAULT_TYPE_MEM_RD_TIMEOUT ||
* FAULT_TYPE_MEM_WR_TIMEOUT
*/
struct {
u32 err_csr_ctrl;
u32 err_csr_data;
u32 ctrl_tab;
u32 mem_index;
} mem_timeout;
/* valid only if type == FAULT_TYPE_REG_RD_TIMEOUT ||
* FAULT_TYPE_REG_WR_TIMEOUT
*/
struct {
u32 err_csr;
u32 rsvd6;
u32 rsvd7;
u32 rsvd8;
} reg_timeout;
struct {
/* 0: read; 1: write */
u8 op_type;
u8 port_id;
u8 dev_ad;
u8 rsvd9;
u32 csr_addr;
u32 op_data;
u32 rsvd10;
} phy_fault;
};
struct hinic_fault_event {
u8 type;
u8 fault_level;
u8 rsvd0[2];
union hinic_fault_hw_mgmt event;
};
struct hinic_cmd_fault_event {
u8 status;
u8 version;
u8 rsvd0[6];
struct hinic_fault_event event;
};
enum hinic_fault_type {
FAULT_TYPE_CHIP,
FAULT_TYPE_UCODE,
FAULT_TYPE_MEM_RD_TIMEOUT,
FAULT_TYPE_MEM_WR_TIMEOUT,
FAULT_TYPE_REG_RD_TIMEOUT,
FAULT_TYPE_REG_WR_TIMEOUT,
FAULT_TYPE_PHY_FAULT,
FAULT_TYPE_MAX,
};
#define FAULT_SHOW_STR_LEN 16
enum hinic_fault_err_level {
FAULT_LEVEL_FATAL,
FAULT_LEVEL_SERIOUS_RESET,
FAULT_LEVEL_SERIOUS_FLR,
FAULT_LEVEL_GENERAL,
FAULT_LEVEL_SUGGESTION,
FAULT_LEVEL_MAX
};
struct hinic_mgmt_watchdog_info {
u8 status;
u8 version;
u8 rsvd0[6];
u32 curr_time_h;
u32 curr_time_l;
u32 task_id;
u32 rsv;
u32 reg[13];
u32 pc;
u32 lr;
u32 cpsr;
u32 stack_top;
u32 stack_bottom;
u32 sp;
u32 curr_used;
u32 peak_used;
u32 is_overflow;
u32 stack_actlen;
u8 data[1024];
};
void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev,
enum hinic_mgmt_msg_cmd cmd, void *handle,
void (*handler)(void *handle, void *buf_in,
......@@ -407,7 +549,7 @@ int hinic_hwdev_ifup(struct hinic_hwdev *hwdev, u16 sq_depth, u16 rq_depth);
void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev);
struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev);
struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev, struct devlink *devlink);
void hinic_free_hwdev(struct hinic_hwdev *hwdev);
......
......@@ -953,3 +953,42 @@ void hinic_ceqs_free(struct hinic_ceqs *ceqs)
for (q_id = 0; q_id < ceqs->num_ceqs; q_id++)
remove_eq(&ceqs->ceq[q_id]);
}
void hinic_dump_ceq_info(struct hinic_hwdev *hwdev)
{
struct hinic_eq *eq = NULL;
u32 addr, ci, pi;
int q_id;
for (q_id = 0; q_id < hwdev->func_to_io.ceqs.num_ceqs; q_id++) {
eq = &hwdev->func_to_io.ceqs.ceq[q_id];
addr = EQ_CONS_IDX_REG_ADDR(eq);
ci = hinic_hwif_read_reg(hwdev->hwif, addr);
addr = EQ_PROD_IDX_REG_ADDR(eq);
pi = hinic_hwif_read_reg(hwdev->hwif, addr);
dev_err(&hwdev->hwif->pdev->dev, "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, tasklet_state: 0x%lx, wrap: %d, ceqe: 0x%x\n",
q_id, ci, eq->cons_idx, pi,
eq->ceq_tasklet.state,
eq->wrapped, be32_to_cpu(*(__be32 *)(GET_CURR_CEQ_ELEM(eq))));
}
}
void hinic_dump_aeq_info(struct hinic_hwdev *hwdev)
{
struct hinic_aeq_elem *aeqe_pos = NULL;
struct hinic_eq *eq = NULL;
u32 addr, ci, pi;
int q_id;
for (q_id = 0; q_id < hwdev->aeqs.num_aeqs; q_id++) {
eq = &hwdev->aeqs.aeq[q_id];
addr = EQ_CONS_IDX_REG_ADDR(eq);
ci = hinic_hwif_read_reg(hwdev->hwif, addr);
addr = EQ_PROD_IDX_REG_ADDR(eq);
pi = hinic_hwif_read_reg(hwdev->hwif, addr);
aeqe_pos = GET_CURR_AEQ_ELEM(eq);
dev_err(&hwdev->hwif->pdev->dev, "Aeq id: %d, ci: 0x%08x, pi: 0x%x, work_state: 0x%x, wrap: %d, desc: 0x%x\n",
q_id, ci, pi, work_busy(&eq->aeq_work.work),
eq->wrapped, be32_to_cpu(aeqe_pos->desc));
}
}
......@@ -162,7 +162,7 @@ enum hinic_eqe_state {
struct hinic_aeq_elem {
u8 data[HINIC_AEQE_DATA_SIZE];
u32 desc;
__be32 desc;
};
struct hinic_eq_work {
......@@ -254,4 +254,8 @@ int hinic_ceqs_init(struct hinic_ceqs *ceqs, struct hinic_hwif *hwif,
void hinic_ceqs_free(struct hinic_ceqs *ceqs);
void hinic_dump_ceq_info(struct hinic_hwdev *hwdev);
void hinic_dump_aeq_info(struct hinic_hwdev *hwdev);
#endif
......@@ -21,6 +21,8 @@
#define WAIT_HWIF_READY_TIMEOUT 10000
#define HINIC_SELFTEST_RESULT 0x883C
/**
* hinic_msix_attr_set - set message attribute for msix entry
* @hwif: the HW interface of a pci function device
......@@ -369,6 +371,26 @@ u16 hinic_pf_id_of_vf_hw(struct hinic_hwif *hwif)
return HINIC_FA0_GET(attr0, PF_IDX);
}
static void __print_selftest_reg(struct hinic_hwif *hwif)
{
u32 addr, attr0, attr1;
addr = HINIC_CSR_FUNC_ATTR1_ADDR;
attr1 = hinic_hwif_read_reg(hwif, addr);
if (attr1 == HINIC_PCIE_LINK_DOWN) {
dev_err(&hwif->pdev->dev, "PCIE is link down\n");
return;
}
addr = HINIC_CSR_FUNC_ATTR0_ADDR;
attr0 = hinic_hwif_read_reg(hwif, addr);
if (HINIC_FA0_GET(attr0, FUNC_TYPE) != HINIC_VF &&
!HINIC_FA0_GET(attr0, PCI_INTF_IDX))
dev_err(&hwif->pdev->dev, "Selftest reg: 0x%08x\n",
hinic_hwif_read_reg(hwif, HINIC_SELFTEST_RESULT));
}
/**
* hinic_init_hwif - initialize the hw interface
* @hwif: the HW interface of a pci function device
......@@ -398,6 +420,7 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
err = wait_hwif_ready(hwif);
if (err) {
dev_err(&pdev->dev, "HW interface is not ready\n");
__print_selftest_reg(hwif);
goto err_hwif_ready;
}
......
......@@ -12,6 +12,8 @@
#include <linux/types.h>
#include <asm/byteorder.h>
#define HINIC_PCIE_LINK_DOWN 0xFFFFFFFF
#define HINIC_DMA_ATTR_ST_SHIFT 0
#define HINIC_DMA_ATTR_AT_SHIFT 8
#define HINIC_DMA_ATTR_PH_SHIFT 10
......@@ -249,13 +251,17 @@ struct hinic_hwif {
static inline u32 hinic_hwif_read_reg(struct hinic_hwif *hwif, u32 reg)
{
return be32_to_cpu(readl(hwif->cfg_regs_bar + reg));
u32 out = readl(hwif->cfg_regs_bar + reg);
return be32_to_cpu(*(__be32 *)&out);
}
static inline void hinic_hwif_write_reg(struct hinic_hwif *hwif, u32 reg,
u32 val)
{
writel(cpu_to_be32(val), hwif->cfg_regs_bar + reg);
__be32 in = cpu_to_be32(val);
writel(*(u32 *)&in, hwif->cfg_regs_bar + reg);
}
int hinic_msix_attr_set(struct hinic_hwif *hwif, u16 msix_index,
......
......@@ -650,6 +650,7 @@ wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func *func_to_func,
if (!wait_for_completion_timeout(done, jif)) {
dev_err(&hwdev->hwif->pdev->dev, "Send mailbox segment timeout\n");
dump_mox_reg(hwdev);
hinic_dump_aeq_info(hwdev);
return -ETIMEDOUT;
}
......@@ -897,6 +898,7 @@ int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
set_mbox_to_func_event(func_to_func, EVENT_TIMEOUT);
dev_err(&func_to_func->hwif->pdev->dev,
"Send mbox msg timeout, msg_id: %d\n", msg_info.msg_id);
hinic_dump_aeq_info(func_to_func->hwdev);
err = -ETIMEDOUT;
goto err_send_mbox;
}
......
......@@ -12,8 +12,10 @@
#include <linux/semaphore.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <net/devlink.h>
#include <asm/barrier.h>
#include "hinic_devlink.h"
#include "hinic_hw_if.h"
#include "hinic_hw_eqs.h"
#include "hinic_hw_api_cmd.h"
......@@ -274,6 +276,7 @@ static int msg_to_mgmt_sync(struct hinic_pf_to_mgmt *pf_to_mgmt,
if (!wait_for_completion_timeout(recv_done, timeo)) {
dev_err(&pdev->dev, "MGMT timeout, MSG id = %d\n", msg_id);
hinic_dump_aeq_info(pf_to_mgmt->hwdev);
err = -ETIMEDOUT;
goto unlock_sync_msg;
}
......@@ -617,10 +620,15 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
if (HINIC_IS_VF(hwif))
return 0;
err = hinic_health_reporters_create(hwdev->devlink_dev);
if (err)
return err;
sema_init(&pf_to_mgmt->sync_msg_lock, 1);
pf_to_mgmt->workq = create_singlethread_workqueue("hinic_mgmt");
if (!pf_to_mgmt->workq) {
dev_err(&pdev->dev, "Failed to initialize MGMT workqueue\n");
hinic_health_reporters_destroy(hwdev->devlink_dev);
return -ENOMEM;
}
pf_to_mgmt->sync_msg_id = 0;
......@@ -628,12 +636,14 @@ int hinic_pf_to_mgmt_init(struct hinic_pf_to_mgmt *pf_to_mgmt,
err = alloc_msg_buf(pf_to_mgmt);
if (err) {
dev_err(&pdev->dev, "Failed to allocate msg buffers\n");
hinic_health_reporters_destroy(hwdev->devlink_dev);
return err;
}
err = hinic_api_cmd_init(pf_to_mgmt->cmd_chain, hwif);
if (err) {
dev_err(&pdev->dev, "Failed to initialize cmd chains\n");
hinic_health_reporters_destroy(hwdev->devlink_dev);
return err;
}
......@@ -658,4 +668,5 @@ void hinic_pf_to_mgmt_free(struct hinic_pf_to_mgmt *pf_to_mgmt)
hinic_aeq_unregister_hw_cb(&hwdev->aeqs, HINIC_MSG_FROM_MGMT_CPU);
hinic_api_cmd_free(pf_to_mgmt->cmd_chain);
destroy_workqueue(pf_to_mgmt->workq);
hinic_health_reporters_destroy(hwdev->devlink_dev);
}
......@@ -81,6 +81,8 @@ enum hinic_comm_cmd {
HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP,
HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP,
HINIC_COMM_CMD_FAULT_REPORT = 0x37,
HINIC_COMM_CMD_SET_LED_STATUS = 0x4a,
HINIC_COMM_CMD_L2NIC_RESET = 0x4b,
......@@ -89,6 +91,8 @@ enum hinic_comm_cmd {
HINIC_COMM_CMD_GET_BOARD_INFO = 0x52,
HINIC_COMM_CMD_WATCHDOG_INFO = 0x56,
HINIC_COMM_CMD_MAX,
};
......
......@@ -444,8 +444,11 @@ int hinic_open(struct net_device *netdev)
if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
hinic_notify_all_vfs_link_changed(nic_dev->hwdev, link_state);
if (link_state == HINIC_LINK_STATE_UP)
if (link_state == HINIC_LINK_STATE_UP) {
nic_dev->flags |= HINIC_LINK_UP;
nic_dev->cable_unplugged = false;
nic_dev->module_unrecognized = false;
}
nic_dev->flags |= HINIC_INTF_UP;
......@@ -935,6 +938,8 @@ static void link_status_event_handler(void *handle, void *buf_in, u16 in_size,
down(&nic_dev->mgmt_lock);
nic_dev->flags |= HINIC_LINK_UP;
nic_dev->cable_unplugged = false;
nic_dev->module_unrecognized = false;
if ((nic_dev->flags & (HINIC_LINK_UP | HINIC_INTF_UP)) ==
(HINIC_LINK_UP | HINIC_INTF_UP)) {
......@@ -971,6 +976,39 @@ static void link_status_event_handler(void *handle, void *buf_in, u16 in_size,
*out_size = sizeof(*ret_link_status);
}
static void cable_plug_event(void *handle,
void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
struct hinic_cable_plug_event *plug_event = buf_in;
struct hinic_dev *nic_dev = handle;
nic_dev->cable_unplugged = plug_event->plugged ? false : true;
*out_size = sizeof(*plug_event);
plug_event = buf_out;
plug_event->status = 0;
}
static void link_err_event(void *handle,
void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
struct hinic_link_err_event *link_err = buf_in;
struct hinic_dev *nic_dev = handle;
if (link_err->err_type >= LINK_ERR_NUM)
netif_info(nic_dev, link, nic_dev->netdev,
"Link failed, Unknown error type: 0x%x\n",
link_err->err_type);
else
nic_dev->module_unrecognized = true;
*out_size = sizeof(*link_err);
link_err = buf_out;
link_err->status = 0;
}
static int set_features(struct hinic_dev *nic_dev,
netdev_features_t pre_features,
netdev_features_t features, bool force_change)
......@@ -1077,28 +1115,24 @@ static int nic_dev_init(struct pci_dev *pdev)
struct hinic_rx_mode_work *rx_mode_work;
struct hinic_txq_stats *tx_stats;
struct hinic_rxq_stats *rx_stats;
struct hinic_devlink_priv *priv;
struct hinic_dev *nic_dev;
struct net_device *netdev;
struct hinic_hwdev *hwdev;
struct devlink *devlink;
int err, num_qps;
hwdev = hinic_init_hwdev(pdev);
if (IS_ERR(hwdev)) {
dev_err(&pdev->dev, "Failed to initialize HW device\n");
return PTR_ERR(hwdev);
}
devlink = hinic_devlink_alloc();
if (!devlink) {
dev_err(&pdev->dev, "Hinic devlink alloc failed\n");
err = -ENOMEM;
goto err_devlink_alloc;
return -ENOMEM;
}
priv = devlink_priv(devlink);
priv->hwdev = hwdev;
hwdev = hinic_init_hwdev(pdev, devlink);
if (IS_ERR(hwdev)) {
dev_err(&pdev->dev, "Failed to initialize HW device\n");
hinic_devlink_free(devlink);
return PTR_ERR(hwdev);
}
num_qps = hinic_hwdev_num_qps(hwdev);
if (num_qps <= 0) {
......@@ -1161,10 +1195,6 @@ static int nic_dev_init(struct pci_dev *pdev)
goto err_workq;
}
err = hinic_devlink_register(devlink, &pdev->dev);
if (err)
goto err_devlink_reg;
pci_set_drvdata(pdev, netdev);
err = hinic_port_get_mac(nic_dev, netdev->dev_addr);
......@@ -1206,6 +1236,12 @@ static int nic_dev_init(struct pci_dev *pdev)
hinic_hwdev_cb_register(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS,
nic_dev, link_status_event_handler);
hinic_hwdev_cb_register(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT,
nic_dev, cable_plug_event);
hinic_hwdev_cb_register(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT,
nic_dev, link_err_event);
err = set_features(nic_dev, 0, nic_dev->netdev->features, true);
if (err)
......@@ -1237,6 +1273,10 @@ static int nic_dev_init(struct pci_dev *pdev)
err_init_intr:
err_set_pfc:
err_set_features:
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT);
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT);
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_LINK_STATUS);
cancel_work_sync(&rx_mode_work->work);
......@@ -1246,17 +1286,15 @@ static int nic_dev_init(struct pci_dev *pdev)
err_add_mac:
err_get_mac:
pci_set_drvdata(pdev, NULL);
err_devlink_reg:
destroy_workqueue(nic_dev->workq);
err_workq:
err_vlan_bitmap:
free_netdev(netdev);
err_alloc_etherdev:
err_num_qps:
err_devlink_alloc:
hinic_free_hwdev(hwdev);
hinic_devlink_free(devlink);
return err;
}
......@@ -1343,6 +1381,7 @@ static void hinic_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct hinic_dev *nic_dev = netdev_priv(netdev);
struct devlink *devlink = nic_dev->devlink;
struct hinic_rx_mode_work *rx_mode_work;
if (!HINIC_IS_VF(nic_dev->hwdev->hwif)) {
......@@ -1356,6 +1395,10 @@ static void hinic_remove(struct pci_dev *pdev)
hinic_port_del_mac(nic_dev, netdev->dev_addr, 0);
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_LINK_ERR_EVENT);
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_CABLE_PLUG_EVENT);
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_LINK_STATUS);
......@@ -1364,16 +1407,14 @@ static void hinic_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
hinic_devlink_unregister(nic_dev->devlink);
destroy_workqueue(nic_dev->workq);
hinic_devlink_free(nic_dev->devlink);
hinic_free_hwdev(nic_dev->hwdev);
free_netdev(netdev);
hinic_devlink_free(devlink);
pci_release_regions(pdev);
pci_disable_device(pdev);
......
......@@ -61,8 +61,8 @@ static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
(port_mac_cmd.status &&
port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY &&
port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
port_mac_cmd.status);
dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
err, port_mac_cmd.status, out_size);
return -EFAULT;
}
......@@ -129,8 +129,8 @@ int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
&port_mac_cmd, sizeof(port_mac_cmd),
&port_mac_cmd, &out_size);
if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
port_mac_cmd.status);
dev_err(&pdev->dev, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",
err, port_mac_cmd.status, out_size);
return -EFAULT;
}
......@@ -172,9 +172,9 @@ int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
&port_mtu_cmd, sizeof(port_mtu_cmd),
&port_mtu_cmd, &out_size);
if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
port_mtu_cmd.status);
if (err || out_size != sizeof(port_mtu_cmd) || port_mtu_cmd.status) {
dev_err(&pdev->dev, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x\n",
err, port_mtu_cmd.status, out_size);
return -EFAULT;
}
......@@ -264,8 +264,8 @@ int hinic_port_link_state(struct hinic_dev *nic_dev,
&link_cmd, sizeof(link_cmd),
&link_cmd, &out_size);
if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
link_cmd.status);
dev_err(&pdev->dev, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n",
err, link_cmd.status, out_size);
return -EINVAL;
}
......@@ -298,8 +298,8 @@ int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
&port_state, sizeof(port_state),
&port_state, &out_size);
if (err || (out_size != sizeof(port_state)) || port_state.status) {
dev_err(&pdev->dev, "Failed to set port state, ret = %d\n",
port_state.status);
dev_err(&pdev->dev, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x\n",
err, port_state.status, out_size);
return -EFAULT;
}
......@@ -330,8 +330,8 @@ int hinic_port_set_func_state(struct hinic_dev *nic_dev,
&func_state, sizeof(func_state),
&func_state, &out_size);
if (err || (out_size != sizeof(func_state)) || func_state.status) {
dev_err(&pdev->dev, "Failed to set port func state, ret = %d\n",
func_state.status);
dev_err(&pdev->dev, "Failed to set port func state, err: %d, status: 0x%x, out size: 0x%x\n",
err, func_state.status, out_size);
return -EFAULT;
}
......@@ -361,9 +361,9 @@ int hinic_port_get_cap(struct hinic_dev *nic_dev,
port_cap, &out_size);
if (err || (out_size != sizeof(*port_cap)) || port_cap->status) {
dev_err(&pdev->dev,
"Failed to get port capabilities, ret = %d\n",
port_cap->status);
return -EINVAL;
"Failed to get port capabilities, err: %d, status: 0x%x, out size: 0x%x\n",
err, port_cap->status, out_size);
return -EIO;
}
return 0;
......@@ -393,9 +393,9 @@ int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
&tso_cfg, &out_size);
if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {
dev_err(&pdev->dev,
"Failed to set port tso, ret = %d\n",
tso_cfg.status);
return -EINVAL;
"Failed to set port tso, err: %d, status: 0x%x, out size: 0x%x\n",
err, tso_cfg.status, out_size);
return -EIO;
}
return 0;
......@@ -423,9 +423,9 @@ int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
&rx_csum_cfg, &out_size);
if (err || !out_size || rx_csum_cfg.status) {
dev_err(&pdev->dev,
"Failed to set rx csum offload, ret = %d\n",
rx_csum_cfg.status);
return -EINVAL;
"Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x\n",
err, rx_csum_cfg.status, out_size);
return -EIO;
}
return 0;
......@@ -480,9 +480,9 @@ int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
&rq_num, &out_size);
if (err || !out_size || rq_num.status) {
dev_err(&pdev->dev,
"Failed to rxq number, ret = %d\n",
rq_num.status);
return -EINVAL;
"Failed to set rxq number, err: %d, status: 0x%x, out size: 0x%x\n",
err, rq_num.status, out_size);
return -EIO;
}
return 0;
......@@ -508,9 +508,9 @@ static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
&lro_cfg, &out_size);
if (err || !out_size || lro_cfg.status) {
dev_err(&pdev->dev,
"Failed to set lro offload, ret = %d\n",
lro_cfg.status);
return -EINVAL;
"Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n",
err, lro_cfg.status, out_size);
return -EIO;
}
return 0;
......@@ -542,10 +542,10 @@ static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
if (err || !out_size || lro_timer.status) {
dev_err(&pdev->dev,
"Failed to set lro timer, ret = %d\n",
lro_timer.status);
"Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n",
err, lro_timer.status, out_size);
return -EINVAL;
return -EIO;
}
return 0;
......
......@@ -189,6 +189,31 @@ struct hinic_port_link_status {
u8 port_id;
};
struct hinic_cable_plug_event {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u8 plugged; /* 0: unplugged, 1: plugged */
u8 port_id;
};
enum link_err_type {
LINK_ERR_MODULE_UNRECOGENIZED,
LINK_ERR_NUM,
};
struct hinic_link_err_event {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u8 err_type;
u8 port_id;
};
struct hinic_port_func_state_cmd {
u8 status;
u8 version;
......
......@@ -40,9 +40,9 @@ static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
if (err || out_size != sizeof(mac_info) ||
(mac_info.status && mac_info.status != HINIC_PF_SET_VF_ALREADY &&
mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to change MAC, ret = %d\n",
mac_info.status);
return -EFAULT;
dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",
err, mac_info.status, out_size);
return -EIO;
}
return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment