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