2 * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 FILE_LICENCE ( GPL2_OR_LATER
);
28 #include <gpxe/settings.h>
29 #include <gpxe/infiniband.h>
30 #include <gpxe/iobuf.h>
31 #include <gpxe/ib_mi.h>
32 #include <gpxe/ib_sma.h>
37 * Infiniband Subnet Management Agent
44 * @v ibdev Infiniband device
45 * @v mi Management interface
47 * @v av Source address vector
49 static void ib_sma_node_info ( struct ib_device
*ibdev
,
50 struct ib_mad_interface
*mi
,
52 struct ib_address_vector
*av
) {
53 struct ib_node_info
*node_info
= &mad
->smp
.smp_data
.node_info
;
56 /* Fill in information */
57 memset ( node_info
, 0, sizeof ( *node_info
) );
58 node_info
->base_version
= IB_MGMT_BASE_VERSION
;
59 node_info
->class_version
= IB_SMP_CLASS_VERSION
;
60 node_info
->node_type
= IB_NODE_TYPE_HCA
;
61 node_info
->num_ports
= ib_get_hca_info ( ibdev
, &node_info
->sys_guid
);
62 memcpy ( &node_info
->node_guid
, &node_info
->sys_guid
,
63 sizeof ( node_info
->node_guid
) );
64 memcpy ( &node_info
->port_guid
, &ibdev
->gid
.u
.half
[1],
65 sizeof ( node_info
->port_guid
) );
66 node_info
->partition_cap
= htons ( 1 );
67 node_info
->local_port_num
= ibdev
->port
;
69 /* Send GetResponse */
70 mad
->hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
71 if ( ( rc
= ib_mi_send ( ibdev
, mi
, mad
, av
) ) != 0 ) {
72 DBGC ( mi
, "SMA %p could not send NodeInfo GetResponse: %s\n",
73 mi
, strerror ( rc
) );
81 * @v ibdev Infiniband device
82 * @v mi Management interface
84 * @v av Source address vector
86 static void ib_sma_node_desc ( struct ib_device
*ibdev
,
87 struct ib_mad_interface
*mi
,
89 struct ib_address_vector
*av
) {
90 struct ib_node_desc
*node_desc
= &mad
->smp
.smp_data
.node_desc
;
91 struct ib_gid_half guid
;
92 char hostname
[ sizeof ( node_desc
->node_string
) ];
96 /* Fill in information */
97 memset ( node_desc
, 0, sizeof ( *node_desc
) );
98 ib_get_hca_info ( ibdev
, &guid
);
99 hostname_len
= fetch_string_setting ( NULL
, &hostname_setting
,
100 hostname
, sizeof ( hostname
) );
101 snprintf ( node_desc
->node_string
, sizeof ( node_desc
->node_string
),
102 "gPXE %s%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)",
103 hostname
, ( ( hostname_len
>= 0 ) ? " " : "" ),
104 guid
.u
.bytes
[0], guid
.u
.bytes
[1], guid
.u
.bytes
[2],
105 guid
.u
.bytes
[3], guid
.u
.bytes
[4], guid
.u
.bytes
[5],
106 guid
.u
.bytes
[6], guid
.u
.bytes
[7], ibdev
->dev
->name
);
108 /* Send GetResponse */
109 mad
->hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
110 if ( ( rc
= ib_mi_send ( ibdev
, mi
, mad
, av
) ) != 0 ) {
111 DBGC ( mi
, "SMA %p could not send NodeDesc GetResponse: %s\n",
112 mi
, strerror ( rc
) );
120 * @v ibdev Infiniband device
121 * @v mi Management interface
122 * @v mad Received MAD
123 * @v av Source address vector
125 static void ib_sma_guid_info ( struct ib_device
*ibdev
,
126 struct ib_mad_interface
*mi
,
128 struct ib_address_vector
*av
) {
129 struct ib_guid_info
*guid_info
= &mad
->smp
.smp_data
.guid_info
;
132 /* Fill in information */
133 memset ( guid_info
, 0, sizeof ( *guid_info
) );
134 memcpy ( guid_info
->guid
[0], &ibdev
->gid
.u
.half
[1],
135 sizeof ( guid_info
->guid
[0] ) );
137 /* Send GetResponse */
138 mad
->hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
139 if ( ( rc
= ib_mi_send ( ibdev
, mi
, mad
, av
) ) != 0 ) {
140 DBGC ( mi
, "SMA %p could not send GuidInfo GetResponse: %s\n",
141 mi
, strerror ( rc
) );
147 * Set port information
149 * @v ibdev Infiniband device
150 * @v mi Management interface
151 * @v mad Received MAD
152 * @ret rc Return status code
154 static int ib_sma_set_port_info ( struct ib_device
*ibdev
,
155 struct ib_mad_interface
*mi
,
156 union ib_mad
*mad
) {
157 const struct ib_port_info
*port_info
= &mad
->smp
.smp_data
.port_info
;
158 unsigned int link_width_enabled
;
159 unsigned int link_speed_enabled
;
163 memcpy ( &ibdev
->gid
.u
.half
[0], port_info
->gid_prefix
,
164 sizeof ( ibdev
->gid
.u
.half
[0] ) );
165 ibdev
->lid
= ntohs ( port_info
->lid
);
166 ibdev
->sm_lid
= ntohs ( port_info
->mastersm_lid
);
167 if ( ( link_width_enabled
= port_info
->link_width_enabled
) )
168 ibdev
->link_width_enabled
= link_width_enabled
;
169 if ( ( link_speed_enabled
=
170 ( port_info
->link_speed_active__link_speed_enabled
& 0xf ) ) )
171 ibdev
->link_speed_enabled
= link_speed_enabled
;
172 ibdev
->sm_sl
= ( port_info
->neighbour_mtu__mastersm_sl
& 0xf );
173 DBGC ( mi
, "SMA %p set LID %04x SMLID %04x link width %02x speed "
174 "%02x\n", mi
, ibdev
->lid
, ibdev
->sm_lid
,
175 ibdev
->link_width_enabled
, ibdev
->link_speed_enabled
);
177 /* Update parameters on device */
178 if ( ( rc
= ib_set_port_info ( ibdev
, mad
) ) != 0 ) {
179 DBGC ( mi
, "SMA %p could not set port information: %s\n",
180 mi
, strerror ( rc
) );
190 * @v ibdev Infiniband device
191 * @v mi Management interface
192 * @v mad Received MAD
193 * @v av Source address vector
195 static void ib_sma_port_info ( struct ib_device
*ibdev
,
196 struct ib_mad_interface
*mi
,
198 struct ib_address_vector
*av
) {
199 struct ib_port_info
*port_info
= &mad
->smp
.smp_data
.port_info
;
202 /* Set parameters if applicable */
203 if ( mad
->hdr
.method
== IB_MGMT_METHOD_SET
) {
204 if ( ( rc
= ib_sma_set_port_info ( ibdev
, mi
, mad
) ) != 0 ) {
206 htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR
);
207 /* Fall through to generate GetResponse */
211 /* Fill in information */
212 memset ( port_info
, 0, sizeof ( *port_info
) );
213 memcpy ( port_info
->gid_prefix
, &ibdev
->gid
.u
.half
[0],
214 sizeof ( port_info
->gid_prefix
) );
215 port_info
->lid
= ntohs ( ibdev
->lid
);
216 port_info
->mastersm_lid
= ntohs ( ibdev
->sm_lid
);
217 port_info
->local_port_num
= ibdev
->port
;
218 port_info
->link_width_enabled
= ibdev
->link_width_enabled
;
219 port_info
->link_width_supported
= ibdev
->link_width_supported
;
220 port_info
->link_width_active
= ibdev
->link_width_active
;
221 port_info
->link_speed_supported__port_state
=
222 ( ( ibdev
->link_speed_supported
<< 4 ) | ibdev
->port_state
);
223 port_info
->port_phys_state__link_down_def_state
=
224 ( ( IB_PORT_PHYS_STATE_POLLING
<< 4 ) |
225 IB_PORT_PHYS_STATE_POLLING
);
226 port_info
->link_speed_active__link_speed_enabled
=
227 ( ( ibdev
->link_speed_active
<< 4 ) |
228 ibdev
->link_speed_enabled
);
229 port_info
->neighbour_mtu__mastersm_sl
=
230 ( ( IB_MTU_2048
<< 4 ) | ibdev
->sm_sl
);
231 port_info
->vl_cap__init_type
= ( IB_VL_0
<< 4 );
232 port_info
->init_type_reply__mtu_cap
= IB_MTU_2048
;
233 port_info
->operational_vls__enforcement
= ( IB_VL_0
<< 4 );
234 port_info
->guid_cap
= 1;
236 /* Send GetResponse */
237 mad
->hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
238 if ( ( rc
= ib_mi_send ( ibdev
, mi
, mad
, av
) ) != 0 ) {
239 DBGC ( mi
, "SMA %p could not send PortInfo GetResponse: %s\n",
240 mi
, strerror ( rc
) );
246 * Set partition key table
248 * @v ibdev Infiniband device
249 * @v mi Management interface
250 * @v mad Received MAD
251 * @ret rc Return status code
253 static int ib_sma_set_pkey_table ( struct ib_device
*ibdev
,
254 struct ib_mad_interface
*mi
,
255 union ib_mad
*mad
) {
256 struct ib_pkey_table
*pkey_table
= &mad
->smp
.smp_data
.pkey_table
;
260 ibdev
->pkey
= ntohs ( pkey_table
->pkey
[0] );
261 DBGC ( mi
, "SMA %p set pkey %04x\n", mi
, ibdev
->pkey
);
263 /* Update parameters on device */
264 if ( ( rc
= ib_set_pkey_table ( ibdev
, mad
) ) != 0 ) {
265 DBGC ( mi
, "SMA %p could not set pkey table: %s\n",
266 mi
, strerror ( rc
) );
274 * Partition key table
276 * @v ibdev Infiniband device
277 * @v mi Management interface
278 * @v mad Received MAD
279 * @v av Source address vector
281 static void ib_sma_pkey_table ( struct ib_device
*ibdev
,
282 struct ib_mad_interface
*mi
,
284 struct ib_address_vector
*av
) {
285 struct ib_pkey_table
*pkey_table
= &mad
->smp
.smp_data
.pkey_table
;
288 /* Set parameters, if applicable */
289 if ( mad
->hdr
.method
== IB_MGMT_METHOD_SET
) {
290 if ( ( rc
= ib_sma_set_pkey_table ( ibdev
, mi
, mad
) ) != 0 ) {
292 htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR
);
293 /* Fall through to generate GetResponse */
297 /* Fill in information */
298 mad
->hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
299 memset ( pkey_table
, 0, sizeof ( *pkey_table
) );
300 pkey_table
->pkey
[0] = htons ( ibdev
->pkey
);
302 /* Send GetResponse */
303 mad
->hdr
.method
= IB_MGMT_METHOD_GET_RESP
;
304 if ( ( rc
= ib_mi_send ( ibdev
, mi
, mad
, av
) ) != 0 ) {
305 DBGC ( mi
, "SMA %p could not send PKeyTable GetResponse: %s\n",
306 mi
, strerror ( rc
) );
311 /** Subnet management agent */
312 struct ib_mad_agent ib_sma_agent
[] __ib_mad_agent
= {
314 .mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
,
315 .class_version
= IB_SMP_CLASS_VERSION
,
316 .attr_id
= htons ( IB_SMP_ATTR_NODE_INFO
),
317 .handle
= ib_sma_node_info
,
320 .mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
,
321 .class_version
= IB_SMP_CLASS_VERSION
,
322 .attr_id
= htons ( IB_SMP_ATTR_NODE_DESC
),
323 .handle
= ib_sma_node_desc
,
326 .mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
,
327 .class_version
= IB_SMP_CLASS_VERSION
,
328 .attr_id
= htons ( IB_SMP_ATTR_GUID_INFO
),
329 .handle
= ib_sma_guid_info
,
332 .mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
,
333 .class_version
= IB_SMP_CLASS_VERSION
,
334 .attr_id
= htons ( IB_SMP_ATTR_PORT_INFO
),
335 .handle
= ib_sma_port_info
,
338 .mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
,
339 .class_version
= IB_SMP_CLASS_VERSION
,
340 .attr_id
= htons ( IB_SMP_ATTR_PKEY_TABLE
),
341 .handle
= ib_sma_pkey_table
,
346 * Create subnet management agent and interface
348 * @v ibdev Infiniband device
349 * @v mi Management interface
350 * @ret rc Return status code
352 int ib_create_sma ( struct ib_device
*ibdev
, struct ib_mad_interface
*mi
) {
355 DBGC ( ibdev
, "IBDEV %p SMA using SMI %p\n", ibdev
, mi
);
361 * Destroy subnet management agent and interface
363 * @v ibdev Infiniband device
364 * @v mi Management interface
366 void ib_destroy_sma ( struct ib_device
*ibdev __unused
,
367 struct ib_mad_interface
*mi __unused
) {