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/infiniband.h>
29
#include <gpxe/iobuf.h>
30
#include <gpxe/ib_mi.h>
31
#include <gpxe/ib_sma.h>
36
* Infiniband Subnet Management Agent
43
* @v ibdev Infiniband device
44
* @v mi Management interface
46
* @v av Source address vector
48
static void ib_sma_node_info ( struct ib_device *ibdev,
49
struct ib_mad_interface *mi,
51
struct ib_address_vector *av ) {
52
struct ib_node_info *node_info = &mad->smp.smp_data.node_info;
55
/* Fill in information */
56
memset ( node_info, 0, sizeof ( *node_info ) );
57
node_info->base_version = IB_MGMT_BASE_VERSION;
58
node_info->class_version = IB_SMP_CLASS_VERSION;
59
node_info->node_type = IB_NODE_TYPE_HCA;
60
node_info->num_ports = ib_get_hca_info ( ibdev, &node_info->sys_guid );
61
memcpy ( &node_info->node_guid, &node_info->sys_guid,
62
sizeof ( node_info->node_guid ) );
63
memcpy ( &node_info->port_guid, &ibdev->gid.u.half[1],
64
sizeof ( node_info->port_guid ) );
65
node_info->partition_cap = htons ( 1 );
66
node_info->local_port_num = ibdev->port;
68
/* Send GetResponse */
69
mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
70
if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
71
DBGC ( mi, "SMA %p could not send NodeInfo GetResponse: %s\n",
72
mi, strerror ( rc ) );
80
* @v ibdev Infiniband device
81
* @v mi Management interface
83
* @v av Source address vector
85
static void ib_sma_node_desc ( struct ib_device *ibdev,
86
struct ib_mad_interface *mi,
88
struct ib_address_vector *av ) {
89
struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc;
90
struct ib_gid_half *guid = &ibdev->gid.u.half[1];
93
/* Fill in information */
94
memset ( node_desc, 0, sizeof ( *node_desc ) );
95
snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ),
96
"gPXE %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)",
97
guid->u.bytes[0], guid->u.bytes[1], guid->u.bytes[2],
98
guid->u.bytes[3], guid->u.bytes[4], guid->u.bytes[5],
99
guid->u.bytes[6], guid->u.bytes[7], ibdev->dev->name );
101
/* Send GetResponse */
102
mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
103
if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
104
DBGC ( mi, "SMA %p could not send NodeDesc GetResponse: %s\n",
105
mi, strerror ( rc ) );
113
* @v ibdev Infiniband device
114
* @v mi Management interface
115
* @v mad Received MAD
116
* @v av Source address vector
118
static void ib_sma_guid_info ( struct ib_device *ibdev,
119
struct ib_mad_interface *mi,
121
struct ib_address_vector *av ) {
122
struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info;
125
/* Fill in information */
126
memset ( guid_info, 0, sizeof ( *guid_info ) );
127
memcpy ( guid_info->guid[0], &ibdev->gid.u.half[1],
128
sizeof ( guid_info->guid[0] ) );
130
/* Send GetResponse */
131
mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
132
if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
133
DBGC ( mi, "SMA %p could not send GuidInfo GetResponse: %s\n",
134
mi, strerror ( rc ) );
140
* Set port information
142
* @v ibdev Infiniband device
143
* @v mi Management interface
144
* @v mad Received MAD
145
* @ret rc Return status code
147
static int ib_sma_set_port_info ( struct ib_device *ibdev,
148
struct ib_mad_interface *mi,
149
union ib_mad *mad ) {
150
const struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
151
unsigned int link_width_enabled;
152
unsigned int link_speed_enabled;
156
memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix,
157
sizeof ( ibdev->gid.u.half[0] ) );
158
ibdev->lid = ntohs ( port_info->lid );
159
ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
160
if ( ( link_width_enabled = port_info->link_width_enabled ) )
161
ibdev->link_width_enabled = link_width_enabled;
162
if ( ( link_speed_enabled =
163
( port_info->link_speed_active__link_speed_enabled & 0xf ) ) )
164
ibdev->link_speed_enabled = link_speed_enabled;
165
ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
166
DBGC ( mi, "SMA %p set LID %04x SMLID %04x link width %02x speed "
167
"%02x\n", mi, ibdev->lid, ibdev->sm_lid,
168
ibdev->link_width_enabled, ibdev->link_speed_enabled );
170
/* Update parameters on device */
171
if ( ( rc = ib_set_port_info ( ibdev, mad ) ) != 0 ) {
172
DBGC ( mi, "SMA %p could not set port information: %s\n",
173
mi, strerror ( rc ) );
183
* @v ibdev Infiniband device
184
* @v mi Management interface
185
* @v mad Received MAD
186
* @v av Source address vector
188
static void ib_sma_port_info ( struct ib_device *ibdev,
189
struct ib_mad_interface *mi,
191
struct ib_address_vector *av ) {
192
struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
195
/* Set parameters if applicable */
196
if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
197
if ( ( rc = ib_sma_set_port_info ( ibdev, mi, mad ) ) != 0 ) {
199
htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
200
/* Fall through to generate GetResponse */
204
/* Fill in information */
205
memset ( port_info, 0, sizeof ( *port_info ) );
206
memcpy ( port_info->gid_prefix, &ibdev->gid.u.half[0],
207
sizeof ( port_info->gid_prefix ) );
208
port_info->lid = ntohs ( ibdev->lid );
209
port_info->mastersm_lid = ntohs ( ibdev->sm_lid );
210
port_info->local_port_num = ibdev->port;
211
port_info->link_width_enabled = ibdev->link_width_enabled;
212
port_info->link_width_supported = ibdev->link_width_supported;
213
port_info->link_width_active = ibdev->link_width_active;
214
port_info->link_speed_supported__port_state =
215
( ( ibdev->link_speed_supported << 4 ) | ibdev->port_state );
216
port_info->port_phys_state__link_down_def_state =
217
( ( IB_PORT_PHYS_STATE_POLLING << 4 ) |
218
IB_PORT_PHYS_STATE_POLLING );
219
port_info->link_speed_active__link_speed_enabled =
220
( ( ibdev->link_speed_active << 4 ) |
221
ibdev->link_speed_enabled );
222
port_info->neighbour_mtu__mastersm_sl =
223
( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl );
224
port_info->vl_cap__init_type = ( IB_VL_0 << 4 );
225
port_info->init_type_reply__mtu_cap = IB_MTU_2048;
226
port_info->operational_vls__enforcement = ( IB_VL_0 << 4 );
227
port_info->guid_cap = 1;
229
/* Send GetResponse */
230
mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
231
if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
232
DBGC ( mi, "SMA %p could not send PortInfo GetResponse: %s\n",
233
mi, strerror ( rc ) );
239
* Set partition key table
241
* @v ibdev Infiniband device
242
* @v mi Management interface
243
* @v mad Received MAD
244
* @ret rc Return status code
246
static int ib_sma_set_pkey_table ( struct ib_device *ibdev,
247
struct ib_mad_interface *mi,
248
union ib_mad *mad ) {
249
struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
253
ibdev->pkey = ntohs ( pkey_table->pkey[0] );
254
DBGC ( mi, "SMA %p set pkey %04x\n", mi, ibdev->pkey );
256
/* Update parameters on device */
257
if ( ( rc = ib_set_pkey_table ( ibdev, mad ) ) != 0 ) {
258
DBGC ( mi, "SMA %p could not set pkey table: %s\n",
259
mi, strerror ( rc ) );
267
* Partition key table
269
* @v ibdev Infiniband device
270
* @v mi Management interface
271
* @v mad Received MAD
272
* @v av Source address vector
274
static void ib_sma_pkey_table ( struct ib_device *ibdev,
275
struct ib_mad_interface *mi,
277
struct ib_address_vector *av ) {
278
struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
281
/* Set parameters, if applicable */
282
if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
283
if ( ( rc = ib_sma_set_pkey_table ( ibdev, mi, mad ) ) != 0 ) {
285
htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
286
/* Fall through to generate GetResponse */
290
/* Fill in information */
291
mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
292
memset ( pkey_table, 0, sizeof ( *pkey_table ) );
293
pkey_table->pkey[0] = htons ( ibdev->pkey );
295
/* Send GetResponse */
296
mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
297
if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
298
DBGC ( mi, "SMA %p could not send PKeyTable GetResponse: %s\n",
299
mi, strerror ( rc ) );
304
/** Subnet management agent */
305
struct ib_mad_agent ib_sma_agent[] __ib_mad_agent = {
307
.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
308
.class_version = IB_SMP_CLASS_VERSION,
309
.attr_id = htons ( IB_SMP_ATTR_NODE_INFO ),
310
.handle = ib_sma_node_info,
313
.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
314
.class_version = IB_SMP_CLASS_VERSION,
315
.attr_id = htons ( IB_SMP_ATTR_NODE_DESC ),
316
.handle = ib_sma_node_desc,
319
.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
320
.class_version = IB_SMP_CLASS_VERSION,
321
.attr_id = htons ( IB_SMP_ATTR_GUID_INFO ),
322
.handle = ib_sma_guid_info,
325
.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
326
.class_version = IB_SMP_CLASS_VERSION,
327
.attr_id = htons ( IB_SMP_ATTR_PORT_INFO ),
328
.handle = ib_sma_port_info,
331
.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
332
.class_version = IB_SMP_CLASS_VERSION,
333
.attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ),
334
.handle = ib_sma_pkey_table,
339
* Create subnet management agent and interface
341
* @v ibdev Infiniband device
342
* @v mi Management interface
343
* @ret rc Return status code
345
int ib_create_sma ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
348
DBGC ( ibdev, "IBDEV %p SMA using SMI %p\n", ibdev, mi );
354
* Destroy subnet management agent and interface
356
* @v ibdev Infiniband device
357
* @v mi Management interface
359
void ib_destroy_sma ( struct ib_device *ibdev __unused,
360
struct ib_mad_interface *mi __unused ) {