xref: /linux/drivers/net/ethernet/huawei/hinic/hinic_port.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
12025cf9eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
225a3ba61SAviad Krawczyk /*
325a3ba61SAviad Krawczyk  * Huawei HiNIC PCI Express Linux driver
425a3ba61SAviad Krawczyk  * Copyright(c) 2017 Huawei Technologies Co., Ltd
525a3ba61SAviad Krawczyk  */
625a3ba61SAviad Krawczyk 
725a3ba61SAviad Krawczyk #include <linux/types.h>
825a3ba61SAviad Krawczyk #include <linux/netdevice.h>
925a3ba61SAviad Krawczyk #include <linux/etherdevice.h>
1025a3ba61SAviad Krawczyk #include <linux/if_vlan.h>
1125a3ba61SAviad Krawczyk #include <linux/pci.h>
1225a3ba61SAviad Krawczyk #include <linux/device.h>
1325a3ba61SAviad Krawczyk #include <linux/errno.h>
1425a3ba61SAviad Krawczyk 
1525a3ba61SAviad Krawczyk #include "hinic_hw_if.h"
1625a3ba61SAviad Krawczyk #include "hinic_hw_dev.h"
1725a3ba61SAviad Krawczyk #include "hinic_port.h"
1825a3ba61SAviad Krawczyk #include "hinic_dev.h"
1925a3ba61SAviad Krawczyk 
2025a3ba61SAviad Krawczyk enum mac_op {
2125a3ba61SAviad Krawczyk 	MAC_DEL,
2225a3ba61SAviad Krawczyk 	MAC_SET,
2325a3ba61SAviad Krawczyk };
2425a3ba61SAviad Krawczyk 
2525a3ba61SAviad Krawczyk /**
2625a3ba61SAviad Krawczyk  * change_mac - change(add or delete) mac address
2725a3ba61SAviad Krawczyk  * @nic_dev: nic device
2825a3ba61SAviad Krawczyk  * @addr: mac address
2925a3ba61SAviad Krawczyk  * @vlan_id: vlan number to set with the mac
3025a3ba61SAviad Krawczyk  * @op: add or delete the mac
3125a3ba61SAviad Krawczyk  *
3225a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
3325a3ba61SAviad Krawczyk  **/
change_mac(struct hinic_dev * nic_dev,const u8 * addr,u16 vlan_id,enum mac_op op)3425a3ba61SAviad Krawczyk static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
3525a3ba61SAviad Krawczyk 		      u16 vlan_id, enum mac_op op)
3625a3ba61SAviad Krawczyk {
3725a3ba61SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
3825a3ba61SAviad Krawczyk 	struct hinic_port_mac_cmd port_mac_cmd;
3925a3ba61SAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
407dd29ee1SLuo bin 	u16 out_size = sizeof(port_mac_cmd);
4125a3ba61SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
4225a3ba61SAviad Krawczyk 	enum hinic_port_cmd cmd;
4325a3ba61SAviad Krawczyk 	int err;
4425a3ba61SAviad Krawczyk 
4525a3ba61SAviad Krawczyk 	if (op == MAC_SET)
4625a3ba61SAviad Krawczyk 		cmd = HINIC_PORT_CMD_SET_MAC;
4725a3ba61SAviad Krawczyk 	else
4825a3ba61SAviad Krawczyk 		cmd = HINIC_PORT_CMD_DEL_MAC;
4925a3ba61SAviad Krawczyk 
5025a3ba61SAviad Krawczyk 	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
5125a3ba61SAviad Krawczyk 	port_mac_cmd.vlan_id = vlan_id;
5225a3ba61SAviad Krawczyk 	memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
5325a3ba61SAviad Krawczyk 
5425a3ba61SAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
5525a3ba61SAviad Krawczyk 				 sizeof(port_mac_cmd),
5625a3ba61SAviad Krawczyk 				 &port_mac_cmd, &out_size);
577dd29ee1SLuo bin 	if (err || out_size != sizeof(port_mac_cmd) ||
587dd29ee1SLuo bin 	    (port_mac_cmd.status &&
59f68910a8SLuo bin 	     (port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY || !HINIC_IS_VF(hwif)) &&
607dd29ee1SLuo bin 	     port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {
6190f86b8aSLuo bin 		dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",
6290f86b8aSLuo bin 			err, port_mac_cmd.status, out_size);
6325a3ba61SAviad Krawczyk 		return -EFAULT;
6425a3ba61SAviad Krawczyk 	}
6525a3ba61SAviad Krawczyk 
6672ef908bSLuo bin 	if (port_mac_cmd.status == HINIC_PF_SET_VF_ALREADY) {
6772ef908bSLuo bin 		dev_warn(&pdev->dev, "PF has already set VF mac, ignore %s operation\n",
6872ef908bSLuo bin 			 (op == MAC_SET) ? "set" : "del");
697dd29ee1SLuo bin 		return HINIC_PF_SET_VF_ALREADY;
707dd29ee1SLuo bin 	}
717dd29ee1SLuo bin 
727dd29ee1SLuo bin 	if (cmd == HINIC_PORT_CMD_SET_MAC && port_mac_cmd.status ==
737dd29ee1SLuo bin 	    HINIC_MGMT_STATUS_EXIST)
7472ef908bSLuo bin 		dev_warn(&pdev->dev, "MAC is repeated, ignore set operation\n");
757dd29ee1SLuo bin 
7625a3ba61SAviad Krawczyk 	return 0;
7725a3ba61SAviad Krawczyk }
7825a3ba61SAviad Krawczyk 
7925a3ba61SAviad Krawczyk /**
8025a3ba61SAviad Krawczyk  * hinic_port_add_mac - add mac address
8125a3ba61SAviad Krawczyk  * @nic_dev: nic device
8225a3ba61SAviad Krawczyk  * @addr: mac address
8325a3ba61SAviad Krawczyk  * @vlan_id: vlan number to set with the mac
8425a3ba61SAviad Krawczyk  *
8525a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
8625a3ba61SAviad Krawczyk  **/
hinic_port_add_mac(struct hinic_dev * nic_dev,const u8 * addr,u16 vlan_id)8725a3ba61SAviad Krawczyk int hinic_port_add_mac(struct hinic_dev *nic_dev,
8825a3ba61SAviad Krawczyk 		       const u8 *addr, u16 vlan_id)
8925a3ba61SAviad Krawczyk {
9025a3ba61SAviad Krawczyk 	return change_mac(nic_dev, addr, vlan_id, MAC_SET);
9125a3ba61SAviad Krawczyk }
9225a3ba61SAviad Krawczyk 
9325a3ba61SAviad Krawczyk /**
9425a3ba61SAviad Krawczyk  * hinic_port_del_mac - remove mac address
9525a3ba61SAviad Krawczyk  * @nic_dev: nic device
9625a3ba61SAviad Krawczyk  * @addr: mac address
9725a3ba61SAviad Krawczyk  * @vlan_id: vlan number that is connected to the mac
9825a3ba61SAviad Krawczyk  *
9925a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
10025a3ba61SAviad Krawczyk  **/
hinic_port_del_mac(struct hinic_dev * nic_dev,const u8 * addr,u16 vlan_id)10125a3ba61SAviad Krawczyk int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
10225a3ba61SAviad Krawczyk 		       u16 vlan_id)
10325a3ba61SAviad Krawczyk {
10425a3ba61SAviad Krawczyk 	return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
10525a3ba61SAviad Krawczyk }
10625a3ba61SAviad Krawczyk 
10725a3ba61SAviad Krawczyk /**
10825a3ba61SAviad Krawczyk  * hinic_port_get_mac - get the mac address of the nic device
10925a3ba61SAviad Krawczyk  * @nic_dev: nic device
11025a3ba61SAviad Krawczyk  * @addr: returned mac address
11125a3ba61SAviad Krawczyk  *
11225a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
11325a3ba61SAviad Krawczyk  **/
hinic_port_get_mac(struct hinic_dev * nic_dev,u8 * addr)11425a3ba61SAviad Krawczyk int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
11525a3ba61SAviad Krawczyk {
11625a3ba61SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
11725a3ba61SAviad Krawczyk 	struct hinic_port_mac_cmd port_mac_cmd;
11825a3ba61SAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
1197dd29ee1SLuo bin 	u16 out_size = sizeof(port_mac_cmd);
12025a3ba61SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
12125a3ba61SAviad Krawczyk 	int err;
12225a3ba61SAviad Krawczyk 
12325a3ba61SAviad Krawczyk 	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
12425a3ba61SAviad Krawczyk 
12525a3ba61SAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
12625a3ba61SAviad Krawczyk 				 &port_mac_cmd, sizeof(port_mac_cmd),
12725a3ba61SAviad Krawczyk 				 &port_mac_cmd, &out_size);
128c8ad5df6SGuangbin Huang 	if (err || out_size != sizeof(port_mac_cmd) || port_mac_cmd.status) {
12990f86b8aSLuo bin 		dev_err(&pdev->dev, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",
13090f86b8aSLuo bin 			err, port_mac_cmd.status, out_size);
13125a3ba61SAviad Krawczyk 		return -EFAULT;
13225a3ba61SAviad Krawczyk 	}
13325a3ba61SAviad Krawczyk 
13425a3ba61SAviad Krawczyk 	memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
13525a3ba61SAviad Krawczyk 	return 0;
13625a3ba61SAviad Krawczyk }
13725a3ba61SAviad Krawczyk 
13825a3ba61SAviad Krawczyk /**
13925a3ba61SAviad Krawczyk  * hinic_port_set_mtu - set mtu
14025a3ba61SAviad Krawczyk  * @nic_dev: nic device
14125a3ba61SAviad Krawczyk  * @new_mtu: new mtu
14225a3ba61SAviad Krawczyk  *
14325a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
14425a3ba61SAviad Krawczyk  **/
hinic_port_set_mtu(struct hinic_dev * nic_dev,int new_mtu)14525a3ba61SAviad Krawczyk int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
14625a3ba61SAviad Krawczyk {
14725a3ba61SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
14825a3ba61SAviad Krawczyk 	struct hinic_port_mtu_cmd port_mtu_cmd;
14925a3ba61SAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
1507dd29ee1SLuo bin 	u16 out_size = sizeof(port_mtu_cmd);
15125a3ba61SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
152022f19cfScaihuoqing 	int err;
15325a3ba61SAviad Krawczyk 
15425a3ba61SAviad Krawczyk 	port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
15525a3ba61SAviad Krawczyk 	port_mtu_cmd.mtu = new_mtu;
15625a3ba61SAviad Krawczyk 
15725a3ba61SAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
15825a3ba61SAviad Krawczyk 				 &port_mtu_cmd, sizeof(port_mtu_cmd),
15925a3ba61SAviad Krawczyk 				 &port_mtu_cmd, &out_size);
16090f86b8aSLuo bin 	if (err || out_size != sizeof(port_mtu_cmd) || port_mtu_cmd.status) {
16190f86b8aSLuo bin 		dev_err(&pdev->dev, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x\n",
16290f86b8aSLuo bin 			err, port_mtu_cmd.status, out_size);
16325a3ba61SAviad Krawczyk 		return -EFAULT;
16425a3ba61SAviad Krawczyk 	}
16525a3ba61SAviad Krawczyk 
16625a3ba61SAviad Krawczyk 	return 0;
16725a3ba61SAviad Krawczyk }
16825a3ba61SAviad Krawczyk 
16925a3ba61SAviad Krawczyk /**
17025a3ba61SAviad Krawczyk  * hinic_port_add_vlan - add vlan to the nic device
17125a3ba61SAviad Krawczyk  * @nic_dev: nic device
17225a3ba61SAviad Krawczyk  * @vlan_id: the vlan number to add
17325a3ba61SAviad Krawczyk  *
17425a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
17525a3ba61SAviad Krawczyk  **/
hinic_port_add_vlan(struct hinic_dev * nic_dev,u16 vlan_id)17625a3ba61SAviad Krawczyk int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
17725a3ba61SAviad Krawczyk {
17825a3ba61SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
17925a3ba61SAviad Krawczyk 	struct hinic_port_vlan_cmd port_vlan_cmd;
18025a3ba61SAviad Krawczyk 
18125a3ba61SAviad Krawczyk 	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
18225a3ba61SAviad Krawczyk 	port_vlan_cmd.vlan_id = vlan_id;
18325a3ba61SAviad Krawczyk 
18425a3ba61SAviad Krawczyk 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
18525a3ba61SAviad Krawczyk 				  &port_vlan_cmd, sizeof(port_vlan_cmd),
18625a3ba61SAviad Krawczyk 				  NULL, NULL);
18725a3ba61SAviad Krawczyk }
18825a3ba61SAviad Krawczyk 
18925a3ba61SAviad Krawczyk /**
19025a3ba61SAviad Krawczyk  * hinic_port_del_vlan - delete vlan from the nic device
19125a3ba61SAviad Krawczyk  * @nic_dev: nic device
19225a3ba61SAviad Krawczyk  * @vlan_id: the vlan number to delete
19325a3ba61SAviad Krawczyk  *
19425a3ba61SAviad Krawczyk  * Return 0 - Success, negative - Failure
19525a3ba61SAviad Krawczyk  **/
hinic_port_del_vlan(struct hinic_dev * nic_dev,u16 vlan_id)19625a3ba61SAviad Krawczyk int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
19725a3ba61SAviad Krawczyk {
19825a3ba61SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
19925a3ba61SAviad Krawczyk 	struct hinic_port_vlan_cmd port_vlan_cmd;
20025a3ba61SAviad Krawczyk 
20125a3ba61SAviad Krawczyk 	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
20225a3ba61SAviad Krawczyk 	port_vlan_cmd.vlan_id = vlan_id;
20325a3ba61SAviad Krawczyk 
20425a3ba61SAviad Krawczyk 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
20525a3ba61SAviad Krawczyk 				 &port_vlan_cmd, sizeof(port_vlan_cmd),
20625a3ba61SAviad Krawczyk 				 NULL, NULL);
20725a3ba61SAviad Krawczyk }
208c4d06d2dSAviad Krawczyk 
209c4d06d2dSAviad Krawczyk /**
210c4d06d2dSAviad Krawczyk  * hinic_port_set_rx_mode - set rx mode in the nic device
211c4d06d2dSAviad Krawczyk  * @nic_dev: nic device
212c4d06d2dSAviad Krawczyk  * @rx_mode: the rx mode to set
213c4d06d2dSAviad Krawczyk  *
214c4d06d2dSAviad Krawczyk  * Return 0 - Success, negative - Failure
215c4d06d2dSAviad Krawczyk  **/
hinic_port_set_rx_mode(struct hinic_dev * nic_dev,u32 rx_mode)216c4d06d2dSAviad Krawczyk int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
217c4d06d2dSAviad Krawczyk {
218c4d06d2dSAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
219c4d06d2dSAviad Krawczyk 	struct hinic_port_rx_mode_cmd rx_mode_cmd;
220c4d06d2dSAviad Krawczyk 
221c4d06d2dSAviad Krawczyk 	rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
222c4d06d2dSAviad Krawczyk 	rx_mode_cmd.rx_mode = rx_mode;
223c4d06d2dSAviad Krawczyk 
224c4d06d2dSAviad Krawczyk 	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
225c4d06d2dSAviad Krawczyk 				  &rx_mode_cmd, sizeof(rx_mode_cmd),
226c4d06d2dSAviad Krawczyk 				  NULL, NULL);
227c4d06d2dSAviad Krawczyk }
228c4d06d2dSAviad Krawczyk 
229c4d06d2dSAviad Krawczyk /**
230c4d06d2dSAviad Krawczyk  * hinic_port_link_state - get the link state
231c4d06d2dSAviad Krawczyk  * @nic_dev: nic device
232c4d06d2dSAviad Krawczyk  * @link_state: the returned link state
233c4d06d2dSAviad Krawczyk  *
234c4d06d2dSAviad Krawczyk  * Return 0 - Success, negative - Failure
235c4d06d2dSAviad Krawczyk  **/
hinic_port_link_state(struct hinic_dev * nic_dev,enum hinic_port_link_state * link_state)236c4d06d2dSAviad Krawczyk int hinic_port_link_state(struct hinic_dev *nic_dev,
237c4d06d2dSAviad Krawczyk 			  enum hinic_port_link_state *link_state)
238c4d06d2dSAviad Krawczyk {
239c4d06d2dSAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
240c4d06d2dSAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
241c4d06d2dSAviad Krawczyk 	struct hinic_port_link_cmd link_cmd;
242c4d06d2dSAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
2437dd29ee1SLuo bin 	u16 out_size = sizeof(link_cmd);
244c4d06d2dSAviad Krawczyk 	int err;
245c4d06d2dSAviad Krawczyk 
246c4d06d2dSAviad Krawczyk 	link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
247c4d06d2dSAviad Krawczyk 
248c4d06d2dSAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
249c4d06d2dSAviad Krawczyk 				 &link_cmd, sizeof(link_cmd),
250c4d06d2dSAviad Krawczyk 				 &link_cmd, &out_size);
251c8ad5df6SGuangbin Huang 	if (err || out_size != sizeof(link_cmd) || link_cmd.status) {
25290f86b8aSLuo bin 		dev_err(&pdev->dev, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n",
25390f86b8aSLuo bin 			err, link_cmd.status, out_size);
254c4d06d2dSAviad Krawczyk 		return -EINVAL;
255c4d06d2dSAviad Krawczyk 	}
256c4d06d2dSAviad Krawczyk 
257c4d06d2dSAviad Krawczyk 	*link_state = link_cmd.state;
258c4d06d2dSAviad Krawczyk 	return 0;
259c4d06d2dSAviad Krawczyk }
260c4d06d2dSAviad Krawczyk 
261c4d06d2dSAviad Krawczyk /**
262c4d06d2dSAviad Krawczyk  * hinic_port_set_state - set port state
263c4d06d2dSAviad Krawczyk  * @nic_dev: nic device
264c4d06d2dSAviad Krawczyk  * @state: the state to set
265c4d06d2dSAviad Krawczyk  *
266c4d06d2dSAviad Krawczyk  * Return 0 - Success, negative - Failure
267c4d06d2dSAviad Krawczyk  **/
hinic_port_set_state(struct hinic_dev * nic_dev,enum hinic_port_state state)268c4d06d2dSAviad Krawczyk int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
269c4d06d2dSAviad Krawczyk {
270c4d06d2dSAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
271c4d06d2dSAviad Krawczyk 	struct hinic_port_state_cmd port_state;
272c4d06d2dSAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
273c4d06d2dSAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
2747dd29ee1SLuo bin 	u16 out_size = sizeof(port_state);
275c4d06d2dSAviad Krawczyk 	int err;
276c4d06d2dSAviad Krawczyk 
2777dd29ee1SLuo bin 	if (HINIC_IS_VF(hwdev->hwif))
2787dd29ee1SLuo bin 		return 0;
279c4d06d2dSAviad Krawczyk 
280c4d06d2dSAviad Krawczyk 	port_state.state = state;
281c4d06d2dSAviad Krawczyk 
282c4d06d2dSAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,
283c4d06d2dSAviad Krawczyk 				 &port_state, sizeof(port_state),
284c4d06d2dSAviad Krawczyk 				 &port_state, &out_size);
285c8ad5df6SGuangbin Huang 	if (err || out_size != sizeof(port_state) || port_state.status) {
28690f86b8aSLuo bin 		dev_err(&pdev->dev, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x\n",
28790f86b8aSLuo bin 			err, port_state.status, out_size);
288c4d06d2dSAviad Krawczyk 		return -EFAULT;
289c4d06d2dSAviad Krawczyk 	}
290c4d06d2dSAviad Krawczyk 
291c4d06d2dSAviad Krawczyk 	return 0;
292c4d06d2dSAviad Krawczyk }
293e2585ea7SAviad Krawczyk 
294e2585ea7SAviad Krawczyk /**
295e2585ea7SAviad Krawczyk  * hinic_port_set_func_state- set func device state
296e2585ea7SAviad Krawczyk  * @nic_dev: nic device
297e2585ea7SAviad Krawczyk  * @state: the state to set
298e2585ea7SAviad Krawczyk  *
299e2585ea7SAviad Krawczyk  * Return 0 - Success, negative - Failure
300e2585ea7SAviad Krawczyk  **/
hinic_port_set_func_state(struct hinic_dev * nic_dev,enum hinic_func_port_state state)301e2585ea7SAviad Krawczyk int hinic_port_set_func_state(struct hinic_dev *nic_dev,
302e2585ea7SAviad Krawczyk 			      enum hinic_func_port_state state)
303e2585ea7SAviad Krawczyk {
304e2585ea7SAviad Krawczyk 	struct hinic_port_func_state_cmd func_state;
305e2585ea7SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
306e2585ea7SAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
307e2585ea7SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
3087dd29ee1SLuo bin 	u16 out_size = sizeof(func_state);
309e2585ea7SAviad Krawczyk 	int err;
310e2585ea7SAviad Krawczyk 
311e2585ea7SAviad Krawczyk 	func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
312e2585ea7SAviad Krawczyk 	func_state.state = state;
313e2585ea7SAviad Krawczyk 
314e2585ea7SAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,
315e2585ea7SAviad Krawczyk 				 &func_state, sizeof(func_state),
316e2585ea7SAviad Krawczyk 				 &func_state, &out_size);
317c8ad5df6SGuangbin Huang 	if (err || out_size != sizeof(func_state) || func_state.status) {
31890f86b8aSLuo bin 		dev_err(&pdev->dev, "Failed to set port func state, err: %d, status: 0x%x, out size: 0x%x\n",
31990f86b8aSLuo bin 			err, func_state.status, out_size);
320e2585ea7SAviad Krawczyk 		return -EFAULT;
321e2585ea7SAviad Krawczyk 	}
322e2585ea7SAviad Krawczyk 
323e2585ea7SAviad Krawczyk 	return 0;
324e2585ea7SAviad Krawczyk }
325edd384f6SAviad Krawczyk 
326edd384f6SAviad Krawczyk /**
327edd384f6SAviad Krawczyk  * hinic_port_get_cap - get port capabilities
328edd384f6SAviad Krawczyk  * @nic_dev: nic device
329edd384f6SAviad Krawczyk  * @port_cap: returned port capabilities
330edd384f6SAviad Krawczyk  *
331edd384f6SAviad Krawczyk  * Return 0 - Success, negative - Failure
332edd384f6SAviad Krawczyk  **/
hinic_port_get_cap(struct hinic_dev * nic_dev,struct hinic_port_cap * port_cap)333edd384f6SAviad Krawczyk int hinic_port_get_cap(struct hinic_dev *nic_dev,
334edd384f6SAviad Krawczyk 		       struct hinic_port_cap *port_cap)
335edd384f6SAviad Krawczyk {
336edd384f6SAviad Krawczyk 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
337edd384f6SAviad Krawczyk 	struct hinic_hwif *hwif = hwdev->hwif;
338edd384f6SAviad Krawczyk 	struct pci_dev *pdev = hwif->pdev;
3397dd29ee1SLuo bin 	u16 out_size = sizeof(*port_cap);
340edd384f6SAviad Krawczyk 	int err;
341edd384f6SAviad Krawczyk 
342edd384f6SAviad Krawczyk 	port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);
343edd384f6SAviad Krawczyk 
344edd384f6SAviad Krawczyk 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,
345edd384f6SAviad Krawczyk 				 port_cap, sizeof(*port_cap),
346edd384f6SAviad Krawczyk 				 port_cap, &out_size);
347c8ad5df6SGuangbin Huang 	if (err || out_size != sizeof(*port_cap) || port_cap->status) {
348edd384f6SAviad Krawczyk 		dev_err(&pdev->dev,
34990f86b8aSLuo bin 			"Failed to get port capabilities, err: %d, status: 0x%x, out size: 0x%x\n",
35090f86b8aSLuo bin 			err, port_cap->status, out_size);
35190f86b8aSLuo bin 		return -EIO;
352edd384f6SAviad Krawczyk 	}
353edd384f6SAviad Krawczyk 
354edd384f6SAviad Krawczyk 	return 0;
355edd384f6SAviad Krawczyk }
356cc18a754SZhao Chen 
357cc18a754SZhao Chen /**
358cc18a754SZhao Chen  * hinic_port_set_tso - set port tso configuration
359cc18a754SZhao Chen  * @nic_dev: nic device
360cc18a754SZhao Chen  * @state: the tso state to set
361cc18a754SZhao Chen  *
362cc18a754SZhao Chen  * Return 0 - Success, negative - Failure
363cc18a754SZhao Chen  **/
hinic_port_set_tso(struct hinic_dev * nic_dev,enum hinic_tso_state state)364cc18a754SZhao Chen int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)
365cc18a754SZhao Chen {
366cc18a754SZhao Chen 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
367cc18a754SZhao Chen 	struct hinic_hwif *hwif = hwdev->hwif;
368cc18a754SZhao Chen 	struct hinic_tso_config tso_cfg = {0};
369cc18a754SZhao Chen 	struct pci_dev *pdev = hwif->pdev;
3707dd29ee1SLuo bin 	u16 out_size = sizeof(tso_cfg);
371cc18a754SZhao Chen 	int err;
372cc18a754SZhao Chen 
373cc18a754SZhao Chen 	tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
374cc18a754SZhao Chen 	tso_cfg.tso_en = state;
375cc18a754SZhao Chen 
376cc18a754SZhao Chen 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_TSO,
377cc18a754SZhao Chen 				 &tso_cfg, sizeof(tso_cfg),
378cc18a754SZhao Chen 				 &tso_cfg, &out_size);
379cc18a754SZhao Chen 	if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {
380cc18a754SZhao Chen 		dev_err(&pdev->dev,
38190f86b8aSLuo bin 			"Failed to set port tso, err: %d, status: 0x%x, out size: 0x%x\n",
38290f86b8aSLuo bin 			err, tso_cfg.status, out_size);
38390f86b8aSLuo bin 		return -EIO;
384cc18a754SZhao Chen 	}
385cc18a754SZhao Chen 
386cc18a754SZhao Chen 	return 0;
387cc18a754SZhao Chen }
3884a61abb1SXue Chaojing 
hinic_set_rx_csum_offload(struct hinic_dev * nic_dev,u32 en)3894a61abb1SXue Chaojing int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)
3904a61abb1SXue Chaojing {
3914a61abb1SXue Chaojing 	struct hinic_checksum_offload rx_csum_cfg = {0};
3924a61abb1SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
3937dd29ee1SLuo bin 	u16 out_size = sizeof(rx_csum_cfg);
394e159e592SColin Ian King 	struct hinic_hwif *hwif;
395e159e592SColin Ian King 	struct pci_dev *pdev;
3964a61abb1SXue Chaojing 	int err;
3974a61abb1SXue Chaojing 
3984a61abb1SXue Chaojing 	if (!hwdev)
3994a61abb1SXue Chaojing 		return -EINVAL;
4004a61abb1SXue Chaojing 
401e159e592SColin Ian King 	hwif = hwdev->hwif;
402e159e592SColin Ian King 	pdev = hwif->pdev;
4034a61abb1SXue Chaojing 	rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
4044a61abb1SXue Chaojing 	rx_csum_cfg.rx_csum_offload = en;
4054a61abb1SXue Chaojing 
4064a61abb1SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
4074a61abb1SXue Chaojing 				 &rx_csum_cfg, sizeof(rx_csum_cfg),
4084a61abb1SXue Chaojing 				 &rx_csum_cfg, &out_size);
4094a61abb1SXue Chaojing 	if (err || !out_size || rx_csum_cfg.status) {
4104a61abb1SXue Chaojing 		dev_err(&pdev->dev,
41190f86b8aSLuo bin 			"Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x\n",
41290f86b8aSLuo bin 			err, rx_csum_cfg.status, out_size);
41390f86b8aSLuo bin 		return -EIO;
4144a61abb1SXue Chaojing 	}
4154a61abb1SXue Chaojing 
4164a61abb1SXue Chaojing 	return 0;
4174a61abb1SXue Chaojing }
4181e007181SXue Chaojing 
hinic_set_rx_vlan_offload(struct hinic_dev * nic_dev,u8 en)419aebd17b7SXue Chaojing int hinic_set_rx_vlan_offload(struct hinic_dev *nic_dev, u8 en)
420aebd17b7SXue Chaojing {
421aebd17b7SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
422aebd17b7SXue Chaojing 	struct hinic_vlan_cfg vlan_cfg;
423aebd17b7SXue Chaojing 	struct hinic_hwif *hwif;
424aebd17b7SXue Chaojing 	struct pci_dev *pdev;
425aebd17b7SXue Chaojing 	u16 out_size;
426aebd17b7SXue Chaojing 	int err;
427aebd17b7SXue Chaojing 
428aebd17b7SXue Chaojing 	if (!hwdev)
429aebd17b7SXue Chaojing 		return -EINVAL;
430aebd17b7SXue Chaojing 
4317dd29ee1SLuo bin 	out_size = sizeof(vlan_cfg);
432aebd17b7SXue Chaojing 	hwif = hwdev->hwif;
433aebd17b7SXue Chaojing 	pdev = hwif->pdev;
434aebd17b7SXue Chaojing 	vlan_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
435aebd17b7SXue Chaojing 	vlan_cfg.vlan_rx_offload = en;
436aebd17b7SXue Chaojing 
437aebd17b7SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
438aebd17b7SXue Chaojing 				 &vlan_cfg, sizeof(vlan_cfg),
439aebd17b7SXue Chaojing 				 &vlan_cfg, &out_size);
440aebd17b7SXue Chaojing 	if (err || !out_size || vlan_cfg.status) {
441aebd17b7SXue Chaojing 		dev_err(&pdev->dev,
442aebd17b7SXue Chaojing 			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
443aebd17b7SXue Chaojing 			err, vlan_cfg.status, out_size);
444aebd17b7SXue Chaojing 		return -EINVAL;
445aebd17b7SXue Chaojing 	}
446aebd17b7SXue Chaojing 
447aebd17b7SXue Chaojing 	return 0;
448aebd17b7SXue Chaojing }
449aebd17b7SXue Chaojing 
hinic_set_vlan_fliter(struct hinic_dev * nic_dev,u32 en)450*2acf960eSCai Huoqing int hinic_set_vlan_fliter(struct hinic_dev *nic_dev, u32 en)
451*2acf960eSCai Huoqing {
452*2acf960eSCai Huoqing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
453*2acf960eSCai Huoqing 	struct hinic_hwif *hwif = hwdev->hwif;
454*2acf960eSCai Huoqing 	struct pci_dev *pdev = hwif->pdev;
455*2acf960eSCai Huoqing 	struct hinic_vlan_filter vlan_filter;
456*2acf960eSCai Huoqing 	u16 out_size = sizeof(vlan_filter);
457*2acf960eSCai Huoqing 	int err;
458*2acf960eSCai Huoqing 
459*2acf960eSCai Huoqing 	vlan_filter.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
460*2acf960eSCai Huoqing 	vlan_filter.enable = en;
461*2acf960eSCai Huoqing 
462*2acf960eSCai Huoqing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
463*2acf960eSCai Huoqing 				 &vlan_filter, sizeof(vlan_filter),
464*2acf960eSCai Huoqing 				 &vlan_filter, &out_size);
465*2acf960eSCai Huoqing 	if (vlan_filter.status == HINIC_MGMT_CMD_UNSUPPORTED) {
466*2acf960eSCai Huoqing 		err = HINIC_MGMT_CMD_UNSUPPORTED;
467*2acf960eSCai Huoqing 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
468*2acf960eSCai Huoqing 			   HINIC_IS_VF(hwif)) {
469*2acf960eSCai Huoqing 		err = HINIC_MGMT_CMD_UNSUPPORTED;
470*2acf960eSCai Huoqing 	} else if (err || !out_size || vlan_filter.status) {
471*2acf960eSCai Huoqing 		dev_err(&pdev->dev,
472*2acf960eSCai Huoqing 			"Failed to set vlan fliter, err: %d, status: 0x%x, out size: 0x%x\n",
473*2acf960eSCai Huoqing 			err, vlan_filter.status, out_size);
474*2acf960eSCai Huoqing 		err = -EINVAL;
475*2acf960eSCai Huoqing 	}
476*2acf960eSCai Huoqing 
477*2acf960eSCai Huoqing 	return err;
478*2acf960eSCai Huoqing }
479*2acf960eSCai Huoqing 
hinic_set_max_qnum(struct hinic_dev * nic_dev,u8 num_rqs)4801e007181SXue Chaojing int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
4811e007181SXue Chaojing {
4821e007181SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
4831e007181SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
4841e007181SXue Chaojing 	struct hinic_rq_num rq_num = { 0 };
4857dd29ee1SLuo bin 	struct pci_dev *pdev = hwif->pdev;
4861e007181SXue Chaojing 	u16 out_size = sizeof(rq_num);
4871e007181SXue Chaojing 	int err;
4881e007181SXue Chaojing 
4891e007181SXue Chaojing 	rq_num.func_id = HINIC_HWIF_FUNC_IDX(hwif);
4901e007181SXue Chaojing 	rq_num.num_rqs = num_rqs;
491bcab6782SLuo bin 	rq_num.rq_depth = ilog2(nic_dev->rq_depth);
4921e007181SXue Chaojing 
4931e007181SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RQ_IQ_MAP,
4941e007181SXue Chaojing 				 &rq_num, sizeof(rq_num),
4951e007181SXue Chaojing 				 &rq_num, &out_size);
4961e007181SXue Chaojing 	if (err || !out_size || rq_num.status) {
4971e007181SXue Chaojing 		dev_err(&pdev->dev,
49890f86b8aSLuo bin 			"Failed to set rxq number, err: %d, status: 0x%x, out size: 0x%x\n",
49990f86b8aSLuo bin 			err, rq_num.status, out_size);
50090f86b8aSLuo bin 		return -EIO;
5011e007181SXue Chaojing 	}
5021e007181SXue Chaojing 
5031e007181SXue Chaojing 	return 0;
5041e007181SXue Chaojing }
5051e007181SXue Chaojing 
hinic_set_rx_lro(struct hinic_dev * nic_dev,u8 ipv4_en,u8 ipv6_en,u8 max_wqe_num)5061e007181SXue Chaojing static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
5071e007181SXue Chaojing 			    u8 max_wqe_num)
5081e007181SXue Chaojing {
5091e007181SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
5101e007181SXue Chaojing 	struct hinic_lro_config lro_cfg = { 0 };
5117dd29ee1SLuo bin 	struct hinic_hwif *hwif = hwdev->hwif;
5121e007181SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
5131e007181SXue Chaojing 	u16 out_size = sizeof(lro_cfg);
5141e007181SXue Chaojing 	int err;
5151e007181SXue Chaojing 
5161e007181SXue Chaojing 	lro_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
5171e007181SXue Chaojing 	lro_cfg.lro_ipv4_en = ipv4_en;
5181e007181SXue Chaojing 	lro_cfg.lro_ipv6_en = ipv6_en;
5191e007181SXue Chaojing 	lro_cfg.lro_max_wqe_num = max_wqe_num;
5201e007181SXue Chaojing 
5211e007181SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO,
5221e007181SXue Chaojing 				 &lro_cfg, sizeof(lro_cfg),
5231e007181SXue Chaojing 				 &lro_cfg, &out_size);
5241e007181SXue Chaojing 	if (err || !out_size || lro_cfg.status) {
5251e007181SXue Chaojing 		dev_err(&pdev->dev,
52690f86b8aSLuo bin 			"Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n",
52790f86b8aSLuo bin 			err, lro_cfg.status, out_size);
52890f86b8aSLuo bin 		return -EIO;
5291e007181SXue Chaojing 	}
5301e007181SXue Chaojing 
5311e007181SXue Chaojing 	return 0;
5321e007181SXue Chaojing }
5331e007181SXue Chaojing 
hinic_set_rx_lro_timer(struct hinic_dev * nic_dev,u32 timer_value)5341e007181SXue Chaojing static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
5351e007181SXue Chaojing {
5361e007181SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
5371e007181SXue Chaojing 	struct hinic_lro_timer lro_timer = { 0 };
5381e007181SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
5391e007181SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
5401e007181SXue Chaojing 	u16 out_size = sizeof(lro_timer);
5411e007181SXue Chaojing 	int err;
5421e007181SXue Chaojing 
5431e007181SXue Chaojing 	lro_timer.status = 0;
5441e007181SXue Chaojing 	lro_timer.type = 0;
5451e007181SXue Chaojing 	lro_timer.enable = 1;
5461e007181SXue Chaojing 	lro_timer.timer = timer_value;
5471e007181SXue Chaojing 
5481e007181SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO_TIMER,
5491e007181SXue Chaojing 				 &lro_timer, sizeof(lro_timer),
5501e007181SXue Chaojing 				 &lro_timer, &out_size);
5511e007181SXue Chaojing 	if (lro_timer.status == 0xFF) {
5521e007181SXue Chaojing 		/* For this case, we think status (0xFF) is OK */
5531e007181SXue Chaojing 		lro_timer.status = 0;
5541e007181SXue Chaojing 		dev_dbg(&pdev->dev,
5551e007181SXue Chaojing 			"Set lro timer not supported by the current FW version, it will be 1ms default\n");
5561e007181SXue Chaojing 	}
5571e007181SXue Chaojing 
5581e007181SXue Chaojing 	if (err || !out_size || lro_timer.status) {
5591e007181SXue Chaojing 		dev_err(&pdev->dev,
56090f86b8aSLuo bin 			"Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n",
56190f86b8aSLuo bin 			err, lro_timer.status, out_size);
5621e007181SXue Chaojing 
56390f86b8aSLuo bin 		return -EIO;
5641e007181SXue Chaojing 	}
5651e007181SXue Chaojing 
5661e007181SXue Chaojing 	return 0;
5671e007181SXue Chaojing }
5681e007181SXue Chaojing 
hinic_set_rx_lro_state(struct hinic_dev * nic_dev,u8 lro_en,u32 lro_timer,u32 wqe_num)5691e007181SXue Chaojing int hinic_set_rx_lro_state(struct hinic_dev *nic_dev, u8 lro_en,
5701e007181SXue Chaojing 			   u32 lro_timer, u32 wqe_num)
5711e007181SXue Chaojing {
5721e007181SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
5731e007181SXue Chaojing 	u8 ipv4_en;
5741e007181SXue Chaojing 	u8 ipv6_en;
5751e007181SXue Chaojing 	int err;
5761e007181SXue Chaojing 
5771e007181SXue Chaojing 	if (!hwdev)
5781e007181SXue Chaojing 		return -EINVAL;
5791e007181SXue Chaojing 
5801e007181SXue Chaojing 	ipv4_en = lro_en ? 1 : 0;
5811e007181SXue Chaojing 	ipv6_en = lro_en ? 1 : 0;
5821e007181SXue Chaojing 
5831e007181SXue Chaojing 	err = hinic_set_rx_lro(nic_dev, ipv4_en, ipv6_en, (u8)wqe_num);
5841e007181SXue Chaojing 	if (err)
5851e007181SXue Chaojing 		return err;
5861e007181SXue Chaojing 
5877dd29ee1SLuo bin 	if (HINIC_IS_VF(nic_dev->hwdev->hwif))
5887dd29ee1SLuo bin 		return 0;
5897dd29ee1SLuo bin 
5901e007181SXue Chaojing 	err = hinic_set_rx_lro_timer(nic_dev, lro_timer);
5911e007181SXue Chaojing 	if (err)
5921e007181SXue Chaojing 		return err;
5931e007181SXue Chaojing 
5941e007181SXue Chaojing 	return 0;
5951e007181SXue Chaojing }
596421e9526SXue Chaojing 
hinic_rss_set_indir_tbl(struct hinic_dev * nic_dev,u32 tmpl_idx,const u32 * indir_table)597421e9526SXue Chaojing int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
598421e9526SXue Chaojing 			    const u32 *indir_table)
599421e9526SXue Chaojing {
600421e9526SXue Chaojing 	struct hinic_rss_indirect_tbl *indir_tbl;
601421e9526SXue Chaojing 	struct hinic_func_to_io *func_to_io;
602421e9526SXue Chaojing 	struct hinic_cmdq_buf cmd_buf;
603421e9526SXue Chaojing 	struct hinic_hwdev *hwdev;
604421e9526SXue Chaojing 	struct hinic_hwif *hwif;
605421e9526SXue Chaojing 	struct pci_dev *pdev;
606421e9526SXue Chaojing 	u32 indir_size;
607421e9526SXue Chaojing 	u64 out_param;
608421e9526SXue Chaojing 	int err, i;
609421e9526SXue Chaojing 	u32 *temp;
610421e9526SXue Chaojing 
611421e9526SXue Chaojing 	hwdev = nic_dev->hwdev;
612421e9526SXue Chaojing 	func_to_io = &hwdev->func_to_io;
613421e9526SXue Chaojing 	hwif = hwdev->hwif;
614421e9526SXue Chaojing 	pdev = hwif->pdev;
615421e9526SXue Chaojing 
616421e9526SXue Chaojing 	err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
617421e9526SXue Chaojing 	if (err) {
618421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");
619421e9526SXue Chaojing 		return err;
620421e9526SXue Chaojing 	}
621421e9526SXue Chaojing 
622421e9526SXue Chaojing 	cmd_buf.size = sizeof(*indir_tbl);
623421e9526SXue Chaojing 
624421e9526SXue Chaojing 	indir_tbl = cmd_buf.buf;
625421e9526SXue Chaojing 	indir_tbl->group_index = cpu_to_be32(tmpl_idx);
626421e9526SXue Chaojing 
627421e9526SXue Chaojing 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
628421e9526SXue Chaojing 		indir_tbl->entry[i] = indir_table[i];
629421e9526SXue Chaojing 
630421e9526SXue Chaojing 		if (0x3 == (i & 0x3)) {
631421e9526SXue Chaojing 			temp = (u32 *)&indir_tbl->entry[i - 3];
632421e9526SXue Chaojing 			*temp = cpu_to_be32(*temp);
633421e9526SXue Chaojing 		}
634421e9526SXue Chaojing 	}
635421e9526SXue Chaojing 
636421e9526SXue Chaojing 	/* cfg the rss indirect table by command queue */
637421e9526SXue Chaojing 	indir_size = HINIC_RSS_INDIR_SIZE / 2;
638421e9526SXue Chaojing 	indir_tbl->offset = 0;
639421e9526SXue Chaojing 	indir_tbl->size = cpu_to_be32(indir_size);
640421e9526SXue Chaojing 
641421e9526SXue Chaojing 	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
642421e9526SXue Chaojing 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
643421e9526SXue Chaojing 				     &cmd_buf, &out_param);
644421e9526SXue Chaojing 	if (err || out_param != 0) {
645421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to set rss indir table\n");
646421e9526SXue Chaojing 		err = -EFAULT;
647421e9526SXue Chaojing 		goto free_buf;
648421e9526SXue Chaojing 	}
649421e9526SXue Chaojing 
650421e9526SXue Chaojing 	indir_tbl->offset = cpu_to_be32(indir_size);
651421e9526SXue Chaojing 	indir_tbl->size = cpu_to_be32(indir_size);
652421e9526SXue Chaojing 	memcpy(&indir_tbl->entry[0], &indir_tbl->entry[indir_size], indir_size);
653421e9526SXue Chaojing 
654421e9526SXue Chaojing 	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
655421e9526SXue Chaojing 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
656421e9526SXue Chaojing 				     &cmd_buf, &out_param);
657421e9526SXue Chaojing 	if (err || out_param != 0) {
658421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to set rss indir table\n");
659421e9526SXue Chaojing 		err = -EFAULT;
660421e9526SXue Chaojing 	}
661421e9526SXue Chaojing 
662421e9526SXue Chaojing free_buf:
663421e9526SXue Chaojing 	hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
664421e9526SXue Chaojing 
665421e9526SXue Chaojing 	return err;
666421e9526SXue Chaojing }
667421e9526SXue Chaojing 
hinic_rss_get_indir_tbl(struct hinic_dev * nic_dev,u32 tmpl_idx,u32 * indir_table)6684fdc51bbSXue Chaojing int hinic_rss_get_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
6694fdc51bbSXue Chaojing 			    u32 *indir_table)
6704fdc51bbSXue Chaojing {
6714fdc51bbSXue Chaojing 	struct hinic_rss_indir_table rss_cfg = { 0 };
6724fdc51bbSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
6734fdc51bbSXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
6744fdc51bbSXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
6754fdc51bbSXue Chaojing 	u16 out_size = sizeof(rss_cfg);
6764fdc51bbSXue Chaojing 	int err = 0, i;
6774fdc51bbSXue Chaojing 
6784fdc51bbSXue Chaojing 	rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
6794fdc51bbSXue Chaojing 	rss_cfg.template_id = tmpl_idx;
6804fdc51bbSXue Chaojing 
6814fdc51bbSXue Chaojing 	err = hinic_port_msg_cmd(hwdev,
6824fdc51bbSXue Chaojing 				 HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
6834fdc51bbSXue Chaojing 				 &rss_cfg, sizeof(rss_cfg), &rss_cfg,
6844fdc51bbSXue Chaojing 				 &out_size);
6854fdc51bbSXue Chaojing 	if (err || !out_size || rss_cfg.status) {
6864fdc51bbSXue Chaojing 		dev_err(&pdev->dev, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x\n",
6874fdc51bbSXue Chaojing 			err, rss_cfg.status, out_size);
6884fdc51bbSXue Chaojing 		return -EINVAL;
6894fdc51bbSXue Chaojing 	}
6904fdc51bbSXue Chaojing 
6914fdc51bbSXue Chaojing 	hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
6924fdc51bbSXue Chaojing 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
6934fdc51bbSXue Chaojing 		indir_table[i] = rss_cfg.indir[i];
6944fdc51bbSXue Chaojing 
6954fdc51bbSXue Chaojing 	return 0;
6964fdc51bbSXue Chaojing }
6974fdc51bbSXue Chaojing 
hinic_set_rss_type(struct hinic_dev * nic_dev,u32 tmpl_idx,struct hinic_rss_type rss_type)698421e9526SXue Chaojing int hinic_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
699421e9526SXue Chaojing 		       struct hinic_rss_type rss_type)
700421e9526SXue Chaojing {
701421e9526SXue Chaojing 	struct hinic_rss_context_tbl *ctx_tbl;
702421e9526SXue Chaojing 	struct hinic_func_to_io *func_to_io;
703421e9526SXue Chaojing 	struct hinic_cmdq_buf cmd_buf;
704421e9526SXue Chaojing 	struct hinic_hwdev *hwdev;
705421e9526SXue Chaojing 	struct hinic_hwif *hwif;
706421e9526SXue Chaojing 	struct pci_dev *pdev;
707421e9526SXue Chaojing 	u64 out_param;
708421e9526SXue Chaojing 	u32 ctx = 0;
709421e9526SXue Chaojing 	int err;
710421e9526SXue Chaojing 
711421e9526SXue Chaojing 	hwdev = nic_dev->hwdev;
712421e9526SXue Chaojing 	func_to_io = &hwdev->func_to_io;
713421e9526SXue Chaojing 	hwif = hwdev->hwif;
714421e9526SXue Chaojing 	pdev = hwif->pdev;
715421e9526SXue Chaojing 
716421e9526SXue Chaojing 	err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
717421e9526SXue Chaojing 	if (err) {
718421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to allocate cmd buf\n");
719421e9526SXue Chaojing 		return -ENOMEM;
720421e9526SXue Chaojing 	}
721421e9526SXue Chaojing 
722421e9526SXue Chaojing 	ctx |=  HINIC_RSS_TYPE_SET(1, VALID) |
723421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
724421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
725421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
726421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
727421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
728421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
729421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
730421e9526SXue Chaojing 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
731421e9526SXue Chaojing 
732421e9526SXue Chaojing 	cmd_buf.size = sizeof(struct hinic_rss_context_tbl);
733421e9526SXue Chaojing 
734421e9526SXue Chaojing 	ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;
735421e9526SXue Chaojing 	ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
736421e9526SXue Chaojing 	ctx_tbl->offset = 0;
737421e9526SXue Chaojing 	ctx_tbl->size = sizeof(u32);
738421e9526SXue Chaojing 	ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
739421e9526SXue Chaojing 	ctx_tbl->rsvd = 0;
740421e9526SXue Chaojing 	ctx_tbl->ctx = cpu_to_be32(ctx);
741421e9526SXue Chaojing 
742421e9526SXue Chaojing 	/* cfg the rss context table by command queue */
743421e9526SXue Chaojing 	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
744421e9526SXue Chaojing 				     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
745421e9526SXue Chaojing 				     &cmd_buf, &out_param);
746421e9526SXue Chaojing 
747421e9526SXue Chaojing 	hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
748421e9526SXue Chaojing 
749421e9526SXue Chaojing 	if (err || out_param != 0) {
750421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",
751421e9526SXue Chaojing 			err);
752421e9526SXue Chaojing 		return -EFAULT;
753421e9526SXue Chaojing 	}
754421e9526SXue Chaojing 
755421e9526SXue Chaojing 	return 0;
756421e9526SXue Chaojing }
757421e9526SXue Chaojing 
hinic_get_rss_type(struct hinic_dev * nic_dev,u32 tmpl_idx,struct hinic_rss_type * rss_type)7584fdc51bbSXue Chaojing int hinic_get_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
7594fdc51bbSXue Chaojing 		       struct hinic_rss_type *rss_type)
7604fdc51bbSXue Chaojing {
7614fdc51bbSXue Chaojing 	struct hinic_rss_context_table ctx_tbl = { 0 };
7624fdc51bbSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
7637dd29ee1SLuo bin 	u16 out_size = sizeof(ctx_tbl);
764137e4e1aSColin Ian King 	struct hinic_hwif *hwif;
765137e4e1aSColin Ian King 	struct pci_dev *pdev;
7664fdc51bbSXue Chaojing 	int err;
7674fdc51bbSXue Chaojing 
7684fdc51bbSXue Chaojing 	if (!hwdev || !rss_type)
7694fdc51bbSXue Chaojing 		return -EINVAL;
7704fdc51bbSXue Chaojing 
771137e4e1aSColin Ian King 	hwif = hwdev->hwif;
772137e4e1aSColin Ian King 	pdev = hwif->pdev;
773137e4e1aSColin Ian King 
7744fdc51bbSXue Chaojing 	ctx_tbl.func_id = HINIC_HWIF_FUNC_IDX(hwif);
7754fdc51bbSXue Chaojing 	ctx_tbl.template_id = tmpl_idx;
7764fdc51bbSXue Chaojing 
7774fdc51bbSXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
7784fdc51bbSXue Chaojing 				 &ctx_tbl, sizeof(ctx_tbl),
7794fdc51bbSXue Chaojing 				 &ctx_tbl, &out_size);
7804fdc51bbSXue Chaojing 	if (err || !out_size || ctx_tbl.status) {
7814fdc51bbSXue Chaojing 		dev_err(&pdev->dev, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n",
7824fdc51bbSXue Chaojing 			err, ctx_tbl.status, out_size);
7834fdc51bbSXue Chaojing 		return -EINVAL;
7844fdc51bbSXue Chaojing 	}
7854fdc51bbSXue Chaojing 
7864fdc51bbSXue Chaojing 	rss_type->ipv4          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
7874fdc51bbSXue Chaojing 	rss_type->ipv6          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
7884fdc51bbSXue Chaojing 	rss_type->ipv6_ext      = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
7894fdc51bbSXue Chaojing 	rss_type->tcp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
7904fdc51bbSXue Chaojing 	rss_type->tcp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
7914fdc51bbSXue Chaojing 	rss_type->tcp_ipv6_ext  = HINIC_RSS_TYPE_GET(ctx_tbl.context,
7924fdc51bbSXue Chaojing 						     TCP_IPV6_EXT);
7934fdc51bbSXue Chaojing 	rss_type->udp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
7944fdc51bbSXue Chaojing 	rss_type->udp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
7954fdc51bbSXue Chaojing 
7964fdc51bbSXue Chaojing 	return 0;
7974fdc51bbSXue Chaojing }
7984fdc51bbSXue Chaojing 
hinic_rss_set_template_tbl(struct hinic_dev * nic_dev,u32 template_id,const u8 * temp)799421e9526SXue Chaojing int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,
800421e9526SXue Chaojing 			       const u8 *temp)
801421e9526SXue Chaojing {
802421e9526SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
803421e9526SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
804421e9526SXue Chaojing 	struct hinic_rss_key rss_key = { 0 };
805421e9526SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
8067dd29ee1SLuo bin 	u16 out_size = sizeof(rss_key);
807421e9526SXue Chaojing 	int err;
808421e9526SXue Chaojing 
809421e9526SXue Chaojing 	rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
810421e9526SXue Chaojing 	rss_key.template_id = template_id;
811421e9526SXue Chaojing 	memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);
812421e9526SXue Chaojing 
813421e9526SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
814421e9526SXue Chaojing 				 &rss_key, sizeof(rss_key),
815421e9526SXue Chaojing 				 &rss_key, &out_size);
816421e9526SXue Chaojing 	if (err || !out_size || rss_key.status) {
817421e9526SXue Chaojing 		dev_err(&pdev->dev,
818421e9526SXue Chaojing 			"Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",
819421e9526SXue Chaojing 			err, rss_key.status, out_size);
820421e9526SXue Chaojing 		return -EINVAL;
821421e9526SXue Chaojing 	}
822421e9526SXue Chaojing 
823421e9526SXue Chaojing 	return 0;
824421e9526SXue Chaojing }
825421e9526SXue Chaojing 
hinic_rss_get_template_tbl(struct hinic_dev * nic_dev,u32 tmpl_idx,u8 * temp)8264fdc51bbSXue Chaojing int hinic_rss_get_template_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
8274fdc51bbSXue Chaojing 			       u8 *temp)
8284fdc51bbSXue Chaojing {
8294fdc51bbSXue Chaojing 	struct hinic_rss_template_key temp_key = { 0 };
8304fdc51bbSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
8317dd29ee1SLuo bin 	u16 out_size = sizeof(temp_key);
832137e4e1aSColin Ian King 	struct hinic_hwif *hwif;
833137e4e1aSColin Ian King 	struct pci_dev *pdev;
8344fdc51bbSXue Chaojing 	int err;
8354fdc51bbSXue Chaojing 
8364fdc51bbSXue Chaojing 	if (!hwdev || !temp)
8374fdc51bbSXue Chaojing 		return -EINVAL;
8384fdc51bbSXue Chaojing 
839137e4e1aSColin Ian King 	hwif = hwdev->hwif;
840137e4e1aSColin Ian King 	pdev = hwif->pdev;
841137e4e1aSColin Ian King 
8424fdc51bbSXue Chaojing 	temp_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
8434fdc51bbSXue Chaojing 	temp_key.template_id = tmpl_idx;
8444fdc51bbSXue Chaojing 
8454fdc51bbSXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
8464fdc51bbSXue Chaojing 				 &temp_key, sizeof(temp_key),
8474fdc51bbSXue Chaojing 				 &temp_key, &out_size);
8484fdc51bbSXue Chaojing 	if (err || !out_size || temp_key.status) {
8494fdc51bbSXue Chaojing 		dev_err(&pdev->dev, "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x\n",
8504fdc51bbSXue Chaojing 			err, temp_key.status, out_size);
8514fdc51bbSXue Chaojing 		return -EINVAL;
8524fdc51bbSXue Chaojing 	}
8534fdc51bbSXue Chaojing 
8544fdc51bbSXue Chaojing 	memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
8554fdc51bbSXue Chaojing 
8564fdc51bbSXue Chaojing 	return 0;
8574fdc51bbSXue Chaojing }
8584fdc51bbSXue Chaojing 
hinic_rss_set_hash_engine(struct hinic_dev * nic_dev,u8 template_id,u8 type)859421e9526SXue Chaojing int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,
860421e9526SXue Chaojing 			      u8 type)
861421e9526SXue Chaojing {
862421e9526SXue Chaojing 	struct hinic_rss_engine_type rss_engine = { 0 };
863421e9526SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
864421e9526SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
865421e9526SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
8667dd29ee1SLuo bin 	u16 out_size = sizeof(rss_engine);
867421e9526SXue Chaojing 	int err;
868421e9526SXue Chaojing 
869421e9526SXue Chaojing 	rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);
870421e9526SXue Chaojing 	rss_engine.hash_engine = type;
871421e9526SXue Chaojing 	rss_engine.template_id = template_id;
872421e9526SXue Chaojing 
873421e9526SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
874421e9526SXue Chaojing 				 &rss_engine, sizeof(rss_engine),
875421e9526SXue Chaojing 				 &rss_engine, &out_size);
876421e9526SXue Chaojing 	if (err || !out_size || rss_engine.status) {
877421e9526SXue Chaojing 		dev_err(&pdev->dev,
878421e9526SXue Chaojing 			"Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
879421e9526SXue Chaojing 			err, rss_engine.status, out_size);
880421e9526SXue Chaojing 		return -EINVAL;
881421e9526SXue Chaojing 	}
882421e9526SXue Chaojing 
883421e9526SXue Chaojing 	return 0;
884421e9526SXue Chaojing }
885421e9526SXue Chaojing 
hinic_rss_get_hash_engine(struct hinic_dev * nic_dev,u8 tmpl_idx,u8 * type)8864fdc51bbSXue Chaojing int hinic_rss_get_hash_engine(struct hinic_dev *nic_dev, u8 tmpl_idx, u8 *type)
8874fdc51bbSXue Chaojing {
8884fdc51bbSXue Chaojing 	struct hinic_rss_engine_type hash_type = { 0 };
8894fdc51bbSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
8907dd29ee1SLuo bin 	u16 out_size = sizeof(hash_type);
891137e4e1aSColin Ian King 	struct hinic_hwif *hwif;
892137e4e1aSColin Ian King 	struct pci_dev *pdev;
8934fdc51bbSXue Chaojing 	int err;
8944fdc51bbSXue Chaojing 
8954fdc51bbSXue Chaojing 	if (!hwdev || !type)
8964fdc51bbSXue Chaojing 		return -EINVAL;
8974fdc51bbSXue Chaojing 
898137e4e1aSColin Ian King 	hwif = hwdev->hwif;
899137e4e1aSColin Ian King 	pdev = hwif->pdev;
900137e4e1aSColin Ian King 
9014fdc51bbSXue Chaojing 	hash_type.func_id = HINIC_HWIF_FUNC_IDX(hwif);
9024fdc51bbSXue Chaojing 	hash_type.template_id = tmpl_idx;
9034fdc51bbSXue Chaojing 
9044fdc51bbSXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,
9054fdc51bbSXue Chaojing 				 &hash_type, sizeof(hash_type),
9064fdc51bbSXue Chaojing 				 &hash_type, &out_size);
9074fdc51bbSXue Chaojing 	if (err || !out_size || hash_type.status) {
9084fdc51bbSXue Chaojing 		dev_err(&pdev->dev, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
9094fdc51bbSXue Chaojing 			err, hash_type.status, out_size);
9104fdc51bbSXue Chaojing 		return -EINVAL;
9114fdc51bbSXue Chaojing 	}
9124fdc51bbSXue Chaojing 
9134fdc51bbSXue Chaojing 	*type = hash_type.hash_engine;
9144fdc51bbSXue Chaojing 	return 0;
9154fdc51bbSXue Chaojing }
9164fdc51bbSXue Chaojing 
hinic_rss_cfg(struct hinic_dev * nic_dev,u8 rss_en,u8 template_id)917421e9526SXue Chaojing int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)
918421e9526SXue Chaojing {
919421e9526SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
920421e9526SXue Chaojing 	struct hinic_rss_config rss_cfg = { 0 };
921421e9526SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
922421e9526SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
9237dd29ee1SLuo bin 	u16 out_size = sizeof(rss_cfg);
924421e9526SXue Chaojing 	int err;
925421e9526SXue Chaojing 
926421e9526SXue Chaojing 	rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
927421e9526SXue Chaojing 	rss_cfg.rss_en = rss_en;
928421e9526SXue Chaojing 	rss_cfg.template_id = template_id;
929421e9526SXue Chaojing 	rss_cfg.rq_priority_number = 0;
930421e9526SXue Chaojing 
931421e9526SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_CFG,
932421e9526SXue Chaojing 				 &rss_cfg, sizeof(rss_cfg),
933421e9526SXue Chaojing 				 &rss_cfg, &out_size);
934421e9526SXue Chaojing 	if (err || !out_size || rss_cfg.status) {
935421e9526SXue Chaojing 		dev_err(&pdev->dev,
936421e9526SXue Chaojing 			"Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",
937421e9526SXue Chaojing 			err, rss_cfg.status, out_size);
938421e9526SXue Chaojing 		return -EINVAL;
939421e9526SXue Chaojing 	}
940421e9526SXue Chaojing 
941421e9526SXue Chaojing 	return 0;
942421e9526SXue Chaojing }
943421e9526SXue Chaojing 
hinic_rss_template_alloc(struct hinic_dev * nic_dev,u8 * tmpl_idx)944421e9526SXue Chaojing int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)
945421e9526SXue Chaojing {
946421e9526SXue Chaojing 	struct hinic_rss_template_mgmt template_mgmt = { 0 };
947421e9526SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
948421e9526SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
9497dd29ee1SLuo bin 	u16 out_size = sizeof(template_mgmt);
950421e9526SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
951421e9526SXue Chaojing 	int err;
952421e9526SXue Chaojing 
953421e9526SXue Chaojing 	template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
954421e9526SXue Chaojing 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
955421e9526SXue Chaojing 
956421e9526SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
957421e9526SXue Chaojing 				 &template_mgmt, sizeof(template_mgmt),
958421e9526SXue Chaojing 				 &template_mgmt, &out_size);
959421e9526SXue Chaojing 	if (err || !out_size || template_mgmt.status) {
960421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",
961421e9526SXue Chaojing 			err, template_mgmt.status, out_size);
962421e9526SXue Chaojing 		return -EINVAL;
963421e9526SXue Chaojing 	}
964421e9526SXue Chaojing 
965421e9526SXue Chaojing 	*tmpl_idx = template_mgmt.template_id;
966421e9526SXue Chaojing 
967421e9526SXue Chaojing 	return 0;
968421e9526SXue Chaojing }
969421e9526SXue Chaojing 
hinic_rss_template_free(struct hinic_dev * nic_dev,u8 tmpl_idx)970421e9526SXue Chaojing int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)
971421e9526SXue Chaojing {
972421e9526SXue Chaojing 	struct hinic_rss_template_mgmt template_mgmt = { 0 };
973421e9526SXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
974421e9526SXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
9757dd29ee1SLuo bin 	u16 out_size = sizeof(template_mgmt);
976421e9526SXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
977421e9526SXue Chaojing 	int err;
978421e9526SXue Chaojing 
979421e9526SXue Chaojing 	template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
980421e9526SXue Chaojing 	template_mgmt.template_id = tmpl_idx;
981421e9526SXue Chaojing 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
982421e9526SXue Chaojing 
983421e9526SXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
984421e9526SXue Chaojing 				 &template_mgmt, sizeof(template_mgmt),
985421e9526SXue Chaojing 				 &template_mgmt, &out_size);
986421e9526SXue Chaojing 	if (err || !out_size || template_mgmt.status) {
987421e9526SXue Chaojing 		dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",
988421e9526SXue Chaojing 			err, template_mgmt.status, out_size);
989421e9526SXue Chaojing 		return -EINVAL;
990421e9526SXue Chaojing 	}
991421e9526SXue Chaojing 
992421e9526SXue Chaojing 	return 0;
993421e9526SXue Chaojing }
994e54fbbdfSXue Chaojing 
hinic_get_vport_stats(struct hinic_dev * nic_dev,struct hinic_vport_stats * stats)995e54fbbdfSXue Chaojing int hinic_get_vport_stats(struct hinic_dev *nic_dev,
996e54fbbdfSXue Chaojing 			  struct hinic_vport_stats *stats)
997e54fbbdfSXue Chaojing {
998e54fbbdfSXue Chaojing 	struct hinic_cmd_vport_stats vport_stats = { 0 };
999e54fbbdfSXue Chaojing 	struct hinic_port_stats_info stats_info = { 0 };
1000e54fbbdfSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
1001e54fbbdfSXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
1002e54fbbdfSXue Chaojing 	u16 out_size = sizeof(vport_stats);
1003e54fbbdfSXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
1004e54fbbdfSXue Chaojing 	int err;
1005e54fbbdfSXue Chaojing 
1006e54fbbdfSXue Chaojing 	stats_info.stats_version = HINIC_PORT_STATS_VERSION;
1007e54fbbdfSXue Chaojing 	stats_info.func_id = HINIC_HWIF_FUNC_IDX(hwif);
1008e54fbbdfSXue Chaojing 	stats_info.stats_size = sizeof(vport_stats);
1009e54fbbdfSXue Chaojing 
1010e54fbbdfSXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
1011e54fbbdfSXue Chaojing 				 &stats_info, sizeof(stats_info),
1012e54fbbdfSXue Chaojing 				 &vport_stats, &out_size);
1013e54fbbdfSXue Chaojing 	if (err || !out_size || vport_stats.status) {
1014e54fbbdfSXue Chaojing 		dev_err(&pdev->dev,
1015e54fbbdfSXue Chaojing 			"Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1016e54fbbdfSXue Chaojing 			err, vport_stats.status, out_size);
1017e54fbbdfSXue Chaojing 		return -EFAULT;
1018e54fbbdfSXue Chaojing 	}
1019e54fbbdfSXue Chaojing 
1020e54fbbdfSXue Chaojing 	memcpy(stats, &vport_stats.stats, sizeof(*stats));
1021e54fbbdfSXue Chaojing 	return 0;
1022e54fbbdfSXue Chaojing }
1023e54fbbdfSXue Chaojing 
hinic_get_phy_port_stats(struct hinic_dev * nic_dev,struct hinic_phy_port_stats * stats)1024e54fbbdfSXue Chaojing int hinic_get_phy_port_stats(struct hinic_dev *nic_dev,
1025e54fbbdfSXue Chaojing 			     struct hinic_phy_port_stats *stats)
1026e54fbbdfSXue Chaojing {
1027e54fbbdfSXue Chaojing 	struct hinic_port_stats_info stats_info = { 0 };
1028e54fbbdfSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
1029e54fbbdfSXue Chaojing 	struct hinic_hwif *hwif = hwdev->hwif;
1030e54fbbdfSXue Chaojing 	struct hinic_port_stats *port_stats;
1031e54fbbdfSXue Chaojing 	u16 out_size = sizeof(*port_stats);
1032e54fbbdfSXue Chaojing 	struct pci_dev *pdev = hwif->pdev;
1033e54fbbdfSXue Chaojing 	int err;
1034e54fbbdfSXue Chaojing 
1035e54fbbdfSXue Chaojing 	port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
1036e54fbbdfSXue Chaojing 	if (!port_stats)
1037e54fbbdfSXue Chaojing 		return -ENOMEM;
1038e54fbbdfSXue Chaojing 
1039e54fbbdfSXue Chaojing 	stats_info.stats_version = HINIC_PORT_STATS_VERSION;
1040e54fbbdfSXue Chaojing 	stats_info.stats_size = sizeof(*port_stats);
1041e54fbbdfSXue Chaojing 
1042e54fbbdfSXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
1043e54fbbdfSXue Chaojing 				 &stats_info, sizeof(stats_info),
1044e54fbbdfSXue Chaojing 				 port_stats, &out_size);
1045e54fbbdfSXue Chaojing 	if (err || !out_size || port_stats->status) {
1046e54fbbdfSXue Chaojing 		dev_err(&pdev->dev,
1047e54fbbdfSXue Chaojing 			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1048e54fbbdfSXue Chaojing 			err, port_stats->status, out_size);
1049e54fbbdfSXue Chaojing 		err = -EINVAL;
1050e54fbbdfSXue Chaojing 		goto out;
1051e54fbbdfSXue Chaojing 	}
1052e54fbbdfSXue Chaojing 
1053e54fbbdfSXue Chaojing 	memcpy(stats, &port_stats->stats, sizeof(*stats));
1054e54fbbdfSXue Chaojing 
1055e54fbbdfSXue Chaojing out:
1056e54fbbdfSXue Chaojing 	kfree(port_stats);
1057e54fbbdfSXue Chaojing 
1058e54fbbdfSXue Chaojing 	return err;
1059e54fbbdfSXue Chaojing }
106061a582beSXue Chaojing 
hinic_get_mgmt_version(struct hinic_dev * nic_dev,u8 * mgmt_ver)106161a582beSXue Chaojing int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver)
106261a582beSXue Chaojing {
106361a582beSXue Chaojing 	struct hinic_hwdev *hwdev = nic_dev->hwdev;
106461a582beSXue Chaojing 	struct hinic_version_info up_ver = {0};
10657dd29ee1SLuo bin 	u16 out_size = sizeof(up_ver);
106661a582beSXue Chaojing 	struct hinic_hwif *hwif;
106761a582beSXue Chaojing 	struct pci_dev *pdev;
106861a582beSXue Chaojing 	int err;
106961a582beSXue Chaojing 
107061a582beSXue Chaojing 	if (!hwdev)
107161a582beSXue Chaojing 		return -EINVAL;
107261a582beSXue Chaojing 
107361a582beSXue Chaojing 	hwif = hwdev->hwif;
107461a582beSXue Chaojing 	pdev = hwif->pdev;
107561a582beSXue Chaojing 
107661a582beSXue Chaojing 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION,
107761a582beSXue Chaojing 				 &up_ver, sizeof(up_ver), &up_ver,
107861a582beSXue Chaojing 				 &out_size);
107961a582beSXue Chaojing 	if (err || !out_size || up_ver.status) {
108061a582beSXue Chaojing 		dev_err(&pdev->dev,
108161a582beSXue Chaojing 			"Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x\n",
108261a582beSXue Chaojing 			err, up_ver.status, out_size);
108361a582beSXue Chaojing 		return -EINVAL;
108461a582beSXue Chaojing 	}
108561a582beSXue Chaojing 
108661a582beSXue Chaojing 	snprintf(mgmt_ver, HINIC_MGMT_VERSION_MAX_LEN, "%s", up_ver.ver);
108761a582beSXue Chaojing 
108861a582beSXue Chaojing 	return 0;
108961a582beSXue Chaojing }
109001f2b3daSLuo bin 
hinic_get_link_mode(struct hinic_hwdev * hwdev,struct hinic_link_mode_cmd * link_mode)109101f2b3daSLuo bin int hinic_get_link_mode(struct hinic_hwdev *hwdev,
109201f2b3daSLuo bin 			struct hinic_link_mode_cmd *link_mode)
109301f2b3daSLuo bin {
109401f2b3daSLuo bin 	u16 out_size;
109501f2b3daSLuo bin 	int err;
109601f2b3daSLuo bin 
109701f2b3daSLuo bin 	if (!hwdev || !link_mode)
109801f2b3daSLuo bin 		return -EINVAL;
109901f2b3daSLuo bin 
1100ea256222SLuo bin 	link_mode->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
110101f2b3daSLuo bin 	out_size = sizeof(*link_mode);
110201f2b3daSLuo bin 
110301f2b3daSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
110401f2b3daSLuo bin 				 link_mode, sizeof(*link_mode),
110501f2b3daSLuo bin 				 link_mode, &out_size);
110601f2b3daSLuo bin 	if (err || !out_size || link_mode->status) {
110701f2b3daSLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
110801f2b3daSLuo bin 			"Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x\n",
110901f2b3daSLuo bin 			err, link_mode->status, out_size);
111001f2b3daSLuo bin 		return -EIO;
111101f2b3daSLuo bin 	}
111201f2b3daSLuo bin 
111301f2b3daSLuo bin 	return 0;
111401f2b3daSLuo bin }
111501f2b3daSLuo bin 
hinic_set_autoneg(struct hinic_hwdev * hwdev,bool enable)111601f2b3daSLuo bin int hinic_set_autoneg(struct hinic_hwdev *hwdev, bool enable)
111701f2b3daSLuo bin {
111801f2b3daSLuo bin 	struct hinic_set_autoneg_cmd autoneg = {0};
111901f2b3daSLuo bin 	u16 out_size = sizeof(autoneg);
112001f2b3daSLuo bin 	int err;
112101f2b3daSLuo bin 
112201f2b3daSLuo bin 	if (!hwdev)
112301f2b3daSLuo bin 		return -EINVAL;
112401f2b3daSLuo bin 
112501f2b3daSLuo bin 	autoneg.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
112601f2b3daSLuo bin 	autoneg.enable = enable;
112701f2b3daSLuo bin 
112801f2b3daSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_AUTONEG,
112901f2b3daSLuo bin 				 &autoneg, sizeof(autoneg),
113001f2b3daSLuo bin 				 &autoneg, &out_size);
113101f2b3daSLuo bin 	if (err || !out_size || autoneg.status) {
113201f2b3daSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to %s autoneg, err: %d, status: 0x%x, out size: 0x%x\n",
113301f2b3daSLuo bin 			enable ? "enable" : "disable", err, autoneg.status,
113401f2b3daSLuo bin 			out_size);
113501f2b3daSLuo bin 		return -EIO;
113601f2b3daSLuo bin 	}
113701f2b3daSLuo bin 
113801f2b3daSLuo bin 	return 0;
113901f2b3daSLuo bin }
114001f2b3daSLuo bin 
hinic_set_speed(struct hinic_hwdev * hwdev,enum nic_speed_level speed)114101f2b3daSLuo bin int hinic_set_speed(struct hinic_hwdev *hwdev, enum nic_speed_level speed)
114201f2b3daSLuo bin {
114301f2b3daSLuo bin 	struct hinic_speed_cmd speed_info = {0};
114401f2b3daSLuo bin 	u16 out_size = sizeof(speed_info);
114501f2b3daSLuo bin 	int err;
114601f2b3daSLuo bin 
114701f2b3daSLuo bin 	if (!hwdev)
114801f2b3daSLuo bin 		return -EINVAL;
114901f2b3daSLuo bin 
115001f2b3daSLuo bin 	speed_info.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
115101f2b3daSLuo bin 	speed_info.speed = speed;
115201f2b3daSLuo bin 
115301f2b3daSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_SPEED,
115401f2b3daSLuo bin 				 &speed_info, sizeof(speed_info),
115501f2b3daSLuo bin 				 &speed_info, &out_size);
115601f2b3daSLuo bin 	if (err || !out_size || speed_info.status) {
115701f2b3daSLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
115801f2b3daSLuo bin 			"Failed to set speed, err: %d, status: 0x%x, out size: 0x%x\n",
115901f2b3daSLuo bin 			err, speed_info.status, out_size);
116001f2b3daSLuo bin 		return -EIO;
116101f2b3daSLuo bin 	}
116201f2b3daSLuo bin 
116301f2b3daSLuo bin 	return 0;
116401f2b3daSLuo bin }
116501f2b3daSLuo bin 
hinic_set_link_settings(struct hinic_hwdev * hwdev,struct hinic_link_ksettings_info * info)116601f2b3daSLuo bin int hinic_set_link_settings(struct hinic_hwdev *hwdev,
116701f2b3daSLuo bin 			    struct hinic_link_ksettings_info *info)
116801f2b3daSLuo bin {
116901f2b3daSLuo bin 	u16 out_size = sizeof(*info);
117001f2b3daSLuo bin 	int err;
117101f2b3daSLuo bin 
117201f2b3daSLuo bin 	err = hinic_hilink_msg_cmd(hwdev, HINIC_HILINK_CMD_SET_LINK_SETTINGS,
117301f2b3daSLuo bin 				   info, sizeof(*info), info, &out_size);
117401f2b3daSLuo bin 	if ((info->status != HINIC_MGMT_CMD_UNSUPPORTED &&
117501f2b3daSLuo bin 	     info->status) || err || !out_size) {
117601f2b3daSLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
117701f2b3daSLuo bin 			"Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n",
117801f2b3daSLuo bin 			err, info->status, out_size);
117901f2b3daSLuo bin 		return -EFAULT;
118001f2b3daSLuo bin 	}
118101f2b3daSLuo bin 
118201f2b3daSLuo bin 	return info->status;
118301f2b3daSLuo bin }
118401f2b3daSLuo bin 
hinic_get_hw_pause_info(struct hinic_hwdev * hwdev,struct hinic_pause_config * pause_info)118501f2b3daSLuo bin int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,
118601f2b3daSLuo bin 			    struct hinic_pause_config *pause_info)
118701f2b3daSLuo bin {
118801f2b3daSLuo bin 	u16 out_size = sizeof(*pause_info);
118901f2b3daSLuo bin 	int err;
119001f2b3daSLuo bin 
1191ea256222SLuo bin 	pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1192ea256222SLuo bin 
119301f2b3daSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
119401f2b3daSLuo bin 				 pause_info, sizeof(*pause_info),
119501f2b3daSLuo bin 				 pause_info, &out_size);
119601f2b3daSLuo bin 	if (err || !out_size || pause_info->status) {
119701f2b3daSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n",
119801f2b3daSLuo bin 			err, pause_info->status, out_size);
119901f2b3daSLuo bin 		return -EIO;
120001f2b3daSLuo bin 	}
120101f2b3daSLuo bin 
120201f2b3daSLuo bin 	return 0;
120301f2b3daSLuo bin }
120401f2b3daSLuo bin 
hinic_set_hw_pause_info(struct hinic_hwdev * hwdev,struct hinic_pause_config * pause_info)120501f2b3daSLuo bin int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,
120601f2b3daSLuo bin 			    struct hinic_pause_config *pause_info)
120701f2b3daSLuo bin {
120801f2b3daSLuo bin 	u16 out_size = sizeof(*pause_info);
120901f2b3daSLuo bin 	int err;
121001f2b3daSLuo bin 
1211ea256222SLuo bin 	pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1212ea256222SLuo bin 
121301f2b3daSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
121401f2b3daSLuo bin 				 pause_info, sizeof(*pause_info),
121501f2b3daSLuo bin 				 pause_info, &out_size);
121601f2b3daSLuo bin 	if (err || !out_size || pause_info->status) {
121701f2b3daSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x\n",
121801f2b3daSLuo bin 			err, pause_info->status, out_size);
121901f2b3daSLuo bin 		return -EIO;
122001f2b3daSLuo bin 	}
122101f2b3daSLuo bin 
122201f2b3daSLuo bin 	return 0;
122301f2b3daSLuo bin }
1224ea256222SLuo bin 
hinic_dcb_set_pfc(struct hinic_hwdev * hwdev,u8 pfc_en,u8 pfc_bitmap)1225ea256222SLuo bin int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap)
1226ea256222SLuo bin {
1227ea256222SLuo bin 	struct hinic_nic_cfg *nic_cfg = &hwdev->func_to_io.nic_cfg;
1228ea256222SLuo bin 	struct hinic_set_pfc pfc = {0};
1229ea256222SLuo bin 	u16 out_size = sizeof(pfc);
1230ea256222SLuo bin 	int err;
1231ea256222SLuo bin 
1232ea256222SLuo bin 	if (HINIC_IS_VF(hwdev->hwif))
1233ea256222SLuo bin 		return 0;
1234ea256222SLuo bin 
1235ea256222SLuo bin 	mutex_lock(&nic_cfg->cfg_mutex);
1236ea256222SLuo bin 
1237ea256222SLuo bin 	pfc.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
1238ea256222SLuo bin 	pfc.pfc_bitmap = pfc_bitmap;
1239ea256222SLuo bin 	pfc.pfc_en = pfc_en;
1240ea256222SLuo bin 
1241ea256222SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PFC,
1242ea256222SLuo bin 				 &pfc, sizeof(pfc), &pfc, &out_size);
1243ea256222SLuo bin 	if (err || pfc.status || !out_size) {
1244ea256222SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to %s pfc, err: %d, status: 0x%x, out size: 0x%x\n",
1245ea256222SLuo bin 			pfc_en ? "enable" : "disable", err, pfc.status,
1246ea256222SLuo bin 			out_size);
1247ea256222SLuo bin 		mutex_unlock(&nic_cfg->cfg_mutex);
1248ea256222SLuo bin 		return -EIO;
1249ea256222SLuo bin 	}
1250ea256222SLuo bin 
1251ea256222SLuo bin 	/* pause settings is opposite from pfc */
1252ea256222SLuo bin 	nic_cfg->rx_pause = pfc_en ? 0 : 1;
1253ea256222SLuo bin 	nic_cfg->tx_pause = pfc_en ? 0 : 1;
1254ea256222SLuo bin 
1255ea256222SLuo bin 	mutex_unlock(&nic_cfg->cfg_mutex);
1256ea256222SLuo bin 
1257ea256222SLuo bin 	return 0;
1258ea256222SLuo bin }
12594aa218a4SLuo bin 
hinic_set_loopback_mode(struct hinic_hwdev * hwdev,u32 mode,u32 enable)12604aa218a4SLuo bin int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable)
12614aa218a4SLuo bin {
12624aa218a4SLuo bin 	struct hinic_port_loopback lb = {0};
12634aa218a4SLuo bin 	u16 out_size = sizeof(lb);
12644aa218a4SLuo bin 	int err;
12654aa218a4SLuo bin 
12664aa218a4SLuo bin 	lb.mode = mode;
12674aa218a4SLuo bin 	lb.en = enable;
12684aa218a4SLuo bin 
12694aa218a4SLuo bin 	if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) {
12704aa218a4SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
12714aa218a4SLuo bin 			"Invalid loopback mode %d to set\n", mode);
12724aa218a4SLuo bin 		return -EINVAL;
12734aa218a4SLuo bin 	}
12744aa218a4SLuo bin 
12754aa218a4SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LOOPBACK_MODE,
12764aa218a4SLuo bin 				 &lb, sizeof(lb), &lb, &out_size);
12774aa218a4SLuo bin 	if (err || !out_size || lb.status) {
12784aa218a4SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
12794aa218a4SLuo bin 			"Failed to set loopback mode %d en %d, err: %d, status: 0x%x, out size: 0x%x\n",
12804aa218a4SLuo bin 			mode, enable, err, lb.status, out_size);
12814aa218a4SLuo bin 		return -EIO;
12824aa218a4SLuo bin 	}
12834aa218a4SLuo bin 
12844aa218a4SLuo bin 	return 0;
12854aa218a4SLuo bin }
128607afcc7aSLuo bin 
_set_led_status(struct hinic_hwdev * hwdev,u8 port,enum hinic_led_type type,enum hinic_led_mode mode,u8 reset)128707afcc7aSLuo bin static int _set_led_status(struct hinic_hwdev *hwdev, u8 port,
128807afcc7aSLuo bin 			   enum hinic_led_type type,
128907afcc7aSLuo bin 			   enum hinic_led_mode mode, u8 reset)
129007afcc7aSLuo bin {
129107afcc7aSLuo bin 	struct hinic_led_info led_info = {0};
129207afcc7aSLuo bin 	u16 out_size = sizeof(led_info);
129307afcc7aSLuo bin 	struct hinic_pfhwdev *pfhwdev;
129407afcc7aSLuo bin 	int err;
129507afcc7aSLuo bin 
129607afcc7aSLuo bin 	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
129707afcc7aSLuo bin 
129807afcc7aSLuo bin 	led_info.port = port;
129907afcc7aSLuo bin 	led_info.reset = reset;
130007afcc7aSLuo bin 
130107afcc7aSLuo bin 	led_info.type = type;
130207afcc7aSLuo bin 	led_info.mode = mode;
130307afcc7aSLuo bin 
130407afcc7aSLuo bin 	err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
130507afcc7aSLuo bin 				HINIC_COMM_CMD_SET_LED_STATUS,
130607afcc7aSLuo bin 				&led_info, sizeof(led_info),
130707afcc7aSLuo bin 				&led_info, &out_size, HINIC_MGMT_MSG_SYNC);
130807afcc7aSLuo bin 	if (err || led_info.status || !out_size) {
130907afcc7aSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n",
131007afcc7aSLuo bin 			err, led_info.status, out_size);
131107afcc7aSLuo bin 		return -EIO;
131207afcc7aSLuo bin 	}
131307afcc7aSLuo bin 
131407afcc7aSLuo bin 	return 0;
131507afcc7aSLuo bin }
131607afcc7aSLuo bin 
hinic_set_led_status(struct hinic_hwdev * hwdev,u8 port,enum hinic_led_type type,enum hinic_led_mode mode)131707afcc7aSLuo bin int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,
131807afcc7aSLuo bin 			 enum hinic_led_type type, enum hinic_led_mode mode)
131907afcc7aSLuo bin {
132007afcc7aSLuo bin 	if (!hwdev)
132107afcc7aSLuo bin 		return -EINVAL;
132207afcc7aSLuo bin 
132307afcc7aSLuo bin 	return _set_led_status(hwdev, port, type, mode, 0);
132407afcc7aSLuo bin }
132507afcc7aSLuo bin 
hinic_reset_led_status(struct hinic_hwdev * hwdev,u8 port)132607afcc7aSLuo bin int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)
132707afcc7aSLuo bin {
132807afcc7aSLuo bin 	int err;
132907afcc7aSLuo bin 
133007afcc7aSLuo bin 	if (!hwdev)
133107afcc7aSLuo bin 		return -EINVAL;
133207afcc7aSLuo bin 
133307afcc7aSLuo bin 	err = _set_led_status(hwdev, port, HINIC_LED_TYPE_INVALID,
133407afcc7aSLuo bin 			      HINIC_LED_MODE_INVALID, 1);
133507afcc7aSLuo bin 	if (err)
133607afcc7aSLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
133707afcc7aSLuo bin 			"Failed to reset led status\n");
133807afcc7aSLuo bin 
133907afcc7aSLuo bin 	return err;
134007afcc7aSLuo bin }
13412ac84cd1SLuo bin 
hinic_if_sfp_absent(struct hinic_hwdev * hwdev)13422ac84cd1SLuo bin static bool hinic_if_sfp_absent(struct hinic_hwdev *hwdev)
13432ac84cd1SLuo bin {
13442ac84cd1SLuo bin 	struct hinic_cmd_get_light_module_abs sfp_abs = {0};
13452ac84cd1SLuo bin 	u16 out_size = sizeof(sfp_abs);
13462ac84cd1SLuo bin 	u8 port_id = hwdev->port_id;
13472ac84cd1SLuo bin 	int err;
13482ac84cd1SLuo bin 
13492ac84cd1SLuo bin 	sfp_abs.port_id = port_id;
13502ac84cd1SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_SFP_ABS,
13512ac84cd1SLuo bin 				 &sfp_abs, sizeof(sfp_abs), &sfp_abs,
13522ac84cd1SLuo bin 				 &out_size);
13532ac84cd1SLuo bin 	if (sfp_abs.status || err || !out_size) {
13542ac84cd1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
13552ac84cd1SLuo bin 			"Failed to get port%d sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n",
13562ac84cd1SLuo bin 			port_id, err, sfp_abs.status, out_size);
13572ac84cd1SLuo bin 		return true;
13582ac84cd1SLuo bin 	}
13592ac84cd1SLuo bin 
13602ac84cd1SLuo bin 	return ((sfp_abs.abs_status == 0) ? false : true);
13612ac84cd1SLuo bin }
13622ac84cd1SLuo bin 
hinic_get_sfp_eeprom(struct hinic_hwdev * hwdev,u8 * data,u16 * len)13632ac84cd1SLuo bin int hinic_get_sfp_eeprom(struct hinic_hwdev *hwdev, u8 *data, u16 *len)
13642ac84cd1SLuo bin {
13652ac84cd1SLuo bin 	struct hinic_cmd_get_std_sfp_info sfp_info = {0};
13662ac84cd1SLuo bin 	u16 out_size = sizeof(sfp_info);
13672ac84cd1SLuo bin 	u8 port_id;
13682ac84cd1SLuo bin 	int err;
13692ac84cd1SLuo bin 
13702ac84cd1SLuo bin 	if (!hwdev || !data || !len)
13712ac84cd1SLuo bin 		return -EINVAL;
13722ac84cd1SLuo bin 
13732ac84cd1SLuo bin 	port_id = hwdev->port_id;
13742ac84cd1SLuo bin 
13752ac84cd1SLuo bin 	if (hinic_if_sfp_absent(hwdev))
13762ac84cd1SLuo bin 		return -ENXIO;
13772ac84cd1SLuo bin 
13782ac84cd1SLuo bin 	sfp_info.port_id = port_id;
13792ac84cd1SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_STD_SFP_INFO,
13802ac84cd1SLuo bin 				 &sfp_info, sizeof(sfp_info), &sfp_info,
13812ac84cd1SLuo bin 				 &out_size);
13822ac84cd1SLuo bin 	if (sfp_info.status || err || !out_size) {
13832ac84cd1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
13842ac84cd1SLuo bin 			"Failed to get port%d sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
13852ac84cd1SLuo bin 			port_id, err, sfp_info.status, out_size);
13862ac84cd1SLuo bin 		return -EIO;
13872ac84cd1SLuo bin 	}
13882ac84cd1SLuo bin 
13892ac84cd1SLuo bin 	*len = min_t(u16, sfp_info.eeprom_len, STD_SFP_INFO_MAX_SIZE);
13902ac84cd1SLuo bin 	memcpy(data, sfp_info.sfp_info, STD_SFP_INFO_MAX_SIZE);
13912ac84cd1SLuo bin 
13922ac84cd1SLuo bin 	return 0;
13932ac84cd1SLuo bin }
13942ac84cd1SLuo bin 
hinic_get_sfp_type(struct hinic_hwdev * hwdev,u8 * data0,u8 * data1)13952ac84cd1SLuo bin int hinic_get_sfp_type(struct hinic_hwdev *hwdev, u8 *data0, u8 *data1)
13962ac84cd1SLuo bin {
13972ac84cd1SLuo bin 	u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
13982ac84cd1SLuo bin 	u16 len;
13992ac84cd1SLuo bin 	int err;
14002ac84cd1SLuo bin 
14012ac84cd1SLuo bin 	if (hinic_if_sfp_absent(hwdev))
14022ac84cd1SLuo bin 		return -ENXIO;
14032ac84cd1SLuo bin 
14042ac84cd1SLuo bin 	err = hinic_get_sfp_eeprom(hwdev, sfp_data, &len);
14052ac84cd1SLuo bin 	if (err)
14062ac84cd1SLuo bin 		return err;
14072ac84cd1SLuo bin 
14082ac84cd1SLuo bin 	*data0 = sfp_data[0];
14092ac84cd1SLuo bin 	*data1 = sfp_data[1];
14102ac84cd1SLuo bin 
14112ac84cd1SLuo bin 	return 0;
14122ac84cd1SLuo bin }
1413