xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c (revision 00c94ca2b99e6610e483f92e531b319eeaed94aa)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3 
4 #include <linux/if_vlan.h>
5 
6 #include "hinic3_hwdev.h"
7 #include "hinic3_hwif.h"
8 #include "hinic3_mbox.h"
9 #include "hinic3_nic_cfg.h"
10 #include "hinic3_nic_dev.h"
11 #include "hinic3_nic_io.h"
12 
13 static int hinic3_feature_nego(struct hinic3_hwdev *hwdev, u8 opcode,
14 			       u64 *s_feature, u16 size)
15 {
16 	struct l2nic_cmd_feature_nego feature_nego = {};
17 	struct mgmt_msg_params msg_params = {};
18 	int err;
19 
20 	feature_nego.func_id = hinic3_global_func_id(hwdev);
21 	feature_nego.opcode = opcode;
22 	if (opcode == MGMT_MSG_CMD_OP_SET)
23 		memcpy(feature_nego.s_feature, s_feature, size * sizeof(u64));
24 
25 	mgmt_msg_params_init_default(&msg_params, &feature_nego,
26 				     sizeof(feature_nego));
27 
28 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
29 				       L2NIC_CMD_FEATURE_NEGO, &msg_params);
30 	if (err || feature_nego.msg_head.status) {
31 		dev_err(hwdev->dev, "Failed to negotiate nic feature, err:%d, status: 0x%x\n",
32 			err, feature_nego.msg_head.status);
33 		return -EIO;
34 	}
35 
36 	if (opcode == MGMT_MSG_CMD_OP_GET)
37 		memcpy(s_feature, feature_nego.s_feature, size * sizeof(u64));
38 
39 	return 0;
40 }
41 
42 int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev)
43 {
44 	return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_GET,
45 				   &nic_dev->nic_io->feature_cap, 1);
46 }
47 
48 int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev)
49 {
50 	return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET,
51 				   &nic_dev->nic_io->feature_cap, 1);
52 }
53 
54 bool hinic3_test_support(struct hinic3_nic_dev *nic_dev,
55 			 enum hinic3_nic_feature_cap feature_bits)
56 {
57 	return (nic_dev->nic_io->feature_cap & feature_bits) == feature_bits;
58 }
59 
60 void hinic3_update_nic_feature(struct hinic3_nic_dev *nic_dev, u64 feature_cap)
61 {
62 	nic_dev->nic_io->feature_cap = feature_cap;
63 }
64 
65 static int hinic3_set_function_table(struct hinic3_hwdev *hwdev, u32 cfg_bitmap,
66 				     const struct l2nic_func_tbl_cfg *cfg)
67 {
68 	struct l2nic_cmd_set_func_tbl cmd_func_tbl = {};
69 	struct mgmt_msg_params msg_params = {};
70 	int err;
71 
72 	cmd_func_tbl.func_id = hinic3_global_func_id(hwdev);
73 	cmd_func_tbl.cfg_bitmap = cfg_bitmap;
74 	cmd_func_tbl.tbl_cfg = *cfg;
75 
76 	mgmt_msg_params_init_default(&msg_params, &cmd_func_tbl,
77 				     sizeof(cmd_func_tbl));
78 
79 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
80 				       L2NIC_CMD_SET_FUNC_TBL, &msg_params);
81 	if (err || cmd_func_tbl.msg_head.status) {
82 		dev_err(hwdev->dev,
83 			"Failed to set func table, bitmap: 0x%x, err: %d, status: 0x%x\n",
84 			cfg_bitmap, err, cmd_func_tbl.msg_head.status);
85 		return -EFAULT;
86 	}
87 
88 	return 0;
89 }
90 
91 int hinic3_init_function_table(struct hinic3_nic_dev *nic_dev)
92 {
93 	struct hinic3_nic_io *nic_io = nic_dev->nic_io;
94 	struct l2nic_func_tbl_cfg func_tbl_cfg = {};
95 	u32 cfg_bitmap;
96 
97 	func_tbl_cfg.mtu = 0x3FFF; /* default, max mtu */
98 	func_tbl_cfg.rx_wqe_buf_size = nic_io->rx_buf_len;
99 
100 	cfg_bitmap = BIT(L2NIC_FUNC_TBL_CFG_INIT) |
101 		     BIT(L2NIC_FUNC_TBL_CFG_MTU) |
102 		     BIT(L2NIC_FUNC_TBL_CFG_RX_BUF_SIZE);
103 
104 	return hinic3_set_function_table(nic_dev->hwdev, cfg_bitmap,
105 					 &func_tbl_cfg);
106 }
107 
108 int hinic3_set_port_mtu(struct net_device *netdev, u16 new_mtu)
109 {
110 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
111 	struct l2nic_func_tbl_cfg func_tbl_cfg = {};
112 	struct hinic3_hwdev *hwdev = nic_dev->hwdev;
113 
114 	func_tbl_cfg.mtu = new_mtu;
115 
116 	return hinic3_set_function_table(hwdev, BIT(L2NIC_FUNC_TBL_CFG_MTU),
117 					 &func_tbl_cfg);
118 }
119 
120 static int hinic3_check_mac_info(struct hinic3_hwdev *hwdev, u8 status,
121 				 u16 vlan_id)
122 {
123 	if ((status && status != MGMT_STATUS_EXIST) ||
124 	    ((vlan_id & BIT(15)) && status == MGMT_STATUS_EXIST)) {
125 		return -EINVAL;
126 	}
127 
128 	return 0;
129 }
130 
131 int hinic3_set_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id,
132 		   u16 func_id)
133 {
134 	struct l2nic_cmd_set_mac mac_info = {};
135 	struct mgmt_msg_params msg_params = {};
136 	int err;
137 
138 	if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) {
139 		dev_err(hwdev->dev, "Invalid VLAN number: %d\n",
140 			(vlan_id & HINIC3_VLAN_ID_MASK));
141 		return -EINVAL;
142 	}
143 
144 	mac_info.func_id = func_id;
145 	mac_info.vlan_id = vlan_id;
146 	ether_addr_copy(mac_info.mac, mac_addr);
147 
148 	mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info));
149 
150 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
151 				       L2NIC_CMD_SET_MAC, &msg_params);
152 	if (err || hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
153 					 mac_info.vlan_id)) {
154 		dev_err(hwdev->dev,
155 			"Failed to update MAC, err: %d, status: 0x%x\n",
156 			err, mac_info.msg_head.status);
157 		return -EIO;
158 	}
159 
160 	if (mac_info.msg_head.status == MGMT_STATUS_PF_SET_VF_ALREADY) {
161 		dev_warn(hwdev->dev, "PF has already set VF mac, Ignore set operation\n");
162 		return 0;
163 	}
164 
165 	if (mac_info.msg_head.status == MGMT_STATUS_EXIST) {
166 		dev_warn(hwdev->dev, "MAC is repeated. Ignore update operation\n");
167 		return 0;
168 	}
169 
170 	return 0;
171 }
172 
173 int hinic3_del_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id,
174 		   u16 func_id)
175 {
176 	struct l2nic_cmd_set_mac mac_info = {};
177 	struct mgmt_msg_params msg_params = {};
178 	int err;
179 
180 	if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) {
181 		dev_err(hwdev->dev, "Invalid VLAN number: %d\n",
182 			(vlan_id & HINIC3_VLAN_ID_MASK));
183 		return -EINVAL;
184 	}
185 
186 	mac_info.func_id = func_id;
187 	mac_info.vlan_id = vlan_id;
188 	ether_addr_copy(mac_info.mac, mac_addr);
189 
190 	mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info));
191 
192 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
193 				       L2NIC_CMD_DEL_MAC, &msg_params);
194 	if (err) {
195 		dev_err(hwdev->dev,
196 			"Failed to delete MAC, err: %d, status: 0x%x\n",
197 			err, mac_info.msg_head.status);
198 		return err;
199 	}
200 
201 	return 0;
202 }
203 
204 int hinic3_update_mac(struct hinic3_hwdev *hwdev, const u8 *old_mac,
205 		      u8 *new_mac, u16 vlan_id, u16 func_id)
206 {
207 	struct l2nic_cmd_update_mac mac_info = {};
208 	struct mgmt_msg_params msg_params = {};
209 	int err;
210 
211 	if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) {
212 		dev_err(hwdev->dev, "Invalid VLAN number: %d\n",
213 			(vlan_id & HINIC3_VLAN_ID_MASK));
214 		return -EINVAL;
215 	}
216 
217 	mac_info.func_id = func_id;
218 	mac_info.vlan_id = vlan_id;
219 	ether_addr_copy(mac_info.old_mac, old_mac);
220 	ether_addr_copy(mac_info.new_mac, new_mac);
221 
222 	mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info));
223 
224 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
225 				       L2NIC_CMD_UPDATE_MAC, &msg_params);
226 	if (err || hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
227 					 mac_info.vlan_id)) {
228 		dev_err(hwdev->dev,
229 			"Failed to update MAC, err: %d, status: 0x%x\n",
230 			err, mac_info.msg_head.status);
231 		return -EIO;
232 	}
233 
234 	return 0;
235 }
236 
237 int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, struct hinic3_sq_attr *attr)
238 {
239 	struct l2nic_cmd_set_ci_attr cons_idx_attr = {};
240 	struct mgmt_msg_params msg_params = {};
241 	int err;
242 
243 	cons_idx_attr.func_idx = hinic3_global_func_id(hwdev);
244 	cons_idx_attr.dma_attr_off  = attr->dma_attr_off;
245 	cons_idx_attr.pending_limit = attr->pending_limit;
246 	cons_idx_attr.coalescing_time  = attr->coalescing_time;
247 
248 	if (attr->intr_en) {
249 		cons_idx_attr.intr_en = attr->intr_en;
250 		cons_idx_attr.intr_idx = attr->intr_idx;
251 	}
252 
253 	cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
254 	cons_idx_attr.ci_addr = attr->ci_dma_base;
255 
256 	mgmt_msg_params_init_default(&msg_params, &cons_idx_attr,
257 				     sizeof(cons_idx_attr));
258 
259 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
260 				       L2NIC_CMD_SET_SQ_CI_ATTR, &msg_params);
261 	if (err || cons_idx_attr.msg_head.status) {
262 		dev_err(hwdev->dev,
263 			"Failed to set ci attribute table, err: %d, status: 0x%x\n",
264 			err, cons_idx_attr.msg_head.status);
265 		return -EFAULT;
266 	}
267 
268 	return 0;
269 }
270 
271 int hinic3_flush_qps_res(struct hinic3_hwdev *hwdev)
272 {
273 	struct l2nic_cmd_clear_qp_resource sq_res = {};
274 	struct mgmt_msg_params msg_params = {};
275 	int err;
276 
277 	sq_res.func_id = hinic3_global_func_id(hwdev);
278 
279 	mgmt_msg_params_init_default(&msg_params, &sq_res, sizeof(sq_res));
280 
281 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
282 				       L2NIC_CMD_CLEAR_QP_RESOURCE,
283 				       &msg_params);
284 	if (err || sq_res.msg_head.status) {
285 		dev_err(hwdev->dev, "Failed to clear sq resources, err: %d, status: 0x%x\n",
286 			err, sq_res.msg_head.status);
287 		return -EINVAL;
288 	}
289 
290 	return 0;
291 }
292 
293 int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev)
294 {
295 	struct l2nic_cmd_force_pkt_drop pkt_drop = {};
296 	struct mgmt_msg_params msg_params = {};
297 	int err;
298 
299 	pkt_drop.port = hinic3_physical_port_id(hwdev);
300 
301 	mgmt_msg_params_init_default(&msg_params, &pkt_drop, sizeof(pkt_drop));
302 
303 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
304 				       L2NIC_CMD_FORCE_PKT_DROP, &msg_params);
305 	if ((pkt_drop.msg_head.status != MGMT_STATUS_CMD_UNSUPPORTED &&
306 	     pkt_drop.msg_head.status) || err) {
307 		dev_err(hwdev->dev,
308 			"Failed to set force tx packets drop, err: %d, status: 0x%x\n",
309 			err, pkt_drop.msg_head.status);
310 		return -EFAULT;
311 	}
312 
313 	return pkt_drop.msg_head.status;
314 }
315 
316 int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state)
317 {
318 	struct l2nic_cmd_set_dcb_state dcb_state = {};
319 	struct mgmt_msg_params msg_params = {};
320 	int err;
321 
322 	dcb_state.op_code = op_code;
323 	dcb_state.state = state;
324 	dcb_state.func_id = hinic3_global_func_id(hwdev);
325 
326 	mgmt_msg_params_init_default(&msg_params, &dcb_state,
327 				     sizeof(dcb_state));
328 
329 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
330 				       L2NIC_CMD_QOS_DCB_STATE, &msg_params);
331 	if (err || dcb_state.head.status) {
332 		dev_err(hwdev->dev,
333 			"Failed to set dcb state, err: %d, status: 0x%x\n",
334 			err, dcb_state.head.status);
335 		return -EFAULT;
336 	}
337 
338 	return 0;
339 }
340 
341 int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_up)
342 {
343 	struct mag_cmd_get_link_status get_link = {};
344 	struct mgmt_msg_params msg_params = {};
345 	int err;
346 
347 	get_link.port_id = hinic3_physical_port_id(hwdev);
348 
349 	mgmt_msg_params_init_default(&msg_params, &get_link, sizeof(get_link));
350 
351 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK,
352 				       MAG_CMD_GET_LINK_STATUS, &msg_params);
353 	if (err || get_link.head.status) {
354 		dev_err(hwdev->dev, "Failed to get link state, err: %d, status: 0x%x\n",
355 			err, get_link.head.status);
356 		return -EIO;
357 	}
358 
359 	*link_status_up = !!get_link.status;
360 
361 	return 0;
362 }
363 
364 int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id,
365 			    bool enable)
366 {
367 	struct l2nic_cmd_set_vport_state en_state = {};
368 	struct mgmt_msg_params msg_params = {};
369 	int err;
370 
371 	en_state.func_id = func_id;
372 	en_state.state = enable ? 1 : 0;
373 
374 	mgmt_msg_params_init_default(&msg_params, &en_state, sizeof(en_state));
375 
376 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
377 				       L2NIC_CMD_SET_VPORT_ENABLE, &msg_params);
378 	if (err || en_state.msg_head.status) {
379 		dev_err(hwdev->dev, "Failed to set vport state, err: %d, status: 0x%x\n",
380 			err, en_state.msg_head.status);
381 		return -EINVAL;
382 	}
383 
384 	return 0;
385 }
386