00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <errno.h>
00025 #include <stdio.h>
00026 #include <unistd.h>
00027 #include <byteswap.h>
00028 #include <gpxe/settings.h>
00029 #include <gpxe/infiniband.h>
00030 #include <gpxe/iobuf.h>
00031 #include <gpxe/ib_mi.h>
00032 #include <gpxe/ib_sma.h>
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 static void ib_sma_node_info ( struct ib_device *ibdev,
00050 struct ib_mad_interface *mi,
00051 union ib_mad *mad,
00052 struct ib_address_vector *av ) {
00053 struct ib_node_info *node_info = &mad->smp.smp_data.node_info;
00054 int rc;
00055
00056
00057 memset ( node_info, 0, sizeof ( *node_info ) );
00058 node_info->base_version = IB_MGMT_BASE_VERSION;
00059 node_info->class_version = IB_SMP_CLASS_VERSION;
00060 node_info->node_type = IB_NODE_TYPE_HCA;
00061 node_info->num_ports = ib_get_hca_info ( ibdev, &node_info->sys_guid );
00062 memcpy ( &node_info->node_guid, &node_info->sys_guid,
00063 sizeof ( node_info->node_guid ) );
00064 memcpy ( &node_info->port_guid, &ibdev->gid.u.half[1],
00065 sizeof ( node_info->port_guid ) );
00066 node_info->partition_cap = htons ( 1 );
00067 node_info->local_port_num = ibdev->port;
00068
00069
00070 mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
00071 if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
00072 DBGC ( mi, "SMA %p could not send NodeInfo GetResponse: %s\n",
00073 mi, strerror ( rc ) );
00074 return;
00075 }
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 static void ib_sma_node_desc ( struct ib_device *ibdev,
00087 struct ib_mad_interface *mi,
00088 union ib_mad *mad,
00089 struct ib_address_vector *av ) {
00090 struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc;
00091 struct ib_gid_half guid;
00092 char hostname[ sizeof ( node_desc->node_string ) ];
00093 int hostname_len;
00094 int rc;
00095
00096
00097 memset ( node_desc, 0, sizeof ( *node_desc ) );
00098 ib_get_hca_info ( ibdev, &guid );
00099 hostname_len = fetch_string_setting ( NULL, &hostname_setting,
00100 hostname, sizeof ( hostname ) );
00101 snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ),
00102 "gPXE %s%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)",
00103 hostname, ( ( hostname_len >= 0 ) ? " " : "" ),
00104 guid.u.bytes[0], guid.u.bytes[1], guid.u.bytes[2],
00105 guid.u.bytes[3], guid.u.bytes[4], guid.u.bytes[5],
00106 guid.u.bytes[6], guid.u.bytes[7], ibdev->dev->name );
00107
00108
00109 mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
00110 if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
00111 DBGC ( mi, "SMA %p could not send NodeDesc GetResponse: %s\n",
00112 mi, strerror ( rc ) );
00113 return;
00114 }
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 static void ib_sma_guid_info ( struct ib_device *ibdev,
00126 struct ib_mad_interface *mi,
00127 union ib_mad *mad,
00128 struct ib_address_vector *av ) {
00129 struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info;
00130 int rc;
00131
00132
00133 memset ( guid_info, 0, sizeof ( *guid_info ) );
00134 memcpy ( guid_info->guid[0], &ibdev->gid.u.half[1],
00135 sizeof ( guid_info->guid[0] ) );
00136
00137
00138 mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
00139 if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
00140 DBGC ( mi, "SMA %p could not send GuidInfo GetResponse: %s\n",
00141 mi, strerror ( rc ) );
00142 return;
00143 }
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static int ib_sma_set_port_info ( struct ib_device *ibdev,
00155 struct ib_mad_interface *mi,
00156 union ib_mad *mad ) {
00157 const struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
00158 unsigned int link_width_enabled;
00159 unsigned int link_speed_enabled;
00160 int rc;
00161
00162
00163 memcpy ( &ibdev->gid.u.half[0], port_info->gid_prefix,
00164 sizeof ( ibdev->gid.u.half[0] ) );
00165 ibdev->lid = ntohs ( port_info->lid );
00166 ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
00167 if ( ( link_width_enabled = port_info->link_width_enabled ) )
00168 ibdev->link_width_enabled = link_width_enabled;
00169 if ( ( link_speed_enabled =
00170 ( port_info->link_speed_active__link_speed_enabled & 0xf ) ) )
00171 ibdev->link_speed_enabled = link_speed_enabled;
00172 ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
00173 DBGC ( mi, "SMA %p set LID %04x SMLID %04x link width %02x speed "
00174 "%02x\n", mi, ibdev->lid, ibdev->sm_lid,
00175 ibdev->link_width_enabled, ibdev->link_speed_enabled );
00176
00177
00178 if ( ( rc = ib_set_port_info ( ibdev, mad ) ) != 0 ) {
00179 DBGC ( mi, "SMA %p could not set port information: %s\n",
00180 mi, strerror ( rc ) );
00181 return rc;
00182 }
00183
00184 return 0;
00185 }
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 static void ib_sma_port_info ( struct ib_device *ibdev,
00196 struct ib_mad_interface *mi,
00197 union ib_mad *mad,
00198 struct ib_address_vector *av ) {
00199 struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
00200 int rc;
00201
00202
00203 if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
00204 if ( ( rc = ib_sma_set_port_info ( ibdev, mi, mad ) ) != 0 ) {
00205 mad->hdr.status =
00206 htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
00207
00208 }
00209 }
00210
00211
00212 memset ( port_info, 0, sizeof ( *port_info ) );
00213 memcpy ( port_info->gid_prefix, &ibdev->gid.u.half[0],
00214 sizeof ( port_info->gid_prefix ) );
00215 port_info->lid = ntohs ( ibdev->lid );
00216 port_info->mastersm_lid = ntohs ( ibdev->sm_lid );
00217 port_info->local_port_num = ibdev->port;
00218 port_info->link_width_enabled = ibdev->link_width_enabled;
00219 port_info->link_width_supported = ibdev->link_width_supported;
00220 port_info->link_width_active = ibdev->link_width_active;
00221 port_info->link_speed_supported__port_state =
00222 ( ( ibdev->link_speed_supported << 4 ) | ibdev->port_state );
00223 port_info->port_phys_state__link_down_def_state =
00224 ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) |
00225 IB_PORT_PHYS_STATE_POLLING );
00226 port_info->link_speed_active__link_speed_enabled =
00227 ( ( ibdev->link_speed_active << 4 ) |
00228 ibdev->link_speed_enabled );
00229 port_info->neighbour_mtu__mastersm_sl =
00230 ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl );
00231 port_info->vl_cap__init_type = ( IB_VL_0 << 4 );
00232 port_info->init_type_reply__mtu_cap = IB_MTU_2048;
00233 port_info->operational_vls__enforcement = ( IB_VL_0 << 4 );
00234 port_info->guid_cap = 1;
00235
00236
00237 mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
00238 if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
00239 DBGC ( mi, "SMA %p could not send PortInfo GetResponse: %s\n",
00240 mi, strerror ( rc ) );
00241 return;
00242 }
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 static int ib_sma_set_pkey_table ( struct ib_device *ibdev,
00254 struct ib_mad_interface *mi,
00255 union ib_mad *mad ) {
00256 struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
00257 int rc;
00258
00259
00260 ibdev->pkey = ntohs ( pkey_table->pkey[0] );
00261 DBGC ( mi, "SMA %p set pkey %04x\n", mi, ibdev->pkey );
00262
00263
00264 if ( ( rc = ib_set_pkey_table ( ibdev, mad ) ) != 0 ) {
00265 DBGC ( mi, "SMA %p could not set pkey table: %s\n",
00266 mi, strerror ( rc ) );
00267 return rc;
00268 }
00269
00270 return 0;
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281 static void ib_sma_pkey_table ( struct ib_device *ibdev,
00282 struct ib_mad_interface *mi,
00283 union ib_mad *mad,
00284 struct ib_address_vector *av ) {
00285 struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
00286 int rc;
00287
00288
00289 if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
00290 if ( ( rc = ib_sma_set_pkey_table ( ibdev, mi, mad ) ) != 0 ) {
00291 mad->hdr.status =
00292 htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
00293
00294 }
00295 }
00296
00297
00298 mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
00299 memset ( pkey_table, 0, sizeof ( *pkey_table ) );
00300 pkey_table->pkey[0] = htons ( ibdev->pkey );
00301
00302
00303 mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
00304 if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
00305 DBGC ( mi, "SMA %p could not send PKeyTable GetResponse: %s\n",
00306 mi, strerror ( rc ) );
00307 return;
00308 }
00309 }
00310
00311
00312 struct ib_mad_agent ib_sma_agent[] __ib_mad_agent = {
00313 {
00314 .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
00315 .class_version = IB_SMP_CLASS_VERSION,
00316 .attr_id = htons ( IB_SMP_ATTR_NODE_INFO ),
00317 .handle = ib_sma_node_info,
00318 },
00319 {
00320 .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
00321 .class_version = IB_SMP_CLASS_VERSION,
00322 .attr_id = htons ( IB_SMP_ATTR_NODE_DESC ),
00323 .handle = ib_sma_node_desc,
00324 },
00325 {
00326 .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
00327 .class_version = IB_SMP_CLASS_VERSION,
00328 .attr_id = htons ( IB_SMP_ATTR_GUID_INFO ),
00329 .handle = ib_sma_guid_info,
00330 },
00331 {
00332 .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
00333 .class_version = IB_SMP_CLASS_VERSION,
00334 .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ),
00335 .handle = ib_sma_port_info,
00336 },
00337 {
00338 .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
00339 .class_version = IB_SMP_CLASS_VERSION,
00340 .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ),
00341 .handle = ib_sma_pkey_table,
00342 },
00343 };
00344
00345
00346
00347
00348
00349
00350
00351
00352 int ib_create_sma ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
00353
00354
00355 DBGC ( ibdev, "IBDEV %p SMA using SMI %p\n", ibdev, mi );
00356
00357 return 0;
00358 }
00359
00360
00361
00362
00363
00364
00365
00366 void ib_destroy_sma ( struct ib_device *ibdev __unused,
00367 struct ib_mad_interface *mi __unused ) {
00368
00369 }