File Index
Files and directories
Sign in
FILE

hinic3_nic_cfg.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c C
  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
 13static 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
 42int 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
 48int 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
 54bool 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
 60void 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
 65static 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
 91int 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
108int 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
120static 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
131int 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
173int 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
204int 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
237int 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
271int 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
293int 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
316int 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
341int 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
364int 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}
~/ Read-only file preview.