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 net_device *netdev = nic_dev->netdev;
  41        struct hinic_hwdev *hwdev = nic_dev->hwdev;
  42        struct hinic_port_mac_cmd port_mac_cmd;
  43        struct hinic_hwif *hwif = hwdev->hwif;
  44        struct pci_dev *pdev = hwif->pdev;
  45        enum hinic_port_cmd cmd;
  46        u16 out_size;
  47        int err;
  48
  49        if (vlan_id >= VLAN_N_VID) {
  50                netif_err(nic_dev, drv, netdev, "Invalid VLAN number\n");
  51                return -EINVAL;
  52        }
  53
  54        if (op == MAC_SET)
  55                cmd = HINIC_PORT_CMD_SET_MAC;
  56        else
  57                cmd = HINIC_PORT_CMD_DEL_MAC;
  58
  59        port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
  60        port_mac_cmd.vlan_id = vlan_id;
  61        memcpy(port_mac_cmd.mac, addr, ETH_ALEN);
  62
  63        err = hinic_port_msg_cmd(hwdev, cmd, &port_mac_cmd,
  64                                 sizeof(port_mac_cmd),
  65                                 &port_mac_cmd, &out_size);
  66        if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
  67                dev_err(&pdev->dev, "Failed to change MAC, ret = %d\n",
  68                        port_mac_cmd.status);
  69                return -EFAULT;
  70        }
  71
  72        return 0;
  73}
  74
  75/**
  76 * hinic_port_add_mac - add mac address
  77 * @nic_dev: nic device
  78 * @addr: mac address
  79 * @vlan_id: vlan number to set with the mac
  80 *
  81 * Return 0 - Success, negative - Failure
  82 **/
  83int hinic_port_add_mac(struct hinic_dev *nic_dev,
  84                       const u8 *addr, u16 vlan_id)
  85{
  86        return change_mac(nic_dev, addr, vlan_id, MAC_SET);
  87}
  88
  89/**
  90 * hinic_port_del_mac - remove mac address
  91 * @nic_dev: nic device
  92 * @addr: mac address
  93 * @vlan_id: vlan number that is connected to the mac
  94 *
  95 * Return 0 - Success, negative - Failure
  96 **/
  97int hinic_port_del_mac(struct hinic_dev *nic_dev, const u8 *addr,
  98                       u16 vlan_id)
  99{
 100        return change_mac(nic_dev, addr, vlan_id, MAC_DEL);
 101}
 102
 103/**
 104 * hinic_port_get_mac - get the mac address of the nic device
 105 * @nic_dev: nic device
 106 * @addr: returned mac address
 107 *
 108 * Return 0 - Success, negative - Failure
 109 **/
 110int hinic_port_get_mac(struct hinic_dev *nic_dev, u8 *addr)
 111{
 112        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 113        struct hinic_port_mac_cmd port_mac_cmd;
 114        struct hinic_hwif *hwif = hwdev->hwif;
 115        struct pci_dev *pdev = hwif->pdev;
 116        u16 out_size;
 117        int err;
 118
 119        port_mac_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 120
 121        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MAC,
 122                                 &port_mac_cmd, sizeof(port_mac_cmd),
 123                                 &port_mac_cmd, &out_size);
 124        if (err || (out_size != sizeof(port_mac_cmd)) || port_mac_cmd.status) {
 125                dev_err(&pdev->dev, "Failed to get mac, ret = %d\n",
 126                        port_mac_cmd.status);
 127                return -EFAULT;
 128        }
 129
 130        memcpy(addr, port_mac_cmd.mac, ETH_ALEN);
 131        return 0;
 132}
 133
 134/**
 135 * hinic_port_set_mtu - set mtu
 136 * @nic_dev: nic device
 137 * @new_mtu: new mtu
 138 *
 139 * Return 0 - Success, negative - Failure
 140 **/
 141int hinic_port_set_mtu(struct hinic_dev *nic_dev, int new_mtu)
 142{
 143        struct net_device *netdev = nic_dev->netdev;
 144        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 145        struct hinic_port_mtu_cmd port_mtu_cmd;
 146        struct hinic_hwif *hwif = hwdev->hwif;
 147        struct pci_dev *pdev = hwif->pdev;
 148        int err, max_frame;
 149        u16 out_size;
 150
 151        if (new_mtu < HINIC_MIN_MTU_SIZE) {
 152                netif_err(nic_dev, drv, netdev, "mtu < MIN MTU size");
 153                return -EINVAL;
 154        }
 155
 156        max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 157        if (max_frame > HINIC_MAX_JUMBO_FRAME_SIZE) {
 158                netif_err(nic_dev, drv, netdev, "mtu > MAX MTU size");
 159                return -EINVAL;
 160        }
 161
 162        port_mtu_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 163        port_mtu_cmd.mtu = new_mtu;
 164
 165        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
 166                                 &port_mtu_cmd, sizeof(port_mtu_cmd),
 167                                 &port_mtu_cmd, &out_size);
 168        if (err || (out_size != sizeof(port_mtu_cmd)) || port_mtu_cmd.status) {
 169                dev_err(&pdev->dev, "Failed to set mtu, ret = %d\n",
 170                        port_mtu_cmd.status);
 171                return -EFAULT;
 172        }
 173
 174        return 0;
 175}
 176
 177/**
 178 * hinic_port_add_vlan - add vlan to the nic device
 179 * @nic_dev: nic device
 180 * @vlan_id: the vlan number to add
 181 *
 182 * Return 0 - Success, negative - Failure
 183 **/
 184int hinic_port_add_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
 185{
 186        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 187        struct hinic_port_vlan_cmd port_vlan_cmd;
 188
 189        port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
 190        port_vlan_cmd.vlan_id = vlan_id;
 191
 192        return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ADD_VLAN,
 193                                  &port_vlan_cmd, sizeof(port_vlan_cmd),
 194                                  NULL, NULL);
 195}
 196
 197/**
 198 * hinic_port_del_vlan - delete vlan from the nic device
 199 * @nic_dev: nic device
 200 * @vlan_id: the vlan number to delete
 201 *
 202 * Return 0 - Success, negative - Failure
 203 **/
 204int hinic_port_del_vlan(struct hinic_dev *nic_dev, u16 vlan_id)
 205{
 206        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 207        struct hinic_port_vlan_cmd port_vlan_cmd;
 208
 209        port_vlan_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
 210        port_vlan_cmd.vlan_id = vlan_id;
 211
 212        return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_DEL_VLAN,
 213                                 &port_vlan_cmd, sizeof(port_vlan_cmd),
 214                                 NULL, NULL);
 215}
 216
 217/**
 218 * hinic_port_set_rx_mode - set rx mode in the nic device
 219 * @nic_dev: nic device
 220 * @rx_mode: the rx mode to set
 221 *
 222 * Return 0 - Success, negative - Failure
 223 **/
 224int hinic_port_set_rx_mode(struct hinic_dev *nic_dev, u32 rx_mode)
 225{
 226        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 227        struct hinic_port_rx_mode_cmd rx_mode_cmd;
 228
 229        rx_mode_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
 230        rx_mode_cmd.rx_mode = rx_mode;
 231
 232        return hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
 233                                  &rx_mode_cmd, sizeof(rx_mode_cmd),
 234                                  NULL, NULL);
 235}
 236
 237/**
 238 * hinic_port_link_state - get the link state
 239 * @nic_dev: nic device
 240 * @link_state: the returned link state
 241 *
 242 * Return 0 - Success, negative - Failure
 243 **/
 244int hinic_port_link_state(struct hinic_dev *nic_dev,
 245                          enum hinic_port_link_state *link_state)
 246{
 247        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 248        struct hinic_hwif *hwif = hwdev->hwif;
 249        struct hinic_port_link_cmd link_cmd;
 250        struct pci_dev *pdev = hwif->pdev;
 251        u16 out_size;
 252        int err;
 253
 254        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 255                dev_err(&pdev->dev, "unsupported PCI Function type\n");
 256                return -EINVAL;
 257        }
 258
 259        link_cmd.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 260
 261        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
 262                                 &link_cmd, sizeof(link_cmd),
 263                                 &link_cmd, &out_size);
 264        if (err || (out_size != sizeof(link_cmd)) || link_cmd.status) {
 265                dev_err(&pdev->dev, "Failed to get link state, ret = %d\n",
 266                        link_cmd.status);
 267                return -EINVAL;
 268        }
 269
 270        *link_state = link_cmd.state;
 271        return 0;
 272}
 273
 274/**
 275 * hinic_port_set_state - set port state
 276 * @nic_dev: nic device
 277 * @state: the state to set
 278 *
 279 * Return 0 - Success, negative - Failure
 280 **/
 281int hinic_port_set_state(struct hinic_dev *nic_dev, enum hinic_port_state state)
 282{
 283        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 284        struct hinic_port_state_cmd port_state;
 285        struct hinic_hwif *hwif = hwdev->hwif;
 286        struct pci_dev *pdev = hwif->pdev;
 287        u16 out_size;
 288        int err;
 289
 290        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 291                dev_err(&pdev->dev, "unsupported PCI Function type\n");
 292                return -EINVAL;
 293        }
 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, ret = %d\n",
 302                        port_state.status);
 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;
 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, ret = %d\n",
 334                        func_state.status);
 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;
 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, ret = %d\n",
 365                        port_cap->status);
 366                return -EINVAL;
 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;
 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, ret = %d\n",
 397                        tso_cfg.status);
 398                return -EINVAL;
 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        struct hinic_hwif *hwif;
 409        struct pci_dev *pdev;
 410        u16 out_size;
 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, ret = %d\n",
 427                        rx_csum_cfg.status);
 428                return -EINVAL;
 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        hwif = hwdev->hwif;
 447        pdev = hwif->pdev;
 448        vlan_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 449        vlan_cfg.vlan_rx_offload = en;
 450
 451        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
 452                                 &vlan_cfg, sizeof(vlan_cfg),
 453                                 &vlan_cfg, &out_size);
 454        if (err || !out_size || vlan_cfg.status) {
 455                dev_err(&pdev->dev,
 456                        "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
 457                        err, vlan_cfg.status, out_size);
 458                return -EINVAL;
 459        }
 460
 461        return 0;
 462}
 463
 464int hinic_set_max_qnum(struct hinic_dev *nic_dev, u8 num_rqs)
 465{
 466        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 467        struct hinic_hwif *hwif = hwdev->hwif;
 468        struct pci_dev *pdev = hwif->pdev;
 469        struct hinic_rq_num rq_num = { 0 };
 470        u16 out_size = sizeof(rq_num);
 471        int err;
 472
 473        rq_num.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 474        rq_num.num_rqs = num_rqs;
 475        rq_num.rq_depth = ilog2(HINIC_SQ_DEPTH);
 476
 477        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RQ_IQ_MAP,
 478                                 &rq_num, sizeof(rq_num),
 479                                 &rq_num, &out_size);
 480        if (err || !out_size || rq_num.status) {
 481                dev_err(&pdev->dev,
 482                        "Failed to rxq number, ret = %d\n",
 483                        rq_num.status);
 484                return -EINVAL;
 485        }
 486
 487        return 0;
 488}
 489
 490static int hinic_set_rx_lro(struct hinic_dev *nic_dev, u8 ipv4_en, u8 ipv6_en,
 491                            u8 max_wqe_num)
 492{
 493        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 494        struct hinic_hwif *hwif = hwdev->hwif;
 495        struct hinic_lro_config lro_cfg = { 0 };
 496        struct pci_dev *pdev = hwif->pdev;
 497        u16 out_size = sizeof(lro_cfg);
 498        int err;
 499
 500        lro_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 501        lro_cfg.lro_ipv4_en = ipv4_en;
 502        lro_cfg.lro_ipv6_en = ipv6_en;
 503        lro_cfg.lro_max_wqe_num = max_wqe_num;
 504
 505        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO,
 506                                 &lro_cfg, sizeof(lro_cfg),
 507                                 &lro_cfg, &out_size);
 508        if (err || !out_size || lro_cfg.status) {
 509                dev_err(&pdev->dev,
 510                        "Failed to set lro offload, ret = %d\n",
 511                        lro_cfg.status);
 512                return -EINVAL;
 513        }
 514
 515        return 0;
 516}
 517
 518static int hinic_set_rx_lro_timer(struct hinic_dev *nic_dev, u32 timer_value)
 519{
 520        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 521        struct hinic_lro_timer lro_timer = { 0 };
 522        struct hinic_hwif *hwif = hwdev->hwif;
 523        struct pci_dev *pdev = hwif->pdev;
 524        u16 out_size = sizeof(lro_timer);
 525        int err;
 526
 527        lro_timer.status = 0;
 528        lro_timer.type = 0;
 529        lro_timer.enable = 1;
 530        lro_timer.timer = timer_value;
 531
 532        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_LRO_TIMER,
 533                                 &lro_timer, sizeof(lro_timer),
 534                                 &lro_timer, &out_size);
 535        if (lro_timer.status == 0xFF) {
 536                /* For this case, we think status (0xFF) is OK */
 537                lro_timer.status = 0;
 538                dev_dbg(&pdev->dev,
 539                        "Set lro timer not supported by the current FW version, it will be 1ms default\n");
 540        }
 541
 542        if (err || !out_size || lro_timer.status) {
 543                dev_err(&pdev->dev,
 544                        "Failed to set lro timer, ret = %d\n",
 545                        lro_timer.status);
 546
 547                return -EINVAL;
 548        }
 549
 550        return 0;
 551}
 552
 553int hinic_set_rx_lro_state(struct hinic_dev *nic_dev, u8 lro_en,
 554                           u32 lro_timer, u32 wqe_num)
 555{
 556        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 557        u8 ipv4_en;
 558        u8 ipv6_en;
 559        int err;
 560
 561        if (!hwdev)
 562                return -EINVAL;
 563
 564        ipv4_en = lro_en ? 1 : 0;
 565        ipv6_en = lro_en ? 1 : 0;
 566
 567        err = hinic_set_rx_lro(nic_dev, ipv4_en, ipv6_en, (u8)wqe_num);
 568        if (err)
 569                return err;
 570
 571        err = hinic_set_rx_lro_timer(nic_dev, lro_timer);
 572        if (err)
 573                return err;
 574
 575        return 0;
 576}
 577
 578int hinic_rss_set_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
 579                            const u32 *indir_table)
 580{
 581        struct hinic_rss_indirect_tbl *indir_tbl;
 582        struct hinic_func_to_io *func_to_io;
 583        struct hinic_cmdq_buf cmd_buf;
 584        struct hinic_hwdev *hwdev;
 585        struct hinic_hwif *hwif;
 586        struct pci_dev *pdev;
 587        u32 indir_size;
 588        u64 out_param;
 589        int err, i;
 590        u32 *temp;
 591
 592        hwdev = nic_dev->hwdev;
 593        func_to_io = &hwdev->func_to_io;
 594        hwif = hwdev->hwif;
 595        pdev = hwif->pdev;
 596
 597        err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
 598        if (err) {
 599                dev_err(&pdev->dev, "Failed to allocate cmdq buf\n");
 600                return err;
 601        }
 602
 603        cmd_buf.size = sizeof(*indir_tbl);
 604
 605        indir_tbl = cmd_buf.buf;
 606        indir_tbl->group_index = cpu_to_be32(tmpl_idx);
 607
 608        for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
 609                indir_tbl->entry[i] = indir_table[i];
 610
 611                if (0x3 == (i & 0x3)) {
 612                        temp = (u32 *)&indir_tbl->entry[i - 3];
 613                        *temp = cpu_to_be32(*temp);
 614                }
 615        }
 616
 617        /* cfg the rss indirect table by command queue */
 618        indir_size = HINIC_RSS_INDIR_SIZE / 2;
 619        indir_tbl->offset = 0;
 620        indir_tbl->size = cpu_to_be32(indir_size);
 621
 622        err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
 623                                     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
 624                                     &cmd_buf, &out_param);
 625        if (err || out_param != 0) {
 626                dev_err(&pdev->dev, "Failed to set rss indir table\n");
 627                err = -EFAULT;
 628                goto free_buf;
 629        }
 630
 631        indir_tbl->offset = cpu_to_be32(indir_size);
 632        indir_tbl->size = cpu_to_be32(indir_size);
 633        memcpy(&indir_tbl->entry[0], &indir_tbl->entry[indir_size], indir_size);
 634
 635        err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
 636                                     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
 637                                     &cmd_buf, &out_param);
 638        if (err || out_param != 0) {
 639                dev_err(&pdev->dev, "Failed to set rss indir table\n");
 640                err = -EFAULT;
 641        }
 642
 643free_buf:
 644        hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
 645
 646        return err;
 647}
 648
 649int hinic_rss_get_indir_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
 650                            u32 *indir_table)
 651{
 652        struct hinic_rss_indir_table rss_cfg = { 0 };
 653        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 654        struct hinic_hwif *hwif = hwdev->hwif;
 655        struct pci_dev *pdev = hwif->pdev;
 656        u16 out_size = sizeof(rss_cfg);
 657        int err = 0, i;
 658
 659        rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 660        rss_cfg.template_id = tmpl_idx;
 661
 662        err = hinic_port_msg_cmd(hwdev,
 663                                 HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
 664                                 &rss_cfg, sizeof(rss_cfg), &rss_cfg,
 665                                 &out_size);
 666        if (err || !out_size || rss_cfg.status) {
 667                dev_err(&pdev->dev, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x\n",
 668                        err, rss_cfg.status, out_size);
 669                return -EINVAL;
 670        }
 671
 672        hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
 673        for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
 674                indir_table[i] = rss_cfg.indir[i];
 675
 676        return 0;
 677}
 678
 679int hinic_set_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
 680                       struct hinic_rss_type rss_type)
 681{
 682        struct hinic_rss_context_tbl *ctx_tbl;
 683        struct hinic_func_to_io *func_to_io;
 684        struct hinic_cmdq_buf cmd_buf;
 685        struct hinic_hwdev *hwdev;
 686        struct hinic_hwif *hwif;
 687        struct pci_dev *pdev;
 688        u64 out_param;
 689        u32 ctx = 0;
 690        int err;
 691
 692        hwdev = nic_dev->hwdev;
 693        func_to_io = &hwdev->func_to_io;
 694        hwif = hwdev->hwif;
 695        pdev = hwif->pdev;
 696
 697        err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
 698        if (err) {
 699                dev_err(&pdev->dev, "Failed to allocate cmd buf\n");
 700                return -ENOMEM;
 701        }
 702
 703        ctx |=  HINIC_RSS_TYPE_SET(1, VALID) |
 704                HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
 705                HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
 706                HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
 707                HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
 708                HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
 709                HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
 710                HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
 711                HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
 712
 713        cmd_buf.size = sizeof(struct hinic_rss_context_tbl);
 714
 715        ctx_tbl = (struct hinic_rss_context_tbl *)cmd_buf.buf;
 716        ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
 717        ctx_tbl->offset = 0;
 718        ctx_tbl->size = sizeof(u32);
 719        ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
 720        ctx_tbl->rsvd = 0;
 721        ctx_tbl->ctx = cpu_to_be32(ctx);
 722
 723        /* cfg the rss context table by command queue */
 724        err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC,
 725                                     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
 726                                     &cmd_buf, &out_param);
 727
 728        hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmd_buf);
 729
 730        if (err || out_param != 0) {
 731                dev_err(&pdev->dev, "Failed to set rss context table, err: %d\n",
 732                        err);
 733                return -EFAULT;
 734        }
 735
 736        return 0;
 737}
 738
 739int hinic_get_rss_type(struct hinic_dev *nic_dev, u32 tmpl_idx,
 740                       struct hinic_rss_type *rss_type)
 741{
 742        struct hinic_rss_context_table ctx_tbl = { 0 };
 743        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 744        struct hinic_hwif *hwif;
 745        struct pci_dev *pdev;
 746        u16 out_size = sizeof(ctx_tbl);
 747        int err;
 748
 749        if (!hwdev || !rss_type)
 750                return -EINVAL;
 751
 752        hwif = hwdev->hwif;
 753        pdev = hwif->pdev;
 754
 755        ctx_tbl.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 756        ctx_tbl.template_id = tmpl_idx;
 757
 758        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
 759                                 &ctx_tbl, sizeof(ctx_tbl),
 760                                 &ctx_tbl, &out_size);
 761        if (err || !out_size || ctx_tbl.status) {
 762                dev_err(&pdev->dev, "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x\n",
 763                        err, ctx_tbl.status, out_size);
 764                return -EINVAL;
 765        }
 766
 767        rss_type->ipv4          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
 768        rss_type->ipv6          = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
 769        rss_type->ipv6_ext      = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
 770        rss_type->tcp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
 771        rss_type->tcp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
 772        rss_type->tcp_ipv6_ext  = HINIC_RSS_TYPE_GET(ctx_tbl.context,
 773                                                     TCP_IPV6_EXT);
 774        rss_type->udp_ipv4      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
 775        rss_type->udp_ipv6      = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
 776
 777        return 0;
 778}
 779
 780int hinic_rss_set_template_tbl(struct hinic_dev *nic_dev, u32 template_id,
 781                               const u8 *temp)
 782{
 783        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 784        struct hinic_hwif *hwif = hwdev->hwif;
 785        struct hinic_rss_key rss_key = { 0 };
 786        struct pci_dev *pdev = hwif->pdev;
 787        u16 out_size;
 788        int err;
 789
 790        rss_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 791        rss_key.template_id = template_id;
 792        memcpy(rss_key.key, temp, HINIC_RSS_KEY_SIZE);
 793
 794        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
 795                                 &rss_key, sizeof(rss_key),
 796                                 &rss_key, &out_size);
 797        if (err || !out_size || rss_key.status) {
 798                dev_err(&pdev->dev,
 799                        "Failed to set rss hash key, err: %d, status: 0x%x, out size: 0x%x\n",
 800                        err, rss_key.status, out_size);
 801                return -EINVAL;
 802        }
 803
 804        return 0;
 805}
 806
 807int hinic_rss_get_template_tbl(struct hinic_dev *nic_dev, u32 tmpl_idx,
 808                               u8 *temp)
 809{
 810        struct hinic_rss_template_key temp_key = { 0 };
 811        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 812        struct hinic_hwif *hwif;
 813        struct pci_dev *pdev;
 814        u16 out_size = sizeof(temp_key);
 815        int err;
 816
 817        if (!hwdev || !temp)
 818                return -EINVAL;
 819
 820        hwif = hwdev->hwif;
 821        pdev = hwif->pdev;
 822
 823        temp_key.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 824        temp_key.template_id = tmpl_idx;
 825
 826        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
 827                                 &temp_key, sizeof(temp_key),
 828                                 &temp_key, &out_size);
 829        if (err || !out_size || temp_key.status) {
 830                dev_err(&pdev->dev, "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x\n",
 831                        err, temp_key.status, out_size);
 832                return -EINVAL;
 833        }
 834
 835        memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
 836
 837        return 0;
 838}
 839
 840int hinic_rss_set_hash_engine(struct hinic_dev *nic_dev, u8 template_id,
 841                              u8 type)
 842{
 843        struct hinic_rss_engine_type rss_engine = { 0 };
 844        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 845        struct hinic_hwif *hwif = hwdev->hwif;
 846        struct pci_dev *pdev = hwif->pdev;
 847        u16 out_size;
 848        int err;
 849
 850        rss_engine.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 851        rss_engine.hash_engine = type;
 852        rss_engine.template_id = template_id;
 853
 854        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
 855                                 &rss_engine, sizeof(rss_engine),
 856                                 &rss_engine, &out_size);
 857        if (err || !out_size || rss_engine.status) {
 858                dev_err(&pdev->dev,
 859                        "Failed to set hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
 860                        err, rss_engine.status, out_size);
 861                return -EINVAL;
 862        }
 863
 864        return 0;
 865}
 866
 867int hinic_rss_get_hash_engine(struct hinic_dev *nic_dev, u8 tmpl_idx, u8 *type)
 868{
 869        struct hinic_rss_engine_type hash_type = { 0 };
 870        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 871        struct hinic_hwif *hwif;
 872        struct pci_dev *pdev;
 873        u16 out_size = sizeof(hash_type);
 874        int err;
 875
 876        if (!hwdev || !type)
 877                return -EINVAL;
 878
 879        hwif = hwdev->hwif;
 880        pdev = hwif->pdev;
 881
 882        hash_type.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 883        hash_type.template_id = tmpl_idx;
 884
 885        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_RSS_HASH_ENGINE,
 886                                 &hash_type, sizeof(hash_type),
 887                                 &hash_type, &out_size);
 888        if (err || !out_size || hash_type.status) {
 889                dev_err(&pdev->dev, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x\n",
 890                        err, hash_type.status, out_size);
 891                return -EINVAL;
 892        }
 893
 894        *type = hash_type.hash_engine;
 895        return 0;
 896}
 897
 898int hinic_rss_cfg(struct hinic_dev *nic_dev, u8 rss_en, u8 template_id)
 899{
 900        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 901        struct hinic_rss_config rss_cfg = { 0 };
 902        struct hinic_hwif *hwif = hwdev->hwif;
 903        struct pci_dev *pdev = hwif->pdev;
 904        u16 out_size;
 905        int err;
 906
 907        rss_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 908        rss_cfg.rss_en = rss_en;
 909        rss_cfg.template_id = template_id;
 910        rss_cfg.rq_priority_number = 0;
 911
 912        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_CFG,
 913                                 &rss_cfg, sizeof(rss_cfg),
 914                                 &rss_cfg, &out_size);
 915        if (err || !out_size || rss_cfg.status) {
 916                dev_err(&pdev->dev,
 917                        "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x\n",
 918                        err, rss_cfg.status, out_size);
 919                return -EINVAL;
 920        }
 921
 922        return 0;
 923}
 924
 925int hinic_rss_template_alloc(struct hinic_dev *nic_dev, u8 *tmpl_idx)
 926{
 927        struct hinic_rss_template_mgmt template_mgmt = { 0 };
 928        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 929        struct hinic_hwif *hwif = hwdev->hwif;
 930        struct pci_dev *pdev = hwif->pdev;
 931        u16 out_size;
 932        int err;
 933
 934        template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 935        template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
 936
 937        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
 938                                 &template_mgmt, sizeof(template_mgmt),
 939                                 &template_mgmt, &out_size);
 940        if (err || !out_size || template_mgmt.status) {
 941                dev_err(&pdev->dev, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x\n",
 942                        err, template_mgmt.status, out_size);
 943                return -EINVAL;
 944        }
 945
 946        *tmpl_idx = template_mgmt.template_id;
 947
 948        return 0;
 949}
 950
 951int hinic_rss_template_free(struct hinic_dev *nic_dev, u8 tmpl_idx)
 952{
 953        struct hinic_rss_template_mgmt template_mgmt = { 0 };
 954        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 955        struct hinic_hwif *hwif = hwdev->hwif;
 956        struct pci_dev *pdev = hwif->pdev;
 957        u16 out_size;
 958        int err;
 959
 960        template_mgmt.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 961        template_mgmt.template_id = tmpl_idx;
 962        template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
 963
 964        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
 965                                 &template_mgmt, sizeof(template_mgmt),
 966                                 &template_mgmt, &out_size);
 967        if (err || !out_size || template_mgmt.status) {
 968                dev_err(&pdev->dev, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x\n",
 969                        err, template_mgmt.status, out_size);
 970                return -EINVAL;
 971        }
 972
 973        return 0;
 974}
 975
 976int hinic_get_vport_stats(struct hinic_dev *nic_dev,
 977                          struct hinic_vport_stats *stats)
 978{
 979        struct hinic_cmd_vport_stats vport_stats = { 0 };
 980        struct hinic_port_stats_info stats_info = { 0 };
 981        struct hinic_hwdev *hwdev = nic_dev->hwdev;
 982        struct hinic_hwif *hwif = hwdev->hwif;
 983        u16 out_size = sizeof(vport_stats);
 984        struct pci_dev *pdev = hwif->pdev;
 985        int err;
 986
 987        stats_info.stats_version = HINIC_PORT_STATS_VERSION;
 988        stats_info.func_id = HINIC_HWIF_FUNC_IDX(hwif);
 989        stats_info.stats_size = sizeof(vport_stats);
 990
 991        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
 992                                 &stats_info, sizeof(stats_info),
 993                                 &vport_stats, &out_size);
 994        if (err || !out_size || vport_stats.status) {
 995                dev_err(&pdev->dev,
 996                        "Failed to get function statistics, err: %d, status: 0x%x, out size: 0x%x\n",
 997                        err, vport_stats.status, out_size);
 998                return -EFAULT;
 999        }
1000
1001        memcpy(stats, &vport_stats.stats, sizeof(*stats));
1002        return 0;
1003}
1004
1005int hinic_get_phy_port_stats(struct hinic_dev *nic_dev,
1006                             struct hinic_phy_port_stats *stats)
1007{
1008        struct hinic_port_stats_info stats_info = { 0 };
1009        struct hinic_hwdev *hwdev = nic_dev->hwdev;
1010        struct hinic_hwif *hwif = hwdev->hwif;
1011        struct hinic_port_stats *port_stats;
1012        u16 out_size = sizeof(*port_stats);
1013        struct pci_dev *pdev = hwif->pdev;
1014        int err;
1015
1016        port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
1017        if (!port_stats)
1018                return -ENOMEM;
1019
1020        stats_info.stats_version = HINIC_PORT_STATS_VERSION;
1021        stats_info.stats_size = sizeof(*port_stats);
1022
1023        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
1024                                 &stats_info, sizeof(stats_info),
1025                                 port_stats, &out_size);
1026        if (err || !out_size || port_stats->status) {
1027                dev_err(&pdev->dev,
1028                        "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
1029                        err, port_stats->status, out_size);
1030                err = -EINVAL;
1031                goto out;
1032        }
1033
1034        memcpy(stats, &port_stats->stats, sizeof(*stats));
1035
1036out:
1037        kfree(port_stats);
1038
1039        return err;
1040}
1041
1042int hinic_get_mgmt_version(struct hinic_dev *nic_dev, u8 *mgmt_ver)
1043{
1044        struct hinic_hwdev *hwdev = nic_dev->hwdev;
1045        struct hinic_version_info up_ver = {0};
1046        struct hinic_hwif *hwif;
1047        struct pci_dev *pdev;
1048        u16 out_size;
1049        int err;
1050
1051        if (!hwdev)
1052                return -EINVAL;
1053
1054        hwif = hwdev->hwif;
1055        pdev = hwif->pdev;
1056
1057        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION,
1058                                 &up_ver, sizeof(up_ver), &up_ver,
1059                                 &out_size);
1060        if (err || !out_size || up_ver.status) {
1061                dev_err(&pdev->dev,
1062                        "Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x\n",
1063                        err, up_ver.status, out_size);
1064                return -EINVAL;
1065        }
1066
1067        snprintf(mgmt_ver, HINIC_MGMT_VERSION_MAX_LEN, "%s", up_ver.ver);
1068
1069        return 0;
1070}
1071