xref: /linux/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
1*17fcb3dcSFan Gong // SPDX-License-Identifier: GPL-2.0
2*17fcb3dcSFan Gong // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
3*17fcb3dcSFan Gong 
4*17fcb3dcSFan Gong #include <linux/if_vlan.h>
5*17fcb3dcSFan Gong 
6*17fcb3dcSFan Gong #include "hinic3_hwdev.h"
7*17fcb3dcSFan Gong #include "hinic3_hwif.h"
8*17fcb3dcSFan Gong #include "hinic3_mbox.h"
9*17fcb3dcSFan Gong #include "hinic3_nic_cfg.h"
10*17fcb3dcSFan Gong #include "hinic3_nic_dev.h"
11*17fcb3dcSFan Gong #include "hinic3_nic_io.h"
12*17fcb3dcSFan Gong 
13*17fcb3dcSFan Gong static int hinic3_feature_nego(struct hinic3_hwdev *hwdev, u8 opcode,
14*17fcb3dcSFan Gong 			       u64 *s_feature, u16 size)
15*17fcb3dcSFan Gong {
16*17fcb3dcSFan Gong 	struct l2nic_cmd_feature_nego feature_nego = {};
17*17fcb3dcSFan Gong 	struct mgmt_msg_params msg_params = {};
18*17fcb3dcSFan Gong 	int err;
19*17fcb3dcSFan Gong 
20*17fcb3dcSFan Gong 	feature_nego.func_id = hinic3_global_func_id(hwdev);
21*17fcb3dcSFan Gong 	feature_nego.opcode = opcode;
22*17fcb3dcSFan Gong 	if (opcode == MGMT_MSG_CMD_OP_SET)
23*17fcb3dcSFan Gong 		memcpy(feature_nego.s_feature, s_feature, size * sizeof(u64));
24*17fcb3dcSFan Gong 
25*17fcb3dcSFan Gong 	mgmt_msg_params_init_default(&msg_params, &feature_nego,
26*17fcb3dcSFan Gong 				     sizeof(feature_nego));
27*17fcb3dcSFan Gong 
28*17fcb3dcSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
29*17fcb3dcSFan Gong 				       L2NIC_CMD_FEATURE_NEGO, &msg_params);
30*17fcb3dcSFan Gong 	if (err || feature_nego.msg_head.status) {
31*17fcb3dcSFan Gong 		dev_err(hwdev->dev, "Failed to negotiate nic feature, err:%d, status: 0x%x\n",
32*17fcb3dcSFan Gong 			err, feature_nego.msg_head.status);
33*17fcb3dcSFan Gong 		return -EIO;
34*17fcb3dcSFan Gong 	}
35*17fcb3dcSFan Gong 
36*17fcb3dcSFan Gong 	if (opcode == MGMT_MSG_CMD_OP_GET)
37*17fcb3dcSFan Gong 		memcpy(s_feature, feature_nego.s_feature, size * sizeof(u64));
38*17fcb3dcSFan Gong 
39*17fcb3dcSFan Gong 	return 0;
40*17fcb3dcSFan Gong }
41*17fcb3dcSFan Gong 
42*17fcb3dcSFan Gong int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev)
43*17fcb3dcSFan Gong {
44*17fcb3dcSFan Gong 	return hinic3_feature_nego(nic_dev->hwdev, MGMT_MSG_CMD_OP_SET,
45*17fcb3dcSFan Gong 				   &nic_dev->nic_io->feature_cap, 1);
46*17fcb3dcSFan Gong }
47*17fcb3dcSFan Gong 
48*17fcb3dcSFan Gong bool hinic3_test_support(struct hinic3_nic_dev *nic_dev,
49*17fcb3dcSFan Gong 			 enum hinic3_nic_feature_cap feature_bits)
50*17fcb3dcSFan Gong {
51*17fcb3dcSFan Gong 	return (nic_dev->nic_io->feature_cap & feature_bits) == feature_bits;
52*17fcb3dcSFan Gong }
53*17fcb3dcSFan Gong 
54*17fcb3dcSFan Gong void hinic3_update_nic_feature(struct hinic3_nic_dev *nic_dev, u64 feature_cap)
55*17fcb3dcSFan Gong {
56*17fcb3dcSFan Gong 	nic_dev->nic_io->feature_cap = feature_cap;
57*17fcb3dcSFan Gong }
58*17fcb3dcSFan Gong 
59*17fcb3dcSFan Gong static int hinic3_set_function_table(struct hinic3_hwdev *hwdev, u32 cfg_bitmap,
60*17fcb3dcSFan Gong 				     const struct l2nic_func_tbl_cfg *cfg)
61*17fcb3dcSFan Gong {
62*17fcb3dcSFan Gong 	struct l2nic_cmd_set_func_tbl cmd_func_tbl = {};
63*17fcb3dcSFan Gong 	struct mgmt_msg_params msg_params = {};
64*17fcb3dcSFan Gong 	int err;
65*17fcb3dcSFan Gong 
66*17fcb3dcSFan Gong 	cmd_func_tbl.func_id = hinic3_global_func_id(hwdev);
67*17fcb3dcSFan Gong 	cmd_func_tbl.cfg_bitmap = cfg_bitmap;
68*17fcb3dcSFan Gong 	cmd_func_tbl.tbl_cfg = *cfg;
69*17fcb3dcSFan Gong 
70*17fcb3dcSFan Gong 	mgmt_msg_params_init_default(&msg_params, &cmd_func_tbl,
71*17fcb3dcSFan Gong 				     sizeof(cmd_func_tbl));
72*17fcb3dcSFan Gong 
73*17fcb3dcSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
74*17fcb3dcSFan Gong 				       L2NIC_CMD_SET_FUNC_TBL, &msg_params);
75*17fcb3dcSFan Gong 	if (err || cmd_func_tbl.msg_head.status) {
76*17fcb3dcSFan Gong 		dev_err(hwdev->dev,
77*17fcb3dcSFan Gong 			"Failed to set func table, bitmap: 0x%x, err: %d, status: 0x%x\n",
78*17fcb3dcSFan Gong 			cfg_bitmap, err, cmd_func_tbl.msg_head.status);
79*17fcb3dcSFan Gong 		return -EFAULT;
80*17fcb3dcSFan Gong 	}
81*17fcb3dcSFan Gong 
82*17fcb3dcSFan Gong 	return 0;
83*17fcb3dcSFan Gong }
84*17fcb3dcSFan Gong 
85*17fcb3dcSFan Gong int hinic3_set_port_mtu(struct net_device *netdev, u16 new_mtu)
86*17fcb3dcSFan Gong {
87*17fcb3dcSFan Gong 	struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
88*17fcb3dcSFan Gong 	struct l2nic_func_tbl_cfg func_tbl_cfg = {};
89*17fcb3dcSFan Gong 	struct hinic3_hwdev *hwdev = nic_dev->hwdev;
90*17fcb3dcSFan Gong 
91*17fcb3dcSFan Gong 	func_tbl_cfg.mtu = new_mtu;
92*17fcb3dcSFan Gong 	return hinic3_set_function_table(hwdev, BIT(L2NIC_FUNC_TBL_CFG_MTU),
93*17fcb3dcSFan Gong 					 &func_tbl_cfg);
94*17fcb3dcSFan Gong }
95*17fcb3dcSFan Gong 
96*17fcb3dcSFan Gong static int hinic3_check_mac_info(struct hinic3_hwdev *hwdev, u8 status,
97*17fcb3dcSFan Gong 				 u16 vlan_id)
98*17fcb3dcSFan Gong {
99*17fcb3dcSFan Gong 	if ((status && status != MGMT_STATUS_EXIST) ||
100*17fcb3dcSFan Gong 	    ((vlan_id & BIT(15)) && status == MGMT_STATUS_EXIST)) {
101*17fcb3dcSFan Gong 		return -EINVAL;
102*17fcb3dcSFan Gong 	}
103*17fcb3dcSFan Gong 
104*17fcb3dcSFan Gong 	return 0;
105*17fcb3dcSFan Gong }
106*17fcb3dcSFan Gong 
107*17fcb3dcSFan Gong int hinic3_set_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id,
108*17fcb3dcSFan Gong 		   u16 func_id)
109*17fcb3dcSFan Gong {
110*17fcb3dcSFan Gong 	struct l2nic_cmd_set_mac mac_info = {};
111*17fcb3dcSFan Gong 	struct mgmt_msg_params msg_params = {};
112*17fcb3dcSFan Gong 	int err;
113*17fcb3dcSFan Gong 
114*17fcb3dcSFan Gong 	if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) {
115*17fcb3dcSFan Gong 		dev_err(hwdev->dev, "Invalid VLAN number: %d\n",
116*17fcb3dcSFan Gong 			(vlan_id & HINIC3_VLAN_ID_MASK));
117*17fcb3dcSFan Gong 		return -EINVAL;
118*17fcb3dcSFan Gong 	}
119*17fcb3dcSFan Gong 
120*17fcb3dcSFan Gong 	mac_info.func_id = func_id;
121*17fcb3dcSFan Gong 	mac_info.vlan_id = vlan_id;
122*17fcb3dcSFan Gong 	ether_addr_copy(mac_info.mac, mac_addr);
123*17fcb3dcSFan Gong 
124*17fcb3dcSFan Gong 	mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info));
125*17fcb3dcSFan Gong 
126*17fcb3dcSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
127*17fcb3dcSFan Gong 				       L2NIC_CMD_SET_MAC, &msg_params);
128*17fcb3dcSFan Gong 	if (err || hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
129*17fcb3dcSFan Gong 					 mac_info.vlan_id)) {
130*17fcb3dcSFan Gong 		dev_err(hwdev->dev,
131*17fcb3dcSFan Gong 			"Failed to update MAC, err: %d, status: 0x%x\n",
132*17fcb3dcSFan Gong 			err, mac_info.msg_head.status);
133*17fcb3dcSFan Gong 		return -EIO;
134*17fcb3dcSFan Gong 	}
135*17fcb3dcSFan Gong 
136*17fcb3dcSFan Gong 	if (mac_info.msg_head.status == MGMT_STATUS_PF_SET_VF_ALREADY) {
137*17fcb3dcSFan Gong 		dev_warn(hwdev->dev, "PF has already set VF mac, Ignore set operation\n");
138*17fcb3dcSFan Gong 		return 0;
139*17fcb3dcSFan Gong 	}
140*17fcb3dcSFan Gong 
141*17fcb3dcSFan Gong 	if (mac_info.msg_head.status == MGMT_STATUS_EXIST) {
142*17fcb3dcSFan Gong 		dev_warn(hwdev->dev, "MAC is repeated. Ignore update operation\n");
143*17fcb3dcSFan Gong 		return 0;
144*17fcb3dcSFan Gong 	}
145*17fcb3dcSFan Gong 
146*17fcb3dcSFan Gong 	return 0;
147*17fcb3dcSFan Gong }
148*17fcb3dcSFan Gong 
149*17fcb3dcSFan Gong int hinic3_del_mac(struct hinic3_hwdev *hwdev, const u8 *mac_addr, u16 vlan_id,
150*17fcb3dcSFan Gong 		   u16 func_id)
151*17fcb3dcSFan Gong {
152*17fcb3dcSFan Gong 	struct l2nic_cmd_set_mac mac_info = {};
153*17fcb3dcSFan Gong 	struct mgmt_msg_params msg_params = {};
154*17fcb3dcSFan Gong 	int err;
155*17fcb3dcSFan Gong 
156*17fcb3dcSFan Gong 	if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) {
157*17fcb3dcSFan Gong 		dev_err(hwdev->dev, "Invalid VLAN number: %d\n",
158*17fcb3dcSFan Gong 			(vlan_id & HINIC3_VLAN_ID_MASK));
159*17fcb3dcSFan Gong 		return -EINVAL;
160*17fcb3dcSFan Gong 	}
161*17fcb3dcSFan Gong 
162*17fcb3dcSFan Gong 	mac_info.func_id = func_id;
163*17fcb3dcSFan Gong 	mac_info.vlan_id = vlan_id;
164*17fcb3dcSFan Gong 	ether_addr_copy(mac_info.mac, mac_addr);
165*17fcb3dcSFan Gong 
166*17fcb3dcSFan Gong 	mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info));
167*17fcb3dcSFan Gong 
168*17fcb3dcSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
169*17fcb3dcSFan Gong 				       L2NIC_CMD_DEL_MAC, &msg_params);
170*17fcb3dcSFan Gong 	if (err) {
171*17fcb3dcSFan Gong 		dev_err(hwdev->dev,
172*17fcb3dcSFan Gong 			"Failed to delete MAC, err: %d, status: 0x%x\n",
173*17fcb3dcSFan Gong 			err, mac_info.msg_head.status);
174*17fcb3dcSFan Gong 		return err;
175*17fcb3dcSFan Gong 	}
176*17fcb3dcSFan Gong 
177*17fcb3dcSFan Gong 	return 0;
178*17fcb3dcSFan Gong }
179*17fcb3dcSFan Gong 
180*17fcb3dcSFan Gong int hinic3_update_mac(struct hinic3_hwdev *hwdev, const u8 *old_mac,
181*17fcb3dcSFan Gong 		      u8 *new_mac, u16 vlan_id, u16 func_id)
182*17fcb3dcSFan Gong {
183*17fcb3dcSFan Gong 	struct l2nic_cmd_update_mac mac_info = {};
184*17fcb3dcSFan Gong 	struct mgmt_msg_params msg_params = {};
185*17fcb3dcSFan Gong 	int err;
186*17fcb3dcSFan Gong 
187*17fcb3dcSFan Gong 	if ((vlan_id & HINIC3_VLAN_ID_MASK) >= VLAN_N_VID) {
188*17fcb3dcSFan Gong 		dev_err(hwdev->dev, "Invalid VLAN number: %d\n",
189*17fcb3dcSFan Gong 			(vlan_id & HINIC3_VLAN_ID_MASK));
190*17fcb3dcSFan Gong 		return -EINVAL;
191*17fcb3dcSFan Gong 	}
192*17fcb3dcSFan Gong 
193*17fcb3dcSFan Gong 	mac_info.func_id = func_id;
194*17fcb3dcSFan Gong 	mac_info.vlan_id = vlan_id;
195*17fcb3dcSFan Gong 	ether_addr_copy(mac_info.old_mac, old_mac);
196*17fcb3dcSFan Gong 	ether_addr_copy(mac_info.new_mac, new_mac);
197*17fcb3dcSFan Gong 
198*17fcb3dcSFan Gong 	mgmt_msg_params_init_default(&msg_params, &mac_info, sizeof(mac_info));
199*17fcb3dcSFan Gong 
200*17fcb3dcSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
201*17fcb3dcSFan Gong 				       L2NIC_CMD_UPDATE_MAC, &msg_params);
202*17fcb3dcSFan Gong 	if (err || hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
203*17fcb3dcSFan Gong 					 mac_info.vlan_id)) {
204*17fcb3dcSFan Gong 		dev_err(hwdev->dev,
205*17fcb3dcSFan Gong 			"Failed to update MAC, err: %d, status: 0x%x\n",
206*17fcb3dcSFan Gong 			err, mac_info.msg_head.status);
207*17fcb3dcSFan Gong 		return -EIO;
208*17fcb3dcSFan Gong 	}
209*17fcb3dcSFan Gong 	return 0;
210*17fcb3dcSFan Gong }
211*17fcb3dcSFan Gong 
212*17fcb3dcSFan Gong int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev)
213*17fcb3dcSFan Gong {
214*17fcb3dcSFan Gong 	struct l2nic_cmd_force_pkt_drop pkt_drop = {};
215*17fcb3dcSFan Gong 	struct mgmt_msg_params msg_params = {};
216*17fcb3dcSFan Gong 	int err;
217*17fcb3dcSFan Gong 
218*17fcb3dcSFan Gong 	pkt_drop.port = hinic3_physical_port_id(hwdev);
219*17fcb3dcSFan Gong 
220*17fcb3dcSFan Gong 	mgmt_msg_params_init_default(&msg_params, &pkt_drop, sizeof(pkt_drop));
221*17fcb3dcSFan Gong 
222*17fcb3dcSFan Gong 	err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
223*17fcb3dcSFan Gong 				       L2NIC_CMD_FORCE_PKT_DROP, &msg_params);
224*17fcb3dcSFan Gong 	if ((pkt_drop.msg_head.status != MGMT_STATUS_CMD_UNSUPPORTED &&
225*17fcb3dcSFan Gong 	     pkt_drop.msg_head.status) || err) {
226*17fcb3dcSFan Gong 		dev_err(hwdev->dev,
227*17fcb3dcSFan Gong 			"Failed to set force tx packets drop, err: %d, status: 0x%x\n",
228*17fcb3dcSFan Gong 			err, pkt_drop.msg_head.status);
229*17fcb3dcSFan Gong 		return -EFAULT;
230*17fcb3dcSFan Gong 	}
231*17fcb3dcSFan Gong 
232*17fcb3dcSFan Gong 	return pkt_drop.msg_head.status;
233*17fcb3dcSFan Gong }
234