1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (c) 2016-2017 Hisilicon Limited.
5 #include "hclgevf_main.h"
8 static void hclgevf_reset_mbx_resp_status(struct hclgevf_dev
*hdev
)
10 /* this function should be called with mbx_resp.mbx_mutex held
11 * to prtect the received_response from race condition
13 hdev
->mbx_resp
.received_resp
= false;
14 hdev
->mbx_resp
.origin_mbx_msg
= 0;
15 hdev
->mbx_resp
.resp_status
= 0;
16 memset(hdev
->mbx_resp
.additional_info
, 0, HCLGE_MBX_MAX_RESP_DATA_SIZE
);
19 /* hclgevf_get_mbx_resp: used to get a response from PF after VF sends a mailbox
21 * @hdev: pointer to struct hclgevf_dev
22 * @resp_msg: pointer to store the original message type and response status
23 * @len: the resp_msg data array length.
25 static int hclgevf_get_mbx_resp(struct hclgevf_dev
*hdev
, u16 code0
, u16 code1
,
26 u8
*resp_data
, u16 resp_len
)
28 #define HCLGEVF_MAX_TRY_TIMES 500
29 #define HCLGEVF_SLEEP_USCOEND 1000
30 struct hclgevf_mbx_resp_status
*mbx_resp
;
34 if (resp_len
> HCLGE_MBX_MAX_RESP_DATA_SIZE
) {
35 dev_err(&hdev
->pdev
->dev
,
36 "VF mbx response len(=%d) exceeds maximum(=%d)\n",
38 HCLGE_MBX_MAX_RESP_DATA_SIZE
);
42 while ((!hdev
->mbx_resp
.received_resp
) && (i
< HCLGEVF_MAX_TRY_TIMES
)) {
43 udelay(HCLGEVF_SLEEP_USCOEND
);
47 if (i
>= HCLGEVF_MAX_TRY_TIMES
) {
48 dev_err(&hdev
->pdev
->dev
,
49 "VF could not get mbx resp(=%d) from PF in %d tries\n",
50 hdev
->mbx_resp
.received_resp
, i
);
54 mbx_resp
= &hdev
->mbx_resp
;
55 r_code0
= (u16
)(mbx_resp
->origin_mbx_msg
>> 16);
56 r_code1
= (u16
)(mbx_resp
->origin_mbx_msg
& 0xff);
58 if (mbx_resp
->resp_status
)
59 return mbx_resp
->resp_status
;
62 memcpy(resp_data
, &mbx_resp
->additional_info
[0], resp_len
);
64 hclgevf_reset_mbx_resp_status(hdev
);
66 if (!(r_code0
== code0
&& r_code1
== code1
&& !mbx_resp
->resp_status
)) {
67 dev_err(&hdev
->pdev
->dev
,
68 "VF could not match resp code(code0=%d,code1=%d), %d",
69 code0
, code1
, mbx_resp
->resp_status
);
76 int hclgevf_send_mbx_msg(struct hclgevf_dev
*hdev
, u16 code
, u16 subcode
,
77 const u8
*msg_data
, u8 msg_len
, bool need_resp
,
78 u8
*resp_data
, u16 resp_len
)
80 struct hclge_mbx_vf_to_pf_cmd
*req
;
81 struct hclgevf_desc desc
;
84 req
= (struct hclge_mbx_vf_to_pf_cmd
*)desc
.data
;
86 /* first two bytes are reserved for code & subcode */
87 if (msg_len
> (HCLGE_MBX_MAX_MSG_SIZE
- 2)) {
88 dev_err(&hdev
->pdev
->dev
,
89 "VF send mbx msg fail, msg len %d exceeds max len %d\n",
90 msg_len
, HCLGE_MBX_MAX_MSG_SIZE
);
94 hclgevf_cmd_setup_basic_desc(&desc
, HCLGEVF_OPC_MBX_VF_TO_PF
, false);
96 req
->msg
[1] = subcode
;
97 memcpy(&req
->msg
[2], msg_data
, msg_len
);
99 /* synchronous send */
101 mutex_lock(&hdev
->mbx_resp
.mbx_mutex
);
102 hclgevf_reset_mbx_resp_status(hdev
);
103 status
= hclgevf_cmd_send(&hdev
->hw
, &desc
, 1);
105 dev_err(&hdev
->pdev
->dev
,
106 "VF failed(=%d) to send mbx message to PF\n",
108 mutex_unlock(&hdev
->mbx_resp
.mbx_mutex
);
112 status
= hclgevf_get_mbx_resp(hdev
, code
, subcode
, resp_data
,
114 mutex_unlock(&hdev
->mbx_resp
.mbx_mutex
);
116 /* asynchronous send */
117 status
= hclgevf_cmd_send(&hdev
->hw
, &desc
, 1);
119 dev_err(&hdev
->pdev
->dev
,
120 "VF failed(=%d) to send mbx message to PF\n",
129 static bool hclgevf_cmd_crq_empty(struct hclgevf_hw
*hw
)
131 u32 tail
= hclgevf_read_dev(hw
, HCLGEVF_NIC_CRQ_TAIL_REG
);
133 return tail
== hw
->cmq
.crq
.next_to_use
;
136 void hclgevf_mbx_handler(struct hclgevf_dev
*hdev
)
138 struct hclgevf_mbx_resp_status
*resp
;
139 struct hclge_mbx_pf_to_vf_cmd
*req
;
140 struct hclgevf_cmq_ring
*crq
;
141 struct hclgevf_desc
*desc
;
147 resp
= &hdev
->mbx_resp
;
148 crq
= &hdev
->hw
.cmq
.crq
;
150 while (!hclgevf_cmd_crq_empty(&hdev
->hw
)) {
151 desc
= &crq
->desc
[crq
->next_to_use
];
152 req
= (struct hclge_mbx_pf_to_vf_cmd
*)desc
->data
;
154 flag
= le16_to_cpu(crq
->desc
[crq
->next_to_use
].flag
);
155 if (unlikely(!hnae3_get_bit(flag
, HCLGEVF_CMDQ_RX_OUTVLD_B
))) {
156 dev_warn(&hdev
->pdev
->dev
,
157 "dropped invalid mailbox message, code = %d\n",
160 /* dropping/not processing this invalid message */
161 crq
->desc
[crq
->next_to_use
].flag
= 0;
162 hclge_mbx_ring_ptr_move_crq(crq
);
166 /* synchronous messages are time critical and need preferential
167 * treatment. Therefore, we need to acknowledge all the sync
168 * responses as quickly as possible so that waiting tasks do not
169 * timeout and simultaneously queue the async messages for later
170 * prcessing in context of mailbox task i.e. the slow path.
172 switch (req
->msg
[0]) {
173 case HCLGE_MBX_PF_VF_RESP
:
174 if (resp
->received_resp
)
175 dev_warn(&hdev
->pdev
->dev
,
176 "VF mbx resp flag not clear(%d)\n",
178 resp
->received_resp
= true;
180 resp
->origin_mbx_msg
= (req
->msg
[1] << 16);
181 resp
->origin_mbx_msg
|= req
->msg
[2];
182 resp
->resp_status
= req
->msg
[3];
184 temp
= (u8
*)&req
->msg
[4];
185 for (i
= 0; i
< HCLGE_MBX_MAX_RESP_DATA_SIZE
; i
++) {
186 resp
->additional_info
[i
] = *temp
;
190 case HCLGE_MBX_LINK_STAT_CHANGE
:
191 case HCLGE_MBX_ASSERTING_RESET
:
192 /* set this mbx event as pending. This is required as we
193 * might loose interrupt event when mbx task is busy
194 * handling. This shall be cleared when mbx task just
195 * enters handling state.
197 hdev
->mbx_event_pending
= true;
199 /* we will drop the async msg if we find ARQ as full
200 * and continue with next message
202 if (hdev
->arq
.count
>= HCLGE_MBX_MAX_ARQ_MSG_NUM
) {
203 dev_warn(&hdev
->pdev
->dev
,
204 "Async Q full, dropping msg(%d)\n",
209 /* tail the async message in arq */
210 msg_q
= hdev
->arq
.msg_q
[hdev
->arq
.tail
];
211 memcpy(&msg_q
[0], req
->msg
,
212 HCLGE_MBX_MAX_ARQ_MSG_SIZE
* sizeof(u16
));
213 hclge_mbx_tail_ptr_move_arq(hdev
->arq
);
216 hclgevf_mbx_task_schedule(hdev
);
220 dev_err(&hdev
->pdev
->dev
,
221 "VF received unsupported(%d) mbx msg from PF\n",
225 crq
->desc
[crq
->next_to_use
].flag
= 0;
226 hclge_mbx_ring_ptr_move_crq(crq
);
229 /* Write back CMDQ_RQ header pointer, M7 need this pointer */
230 hclgevf_write_dev(&hdev
->hw
, HCLGEVF_NIC_CRQ_HEAD_REG
,
234 void hclgevf_mbx_async_handler(struct hclgevf_dev
*hdev
)
242 /* we can safely clear it now as we are at start of the async message
245 hdev
->mbx_event_pending
= false;
247 tail
= hdev
->arq
.tail
;
249 /* process all the async queue messages */
250 while (tail
!= hdev
->arq
.head
) {
251 msg_q
= hdev
->arq
.msg_q
[hdev
->arq
.head
];
254 case HCLGE_MBX_LINK_STAT_CHANGE
:
255 link_status
= le16_to_cpu(msg_q
[1]);
256 memcpy(&speed
, &msg_q
[2], sizeof(speed
));
257 duplex
= (u8
)le16_to_cpu(msg_q
[4]);
259 /* update upper layer with new link link status */
260 hclgevf_update_link_status(hdev
, link_status
);
261 hclgevf_update_speed_duplex(hdev
, speed
, duplex
);
264 case HCLGE_MBX_ASSERTING_RESET
:
265 /* PF has asserted reset hence VF should go in pending
266 * state and poll for the hardware reset status till it
267 * has been completely reset. After this stack should
268 * eventually be re-initialized.
270 hdev
->nic
.reset_level
= HNAE3_VF_RESET
;
271 set_bit(HCLGEVF_RESET_PENDING
, &hdev
->reset_state
);
272 hclgevf_reset_task_schedule(hdev
);
276 dev_err(&hdev
->pdev
->dev
,
277 "fetched unsupported(%d) message from arq\n",
282 hclge_mbx_head_ptr_move_arq(hdev
->arq
);
284 msg_q
= hdev
->arq
.msg_q
[hdev
->arq
.head
];