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., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
28 #include <ipxe/infiniband.h>
29 #include <ipxe/ib_smc.h>
34 * Infiniband Subnet Management Client
41 * @v ibdev Infiniband device
42 * @v attr_id Attribute ID, in network byte order
43 * @v attr_mod Attribute modifier, in network byte order
44 * @v local_mad Method for issuing local MADs
45 * @v mad Management datagram to fill in
46 * @ret rc Return status code
48 static int ib_smc_mad ( struct ib_device *ibdev, uint16_t attr_id,
49 uint32_t attr_mod, ib_local_mad_t local_mad,
54 memset ( mad, 0, sizeof ( *mad ) );
55 mad->hdr.base_version = IB_MGMT_BASE_VERSION;
56 mad->hdr.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
57 mad->hdr.class_version = 1;
58 mad->hdr.method = IB_MGMT_METHOD_GET;
59 mad->hdr.attr_id = attr_id;
60 mad->hdr.attr_mod = attr_mod;
63 if ( ( rc = local_mad ( ibdev, mad ) ) != 0 )
70 * Get node information
72 * @v ibdev Infiniband device
73 * @v local_mad Method for issuing local MADs
74 * @v mad Management datagram to fill in
75 * @ret rc Return status code
77 static int ib_smc_get_node_info ( struct ib_device *ibdev,
78 ib_local_mad_t local_mad,
83 if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_NODE_INFO ), 0,
84 local_mad, mad ) ) != 0 ) {
85 DBGC ( ibdev, "IBDEV %p could not get node info: %s\n",
86 ibdev, strerror ( rc ) );
93 * Get port information
95 * @v ibdev Infiniband device
96 * @v local_mad Method for issuing local MADs
97 * @v mad Management datagram to fill in
98 * @ret rc Return status code
100 static int ib_smc_get_port_info ( struct ib_device *ibdev,
101 ib_local_mad_t local_mad,
102 union ib_mad *mad ) {
106 if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PORT_INFO ),
107 htonl ( ibdev->port ), local_mad, mad )) !=0){
108 DBGC ( ibdev, "IBDEV %p could not get port info: %s\n",
109 ibdev, strerror ( rc ) );
116 * Get GUID information
118 * @v ibdev Infiniband device
119 * @v local_mad Method for issuing local MADs
120 * @v mad Management datagram to fill in
121 * @ret rc Return status code
123 static int ib_smc_get_guid_info ( struct ib_device *ibdev,
124 ib_local_mad_t local_mad,
125 union ib_mad *mad ) {
129 if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_GUID_INFO ), 0,
130 local_mad, mad ) ) != 0 ) {
131 DBGC ( ibdev, "IBDEV %p could not get GUID info: %s\n",
132 ibdev, strerror ( rc ) );
139 * Get partition key table
141 * @v ibdev Infiniband device
142 * @v local_mad Method for issuing local MADs
143 * @v mad Management datagram to fill in
144 * @ret rc Return status code
146 static int ib_smc_get_pkey_table ( struct ib_device *ibdev,
147 ib_local_mad_t local_mad,
148 union ib_mad *mad ) {
152 if ( ( rc = ib_smc_mad ( ibdev, htons ( IB_SMP_ATTR_PKEY_TABLE ), 0,
153 local_mad, mad ) ) != 0 ) {
154 DBGC ( ibdev, "IBDEV %p could not get pkey table: %s\n",
155 ibdev, strerror ( rc ) );
162 * Get Infiniband parameters using SMC
164 * @v ibdev Infiniband device
165 * @v local_mad Method for issuing local MADs
166 * @ret rc Return status code
168 static int ib_smc_get ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
170 struct ib_node_info *node_info = &mad.smp.smp_data.node_info;
171 struct ib_port_info *port_info = &mad.smp.smp_data.port_info;
172 struct ib_guid_info *guid_info = &mad.smp.smp_data.guid_info;
173 struct ib_pkey_table *pkey_table = &mad.smp.smp_data.pkey_table;
176 /* Node info gives us the node GUID */
177 if ( ( rc = ib_smc_get_node_info ( ibdev, local_mad, &mad ) ) != 0 )
179 memcpy ( &ibdev->node_guid, &node_info->node_guid,
180 sizeof ( ibdev->node_guid ) );
182 /* Port info gives us the link state, the first half of the
183 * port GID and the SM LID.
185 if ( ( rc = ib_smc_get_port_info ( ibdev, local_mad, &mad ) ) != 0 )
187 memcpy ( &ibdev->gid.s.prefix, port_info->gid_prefix,
188 sizeof ( ibdev->gid.s.prefix ) );
189 ibdev->lid = ntohs ( port_info->lid );
190 ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
191 ibdev->link_width_enabled = port_info->link_width_enabled;
192 ibdev->link_width_supported = port_info->link_width_supported;
193 ibdev->link_width_active = port_info->link_width_active;
194 ibdev->link_speed_supported =
195 ( port_info->link_speed_supported__port_state >> 4 );
197 ( port_info->link_speed_supported__port_state & 0xf );
198 ibdev->link_speed_active =
199 ( port_info->link_speed_active__link_speed_enabled >> 4 );
200 ibdev->link_speed_enabled =
201 ( port_info->link_speed_active__link_speed_enabled & 0xf );
202 ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
204 /* GUID info gives us the second half of the port GID */
205 if ( ( rc = ib_smc_get_guid_info ( ibdev, local_mad, &mad ) ) != 0 )
207 memcpy ( &ibdev->gid.s.guid, guid_info->guid[0],
208 sizeof ( ibdev->gid.s.guid ) );
210 /* Get partition key */
211 if ( ( rc = ib_smc_get_pkey_table ( ibdev, local_mad, &mad ) ) != 0 )
213 ibdev->pkey = ntohs ( pkey_table->pkey[0] );
215 DBGC ( ibdev, "IBDEV %p port GID is " IB_GID_FMT "\n",
216 ibdev, IB_GID_ARGS ( &ibdev->gid ) );
222 * Initialise Infiniband parameters using SMC
224 * @v ibdev Infiniband device
225 * @v local_mad Method for issuing local MADs
226 * @ret rc Return status code
228 int ib_smc_init ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
231 /* Get MAD parameters */
232 if ( ( rc = ib_smc_get ( ibdev, local_mad ) ) != 0 )
239 * Update Infiniband parameters using SMC
241 * @v ibdev Infiniband device
242 * @v local_mad Method for issuing local MADs
243 * @ret rc Return status code
245 int ib_smc_update ( struct ib_device *ibdev, ib_local_mad_t local_mad ) {
248 /* Get MAD parameters */
249 if ( ( rc = ib_smc_get ( ibdev, local_mad ) ) != 0 )
252 /* Notify Infiniband core of potential link state change */
253 ib_link_state_changed ( ibdev );