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
/* 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;
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;
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) & \
spin_unlock_bh(&cmdq->cmdq_lock);
+ hinic_dump_ceq_info(cmdq->hwdev);
return -ETIMEDOUT;
}
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]);
};
struct hinic_cmdq {
+ struct hinic_hwdev *hwdev;
+
struct hinic_wq *wq;
enum hinic_cmdq_type cmdq_type;
&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;
&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;
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));
+ }
+}
struct hinic_aeq_elem {
u8 data[HINIC_AEQE_DATA_SIZE];
- u32 desc;
+ __be32 desc;
};
struct hinic_eq_work {
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
#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
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
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;
}
#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
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,
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;
}
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;
}
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;
}
(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;
}
&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;
}
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;
}
&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;
}
&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;
}
&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;
}
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;
&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;
&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;
&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;
&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;
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;
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;