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_HERMON_WR_H
28 #define _SYS_IB_ADAPTERS_HERMON_WR_H
32 * Contains all of the prototypes, #defines, and structures necessary
33 * for the Hermon Work Request Processing Routines
34 * Specifically it contains #defines, macros, and prototypes for each of
35 * building each of the various types of WQE and for managing the WRID
36 * tracking mechanisms.
39 #include <sys/types.h>
42 #include <sys/sunddi.h>
49 * WQEADDRSZ is a bit of a misnomer, it's really a token for the
50 * WRID processing. We simply use the wqe_counter.
52 #define HERMON_QP_WQEADDRSZ(wcnt, qpn) (wcnt) & 0xFFFF
54 /* And put the get from the CQ here as well */
55 #define HERMON_CQE_WQEADDRSZ_GET(cq, cqe) \
56 ((uint32_t)((((uint8_t *)(cqe))[0x18]) << 8) | ((uint8_t *)(cqe))[0x19])
60 * The following macro sets the owner bit in the Control Segment of the
61 * WQE, based on the wqe_counter value passed in
63 #define HERMON_SET_SEND_WQE_OWNER(qp, desc, opcode) \
64 *(uint32_t *)desc = htonl((((*(uint8_t *)desc & 0x80) ^ 0x80) << 24) | \
68 * The following macros are used to calculate pointers to the Send or Receive
69 * (or SRQ) WQEs on a given QP, respectively
71 #define HERMON_QP_SQ_ENTRY(qp, tail) \
72 ((uint64_t *)((uintptr_t)((qp)->qp_sq_buf) + \
73 ((tail) << (qp)->qp_sq_log_wqesz)))
74 #define HERMON_QP_RQ_ENTRY(qp, tail) \
75 ((uint64_t *)((uintptr_t)((qp)->qp_rq_buf) + \
76 ((tail) << (qp)->qp_rq_log_wqesz)))
77 #define HERMON_SRQ_WQ_ENTRY(srq, tail) \
78 ((uint64_t *)((uintptr_t)((srq)->srq_wq_buf) + \
79 ((tail) << (srq)->srq_wq_log_wqesz)))
82 * The following macro is used to calculate the 'wqe_index' field during SRQ
83 * operation. This returns the index based on the WQE size, that can be used
84 * to reference WQEs in an SRQ.
86 #define HERMON_SRQ_WQE_INDEX(srq_base_addr, wqe_addr, log_wqesz) \
87 (((uint32_t)(uintptr_t)wqe_addr - \
88 (uint32_t)(uintptr_t)srq_base_addr) >> log_wqesz)
90 * The following macro is used to calculate the 'wqe_addr' during SRQ
91 * operation. This returns the addr based on the WQE size and index,
92 * that can be used to reference WQEs in an SRQ.
95 #define HERMON_SRQ_WQE_ADDR(srq, wqe_index) \
96 ((uint64_t *)((uintptr_t)srq->srq_wq_buf + \
97 (wqe_index << srq->srq_wq_log_wqesz)))
100 * The following macros are used to access specific fields in Directed Route
101 * MAD packets. We can extract the MgmtClass, "hop pointer", and "hop count".
102 * We can also update the "hop pointer" as appropriate. Note: Again, because
103 * of the limited amount of direct handling the Hermon hardware does on special
104 * QP request (specifically on Directed Route MADs), the driver needs to
105 * update (as necessary) the "hop pointer" value depending on whether a MAD
106 * is outbound or inbound (i.e. depending on the relationship between "hop
107 * pointer" and "hop count" in the given MAD)
109 #define HERMON_SPECIAL_QP_DRMAD_GET_MGMTCLASS(mgmtclass, offset, va, len) \
110 if (((mgmtclass) == NULL) && ((offset) + (len) > 1)) { \
111 (mgmtclass) = &((uint8_t *)(uintptr_t)(va))[1 - (offset)]; \
113 #define HERMON_SPECIAL_QP_DRMAD_GET_HOPPOINTER(hp, offset, va, len) \
114 if (((hp) == NULL) && \
115 ((offset) + (len) > 6)) { \
116 (hp) = &((uint8_t *)(uintptr_t)(va))[6 - (offset)]; \
118 #define HERMON_SPECIAL_QP_DRMAD_GET_HOPCOUNT(hc, offset, va, len) \
119 if (((hc) == NULL) && \
120 ((offset) + (len) > 7)) { \
121 (hc) = &((uint8_t *)(uintptr_t)(va))[7 - (offset)]; \
123 #define HERMON_SPECIAL_QP_DRMAD_DO_HOPPOINTER_MODIFY(mgmtclass, hp, hc) \
124 if ((mgmtclass) == 0x81) { \
127 } else if ((hp) > (hc)) { \
133 * The hermon_workq_hdr_s structure is used internally by the Hermon driver
134 * to track the information necessary to manage the work queues (send, recv,
135 * or shared recv). The hermon_workq_avl_s is used for each association of
136 * a work queue with a given completion queue, where SRQs can be associated
137 * with multiple queue pairs and their associated completion queues.
139 struct hermon_workq_hdr_s
{
148 _NOTE(SCHEME_PROTECTS_DATA("safe sharing",
149 hermon_workq_hdr_s::wq_wrid
150 hermon_workq_hdr_s::wq_head
151 hermon_workq_hdr_s::wq_tail
152 hermon_workq_hdr_s::wq_full
))
154 struct hermon_workq_avl_s
{
157 uint32_t wqa_type
; /* send or recv */
158 struct hermon_workq_hdr_s
*wqa_wq
;
160 /* For SRQ, this is needed to add the wqe to the free list */
162 hermon_srqhdl_t wqa_srq
;
165 #define HERMON_WR_RECV 0x0
166 #define HERMON_WR_SEND 0x1
167 #define HERMON_WR_SRQ 0x2
169 extern int hermon_wrid_workq_compare(const void *p1
, const void *p2
);
170 typedef struct hermon_workq_compare_s
{
173 } hermon_workq_compare_t
;
175 /* For Work Request posting */
176 int hermon_post_send(hermon_state_t
*state
, hermon_qphdl_t qphdl
,
177 ibt_send_wr_t
*wr_p
, uint_t num_wr
, uint_t
*num_posted
);
178 int hermon_post_recv(hermon_state_t
*state
, hermon_qphdl_t qphdl
,
179 ibt_recv_wr_t
*wr_p
, uint_t num_wr
, uint_t
*num_posted
);
180 int hermon_post_srq(hermon_state_t
*state
, hermon_srqhdl_t srqhdl
,
181 ibt_recv_wr_t
*wr_p
, uint_t num_wr
, uint_t
*num_posted
);
183 /* For WRID handling */
184 int hermon_wrid_from_reset_handling(hermon_state_t
*state
, hermon_qphdl_t qp
);
185 int hermon_wrid_to_reset_handling(hermon_state_t
*state
, hermon_qphdl_t qp
);
186 ibt_wrid_t
hermon_wrid_get_entry(hermon_cqhdl_t cqhdl
, hermon_hw_cqe_t
*cqe
);
187 hermon_workq_hdr_t
*hermon_wrid_wqhdr_create(int bufsz
);
188 void hermon_wrid_wqhdr_destroy(hermon_workq_hdr_t
*wqhdr
);
191 void hermon_check_qp_debug(hermon_state_t
*state
, hermon_qphdl_t qp
);
198 #endif /* _SYS_IB_ADAPTERS_HERMON_WR_H */