You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
  3. *
  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.
  8. *
  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.
  13. *
  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
  17. * 02110-1301, USA.
  18. *
  19. * You can also choose to distribute this program under the terms of
  20. * the Unmodified Binary Distribution Licence (as given in the file
  21. * COPYING.UBDL), provided that you have satisfied its requirements.
  22. */
  23. FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  24. #include <stdint.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <errno.h>
  28. #include <stdio.h>
  29. #include <unistd.h>
  30. #include <byteswap.h>
  31. #include <ipxe/settings.h>
  32. #include <ipxe/infiniband.h>
  33. #include <ipxe/iobuf.h>
  34. #include <ipxe/ib_mi.h>
  35. #include <ipxe/ib_sma.h>
  36. /**
  37. * @file
  38. *
  39. * Infiniband Subnet Management Agent
  40. *
  41. */
  42. /**
  43. * Node information
  44. *
  45. * @v ibdev Infiniband device
  46. * @v mi Management interface
  47. * @v mad Received MAD
  48. * @v av Source address vector
  49. */
  50. static void ib_sma_node_info ( struct ib_device *ibdev,
  51. struct ib_mad_interface *mi,
  52. union ib_mad *mad,
  53. struct ib_address_vector *av ) {
  54. struct ib_node_info *node_info = &mad->smp.smp_data.node_info;
  55. int rc;
  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_count_ports ( ibdev );
  62. memcpy ( &node_info->sys_guid, &ibdev->node_guid,
  63. sizeof ( node_info->sys_guid ) );
  64. memcpy ( &node_info->node_guid, &ibdev->node_guid,
  65. sizeof ( node_info->node_guid ) );
  66. memcpy ( &node_info->port_guid, &ibdev->gid.s.guid,
  67. sizeof ( node_info->port_guid ) );
  68. node_info->partition_cap = htons ( 1 );
  69. node_info->local_port_num = ibdev->port;
  70. /* Send GetResponse */
  71. mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
  72. if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
  73. DBGC ( mi, "SMA %p could not send NodeInfo GetResponse: %s\n",
  74. mi, strerror ( rc ) );
  75. return;
  76. }
  77. }
  78. /**
  79. * Node description
  80. *
  81. * @v ibdev Infiniband device
  82. * @v mi Management interface
  83. * @v mad Received MAD
  84. * @v av Source address vector
  85. */
  86. static void ib_sma_node_desc ( struct ib_device *ibdev,
  87. struct ib_mad_interface *mi,
  88. union ib_mad *mad,
  89. struct ib_address_vector *av ) {
  90. struct ib_node_desc *node_desc = &mad->smp.smp_data.node_desc;
  91. union ib_guid *guid = &ibdev->node_guid;
  92. char hostname[ sizeof ( node_desc->node_string ) ];
  93. int hostname_len;
  94. int rc;
  95. /* Fill in information */
  96. memset ( node_desc, 0, sizeof ( *node_desc ) );
  97. hostname_len = fetch_string_setting ( NULL, &hostname_setting,
  98. hostname, sizeof ( hostname ) );
  99. snprintf ( node_desc->node_string, sizeof ( node_desc->node_string ),
  100. "iPXE %s%s%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x (%s)",
  101. hostname, ( ( hostname_len >= 0 ) ? " " : "" ),
  102. guid->bytes[0], guid->bytes[1], guid->bytes[2],
  103. guid->bytes[3], guid->bytes[4], guid->bytes[5],
  104. guid->bytes[6], guid->bytes[7], ibdev->dev->name );
  105. /* Send GetResponse */
  106. mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
  107. if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
  108. DBGC ( mi, "SMA %p could not send NodeDesc GetResponse: %s\n",
  109. mi, strerror ( rc ) );
  110. return;
  111. }
  112. }
  113. /**
  114. * GUID information
  115. *
  116. * @v ibdev Infiniband device
  117. * @v mi Management interface
  118. * @v mad Received MAD
  119. * @v av Source address vector
  120. */
  121. static void ib_sma_guid_info ( struct ib_device *ibdev,
  122. struct ib_mad_interface *mi,
  123. union ib_mad *mad,
  124. struct ib_address_vector *av ) {
  125. struct ib_guid_info *guid_info = &mad->smp.smp_data.guid_info;
  126. int rc;
  127. /* Fill in information */
  128. memset ( guid_info, 0, sizeof ( *guid_info ) );
  129. memcpy ( guid_info->guid[0], &ibdev->gid.s.guid,
  130. sizeof ( guid_info->guid[0] ) );
  131. /* Send GetResponse */
  132. mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
  133. if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
  134. DBGC ( mi, "SMA %p could not send GuidInfo GetResponse: %s\n",
  135. mi, strerror ( rc ) );
  136. return;
  137. }
  138. }
  139. /**
  140. * Set port information
  141. *
  142. * @v ibdev Infiniband device
  143. * @v mi Management interface
  144. * @v mad Received MAD
  145. * @ret rc Return status code
  146. */
  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;
  153. int rc;
  154. /* Set parameters */
  155. memcpy ( &ibdev->gid.s.prefix, port_info->gid_prefix,
  156. sizeof ( ibdev->gid.s.prefix ) );
  157. ibdev->lid = ntohs ( port_info->lid );
  158. ibdev->sm_lid = ntohs ( port_info->mastersm_lid );
  159. if ( ( link_width_enabled = port_info->link_width_enabled ) )
  160. ibdev->link_width_enabled = link_width_enabled;
  161. if ( ( link_speed_enabled =
  162. ( port_info->link_speed_active__link_speed_enabled & 0xf ) ) )
  163. ibdev->link_speed_enabled = link_speed_enabled;
  164. ibdev->sm_sl = ( port_info->neighbour_mtu__mastersm_sl & 0xf );
  165. DBGC ( mi, "SMA %p set LID %d SMLID %d link width %d speed %d\n",
  166. mi, ibdev->lid, ibdev->sm_lid, ibdev->link_width_enabled,
  167. ibdev->link_speed_enabled );
  168. /* Update parameters on device */
  169. if ( ( rc = ib_set_port_info ( ibdev, mad ) ) != 0 ) {
  170. DBGC ( mi, "SMA %p could not set port information: %s\n",
  171. mi, strerror ( rc ) );
  172. return rc;
  173. }
  174. return 0;
  175. }
  176. /**
  177. * Port information
  178. *
  179. * @v ibdev Infiniband device
  180. * @v mi Management interface
  181. * @v mad Received MAD
  182. * @v av Source address vector
  183. */
  184. static void ib_sma_port_info ( struct ib_device *ibdev,
  185. struct ib_mad_interface *mi,
  186. union ib_mad *mad,
  187. struct ib_address_vector *av ) {
  188. struct ib_port_info *port_info = &mad->smp.smp_data.port_info;
  189. int rc;
  190. /* Set parameters if applicable */
  191. if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
  192. if ( ( rc = ib_sma_set_port_info ( ibdev, mi, mad ) ) != 0 ) {
  193. mad->hdr.status =
  194. htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
  195. /* Fall through to generate GetResponse */
  196. }
  197. }
  198. /* Fill in information */
  199. memset ( port_info, 0, sizeof ( *port_info ) );
  200. memcpy ( port_info->gid_prefix, &ibdev->gid.s.prefix,
  201. sizeof ( port_info->gid_prefix ) );
  202. port_info->lid = ntohs ( ibdev->lid );
  203. port_info->mastersm_lid = ntohs ( ibdev->sm_lid );
  204. port_info->local_port_num = ibdev->port;
  205. port_info->link_width_enabled = ibdev->link_width_enabled;
  206. port_info->link_width_supported = ibdev->link_width_supported;
  207. port_info->link_width_active = ibdev->link_width_active;
  208. port_info->link_speed_supported__port_state =
  209. ( ( ibdev->link_speed_supported << 4 ) | ibdev->port_state );
  210. port_info->port_phys_state__link_down_def_state =
  211. ( ( IB_PORT_PHYS_STATE_POLLING << 4 ) |
  212. IB_PORT_PHYS_STATE_POLLING );
  213. port_info->link_speed_active__link_speed_enabled =
  214. ( ( ibdev->link_speed_active << 4 ) |
  215. ibdev->link_speed_enabled );
  216. port_info->neighbour_mtu__mastersm_sl =
  217. ( ( IB_MTU_2048 << 4 ) | ibdev->sm_sl );
  218. port_info->vl_cap__init_type = ( IB_VL_0 << 4 );
  219. port_info->init_type_reply__mtu_cap = IB_MTU_2048;
  220. port_info->operational_vls__enforcement = ( IB_VL_0 << 4 );
  221. port_info->guid_cap = 1;
  222. /* Send GetResponse */
  223. mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
  224. if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
  225. DBGC ( mi, "SMA %p could not send PortInfo GetResponse: %s\n",
  226. mi, strerror ( rc ) );
  227. return;
  228. }
  229. }
  230. /**
  231. * Set partition key table
  232. *
  233. * @v ibdev Infiniband device
  234. * @v mi Management interface
  235. * @v mad Received MAD
  236. * @ret rc Return status code
  237. */
  238. static int ib_sma_set_pkey_table ( struct ib_device *ibdev,
  239. struct ib_mad_interface *mi,
  240. union ib_mad *mad ) {
  241. struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
  242. int rc;
  243. /* Set parameters */
  244. ibdev->pkey = ntohs ( pkey_table->pkey[0] );
  245. DBGC ( mi, "SMA %p set pkey %04x\n", mi, ibdev->pkey );
  246. /* Update parameters on device */
  247. if ( ( rc = ib_set_pkey_table ( ibdev, mad ) ) != 0 ) {
  248. DBGC ( mi, "SMA %p could not set pkey table: %s\n",
  249. mi, strerror ( rc ) );
  250. return rc;
  251. }
  252. return 0;
  253. }
  254. /**
  255. * Partition key table
  256. *
  257. * @v ibdev Infiniband device
  258. * @v mi Management interface
  259. * @v mad Received MAD
  260. * @v av Source address vector
  261. */
  262. static void ib_sma_pkey_table ( struct ib_device *ibdev,
  263. struct ib_mad_interface *mi,
  264. union ib_mad *mad,
  265. struct ib_address_vector *av ) {
  266. struct ib_pkey_table *pkey_table = &mad->smp.smp_data.pkey_table;
  267. int rc;
  268. /* Set parameters, if applicable */
  269. if ( mad->hdr.method == IB_MGMT_METHOD_SET ) {
  270. if ( ( rc = ib_sma_set_pkey_table ( ibdev, mi, mad ) ) != 0 ) {
  271. mad->hdr.status =
  272. htons ( IB_MGMT_STATUS_UNSUPPORTED_METHOD_ATTR );
  273. /* Fall through to generate GetResponse */
  274. }
  275. }
  276. /* Fill in information */
  277. mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
  278. memset ( pkey_table, 0, sizeof ( *pkey_table ) );
  279. pkey_table->pkey[0] = htons ( ibdev->pkey );
  280. /* Send GetResponse */
  281. mad->hdr.method = IB_MGMT_METHOD_GET_RESP;
  282. if ( ( rc = ib_mi_send ( ibdev, mi, mad, av ) ) != 0 ) {
  283. DBGC ( mi, "SMA %p could not send PKeyTable GetResponse: %s\n",
  284. mi, strerror ( rc ) );
  285. return;
  286. }
  287. }
  288. /** Subnet management agent */
  289. struct ib_mad_agent ib_sma_agent[] __ib_mad_agent = {
  290. {
  291. .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
  292. .class_version = IB_SMP_CLASS_VERSION,
  293. .attr_id = htons ( IB_SMP_ATTR_NODE_INFO ),
  294. .handle = ib_sma_node_info,
  295. },
  296. {
  297. .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
  298. .class_version = IB_SMP_CLASS_VERSION,
  299. .attr_id = htons ( IB_SMP_ATTR_NODE_DESC ),
  300. .handle = ib_sma_node_desc,
  301. },
  302. {
  303. .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
  304. .class_version = IB_SMP_CLASS_VERSION,
  305. .attr_id = htons ( IB_SMP_ATTR_GUID_INFO ),
  306. .handle = ib_sma_guid_info,
  307. },
  308. {
  309. .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
  310. .class_version = IB_SMP_CLASS_VERSION,
  311. .attr_id = htons ( IB_SMP_ATTR_PORT_INFO ),
  312. .handle = ib_sma_port_info,
  313. },
  314. {
  315. .mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED,
  316. .class_version = IB_SMP_CLASS_VERSION,
  317. .attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE ),
  318. .handle = ib_sma_pkey_table,
  319. },
  320. };
  321. /**
  322. * Create subnet management agent and interface
  323. *
  324. * @v ibdev Infiniband device
  325. * @v mi Management interface
  326. * @ret rc Return status code
  327. */
  328. int ib_create_sma ( struct ib_device *ibdev, struct ib_mad_interface *mi ) {
  329. /* Nothing to do */
  330. DBGC ( ibdev, "IBDEV %s SMA using SMI %p\n", ibdev->name, mi );
  331. return 0;
  332. }
  333. /**
  334. * Destroy subnet management agent and interface
  335. *
  336. * @v ibdev Infiniband device
  337. * @v mi Management interface
  338. */
  339. void ib_destroy_sma ( struct ib_device *ibdev __unused,
  340. struct ib_mad_interface *mi __unused ) {
  341. /* Nothing to do */
  342. }