File Index
Files and directories
Sign in
FILE

hinic_port.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/huawei/hinic/hinic_port.c C
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Huawei HiNIC PCI Express Linux driver
   4 * Copyright(c) 2017 Huawei Technologies Co., Ltd
   5 */
   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 address
  27 * @nic_dev: nic device
  28 * @addr: mac address
  29 * @vlan_id: vlan number to set with the mac
  30 * @op: add or delete the mac
  31 *
  32 * Return 0 - Success, negative - Failure
  33 **/
  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	else
  48		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 address
  81 * @nic_dev: nic device
  82 * @addr: mac address
  83 * @vlan_id: vlan number to set with the mac
  84 *
  85 * Return 0 - Success, negative - Failure
  86 **/
  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 address
  95 * @nic_dev: nic device
  96 * @addr: mac address
  97 * @vlan_id: vlan number that is connected to the mac
  98 *
  99 * Return 0 - Success, negative - Failure
 100 **/
 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 device
 109 * @nic_dev: nic device
 110 * @addr: returned mac address
 111 *
 112 * Return 0 - Success, negative - Failure
 113 **/
 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 mtu
 140 * @nic_dev: nic device
 141 * @new_mtu: new mtu
 142 *
 143 * Return 0 - Success, negative - Failure
 144 **/
 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 device
 171 * @nic_dev: nic device
 172 * @vlan_id: the vlan number to add
 173 *
 174 * Return 0 - Success, negative - Failure
 175 **/
 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 device
 191 * @nic_dev: nic device
 192 * @vlan_id: the vlan number to delete
 193 *
 194 * Return 0 - Success, negative - Failure
 195 **/
 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 device
 211 * @nic_dev: nic device
 212 * @rx_mode: the rx mode to set
 213 *
 214 * Return 0 - Success, negative - Failure
 215 **/
 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 state
 231 * @nic_dev: nic device
 232 * @link_state: the returned link state
 233 *
 234 * Return 0 - Success, negative - Failure
 235 **/
 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 state
 263 * @nic_dev: nic device
 264 * @state: the state to set
 265 *
 266 * Return 0 - Success, negative - Failure
 267 **/
 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 state
 296 * @nic_dev: nic device
 297 * @state: the state to set
 298 *
 299 * Return 0 - Success, negative - Failure
 300 **/
 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 capabilities
 328 * @nic_dev: nic device
 329 * @port_cap: returned port capabilities
 330 *
 331 * Return 0 - Success, negative - Failure
 332 **/
 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 configuration
 359 * @nic_dev: nic device
 360 * @state: the tso state to set
 361 *
 362 * Return 0 - Success, negative - Failure
 363 **/
 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 filter, 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}
~/ Read-only file preview.