2 * Copyright (C) 2008 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
);
27 #include <gpxe/infiniband.h>
28 #include <gpxe/ib_smc.h>
33 * Infiniband Subnet Management Client
38 * Get port information
40 * @v ibdev Infiniband device
41 * @v local_mad Method for issuing local MADs
42 * @v mad Management datagram to fill in
43 * @ret rc Return status code
45 static int ib_smc_get_port_info ( struct ib_device
*ibdev
,
46 ib_local_mad_t local_mad
,
51 memset ( mad
, 0, sizeof ( *mad
) );
52 mad
->hdr
.base_version
= IB_MGMT_BASE_VERSION
;
53 mad
->hdr
.mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
;
54 mad
->hdr
.class_version
= 1;
55 mad
->hdr
.method
= IB_MGMT_METHOD_GET
;
56 mad
->hdr
.attr_id
= htons ( IB_SMP_ATTR_PORT_INFO
);
57 mad
->hdr
.attr_mod
= htonl ( ibdev
->port
);
59 if ( ( rc
= local_mad ( ibdev
, mad
) ) != 0 ) {
60 DBGC ( ibdev
, "IBDEV %p could not get port info: %s\n",
61 ibdev
, strerror ( rc
) );
68 * Get GUID information
70 * @v ibdev Infiniband device
71 * @v local_mad Method for issuing local MADs
72 * @v mad Management datagram to fill in
73 * @ret rc Return status code
75 static int ib_smc_get_guid_info ( struct ib_device
*ibdev
,
76 ib_local_mad_t local_mad
,
81 memset ( mad
, 0, sizeof ( *mad
) );
82 mad
->hdr
.base_version
= IB_MGMT_BASE_VERSION
;
83 mad
->hdr
.mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
;
84 mad
->hdr
.class_version
= 1;
85 mad
->hdr
.method
= IB_MGMT_METHOD_GET
;
86 mad
->hdr
.attr_id
= htons ( IB_SMP_ATTR_GUID_INFO
);
88 if ( ( rc
= local_mad ( ibdev
, mad
) ) != 0 ) {
89 DBGC ( ibdev
, "IBDEV %p could not get GUID info: %s\n",
90 ibdev
, strerror ( rc
) );
97 * Get partition key table
99 * @v ibdev Infiniband device
100 * @v local_mad Method for issuing local MADs
101 * @v mad Management datagram to fill in
102 * @ret rc Return status code
104 static int ib_smc_get_pkey_table ( struct ib_device
*ibdev
,
105 ib_local_mad_t local_mad
,
106 union ib_mad
*mad
) {
110 memset ( mad
, 0, sizeof ( *mad
) );
111 mad
->hdr
.base_version
= IB_MGMT_BASE_VERSION
;
112 mad
->hdr
.mgmt_class
= IB_MGMT_CLASS_SUBN_LID_ROUTED
;
113 mad
->hdr
.class_version
= 1;
114 mad
->hdr
.method
= IB_MGMT_METHOD_GET
;
115 mad
->hdr
.attr_id
= htons ( IB_SMP_ATTR_PKEY_TABLE
);
117 if ( ( rc
= local_mad ( ibdev
, mad
) ) != 0 ) {
118 DBGC ( ibdev
, "IBDEV %p could not get pkey table: %s\n",
119 ibdev
, strerror ( rc
) );
128 * @v ibdev Infiniband device
129 * @v local_mad Method for issuing local MADs
130 * @ret rc Return status code
132 int ib_smc_update ( struct ib_device
*ibdev
, ib_local_mad_t local_mad
) {
134 struct ib_port_info
*port_info
= &mad
.smp
.smp_data
.port_info
;
135 struct ib_guid_info
*guid_info
= &mad
.smp
.smp_data
.guid_info
;
136 struct ib_pkey_table
*pkey_table
= &mad
.smp
.smp_data
.pkey_table
;
139 /* Port info gives us the link state, the first half of the
140 * port GID and the SM LID.
142 if ( ( rc
= ib_smc_get_port_info ( ibdev
, local_mad
, &mad
) ) != 0 )
144 memcpy ( &ibdev
->gid
.u
.half
[0], port_info
->gid_prefix
,
145 sizeof ( ibdev
->gid
.u
.half
[0] ) );
146 ibdev
->lid
= ntohs ( port_info
->lid
);
147 ibdev
->sm_lid
= ntohs ( port_info
->mastersm_lid
);
148 ibdev
->link_width_enabled
= port_info
->link_width_enabled
;
149 ibdev
->link_width_supported
= port_info
->link_width_supported
;
150 ibdev
->link_width_active
= port_info
->link_width_active
;
151 ibdev
->link_speed_supported
=
152 ( port_info
->link_speed_supported__port_state
>> 4 );
154 ( port_info
->link_speed_supported__port_state
& 0xf );
155 ibdev
->link_speed_active
=
156 ( port_info
->link_speed_active__link_speed_enabled
>> 4 );
157 ibdev
->link_speed_enabled
=
158 ( port_info
->link_speed_active__link_speed_enabled
& 0xf );
159 ibdev
->sm_sl
= ( port_info
->neighbour_mtu__mastersm_sl
& 0xf );
161 /* GUID info gives us the second half of the port GID */
162 if ( ( rc
= ib_smc_get_guid_info ( ibdev
, local_mad
, &mad
) ) != 0 )
164 memcpy ( &ibdev
->gid
.u
.half
[1], guid_info
->guid
[0],
165 sizeof ( ibdev
->gid
.u
.half
[1] ) );
167 /* Get partition key */
168 if ( ( rc
= ib_smc_get_pkey_table ( ibdev
, local_mad
, &mad
) ) != 0 )
170 ibdev
->pkey
= ntohs ( pkey_table
->pkey
[0] );
172 DBGC ( ibdev
, "IBDEV %p port GID is %08x:%08x:%08x:%08x\n", ibdev
,
173 htonl ( ibdev
->gid
.u
.dwords
[0] ),
174 htonl ( ibdev
->gid
.u
.dwords
[1] ),
175 htonl ( ibdev
->gid
.u
.dwords
[2] ),
176 htonl ( ibdev
->gid
.u
.dwords
[3] ) );