Commit | Line | Data |
---|---|---|
dde1a86e SM |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | // Copyright (c) 2016-2017 Hisilicon Limited. | |
3 | ||
4 | #include "hclge_main.h" | |
5 | #include "hclge_mbx.h" | |
6 | #include "hnae3.h" | |
7 | ||
8 | /* hclge_gen_resp_to_vf: used to generate a synchronous response to VF when PF | |
9 | * receives a mailbox message from VF. | |
10 | * @vport: pointer to struct hclge_vport | |
11 | * @vf_to_pf_req: pointer to hclge_mbx_vf_to_pf_cmd of the original mailbox | |
12 | * message | |
13 | * @resp_status: indicate to VF whether its request success(0) or failed. | |
14 | */ | |
15 | static int hclge_gen_resp_to_vf(struct hclge_vport *vport, | |
16 | struct hclge_mbx_vf_to_pf_cmd *vf_to_pf_req, | |
17 | int resp_status, | |
18 | u8 *resp_data, u16 resp_data_len) | |
19 | { | |
20 | struct hclge_mbx_pf_to_vf_cmd *resp_pf_to_vf; | |
21 | struct hclge_dev *hdev = vport->back; | |
22 | enum hclge_cmd_status status; | |
23 | struct hclge_desc desc; | |
24 | ||
25 | resp_pf_to_vf = (struct hclge_mbx_pf_to_vf_cmd *)desc.data; | |
26 | ||
27 | if (resp_data_len > HCLGE_MBX_MAX_RESP_DATA_SIZE) { | |
28 | dev_err(&hdev->pdev->dev, | |
adcf738b | 29 | "PF fail to gen resp to VF len %u exceeds max len %u\n", |
dde1a86e SM |
30 | resp_data_len, |
31 | HCLGE_MBX_MAX_RESP_DATA_SIZE); | |
89295152 PL |
32 | /* If resp_data_len is too long, set the value to max length |
33 | * and return the msg to VF | |
34 | */ | |
35 | resp_data_len = HCLGE_MBX_MAX_RESP_DATA_SIZE; | |
dde1a86e SM |
36 | } |
37 | ||
38 | hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false); | |
39 | ||
40 | resp_pf_to_vf->dest_vfid = vf_to_pf_req->mbx_src_vfid; | |
41 | resp_pf_to_vf->msg_len = vf_to_pf_req->msg_len; | |
42 | ||
43 | resp_pf_to_vf->msg[0] = HCLGE_MBX_PF_VF_RESP; | |
44 | resp_pf_to_vf->msg[1] = vf_to_pf_req->msg[0]; | |
45 | resp_pf_to_vf->msg[2] = vf_to_pf_req->msg[1]; | |
46 | resp_pf_to_vf->msg[3] = (resp_status == 0) ? 0 : 1; | |
47 | ||
48 | if (resp_data && resp_data_len > 0) | |
49 | memcpy(&resp_pf_to_vf->msg[4], resp_data, resp_data_len); | |
50 | ||
51 | status = hclge_cmd_send(&hdev->hw, &desc, 1); | |
52 | if (status) | |
53 | dev_err(&hdev->pdev->dev, | |
54 | "PF failed(=%d) to send response to VF\n", status); | |
55 | ||
56 | return status; | |
57 | } | |
58 | ||
59 | static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len, | |
60 | u16 mbx_opcode, u8 dest_vfid) | |
61 | { | |
62 | struct hclge_mbx_pf_to_vf_cmd *resp_pf_to_vf; | |
63 | struct hclge_dev *hdev = vport->back; | |
64 | enum hclge_cmd_status status; | |
65 | struct hclge_desc desc; | |
66 | ||
67 | resp_pf_to_vf = (struct hclge_mbx_pf_to_vf_cmd *)desc.data; | |
68 | ||
69 | hclge_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_MBX_PF_TO_VF, false); | |
70 | ||
71 | resp_pf_to_vf->dest_vfid = dest_vfid; | |
72 | resp_pf_to_vf->msg_len = msg_len; | |
73 | resp_pf_to_vf->msg[0] = mbx_opcode; | |
74 | ||
75 | memcpy(&resp_pf_to_vf->msg[1], msg, msg_len); | |
76 | ||
77 | status = hclge_cmd_send(&hdev->hw, &desc, 1); | |
78 | if (status) | |
79 | dev_err(&hdev->pdev->dev, | |
80 | "PF failed(=%d) to send mailbox message to VF\n", | |
81 | status); | |
82 | ||
83 | return status; | |
84 | } | |
85 | ||
dea846e8 | 86 | int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport) |
2bfbd35d | 87 | { |
aa5c4f17 HT |
88 | struct hclge_dev *hdev = vport->back; |
89 | enum hnae3_reset_type reset_type; | |
2bfbd35d SM |
90 | u8 msg_data[2]; |
91 | u8 dest_vfid; | |
92 | ||
93 | dest_vfid = (u8)vport->vport_id; | |
94 | ||
aa5c4f17 HT |
95 | if (hdev->reset_type == HNAE3_FUNC_RESET) |
96 | reset_type = HNAE3_VF_PF_FUNC_RESET; | |
6b9a97ee HT |
97 | else if (hdev->reset_type == HNAE3_FLR_RESET) |
98 | reset_type = HNAE3_VF_FULL_RESET; | |
aa5c4f17 | 99 | else |
0cd86182 | 100 | reset_type = HNAE3_VF_FUNC_RESET; |
aa5c4f17 HT |
101 | |
102 | memcpy(&msg_data[0], &reset_type, sizeof(u16)); | |
103 | ||
2bfbd35d | 104 | /* send this requested info to VF */ |
aa5c4f17 | 105 | return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), |
2bfbd35d SM |
106 | HCLGE_MBX_ASSERTING_RESET, dest_vfid); |
107 | } | |
108 | ||
84e095d6 SM |
109 | static void hclge_free_vector_ring_chain(struct hnae3_ring_chain_node *head) |
110 | { | |
111 | struct hnae3_ring_chain_node *chain_tmp, *chain; | |
112 | ||
113 | chain = head->next; | |
114 | ||
115 | while (chain) { | |
116 | chain_tmp = chain->next; | |
117 | kzfree(chain); | |
118 | chain = chain_tmp; | |
119 | } | |
120 | } | |
121 | ||
5550aa4d FL |
122 | /* hclge_get_ring_chain_from_mbx: get ring type & tqp id & int_gl idx |
123 | * from mailbox message | |
84e095d6 SM |
124 | * msg[0]: opcode |
125 | * msg[1]: <not relevant to this function> | |
126 | * msg[2]: ring_num | |
127 | * msg[3]: first ring type (TX|RX) | |
128 | * msg[4]: first tqp id | |
5550aa4d FL |
129 | * msg[5]: first int_gl idx |
130 | * msg[6] ~ msg[14]: other ring type, tqp id and int_gl idx | |
84e095d6 SM |
131 | */ |
132 | static int hclge_get_ring_chain_from_mbx( | |
133 | struct hclge_mbx_vf_to_pf_cmd *req, | |
134 | struct hnae3_ring_chain_node *ring_chain, | |
135 | struct hclge_vport *vport) | |
136 | { | |
84e095d6 SM |
137 | struct hnae3_ring_chain_node *cur_chain, *new_chain; |
138 | int ring_num; | |
139 | int i; | |
140 | ||
141 | ring_num = req->msg[2]; | |
142 | ||
5d02a58d YL |
143 | if (ring_num > ((HCLGE_MBX_VF_MSG_DATA_NUM - |
144 | HCLGE_MBX_RING_MAP_BASIC_MSG_NUM) / | |
145 | HCLGE_MBX_RING_NODE_VARIABLE_NUM)) | |
146 | return -ENOMEM; | |
147 | ||
e4e87715 | 148 | hnae3_set_bit(ring_chain->flag, HNAE3_RING_TYPE_B, req->msg[3]); |
84e095d6 SM |
149 | ring_chain->tqp_index = |
150 | hclge_get_queue_id(vport->nic.kinfo.tqp[req->msg[4]]); | |
cf4103c6 FL |
151 | hnae3_set_field(ring_chain->int_gl_idx, HNAE3_RING_GL_IDX_M, |
152 | HNAE3_RING_GL_IDX_S, | |
e4e87715 | 153 | req->msg[5]); |
84e095d6 SM |
154 | |
155 | cur_chain = ring_chain; | |
156 | ||
157 | for (i = 1; i < ring_num; i++) { | |
158 | new_chain = kzalloc(sizeof(*new_chain), GFP_KERNEL); | |
159 | if (!new_chain) | |
160 | goto err; | |
161 | ||
e4e87715 PL |
162 | hnae3_set_bit(new_chain->flag, HNAE3_RING_TYPE_B, |
163 | req->msg[HCLGE_MBX_RING_NODE_VARIABLE_NUM * i + | |
164 | HCLGE_MBX_RING_MAP_BASIC_MSG_NUM]); | |
84e095d6 SM |
165 | |
166 | new_chain->tqp_index = | |
167 | hclge_get_queue_id(vport->nic.kinfo.tqp | |
5d02a58d YL |
168 | [req->msg[HCLGE_MBX_RING_NODE_VARIABLE_NUM * i + |
169 | HCLGE_MBX_RING_MAP_BASIC_MSG_NUM + 1]]); | |
84e095d6 | 170 | |
cf4103c6 FL |
171 | hnae3_set_field(new_chain->int_gl_idx, HNAE3_RING_GL_IDX_M, |
172 | HNAE3_RING_GL_IDX_S, | |
e4e87715 PL |
173 | req->msg[HCLGE_MBX_RING_NODE_VARIABLE_NUM * i + |
174 | HCLGE_MBX_RING_MAP_BASIC_MSG_NUM + 2]); | |
79eee410 | 175 | |
84e095d6 SM |
176 | cur_chain->next = new_chain; |
177 | cur_chain = new_chain; | |
178 | } | |
179 | ||
180 | return 0; | |
181 | err: | |
182 | hclge_free_vector_ring_chain(ring_chain); | |
183 | return -ENOMEM; | |
184 | } | |
185 | ||
186 | static int hclge_map_unmap_ring_to_vf_vector(struct hclge_vport *vport, bool en, | |
187 | struct hclge_mbx_vf_to_pf_cmd *req) | |
188 | { | |
189 | struct hnae3_ring_chain_node ring_chain; | |
190 | int vector_id = req->msg[1]; | |
191 | int ret; | |
192 | ||
193 | memset(&ring_chain, 0, sizeof(ring_chain)); | |
194 | ret = hclge_get_ring_chain_from_mbx(req, &ring_chain, vport); | |
195 | if (ret) | |
196 | return ret; | |
197 | ||
198 | ret = hclge_bind_ring_with_vector(vport, vector_id, en, &ring_chain); | |
84e095d6 SM |
199 | |
200 | hclge_free_vector_ring_chain(&ring_chain); | |
201 | ||
49f971bd | 202 | return ret; |
84e095d6 SM |
203 | } |
204 | ||
dde1a86e SM |
205 | static int hclge_set_vf_promisc_mode(struct hclge_vport *vport, |
206 | struct hclge_mbx_vf_to_pf_cmd *req) | |
207 | { | |
e196ec75 JS |
208 | #define HCLGE_MBX_BC_INDEX 1 |
209 | #define HCLGE_MBX_UC_INDEX 2 | |
210 | #define HCLGE_MBX_MC_INDEX 3 | |
dde1a86e | 211 | |
e196ec75 JS |
212 | bool en_bc = req->msg[HCLGE_MBX_BC_INDEX] ? true : false; |
213 | bool en_uc = req->msg[HCLGE_MBX_UC_INDEX] ? true : false; | |
214 | bool en_mc = req->msg[HCLGE_MBX_MC_INDEX] ? true : false; | |
215 | int ret; | |
216 | ||
217 | if (!vport->vf_info.trusted) { | |
218 | en_uc = false; | |
219 | en_mc = false; | |
220 | } | |
221 | ||
222 | ret = hclge_set_vport_promisc_mode(vport, en_uc, en_mc, en_bc); | |
223 | if (req->mbx_need_resp) | |
224 | hclge_gen_resp_to_vf(vport, req, ret, NULL, 0); | |
225 | ||
226 | vport->vf_info.promisc_enable = (en_uc || en_mc) ? 1 : 0; | |
227 | ||
228 | return ret; | |
229 | } | |
230 | ||
231 | void hclge_inform_vf_promisc_info(struct hclge_vport *vport) | |
232 | { | |
233 | u8 dest_vfid = (u8)vport->vport_id; | |
234 | u8 msg_data[2]; | |
235 | ||
236 | memcpy(&msg_data[0], &vport->vf_info.promisc_enable, sizeof(u16)); | |
237 | ||
238 | hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), | |
239 | HCLGE_MBX_PUSH_PROMISC_INFO, dest_vfid); | |
dde1a86e SM |
240 | } |
241 | ||
242 | static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport, | |
b7048d32 | 243 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) |
dde1a86e SM |
244 | { |
245 | const u8 *mac_addr = (const u8 *)(&mbx_req->msg[2]); | |
246 | struct hclge_dev *hdev = vport->back; | |
247 | int status; | |
248 | ||
249 | if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_MODIFY) { | |
250 | const u8 *old_addr = (const u8 *)(&mbx_req->msg[8]); | |
251 | ||
8e6de441 HT |
252 | /* If VF MAC has been configured by the host then it |
253 | * cannot be overridden by the MAC specified by the VM. | |
254 | */ | |
255 | if (!is_zero_ether_addr(vport->vf_info.mac) && | |
256 | !ether_addr_equal(mac_addr, vport->vf_info.mac)) { | |
257 | status = -EPERM; | |
258 | goto out; | |
259 | } | |
260 | ||
261 | if (!is_valid_ether_addr(mac_addr)) { | |
262 | status = -EINVAL; | |
263 | goto out; | |
264 | } | |
265 | ||
dde1a86e SM |
266 | hclge_rm_uc_addr_common(vport, old_addr); |
267 | status = hclge_add_uc_addr_common(vport, mac_addr); | |
6dd86902 | 268 | if (status) { |
59098055 | 269 | hclge_add_uc_addr_common(vport, old_addr); |
6dd86902 | 270 | } else { |
271 | hclge_rm_vport_mac_table(vport, mac_addr, | |
272 | false, HCLGE_MAC_ADDR_UC); | |
273 | hclge_add_vport_mac_table(vport, mac_addr, | |
274 | HCLGE_MAC_ADDR_UC); | |
275 | } | |
dde1a86e SM |
276 | } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_ADD) { |
277 | status = hclge_add_uc_addr_common(vport, mac_addr); | |
6dd86902 | 278 | if (!status) |
279 | hclge_add_vport_mac_table(vport, mac_addr, | |
280 | HCLGE_MAC_ADDR_UC); | |
dde1a86e SM |
281 | } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_REMOVE) { |
282 | status = hclge_rm_uc_addr_common(vport, mac_addr); | |
6dd86902 | 283 | if (!status) |
284 | hclge_rm_vport_mac_table(vport, mac_addr, | |
285 | false, HCLGE_MAC_ADDR_UC); | |
dde1a86e SM |
286 | } else { |
287 | dev_err(&hdev->pdev->dev, | |
adcf738b | 288 | "failed to set unicast mac addr, unknown subcode %u\n", |
dde1a86e SM |
289 | mbx_req->msg[1]); |
290 | return -EIO; | |
291 | } | |
292 | ||
8e6de441 | 293 | out: |
b7048d32 | 294 | if (mbx_req->mbx_need_resp & HCLGE_MBX_NEED_RESP_BIT) |
dde1a86e SM |
295 | hclge_gen_resp_to_vf(vport, mbx_req, status, NULL, 0); |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
300 | static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport, | |
301 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
302 | bool gen_resp) | |
303 | { | |
304 | const u8 *mac_addr = (const u8 *)(&mbx_req->msg[2]); | |
305 | struct hclge_dev *hdev = vport->back; | |
3a678b58 XW |
306 | u8 resp_len = 0; |
307 | u8 resp_data; | |
dde1a86e SM |
308 | int status; |
309 | ||
310 | if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_ADD) { | |
311 | status = hclge_add_mc_addr_common(vport, mac_addr); | |
6dd86902 | 312 | if (!status) |
313 | hclge_add_vport_mac_table(vport, mac_addr, | |
314 | HCLGE_MAC_ADDR_MC); | |
dde1a86e SM |
315 | } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_REMOVE) { |
316 | status = hclge_rm_mc_addr_common(vport, mac_addr); | |
6dd86902 | 317 | if (!status) |
318 | hclge_rm_vport_mac_table(vport, mac_addr, | |
319 | false, HCLGE_MAC_ADDR_MC); | |
dde1a86e SM |
320 | } else { |
321 | dev_err(&hdev->pdev->dev, | |
adcf738b | 322 | "failed to set mcast mac addr, unknown subcode %u\n", |
dde1a86e SM |
323 | mbx_req->msg[1]); |
324 | return -EIO; | |
325 | } | |
326 | ||
327 | if (gen_resp) | |
3a678b58 XW |
328 | hclge_gen_resp_to_vf(vport, mbx_req, status, |
329 | &resp_data, resp_len); | |
dde1a86e SM |
330 | |
331 | return 0; | |
332 | } | |
333 | ||
92f11ea1 JS |
334 | int hclge_push_vf_port_base_vlan_info(struct hclge_vport *vport, u8 vfid, |
335 | u16 state, u16 vlan_tag, u16 qos, | |
336 | u16 vlan_proto) | |
337 | { | |
338 | #define MSG_DATA_SIZE 8 | |
339 | ||
340 | u8 msg_data[MSG_DATA_SIZE]; | |
341 | ||
342 | memcpy(&msg_data[0], &state, sizeof(u16)); | |
343 | memcpy(&msg_data[2], &vlan_proto, sizeof(u16)); | |
344 | memcpy(&msg_data[4], &qos, sizeof(u16)); | |
345 | memcpy(&msg_data[6], &vlan_tag, sizeof(u16)); | |
346 | ||
347 | return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), | |
4803d010 | 348 | HCLGE_MBX_PUSH_VLAN_INFO, vfid); |
92f11ea1 JS |
349 | } |
350 | ||
dde1a86e | 351 | static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport, |
92f11ea1 | 352 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) |
dde1a86e | 353 | { |
ebaf1908 | 354 | struct hclge_vf_vlan_cfg *msg_cmd; |
dde1a86e SM |
355 | int status = 0; |
356 | ||
ebaf1908 WL |
357 | msg_cmd = (struct hclge_vf_vlan_cfg *)mbx_req->msg; |
358 | if (msg_cmd->subcode == HCLGE_MBX_VLAN_FILTER) { | |
dc8131d8 | 359 | struct hnae3_handle *handle = &vport->nic; |
dde1a86e SM |
360 | u16 vlan, proto; |
361 | bool is_kill; | |
362 | ||
ebaf1908 WL |
363 | is_kill = !!msg_cmd->is_kill; |
364 | vlan = msg_cmd->vlan; | |
365 | proto = msg_cmd->proto; | |
dc8131d8 YL |
366 | status = hclge_set_vlan_filter(handle, cpu_to_be16(proto), |
367 | vlan, is_kill); | |
22044f95 JS |
368 | if (mbx_req->mbx_need_resp) |
369 | return hclge_gen_resp_to_vf(vport, mbx_req, status, | |
370 | NULL, 0); | |
ebaf1908 | 371 | } else if (msg_cmd->subcode == HCLGE_MBX_VLAN_RX_OFF_CFG) { |
b2641e2a | 372 | struct hnae3_handle *handle = &vport->nic; |
ebaf1908 | 373 | bool en = msg_cmd->is_kill ? true : false; |
b2641e2a YL |
374 | |
375 | status = hclge_en_hw_strip_rxvtag(handle, en); | |
92f11ea1 JS |
376 | } else if (mbx_req->msg[1] == HCLGE_MBX_PORT_BASE_VLAN_CFG) { |
377 | struct hclge_vlan_info *vlan_info; | |
378 | u16 *state; | |
379 | ||
380 | state = (u16 *)&mbx_req->msg[2]; | |
381 | vlan_info = (struct hclge_vlan_info *)&mbx_req->msg[4]; | |
382 | status = hclge_update_port_base_vlan_cfg(vport, *state, | |
383 | vlan_info); | |
384 | } else if (mbx_req->msg[1] == HCLGE_MBX_GET_PORT_BASE_VLAN_STATE) { | |
385 | u8 state; | |
386 | ||
387 | state = vport->port_base_vlan_cfg.state; | |
388 | status = hclge_gen_resp_to_vf(vport, mbx_req, 0, &state, | |
389 | sizeof(u8)); | |
dde1a86e SM |
390 | } |
391 | ||
dde1a86e SM |
392 | return status; |
393 | } | |
394 | ||
a6d818e3 YL |
395 | static int hclge_set_vf_alive(struct hclge_vport *vport, |
396 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
397 | bool gen_resp) | |
398 | { | |
399 | bool alive = !!mbx_req->msg[2]; | |
400 | int ret = 0; | |
401 | ||
402 | if (alive) | |
403 | ret = hclge_vport_start(vport); | |
404 | else | |
405 | hclge_vport_stop(vport); | |
406 | ||
407 | return ret; | |
408 | } | |
409 | ||
dde1a86e SM |
410 | static int hclge_get_vf_tcinfo(struct hclge_vport *vport, |
411 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
412 | bool gen_resp) | |
413 | { | |
de67a690 YL |
414 | struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; |
415 | u8 vf_tc_map = 0; | |
ebaf1908 WL |
416 | unsigned int i; |
417 | int ret; | |
de67a690 YL |
418 | |
419 | for (i = 0; i < kinfo->num_tc; i++) | |
420 | vf_tc_map |= BIT(i); | |
dde1a86e | 421 | |
de67a690 | 422 | ret = hclge_gen_resp_to_vf(vport, mbx_req, 0, &vf_tc_map, |
63cbf7a9 | 423 | sizeof(vf_tc_map)); |
dde1a86e SM |
424 | |
425 | return ret; | |
426 | } | |
427 | ||
428 | static int hclge_get_vf_queue_info(struct hclge_vport *vport, | |
429 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
430 | bool gen_resp) | |
431 | { | |
c0425944 | 432 | #define HCLGE_TQPS_RSS_INFO_LEN 6 |
dde1a86e SM |
433 | u8 resp_data[HCLGE_TQPS_RSS_INFO_LEN]; |
434 | struct hclge_dev *hdev = vport->back; | |
435 | ||
436 | /* get the queue related info */ | |
437 | memcpy(&resp_data[0], &vport->alloc_tqps, sizeof(u16)); | |
f5e084b8 | 438 | memcpy(&resp_data[2], &vport->nic.kinfo.rss_size, sizeof(u16)); |
c0425944 | 439 | memcpy(&resp_data[4], &hdev->rx_buf_len, sizeof(u16)); |
dde1a86e SM |
440 | |
441 | return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, | |
442 | HCLGE_TQPS_RSS_INFO_LEN); | |
443 | } | |
444 | ||
8e6de441 HT |
445 | static int hclge_get_vf_mac_addr(struct hclge_vport *vport, |
446 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
447 | { | |
448 | return hclge_gen_resp_to_vf(vport, mbx_req, 0, vport->vf_info.mac, | |
449 | ETH_ALEN); | |
450 | } | |
451 | ||
c0425944 PL |
452 | static int hclge_get_vf_queue_depth(struct hclge_vport *vport, |
453 | struct hclge_mbx_vf_to_pf_cmd *mbx_req, | |
454 | bool gen_resp) | |
455 | { | |
456 | #define HCLGE_TQPS_DEPTH_INFO_LEN 4 | |
457 | u8 resp_data[HCLGE_TQPS_DEPTH_INFO_LEN]; | |
458 | struct hclge_dev *hdev = vport->back; | |
459 | ||
460 | /* get the queue depth info */ | |
461 | memcpy(&resp_data[0], &hdev->num_tx_desc, sizeof(u16)); | |
462 | memcpy(&resp_data[2], &hdev->num_rx_desc, sizeof(u16)); | |
463 | return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, | |
464 | HCLGE_TQPS_DEPTH_INFO_LEN); | |
465 | } | |
466 | ||
9c3e7130 | 467 | static int hclge_get_vf_media_type(struct hclge_vport *vport, |
468 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
469 | { | |
470 | struct hclge_dev *hdev = vport->back; | |
88d10bd6 | 471 | u8 resp_data[2]; |
9c3e7130 | 472 | |
88d10bd6 JS |
473 | resp_data[0] = hdev->hw.mac.media_type; |
474 | resp_data[1] = hdev->hw.mac.module_type; | |
475 | return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, | |
9c3e7130 | 476 | sizeof(resp_data)); |
477 | } | |
478 | ||
dde1a86e SM |
479 | static int hclge_get_link_info(struct hclge_vport *vport, |
480 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
481 | { | |
6430f744 YM |
482 | #define HCLGE_VF_LINK_STATE_UP 1U |
483 | #define HCLGE_VF_LINK_STATE_DOWN 0U | |
484 | ||
dde1a86e SM |
485 | struct hclge_dev *hdev = vport->back; |
486 | u16 link_status; | |
9c3e7130 | 487 | u8 msg_data[8]; |
dde1a86e | 488 | u8 dest_vfid; |
4a152de9 | 489 | u16 duplex; |
dde1a86e SM |
490 | |
491 | /* mac.link can only be 0 or 1 */ | |
6430f744 YM |
492 | switch (vport->vf_info.link_state) { |
493 | case IFLA_VF_LINK_STATE_ENABLE: | |
494 | link_status = HCLGE_VF_LINK_STATE_UP; | |
495 | break; | |
496 | case IFLA_VF_LINK_STATE_DISABLE: | |
497 | link_status = HCLGE_VF_LINK_STATE_DOWN; | |
498 | break; | |
499 | case IFLA_VF_LINK_STATE_AUTO: | |
500 | default: | |
501 | link_status = (u16)hdev->hw.mac.link; | |
502 | break; | |
503 | } | |
504 | ||
4a152de9 | 505 | duplex = hdev->hw.mac.duplex; |
dde1a86e | 506 | memcpy(&msg_data[0], &link_status, sizeof(u16)); |
4a152de9 FL |
507 | memcpy(&msg_data[2], &hdev->hw.mac.speed, sizeof(u32)); |
508 | memcpy(&msg_data[6], &duplex, sizeof(u16)); | |
dde1a86e SM |
509 | dest_vfid = mbx_req->mbx_src_vfid; |
510 | ||
511 | /* send this requested info to VF */ | |
4a152de9 | 512 | return hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), |
dde1a86e SM |
513 | HCLGE_MBX_LINK_STAT_CHANGE, dest_vfid); |
514 | } | |
515 | ||
9194d18b | 516 | static void hclge_get_link_mode(struct hclge_vport *vport, |
517 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
518 | { | |
519 | #define HCLGE_SUPPORTED 1 | |
520 | struct hclge_dev *hdev = vport->back; | |
521 | unsigned long advertising; | |
522 | unsigned long supported; | |
523 | unsigned long send_data; | |
524 | u8 msg_data[10]; | |
525 | u8 dest_vfid; | |
526 | ||
527 | advertising = hdev->hw.mac.advertising[0]; | |
528 | supported = hdev->hw.mac.supported[0]; | |
529 | dest_vfid = mbx_req->mbx_src_vfid; | |
530 | msg_data[0] = mbx_req->msg[2]; | |
531 | ||
532 | send_data = msg_data[0] == HCLGE_SUPPORTED ? supported : advertising; | |
533 | ||
534 | memcpy(&msg_data[2], &send_data, sizeof(unsigned long)); | |
535 | hclge_send_mbx_msg(vport, msg_data, sizeof(msg_data), | |
536 | HCLGE_MBX_LINK_STAT_MODE, dest_vfid); | |
537 | } | |
538 | ||
1a426f8b PL |
539 | static void hclge_mbx_reset_vf_queue(struct hclge_vport *vport, |
540 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
84e095d6 SM |
541 | { |
542 | u16 queue_id; | |
543 | ||
544 | memcpy(&queue_id, &mbx_req->msg[2], sizeof(queue_id)); | |
545 | ||
1a426f8b PL |
546 | hclge_reset_vf_queue(vport, queue_id); |
547 | ||
46ee7350 | 548 | /* send response msg to VF after queue reset complete */ |
1a426f8b | 549 | hclge_gen_resp_to_vf(vport, mbx_req, 0, NULL, 0); |
84e095d6 SM |
550 | } |
551 | ||
2bfbd35d SM |
552 | static void hclge_reset_vf(struct hclge_vport *vport, |
553 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
554 | { | |
555 | struct hclge_dev *hdev = vport->back; | |
556 | int ret; | |
557 | ||
adcf738b | 558 | dev_warn(&hdev->pdev->dev, "PF received VF reset request from VF %u!", |
dea846e8 | 559 | vport->vport_id); |
2bfbd35d | 560 | |
dea846e8 HT |
561 | ret = hclge_func_reset_cmd(hdev, vport->vport_id); |
562 | hclge_gen_resp_to_vf(vport, mbx_req, ret, NULL, 0); | |
2bfbd35d SM |
563 | } |
564 | ||
a6d818e3 YL |
565 | static void hclge_vf_keep_alive(struct hclge_vport *vport, |
566 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
567 | { | |
568 | vport->last_active_jiffies = jiffies; | |
569 | } | |
570 | ||
818f1675 YL |
571 | static int hclge_set_vf_mtu(struct hclge_vport *vport, |
572 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
573 | { | |
574 | int ret; | |
575 | u32 mtu; | |
576 | ||
577 | memcpy(&mtu, &mbx_req->msg[2], sizeof(mtu)); | |
578 | ret = hclge_set_vport_mtu(vport, mtu); | |
579 | ||
580 | return hclge_gen_resp_to_vf(vport, mbx_req, ret, NULL, 0); | |
581 | } | |
582 | ||
0c29d191 | 583 | static int hclge_get_queue_id_in_pf(struct hclge_vport *vport, |
584 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
585 | { | |
586 | u16 queue_id, qid_in_pf; | |
587 | u8 resp_data[2]; | |
588 | ||
589 | memcpy(&queue_id, &mbx_req->msg[2], sizeof(queue_id)); | |
590 | qid_in_pf = hclge_covert_handle_qid_global(&vport->nic, queue_id); | |
591 | memcpy(resp_data, &qid_in_pf, sizeof(qid_in_pf)); | |
592 | ||
d6ad7c53 GL |
593 | return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, |
594 | sizeof(resp_data)); | |
0c29d191 | 595 | } |
596 | ||
a638b1d8 JS |
597 | static int hclge_get_rss_key(struct hclge_vport *vport, |
598 | struct hclge_mbx_vf_to_pf_cmd *mbx_req) | |
599 | { | |
600 | #define HCLGE_RSS_MBX_RESP_LEN 8 | |
601 | u8 resp_data[HCLGE_RSS_MBX_RESP_LEN]; | |
602 | struct hclge_dev *hdev = vport->back; | |
603 | u8 index; | |
604 | ||
605 | index = mbx_req->msg[2]; | |
606 | ||
607 | memcpy(&resp_data[0], | |
608 | &hdev->vport[0].rss_hash_key[index * HCLGE_RSS_MBX_RESP_LEN], | |
609 | HCLGE_RSS_MBX_RESP_LEN); | |
610 | ||
611 | return hclge_gen_resp_to_vf(vport, mbx_req, 0, resp_data, | |
612 | HCLGE_RSS_MBX_RESP_LEN); | |
613 | } | |
614 | ||
ed8fb4b2 JS |
615 | static void hclge_link_fail_parse(struct hclge_dev *hdev, u8 link_fail_code) |
616 | { | |
617 | switch (link_fail_code) { | |
618 | case HCLGE_LF_REF_CLOCK_LOST: | |
619 | dev_warn(&hdev->pdev->dev, "Reference clock lost!\n"); | |
620 | break; | |
621 | case HCLGE_LF_XSFP_TX_DISABLE: | |
622 | dev_warn(&hdev->pdev->dev, "SFP tx is disabled!\n"); | |
623 | break; | |
624 | case HCLGE_LF_XSFP_ABSENT: | |
625 | dev_warn(&hdev->pdev->dev, "SFP is absent!\n"); | |
626 | break; | |
627 | default: | |
628 | break; | |
629 | } | |
630 | } | |
631 | ||
632 | static void hclge_handle_link_change_event(struct hclge_dev *hdev, | |
633 | struct hclge_mbx_vf_to_pf_cmd *req) | |
634 | { | |
635 | #define LINK_STATUS_OFFSET 1 | |
636 | #define LINK_FAIL_CODE_OFFSET 2 | |
637 | ||
638 | clear_bit(HCLGE_STATE_SERVICE_SCHED, &hdev->state); | |
639 | hclge_task_schedule(hdev, 0); | |
640 | ||
641 | if (!req->msg[LINK_STATUS_OFFSET]) | |
642 | hclge_link_fail_parse(hdev, req->msg[LINK_FAIL_CODE_OFFSET]); | |
643 | } | |
644 | ||
7c4bfcb0 XW |
645 | static bool hclge_cmd_crq_empty(struct hclge_hw *hw) |
646 | { | |
647 | u32 tail = hclge_read_dev(hw, HCLGE_NIC_CRQ_TAIL_REG); | |
648 | ||
649 | return tail == hw->cmq.crq.next_to_use; | |
650 | } | |
651 | ||
b18bf305 HT |
652 | static void hclge_handle_ncsi_error(struct hclge_dev *hdev) |
653 | { | |
654 | struct hnae3_ae_dev *ae_dev = hdev->ae_dev; | |
655 | ||
656 | ae_dev->ops->set_default_reset_request(ae_dev, HNAE3_GLOBAL_RESET); | |
657 | dev_warn(&hdev->pdev->dev, "requesting reset due to NCSI error\n"); | |
658 | ae_dev->ops->reset_event(hdev->pdev, NULL); | |
659 | } | |
660 | ||
dde1a86e SM |
661 | void hclge_mbx_handler(struct hclge_dev *hdev) |
662 | { | |
663 | struct hclge_cmq_ring *crq = &hdev->hw.cmq.crq; | |
664 | struct hclge_mbx_vf_to_pf_cmd *req; | |
665 | struct hclge_vport *vport; | |
666 | struct hclge_desc *desc; | |
ebaf1908 WL |
667 | unsigned int flag; |
668 | int ret; | |
dde1a86e SM |
669 | |
670 | /* handle all the mailbox requests in the queue */ | |
7c4bfcb0 | 671 | while (!hclge_cmd_crq_empty(&hdev->hw)) { |
3c88ed1d HT |
672 | if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state)) { |
673 | dev_warn(&hdev->pdev->dev, | |
674 | "command queue needs re-initializing\n"); | |
675 | return; | |
676 | } | |
677 | ||
dde1a86e SM |
678 | desc = &crq->desc[crq->next_to_use]; |
679 | req = (struct hclge_mbx_vf_to_pf_cmd *)desc->data; | |
680 | ||
7c4bfcb0 | 681 | flag = le16_to_cpu(crq->desc[crq->next_to_use].flag); |
e4e87715 | 682 | if (unlikely(!hnae3_get_bit(flag, HCLGE_CMDQ_RX_OUTVLD_B))) { |
7c4bfcb0 | 683 | dev_warn(&hdev->pdev->dev, |
adcf738b | 684 | "dropped invalid mailbox message, code = %u\n", |
7c4bfcb0 XW |
685 | req->msg[0]); |
686 | ||
687 | /* dropping/not processing this invalid message */ | |
688 | crq->desc[crq->next_to_use].flag = 0; | |
689 | hclge_mbx_ring_ptr_move_crq(crq); | |
690 | continue; | |
691 | } | |
692 | ||
dde1a86e SM |
693 | vport = &hdev->vport[req->mbx_src_vfid]; |
694 | ||
695 | switch (req->msg[0]) { | |
84e095d6 SM |
696 | case HCLGE_MBX_MAP_RING_TO_VECTOR: |
697 | ret = hclge_map_unmap_ring_to_vf_vector(vport, true, | |
698 | req); | |
699 | break; | |
700 | case HCLGE_MBX_UNMAP_RING_TO_VECTOR: | |
701 | ret = hclge_map_unmap_ring_to_vf_vector(vport, false, | |
702 | req); | |
703 | break; | |
dde1a86e SM |
704 | case HCLGE_MBX_SET_PROMISC_MODE: |
705 | ret = hclge_set_vf_promisc_mode(vport, req); | |
706 | if (ret) | |
707 | dev_err(&hdev->pdev->dev, | |
708 | "PF fail(%d) to set VF promisc mode\n", | |
709 | ret); | |
710 | break; | |
711 | case HCLGE_MBX_SET_UNICAST: | |
b7048d32 | 712 | ret = hclge_set_vf_uc_mac_addr(vport, req); |
dde1a86e SM |
713 | if (ret) |
714 | dev_err(&hdev->pdev->dev, | |
715 | "PF fail(%d) to set VF UC MAC Addr\n", | |
716 | ret); | |
717 | break; | |
718 | case HCLGE_MBX_SET_MULTICAST: | |
719 | ret = hclge_set_vf_mc_mac_addr(vport, req, false); | |
720 | if (ret) | |
721 | dev_err(&hdev->pdev->dev, | |
722 | "PF fail(%d) to set VF MC MAC Addr\n", | |
723 | ret); | |
724 | break; | |
725 | case HCLGE_MBX_SET_VLAN: | |
92f11ea1 | 726 | ret = hclge_set_vf_vlan_cfg(vport, req); |
dde1a86e SM |
727 | if (ret) |
728 | dev_err(&hdev->pdev->dev, | |
729 | "PF failed(%d) to config VF's VLAN\n", | |
730 | ret); | |
731 | break; | |
a6d818e3 YL |
732 | case HCLGE_MBX_SET_ALIVE: |
733 | ret = hclge_set_vf_alive(vport, req, false); | |
734 | if (ret) | |
735 | dev_err(&hdev->pdev->dev, | |
736 | "PF failed(%d) to set VF's ALIVE\n", | |
737 | ret); | |
738 | break; | |
dde1a86e SM |
739 | case HCLGE_MBX_GET_QINFO: |
740 | ret = hclge_get_vf_queue_info(vport, req, true); | |
741 | if (ret) | |
742 | dev_err(&hdev->pdev->dev, | |
743 | "PF failed(%d) to get Q info for VF\n", | |
744 | ret); | |
745 | break; | |
c0425944 PL |
746 | case HCLGE_MBX_GET_QDEPTH: |
747 | ret = hclge_get_vf_queue_depth(vport, req, true); | |
748 | if (ret) | |
749 | dev_err(&hdev->pdev->dev, | |
750 | "PF failed(%d) to get Q depth for VF\n", | |
751 | ret); | |
752 | break; | |
753 | ||
dde1a86e SM |
754 | case HCLGE_MBX_GET_TCINFO: |
755 | ret = hclge_get_vf_tcinfo(vport, req, true); | |
756 | if (ret) | |
757 | dev_err(&hdev->pdev->dev, | |
758 | "PF failed(%d) to get TC info for VF\n", | |
759 | ret); | |
760 | break; | |
761 | case HCLGE_MBX_GET_LINK_STATUS: | |
762 | ret = hclge_get_link_info(vport, req); | |
763 | if (ret) | |
764 | dev_err(&hdev->pdev->dev, | |
765 | "PF fail(%d) to get link stat for VF\n", | |
766 | ret); | |
767 | break; | |
84e095d6 | 768 | case HCLGE_MBX_QUEUE_RESET: |
1a426f8b | 769 | hclge_mbx_reset_vf_queue(vport, req); |
84e095d6 | 770 | break; |
2bfbd35d SM |
771 | case HCLGE_MBX_RESET: |
772 | hclge_reset_vf(vport, req); | |
773 | break; | |
a6d818e3 YL |
774 | case HCLGE_MBX_KEEP_ALIVE: |
775 | hclge_vf_keep_alive(vport, req); | |
776 | break; | |
818f1675 YL |
777 | case HCLGE_MBX_SET_MTU: |
778 | ret = hclge_set_vf_mtu(vport, req); | |
779 | if (ret) | |
780 | dev_err(&hdev->pdev->dev, | |
781 | "VF fail(%d) to set mtu\n", ret); | |
782 | break; | |
0c29d191 | 783 | case HCLGE_MBX_GET_QID_IN_PF: |
784 | ret = hclge_get_queue_id_in_pf(vport, req); | |
785 | if (ret) | |
786 | dev_err(&hdev->pdev->dev, | |
787 | "PF failed(%d) to get qid for VF\n", | |
788 | ret); | |
789 | break; | |
a638b1d8 JS |
790 | case HCLGE_MBX_GET_RSS_KEY: |
791 | ret = hclge_get_rss_key(vport, req); | |
792 | if (ret) | |
793 | dev_err(&hdev->pdev->dev, | |
794 | "PF fail(%d) to get rss key for VF\n", | |
795 | ret); | |
796 | break; | |
9194d18b | 797 | case HCLGE_MBX_GET_LINK_MODE: |
798 | hclge_get_link_mode(vport, req); | |
799 | break; | |
6dd86902 | 800 | case HCLGE_MBX_GET_VF_FLR_STATUS: |
801 | mutex_lock(&hdev->vport_cfg_mutex); | |
802 | hclge_rm_vport_all_mac_table(vport, true, | |
803 | HCLGE_MAC_ADDR_UC); | |
804 | hclge_rm_vport_all_mac_table(vport, true, | |
805 | HCLGE_MAC_ADDR_MC); | |
c6075b19 | 806 | hclge_rm_vport_all_vlan_table(vport, true); |
6dd86902 | 807 | mutex_unlock(&hdev->vport_cfg_mutex); |
808 | break; | |
9c3e7130 | 809 | case HCLGE_MBX_GET_MEDIA_TYPE: |
810 | ret = hclge_get_vf_media_type(vport, req); | |
811 | if (ret) | |
812 | dev_err(&hdev->pdev->dev, | |
813 | "PF fail(%d) to media type for VF\n", | |
814 | ret); | |
815 | break; | |
ed8fb4b2 JS |
816 | case HCLGE_MBX_PUSH_LINK_STATUS: |
817 | hclge_handle_link_change_event(hdev, req); | |
818 | break; | |
8e6de441 HT |
819 | case HCLGE_MBX_GET_MAC_ADDR: |
820 | ret = hclge_get_vf_mac_addr(vport, req); | |
821 | if (ret) | |
822 | dev_err(&hdev->pdev->dev, | |
823 | "PF failed(%d) to get MAC for VF\n", | |
824 | ret); | |
825 | break; | |
b18bf305 HT |
826 | case HCLGE_MBX_NCSI_ERROR: |
827 | hclge_handle_ncsi_error(hdev); | |
828 | break; | |
dde1a86e SM |
829 | default: |
830 | dev_err(&hdev->pdev->dev, | |
adcf738b | 831 | "un-supported mailbox message, code = %u\n", |
dde1a86e SM |
832 | req->msg[0]); |
833 | break; | |
834 | } | |
090e3b53 | 835 | crq->desc[crq->next_to_use].flag = 0; |
dde1a86e SM |
836 | hclge_mbx_ring_ptr_move_crq(crq); |
837 | } | |
838 | ||
839 | /* Write back CMDQ_RQ header pointer, M7 need this pointer */ | |
840 | hclge_write_dev(&hdev->hw, HCLGE_NIC_CRQ_HEAD_REG, crq->next_to_use); | |
841 | } |