提交 b81b8061 编写于 作者: J Jie Wang 提交者: Zheng Zengkai

net: hns3: add byte order conversion for PF to VF mailbox message

mainline inclusion
from mainline-origin
commit 767975e5
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I56XHY
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=767975e582c5

----------------------------------------------------------------------

Currently, hns3 mailbox processing between PF and VF missed to convert
message byte order and use data type u16 instead of __le16 for mailbox
data process. These processes may cause problems between different
architectures.

So this patch uses __le16/__le32 data type to define mailbox data
structures. To be compatible with old hns3 driver, these structures use
one-byte alignment. Then byte order conversions are added to mailbox
messages from PF to VF.
Signed-off-by: NJie Wang <wangjie125@huawei.com>
Signed-off-by: NGuangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Signed-off-by: NJiantao Xiao <xiaojiantao1@h-partners.com>
Reviewed-by: NYue Haibing <yuehaibing@huawei.com>
Reviewed-by: NJian Shen <shenjian15@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 99c65159
......@@ -134,13 +134,13 @@ struct hclge_vf_to_pf_msg {
};
struct hclge_pf_to_vf_msg {
u16 code;
__le16 code;
union {
/* used for mbx response */
struct {
u16 vf_mbx_msg_code;
u16 vf_mbx_msg_subcode;
u16 resp_status;
__le16 vf_mbx_msg_code;
__le16 vf_mbx_msg_subcode;
__le16 resp_status;
u8 resp_data[HCLGE_MBX_MAX_RESP_DATA_SIZE];
};
/* used for general mbx */
......@@ -157,7 +157,7 @@ struct hclge_mbx_vf_to_pf_cmd {
u8 rsv1[1];
u8 msg_len;
u8 rsv2;
u16 match_id;
__le16 match_id;
struct hclge_vf_to_pf_msg msg;
};
......@@ -168,7 +168,7 @@ struct hclge_mbx_pf_to_vf_cmd {
u8 rsv[3];
u8 msg_len;
u8 rsv1;
u16 match_id;
__le16 match_id;
struct hclge_pf_to_vf_msg msg;
};
......@@ -178,6 +178,28 @@ struct hclge_vf_rst_cmd {
u8 rsv[22];
};
#pragma pack(1)
struct hclge_mbx_link_status {
__le16 link_status;
__le32 speed;
__le16 duplex;
u8 flag;
};
struct hclge_mbx_link_mode {
__le16 idx;
__le64 link_mode;
};
struct hclge_mbx_port_base_vlan {
__le16 state;
__le16 vlan_proto;
__le16 qos;
__le16 vlan_tag;
};
#pragma pack()
/* used by VF to store the received Async responses from PF */
struct hclgevf_mbx_arq_ring {
#define HCLGE_MBX_MAX_ARQ_MSG_SIZE 8
......@@ -186,7 +208,7 @@ struct hclgevf_mbx_arq_ring {
u32 head;
u32 tail;
atomic_t count;
u16 msg_q[HCLGE_MBX_MAX_ARQ_MSG_NUM][HCLGE_MBX_MAX_ARQ_MSG_SIZE];
__le16 msg_q[HCLGE_MBX_MAX_ARQ_MSG_NUM][HCLGE_MBX_MAX_ARQ_MSG_SIZE];
};
#define hclge_mbx_ring_ptr_move_crq(crq) \
......
......@@ -57,17 +57,19 @@ static int hclge_gen_resp_to_vf(struct hclge_vport *vport,
resp_pf_to_vf->msg_len = vf_to_pf_req->msg_len;
resp_pf_to_vf->match_id = vf_to_pf_req->match_id;
resp_pf_to_vf->msg.code = HCLGE_MBX_PF_VF_RESP;
resp_pf_to_vf->msg.vf_mbx_msg_code = vf_to_pf_req->msg.code;
resp_pf_to_vf->msg.vf_mbx_msg_subcode = vf_to_pf_req->msg.subcode;
resp_pf_to_vf->msg.code = cpu_to_le16(HCLGE_MBX_PF_VF_RESP);
resp_pf_to_vf->msg.vf_mbx_msg_code =
cpu_to_le16(vf_to_pf_req->msg.code);
resp_pf_to_vf->msg.vf_mbx_msg_subcode =
cpu_to_le16(vf_to_pf_req->msg.subcode);
resp = hclge_errno_to_resp(resp_msg->status);
if (resp < SHRT_MAX) {
resp_pf_to_vf->msg.resp_status = resp;
resp_pf_to_vf->msg.resp_status = cpu_to_le16(resp);
} else {
dev_warn(&hdev->pdev->dev,
"failed to send response to VF, response status %u is out-of-bound\n",
resp);
resp_pf_to_vf->msg.resp_status = EIO;
resp_pf_to_vf->msg.resp_status = cpu_to_le16(EIO);
}
if (resp_msg->len > 0)
......@@ -107,7 +109,7 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
resp_pf_to_vf->dest_vfid = dest_vfid;
resp_pf_to_vf->msg_len = msg_len;
resp_pf_to_vf->msg.code = mbx_opcode;
resp_pf_to_vf->msg.code = cpu_to_le16(mbx_opcode);
memcpy(resp_pf_to_vf->msg.msg_data, msg, msg_len);
......@@ -125,8 +127,8 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len,
int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
{
struct hclge_dev *hdev = vport->back;
__le16 msg_data;
u16 reset_type;
u8 msg_data[2];
u8 dest_vfid;
BUILD_BUG_ON(HNAE3_MAX_RESET > U16_MAX);
......@@ -140,10 +142,10 @@ int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport)
else
reset_type = HNAE3_VF_FUNC_RESET;
memcpy(&msg_data[0], &reset_type, sizeof(u16));
msg_data = cpu_to_le16(reset_type);
/* send this requested info to VF */
return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data),
HCLGE_MBX_ASSERTING_RESET, dest_vfid);
}
......@@ -339,16 +341,14 @@ int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid,
u16 state,
struct hclge_vlan_info *vlan_info)
{
#define MSG_DATA_SIZE 8
struct hclge_mbx_port_base_vlan base_vlan;
u8 msg_data[MSG_DATA_SIZE];
base_vlan.state = cpu_to_le16(state);
base_vlan.vlan_proto = cpu_to_le16(vlan_info->vlan_proto);
base_vlan.qos = cpu_to_le16(vlan_info->qos);
base_vlan.vlan_tag = cpu_to_le16(vlan_info->vlan_tag);
memcpy(&msg_data[0], &state, sizeof(u16));
memcpy(&msg_data[2], &vlan_info->vlan_proto, sizeof(u16));
memcpy(&msg_data[4], &vlan_info->qos, sizeof(u16));
memcpy(&msg_data[6], &vlan_info->vlan_tag, sizeof(u16));
return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
return hclge_send_mbx_msg(vport, (u8 *)&base_vlan, sizeof(base_vlan),
HCLGE_MBX_PUSH_VLAN_INFO, vfid);
}
......@@ -488,10 +488,9 @@ int hclge_push_vf_link_status(struct hclge_vport *vport)
#define HCLGE_VF_LINK_STATE_UP 1U
#define HCLGE_VF_LINK_STATE_DOWN 0U
struct hclge_mbx_link_status link_info;
struct hclge_dev *hdev = vport->back;
u16 link_status;
u8 msg_data[9];
u16 duplex;
/* mac.link can only be 0 or 1 */
switch (vport->vf_info.link_state) {
......@@ -507,14 +506,13 @@ int hclge_push_vf_link_status(struct hclge_vport *vport)
break;
}
duplex = hdev->hw.mac.duplex;
memcpy(&msg_data[0], &link_status, sizeof(u16));
memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32));
memcpy(&msg_data[6], &duplex, sizeof(u16));
msg_data[8] = HCLGE_MBX_PUSH_LINK_STATUS_EN;
link_info.link_status = cpu_to_le16(link_status);
link_info.speed = cpu_to_le32(hdev->hw.mac.speed);
link_info.duplex = cpu_to_le16(hdev->hw.mac.duplex);
link_info.flag = HCLGE_MBX_PUSH_LINK_STATUS_EN;
/* send this requested info to VF */
return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
return hclge_send_mbx_msg(vport, (u8 *)&link_info, sizeof(link_info),
HCLGE_MBX_LINK_STAT_CHANGE, vport->vport_id);
}
......@@ -522,22 +520,22 @@ static void hclge_get_link_mode(struct hclge_vport *vport,
struct hclge_mbx_vf_to_pf_cmd *mbx_req)
{
#define HCLGE_SUPPORTED 1
struct hclge_mbx_link_mode link_mode;
struct hclge_dev *hdev = vport->back;
unsigned long advertising;
unsigned long supported;
unsigned long send_data;
u8 msg_data[10] = {};
u8 dest_vfid;
advertising = hdev->hw.mac.advertising[0];
supported = hdev->hw.mac.supported[0];
dest_vfid = mbx_req->mbx_src_vfid;
msg_data[0] = mbx_req->msg.data[0];
send_data = msg_data[0] == HCLGE_SUPPORTED ? supported : advertising;
send_data = mbx_req->msg.data[0] == HCLGE_SUPPORTED ? supported :
advertising;
link_mode.idx = cpu_to_le16((u16)mbx_req->msg.data[0]);
link_mode.link_mode = cpu_to_le64(send_data);
memcpy(&msg_data[2], &send_data, sizeof(unsigned long));
hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data),
hclge_send_mbx_msg(vport, (u8 *)&link_mode, sizeof(link_mode),
HCLGE_MBX_LINK_STAT_MODE, dest_vfid);
}
......
......@@ -62,7 +62,7 @@ TRACE_EVENT(hclge_pf_mbx_send,
TP_fast_assign(
__entry->vfid = req->dest_vfid;
__entry->code = req->msg.code;
__entry->code = le16_to_cpu(req->msg.code);
__assign_str(pciname, pci_name(hdev->pdev));
__assign_str(devname, &hdev->vport[0].nic.kinfo.netdev->name);
memcpy(__entry->mbx_data, req,
......
......@@ -3333,7 +3333,7 @@ static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
}
void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
u8 *port_base_vlan_info, u8 data_size)
struct hclge_mbx_port_base_vlan *port_base_vlan)
{
struct hnae3_handle *nic = &hdev->nic;
struct hclge_vf_to_pf_msg send_msg;
......@@ -3358,7 +3358,7 @@ void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
/* send msg to PF and wait update port based vlan info */
hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
HCLGE_MBX_PORT_BASE_VLAN_CFG);
memcpy(send_msg.data, port_base_vlan_info, data_size);
memcpy(send_msg.data, port_base_vlan, sizeof(*port_base_vlan));
ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
if (!ret) {
if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
......
......@@ -293,5 +293,5 @@ void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev);
void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev);
void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
u8 *port_base_vlan_info, u8 data_size);
struct hclge_mbx_port_base_vlan *port_base_vlan);
#endif
......@@ -124,7 +124,7 @@ int hclgevf_send_mbx_msg(struct hclgevf_dev *hdev,
if (need_resp) {
mutex_lock(&hdev->mbx_resp.mbx_mutex);
hclgevf_reset_mbx_resp_status(hdev);
req->match_id = hdev->mbx_resp.match_id;
req->match_id = cpu_to_le16(hdev->mbx_resp.match_id);
status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
if (status) {
dev_err(&hdev->pdev->dev,
......@@ -162,27 +162,29 @@ static bool hclgevf_cmd_crq_empty(struct hclgevf_hw *hw)
static void hclgevf_handle_mbx_response(struct hclgevf_dev *hdev,
struct hclge_mbx_pf_to_vf_cmd *req)
{
u16 vf_mbx_msg_subcode = le16_to_cpu(req->msg.vf_mbx_msg_subcode);
u16 vf_mbx_msg_code = le16_to_cpu(req->msg.vf_mbx_msg_code);
struct hclgevf_mbx_resp_status *resp = &hdev->mbx_resp;
u16 resp_status = le16_to_cpu(req->msg.resp_status);
u16 match_id = le16_to_cpu(req->match_id);
if (resp->received_resp)
dev_warn(&hdev->pdev->dev,
"VF mbx resp flag not clear(%u)\n",
req->msg.vf_mbx_msg_code);
resp->origin_mbx_msg =
(req->msg.vf_mbx_msg_code << 16);
resp->origin_mbx_msg |= req->msg.vf_mbx_msg_subcode;
resp->resp_status =
hclgevf_resp_to_errno(req->msg.resp_status);
"VF mbx resp flag not clear(%u)\n",
vf_mbx_msg_code);
resp->origin_mbx_msg = (vf_mbx_msg_code << 16);
resp->origin_mbx_msg |= vf_mbx_msg_subcode;
resp->resp_status = hclgevf_resp_to_errno(resp_status);
memcpy(resp->additional_info, req->msg.resp_data,
HCLGE_MBX_MAX_RESP_DATA_SIZE * sizeof(u8));
if (req->match_id) {
if (match_id) {
/* If match_id is not zero, it means PF support match_id.
* if the match_id is right, VF get the right response, or
* ignore the response. and driver will clear hdev->mbx_resp
* when send next message which need response.
*/
if (req->match_id == resp->match_id)
if (match_id == resp->match_id)
resp->received_resp = true;
} else {
resp->received_resp = true;
......@@ -199,7 +201,7 @@ static void hclgevf_handle_mbx_msg(struct hclgevf_dev *hdev,
HCLGE_MBX_MAX_ARQ_MSG_NUM) {
dev_warn(&hdev->pdev->dev,
"Async Q full, dropping msg(%u)\n",
req->msg.code);
le16_to_cpu(req->msg.code));
return;
}
......@@ -218,6 +220,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
struct hclge_comm_cmq_ring *crq;
struct hclge_desc *desc;
u16 flag;
u16 code;
crq = &hdev->hw.hw.cmq.crq;
......@@ -232,10 +235,11 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
req = (struct hclge_mbx_pf_to_vf_cmd *)desc->data;
flag = le16_to_cpu(crq->desc[crq->next_to_use].flag);
code = le16_to_cpu(req->msg.code);
if (unlikely(!hnae3_get_bit(flag, HCLGEVF_CMDQ_RX_OUTVLD_B))) {
dev_warn(&hdev->pdev->dev,
"dropped invalid mailbox message, code = %u\n",
req->msg.code);
code);
/* dropping/not processing this invalid message */
crq->desc[crq->next_to_use].flag = 0;
......@@ -251,7 +255,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
* timeout and simultaneously queue the async messages for later
* prcessing in context of mailbox task i.e. the slow path.
*/
switch (req->msg.code) {
switch (code) {
case HCLGE_MBX_PF_VF_RESP:
hclgevf_handle_mbx_response(hdev, req);
break;
......@@ -265,7 +269,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
default:
dev_err(&hdev->pdev->dev,
"VF received unsupported(%u) mbx msg from PF\n",
req->msg.code);
code);
break;
}
crq->desc[crq->next_to_use].flag = 0;
......@@ -287,14 +291,18 @@ static void hclgevf_parse_promisc_info(struct hclgevf_dev *hdev,
void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
{
struct hclge_mbx_port_base_vlan *vlan_info;
struct hclge_mbx_link_status *link_info;
struct hclge_mbx_link_mode *link_mode;
enum hnae3_reset_type reset_type;
u16 link_status, state;
u16 *msg_q, *vlan_info;
__le16 *msg_q;
u16 opcode;
u8 duplex;
u32 speed;
u32 tail;
u8 flag;
u8 idx;
u16 idx;
tail = hdev->arq.tail;
......@@ -308,13 +316,14 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
}
msg_q = hdev->arq.msg_q[hdev->arq.head];
switch (msg_q[0]) {
opcode = le16_to_cpu(msg_q[0]);
switch (opcode) {
case HCLGE_MBX_LINK_STAT_CHANGE:
link_status = msg_q[1];
memcpy(&speed, &msg_q[2], sizeof(speed));
duplex = (u8)msg_q[4];
flag = (u8)msg_q[5];
link_info = (struct hclge_mbx_link_status *)(msg_q + 1);
link_status = le16_to_cpu(link_info->link_status);
speed = le32_to_cpu(link_info->speed);
duplex = (u8)le16_to_cpu(link_info->duplex);
flag = link_info->flag;
/* update upper layer with new link link status */
hclgevf_update_speed_duplex(hdev, speed, duplex);
......@@ -326,13 +335,14 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
break;
case HCLGE_MBX_LINK_STAT_MODE:
idx = (u8)msg_q[1];
link_mode = (struct hclge_mbx_link_mode *)(msg_q + 1);
idx = le16_to_cpu(link_mode->idx);
if (idx)
memcpy(&hdev->hw.mac.supported, &msg_q[2],
sizeof(unsigned long));
hdev->hw.mac.supported =
le64_to_cpu(link_mode->link_mode);
else
memcpy(&hdev->hw.mac.advertising, &msg_q[2],
sizeof(unsigned long));
hdev->hw.mac.advertising =
le64_to_cpu(link_mode->link_mode);
break;
case HCLGE_MBX_ASSERTING_RESET:
/* PF has asserted reset hence VF should go in pending
......@@ -340,25 +350,27 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
* has been completely reset. After this stack should
* eventually be re-initialized.
*/
reset_type = (enum hnae3_reset_type)msg_q[1];
reset_type =
(enum hnae3_reset_type)le16_to_cpu(msg_q[1]);
set_bit(reset_type, &hdev->reset_pending);
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
hclgevf_reset_task_schedule(hdev);
break;
case HCLGE_MBX_PUSH_VLAN_INFO:
state = msg_q[1];
vlan_info = &msg_q[1];
vlan_info =
(struct hclge_mbx_port_base_vlan *)(msg_q + 1);
state = le16_to_cpu(vlan_info->state);
hclgevf_update_port_base_vlan_info(hdev, state,
(u8 *)vlan_info, 8);
vlan_info);
break;
case HCLGE_MBX_PUSH_PROMISC_INFO:
hclgevf_parse_promisc_info(hdev, msg_q[1]);
hclgevf_parse_promisc_info(hdev, le16_to_cpu(msg_q[1]));
break;
default:
dev_err(&hdev->pdev->dev,
"fetched unsupported(%u) message from arq\n",
msg_q[0]);
opcode);
break;
}
......
......@@ -29,7 +29,7 @@ TRACE_EVENT(hclge_vf_mbx_get,
TP_fast_assign(
__entry->vfid = req->dest_vfid;
__entry->code = req->msg.code;
__entry->code = le16_to_cpu(req->msg.code);
__assign_str(pciname, pci_name(hdev->pdev));
__assign_str(devname, &hdev->nic.kinfo.netdev->name);
memcpy(__entry->mbx_data, req,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册