| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
|---|
| 1 | 2 | /* QLogic qed NIC Driver |
|---|
| 2 | 3 | * Copyright (c) 2015-2017 QLogic Corporation |
|---|
| 3 | | - * |
|---|
| 4 | | - * This software is available to you under a choice of one of two |
|---|
| 5 | | - * licenses. You may choose to be licensed under the terms of the GNU |
|---|
| 6 | | - * General Public License (GPL) Version 2, available from the file |
|---|
| 7 | | - * COPYING in the main directory of this source tree, or the |
|---|
| 8 | | - * OpenIB.org BSD license below: |
|---|
| 9 | | - * |
|---|
| 10 | | - * Redistribution and use in source and binary forms, with or |
|---|
| 11 | | - * without modification, are permitted provided that the following |
|---|
| 12 | | - * conditions are met: |
|---|
| 13 | | - * |
|---|
| 14 | | - * - Redistributions of source code must retain the above |
|---|
| 15 | | - * copyright notice, this list of conditions and the following |
|---|
| 16 | | - * disclaimer. |
|---|
| 17 | | - * |
|---|
| 18 | | - * - Redistributions in binary form must reproduce the above |
|---|
| 19 | | - * copyright notice, this list of conditions and the following |
|---|
| 20 | | - * disclaimer in the documentation and /or other materials |
|---|
| 21 | | - * provided with the distribution. |
|---|
| 22 | | - * |
|---|
| 23 | | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|---|
| 24 | | - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|---|
| 25 | | - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|---|
| 26 | | - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
|---|
| 27 | | - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
|---|
| 28 | | - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|---|
| 29 | | - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|---|
| 30 | | - * SOFTWARE. |
|---|
| 4 | + * Copyright (c) 2019-2020 Marvell International Ltd. |
|---|
| 31 | 5 | */ |
|---|
| 32 | 6 | |
|---|
| 33 | 7 | #include <linux/types.h> |
|---|
| .. | .. |
|---|
| 392 | 366 | } |
|---|
| 393 | 367 | |
|---|
| 394 | 368 | /* DMAE */ |
|---|
| 369 | +#define QED_DMAE_FLAGS_IS_SET(params, flag) \ |
|---|
| 370 | + ((params) != NULL && GET_FIELD((params)->flags, QED_DMAE_PARAMS_##flag)) |
|---|
| 371 | + |
|---|
| 395 | 372 | static void qed_dmae_opcode(struct qed_hwfn *p_hwfn, |
|---|
| 396 | 373 | const u8 is_src_type_grc, |
|---|
| 397 | 374 | const u8 is_dst_type_grc, |
|---|
| 398 | 375 | struct qed_dmae_params *p_params) |
|---|
| 399 | 376 | { |
|---|
| 377 | + u8 src_pfid, dst_pfid, port_id; |
|---|
| 400 | 378 | u16 opcode_b = 0; |
|---|
| 401 | 379 | u32 opcode = 0; |
|---|
| 402 | 380 | |
|---|
| .. | .. |
|---|
| 404 | 382 | * 0- The source is the PCIe |
|---|
| 405 | 383 | * 1- The source is the GRC. |
|---|
| 406 | 384 | */ |
|---|
| 407 | | - opcode |= (is_src_type_grc ? DMAE_CMD_SRC_MASK_GRC |
|---|
| 408 | | - : DMAE_CMD_SRC_MASK_PCIE) << |
|---|
| 409 | | - DMAE_CMD_SRC_SHIFT; |
|---|
| 410 | | - opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_SRC_PF_ID_MASK) << |
|---|
| 411 | | - DMAE_CMD_SRC_PF_ID_SHIFT); |
|---|
| 385 | + SET_FIELD(opcode, DMAE_CMD_SRC, |
|---|
| 386 | + (is_src_type_grc ? dmae_cmd_src_grc : dmae_cmd_src_pcie)); |
|---|
| 387 | + src_pfid = QED_DMAE_FLAGS_IS_SET(p_params, SRC_PF_VALID) ? |
|---|
| 388 | + p_params->src_pfid : p_hwfn->rel_pf_id; |
|---|
| 389 | + SET_FIELD(opcode, DMAE_CMD_SRC_PF_ID, src_pfid); |
|---|
| 412 | 390 | |
|---|
| 413 | 391 | /* The destination of the DMA can be: 0-None 1-PCIe 2-GRC 3-None */ |
|---|
| 414 | | - opcode |= (is_dst_type_grc ? DMAE_CMD_DST_MASK_GRC |
|---|
| 415 | | - : DMAE_CMD_DST_MASK_PCIE) << |
|---|
| 416 | | - DMAE_CMD_DST_SHIFT; |
|---|
| 417 | | - opcode |= ((p_hwfn->rel_pf_id & DMAE_CMD_DST_PF_ID_MASK) << |
|---|
| 418 | | - DMAE_CMD_DST_PF_ID_SHIFT); |
|---|
| 392 | + SET_FIELD(opcode, DMAE_CMD_DST, |
|---|
| 393 | + (is_dst_type_grc ? dmae_cmd_dst_grc : dmae_cmd_dst_pcie)); |
|---|
| 394 | + dst_pfid = QED_DMAE_FLAGS_IS_SET(p_params, DST_PF_VALID) ? |
|---|
| 395 | + p_params->dst_pfid : p_hwfn->rel_pf_id; |
|---|
| 396 | + SET_FIELD(opcode, DMAE_CMD_DST_PF_ID, dst_pfid); |
|---|
| 397 | + |
|---|
| 419 | 398 | |
|---|
| 420 | 399 | /* Whether to write a completion word to the completion destination: |
|---|
| 421 | 400 | * 0-Do not write a completion word |
|---|
| 422 | 401 | * 1-Write the completion word |
|---|
| 423 | 402 | */ |
|---|
| 424 | | - opcode |= (DMAE_CMD_COMP_WORD_EN_MASK << DMAE_CMD_COMP_WORD_EN_SHIFT); |
|---|
| 425 | | - opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK << |
|---|
| 426 | | - DMAE_CMD_SRC_ADDR_RESET_SHIFT); |
|---|
| 403 | + SET_FIELD(opcode, DMAE_CMD_COMP_WORD_EN, 1); |
|---|
| 404 | + SET_FIELD(opcode, DMAE_CMD_SRC_ADDR_RESET, 1); |
|---|
| 427 | 405 | |
|---|
| 428 | | - if (p_params->flags & QED_DMAE_FLAG_COMPLETION_DST) |
|---|
| 429 | | - opcode |= (1 << DMAE_CMD_COMP_FUNC_SHIFT); |
|---|
| 406 | + if (QED_DMAE_FLAGS_IS_SET(p_params, COMPLETION_DST)) |
|---|
| 407 | + SET_FIELD(opcode, DMAE_CMD_COMP_FUNC, 1); |
|---|
| 430 | 408 | |
|---|
| 431 | | - opcode |= (DMAE_CMD_ENDIANITY << DMAE_CMD_ENDIANITY_MODE_SHIFT); |
|---|
| 409 | + /* swapping mode 3 - big endian */ |
|---|
| 410 | + SET_FIELD(opcode, DMAE_CMD_ENDIANITY_MODE, DMAE_CMD_ENDIANITY); |
|---|
| 432 | 411 | |
|---|
| 433 | | - opcode |= ((p_hwfn->port_id) << DMAE_CMD_PORT_ID_SHIFT); |
|---|
| 412 | + port_id = (QED_DMAE_FLAGS_IS_SET(p_params, PORT_VALID)) ? |
|---|
| 413 | + p_params->port_id : p_hwfn->port_id; |
|---|
| 414 | + SET_FIELD(opcode, DMAE_CMD_PORT_ID, port_id); |
|---|
| 434 | 415 | |
|---|
| 435 | 416 | /* reset source address in next go */ |
|---|
| 436 | | - opcode |= (DMAE_CMD_SRC_ADDR_RESET_MASK << |
|---|
| 437 | | - DMAE_CMD_SRC_ADDR_RESET_SHIFT); |
|---|
| 417 | + SET_FIELD(opcode, DMAE_CMD_SRC_ADDR_RESET, 1); |
|---|
| 438 | 418 | |
|---|
| 439 | 419 | /* reset dest address in next go */ |
|---|
| 440 | | - opcode |= (DMAE_CMD_DST_ADDR_RESET_MASK << |
|---|
| 441 | | - DMAE_CMD_DST_ADDR_RESET_SHIFT); |
|---|
| 420 | + SET_FIELD(opcode, DMAE_CMD_DST_ADDR_RESET, 1); |
|---|
| 442 | 421 | |
|---|
| 443 | 422 | /* SRC/DST VFID: all 1's - pf, otherwise VF id */ |
|---|
| 444 | | - if (p_params->flags & QED_DMAE_FLAG_VF_SRC) { |
|---|
| 445 | | - opcode |= 1 << DMAE_CMD_SRC_VF_ID_VALID_SHIFT; |
|---|
| 446 | | - opcode_b |= p_params->src_vfid << DMAE_CMD_SRC_VF_ID_SHIFT; |
|---|
| 423 | + if (QED_DMAE_FLAGS_IS_SET(p_params, SRC_VF_VALID)) { |
|---|
| 424 | + SET_FIELD(opcode, DMAE_CMD_SRC_VF_ID_VALID, 1); |
|---|
| 425 | + SET_FIELD(opcode_b, DMAE_CMD_SRC_VF_ID, p_params->src_vfid); |
|---|
| 447 | 426 | } else { |
|---|
| 448 | | - opcode_b |= DMAE_CMD_SRC_VF_ID_MASK << |
|---|
| 449 | | - DMAE_CMD_SRC_VF_ID_SHIFT; |
|---|
| 427 | + SET_FIELD(opcode_b, DMAE_CMD_SRC_VF_ID, 0xFF); |
|---|
| 450 | 428 | } |
|---|
| 451 | | - |
|---|
| 452 | | - if (p_params->flags & QED_DMAE_FLAG_VF_DST) { |
|---|
| 453 | | - opcode |= 1 << DMAE_CMD_DST_VF_ID_VALID_SHIFT; |
|---|
| 454 | | - opcode_b |= p_params->dst_vfid << DMAE_CMD_DST_VF_ID_SHIFT; |
|---|
| 429 | + if (QED_DMAE_FLAGS_IS_SET(p_params, DST_VF_VALID)) { |
|---|
| 430 | + SET_FIELD(opcode, DMAE_CMD_DST_VF_ID_VALID, 1); |
|---|
| 431 | + SET_FIELD(opcode_b, DMAE_CMD_DST_VF_ID, p_params->dst_vfid); |
|---|
| 455 | 432 | } else { |
|---|
| 456 | | - opcode_b |= DMAE_CMD_DST_VF_ID_MASK << DMAE_CMD_DST_VF_ID_SHIFT; |
|---|
| 433 | + SET_FIELD(opcode_b, DMAE_CMD_DST_VF_ID, 0xFF); |
|---|
| 457 | 434 | } |
|---|
| 458 | 435 | |
|---|
| 459 | 436 | p_hwfn->dmae_info.p_dmae_cmd->opcode = cpu_to_le32(opcode); |
|---|
| .. | .. |
|---|
| 703 | 680 | int qed_status = 0; |
|---|
| 704 | 681 | u32 offset = 0; |
|---|
| 705 | 682 | |
|---|
| 683 | + if (p_hwfn->cdev->recov_in_prog) { |
|---|
| 684 | + DP_VERBOSE(p_hwfn, |
|---|
| 685 | + NETIF_MSG_HW, |
|---|
| 686 | + "Recovery is in progress. Avoid DMAE transaction [{src: addr 0x%llx, type %d}, {dst: addr 0x%llx, type %d}, size %d].\n", |
|---|
| 687 | + src_addr, src_type, dst_addr, dst_type, |
|---|
| 688 | + size_in_dwords); |
|---|
| 689 | + |
|---|
| 690 | + /* Let the flow complete w/o any error handling */ |
|---|
| 691 | + return 0; |
|---|
| 692 | + } |
|---|
| 693 | + |
|---|
| 706 | 694 | qed_dmae_opcode(p_hwfn, |
|---|
| 707 | 695 | (src_type == QED_DMAE_ADDRESS_GRC), |
|---|
| 708 | 696 | (dst_type == QED_DMAE_ADDRESS_GRC), |
|---|
| .. | .. |
|---|
| 722 | 710 | for (i = 0; i <= cnt_split; i++) { |
|---|
| 723 | 711 | offset = length_limit * i; |
|---|
| 724 | 712 | |
|---|
| 725 | | - if (!(p_params->flags & QED_DMAE_FLAG_RW_REPL_SRC)) { |
|---|
| 713 | + if (!QED_DMAE_FLAGS_IS_SET(p_params, RW_REPL_SRC)) { |
|---|
| 726 | 714 | if (src_type == QED_DMAE_ADDRESS_GRC) |
|---|
| 727 | 715 | src_addr_split = src_addr + offset; |
|---|
| 728 | 716 | else |
|---|
| .. | .. |
|---|
| 748 | 736 | dst_type, |
|---|
| 749 | 737 | length_cur); |
|---|
| 750 | 738 | if (qed_status) { |
|---|
| 751 | | - DP_NOTICE(p_hwfn, |
|---|
| 752 | | - "qed_dmae_execute_sub_operation Failed with error 0x%x. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n", |
|---|
| 753 | | - qed_status, src_addr, dst_addr, length_cur); |
|---|
| 739 | + qed_hw_err_notify(p_hwfn, p_ptt, QED_HW_ERR_DMAE_FAIL, |
|---|
| 740 | + "qed_dmae_execute_sub_operation Failed with error 0x%x. source_addr 0x%llx, destination addr 0x%llx, size_in_dwords 0x%x\n", |
|---|
| 741 | + qed_status, src_addr, |
|---|
| 742 | + dst_addr, length_cur); |
|---|
| 754 | 743 | break; |
|---|
| 755 | 744 | } |
|---|
| 756 | 745 | } |
|---|
| .. | .. |
|---|
| 760 | 749 | |
|---|
| 761 | 750 | int qed_dmae_host2grc(struct qed_hwfn *p_hwfn, |
|---|
| 762 | 751 | struct qed_ptt *p_ptt, |
|---|
| 763 | | - u64 source_addr, u32 grc_addr, u32 size_in_dwords, u32 flags) |
|---|
| 752 | + u64 source_addr, u32 grc_addr, u32 size_in_dwords, |
|---|
| 753 | + struct qed_dmae_params *p_params) |
|---|
| 764 | 754 | { |
|---|
| 765 | 755 | u32 grc_addr_in_dw = grc_addr / sizeof(u32); |
|---|
| 766 | | - struct qed_dmae_params params; |
|---|
| 767 | 756 | int rc; |
|---|
| 768 | 757 | |
|---|
| 769 | | - memset(¶ms, 0, sizeof(struct qed_dmae_params)); |
|---|
| 770 | | - params.flags = flags; |
|---|
| 771 | 758 | |
|---|
| 772 | 759 | mutex_lock(&p_hwfn->dmae_info.mutex); |
|---|
| 773 | 760 | |
|---|
| .. | .. |
|---|
| 775 | 762 | grc_addr_in_dw, |
|---|
| 776 | 763 | QED_DMAE_ADDRESS_HOST_VIRT, |
|---|
| 777 | 764 | QED_DMAE_ADDRESS_GRC, |
|---|
| 778 | | - size_in_dwords, ¶ms); |
|---|
| 765 | + size_in_dwords, p_params); |
|---|
| 779 | 766 | |
|---|
| 780 | 767 | mutex_unlock(&p_hwfn->dmae_info.mutex); |
|---|
| 781 | 768 | |
|---|
| .. | .. |
|---|
| 785 | 772 | int qed_dmae_grc2host(struct qed_hwfn *p_hwfn, |
|---|
| 786 | 773 | struct qed_ptt *p_ptt, |
|---|
| 787 | 774 | u32 grc_addr, |
|---|
| 788 | | - dma_addr_t dest_addr, u32 size_in_dwords, u32 flags) |
|---|
| 775 | + dma_addr_t dest_addr, u32 size_in_dwords, |
|---|
| 776 | + struct qed_dmae_params *p_params) |
|---|
| 789 | 777 | { |
|---|
| 790 | 778 | u32 grc_addr_in_dw = grc_addr / sizeof(u32); |
|---|
| 791 | | - struct qed_dmae_params params; |
|---|
| 792 | 779 | int rc; |
|---|
| 793 | 780 | |
|---|
| 794 | | - memset(¶ms, 0, sizeof(struct qed_dmae_params)); |
|---|
| 795 | | - params.flags = flags; |
|---|
| 796 | 781 | |
|---|
| 797 | 782 | mutex_lock(&p_hwfn->dmae_info.mutex); |
|---|
| 798 | 783 | |
|---|
| 799 | 784 | rc = qed_dmae_execute_command(p_hwfn, p_ptt, grc_addr_in_dw, |
|---|
| 800 | 785 | dest_addr, QED_DMAE_ADDRESS_GRC, |
|---|
| 801 | 786 | QED_DMAE_ADDRESS_HOST_VIRT, |
|---|
| 802 | | - size_in_dwords, ¶ms); |
|---|
| 787 | + size_in_dwords, p_params); |
|---|
| 803 | 788 | |
|---|
| 804 | 789 | mutex_unlock(&p_hwfn->dmae_info.mutex); |
|---|
| 805 | 790 | |
|---|
| .. | .. |
|---|
| 827 | 812 | return rc; |
|---|
| 828 | 813 | } |
|---|
| 829 | 814 | |
|---|
| 815 | +void qed_hw_err_notify(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, |
|---|
| 816 | + enum qed_hw_err_type err_type, const char *fmt, ...) |
|---|
| 817 | +{ |
|---|
| 818 | + char buf[QED_HW_ERR_MAX_STR_SIZE]; |
|---|
| 819 | + va_list vl; |
|---|
| 820 | + int len; |
|---|
| 821 | + |
|---|
| 822 | + if (fmt) { |
|---|
| 823 | + va_start(vl, fmt); |
|---|
| 824 | + len = vsnprintf(buf, QED_HW_ERR_MAX_STR_SIZE, fmt, vl); |
|---|
| 825 | + va_end(vl); |
|---|
| 826 | + |
|---|
| 827 | + if (len > QED_HW_ERR_MAX_STR_SIZE - 1) |
|---|
| 828 | + len = QED_HW_ERR_MAX_STR_SIZE - 1; |
|---|
| 829 | + |
|---|
| 830 | + DP_NOTICE(p_hwfn, "%s", buf); |
|---|
| 831 | + } |
|---|
| 832 | + |
|---|
| 833 | + /* Fan failure cannot be masked by handling of another HW error */ |
|---|
| 834 | + if (p_hwfn->cdev->recov_in_prog && |
|---|
| 835 | + err_type != QED_HW_ERR_FAN_FAIL) { |
|---|
| 836 | + DP_VERBOSE(p_hwfn, |
|---|
| 837 | + NETIF_MSG_DRV, |
|---|
| 838 | + "Recovery is in progress. Avoid notifying about HW error %d.\n", |
|---|
| 839 | + err_type); |
|---|
| 840 | + return; |
|---|
| 841 | + } |
|---|
| 842 | + |
|---|
| 843 | + qed_hw_error_occurred(p_hwfn, err_type); |
|---|
| 844 | + |
|---|
| 845 | + if (fmt) |
|---|
| 846 | + qed_mcp_send_raw_debug_data(p_hwfn, p_ptt, buf, len); |
|---|
| 847 | +} |
|---|
| 848 | + |
|---|
| 830 | 849 | int qed_dmae_sanity(struct qed_hwfn *p_hwfn, |
|---|
| 831 | 850 | struct qed_ptt *p_ptt, const char *phase) |
|---|
| 832 | 851 | { |
|---|
| 833 | 852 | u32 size = PAGE_SIZE / 2, val; |
|---|
| 834 | | - struct qed_dmae_params params; |
|---|
| 835 | 853 | int rc = 0; |
|---|
| 836 | 854 | dma_addr_t p_phys; |
|---|
| 837 | 855 | void *p_virt; |
|---|
| .. | .. |
|---|
| 864 | 882 | (u64)p_phys, |
|---|
| 865 | 883 | p_virt, (u64)(p_phys + size), (u8 *)p_virt + size, size); |
|---|
| 866 | 884 | |
|---|
| 867 | | - memset(¶ms, 0, sizeof(params)); |
|---|
| 868 | 885 | rc = qed_dmae_host2host(p_hwfn, p_ptt, p_phys, p_phys + size, |
|---|
| 869 | | - size / 4 /* size_in_dwords */, ¶ms); |
|---|
| 886 | + size / 4, NULL); |
|---|
| 870 | 887 | if (rc) { |
|---|
| 871 | 888 | DP_NOTICE(p_hwfn, |
|---|
| 872 | 889 | "DMAE sanity [%s]: qed_dmae_host2host() failed. rc = %d.\n", |
|---|