2 * IBM eServer eHCA Infiniband device driver for Linux on POWER
6 * Authors: Khadija Souissi <souissi@de.ibm.com>
7 * Heiko J Schick <schickhj@de.ibm.com>
9 * Copyright (c) 2005 IBM Corporation
11 * All rights reserved.
13 * This source code is distributed under a dual license of GPL v2.0 and OpenIB
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are met:
21 * Redistributions of source code must retain the above copyright notice, this
22 * list of conditions and the following disclaimer.
24 * Redistributions in binary form must reproduce the above copyright notice,
25 * this list of conditions and the following disclaimer in the documentation
26 * and/or other materials
27 * provided with the distribution.
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
33 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
36 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
37 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 * POSSIBILITY OF SUCH DAMAGE.
42 #include <rdma/ib_mad.h>
44 #include "ehca_classes.h"
45 #include "ehca_tools.h"
46 #include "ehca_iverbs.h"
49 #define IB_MAD_STATUS_REDIRECT cpu_to_be16(0x0002)
50 #define IB_MAD_STATUS_UNSUP_VERSION cpu_to_be16(0x0004)
51 #define IB_MAD_STATUS_UNSUP_METHOD cpu_to_be16(0x0008)
53 #define IB_PMA_CLASS_PORT_INFO cpu_to_be16(0x0001)
56 * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue
57 * pair is created successfully, the corresponding port gets active.
59 * Define Special Queue pair 0 (SMI QP) is still not supported.
61 * @qp_init_attr: Queue pair init attributes with port and queue pair type
64 u64
ehca_define_sqp(struct ehca_shca
*shca
,
65 struct ehca_qp
*ehca_qp
,
66 struct ib_qp_init_attr
*qp_init_attr
)
68 u32 pma_qp_nr
, bma_qp_nr
;
70 u8 port
= qp_init_attr
->port_num
;
73 shca
->sport
[port
- 1].port_state
= IB_PORT_DOWN
;
75 switch (qp_init_attr
->qp_type
) {
77 /* function not supported yet */
80 ret
= hipz_h_define_aqp1(shca
->ipz_hca_handle
,
81 ehca_qp
->ipz_qp_handle
,
82 ehca_qp
->galpas
.kernel
,
83 (u32
) qp_init_attr
->port_num
,
84 &pma_qp_nr
, &bma_qp_nr
);
86 if (ret
!= H_SUCCESS
) {
87 ehca_err(&shca
->ib_device
,
88 "Can't define AQP1 for port %x. h_ret=%lli",
92 shca
->sport
[port
- 1].pma_qp_nr
= pma_qp_nr
;
93 ehca_dbg(&shca
->ib_device
, "port=%x pma_qp_nr=%x",
97 ehca_err(&shca
->ib_device
, "invalid qp_type=%x",
98 qp_init_attr
->qp_type
);
102 if (ehca_nr_ports
< 0) /* autodetect mode */
106 shca
->sport
[port
- 1].port_state
!= IB_PORT_ACTIVE
&&
107 counter
< ehca_port_act_time
;
109 ehca_dbg(&shca
->ib_device
, "... wait until port %x is active",
111 msleep_interruptible(1000);
114 if (counter
== ehca_port_act_time
) {
115 ehca_err(&shca
->ib_device
, "Port %x is not active.", port
);
123 struct ib_mad_hdr mad_hdr
;
126 } __attribute__ ((packed
));
128 /* TC/SL/FL packed into 32 bits, as in ClassPortInfo */
133 } __attribute__ ((packed
));
135 /* IP Version/TC/FL packed into 32 bits, as in GRH */
140 } __attribute__ ((packed
));
142 static int ehca_process_perf(struct ib_device
*ibdev
, u8 port_num
,
143 struct ib_wc
*in_wc
, struct ib_grh
*in_grh
,
144 struct ib_mad
*in_mad
, struct ib_mad
*out_mad
)
146 struct ib_perf
*in_perf
= (struct ib_perf
*)in_mad
;
147 struct ib_perf
*out_perf
= (struct ib_perf
*)out_mad
;
148 struct ib_class_port_info
*poi
=
149 (struct ib_class_port_info
*)out_perf
->data
;
150 struct tcslfl
*tcslfl
=
151 (struct tcslfl
*)&poi
->redirect_tcslfl
;
152 struct ehca_shca
*shca
=
153 container_of(ibdev
, struct ehca_shca
, ib_device
);
154 struct ehca_sport
*sport
= &shca
->sport
[port_num
- 1];
156 ehca_dbg(ibdev
, "method=%x", in_perf
->mad_hdr
.method
);
160 if (in_perf
->mad_hdr
.class_version
!= 1) {
161 ehca_warn(ibdev
, "Unsupported class_version=%x",
162 in_perf
->mad_hdr
.class_version
);
163 out_perf
->mad_hdr
.status
= IB_MAD_STATUS_UNSUP_VERSION
;
167 switch (in_perf
->mad_hdr
.method
) {
168 case IB_MGMT_METHOD_GET
:
169 case IB_MGMT_METHOD_SET
:
170 /* set class port info for redirection */
171 out_perf
->mad_hdr
.attr_id
= IB_PMA_CLASS_PORT_INFO
;
172 out_perf
->mad_hdr
.status
= IB_MAD_STATUS_REDIRECT
;
173 memset(poi
, 0, sizeof(*poi
));
174 poi
->base_version
= 1;
175 poi
->class_version
= 1;
176 poi
->resp_time_value
= 18;
178 /* copy local routing information from WC where applicable */
179 tcslfl
->sl
= in_wc
->sl
;
181 sport
->saved_attr
.lid
| in_wc
->dlid_path_bits
;
182 poi
->redirect_qp
= sport
->pma_qp_nr
;
183 poi
->redirect_qkey
= IB_QP1_QKEY
;
185 ehca_query_pkey(ibdev
, port_num
, in_wc
->pkey_index
,
186 &poi
->redirect_pkey
);
188 /* if request was globally routed, copy route info */
190 struct vertcfl
*vertcfl
=
191 (struct vertcfl
*)&in_grh
->version_tclass_flow
;
192 memcpy(poi
->redirect_gid
, in_grh
->dgid
.raw
,
193 sizeof(poi
->redirect_gid
));
194 tcslfl
->tc
= vertcfl
->tc
;
195 tcslfl
->fl
= vertcfl
->fl
;
197 /* else only fill in default GID */
198 ehca_query_gid(ibdev
, port_num
, 0,
199 (union ib_gid
*)&poi
->redirect_gid
);
201 ehca_dbg(ibdev
, "ehca_pma_lid=%x ehca_pma_qp=%x",
202 sport
->saved_attr
.lid
, sport
->pma_qp_nr
);
205 case IB_MGMT_METHOD_GET_RESP
:
206 return IB_MAD_RESULT_FAILURE
;
209 out_perf
->mad_hdr
.status
= IB_MAD_STATUS_UNSUP_METHOD
;
214 out_perf
->mad_hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
216 return IB_MAD_RESULT_SUCCESS
| IB_MAD_RESULT_REPLY
;
219 int ehca_process_mad(struct ib_device
*ibdev
, int mad_flags
, u8 port_num
,
220 struct ib_wc
*in_wc
, struct ib_grh
*in_grh
,
221 struct ib_mad
*in_mad
, struct ib_mad
*out_mad
)
225 if (!port_num
|| port_num
> ibdev
->phys_port_cnt
|| !in_wc
)
226 return IB_MAD_RESULT_FAILURE
;
228 /* accept only pma request */
229 if (in_mad
->mad_hdr
.mgmt_class
!= IB_MGMT_CLASS_PERF_MGMT
)
230 return IB_MAD_RESULT_SUCCESS
;
232 ehca_dbg(ibdev
, "port_num=%x src_qp=%x", port_num
, in_wc
->src_qp
);
233 ret
= ehca_process_perf(ibdev
, port_num
, in_wc
, in_grh
,