4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #ifndef _SYS_IB_ADAPTERS_TAVOR_HW_H
28 #define _SYS_IB_ADAPTERS_TAVOR_HW_H
32 * Contains all the structure definitions and #defines for all Tavor
33 * hardware resources and registers (as defined by the Tavor register
34 * specification). Wherever possible, the names in the Tavor spec
35 * have been preserved in the structure and field names below.
38 #include <sys/types.h>
41 #include <sys/sunddi.h>
49 * Offsets into the CMD BAR (BAR 0) for many of the more interesting hardware
50 * registers. These registers include the HCR (more below), the Event Cause
51 * Register (ECR) and its related clear register, the Interrupt Clear register
52 * (CLR_INT), and the software reset register (SW_RESET).
54 #define TAVOR_CMD_HCR_OFFSET 0x80680
55 #define TAVOR_CMD_ECR_OFFSET 0x80700
56 #define TAVOR_CMD_CLR_ECR_OFFSET 0x80708
57 #define TAVOR_CMD_CLR_INT_OFFSET 0xF00D8
58 #define TAVOR_CMD_SW_RESET_OFFSET 0xF0010
61 * Ownership flags used to define hardware or software ownership for
62 * various Tavor resources
64 #define TAVOR_HW_OWNER 0x1
65 #define TAVOR_SW_OWNER 0x0
68 * Determines whether or not virtual-to-physical address translation is
69 * required. Several of the Tavor hardware structures can be optionally
70 * accessed by Tavor without going through the TPT address translation
73 #define TAVOR_VA2PA_XLAT_ENABLED 0x1
74 #define TAVOR_VA2PA_XLAT_DISABLED 0x0
77 * HCA Command Register (HCR)
78 * The HCR command interface provides privileged access to the HCA in
79 * order to query, configure and modify HCA execution. It is the
80 * primary mechanism through which mailboxes may be posted to Tavor
81 * firmware. To use this interface software fills the HCR with pointers
82 * to input and output mailboxes. Some commands support immediate
83 * parameters, however, and for these commands the HCR will contain the
84 * input or output parameters. Command execution completion can be
85 * detected either by the software polling the HCR or by waiting for a
86 * command completion event.
88 struct tavor_hw_hcr_s
{
91 uint32_t input_modifier
;
97 #define TAVOR_HCR_TOKEN_MASK 0xFFFF0000
98 #define TAVOR_HCR_TOKEN_SHIFT 16
100 #define TAVOR_HCR_CMD_STATUS_MASK 0xFF000000
101 #define TAVOR_HCR_CMD_GO_MASK 0x00800000
102 #define TAVOR_HCR_CMD_E_MASK 0x00400000
103 #define TAVOR_HCR_CMD_OPMOD_MASK 0x0000F000
104 #define TAVOR_HCR_CMD_OPCODE_MASK 0x00000FFF
105 #define TAVOR_HCR_CMD_STATUS_SHFT 24
106 #define TAVOR_HCR_CMD_GO_SHFT 23
107 #define TAVOR_HCR_CMD_E_SHFT 22
108 #define TAVOR_HCR_CMD_OPMOD_SHFT 12
112 * Tavor "QUERY_DEV_LIM" command
113 * The QUERY_DEV_LIM command returns the device limits and capabilities
114 * supported by the Tavor device. This command should be run before
115 * running the INIT_HCA command (below) in order to determine the maximum
116 * capabilities of the device and which optional features are supported.
118 #ifdef _LITTLE_ENDIAN
119 struct tavor_hw_querydevlim_s
{
121 uint32_t log_max_ee
:5;
123 uint32_t log_rsvd_ee
:4;
125 uint32_t log_max_srq
:5;
127 uint32_t log_rsvd_srq
:4;
128 uint32_t log_max_qp
:5;
130 uint32_t log_rsvd_qp
:4;
132 uint32_t log_max_qp_sz
:8;
133 uint32_t log_max_srq_sz
:8;
134 uint32_t log_max_eq
:3;
136 uint32_t num_rsvd_eq
:4;
138 uint32_t log_max_mpt
:6;
140 uint32_t log_max_cq
:5;
142 uint32_t log_rsvd_cq
:4;
144 uint32_t log_max_cq_sz
:8;
146 uint32_t log_max_av
:6;
148 uint32_t log_max_mttseg
:6;
150 uint32_t log_rsvd_mpt
:4;
152 uint32_t log_max_mrw_sz
:8;
154 uint32_t log_rsvd_mttseg
:4;
155 uint32_t log_max_ra_glob
:6;
157 uint32_t log_max_ras_qp
:6;
159 uint32_t log_max_raq_qp
:6;
161 uint32_t num_ports
:4;
163 uint32_t max_port_width
:4;
165 uint32_t ca_ack_delay
:5;
168 uint32_t log_max_pkey
:4;
170 uint32_t stat_rate_sup
:16;
171 uint32_t log_max_gid
:4;
177 uint32_t raw_ipv6
:1;
178 uint32_t raw_ether
:1;
187 uint32_t raw_multi
:1;
189 uint32_t ud_multi
:1;
191 uint32_t pg_on_demand
:1;
196 uint32_t log_pg_sz
:8;
198 uint32_t log_max_uar_sz
:6;
200 uint32_t num_rsvd_uar
:4;
202 uint32_t max_desc_sz
:16;
206 uint32_t log_max_rdd
:6;
208 uint32_t num_rsvd_rdd
:4;
209 uint32_t log_max_pd
:6;
211 uint32_t num_rsvd_pd
:4;
212 uint32_t log_max_mcg
:8;
213 uint32_t num_rsvd_mcg
:4;
215 uint32_t log_max_qp_mcg
:8;
218 uint32_t eqpc_entry_sz
:16;
219 uint32_t eeec_entry_sz
:16;
220 uint32_t qpc_entry_sz
:16;
221 uint32_t eec_entry_sz
:16;
222 uint32_t uarscr_entry_sz
:16;
223 uint32_t srq_entry_sz
:16;
224 uint32_t cqc_entry_sz
:16;
225 uint32_t eqc_entry_sz
:16;
229 struct tavor_hw_querydevlim_s
{
231 uint32_t log_max_srq_sz
:8;
232 uint32_t log_max_qp_sz
:8;
234 uint32_t log_rsvd_qp
:4;
236 uint32_t log_max_qp
:5;
237 uint32_t log_rsvd_srq
:4;
239 uint32_t log_max_srq
:5;
241 uint32_t log_rsvd_ee
:4;
243 uint32_t log_max_ee
:5;
245 uint32_t log_max_cq_sz
:8;
247 uint32_t log_rsvd_cq
:4;
249 uint32_t log_max_cq
:5;
251 uint32_t log_max_mpt
:6;
253 uint32_t num_rsvd_eq
:4;
255 uint32_t log_max_eq
:3;
256 uint32_t log_rsvd_mttseg
:4;
258 uint32_t log_max_mrw_sz
:8;
260 uint32_t log_rsvd_mpt
:4;
262 uint32_t log_max_mttseg
:6;
264 uint32_t log_max_av
:6;
266 uint32_t log_max_raq_qp
:6;
268 uint32_t log_max_ras_qp
:6;
270 uint32_t log_max_ra_glob
:6;
273 uint32_t ca_ack_delay
:5;
275 uint32_t max_port_width
:4;
277 uint32_t num_ports
:4;
279 uint32_t log_max_gid
:4;
280 uint32_t stat_rate_sup
:16;
282 uint32_t log_max_pkey
:4;
286 uint32_t pg_on_demand
:1;
288 uint32_t ud_multi
:1;
290 uint32_t raw_multi
:1;
299 uint32_t raw_ether
:1;
300 uint32_t raw_ipv6
:1;
305 uint32_t num_rsvd_uar
:4;
307 uint32_t log_max_uar_sz
:6;
309 uint32_t log_pg_sz
:8;
313 uint32_t max_desc_sz
:16;
317 uint32_t log_max_qp_mcg
:8;
319 uint32_t num_rsvd_mcg
:4;
320 uint32_t log_max_mcg
:8;
321 uint32_t num_rsvd_pd
:4;
323 uint32_t log_max_pd
:6;
324 uint32_t num_rsvd_rdd
:4;
326 uint32_t log_max_rdd
:6;
328 uint32_t eec_entry_sz
:16;
329 uint32_t qpc_entry_sz
:16;
330 uint32_t eeec_entry_sz
:16;
331 uint32_t eqpc_entry_sz
:16;
332 uint32_t eqc_entry_sz
:16;
333 uint32_t cqc_entry_sz
:16;
334 uint32_t srq_entry_sz
:16;
335 uint32_t uarscr_entry_sz
:16;
342 * Tavor "QUERY_FW" command
343 * The QUERY_FW command retrieves the firmware revision and the Command
344 * Interface revision. The command also returns the HCA attached local
345 * memory area (DDR) which is used by the firmware. Below we also
346 * include some defines which are used to enforce a minimum firmware
347 * version check (see tavor_fw_version_check() for more details).
349 #ifdef _LITTLE_ENDIAN
350 struct tavor_hw_queryfw_s
{
351 uint32_t fw_rev_minor
:16;
352 uint32_t fw_rev_subminor
:16;
353 uint32_t fw_rev_major
:16;
355 uint32_t log_max_cmd
:8;
357 uint32_t dbg_trace
:1;
358 uint32_t cmd_intf_rev
:16;
361 uint64_t fw_baseaddr
;
363 uint64_t error_buf_addr
;
365 uint32_t error_buf_sz
;
369 struct tavor_hw_queryfw_s
{
371 uint32_t fw_rev_major
:16;
372 uint32_t fw_rev_subminor
:16;
373 uint32_t fw_rev_minor
:16;
375 uint32_t cmd_intf_rev
:16;
376 uint32_t dbg_trace
:1;
378 uint32_t log_max_cmd
:8;
380 uint64_t fw_baseaddr
;
382 uint64_t error_buf_addr
;
383 uint32_t error_buf_sz
;
387 #define TAVOR_FW_VER_MAJOR 0x0003
388 #define TAVOR_FW_VER_MINOR 0x0001
389 #define TAVOR_FW_VER_SUBMINOR 0x0000
390 #define TAVOR_COMPAT_FW_VER_MAJOR 0x0004
391 #define TAVOR_COMPAT_FW_VER_MINOR 0x0005
392 #define TAVOR_COMPAT_FW_VER_SUBMINOR 0x0003
396 * Tavor "QUERY_DDR" command
397 * The QUERY_DDR command retrieves information regarding the HCA attached
398 * local memory area (DDR). This information includes: the DIMM PCI BAR,
399 * the total address space provided by the HCA attached local memory, and
400 * some DIMM-specific information. Note: Some of the HCA attached local
401 * memory is reserved for use by firmware. This extent of this reserved
402 * area can be obtained through the QUERY_FW command (above).
404 * Below we first define the tavor_hw_queryddr_dimm_t or "Logical DIMM
405 * Information" structure. Four of these are present in the QUERY_DDR
408 #ifdef _LITTLE_ENDIAN
409 typedef struct tavor_hw_queryddr_dimm_s
{
412 uint32_t sock_num
:2;
417 uint32_t dimmstatus
:1;
418 uint32_t dimm_hidden
:1;
419 uint32_t write_only
:1;
421 uint32_t vendor_id_l
;
422 uint32_t vendor_id_h
;
423 uint32_t dimm_baseaddr_l
;
424 uint32_t dimm_baseaddr_h
;
426 } tavor_hw_queryddr_dimm_t
;
428 typedef struct tavor_hw_queryddr_dimm_s
{
430 uint32_t write_only
:1;
431 uint32_t dimm_hidden
:1;
432 uint32_t dimmstatus
:1;
437 uint32_t sock_num
:2;
440 uint32_t vendor_id_h
;
441 uint32_t vendor_id_l
;
442 uint32_t dimm_baseaddr_h
;
443 uint32_t dimm_baseaddr_l
;
445 } tavor_hw_queryddr_dimm_t
;
447 #define TAVOR_DIMMSTATUS_ENABLED 0x0
448 #define TAVOR_DIMMSTATUS_DISABLED 0x1
450 #define TAVOR_DIMM_ERR_NONE 0x0
451 #define TAVOR_DIMM_ERR_SPD 0x1
452 #define TAVOR_DIMM_ERR_BOUNDS 0x2
453 #define TAVOR_DIMM_ERR_CONFLICT 0x3
454 #define TAVOR_DIMM_ERR_SIZETRIM 0x5
456 #define TAVOR_DIMM_SPD_FROM_DIMM 0x0
457 #define TAVOR_DIMM_SPD_FROM_NVMEM 0x1
459 #ifdef _LITTLE_ENDIAN
460 struct tavor_hw_queryddr_s
{
461 uint64_t ddr_baseaddr
;
462 uint64_t ddr_endaddr
;
464 uint32_t data_integrity
:2;
465 uint32_t auto_precharge
:2;
466 uint32_t ddr_hidden
:1;
469 tavor_hw_queryddr_dimm_t dimm
[4];
473 struct tavor_hw_queryddr_s
{
474 uint64_t ddr_baseaddr
;
475 uint64_t ddr_endaddr
;
477 uint32_t ddr_hidden
:1;
478 uint32_t auto_precharge
:2;
479 uint32_t data_integrity
:2;
482 tavor_hw_queryddr_dimm_t dimm
[4];
486 #define TAVOR_AUTO_PRECHRG_NONE 0x0
487 #define TAVOR_AUTO_PRECHRG_PER_TRANS 0x1
488 #define TAVOR_AUTO_PRECHRG_PER_64B 0x2
490 #define TAVOR_DATA_INT_NONE 0x0
491 #define TAVOR_DATA_INT_PARITY 0x1
492 #define TAVOR_DATA_INT_ECC_DETECT_ONLY 0x2
493 #define TAVOR_DATA_INT_ECC_CORRECT 0x3
497 * Tavor "QUERY_ADAPTER" command
498 * The QUERY_ADAPTER command retrieves adapter specific parameters. The
499 * command also retrieves the PCI(X) interrupt pin routing for each of
500 * the INTx# pins supported by the device. This information is used by
501 * the driver during interrupt processing in order to clear the appropriate
504 #ifdef _LITTLE_ENDIAN
505 struct tavor_hw_queryadapter_s
{
512 uint32_t inta_pin
:8;
516 struct tavor_hw_queryadapter_s
{
521 uint32_t inta_pin
:8;
527 #define TAVOR_REV_A0 0xA0
528 #define TAVOR_REV_A1 0xA1
532 * Tavor "INIT_HCA" and "QUERY_HCA" commands
533 * The INIT_HCA command configures all HCA resources in HCA attached local
534 * memory and some system relevant information. The same mailbox output
535 * format is used by the QUERY_HCA command. All parameters, which are
536 * specifically the output of the QUERY_HCA command are marked as
537 * "QUERY_HCA only". These parameters are not configurable through the
538 * INIT_HCA command, but can be retrieved as read-only through the
541 * Below we first define several structures which help make up the whole
542 * of the INIT_HCA/QUERY_HCA command. These are:
543 * tavor_hw_qp_ee_cq_eq_rdb_t for "QPC/EEC/CQC/EQC/RDB Parameters",
544 * tavor_udav_mem_param_t for "Memory Access Parameters for UDAV Table",
545 * tavor_multicast_param_t for "Multicast Support Parameters",
546 * tavor_tpt_param_t for "Translation and Protection Table Parameters",
547 * and tavor_uar_param_t for Tavor "UAR Parameters".
549 #ifdef _LITTLE_ENDIAN
550 typedef struct tavor_hw_qp_ee_cq_eq_rdb_s
{
552 uint32_t log_num_qp
:5;
554 uint32_t qpc_baseaddr_l
:25;
555 uint32_t qpc_baseaddr_h
;
557 uint32_t log_num_ee
:5;
559 uint32_t eec_baseaddr_l
:25;
560 uint32_t eec_baseaddr_h
;
561 uint32_t log_num_srq
:5;
562 uint32_t srqc_baseaddr_l
:27;
563 uint32_t srqc_baseaddr_h
;
564 uint32_t log_num_cq
:5;
566 uint32_t cqc_baseaddr_l
:26;
567 uint32_t cqc_baseaddr_h
;
569 uint64_t eqpc_baseaddr
;
571 uint64_t eeec_baseaddr
;
573 uint32_t log_num_eq
:4;
575 uint32_t eqc_baseaddr_l
:26;
576 uint32_t eqc_baseaddr_h
;
578 uint32_t rdb_baseaddr_l
;
579 uint32_t rdb_baseaddr_h
;
581 } tavor_hw_qp_ee_cq_eq_rdb_t
;
583 typedef struct tavor_hw_qp_ee_cq_eq_rdb_s
{
585 uint32_t qpc_baseaddr_h
;
586 uint32_t qpc_baseaddr_l
:25;
588 uint32_t log_num_qp
:5;
590 uint32_t eec_baseaddr_h
;
591 uint32_t eec_baseaddr_l
:25;
593 uint32_t log_num_ee
:5;
594 uint32_t srqc_baseaddr_h
;
595 uint32_t srqc_baseaddr_l
:27;
596 uint32_t log_num_srq
:5;
597 uint32_t cqc_baseaddr_h
;
598 uint32_t cqc_baseaddr_l
:26;
600 uint32_t log_num_cq
:5;
602 uint64_t eqpc_baseaddr
;
604 uint64_t eeec_baseaddr
;
606 uint32_t eqc_baseaddr_h
;
607 uint32_t eqc_baseaddr_l
:26;
609 uint32_t log_num_eq
:4;
611 uint32_t rdb_baseaddr_h
;
612 uint32_t rdb_baseaddr_l
;
614 } tavor_hw_qp_ee_cq_eq_rdb_t
;
617 #ifdef _LITTLE_ENDIAN
618 typedef struct tavor_udav_mem_param_s
{
619 uint32_t udav_pd
:24;
621 uint32_t udav_xlat_en
:1;
624 } tavor_udav_mem_param_t
;
626 typedef struct tavor_udav_mem_param_s
{
629 uint32_t udav_xlat_en
:1;
631 uint32_t udav_pd
:24;
632 } tavor_udav_mem_param_t
;
635 #ifdef _LITTLE_ENDIAN
636 typedef struct tavor_multicast_param_s
{
637 uint64_t mc_baseaddr
;
639 uint32_t mc_tbl_hash_sz
:17;
641 uint32_t log_mc_tbl_ent
:16;
644 uint32_t log_mc_tbl_sz
:5;
646 uint32_t mc_hash_fn
:3;
648 } tavor_multicast_param_t
;
650 typedef struct tavor_multicast_param_s
{
651 uint64_t mc_baseaddr
;
654 uint32_t log_mc_tbl_ent
:16;
656 uint32_t mc_tbl_hash_sz
:17;
658 uint32_t mc_hash_fn
:3;
660 uint32_t log_mc_tbl_sz
:5;
662 } tavor_multicast_param_t
;
664 #define TAVOR_MCG_DEFAULT_HASH_FN 0x0
666 #ifdef _LITTLE_ENDIAN
667 typedef struct tavor_tpt_param_s
{
668 uint64_t mpt_baseaddr
;
669 uint32_t mtt_version
:8;
671 uint32_t log_mpt_sz
:6;
673 uint32_t pgfault_rnr_to
:5;
675 uint32_t mttseg_sz
:3;
677 uint64_t mtt_baseaddr
;
681 typedef struct tavor_tpt_param_s
{
682 uint64_t mpt_baseaddr
;
684 uint32_t mttseg_sz
:3;
686 uint32_t pgfault_rnr_to
:5;
688 uint32_t log_mpt_sz
:6;
690 uint32_t mtt_version
:8;
691 uint64_t mtt_baseaddr
;
696 #ifdef _LITTLE_ENDIAN
697 typedef struct tavor_uar_param_s
{
699 uint32_t uar_baseaddr_l
:12; /* QUERY_HCA only */
700 uint32_t uar_baseaddr_h
; /* QUERY_HCA only */
702 uint32_t uar_pg_sz
:8;
704 uint64_t uarscr_baseaddr
;
708 typedef struct tavor_uar_param_s
{
709 uint32_t uar_baseaddr_h
; /* QUERY_HCA only */
710 uint32_t uar_baseaddr_l
:12; /* QUERY_HCA only */
713 uint32_t uar_pg_sz
:8;
715 uint64_t uarscr_baseaddr
;
720 #ifdef _LITTLE_ENDIAN
721 struct tavor_hw_initqueryhca_s
{
724 uint32_t hca_core_clock
:8; /* QUERY_HCA only */
726 uint32_t udav_port_chk
:1;
727 uint32_t big_endian
:1;
728 uint32_t udav_chk
:1;
730 uint32_t responder_exu
:4;
732 uint32_t wqe_quota
:15;
733 uint32_t wqe_quota_en
:1;
735 uint32_t router_qp
:16;
737 uint32_t router_en
:1;
739 tavor_hw_qp_ee_cq_eq_rdb_t context
;
741 tavor_udav_mem_param_t udav
;
743 tavor_multicast_param_t multi
;
745 tavor_tpt_param_t tpt
;
747 tavor_uar_param_t uar
;
751 struct tavor_hw_initqueryhca_s
{
754 uint32_t hca_core_clock
:8; /* QUERY_HCA only */
756 uint32_t router_en
:1;
758 uint32_t router_qp
:16;
760 uint32_t wqe_quota_en
:1;
761 uint32_t wqe_quota
:15;
763 uint32_t responder_exu
:4;
765 uint32_t udav_chk
:1;
766 uint32_t big_endian
:1;
767 uint32_t udav_port_chk
:1;
769 tavor_hw_qp_ee_cq_eq_rdb_t context
;
771 tavor_udav_mem_param_t udav
;
773 tavor_multicast_param_t multi
;
775 tavor_tpt_param_t tpt
;
777 tavor_uar_param_t uar
;
781 #define TAVOR_UDAV_PROTECT_DISABLED 0x0
782 #define TAVOR_UDAV_PROTECT_ENABLED 0x1
783 #define TAVOR_UDAV_PORTCHK_DISABLED 0x0
784 #define TAVOR_UDAV_PORTCHK_ENABLED 0x1
788 * Tavor "INIT_IB" command
789 * The INIT_IB command enables the physical layer of a given IB port.
790 * It provides control over the IB port attributes. The capabilities
791 * requested here should not exceed the device limits, as retrieved by
792 * the QUERY_DEV_LIM command (above). To query information about the IB
793 * port or node, the driver may submit GetPortInfo or GetNodeInfo MADs
794 * through the Tavor MAD_IFC command.
796 #ifdef _LITTLE_ENDIAN
797 struct tavor_hw_initib_s
{
798 uint32_t max_gid
:16;
802 uint32_t port_width_cap
:4;
804 uint32_t set_port_guid0
:1;
805 uint32_t set_node_guid
:1;
806 uint32_t set_sysimg_guid
:1;
809 uint32_t max_pkey
:16;
813 uint64_t sysimg_guid
;
817 struct tavor_hw_initib_s
{
819 uint32_t set_sysimg_guid
:1;
820 uint32_t set_node_guid
:1;
821 uint32_t set_port_guid0
:1;
823 uint32_t port_width_cap
:4;
827 uint32_t max_gid
:16;
829 uint32_t max_pkey
:16;
833 uint64_t sysimg_guid
;
839 * Tavor Memory Protection Table (MPT) entries
840 * The Memory Protection Table (MPT) contains the information associated
841 * with all the regions and windows. The MPT table resides in a physically-
842 * contiguous area in HCA attached local memory, and the memory key (R_Key
843 * or L_Key) is used to calculate the physical address for accessing the
844 * entries in the table.
846 * The following structure is used in the SW2HW_MPT, QUERY_MPT, and
847 * HW2SW_MPT commands.
848 * The SW2HW_MPT command transfers ownership of an MPT entry from software
849 * to hardware. The command takes the MPT entry from the input mailbox and
850 * stores it in the MPT in the hardware. The command will fail if the
851 * requested MPT entry is already owned by the hardware or if the MPT index
852 * given in the command is inconsistent with the MPT entry memory key.
853 * The QUERY_MPT command retrieves a snapshot of an MPT entry. The command
854 * takes the current state of an MPT entry from the hardware and stores it
855 * in the output mailbox. The command will fail if the requested MPT entry
856 * is already owned by software.
857 * Finally, the HW2SW_MPT command transfers ownership of an MPT entry from
858 * the hardware to the software. The command takes the MPT entry from the
859 * hardware, invalidates it, and stores it in the output mailbox. The
860 * command will fail if the requested entry is already owned by software.
861 * The command will also fail if the MPT entry in question is a Memory
862 * Region which has Memory Windows currently bound to it.
864 #ifdef _LITTLE_ENDIAN
865 struct tavor_hw_mpt_s
{
871 uint32_t phys_addr
:1;
886 uint64_t reg_win_len
;
889 uint32_t mttseg_addr_h
;
890 uint32_t win_cnt_limit
;
893 uint32_t mttseg_addr_l
:26;
897 struct tavor_hw_mpt_s
{
908 uint32_t phys_addr
:1;
918 uint64_t reg_win_len
;
921 uint32_t win_cnt_limit
;
922 uint32_t mttseg_addr_h
;
923 uint32_t mttseg_addr_l
:26;
929 #define TAVOR_MEM_CYCLE_GENERATE 0x1
930 #define TAVOR_IO_CYCLE_GENERATE 0x0
932 #define TAVOR_MPT_IS_WINDOW 0x0
933 #define TAVOR_MPT_IS_REGION 0x1
935 #define TAVOR_MPT_DEFAULT_VERSION 0x0
937 #define TAVOR_UNLIMITED_WIN_BIND 0x0
939 #define TAVOR_PHYSADDR_ENABLED 0x1
940 #define TAVOR_PHYSADDR_DISABLED 0x0
944 * Tavor Memory Translation Table (MTT) entries
945 * After accessing the MPT table (above) and validating the access rights
946 * to the region/window, Tavor address translation moves to the next step
947 * where it translates the virtual address to a physical address. This
948 * translation is performed using the Memory Translation Table entries
949 * (MTT). Note: The MTT in hardware is organized into segments and each
950 * segment contains multiple address translation pages (MTT entries).
951 * Each memory region (MPT above) points to the first segment in the MTT
952 * that corresponds to that region.
954 #ifdef _LITTLE_ENDIAN
955 struct tavor_hw_mtt_s
{
962 struct tavor_hw_mtt_s
{
969 #define TAVOR_MTT_ENTRY_NOTPRESET 0x0
970 #define TAVOR_MTT_ENTRY_PRESET 0x1
974 * Tavor Event Queue Context Table (EQC) entries
975 * Tavor supports 64 Event Queues, and the status of Event Queues is stored
976 * in the Event Queue Context (EQC) table. The EQC table is a physically-
977 * contiguous memory structure in the HCA attached local memory. Each EQC
978 * table entry contains Event Queue status and information required by
979 * the hardware in order to access the event queue.
981 * The following structure is used in the SW2HW_EQ, QUERY_EQ, and HW2SW_EQ
983 * The SW2HW_EQ command transfers ownership of an EQ context from software
984 * to hardware. The command takes the EQC entry from the input mailbox and
985 * stores it in the EQC in the hardware. The command will fail if the
986 * requested EQC entry is already owned by the hardware.
987 * The QUERY_EQ command retrieves a snapshot of an EQC entry. The command
988 * stores the snapshot in the output mailbox. The EQC state and its values
989 * are not affected by the QUERY_EQ command.
990 * Finally, the HW2SW_EQ command transfers ownership of an EQC entry from
991 * the hardware to the software. The command takes the EQC entry from the
992 * hardware and stores it in the output mailbox. The EQC entry will be
993 * invalidated as a result of the command. It is the responsibility of the
994 * software to unmap all the events, which might have been previously
995 * mapped to the EQ, prior to issuing the HW2SW_EQ command.
997 #ifdef _LITTLE_ENDIAN
998 struct tavor_hw_eqc_s
{
999 uint32_t start_addr_h
;
1003 uint32_t overrun_ignore
:1;
1008 uint32_t usr_page
:24;
1009 uint32_t log_eq_sz
:5;
1011 uint32_t start_addr_l
;
1024 struct tavor_hw_eqc_s
{
1029 uint32_t overrun_ignore
:1;
1033 uint32_t start_addr_h
;
1034 uint32_t start_addr_l
;
1036 uint32_t log_eq_sz
:5;
1037 uint32_t usr_page
:24;
1050 #define TAVOR_EQ_STATUS_OK 0x0
1051 #define TAVOR_EQ_STATUS_OVERFLOW 0x9
1052 #define TAVOR_EQ_STATUS_WRITE_FAILURE 0xA
1054 #define TAVOR_EQ_ARMED 0x1
1055 #define TAVOR_EQ_FIRED 0x2
1056 #define TAVOR_EQ_ALWAYS_ARMED 0x3
1060 * Tavor Event Queue Entries (EQE)
1061 * Each EQE contains enough information for the software to identify the
1062 * source of the event. The following structures are used to define each
1063 * of the various kinds of events that the Tavor hardware will generate.
1064 * Note: The tavor_hw_eqe_t below is the generic "Event Queue Entry". All
1065 * other EQEs differ only in the contents of their "event_data" field.
1067 * Below we first define several structures which define the contents of
1068 * the "event_data" fields:
1069 * tavor_hw_eqe_cq_t for "Completion Queue Events"
1070 * tavor_hw_eqe_cqerr_t for "Completion Queue Error Events"
1071 * tavor_hw_eqe_portstate_t for "Port State Change Events"
1072 * tavor_hw_eqe_cmdcmpl_t for "Command Interface Completion Events"
1073 * tavor_hw_eqe_qp_evt_t for "Queue Pair Events" such as Path Migration
1074 * Succeeded, Path Migration Failed, Communication Established, Send
1075 * Queue Drained, Local WQ Catastrophic Error, Invalid Request Local
1076 * WQ Error, and Local Access Violation WQ Error.
1077 * tavor_hw_eqe_operr_t for "Operational and Catastrophic Error Events"
1078 * such as EQ Overflow, Misbehaved UAR page, Internal Parity Error,
1079 * Uplink bus error, and DDR data error.
1080 * tavor_hw_eqe_pgflt_t for "Not-present Page Fault on WQE or Data
1081 * Buffer Access". (Note: Currently, this event is unsupported).
1083 * Note also: The following structures are not #define'd with both
1084 * little-endian and big-endian definitions. This is because their
1085 * individual fields are not directly accessed except through the macros
1088 typedef struct tavor_hw_eqe_cq_s
{
1092 } tavor_hw_eqe_cq_t
;
1094 typedef struct tavor_hw_eqe_cqerr_s
{
1099 uint32_t syndrome
:8;
1101 } tavor_hw_eqe_cqerr_t
;
1102 #define TAVOR_CQERR_OVERFLOW 0x1
1103 #define TAVOR_CQERR_ACCESS_VIOLATION 0x2
1105 typedef struct tavor_hw_eqe_portstate_s
{
1111 } tavor_hw_eqe_portstate_t
;
1112 #define TAVOR_PORT_LINK_ACTIVE 0x4
1113 #define TAVOR_PORT_LINK_DOWN 0x1
1115 typedef struct tavor_hw_eqe_cmdcmpl_s
{
1121 uint32_t out_param0
;
1122 uint32_t out_param1
;
1124 } tavor_hw_eqe_cmdcmpl_t
;
1126 typedef struct tavor_hw_eqe_qp_evt_s
{
1134 } tavor_hw_eqe_qpevt_t
;
1136 typedef struct tavor_hw_eqe_operr_s
{
1139 uint32_t error_type
:8;
1142 } tavor_hw_eqe_operr_t
;
1143 #define TAVOR_ERREVT_EQ_OVERFLOW 0x1
1144 #define TAVOR_ERREVT_BAD_UARPG 0x2
1145 #define TAVOR_ERREVT_UPLINK_BUSERR 0x3
1146 #define TAVOR_ERREVT_DDR_DATAERR 0x4
1147 #define TAVOR_ERREVT_INTERNAL_PARITY 0x5
1149 typedef struct tavor_hw_eqe_pgflt_s
{
1152 uint32_t fault_type
:4;
1154 uint32_t wqe_data
:1;
1155 uint32_t rem_loc
:1;
1156 uint32_t snd_rcv
:1;
1160 } tavor_hw_eqe_pgflt_t
;
1161 #define TAVOR_PGFLT_PG_NOTPRESENT 0x8
1162 #define TAVOR_PGFLT_PG_WRACC_VIOL 0xA
1163 #define TAVOR_PGFLT_UNSUP_NOTPRESENT 0xE
1164 #define TAVOR_PGFLT_UNSUP_WRACC_VIOL 0xF
1165 #define TAVOR_PGFLT_WQE_CAUSED 0x1
1166 #define TAVOR_PGFLT_DATA_CAUSED 0x0
1167 #define TAVOR_PGFLT_REMOTE_CAUSED 0x1
1168 #define TAVOR_PGFLT_LOCAL_CAUSED 0x0
1169 #define TAVOR_PGFLT_SEND_CAUSED 0x1
1170 #define TAVOR_PGFLT_RECV_CAUSED 0x0
1171 #define TAVOR_PGFLT_DESC_CONSUMED 0x1
1172 #define TAVOR_PGFLT_DESC_NOTCONSUMED 0x0
1174 typedef struct tavor_hw_eqe_ecc_s
{
1176 uint32_t overflow
:1;
1181 uint32_t err_src_id
:3;
1182 uint32_t err_rmw
:1;
1184 uint32_t cause_msb
:1;
1186 uint32_t cause_lsb
:1;
1188 uint32_t err_ca
:16;
1189 uint32_t err_ra
:16;
1190 } tavor_hw_eqe_ecc_t
;
1192 struct tavor_hw_eqe_s
{
1194 uint32_t event_type
:8;
1196 uint32_t event_subtype
:8;
1198 tavor_hw_eqe_cq_t eqe_cq
;
1199 tavor_hw_eqe_cqerr_t eqe_cqerr
;
1200 tavor_hw_eqe_portstate_t eqe_portstate
;
1201 tavor_hw_eqe_cmdcmpl_t eqe_cmdcmpl
;
1202 tavor_hw_eqe_qpevt_t eqe_qpevt
;
1203 tavor_hw_eqe_operr_t eqe_operr
;
1204 tavor_hw_eqe_pgflt_t eqe_pgflt
;
1205 tavor_hw_eqe_ecc_t eqe_ecc
;
1211 #define eqe_cq event_data.eqe_cq
1212 #define eqe_cqerr event_data.eqe_cqerr
1213 #define eqe_portstate event_data.eqe_portstate
1214 #define eqe_cmdcmpl event_data.eqe_cmdcmpl
1215 #define eqe_qpevt event_data.eqe_qpevt
1216 #define eqe_operr event_data.eqe_operr
1217 #define eqe_pgflt event_data.eqe_pgflt
1220 * The following macros are used for extracting (and in some cases filling in)
1221 * information from EQEs
1223 #define TAVOR_EQE_EVTTYPE_MASK 0x00FF0000
1224 #define TAVOR_EQE_EVTTYPE_SHIFT 16
1225 #define TAVOR_EQE_EVTSUBTYPE_MASK 0x000000FF
1226 #define TAVOR_EQE_EVTSUBTYPE_SHIFT 0
1227 #define TAVOR_EQE_CQNUM_MASK 0x00FFFFFF
1228 #define TAVOR_EQE_CQNUM_SHIFT 0
1229 #define TAVOR_EQE_QPNUM_MASK 0x00FFFFFF
1230 #define TAVOR_EQE_QPNUM_SHIFT 0
1231 #define TAVOR_EQE_PORTNUM_MASK 0x30000000
1232 #define TAVOR_EQE_PORTNUM_SHIFT 28
1233 #define TAVOR_EQE_CMDTOKEN_MASK 0x0000FFFF
1234 #define TAVOR_EQE_CMDTOKEN_SHIFT 0
1235 #define TAVOR_EQE_CMDSTATUS_MASK 0x000000FF
1236 #define TAVOR_EQE_CMDSTATUS_SHIFT 0
1237 #define TAVOR_EQE_OPERRTYPE_MASK 0x000000FF
1238 #define TAVOR_EQE_OPERRTYPE_SHIFT 0
1239 #define TAVOR_EQE_OWNER_MASK 0x00000080
1240 #define TAVOR_EQE_OWNER_SHIFT 7
1242 #define TAVOR_EQE_EVTTYPE_GET(eq, eqe) \
1243 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1244 &((uint32_t *)(eqe))[0]) & TAVOR_EQE_EVTTYPE_MASK) >> \
1245 TAVOR_EQE_EVTTYPE_SHIFT)
1246 #define TAVOR_EQE_EVTSUBTYPE_GET(eq, eqe) \
1247 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1248 &((uint32_t *)(eqe))[0]) & TAVOR_EQE_EVTSUBTYPE_MASK) >> \
1249 TAVOR_EQE_EVTSUBTYPE_SHIFT)
1250 #define TAVOR_EQE_CQNUM_GET(eq, eqe) \
1251 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1252 &((uint32_t *)(eqe))[1]) & TAVOR_EQE_CQNUM_MASK) >> \
1253 TAVOR_EQE_CQNUM_SHIFT)
1254 #define TAVOR_EQE_QPNUM_GET(eq, eqe) \
1255 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1256 &((uint32_t *)(eqe))[1]) & TAVOR_EQE_QPNUM_MASK) >> \
1257 TAVOR_EQE_QPNUM_SHIFT)
1258 #define TAVOR_EQE_PORTNUM_GET(eq, eqe) \
1259 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1260 &((uint32_t *)(eqe))[3]) & TAVOR_EQE_PORTNUM_MASK) >> \
1261 TAVOR_EQE_PORTNUM_SHIFT)
1262 #define TAVOR_EQE_CMDTOKEN_GET(eq, eqe) \
1263 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1264 &((uint32_t *)(eqe))[1]) & TAVOR_EQE_CMDTOKEN_MASK) >> \
1265 TAVOR_EQE_CMDTOKEN_SHIFT)
1266 #define TAVOR_EQE_CMDSTATUS_GET(eq, eqe) \
1267 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1268 &((uint32_t *)(eqe))[3]) & TAVOR_EQE_CMDSTATUS_MASK) >> \
1269 TAVOR_EQE_CMDSTATUS_SHIFT)
1270 #define TAVOR_EQE_CMDOUTP0_GET(eq, eqe) \
1271 (ddi_get32((eq)->eq_eqinfo.qa_acchdl, &((uint32_t *)(eqe))[4]))
1272 #define TAVOR_EQE_CMDOUTP1_GET(eq, eqe) \
1273 (ddi_get32((eq)->eq_eqinfo.qa_acchdl, &((uint32_t *)(eqe))[5]))
1274 #define TAVOR_EQE_OPERRTYPE_GET(eq, eqe) \
1275 ((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1276 &((uint32_t *)(eqe))[3]) & TAVOR_EQE_OPERRTYPE_MASK) >> \
1277 TAVOR_EQE_OPERRTYPE_SHIFT)
1278 #define TAVOR_EQE_OPERRDATA_GET(eq, eqe) \
1279 (ddi_get32((eq)->eq_eqinfo.qa_acchdl, &((uint32_t *)(eqe))[4]))
1280 #define TAVOR_EQE_OWNER_IS_SW(eq, eqe) \
1281 (((ddi_get32((eq)->eq_eqinfo.qa_acchdl, \
1282 &((uint32_t *)(eqe))[7]) & TAVOR_EQE_OWNER_MASK) >> \
1283 TAVOR_EQE_OWNER_SHIFT) == TAVOR_SW_OWNER)
1284 #define TAVOR_EQE_OWNER_SET_HW(eq, eqe) \
1285 (ddi_put32((eq)->eq_eqinfo.qa_acchdl, &((uint32_t *)(eqe))[7], \
1286 ((TAVOR_HW_OWNER << TAVOR_EQE_OWNER_SHIFT) & \
1287 TAVOR_EQE_OWNER_MASK)))
1291 * Tavor Completion Queue Context Table (CQC) entries
1292 * The CQC table is a physically-contiguous memory area residing in HCA
1293 * attached local memory. Each CQC table entry contains information
1294 * required by the hardware to access the completion queue to post
1295 * completions (CQE).
1297 * The following structure is used in the SW2HW_CQ, QUERY_CQ, RESIZE_CQ,
1298 * and HW2SW_CQ commands.
1299 * The SW2HW_CQ command transfers ownership of an CQ context from software
1300 * to hardware. The command takes the CQC entry from the input mailbox and
1301 * stores it in the CQC in the hardware. The command will fail if the
1302 * requested CQC entry is already owned by the hardware.
1303 * The QUERY_CQ command retrieves a snapshot of a CQC entry. The command
1304 * stores the snapshot in the output mailbox. The CQC state and its values
1305 * are not affected by the QUERY_CQ command.
1306 * Finally, the HW2SW_CQ command transfers ownership of a CQC entry from
1307 * the hardware to the software. The command takes the CQC entry from the
1308 * hardware and stores it in the output mailbox. The CQC entry will be
1309 * invalidated as a result of the command.
1311 #ifdef _LITTLE_ENDIAN
1312 struct tavor_hw_cqc_s
{
1313 uint32_t start_addr_h
;
1317 uint32_t overrun_ignore
:1;
1321 uint32_t usr_page
:24;
1322 uint32_t log_cq_sz
:5;
1324 uint32_t start_addr_l
;
1332 uint32_t solicit_prod_indx
;
1333 uint32_t last_notified_indx
;
1342 struct tavor_hw_cqc_s
{
1346 uint32_t overrun_ignore
:1;
1350 uint32_t start_addr_h
;
1351 uint32_t start_addr_l
;
1353 uint32_t log_cq_sz
:5;
1354 uint32_t usr_page
:24;
1362 uint32_t last_notified_indx
;
1363 uint32_t solicit_prod_indx
;
1372 #define TAVOR_CQ_STATUS_OK 0x0
1373 #define TAVOR_CQ_STATUS_OVERFLOW 0x9
1374 #define TAVOR_CQ_STATUS_WRITE_FAILURE 0xA
1376 #define TAVOR_CQ_DISARMED 0x0
1377 #define TAVOR_CQ_ARMED 0x1
1378 #define TAVOR_CQ_ARMED_SOLICITED 0x4
1379 #define TAVOR_CQ_FIRED 0xA
1382 * Tavor Completion Queue Entries (CQE)
1383 * Each CQE contains enough information for the software to associate the
1384 * completion with the Work Queue Element (WQE) to which it corresponds.
1386 * Note: The following structure is not #define'd with both little-endian
1387 * and big-endian definitions. This is because each CQE's individual
1388 * fields are not directly accessed except through the macros defined below.
1390 struct tavor_hw_cqe_s
{
1393 uint32_t my_qpn
:24;
1401 uint32_t ml_path
:7;
1403 uint32_t imm_eth_pkey_cred
;
1405 uint32_t wqe_addr
:26;
1408 uint32_t send_or_recv
:1;
1413 #define TAVOR_COMPLETION_RECV 0x0
1414 #define TAVOR_COMPLETION_SEND 0x1
1416 #define TAVOR_CQE_DEFAULT_VERSION 0x0
1419 * The following macros are used for extracting (and in some cases filling in)
1420 * information from CQEs
1422 #define TAVOR_CQE_QPNUM_MASK 0x00FFFFFF
1423 #define TAVOR_CQE_QPNUM_SHIFT 0
1424 #define TAVOR_CQE_DQPN_MASK 0x00FFFFFF
1425 #define TAVOR_CQE_DQPN_SHIFT 0
1426 #define TAVOR_CQE_SL_MASK 0xF0000000
1427 #define TAVOR_CQE_SL_SHIFT 28
1428 #define TAVOR_CQE_GRH_MASK 0x00800000
1429 #define TAVOR_CQE_GRH_SHIFT 23
1430 #define TAVOR_CQE_PATHBITS_MASK 0x007F0000
1431 #define TAVOR_CQE_PATHBITS_SHIFT 16
1432 #define TAVOR_CQE_DLID_MASK 0x0000FFFF
1433 #define TAVOR_CQE_DLID_SHIFT 0
1434 #define TAVOR_CQE_OPCODE_MASK 0xFF000000
1435 #define TAVOR_CQE_OPCODE_SHIFT 24
1436 #define TAVOR_CQE_SENDRECV_MASK 0x00800000
1437 #define TAVOR_CQE_SENDRECV_SHIFT 23
1438 #define TAVOR_CQE_OWNER_MASK 0x00000080
1439 #define TAVOR_CQE_OWNER_SHIFT 7
1441 #define TAVOR_CQE_QPNUM_GET(cq, cqe) \
1442 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1443 &((uint32_t *)(cqe))[0]) & TAVOR_CQE_QPNUM_MASK) >> \
1444 TAVOR_CQE_QPNUM_SHIFT)
1445 #define TAVOR_CQE_DQPN_GET(cq, cqe) \
1446 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1447 &((uint32_t *)(cqe))[2]) & TAVOR_CQE_DQPN_MASK) >> \
1448 TAVOR_CQE_DQPN_SHIFT)
1449 #define TAVOR_CQE_SL_GET(cq, cqe) \
1450 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1451 &((uint32_t *)(cqe))[3]) & TAVOR_CQE_SL_MASK) >> \
1453 #define TAVOR_CQE_GRH_GET(cq, cqe) \
1454 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1455 &((uint32_t *)(cqe))[3]) & TAVOR_CQE_GRH_MASK) >> \
1456 TAVOR_CQE_GRH_SHIFT)
1457 #define TAVOR_CQE_PATHBITS_GET(cq, cqe) \
1458 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1459 &((uint32_t *)(cqe))[3]) & TAVOR_CQE_PATHBITS_MASK) >> \
1460 TAVOR_CQE_PATHBITS_SHIFT)
1461 #define TAVOR_CQE_DLID_GET(cq, cqe) \
1462 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1463 &((uint32_t *)(cqe))[3]) & TAVOR_CQE_DLID_MASK) >> \
1464 TAVOR_CQE_DLID_SHIFT)
1465 #define TAVOR_CQE_IMM_ETH_PKEY_CRED_GET(cq, cqe) \
1466 (ddi_get32((cq)->cq_cqinfo.qa_acchdl, &((uint32_t *)(cqe))[4]))
1467 #define TAVOR_CQE_IMM_ETH_PKEY_CRED_SET(cq, cqe, arg) \
1468 (ddi_put32((cq)->cq_cqinfo.qa_acchdl, &((uint32_t *)(cqe))[4], \
1470 #define TAVOR_CQE_BYTECNT_GET(cq, cqe) \
1471 (ddi_get32((cq)->cq_cqinfo.qa_acchdl, &((uint32_t *)(cqe))[5]))
1472 #define TAVOR_CQE_WQEADDRSZ_GET(cq, cqe) \
1473 (ddi_get32((cq)->cq_cqinfo.qa_acchdl, &((uint32_t *)(cqe))[6]))
1474 #define TAVOR_CQE_WQEADDRSZ_SET(cq, cqe, arg) \
1475 (ddi_put32((cq)->cq_cqinfo.qa_acchdl, &((uint32_t *)(cqe))[6], \
1477 #define TAVOR_CQE_OPCODE_GET(cq, cqe) \
1478 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1479 &((uint32_t *)(cqe))[7]) & TAVOR_CQE_OPCODE_MASK) >> \
1480 TAVOR_CQE_OPCODE_SHIFT)
1481 #define TAVOR_CQE_SENDRECV_GET(cq, cqe) \
1482 ((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1483 &((uint32_t *)(cqe))[7]) & TAVOR_CQE_SENDRECV_MASK) >> \
1484 TAVOR_CQE_SENDRECV_SHIFT)
1485 #define TAVOR_CQE_OWNER_IS_SW(cq, cqe) \
1486 (((ddi_get32((cq)->cq_cqinfo.qa_acchdl, \
1487 &((uint32_t *)(cqe))[7]) & TAVOR_CQE_OWNER_MASK) >> \
1488 TAVOR_CQE_OWNER_SHIFT) == TAVOR_SW_OWNER)
1489 #ifdef _LITTLE_ENDIAN
1490 #define TAVOR_CQE_OWNER_SET_HW(cq, cqe) \
1492 if ((cq)->cq_is_umap) { \
1493 ((uint32_t *)(cqe))[7] = 0x80000000; \
1495 ddi_put32((cq)->cq_cqinfo.qa_acchdl, \
1496 &((uint32_t *)(cqe))[7], 0x00000080); \
1500 #define TAVOR_CQE_OWNER_SET_HW(cq, cqe) \
1502 if ((cq)->cq_is_umap) { \
1503 ((uint32_t *)(cqe))[7] = 0x00000080; \
1505 ddi_put32((cq)->cq_cqinfo.qa_acchdl, \
1506 &((uint32_t *)(cqe))[7], 0x00000080); \
1512 * Tavor Shared Receive Queue (SRQ) Context Entry Format
1514 #ifdef _LITTLE_ENDIAN
1515 struct tavor_hw_srqc_s
{
1517 uint32_t next_wqe_addr_l
:27;
1518 uint32_t wqe_addr_h
;
1525 uint32_t wqe_cnt
:16;
1531 struct tavor_hw_srqc_s
{
1532 uint32_t wqe_addr_h
;
1533 uint32_t next_wqe_addr_l
:27;
1544 uint32_t wqe_cnt
:16;
1549 * Tavor MOD_STAT_CFG input mailbox structure
1551 #ifdef _LITTLE_ENDIAN
1552 struct tavor_hw_mod_stat_cfg_s
{
1554 uint32_t log_max_srq
:5;
1559 uint32_t reserved
[62];
1562 struct tavor_hw_mod_stat_cfg_s
{
1567 uint32_t log_max_srq
:5;
1569 uint32_t reserved
[62];
1574 * Tavor UD Address Vector (UDAV)
1575 * Tavor UDAV are used in conjunction with Unreliable Datagram (UD) send
1576 * WQEs. Each UD send message specifies an address vector that denotes its
1577 * link and (optional) network layer destination address. The IBA verbs
1578 * interface enables the separation of the address administration from the
1579 * send WQE posting. The verbs consumer must use special verbs to create
1580 * and modify address handles (which represent hardware address vectors).
1581 * When posting send WQEs to UD QP, the verbs consumer must supply a
1582 * valid address handle/UDAV.
1584 #ifdef _LITTLE_ENDIAN
1585 struct tavor_hw_udav_s
{
1587 uint32_t ml_path
:7;
1591 uint32_t portnum
:2;
1593 uint32_t flow_label
:20;
1596 uint32_t hop_limit
:8;
1597 uint32_t max_stat_rate
:3;
1601 uint32_t mgid_index
:6;
1607 struct tavor_hw_udav_s
{
1609 uint32_t portnum
:2;
1613 uint32_t ml_path
:7;
1616 uint32_t mgid_index
:6;
1620 uint32_t max_stat_rate
:3;
1621 uint32_t hop_limit
:8;
1624 uint32_t flow_label
:20;
1629 #define TAVOR_UDAV_MODIFY_MASK0 0xFCFFFFFFFF000000ULL
1630 #define TAVOR_UDAV_MODIFY_MASK1 0xFFC0F80000000000ULL
1634 * Tavor Queue Pair Context Table (QPC) entries
1635 * The QPC table is a physically-contiguous memory area residing in HCA
1636 * attached local memory. Each QPC entry is accessed for reads and writes
1637 * by the HCA while executing work requests on the associated QP.
1639 * The following structure is used in the RST2INIT_QP, INIT2INIT_QP,
1640 * INIT2RTR_QP, RTR2RTS_QP, RTS2RTS_QP, SQERR2RTS_QP, TOERR_QP, RTS2SQD_QP,
1641 * SQD2RTS_QP, TORST_QP, and QUERY_QP commands.
1642 * With the exception of the QUERY_QP command, each of these commands reads
1643 * from some portion of the QPC in the input mailbox and modified the QPC
1644 * stored in the hardware. The QUERY_QP command retrieves a snapshot of a
1645 * QPC entry. The command stores the snapshot in the output mailbox. The
1646 * QPC state and its values are not affected by the QUERY_QP command.
1648 * Below we first define the tavor_hw_addr_path_t or "Tavor Address Path"
1649 * structure. This structure is used to provide address path information
1650 * (both primary and secondary) for each QP context. Note: Since this
1651 * structure is _very_ similar to the tavor_hw_udav_t structure above,
1652 * we are able to leverage the similarity with filling in and reading from
1653 * the two types of structures. See tavor_get_addr_path() and
1654 * tavor_set_addr_path() in tavor_misc.c for more details.
1656 #ifdef _LITTLE_ENDIAN
1657 struct tavor_hw_addr_path_s
{
1659 uint32_t ml_path
:7;
1662 uint32_t rnr_retry
:3;
1663 uint32_t pkey_indx
:7;
1665 uint32_t portnum
:2;
1667 uint32_t flow_label
:20;
1670 uint32_t hop_limit
:8;
1671 uint32_t max_stat_rate
:3;
1673 uint32_t mgid_index
:6;
1675 uint32_t ack_timeout
:5;
1680 struct tavor_hw_addr_path_s
{
1682 uint32_t portnum
:2;
1684 uint32_t pkey_indx
:7;
1685 uint32_t rnr_retry
:3;
1688 uint32_t ml_path
:7;
1690 uint32_t ack_timeout
:5;
1692 uint32_t mgid_index
:6;
1694 uint32_t max_stat_rate
:3;
1695 uint32_t hop_limit
:8;
1698 uint32_t flow_label
:20;
1704 #ifdef _LITTLE_ENDIAN
1705 struct tavor_hw_qpc_s
{
1706 uint32_t sched_q
:4;
1711 uint32_t pm_state
:2;
1713 uint32_t serv_type
:3;
1716 uint32_t usr_page
:24;
1719 uint32_t msg_max
:5;
1721 uint32_t rem_qpn
:24;
1723 uint32_t loc_qpn
:24;
1727 tavor_hw_addr_path_t pri_addr_path
;
1728 tavor_hw_addr_path_t alt_addr_path
;
1734 uint32_t wqe_baseaddr
;
1739 uint32_t cur_retry_cnt
:3;
1740 uint32_t cur_rnr_retry
:3;
1745 uint32_t retry_cnt
:3;
1747 uint32_t sra_max
:3;
1748 uint32_t flight_lim
:4;
1749 uint32_t ack_req_freq
:4;
1750 uint32_t cqn_snd
:24;
1752 uint32_t next_snd_psn
:24;
1754 uint64_t next_snd_wqe
;
1757 uint32_t last_acked_psn
:24;
1759 uint32_t next_rcv_psn
:24;
1760 uint32_t min_rnr_nak
:5;
1770 uint32_t rra_max
:3;
1772 uint32_t cqn_rcv
:24;
1775 uint32_t ra_buff_indx
:27;
1776 uint64_t next_rcv_wqe
;
1777 uint32_t srq_number
:24;
1787 struct tavor_hw_qpc_s
{
1790 uint32_t serv_type
:3;
1792 uint32_t pm_state
:2;
1797 uint32_t sched_q
:4;
1799 uint32_t msg_max
:5;
1802 uint32_t usr_page
:24;
1804 uint32_t loc_qpn
:24;
1806 uint32_t rem_qpn
:24;
1809 tavor_hw_addr_path_t pri_addr_path
;
1810 tavor_hw_addr_path_t alt_addr_path
;
1815 uint32_t wqe_baseaddr
;
1817 uint32_t ack_req_freq
:4;
1818 uint32_t flight_lim
:4;
1819 uint32_t sra_max
:3;
1821 uint32_t retry_cnt
:3;
1826 uint32_t cur_rnr_retry
:3;
1827 uint32_t cur_retry_cnt
:3;
1833 uint32_t next_snd_psn
:24;
1835 uint32_t cqn_snd
:24;
1836 uint64_t next_snd_wqe
;
1838 uint32_t last_acked_psn
:24;
1842 uint32_t rra_max
:3;
1852 uint32_t min_rnr_nak
:5;
1853 uint32_t next_rcv_psn
:24;
1854 uint32_t ra_buff_indx
:27;
1857 uint32_t cqn_rcv
:24;
1858 uint64_t next_rcv_wqe
;
1862 uint32_t srq_number
:24;
1869 #define TAVOR_QP_RESET 0x0
1870 #define TAVOR_QP_INIT 0x1
1871 #define TAVOR_QP_RTR 0x2
1872 #define TAVOR_QP_RTS 0x3
1873 #define TAVOR_QP_SQERR 0x4
1874 #define TAVOR_QP_SQD 0x5
1875 #define TAVOR_QP_ERR 0x6
1876 #define TAVOR_QP_SQDRAINING 0x7
1878 #define TAVOR_QP_RC 0x0
1879 #define TAVOR_QP_UC 0x1
1880 #define TAVOR_QP_UD 0x3
1881 #define TAVOR_QP_MLX 0x7
1883 #define TAVOR_QP_PMSTATE_MIGRATED 0x3
1884 #define TAVOR_QP_PMSTATE_ARMED 0x0
1885 #define TAVOR_QP_PMSTATE_REARM 0x1
1887 #define TAVOR_QP_DESC_EVT_DISABLED 0x0
1888 #define TAVOR_QP_DESC_EVT_ENABLED 0x1
1890 #define TAVOR_QP_FLIGHT_LIM_UNLIMITED 0xF
1892 #define TAVOR_QP_SQ_ALL_SIGNALED 0x1
1893 #define TAVOR_QP_SQ_WR_SIGNALED 0x0
1894 #define TAVOR_QP_RQ_ALL_SIGNALED 0x1
1895 #define TAVOR_QP_RQ_WR_SIGNALED 0x0
1897 #define TAVOR_QP_SRQ_ENABLED 0x1
1898 #define TAVOR_QP_SRQ_DISABLED 0x0
1902 * Tavor Multicast Group Member (MCG)
1903 * Tavor MCG are organized in a physically-contiguous memory table (the
1904 * Multicast Group Table) in the HCA attached local memory. This table is
1905 * actually comprised of two consecutive tables: the Multicast Group Hash
1906 * Table (MGHT) and the Additional Multicast Group Members Table (AMGM).
1907 * Each such entry contains an MGID and a list of QPs that are attached to
1908 * the multicast group. Each such entry may also include an index to an
1909 * Additional Multicast Group Member Table (AMGM) entry. The AMGMs are
1910 * used to form a linked list of MCG entries that all map to the same hash
1911 * value. The MCG entry size is configured through the INIT_HCA command.
1912 * Note: An MCG actually consists of a single tavor_hw_mcg_t and some
1913 * number of tavor_hw_mcg_qp_list_t (such that the combined structure is a
1916 * The following structures are used in the READ_MGM and WRITE_MGM commands.
1917 * The READ_MGM command reads an MCG entry from the multicast table and
1918 * returns it in the output mailbox. Note: This operation does not affect
1919 * the MCG entry state or values.
1920 * The WRITE_MGM command retrieves an MCG entry from the input mailbox and
1921 * stores it in the multicast group table at the index specified in the
1922 * command. Once the command has finished execution, the multicast group
1923 * table is updated. The old entry contents are lost.
1925 #ifdef _LITTLE_ENDIAN
1926 struct tavor_hw_mcg_s
{
1929 uint32_t next_gid_indx
:26;
1936 struct tavor_hw_mcg_s
{
1937 uint32_t next_gid_indx
:26;
1947 /* Multicast Group Member - QP List entries */
1948 #ifdef _LITTLE_ENDIAN
1949 struct tavor_hw_mcg_qp_list_s
{
1955 struct tavor_hw_mcg_qp_list_s
{
1961 #define TAVOR_MCG_QPN_INVALID 0x0
1962 #define TAVOR_MCG_QPN_VALID 0x1
1965 * Structure for getting the peformance counters from the HCA
1968 #ifdef _LITTLE_ENDIAN
1969 struct tavor_hw_sm_perfcntr_s
{
1970 uint32_t linkdown
:8;
1971 uint32_t linkerrrec
:8;
1972 uint32_t symerr
:16;
1974 uint32_t cntrsel
:16;
1975 uint32_t portsel
:8;
1978 uint32_t portxmdiscard
:16;
1979 uint32_t portrcvswrelay
:16;
1981 uint32_t portrcvrem
:16;
1982 uint32_t portrcv
:16;
1984 uint32_t vl15drop
:16;
1987 uint32_t xsbuffovrun
:4;
1988 uint32_t locallinkint
:4;
1990 uint32_t portrcconstr
:8;
1991 uint32_t portxmconstr
:8;
1993 uint32_t portrcdata
;
1995 uint32_t portxmdata
;
1997 uint32_t portrcpkts
;
1999 uint32_t portxmpkts
;
2003 uint32_t portxmwait
;
2005 #else /* BIG ENDIAN */
2006 struct tavor_hw_sm_perfcntr_s
{
2008 uint32_t portsel
:8;
2009 uint32_t cntrsel
:16;
2011 uint32_t symerr
:16;
2012 uint32_t linkerrrec
:8;
2013 uint32_t linkdown
:8;
2015 uint32_t portrcv
:16;
2016 uint32_t portrcvrem
:16;
2018 uint32_t portrcvswrelay
:16;
2019 uint32_t portxmdiscard
:16;
2021 uint32_t portxmconstr
:8;
2022 uint32_t portrcconstr
:8;
2024 uint32_t locallinkint
:4;
2025 uint32_t xsbuffovrun
:4;
2028 uint32_t vl15drop
:16;
2030 uint32_t portxmdata
;
2032 uint32_t portrcdata
;
2034 uint32_t portxmpkts
;
2036 uint32_t portrcpkts
;
2038 uint32_t portxmwait
;
2046 * Tavor User Access Region (UAR)
2047 * Tavor doorbells are each rung by writing to the doorbell registers that
2048 * form a User Access Region (UAR). A doorbell is a write-only hardware
2049 * register which enables passing information from software to hardware
2050 * with minimum software latency. A write operation from the host software
2051 * to these doorbell registers passes information about the HCA resources
2052 * and initiates processing of the doorbell data. There are 6 types of
2053 * doorbells in Tavor.
2055 * "Send Doorbell" for synchronizing the attachment of a WQE (or a chain
2056 * of WQEs) to the send queue.
2057 * "RD Send Doorbell" (Same as above, except for RD QPs) is not supported.
2058 * "Receive Doorbell" for synchronizing the attachment of a WQE (or a chain
2059 * of WQEs) to the receive queue.
2060 * "CQ Doorbell" for updating the CQ consumer index and requesting
2061 * completion notifications.
2062 * "EQ Doorbell" for updating the EQ consumer index, arming interrupt
2063 * triggering, and disarming CQ notification requests.
2064 * "InfiniBlast" (which would have enabled access to the "InfiniBlast
2065 * buffer") is not supported.
2067 * Note: The tavor_hw_uar_t below is the container for all of the various
2068 * doorbell types. Below we first define several structures which make up
2069 * the contents of those doorbell types.
2071 * Note also: The following structures are not #define'd with both little-
2072 * endian and big-endian definitions. This is because each doorbell type
2073 * is not directly accessed except through a single ddi_put64() operation
2074 * (see tavor_qp_send_doorbell, tavor_qp_recv_doorbell, tavor_cq_doorbell,
2075 * or tavor_eq_doorbell)
2077 typedef struct tavor_hw_uar_send_s
{
2080 uint32_t nopcode
:5;
2084 } tavor_hw_uar_send_t
;
2085 #define TAVOR_QPSNDDB_NDA_MASK 0xFFFFFFC0
2086 #define TAVOR_QPSNDDB_NDA_SHIFT 0x20
2087 #define TAVOR_QPSNDDB_F_SHIFT 0x25
2088 #define TAVOR_QPSNDDB_NOPCODE_SHIFT 0x20
2089 #define TAVOR_QPSNDDB_QPN_SHIFT 0x8
2091 typedef struct tavor_hw_uar_recv_s
{
2095 uint32_t credits
:8;
2096 } tavor_hw_uar_recv_t
;
2097 #define TAVOR_QPRCVDB_NDA_MASK 0xFFFFFFC0
2098 #define TAVOR_QPRCVDB_NDA_SHIFT 0x20
2099 #define TAVOR_QPRCVDB_NDS_SHIFT 0x20
2100 #define TAVOR_QPRCVDB_QPN_SHIFT 0x8
2101 /* Max descriptors per Tavor doorbell */
2102 #define TAVOR_QP_MAXDESC_PER_DB 256
2104 typedef struct tavor_hw_uar_cq_s
{
2108 } tavor_hw_uar_cq_t
;
2109 #define TAVOR_CQDB_CMD_SHIFT 0x38
2110 #define TAVOR_CQDB_CQN_SHIFT 0x20
2112 #define TAVOR_CQDB_INCR_CONSINDX 0x01
2113 #define TAVOR_CQDB_NOTIFY_CQ 0x02
2114 #define TAVOR_CQDB_NOTIFY_CQ_SOLICIT 0x03
2115 #define TAVOR_CQDB_SET_CONSINDX 0x04
2116 /* Default value for use in NOTIFY_CQ doorbell */
2117 #define TAVOR_CQDB_DEFAULT_PARAM 0xFFFFFFFF
2119 typedef struct tavor_hw_uar_eq_s
{
2124 } tavor_hw_uar_eq_t
;
2125 #define TAVOR_EQDB_CMD_SHIFT 0x38
2126 #define TAVOR_EQDB_EQN_SHIFT 0x20
2128 #define TAVOR_EQDB_INCR_CONSINDX 0x01
2129 #define TAVOR_EQDB_REARM_EQ 0x02
2130 #define TAVOR_EQDB_DISARM_CQ 0x03
2131 #define TAVOR_EQDB_SET_CONSINDX 0x04
2132 #define TAVOR_EQDB_SET_ALWAYSARMED 0x05
2134 struct tavor_hw_uar_s
{
2135 uint32_t rsrv0
[4]; /* "RD Send" unsupported */
2136 tavor_hw_uar_send_t send
;
2137 tavor_hw_uar_recv_t recv
;
2138 tavor_hw_uar_cq_t cq
;
2139 tavor_hw_uar_eq_t eq
;
2140 uint32_t rsrv1
[244];
2141 uint32_t iblast
[256]; /* "InfiniBlast" unsupported */
2146 * Tavor Send Work Queue Element (WQE)
2147 * A Tavor Send WQE is built of the following segments, each of which is a
2148 * multiple of 16 bytes. Note: Each individual WQE may contain only a
2149 * subset of these segments described below (according to the operation type
2150 * and transport type of the QP).
2152 * The first 16 bytes of ever WQE are formed from the "Next/Ctrl" segment.
2153 * This segment contains the address of the next WQE to be executed and the
2154 * information required in order to allocate the resources to execute the
2155 * next WQE. The "Ctrl" part of this segment contains the control
2156 * information required to execute the WQE, including the opcode and other
2157 * control information.
2158 * The "Datagram" segment contains address information required in order to
2159 * form a UD message.
2160 * The "Bind" segment contains the parameters required for a Bind Memory
2162 * The "Remote Address" segment is present only in RDMA or Atomic WQEs and
2163 * specifies remote virtual addresses and RKey, respectively. Length of
2164 * the remote access is calculated from the scatter/gather list (for
2165 * RDMA-write/RDMA-read) or set to eight (for Atomic).
2166 * The "Atomic" segment is present only in Atomic WQEs and specifies
2167 * Swap/Add and Compare data.
2169 * Note: The following structures are not #define'd with both little-endian
2170 * and big-endian definitions. This is because their individual fields are
2171 * not directly accessed except through macros defined below.
2173 struct tavor_hw_snd_wqe_nextctrl_s
{
2174 uint32_t next_wqe_addr
:26;
2176 uint32_t nopcode
:5;
2177 uint32_t next_eec
:24;
2187 uint32_t immediate
:32;
2189 #define TAVOR_WQE_NDA_MASK 0x00000000FFFFFFC0ull
2190 #define TAVOR_WQE_NDS_MASK 0x3F
2191 #define TAVOR_WQE_DBD_MASK 0x80
2193 #define TAVOR_WQE_SEND_FENCE_MASK 0x40
2194 #define TAVOR_WQE_SEND_NOPCODE_RDMAW 0x8
2195 #define TAVOR_WQE_SEND_NOPCODE_RDMAWI 0x9
2196 #define TAVOR_WQE_SEND_NOPCODE_SEND 0xA
2197 #define TAVOR_WQE_SEND_NOPCODE_SENDI 0xB
2198 #define TAVOR_WQE_SEND_NOPCODE_RDMAR 0x10
2199 #define TAVOR_WQE_SEND_NOPCODE_ATMCS 0x11
2200 #define TAVOR_WQE_SEND_NOPCODE_ATMFA 0x12
2201 #define TAVOR_WQE_SEND_NOPCODE_BIND 0x18
2203 #define TAVOR_WQE_SEND_SIGNALED_MASK 0x0000000800000000ull
2204 #define TAVOR_WQE_SEND_SOLICIT_MASK 0x0000000200000000ull
2205 #define TAVOR_WQE_SEND_IMMEDIATE_MASK 0x0000000100000000ull
2207 struct tavor_hw_snd_wqe_ud_s
{
2210 uint32_t av_addr_h
:32;
2211 uint32_t av_addr_l
:27;
2215 uint32_t dest_qp
:24;
2220 #define TAVOR_WQE_SENDHDR_UD_AV_MASK 0xFFFFFFFFFFFFFFE0ull
2221 #define TAVOR_WQE_SENDHDR_UD_DQPN_MASK 0xFFFFFF
2223 struct tavor_hw_snd_wqe_bind_s
{
2234 #define TAVOR_WQE_SENDHDR_BIND_ATOM 0x8000000000000000ull
2235 #define TAVOR_WQE_SENDHDR_BIND_WR 0x4000000000000000ull
2236 #define TAVOR_WQE_SENDHDR_BIND_RD 0x2000000000000000ull
2238 struct tavor_hw_snd_wqe_remaddr_s
{
2244 struct tavor_hw_snd_wqe_atomic_s
{
2251 * Tavor "MLX transport" Work Queue Element (WQE)
2252 * The format of the MLX WQE is similar to that of the Send WQE (above)
2253 * with the following exceptions. MLX WQEs are used for sending MADs on
2254 * special QPs 0 and 1. Everything following the "Next/Ctrl" header
2255 * (defined below) consists of scatter-gather list entries. The contents
2256 * of these SGLs (also defined below) will be put on the wire exactly as
2257 * they appear in the buffers. In addition, the VCRC and the ICRC of each
2258 * sent packet can be modified by changing values in the following header
2259 * or in the payload of the packet itself.
2261 struct tavor_hw_mlx_wqe_nextctrl_s
{
2262 uint32_t next_wqe_addr
:26;
2264 uint32_t nopcode
:5;
2274 uint32_t max_srate
:3;
2283 #define TAVOR_WQE_MLXHDR_VL15_MASK 0x0002000000000000ull
2284 #define TAVOR_WQE_MLXHDR_SLR_MASK 0x0001000000000000ull
2285 #define TAVOR_WQE_MLXHDR_SRATE_SHIFT 44
2286 #define TAVOR_WQE_MLXHDR_SL_SHIFT 40
2287 #define TAVOR_WQE_MLXHDR_SIGNALED_MASK 0x0000000800000000ull
2288 #define TAVOR_WQE_MLXHDR_RLID_SHIFT 16
2291 * Tavor Receive Work Queue Element (WQE)
2292 * Like the Send WQE, the Receive WQE is built of 16-byte segments. The
2293 * segment is the "Next/Ctrl" segment (defined below). It is followed by
2294 * some number of scatter list entries for the incoming message.
2296 * The format of the scatter-gather list entries is also shown below. For
2297 * Receive WQEs the "inline_data" field must be cleared (i.e. data segments
2298 * cannot contain inline data).
2300 struct tavor_hw_rcv_wqe_nextctrl_s
{
2301 uint32_t next_wqe_addr
:26;
2317 * This bit must be set in the next/ctrl field of all Receive WQEs
2318 * as a workaround to a Tavor hardware erratum related to having
2319 * the first 32-bits in the WQE set to zero.
2321 #define TAVOR_RCV_WQE_NDA0_WA_MASK 0x0000000100000000ull
2323 struct tavor_hw_wqe_sgl_s
{
2324 uint32_t inline_data
:1;
2325 uint32_t byte_cnt
:31;
2329 #define TAVOR_WQE_SGL_BYTE_CNT_MASK 0x7FFFFFFF
2330 #define TAVOR_WQE_SGL_INLINE_MASK 0x80000000
2333 * The following defines are used when building descriptors for special QP
2334 * work requests (i.e. MLX transport WQEs). Note: Because Tavor MLX transport
2335 * requires the driver to build actual IB packet headers, we use these defines
2336 * for the most common fields in those headers.
2338 #define TAVOR_MLX_VL15_LVER 0xF0000000
2339 #define TAVOR_MLX_VL0_LVER 0x00000000
2340 #define TAVOR_MLX_IPVER_TC_FLOW 0x60000000
2341 #define TAVOR_MLX_TC_SHIFT 20
2342 #define TAVOR_MLX_DEF_PKEY 0xFFFF
2343 #define TAVOR_MLX_GSI_QKEY 0x80010000
2344 #define TAVOR_MLX_UDSEND_OPCODE 0x64000000
2345 #define TAVOR_MLX_DQPN_MASK 0xFFFFFF
2348 * The following macros are used for building each of the individual
2349 * segments that can make up a Tavor WQE. Note: We try not to use the
2350 * structures (with their associated bitfields) here, instead opting to
2351 * build and put 64-bit or 32-bit chunks to the WQEs as appropriate,
2352 * primarily because using the bitfields appears to force more read-modify-
2355 * TAVOR_WQE_BUILD_UD - Builds Unreliable Datagram Segment
2357 * TAVOR_WQE_BUILD_REMADDR - Builds Remote Address Segment using
2358 * RDMA info from the work request
2359 * TAVOR_WQE_BUILD_RC_ATOMIC_REMADDR - Builds Remote Address Segment
2360 * for RC Atomic work requests
2361 * TAVOR_WQE_BUILD_ATOMIC - Builds Atomic Segment using atomic
2362 * info from the work request
2363 * TAVOR_WQE_BUILD_BIND - Builds the Bind Memory Window
2364 * Segment using bind info from the
2366 * TAVOR_WQE_BUILD_DATA_SEG - Builds the individual Data Segments
2367 * for Send, Receive, and MLX WQEs
2368 * TAVOR_WQE_BUILD_INLINE - Builds an "inline" Data Segment
2369 * (primarily for MLX transport)
2370 * TAVOR_WQE_BUILD_INLINE_ICRC - Also builds an "inline" Data Segment
2371 * (but used primarily in the ICRC
2372 * portion of MLX transport WQEs)
2373 * TAVOR_WQE_LINKNEXT - Links the current WQE to the
2375 * TAVOR_WQE_LINKFIRST - Links the first WQE on the current
2376 * chain to the previous WQE
2377 * TAVOR_WQE_BUILD_MLX_LRH - Builds the inline LRH header for
2378 * MLX transport MADs
2379 * TAVOR_WQE_BUILD_MLX_GRH - Builds the inline GRH header for
2380 * MLX transport MADs
2381 * TAVOR_WQE_BUILD_MLX_BTH - Builds the inline BTH header for
2382 * MLX transport MADs
2383 * TAVOR_WQE_BUILD_MLX_DETH - Builds the inline DETH header for
2384 * MLX transport MADs
2386 #define TAVOR_WQE_BUILD_UD(qp, ud, ah, wr) \
2390 tmp = (uint64_t *)(ud); \
2391 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[0], \
2392 (uint64_t)(ah)->ah_mrhdl->mr_lkey); \
2393 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[1], \
2394 (ah)->ah_mrhdl->mr_bindinfo.bi_addr & \
2395 TAVOR_WQE_SENDHDR_UD_AV_MASK); \
2396 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[2], 0x0); \
2397 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[3], 0x0); \
2398 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[4], \
2399 (((uint64_t)((wr)->wr.ud.udwr_dest->ud_dst_qpn & \
2400 TAVOR_WQE_SENDHDR_UD_DQPN_MASK) << 32) | \
2401 (wr)->wr.ud.udwr_dest->ud_qkey)); \
2404 #define TAVOR_WQE_BUILD_REMADDR(qp, ra, wr_rdma) \
2408 tmp = (uint64_t *)(ra); \
2409 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[0], \
2410 (wr_rdma)->rdma_raddr); \
2411 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[1], \
2412 (uint64_t)(wr_rdma)->rdma_rkey << 32); \
2415 #define TAVOR_WQE_BUILD_RC_ATOMIC_REMADDR(qp, rc, wr) \
2419 tmp = (uint64_t *)(rc); \
2420 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[0], \
2421 (wr)->wr.rc.rcwr.atomic->atom_raddr); \
2422 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[1], \
2423 (uint64_t)(wr)->wr.rc.rcwr.atomic->atom_rkey << 32); \
2426 #define TAVOR_WQE_BUILD_ATOMIC(qp, at, wr_atom) \
2430 tmp = (uint64_t *)(at); \
2431 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[0], \
2432 (wr_atom)->atom_arg2); \
2433 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[1], \
2434 (wr_atom)->atom_arg1); \
2437 #define TAVOR_WQE_BUILD_BIND(qp, bn, wr_bind) \
2441 ibt_bind_flags_t bind_flags; \
2443 tmp = (uint64_t *)(bn); \
2444 bind_flags = (wr_bind)->bind_flags; \
2445 bn0_tmp = (bind_flags & IBT_WR_BIND_ATOMIC) ? \
2446 TAVOR_WQE_SENDHDR_BIND_ATOM : 0; \
2447 bn0_tmp |= (bind_flags & IBT_WR_BIND_WRITE) ? \
2448 TAVOR_WQE_SENDHDR_BIND_WR : 0; \
2449 bn0_tmp |= (bind_flags & IBT_WR_BIND_READ) ? \
2450 TAVOR_WQE_SENDHDR_BIND_RD : 0; \
2451 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[0], bn0_tmp); \
2452 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[1], \
2453 (((uint64_t)(wr_bind)->bind_rkey_out << 32) | \
2454 (wr_bind)->bind_lkey)); \
2455 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[2], \
2456 (wr_bind)->bind_va); \
2457 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[3], \
2458 (wr_bind)->bind_len); \
2461 #define TAVOR_WQE_BUILD_DATA_SEG(qp, ds, sgl) \
2465 tmp = (uint64_t *)(ds); \
2466 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[0], \
2467 (((uint64_t)((sgl)->ds_len & \
2468 TAVOR_WQE_SGL_BYTE_CNT_MASK) << 32) | (sgl)->ds_key)); \
2469 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &tmp[1], (sgl)->ds_va); \
2472 #define TAVOR_WQE_BUILD_DATA_SEG_SRQ(srq, ds, sgl) \
2476 tmp = (uint64_t *)(ds); \
2477 ddi_put64((srq)->srq_wqinfo.qa_acchdl, &tmp[0], \
2478 (((uint64_t)((sgl)->ds_len & \
2479 TAVOR_WQE_SGL_BYTE_CNT_MASK) << 32) | (sgl)->ds_key)); \
2480 ddi_put64((srq)->srq_wqinfo.qa_acchdl, &tmp[1], (sgl)->ds_va); \
2483 #define TAVOR_WQE_BUILD_INLINE(qp, ds, sz) \
2486 uint32_t inline_tmp; \
2488 tmp = (uint32_t *)(ds); \
2489 inline_tmp = TAVOR_WQE_SGL_INLINE_MASK | sz; \
2490 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], inline_tmp); \
2493 #define TAVOR_WQE_BUILD_INLINE_ICRC(qp, ds, sz, icrc) \
2496 uint32_t inline_tmp; \
2498 tmp = (uint32_t *)(ds); \
2499 inline_tmp = TAVOR_WQE_SGL_INLINE_MASK | sz; \
2500 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], inline_tmp); \
2501 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[1], icrc); \
2504 #define TAVOR_WQE_LINKNEXT(qp, prev, ctrl, next) \
2506 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &((uint64_t *)(prev))[1], \
2508 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &((uint64_t *)(prev))[0], \
2512 #define TAVOR_WQE_LINKNEXT_SRQ(srq, prev, ctrl, next) \
2514 ddi_put64((srq)->srq_wqinfo.qa_acchdl, &((uint64_t *)(prev))[1],\
2516 ddi_put64((srq)->srq_wqinfo.qa_acchdl, &((uint64_t *)(prev))[0],\
2520 #define TAVOR_WQE_LINKFIRST(qp, prev, next) \
2522 ddi_put64((qp)->qp_wqinfo.qa_acchdl, &((uint64_t *)(prev))[0], \
2526 #define TAVOR_WQE_BUILD_MLX_LRH(lrh, qp, udav, pktlen) \
2531 tmp = (uint32_t *)(lrh); \
2533 if ((qp)->qp_is_special == TAVOR_QP_SMI) { \
2534 lrh_tmp = TAVOR_MLX_VL15_LVER; \
2536 lrh_tmp = TAVOR_MLX_VL0_LVER | ((udav).sl << 20); \
2539 lrh_tmp |= (IB_LRH_NEXT_HDR_GRH << 16); \
2541 lrh_tmp |= (IB_LRH_NEXT_HDR_BTH << 16); \
2543 lrh_tmp |= (udav).rlid; \
2544 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], lrh_tmp); \
2546 lrh_tmp = (pktlen) << 16; \
2547 if ((udav).rlid == IB_LID_PERMISSIVE) { \
2548 lrh_tmp |= IB_LID_PERMISSIVE; \
2550 lrh_tmp |= (udav).ml_path; \
2552 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[1], lrh_tmp); \
2556 * Note: The GRH payload length, calculated below, is the overall packet
2557 * length (in bytes) minus LRH header and GRH headers.
2559 * Also note: Filling in the GIDs in the way we do below is helpful because
2560 * it avoids potential alignment restrictions and/or conflicts.
2562 #define TAVOR_WQE_BUILD_MLX_GRH(state, grh, qp, udav, pktlen) \
2568 tmp = (uint32_t *)(grh); \
2570 grh_tmp = TAVOR_MLX_IPVER_TC_FLOW; \
2571 grh_tmp |= (udav).tclass << TAVOR_MLX_TC_SHIFT; \
2572 grh_tmp |= (udav).flow_label; \
2573 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], grh_tmp); \
2575 grh_tmp = (((pktlen) << 2) - (sizeof (ib_lrh_hdr_t) + \
2576 sizeof (ib_grh_t))) << 16; \
2577 grh_tmp |= (IB_GRH_NEXT_HDR_BTH << 8); \
2578 grh_tmp |= (udav).hop_limit; \
2579 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[1], grh_tmp); \
2581 TAVOR_SGID_FROM_INDX_GET((state), (qp)->qp_portnum, \
2582 (udav).mgid_index, &sgid); \
2583 bcopy(&sgid, &tmp[2], sizeof (ib_gid_t)); \
2584 bcopy(&(udav).rgid_h, &tmp[6], sizeof (ib_gid_t)); \
2587 #define TAVOR_WQE_BUILD_MLX_BTH(state, bth, qp, wr) \
2592 tmp = (uint32_t *)(bth); \
2594 bth_tmp = TAVOR_MLX_UDSEND_OPCODE; \
2595 if ((wr)->wr_flags & IBT_WR_SEND_SOLICIT) { \
2596 bth_tmp |= (IB_BTH_SOLICITED_EVENT_MASK << 16); \
2598 if (qp->qp_is_special == TAVOR_QP_SMI) { \
2599 bth_tmp |= TAVOR_MLX_DEF_PKEY; \
2601 bth_tmp |= TAVOR_PKEY_FROM_INDX_GET((state), \
2602 (qp)->qp_portnum, (qp)->qp_pkeyindx); \
2604 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], bth_tmp); \
2605 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[1], \
2606 (wr)->wr.ud.udwr_dest->ud_dst_qpn & \
2607 TAVOR_MLX_DQPN_MASK); \
2608 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[2], 0x0); \
2611 #define TAVOR_WQE_BUILD_MLX_DETH(deth, qp) \
2615 tmp = (uint32_t *)(deth); \
2617 if ((qp)->qp_is_special == TAVOR_QP_SMI) { \
2618 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], 0x0); \
2619 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[1], 0x0); \
2621 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[0], \
2622 TAVOR_MLX_GSI_QKEY); \
2623 ddi_put32((qp)->qp_wqinfo.qa_acchdl, &tmp[1], 0x1); \
2630 * The following registers (and the macros to access them) are not defined
2631 * in the Tavor PRM. But we have high confidence that these offsets are
2632 * unlikely to change in the lifetime of the Tavor hardware.
2634 #define TAVOR_HW_PORTINFO_LMC_OFFSET 0x10020
2635 #define TAVOR_HW_PORTINFO_BASELID_OFFSET 0x10010
2636 #define TAVOR_HW_PORTINFO_MASTERSMLID_OFFSET 0x10010
2637 #define TAVOR_HW_PORTINFO_LINKWIDTH_OFFSET 0x1001C
2638 #define TAVOR_HW_PORT_SIZE 0x800
2640 #define TAVOR_HW_PMEG_PORTXMITDATA_OFFSET 0x10120
2641 #define TAVOR_HW_PMEG_PORTRECVDATA_OFFSET 0x10124
2642 #define TAVOR_HW_PMEG_PORTXMITPKTS_OFFSET 0x10128
2643 #define TAVOR_HW_PMEG_PORTRECVPKTS_OFFSET 0x1012C
2644 #define TAVOR_HW_PMEG_PORTRECVERR_OFFSET 0x10130
2645 #define TAVOR_HW_PMEG_PORTXMITDISCARD_OFFSET 0x10134
2646 #define TAVOR_HW_PMEG_VL15DROPPED_OFFSET 0x10138
2647 #define TAVOR_HW_PMEG_PORTXMITWAIT_OFFSET 0x1013C
2648 #define TAVOR_HW_PMEG_PORTRECVREMPHYSERR_OFFSET 0x10144
2649 #define TAVOR_HW_PMEG_PORTXMITCONSTERR_OFFSET 0x10148
2650 #define TAVOR_HW_PMEG_PORTRECVCONSTERR_OFFSET 0x1014C
2651 #define TAVOR_HW_PMEG_SYMBOLERRCNT_OFFSET 0x10150
2652 #define TAVOR_HW_PMEG_LINKERRRECOVERCNT_OFFSET 0x10154
2653 #define TAVOR_HW_PMEG_LINKDOWNEDCNT_OFFSET 0x10154
2654 #define TAVOR_HW_PMEG_EXCESSBUFOVERRUN_OFFSET 0x10164
2655 #define TAVOR_HW_PMEG_LOCALLINKINTERR_OFFSET 0x10164
2657 #define TAVOR_HW_GUIDTABLE_OFFSET 0x4C800
2658 #define TAVOR_HW_GUIDTABLE_PORT_SIZE 0x200
2659 #define TAVOR_HW_GUIDTABLE_GID_SIZE 0x10
2660 #define TAVOR_HW_GUIDTABLE_GIDPREFIX_SIZE 0x8
2662 #define TAVOR_HW_PKEYTABLE_OFFSET 0x4D800
2663 #define TAVOR_HW_PKEYTABLE_PORT_SIZE 0x100
2664 #define TAVOR_HW_PKEYTABLE_PKEY_SIZE 0x4
2666 #define TAVOR_PORT_LMC_GET(state, port) \
2667 ((ddi_get32((state)->ts_reg_cmdhdl, \
2668 (uint32_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2669 TAVOR_HW_PORTINFO_LMC_OFFSET + \
2670 (TAVOR_HW_PORT_SIZE * (port)))) >> 8) & 0x7);
2672 #define TAVOR_PORT_BASELID_GET(state, port) \
2673 (ddi_get32((state)->ts_reg_cmdhdl, \
2674 (uint32_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2675 TAVOR_HW_PORTINFO_BASELID_OFFSET + \
2676 (TAVOR_HW_PORT_SIZE * (port)))) >> 16);
2678 #define TAVOR_PORT_MASTERSMLID_GET(state, port) \
2679 (ddi_get32((state)->ts_reg_cmdhdl, \
2680 (uint32_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2681 TAVOR_HW_PORTINFO_MASTERSMLID_OFFSET + \
2682 (TAVOR_HW_PORT_SIZE * (port)))) & 0xFFFF);
2684 #define TAVOR_PORT_LINKWIDTH_ACTIVE_GET(state, port) \
2685 (ddi_get32((state)->ts_reg_cmdhdl, \
2686 (uint32_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2687 TAVOR_HW_PORTINFO_LINKWIDTH_OFFSET + \
2688 (TAVOR_HW_PORT_SIZE * (port)))) & 0xF);
2690 #define TAVOR_SGID_FROM_INDX_GET(state, port, sgid_ix, sgid) \
2691 (sgid)->gid_prefix = ddi_get64((state)->ts_reg_cmdhdl, \
2692 (uint64_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2693 TAVOR_HW_GUIDTABLE_OFFSET + \
2694 ((port) * TAVOR_HW_GUIDTABLE_PORT_SIZE) + \
2695 ((sgid_ix) * TAVOR_HW_GUIDTABLE_GID_SIZE))); \
2696 (sgid)->gid_guid = ddi_get64((state)->ts_reg_cmdhdl, \
2697 (uint64_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2698 TAVOR_HW_GUIDTABLE_OFFSET + \
2699 ((port) * TAVOR_HW_GUIDTABLE_PORT_SIZE) + \
2700 ((sgid_ix) * TAVOR_HW_GUIDTABLE_GID_SIZE) + \
2701 TAVOR_HW_GUIDTABLE_GIDPREFIX_SIZE));
2703 #define TAVOR_PKEY_FROM_INDX_GET(state, port, pkey_ix) \
2704 (ddi_get32((state)->ts_reg_cmdhdl, \
2705 (uint32_t *)((uintptr_t)(state)->ts_reg_cmd_baseaddr + \
2706 TAVOR_HW_PKEYTABLE_OFFSET + \
2707 ((port) * TAVOR_HW_PKEYTABLE_PORT_SIZE) + \
2708 ((pkey_ix) * TAVOR_HW_PKEYTABLE_PKEY_SIZE))) & 0xFFFF)
2713 * Below we have PCI config space space offsets for flash interface
2714 * access, offsets within Tavor CR space for accessing flash-specific
2715 * information or settings, masks used for flash settings, and
2716 * timeout values for flash operations.
2718 #define TAVOR_HW_FLASH_CFG_HWREV 8
2719 #define TAVOR_HW_FLASH_CFG_ADDR 88
2720 #define TAVOR_HW_FLASH_CFG_DATA 92
2722 #define TAVOR_HW_FLASH_RESET_AMD 0xF0
2723 #define TAVOR_HW_FLASH_RESET_INTEL 0xFF
2724 #define TAVOR_HW_FLASH_CPUMODE 0xF0150
2725 #define TAVOR_HW_FLASH_ADDR 0xF01A4
2726 #define TAVOR_HW_FLASH_DATA 0xF01A8
2727 #define TAVOR_HW_FLASH_GPIO_SEMA 0xF03FC
2728 #define TAVOR_HW_FLASH_GPIO_DIR 0xF008C
2729 #define TAVOR_HW_FLASH_GPIO_POL 0xF0094
2730 #define TAVOR_HW_FLASH_GPIO_MOD 0xF009C
2731 #define TAVOR_HW_FLASH_GPIO_DAT 0xF0084
2732 #define TAVOR_HW_FLASH_GPIO_DATACLEAR 0xF00D4
2733 #define TAVOR_HW_FLASH_GPIO_DATASET 0xF00DC
2735 #define TAVOR_HW_FLASH_CPU_MASK 0xC0000000
2736 #define TAVOR_HW_FLASH_CPU_SHIFT 30
2737 #define TAVOR_HW_FLASH_ADDR_MASK 0x0007FFFC
2738 #define TAVOR_HW_FLASH_CMD_MASK 0xE0000000
2739 #define TAVOR_HW_FLASH_BANK_MASK 0xFFF80000
2741 #define TAVOR_HW_FLASH_TIMEOUT_WRITE 300
2742 #define TAVOR_HW_FLASH_TIMEOUT_ERASE 1000000
2743 #define TAVOR_HW_FLASH_TIMEOUT_GPIO_SEMA 1000
2744 #define TAVOR_HW_FLASH_TIMEOUT_CONFIG 50
2746 /* Intel Command Set */
2747 #define TAVOR_HW_FLASH_ICS_ERASE 0x20
2748 #define TAVOR_HW_FLASH_ICS_ERROR 0x3E
2749 #define TAVOR_HW_FLASH_ICS_WRITE 0x40
2750 #define TAVOR_HW_FLASH_ICS_STATUS 0x70
2751 #define TAVOR_HW_FLASH_ICS_READY 0x80
2752 #define TAVOR_HW_FLASH_ICS_CONFIRM 0xD0
2753 #define TAVOR_HW_FLASH_ICS_READ 0xFF
2759 #endif /* _SYS_IB_ADAPTERS_TAVOR_HW_H */