| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Huawei HiNIC PCI Express Linux driver |
|---|
| 3 | 4 | * 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 | 5 | */ |
|---|
| 15 | 6 | |
|---|
| 16 | 7 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 24 | 15 | #include <linux/jiffies.h> |
|---|
| 25 | 16 | #include <linux/log2.h> |
|---|
| 26 | 17 | #include <linux/err.h> |
|---|
| 18 | +#include <linux/netdevice.h> |
|---|
| 19 | +#include <net/devlink.h> |
|---|
| 27 | 20 | |
|---|
| 21 | +#include "hinic_devlink.h" |
|---|
| 22 | +#include "hinic_sriov.h" |
|---|
| 23 | +#include "hinic_dev.h" |
|---|
| 28 | 24 | #include "hinic_hw_if.h" |
|---|
| 29 | 25 | #include "hinic_hw_eqs.h" |
|---|
| 30 | 26 | #include "hinic_hw_mgmt.h" |
|---|
| .. | .. |
|---|
| 51 | 47 | IO_RUNNING = 1, |
|---|
| 52 | 48 | }; |
|---|
| 53 | 49 | |
|---|
| 54 | | -enum hw_ioctxt_set_cmdq_depth { |
|---|
| 55 | | - HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT, |
|---|
| 56 | | -}; |
|---|
| 57 | | - |
|---|
| 58 | | -/* HW struct */ |
|---|
| 59 | | -struct 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 | 50 | /** |
|---|
| 73 | 51 | * get_capability - convert device capabilities to NIC capabilities |
|---|
| 74 | 52 | * @hwdev: the HW device to set and convert device capabilities for |
|---|
| .. | .. |
|---|
| 76 | 54 | * |
|---|
| 77 | 55 | * Return 0 - Success, negative - Failure |
|---|
| 78 | 56 | **/ |
|---|
| 79 | | -static int get_capability(struct hinic_hwdev *hwdev, |
|---|
| 80 | | - struct hinic_dev_cap *dev_cap) |
|---|
| 57 | +static int parse_capability(struct hinic_hwdev *hwdev, |
|---|
| 58 | + struct hinic_dev_cap *dev_cap) |
|---|
| 81 | 59 | { |
|---|
| 82 | 60 | struct hinic_cap *nic_cap = &hwdev->nic_cap; |
|---|
| 83 | 61 | int num_aeqs, num_ceqs, num_irqs; |
|---|
| 84 | 62 | |
|---|
| 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) |
|---|
| 63 | + if (!HINIC_IS_VF(hwdev->hwif) && dev_cap->intr_type != INTR_MSIX_TYPE) |
|---|
| 89 | 64 | return -EFAULT; |
|---|
| 90 | 65 | |
|---|
| 91 | 66 | num_aeqs = HINIC_HWIF_NUM_AEQS(hwdev->hwif); |
|---|
| .. | .. |
|---|
| 98 | 73 | if (nic_cap->num_qps > HINIC_Q_CTXT_MAX) |
|---|
| 99 | 74 | nic_cap->num_qps = HINIC_Q_CTXT_MAX; |
|---|
| 100 | 75 | |
|---|
| 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; |
|---|
| 76 | + if (!HINIC_IS_VF(hwdev->hwif)) |
|---|
| 77 | + nic_cap->max_qps = dev_cap->max_sqs + 1; |
|---|
| 78 | + else |
|---|
| 79 | + nic_cap->max_qps = dev_cap->max_sqs; |
|---|
| 107 | 80 | |
|---|
| 108 | 81 | if (nic_cap->num_qps > nic_cap->max_qps) |
|---|
| 109 | 82 | nic_cap->num_qps = nic_cap->max_qps; |
|---|
| 83 | + |
|---|
| 84 | + if (!HINIC_IS_VF(hwdev->hwif)) { |
|---|
| 85 | + nic_cap->max_vf = dev_cap->max_vf; |
|---|
| 86 | + nic_cap->max_vf_qps = dev_cap->max_vf_sqs + 1; |
|---|
| 87 | + } |
|---|
| 88 | + |
|---|
| 89 | + hwdev->port_id = dev_cap->port_id; |
|---|
| 110 | 90 | |
|---|
| 111 | 91 | return 0; |
|---|
| 112 | 92 | } |
|---|
| .. | .. |
|---|
| 117 | 97 | * |
|---|
| 118 | 98 | * Return 0 - Success, negative - Failure |
|---|
| 119 | 99 | **/ |
|---|
| 120 | | -static int get_cap_from_fw(struct hinic_pfhwdev *pfhwdev) |
|---|
| 100 | +static int get_capability(struct hinic_pfhwdev *pfhwdev) |
|---|
| 121 | 101 | { |
|---|
| 122 | 102 | struct hinic_hwdev *hwdev = &pfhwdev->hwdev; |
|---|
| 123 | 103 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 124 | 104 | struct pci_dev *pdev = hwif->pdev; |
|---|
| 125 | 105 | struct hinic_dev_cap dev_cap; |
|---|
| 126 | | - u16 in_len, out_len; |
|---|
| 106 | + u16 out_len; |
|---|
| 127 | 107 | int err; |
|---|
| 128 | 108 | |
|---|
| 129 | | - in_len = 0; |
|---|
| 130 | 109 | out_len = sizeof(dev_cap); |
|---|
| 131 | 110 | |
|---|
| 132 | 111 | 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); |
|---|
| 112 | + HINIC_CFG_NIC_CAP, &dev_cap, sizeof(dev_cap), |
|---|
| 113 | + &dev_cap, &out_len, HINIC_MGMT_MSG_SYNC); |
|---|
| 135 | 114 | if (err) { |
|---|
| 136 | 115 | dev_err(&pdev->dev, "Failed to get capability from FW\n"); |
|---|
| 137 | 116 | return err; |
|---|
| 138 | 117 | } |
|---|
| 139 | 118 | |
|---|
| 140 | | - return get_capability(hwdev, &dev_cap); |
|---|
| 119 | + return parse_capability(hwdev, &dev_cap); |
|---|
| 141 | 120 | } |
|---|
| 142 | 121 | |
|---|
| 143 | 122 | /** |
|---|
| .. | .. |
|---|
| 156 | 135 | switch (HINIC_FUNC_TYPE(hwif)) { |
|---|
| 157 | 136 | case HINIC_PPF: |
|---|
| 158 | 137 | case HINIC_PF: |
|---|
| 138 | + case HINIC_VF: |
|---|
| 159 | 139 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 160 | | - |
|---|
| 161 | | - err = get_cap_from_fw(pfhwdev); |
|---|
| 140 | + err = get_capability(pfhwdev); |
|---|
| 162 | 141 | if (err) { |
|---|
| 163 | | - dev_err(&pdev->dev, "Failed to get capability from FW\n"); |
|---|
| 142 | + dev_err(&pdev->dev, "Failed to get capability\n"); |
|---|
| 164 | 143 | return err; |
|---|
| 165 | 144 | } |
|---|
| 166 | 145 | break; |
|---|
| 167 | | - |
|---|
| 168 | 146 | default: |
|---|
| 169 | 147 | dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 170 | 148 | return -EINVAL; |
|---|
| .. | .. |
|---|
| 184 | 162 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 185 | 163 | struct pci_dev *pdev = hwif->pdev; |
|---|
| 186 | 164 | int nr_irqs, num_aeqs, num_ceqs; |
|---|
| 187 | | - size_t msix_entries_size; |
|---|
| 188 | 165 | int i, err; |
|---|
| 189 | 166 | |
|---|
| 190 | 167 | num_aeqs = HINIC_HWIF_NUM_AEQS(hwif); |
|---|
| .. | .. |
|---|
| 193 | 170 | if (nr_irqs > HINIC_HWIF_NUM_IRQS(hwif)) |
|---|
| 194 | 171 | nr_irqs = HINIC_HWIF_NUM_IRQS(hwif); |
|---|
| 195 | 172 | |
|---|
| 196 | | - msix_entries_size = nr_irqs * sizeof(*hwdev->msix_entries); |
|---|
| 197 | | - hwdev->msix_entries = devm_kzalloc(&pdev->dev, msix_entries_size, |
|---|
| 173 | + hwdev->msix_entries = devm_kcalloc(&pdev->dev, nr_irqs, |
|---|
| 174 | + sizeof(*hwdev->msix_entries), |
|---|
| 198 | 175 | GFP_KERNEL); |
|---|
| 199 | 176 | if (!hwdev->msix_entries) |
|---|
| 200 | 177 | return -ENOMEM; |
|---|
| .. | .. |
|---|
| 237 | 214 | int hinic_port_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_port_cmd cmd, |
|---|
| 238 | 215 | void *buf_in, u16 in_size, void *buf_out, u16 *out_size) |
|---|
| 239 | 216 | { |
|---|
| 240 | | - struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 241 | | - struct pci_dev *pdev = hwif->pdev; |
|---|
| 242 | 217 | 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 | 218 | |
|---|
| 249 | 219 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 250 | 220 | |
|---|
| 251 | 221 | return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, cmd, |
|---|
| 222 | + buf_in, in_size, buf_out, out_size, |
|---|
| 223 | + HINIC_MGMT_MSG_SYNC); |
|---|
| 224 | +} |
|---|
| 225 | + |
|---|
| 226 | +int hinic_hilink_msg_cmd(struct hinic_hwdev *hwdev, enum hinic_hilink_cmd cmd, |
|---|
| 227 | + void *buf_in, u16 in_size, void *buf_out, |
|---|
| 228 | + u16 *out_size) |
|---|
| 229 | +{ |
|---|
| 230 | + struct hinic_pfhwdev *pfhwdev; |
|---|
| 231 | + |
|---|
| 232 | + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 233 | + |
|---|
| 234 | + return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_HILINK, cmd, |
|---|
| 252 | 235 | buf_in, in_size, buf_out, out_size, |
|---|
| 253 | 236 | HINIC_MGMT_MSG_SYNC); |
|---|
| 254 | 237 | } |
|---|
| .. | .. |
|---|
| 264 | 247 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 265 | 248 | struct pci_dev *pdev = hwif->pdev; |
|---|
| 266 | 249 | struct hinic_cmd_fw_ctxt fw_ctxt; |
|---|
| 267 | | - u16 out_size; |
|---|
| 250 | + u16 out_size = sizeof(fw_ctxt); |
|---|
| 268 | 251 | int err; |
|---|
| 269 | | - |
|---|
| 270 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 271 | | - dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 272 | | - return -EINVAL; |
|---|
| 273 | | - } |
|---|
| 274 | 252 | |
|---|
| 275 | 253 | fw_ctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); |
|---|
| 276 | 254 | fw_ctxt.rx_buf_sz = HINIC_RX_BUF_SZ; |
|---|
| .. | .. |
|---|
| 279 | 257 | &fw_ctxt, sizeof(fw_ctxt), |
|---|
| 280 | 258 | &fw_ctxt, &out_size); |
|---|
| 281 | 259 | if (err || (out_size != sizeof(fw_ctxt)) || fw_ctxt.status) { |
|---|
| 282 | | - dev_err(&pdev->dev, "Failed to init FW ctxt, ret = %d\n", |
|---|
| 283 | | - fw_ctxt.status); |
|---|
| 284 | | - return -EFAULT; |
|---|
| 260 | + dev_err(&pdev->dev, "Failed to init FW ctxt, err: %d, status: 0x%x, out size: 0x%x\n", |
|---|
| 261 | + err, fw_ctxt.status, out_size); |
|---|
| 262 | + return -EIO; |
|---|
| 285 | 263 | } |
|---|
| 286 | 264 | |
|---|
| 287 | 265 | return 0; |
|---|
| .. | .. |
|---|
| 295 | 273 | * |
|---|
| 296 | 274 | * Return 0 - Success, negative - Failure |
|---|
| 297 | 275 | **/ |
|---|
| 298 | | -static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int rq_depth, |
|---|
| 299 | | - unsigned int sq_depth) |
|---|
| 276 | +static int set_hw_ioctxt(struct hinic_hwdev *hwdev, unsigned int sq_depth, |
|---|
| 277 | + unsigned int rq_depth) |
|---|
| 300 | 278 | { |
|---|
| 301 | 279 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 302 | 280 | struct hinic_cmd_hw_ioctxt hw_ioctxt; |
|---|
| 303 | | - struct pci_dev *pdev = hwif->pdev; |
|---|
| 304 | 281 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 305 | | - |
|---|
| 306 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 307 | | - dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 308 | | - return -EINVAL; |
|---|
| 309 | | - } |
|---|
| 310 | 282 | |
|---|
| 311 | 283 | hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwif); |
|---|
| 312 | 284 | hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwif); |
|---|
| 313 | 285 | |
|---|
| 314 | 286 | hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT; |
|---|
| 315 | 287 | hw_ioctxt.cmdq_depth = 0; |
|---|
| 288 | + |
|---|
| 289 | + hw_ioctxt.lro_en = 1; |
|---|
| 316 | 290 | |
|---|
| 317 | 291 | hw_ioctxt.rq_depth = ilog2(rq_depth); |
|---|
| 318 | 292 | |
|---|
| .. | .. |
|---|
| 384 | 358 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 385 | 359 | int err; |
|---|
| 386 | 360 | |
|---|
| 387 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 388 | | - dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 389 | | - return -EINVAL; |
|---|
| 390 | | - } |
|---|
| 391 | | - |
|---|
| 392 | 361 | /* sleep 100ms to wait for firmware stopping I/O */ |
|---|
| 393 | 362 | msleep(100); |
|---|
| 394 | 363 | |
|---|
| .. | .. |
|---|
| 420 | 389 | { |
|---|
| 421 | 390 | struct hinic_cmd_set_res_state res_state; |
|---|
| 422 | 391 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 423 | | - struct pci_dev *pdev = hwif->pdev; |
|---|
| 424 | 392 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 425 | | - |
|---|
| 426 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 427 | | - dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 428 | | - return -EINVAL; |
|---|
| 429 | | - } |
|---|
| 430 | 393 | |
|---|
| 431 | 394 | res_state.func_idx = HINIC_HWIF_FUNC_IDX(hwif); |
|---|
| 432 | 395 | res_state.state = state; |
|---|
| .. | .. |
|---|
| 451 | 414 | { |
|---|
| 452 | 415 | struct hinic_cmd_base_qpn cmd_base_qpn; |
|---|
| 453 | 416 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 417 | + u16 out_size = sizeof(cmd_base_qpn); |
|---|
| 454 | 418 | struct pci_dev *pdev = hwif->pdev; |
|---|
| 455 | | - u16 out_size; |
|---|
| 456 | 419 | int err; |
|---|
| 457 | 420 | |
|---|
| 458 | 421 | cmd_base_qpn.func_idx = HINIC_HWIF_FUNC_IDX(hwif); |
|---|
| .. | .. |
|---|
| 461 | 424 | &cmd_base_qpn, sizeof(cmd_base_qpn), |
|---|
| 462 | 425 | &cmd_base_qpn, &out_size); |
|---|
| 463 | 426 | if (err || (out_size != sizeof(cmd_base_qpn)) || cmd_base_qpn.status) { |
|---|
| 464 | | - dev_err(&pdev->dev, "Failed to get base qpn, status = %d\n", |
|---|
| 465 | | - cmd_base_qpn.status); |
|---|
| 466 | | - return -EFAULT; |
|---|
| 427 | + dev_err(&pdev->dev, "Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x\n", |
|---|
| 428 | + err, cmd_base_qpn.status, out_size); |
|---|
| 429 | + return -EIO; |
|---|
| 467 | 430 | } |
|---|
| 468 | 431 | |
|---|
| 469 | 432 | *base_qpn = cmd_base_qpn.qpn; |
|---|
| .. | .. |
|---|
| 473 | 436 | /** |
|---|
| 474 | 437 | * hinic_hwdev_ifup - Preparing the HW for passing IO |
|---|
| 475 | 438 | * @hwdev: the NIC HW device |
|---|
| 439 | + * @sq_depth: the send queue depth |
|---|
| 440 | + * @rq_depth: the receive queue depth |
|---|
| 476 | 441 | * |
|---|
| 477 | 442 | * Return 0 - Success, negative - Failure |
|---|
| 478 | 443 | **/ |
|---|
| 479 | | -int hinic_hwdev_ifup(struct hinic_hwdev *hwdev) |
|---|
| 444 | +int hinic_hwdev_ifup(struct hinic_hwdev *hwdev, u16 sq_depth, u16 rq_depth) |
|---|
| 480 | 445 | { |
|---|
| 481 | 446 | struct hinic_func_to_io *func_to_io = &hwdev->func_to_io; |
|---|
| 482 | 447 | struct hinic_cap *nic_cap = &hwdev->nic_cap; |
|---|
| .. | .. |
|---|
| 498 | 463 | num_ceqs = HINIC_HWIF_NUM_CEQS(hwif); |
|---|
| 499 | 464 | |
|---|
| 500 | 465 | ceq_msix_entries = &hwdev->msix_entries[num_aeqs]; |
|---|
| 466 | + func_to_io->hwdev = hwdev; |
|---|
| 467 | + func_to_io->sq_depth = sq_depth; |
|---|
| 468 | + func_to_io->rq_depth = rq_depth; |
|---|
| 469 | + func_to_io->global_qpn = base_qpn; |
|---|
| 501 | 470 | |
|---|
| 502 | 471 | err = hinic_io_init(func_to_io, hwif, nic_cap->max_qps, num_ceqs, |
|---|
| 503 | 472 | ceq_msix_entries); |
|---|
| .. | .. |
|---|
| 523 | 492 | hinic_db_state_set(hwif, HINIC_DB_ENABLE); |
|---|
| 524 | 493 | } |
|---|
| 525 | 494 | |
|---|
| 526 | | - err = set_hw_ioctxt(hwdev, HINIC_SQ_DEPTH, HINIC_RQ_DEPTH); |
|---|
| 495 | + err = set_hw_ioctxt(hwdev, sq_depth, rq_depth); |
|---|
| 527 | 496 | if (err) { |
|---|
| 528 | 497 | dev_err(&pdev->dev, "Failed to set HW IO ctxt\n"); |
|---|
| 529 | 498 | goto err_hw_ioctxt; |
|---|
| .. | .. |
|---|
| 568 | 537 | u16 in_size, void *buf_out, |
|---|
| 569 | 538 | u16 *out_size)) |
|---|
| 570 | 539 | { |
|---|
| 571 | | - struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 572 | | - struct pci_dev *pdev = hwif->pdev; |
|---|
| 573 | 540 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 574 | 541 | struct hinic_nic_cb *nic_cb; |
|---|
| 575 | 542 | u8 cmd_cb; |
|---|
| 576 | | - |
|---|
| 577 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 578 | | - dev_err(&pdev->dev, "unsupported PCI Function type\n"); |
|---|
| 579 | | - return; |
|---|
| 580 | | - } |
|---|
| 581 | 543 | |
|---|
| 582 | 544 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 583 | 545 | |
|---|
| .. | .. |
|---|
| 598 | 560 | enum hinic_mgmt_msg_cmd cmd) |
|---|
| 599 | 561 | { |
|---|
| 600 | 562 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 601 | | - struct pci_dev *pdev = hwif->pdev; |
|---|
| 602 | 563 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 603 | 564 | struct hinic_nic_cb *nic_cb; |
|---|
| 604 | 565 | u8 cmd_cb; |
|---|
| 605 | 566 | |
|---|
| 606 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 607 | | - dev_err(&pdev->dev, "unsupported PCI Function type\n"); |
|---|
| 567 | + if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) |
|---|
| 608 | 568 | return; |
|---|
| 609 | | - } |
|---|
| 610 | 569 | |
|---|
| 611 | 570 | pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 612 | 571 | |
|---|
| .. | .. |
|---|
| 624 | 583 | /** |
|---|
| 625 | 584 | * nic_mgmt_msg_handler - nic mgmt event handler |
|---|
| 626 | 585 | * @handle: private data for the handler |
|---|
| 586 | + * @cmd: message command |
|---|
| 627 | 587 | * @buf_in: input buffer |
|---|
| 628 | 588 | * @in_size: input size |
|---|
| 629 | 589 | * @buf_out: output buffer |
|---|
| .. | .. |
|---|
| 667 | 627 | nic_cb->cb_state &= ~HINIC_CB_RUNNING; |
|---|
| 668 | 628 | } |
|---|
| 669 | 629 | |
|---|
| 630 | +static void hinic_comm_recv_mgmt_self_cmd_reg(struct hinic_pfhwdev *pfhwdev, |
|---|
| 631 | + u8 cmd, |
|---|
| 632 | + comm_mgmt_self_msg_proc proc) |
|---|
| 633 | +{ |
|---|
| 634 | + u8 cmd_idx; |
|---|
| 635 | + |
|---|
| 636 | + cmd_idx = pfhwdev->proc.cmd_num; |
|---|
| 637 | + if (cmd_idx >= HINIC_COMM_SELF_CMD_MAX) { |
|---|
| 638 | + dev_err(&pfhwdev->hwdev.hwif->pdev->dev, |
|---|
| 639 | + "Register recv mgmt process failed, cmd: 0x%x\n", cmd); |
|---|
| 640 | + return; |
|---|
| 641 | + } |
|---|
| 642 | + |
|---|
| 643 | + pfhwdev->proc.info[cmd_idx].cmd = cmd; |
|---|
| 644 | + pfhwdev->proc.info[cmd_idx].proc = proc; |
|---|
| 645 | + pfhwdev->proc.cmd_num++; |
|---|
| 646 | +} |
|---|
| 647 | + |
|---|
| 648 | +static void hinic_comm_recv_mgmt_self_cmd_unreg(struct hinic_pfhwdev *pfhwdev, |
|---|
| 649 | + u8 cmd) |
|---|
| 650 | +{ |
|---|
| 651 | + u8 cmd_idx; |
|---|
| 652 | + |
|---|
| 653 | + cmd_idx = pfhwdev->proc.cmd_num; |
|---|
| 654 | + if (cmd_idx >= HINIC_COMM_SELF_CMD_MAX) { |
|---|
| 655 | + dev_err(&pfhwdev->hwdev.hwif->pdev->dev, "Unregister recv mgmt process failed, cmd: 0x%x\n", |
|---|
| 656 | + cmd); |
|---|
| 657 | + return; |
|---|
| 658 | + } |
|---|
| 659 | + |
|---|
| 660 | + for (cmd_idx = 0; cmd_idx < HINIC_COMM_SELF_CMD_MAX; cmd_idx++) { |
|---|
| 661 | + if (cmd == pfhwdev->proc.info[cmd_idx].cmd) { |
|---|
| 662 | + pfhwdev->proc.info[cmd_idx].cmd = 0; |
|---|
| 663 | + pfhwdev->proc.info[cmd_idx].proc = NULL; |
|---|
| 664 | + pfhwdev->proc.cmd_num--; |
|---|
| 665 | + } |
|---|
| 666 | + } |
|---|
| 667 | +} |
|---|
| 668 | + |
|---|
| 669 | +static void comm_mgmt_msg_handler(void *handle, u8 cmd, void *buf_in, |
|---|
| 670 | + u16 in_size, void *buf_out, u16 *out_size) |
|---|
| 671 | +{ |
|---|
| 672 | + struct hinic_pfhwdev *pfhwdev = handle; |
|---|
| 673 | + u8 cmd_idx; |
|---|
| 674 | + |
|---|
| 675 | + for (cmd_idx = 0; cmd_idx < pfhwdev->proc.cmd_num; cmd_idx++) { |
|---|
| 676 | + if (cmd == pfhwdev->proc.info[cmd_idx].cmd) { |
|---|
| 677 | + if (!pfhwdev->proc.info[cmd_idx].proc) { |
|---|
| 678 | + dev_warn(&pfhwdev->hwdev.hwif->pdev->dev, |
|---|
| 679 | + "PF recv mgmt comm msg handle null, cmd: 0x%x\n", |
|---|
| 680 | + cmd); |
|---|
| 681 | + } else { |
|---|
| 682 | + pfhwdev->proc.info[cmd_idx].proc |
|---|
| 683 | + (&pfhwdev->hwdev, buf_in, in_size, |
|---|
| 684 | + buf_out, out_size); |
|---|
| 685 | + } |
|---|
| 686 | + |
|---|
| 687 | + return; |
|---|
| 688 | + } |
|---|
| 689 | + } |
|---|
| 690 | + |
|---|
| 691 | + dev_warn(&pfhwdev->hwdev.hwif->pdev->dev, "Received unknown mgmt cpu event: 0x%x\n", |
|---|
| 692 | + cmd); |
|---|
| 693 | + |
|---|
| 694 | + *out_size = 0; |
|---|
| 695 | +} |
|---|
| 696 | + |
|---|
| 697 | +/* pf fault report event */ |
|---|
| 698 | +static void pf_fault_event_handler(void *dev, void *buf_in, u16 in_size, |
|---|
| 699 | + void *buf_out, u16 *out_size) |
|---|
| 700 | +{ |
|---|
| 701 | + struct hinic_cmd_fault_event *fault_event = buf_in; |
|---|
| 702 | + struct hinic_hwdev *hwdev = dev; |
|---|
| 703 | + |
|---|
| 704 | + if (in_size != sizeof(*fault_event)) { |
|---|
| 705 | + dev_err(&hwdev->hwif->pdev->dev, "Invalid fault event report, length: %d, should be %zu\n", |
|---|
| 706 | + in_size, sizeof(*fault_event)); |
|---|
| 707 | + return; |
|---|
| 708 | + } |
|---|
| 709 | + |
|---|
| 710 | + if (!hwdev->devlink_dev || IS_ERR_OR_NULL(hwdev->devlink_dev->hw_fault_reporter)) |
|---|
| 711 | + return; |
|---|
| 712 | + |
|---|
| 713 | + devlink_health_report(hwdev->devlink_dev->hw_fault_reporter, |
|---|
| 714 | + "HW fatal error reported", &fault_event->event); |
|---|
| 715 | +} |
|---|
| 716 | + |
|---|
| 717 | +static void mgmt_watchdog_timeout_event_handler(void *dev, |
|---|
| 718 | + void *buf_in, u16 in_size, |
|---|
| 719 | + void *buf_out, u16 *out_size) |
|---|
| 720 | +{ |
|---|
| 721 | + struct hinic_mgmt_watchdog_info *watchdog_info = buf_in; |
|---|
| 722 | + struct hinic_hwdev *hwdev = dev; |
|---|
| 723 | + |
|---|
| 724 | + if (in_size != sizeof(*watchdog_info)) { |
|---|
| 725 | + dev_err(&hwdev->hwif->pdev->dev, "Invalid mgmt watchdog report, length: %d, should be %zu\n", |
|---|
| 726 | + in_size, sizeof(*watchdog_info)); |
|---|
| 727 | + return; |
|---|
| 728 | + } |
|---|
| 729 | + |
|---|
| 730 | + if (!hwdev->devlink_dev || IS_ERR_OR_NULL(hwdev->devlink_dev->fw_fault_reporter)) |
|---|
| 731 | + return; |
|---|
| 732 | + |
|---|
| 733 | + devlink_health_report(hwdev->devlink_dev->fw_fault_reporter, |
|---|
| 734 | + "FW fatal error reported", watchdog_info); |
|---|
| 735 | +} |
|---|
| 736 | + |
|---|
| 670 | 737 | /** |
|---|
| 671 | 738 | * init_pfhwdev - Initialize the extended components of PF |
|---|
| 672 | 739 | * @pfhwdev: the HW device for PF |
|---|
| .. | .. |
|---|
| 686 | 753 | return err; |
|---|
| 687 | 754 | } |
|---|
| 688 | 755 | |
|---|
| 689 | | - hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC, |
|---|
| 690 | | - pfhwdev, nic_mgmt_msg_handler); |
|---|
| 756 | + err = hinic_devlink_register(hwdev->devlink_dev, &pdev->dev); |
|---|
| 757 | + if (err) { |
|---|
| 758 | + dev_err(&hwif->pdev->dev, "Failed to register devlink\n"); |
|---|
| 759 | + hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt); |
|---|
| 760 | + return err; |
|---|
| 761 | + } |
|---|
| 762 | + |
|---|
| 763 | + err = hinic_func_to_func_init(hwdev); |
|---|
| 764 | + if (err) { |
|---|
| 765 | + dev_err(&hwif->pdev->dev, "Failed to init mailbox\n"); |
|---|
| 766 | + hinic_devlink_unregister(hwdev->devlink_dev); |
|---|
| 767 | + hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt); |
|---|
| 768 | + return err; |
|---|
| 769 | + } |
|---|
| 770 | + |
|---|
| 771 | + if (!HINIC_IS_VF(hwif)) { |
|---|
| 772 | + hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, |
|---|
| 773 | + HINIC_MOD_L2NIC, pfhwdev, |
|---|
| 774 | + nic_mgmt_msg_handler); |
|---|
| 775 | + hinic_register_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, |
|---|
| 776 | + pfhwdev, comm_mgmt_msg_handler); |
|---|
| 777 | + hinic_comm_recv_mgmt_self_cmd_reg(pfhwdev, |
|---|
| 778 | + HINIC_COMM_CMD_FAULT_REPORT, |
|---|
| 779 | + pf_fault_event_handler); |
|---|
| 780 | + hinic_comm_recv_mgmt_self_cmd_reg |
|---|
| 781 | + (pfhwdev, HINIC_COMM_CMD_WATCHDOG_INFO, |
|---|
| 782 | + mgmt_watchdog_timeout_event_handler); |
|---|
| 783 | + } else { |
|---|
| 784 | + hinic_register_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC, |
|---|
| 785 | + nic_mgmt_msg_handler); |
|---|
| 786 | + } |
|---|
| 691 | 787 | |
|---|
| 692 | 788 | hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE); |
|---|
| 789 | + |
|---|
| 693 | 790 | return 0; |
|---|
| 694 | 791 | } |
|---|
| 695 | 792 | |
|---|
| .. | .. |
|---|
| 703 | 800 | |
|---|
| 704 | 801 | hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT); |
|---|
| 705 | 802 | |
|---|
| 706 | | - hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC); |
|---|
| 803 | + if (!HINIC_IS_VF(hwdev->hwif)) { |
|---|
| 804 | + hinic_comm_recv_mgmt_self_cmd_unreg(pfhwdev, |
|---|
| 805 | + HINIC_COMM_CMD_WATCHDOG_INFO); |
|---|
| 806 | + hinic_comm_recv_mgmt_self_cmd_unreg(pfhwdev, |
|---|
| 807 | + HINIC_COMM_CMD_FAULT_REPORT); |
|---|
| 808 | + hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, |
|---|
| 809 | + HINIC_MOD_COMM); |
|---|
| 810 | + hinic_unregister_mgmt_msg_cb(&pfhwdev->pf_to_mgmt, |
|---|
| 811 | + HINIC_MOD_L2NIC); |
|---|
| 812 | + } else { |
|---|
| 813 | + hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC); |
|---|
| 814 | + } |
|---|
| 815 | + |
|---|
| 816 | + hinic_func_to_func_free(hwdev); |
|---|
| 817 | + |
|---|
| 818 | + hinic_devlink_unregister(hwdev->devlink_dev); |
|---|
| 707 | 819 | |
|---|
| 708 | 820 | hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt); |
|---|
| 821 | +} |
|---|
| 822 | + |
|---|
| 823 | +static int hinic_l2nic_reset(struct hinic_hwdev *hwdev) |
|---|
| 824 | +{ |
|---|
| 825 | + struct hinic_cmd_l2nic_reset l2nic_reset = {0}; |
|---|
| 826 | + u16 out_size = sizeof(l2nic_reset); |
|---|
| 827 | + struct hinic_pfhwdev *pfhwdev; |
|---|
| 828 | + int err; |
|---|
| 829 | + |
|---|
| 830 | + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 831 | + |
|---|
| 832 | + l2nic_reset.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif); |
|---|
| 833 | + /* 0 represents standard l2nic reset flow */ |
|---|
| 834 | + l2nic_reset.reset_flag = 0; |
|---|
| 835 | + |
|---|
| 836 | + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, |
|---|
| 837 | + HINIC_COMM_CMD_L2NIC_RESET, &l2nic_reset, |
|---|
| 838 | + sizeof(l2nic_reset), &l2nic_reset, |
|---|
| 839 | + &out_size, HINIC_MGMT_MSG_SYNC); |
|---|
| 840 | + if (err || !out_size || l2nic_reset.status) { |
|---|
| 841 | + dev_err(&hwdev->hwif->pdev->dev, "Failed to reset L2NIC resources, err: %d, status: 0x%x, out_size: 0x%x\n", |
|---|
| 842 | + err, l2nic_reset.status, out_size); |
|---|
| 843 | + return -EIO; |
|---|
| 844 | + } |
|---|
| 845 | + |
|---|
| 846 | + return 0; |
|---|
| 847 | +} |
|---|
| 848 | + |
|---|
| 849 | +int hinic_get_interrupt_cfg(struct hinic_hwdev *hwdev, |
|---|
| 850 | + struct hinic_msix_config *interrupt_info) |
|---|
| 851 | +{ |
|---|
| 852 | + u16 out_size = sizeof(*interrupt_info); |
|---|
| 853 | + struct hinic_pfhwdev *pfhwdev; |
|---|
| 854 | + int err; |
|---|
| 855 | + |
|---|
| 856 | + if (!hwdev || !interrupt_info) |
|---|
| 857 | + return -EINVAL; |
|---|
| 858 | + |
|---|
| 859 | + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 860 | + |
|---|
| 861 | + interrupt_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif); |
|---|
| 862 | + |
|---|
| 863 | + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, |
|---|
| 864 | + HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP, |
|---|
| 865 | + interrupt_info, sizeof(*interrupt_info), |
|---|
| 866 | + interrupt_info, &out_size, HINIC_MGMT_MSG_SYNC); |
|---|
| 867 | + if (err || !out_size || interrupt_info->status) { |
|---|
| 868 | + dev_err(&hwdev->hwif->pdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n", |
|---|
| 869 | + err, interrupt_info->status, out_size); |
|---|
| 870 | + return -EIO; |
|---|
| 871 | + } |
|---|
| 872 | + |
|---|
| 873 | + return 0; |
|---|
| 874 | +} |
|---|
| 875 | + |
|---|
| 876 | +int hinic_set_interrupt_cfg(struct hinic_hwdev *hwdev, |
|---|
| 877 | + struct hinic_msix_config *interrupt_info) |
|---|
| 878 | +{ |
|---|
| 879 | + u16 out_size = sizeof(*interrupt_info); |
|---|
| 880 | + struct hinic_msix_config temp_info; |
|---|
| 881 | + struct hinic_pfhwdev *pfhwdev; |
|---|
| 882 | + int err; |
|---|
| 883 | + |
|---|
| 884 | + if (!hwdev) |
|---|
| 885 | + return -EINVAL; |
|---|
| 886 | + |
|---|
| 887 | + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 888 | + |
|---|
| 889 | + interrupt_info->func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif); |
|---|
| 890 | + |
|---|
| 891 | + err = hinic_get_interrupt_cfg(hwdev, &temp_info); |
|---|
| 892 | + if (err) |
|---|
| 893 | + return -EINVAL; |
|---|
| 894 | + |
|---|
| 895 | + interrupt_info->lli_credit_cnt = temp_info.lli_credit_cnt; |
|---|
| 896 | + interrupt_info->lli_timer_cnt = temp_info.lli_timer_cnt; |
|---|
| 897 | + |
|---|
| 898 | + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, |
|---|
| 899 | + HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP, |
|---|
| 900 | + interrupt_info, sizeof(*interrupt_info), |
|---|
| 901 | + interrupt_info, &out_size, HINIC_MGMT_MSG_SYNC); |
|---|
| 902 | + if (err || !out_size || interrupt_info->status) { |
|---|
| 903 | + dev_err(&hwdev->hwif->pdev->dev, "Failed to get interrupt config, err: %d, status: 0x%x, out size: 0x%x\n", |
|---|
| 904 | + err, interrupt_info->status, out_size); |
|---|
| 905 | + return -EIO; |
|---|
| 906 | + } |
|---|
| 907 | + |
|---|
| 908 | + return 0; |
|---|
| 709 | 909 | } |
|---|
| 710 | 910 | |
|---|
| 711 | 911 | /** |
|---|
| 712 | 912 | * hinic_init_hwdev - Initialize the NIC HW |
|---|
| 713 | 913 | * @pdev: the NIC pci device |
|---|
| 914 | + * @devlink: the poniter of hinic devlink |
|---|
| 714 | 915 | * |
|---|
| 715 | 916 | * Return initialized NIC HW device |
|---|
| 716 | 917 | * |
|---|
| 717 | 918 | * Initialize the NIC HW device and return a pointer to it |
|---|
| 718 | 919 | **/ |
|---|
| 719 | | -struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev) |
|---|
| 920 | +struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev, struct devlink *devlink) |
|---|
| 720 | 921 | { |
|---|
| 721 | 922 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 722 | 923 | struct hinic_hwdev *hwdev; |
|---|
| .. | .. |
|---|
| 733 | 934 | return ERR_PTR(err); |
|---|
| 734 | 935 | } |
|---|
| 735 | 936 | |
|---|
| 736 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 737 | | - dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 738 | | - err = -EFAULT; |
|---|
| 739 | | - goto err_func_type; |
|---|
| 740 | | - } |
|---|
| 741 | | - |
|---|
| 742 | 937 | pfhwdev = devm_kzalloc(&pdev->dev, sizeof(*pfhwdev), GFP_KERNEL); |
|---|
| 743 | 938 | if (!pfhwdev) { |
|---|
| 744 | 939 | err = -ENOMEM; |
|---|
| .. | .. |
|---|
| 747 | 942 | |
|---|
| 748 | 943 | hwdev = &pfhwdev->hwdev; |
|---|
| 749 | 944 | hwdev->hwif = hwif; |
|---|
| 945 | + hwdev->devlink_dev = devlink_priv(devlink); |
|---|
| 946 | + hwdev->devlink_dev->hwdev = hwdev; |
|---|
| 750 | 947 | |
|---|
| 751 | 948 | err = init_msix(hwdev); |
|---|
| 752 | 949 | if (err) { |
|---|
| .. | .. |
|---|
| 776 | 973 | goto err_init_pfhwdev; |
|---|
| 777 | 974 | } |
|---|
| 778 | 975 | |
|---|
| 976 | + err = hinic_l2nic_reset(hwdev); |
|---|
| 977 | + if (err) |
|---|
| 978 | + goto err_l2nic_reset; |
|---|
| 979 | + |
|---|
| 779 | 980 | err = get_dev_cap(hwdev); |
|---|
| 780 | 981 | if (err) { |
|---|
| 781 | 982 | dev_err(&pdev->dev, "Failed to get device capabilities\n"); |
|---|
| 782 | 983 | goto err_dev_cap; |
|---|
| 984 | + } |
|---|
| 985 | + |
|---|
| 986 | + mutex_init(&hwdev->func_to_io.nic_cfg.cfg_mutex); |
|---|
| 987 | + |
|---|
| 988 | + err = hinic_vf_func_init(hwdev); |
|---|
| 989 | + if (err) { |
|---|
| 990 | + dev_err(&pdev->dev, "Failed to init nic mbox\n"); |
|---|
| 991 | + goto err_vf_func_init; |
|---|
| 783 | 992 | } |
|---|
| 784 | 993 | |
|---|
| 785 | 994 | err = init_fw_ctxt(hwdev); |
|---|
| .. | .. |
|---|
| 798 | 1007 | |
|---|
| 799 | 1008 | err_resources_state: |
|---|
| 800 | 1009 | err_init_fw_ctxt: |
|---|
| 1010 | + hinic_vf_func_free(hwdev); |
|---|
| 1011 | +err_vf_func_init: |
|---|
| 1012 | +err_l2nic_reset: |
|---|
| 801 | 1013 | err_dev_cap: |
|---|
| 802 | 1014 | free_pfhwdev(pfhwdev); |
|---|
| 803 | 1015 | |
|---|
| .. | .. |
|---|
| 809 | 1021 | |
|---|
| 810 | 1022 | err_init_msix: |
|---|
| 811 | 1023 | err_pfhwdev_alloc: |
|---|
| 812 | | -err_func_type: |
|---|
| 813 | 1024 | hinic_free_hwif(hwif); |
|---|
| 1025 | + if (err > 0) |
|---|
| 1026 | + err = -EIO; |
|---|
| 814 | 1027 | return ERR_PTR(err); |
|---|
| 815 | 1028 | } |
|---|
| 816 | 1029 | |
|---|
| .. | .. |
|---|
| 826 | 1039 | |
|---|
| 827 | 1040 | set_resources_state(hwdev, HINIC_RES_CLEAN); |
|---|
| 828 | 1041 | |
|---|
| 1042 | + hinic_vf_func_free(hwdev); |
|---|
| 1043 | + |
|---|
| 829 | 1044 | free_pfhwdev(pfhwdev); |
|---|
| 830 | 1045 | |
|---|
| 831 | 1046 | hinic_aeqs_free(&hwdev->aeqs); |
|---|
| .. | .. |
|---|
| 833 | 1048 | disable_msix(hwdev); |
|---|
| 834 | 1049 | |
|---|
| 835 | 1050 | hinic_free_hwif(hwdev->hwif); |
|---|
| 1051 | +} |
|---|
| 1052 | + |
|---|
| 1053 | +int hinic_hwdev_max_num_qps(struct hinic_hwdev *hwdev) |
|---|
| 1054 | +{ |
|---|
| 1055 | + struct hinic_cap *nic_cap = &hwdev->nic_cap; |
|---|
| 1056 | + |
|---|
| 1057 | + return nic_cap->max_qps; |
|---|
| 836 | 1058 | } |
|---|
| 837 | 1059 | |
|---|
| 838 | 1060 | /** |
|---|
| .. | .. |
|---|
| 902 | 1124 | * @msix_index: msix_index |
|---|
| 903 | 1125 | * @pending_limit: the maximum pending interrupt events (unit 8) |
|---|
| 904 | 1126 | * @coalesc_timer: coalesc period for interrupt (unit 8 us) |
|---|
| 905 | | - * @lli_timer: replenishing period for low latency credit (unit 8 us) |
|---|
| 1127 | + * @lli_timer_cfg: replenishing period for low latency credit (unit 8 us) |
|---|
| 906 | 1128 | * @lli_credit_limit: maximum credits for low latency msix messages (unit 8) |
|---|
| 907 | 1129 | * @resend_timer: maximum wait for resending msix (unit coalesc period) |
|---|
| 908 | 1130 | * |
|---|
| .. | .. |
|---|
| 933 | 1155 | { |
|---|
| 934 | 1156 | struct hinic_qp *qp = container_of(sq, struct hinic_qp, sq); |
|---|
| 935 | 1157 | struct hinic_hwif *hwif = hwdev->hwif; |
|---|
| 936 | | - struct pci_dev *pdev = hwif->pdev; |
|---|
| 937 | 1158 | struct hinic_pfhwdev *pfhwdev; |
|---|
| 938 | 1159 | struct hinic_cmd_hw_ci hw_ci; |
|---|
| 939 | | - |
|---|
| 940 | | - if (!HINIC_IS_PF(hwif) && !HINIC_IS_PPF(hwif)) { |
|---|
| 941 | | - dev_err(&pdev->dev, "Unsupported PCI Function type\n"); |
|---|
| 942 | | - return -EINVAL; |
|---|
| 943 | | - } |
|---|
| 944 | 1160 | |
|---|
| 945 | 1161 | hw_ci.dma_attr_off = 0; |
|---|
| 946 | 1162 | hw_ci.pending_limit = pending_limit; |
|---|
| .. | .. |
|---|
| 962 | 1178 | &hw_ci, sizeof(hw_ci), NULL, |
|---|
| 963 | 1179 | NULL, HINIC_MGMT_MSG_SYNC); |
|---|
| 964 | 1180 | } |
|---|
| 1181 | + |
|---|
| 1182 | +/** |
|---|
| 1183 | + * hinic_hwdev_set_msix_state- set msix state |
|---|
| 1184 | + * @hwdev: the NIC HW device |
|---|
| 1185 | + * @msix_index: IRQ corresponding index number |
|---|
| 1186 | + * @flag: msix state |
|---|
| 1187 | + * |
|---|
| 1188 | + **/ |
|---|
| 1189 | +void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index, |
|---|
| 1190 | + enum hinic_msix_state flag) |
|---|
| 1191 | +{ |
|---|
| 1192 | + hinic_set_msix_state(hwdev->hwif, msix_index, flag); |
|---|
| 1193 | +} |
|---|
| 1194 | + |
|---|
| 1195 | +int hinic_get_board_info(struct hinic_hwdev *hwdev, |
|---|
| 1196 | + struct hinic_comm_board_info *board_info) |
|---|
| 1197 | +{ |
|---|
| 1198 | + u16 out_size = sizeof(*board_info); |
|---|
| 1199 | + struct hinic_pfhwdev *pfhwdev; |
|---|
| 1200 | + int err; |
|---|
| 1201 | + |
|---|
| 1202 | + if (!hwdev || !board_info) |
|---|
| 1203 | + return -EINVAL; |
|---|
| 1204 | + |
|---|
| 1205 | + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
|---|
| 1206 | + |
|---|
| 1207 | + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, |
|---|
| 1208 | + HINIC_COMM_CMD_GET_BOARD_INFO, |
|---|
| 1209 | + board_info, sizeof(*board_info), |
|---|
| 1210 | + board_info, &out_size, HINIC_MGMT_MSG_SYNC); |
|---|
| 1211 | + if (err || board_info->status || !out_size) { |
|---|
| 1212 | + dev_err(&hwdev->hwif->pdev->dev, |
|---|
| 1213 | + "Failed to get board info, err: %d, status: 0x%x, out size: 0x%x\n", |
|---|
| 1214 | + err, board_info->status, out_size); |
|---|
| 1215 | + return -EIO; |
|---|
| 1216 | + } |
|---|
| 1217 | + |
|---|
| 1218 | + return 0; |
|---|
| 1219 | +} |
|---|