From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFDC239C639; Tue, 24 Feb 2026 13:16:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938972; cv=none; b=PmZUv5br8NCM7ewEMef6td6mV5pOQtPmmQn+1TJ+rGC0JnJfx6zmmySqBo0Lfl4b+B1iixlIm4twxgYFieJOdGEwG9xsXMMOdmGbNjyCkQ5oMmWFX6fjCUdEAp3QAnH5RGsI2yolZXOP3Q/u+3e938uPDhj5Ni2mYkSB0aGn0Ds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938972; c=relaxed/simple; bh=DNNsj4h8iSHXDowtO7siaDjckAZ+yivZns1553XB9nQ=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=oNG2EWb4syOVqYhTeAyTblasPa8UBJqnkVu+0dOiP9jKJvF4+18tnyOKWGj45gDE1Ev2zGcl5akMNUQgc1yAZvbFJgYjLcnka+sRlizdmNIAG4fd+Y9QKu8fCfjbl6iZPfNWdHbzhH8FajitlSItfhirK84Ks/+isxyZIfI/geE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=4Vir9xgD; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="4Vir9xgD" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=rk8G/nJP/MbOl67IiITZ+A0965i7v1i3XlRY7V0eltU=; b=4Vir9xgDNssr6uDZmH4Q8J96a4HH4rX4VyyiWvv4gF/+7NFYIjE5yplI14jtOtQmGAtYTd/1X riHTwCcjPO5H2I6QsPiKv8X+j63anHTatNizo8jHdYmS1xGbxTY8OUL+jqPxDu3lDfeyGwrXp0x oTOIbfGDLgv8wHj6zOkgp/w= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4fKylq3Qlsz1cyPh; Tue, 24 Feb 2026 21:11:19 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 87EF04055B; Tue, 24 Feb 2026 21:16:05 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:04 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 01/15] hinic3: Add command queue detailed-respone interfaces Date: Tue, 24 Feb 2026 21:15:38 +0800 Message-ID: <6bc8e54b0af927048e58555e73219e176fb7b860.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../net/ethernet/huawei/hinic3/hinic3_cmdq.c | 196 +++++++++++++++++- .../net/ethernet/huawei/hinic3/hinic3_cmdq.h | 15 ++ 2 files changed, 209 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_cmdq.c index 86720bb119e9..15c9aa247bae 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c @@ -61,6 +61,10 @@ #define CMDQ_DB_HEAD_SET(val, member) \ FIELD_PREP(CMDQ_DB_HEAD_##member##_MASK, val) =20 +#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 =3D 1, }; =20 +enum cmdq_scmd_type { + CMDQ_SET_ARM_CMD =3D 2, +}; + enum cmdq_ctrl_sect_len { CMDQ_CTRL_SECT_LEN =3D 1, CMDQ_CTRL_DIRECT_SECT_LEN =3D 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 =3D NULL; } + + if (cmd_info->buf_out) { + hinic3_free_cmd_buf(hwdev, cmd_info->buf_out); + cmd_info->buf_out =3D NULL; + } } =20 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); } =20 +static int cmdq_arm_ceq_handler(struct hinic3_cmdq *cmdq, + struct cmdq_wqe *wqe, u16 ci) +{ + struct cmdq_ctrl *ctrl =3D &wqe->wqe_scmd.ctrl; + __le32 ctrl_info =3D 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 *hwde= v, __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 *hwde= v, __le32 ceqe_data) } } =20 +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", + 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 =3D CMDQ_WQE_HEADER(wqe); + __le32 saved_data =3D 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 &=3D ~cpu_to_le32(SAVED_DATA_ARM_MASK); + if (cmd =3D=3D CMDQ_SET_ARM_CMD && mod =3D=3D MGMT_MOD_COMM) + saved_data |=3D cpu_to_le32(SAVED_DATA_SET(1, ARM)); + hdr->saved_data =3D saved_data; } =20 static void cmdq_set_lcmd_wqe(struct cmdq_wqe *wqe, @@ -557,11 +607,118 @@ static int cmdq_sync_cmd_direct_resp(struct hinic3_c= mdq *cmdq, u8 mod, u8 cmd, return err ? err : errcode; } =20 +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) +{ + struct hinic3_cmdq_cmd_info *cmd_info, saved_cmd_info; + struct cmdq_wqe *curr_wqe, wqe =3D {}; + int cmpt_code =3D CMDQ_SEND_CMPT_CODE; + struct hinic3_wq *wq =3D &cmdq->wq; + u16 curr_prod_idx, next_prod_idx; + struct completion done; + u64 curr_msg_id; + int errcode; + u8 wrapped; + int err; + + spin_lock_bh(&cmdq->cmdq_lock); + curr_wqe =3D cmdq_get_wqe(wq, &curr_prod_idx); + if (!curr_wqe) { + spin_unlock_bh(&cmdq->cmdq_lock); + return -EBUSY; + } + + wrapped =3D cmdq->wrapped; + + next_prod_idx =3D curr_prod_idx + CMDQ_WQE_NUM_WQEBBS; + if (next_prod_idx >=3D wq->q_depth) { + cmdq->wrapped ^=3D 1; + next_prod_idx -=3D wq->q_depth; + } + + cmd_info =3D &cmdq->cmd_infos[curr_prod_idx]; + + init_completion(&done); + refcount_inc(&buf_in->ref_cnt); + refcount_inc(&buf_out->ref_cnt); + cmd_info->cmd_type =3D HINIC3_CMD_TYPE_SGE_RESP; + cmd_info->done =3D &done; + cmd_info->errcode =3D &errcode; + cmd_info->direct_resp =3D out_param; + cmd_info->cmpt_code =3D &cmpt_code; + cmd_info->buf_in =3D buf_in; + cmd_info->buf_out =3D buf_out; + + saved_cmd_info =3D *cmd_info; + cmdq_set_lcmd_wqe(&wqe, CMDQ_CMD_SGE_RESP, buf_in, buf_out, + wrapped, mod, cmd, curr_prod_idx); + cmdq_wqe_fill(curr_wqe, &wqe); + cmd_info->cmdq_msg_id++; + curr_msg_id =3D cmd_info->cmdq_msg_id; + + cmdq_set_db(cmdq, cmdq->cmdq_type, next_prod_idx); + spin_unlock_bh(&cmdq->cmdq_lock); + + err =3D wait_cmdq_sync_cmd_completion(cmdq, cmd_info, &saved_cmd_info, + curr_msg_id, curr_prod_idx, + curr_wqe, CMDQ_CMD_TIMEOUT); + 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 =3D -ETIMEDOUT; + } + + if (cmpt_code =3D=3D CMDQ_FORCE_STOP_CMPT_CODE) { + dev_dbg(cmdq->hwdev->dev, + "Force stop cmdq cmd, mod: %u, cmd: %u\n", + mod, cmd); + err =3D -EAGAIN; + } + + smp_rmb(); /* read error code after completion */ + + return err ? err : errcode; +} + +int hinic3_cmd_buf_pair_init(struct hinic3_hwdev *hwdev, + struct hinic3_cmd_buf_pair *pair) +{ + pair->in =3D hinic3_alloc_cmd_buf(hwdev); + if (!pair->in) + goto err_out; + + pair->out =3D 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 =3D cmdq_params_valid(hwdev, buf_in); + if (err) { + dev_err(hwdev->dev, "Invalid CMDQ parameters\n"); + goto err_out; + } =20 cmdqs =3D hwdev->cmdqs; err =3D wait_cmdqs_enable(cmdqs); @@ -573,6 +730,39 @@ int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev= , u8 mod, u8 cmd, err =3D cmdq_sync_cmd_direct_resp(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod, cmd, buf_in, out_param); =20 + 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 =3D cmdq_params_valid(hwdev, buf_in); + if (err) + goto err_out; + + cmdqs =3D hwdev->cmdqs; + + err =3D wait_cmdqs_enable(cmdqs); + if (err) { + dev_err(hwdev->dev, "Cmdq is disabled\n"); + goto err_out; + } + + err =3D 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; } =20 @@ -759,7 +949,8 @@ static int init_cmdqs(struct hinic3_hwdev *hwdev) =20 static void cmdq_flush_sync_cmd(struct hinic3_cmdq_cmd_info *cmd_info) { - if (cmd_info->cmd_type !=3D HINIC3_CMD_TYPE_DIRECT_RESP) + if (cmd_info->cmd_type !=3D HINIC3_CMD_TYPE_DIRECT_RESP && + cmd_info->cmd_type !=3D HINIC3_CMD_TYPE_SGE_RESP) return; =20 cmd_info->cmd_type =3D HINIC3_CMD_TYPE_FORCE_STOP; @@ -786,7 +977,8 @@ static void hinic3_cmdq_flush_cmd(struct hinic3_cmdq *c= mdq) while (cmdq_read_wqe(&cmdq->wq, &ci)) { hinic3_wq_put_wqebbs(&cmdq->wq, CMDQ_WQE_NUM_WQEBBS); cmd_info =3D &cmdq->cmd_infos[ci]; - if (cmd_info->cmd_type =3D=3D HINIC3_CMD_TYPE_DIRECT_RESP) + if (cmd_info->cmd_type =3D=3D HINIC3_CMD_TYPE_DIRECT_RESP || + cmd_info->cmd_type =3D=3D HINIC3_CMD_TYPE_SGE_RESP) cmdq_flush_sync_cmd(cmd_info); } spin_unlock_bh(&cmdq->cmdq_lock); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.h b/drivers/net= /ethernet/huawei/hinic3/hinic3_cmdq.h index f99c386a2780..29bad2fae7ba 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.h @@ -85,7 +85,9 @@ enum hinic3_cmdq_status { =20 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; }; =20 +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; }; =20 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); =20 +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); =20 void hinic3_cmdq_flush_sync_cmd(struct hinic3_hwdev *hwdev); int hinic3_reinit_cmdq_ctxts(struct hinic3_hwdev *hwdev); --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FB5B39C630; Tue, 24 Feb 2026 13:16:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938973; cv=none; b=VnmH9+mquh6C54tg9BVo7wrNAFldVl3dEhD2f7gNHM+AwZl1BATZWmO4yquc9LqW3fi9CD4KPJwq5HcBaSIz4DkbKN1GUvQT60gLghaXLa72Z4LdHXZOejX1fyymM7bdWseOgi+VVZx/MvP51WV8ToOJJB19ghvGziw3TVhncpg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938973; c=relaxed/simple; bh=JWi7xOGUAAklJ2iK/Yh5d39MPzBDhncc72z1PddnmnI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uzCuGpPQk29Z4xHOrzwvPghXvCc/Ch3oBcXlwKjnJofc+CD9MlkHAIcnJCDqPr5ONuCfzrVVJGCB6dGs7WmL+XEbz92TF14rFzr7vVQ4PpaX2Fw5RDHF0Rc4BA7IbWtQbG2ACYLa0HP2G1J6m9eWMAuULO1wxAc8T+O/CFTxNHY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=sZRhqD8a; arc=none smtp.client-ip=113.46.200.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="sZRhqD8a" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=OO7ZywSotYxKYTcrQfTyH3yxYXm3Kp6nWpw60m8kjWI=; b=sZRhqD8aFLfZWhRXP8x5IdZFSGBlOzBEF2N1Bdgy5SQ14tkXRtw5WCjazY1EFIYKGkG0OIouu 3dKrjlf0vMF/SN2La4AV78pwGYVop0JvPaLiU1fUhGXjoDy9IXXZnjcMnUoovLEBfnDMnOZ4Il3 wmFdqBAKBsGQpw9TRSxZFg8= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4fKylp4nxYz1prKq; Tue, 24 Feb 2026 21:11:18 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 5B8544056B; Tue, 24 Feb 2026 21:16:07 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:06 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 02/15] hinic3: Add Command Queue/Async Event Queue/Mailbox dump interfaces Date: Tue, 24 Feb 2026 21:15:39 +0800 Message-ID: <16ace51aa4ff2cdcfb3e3f41799d06f574b0dc7d.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../net/ethernet/huawei/hinic3/hinic3_cmdq.c | 19 ++++++ .../net/ethernet/huawei/hinic3/hinic3_csr.h | 2 + .../net/ethernet/huawei/hinic3/hinic3_eqs.c | 67 +++++++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_eqs.h | 6 ++ .../net/ethernet/huawei/hinic3/hinic3_mbox.c | 15 +++++ 5 files changed, 109 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_cmdq.c index 15c9aa247bae..928bcd857751 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c @@ -6,12 +6,14 @@ #include =20 #include "hinic3_cmdq.h" +#include "hinic3_eqs.h" #include "hinic3_hwdev.h" #include "hinic3_hwif.h" #include "hinic3_mbox.h" =20 #define CMDQ_BUF_SIZE 2048 #define CMDQ_WQEBB_SIZE 64 +#define CMDQ_WQE_HEAD_LEN 32 =20 #define CMDQ_CMD_TIMEOUT 5000 #define CMDQ_ENABLE_WAIT_TIMEOUT 300 @@ -114,6 +116,20 @@ enum cmdq_cmd_type { =20 #define CMDQ_WQE_NUM_WQEBBS 1 =20 +static void hinic3_dump_cmdq_wqe_head(struct hinic3_hwdev *hwdev, + struct cmdq_wqe *wqe) +{ + u32 *data =3D (u32 *)wqe; + u32 i; + + for (i =3D 0; i < (CMDQ_WQE_HEAD_LEN / sizeof(u32)); i +=3D 0x4) { + dev_dbg(hwdev->dev, + "wqe data: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", + *(data + i), *(data + i + 0x1), *(data + i + 0x2), + *(data + i + 0x3)); + } +} + static struct cmdq_wqe *cmdq_read_wqe(struct hinic3_wq *wq, u16 *ci) { if (hinic3_wq_get_used(wq) =3D=3D 0) @@ -279,6 +295,7 @@ void hinic3_cmdq_ceq_handler(struct hinic3_hwdev *hwdev= , __le32 ceqe_data) case HINIC3_CMD_TYPE_TIMEOUT: dev_warn(hwdev->dev, "Cmdq timeout, q_id: %u, ci: %u\n", cmdq_type, ci); + hinic3_dump_cmdq_wqe_head(hwdev, wqe); fallthrough; case HINIC3_CMD_TYPE_FAKE_TIMEOUT: cmdq_clear_cmd_buf(cmd_info, hwdev); @@ -535,6 +552,8 @@ static int wait_cmdq_sync_cmd_completion(struct hinic3_= cmdq *cmdq, clear_cmd_info(cmd_info, saved_cmd_info); spin_unlock_bh(&cmdq->cmdq_lock); =20 + hinic3_dump_ceq_info(cmdq->hwdev); + return err; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_csr.h b/drivers/net/= ethernet/huawei/hinic3/hinic3_csr.h index f7083a6e7df9..0e32ff34919e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_csr.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_csr.h @@ -76,9 +76,11 @@ =20 #define HINIC3_CSR_AEQ_CTRL_0_ADDR (HINIC3_CFG_REGS_FLAG + 0x200) #define HINIC3_CSR_AEQ_CTRL_1_ADDR (HINIC3_CFG_REGS_FLAG + 0x204) +#define HINIC3_CSR_AEQ_CONS_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x208) #define HINIC3_CSR_AEQ_PROD_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x20C) #define HINIC3_CSR_AEQ_CI_SIMPLE_INDIR_ADDR (HINIC3_CFG_REGS_FLAG + 0x50) =20 +#define HINIC3_CSR_CEQ_CONS_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x288) #define HINIC3_CSR_CEQ_PROD_IDX_ADDR (HINIC3_CFG_REGS_FLAG + 0x28c) #define HINIC3_CSR_CEQ_CI_SIMPLE_INDIR_ADDR (HINIC3_CFG_REGS_FLAG + 0x54) =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_eqs.c index a2c3962116d5..1bdc6a82ca4d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.c @@ -56,6 +56,10 @@ #define EQ_CI_SIMPLE_INDIR_SET(val, member) \ FIELD_PREP(EQ_CI_SIMPLE_INDIR_##member##_MASK, val) =20 +#define EQ_CONS_IDX_REG_ADDR(eq) \ + (((eq)->type =3D=3D HINIC3_AEQ) ? \ + HINIC3_CSR_AEQ_CONS_IDX_ADDR : HINIC3_CSR_CEQ_CONS_IDX_ADDR) + #define EQ_CI_SIMPLE_INDIR_REG_ADDR(eq) \ (((eq)->type =3D=3D HINIC3_AEQ) ? \ HINIC3_CSR_AEQ_CI_SIMPLE_INDIR_ADDR : \ @@ -353,6 +357,7 @@ static irqreturn_t ceq_interrupt(int irq, void *data) struct hinic3_eq *ceq =3D data; int err; =20 + ceq->hard_intr_jif =3D jiffies; /* clear resend timer counters */ hinic3_msix_intr_clear_resend_bit(ceq->hwdev, ceq->msix_entry_idx, EQ_MSIX_RESEND_TIMER_CLEAR); @@ -713,6 +718,39 @@ void hinic3_aeqs_free(struct hinic3_hwdev *hwdev) kfree(aeqs); } =20 +void hinic3_dump_aeq_info(struct hinic3_hwdev *hwdev) +{ + const struct hinic3_aeq_elem *aeqe_pos; + u32 addr, ci, pi, ctrl0, idx; + struct hinic3_eq *eq; + int q_id; + + for (q_id =3D 0; q_id < hwdev->aeqs->num_aeqs; q_id++) { + eq =3D &hwdev->aeqs->aeq[q_id]; + /* Indirect access should set q_id first */ + hinic3_hwif_write_reg(eq->hwdev->hwif, + HINIC3_EQ_INDIR_IDX_ADDR(eq->type), + eq->q_id); + + addr =3D HINIC3_CSR_AEQ_CTRL_0_ADDR; + + ctrl0 =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + + idx =3D hinic3_hwif_read_reg(hwdev->hwif, + HINIC3_EQ_INDIR_IDX_ADDR(eq->type)); + + addr =3D EQ_CONS_IDX_REG_ADDR(eq); + ci =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + addr =3D EQ_PROD_IDX_REG_ADDR(eq); + pi =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + aeqe_pos =3D get_curr_aeq_elem(eq); + dev_err(hwdev->dev, + "Aeq id: %d, idx: %u, ctrl0: 0x%08x, ci: 0x%08x, pi: 0x%x, work_state: = 0x%x, wrap: %u, desc: 0x%x swci:0x%x\n", + q_id, idx, ctrl0, ci, pi, work_busy(&eq->aeq_work), + eq->wrapped, be32_to_cpu(aeqe_pos->desc), eq->cons_idx); + } +} + int hinic3_ceqs_init(struct hinic3_hwdev *hwdev, u16 num_ceqs, struct msix_entry *msix_entries) { @@ -773,3 +811,32 @@ void hinic3_ceqs_free(struct hinic3_hwdev *hwdev) =20 kfree(ceqs); } + +void hinic3_dump_ceq_info(struct hinic3_hwdev *hwdev) +{ + struct hinic3_eq *eq; + u32 addr, ci, pi; + int q_id; + + for (q_id =3D 0; q_id < hwdev->ceqs->num_ceqs; q_id++) { + eq =3D &hwdev->ceqs->ceq[q_id]; + /* Indirect access should set q_id first */ + hinic3_hwif_write_reg(eq->hwdev->hwif, + HINIC3_EQ_INDIR_IDX_ADDR(eq->type), + eq->q_id); + + addr =3D EQ_CONS_IDX_REG_ADDR(eq); + ci =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + addr =3D EQ_PROD_IDX_REG_ADDR(eq); + pi =3D hinic3_hwif_read_reg(hwdev->hwif, addr); + dev_err(hwdev->dev, + "Ceq id: %d, ci: 0x%08x, sw_ci: 0x%08x, pi: 0x%x, wrap: %u, ceqe: 0x%x\= n", + q_id, ci, eq->cons_idx, pi, + eq->wrapped, be32_to_cpu(*get_curr_ceq_elem(eq))); + + dev_err(hwdev->dev, "Ceq last response hard interrupt time: %u\n", + jiffies_to_msecs(jiffies - eq->hard_intr_jif)); + dev_err(hwdev->dev, "Ceq last response soft interrupt time: %u\n", + jiffies_to_msecs(jiffies - eq->soft_intr_jif)); + } +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.h b/drivers/net/= ethernet/huawei/hinic3/hinic3_eqs.h index 005a6e0745b3..dfcd1a00855a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_eqs.h @@ -56,6 +56,9 @@ struct hinic3_eq { u16 msix_entry_idx; char irq_name[HINIC3_EQ_IRQ_NAME_LEN]; struct work_struct aeq_work; + + u64 hard_intr_jif; + u64 soft_intr_jif; }; =20 struct hinic3_aeq_elem { @@ -110,6 +113,8 @@ int hinic3_aeq_register_cb(struct hinic3_hwdev *hwdev, hinic3_aeq_event_cb hwe_cb); void hinic3_aeq_unregister_cb(struct hinic3_hwdev *hwdev, enum hinic3_aeq_type event); +void hinic3_dump_aeq_info(struct hinic3_hwdev *hwdev); + int hinic3_ceqs_init(struct hinic3_hwdev *hwdev, u16 num_ceqs, struct msix_entry *msix_entries); void hinic3_ceqs_free(struct hinic3_hwdev *hwdev); @@ -118,5 +123,6 @@ int hinic3_ceq_register_cb(struct hinic3_hwdev *hwdev, hinic3_ceq_event_cb callback); void hinic3_ceq_unregister_cb(struct hinic3_hwdev *hwdev, enum hinic3_ceq_event event); +void hinic3_dump_ceq_info(struct hinic3_hwdev *hwdev); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_mbox.c index c871fd0fb109..1bfaff9ba253 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c @@ -5,6 +5,7 @@ =20 #include "hinic3_common.h" #include "hinic3_csr.h" +#include "hinic3_eqs.h" #include "hinic3_hwdev.h" #include "hinic3_hwif.h" #include "hinic3_mbox.h" @@ -616,6 +617,18 @@ static void write_mbox_msg_attr(struct hinic3_mbox *mb= ox, mbox_ctrl); } =20 +static void hinic3_dump_mbox_reg(struct hinic3_hwdev *hwdev) +{ + u32 val; + + val =3D hinic3_hwif_read_reg(hwdev->hwif, + HINIC3_FUNC_CSR_MAILBOX_CONTROL_OFF); + dev_err(hwdev->dev, "Mailbox control reg: 0x%x\n", val); + val =3D hinic3_hwif_read_reg(hwdev->hwif, + HINIC3_FUNC_CSR_MAILBOX_INT_OFF); + dev_err(hwdev->dev, "Mailbox interrupt offset: 0x%x\n", val); +} + static u16 get_mbox_status(const struct hinic3_send_mbox *mbox) { __be64 *wb_status =3D mbox->wb_vaddr; @@ -670,6 +683,7 @@ static int send_mbox_seg(struct hinic3_mbox *mbox, __le= 64 header, if (err) { dev_err(hwdev->dev, "Send mailbox segment timeout, wb status: 0x%x\n", wb_status); + hinic3_dump_mbox_reg(hwdev); return err; } =20 @@ -825,6 +839,7 @@ int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev= , u8 mod, u16 cmd, if (wait_mbox_msg_completion(mbox, msg_params->timeout_ms)) { dev_err(hwdev->dev, "Send mbox msg timeout, msg_id: %u\n", msg_info.msg_id); + hinic3_dump_aeq_info(mbox->hwdev); err =3D -ETIMEDOUT; goto err_send; } --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout06.his.huawei.com (canpmsgout06.his.huawei.com [113.46.200.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7021239E176; Tue, 24 Feb 2026 13:16:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.221 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938977; cv=none; b=AxqISl3joJ3+A/QMLih64kg3YXQPlE+uUA4XaPydmtQGjh79LtCL0HH6XUYHQlBwKevoQ/XjpfRTAJzVTxD/tBa0Zl6vqdKhxd/ry47ZHq1ynfozSL4ltSGnl9F3eNS3deF0ta2ELGQs1+VxBM72W5vQfevoKDc6OfAF86iucbQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938977; c=relaxed/simple; bh=SHthbn4VGlu/Beddc2xoszPZllY3FA992BSmvBZLKRw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Cm0jdXP3F1E7qKlzA4r7kPOVj05ldZBoyKO3UMGeZi83B3613BusYVdCmzZKrDtMxXAx20Ke2skn/BiEn8j6i/ky0OKp9y7d2Pe0GLqUnC7xDoTFTQROrhVIcWRyKDo/nYJyAcEF0OpEaHT0r7lTtbM8opI4k1cXhE0zMz5qO5o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=jkna6yPe; arc=none smtp.client-ip=113.46.200.221 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="jkna6yPe" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=3MSe58sTIpT/PsMEP/t7EW6U1is858It/nNQbziFH44=; b=jkna6yPelo26c4CY2fV6Vd3s0yGoBTgw0bKXeXPK1Ect4DJIYljrUvwKE9x6jtRGW8+jcXmsE KfNT8eigzaMDw6/C3pv87fqM4/iGSYS4qyjKGffm6/WIvP5a1RtSlpfHD7mF7BMcWIy3ieZvTN/ 4D07gUotaRyRID8AYxqRf+E= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout06.his.huawei.com (SkyGuard) with ESMTPS id 4fKylv1g0NzRhvY; Tue, 24 Feb 2026 21:11:23 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id DA075201EB; Tue, 24 Feb 2026 21:16:08 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:07 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 03/15] hinic3: Add chip_present_flag checks to prevent errors when card is absent Date: Tue, 24 Feb 2026 21:15:40 +0800 Message-ID: <2ac16da010b80f4a5286b23a62bc90eeddca528e.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c | 10 +++++++++- .../net/ethernet/huawei/hinic3/hinic3_common.h | 1 + .../net/ethernet/huawei/hinic3/hinic3_hw_comm.c | 7 +++++++ .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 5 +++++ .../net/ethernet/huawei/hinic3/hinic3_hwdev.h | 1 + drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c | 10 +++++++--- drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c | 12 ++++++++++++ .../ethernet/huawei/hinic3/hinic3_netdev_ops.c | 16 ++++++++++------ 8 files changed, 52 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_cmdq.c index 928bcd857751..a1189751e2a8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c @@ -353,7 +353,8 @@ static int wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs) if (cmdqs->status & HINIC3_CMDQ_ENABLE) return 0; usleep_range(1000, 2000); - } while (time_before(jiffies, end) && !cmdqs->disable_flag); + } while (time_before(jiffies, end) && !cmdqs->disable_flag && + cmdqs->hwdev->chip_present_flag); =20 cmdqs->disable_flag =3D 1; =20 @@ -733,6 +734,10 @@ int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev= , u8 mod, u8 cmd, { struct hinic3_cmdqs *cmdqs; int err; + + if (!hwdev->chip_present_flag) + return -ETIMEDOUT; + err =3D cmdq_params_valid(hwdev, buf_in); if (err) { dev_err(hwdev->dev, "Invalid CMDQ parameters\n"); @@ -762,6 +767,9 @@ int hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev,= u8 mod, u8 cmd, struct hinic3_cmdqs *cmdqs; int err; =20 + if (!hwdev->chip_present_flag) + return -ETIMEDOUT; + err =3D cmdq_params_valid(hwdev, buf_in); if (err) goto err_out; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_common.h index a8fabfae90fb..c892439fa3cd 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h @@ -21,6 +21,7 @@ struct hinic3_dma_addr_align { enum hinic3_wait_return { HINIC3_WAIT_PROCESS_CPL =3D 0, HINIC3_WAIT_PROCESS_WAITING =3D 1, + HINIC3_WAIT_PROCESS_ERR =3D 2, }; =20 struct hinic3_sge { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index ecfe6265954e..dc2f236a88b8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -300,6 +300,10 @@ static enum hinic3_wait_return check_cmdq_stop_handler= (void *priv_data) enum hinic3_cmdq_type cmdq_type; struct hinic3_cmdqs *cmdqs; =20 + /* Stop waiting when card unpresent */ + if (!hwdev->chip_present_flag) + return HINIC3_WAIT_PROCESS_CPL; + cmdqs =3D hwdev->cmdqs; for (cmdq_type =3D 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { if (!hinic3_cmdq_idle(&cmdqs->cmdq[cmdq_type])) @@ -347,6 +351,9 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev) int ret =3D 0; int err; =20 + if (!hwdev->chip_present_flag) + return 0; + err =3D wait_cmdq_stop(hwdev); if (err) { dev_warn(hwdev->dev, "CMDQ is still working, CMDQ timeout value is unrea= sonable\n"); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index 7906d4057cf2..c02a0a4a5771 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -32,6 +32,9 @@ #define HINIC3_PCIE_PH_DISABLE 0 #define HINIC3_PCIE_MSIX_ATTR_ENTRY 0 =20 +#define HINIC3_CHIP_PRESENT 1 +#define HINIC3_CHIP_ABSENT 0 + #define HINIC3_DEFAULT_EQ_MSIX_PENDING_LIMIT 0 #define HINIC3_DEFAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF #define HINIC3_DEFAULT_EQ_MSIX_RESEND_TIMER_CFG 7 @@ -545,6 +548,7 @@ int hinic3_init_hwdev(struct pci_dev *pdev) dev_err(hwdev->dev, "Failed to init hwif\n"); goto err_free_hwdev; } + hwdev->chip_present_flag =3D HINIC3_CHIP_PRESENT; =20 hwdev->workq =3D alloc_workqueue(HINIC3_HWDEV_WQ_NAME, WQ_MEM_RECLAIM | W= Q_PERCPU, HINIC3_WQ_MAX_REQ); @@ -621,6 +625,7 @@ void hinic3_set_api_stop(struct hinic3_hwdev *hwdev) struct hinic3_recv_msg *recv_resp_msg; struct hinic3_mbox *mbox; =20 + hwdev->chip_present_flag =3D HINIC3_CHIP_ABSENT; spin_lock_bh(&hwdev->channel_lock); if (HINIC3_IS_PF(hwdev) && test_bit(HINIC3_HWDEV_MGMT_INITED, &hwdev->func_state)) { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.h index 9686c2600b46..4276ac136464 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h @@ -76,6 +76,7 @@ struct hinic3_hwdev { u32 wq_page_size; u8 max_cmdq; ulong func_state; + int chip_present_flag; }; =20 struct hinic3_event_info { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.c index 801f48e241f8..e4dd4c717eec 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c @@ -94,12 +94,16 @@ void hinic3_hwif_write_reg(struct hinic3_hwif *hwif, u3= 2 reg, u32 val) static enum hinic3_wait_return check_hwif_ready_handler(void *priv_data) { struct hinic3_hwdev *hwdev =3D priv_data; - u32 attr1; + u32 attr1, status; =20 attr1 =3D hinic3_hwif_read_reg(hwdev->hwif, HINIC3_CSR_FUNC_ATTR1_ADDR); + status =3D !HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS); + if (status =3D=3D HINIC3_PCIE_LINK_DOWN) + return HINIC3_WAIT_PROCESS_ERR; + else if (!status) + return HINIC3_WAIT_PROCESS_CPL; =20 - return HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS) ? - HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; + return HINIC3_WAIT_PROCESS_WAITING; } =20 static int wait_hwif_ready(struct hinic3_hwdev *hwdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_mbox.c index 1bfaff9ba253..63cc70bce8b0 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c @@ -646,6 +646,9 @@ static enum hinic3_wait_return check_mbox_wb_status(voi= d *priv_data) struct hinic3_mbox *mbox =3D priv_data; u16 wb_status; =20 + if (!mbox->hwdev->chip_present_flag) + return HINIC3_WAIT_PROCESS_ERR; + wb_status =3D get_mbox_status(&mbox->send_mbox); =20 return MBOX_STATUS_FINISHED(wb_status) ? @@ -788,6 +791,9 @@ static enum hinic3_wait_return check_mbox_msg_finish(vo= id *priv_data) { struct hinic3_mbox *mbox =3D priv_data; =20 + if (!mbox->hwdev->chip_present_flag) + return HINIC3_WAIT_PROCESS_ERR; + return (mbox->event_flag =3D=3D MBOX_EVENT_SUCCESS) ? HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; } @@ -819,6 +825,9 @@ int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev= , u8 mod, u16 cmd, u32 msg_len; int err; =20 + if (!hwdev->chip_present_flag) + return -EPERM; + /* expect response message */ msg_desc =3D get_mbox_msg_desc(mbox, MBOX_MSG_RESP, MBOX_MGMT_FUNC_ID); mutex_lock(&mbox->mbox_send_lock); @@ -897,6 +906,9 @@ int hinic3_send_mbox_to_mgmt_no_ack(struct hinic3_hwdev= *hwdev, u8 mod, u16 cmd, struct mbox_msg_info msg_info =3D {}; int err; =20 + if (!hwdev->chip_present_flag) + return -EPERM; + mutex_lock(&mbox->mbox_send_lock); err =3D send_mbox_msg(mbox, mod, cmd, msg_params->buf_in, msg_params->in_size, MBOX_MGMT_FUNC_ID, diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index 75adfe897e81..75b6abdf1024 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -417,13 +417,17 @@ static void hinic3_vport_down(struct net_device *netd= ev) netif_carrier_off(netdev); netif_tx_disable(netdev); =20 - glb_func_id =3D hinic3_global_func_id(nic_dev->hwdev); - hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); + if (nic_dev->hwdev->chip_present_flag) { + hinic3_maybe_set_port_state(netdev, false); =20 - hinic3_flush_txqs(netdev); - /* wait to guarantee that no packets will be sent to host */ - msleep(100); - hinic3_flush_qps_res(nic_dev->hwdev); + glb_func_id =3D hinic3_global_func_id(nic_dev->hwdev); + hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); + + hinic3_flush_txqs(netdev); + /* wait to guarantee that no packets will be sent to host */ + msleep(100); + hinic3_flush_qps_res(nic_dev->hwdev); + } } =20 static int hinic3_open(struct net_device *netdev) --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9A29639E6CA; Tue, 24 Feb 2026 13:16:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938981; cv=none; b=mg+KptoAWIwHY7VFHHHXpQ5IEnarcDlU8FmADfC1cgUGD6OBDT5CuGawVilCWnad2h/0MZb5VucrHpfqaeZUZK8E2CngPermxesaKdUOFUTXfjrOupe1lZRY75NZOlK673xNU9xuRi+YzW7yxBpBa3XQDAI/Skv8Xkp92Sm6N4g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938981; c=relaxed/simple; bh=PuwG/keMEByyBRzSJCCvTUkYwbLRC/waxnE4miTtkXU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=vBSi0ez1j8/TUxhWFYLFRqkCFPRmScthSu9DxpTxX0koU6vf00rZA/NMzwODvx6PahYGLvBhHXvoj4xgBpN8aVf5djZLW7CFuoNqAOMXe/hZvy1FmjilbBGVb4+NRJi8zzVEG49nxMi1Pf0bQnRab/iCByMpNIrFX51/BQy3oBo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=CVL7Ifl1; arc=none smtp.client-ip=113.46.200.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="CVL7Ifl1" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=VrjNgYENEFdEskuM+UhiVN06tUFuQ1OIIBPuFajVydA=; b=CVL7Ifl1X4zetnnFo1OGUTu/DQjQcpvV3/2nspC+gUffs4VfZmDGg3dVUTuti7QlTHZ+l6D2H EGeA8t4K/jjpC0cEi+ygvEAz9yrz55Ejkj4Q+T920xjZQA4P6jFd933dZzOhdOP+CvBtlMSazvD FXTrtlALn858IBrIDyiXtU0= Received: from mail.maildlp.com (unknown [172.19.163.15]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4fKylv30syzKm50; Tue, 24 Feb 2026 21:11:23 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 5C45A40565; Tue, 24 Feb 2026 21:16:10 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:09 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 04/15] hinic3: Add RX GRO and VLAN offload support Date: Tue, 24 Feb 2026 21:15:41 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../net/ethernet/huawei/hinic3/hinic3_rx.c | 26 +++++++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_rx.h | 3 +++ 2 files changed, 29 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.c index 159c291fa293..fe7fdd06c1b6 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c @@ -357,6 +357,23 @@ static void hinic3_rx_csum(struct hinic3_rxq *rxq, u32= offload_type, } } =20 +static void hinic3_rx_gro(struct hinic3_rxq *rxq, u32 offload_type, + struct sk_buff *skb) +{ + struct net_device *netdev =3D rxq->netdev; + bool l2_tunnel; + + if (!(netdev->features & NETIF_F_GRO)) + return; + + l2_tunnel =3D HINIC3_GET_RX_TUNNEL_PKT_FORMAT(offload_type) =3D=3D + HINIC3_RX_PKT_FORMAT_VXLAN ? 1 : 0; + if (l2_tunnel && skb->ip_summed =3D=3D CHECKSUM_UNNECESSARY) { + /* If we checked the outer header let the stack know */ + skb->csum_level =3D 1; + } +} + static void hinic3_lro_set_gso_params(struct sk_buff *skb, u16 num_lro) { struct ethhdr *eth =3D (struct ethhdr *)(skb->data); @@ -389,6 +406,15 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct= hinic3_rq_cqe *rx_cqe, =20 offload_type =3D le32_to_cpu(rx_cqe->offload_type); hinic3_rx_csum(rxq, offload_type, status, skb); + hinic3_rx_gro(rxq, offload_type, skb); + + if ((netdev->features & NETIF_F_HW_VLAN_CTAG_RX) && + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, VLAN_EN)) { + u16 vid =3D RQ_CQE_SGE_GET(vlan_len, VLAN); + + /* if the packet is a vlan pkt, the vid may be 0 */ + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); + } =20 num_lro =3D RQ_CQE_STATUS_GET(status, NUM_LRO); if (num_lro) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.h index 31622e0a63d0..06d1b3299e7c 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h @@ -15,6 +15,9 @@ #define RQ_CQE_OFFOLAD_TYPE_GET(val, member) \ FIELD_GET(RQ_CQE_OFFOLAD_TYPE_##member##_MASK, val) =20 +#define HINIC3_GET_RX_TUNNEL_PKT_FORMAT(offload_type) \ + RQ_CQE_OFFOLAD_TYPE_GET(offload_type, TUNNEL_PKT_FORMAT) + #define RQ_CQE_SGE_VLAN_MASK GENMASK(15, 0) #define RQ_CQE_SGE_LEN_MASK GENMASK(31, 16) #define RQ_CQE_SGE_GET(val, member) \ --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout07.his.huawei.com (canpmsgout07.his.huawei.com [113.46.200.222]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49C5439C64C; Tue, 24 Feb 2026 13:16:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.222 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938978; cv=none; b=MjCpxbgVZpTlGRZ/5Ud2srS4Ph98m16SY1nOQhLLHfHRLijWacKkyMlGYkQ073pLr05MX8N9It5gXUYymQYaF1fO3wx+7iVGS/BoTG4KSM8gHth++XcrOr5DSqy9TVHYppkkeDORqa21LlH1tXkrJOyt9N7oIHxKYF2BV7DHbzU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938978; c=relaxed/simple; bh=piTICk03gyySJY/rmyPdJDdA3q8tjm7nIVlT98bRjgE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=KHEKxzjgobFGt3zw8G4me1yq1wsi5GMGNH/v5VqafILRzc76ArgdOisRghMPpkCNPocxCJRkLxDCCZ2DqQaUNUP8P7dTEJwQEAV9JOwAy0XmBKnS3EX3I9p4YBOK41vDRYNtUlDfnCfz36YIDglZMnPhV/G2+1R+s1mNX+Goego= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=PTxrXiaI; arc=none smtp.client-ip=113.46.200.222 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="PTxrXiaI" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=zOgGPvfDC99ROaDQZy0YgezA0R/9BYReTv2IpGbPAgE=; b=PTxrXiaI7Y6vftsdUqljMfUxcKUlanls8gG4Fhk2jhbBOUVUoCnu1xudJ/bFrlRIQamTRCxYN mOuySXJ5YYzlb0AyVUONCS7QP4Py4i+SoAWtPys6VZUZdLiXDjEzCnLc9DcaVCxqM+/M+lNVDIR A3d6QWb3cNKnxGDNBMJjGQA= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout07.his.huawei.com (SkyGuard) with ESMTPS id 4fKylx51YkzLlSJ; Tue, 24 Feb 2026 21:11:25 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id DC7F440561; Tue, 24 Feb 2026 21:16:11 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:10 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 05/15] hinic3: Add msg_send_lock for message sending concurrecy Date: Tue, 24 Feb 2026 21:15:42 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c | 5 +++++ drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_mbox.c index 63cc70bce8b0..8554291f852d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c @@ -396,6 +396,7 @@ static int hinic3_mbox_pre_init(struct hinic3_hwdev *hw= dev, { mbox->hwdev =3D hwdev; mutex_init(&mbox->mbox_send_lock); + mutex_init(&mbox->msg_send_lock); spin_lock_init(&mbox->mbox_lock); =20 mbox->workq =3D create_singlethread_workqueue(HINIC3_MBOX_WQ_NAME); @@ -723,6 +724,8 @@ static int send_mbox_msg(struct hinic3_mbox *mbox, u8 m= od, u16 cmd, else rsp_aeq_id =3D 0; =20 + mutex_lock(&mbox->msg_send_lock); + if (dst_func =3D=3D MBOX_MGMT_FUNC_ID && !(hwdev->features[0] & MBOX_COMM_F_MBOX_SEGMENT)) { err =3D mbox_prepare_dma_msg(mbox, ack_type, &dma_msg, @@ -776,6 +779,8 @@ static int send_mbox_msg(struct hinic3_mbox *mbox, u8 m= od, u16 cmd, } =20 err_send: + mutex_unlock(&mbox->msg_send_lock); + return err; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h b/drivers/net= /ethernet/huawei/hinic3/hinic3_mbox.h index e26f22d1d564..d972d2bfd528 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.h @@ -114,6 +114,8 @@ struct hinic3_mbox { struct hinic3_hwdev *hwdev; /* lock for send mbox message and ack message */ struct mutex mbox_send_lock; + /* lock for send mbox message */ + struct mutex msg_send_lock; struct hinic3_send_mbox send_mbox; struct mbox_dma_queue sync_msg_queue; struct mbox_dma_queue async_msg_queue; --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D63539C634; Tue, 24 Feb 2026 13:16:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938980; cv=none; b=nJ6dp0AaFYA10LcX0eQo8ZE1dspTCmADsi/NnfofDDHKPTcc6CGjQU1c0n4BXFVJEoO//pp0jEBSkWG93nV97UQEkWS2RFcm7I/A0P8j9LBYfqPxIBkFLtM19bo/4aqsH/E+SE89cWVeQfUHT4oL4iNAvP3acIQFTwIGnLuoXH8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938980; c=relaxed/simple; bh=d9dTAKwjA0riwui6UsdxBr8mN+j0DxeF5FO2RsgksLw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NotK7aQidEEIZurJ/3n5cQEG11qiXkXG8Nju83o8V/csqYDx1TnZI7CCOXN/E5a3IjHj/YtDrdv9mXjrgOi0rhWD6pgRr92iJAvdCzGOcnCLJ3og99MEiKzNWUtg0K+1fhvgfj7EMkdcAj2ry9+5uCI9gMV2hSoMXCrYX5hEZrA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=YfsRMraz; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="YfsRMraz" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=1xJ2QJhWxIAVVvE8xZz70eCPxBajA67SOUZtgZWuWY4=; b=YfsRMraz2olsoXNFkV/NmH2iRFhg+3ed4Ni64RYbV7yDOA3aYeH3fMmFjlSIt8NygU39OB27Z puzRCAjv2tWztDnVVQTL0t/xgRNAiueN8q/cIces4i9ypbgsAPawdc4OViSx8zxtCEl+yPqqxTi 2sXtgNt7xj0uZbqoRXghx1c= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4fKym433syz12LD7; Tue, 24 Feb 2026 21:11:32 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 6C91440570; Tue, 24 Feb 2026 21:16:13 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:12 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 06/15] hinic3: Add PF device support and function type validation Date: Tue, 24 Feb 2026 21:15:43 +0800 Message-ID: <34c08860101ba62390782894a6d25d101dd5ad5a.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../net/ethernet/huawei/hinic3/hinic3_hwdev.c | 6 ++++++ .../net/ethernet/huawei/hinic3/hinic3_hwif.c | 21 +++++++++++++++++-- .../net/ethernet/huawei/hinic3/hinic3_lld.c | 1 + .../net/ethernet/huawei/hinic3/hinic3_mbox.c | 3 ++- .../huawei/hinic3/hinic3_pci_id_tbl.h | 1 + 5 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/ne= t/ethernet/huawei/hinic3/hinic3_hwdev.c index c02a0a4a5771..47433a81b570 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -423,6 +423,7 @@ static int init_cmdqs_channel(struct hinic3_hwdev *hwde= v) return 0; =20 err_reset_wq_page_size: +if (HINIC3_FUNC_TYPE(hwdev) !=3D HINIC3_FUNC_TYPE_VF) hinic3_set_wq_page_size(hwdev, hinic3_global_func_id(hwdev), HINIC3_MIN_PAGE_SIZE); err_free_ceqs: @@ -434,6 +435,11 @@ static int init_cmdqs_channel(struct hinic3_hwdev *hwd= ev) static void hinic3_free_cmdqs_channel(struct hinic3_hwdev *hwdev) { hinic3_comm_cmdqs_free(hwdev); + + if (HINIC3_FUNC_TYPE(hwdev) !=3D HINIC3_FUNC_TYPE_VF) + hinic3_set_wq_page_size(hwdev, hinic3_global_func_id(hwdev), + HINIC3_MIN_PAGE_SIZE); + hinic3_ceqs_free(hwdev); } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_hwif.c index e4dd4c717eec..518d4723d6c8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c @@ -70,11 +70,19 @@ #define HINIC3_PPF_ELECTION_GET(val, member) \ FIELD_GET(HINIC3_PPF_ELECTION_##member##_MASK, val) =20 +#define HINIC3_GET_REG_FLAG(reg) ((reg) & (~(HINIC3_REGS_FLAG_MASK))) #define HINIC3_GET_REG_ADDR(reg) ((reg) & (HINIC3_REGS_FLAG_MASK)) =20 static void __iomem *hinic3_reg_addr(struct hinic3_hwif *hwif, u32 reg) { - return hwif->cfg_regs_base + HINIC3_GET_REG_ADDR(reg); + void __iomem *addr; + + if (HINIC3_GET_REG_FLAG(reg) =3D=3D HINIC3_MGMT_REGS_FLAG) + addr =3D hwif->mgmt_regs_base + HINIC3_GET_REG_ADDR(reg); + else + addr =3D hwif->cfg_regs_base + HINIC3_GET_REG_ADDR(reg); + + return addr; } =20 u32 hinic3_hwif_read_reg(struct hinic3_hwif *hwif, u32 reg) @@ -139,6 +147,7 @@ static void set_hwif_attr(struct hinic3_func_attr *attr= , u32 attr0, u32 attr1, static int init_hwif_attr(struct hinic3_hwdev *hwdev) { u32 attr0, attr1, attr2, attr3, attr6; + struct hinic3_func_attr *attr; struct hinic3_hwif *hwif; =20 hwif =3D hwdev->hwif; @@ -162,7 +171,15 @@ static int init_hwif_attr(struct hinic3_hwdev *hwdev) if (attr6 =3D=3D HINIC3_PCIE_LINK_DOWN) return -EFAULT; =20 - set_hwif_attr(&hwif->attr, attr0, attr1, attr2, attr3, attr6); + attr =3D &hwif->attr; + set_hwif_attr(attr, attr0, attr1, attr2, attr3, attr6); + + if (attr->func_type !=3D HINIC3_FUNC_TYPE_VF && + attr->func_type !=3D HINIC3_FUNC_TYPE_PF) { + dev_err(hwdev->dev, "unexpected func_type %u\n", + attr->func_type); + return -EINVAL; + } =20 if (!hwif->attr.num_ceqs) { dev_err(hwdev->dev, "Ceq num cfg in fw is zero\n"); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_lld.c index 87413e192f10..1465c54e579e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_lld.c @@ -426,6 +426,7 @@ static void hinic3_remove(struct pci_dev *pdev) } =20 static const struct pci_device_id hinic3_pci_table[] =3D { + {PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_PF), 0}, {PCI_VDEVICE(HUAWEI, PCI_DEV_ID_HINIC3_VF), 0}, {0, 0} =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_mbox.c index 8554291f852d..2da18145befa 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c @@ -462,7 +462,8 @@ void hinic3_free_mbox(struct hinic3_hwdev *hwdev) =20 destroy_workqueue(mbox->workq); free_mbox_wb_status(mbox); - hinic3_uninit_func_mbox_msg_channel(hwdev); + if (HINIC3_IS_VF(hwdev)) + hinic3_uninit_func_mbox_msg_channel(hwdev); uninit_mgmt_msg_channel(mbox); kfree(mbox); } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h b/drive= rs/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h index 86c88d0bb4bd..02b2b0fbecc7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_pci_id_tbl.h @@ -4,6 +4,7 @@ #ifndef _HINIC3_PCI_ID_TBL_H_ #define _HINIC3_PCI_ID_TBL_H_ =20 +#define PCI_DEV_ID_HINIC3_PF 0x0222 #define PCI_DEV_ID_HINIC3_VF 0x375F =20 #endif --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout12.his.huawei.com (canpmsgout12.his.huawei.com [113.46.200.227]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 747F639C654; Tue, 24 Feb 2026 13:16:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938979; cv=none; b=FymbXyodcKcdST2IoAFe1TyH6sm2hoXbLr/VAdEbQACcPQzIBN1lAJImVlpTwi6ZKdX+mKcW5MxNhh0GKbE7iFUUmrvxkZSfS5Wg88Dulas5j5cB1xTH499cCQouO9fvXUEesKGFvtDfSr5k1l5FCaHBbSuUyFeMx/rfhaFD4/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938979; c=relaxed/simple; bh=BeWFJxf2XYxYu02a4dfK8lnCInbOQTUZD7emoGiYkG0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PlQUxqv15fpkwviFdi94a58HqK7f0+oiJdaS+Yt7fx3WbFH1Z6R2lv06ylBfYrnKfwjomUkptRrygKugtmBHHEfNkwD571tz/GYATxq39vo5QJV1TmTVzPy55kBT9lVPqXXWsYpaVyDBG6MFealuqbFJSrD3YT28K0DGF/uQ8Zc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=xcMFw7uH; arc=none smtp.client-ip=113.46.200.227 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="xcMFw7uH" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=k1otGlIq0DvgLuj19r0nerBLtwuaRaSRi85XHRod0V8=; b=xcMFw7uHzi5CQE7UeAXBxeggg7RIuzbRwPIedMRkBYtca47A4zZFPVC25zRr2B5KMaxQ+R/j1 7vxHOQEEGVK5d6k4zFRCpmx5wMw0N8lZNtXs9V0oBsmj/qyYunFtNLagXhOVRRkImMjXlK+Pwg/ F1FMfnEzKZleqegzYMpTPK4= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4fKym55QlGznTV9; Tue, 24 Feb 2026 21:11:33 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id E980640561; Tue, 24 Feb 2026 21:16:14 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:14 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 07/15] hinic3: Add PF FLR wait and timeout handling Date: Tue, 24 Feb 2026 21:15:44 +0800 Message-ID: <0b0cacfc5dad177c49a25385e9857dfe95a08a7f.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Add a mechanisim for PF to wait for FLR completion, ensuring HW state consistency after a FLR event. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_comm.c | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index dc2f236a88b8..e494e3ce61f6 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -292,6 +292,28 @@ int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, = u16 cmdq_depth) return 0; } =20 +#define HINIC3_FLR_TIMEOUT 1000 + +static enum hinic3_wait_return hinic3_check_flr_finish_handler(void *priv_= data) +{ + struct hinic3_hwif *hwif =3D priv_data; + enum hinic3_pf_status status; + + status =3D hinic3_get_pf_status(hwif); + if (status =3D=3D HINIC3_PF_STATUS_FLR_FINISH_FLAG) { + hinic3_set_pf_status(hwif, HINIC3_PF_STATUS_ACTIVE_FLAG); + return HINIC3_WAIT_PROCESS_CPL; + } + + return HINIC3_WAIT_PROCESS_WAITING; +} + +static int hinic3_wait_for_flr_finish(struct hinic3_hwif *hwif) +{ + return hinic3_wait_for_timeout(hwif, hinic3_check_flr_finish_handler, + HINIC3_FLR_TIMEOUT, 0xa * USEC_PER_MSEC); +} + #define HINIC3_WAIT_CMDQ_IDLE_TIMEOUT 5000 =20 static enum hinic3_wait_return check_cmdq_stop_handler(void *priv_data) @@ -389,6 +411,14 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev) ret =3D err; } =20 + if (HINIC3_FUNC_TYPE(hwdev) !=3D HINIC3_FUNC_TYPE_VF) { + err =3D hinic3_wait_for_flr_finish(hwif); + if (err) { + dev_warn(hwdev->dev, "Wait firmware FLR timeout\n"); + ret =3D err; + } + } + hinic3_toggle_doorbell(hwif, ENABLE_DOORBELL); =20 err =3D hinic3_reinit_cmdq_ctxts(hwdev); --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout01.his.huawei.com (canpmsgout01.his.huawei.com [113.46.200.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E95163A0B27; Tue, 24 Feb 2026 13:16:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.216 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938983; cv=none; b=c66oGa16hYpgY60vLE1c1oPLc25fm91QnS4lBVPbJg2U6uTjRo9X9Qz8koGj9b702BZukjEpHrEEzYHRgZOXvboTZQex062LydhFyWh+EWwqHYWCvG4XrDH0TUwvGH33wdXbGzwXesN6WCi/And8Z1hWRlcF2RktH5esSHlLoAc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938983; c=relaxed/simple; bh=1n1JFFSsnJ4S0SjSrsCZmNziMLFcd8MY4OQGEhWmRuM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=H/k9GLZmMgcpFyI3GRhSVBHQdQMD5YGDJpb/ujEHQWXnz20LyF+qO+v4ADpUHm3UN4zaqsKHyWdkPG7X+ZcaAUAkiwsQ4gZ+TlH+4aF6FOH62E6Xc0EKJeMHM8jGjt7LtH3XEwlfY2kyRLXAMh9D5F1LALH6WSUKMyvzpCNAPHY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=ef0hkez6; arc=none smtp.client-ip=113.46.200.216 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="ef0hkez6" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=4F86HGpzEnxmd8j3S0gmeUC3XNn6PZTHj4EFCv9toUw=; b=ef0hkez6a1gy02L+gtcgxjijoW7ohbwhjAy+CCbH2Xj0X0XAxLT8GK8jqZx0Gq7YrmCZVb+F4 5xOSubBZ75RKVC0QAN+SwNPunKeYBCjdLGcTGXEa8gHgr83QUDVggUEW0gpeOaDkpVi5Mfj7POa K1dMwOsjnM+R5xQyr8Z4gYg= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout01.his.huawei.com (SkyGuard) with ESMTPS id 4fKylx6cnXz1T4gn; Tue, 24 Feb 2026 21:11:25 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 8C9C92016A; Tue, 24 Feb 2026 21:16:16 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:15 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 08/15] hinic3: Add PF/VF capability parsing and parameter validation Date: Tue, 24 Feb 2026 21:15:45 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_cfg.c | 53 ++++++++++++++++++- .../ethernet/huawei/hinic3/hinic3_hw_cfg.h | 8 +++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_hw_cfg.c index 7827c1f626db..77534320c6a1 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.c @@ -17,6 +17,17 @@ static void hinic3_parse_pub_res_cap(struct hinic3_hwdev= *hwdev, { cap->port_id =3D dev_cap->port_id; cap->supp_svcs_bitmap =3D dev_cap->svc_cap_en; + + cap->cos_valid_bitmap =3D dev_cap->valid_cos_bitmap; + cap->port_cos_valid_bitmap =3D dev_cap->port_cos_valid_bitmap; + + if (type !=3D HINIC3_FUNC_TYPE_VF) + cap->max_vf =3D dev_cap->max_vf; + else + cap->max_vf =3D 0; + + dev_dbg(hwdev->dev, "Port_id: 0x%x, cos_bitmap: 0x%x, Max_vf: 0x%x\n", + cap->port_id, cap->cos_valid_bitmap, cap->max_vf); } =20 static void hinic3_parse_l2nic_res_cap(struct hinic3_hwdev *hwdev, @@ -28,6 +39,23 @@ static void hinic3_parse_l2nic_res_cap(struct hinic3_hwd= ev *hwdev, =20 nic_svc_cap->max_sqs =3D min(dev_cap->nic_max_sq_id + 1, HINIC3_CFG_MAX_QP); + + nic_svc_cap->max_rqs =3D dev_cap->nic_max_rq_id + 1; + nic_svc_cap->default_num_queues =3D dev_cap->nic_default_num_queues; + + dev_dbg(hwdev->dev, "L2nic resource capbility, max_sqs: 0x%x, max_rqs: 0x= %x\n", + nic_svc_cap->max_sqs, nic_svc_cap->max_rqs); + + /* Check parameters from firmware */ + if (nic_svc_cap->max_sqs > HINIC3_CFG_MAX_QP || + nic_svc_cap->max_rqs > HINIC3_CFG_MAX_QP) { + dev_dbg(hwdev->dev, + "Number of qp exceeds limit[1-%d]: sq: %u, rq: %u\n", + HINIC3_CFG_MAX_QP, nic_svc_cap->max_sqs, + nic_svc_cap->max_rqs); + nic_svc_cap->max_sqs =3D HINIC3_CFG_MAX_QP; + nic_svc_cap->max_rqs =3D HINIC3_CFG_MAX_QP; + } } =20 static void hinic3_parse_dev_cap(struct hinic3_hwdev *hwdev, @@ -69,6 +97,29 @@ static int get_cap_from_fw(struct hinic3_hwdev *hwdev, return 0; } =20 +static int hinic3_get_dev_cap(struct hinic3_hwdev *hwdev) +{ + enum hinic3_func_type type =3D HINIC3_FUNC_TYPE(hwdev); + int err; + + switch (type) { + case HINIC3_FUNC_TYPE_PF: + case HINIC3_FUNC_TYPE_VF: + err =3D get_cap_from_fw(hwdev, type); + if (err) { + dev_err(hwdev->dev, "Failed to get PF capability\n"); + return err; + } + break; + default: + dev_err(hwdev->dev, "Unsupported PCI Function type: %d\n", + type); + return -EINVAL; + } + + return 0; +} + static int hinic3_init_irq_info(struct hinic3_hwdev *hwdev) { struct hinic3_cfg_mgmt_info *cfg_mgmt =3D hwdev->cfg_mgmt; @@ -216,7 +267,7 @@ void hinic3_free_irq(struct hinic3_hwdev *hwdev, u32 ir= q_id) =20 int hinic3_init_capability(struct hinic3_hwdev *hwdev) { - return get_cap_from_fw(hwdev, HINIC3_FUNC_TYPE_VF); + return hinic3_get_dev_cap(hwdev); } =20 bool hinic3_support_nic(struct hinic3_hwdev *hwdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_hw_cfg.h index 58806199bf54..361c0b6a70f0 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_cfg.h @@ -26,6 +26,8 @@ struct hinic3_irq_info { =20 struct hinic3_nic_service_cap { u16 max_sqs; + u16 max_rqs; + u16 default_num_queues; }; =20 /* Device capabilities */ @@ -34,6 +36,12 @@ struct hinic3_dev_cap { u16 supp_svcs_bitmap; /* Physical port */ u8 port_id; + + u8 cos_valid_bitmap; + u8 port_cos_valid_bitmap; + /* max number of VFs that PF supports */ + u16 max_vf; + struct hinic3_nic_service_cap nic_svc_cap; }; =20 --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout06.his.huawei.com (canpmsgout06.his.huawei.com [113.46.200.221]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C7303A0B13; Tue, 24 Feb 2026 13:16:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.221 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938983; cv=none; b=tGzMT7fuJgpsZdsz7KeeQbv9aVJ0/qXb+vdNioMgMORK3gZb/HTsLcMsCEiB/4ZXqfMfXi4rheZGXG5OXmA5SvD/KHQkdWzfn8gloPbsyp0QYGbJK3Rw7/pv2jQQW5Dg4yJ1gZkfIbjpcwpcyWAKqfaq9Y4hQ0UN2FkBdvNYkao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938983; c=relaxed/simple; bh=2p+38rDvhkofLS8KiSqXAZYZVpV81BcZkZkkX9lhkn4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Ld9AUbK7wOJ2xVHmVinnvCyF7xPrka6gLUTTWlWHFCaZJfvOtFVuYA4QMU6qnKnickvovoXNBlP7WNpWLVUAxeO7YY02afdpAkROLfefxIr9ABjAaudLs71IxwlGkA0beLXUh3Fbj27uorYjNljypmRtwkzhF6EFu9uPBBCmk2Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=MZ+jfXdl; arc=none smtp.client-ip=113.46.200.221 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="MZ+jfXdl" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=1VuH2zaCbWQ8G/0BmfzAXxPcbQt/Erml0TT+HNGBrVA=; b=MZ+jfXdlmjutPLhC8yvwC8WBYPX3XY25/tMnndxNG+ydP50ZWhCEyn6cIAaMSLEctmcB5DcQO ix0XkxLbfUOkIMXnKKjpD7xEt4vqBMHGu+jIQtEbRNZIAe5MqqEAgvdXWpFc9gOCzwU+tD6POJq EvdCZWp9T5FhYC0nChVblzY= Received: from mail.maildlp.com (unknown [172.19.162.144]) by canpmsgout06.his.huawei.com (SkyGuard) with ESMTPS id 4fKym450lJzRhvw; Tue, 24 Feb 2026 21:11:32 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 5010140567; Tue, 24 Feb 2026 21:16:18 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:17 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 09/15] hinic3: Add ethtool basic ops Date: Tue, 24 Feb 2026 21:15:46 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/Makefile | 1 + .../ethernet/huawei/hinic3/hinic3_ethtool.c | 425 ++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_hw_comm.c | 28 ++ .../ethernet/huawei/hinic3/hinic3_hw_comm.h | 2 + .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 12 + .../net/ethernet/huawei/hinic3/hinic3_main.c | 3 + .../huawei/hinic3/hinic3_mgmt_interface.h | 16 +- .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 90 ++++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 110 +++++ .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 3 + .../net/ethernet/huawei/hinic3/hinic3_rss.c | 2 +- 11 files changed, 690 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/Makefile b/drivers/net/ethe= rnet/huawei/hinic3/Makefile index 26c05ecf31c9..4ebad3a4f943 100644 --- a/drivers/net/ethernet/huawei/hinic3/Makefile +++ b/drivers/net/ethernet/huawei/hinic3/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_HINIC3) +=3D hinic3.o hinic3-objs :=3D hinic3_cmdq.o \ hinic3_common.o \ hinic3_eqs.o \ + hinic3_ethtool.o \ hinic3_filter.o \ hinic3_hw_cfg.o \ hinic3_hw_comm.o \ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_ethtool.c new file mode 100644 index 000000000000..1b5b8b5a2d20 --- /dev/null +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hinic3_lld.h" +#include "hinic3_hw_comm.h" +#include "hinic3_nic_dev.h" +#include "hinic3_nic_cfg.h" + +#define HINIC3_MGMT_VERSION_MAX_LEN 32 + +static void hinic3_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *info) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u8 mgmt_ver[HINIC3_MGMT_VERSION_MAX_LEN]; + struct pci_dev *pdev =3D nic_dev->pdev; + int err; + + strscpy(info->driver, HINIC3_NIC_DRV_NAME, sizeof(info->driver)); + strscpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info)); + + err =3D hinic3_get_mgmt_version(nic_dev->hwdev, mgmt_ver, + HINIC3_MGMT_VERSION_MAX_LEN); + if (err) { + netdev_err(netdev, "Failed to get fw version\n"); + return; + } + + snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver); +} + +static u32 hinic3_get_msglevel(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + return nic_dev->msg_enable; +} + +static void hinic3_set_msglevel(struct net_device *netdev, u32 data) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + nic_dev->msg_enable =3D data; + + netdev_dbg(netdev, "Set message level: 0x%x\n", data); +} + +static const u32 hinic3_link_mode_ge[] =3D { + ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, + ETHTOOL_LINK_MODE_1000baseX_Full_BIT, +}; + +static const u32 hinic3_link_mode_10ge_base_r[] =3D { + ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, + ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, +}; + +static const u32 hinic3_link_mode_25ge_base_r[] =3D { + ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, +}; + +static const u32 hinic3_link_mode_40ge_base_r4[] =3D { + ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, +}; + +static const u32 hinic3_link_mode_50ge_base_r[] =3D { + ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, +}; + +static const u32 hinic3_link_mode_50ge_base_r2[] =3D { + ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, +}; + +static const u32 hinic3_link_mode_100ge_base_r[] =3D { + ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, +}; + +static const u32 hinic3_link_mode_100ge_base_r2[] =3D { + ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, +}; + +static const u32 hinic3_link_mode_100ge_base_r4[] =3D { + ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, + ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, +}; + +static const u32 hinic3_link_mode_200ge_base_r2[] =3D { + ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, + ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, + ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, +}; + +static const u32 hinic3_link_mode_200ge_base_r4[] =3D { + ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, + ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, +}; + +struct hw2ethtool_link_mode { + const u32 *link_mode_bit_arr; + u32 arr_size; + u32 speed; +}; + +static const struct hw2ethtool_link_mode + hw2ethtool_link_mode_table[LINK_MODE_MAX_NUMBERS] =3D { + [LINK_MODE_GE] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_ge, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_ge), + .speed =3D SPEED_1000, + }, + [LINK_MODE_10GE_BASE_R] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_10ge_base_r, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_10ge_base_r), + .speed =3D SPEED_10000, + }, + [LINK_MODE_25GE_BASE_R] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_25ge_base_r, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_25ge_base_r), + .speed =3D SPEED_25000, + }, + [LINK_MODE_40GE_BASE_R4] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_40ge_base_r4, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_40ge_base_r4), + .speed =3D SPEED_40000, + }, + [LINK_MODE_50GE_BASE_R] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_50ge_base_r, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_50ge_base_r), + .speed =3D SPEED_50000, + }, + [LINK_MODE_50GE_BASE_R2] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_50ge_base_r2, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_50ge_base_r2), + .speed =3D SPEED_50000, + }, + [LINK_MODE_100GE_BASE_R] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_100ge_base_r, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_100ge_base_r), + .speed =3D SPEED_100000, + }, + [LINK_MODE_100GE_BASE_R2] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_100ge_base_r2, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_100ge_base_r2), + .speed =3D SPEED_100000, + }, + [LINK_MODE_100GE_BASE_R4] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_100ge_base_r4, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_100ge_base_r4), + .speed =3D SPEED_100000, + }, + [LINK_MODE_200GE_BASE_R2] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_200ge_base_r2, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_200ge_base_r2), + .speed =3D SPEED_200000, + }, + [LINK_MODE_200GE_BASE_R4] =3D { + .link_mode_bit_arr =3D hinic3_link_mode_200ge_base_r4, + .arr_size =3D ARRAY_SIZE(hinic3_link_mode_200ge_base_r4), + .speed =3D SPEED_200000, + }, +}; + +#define GET_SUPPORTED_MODE 0 +#define GET_ADVERTISED_MODE 1 + +struct ethtool_cmd_link_settings { + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); + __ETHTOOL_DECLARE_LINK_MODE_MASK(advertising); + + u32 speed; + u8 duplex; + u8 port; + u8 autoneg; +}; + +#define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \ + set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->supported) +#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \ + set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->advertising) + +static void ethtool_add_speed_link_mode(unsigned long *bitmap, u32 mode) +{ + u32 i; + + for (i =3D 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) { + if (hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i] >=3D + __ETHTOOL_LINK_MODE_MASK_NBITS) + continue; + + set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i], + bitmap); + } +} + +/* Related to enum mag_cmd_port_speed */ +static u32 hw_to_ethtool_speed[] =3D { + (u32)SPEED_UNKNOWN, SPEED_10, SPEED_100, SPEED_1000, SPEED_10000, + SPEED_25000, SPEED_40000, SPEED_50000, SPEED_100000, SPEED_200000 +}; + +static void +hinic3_add_ethtool_link_mode(struct ethtool_cmd_link_settings *link_settin= gs, + u32 hw_link_mode, u32 name) +{ + unsigned long *advertising_mask =3D link_settings->advertising; + unsigned long *supported_mask =3D link_settings->supported; + u32 link_mode; + + for (link_mode =3D 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) { + if (hw_link_mode & BIT(link_mode)) { + if (name =3D=3D GET_SUPPORTED_MODE) + ethtool_add_speed_link_mode(supported_mask, + link_mode); + else + ethtool_add_speed_link_mode(advertising_mask, + link_mode); + } + } +} + +static void +hinic3_link_speed_set(struct net_device *netdev, + struct ethtool_cmd_link_settings *link_settings, + struct hinic3_nic_port_info *port_info) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + bool link_status_up; + int err; + + if (port_info->supported_mode !=3D LINK_MODE_UNKNOWN) + hinic3_add_ethtool_link_mode(link_settings, + port_info->supported_mode, + GET_SUPPORTED_MODE); + if (port_info->advertised_mode !=3D LINK_MODE_UNKNOWN) + hinic3_add_ethtool_link_mode(link_settings, + port_info->advertised_mode, + GET_ADVERTISED_MODE); + + err =3D hinic3_get_link_status(nic_dev->hwdev, &link_status_up); + if (!err && link_status_up) { + link_settings->speed =3D + port_info->speed < ARRAY_SIZE(hw_to_ethtool_speed) ? + hw_to_ethtool_speed[port_info->speed] : + (u32)SPEED_UNKNOWN; + + link_settings->duplex =3D port_info->duplex; + } else { + link_settings->speed =3D (u32)SPEED_UNKNOWN; + link_settings->duplex =3D DUPLEX_UNKNOWN; + } +} + +static void +hinic3_link_port_type_set(struct ethtool_cmd_link_settings *link_settings, + u8 port_type) +{ + switch (port_type) { + case MAG_CMD_WIRE_TYPE_ELECTRIC: + ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_TP); + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_TP); + link_settings->port =3D PORT_TP; + break; + + case MAG_CMD_WIRE_TYPE_AOC: + case MAG_CMD_WIRE_TYPE_MM: + case MAG_CMD_WIRE_TYPE_SM: + ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE); + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE); + link_settings->port =3D PORT_FIBRE; + break; + + case MAG_CMD_WIRE_TYPE_COPPER: + ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE); + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE); + link_settings->port =3D PORT_DA; + break; + + case MAG_CMD_WIRE_TYPE_BACKPLANE: + ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Backplane); + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Backplane); + link_settings->port =3D PORT_NONE; + break; + + default: + link_settings->port =3D PORT_OTHER; + break; + } +} + +static int +hinic3_get_link_pause_settings(struct net_device *netdev, + struct ethtool_cmd_link_settings *link_settings) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_nic_pause_config nic_pause =3D {}; + int err; + + err =3D hinic3_get_pause_info(nic_dev, &nic_pause); + if (err) { + netdev_err(netdev, "Failed to get pause param from hw\n"); + return err; + } + + ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Pause); + if (nic_pause.rx_pause && nic_pause.tx_pause) { + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause); + } else if (nic_pause.tx_pause) { + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, + MODE_Asym_Pause); + } else if (nic_pause.rx_pause) { + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause); + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, + MODE_Asym_Pause); + } + + return 0; +} + +static int +hinic3_get_link_settings(struct net_device *netdev, + struct ethtool_cmd_link_settings *link_settings) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_nic_port_info port_info =3D {}; + int err; + + err =3D hinic3_get_port_info(nic_dev->hwdev, &port_info); + if (err) { + netdev_err(netdev, "Failed to get port info\n"); + return err; + } + + hinic3_link_speed_set(netdev, link_settings, &port_info); + + hinic3_link_port_type_set(link_settings, port_info.port_type); + + link_settings->autoneg =3D port_info.autoneg_state =3D=3D PORT_CFG_AN_ON ? + AUTONEG_ENABLE : AUTONEG_DISABLE; + if (port_info.autoneg_cap) + ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Autoneg); + if (port_info.autoneg_state =3D=3D PORT_CFG_AN_ON) + ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Autoneg); + + if (!HINIC3_IS_VF(nic_dev->hwdev)) { + err =3D hinic3_get_link_pause_settings(netdev, link_settings); + if (err) + return err; + } + + return 0; +} + +static int +hinic3_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *link_settings) +{ + struct ethtool_link_settings *base =3D &link_settings->base; + struct ethtool_cmd_link_settings settings =3D {}; + int err; + + ethtool_link_ksettings_zero_link_mode(link_settings, supported); + ethtool_link_ksettings_zero_link_mode(link_settings, advertising); + + err =3D hinic3_get_link_settings(netdev, &settings); + if (err) + return err; + + bitmap_copy(link_settings->link_modes.supported, settings.supported, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_copy(link_settings->link_modes.advertising, settings.advertising, + __ETHTOOL_LINK_MODE_MASK_NBITS); + + base->autoneg =3D settings.autoneg; + base->speed =3D settings.speed; + base->duplex =3D settings.duplex; + base->port =3D settings.port; + + return 0; +} + +static const struct ethtool_ops hinic3_ethtool_ops =3D { + .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_PKT_RATE_RX_USECS, + .get_link_ksettings =3D hinic3_get_link_ksettings, + .get_drvinfo =3D hinic3_get_drvinfo, + .get_msglevel =3D hinic3_get_msglevel, + .set_msglevel =3D hinic3_set_msglevel, + .get_link =3D ethtool_op_get_link, +}; + +void hinic3_set_ethtool_ops(struct net_device *netdev) +{ + netdev->ethtool_ops =3D &hinic3_ethtool_ops; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index e494e3ce61f6..69375ad5d832 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -576,3 +576,31 @@ int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev) =20 return 0; } + +#define HINIC3_FW_VER_TYPE_MPU 1 + +int hinic3_get_mgmt_version(struct hinic3_hwdev *hwdev, u8 *mgmt_ver, + u8 version_size) +{ + struct comm_cmd_get_fw_version fw_ver =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + fw_ver.fw_type =3D HINIC3_FW_VER_TYPE_MPU; + + mgmt_msg_params_init_default(&msg_params, &fw_ver, sizeof(fw_ver)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_GET_FW_VERSION, &msg_params); + + if (err || fw_ver.head.status) { + dev_err(hwdev->dev, + "Failed to get fw version, err: %d, status: 0x%x\n", + err, fw_ver.head.status); + return -EFAULT; + } + + snprintf(mgmt_ver, version_size, "%s", fw_ver.ver); + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.h index 8e4737c486b7..e672f9af5cb1 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h @@ -49,5 +49,7 @@ void hinic3_sync_time_to_fw(struct hinic3_hwdev *hwdev); int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_= depth, int rx_buf_sz); int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev); +int hinic3_get_mgmt_version(struct hinic3_hwdev *hwdev, u8 *mgmt_ver, + u8 version_size); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_intf.h index 329a9c464ff9..cfc9daa3034f 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h @@ -114,6 +114,7 @@ enum comm_cmd { COMM_CMD_SET_DMA_ATTR =3D 25, =20 /* Commands for obtaining information */ + COMM_CMD_GET_FW_VERSION =3D 60, COMM_CMD_SYNC_TIME =3D 62, COMM_CMD_SEND_BDF_INFO =3D 64, }; @@ -275,6 +276,17 @@ struct comm_cmd_bdf_info { u8 rsvd2[5]; }; =20 +#define COMM_FW_VERSION_LEN 16 +#define COMM_FW_COMPILE_TIME_LEN 20 +struct comm_cmd_get_fw_version { + struct mgmt_msg_head head; + + u16 fw_type; + u16 rsvd1; + u8 ver[COMM_FW_VERSION_LEN]; + u8 time[COMM_FW_COMPILE_TIME_LEN]; +}; + /* Services supported by HW. HW uses these values when delivering events. * HW supports multiple services that are not yet supported by driver * (e.g. RoCE). diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_main.c index 6275d94dfefd..727994e72b2a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c @@ -18,6 +18,7 @@ =20 #define HINIC3_NIC_DRV_DESC "Intelligent Network Interface Card Driver" =20 +#define HINIC3_DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_LINK) #define HINIC3_RX_BUF_LEN 2048 #define HINIC3_LRO_REPLENISH_THLD 256 #define HINIC3_NIC_DEV_WQ_NAME "hinic3_nic_dev_wq" @@ -144,6 +145,7 @@ static int hinic3_init_nic_dev(struct net_device *netde= v, nic_dev->hwdev =3D hwdev; nic_dev->pdev =3D pdev; =20 + nic_dev->msg_enable =3D HINIC3_DEFAULT_MSG_ENABLE; nic_dev->rx_buf_len =3D HINIC3_RX_BUF_LEN; nic_dev->lro_replenish_thld =3D HINIC3_LRO_REPLENISH_THLD; nic_dev->vlan_bitmap =3D kzalloc(HINIC3_VLAN_BITMAP_SIZE(nic_dev), @@ -242,6 +244,7 @@ static void hinic3_sw_uninit(struct net_device *netdev) static void hinic3_assign_netdev_ops(struct net_device *netdev) { hinic3_set_netdev_ops(netdev); + hinic3_set_ethtool_ops(netdev); } =20 static void netdev_feature_init(struct net_device *netdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index c0c87a8c2198..c5bca3c4af96 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -183,7 +183,18 @@ struct l2nic_cmd_lro_timer { /* IEEE 802.1Qaz std */ #define L2NIC_DCB_COS_MAX 0x8 =20 -struct l2nic_cmd_set_rss_ctx_tbl { +struct l2nic_cmd_pause_config { + struct mgmt_msg_head msg_head; + u8 port_id; + u8 opcode; + u16 rsvd1; + u8 auto_neg; + u8 rx_pause; + u8 tx_pause; + u8 rsvd2[5]; +}; + +struct l2nic_cmd_rss_ctx_tbl { struct mgmt_msg_head msg_head; u16 func_id; u16 rsvd1; @@ -238,6 +249,7 @@ enum l2nic_cmd { L2NIC_CMD_CFG_RSS_HASH_KEY =3D 63, L2NIC_CMD_CFG_RSS_HASH_ENGINE =3D 64, L2NIC_CMD_SET_RSS_CTX_TBL =3D 65, + L2NIC_CMD_CFG_PAUSE_INFO =3D 101, L2NIC_CMD_QOS_DCB_STATE =3D 110, L2NIC_CMD_FORCE_PKT_DROP =3D 113, L2NIC_CMD_MAX =3D 256, @@ -259,6 +271,8 @@ enum l2nic_ucode_cmd { enum mag_cmd { MAG_CMD_SET_PORT_ENABLE =3D 6, MAG_CMD_GET_LINK_STATUS =3D 7, + + MAG_CMD_GET_PORT_INFO =3D 153, }; =20 /* firmware also use this cmd report link event to driver */ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 44abccf9cb29..11ef362ace95 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -639,6 +639,39 @@ int hinic3_get_link_status(struct hinic3_hwdev *hwdev,= bool *link_status_up) return 0; } =20 +int hinic3_get_port_info(struct hinic3_hwdev *hwdev, + struct hinic3_nic_port_info *port_info) +{ + struct mag_cmd_get_port_info port_msg =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + port_msg.port_id =3D hinic3_physical_port_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &port_msg, sizeof(port_msg)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK, + MAG_CMD_GET_PORT_INFO, &msg_params); + + if (err || port_msg.head.status) { + dev_err(hwdev->dev, + "Failed to get port info, err: %d, status: 0x%x\n", + err, port_msg.head.status); + return -EFAULT; + } + + port_info->autoneg_cap =3D port_msg.an_support; + port_info->autoneg_state =3D port_msg.an_en; + port_info->duplex =3D port_msg.duplex; + port_info->port_type =3D port_msg.wire_type; + port_info->speed =3D port_msg.speed; + port_info->fec =3D port_msg.fec; + port_info->supported_mode =3D port_msg.supported_mode; + port_info->advertised_mode =3D port_msg.advertised_mode; + + return 0; +} + int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, bool enable) { @@ -661,3 +694,60 @@ int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev= , u16 func_id, =20 return 0; } + +#define UNSUPPORT_SET_PAUSE 0x10 +static int hinic3_cfg_hw_pause(struct hinic3_hwdev *hwdev, u8 opcode, + struct hinic3_nic_pause_config *nic_pause) +{ + struct l2nic_cmd_pause_config pause_info =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + pause_info.port_id =3D hinic3_physical_port_id(hwdev); + pause_info.opcode =3D opcode; + if (opcode =3D=3D MGMT_MSG_CMD_OP_SET) { + pause_info.auto_neg =3D nic_pause->auto_neg; + pause_info.rx_pause =3D nic_pause->rx_pause; + pause_info.tx_pause =3D nic_pause->tx_pause; + } + + mgmt_msg_params_init_default(&msg_params, &pause_info, + sizeof(pause_info)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_CFG_PAUSE_INFO, &msg_params); + + if (err || pause_info.msg_head.status) { + if (pause_info.msg_head.status =3D=3D UNSUPPORT_SET_PAUSE) { + err =3D -EOPNOTSUPP; + dev_err(hwdev->dev, "Can not set pause when pfc is enabled\n"); + } else { + err =3D -EFAULT; + dev_err(hwdev->dev, "Failed to %s pause info, err: %d, status: 0x%x\n", + opcode =3D=3D MGMT_MSG_CMD_OP_SET ? "set" : "get", + err, pause_info.msg_head.status); + } + return err; + } + + if (opcode =3D=3D MGMT_MSG_CMD_OP_GET) { + nic_pause->auto_neg =3D pause_info.auto_neg; + nic_pause->rx_pause =3D pause_info.rx_pause; + nic_pause->tx_pause =3D pause_info.tx_pause; + } + + return 0; +} + +int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev, + struct hinic3_nic_pause_config *nic_pause) +{ + int err; + + err =3D hinic3_cfg_hw_pause(nic_dev->hwdev, MGMT_MSG_CMD_OP_GET, + nic_pause); + if (err) + return err; + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index c32eaa886e17..5d52202a8d4e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -6,6 +6,7 @@ =20 #include =20 +#include "hinic3_hwif.h" #include "hinic3_hw_intf.h" #include "hinic3_mgmt_interface.h" =20 @@ -35,6 +36,49 @@ struct hinic3_sq_attr { u64 ci_dma_base; }; =20 +enum mag_cmd_port_an { + PORT_CFG_AN_ON =3D 1, +}; + +/* mag supported/advertised link mode bitmap */ +enum mag_cmd_link_mode { + LINK_MODE_GE =3D 0, + LINK_MODE_10GE_BASE_R =3D 1, + LINK_MODE_25GE_BASE_R =3D 2, + LINK_MODE_40GE_BASE_R4 =3D 3, + LINK_MODE_50GE_BASE_R =3D 4, + LINK_MODE_50GE_BASE_R2 =3D 5, + LINK_MODE_100GE_BASE_R =3D 6, + LINK_MODE_100GE_BASE_R2 =3D 7, + LINK_MODE_100GE_BASE_R4 =3D 8, + LINK_MODE_200GE_BASE_R2 =3D 9, + LINK_MODE_200GE_BASE_R4 =3D 10, + LINK_MODE_MAX_NUMBERS, + + LINK_MODE_UNKNOWN =3D 0xFFFF +}; + +struct mag_cmd_get_port_info { + struct mgmt_msg_head head; + + u8 port_id; + u8 rsvd0[3]; + + u8 wire_type; + u8 an_support; + u8 an_en; + u8 duplex; + + u8 speed; + u8 fec; + u8 lanes; + u8 rsvd1; + + u32 supported_mode; + u32 advertised_mode; + u8 rsvd2[8]; +}; + #define MAG_CMD_PORT_DISABLE 0x0 #define MAG_CMD_TX_ENABLE 0x1 #define MAG_CMD_RX_ENABLE 0x2 @@ -52,6 +96,39 @@ struct mag_cmd_set_port_enable { u8 rsvd1[3]; }; =20 +/* xsfp wire type, refers to cmis protocol definition */ +enum mag_wire_type { + MAG_CMD_WIRE_TYPE_UNKNOWN =3D 0x0, + MAG_CMD_WIRE_TYPE_MM =3D 0x1, + MAG_CMD_WIRE_TYPE_SM =3D 0x2, + MAG_CMD_WIRE_TYPE_COPPER =3D 0x3, + MAG_CMD_WIRE_TYPE_ACC =3D 0x4, + MAG_CMD_WIRE_TYPE_BASET =3D 0x5, + MAG_CMD_WIRE_TYPE_AOC =3D 0x40, + MAG_CMD_WIRE_TYPE_ELECTRIC =3D 0x41, + MAG_CMD_WIRE_TYPE_BACKPLANE =3D 0x42 +}; + +#define XSFP_INFO_MAX_SIZE 640 +struct mag_cmd_get_xsfp_info { + struct mgmt_msg_head head; + + u8 port_id; + u8 wire_type; + u16 out_len; + u32 rsvd; + u8 sfp_info[XSFP_INFO_MAX_SIZE]; +}; + +struct mag_cmd_get_xsfp_present { + struct mgmt_msg_head head; + + u8 port_id; + /* 0:present, 1:absent */ + u8 abs_status; + u8 rsvd[2]; +}; + enum link_err_type { LINK_ERR_MODULE_UNRECOGENIZED, LINK_ERR_NUM, @@ -69,6 +146,34 @@ struct hinic3_port_module_event { enum link_err_type err_type; }; =20 +struct hinic3_nic_port_info { + u8 port_type; + u8 autoneg_cap; + u8 autoneg_state; + u8 duplex; + u8 speed; + u8 fec; + u32 supported_mode; + u32 advertised_mode; +}; + +struct hinic3_nic_pause_config { + u8 auto_neg; + u8 rx_pause; + u8 tx_pause; +}; + +struct hinic3_nic_cfg { + /* Valid when pfc is disabled */ + bool pause_set; + struct hinic3_nic_pause_config nic_pause; + + u8 pfc_en; + u8 pfc_bitmap; + + struct hinic3_nic_port_info port_info; +}; + int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev); int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev); bool hinic3_test_support(struct hinic3_nic_dev *nic_dev, @@ -100,9 +205,14 @@ int hinic3_set_rx_mode(struct hinic3_hwdev *hwdev, u32= rx_mode); int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state= ); int hinic3_set_port_enable(struct hinic3_hwdev *hwdev, bool enable); int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_u= p); +int hinic3_get_port_info(struct hinic3_hwdev *hwdev, + struct hinic3_nic_port_info *port_info); int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, bool enable); int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); =20 +int hinic3_get_pause_info(struct hinic3_nic_dev *nic_dev, + struct hinic3_nic_pause_config *nic_pause); + #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_dev.h index 29189241f446..9502293ff710 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h @@ -101,6 +101,7 @@ struct hinic3_nic_dev { struct hinic3_hwdev *hwdev; struct hinic3_nic_io *nic_io; =20 + u32 msg_enable; u16 max_qps; u16 rx_buf_len; u32 lro_replenish_thld; @@ -148,4 +149,6 @@ void hinic3_qps_irq_uninit(struct net_device *netdev); void hinic3_set_rx_mode_work(struct work_struct *work); void hinic3_clean_mac_list_filter(struct net_device *netdev); =20 +void hinic3_set_ethtool_ops(struct net_device *netdev); + #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_rss.c index 4ff1b2f79838..25db74d8c7dd 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c @@ -132,7 +132,7 @@ static int hinic3_rss_set_indir_tbl(struct hinic3_hwdev= *hwdev, static int hinic3_set_rss_type(struct hinic3_hwdev *hwdev, struct hinic3_rss_type rss_type) { - struct l2nic_cmd_set_rss_ctx_tbl ctx_tbl =3D {}; + struct l2nic_cmd_rss_ctx_tbl ctx_tbl =3D {}; struct mgmt_msg_params msg_params =3D {}; u32 ctx; int err; --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 931C339E195; Tue, 24 Feb 2026 13:16:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938984; cv=none; b=IjUkuP8QnS6TgSB1zXkZJl+spkx0UA92ul2JO2QbsA/8DMWHbCzrYIR1Y4UwKAcRdMt0b9Z3eBqTymSvAQjGOHIhX/3f9Pfza6C7rZjJRlBF3Njv02i/2PXjpAeMJ7OTCiH9J38krNdJ0ELMe7WVAsHsAzVtjoA1Oa8RCNMwbgE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938984; c=relaxed/simple; bh=KgNHVD1b+WYIbu0kn4xAF1wMKs0E2L6ltQhUhTtuaJY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sJWuqSqxTiGaVfBF/52w4HAOjhIFmLOh3sqlM7sFYHT/3KgvvG1GkBXTxWWxsqxbNmbP0SE6plGa0hk/RAzPDBbrUQAp/6HFf+cvh8Rb/3e8TqWFlexN0nj/c71oaIprDPYuFdkQyFXfz/hGonngq6kcncIatvEbtmlh3HvdOoY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=Gcwp86HK; arc=none smtp.client-ip=113.46.200.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="Gcwp86HK" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=0gyaeJO4L4k4odp9UkT1iqnLL3fHPMi2elyX1HUwspM=; b=Gcwp86HKw9xIDXebcJp4VAebG/Tdv/7zHXKwBu2sv0nGXNcNTEmG4ZmMuEZJo1bfRIcsvKraY bX9tQ42aX0ecLA4BOHlArihKM3n23wislcIDZnGsDKZQY/5RL6Bnz9u2onUmXfdrR644T7kS4KP DrxypEBZJvUG2jv6MIjm78k= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4fKym472LZzKm50; Tue, 24 Feb 2026 21:11:32 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id E313B402AB; Tue, 24 Feb 2026 21:16:19 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:18 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 10/15] hinic3: Add ethtool queue ops Date: Tue, 24 Feb 2026 21:15:47 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 94 +++++++++++++++++++ .../net/ethernet/huawei/hinic3/hinic3_irq.c | 3 +- .../net/ethernet/huawei/hinic3/hinic3_main.c | 3 + .../huawei/hinic3/hinic3_netdev_ops.c | 60 ++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 12 +++ .../ethernet/huawei/hinic3/hinic3_nic_io.h | 4 + 6 files changed, 175 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_ethtool.c index 1b5b8b5a2d20..d155d8c533c7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c @@ -409,6 +409,98 @@ hinic3_get_link_ksettings(struct net_device *netdev, return 0; } =20 +static void hinic3_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring, + struct kernel_ethtool_ringparam *kernel_ring, + struct netlink_ext_ack *extack) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + ring->rx_max_pending =3D HINIC3_MAX_RX_QUEUE_DEPTH; + ring->tx_max_pending =3D HINIC3_MAX_TX_QUEUE_DEPTH; + ring->rx_pending =3D nic_dev->rxqs[0].q_depth; + ring->tx_pending =3D nic_dev->txqs[0].q_depth; +} + +static void hinic3_update_qp_depth(struct net_device *netdev, + u32 sq_depth, u32 rq_depth) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 i; + + nic_dev->q_params.sq_depth =3D sq_depth; + nic_dev->q_params.rq_depth =3D rq_depth; + for (i =3D 0; i < nic_dev->max_qps; i++) { + nic_dev->txqs[i].q_depth =3D sq_depth; + nic_dev->txqs[i].q_mask =3D sq_depth - 1; + nic_dev->rxqs[i].q_depth =3D rq_depth; + nic_dev->rxqs[i].q_mask =3D rq_depth - 1; + } +} + +static int hinic3_check_ringparam_valid(struct net_device *netdev, + const struct ethtool_ringparam *ring) +{ + if (ring->rx_jumbo_pending || ring->rx_mini_pending) { + netdev_err(netdev, "Unsupported rx_jumbo_pending/rx_mini_pending\n"); + return -EINVAL; + } + + if (ring->tx_pending > HINIC3_MAX_TX_QUEUE_DEPTH || + ring->tx_pending < HINIC3_MIN_QUEUE_DEPTH || + ring->rx_pending > HINIC3_MAX_RX_QUEUE_DEPTH || + ring->rx_pending < HINIC3_MIN_QUEUE_DEPTH) { + netdev_err(netdev, + "Queue depth out of rang tx[%d-%d] rx[%d-%d]\n", + HINIC3_MIN_QUEUE_DEPTH, HINIC3_MAX_TX_QUEUE_DEPTH, + HINIC3_MIN_QUEUE_DEPTH, HINIC3_MAX_RX_QUEUE_DEPTH); + return -EINVAL; + } + + return 0; +} + +static int hinic3_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring, + struct kernel_ethtool_ringparam *kernel_ring, + struct netlink_ext_ack *extack) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_txrxq_params q_params =3D {}; + u32 new_sq_depth, new_rq_depth; + int err; + + err =3D hinic3_check_ringparam_valid(netdev, ring); + if (err) + return err; + + new_sq_depth =3D 1U << ilog2(ring->tx_pending); + new_rq_depth =3D 1U << ilog2(ring->rx_pending); + if (new_sq_depth =3D=3D nic_dev->q_params.sq_depth && + new_rq_depth =3D=3D nic_dev->q_params.rq_depth) + return 0; + + netdev_dbg(netdev, "Change Tx/Rx ring depth from %u/%u to %u/%u\n", + nic_dev->q_params.sq_depth, nic_dev->q_params.rq_depth, + new_sq_depth, new_rq_depth); + + if (!netif_running(netdev)) { + hinic3_update_qp_depth(netdev, new_sq_depth, new_rq_depth); + } else { + q_params =3D nic_dev->q_params; + q_params.sq_depth =3D new_sq_depth; + q_params.rq_depth =3D new_rq_depth; + + err =3D hinic3_change_channel_settings(netdev, &q_params); + if (err) { + netdev_err(netdev, "Failed to change channel settings\n"); + return err; + } + } + + return 0; +} + static const struct ethtool_ops hinic3_ethtool_ops =3D { .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_PKT_RATE_RX_USECS, @@ -417,6 +509,8 @@ static const struct ethtool_ops hinic3_ethtool_ops =3D { .get_msglevel =3D hinic3_get_msglevel, .set_msglevel =3D hinic3_set_msglevel, .get_link =3D ethtool_op_get_link, + .get_ringparam =3D hinic3_get_ringparam, + .set_ringparam =3D hinic3_set_ringparam, }; =20 void hinic3_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_irq.c index e7d6c2033b45..fb3865fc986a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c @@ -137,7 +137,8 @@ static int hinic3_set_interrupt_moder(struct net_device= *netdev, u16 q_id, struct hinic3_interrupt_info info =3D {}; int err; =20 - if (q_id >=3D nic_dev->q_params.num_qps) + if (!HINIC3_CHANNEL_RES_VALID(nic_dev) || + q_id >=3D nic_dev->q_params.num_qps) return 0; =20 info.interrupt_coalesc_set =3D 1; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_main.c index 727994e72b2a..1a7126c7810e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c @@ -316,6 +316,9 @@ static void hinic3_link_status_change(struct net_device= *netdev, { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); =20 + if (!HINIC3_CHANNEL_RES_VALID(nic_dev)) + return; + if (link_status_up) { if (netif_carrier_ok(netdev)) return; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index 75b6abdf1024..8bc24aa10b0b 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -430,6 +430,59 @@ static void hinic3_vport_down(struct net_device *netde= v) } } =20 +int +hinic3_change_channel_settings(struct net_device *netdev, + struct hinic3_dyna_txrxq_params *trxq_params) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_dyna_qp_params new_qp_params =3D {}; + struct hinic3_dyna_qp_params cur_qp_params =3D {}; + int err; + + hinic3_config_num_qps(netdev, trxq_params); + + err =3D hinic3_alloc_channel_resources(netdev, &new_qp_params, + trxq_params); + if (err) { + netdev_err(netdev, "Failed to alloc channel resources\n"); + return err; + } + + if (!test_and_set_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags)) { + hinic3_vport_down(netdev); + hinic3_close_channel(netdev); + hinic3_uninit_qps(nic_dev, &cur_qp_params); + hinic3_free_channel_resources(netdev, &cur_qp_params, + &nic_dev->q_params); + } + + if (nic_dev->num_qp_irq > trxq_params->num_qps) + hinic3_qp_irq_change(netdev, trxq_params->num_qps); + nic_dev->q_params =3D *trxq_params; + + hinic3_init_qps(nic_dev, &new_qp_params); + + err =3D hinic3_open_channel(netdev); + if (err) + goto err_uninit_qps; + + err =3D hinic3_vport_up(netdev); + if (err) + goto err_close_channel; + + clear_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags); + + return 0; + +err_close_channel: + hinic3_close_channel(netdev); +err_uninit_qps: + hinic3_uninit_qps(nic_dev, &new_qp_params); + hinic3_free_channel_resources(netdev, &new_qp_params, trxq_params); + + return err; +} + static int hinic3_open(struct net_device *netdev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); @@ -495,11 +548,18 @@ static int hinic3_close(struct net_device *netdev) return 0; } =20 + if (test_and_clear_bit(HINIC3_CHANGE_RES_INVALID, &nic_dev->flags)) + goto out; + hinic3_vport_down(netdev); hinic3_close_channel(netdev); hinic3_uninit_qps(nic_dev, &qp_params); hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); =20 +out: + hinic3_free_nicio_res(nic_dev); + hinic3_destroy_num_qps(netdev); + return 0; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_dev.h index 9502293ff710..a94c3dde421e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h @@ -10,6 +10,9 @@ #include "hinic3_hw_cfg.h" #include "hinic3_hwdev.h" #include "hinic3_mgmt_interface.h" +#include "hinic3_nic_io.h" +#include "hinic3_tx.h" +#include "hinic3_rx.h" =20 #define HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bi= tmap)) #define HINIC3_VLAN_BITMAP_SIZE(nic_dev) \ @@ -20,8 +23,13 @@ enum hinic3_flags { HINIC3_MAC_FILTER_CHANGED, HINIC3_RSS_ENABLE, HINIC3_UPDATE_MAC_FILTER, + HINIC3_CHANGE_RES_INVALID, }; =20 +#define HINIC3_CHANNEL_RES_VALID(nic_dev) \ + (test_bit(HINIC3_INTF_UP, &(nic_dev)->flags) && \ + !test_bit(HINIC3_CHANGE_RES_INVALID, &(nic_dev)->flags)) + enum hinic3_event_work_flags { HINIC3_EVENT_WORK_TX_TIMEOUT, }; @@ -143,6 +151,10 @@ struct hinic3_nic_dev { =20 void hinic3_set_netdev_ops(struct net_device *netdev); int hinic3_set_hw_features(struct net_device *netdev); +int +hinic3_change_channel_settings(struct net_device *netdev, + struct hinic3_dyna_txrxq_params *trxq_params); + int hinic3_qps_irq_init(struct net_device *netdev); void hinic3_qps_irq_uninit(struct net_device *netdev); =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.h index 12eefabcf1db..3791b9bc865b 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h @@ -14,6 +14,10 @@ struct hinic3_nic_dev; #define HINIC3_RQ_WQEBB_SHIFT 3 #define HINIC3_SQ_WQEBB_SIZE BIT(HINIC3_SQ_WQEBB_SHIFT) =20 +#define HINIC3_MAX_TX_QUEUE_DEPTH 65536 +#define HINIC3_MAX_RX_QUEUE_DEPTH 16384 +#define HINIC3_MIN_QUEUE_DEPTH 128 + /* ******************** RQ_CTRL ******************** */ enum hinic3_rq_wqe_type { HINIC3_NORMAL_RQ_WQE =3D 1, --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3A3C33A1A3D; Tue, 24 Feb 2026 13:16:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938989; cv=none; b=FgucyPFszmRcDRGFJBnIF1uG+tl3o87JSDayWJpAlv71t+x3aprU9lICdN5yOwsSZ80bQoML3w25QvGyJ4ODpUaACnOkCRrHkgz5x+82hQT2vvDLeAXFL1H9KAowM1WDAmPl2Ms0YSUIoW7A+rkbhGVxyqjwmli0/0MwgZ2kOMc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938989; c=relaxed/simple; bh=98Wj99HSV5Al8LWedN3mb1cebsKw4eJRqW7T0HvRXks=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ceCuCxbdVeMMWvaqI/xpdQZCD8J9nXgcNZR11+71YgKuOGKIxrAuHUBWImBuvwfXLMF+oHnT0QlY5gYDqQB9qOBx+YDFUh5C0DU8hZiKg7WYn/aJFKeRNQtK3LqXUUSbvtceS8eK+qnW+LcL6JhySc3dBQBH0UVVGYinT5gvy6g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=TUzbKZdI; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="TUzbKZdI" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=kma0hz3STBGSZ6ldhWjWbS6B+jp7JplQW86qgN8w3tI=; b=TUzbKZdIZ3nzXzYUM18CcVjGwSywUbDVeYXRXy7zOCLKXBFLGaMd0PrLCkHD8Aq0j26nETIb9 K6PmOqhK0gvLcoTc7nHQp8blDWvmjBTc86EYwZQFmqyBiwLqsQ/hGjC9WNuIsl0EFm5qU7k3IcD XoFCsYiIYM2wGH0DWygrWLU= Received: from mail.maildlp.com (unknown [172.19.162.92]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4fKym7389wz1cyPh; Tue, 24 Feb 2026 21:11:35 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 7C5F140565; Tue, 24 Feb 2026 21:16:21 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:20 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 11/15] hinic3: Add ethtool statistic ops Date: Tue, 24 Feb 2026 21:15:48 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 414 ++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_hw_intf.h | 13 +- .../huawei/hinic3/hinic3_mgmt_interface.h | 37 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 64 +++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 109 +++++ .../ethernet/huawei/hinic3/hinic3_nic_dev.h | 15 + .../net/ethernet/huawei/hinic3/hinic3_rx.c | 58 ++- .../net/ethernet/huawei/hinic3/hinic3_rx.h | 14 + .../net/ethernet/huawei/hinic3/hinic3_tx.c | 72 ++- .../net/ethernet/huawei/hinic3/hinic3_tx.h | 2 + 10 files changed, 789 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_ethtool.c index d155d8c533c7..ea0b2df73e9f 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c @@ -501,6 +501,417 @@ static int hinic3_set_ringparam(struct net_device *ne= tdev, return 0; } =20 +struct hinic3_stats { + char name[ETH_GSTRING_LEN]; + u32 size; + int offset; +}; + +#define HINIC3_NETDEV_STAT(_stat_item) { \ + .name =3D #_stat_item, \ + .size =3D sizeof_field(struct rtnl_link_stats64, _stat_item), \ + .offset =3D offsetof(struct rtnl_link_stats64, _stat_item) \ +} + +static const struct hinic3_stats hinic3_netdev_stats[] =3D { + HINIC3_NETDEV_STAT(rx_packets), + HINIC3_NETDEV_STAT(tx_packets), + HINIC3_NETDEV_STAT(rx_bytes), + HINIC3_NETDEV_STAT(tx_bytes), + HINIC3_NETDEV_STAT(rx_errors), + HINIC3_NETDEV_STAT(tx_errors), + HINIC3_NETDEV_STAT(rx_dropped), + HINIC3_NETDEV_STAT(tx_dropped), + HINIC3_NETDEV_STAT(multicast), + HINIC3_NETDEV_STAT(collisions), + HINIC3_NETDEV_STAT(rx_length_errors), + HINIC3_NETDEV_STAT(rx_over_errors), + HINIC3_NETDEV_STAT(rx_crc_errors), + HINIC3_NETDEV_STAT(rx_frame_errors), + HINIC3_NETDEV_STAT(rx_fifo_errors), + HINIC3_NETDEV_STAT(rx_missed_errors), + HINIC3_NETDEV_STAT(tx_aborted_errors), + HINIC3_NETDEV_STAT(tx_carrier_errors), + HINIC3_NETDEV_STAT(tx_fifo_errors), + HINIC3_NETDEV_STAT(tx_heartbeat_errors), +}; + +#define HINIC3_NIC_STAT(_stat_item) { \ + .name =3D #_stat_item, \ + .size =3D sizeof_field(struct hinic3_nic_stats, _stat_item), \ + .offset =3D offsetof(struct hinic3_nic_stats, _stat_item) \ +} + +#define HINIC3_RXQ_STAT(_stat_item) { \ + .name =3D "rxq%d_"#_stat_item, \ + .size =3D sizeof_field(struct hinic3_rxq_stats, _stat_item), \ + .offset =3D offsetof(struct hinic3_rxq_stats, _stat_item) \ +} + +#define HINIC3_TXQ_STAT(_stat_item) { \ + .name =3D "txq%d_"#_stat_item, \ + .size =3D sizeof_field(struct hinic3_txq_stats, _stat_item), \ + .offset =3D offsetof(struct hinic3_txq_stats, _stat_item) \ +} + +static struct hinic3_stats hinic3_rx_queue_stats[] =3D { + HINIC3_RXQ_STAT(packets), + HINIC3_RXQ_STAT(bytes), + HINIC3_RXQ_STAT(errors), + HINIC3_RXQ_STAT(csum_errors), + HINIC3_RXQ_STAT(other_errors), + HINIC3_RXQ_STAT(dropped), + HINIC3_RXQ_STAT(rx_buf_empty), + HINIC3_RXQ_STAT(alloc_skb_err), + HINIC3_RXQ_STAT(alloc_rx_buf_err), + HINIC3_RXQ_STAT(restore_drop_sge), +}; + +static struct hinic3_stats hinic3_tx_queue_stats[] =3D { + HINIC3_TXQ_STAT(packets), + HINIC3_TXQ_STAT(bytes), + HINIC3_TXQ_STAT(busy), + HINIC3_TXQ_STAT(dropped), + HINIC3_TXQ_STAT(skb_pad_err), + HINIC3_TXQ_STAT(frag_len_overflow), + HINIC3_TXQ_STAT(offload_cow_skb_err), + HINIC3_TXQ_STAT(map_frag_err), + HINIC3_TXQ_STAT(unknown_tunnel_pkt), + HINIC3_TXQ_STAT(frag_size_err), +}; + +#define HINIC3_FUNC_STAT(_stat_item) { \ + .name =3D #_stat_item, \ + .size =3D sizeof_field(struct l2nic_vport_stats, _stat_item), \ + .offset =3D offsetof(struct l2nic_vport_stats, _stat_item) \ +} + +static struct hinic3_stats hinic3_function_stats[] =3D { + HINIC3_FUNC_STAT(tx_unicast_pkts_vport), + HINIC3_FUNC_STAT(tx_unicast_bytes_vport), + HINIC3_FUNC_STAT(tx_multicast_pkts_vport), + HINIC3_FUNC_STAT(tx_multicast_bytes_vport), + HINIC3_FUNC_STAT(tx_broadcast_pkts_vport), + HINIC3_FUNC_STAT(tx_broadcast_bytes_vport), + + HINIC3_FUNC_STAT(rx_unicast_pkts_vport), + HINIC3_FUNC_STAT(rx_unicast_bytes_vport), + HINIC3_FUNC_STAT(rx_multicast_pkts_vport), + HINIC3_FUNC_STAT(rx_multicast_bytes_vport), + HINIC3_FUNC_STAT(rx_broadcast_pkts_vport), + HINIC3_FUNC_STAT(rx_broadcast_bytes_vport), + + HINIC3_FUNC_STAT(tx_discard_vport), + HINIC3_FUNC_STAT(rx_discard_vport), + HINIC3_FUNC_STAT(tx_err_vport), + HINIC3_FUNC_STAT(rx_err_vport), +}; + +#define HINIC3_PORT_STAT(_stat_item) { \ + .name =3D #_stat_item, \ + .size =3D sizeof_field(struct mag_cmd_port_stats, _stat_item), \ + .offset =3D offsetof(struct mag_cmd_port_stats, _stat_item) \ +} + +static struct hinic3_stats hinic3_port_stats[] =3D { + HINIC3_PORT_STAT(mac_tx_fragment_pkt_num), + HINIC3_PORT_STAT(mac_tx_undersize_pkt_num), + HINIC3_PORT_STAT(mac_tx_undermin_pkt_num), + HINIC3_PORT_STAT(mac_tx_64_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_65_127_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_128_255_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_256_511_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_512_1023_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_1024_1518_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_1519_2047_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_2048_4095_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_4096_8191_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_8192_9216_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_9217_12287_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_12288_16383_oct_pkt_num), + HINIC3_PORT_STAT(mac_tx_1519_max_bad_pkt_num), + HINIC3_PORT_STAT(mac_tx_1519_max_good_pkt_num), + HINIC3_PORT_STAT(mac_tx_oversize_pkt_num), + HINIC3_PORT_STAT(mac_tx_jabber_pkt_num), + HINIC3_PORT_STAT(mac_tx_bad_pkt_num), + HINIC3_PORT_STAT(mac_tx_bad_oct_num), + HINIC3_PORT_STAT(mac_tx_good_pkt_num), + HINIC3_PORT_STAT(mac_tx_good_oct_num), + HINIC3_PORT_STAT(mac_tx_total_pkt_num), + HINIC3_PORT_STAT(mac_tx_total_oct_num), + HINIC3_PORT_STAT(mac_tx_uni_pkt_num), + HINIC3_PORT_STAT(mac_tx_multi_pkt_num), + HINIC3_PORT_STAT(mac_tx_broad_pkt_num), + HINIC3_PORT_STAT(mac_tx_pause_num), + HINIC3_PORT_STAT(mac_tx_pfc_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri0_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri1_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri2_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri3_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri4_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri5_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri6_pkt_num), + HINIC3_PORT_STAT(mac_tx_pfc_pri7_pkt_num), + HINIC3_PORT_STAT(mac_tx_control_pkt_num), + HINIC3_PORT_STAT(mac_tx_err_all_pkt_num), + HINIC3_PORT_STAT(mac_tx_from_app_good_pkt_num), + HINIC3_PORT_STAT(mac_tx_from_app_bad_pkt_num), + + HINIC3_PORT_STAT(mac_rx_fragment_pkt_num), + HINIC3_PORT_STAT(mac_rx_undersize_pkt_num), + HINIC3_PORT_STAT(mac_rx_undermin_pkt_num), + HINIC3_PORT_STAT(mac_rx_64_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_65_127_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_128_255_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_256_511_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_512_1023_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_1024_1518_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_1519_2047_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_2048_4095_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_4096_8191_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_8192_9216_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_9217_12287_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_12288_16383_oct_pkt_num), + HINIC3_PORT_STAT(mac_rx_1519_max_bad_pkt_num), + HINIC3_PORT_STAT(mac_rx_1519_max_good_pkt_num), + HINIC3_PORT_STAT(mac_rx_oversize_pkt_num), + HINIC3_PORT_STAT(mac_rx_jabber_pkt_num), + HINIC3_PORT_STAT(mac_rx_bad_pkt_num), + HINIC3_PORT_STAT(mac_rx_bad_oct_num), + HINIC3_PORT_STAT(mac_rx_good_pkt_num), + HINIC3_PORT_STAT(mac_rx_good_oct_num), + HINIC3_PORT_STAT(mac_rx_total_pkt_num), + HINIC3_PORT_STAT(mac_rx_total_oct_num), + HINIC3_PORT_STAT(mac_rx_uni_pkt_num), + HINIC3_PORT_STAT(mac_rx_multi_pkt_num), + HINIC3_PORT_STAT(mac_rx_broad_pkt_num), + HINIC3_PORT_STAT(mac_rx_pause_num), + HINIC3_PORT_STAT(mac_rx_pfc_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri0_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri1_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri2_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri3_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri4_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri5_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri6_pkt_num), + HINIC3_PORT_STAT(mac_rx_pfc_pri7_pkt_num), + HINIC3_PORT_STAT(mac_rx_control_pkt_num), + HINIC3_PORT_STAT(mac_rx_sym_err_pkt_num), + HINIC3_PORT_STAT(mac_rx_fcs_err_pkt_num), + HINIC3_PORT_STAT(mac_rx_send_app_good_pkt_num), + HINIC3_PORT_STAT(mac_rx_send_app_bad_pkt_num), + HINIC3_PORT_STAT(mac_rx_unfilter_pkt_num), +}; + +static int hinic3_get_sset_count(struct net_device *netdev, int sset) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int count, q_num; + + switch (sset) { + case ETH_SS_STATS: + q_num =3D nic_dev->q_params.num_qps; + count =3D ARRAY_SIZE(hinic3_netdev_stats) + + ARRAY_SIZE(hinic3_function_stats) + + (ARRAY_SIZE(hinic3_tx_queue_stats) + + ARRAY_SIZE(hinic3_rx_queue_stats)) * + q_num; + + if (!HINIC3_IS_VF(nic_dev->hwdev)) + count +=3D ARRAY_SIZE(hinic3_port_stats); + + return count; + default: + return -EOPNOTSUPP; + } +} + +static u64 get_val_of_ptr(u32 size, const void *ptr) +{ + u64 ret =3D size =3D=3D sizeof(u64) ? *(u64 *)ptr : + size =3D=3D sizeof(u32) ? *(u32 *)ptr : + size =3D=3D sizeof(u16) ? *(u16 *)ptr : + *(u8 *)ptr; + + return ret; +} + +static void hinic3_get_drv_queue_stats(struct net_device *netdev, u64 *dat= a) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_txq_stats txq_stats =3D {}; + struct hinic3_rxq_stats rxq_stats =3D {}; + u16 i =3D 0, j, qid; + char *p; + + for (qid =3D 0; qid < nic_dev->q_params.num_qps; qid++) { + if (!nic_dev->txqs) + break; + + hinic3_txq_get_stats(&nic_dev->txqs[qid], &txq_stats); + for (j =3D 0; j < ARRAY_SIZE(hinic3_tx_queue_stats); j++, i++) { + p =3D (char *)&txq_stats + + hinic3_tx_queue_stats[j].offset; + data[i] =3D get_val_of_ptr(hinic3_tx_queue_stats[j].size, + p); + } + } + + for (qid =3D 0; qid < nic_dev->q_params.num_qps; qid++) { + if (!nic_dev->rxqs) + break; + + hinic3_rxq_get_stats(&nic_dev->rxqs[qid], &rxq_stats); + for (j =3D 0; j < ARRAY_SIZE(hinic3_rx_queue_stats); j++, i++) { + p =3D (char *)&rxq_stats + + hinic3_rx_queue_stats[j].offset; + data[i] =3D get_val_of_ptr(hinic3_rx_queue_stats[j].size, + p); + } + } +} + +static u16 hinic3_get_ethtool_port_stats(struct net_device *netdev, u64 *d= ata) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct mag_cmd_port_stats *port_stats; + u16 i =3D 0, j; + char *p; + int err; + + port_stats =3D kmalloc_obj(*port_stats, GFP_KERNEL); + if (!port_stats) { + memset(&data[i], 0, + ARRAY_SIZE(hinic3_port_stats) * sizeof(*data)); + i +=3D ARRAY_SIZE(hinic3_port_stats); + return i; + } + + err =3D hinic3_get_phy_port_stats(nic_dev->hwdev, port_stats); + if (err) + netdev_err(netdev, "Failed to get port stats from fw\n"); + + for (j =3D 0; j < ARRAY_SIZE(hinic3_port_stats); j++, i++) { + p =3D (char *)port_stats + hinic3_port_stats[j].offset; + data[i] =3D get_val_of_ptr(hinic3_port_stats[j].size, p); + } + + kfree(port_stats); + + return i; +} + +static void hinic3_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, u64 *data) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct l2nic_vport_stats vport_stats =3D {}; + const struct rtnl_link_stats64 *net_stats; + struct rtnl_link_stats64 temp; + u16 i =3D 0, j; + char *p; + int err; + + net_stats =3D dev_get_stats(netdev, &temp); + for (j =3D 0; j < ARRAY_SIZE(hinic3_netdev_stats); j++, i++) { + p =3D (char *)net_stats + hinic3_netdev_stats[j].offset; + data[i] =3D get_val_of_ptr(hinic3_netdev_stats[j].size, p); + } + + err =3D hinic3_get_vport_stats(nic_dev->hwdev, + hinic3_global_func_id(nic_dev->hwdev), + &vport_stats); + if (err) + netdev_err(netdev, "Failed to get function stats from fw\n"); + + for (j =3D 0; j < ARRAY_SIZE(hinic3_function_stats); j++, i++) { + p =3D (char *)&vport_stats + hinic3_function_stats[j].offset; + data[i] =3D get_val_of_ptr(hinic3_function_stats[j].size, p); + } + + if (!HINIC3_IS_VF(nic_dev->hwdev)) + i +=3D hinic3_get_ethtool_port_stats(netdev, data + i); + + hinic3_get_drv_queue_stats(netdev, data + i); +} + +static u16 hinic3_get_drv_dev_strings(char *p) +{ + u16 i, cnt =3D 0; + + for (i =3D 0; i < ARRAY_SIZE(hinic3_netdev_stats); i++) { + memcpy(p, hinic3_netdev_stats[i].name, ETH_GSTRING_LEN); + p +=3D ETH_GSTRING_LEN; + cnt++; + } + + return cnt; +} + +static u16 hinic3_get_hw_stats_strings(struct net_device *netdev, char *p) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 i, cnt =3D 0; + + for (i =3D 0; i < ARRAY_SIZE(hinic3_function_stats); i++) { + memcpy(p, hinic3_function_stats[i].name, ETH_GSTRING_LEN); + p +=3D ETH_GSTRING_LEN; + cnt++; + } + + if (!HINIC3_IS_VF(nic_dev->hwdev)) { + for (i =3D 0; i < ARRAY_SIZE(hinic3_port_stats); i++) { + memcpy(p, hinic3_port_stats[i].name, ETH_GSTRING_LEN); + p +=3D ETH_GSTRING_LEN; + cnt++; + } + } + + return cnt; +} + +static void hinic3_get_qp_stats_strings(const struct net_device *netdev, + char *p) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u8 *data =3D p; + u16 i, j; + + for (i =3D 0; i < nic_dev->q_params.num_qps; i++) { + for (j =3D 0; j < ARRAY_SIZE(hinic3_tx_queue_stats); j++) + ethtool_sprintf(&data, + hinic3_tx_queue_stats[j].name, i); + } + + for (i =3D 0; i < nic_dev->q_params.num_qps; i++) { + for (j =3D 0; j < ARRAY_SIZE(hinic3_rx_queue_stats); j++) + ethtool_sprintf(&data, + hinic3_rx_queue_stats[j].name, i); + } +} + +static void hinic3_get_strings(struct net_device *netdev, + u32 stringset, u8 *data) +{ + char *p =3D (char *)data; + u16 offset; + + switch (stringset) { + case ETH_SS_STATS: + offset =3D hinic3_get_drv_dev_strings(p); + offset +=3D hinic3_get_hw_stats_strings(netdev, p + + offset * + ETH_GSTRING_LEN); + hinic3_get_qp_stats_strings(netdev, + p + offset * ETH_GSTRING_LEN); + + return; + default: + netdev_err(netdev, "Invalid string set %u.\n", stringset); + return; + } +} + static const struct ethtool_ops hinic3_ethtool_ops =3D { .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_PKT_RATE_RX_USECS, @@ -511,6 +922,9 @@ static const struct ethtool_ops hinic3_ethtool_ops =3D { .get_link =3D ethtool_op_get_link, .get_ringparam =3D hinic3_get_ringparam, .set_ringparam =3D hinic3_set_ringparam, + .get_sset_count =3D hinic3_get_sset_count, + .get_ethtool_stats =3D hinic3_get_ethtool_stats, + .get_strings =3D hinic3_get_strings, }; =20 void hinic3_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_intf.h index cfc9daa3034f..0b2ebef04c02 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_intf.h @@ -51,7 +51,18 @@ static inline void mgmt_msg_params_init_default(struct m= gmt_msg_params *msg_para msg_params->in_size =3D buf_size; msg_params->expected_out_size =3D buf_size; msg_params->timeout_ms =3D 0; -} +}; + +static inline void +mgmt_msg_params_init_in_out(struct mgmt_msg_params *msg_params, void *in_b= uf, + void *out_buf, u32 in_buf_size, u32 out_buf_size) +{ + msg_params->buf_in =3D in_buf; + msg_params->buf_out =3D out_buf; + msg_params->in_size =3D in_buf_size; + msg_params->expected_out_size =3D out_buf_size; + msg_params->timeout_ms =3D 0; +}; =20 enum cfg_cmd { CFG_CMD_GET_DEV_CAP =3D 0, diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index c5bca3c4af96..76c691f82703 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -143,6 +143,41 @@ struct l2nic_cmd_set_dcb_state { u8 rsvd[7]; }; =20 +struct l2nic_port_stats_info { + struct mgmt_msg_head msg_head; + u16 func_id; + u16 rsvd1; +}; + +struct l2nic_vport_stats { + u64 tx_unicast_pkts_vport; + u64 tx_unicast_bytes_vport; + u64 tx_multicast_pkts_vport; + u64 tx_multicast_bytes_vport; + u64 tx_broadcast_pkts_vport; + u64 tx_broadcast_bytes_vport; + + u64 rx_unicast_pkts_vport; + u64 rx_unicast_bytes_vport; + u64 rx_multicast_pkts_vport; + u64 rx_multicast_bytes_vport; + u64 rx_broadcast_pkts_vport; + u64 rx_broadcast_bytes_vport; + + u64 tx_discard_vport; + u64 rx_discard_vport; + u64 tx_err_vport; + u64 rx_err_vport; +}; + +struct l2nic_cmd_vport_stats { + struct mgmt_msg_head msg_head; + u32 stats_size; + u32 rsvd1; + struct l2nic_vport_stats stats; + u64 rsvd2[6]; +}; + struct l2nic_cmd_lro_config { struct mgmt_msg_head msg_head; u16 func_id; @@ -234,6 +269,7 @@ enum l2nic_cmd { L2NIC_CMD_SET_VPORT_ENABLE =3D 6, L2NIC_CMD_SET_RX_MODE =3D 7, L2NIC_CMD_SET_SQ_CI_ATTR =3D 8, + L2NIC_CMD_GET_VPORT_STAT =3D 9, L2NIC_CMD_CLEAR_QP_RESOURCE =3D 11, L2NIC_CMD_CFG_RX_LRO =3D 13, L2NIC_CMD_CFG_LRO_TIMER =3D 14, @@ -272,6 +308,7 @@ enum mag_cmd { MAG_CMD_SET_PORT_ENABLE =3D 6, MAG_CMD_GET_LINK_STATUS =3D 7, =20 + MAG_CMD_GET_PORT_STAT =3D 151, MAG_CMD_GET_PORT_INFO =3D 153, }; =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 11ef362ace95..a1a193201afd 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -639,6 +639,42 @@ int hinic3_get_link_status(struct hinic3_hwdev *hwdev,= bool *link_status_up) return 0; } =20 +int hinic3_get_phy_port_stats(struct hinic3_hwdev *hwdev, + struct mag_cmd_port_stats *stats) +{ + struct mag_cmd_port_stats_info stats_info =3D {}; + struct mag_cmd_get_port_stat *port_stats; + struct mgmt_msg_params msg_params =3D {}; + int err; + + port_stats =3D kzalloc_obj(*port_stats, GFP_KERNEL); + if (!port_stats) + return -ENOMEM; + + stats_info.port_id =3D hinic3_physical_port_id(hwdev); + + mgmt_msg_params_init_in_out(&msg_params, &stats_info, port_stats, + sizeof(stats_info), sizeof(*port_stats)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK, + MAG_CMD_GET_PORT_STAT, &msg_params); + + if (err || stats_info.head.status) { + dev_err(hwdev->dev, + "Failed to get port statistics, err: %d, status: 0x%x\n", + err, stats_info.head.status); + err =3D -EFAULT; + goto out; + } + + memcpy(stats, &port_stats->counter, sizeof(*stats)); + +out: + kfree(port_stats); + + return err; +} + int hinic3_get_port_info(struct hinic3_hwdev *hwdev, struct hinic3_nic_port_info *port_info) { @@ -751,3 +787,31 @@ int hinic3_get_pause_info(struct hinic3_nic_dev *nic_d= ev, =20 return 0; } + +int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id, + struct l2nic_vport_stats *stats) +{ + struct l2nic_cmd_vport_stats vport_stats =3D {}; + struct l2nic_port_stats_info stats_info =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + stats_info.func_id =3D func_id; + + mgmt_msg_params_init_in_out(&msg_params, &stats_info, &vport_stats, + sizeof(stats_info), sizeof(vport_stats)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_GET_VPORT_STAT, &msg_params); + + if (err || vport_stats.msg_head.status) { + dev_err(hwdev->dev, + "Failed to get function statistics, err: %d, status: 0x%x\n", + err, vport_stats.msg_head.status); + return -EFAULT; + } + + memcpy(stats, &vport_stats.stats, sizeof(*stats)); + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index 5d52202a8d4e..80573c121539 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -129,6 +129,110 @@ struct mag_cmd_get_xsfp_present { u8 rsvd[2]; }; =20 +struct mag_cmd_port_stats { + u64 mac_tx_fragment_pkt_num; + u64 mac_tx_undersize_pkt_num; + u64 mac_tx_undermin_pkt_num; + u64 mac_tx_64_oct_pkt_num; + u64 mac_tx_65_127_oct_pkt_num; + u64 mac_tx_128_255_oct_pkt_num; + u64 mac_tx_256_511_oct_pkt_num; + u64 mac_tx_512_1023_oct_pkt_num; + u64 mac_tx_1024_1518_oct_pkt_num; + u64 mac_tx_1519_2047_oct_pkt_num; + u64 mac_tx_2048_4095_oct_pkt_num; + u64 mac_tx_4096_8191_oct_pkt_num; + u64 mac_tx_8192_9216_oct_pkt_num; + u64 mac_tx_9217_12287_oct_pkt_num; + u64 mac_tx_12288_16383_oct_pkt_num; + u64 mac_tx_1519_max_bad_pkt_num; + u64 mac_tx_1519_max_good_pkt_num; + u64 mac_tx_oversize_pkt_num; + u64 mac_tx_jabber_pkt_num; + u64 mac_tx_bad_pkt_num; + u64 mac_tx_bad_oct_num; + u64 mac_tx_good_pkt_num; + u64 mac_tx_good_oct_num; + u64 mac_tx_total_pkt_num; + u64 mac_tx_total_oct_num; + u64 mac_tx_uni_pkt_num; + u64 mac_tx_multi_pkt_num; + u64 mac_tx_broad_pkt_num; + u64 mac_tx_pause_num; + u64 mac_tx_pfc_pkt_num; + u64 mac_tx_pfc_pri0_pkt_num; + u64 mac_tx_pfc_pri1_pkt_num; + u64 mac_tx_pfc_pri2_pkt_num; + u64 mac_tx_pfc_pri3_pkt_num; + u64 mac_tx_pfc_pri4_pkt_num; + u64 mac_tx_pfc_pri5_pkt_num; + u64 mac_tx_pfc_pri6_pkt_num; + u64 mac_tx_pfc_pri7_pkt_num; + u64 mac_tx_control_pkt_num; + u64 mac_tx_err_all_pkt_num; + u64 mac_tx_from_app_good_pkt_num; + u64 mac_tx_from_app_bad_pkt_num; + + u64 mac_rx_fragment_pkt_num; + u64 mac_rx_undersize_pkt_num; + u64 mac_rx_undermin_pkt_num; + u64 mac_rx_64_oct_pkt_num; + u64 mac_rx_65_127_oct_pkt_num; + u64 mac_rx_128_255_oct_pkt_num; + u64 mac_rx_256_511_oct_pkt_num; + u64 mac_rx_512_1023_oct_pkt_num; + u64 mac_rx_1024_1518_oct_pkt_num; + u64 mac_rx_1519_2047_oct_pkt_num; + u64 mac_rx_2048_4095_oct_pkt_num; + u64 mac_rx_4096_8191_oct_pkt_num; + u64 mac_rx_8192_9216_oct_pkt_num; + u64 mac_rx_9217_12287_oct_pkt_num; + u64 mac_rx_12288_16383_oct_pkt_num; + u64 mac_rx_1519_max_bad_pkt_num; + u64 mac_rx_1519_max_good_pkt_num; + u64 mac_rx_oversize_pkt_num; + u64 mac_rx_jabber_pkt_num; + u64 mac_rx_bad_pkt_num; + u64 mac_rx_bad_oct_num; + u64 mac_rx_good_pkt_num; + u64 mac_rx_good_oct_num; + u64 mac_rx_total_pkt_num; + u64 mac_rx_total_oct_num; + u64 mac_rx_uni_pkt_num; + u64 mac_rx_multi_pkt_num; + u64 mac_rx_broad_pkt_num; + u64 mac_rx_pause_num; + u64 mac_rx_pfc_pkt_num; + u64 mac_rx_pfc_pri0_pkt_num; + u64 mac_rx_pfc_pri1_pkt_num; + u64 mac_rx_pfc_pri2_pkt_num; + u64 mac_rx_pfc_pri3_pkt_num; + u64 mac_rx_pfc_pri4_pkt_num; + u64 mac_rx_pfc_pri5_pkt_num; + u64 mac_rx_pfc_pri6_pkt_num; + u64 mac_rx_pfc_pri7_pkt_num; + u64 mac_rx_control_pkt_num; + u64 mac_rx_sym_err_pkt_num; + u64 mac_rx_fcs_err_pkt_num; + u64 mac_rx_send_app_good_pkt_num; + u64 mac_rx_send_app_bad_pkt_num; + u64 mac_rx_unfilter_pkt_num; +}; + +struct mag_cmd_port_stats_info { + struct mgmt_msg_head head; + + u8 port_id; + u8 rsvd0[3]; +}; + +struct mag_cmd_get_port_stat { + struct mgmt_msg_head head; + + struct mag_cmd_port_stats counter; + u64 rsvd1[15]; +}; + enum link_err_type { LINK_ERR_MODULE_UNRECOGENIZED, LINK_ERR_NUM, @@ -209,6 +313,11 @@ int hinic3_get_port_info(struct hinic3_hwdev *hwdev, struct hinic3_nic_port_info *port_info); int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id, bool enable); +int hinic3_get_phy_port_stats(struct hinic3_hwdev *hwdev, + struct mag_cmd_port_stats *stats); +int hinic3_get_vport_stats(struct hinic3_hwdev *hwdev, u16 func_id, + struct l2nic_vport_stats *stats); + int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id); =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_dev.h index a94c3dde421e..107bf392f5ed 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h @@ -34,6 +34,20 @@ enum hinic3_event_work_flags { HINIC3_EVENT_WORK_TX_TIMEOUT, }; =20 +#define HINIC3_NIC_STATS_INC(nic_dev, field) \ +do { \ + u64_stats_update_begin(&(nic_dev)->stats.syncp); \ + (nic_dev)->stats.field++; \ + u64_stats_update_end(&(nic_dev)->stats.syncp); \ +} while (0) + +struct hinic3_nic_stats { + /* Subdivision statistics show in private tool */ + u64 tx_carrier_off_drop; + u64 tx_invalid_qid; + struct u64_stats_sync syncp; +}; + enum hinic3_rx_mode_state { HINIC3_HW_PROMISC_ON, HINIC3_HW_ALLMULTI_ON, @@ -120,6 +134,7 @@ struct hinic3_nic_dev { struct hinic3_dyna_txrxq_params q_params; struct hinic3_txq *txqs; struct hinic3_rxq *rxqs; + struct hinic3_nic_stats stats; =20 enum hinic3_rss_hash_type rss_hash_type; struct hinic3_rss_type rss_type; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.c index fe7fdd06c1b6..802ec9dffcd9 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c @@ -29,10 +29,17 @@ #define HINIC3_LRO_PKT_HDR_LEN_IPV4 66 #define HINIC3_LRO_PKT_HDR_LEN_IPV6 86 #define HINIC3_LRO_PKT_HDR_LEN(cqe) \ - (RQ_CQE_OFFOLAD_TYPE_GET((cqe)->offload_type, IP_TYPE) =3D=3D \ + (RQ_CQE_OFFOLAD_TYPE_GET(le32_to_cpu((cqe)->offload_type), IP_TYPE) =3D= =3D \ HINIC3_RX_IPV6_PKT ? HINIC3_LRO_PKT_HDR_LEN_IPV6 : \ HINIC3_LRO_PKT_HDR_LEN_IPV4) =20 +#define RXQ_STATS_INC(rxq, field) \ +do { \ + u64_stats_update_begin(&(rxq)->rxq_stats.syncp); \ + (rxq)->rxq_stats.field++; \ + u64_stats_update_end(&(rxq)->rxq_stats.syncp); \ +} while (0) + static void hinic3_rxq_clean_stats(struct hinic3_rxq_stats *rxq_stats) { u64_stats_update_begin(&rxq_stats->syncp); @@ -155,8 +162,10 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *r= xq) =20 err =3D rx_alloc_mapped_page(rxq->page_pool, rx_info, rxq->buf_len); - if (unlikely(err)) + if (unlikely(err)) { + RXQ_STATS_INC(rxq, alloc_rx_buf_err); break; + } =20 dma_addr =3D page_pool_get_dma_addr(rx_info->page) + rx_info->page_offset; @@ -170,6 +179,8 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rx= q) rxq->next_to_update << HINIC3_NORMAL_RQ_WQE); rxq->delta -=3D i; rxq->next_to_alloc =3D rxq->next_to_update; + } else if (free_wqebbs =3D=3D rxq->q_depth - 1) { + RXQ_STATS_INC(rxq, rx_buf_empty); } =20 return i; @@ -329,11 +340,17 @@ static void hinic3_rx_csum(struct hinic3_rxq *rxq, u3= 2 offload_type, u32 csum_err =3D RQ_CQE_STATUS_GET(status, CSUM_ERR); struct net_device *netdev =3D rxq->netdev; =20 + if (unlikely(csum_err =3D=3D HINIC3_RX_CSUM_IPSU_OTHER_ERR)) + rxq->rxq_stats.other_errors++; + if (!(netdev->features & NETIF_F_RXCSUM)) return; =20 if (unlikely(csum_err)) { /* pkt type is recognized by HW, and csum is wrong */ + if (!(csum_err & (HINIC3_RX_CSUM_HW_CHECK_NONE | + HINIC3_RX_CSUM_IPSU_OTHER_ERR))) + rxq->rxq_stats.csum_errors++; skb->ip_summed =3D CHECKSUM_NONE; return; } @@ -397,8 +414,10 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct= hinic3_rq_cqe *rx_cqe, u16 num_lro; =20 skb =3D hinic3_fetch_rx_buffer(rxq, pkt_len); - if (unlikely(!skb)) + if (unlikely(!skb)) { + RXQ_STATS_INC(rxq, alloc_skb_err); return -ENOMEM; + } =20 /* place header in linear portion of buffer */ if (skb_is_nonlinear(skb)) @@ -562,11 +581,33 @@ int hinic3_configure_rxqs(struct net_device *netdev, = u16 num_rq, return 0; } =20 +void hinic3_rxq_get_stats(struct hinic3_rxq *rxq, + struct hinic3_rxq_stats *stats) +{ + struct hinic3_rxq_stats *rxq_stats =3D &rxq->rxq_stats; + unsigned int start; + + u64_stats_update_begin(&stats->syncp); + do { + start =3D u64_stats_fetch_begin(&rxq_stats->syncp); + stats->bytes =3D rxq_stats->bytes; + stats->packets =3D rxq_stats->packets; + stats->errors =3D rxq_stats->csum_errors + + rxq_stats->other_errors; + stats->csum_errors =3D rxq_stats->csum_errors; + stats->other_errors =3D rxq_stats->other_errors; + stats->dropped =3D rxq_stats->dropped; + stats->rx_buf_empty =3D rxq_stats->rx_buf_empty; + } while (u64_stats_fetch_retry(&rxq_stats->syncp, start)); + u64_stats_update_end(&stats->syncp); +} + int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(rxq->netdev); u32 sw_ci, status, pkt_len, vlan_len; struct hinic3_rq_cqe *rx_cqe; + u64 rx_bytes =3D 0; u32 num_wqe =3D 0; int nr_pkts =3D 0; u16 num_lro; @@ -586,10 +627,14 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget) if (recv_one_pkt(rxq, rx_cqe, pkt_len, vlan_len, status)) break; =20 + rx_bytes +=3D pkt_len; nr_pkts++; num_lro =3D RQ_CQE_STATUS_GET(status, NUM_LRO); - if (num_lro) + if (num_lro) { + rx_bytes +=3D (num_lro - 1) * + HINIC3_LRO_PKT_HDR_LEN(rx_cqe); num_wqe +=3D hinic3_get_sge_num(rxq, pkt_len); + } =20 rx_cqe->status =3D 0; =20 @@ -600,5 +645,10 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget) if (rxq->delta >=3D HINIC3_RX_BUFFER_WRITE) hinic3_rx_fill_buffers(rxq); =20 + u64_stats_update_begin(&rxq->rxq_stats.syncp); + rxq->rxq_stats.packets +=3D (u64)nr_pkts; + rxq->rxq_stats.bytes +=3D rx_bytes; + u64_stats_update_end(&rxq->rxq_stats.syncp); + return nr_pkts; } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_rx.h index 06d1b3299e7c..cd2dcaab6cf7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h @@ -8,6 +8,17 @@ #include #include =20 +/* rx cqe checksum err */ +#define HINIC3_RX_CSUM_IP_CSUM_ERR BIT(0) +#define HINIC3_RX_CSUM_TCP_CSUM_ERR BIT(1) +#define HINIC3_RX_CSUM_UDP_CSUM_ERR BIT(2) +#define HINIC3_RX_CSUM_IGMP_CSUM_ERR BIT(3) +#define HINIC3_RX_CSUM_ICMPV4_CSUM_ERR BIT(4) +#define HINIC3_RX_CSUM_ICMPV6_CSUM_ERR BIT(5) +#define HINIC3_RX_CSUM_SCTP_CRC_ERR BIT(6) +#define HINIC3_RX_CSUM_HW_CHECK_NONE BIT(7) +#define HINIC3_RX_CSUM_IPSU_OTHER_ERR BIT(8) + #define RQ_CQE_OFFOLAD_TYPE_PKT_TYPE_MASK GENMASK(4, 0) #define RQ_CQE_OFFOLAD_TYPE_IP_TYPE_MASK GENMASK(6, 5) #define RQ_CQE_OFFOLAD_TYPE_TUNNEL_PKT_FORMAT_MASK GENMASK(11, 8) @@ -123,6 +134,9 @@ void hinic3_free_rxqs_res(struct net_device *netdev, u1= 6 num_rq, u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); int hinic3_configure_rxqs(struct net_device *netdev, u16 num_rq, u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res); + +void hinic3_rxq_get_stats(struct hinic3_rxq *rxq, + struct hinic3_rxq_stats *stats); int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.c index 6d3dc930ca97..79f877c9aa03 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c @@ -16,6 +16,13 @@ =20 #define MIN_SKB_LEN 32 =20 +#define TXQ_STATS_INC(txq, field) \ +do { \ + u64_stats_update_begin(&(txq)->txq_stats.syncp); \ + (txq)->txq_stats.field++; \ + u64_stats_update_end(&(txq)->txq_stats.syncp); \ +} while (0) + static void hinic3_txq_clean_stats(struct hinic3_txq_stats *txq_stats) { u64_stats_update_begin(&txq_stats->syncp); @@ -97,8 +104,10 @@ static int hinic3_tx_map_skb(struct net_device *netdev,= struct sk_buff *skb, =20 dma_info[0].dma =3D dma_map_single(&pdev->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, dma_info[0].dma)) + if (dma_mapping_error(&pdev->dev, dma_info[0].dma)) { + TXQ_STATS_INC(txq, map_frag_err); return -EFAULT; + } =20 dma_info[0].len =3D skb_headlen(skb); =20 @@ -117,6 +126,7 @@ static int hinic3_tx_map_skb(struct net_device *netdev,= struct sk_buff *skb, skb_frag_size(frag), DMA_TO_DEVICE); if (dma_mapping_error(&pdev->dev, dma_info[idx].dma)) { + TXQ_STATS_INC(txq, map_frag_err); err =3D -EFAULT; goto err_unmap_page; } @@ -260,6 +270,7 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struc= t hinic3_sq_task *task, if (l4_proto !=3D IPPROTO_UDP || ((struct udphdr *)skb_transport_header(skb))->dest !=3D VXLAN_OFFLOAD_PORT_LE) { + TXQ_STATS_INC(txq, unknown_tunnel_pkt); /* Unsupported tunnel packet, disable csum offload */ skb_checksum_help(skb); return 0; @@ -433,6 +444,27 @@ static u32 hinic3_tx_offload(struct sk_buff *skb, stru= ct hinic3_sq_task *task, return offload; } =20 +static void hinic3_get_pkt_stats(struct hinic3_txq *txq, struct sk_buff *s= kb) +{ + u32 hdr_len, tx_bytes; + unsigned short pkts; + + if (skb_is_gso(skb)) { + hdr_len =3D (skb_shinfo(skb)->gso_segs - 1) * + skb_tcp_all_headers(skb); + tx_bytes =3D skb->len + hdr_len; + pkts =3D skb_shinfo(skb)->gso_segs; + } else { + tx_bytes =3D skb->len > ETH_ZLEN ? skb->len : ETH_ZLEN; + pkts =3D 1; + } + + u64_stats_update_begin(&txq->txq_stats.syncp); + txq->txq_stats.bytes +=3D tx_bytes; + txq->txq_stats.packets +=3D pkts; + u64_stats_update_end(&txq->txq_stats.syncp); +} + static u16 hinic3_get_and_update_sq_owner(struct hinic3_io_queue *sq, u16 curr_pi, u16 wqebb_cnt) { @@ -539,8 +571,10 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff = *skb, int err; =20 if (unlikely(skb->len < MIN_SKB_LEN)) { - if (skb_pad(skb, MIN_SKB_LEN - skb->len)) + if (skb_pad(skb, MIN_SKB_LEN - skb->len)) { + TXQ_STATS_INC(txq, skb_pad_err); goto err_out; + } =20 skb->len =3D MIN_SKB_LEN; } @@ -595,6 +629,7 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *= skb, txq->tx_stop_thrs, txq->tx_start_thrs); =20 + hinic3_get_pkt_stats(txq, skb); hinic3_prepare_sq_ctrl(&wqe_combo, queue_info, num_sge, owner); hinic3_write_db(txq->sq, 0, DB_CFLAG_DP_SQ, hinic3_get_sq_local_pi(txq->sq)); @@ -604,6 +639,8 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *= skb, err_drop_pkt: dev_kfree_skb_any(skb); err_out: + TXQ_STATS_INC(txq, dropped); + return NETDEV_TX_OK; } =20 @@ -611,12 +648,22 @@ netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, st= ruct net_device *netdev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); u16 q_id =3D skb_get_queue_mapping(skb); + struct hinic3_txq *txq; =20 - if (unlikely(!netif_carrier_ok(netdev))) + if (unlikely(!netif_carrier_ok(netdev))) { + HINIC3_NIC_STATS_INC(nic_dev, tx_carrier_off_drop); goto err_drop_pkt; + } + + if (unlikely(q_id >=3D nic_dev->q_params.num_qps)) { + txq =3D &nic_dev->txqs[0]; + u64_stats_update_begin(&txq->txq_stats.syncp); + txq->txq_stats.dropped++; + u64_stats_update_end(&txq->txq_stats.syncp); =20 - if (unlikely(q_id >=3D nic_dev->q_params.num_qps)) + HINIC3_NIC_STATS_INC(nic_dev, tx_invalid_qid); goto err_drop_pkt; + } =20 return hinic3_send_one_skb(skb, netdev, &nic_dev->txqs[q_id]); =20 @@ -756,6 +803,23 @@ int hinic3_configure_txqs(struct net_device *netdev, u= 16 num_sq, return 0; } =20 +void hinic3_txq_get_stats(struct hinic3_txq *txq, + struct hinic3_txq_stats *stats) +{ + struct hinic3_txq_stats *txq_stats =3D &txq->txq_stats; + unsigned int start; + + u64_stats_update_begin(&stats->syncp); + do { + start =3D u64_stats_fetch_begin(&txq_stats->syncp); + stats->bytes =3D txq_stats->bytes; + stats->packets =3D txq_stats->packets; + stats->busy =3D txq_stats->busy; + stats->dropped =3D txq_stats->dropped; + } while (u64_stats_fetch_retry(&txq_stats->syncp, start)); + u64_stats_update_end(&stats->syncp); +} + bool hinic3_tx_poll(struct hinic3_txq *txq, int budget) { struct net_device *netdev =3D txq->netdev; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h b/drivers/net/e= thernet/huawei/hinic3/hinic3_tx.h index 00194f2a1bcc..0a21c423618f 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.h @@ -157,6 +157,8 @@ int hinic3_configure_txqs(struct net_device *netdev, u1= 6 num_sq, u32 sq_depth, struct hinic3_dyna_txq_res *txqs_res); =20 netdev_tx_t hinic3_xmit_frame(struct sk_buff *skb, struct net_device *netd= ev); +void hinic3_txq_get_stats(struct hinic3_txq *txq, + struct hinic3_txq_stats *stats); bool hinic3_tx_poll(struct hinic3_txq *txq, int budget); void hinic3_flush_txqs(struct net_device *netdev); =20 --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D11F23A1A43; Tue, 24 Feb 2026 13:16:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938988; cv=none; b=XHryfMIJwzXOUWmSmAY+PKlNFpaMFz9APTSu9ZwYSXpEtVqLnnQua65fMFh83s5qhJkuR08+n3vXSgW4NTueW6Uj8eq8C1z8nsy7uFHypm2u9GEpfW8baK8G7qLQ6BnfMyoJMBvRtGYvUVSwtRx+h35X+uibvhJd+fEc0US1tXI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938988; c=relaxed/simple; bh=bf0NxaGL/wrr28K/C5Ym3GsrBAaZEk8EPyKIFNb9cI0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ehLpfps2jqnkGeCgP9aOipSxKJ/E+6gj1n1tUvVtg1fvWds48h5W1Dtzc/WFP2Fz/msr1ucv94DFNskQCmUMerPHYKBlU+Efkn6nJxvcY9QG7qCSAT/3nUtfz7i+073/ggPY00RueSIHjf1Z+9YVU502QBm7lbEzMWDS5+uJuDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=tL+zQEEX; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="tL+zQEEX" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=n/pg0Tw1O/MBIkjV9GqpJlB9KUTV7XWENZDkOwJq7Ak=; b=tL+zQEEXOAuGhHAC4rw/6nMIzDWnYUZT/h5uWEZL6fwV+mDvkaHgfzORsu6le6RC0GPxHxpoj M8vbfJcZF/XgGL2qOG1QxXe7468Ei0tzbMhJksUFVRLj7Aj0SsWIZYAltue18YRFWAsYLeG3BST BxSUkEhjqh4UjH0ESHBoNZE= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4fKym91h4gzpT14; Tue, 24 Feb 2026 21:11:37 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 0FE252016A; Tue, 24 Feb 2026 21:16:23 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:22 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 12/15] hinic3: Add ethtool coalesce ops Date: Tue, 24 Feb 2026 21:15:49 +0800 Message-ID: <3f472dcdeae0c5571a7f2095231a3f8a8dabc79e.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 275 ++++++++++++++++++ 1 file changed, 275 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_ethtool.c index ea0b2df73e9f..b8aee18fac8f 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c @@ -17,6 +17,12 @@ #include "hinic3_nic_cfg.h" =20 #define HINIC3_MGMT_VERSION_MAX_LEN 32 +#define COALESCE_ALL_QUEUE 0xFFFF +/* Coalesce time properties in milliseconds */ +#define COALESCE_PENDING_LIMIT_UNIT 8 +#define COALESCE_TIMER_CFG_UNIT 5 +#define COALESCE_MAX_PENDING_LIMIT (255 * COALESCE_PENDING_LIMIT_UNIT) +#define COALESCE_MAX_TIMER_CFG (255 * COALESCE_TIMER_CFG_UNIT) =20 static void hinic3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) @@ -912,6 +918,273 @@ static void hinic3_get_strings(struct net_device *net= dev, } } =20 +static int hinic3_set_queue_coalesce(struct net_device *netdev, u16 q_id, + struct hinic3_intr_coal_info *coal) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_intr_coal_info *intr_coal; + struct hinic3_interrupt_info info =3D {}; + int err; + + intr_coal =3D &nic_dev->intr_coalesce[q_id]; + + intr_coal->coalesce_timer_cfg =3D coal->coalesce_timer_cfg; + intr_coal->pending_limit =3D coal->pending_limit; + intr_coal->rx_pending_limit_low =3D coal->rx_pending_limit_low; + intr_coal->rx_pending_limit_high =3D coal->rx_pending_limit_high; + + if (!test_bit(HINIC3_INTF_UP, &nic_dev->flags) || + q_id >=3D nic_dev->q_params.num_qps || nic_dev->adaptive_rx_coal) + return 0; + + info.msix_index =3D nic_dev->q_params.irq_cfg[q_id].msix_entry_idx; + info.interrupt_coalesc_set =3D 1; + info.coalesc_timer_cfg =3D intr_coal->coalesce_timer_cfg; + info.pending_limit =3D intr_coal->pending_limit; + info.resend_timer_cfg =3D intr_coal->resend_timer_cfg; + err =3D hinic3_set_interrupt_cfg(nic_dev->hwdev, info); + if (err) { + netdev_warn(netdev, "Failed to set queue%u coalesce\n", q_id); + return err; + } + + return 0; +} + +static int is_coalesce_exceed_limit(struct net_device *netdev, + const struct ethtool_coalesce *coal) +{ + if (coal->rx_coalesce_usecs > COALESCE_MAX_TIMER_CFG) { + netdev_err(netdev, "rx_coalesce_usecs out of range %d-%d\n", 0, + COALESCE_MAX_TIMER_CFG); + return -EOPNOTSUPP; + } + + if (coal->rx_max_coalesced_frames > COALESCE_MAX_PENDING_LIMIT) { + netdev_err(netdev, "rx_max_coalesced_frames out of range %d-%d\n", + 0, COALESCE_MAX_PENDING_LIMIT); + return -EOPNOTSUPP; + } + + if (coal->rx_coalesce_usecs_low > COALESCE_MAX_TIMER_CFG) { + netdev_err(netdev, "rx_coalesce_usecs_low out of range %d-%d\n", + 0, COALESCE_MAX_TIMER_CFG); + return -EOPNOTSUPP; + } + + if (coal->rx_max_coalesced_frames_low > COALESCE_MAX_PENDING_LIMIT) { + netdev_err(netdev, "rx_max_coalesced_frames_low out of range %d-%d\n", + 0, COALESCE_MAX_PENDING_LIMIT); + return -EOPNOTSUPP; + } + + if (coal->rx_coalesce_usecs_high > COALESCE_MAX_TIMER_CFG) { + netdev_err(netdev, "rx_coalesce_usecs_high out of range %d-%d\n", + 0, COALESCE_MAX_TIMER_CFG); + return -EOPNOTSUPP; + } + + if (coal->rx_max_coalesced_frames_high > COALESCE_MAX_PENDING_LIMIT) { + netdev_err(netdev, "rx_max_coalesced_frames_high out of range %d-%d\n", + 0, COALESCE_MAX_PENDING_LIMIT); + return -EOPNOTSUPP; + } + + return 0; +} + +static int is_coalesce_legal(struct net_device *netdev, + const struct ethtool_coalesce *coal) +{ + struct ethtool_coalesce tmp_coal =3D {}; + int err; + + if (coal->rx_coalesce_usecs !=3D coal->tx_coalesce_usecs) { + netdev_err(netdev, "tx-usecs must be equal to rx-usecs\n"); + return -EINVAL; + } + + if (coal->rx_max_coalesced_frames !=3D coal->tx_max_coalesced_frames) { + netdev_err(netdev, "tx-frames must be equal to rx-frames\n"); + return -EINVAL; + } + + tmp_coal.cmd =3D coal->cmd; + tmp_coal.rx_coalesce_usecs =3D coal->rx_coalesce_usecs; + tmp_coal.rx_max_coalesced_frames =3D coal->rx_max_coalesced_frames; + tmp_coal.tx_coalesce_usecs =3D coal->tx_coalesce_usecs; + tmp_coal.tx_max_coalesced_frames =3D coal->tx_max_coalesced_frames; + tmp_coal.use_adaptive_rx_coalesce =3D coal->use_adaptive_rx_coalesce; + + tmp_coal.rx_coalesce_usecs_low =3D coal->rx_coalesce_usecs_low; + tmp_coal.rx_max_coalesced_frames_low =3D + coal->rx_max_coalesced_frames_low; + + tmp_coal.rx_coalesce_usecs_high =3D coal->rx_coalesce_usecs_high; + tmp_coal.rx_max_coalesced_frames_high =3D + coal->rx_max_coalesced_frames_high; + + if (memcmp(coal, &tmp_coal, sizeof(struct ethtool_coalesce))) { + netdev_err(netdev, "Only support to change rx/tx-usecs and rx/tx-frames\= n"); + return -EOPNOTSUPP; + } + + err =3D is_coalesce_exceed_limit(netdev, coal); + if (err) + return err; + + if (coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT >=3D + coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT) { + netdev_err(netdev, "invalid coalesce usec high %u, low %u, unit %d\n", + coal->rx_coalesce_usecs_high, + coal->rx_coalesce_usecs_low, + COALESCE_TIMER_CFG_UNIT); + return -EINVAL; + } + + if (coal->rx_max_coalesced_frames_low / COALESCE_PENDING_LIMIT_UNIT >=3D + coal->rx_max_coalesced_frames_high / COALESCE_PENDING_LIMIT_UNIT) { + netdev_err(netdev, "invalid coalesce frame high %u, low %u, unit %d\n", + coal->rx_max_coalesced_frames_high, + coal->rx_max_coalesced_frames_low, + COALESCE_PENDING_LIMIT_UNIT); + return -EOPNOTSUPP; + } + + return 0; +} + +static void check_coalesce_align(struct net_device *netdev, + u32 item, u32 unit, const char *str) +{ + if (item % unit) + netdev_warn(netdev, "%s in %d units, change to %u\n", + str, unit, item - item % unit); +} + +#define CHECK_COALESCE_ALIGN(member, unit) \ + check_coalesce_align(netdev, member, unit, #member) + +static void check_coalesce_changed(struct net_device *netdev, + u32 item, u32 unit, u32 ori_val, + const char *obj_str, const char *str) +{ + if ((item / unit) !=3D ori_val) + netdev_dbg(netdev, "Change %s from %d to %u %s\n", + str, ori_val * unit, item - item % unit, obj_str); +} + +#define CHECK_COALESCE_CHANGED(member, unit, ori_val, obj_str) \ + check_coalesce_changed(netdev, member, unit, ori_val, obj_str, #member) + +static int hinic3_set_hw_coal_param(struct net_device *netdev, + struct hinic3_intr_coal_info *intr_coal) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u16 i; + + for (i =3D 0; i < nic_dev->max_qps; i++) + hinic3_set_queue_coalesce(netdev, i, intr_coal); + + return 0; +} + +static int hinic3_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coal, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_intr_coal_info *interrupt_info; + + interrupt_info =3D &nic_dev->intr_coalesce[0]; + + coal->rx_coalesce_usecs =3D interrupt_info->coalesce_timer_cfg * + COALESCE_TIMER_CFG_UNIT; + coal->rx_max_coalesced_frames =3D interrupt_info->pending_limit * + COALESCE_PENDING_LIMIT_UNIT; + + /* tx/rx use the same interrupt */ + coal->tx_coalesce_usecs =3D coal->rx_coalesce_usecs; + coal->tx_max_coalesced_frames =3D coal->rx_max_coalesced_frames; + coal->use_adaptive_rx_coalesce =3D nic_dev->adaptive_rx_coal; + + coal->rx_max_coalesced_frames_high =3D + interrupt_info->rx_pending_limit_high * + COALESCE_PENDING_LIMIT_UNIT; + + coal->rx_max_coalesced_frames_low =3D + interrupt_info->rx_pending_limit_low * + COALESCE_PENDING_LIMIT_UNIT; + + return 0; +} + +static int hinic3_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *coal, + struct kernel_ethtool_coalesce *kernel_coal, + struct netlink_ext_ack *extack) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_intr_coal_info *ori_intr_coal; + struct hinic3_intr_coal_info intr_coal =3D {}; + char obj_str[32]; + int err; + + err =3D is_coalesce_legal(netdev, coal); + if (err) + return err; + + CHECK_COALESCE_ALIGN(coal->rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT); + CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames, + COALESCE_PENDING_LIMIT_UNIT); + CHECK_COALESCE_ALIGN(coal->rx_coalesce_usecs_high, + COALESCE_TIMER_CFG_UNIT); + CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames_high, + COALESCE_PENDING_LIMIT_UNIT); + CHECK_COALESCE_ALIGN(coal->rx_coalesce_usecs_low, + COALESCE_TIMER_CFG_UNIT); + CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames_low, + COALESCE_PENDING_LIMIT_UNIT); + + ori_intr_coal =3D &nic_dev->intr_coalesce[0]; + snprintf(obj_str, sizeof(obj_str), "for netdev"); + + CHECK_COALESCE_CHANGED(coal->rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT, + ori_intr_coal->coalesce_timer_cfg, obj_str); + CHECK_COALESCE_CHANGED(coal->rx_max_coalesced_frames, + COALESCE_PENDING_LIMIT_UNIT, + ori_intr_coal->pending_limit, obj_str); + CHECK_COALESCE_CHANGED(coal->rx_max_coalesced_frames_high, + COALESCE_PENDING_LIMIT_UNIT, + ori_intr_coal->rx_pending_limit_high, obj_str); + CHECK_COALESCE_CHANGED(coal->rx_max_coalesced_frames_low, + COALESCE_PENDING_LIMIT_UNIT, + ori_intr_coal->rx_pending_limit_low, obj_str); + + intr_coal.coalesce_timer_cfg =3D + (u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT); + intr_coal.pending_limit =3D (u8)(coal->rx_max_coalesced_frames / + COALESCE_PENDING_LIMIT_UNIT); + + nic_dev->adaptive_rx_coal =3D coal->use_adaptive_rx_coalesce; + + intr_coal.rx_pending_limit_high =3D + (u8)(coal->rx_max_coalesced_frames_high / + COALESCE_PENDING_LIMIT_UNIT); + + intr_coal.rx_pending_limit_low =3D + (u8)(coal->rx_max_coalesced_frames_low / + COALESCE_PENDING_LIMIT_UNIT); + + /* coalesce timer or pending set to zero will disable coalesce */ + if (!nic_dev->adaptive_rx_coal && + (!intr_coal.coalesce_timer_cfg || !intr_coal.pending_limit)) + netdev_warn(netdev, "Coalesce will be disabled\n"); + + return hinic3_set_hw_coal_param(netdev, &intr_coal); +} + static const struct ethtool_ops hinic3_ethtool_ops =3D { .supported_coalesce_params =3D ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_PKT_RATE_RX_USECS, @@ -925,6 +1198,8 @@ static const struct ethtool_ops hinic3_ethtool_ops =3D= { .get_sset_count =3D hinic3_get_sset_count, .get_ethtool_stats =3D hinic3_get_ethtool_stats, .get_strings =3D hinic3_get_strings, + .get_coalesce =3D hinic3_get_coalesce, + .set_coalesce =3D hinic3_set_coalesce, }; =20 void hinic3_set_ethtool_ops(struct net_device *netdev) --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3F8739E6C1; Tue, 24 Feb 2026 13:16:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938988; cv=none; b=PHRbwkv1WLsgmHTWMvISbcPYsddekRDEgDwAgB09eiZ7w5s+Z55W2XgEI/rnkK31sIO4/qziPQAIlfXcp1rCEPj2yT4oBEfykc/rsxtls1VwLzVZpvGDBgLxaUNICxori2PAxwxfUBkh9dKxNbx/ipCFgf1gz8xKUpsiqu0tuxo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938988; c=relaxed/simple; bh=2NiP1a9kn8WYGosP/pIFMstg35BP96X/A0vXtWz1QxI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=TooeK6Q2zIKN++/VVW920O4fdgNVPUYbzp+ZabNA39l4haFyQPGUSnjVvdejNKEKA+7505E89npS+UhYuoEPZLIY3F1oOvJSkm6kQD/2FY2FCv0UvGVCsY/CneIYa9OVH2fDR1/6j9s83RTXbZtM9sxtgwhr2bgbLrkuwJ+/s+4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=YgXDk3Y+; arc=none smtp.client-ip=113.46.200.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="YgXDk3Y+" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=Th4CqLiVAwzr/jkQbgyYcR5mSzqiS1j4YbjqDxvSvwo=; b=YgXDk3Y+HNXiz1dgcAm4hU5eSO2/a9CzGNtlW+4gPUrwaRyMI45PyYDGG62dc0XcfWVy3IcqF 8NAk0tI00+jwWUdoHIpGzcffnnMGv/XJcgUb3eE2nJ/nYifkvAj4yZAqYHF7Jjwyq2hTp6OJaFE vnS9VEUOBXk9Rptuo+Q/+o8= Received: from mail.maildlp.com (unknown [172.19.162.223]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4fKym80LHwz1prKq; Tue, 24 Feb 2026 21:11:36 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id B5EF940561; Tue, 24 Feb 2026 21:16:24 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:23 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 13/15] hinic3: Add ethtool rss ops Date: Tue, 24 Feb 2026 21:15:50 +0800 Message-ID: X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_ethtool.c | 9 + .../huawei/hinic3/hinic3_mgmt_interface.h | 2 + .../net/ethernet/huawei/hinic3/hinic3_rss.c | 485 +++++++++++++++++- .../net/ethernet/huawei/hinic3/hinic3_rss.h | 19 + 4 files changed, 514 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_ethtool.c index b8aee18fac8f..074468125490 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c @@ -15,6 +15,7 @@ #include "hinic3_hw_comm.h" #include "hinic3_nic_dev.h" #include "hinic3_nic_cfg.h" +#include "hinic3_rss.h" =20 #define HINIC3_MGMT_VERSION_MAX_LEN 32 #define COALESCE_ALL_QUEUE 0xFFFF @@ -1200,6 +1201,14 @@ static const struct ethtool_ops hinic3_ethtool_ops = =3D { .get_strings =3D hinic3_get_strings, .get_coalesce =3D hinic3_get_coalesce, .set_coalesce =3D hinic3_set_coalesce, + .get_rxnfc =3D hinic3_get_rxnfc, + .set_rxnfc =3D hinic3_set_rxnfc, + .get_channels =3D hinic3_get_channels, + .set_channels =3D hinic3_set_channels, + .get_rxfh_indir_size =3D hinic3_get_rxfh_indir_size, + .get_rxfh_key_size =3D hinic3_get_rxfh_key_size, + .get_rxfh =3D hinic3_get_rxfh, + .set_rxfh =3D hinic3_set_rxfh, }; =20 void hinic3_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index 76c691f82703..3c1263ff99ff 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -282,6 +282,7 @@ enum l2nic_cmd { L2NIC_CMD_SET_VLAN_FILTER_EN =3D 26, L2NIC_CMD_SET_RX_VLAN_OFFLOAD =3D 27, L2NIC_CMD_CFG_RSS =3D 60, + L2NIC_CMD_GET_RSS_CTX_TBL =3D 62, L2NIC_CMD_CFG_RSS_HASH_KEY =3D 63, L2NIC_CMD_CFG_RSS_HASH_ENGINE =3D 64, L2NIC_CMD_SET_RSS_CTX_TBL =3D 65, @@ -301,6 +302,7 @@ enum l2nic_ucode_cmd { L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX =3D 0, L2NIC_UCODE_CMD_CLEAN_QUEUE_CTX =3D 1, L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL =3D 4, + L2NIC_UCODE_CMD_GET_RSS_INDIR_TBL =3D 6, }; =20 /* hilink mac group command */ diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c b/drivers/net/= ethernet/huawei/hinic3/hinic3_rss.c index 25db74d8c7dd..9f9e6681f0fa 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c @@ -165,6 +165,39 @@ static int hinic3_set_rss_type(struct hinic3_hwdev *hw= dev, return 0; } =20 +static int hinic3_get_rss_type(struct hinic3_hwdev *hwdev, + struct hinic3_rss_type *rss_type) +{ + struct l2nic_cmd_rss_ctx_tbl ctx_tbl =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + ctx_tbl.func_id =3D hinic3_global_func_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &ctx_tbl, sizeof(ctx_tbl)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_GET_RSS_CTX_TBL, + &msg_params); + if (err || ctx_tbl.msg_head.status) { + dev_err(hwdev->dev, "Failed to get hash type, err: %d, status: 0x%x\n", + err, ctx_tbl.msg_head.status); + return -EINVAL; + } + + rss_type->ipv4 =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, IPV4); + rss_type->ipv6 =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, IPV6); + rss_type->ipv6_ext =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT); + rss_type->tcp_ipv4 =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4); + rss_type->tcp_ipv6 =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6); + rss_type->tcp_ipv6_ext =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, + TCP_IPV6_EXT); + rss_type->udp_ipv4 =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4); + rss_type->udp_ipv6 =3D L2NIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6); + + return 0; +} + static int hinic3_rss_cfg_hash_type(struct hinic3_hwdev *hwdev, u8 opcode, enum hinic3_rss_hash_type *type) { @@ -264,7 +297,8 @@ static int hinic3_set_hw_rss_parameters(struct net_devi= ce *netdev, u8 rss_en) if (err) return err; =20 - hinic3_fillout_indir_tbl(netdev, nic_dev->rss_indir); + if (!netif_is_rxfh_configured(netdev)) + hinic3_fillout_indir_tbl(netdev, nic_dev->rss_indir); =20 err =3D hinic3_config_rss_hw_resource(netdev, nic_dev->rss_indir); if (err) @@ -334,3 +368,452 @@ void hinic3_try_to_enable_rss(struct net_device *netd= ev) clear_bit(HINIC3_RSS_ENABLE, &nic_dev->flags); nic_dev->q_params.num_qps =3D nic_dev->max_qps; } + +static int hinic3_set_l4_rss_hash_ops(const struct ethtool_rxnfc *cmd, + struct hinic3_rss_type *rss_type) +{ + u8 rss_l4_en; + + switch (cmd->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { + case 0: + rss_l4_en =3D 0; + break; + case (RXH_L4_B_0_1 | RXH_L4_B_2_3): + rss_l4_en =3D 1; + break; + default: + return -EINVAL; + } + + switch (cmd->flow_type) { + case TCP_V4_FLOW: + rss_type->tcp_ipv4 =3D rss_l4_en; + break; + case TCP_V6_FLOW: + rss_type->tcp_ipv6 =3D rss_l4_en; + break; + case UDP_V4_FLOW: + rss_type->udp_ipv4 =3D rss_l4_en; + break; + case UDP_V6_FLOW: + rss_type->udp_ipv6 =3D rss_l4_en; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int hinic3_update_rss_hash_opts(struct net_device *netdev, + struct ethtool_rxnfc *cmd, + struct hinic3_rss_type *rss_type) +{ + int err; + + switch (cmd->flow_type) { + case TCP_V4_FLOW: + case TCP_V6_FLOW: + case UDP_V4_FLOW: + case UDP_V6_FLOW: + err =3D hinic3_set_l4_rss_hash_ops(cmd, rss_type); + if (err) + return err; + + break; + case IPV4_FLOW: + rss_type->ipv4 =3D 1; + break; + case IPV6_FLOW: + rss_type->ipv6 =3D 1; + break; + default: + netdev_err(netdev, "Unsupported flow type\n"); + return -EINVAL; + } + + return 0; +} + +static int hinic3_set_rss_hash_opts(struct net_device *netdev, + struct ethtool_rxnfc *cmd) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_rss_type *rss_type; + int err; + + rss_type =3D &nic_dev->rss_type; + + if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) { + cmd->data =3D 0; + netdev_err(netdev, "RSS is disable, not support to set flow-hash\n"); + return -EOPNOTSUPP; + } + + /* RSS only supports hashing of IP addresses and L4 ports */ + if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3)) + return -EINVAL; + + /* Both IP addresses must be part of the hash tuple */ + if (!(cmd->data & RXH_IP_SRC) || !(cmd->data & RXH_IP_DST)) + return -EINVAL; + + err =3D hinic3_get_rss_type(nic_dev->hwdev, rss_type); + if (err) { + netdev_err(netdev, "Failed to get rss type\n"); + return err; + } + + err =3D hinic3_update_rss_hash_opts(netdev, cmd, rss_type); + if (err) + return err; + + err =3D hinic3_set_rss_type(nic_dev->hwdev, *rss_type); + if (err) { + netdev_err(netdev, "Failed to set rss type\n"); + return err; + } + + return 0; +} + +static void convert_rss_type(u8 rss_opt, struct ethtool_rxnfc *cmd) +{ + if (rss_opt) + cmd->data |=3D RXH_L4_B_0_1 | RXH_L4_B_2_3; +} + +static int hinic3_convert_rss_type(struct net_device *netdev, + struct hinic3_rss_type *rss_type, + struct ethtool_rxnfc *cmd) +{ + cmd->data =3D RXH_IP_SRC | RXH_IP_DST; + switch (cmd->flow_type) { + case TCP_V4_FLOW: + convert_rss_type(rss_type->tcp_ipv4, cmd); + break; + case TCP_V6_FLOW: + convert_rss_type(rss_type->tcp_ipv6, cmd); + break; + case UDP_V4_FLOW: + convert_rss_type(rss_type->udp_ipv4, cmd); + break; + case UDP_V6_FLOW: + convert_rss_type(rss_type->udp_ipv6, cmd); + break; + case IPV4_FLOW: + case IPV6_FLOW: + break; + default: + netdev_err(netdev, "Unsupported flow type\n"); + cmd->data =3D 0; + return -EINVAL; + } + + return 0; +} + +static int hinic3_get_rss_hash_opts(struct net_device *netdev, + struct ethtool_rxnfc *cmd) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + struct hinic3_rss_type rss_type; + int err; + + cmd->data =3D 0; + + if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) + return 0; + + err =3D hinic3_get_rss_type(nic_dev->hwdev, &rss_type); + if (err) { + netdev_err(netdev, "Failed to get rss type\n"); + return err; + } + + return hinic3_convert_rss_type(netdev, &rss_type, cmd); +} + +int hinic3_get_rxnfc(struct net_device *netdev, + struct ethtool_rxnfc *cmd, u32 *rule_locs) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err =3D 0; + + switch (cmd->cmd) { + case ETHTOOL_GRXRINGS: + cmd->data =3D nic_dev->q_params.num_qps; + break; + case ETHTOOL_GRXFH: + err =3D hinic3_get_rss_hash_opts(netdev, cmd); + break; + default: + err =3D -EOPNOTSUPP; + break; + } + + return err; +} + +int hinic3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd) +{ + int err; + + switch (cmd->cmd) { + case ETHTOOL_SRXFH: + err =3D hinic3_set_rss_hash_opts(netdev, cmd); + break; + default: + err =3D -EOPNOTSUPP; + break; + } + + return err; +} + +static u16 hinic3_max_channels(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + u8 tcs =3D netdev_get_num_tc(netdev); + + return tcs ? nic_dev->max_qps / tcs : nic_dev->max_qps; +} + +static u16 hinic3_curr_channels(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + if (netif_running(netdev)) + return nic_dev->q_params.num_qps ? + nic_dev->q_params.num_qps : 1; + else + return min_t(u16, hinic3_max_channels(netdev), + nic_dev->q_params.num_qps); +} + +void hinic3_get_channels(struct net_device *netdev, + struct ethtool_channels *channels) +{ + channels->max_rx =3D 0; + channels->max_tx =3D 0; + channels->max_other =3D 0; + /* report maximum channels */ + channels->max_combined =3D hinic3_max_channels(netdev); + channels->rx_count =3D 0; + channels->tx_count =3D 0; + channels->other_count =3D 0; + /* report flow director queues as maximum channels */ + channels->combined_count =3D hinic3_curr_channels(netdev); +} + +static int +hinic3_validate_channel_parameter(struct net_device *netdev, + const struct ethtool_channels *channels) +{ + u16 max_channel =3D hinic3_max_channels(netdev); + unsigned int count =3D channels->combined_count; + + if (!count) { + netdev_err(netdev, "Unsupported combined_count=3D0\n"); + return -EINVAL; + } + + if (channels->tx_count || channels->rx_count || channels->other_count) { + netdev_err(netdev, "Setting rx/tx/other count not supported\n"); + return -EINVAL; + } + + if (count > max_channel) { + netdev_err(netdev, "Combined count %u exceed limit %u\n", count, + max_channel); + return -EINVAL; + } + + return 0; +} + +int hinic3_set_channels(struct net_device *netdev, + struct ethtool_channels *channels) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + unsigned int count =3D channels->combined_count; + struct hinic3_dyna_txrxq_params q_params; + int err; + + if (hinic3_validate_channel_parameter(netdev, channels)) + return -EINVAL; + + if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) { + netdev_err(netdev, "This function doesn't support RSS, only support 1 qu= eue pair\n"); + return -EOPNOTSUPP; + } + + netdev_dbg(netdev, "Set max combined queue number from %u to %u\n", + nic_dev->q_params.num_qps, count); + + if (netif_running(netdev)) { + q_params =3D nic_dev->q_params; + q_params.num_qps =3D (u16)count; + q_params.txqs_res =3D NULL; + q_params.rxqs_res =3D NULL; + q_params.irq_cfg =3D NULL; + + err =3D hinic3_change_channel_settings(netdev, &q_params); + if (err) { + netdev_err(netdev, "Failed to change channel settings\n"); + return err; + } + } else { + nic_dev->q_params.num_qps =3D (u16)count; + } + + return 0; +} + +u32 hinic3_get_rxfh_indir_size(struct net_device *netdev) +{ + return L2NIC_RSS_INDIR_SIZE; +} + +static int hinic3_set_rss_rxfh(struct net_device *netdev, + const u32 *indir, u8 *key) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + u32 i; + + if (indir) { + err =3D hinic3_rss_set_indir_tbl(nic_dev->hwdev, + (const u16 *)indir); + if (err) { + netdev_err(netdev, "Failed to set rss indir table\n"); + return err; + } + + for (i =3D 0; i < L2NIC_RSS_INDIR_SIZE; i++) + nic_dev->rss_indir[i] =3D (u16)indir[i]; + } + + if (key) { + err =3D hinic3_rss_set_hash_key(nic_dev->hwdev, key); + if (err) { + netdev_err(netdev, "Failed to set rss key\n"); + return err; + } + + memcpy(nic_dev->rss_hkey, key, L2NIC_RSS_KEY_SIZE); + } + + return 0; +} + +u32 hinic3_get_rxfh_key_size(struct net_device *netdev) +{ + return L2NIC_RSS_KEY_SIZE; +} + +static int hinic3_rss_get_indir_tbl(struct hinic3_hwdev *hwdev, + u32 *indir_table) +{ + struct hinic3_cmd_buf_pair pair; + u16 *indir_tbl =3D NULL; + int err, i; + + err =3D hinic3_cmd_buf_pair_init(hwdev, &pair); + if (err) { + dev_err(hwdev->dev, "Failed to allocate cmd_buf.\n"); + return err; + } + + err =3D hinic3_cmdq_detail_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_GET_RSS_INDIR_TBL, + pair.in, pair.out, NULL); + if (err) { + dev_err(hwdev->dev, "Failed to get rss indir table\n"); + goto err_get_indir_tbl; + } + + indir_tbl =3D (u16 *)pair.out->buf; + for (i =3D 0; i < L2NIC_RSS_INDIR_SIZE; i++) + indir_table[i] =3D *(indir_tbl + i); + +err_get_indir_tbl: + hinic3_cmd_buf_pair_uninit(hwdev, &pair); + + return err; +} + +int hinic3_get_rxfh(struct net_device *netdev, + struct ethtool_rxfh_param *rxfh) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err =3D 0; + + if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) { + netdev_err(netdev, "Rss is disabled\n"); + return -EOPNOTSUPP; + } + + rxfh->hfunc =3D + nic_dev->rss_hash_type =3D=3D HINIC3_RSS_HASH_ENGINE_TYPE_XOR ? + ETH_RSS_HASH_XOR : ETH_RSS_HASH_TOP; + + if (rxfh->indir) { + err =3D hinic3_rss_get_indir_tbl(nic_dev->hwdev, rxfh->indir); + if (err) + return err; + } + + if (rxfh->key) + memcpy(rxfh->key, nic_dev->rss_hkey, L2NIC_RSS_KEY_SIZE); + + return err; +} + +static int hinic3_update_hash_func_type(struct net_device *netdev, u8 hfun= c) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + enum hinic3_rss_hash_type new_rss_hash_type; + + switch (hfunc) { + case ETH_RSS_HASH_NO_CHANGE: + return 0; + case ETH_RSS_HASH_XOR: + new_rss_hash_type =3D HINIC3_RSS_HASH_ENGINE_TYPE_XOR; + break; + case ETH_RSS_HASH_TOP: + new_rss_hash_type =3D HINIC3_RSS_HASH_ENGINE_TYPE_TOEP; + break; + default: + netdev_err(netdev, "Unsupported hash func %u\n", hfunc); + return -EOPNOTSUPP; + } + + if (new_rss_hash_type =3D=3D nic_dev->rss_hash_type) + return 0; + + nic_dev->rss_hash_type =3D new_rss_hash_type; + return hinic3_rss_set_hash_type(nic_dev->hwdev, nic_dev->rss_hash_type); +} + +int hinic3_set_rxfh(struct net_device *netdev, + struct ethtool_rxfh_param *rxfh, + struct netlink_ext_ack *extack) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) { + netdev_err(netdev, "Not support to set rss parameters when rss is disabl= e\n"); + return -EOPNOTSUPP; + } + + err =3D hinic3_update_hash_func_type(netdev, rxfh->hfunc); + if (err) + return err; + + err =3D hinic3_set_rss_rxfh(netdev, rxfh->indir, rxfh->key); + + return err; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.h b/drivers/net/= ethernet/huawei/hinic3/hinic3_rss.h index 78d82c2aca06..9f1b77780cd4 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.h @@ -5,10 +5,29 @@ #define _HINIC3_RSS_H_ =20 #include +#include =20 int hinic3_rss_init(struct net_device *netdev); void hinic3_rss_uninit(struct net_device *netdev); void hinic3_try_to_enable_rss(struct net_device *netdev); void hinic3_clear_rss_config(struct net_device *netdev); =20 +int hinic3_get_rxnfc(struct net_device *netdev, + struct ethtool_rxnfc *cmd, u32 *rule_locs); +int hinic3_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd); + +void hinic3_get_channels(struct net_device *netdev, + struct ethtool_channels *channels); +int hinic3_set_channels(struct net_device *netdev, + struct ethtool_channels *channels); + +u32 hinic3_get_rxfh_indir_size(struct net_device *netdev); +u32 hinic3_get_rxfh_key_size(struct net_device *netdev); + +int hinic3_get_rxfh(struct net_device *netdev, + struct ethtool_rxfh_param *rxfh); +int hinic3_set_rxfh(struct net_device *netdev, + struct ethtool_rxfh_param *rxfh, + struct netlink_ext_ack *extack); + #endif --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout11.his.huawei.com (canpmsgout11.his.huawei.com [113.46.200.226]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE83A3A1A5D; Tue, 24 Feb 2026 13:16:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.226 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938990; cv=none; b=LxUNXwmSanCVPWM5B9ZQkiWn5cQD9SSrCfdf/vjSDU5Rwx0oL9TwZ6sRogWljx7LUVQQGExW533AfrhN/1zFQvLlLuSqB2Tdm20y0w/+2b265R9sFAnrd6NFX+gfqzkFsjM7wis6sgNRubPs1nCf5bYF78OZB3e43b61VYRxpsU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938990; c=relaxed/simple; bh=4tK7AlCcUYAHSo9DJ6za+giSv/eJY23Y9yUW7P/6Y9k=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=aa3qSbO5q4nYKaSMAYgaCTQCBMjk8CxUj69TkUHvXJRJzhEZ9GCBKmeqnZ9hPJ0Dmm0pkApLYMLfvyfIfHi3RAVjD05eLAv5niWK6dHj6W3YN52tGvU+v6H+QyPA0yYo30DePvkH4jU4uRzzivhDEja0ikke98kmMwLr632lluc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=BDXb/Ndw; arc=none smtp.client-ip=113.46.200.226 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="BDXb/Ndw" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=lNpWRIb5NOnFFbs4LfS6pOxuRiA74/pcgurF0PmUllk=; b=BDXb/NdwizUL/1w85tyyKcv68hCwodbHH94vT4S60WpdxJuQlbBBdWMXOxt93HbnUfVO+qQv+ 9iH8GC2PGIocpq2BxqsoCk38BbBnTm1Vb3KldOIEZMp7hAsWhrh3tSFKip9+AFBJwcGygSk6ZKy ntitic9eFNRkGh5YvvXJ2sk= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4fKymC2l27zKm50; Tue, 24 Feb 2026 21:11:39 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 513ED40567; Tue, 24 Feb 2026 21:16:26 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:25 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 14/15] hinic3: Add MTU size validation Date: Tue, 24 Feb 2026 21:15:51 +0800 Message-ID: <98b65fc9942972ba5fe1091bd58143ef7691f4cf.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index a1a193201afd..521035b47932 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -246,6 +246,19 @@ int hinic3_set_port_mtu(struct net_device *netdev, u16= new_mtu) struct l2nic_func_tbl_cfg func_tbl_cfg =3D {}; struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; =20 + if (new_mtu < HINIC3_MIN_MTU_SIZE) { + dev_err(hwdev->dev, + "Invalid mtu size: %ubytes, mtu size < %ubytes\n", + new_mtu, HINIC3_MIN_MTU_SIZE); + return -EINVAL; + } + + if (new_mtu > HINIC3_MAX_JUMBO_FRAME_SIZE) { + dev_err(hwdev->dev, "Invalid mtu size: %ubytes, mtu size > %ubytes\n", + new_mtu, HINIC3_MAX_JUMBO_FRAME_SIZE); + return -EINVAL; + } + func_tbl_cfg.mtu =3D new_mtu; =20 return hinic3_set_function_table(hwdev, BIT(L2NIC_FUNC_TBL_CFG_MTU), --=20 2.43.0 From nobody Fri Apr 17 01:43:54 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A97543A1CF1; Tue, 24 Feb 2026 13:16:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938991; cv=none; b=hcBPBELdFQDVfQGBRPmXM5l5hyI8TURKQFTvmeSXISLtAP1CceyMFjMfccYeAq0VupEDdnPi60qmtyTQPWJtUsyY2uyGx22S4kJWr435LN/ae18SfB8sK64y+pA952LfvOMuWcN5K3sHN4FdNMi7Ezyx757mtTNELkvgYeTLQ5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771938991; c=relaxed/simple; bh=7CpA0wHO/WBiBMYLrVDRf7LFOSoynJit4dF/fk/h1BE=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=ctmVx3Ui7dXN38ABjJverP7t8MKJimWUPJROORinsdL8tNKugqPJ+NbQy8+MCzhHP5po0a5AnRZ3ufX5U2U7PTQsMm1Dyfr2O0ROrpUToFGQe8InB6aUIcSJdidPE4Yf197D5ofNhWLgxeCvGlkKrcJWcJ5eGNT5JmHohvKHVOI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=51fKr2Oc; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="51fKr2Oc" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=kwf7Q9r9UsGCmjs+yivMWP2XtP0ces3L8Glr+Whzytg=; b=51fKr2OcOOKZcUPXWfAp8LJoErGhDXe4+sSVM9g862MGJHqeGrK8rKvIZCAMX3NXQoBJtIIVS a5/J3GxvZB3UexRkMWZj+tULk0VFTMA5DxInfvuFKyhDkkW/9dBwpNZrYkmqBmmhiKyFBsS9LeE T1kT81Bry5gLA6Gf4xzcJYg= Received: from mail.maildlp.com (unknown [172.19.163.214]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4fKymF674Qz1cyPh; Tue, 24 Feb 2026 21:11:41 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id E735040561; Tue, 24 Feb 2026 21:16:27 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.124) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Tue, 24 Feb 2026 21:16:26 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn CC: , , luosifu , Xin Guo , Zhou Shuai , Wu Like , Shi Jing Subject: [PATCH net-next v01 15/15] hinic3: Config netdev->watchdog_timeo to set nic tx timeout Date: Tue, 24 Feb 2026 21:15:52 +0800 Message-ID: <6231d7a755326dd6bdef2334506dfc8004171772.1771916043.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems500001.china.huawei.com (7.221.188.70) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- drivers/net/ethernet/huawei/hinic3/hinic3_main.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net= /ethernet/huawei/hinic3/hinic3_main.c index 1a7126c7810e..27bafdc21c25 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c @@ -33,6 +33,8 @@ #define HINIC3_RX_PENDING_LIMIT_LOW 2 #define HINIC3_RX_PENDING_LIMIT_HIGH 8 =20 +#define HINIC3_WATCHDOG_TIMEOUT 5 + static void init_intr_coal_param(struct net_device *netdev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); @@ -245,6 +247,8 @@ static void hinic3_assign_netdev_ops(struct net_device = *netdev) { hinic3_set_netdev_ops(netdev); hinic3_set_ethtool_ops(netdev); + + netdev->watchdog_timeo =3D HINIC3_WATCHDOG_TIMEOUT * HZ; } =20 static void netdev_feature_init(struct net_device *netdev) --=20 2.43.0