linux/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
<<
>>
Prefs
   1/*
   2 * Huawei HiNIC PCI Express Linux driver
   3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms and conditions of the GNU General Public License,
   7 * version 2, as published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12 * for more details.
  13 *
  14 */
  15
  16#include <linux/kernel.h>
  17#include <linux/types.h>
  18#include <linux/pci.h>
  19#include <linux/device.h>
  20#include <linux/errno.h>
  21#include <linux/slab.h>
  22#include <linux/bitops.h>
  23#include <linux/delay.h>
  24#include <linux/jiffies.h>
  25#include <linux/log2.h>
  26#include <linux/err.h>
  27
  28#include "hinic_hw_if.h"
  29#include "hinic_hw_eqs.h"
  30#include "hinic_hw_mgmt.h"
  31#include "hinic_hw_qp_ctxt.h"
  32#include "hinic_hw_qp.h"
  33#include "hinic_hw_io.h"
  34#include "hinic_hw_dev.h"
  35
  36#define IO_STATUS_TIMEOUT               100
  37#define OUTBOUND_STATE_TIMEOUT          100
  38#define DB_STATE_TIMEOUT                100
  39
  40#define MAX_IRQS(max_qps, num_aeqs, num_ceqs)   \
  41                 (2 * (max_qps) + (num_aeqs) + (num_ceqs))
  42
  43#define ADDR_IN_4BYTES(addr)            ((addr) >> 2)
  44
  45enum intr_type {
  46        INTR_MSIX_TYPE,
  47};
  48
  49enum io_status {
  50        IO_STOPPED = 0,
  51        IO_RUNNING = 1,
  52};
  53
  54enum hw_ioctxt_set_cmdq_depth {
  55        HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT,
  56};
  57
  58/* HW struct */
  59struct hinic_dev_cap {
  60        u8      status;
  61        u8      version;
  62        u8      rsvd0[6];
  63
  64        u8      rsvd1[5];
  65        u8      intr_type;
  66        u8      rsvd2[66];
  67        u16     max_sqs;
  68        u16     max_rqs;
  69        u8      rsvd3[208];
  70};
  71
  72/**
  73 * get_capability - convert device capabilities to NIC capabilities
  74 * @hwdev: the HW device to set and convert device capabilities for
  75 * @dev_cap: device capabilities from FW
  76 *
  77 * Return 0 - Success, negative - Failure
  78 **/
  79static int get_capability(struct hinic_hwdev *hwdev,
  80                          struct hinic_dev_cap *dev_cap)
  81{
  82        struct hinic_cap *nic_cap = &hwdev->nic_cap;
  83        int num_aeqs, num_ceqs, num_irqs;
  84
  85        if (!HINIC_IS_PF(hwdev->hwif) && !HINIC_IS_PPF(hwdev->hwif))
  86                return -EINVAL;
  87
  88        if (dev_cap->intr_type != INTR_MSIX_TYPE)
  89                return -EFAULT;
  90
  91        num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif);
  92        num_ceqs = HINIC_HWIF_NUM_CEQS(hwdev->hwif);
  93        num_irqs = HINIC_HWIF_NUM_IRQS(hwdev->hwif);
  94
  95        /* Each QP has its own (SQ + RQ) interrupts */
  96        nic_cap->num_qps = (num_irqs - (num_aeqs + num_ceqs)) / 2;
  97
  98        if (nic_cap->num_qps > HINIC_Q_CTXT_MAX)
  99                nic_cap->num_qps = HINIC_Q_CTXT_MAX;
 100
 101        /* num_qps must be power of 2 */
 102        nic_cap->num_qps = BIT(fls(nic_cap->num_qps) - 1);
 103
 104        nic_cap->max_qps = dev_cap->max_sqs + 1;
 105        if (nic_cap->max_qps != (dev_cap->max_rqs + 1))
 106                return -EFAULT;
 107
 108        if (nic_cap->num_qps > nic_cap->max_qps)
 109                nic_cap->num_qps = nic_cap->max_qps;
 110
 111        return 0;
 112}
 113
 114/**
 115 * get_cap_from_fw - get device capabilities from FW
 116 * @pfhwdev: the PF HW device to get capabilities for
 117 *
 118 * Return 0 - Success, negative - Failure
 119 **/
 120static int get_cap_from_fw(struct hinic_pfhwdev *pfhwdev)
 121{
 122        struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 123        struct hinic_hwif *hwif = hwdev->hwif;
 124        struct pci_dev *pdev = hwif->pdev;
 125        struct hinic_dev_cap dev_cap;
 126        u16 in_len, out_len;
 127        int err;
 128
 129        in_len = 0;
 130        out_len = sizeof(dev_cap);
 131
 132        err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_CFGM,
 133                                HINIC_CFG_NIC_CAP, &dev_cap, in_len, &dev_cap,
 134                                &out_len, HINIC_MGMT_MSG_SYNC);
 135        if (err) {
 136                dev_err(&pdev->dev, "Failed to get capability from FW\n");
 137                return err;
 138        }
 139
 140        return get_capability(hwdev, &dev_cap);
 141}
 142
 143/**
 144 * get_dev_cap - get device capabilities
 145 * @hwdev: the NIC HW device to get capabilities for
 146 *
 147 * Return 0 - Success, negative - Failure
 148 **/
 149static int get_dev_cap(struct hinic_hwdev *hwdev)
 150{
 151        struct hinic_hwif *hwif = hwdev->hwif;
 152        struct pci_dev *pdev = hwif->pdev;
 153        struct hinic_pfhwdev *pfhwdev;
 154        int err;
 155
 156        switch (HINIC_FUNC_TYPE(hwif)) {
 157        case HINIC_PPF:
 158        case HINIC_PF:
 159                pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 160
 161                err = get_cap_from_fw(pfhwdev);
 162                if (err) {
 163                        dev_err(&pdev->dev, "Failed to get capability from FW\n");
 164                        return err;
 165                }
 166                break;
 167
 168        default:
 169                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 170                return -EINVAL;
 171        }
 172
 173        return 0;
 174}
 175
 176/**
 177 * init_msix - enable the msix and save the entries
 178 * @hwdev: the NIC HW device
 179 *
 180 * Return 0 - Success, negative - Failure
 181 **/
 182static int init_msix(struct hinic_hwdev *hwdev)
 183{
 184        struct hinic_hwif *hwif = hwdev->hwif;
 185        struct pci_dev *pdev = hwif->pdev;
 186        int nr_irqs, num_aeqs, num_ceqs;
 187        size_t msix_entries_size;
 188        int i, err;
 189
 190        num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
 191        num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
 192        nr_irqs = MAX_IRQS(HINIC_MAX_QPS, num_aeqs, num_ceqs);
 193        if (nr_irqs > HINIC_HWIF_NUM_IRQS(hwif))
 194                nr_irqs = HINIC_HWIF_NUM_IRQS(hwif);
 195
 196        msix_entries_size = nr_irqs * sizeof(*hwdev->msix_entries);
 197        hwdev->msix_entries = devm_kzalloc(&pdev->dev, msix_entries_size,
 198                                           GFP_KERNEL);
 199        if (!hwdev->msix_entries)
 200                return -ENOMEM;
 201
 202        for (i = 0; i < nr_irqs; i++)
 203                hwdev->msix_entries[i].entry = i;
 204
 205        err = pci_enable_msix_exact(pdev, hwdev->msix_entries, nr_irqs);
 206        if (err) {
 207                dev_err(&pdev->dev, "Failed to enable pci msix\n");
 208                return err;
 209        }
 210
 211        return 0;
 212}
 213
 214/**
 215 * disable_msix - disable the msix
 216 * @hwdev: the NIC HW device
 217 **/
 218static void disable_msix(struct hinic_hwdev *hwdev)
 219{
 220        struct hinic_hwif *hwif = hwdev->hwif;
 221        struct pci_dev *pdev = hwif->pdev;
 222
 223        pci_disable_msix(pdev);
 224}
 225
 226/**
 227 * hinic_port_msg_cmd - send port msg to mgmt
 228 * @hwdev: the NIC HW device
 229 * @cmd: the port command
 230 * @buf_in: input buffer
 231 * @in_size: input size
 232 * @buf_out: output buffer
 233 * @out_size: returned output size
 234 *
 235 * Return 0 - Success, negative - Failure
 236 **/
 237int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd,
 238                       void *buf_in, u16 in_size, void *buf_out, u16 *out_size)
 239{
 240        struct hinic_hwif *hwif = hwdev->hwif;
 241        struct pci_dev *pdev = hwif->pdev;
 242        struct hinic_pfhwdev *pfhwdev;
 243
 244        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 245                dev_err(&pdev->dev, "unsupported PCI Function type\n");
 246                return -EINVAL;
 247        }
 248
 249        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 250
 251        return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd,
 252                                 buf_in, in_size, buf_out, out_size,
 253                                 HINIC_MGMT_MSG_SYNC);
 254}
 255
 256/**
 257 * init_fw_ctxt- Init Firmware tables before network mgmt and io operations
 258 * @hwdev: the NIC HW device
 259 *
 260 * Return 0 - Success, negative - Failure
 261 **/
 262static int init_fw_ctxt(struct hinic_hwdev *hwdev)
 263{
 264        struct hinic_hwif *hwif = hwdev->hwif;
 265        struct pci_dev *pdev = hwif->pdev;
 266        struct hinic_cmd_fw_ctxt fw_ctxt;
 267        struct hinic_pfhwdev *pfhwdev;
 268        u16 out_size;
 269        int err;
 270
 271        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 272                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 273                return -EINVAL;
 274        }
 275
 276        fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 277        fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ;
 278
 279        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 280
 281        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_FWCTXT_INIT,
 282                                 &fw_ctxt, sizeof(fw_ctxt),
 283                                 &fw_ctxt, &out_size);
 284        if (err || (out_size != sizeof(fw_ctxt)) || fw_ctxt.status) {
 285                dev_err(&pdev->dev, "Failed to init FW ctxt, ret = %d\n",
 286                        fw_ctxt.status);
 287                return -EFAULT;
 288        }
 289
 290        return 0;
 291}
 292
 293/**
 294 * set_hw_ioctxt - set the shape of the IO queues in FW
 295 * @hwdev: the NIC HW device
 296 * @rq_depth: rq depth
 297 * @sq_depth: sq depth
 298 *
 299 * Return 0 - Success, negative - Failure
 300 **/
 301static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth,
 302                         unsigned int sq_depth)
 303{
 304        struct hinic_hwif *hwif = hwdev->hwif;
 305        struct hinic_cmd_hw_ioctxt hw_ioctxt;
 306        struct pci_dev *pdev = hwif->pdev;
 307        struct hinic_pfhwdev *pfhwdev;
 308
 309        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 310                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 311                return -EINVAL;
 312        }
 313
 314        hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 315
 316        hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT;
 317        hw_ioctxt.cmdq_depth = 0;
 318
 319        hw_ioctxt.rq_depth  = ilog2(rq_depth);
 320
 321        hw_ioctxt.rx_buf_sz_idx = HINIC_RX_BUF_SZ_IDX;
 322
 323        hw_ioctxt.sq_depth  = ilog2(sq_depth);
 324
 325        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 326
 327        return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
 328                                 HINIC_COMM_CMD_HWCTXT_SET,
 329                                 &hw_ioctxt, sizeof(hw_ioctxt), NULL,
 330                                 NULL, HINIC_MGMT_MSG_SYNC);
 331}
 332
 333static int wait_for_outbound_state(struct hinic_hwdev *hwdev)
 334{
 335        enum hinic_outbound_state outbound_state;
 336        struct hinic_hwif *hwif = hwdev->hwif;
 337        struct pci_dev *pdev = hwif->pdev;
 338        unsigned long end;
 339
 340        end = jiffies + msecs_to_jiffies(OUTBOUND_STATE_TIMEOUT);
 341        do {
 342                outbound_state = hinic_outbound_state_get(hwif);
 343
 344                if (outbound_state == HINIC_OUTBOUND_ENABLE)
 345                        return 0;
 346
 347                msleep(20);
 348        } while (time_before(jiffies, end));
 349
 350        dev_err(&pdev->dev, "Wait for OUTBOUND - Timeout\n");
 351        return -EFAULT;
 352}
 353
 354static int wait_for_db_state(struct hinic_hwdev *hwdev)
 355{
 356        struct hinic_hwif *hwif = hwdev->hwif;
 357        struct pci_dev *pdev = hwif->pdev;
 358        enum hinic_db_state db_state;
 359        unsigned long end;
 360
 361        end = jiffies + msecs_to_jiffies(DB_STATE_TIMEOUT);
 362        do {
 363                db_state = hinic_db_state_get(hwif);
 364
 365                if (db_state == HINIC_DB_ENABLE)
 366                        return 0;
 367
 368                msleep(20);
 369        } while (time_before(jiffies, end));
 370
 371        dev_err(&pdev->dev, "Wait for DB - Timeout\n");
 372        return -EFAULT;
 373}
 374
 375static int wait_for_io_stopped(struct hinic_hwdev *hwdev)
 376{
 377        struct hinic_cmd_io_status cmd_io_status;
 378        struct hinic_hwif *hwif = hwdev->hwif;
 379        struct pci_dev *pdev = hwif->pdev;
 380        struct hinic_pfhwdev *pfhwdev;
 381        unsigned long end;
 382        u16 out_size;
 383        int err;
 384
 385        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 386                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 387                return -EINVAL;
 388        }
 389
 390        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 391
 392        cmd_io_status.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 393
 394        end = jiffies + msecs_to_jiffies(IO_STATUS_TIMEOUT);
 395        do {
 396                err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
 397                                        HINIC_COMM_CMD_IO_STATUS_GET,
 398                                        &cmd_io_status, sizeof(cmd_io_status),
 399                                        &cmd_io_status, &out_size,
 400                                        HINIC_MGMT_MSG_SYNC);
 401                if ((err) || (out_size != sizeof(cmd_io_status))) {
 402                        dev_err(&pdev->dev, "Failed to get IO status, ret = %d\n",
 403                                err);
 404                        return err;
 405                }
 406
 407                if (cmd_io_status.status == IO_STOPPED) {
 408                        dev_info(&pdev->dev, "IO stopped\n");
 409                        return 0;
 410                }
 411
 412                msleep(20);
 413        } while (time_before(jiffies, end));
 414
 415        dev_err(&pdev->dev, "Wait for IO stopped - Timeout\n");
 416        return -ETIMEDOUT;
 417}
 418
 419/**
 420 * clear_io_resource - set the IO resources as not active in the NIC
 421 * @hwdev: the NIC HW device
 422 *
 423 * Return 0 - Success, negative - Failure
 424 **/
 425static int clear_io_resources(struct hinic_hwdev *hwdev)
 426{
 427        struct hinic_cmd_clear_io_res cmd_clear_io_res;
 428        struct hinic_hwif *hwif = hwdev->hwif;
 429        struct pci_dev *pdev = hwif->pdev;
 430        struct hinic_pfhwdev *pfhwdev;
 431        int err;
 432
 433        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 434                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 435                return -EINVAL;
 436        }
 437
 438        err = wait_for_io_stopped(hwdev);
 439        if (err) {
 440                dev_err(&pdev->dev, "IO has not stopped yet\n");
 441                return err;
 442        }
 443
 444        cmd_clear_io_res.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 445
 446        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 447
 448        err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
 449                                HINIC_COMM_CMD_IO_RES_CLEAR, &cmd_clear_io_res,
 450                                sizeof(cmd_clear_io_res), NULL, NULL,
 451                                HINIC_MGMT_MSG_SYNC);
 452        if (err) {
 453                dev_err(&pdev->dev, "Failed to clear IO resources\n");
 454                return err;
 455        }
 456
 457        return 0;
 458}
 459
 460/**
 461 * set_resources_state - set the state of the resources in the NIC
 462 * @hwdev: the NIC HW device
 463 * @state: the state to set
 464 *
 465 * Return 0 - Success, negative - Failure
 466 **/
 467static int set_resources_state(struct hinic_hwdev *hwdev,
 468                               enum hinic_res_state state)
 469{
 470        struct hinic_cmd_set_res_state res_state;
 471        struct hinic_hwif *hwif = hwdev->hwif;
 472        struct pci_dev *pdev = hwif->pdev;
 473        struct hinic_pfhwdev *pfhwdev;
 474
 475        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 476                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 477                return -EINVAL;
 478        }
 479
 480        res_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 481        res_state.state = state;
 482
 483        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 484
 485        return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt,
 486                                 HINIC_MOD_COMM,
 487                                 HINIC_COMM_CMD_RES_STATE_SET,
 488                                 &res_state, sizeof(res_state), NULL,
 489                                 NULL, HINIC_MGMT_MSG_SYNC);
 490}
 491
 492/**
 493 * get_base_qpn - get the first qp number
 494 * @hwdev: the NIC HW device
 495 * @base_qpn: returned qp number
 496 *
 497 * Return 0 - Success, negative - Failure
 498 **/
 499static int get_base_qpn(struct hinic_hwdev *hwdev, u16 *base_qpn)
 500{
 501        struct hinic_cmd_base_qpn cmd_base_qpn;
 502        struct hinic_hwif *hwif = hwdev->hwif;
 503        struct pci_dev *pdev = hwif->pdev;
 504        u16 out_size;
 505        int err;
 506
 507        cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
 508
 509        err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_GET_GLOBAL_QPN,
 510                                 &cmd_base_qpn, sizeof(cmd_base_qpn),
 511                                 &cmd_base_qpn, &out_size);
 512        if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) {
 513                dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n",
 514                        cmd_base_qpn.status);
 515                return -EFAULT;
 516        }
 517
 518        *base_qpn = cmd_base_qpn.qpn;
 519        return 0;
 520}
 521
 522/**
 523 * hinic_hwdev_ifup - Preparing the HW for passing IO
 524 * @hwdev: the NIC HW device
 525 *
 526 * Return 0 - Success, negative - Failure
 527 **/
 528int hinic_hwdev_ifup(struct hinic_hwdev *hwdev)
 529{
 530        struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
 531        struct hinic_cap *nic_cap = &hwdev->nic_cap;
 532        struct hinic_hwif *hwif = hwdev->hwif;
 533        int err, num_aeqs, num_ceqs, num_qps;
 534        struct msix_entry *ceq_msix_entries;
 535        struct msix_entry *sq_msix_entries;
 536        struct msix_entry *rq_msix_entries;
 537        struct pci_dev *pdev = hwif->pdev;
 538        u16 base_qpn;
 539
 540        err = get_base_qpn(hwdev, &base_qpn);
 541        if (err) {
 542                dev_err(&pdev->dev, "Failed to get global base qp number\n");
 543                return err;
 544        }
 545
 546        num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
 547        num_ceqs = HINIC_HWIF_NUM_CEQS(hwif);
 548
 549        ceq_msix_entries = &hwdev->msix_entries[num_aeqs];
 550
 551        err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs,
 552                            ceq_msix_entries);
 553        if (err) {
 554                dev_err(&pdev->dev, "Failed to init IO channel\n");
 555                return err;
 556        }
 557
 558        num_qps = nic_cap->num_qps;
 559        sq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs];
 560        rq_msix_entries = &hwdev->msix_entries[num_aeqs + num_ceqs + num_qps];
 561
 562        err = hinic_io_create_qps(func_to_io, base_qpn, num_qps,
 563                                  sq_msix_entries, rq_msix_entries);
 564        if (err) {
 565                dev_err(&pdev->dev, "Failed to create QPs\n");
 566                goto err_create_qps;
 567        }
 568
 569        err = wait_for_db_state(hwdev);
 570        if (err) {
 571                dev_warn(&pdev->dev, "db - disabled, try again\n");
 572                hinic_db_state_set(hwif, HINIC_DB_ENABLE);
 573        }
 574
 575        err = set_hw_ioctxt(hwdev, HINIC_SQ_DEPTH, HINIC_RQ_DEPTH);
 576        if (err) {
 577                dev_err(&pdev->dev, "Failed to set HW IO ctxt\n");
 578                goto err_hw_ioctxt;
 579        }
 580
 581        return 0;
 582
 583err_hw_ioctxt:
 584        hinic_io_destroy_qps(func_to_io, num_qps);
 585
 586err_create_qps:
 587        hinic_io_free(func_to_io);
 588        return err;
 589}
 590
 591/**
 592 * hinic_hwdev_ifdown - Closing the HW for passing IO
 593 * @hwdev: the NIC HW device
 594 *
 595 **/
 596void hinic_hwdev_ifdown(struct hinic_hwdev *hwdev)
 597{
 598        struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
 599        struct hinic_cap *nic_cap = &hwdev->nic_cap;
 600
 601        clear_io_resources(hwdev);
 602
 603        hinic_io_destroy_qps(func_to_io, nic_cap->num_qps);
 604        hinic_io_free(func_to_io);
 605}
 606
 607/**
 608 * hinic_hwdev_cb_register - register callback handler for MGMT events
 609 * @hwdev: the NIC HW device
 610 * @cmd: the mgmt event
 611 * @handle: private data for the handler
 612 * @handler: event handler
 613 **/
 614void hinic_hwdev_cb_register(struct hinic_hwdev *hwdev,
 615                             enum hinic_mgmt_msg_cmd cmd, void *handle,
 616                             void (*handler)(void *handle, void *buf_in,
 617                                             u16 in_size, void *buf_out,
 618                                             u16 *out_size))
 619{
 620        struct hinic_hwif *hwif = hwdev->hwif;
 621        struct pci_dev *pdev = hwif->pdev;
 622        struct hinic_pfhwdev *pfhwdev;
 623        struct hinic_nic_cb *nic_cb;
 624        u8 cmd_cb;
 625
 626        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 627                dev_err(&pdev->dev, "unsupported PCI Function type\n");
 628                return;
 629        }
 630
 631        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 632
 633        cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
 634        nic_cb = &pfhwdev->nic_cb[cmd_cb];
 635
 636        nic_cb->handler = handler;
 637        nic_cb->handle = handle;
 638        nic_cb->cb_state = HINIC_CB_ENABLED;
 639}
 640
 641/**
 642 * hinic_hwdev_cb_unregister - unregister callback handler for MGMT events
 643 * @hwdev: the NIC HW device
 644 * @cmd: the mgmt event
 645 **/
 646void hinic_hwdev_cb_unregister(struct hinic_hwdev *hwdev,
 647                               enum hinic_mgmt_msg_cmd cmd)
 648{
 649        struct hinic_hwif *hwif = hwdev->hwif;
 650        struct pci_dev *pdev = hwif->pdev;
 651        struct hinic_pfhwdev *pfhwdev;
 652        struct hinic_nic_cb *nic_cb;
 653        u8 cmd_cb;
 654
 655        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 656                dev_err(&pdev->dev, "unsupported PCI Function type\n");
 657                return;
 658        }
 659
 660        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
 661
 662        cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
 663        nic_cb = &pfhwdev->nic_cb[cmd_cb];
 664
 665        nic_cb->cb_state &= ~HINIC_CB_ENABLED;
 666
 667        while (nic_cb->cb_state & HINIC_CB_RUNNING)
 668                schedule();
 669
 670        nic_cb->handler = NULL;
 671}
 672
 673/**
 674 * nic_mgmt_msg_handler - nic mgmt event handler
 675 * @handle: private data for the handler
 676 * @buf_in: input buffer
 677 * @in_size: input size
 678 * @buf_out: output buffer
 679 * @out_size: returned output size
 680 **/
 681static void nic_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in,
 682                                 u16 in_size, void *buf_out, u16 *out_size)
 683{
 684        struct hinic_pfhwdev *pfhwdev = handle;
 685        enum hinic_cb_state cb_state;
 686        struct hinic_nic_cb *nic_cb;
 687        struct hinic_hwdev *hwdev;
 688        struct hinic_hwif *hwif;
 689        struct pci_dev *pdev;
 690        u8 cmd_cb;
 691
 692        hwdev = &pfhwdev->hwdev;
 693        hwif = hwdev->hwif;
 694        pdev = hwif->pdev;
 695
 696        if ((cmd < HINIC_MGMT_MSG_CMD_BASE) ||
 697            (cmd >= HINIC_MGMT_MSG_CMD_MAX)) {
 698                dev_err(&pdev->dev, "unknown L2NIC event, cmd = %d\n", cmd);
 699                return;
 700        }
 701
 702        cmd_cb = cmd - HINIC_MGMT_MSG_CMD_BASE;
 703
 704        nic_cb = &pfhwdev->nic_cb[cmd_cb];
 705
 706        cb_state = cmpxchg(&nic_cb->cb_state,
 707                           HINIC_CB_ENABLED,
 708                           HINIC_CB_ENABLED | HINIC_CB_RUNNING);
 709
 710        if ((cb_state == HINIC_CB_ENABLED) && (nic_cb->handler))
 711                nic_cb->handler(nic_cb->handle, buf_in,
 712                                in_size, buf_out, out_size);
 713        else
 714                dev_err(&pdev->dev, "Unhandled NIC Event %d\n", cmd);
 715
 716        nic_cb->cb_state &= ~HINIC_CB_RUNNING;
 717}
 718
 719/**
 720 * init_pfhwdev - Initialize the extended components of PF
 721 * @pfhwdev: the HW device for PF
 722 *
 723 * Return 0 - success, negative - failure
 724 **/
 725static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
 726{
 727        struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 728        struct hinic_hwif *hwif = hwdev->hwif;
 729        struct pci_dev *pdev = hwif->pdev;
 730        int err;
 731
 732        err = hinic_pf_to_mgmt_init(&pfhwdev->pf_to_mgmt, hwif);
 733        if (err) {
 734                dev_err(&pdev->dev, "Failed to initialize PF to MGMT channel\n");
 735                return err;
 736        }
 737
 738        hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC,
 739                                   pfhwdev, nic_mgmt_msg_handler);
 740
 741        hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE);
 742        return 0;
 743}
 744
 745/**
 746 * free_pfhwdev - Free the extended components of PF
 747 * @pfhwdev: the HW device for PF
 748 **/
 749static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
 750{
 751        struct hinic_hwdev *hwdev = &pfhwdev->hwdev;
 752
 753        hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT);
 754
 755        hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC);
 756
 757        hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
 758}
 759
 760/**
 761 * hinic_init_hwdev - Initialize the NIC HW
 762 * @pdev: the NIC pci device
 763 *
 764 * Return initialized NIC HW device
 765 *
 766 * Initialize the NIC HW device and return a pointer to it
 767 **/
 768struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
 769{
 770        struct hinic_pfhwdev *pfhwdev;
 771        struct hinic_hwdev *hwdev;
 772        struct hinic_hwif *hwif;
 773        int err, num_aeqs;
 774
 775        hwif = devm_kzalloc(&pdev->dev, sizeof(*hwif), GFP_KERNEL);
 776        if (!hwif)
 777                return ERR_PTR(-ENOMEM);
 778
 779        err = hinic_init_hwif(hwif, pdev);
 780        if (err) {
 781                dev_err(&pdev->dev, "Failed to init HW interface\n");
 782                return ERR_PTR(err);
 783        }
 784
 785        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 786                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 787                err = -EFAULT;
 788                goto err_func_type;
 789        }
 790
 791        pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL);
 792        if (!pfhwdev) {
 793                err = -ENOMEM;
 794                goto err_pfhwdev_alloc;
 795        }
 796
 797        hwdev = &pfhwdev->hwdev;
 798        hwdev->hwif = hwif;
 799
 800        err = init_msix(hwdev);
 801        if (err) {
 802                dev_err(&pdev->dev, "Failed to init msix\n");
 803                goto err_init_msix;
 804        }
 805
 806        err = wait_for_outbound_state(hwdev);
 807        if (err) {
 808                dev_warn(&pdev->dev, "outbound - disabled, try again\n");
 809                hinic_outbound_state_set(hwif, HINIC_OUTBOUND_ENABLE);
 810        }
 811
 812        num_aeqs = HINIC_HWIF_NUM_AEQS(hwif);
 813
 814        err = hinic_aeqs_init(&hwdev->aeqs, hwif, num_aeqs,
 815                              HINIC_DEFAULT_AEQ_LEN, HINIC_EQ_PAGE_SIZE,
 816                              hwdev->msix_entries);
 817        if (err) {
 818                dev_err(&pdev->dev, "Failed to init async event queues\n");
 819                goto err_aeqs_init;
 820        }
 821
 822        err = init_pfhwdev(pfhwdev);
 823        if (err) {
 824                dev_err(&pdev->dev, "Failed to init PF HW device\n");
 825                goto err_init_pfhwdev;
 826        }
 827
 828        err = get_dev_cap(hwdev);
 829        if (err) {
 830                dev_err(&pdev->dev, "Failed to get device capabilities\n");
 831                goto err_dev_cap;
 832        }
 833
 834        err = init_fw_ctxt(hwdev);
 835        if (err) {
 836                dev_err(&pdev->dev, "Failed to init function table\n");
 837                goto err_init_fw_ctxt;
 838        }
 839
 840        err = set_resources_state(hwdev, HINIC_RES_ACTIVE);
 841        if (err) {
 842                dev_err(&pdev->dev, "Failed to set resources state\n");
 843                goto err_resources_state;
 844        }
 845
 846        return hwdev;
 847
 848err_resources_state:
 849err_init_fw_ctxt:
 850err_dev_cap:
 851        free_pfhwdev(pfhwdev);
 852
 853err_init_pfhwdev:
 854        hinic_aeqs_free(&hwdev->aeqs);
 855
 856err_aeqs_init:
 857        disable_msix(hwdev);
 858
 859err_init_msix:
 860err_pfhwdev_alloc:
 861err_func_type:
 862        hinic_free_hwif(hwif);
 863        return ERR_PTR(err);
 864}
 865
 866/**
 867 * hinic_free_hwdev - Free the NIC HW device
 868 * @hwdev: the NIC HW device
 869 **/
 870void hinic_free_hwdev(struct hinic_hwdev *hwdev)
 871{
 872        struct hinic_pfhwdev *pfhwdev = container_of(hwdev,
 873                                                     struct hinic_pfhwdev,
 874                                                     hwdev);
 875
 876        set_resources_state(hwdev, HINIC_RES_CLEAN);
 877
 878        free_pfhwdev(pfhwdev);
 879
 880        hinic_aeqs_free(&hwdev->aeqs);
 881
 882        disable_msix(hwdev);
 883
 884        hinic_free_hwif(hwdev->hwif);
 885}
 886
 887/**
 888 * hinic_hwdev_num_qps - return the number QPs available for use
 889 * @hwdev: the NIC HW device
 890 *
 891 * Return number QPs available for use
 892 **/
 893int hinic_hwdev_num_qps(struct hinic_hwdev *hwdev)
 894{
 895        struct hinic_cap *nic_cap = &hwdev->nic_cap;
 896
 897        return nic_cap->num_qps;
 898}
 899
 900/**
 901 * hinic_hwdev_get_sq - get SQ
 902 * @hwdev: the NIC HW device
 903 * @i: the position of the SQ
 904 *
 905 * Return: the SQ in the i position
 906 **/
 907struct hinic_sq *hinic_hwdev_get_sq(struct hinic_hwdev *hwdev, int i)
 908{
 909        struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
 910        struct hinic_qp *qp = &func_to_io->qps[i];
 911
 912        if (i >= hinic_hwdev_num_qps(hwdev))
 913                return NULL;
 914
 915        return &qp->sq;
 916}
 917
 918/**
 919 * hinic_hwdev_get_sq - get RQ
 920 * @hwdev: the NIC HW device
 921 * @i: the position of the RQ
 922 *
 923 * Return: the RQ in the i position
 924 **/
 925struct hinic_rq *hinic_hwdev_get_rq(struct hinic_hwdev *hwdev, int i)
 926{
 927        struct hinic_func_to_io *func_to_io = &hwdev->func_to_io;
 928        struct hinic_qp *qp = &func_to_io->qps[i];
 929
 930        if (i >= hinic_hwdev_num_qps(hwdev))
 931                return NULL;
 932
 933        return &qp->rq;
 934}
 935
 936/**
 937 * hinic_hwdev_msix_cnt_set - clear message attribute counters for msix entry
 938 * @hwdev: the NIC HW device
 939 * @msix_index: msix_index
 940 *
 941 * Return 0 - Success, negative - Failure
 942 **/
 943int hinic_hwdev_msix_cnt_set(struct hinic_hwdev *hwdev, u16 msix_index)
 944{
 945        return hinic_msix_attr_cnt_clear(hwdev->hwif, msix_index);
 946}
 947
 948/**
 949 * hinic_hwdev_msix_set - set message attribute for msix entry
 950 * @hwdev: the NIC HW device
 951 * @msix_index: msix_index
 952 * @pending_limit: the maximum pending interrupt events (unit 8)
 953 * @coalesc_timer: coalesc period for interrupt (unit 8 us)
 954 * @lli_timer: replenishing period for low latency credit (unit 8 us)
 955 * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
 956 * @resend_timer: maximum wait for resending msix (unit coalesc period)
 957 *
 958 * Return 0 - Success, negative - Failure
 959 **/
 960int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index,
 961                         u8 pending_limit, u8 coalesc_timer,
 962                         u8 lli_timer_cfg, u8 lli_credit_limit,
 963                         u8 resend_timer)
 964{
 965        return hinic_msix_attr_set(hwdev->hwif, msix_index,
 966                                   pending_limit, coalesc_timer,
 967                                   lli_timer_cfg, lli_credit_limit,
 968                                   resend_timer);
 969}
 970
 971/**
 972 * hinic_hwdev_hw_ci_addr_set - set cons idx addr and attributes in HW for sq
 973 * @hwdev: the NIC HW device
 974 * @sq: send queue
 975 * @pending_limit: the maximum pending update ci events (unit 8)
 976 * @coalesc_timer: coalesc period for update ci (unit 8 us)
 977 *
 978 * Return 0 - Success, negative - Failure
 979 **/
 980int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq,
 981                               u8 pending_limit, u8 coalesc_timer)
 982{
 983        struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq);
 984        struct hinic_hwif *hwif = hwdev->hwif;
 985        struct pci_dev *pdev = hwif->pdev;
 986        struct hinic_pfhwdev *pfhwdev;
 987        struct hinic_cmd_hw_ci hw_ci;
 988
 989        if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) {
 990                dev_err(&pdev->dev, "Unsupported PCI Function type\n");
 991                return -EINVAL;
 992        }
 993
 994        hw_ci.dma_attr_off  = 0;
 995        hw_ci.pending_limit = pending_limit;
 996        hw_ci.coalesc_timer = coalesc_timer;
 997
 998        hw_ci.msix_en = 1;
 999        hw_ci.msix_entry_idx = sq->msix_entry;
1000
1001        hw_ci.func_idx = HINIC_HWIF_FUNC_IDX(hwif);
1002
1003        hw_ci.sq_id = qp->q_id;
1004
1005        hw_ci.ci_addr = ADDR_IN_4BYTES(sq->hw_ci_dma_addr);
1006
1007        pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
1008        return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt,
1009                                 HINIC_MOD_COMM,
1010                                 HINIC_COMM_CMD_SQ_HI_CI_SET,
1011                                 &hw_ci, sizeof(hw_ci), NULL,
1012                                 NULL, HINIC_MGMT_MSG_SYNC);
1013}
1014