.. | .. |
---|
| 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/io.h> |
---|
25 | 16 | #include <linux/err.h> |
---|
26 | 17 | |
---|
| 18 | +#include "hinic_hw_dev.h" |
---|
27 | 19 | #include "hinic_hw_if.h" |
---|
28 | 20 | #include "hinic_hw_eqs.h" |
---|
29 | 21 | #include "hinic_hw_wqe.h" |
---|
.. | .. |
---|
43 | 35 | #define DB_IDX(db, db_base) \ |
---|
44 | 36 | (((unsigned long)(db) - (unsigned long)(db_base)) / HINIC_DB_PAGE_SIZE) |
---|
45 | 37 | |
---|
| 38 | +#define HINIC_PAGE_SIZE_HW(pg_size) ((u8)ilog2((u32)((pg_size) >> 12))) |
---|
| 39 | + |
---|
46 | 40 | enum io_cmd { |
---|
47 | 41 | IO_CMD_MODIFY_QUEUE_CTXT = 0, |
---|
| 42 | + IO_CMD_CLEAN_QUEUE_CTXT, |
---|
48 | 43 | }; |
---|
49 | 44 | |
---|
50 | 45 | static void init_db_area_idx(struct hinic_free_db_area *free_db_area) |
---|
.. | .. |
---|
210 | 205 | write_rq_ctxts(func_to_io, base_qpn, num_qps)); |
---|
211 | 206 | } |
---|
212 | 207 | |
---|
| 208 | +static int hinic_clean_queue_offload_ctxt(struct hinic_func_to_io *func_to_io, |
---|
| 209 | + enum hinic_qp_ctxt_type ctxt_type) |
---|
| 210 | +{ |
---|
| 211 | + struct hinic_hwif *hwif = func_to_io->hwif; |
---|
| 212 | + struct hinic_clean_queue_ctxt *ctxt_block; |
---|
| 213 | + struct pci_dev *pdev = hwif->pdev; |
---|
| 214 | + struct hinic_cmdq_buf cmdq_buf; |
---|
| 215 | + u64 out_param = 0; |
---|
| 216 | + int err; |
---|
| 217 | + |
---|
| 218 | + err = hinic_alloc_cmdq_buf(&func_to_io->cmdqs, &cmdq_buf); |
---|
| 219 | + if (err) { |
---|
| 220 | + dev_err(&pdev->dev, "Failed to allocate cmdq buf\n"); |
---|
| 221 | + return err; |
---|
| 222 | + } |
---|
| 223 | + |
---|
| 224 | + ctxt_block = cmdq_buf.buf; |
---|
| 225 | + ctxt_block->cmdq_hdr.num_queues = func_to_io->max_qps; |
---|
| 226 | + ctxt_block->cmdq_hdr.queue_type = ctxt_type; |
---|
| 227 | + ctxt_block->cmdq_hdr.addr_offset = 0; |
---|
| 228 | + |
---|
| 229 | + /* TSO/LRO ctxt size: 0x0:0B; 0x1:160B; 0x2:200B; 0x3:240B */ |
---|
| 230 | + ctxt_block->ctxt_size = 0x3; |
---|
| 231 | + |
---|
| 232 | + hinic_cpu_to_be32(ctxt_block, sizeof(*ctxt_block)); |
---|
| 233 | + |
---|
| 234 | + cmdq_buf.size = sizeof(*ctxt_block); |
---|
| 235 | + |
---|
| 236 | + err = hinic_cmdq_direct_resp(&func_to_io->cmdqs, HINIC_MOD_L2NIC, |
---|
| 237 | + IO_CMD_CLEAN_QUEUE_CTXT, |
---|
| 238 | + &cmdq_buf, &out_param); |
---|
| 239 | + |
---|
| 240 | + if (err || out_param) { |
---|
| 241 | + dev_err(&pdev->dev, "Failed to clean offload ctxts, err: %d, out_param: 0x%llx\n", |
---|
| 242 | + err, out_param); |
---|
| 243 | + |
---|
| 244 | + err = -EFAULT; |
---|
| 245 | + } |
---|
| 246 | + |
---|
| 247 | + hinic_free_cmdq_buf(&func_to_io->cmdqs, &cmdq_buf); |
---|
| 248 | + |
---|
| 249 | + return err; |
---|
| 250 | +} |
---|
| 251 | + |
---|
| 252 | +static int hinic_clean_qp_offload_ctxt(struct hinic_func_to_io *func_to_io) |
---|
| 253 | +{ |
---|
| 254 | + /* clean LRO/TSO context space */ |
---|
| 255 | + return (hinic_clean_queue_offload_ctxt(func_to_io, |
---|
| 256 | + HINIC_QP_CTXT_TYPE_SQ) || |
---|
| 257 | + hinic_clean_queue_offload_ctxt(func_to_io, |
---|
| 258 | + HINIC_QP_CTXT_TYPE_RQ)); |
---|
| 259 | +} |
---|
| 260 | + |
---|
213 | 261 | /** |
---|
214 | 262 | * init_qp - Initialize a Queue Pair |
---|
215 | 263 | * @func_to_io: func to io channel that holds the IO components |
---|
.. | .. |
---|
234 | 282 | |
---|
235 | 283 | err = hinic_wq_allocate(&func_to_io->wqs, &func_to_io->sq_wq[q_id], |
---|
236 | 284 | HINIC_SQ_WQEBB_SIZE, HINIC_SQ_PAGE_SIZE, |
---|
237 | | - HINIC_SQ_DEPTH, HINIC_SQ_WQE_MAX_SIZE); |
---|
| 285 | + func_to_io->sq_depth, HINIC_SQ_WQE_MAX_SIZE); |
---|
238 | 286 | if (err) { |
---|
239 | 287 | dev_err(&pdev->dev, "Failed to allocate WQ for SQ\n"); |
---|
240 | 288 | return err; |
---|
.. | .. |
---|
242 | 290 | |
---|
243 | 291 | err = hinic_wq_allocate(&func_to_io->wqs, &func_to_io->rq_wq[q_id], |
---|
244 | 292 | HINIC_RQ_WQEBB_SIZE, HINIC_RQ_PAGE_SIZE, |
---|
245 | | - HINIC_RQ_DEPTH, HINIC_RQ_WQE_SIZE); |
---|
| 293 | + func_to_io->rq_depth, HINIC_RQ_WQE_SIZE); |
---|
246 | 294 | if (err) { |
---|
247 | 295 | dev_err(&pdev->dev, "Failed to allocate WQ for RQ\n"); |
---|
248 | 296 | goto err_rq_alloc; |
---|
.. | .. |
---|
257 | 305 | |
---|
258 | 306 | func_to_io->sq_db[q_id] = db_base; |
---|
259 | 307 | |
---|
| 308 | + qp->sq.qid = q_id; |
---|
260 | 309 | err = hinic_init_sq(&qp->sq, hwif, &func_to_io->sq_wq[q_id], |
---|
261 | 310 | sq_msix_entry, |
---|
262 | 311 | CI_ADDR(func_to_io->ci_addr_base, q_id), |
---|
.. | .. |
---|
266 | 315 | goto err_sq_init; |
---|
267 | 316 | } |
---|
268 | 317 | |
---|
| 318 | + qp->rq.qid = q_id; |
---|
269 | 319 | err = hinic_init_rq(&qp->rq, hwif, &func_to_io->rq_wq[q_id], |
---|
270 | 320 | rq_msix_entry); |
---|
271 | 321 | if (err) { |
---|
.. | .. |
---|
313 | 363 | * @func_to_io: func to io channel that holds the IO components |
---|
314 | 364 | * @base_qpn: base qp number |
---|
315 | 365 | * @num_qps: number queue pairs to create |
---|
316 | | - * @sq_msix_entry: msix entries for sq |
---|
317 | | - * @rq_msix_entry: msix entries for rq |
---|
| 366 | + * @sq_msix_entries: msix entries for sq |
---|
| 367 | + * @rq_msix_entries: msix entries for rq |
---|
318 | 368 | * |
---|
319 | 369 | * Return 0 - Success, negative - Failure |
---|
320 | 370 | **/ |
---|
.. | .. |
---|
355 | 405 | goto err_sq_db; |
---|
356 | 406 | } |
---|
357 | 407 | |
---|
358 | | - ci_addr_base = dma_zalloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps), |
---|
359 | | - &func_to_io->ci_dma_base, |
---|
360 | | - GFP_KERNEL); |
---|
| 408 | + ci_addr_base = dma_alloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps), |
---|
| 409 | + &func_to_io->ci_dma_base, |
---|
| 410 | + GFP_KERNEL); |
---|
361 | 411 | if (!ci_addr_base) { |
---|
362 | 412 | dev_err(&pdev->dev, "Failed to allocate CI area\n"); |
---|
363 | 413 | err = -ENOMEM; |
---|
.. | .. |
---|
378 | 428 | err = write_qp_ctxts(func_to_io, base_qpn, num_qps); |
---|
379 | 429 | if (err) { |
---|
380 | 430 | dev_err(&pdev->dev, "Failed to init QP ctxts\n"); |
---|
| 431 | + goto err_write_qp_ctxts; |
---|
| 432 | + } |
---|
| 433 | + |
---|
| 434 | + err = hinic_clean_qp_offload_ctxt(func_to_io); |
---|
| 435 | + if (err) { |
---|
| 436 | + dev_err(&pdev->dev, "Failed to clean QP contexts space\n"); |
---|
381 | 437 | goto err_write_qp_ctxts; |
---|
382 | 438 | } |
---|
383 | 439 | |
---|
.. | .. |
---|
433 | 489 | devm_kfree(&pdev->dev, func_to_io->qps); |
---|
434 | 490 | } |
---|
435 | 491 | |
---|
| 492 | +int hinic_set_wq_page_size(struct hinic_hwdev *hwdev, u16 func_idx, |
---|
| 493 | + u32 page_size) |
---|
| 494 | +{ |
---|
| 495 | + struct hinic_wq_page_size page_size_info = {0}; |
---|
| 496 | + u16 out_size = sizeof(page_size_info); |
---|
| 497 | + struct hinic_pfhwdev *pfhwdev; |
---|
| 498 | + int err; |
---|
| 499 | + |
---|
| 500 | + pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev); |
---|
| 501 | + |
---|
| 502 | + page_size_info.func_idx = func_idx; |
---|
| 503 | + page_size_info.ppf_idx = HINIC_HWIF_PPF_IDX(hwdev->hwif); |
---|
| 504 | + page_size_info.page_size = HINIC_PAGE_SIZE_HW(page_size); |
---|
| 505 | + |
---|
| 506 | + err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM, |
---|
| 507 | + HINIC_COMM_CMD_PAGESIZE_SET, &page_size_info, |
---|
| 508 | + sizeof(page_size_info), &page_size_info, |
---|
| 509 | + &out_size, HINIC_MGMT_MSG_SYNC); |
---|
| 510 | + if (err || !out_size || page_size_info.status) { |
---|
| 511 | + dev_err(&hwdev->hwif->pdev->dev, "Failed to set wq page size, err: %d, status: 0x%x, out_size: 0x%0x\n", |
---|
| 512 | + err, page_size_info.status, out_size); |
---|
| 513 | + return -EFAULT; |
---|
| 514 | + } |
---|
| 515 | + |
---|
| 516 | + return 0; |
---|
| 517 | +} |
---|
| 518 | + |
---|
436 | 519 | /** |
---|
437 | 520 | * hinic_io_init - Initialize the IO components |
---|
438 | 521 | * @func_to_io: func to io channel that holds the IO components |
---|
.. | .. |
---|
455 | 538 | func_to_io->hwif = hwif; |
---|
456 | 539 | func_to_io->qps = NULL; |
---|
457 | 540 | func_to_io->max_qps = max_qps; |
---|
| 541 | + func_to_io->ceqs.hwdev = func_to_io->hwdev; |
---|
458 | 542 | |
---|
459 | 543 | err = hinic_ceqs_init(&func_to_io->ceqs, hwif, num_ceqs, |
---|
460 | 544 | HINIC_DEFAULT_CEQ_LEN, HINIC_EQ_PAGE_SIZE, |
---|
.. | .. |
---|
490 | 574 | func_to_io->cmdq_db_area[cmdq] = db_area; |
---|
491 | 575 | } |
---|
492 | 576 | |
---|
| 577 | + err = hinic_set_wq_page_size(func_to_io->hwdev, |
---|
| 578 | + HINIC_HWIF_FUNC_IDX(hwif), |
---|
| 579 | + HINIC_DEFAULT_WQ_PAGE_SIZE); |
---|
| 580 | + if (err) { |
---|
| 581 | + dev_err(&func_to_io->hwif->pdev->dev, "Failed to set wq page size\n"); |
---|
| 582 | + goto init_wq_pg_size_err; |
---|
| 583 | + } |
---|
| 584 | + |
---|
493 | 585 | err = hinic_init_cmdqs(&func_to_io->cmdqs, hwif, |
---|
494 | 586 | func_to_io->cmdq_db_area); |
---|
495 | 587 | if (err) { |
---|
.. | .. |
---|
500 | 592 | return 0; |
---|
501 | 593 | |
---|
502 | 594 | err_init_cmdqs: |
---|
| 595 | + if (!HINIC_IS_VF(func_to_io->hwif)) |
---|
| 596 | + hinic_set_wq_page_size(func_to_io->hwdev, |
---|
| 597 | + HINIC_HWIF_FUNC_IDX(hwif), |
---|
| 598 | + HINIC_HW_WQ_PAGE_SIZE); |
---|
| 599 | +init_wq_pg_size_err: |
---|
503 | 600 | err_db_area: |
---|
504 | 601 | for (type = HINIC_CMDQ_SYNC; type < cmdq; type++) |
---|
505 | 602 | return_db_area(func_to_io, func_to_io->cmdq_db_area[type]); |
---|
.. | .. |
---|
524 | 621 | |
---|
525 | 622 | hinic_free_cmdqs(&func_to_io->cmdqs); |
---|
526 | 623 | |
---|
| 624 | + if (!HINIC_IS_VF(func_to_io->hwif)) |
---|
| 625 | + hinic_set_wq_page_size(func_to_io->hwdev, |
---|
| 626 | + HINIC_HWIF_FUNC_IDX(func_to_io->hwif), |
---|
| 627 | + HINIC_HW_WQ_PAGE_SIZE); |
---|
| 628 | + |
---|
527 | 629 | for (cmdq = HINIC_CMDQ_SYNC; cmdq < HINIC_MAX_CMDQ_TYPES; cmdq++) |
---|
528 | 630 | return_db_area(func_to_io, func_to_io->cmdq_db_area[cmdq]); |
---|
529 | 631 | |
---|