brintos

brintos / linux-shallow public Read only

0
0
Text · 37.3 KiB · f81a43d Raw
1413 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Huawei HiNIC PCI Express Linux driver4 * Copyright(c) 2017 Huawei Technologies Co., Ltd5 */6 7#include <linux/types.h>8#include <linux/netdevice.h>9#include <linux/etherdevice.h>10#include <linux/if_vlan.h>11#include <linux/pci.h>12#include <linux/device.h>13#include <linux/errno.h>14 15#include "hinic_hw_if.h"16#include "hinic_hw_dev.h"17#include "hinic_port.h"18#include "hinic_dev.h"19 20enum mac_op {21	MAC_DEL,22	MAC_SET,23};24 25/**26 * change_mac - change(add or delete) mac address27 * @nic_dev: nic device28 * @addr: mac address29 * @vlan_id: vlan number to set with the mac30 * @op: add or delete the mac31 *32 * Return 0 - Success, negative - Failure33 **/34static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,35		      u16 vlan_id, enum mac_op op)36{37	struct hinic_hwdev *hwdev = nic_dev->hwdev;38	struct hinic_port_mac_cmd port_mac_cmd;39	struct hinic_hwif *hwif = hwdev->hwif;40	u16 out_size = sizeof(port_mac_cmd);41	struct pci_dev *pdev = hwif->pdev;42	enum hinic_port_cmd cmd;43	int err;44 45	if (op == MAC_SET)46		cmd = HINIC_PORT_CMD_SET_MAC;47	else48		cmd = HINIC_PORT_CMD_DEL_MAC;49 50	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);51	port_mac_cmd.vlan_id = vlan_id;52	memcpy(port_mac_cmd.mac, addr, ETH_ALEN);53 54	err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,55				 sizeof(port_mac_cmd),56				 &port_mac_cmd, &out_size);57	if (err || out_size != sizeof(port_mac_cmd) ||58	    (port_mac_cmd.status &&59	     (port_mac_cmd.status != HINIC_PF_SET_VF_ALREADY || !HINIC_IS_VF(hwif)) &&60	     port_mac_cmd.status != HINIC_MGMT_STATUS_EXIST)) {61		dev_err(&pdev->dev, "Failed to change MAC, err: %d, status: 0x%x, out size: 0x%x\n",62			err, port_mac_cmd.status, out_size);63		return -EFAULT;64	}65 66	if (port_mac_cmd.status == HINIC_PF_SET_VF_ALREADY) {67		dev_warn(&pdev->dev, "PF has already set VF mac, ignore %s operation\n",68			 (op == MAC_SET) ? "set" : "del");69		return HINIC_PF_SET_VF_ALREADY;70	}71 72	if (cmd == HINIC_PORT_CMD_SET_MAC && port_mac_cmd.status ==73	    HINIC_MGMT_STATUS_EXIST)74		dev_warn(&pdev->dev, "MAC is repeated, ignore set operation\n");75 76	return 0;77}78 79/**80 * hinic_port_add_mac - add mac address81 * @nic_dev: nic device82 * @addr: mac address83 * @vlan_id: vlan number to set with the mac84 *85 * Return 0 - Success, negative - Failure86 **/87int hinic_port_add_mac(struct hinic_dev *nic_dev,88		       const u8 *addr, u16 vlan_id)89{90	return change_mac(nic_dev, addr, vlan_id, MAC_SET);91}92 93/**94 * hinic_port_del_mac - remove mac address95 * @nic_dev: nic device96 * @addr: mac address97 * @vlan_id: vlan number that is connected to the mac98 *99 * Return 0 - Success, negative - Failure100 **/101int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,102		       u16 vlan_id)103{104	return change_mac(nic_dev, addr, vlan_id, MAC_DEL);105}106 107/**108 * hinic_port_get_mac - get the mac address of the nic device109 * @nic_dev: nic device110 * @addr: returned mac address111 *112 * Return 0 - Success, negative - Failure113 **/114int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)115{116	struct hinic_hwdev *hwdev = nic_dev->hwdev;117	struct hinic_port_mac_cmd port_mac_cmd;118	struct hinic_hwif *hwif = hwdev->hwif;119	u16 out_size = sizeof(port_mac_cmd);120	struct pci_dev *pdev = hwif->pdev;121	int err;122 123	port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);124 125	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,126				 &port_mac_cmd, sizeof(port_mac_cmd),127				 &port_mac_cmd, &out_size);128	if (err || out_size != sizeof(port_mac_cmd) || port_mac_cmd.status) {129		dev_err(&pdev->dev, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x\n",130			err, port_mac_cmd.status, out_size);131		return -EFAULT;132	}133 134	memcpy(addr, port_mac_cmd.mac, ETH_ALEN);135	return 0;136}137 138/**139 * hinic_port_set_mtu - set mtu140 * @nic_dev: nic device141 * @new_mtu: new mtu142 *143 * Return 0 - Success, negative - Failure144 **/145int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)146{147	struct hinic_hwdev *hwdev = nic_dev->hwdev;148	struct hinic_port_mtu_cmd port_mtu_cmd;149	struct hinic_hwif *hwif = hwdev->hwif;150	u16 out_size = sizeof(port_mtu_cmd);151	struct pci_dev *pdev = hwif->pdev;152	int err;153 154	port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);155	port_mtu_cmd.mtu = new_mtu;156 157	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,158				 &port_mtu_cmd, sizeof(port_mtu_cmd),159				 &port_mtu_cmd, &out_size);160	if (err || out_size != sizeof(port_mtu_cmd) || port_mtu_cmd.status) {161		dev_err(&pdev->dev, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x\n",162			err, port_mtu_cmd.status, out_size);163		return -EFAULT;164	}165 166	return 0;167}168 169/**170 * hinic_port_add_vlan - add vlan to the nic device171 * @nic_dev: nic device172 * @vlan_id: the vlan number to add173 *174 * Return 0 - Success, negative - Failure175 **/176int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)177{178	struct hinic_hwdev *hwdev = nic_dev->hwdev;179	struct hinic_port_vlan_cmd port_vlan_cmd;180 181	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);182	port_vlan_cmd.vlan_id = vlan_id;183 184	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,185				  &port_vlan_cmd, sizeof(port_vlan_cmd),186				  NULL, NULL);187}188 189/**190 * hinic_port_del_vlan - delete vlan from the nic device191 * @nic_dev: nic device192 * @vlan_id: the vlan number to delete193 *194 * Return 0 - Success, negative - Failure195 **/196int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)197{198	struct hinic_hwdev *hwdev = nic_dev->hwdev;199	struct hinic_port_vlan_cmd port_vlan_cmd;200 201	port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);202	port_vlan_cmd.vlan_id = vlan_id;203 204	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,205				 &port_vlan_cmd, sizeof(port_vlan_cmd),206				 NULL, NULL);207}208 209/**210 * hinic_port_set_rx_mode - set rx mode in the nic device211 * @nic_dev: nic device212 * @rx_mode: the rx mode to set213 *214 * Return 0 - Success, negative - Failure215 **/216int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)217{218	struct hinic_hwdev *hwdev = nic_dev->hwdev;219	struct hinic_port_rx_mode_cmd rx_mode_cmd;220 221	rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);222	rx_mode_cmd.rx_mode = rx_mode;223 224	return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,225				  &rx_mode_cmd, sizeof(rx_mode_cmd),226				  NULL, NULL);227}228 229/**230 * hinic_port_link_state - get the link state231 * @nic_dev: nic device232 * @link_state: the returned link state233 *234 * Return 0 - Success, negative - Failure235 **/236int hinic_port_link_state(struct hinic_dev *nic_dev,237			  enum hinic_port_link_state *link_state)238{239	struct hinic_hwdev *hwdev = nic_dev->hwdev;240	struct hinic_hwif *hwif = hwdev->hwif;241	struct hinic_port_link_cmd link_cmd;242	struct pci_dev *pdev = hwif->pdev;243	u16 out_size = sizeof(link_cmd);244	int err;245 246	link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);247 248	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,249				 &link_cmd, sizeof(link_cmd),250				 &link_cmd, &out_size);251	if (err || out_size != sizeof(link_cmd) || link_cmd.status) {252		dev_err(&pdev->dev, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x\n",253			err, link_cmd.status, out_size);254		return -EINVAL;255	}256 257	*link_state = link_cmd.state;258	return 0;259}260 261/**262 * hinic_port_set_state - set port state263 * @nic_dev: nic device264 * @state: the state to set265 *266 * Return 0 - Success, negative - Failure267 **/268int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)269{270	struct hinic_hwdev *hwdev = nic_dev->hwdev;271	struct hinic_port_state_cmd port_state;272	struct hinic_hwif *hwif = hwdev->hwif;273	struct pci_dev *pdev = hwif->pdev;274	u16 out_size = sizeof(port_state);275	int err;276 277	if (HINIC_IS_VF(hwdev->hwif))278		return 0;279 280	port_state.state = state;281 282	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PORT_STATE,283				 &port_state, sizeof(port_state),284				 &port_state, &out_size);285	if (err || out_size != sizeof(port_state) || port_state.status) {286		dev_err(&pdev->dev, "Failed to set port state, err: %d, status: 0x%x, out size: 0x%x\n",287			err, port_state.status, out_size);288		return -EFAULT;289	}290 291	return 0;292}293 294/**295 * hinic_port_set_func_state- set func device state296 * @nic_dev: nic device297 * @state: the state to set298 *299 * Return 0 - Success, negative - Failure300 **/301int hinic_port_set_func_state(struct hinic_dev *nic_dev,302			      enum hinic_func_port_state state)303{304	struct hinic_port_func_state_cmd func_state;305	struct hinic_hwdev *hwdev = nic_dev->hwdev;306	struct hinic_hwif *hwif = hwdev->hwif;307	struct pci_dev *pdev = hwif->pdev;308	u16 out_size = sizeof(func_state);309	int err;310 311	func_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);312	func_state.state = state;313 314	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_FUNC_STATE,315				 &func_state, sizeof(func_state),316				 &func_state, &out_size);317	if (err || out_size != sizeof(func_state) || func_state.status) {318		dev_err(&pdev->dev, "Failed to set port func state, err: %d, status: 0x%x, out size: 0x%x\n",319			err, func_state.status, out_size);320		return -EFAULT;321	}322 323	return 0;324}325 326/**327 * hinic_port_get_cap - get port capabilities328 * @nic_dev: nic device329 * @port_cap: returned port capabilities330 *331 * Return 0 - Success, negative - Failure332 **/333int hinic_port_get_cap(struct hinic_dev *nic_dev,334		       struct hinic_port_cap *port_cap)335{336	struct hinic_hwdev *hwdev = nic_dev->hwdev;337	struct hinic_hwif *hwif = hwdev->hwif;338	struct pci_dev *pdev = hwif->pdev;339	u16 out_size = sizeof(*port_cap);340	int err;341 342	port_cap->func_idx = HINIC_HWIF_FUNC_IDX(hwif);343 344	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_CAP,345				 port_cap, sizeof(*port_cap),346				 port_cap, &out_size);347	if (err || out_size != sizeof(*port_cap) || port_cap->status) {348		dev_err(&pdev->dev,349			"Failed to get port capabilities, err: %d, status: 0x%x, out size: 0x%x\n",350			err, port_cap->status, out_size);351		return -EIO;352	}353 354	return 0;355}356 357/**358 * hinic_port_set_tso - set port tso configuration359 * @nic_dev: nic device360 * @state: the tso state to set361 *362 * Return 0 - Success, negative - Failure363 **/364int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state)365{366	struct hinic_hwdev *hwdev = nic_dev->hwdev;367	struct hinic_hwif *hwif = hwdev->hwif;368	struct hinic_tso_config tso_cfg = {0};369	struct pci_dev *pdev = hwif->pdev;370	u16 out_size = sizeof(tso_cfg);371	int err;372 373	tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);374	tso_cfg.tso_en = state;375 376	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_TSO,377				 &tso_cfg, sizeof(tso_cfg),378				 &tso_cfg, &out_size);379	if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) {380		dev_err(&pdev->dev,381			"Failed to set port tso, err: %d, status: 0x%x, out size: 0x%x\n",382			err, tso_cfg.status, out_size);383		return -EIO;384	}385 386	return 0;387}388 389int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en)390{391	struct hinic_checksum_offload rx_csum_cfg = {0};392	struct hinic_hwdev *hwdev = nic_dev->hwdev;393	u16 out_size = sizeof(rx_csum_cfg);394	struct hinic_hwif *hwif;395	struct pci_dev *pdev;396	int err;397 398	if (!hwdev)399		return -EINVAL;400 401	hwif = hwdev->hwif;402	pdev = hwif->pdev;403	rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);404	rx_csum_cfg.rx_csum_offload = en;405 406	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,407				 &rx_csum_cfg, sizeof(rx_csum_cfg),408				 &rx_csum_cfg, &out_size);409	if (err || !out_size || rx_csum_cfg.status) {410		dev_err(&pdev->dev,411			"Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x\n",412			err, rx_csum_cfg.status, out_size);413		return -EIO;414	}415 416	return 0;417}418 419int hinic_set_rx_vlan_offload(struct hinic_dev *nic_dev, u8 en)420{421	struct hinic_hwdev *hwdev = nic_dev->hwdev;422	struct hinic_vlan_cfg vlan_cfg;423	struct hinic_hwif *hwif;424	struct pci_dev *pdev;425	u16 out_size;426	int err;427 428	if (!hwdev)429		return -EINVAL;430 431	out_size = sizeof(vlan_cfg);432	hwif = hwdev->hwif;433	pdev = hwif->pdev;434	vlan_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);435	vlan_cfg.vlan_rx_offload = en;436 437	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,438				 &vlan_cfg, sizeof(vlan_cfg),439				 &vlan_cfg, &out_size);440	if (err || !out_size || vlan_cfg.status) {441		dev_err(&pdev->dev,442			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",443			err, vlan_cfg.status, out_size);444		return -EINVAL;445	}446 447	return 0;448}449 450int hinic_set_vlan_fliter(struct hinic_dev *nic_dev, u32 en)451{452	struct hinic_hwdev *hwdev = nic_dev->hwdev;453	struct hinic_hwif *hwif = hwdev->hwif;454	struct pci_dev *pdev = hwif->pdev;455	struct hinic_vlan_filter vlan_filter;456	u16 out_size = sizeof(vlan_filter);457	int err;458 459	vlan_filter.func_idx = HINIC_HWIF_FUNC_IDX(hwif);460	vlan_filter.enable = en;461 462	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,463				 &vlan_filter, sizeof(vlan_filter),464				 &vlan_filter, &out_size);465	if (vlan_filter.status == HINIC_MGMT_CMD_UNSUPPORTED) {466		err = HINIC_MGMT_CMD_UNSUPPORTED;467	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&468			   HINIC_IS_VF(hwif)) {469		err = HINIC_MGMT_CMD_UNSUPPORTED;470	} else if (err || !out_size || vlan_filter.status) {471		dev_err(&pdev->dev,472			"Failed to set vlan fliter, err: %d, status: 0x%x, out size: 0x%x\n",473			err, vlan_filter.status, out_size);474		err = -EINVAL;475	}476 477	return err;478}479 480int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)481{482	struct hinic_hwdev *hwdev = nic_dev->hwdev;483	struct hinic_hwif *hwif = hwdev->hwif;484	struct hinic_rq_num rq_num = { 0 };485	struct pci_dev *pdev = hwif->pdev;486	u16 out_size = sizeof(rq_num);487	int err;488 489	rq_num.func_id = HINIC_HWIF_FUNC_IDX(hwif);490	rq_num.num_rqs = num_rqs;491	rq_num.rq_depth = ilog2(nic_dev->rq_depth);492 493	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RQ_IQ_MAP,494				 &rq_num, sizeof(rq_num),495				 &rq_num, &out_size);496	if (err || !out_size || rq_num.status) {497		dev_err(&pdev->dev,498			"Failed to set rxq number, err: %d, status: 0x%x, out size: 0x%x\n",499			err, rq_num.status, out_size);500		return -EIO;501	}502 503	return 0;504}505 506static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,507			    u8 max_wqe_num)508{509	struct hinic_hwdev *hwdev = nic_dev->hwdev;510	struct hinic_lro_config lro_cfg = { 0 };511	struct hinic_hwif *hwif = hwdev->hwif;512	struct pci_dev *pdev = hwif->pdev;513	u16 out_size = sizeof(lro_cfg);514	int err;515 516	lro_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);517	lro_cfg.lro_ipv4_en = ipv4_en;518	lro_cfg.lro_ipv6_en = ipv6_en;519	lro_cfg.lro_max_wqe_num = max_wqe_num;520 521	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO,522				 &lro_cfg, sizeof(lro_cfg),523				 &lro_cfg, &out_size);524	if (err || !out_size || lro_cfg.status) {525		dev_err(&pdev->dev,526			"Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x\n",527			err, lro_cfg.status, out_size);528		return -EIO;529	}530 531	return 0;532}533 534static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)535{536	struct hinic_hwdev *hwdev = nic_dev->hwdev;537	struct hinic_lro_timer lro_timer = { 0 };538	struct hinic_hwif *hwif = hwdev->hwif;539	struct pci_dev *pdev = hwif->pdev;540	u16 out_size = sizeof(lro_timer);541	int err;542 543	lro_timer.status = 0;544	lro_timer.type = 0;545	lro_timer.enable = 1;546	lro_timer.timer = timer_value;547 548	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO_TIMER,549				 &lro_timer, sizeof(lro_timer),550				 &lro_timer, &out_size);551	if (lro_timer.status == 0xFF) {552		/* For this case, we think status (0xFF) is OK */553		lro_timer.status = 0;554		dev_dbg(&pdev->dev,555			"Set lro timer not supported by the current FW version, it will be 1ms default\n");556	}557 558	if (err || !out_size || lro_timer.status) {559		dev_err(&pdev->dev,560			"Failed to set lro timer, err: %d, status: 0x%x, out size: 0x%x\n",561			err, lro_timer.status, out_size);562 563		return -EIO;564	}565 566	return 0;567}568 569int hinic_set_rx_lro_state(struct hinic_dev *nic_dev, u8 lro_en,570			   u32 lro_timer, u32 wqe_num)571{572	struct hinic_hwdev *hwdev = nic_dev->hwdev;573	u8 ipv4_en;574	u8 ipv6_en;575	int err;576 577	if (!hwdev)578		return -EINVAL;579 580	ipv4_en = lro_en ? 1 : 0;581	ipv6_en = lro_en ? 1 : 0;582 583	err = hinic_set_rx_lro(nic_dev, ipv4_en, ipv6_en, (u8)wqe_num);584	if (err)585		return err;586 587	if (HINIC_IS_VF(nic_dev->hwdev->hwif))588		return 0;589 590	err = hinic_set_rx_lro_timer(nic_dev, lro_timer);591	if (err)592		return err;593 594	return 0;595}596 597int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,598			    const u32 *indir_table)599{600	struct hinic_rss_indirect_tbl *indir_tbl;601	struct hinic_func_to_io *func_to_io;602	struct hinic_cmdq_buf cmd_buf;603	struct hinic_hwdev *hwdev;604	struct hinic_hwif *hwif;605	struct pci_dev *pdev;606	u32 indir_size;607	u64 out_param;608	int err, i;609	u32 *temp;610 611	hwdev = nic_dev->hwdev;612	func_to_io = &hwdev->func_to_io;613	hwif = hwdev->hwif;614	pdev = hwif->pdev;615 616	err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);617	if (err) {618		dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");619		return err;620	}621 622	cmd_buf.size = sizeof(*indir_tbl);623 624	indir_tbl = cmd_buf.buf;625	indir_tbl->group_index = cpu_to_be32(tmpl_idx);626 627	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {628		indir_tbl->entry[i] = indir_table[i];629 630		if (0x3 == (i & 0x3)) {631			temp = (u32 *)&indir_tbl->entry[i - 3];632			*temp = cpu_to_be32(*temp);633		}634	}635 636	/* cfg the rss indirect table by command queue */637	indir_size = HINIC_RSS_INDIR_SIZE / 2;638	indir_tbl->offset = 0;639	indir_tbl->size = cpu_to_be32(indir_size);640 641	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,642				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,643				     &cmd_buf, &out_param);644	if (err || out_param != 0) {645		dev_err(&pdev->dev, "Failed to set rss indir table\n");646		err = -EFAULT;647		goto free_buf;648	}649 650	indir_tbl->offset = cpu_to_be32(indir_size);651	indir_tbl->size = cpu_to_be32(indir_size);652	memcpy(&indir_tbl->entry[0], &indir_tbl->entry[indir_size], indir_size);653 654	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,655				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,656				     &cmd_buf, &out_param);657	if (err || out_param != 0) {658		dev_err(&pdev->dev, "Failed to set rss indir table\n");659		err = -EFAULT;660	}661 662free_buf:663	hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);664 665	return err;666}667 668int hinic_rss_get_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,669			    u32 *indir_table)670{671	struct hinic_rss_indir_table rss_cfg = { 0 };672	struct hinic_hwdev *hwdev = nic_dev->hwdev;673	struct hinic_hwif *hwif = hwdev->hwif;674	struct pci_dev *pdev = hwif->pdev;675	u16 out_size = sizeof(rss_cfg);676	int err = 0, i;677 678	rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);679	rss_cfg.template_id = tmpl_idx;680 681	err = hinic_port_msg_cmd(hwdev,682				 HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,683				 &rss_cfg, sizeof(rss_cfg), &rss_cfg,684				 &out_size);685	if (err || !out_size || rss_cfg.status) {686		dev_err(&pdev->dev, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x\n",687			err, rss_cfg.status, out_size);688		return -EINVAL;689	}690 691	hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);692	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)693		indir_table[i] = rss_cfg.indir[i];694 695	return 0;696}697 698int hinic_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,699		       struct hinic_rss_type rss_type)700{701	struct hinic_rss_context_tbl *ctx_tbl;702	struct hinic_func_to_io *func_to_io;703	struct hinic_cmdq_buf cmd_buf;704	struct hinic_hwdev *hwdev;705	struct hinic_hwif *hwif;706	struct pci_dev *pdev;707	u64 out_param;708	u32 ctx = 0;709	int err;710 711	hwdev = nic_dev->hwdev;712	func_to_io = &hwdev->func_to_io;713	hwif = hwdev->hwif;714	pdev = hwif->pdev;715 716	err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);717	if (err) {718		dev_err(&pdev->dev, "Failed to allocate cmd buf\n");719		return -ENOMEM;720	}721 722	ctx |=  HINIC_RSS_TYPE_SET(1, VALID) |723		HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |724		HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |725		HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |726		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |727		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |728		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |729		HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |730		HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);731 732	cmd_buf.size = sizeof(struct hinic_rss_context_tbl);733 734	ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;735	ctx_tbl->group_index = cpu_to_be32(tmpl_idx);736	ctx_tbl->offset = 0;737	ctx_tbl->size = sizeof(u32);738	ctx_tbl->size = cpu_to_be32(ctx_tbl->size);739	ctx_tbl->rsvd = 0;740	ctx_tbl->ctx = cpu_to_be32(ctx);741 742	/* cfg the rss context table by command queue */743	err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,744				     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,745				     &cmd_buf, &out_param);746 747	hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);748 749	if (err || out_param != 0) {750		dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",751			err);752		return -EFAULT;753	}754 755	return 0;756}757 758int hinic_get_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,759		       struct hinic_rss_type *rss_type)760{761	struct hinic_rss_context_table ctx_tbl = { 0 };762	struct hinic_hwdev *hwdev = nic_dev->hwdev;763	u16 out_size = sizeof(ctx_tbl);764	struct hinic_hwif *hwif;765	struct pci_dev *pdev;766	int err;767 768	if (!hwdev || !rss_type)769		return -EINVAL;770 771	hwif = hwdev->hwif;772	pdev = hwif->pdev;773 774	ctx_tbl.func_id = HINIC_HWIF_FUNC_IDX(hwif);775	ctx_tbl.template_id = tmpl_idx;776 777	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,778				 &ctx_tbl, sizeof(ctx_tbl),779				 &ctx_tbl, &out_size);780	if (err || !out_size || ctx_tbl.status) {781		dev_err(&pdev->dev, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n",782			err, ctx_tbl.status, out_size);783		return -EINVAL;784	}785 786	rss_type->ipv4          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);787	rss_type->ipv6          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);788	rss_type->ipv6_ext      = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);789	rss_type->tcp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);790	rss_type->tcp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);791	rss_type->tcp_ipv6_ext  = HINIC_RSS_TYPE_GET(ctx_tbl.context,792						     TCP_IPV6_EXT);793	rss_type->udp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);794	rss_type->udp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);795 796	return 0;797}798 799int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,800			       const u8 *temp)801{802	struct hinic_hwdev *hwdev = nic_dev->hwdev;803	struct hinic_hwif *hwif = hwdev->hwif;804	struct hinic_rss_key rss_key = { 0 };805	struct pci_dev *pdev = hwif->pdev;806	u16 out_size = sizeof(rss_key);807	int err;808 809	rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);810	rss_key.template_id = template_id;811	memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);812 813	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,814				 &rss_key, sizeof(rss_key),815				 &rss_key, &out_size);816	if (err || !out_size || rss_key.status) {817		dev_err(&pdev->dev,818			"Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",819			err, rss_key.status, out_size);820		return -EINVAL;821	}822 823	return 0;824}825 826int hinic_rss_get_template_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,827			       u8 *temp)828{829	struct hinic_rss_template_key temp_key = { 0 };830	struct hinic_hwdev *hwdev = nic_dev->hwdev;831	u16 out_size = sizeof(temp_key);832	struct hinic_hwif *hwif;833	struct pci_dev *pdev;834	int err;835 836	if (!hwdev || !temp)837		return -EINVAL;838 839	hwif = hwdev->hwif;840	pdev = hwif->pdev;841 842	temp_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);843	temp_key.template_id = tmpl_idx;844 845	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,846				 &temp_key, sizeof(temp_key),847				 &temp_key, &out_size);848	if (err || !out_size || temp_key.status) {849		dev_err(&pdev->dev, "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x\n",850			err, temp_key.status, out_size);851		return -EINVAL;852	}853 854	memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);855 856	return 0;857}858 859int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,860			      u8 type)861{862	struct hinic_rss_engine_type rss_engine = { 0 };863	struct hinic_hwdev *hwdev = nic_dev->hwdev;864	struct hinic_hwif *hwif = hwdev->hwif;865	struct pci_dev *pdev = hwif->pdev;866	u16 out_size = sizeof(rss_engine);867	int err;868 869	rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);870	rss_engine.hash_engine = type;871	rss_engine.template_id = template_id;872 873	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,874				 &rss_engine, sizeof(rss_engine),875				 &rss_engine, &out_size);876	if (err || !out_size || rss_engine.status) {877		dev_err(&pdev->dev,878			"Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",879			err, rss_engine.status, out_size);880		return -EINVAL;881	}882 883	return 0;884}885 886int hinic_rss_get_hash_engine(struct hinic_dev *nic_dev, u8 tmpl_idx, u8 *type)887{888	struct hinic_rss_engine_type hash_type = { 0 };889	struct hinic_hwdev *hwdev = nic_dev->hwdev;890	u16 out_size = sizeof(hash_type);891	struct hinic_hwif *hwif;892	struct pci_dev *pdev;893	int err;894 895	if (!hwdev || !type)896		return -EINVAL;897 898	hwif = hwdev->hwif;899	pdev = hwif->pdev;900 901	hash_type.func_id = HINIC_HWIF_FUNC_IDX(hwif);902	hash_type.template_id = tmpl_idx;903 904	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,905				 &hash_type, sizeof(hash_type),906				 &hash_type, &out_size);907	if (err || !out_size || hash_type.status) {908		dev_err(&pdev->dev, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x\n",909			err, hash_type.status, out_size);910		return -EINVAL;911	}912 913	*type = hash_type.hash_engine;914	return 0;915}916 917int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)918{919	struct hinic_hwdev *hwdev = nic_dev->hwdev;920	struct hinic_rss_config rss_cfg = { 0 };921	struct hinic_hwif *hwif = hwdev->hwif;922	struct pci_dev *pdev = hwif->pdev;923	u16 out_size = sizeof(rss_cfg);924	int err;925 926	rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);927	rss_cfg.rss_en = rss_en;928	rss_cfg.template_id = template_id;929	rss_cfg.rq_priority_number = 0;930 931	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_CFG,932				 &rss_cfg, sizeof(rss_cfg),933				 &rss_cfg, &out_size);934	if (err || !out_size || rss_cfg.status) {935		dev_err(&pdev->dev,936			"Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",937			err, rss_cfg.status, out_size);938		return -EINVAL;939	}940 941	return 0;942}943 944int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)945{946	struct hinic_rss_template_mgmt template_mgmt = { 0 };947	struct hinic_hwdev *hwdev = nic_dev->hwdev;948	struct hinic_hwif *hwif = hwdev->hwif;949	u16 out_size = sizeof(template_mgmt);950	struct pci_dev *pdev = hwif->pdev;951	int err;952 953	template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);954	template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;955 956	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,957				 &template_mgmt, sizeof(template_mgmt),958				 &template_mgmt, &out_size);959	if (err || !out_size || template_mgmt.status) {960		dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",961			err, template_mgmt.status, out_size);962		return -EINVAL;963	}964 965	*tmpl_idx = template_mgmt.template_id;966 967	return 0;968}969 970int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)971{972	struct hinic_rss_template_mgmt template_mgmt = { 0 };973	struct hinic_hwdev *hwdev = nic_dev->hwdev;974	struct hinic_hwif *hwif = hwdev->hwif;975	u16 out_size = sizeof(template_mgmt);976	struct pci_dev *pdev = hwif->pdev;977	int err;978 979	template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);980	template_mgmt.template_id = tmpl_idx;981	template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;982 983	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,984				 &template_mgmt, sizeof(template_mgmt),985				 &template_mgmt, &out_size);986	if (err || !out_size || template_mgmt.status) {987		dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",988			err, template_mgmt.status, out_size);989		return -EINVAL;990	}991 992	return 0;993}994 995int hinic_get_vport_stats(struct hinic_dev *nic_dev,996			  struct hinic_vport_stats *stats)997{998	struct hinic_cmd_vport_stats vport_stats = { 0 };999	struct hinic_port_stats_info stats_info = { 0 };1000	struct hinic_hwdev *hwdev = nic_dev->hwdev;1001	struct hinic_hwif *hwif = hwdev->hwif;1002	u16 out_size = sizeof(vport_stats);1003	struct pci_dev *pdev = hwif->pdev;1004	int err;1005 1006	stats_info.stats_version = HINIC_PORT_STATS_VERSION;1007	stats_info.func_id = HINIC_HWIF_FUNC_IDX(hwif);1008	stats_info.stats_size = sizeof(vport_stats);1009 1010	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,1011				 &stats_info, sizeof(stats_info),1012				 &vport_stats, &out_size);1013	if (err || !out_size || vport_stats.status) {1014		dev_err(&pdev->dev,1015			"Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n",1016			err, vport_stats.status, out_size);1017		return -EFAULT;1018	}1019 1020	memcpy(stats, &vport_stats.stats, sizeof(*stats));1021	return 0;1022}1023 1024int hinic_get_phy_port_stats(struct hinic_dev *nic_dev,1025			     struct hinic_phy_port_stats *stats)1026{1027	struct hinic_port_stats_info stats_info = { 0 };1028	struct hinic_hwdev *hwdev = nic_dev->hwdev;1029	struct hinic_hwif *hwif = hwdev->hwif;1030	struct hinic_port_stats *port_stats;1031	u16 out_size = sizeof(*port_stats);1032	struct pci_dev *pdev = hwif->pdev;1033	int err;1034 1035	port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);1036	if (!port_stats)1037		return -ENOMEM;1038 1039	stats_info.stats_version = HINIC_PORT_STATS_VERSION;1040	stats_info.stats_size = sizeof(*port_stats);1041 1042	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,1043				 &stats_info, sizeof(stats_info),1044				 port_stats, &out_size);1045	if (err || !out_size || port_stats->status) {1046		dev_err(&pdev->dev,1047			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",1048			err, port_stats->status, out_size);1049		err = -EINVAL;1050		goto out;1051	}1052 1053	memcpy(stats, &port_stats->stats, sizeof(*stats));1054 1055out:1056	kfree(port_stats);1057 1058	return err;1059}1060 1061int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver)1062{1063	struct hinic_hwdev *hwdev = nic_dev->hwdev;1064	struct hinic_version_info up_ver = {0};1065	u16 out_size = sizeof(up_ver);1066	struct hinic_hwif *hwif;1067	struct pci_dev *pdev;1068	int err;1069 1070	if (!hwdev)1071		return -EINVAL;1072 1073	hwif = hwdev->hwif;1074	pdev = hwif->pdev;1075 1076	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION,1077				 &up_ver, sizeof(up_ver), &up_ver,1078				 &out_size);1079	if (err || !out_size || up_ver.status) {1080		dev_err(&pdev->dev,1081			"Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x\n",1082			err, up_ver.status, out_size);1083		return -EINVAL;1084	}1085 1086	snprintf(mgmt_ver, HINIC_MGMT_VERSION_MAX_LEN, "%s", up_ver.ver);1087 1088	return 0;1089}1090 1091int hinic_get_link_mode(struct hinic_hwdev *hwdev,1092			struct hinic_link_mode_cmd *link_mode)1093{1094	u16 out_size;1095	int err;1096 1097	if (!hwdev || !link_mode)1098		return -EINVAL;1099 1100	link_mode->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);1101	out_size = sizeof(*link_mode);1102 1103	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,1104				 link_mode, sizeof(*link_mode),1105				 link_mode, &out_size);1106	if (err || !out_size || link_mode->status) {1107		dev_err(&hwdev->hwif->pdev->dev,1108			"Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x\n",1109			err, link_mode->status, out_size);1110		return -EIO;1111	}1112 1113	return 0;1114}1115 1116int hinic_set_autoneg(struct hinic_hwdev *hwdev, bool enable)1117{1118	struct hinic_set_autoneg_cmd autoneg = {0};1119	u16 out_size = sizeof(autoneg);1120	int err;1121 1122	if (!hwdev)1123		return -EINVAL;1124 1125	autoneg.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);1126	autoneg.enable = enable;1127 1128	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_AUTONEG,1129				 &autoneg, sizeof(autoneg),1130				 &autoneg, &out_size);1131	if (err || !out_size || autoneg.status) {1132		dev_err(&hwdev->hwif->pdev->dev, "Failed to %s autoneg, err: %d, status: 0x%x, out size: 0x%x\n",1133			enable ? "enable" : "disable", err, autoneg.status,1134			out_size);1135		return -EIO;1136	}1137 1138	return 0;1139}1140 1141int hinic_set_speed(struct hinic_hwdev *hwdev, enum nic_speed_level speed)1142{1143	struct hinic_speed_cmd speed_info = {0};1144	u16 out_size = sizeof(speed_info);1145	int err;1146 1147	if (!hwdev)1148		return -EINVAL;1149 1150	speed_info.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);1151	speed_info.speed = speed;1152 1153	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_SPEED,1154				 &speed_info, sizeof(speed_info),1155				 &speed_info, &out_size);1156	if (err || !out_size || speed_info.status) {1157		dev_err(&hwdev->hwif->pdev->dev,1158			"Failed to set speed, err: %d, status: 0x%x, out size: 0x%x\n",1159			err, speed_info.status, out_size);1160		return -EIO;1161	}1162 1163	return 0;1164}1165 1166int hinic_set_link_settings(struct hinic_hwdev *hwdev,1167			    struct hinic_link_ksettings_info *info)1168{1169	u16 out_size = sizeof(*info);1170	int err;1171 1172	err = hinic_hilink_msg_cmd(hwdev, HINIC_HILINK_CMD_SET_LINK_SETTINGS,1173				   info, sizeof(*info), info, &out_size);1174	if ((info->status != HINIC_MGMT_CMD_UNSUPPORTED &&1175	     info->status) || err || !out_size) {1176		dev_err(&hwdev->hwif->pdev->dev,1177			"Failed to set link settings, err: %d, status: 0x%x, out size: 0x%x\n",1178			err, info->status, out_size);1179		return -EFAULT;1180	}1181 1182	return info->status;1183}1184 1185int hinic_get_hw_pause_info(struct hinic_hwdev *hwdev,1186			    struct hinic_pause_config *pause_info)1187{1188	u16 out_size = sizeof(*pause_info);1189	int err;1190 1191	pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);1192 1193	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,1194				 pause_info, sizeof(*pause_info),1195				 pause_info, &out_size);1196	if (err || !out_size || pause_info->status) {1197		dev_err(&hwdev->hwif->pdev->dev, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n",1198			err, pause_info->status, out_size);1199		return -EIO;1200	}1201 1202	return 0;1203}1204 1205int hinic_set_hw_pause_info(struct hinic_hwdev *hwdev,1206			    struct hinic_pause_config *pause_info)1207{1208	u16 out_size = sizeof(*pause_info);1209	int err;1210 1211	pause_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);1212 1213	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,1214				 pause_info, sizeof(*pause_info),1215				 pause_info, &out_size);1216	if (err || !out_size || pause_info->status) {1217		dev_err(&hwdev->hwif->pdev->dev, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x\n",1218			err, pause_info->status, out_size);1219		return -EIO;1220	}1221 1222	return 0;1223}1224 1225int hinic_dcb_set_pfc(struct hinic_hwdev *hwdev, u8 pfc_en, u8 pfc_bitmap)1226{1227	struct hinic_nic_cfg *nic_cfg = &hwdev->func_to_io.nic_cfg;1228	struct hinic_set_pfc pfc = {0};1229	u16 out_size = sizeof(pfc);1230	int err;1231 1232	if (HINIC_IS_VF(hwdev->hwif))1233		return 0;1234 1235	mutex_lock(&nic_cfg->cfg_mutex);1236 1237	pfc.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);1238	pfc.pfc_bitmap = pfc_bitmap;1239	pfc.pfc_en = pfc_en;1240 1241	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_PFC,1242				 &pfc, sizeof(pfc), &pfc, &out_size);1243	if (err || pfc.status || !out_size) {1244		dev_err(&hwdev->hwif->pdev->dev, "Failed to %s pfc, err: %d, status: 0x%x, out size: 0x%x\n",1245			pfc_en ? "enable" : "disable", err, pfc.status,1246			out_size);1247		mutex_unlock(&nic_cfg->cfg_mutex);1248		return -EIO;1249	}1250 1251	/* pause settings is opposite from pfc */1252	nic_cfg->rx_pause = pfc_en ? 0 : 1;1253	nic_cfg->tx_pause = pfc_en ? 0 : 1;1254 1255	mutex_unlock(&nic_cfg->cfg_mutex);1256 1257	return 0;1258}1259 1260int hinic_set_loopback_mode(struct hinic_hwdev *hwdev, u32 mode, u32 enable)1261{1262	struct hinic_port_loopback lb = {0};1263	u16 out_size = sizeof(lb);1264	int err;1265 1266	lb.mode = mode;1267	lb.en = enable;1268 1269	if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) {1270		dev_err(&hwdev->hwif->pdev->dev,1271			"Invalid loopback mode %d to set\n", mode);1272		return -EINVAL;1273	}1274 1275	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LOOPBACK_MODE,1276				 &lb, sizeof(lb), &lb, &out_size);1277	if (err || !out_size || lb.status) {1278		dev_err(&hwdev->hwif->pdev->dev,1279			"Failed to set loopback mode %d en %d, err: %d, status: 0x%x, out size: 0x%x\n",1280			mode, enable, err, lb.status, out_size);1281		return -EIO;1282	}1283 1284	return 0;1285}1286 1287static int _set_led_status(struct hinic_hwdev *hwdev, u8 port,1288			   enum hinic_led_type type,1289			   enum hinic_led_mode mode, u8 reset)1290{1291	struct hinic_led_info led_info = {0};1292	u16 out_size = sizeof(led_info);1293	struct hinic_pfhwdev *pfhwdev;1294	int err;1295 1296	pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);1297 1298	led_info.port = port;1299	led_info.reset = reset;1300 1301	led_info.type = type;1302	led_info.mode = mode;1303 1304	err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,1305				HINIC_COMM_CMD_SET_LED_STATUS,1306				&led_info, sizeof(led_info),1307				&led_info, &out_size, HINIC_MGMT_MSG_SYNC);1308	if (err || led_info.status || !out_size) {1309		dev_err(&hwdev->hwif->pdev->dev, "Failed to set led status, err: %d, status: 0x%x, out size: 0x%x\n",1310			err, led_info.status, out_size);1311		return -EIO;1312	}1313 1314	return 0;1315}1316 1317int hinic_set_led_status(struct hinic_hwdev *hwdev, u8 port,1318			 enum hinic_led_type type, enum hinic_led_mode mode)1319{1320	if (!hwdev)1321		return -EINVAL;1322 1323	return _set_led_status(hwdev, port, type, mode, 0);1324}1325 1326int hinic_reset_led_status(struct hinic_hwdev *hwdev, u8 port)1327{1328	int err;1329 1330	if (!hwdev)1331		return -EINVAL;1332 1333	err = _set_led_status(hwdev, port, HINIC_LED_TYPE_INVALID,1334			      HINIC_LED_MODE_INVALID, 1);1335	if (err)1336		dev_err(&hwdev->hwif->pdev->dev,1337			"Failed to reset led status\n");1338 1339	return err;1340}1341 1342static bool hinic_if_sfp_absent(struct hinic_hwdev *hwdev)1343{1344	struct hinic_cmd_get_light_module_abs sfp_abs = {0};1345	u16 out_size = sizeof(sfp_abs);1346	u8 port_id = hwdev->port_id;1347	int err;1348 1349	sfp_abs.port_id = port_id;1350	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_SFP_ABS,1351				 &sfp_abs, sizeof(sfp_abs), &sfp_abs,1352				 &out_size);1353	if (sfp_abs.status || err || !out_size) {1354		dev_err(&hwdev->hwif->pdev->dev,1355			"Failed to get port%d sfp absent status, err: %d, status: 0x%x, out size: 0x%x\n",1356			port_id, err, sfp_abs.status, out_size);1357		return true;1358	}1359 1360	return ((sfp_abs.abs_status == 0) ? false : true);1361}1362 1363int hinic_get_sfp_eeprom(struct hinic_hwdev *hwdev, u8 *data, u16 *len)1364{1365	struct hinic_cmd_get_std_sfp_info sfp_info = {0};1366	u16 out_size = sizeof(sfp_info);1367	u8 port_id;1368	int err;1369 1370	if (!hwdev || !data || !len)1371		return -EINVAL;1372 1373	port_id = hwdev->port_id;1374 1375	if (hinic_if_sfp_absent(hwdev))1376		return -ENXIO;1377 1378	sfp_info.port_id = port_id;1379	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_STD_SFP_INFO,1380				 &sfp_info, sizeof(sfp_info), &sfp_info,1381				 &out_size);1382	if (sfp_info.status || err || !out_size) {1383		dev_err(&hwdev->hwif->pdev->dev,1384			"Failed to get port%d sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",1385			port_id, err, sfp_info.status, out_size);1386		return -EIO;1387	}1388 1389	*len = min_t(u16, sfp_info.eeprom_len, STD_SFP_INFO_MAX_SIZE);1390	memcpy(data, sfp_info.sfp_info, STD_SFP_INFO_MAX_SIZE);1391 1392	return 0;1393}1394 1395int hinic_get_sfp_type(struct hinic_hwdev *hwdev, u8 *data0, u8 *data1)1396{1397	u8 sfp_data[STD_SFP_INFO_MAX_SIZE];1398	u16 len;1399	int err;1400 1401	if (hinic_if_sfp_absent(hwdev))1402		return -ENXIO;1403 1404	err = hinic_get_sfp_eeprom(hwdev, sfp_data, &len);1405	if (err)1406		return err;1407 1408	*data0 = sfp_data[0];1409	*data1 = sfp_data[1];1410 1411	return 0;1412}1413