mirror of
https://github.com/torvalds/linux.git
synced 2026-05-25 07:33:19 +02:00
hinic3: Add command queue detailed-response interfaces
Add new detailed response interfaces for the hinic3 command queue (CMDQ), enhancing its functionality to handle commands requiring input and output buffer pairs. Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com> Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com> Signed-off-by: Fan Gong <gongfan1@huawei.com> Link: https://patch.msgid.link/cc3cff8458aeb27b07749dc9dcee43c11c45a4c1.1773062356.git.zhuyikai1@h-partners.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
0de607dc4f
commit
15b5be9389
|
|
@ -61,6 +61,10 @@
|
|||
#define CMDQ_DB_HEAD_SET(val, member) \
|
||||
FIELD_PREP(CMDQ_DB_HEAD_##member##_MASK, val)
|
||||
|
||||
#define SAVED_DATA_ARM_MASK BIT(31)
|
||||
#define SAVED_DATA_SET(val, member) \
|
||||
FIELD_PREP(SAVED_DATA_##member##_MASK, val)
|
||||
|
||||
#define CMDQ_CEQE_TYPE_MASK GENMASK(2, 0)
|
||||
#define CMDQ_CEQE_GET(val, member) \
|
||||
FIELD_GET(CMDQ_CEQE_##member##_MASK, le32_to_cpu(val))
|
||||
|
|
@ -84,6 +88,10 @@ enum cmdq_data_format {
|
|||
CMDQ_DATA_DIRECT = 1,
|
||||
};
|
||||
|
||||
enum cmdq_scmd_type {
|
||||
CMDQ_SET_ARM_CMD = 2,
|
||||
};
|
||||
|
||||
enum cmdq_ctrl_sect_len {
|
||||
CMDQ_CTRL_SECT_LEN = 1,
|
||||
CMDQ_CTRL_DIRECT_SECT_LEN = 2,
|
||||
|
|
@ -166,6 +174,11 @@ static void cmdq_clear_cmd_buf(struct hinic3_cmdq_cmd_info *cmd_info,
|
|||
hinic3_free_cmd_buf(hwdev, cmd_info->buf_in);
|
||||
cmd_info->buf_in = NULL;
|
||||
}
|
||||
|
||||
if (cmd_info->buf_out) {
|
||||
hinic3_free_cmd_buf(hwdev, cmd_info->buf_out);
|
||||
cmd_info->buf_out = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_wqe_complete_bit(struct hinic3_cmdq *cmdq,
|
||||
|
|
@ -189,6 +202,20 @@ static void clear_wqe_complete_bit(struct hinic3_cmdq *cmdq,
|
|||
hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS);
|
||||
}
|
||||
|
||||
static int cmdq_arm_ceq_handler(struct hinic3_cmdq *cmdq,
|
||||
struct cmdq_wqe *wqe, u16 ci)
|
||||
{
|
||||
struct cmdq_ctrl *ctrl = &wqe->wqe_scmd.ctrl;
|
||||
__le32 ctrl_info = ctrl->ctrl_info;
|
||||
|
||||
if (!CMDQ_WQE_COMPLETED(ctrl_info))
|
||||
return -EBUSY;
|
||||
|
||||
clear_wqe_complete_bit(cmdq, wqe, ci);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cmdq_update_cmd_status(struct hinic3_cmdq *cmdq, u16 prod_idx,
|
||||
struct cmdq_wqe *wqe)
|
||||
{
|
||||
|
|
@ -257,6 +284,11 @@ void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev, __le32 ceqe_data)
|
|||
cmdq_clear_cmd_buf(cmd_info, hwdev);
|
||||
clear_wqe_complete_bit(cmdq, wqe, ci);
|
||||
break;
|
||||
case HINIC3_CMD_TYPE_SET_ARM:
|
||||
/* arm_bit was set until here */
|
||||
if (cmdq_arm_ceq_handler(cmdq, wqe, ci))
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
/* only arm bit is using scmd wqe,
|
||||
* the other wqe is lcmd
|
||||
|
|
@ -283,6 +315,18 @@ void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev, __le32 ceqe_data)
|
|||
}
|
||||
}
|
||||
|
||||
static int cmdq_params_valid(const struct hinic3_hwdev *hwdev,
|
||||
const struct hinic3_cmd_buf *buf_in)
|
||||
{
|
||||
if (le16_to_cpu(buf_in->size) > CMDQ_BUF_SIZE) {
|
||||
dev_err(hwdev->dev, "Invalid CMDQ buffer size: 0x%x\n",
|
||||
le16_to_cpu(buf_in->size));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs)
|
||||
{
|
||||
unsigned long end;
|
||||
|
|
@ -356,6 +400,7 @@ static void cmdq_prepare_wqe_ctrl(struct cmdq_wqe *wqe, u8 wrapped,
|
|||
enum cmdq_bufdesc_len buf_len)
|
||||
{
|
||||
struct cmdq_header *hdr = CMDQ_WQE_HEADER(wqe);
|
||||
__le32 saved_data = hdr->saved_data;
|
||||
enum cmdq_ctrl_sect_len ctrl_len;
|
||||
struct cmdq_wqe_lcmd *wqe_lcmd;
|
||||
struct cmdq_wqe_scmd *wqe_scmd;
|
||||
|
|
@ -386,6 +431,11 @@ static void cmdq_prepare_wqe_ctrl(struct cmdq_wqe *wqe, u8 wrapped,
|
|||
CMDQ_WQE_HDR_SET(3, COMPLETE_SECT_LEN) |
|
||||
CMDQ_WQE_HDR_SET(ctrl_len, CTRL_LEN) |
|
||||
CMDQ_WQE_HDR_SET(wrapped, HW_BUSY_BIT));
|
||||
|
||||
saved_data &= ~cpu_to_le32(SAVED_DATA_ARM_MASK);
|
||||
if (cmd == CMDQ_SET_ARM_CMD && mod == MGMT_MOD_COMM)
|
||||
saved_data |= cpu_to_le32(SAVED_DATA_SET(1, ARM));
|
||||
hdr->saved_data = saved_data;
|
||||
}
|
||||
|
||||
static void cmdq_set_lcmd_wqe(struct cmdq_wqe *wqe,
|
||||
|
|
@ -488,9 +538,10 @@ static int wait_cmdq_sync_cmd_completion(struct hinic3_cmdq *cmdq,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in,
|
||||
__le64 *out_param)
|
||||
static int cmdq_sync_cmd_exec(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in,
|
||||
struct hinic3_cmd_buf *buf_out,
|
||||
__le64 *out_param, u8 cmd_type, u8 wqe_cmd)
|
||||
{
|
||||
struct hinic3_cmdq_cmd_info *cmd_info, saved_cmd_info;
|
||||
int cmpt_code = CMDQ_SEND_CMPT_CODE;
|
||||
|
|
@ -520,31 +571,35 @@ static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
|
|||
cmd_info = &cmdq->cmd_infos[curr_prod_idx];
|
||||
init_completion(&done);
|
||||
refcount_inc(&buf_in->ref_cnt);
|
||||
cmd_info->cmd_type = HINIC3_CMD_TYPE_DIRECT_RESP;
|
||||
if (buf_out)
|
||||
refcount_inc(&buf_out->ref_cnt);
|
||||
|
||||
cmd_info->cmd_type = cmd_type;
|
||||
cmd_info->done = &done;
|
||||
cmd_info->errcode = &errcode;
|
||||
cmd_info->direct_resp = out_param;
|
||||
cmd_info->cmpt_code = &cmpt_code;
|
||||
cmd_info->buf_in = buf_in;
|
||||
if (buf_out)
|
||||
cmd_info->buf_out = buf_out;
|
||||
|
||||
saved_cmd_info = *cmd_info;
|
||||
cmdq_set_lcmd_wqe(&wqe, CMDQ_CMD_DIRECT_RESP, buf_in, NULL,
|
||||
cmdq_set_lcmd_wqe(&wqe, wqe_cmd, buf_in, buf_out,
|
||||
wrapped, mod, cmd, curr_prod_idx);
|
||||
|
||||
cmdq_wqe_fill(curr_wqe, &wqe);
|
||||
(cmd_info->cmdq_msg_id)++;
|
||||
curr_msg_id = cmd_info->cmdq_msg_id;
|
||||
cmdq_set_db(cmdq, HINIC3_CMDQ_SYNC, next_prod_idx);
|
||||
cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx);
|
||||
spin_unlock_bh(&cmdq->cmdq_lock);
|
||||
|
||||
err = wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info,
|
||||
curr_msg_id, curr_prod_idx,
|
||||
curr_wqe, CMDQ_CMD_TIMEOUT);
|
||||
if (err) {
|
||||
if (err)
|
||||
dev_err(cmdq->hwdev->dev,
|
||||
"Cmdq sync command timeout, mod: %u, cmd: %u, prod idx: 0x%x\n",
|
||||
mod, cmd, curr_prod_idx);
|
||||
err = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
if (cmpt_code == CMDQ_FORCE_STOP_CMPT_CODE) {
|
||||
dev_dbg(cmdq->hwdev->dev,
|
||||
|
|
@ -557,22 +612,107 @@ static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
|
|||
return err ? err : errcode;
|
||||
}
|
||||
|
||||
static int cmdq_sync_cmd_direct_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in,
|
||||
__le64 *out_param)
|
||||
{
|
||||
return cmdq_sync_cmd_exec(cmdq, mod, cmd, buf_in, NULL, out_param,
|
||||
HINIC3_CMD_TYPE_DIRECT_RESP,
|
||||
CMDQ_CMD_DIRECT_RESP);
|
||||
}
|
||||
|
||||
static int cmdq_sync_cmd_detail_resp(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in,
|
||||
struct hinic3_cmd_buf *buf_out,
|
||||
__le64 *out_param)
|
||||
{
|
||||
return cmdq_sync_cmd_exec(cmdq, mod, cmd, buf_in, buf_out, out_param,
|
||||
HINIC3_CMD_TYPE_SGE_RESP,
|
||||
CMDQ_CMD_SGE_RESP);
|
||||
}
|
||||
|
||||
int hinic3_cmd_buf_pair_init(struct hinic3_hwdev *hwdev,
|
||||
struct hinic3_cmd_buf_pair *pair)
|
||||
{
|
||||
pair->in = hinic3_alloc_cmd_buf(hwdev);
|
||||
if (!pair->in)
|
||||
goto err_out;
|
||||
|
||||
pair->out = hinic3_alloc_cmd_buf(hwdev);
|
||||
if (!pair->out)
|
||||
goto err_free_cmd_buf_in;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_cmd_buf_in:
|
||||
hinic3_free_cmd_buf(hwdev, pair->in);
|
||||
err_out:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void hinic3_cmd_buf_pair_uninit(struct hinic3_hwdev *hwdev,
|
||||
struct hinic3_cmd_buf_pair *pair)
|
||||
{
|
||||
hinic3_free_cmd_buf(hwdev, pair->in);
|
||||
hinic3_free_cmd_buf(hwdev, pair->out);
|
||||
}
|
||||
|
||||
int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in, __le64 *out_param)
|
||||
{
|
||||
struct hinic3_cmdqs *cmdqs;
|
||||
int err;
|
||||
err = cmdq_params_valid(hwdev, buf_in);
|
||||
if (err) {
|
||||
dev_err(hwdev->dev, "Invalid CMDQ parameters\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
cmdqs = hwdev->cmdqs;
|
||||
err = wait_cmdqs_enable(cmdqs);
|
||||
if (err) {
|
||||
dev_err(hwdev->dev, "Cmdq is disabled\n");
|
||||
return err;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
err = cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC],
|
||||
mod, cmd, buf_in, out_param);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in,
|
||||
struct hinic3_cmd_buf *buf_out, __le64 *out_param)
|
||||
{
|
||||
struct hinic3_cmdqs *cmdqs;
|
||||
int err;
|
||||
|
||||
err = cmdq_params_valid(hwdev, buf_in);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
cmdqs = hwdev->cmdqs;
|
||||
|
||||
err = wait_cmdqs_enable(cmdqs);
|
||||
if (err) {
|
||||
dev_err(hwdev->dev, "Cmdq is disabled\n");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
err = cmdq_sync_cmd_detail_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC],
|
||||
mod, cmd, buf_in, buf_out, out_param);
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -758,7 +898,8 @@ static int init_cmdqs(struct hinic3_hwdev *hwdev)
|
|||
|
||||
static void cmdq_flush_sync_cmd(struct hinic3_cmdq_cmd_info *cmd_info)
|
||||
{
|
||||
if (cmd_info->cmd_type != HINIC3_CMD_TYPE_DIRECT_RESP)
|
||||
if (cmd_info->cmd_type != HINIC3_CMD_TYPE_DIRECT_RESP &&
|
||||
cmd_info->cmd_type != HINIC3_CMD_TYPE_SGE_RESP)
|
||||
return;
|
||||
|
||||
cmd_info->cmd_type = HINIC3_CMD_TYPE_FORCE_STOP;
|
||||
|
|
@ -785,7 +926,8 @@ static void hinic3_cmdq_flush_cmd(struct hinic3_cmdq *cmdq)
|
|||
while (cmdq_read_wqe(&cmdq->wq, &ci)) {
|
||||
hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS);
|
||||
cmd_info = &cmdq->cmd_infos[ci];
|
||||
if (cmd_info->cmd_type == HINIC3_CMD_TYPE_DIRECT_RESP)
|
||||
if (cmd_info->cmd_type == HINIC3_CMD_TYPE_DIRECT_RESP ||
|
||||
cmd_info->cmd_type == HINIC3_CMD_TYPE_SGE_RESP)
|
||||
cmdq_flush_sync_cmd(cmd_info);
|
||||
}
|
||||
spin_unlock_bh(&cmdq->cmdq_lock);
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ enum hinic3_cmdq_status {
|
|||
|
||||
enum hinic3_cmdq_cmd_type {
|
||||
HINIC3_CMD_TYPE_NONE,
|
||||
HINIC3_CMD_TYPE_SET_ARM,
|
||||
HINIC3_CMD_TYPE_DIRECT_RESP,
|
||||
HINIC3_CMD_TYPE_SGE_RESP,
|
||||
HINIC3_CMD_TYPE_FAKE_TIMEOUT,
|
||||
HINIC3_CMD_TYPE_TIMEOUT,
|
||||
HINIC3_CMD_TYPE_FORCE_STOP,
|
||||
|
|
@ -98,6 +100,11 @@ struct hinic3_cmd_buf {
|
|||
refcount_t ref_cnt;
|
||||
};
|
||||
|
||||
struct hinic3_cmd_buf_pair {
|
||||
struct hinic3_cmd_buf *in;
|
||||
struct hinic3_cmd_buf *out;
|
||||
};
|
||||
|
||||
struct hinic3_cmdq_cmd_info {
|
||||
enum hinic3_cmdq_cmd_type cmd_type;
|
||||
struct completion *done;
|
||||
|
|
@ -107,6 +114,7 @@ struct hinic3_cmdq_cmd_info {
|
|||
__le64 *direct_resp;
|
||||
u64 cmdq_msg_id;
|
||||
struct hinic3_cmd_buf *buf_in;
|
||||
struct hinic3_cmd_buf *buf_out;
|
||||
};
|
||||
|
||||
struct hinic3_cmdq {
|
||||
|
|
@ -146,8 +154,15 @@ void hinic3_free_cmd_buf(struct hinic3_hwdev *hwdev,
|
|||
struct hinic3_cmd_buf *cmd_buf);
|
||||
void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev, __le32 ceqe_data);
|
||||
|
||||
int hinic3_cmd_buf_pair_init(struct hinic3_hwdev *hwdev,
|
||||
struct hinic3_cmd_buf_pair *pair);
|
||||
void hinic3_cmd_buf_pair_uninit(struct hinic3_hwdev *hwdev,
|
||||
struct hinic3_cmd_buf_pair *pair);
|
||||
int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in, __le64 *out_param);
|
||||
int hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd,
|
||||
struct hinic3_cmd_buf *buf_in,
|
||||
struct hinic3_cmd_buf *buf_out, __le64 *out_param);
|
||||
|
||||
void hinic3_cmdq_flush_sync_cmd(struct hinic3_hwdev *hwdev);
|
||||
int hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user