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