Browse Source

[Infiniband] Centralise MAD operations

Pull out common code for handling management datagrams from arbel.c
and hermon.c into infiniband.c.

Add port number to struct ib_device.

Add open(), close() and mad() methods to struct ib_device_operations.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
6570203571
4 changed files with 499 additions and 550 deletions
  1. 102
    270
      src/drivers/infiniband/arbel.c
  2. 105
    273
      src/drivers/infiniband/hermon.c
  3. 70
    7
      src/include/gpxe/infiniband.h
  4. 222
    0
      src/net/infiniband.c

+ 102
- 270
src/drivers/infiniband/arbel.c View File

@@ -34,7 +34,6 @@
34 34
 #include <gpxe/iobuf.h>
35 35
 #include <gpxe/netdevice.h>
36 36
 #include <gpxe/infiniband.h>
37
-#include <gpxe/ipoib.h>
38 37
 #include "arbel.h"
39 38
 
40 39
 /**
@@ -349,12 +348,13 @@ arbel_cmd_2rst_qpee ( struct arbel *arbel, unsigned long qpn ) {
349 348
 }
350 349
 
351 350
 static inline int
352
-arbel_cmd_mad_ifc ( struct arbel *arbel, union arbelprm_mad *mad ) {
351
+arbel_cmd_mad_ifc ( struct arbel *arbel, unsigned int port,
352
+		    union arbelprm_mad *mad ) {
353 353
 	return arbel_cmd ( arbel,
354 354
 			   ARBEL_HCR_INOUT_CMD ( ARBEL_HCR_MAD_IFC,
355 355
 						 1, sizeof ( *mad ),
356 356
 						 1, sizeof ( *mad ) ),
357
-			   0x03, mad, PXE_IB_PORT, mad );
357
+			   0x03, mad, port, mad );
358 358
 }
359 359
 
360 360
 static inline int
@@ -776,7 +776,7 @@ static int arbel_create_qp ( struct ib_device *ibdev,
776 776
 	MLX_FILL_1 ( &qpctx, 5,
777 777
 		     qpc_eec_data.usr_page, arbel->limits.reserved_uars );
778 778
 	MLX_FILL_1 ( &qpctx, 10, qpc_eec_data.primary_address_path.port_number,
779
-		     PXE_IB_PORT );
779
+		     ibdev->port );
780 780
 	MLX_FILL_1 ( &qpctx, 27, qpc_eec_data.pd, ARBEL_GLOBAL_PD );
781 781
 	MLX_FILL_1 ( &qpctx, 29, qpc_eec_data.wqe_lkey, arbel->reserved_lkey );
782 782
 	MLX_FILL_1 ( &qpctx, 30, qpc_eec_data.ssc, 1 );
@@ -955,7 +955,7 @@ static int arbel_post_send ( struct ib_device *ibdev,
955 955
 	memset ( &wqe->ud, 0, sizeof ( wqe->ud ) );
956 956
 	MLX_FILL_2 ( &wqe->ud, 0,
957 957
 		     ud_address_vector.pd, ARBEL_GLOBAL_PD,
958
-		     ud_address_vector.port_number, PXE_IB_PORT );
958
+		     ud_address_vector.port_number, ibdev->port );
959 959
 	MLX_FILL_2 ( &wqe->ud, 1,
960 960
 		     ud_address_vector.rlid, av->dlid,
961 961
 		     ud_address_vector.g, av->gid_present );
@@ -1206,6 +1206,57 @@ static void arbel_poll_cq ( struct ib_device *ibdev,
1206 1206
 	}
1207 1207
 }
1208 1208
 
1209
+/***************************************************************************
1210
+ *
1211
+ * Infiniband link-layer operations
1212
+ *
1213
+ ***************************************************************************
1214
+ */
1215
+
1216
+/**
1217
+ * Initialise Infiniband link
1218
+ *
1219
+ * @v ibdev		Infiniband device
1220
+ * @ret rc		Return status code
1221
+ */
1222
+static int arbel_open ( struct ib_device *ibdev ) {
1223
+	struct arbel *arbel = ibdev->dev_priv;
1224
+	struct arbelprm_init_ib init_ib;
1225
+	int rc;
1226
+
1227
+	memset ( &init_ib, 0, sizeof ( init_ib ) );
1228
+	MLX_FILL_3 ( &init_ib, 0,
1229
+		     mtu_cap, ARBEL_MTU_2048,
1230
+		     port_width_cap, 3,
1231
+		     vl_cap, 1 );
1232
+	MLX_FILL_1 ( &init_ib, 1, max_gid, 1 );
1233
+	MLX_FILL_1 ( &init_ib, 2, max_pkey, 64 );
1234
+	if ( ( rc = arbel_cmd_init_ib ( arbel, ibdev->port,
1235
+					&init_ib ) ) != 0 ) {
1236
+		DBGC ( arbel, "Arbel %p could not intialise IB: %s\n",
1237
+		       arbel, strerror ( rc ) );
1238
+		return rc;
1239
+	}
1240
+
1241
+	return 0;
1242
+}
1243
+
1244
+/**
1245
+ * Close Infiniband link
1246
+ *
1247
+ * @v ibdev		Infiniband device
1248
+ */
1249
+static void arbel_close ( struct ib_device *ibdev ) {
1250
+	struct arbel *arbel = ibdev->dev_priv;
1251
+	int rc;
1252
+
1253
+	if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) {
1254
+		DBGC ( arbel, "Arbel %p could not close IB: %s\n",
1255
+		       arbel, strerror ( rc ) );
1256
+		/* Nothing we can do about this */
1257
+	}
1258
+}
1259
+
1209 1260
 /***************************************************************************
1210 1261
  *
1211 1262
  * Multicast group operations
@@ -1302,215 +1353,67 @@ static void arbel_mcast_detach ( struct ib_device *ibdev,
1302 1353
 	}
1303 1354
 }
1304 1355
 
1305
-/** Arbel Infiniband operations */
1306
-static struct ib_device_operations arbel_ib_operations = {
1307
-	.create_cq	= arbel_create_cq,
1308
-	.destroy_cq	= arbel_destroy_cq,
1309
-	.create_qp	= arbel_create_qp,
1310
-	.destroy_qp	= arbel_destroy_qp,
1311
-	.post_send	= arbel_post_send,
1312
-	.post_recv	= arbel_post_recv,
1313
-	.poll_cq	= arbel_poll_cq,
1314
-	.mcast_attach	= arbel_mcast_attach,
1315
-	.mcast_detach	= arbel_mcast_detach,
1316
-};
1317
-
1318 1356
 /***************************************************************************
1319 1357
  *
1320
- * MAD IFC operations
1358
+ * MAD operations
1321 1359
  *
1322 1360
  ***************************************************************************
1323 1361
  */
1324 1362
 
1325
-static int arbel_mad_ifc ( struct arbel *arbel,
1326
-			   union arbelprm_mad *mad ) {
1327
-	struct ib_mad_hdr *hdr = &mad->mad.mad_hdr;
1328
-	int rc;
1329
-
1330
-	hdr->base_version = IB_MGMT_BASE_VERSION;
1331
-	if ( ( rc = arbel_cmd_mad_ifc ( arbel, mad ) ) != 0 ) {
1332
-		DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n",
1333
-		       arbel, strerror ( rc ) );
1334
-		return rc;
1335
-	}
1336
-	if ( hdr->status != 0 ) {
1337
-		DBGC ( arbel, "Arbel %p MAD IFC status %04x\n",
1338
-		       arbel, ntohs ( hdr->status ) );
1339
-		return -EIO;
1340
-	}
1341
-	return 0;
1342
-}
1343
-
1344
-static int arbel_get_port_info ( struct arbel *arbel,
1345
-				 struct ib_mad_port_info *port_info ) {
1346
-	union arbelprm_mad mad;
1347
-	struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
1348
-	int rc;
1349
-
1350
-	memset ( &mad, 0, sizeof ( mad ) );
1351
-	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
1352
-	hdr->class_version = 1;
1353
-	hdr->method = IB_MGMT_METHOD_GET;
1354
-	hdr->attr_id = htons ( IB_SMP_ATTR_PORT_INFO );
1355
-	hdr->attr_mod = htonl ( PXE_IB_PORT );
1356
-	if ( ( rc = arbel_mad_ifc ( arbel, &mad ) ) != 0 ) {
1357
-		DBGC ( arbel, "Arbel %p could not get port info: %s\n",
1358
-		       arbel, strerror ( rc ) );
1359
-		return rc;
1360
-	}
1361
-	memcpy ( port_info, &mad.mad.port_info, sizeof ( *port_info ) );
1362
-	return 0;
1363
-}
1364
-
1365
-static int arbel_get_guid_info ( struct arbel *arbel,
1366
-				 struct ib_mad_guid_info *guid_info ) {
1367
-	union arbelprm_mad mad;
1368
-	struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
1369
-	int rc;
1370
-
1371
-	memset ( &mad, 0, sizeof ( mad ) );
1372
-	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
1373
-	hdr->class_version = 1;
1374
-	hdr->method = IB_MGMT_METHOD_GET;
1375
-	hdr->attr_id = htons ( IB_SMP_ATTR_GUID_INFO );
1376
-	if ( ( rc = arbel_mad_ifc ( arbel, &mad ) ) != 0 ) {
1377
-		DBGC ( arbel, "Arbel %p could not get GUID info: %s\n",
1378
-		       arbel, strerror ( rc ) );
1379
-		return rc;
1380
-	}
1381
-	memcpy ( guid_info, &mad.mad.guid_info, sizeof ( *guid_info ) );
1382
-	return 0;
1383
-}
1384
-
1385
-static int arbel_get_pkey_table ( struct arbel *arbel,
1386
-				  struct ib_mad_pkey_table *pkey_table ) {
1387
-	union arbelprm_mad mad;
1388
-	struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
1389
-	int rc;
1390
-
1391
-	memset ( &mad, 0, sizeof ( mad ) );
1392
-	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
1393
-	hdr->class_version = 1;
1394
-	hdr->method = IB_MGMT_METHOD_GET;
1395
-	hdr->attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE );
1396
-	if ( ( rc = arbel_mad_ifc ( arbel, &mad ) ) != 0 ) {
1397
-		DBGC ( arbel, "Arbel %p could not get pkey table: %s\n",
1398
-		       arbel, strerror ( rc ) );
1399
-		return rc;
1400
-	}
1401
-	memcpy ( pkey_table, &mad.mad.pkey_table, sizeof ( *pkey_table ) );
1402
-	return 0;
1403
-}
1404
-
1405
-static int arbel_get_port_gid ( struct arbel *arbel,
1406
-				struct ib_gid *port_gid ) {
1407
-	union {
1408
-		/* This union exists just to save stack space */
1409
-		struct ib_mad_port_info port_info;
1410
-		struct ib_mad_guid_info guid_info;
1411
-	} u;
1412
-	int rc;
1413
-
1414
-	/* Port info gives us the first half of the port GID */
1415
-	if ( ( rc = arbel_get_port_info ( arbel, &u.port_info ) ) != 0 )
1416
-		return rc;
1417
-	memcpy ( &port_gid->u.bytes[0], u.port_info.gid_prefix, 8 );
1418
-	
1419
-	/* GUID info gives us the second half of the port GID */
1420
-	if ( ( rc = arbel_get_guid_info ( arbel, &u.guid_info ) ) != 0 )
1421
-		return rc;
1422
-	memcpy ( &port_gid->u.bytes[8], u.guid_info.gid_local, 8 );
1423
-
1424
-	return 0;
1425
-}
1426
-
1427
-static int arbel_get_sm_lid ( struct arbel *arbel,
1428
-			      unsigned long *sm_lid ) {
1429
-	struct ib_mad_port_info port_info;
1430
-	int rc;
1431
-
1432
-	if ( ( rc = arbel_get_port_info ( arbel, &port_info ) ) != 0 )
1433
-		return rc;
1434
-	*sm_lid = ntohs ( port_info.mastersm_lid );
1435
-	return 0;
1436
-}
1437
-
1438
-static int arbel_get_pkey ( struct arbel *arbel, unsigned int *pkey ) {
1439
-	struct ib_mad_pkey_table pkey_table;
1440
-	int rc;
1441
-
1442
-	if ( ( rc = arbel_get_pkey_table ( arbel, &pkey_table ) ) != 0 )
1443
-		return rc;
1444
-	*pkey = ntohs ( pkey_table.pkey[0][0] );
1445
-	return 0;
1446
-}
1447
-
1448
-/**
1449
- * Wait for link up
1450
- *
1451
- * @v arbel		Arbel device
1452
- * @ret rc		Return status code
1453
- *
1454
- * This function shouldn't really exist.  Unfortunately, IB links take
1455
- * a long time to come up, and we can't get various key parameters
1456
- * e.g. our own IPoIB MAC address without information from the subnet
1457
- * manager).  We should eventually make link-up an asynchronous event.
1458
- */
1459
-static int arbel_wait_for_link ( struct arbel *arbel ) {
1460
-	struct ib_mad_port_info port_info;
1461
-	unsigned int retries;
1462
-	int rc;
1463
-
1464
-	printf ( "Waiting for Infiniband link-up..." );
1465
-	for ( retries = 20 ; retries ; retries-- ) {
1466
-		if ( ( rc = arbel_get_port_info ( arbel, &port_info ) ) != 0 )
1467
-			continue;
1468
-		if ( ( ( port_info.port_state__link_speed_supported ) & 0xf )
1469
-		     == 4 ) {
1470
-			printf ( "ok\n" );
1471
-			return 0;
1472
-		}
1473
-		printf ( "." );
1474
-		sleep ( 1 );
1475
-	}
1476
-	printf ( "failed\n" );
1477
-	return -ENODEV;
1478
-};
1479
-
1480 1363
 /**
1481
- * Get MAD parameters
1364
+ * Issue management datagram
1482 1365
  *
1483
- * @v arbel		Arbel device
1366
+ * @v ibdev		Infiniband device
1367
+ * @v mad		Management datagram
1368
+ * @v len		Length of management datagram
1484 1369
  * @ret rc		Return status code
1485 1370
  */
1486
-static int arbel_get_mad_params ( struct ib_device *ibdev ) {
1371
+static int arbel_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
1372
+		       size_t len ) {
1487 1373
 	struct arbel *arbel = ibdev->dev_priv;
1374
+	union arbelprm_mad mad_ifc;
1488 1375
 	int rc;
1489 1376
 
1490
-	/* Get subnet manager LID */
1491
-	if ( ( rc = arbel_get_sm_lid ( arbel, &ibdev->sm_lid ) ) != 0 ) {
1492
-		DBGC ( arbel, "Arbel %p could not determine subnet manager "
1493
-		       "LID: %s\n", arbel, strerror ( rc ) );
1494
-		return rc;
1495
-	}
1377
+	/* Copy in request packet */
1378
+	memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
1379
+	assert ( len <= sizeof ( mad_ifc.mad ) );
1380
+	memcpy ( &mad_ifc.mad, mad, len );
1496 1381
 
1497
-	/* Get port GID */
1498
-	if ( ( rc = arbel_get_port_gid ( arbel, &ibdev->port_gid ) ) != 0 ) {
1499
-		DBGC ( arbel, "Arbel %p could not determine port GID: %s\n",
1382
+	/* Issue MAD */
1383
+	if ( ( rc = arbel_cmd_mad_ifc ( arbel, ibdev->port,
1384
+					&mad_ifc ) ) != 0 ) {
1385
+		DBGC ( arbel, "Arbel %p could not issue MAD IFC: %s\n",
1500 1386
 		       arbel, strerror ( rc ) );
1501 1387
 		return rc;
1502 1388
 	}
1503 1389
 
1504
-	/* Get partition key */
1505
-	if ( ( rc = arbel_get_pkey ( arbel, &ibdev->pkey ) ) != 0 ) {
1506
-		DBGC ( arbel, "Arbel %p could not determine partition key: "
1507
-		       "%s\n", arbel, strerror ( rc ) );
1508
-		return rc;
1509
-	}
1390
+	/* Copy out reply packet */
1391
+	memcpy ( mad, &mad_ifc.mad, len );
1510 1392
 
1393
+	if ( mad->status != 0 ) {
1394
+		DBGC ( arbel, "Arbel %p MAD IFC status %04x\n",
1395
+		       arbel, ntohs ( mad->status ) );
1396
+		return -EIO;
1397
+	}
1511 1398
 	return 0;
1512 1399
 }
1513 1400
 
1401
+/** Arbel Infiniband operations */
1402
+static struct ib_device_operations arbel_ib_operations = {
1403
+	.create_cq	= arbel_create_cq,
1404
+	.destroy_cq	= arbel_destroy_cq,
1405
+	.create_qp	= arbel_create_qp,
1406
+	.destroy_qp	= arbel_destroy_qp,
1407
+	.post_send	= arbel_post_send,
1408
+	.post_recv	= arbel_post_recv,
1409
+	.poll_cq	= arbel_poll_cq,
1410
+	.open		= arbel_open,
1411
+	.close		= arbel_close,
1412
+	.mcast_attach	= arbel_mcast_attach,
1413
+	.mcast_detach	= arbel_mcast_detach,
1414
+	.mad		= arbel_mad,
1415
+};
1416
+
1514 1417
 /***************************************************************************
1515 1418
  *
1516 1419
  * Firmware control
@@ -1882,55 +1785,6 @@ static void arbel_free_icm ( struct arbel *arbel ) {
1882 1785
 	arbel->icm = UNULL;
1883 1786
 }
1884 1787
 
1885
-/***************************************************************************
1886
- *
1887
- * Infiniband link-layer operations
1888
- *
1889
- ***************************************************************************
1890
- */
1891
-
1892
-/**
1893
- * Initialise Infiniband link
1894
- *
1895
- * @v arbel		Arbel device
1896
- * @ret rc		Return status code
1897
- */
1898
-static int arbel_init_ib ( struct arbel *arbel ) {
1899
-	struct arbelprm_init_ib init_ib;
1900
-	int rc;
1901
-
1902
-	memset ( &init_ib, 0, sizeof ( init_ib ) );
1903
-	MLX_FILL_3 ( &init_ib, 0,
1904
-		     mtu_cap, ARBEL_MTU_2048,
1905
-		     port_width_cap, 3,
1906
-		     vl_cap, 1 );
1907
-	MLX_FILL_1 ( &init_ib, 1, max_gid, 1 );
1908
-	MLX_FILL_1 ( &init_ib, 2, max_pkey, 64 );
1909
-	if ( ( rc = arbel_cmd_init_ib ( arbel, PXE_IB_PORT,
1910
-					&init_ib ) ) != 0 ) {
1911
-		DBGC ( arbel, "Arbel %p could not intialise IB: %s\n",
1912
-		       arbel, strerror ( rc ) );
1913
-		return rc;
1914
-	}
1915
-
1916
-	return 0;
1917
-}
1918
-
1919
-/**
1920
- * Close Infiniband link
1921
- *
1922
- * @v arbel		Arbel device
1923
- */
1924
-static void arbel_close_ib ( struct arbel *arbel ) {
1925
-	int rc;
1926
-
1927
-	if ( ( rc = arbel_cmd_close_ib ( arbel, PXE_IB_PORT ) ) != 0 ) {
1928
-		DBGC ( arbel, "Arbel %p could not close IB: %s\n",
1929
-		       arbel, strerror ( rc ) );
1930
-		/* Nothing we can do about this */
1931
-	}
1932
-}
1933
-
1934 1788
 /***************************************************************************
1935 1789
  *
1936 1790
  * PCI interface
@@ -1997,6 +1851,7 @@ static int arbel_probe ( struct pci_device *pci,
1997 1851
 	ibdev->op = &arbel_ib_operations;
1998 1852
 	pci_set_drvdata ( pci, ibdev );
1999 1853
 	ibdev->dev = &pci->dev;
1854
+	ibdev->port = PXE_IB_PORT;
2000 1855
 	arbel = ibdev->dev_priv;
2001 1856
 	memset ( arbel, 0, sizeof ( *arbel ) );
2002 1857
 
@@ -2047,38 +1902,16 @@ static int arbel_probe ( struct pci_device *pci,
2047 1902
 	if ( ( rc = arbel_setup_mpt ( arbel ) ) != 0 )
2048 1903
 		goto err_setup_mpt;
2049 1904
 
2050
-	/* Bring up IB layer */
2051
-	if ( ( rc = arbel_init_ib ( arbel ) ) != 0 )
2052
-		goto err_init_ib;
2053
-
2054
-	/* Wait for link */
2055
-	if ( ( rc = arbel_wait_for_link ( arbel ) ) != 0 )
2056
-		goto err_wait_for_link;
2057
-
2058
-	/* Get MAD parameters */
2059
-	if ( ( rc = arbel_get_mad_params ( ibdev ) ) != 0 )
2060
-		goto err_get_mad_params;
2061
-
2062
-	DBGC ( arbel, "Arbel %p port GID is %08lx:%08lx:%08lx:%08lx\n", arbel,
2063
-	       htonl ( ibdev->port_gid.u.dwords[0] ),
2064
-	       htonl ( ibdev->port_gid.u.dwords[1] ),
2065
-	       htonl ( ibdev->port_gid.u.dwords[2] ),
2066
-	       htonl ( ibdev->port_gid.u.dwords[3] ) );
2067
-
2068
-	/* Add IPoIB device */
2069
-	if ( ( rc = ipoib_probe ( ibdev ) ) != 0 ) {
2070
-		DBGC ( arbel, "Arbel %p could not add IPoIB device: %s\n",
1905
+	/* Register Infiniband device */
1906
+	if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
1907
+		DBGC ( arbel, "Arbel %p could not register IB device: %s\n",
2071 1908
 		       arbel, strerror ( rc ) );
2072
-		goto err_ipoib_probe;
1909
+		goto err_register_ibdev;
2073 1910
 	}
2074 1911
 
2075 1912
 	return 0;
2076 1913
 
2077
- err_ipoib_probe:
2078
- err_get_mad_params:
2079
- err_wait_for_link:
2080
-	arbel_close_ib ( arbel );
2081
- err_init_ib:
1914
+ err_register_ibdev:
2082 1915
  err_setup_mpt:
2083 1916
 	arbel_cmd_close_hca ( arbel );
2084 1917
  err_init_hca:
@@ -2105,8 +1938,7 @@ static void arbel_remove ( struct pci_device *pci ) {
2105 1938
 	struct ib_device *ibdev = pci_get_drvdata ( pci );
2106 1939
 	struct arbel *arbel = ibdev->dev_priv;
2107 1940
 
2108
-	ipoib_remove ( ibdev );
2109
-	arbel_close_ib ( arbel );
1941
+	unregister_ibdev ( ibdev );
2110 1942
 	arbel_cmd_close_hca ( arbel );
2111 1943
 	arbel_free_icm ( arbel );
2112 1944
 	arbel_stop_firmware ( arbel );

+ 105
- 273
src/drivers/infiniband/hermon.c View File

@@ -32,7 +32,6 @@
32 32
 #include <gpxe/iobuf.h>
33 33
 #include <gpxe/netdevice.h>
34 34
 #include <gpxe/infiniband.h>
35
-#include <gpxe/ipoib.h>
36 35
 #include "hermon.h"
37 36
 
38 37
 /**
@@ -390,12 +389,13 @@ hermon_cmd_2rst_qp ( struct hermon *hermon, unsigned long qpn ) {
390 389
 }
391 390
 
392 391
 static inline int
393
-hermon_cmd_mad_ifc ( struct hermon *hermon, union hermonprm_mad *mad ) {
392
+hermon_cmd_mad_ifc ( struct hermon *hermon, unsigned int port,
393
+		     union hermonprm_mad *mad ) {
394 394
 	return hermon_cmd ( hermon,
395 395
 			    HERMON_HCR_INOUT_CMD ( HERMON_HCR_MAD_IFC,
396 396
 						   1, sizeof ( *mad ),
397 397
 						   1, sizeof ( *mad ) ),
398
-			    0x03, mad, PXE_IB_PORT, mad );
398
+			    0x03, mad, port, mad );
399 399
 }
400 400
 
401 401
 static inline int
@@ -785,7 +785,7 @@ static int hermon_create_qp ( struct ib_device *ibdev,
785 785
 		goto err_alloc_mtt;
786 786
 	}
787 787
 
788
-	/* Hand queue over to hardware */
788
+	/* Transition queue to INIT state */
789 789
 	memset ( &qpctx, 0, sizeof ( qpctx ) );
790 790
 	MLX_FILL_2 ( &qpctx, 2,
791 791
 		     qpc_eec_data.pm_state, 0x03 /* Always 0x03 for UD */,
@@ -817,6 +817,7 @@ static int hermon_create_qp ( struct ib_device *ibdev,
817 817
 		goto err_rst2init_qp;
818 818
 	}
819 819
 
820
+	/* Transition queue to RTR state */
820 821
 	memset ( &qpctx, 0, sizeof ( qpctx ) );
821 822
 	MLX_FILL_2 ( &qpctx, 4,
822 823
 		     qpc_eec_data.mtu, HERMON_MTU_2048,
@@ -824,7 +825,7 @@ static int hermon_create_qp ( struct ib_device *ibdev,
824 825
 	MLX_FILL_1 ( &qpctx, 16,
825 826
 		     qpc_eec_data.primary_address_path.sched_queue,
826 827
 		     ( 0x83 /* default policy */ |
827
-		       ( ( PXE_IB_PORT - 1 ) << 6 ) ) );
828
+		       ( ( ibdev->port - 1 ) << 6 ) ) );
828 829
 	if ( ( rc = hermon_cmd_init2rtr_qp ( hermon, qp->qpn,
829 830
 					     &qpctx ) ) != 0 ) {
830 831
 		DBGC ( hermon, "Hermon %p INIT2RTR_QP failed: %s\n",
@@ -949,7 +950,7 @@ static int hermon_post_send ( struct ib_device *ibdev,
949 950
 	MLX_FILL_1 ( &wqe->ctrl, 2, c, 0x03 /* generate completion */ );
950 951
 	MLX_FILL_2 ( &wqe->ud, 0,
951 952
 		     ud_address_vector.pd, HERMON_GLOBAL_PD,
952
-		     ud_address_vector.port_number, PXE_IB_PORT );
953
+		     ud_address_vector.port_number, ibdev->port );
953 954
 	MLX_FILL_2 ( &wqe->ud, 1,
954 955
 		     ud_address_vector.rlid, av->dlid,
955 956
 		     ud_address_vector.g, av->gid_present );
@@ -1162,6 +1163,58 @@ static void hermon_poll_cq ( struct ib_device *ibdev,
1162 1163
 	}
1163 1164
 }
1164 1165
 
1166
+/***************************************************************************
1167
+ *
1168
+ * Infiniband link-layer operations
1169
+ *
1170
+ ***************************************************************************
1171
+ */
1172
+
1173
+/**
1174
+ * Initialise Infiniband link
1175
+ *
1176
+ * @v ibdev		Infiniband device
1177
+ * @ret rc		Return status code
1178
+ */
1179
+static int hermon_open ( struct ib_device *ibdev ) {
1180
+	struct hermon *hermon = ibdev->dev_priv;
1181
+	struct hermonprm_init_port init_port;
1182
+	int rc;
1183
+
1184
+	memset ( &init_port, 0, sizeof ( init_port ) );
1185
+	MLX_FILL_2 ( &init_port, 0,
1186
+		     port_width_cap, 3,
1187
+		     vl_cap, 1 );
1188
+	MLX_FILL_2 ( &init_port, 1,
1189
+		     mtu, HERMON_MTU_2048,
1190
+		     max_gid, 1 );
1191
+	MLX_FILL_1 ( &init_port, 2, max_pkey, 64 );
1192
+	if ( ( rc = hermon_cmd_init_port ( hermon, ibdev->port,
1193
+					   &init_port ) ) != 0 ) {
1194
+		DBGC ( hermon, "Hermon %p could not intialise port: %s\n",
1195
+		       hermon, strerror ( rc ) );
1196
+		return rc;
1197
+	}
1198
+
1199
+	return 0;
1200
+}
1201
+
1202
+/**
1203
+ * Close Infiniband link
1204
+ *
1205
+ * @v ibdev		Infiniband device
1206
+ */
1207
+static void hermon_close ( struct ib_device *ibdev ) {
1208
+	struct hermon *hermon = ibdev->dev_priv;
1209
+	int rc;
1210
+
1211
+	if ( ( rc = hermon_cmd_close_port ( hermon, ibdev->port ) ) != 0 ) {
1212
+		DBGC ( hermon, "Hermon %p could not close port: %s\n",
1213
+		       hermon, strerror ( rc ) );
1214
+		/* Nothing we can do about this */
1215
+	}
1216
+}
1217
+
1165 1218
 /***************************************************************************
1166 1219
  *
1167 1220
  * Multicast group operations
@@ -1257,216 +1310,67 @@ static void hermon_mcast_detach ( struct ib_device *ibdev,
1257 1310
 	}
1258 1311
 }
1259 1312
 
1260
-/** Hermon Infiniband operations */
1261
-static struct ib_device_operations hermon_ib_operations = {
1262
-	.create_cq	= hermon_create_cq,
1263
-	.destroy_cq	= hermon_destroy_cq,
1264
-	.create_qp	= hermon_create_qp,
1265
-	.destroy_qp	= hermon_destroy_qp,
1266
-	.post_send	= hermon_post_send,
1267
-	.post_recv	= hermon_post_recv,
1268
-	.poll_cq	= hermon_poll_cq,
1269
-	.mcast_attach	= hermon_mcast_attach,
1270
-	.mcast_detach	= hermon_mcast_detach,
1271
-};
1272
-
1273 1313
 /***************************************************************************
1274 1314
  *
1275
- * MAD IFC operations
1315
+ * MAD operations
1276 1316
  *
1277 1317
  ***************************************************************************
1278 1318
  */
1279 1319
 
1280
-static int hermon_mad_ifc ( struct hermon *hermon,
1281
-			    union hermonprm_mad *mad ) {
1282
-	struct ib_mad_hdr *hdr = &mad->mad.mad_hdr;
1283
-	int rc;
1284
-
1285
-	hdr->base_version = IB_MGMT_BASE_VERSION;
1286
-	if ( ( rc = hermon_cmd_mad_ifc ( hermon, mad ) ) != 0 ) {
1287
-		DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
1288
-		       hermon, strerror ( rc ) );
1289
-		return rc;
1290
-	}
1291
-	if ( hdr->status != 0 ) {
1292
-		DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
1293
-		       hermon, ntohs ( hdr->status ) );
1294
-		return -EIO;
1295
-	}
1296
-	return 0;
1297
-}
1298
-
1299
-static int hermon_get_port_info ( struct hermon *hermon,
1300
-				  struct ib_mad_port_info *port_info ) {
1301
-	union hermonprm_mad mad;
1302
-	struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
1303
-	int rc;
1304
-
1305
-	memset ( &mad, 0, sizeof ( mad ) );
1306
-	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
1307
-	hdr->class_version = 1;
1308
-	hdr->method = IB_MGMT_METHOD_GET;
1309
-	hdr->attr_id = htons ( IB_SMP_ATTR_PORT_INFO );
1310
-	hdr->attr_mod = htonl ( PXE_IB_PORT );
1311
-	if ( ( rc = hermon_mad_ifc ( hermon, &mad ) ) != 0 ) {
1312
-		DBGC ( hermon, "Hermon %p could not get port info: %s\n",
1313
-		       hermon, strerror ( rc ) );
1314
-		return rc;
1315
-	}
1316
-	memcpy ( port_info, &mad.mad.port_info, sizeof ( *port_info ) );
1317
-	return 0;
1318
-}
1319
-
1320
-static int hermon_get_guid_info ( struct hermon *hermon,
1321
-				  struct ib_mad_guid_info *guid_info ) {
1322
-	union hermonprm_mad mad;
1323
-	struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
1324
-	int rc;
1325
-
1326
-	memset ( &mad, 0, sizeof ( mad ) );
1327
-	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
1328
-	hdr->class_version = 1;
1329
-	hdr->method = IB_MGMT_METHOD_GET;
1330
-	hdr->attr_id = htons ( IB_SMP_ATTR_GUID_INFO );
1331
-	if ( ( rc = hermon_mad_ifc ( hermon, &mad ) ) != 0 ) {
1332
-		DBGC ( hermon, "Hermon %p could not get GUID info: %s\n",
1333
-		       hermon, strerror ( rc ) );
1334
-		return rc;
1335
-	}
1336
-	memcpy ( guid_info, &mad.mad.guid_info, sizeof ( *guid_info ) );
1337
-	return 0;
1338
-}
1339
-
1340
-static int hermon_get_pkey_table ( struct hermon *hermon,
1341
-				   struct ib_mad_pkey_table *pkey_table ) {
1342
-	union hermonprm_mad mad;
1343
-	struct ib_mad_hdr *hdr = &mad.mad.mad_hdr;
1344
-	int rc;
1345
-
1346
-	memset ( &mad, 0, sizeof ( mad ) );
1347
-	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
1348
-	hdr->class_version = 1;
1349
-	hdr->method = IB_MGMT_METHOD_GET;
1350
-	hdr->attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE );
1351
-	if ( ( rc = hermon_mad_ifc ( hermon, &mad ) ) != 0 ) {
1352
-		DBGC ( hermon, "Hermon %p could not get pkey table: %s\n",
1353
-		       hermon, strerror ( rc ) );
1354
-		return rc;
1355
-	}
1356
-	memcpy ( pkey_table, &mad.mad.pkey_table, sizeof ( *pkey_table ) );
1357
-	return 0;
1358
-}
1359
-
1360
-static int hermon_get_port_gid ( struct hermon *hermon,
1361
-				 struct ib_gid *port_gid ) {
1362
-	union {
1363
-		/* This union exists just to save stack space */
1364
-		struct ib_mad_port_info port_info;
1365
-		struct ib_mad_guid_info guid_info;
1366
-	} u;
1367
-	int rc;
1368
-
1369
-	/* Port info gives us the first half of the port GID */
1370
-	if ( ( rc = hermon_get_port_info ( hermon, &u.port_info ) ) != 0 )
1371
-		return rc;
1372
-	memcpy ( &port_gid->u.bytes[0], u.port_info.gid_prefix, 8 );
1373
-
1374
-	/* GUID info gives us the second half of the port GID */
1375
-	if ( ( rc = hermon_get_guid_info ( hermon, &u.guid_info ) ) != 0 )
1376
-		return rc;
1377
-	memcpy ( &port_gid->u.bytes[8], u.guid_info.gid_local, 8 );
1378
-
1379
-	return 0;
1380
-}
1381
-
1382
-static int hermon_get_sm_lid ( struct hermon *hermon,
1383
-			       unsigned long *sm_lid ) {
1384
-	struct ib_mad_port_info port_info;
1385
-	int rc;
1386
-
1387
-	if ( ( rc = hermon_get_port_info ( hermon, &port_info ) ) != 0 )
1388
-		return rc;
1389
-	*sm_lid = ntohs ( port_info.mastersm_lid );
1390
-	return 0;
1391
-}
1392
-
1393
-static int hermon_get_pkey ( struct hermon *hermon, unsigned int *pkey ) {
1394
-	struct ib_mad_pkey_table pkey_table;
1395
-	int rc;
1396
-
1397
-	if ( ( rc = hermon_get_pkey_table ( hermon, &pkey_table ) ) != 0 )
1398
-		return rc;
1399
-	*pkey = ntohs ( pkey_table.pkey[0][0] );
1400
-	return 0;
1401
-}
1402
-
1403 1320
 /**
1404
- * Wait for link up
1321
+ * Issue management datagram
1405 1322
  *
1406
- * @v hermon		Hermon device
1407
- * @ret rc		Return status code
1408
- *
1409
- * This function shouldn't really exist.  Unfortunately, IB links take
1410
- * a long time to come up, and we can't get various key parameters
1411
- * e.g. our own IPoIB MAC address without information from the subnet
1412
- * manager).  We should eventually make link-up an asynchronous event.
1413
- */
1414
-static int hermon_wait_for_link ( struct hermon *hermon ) {
1415
-	struct ib_mad_port_info port_info;
1416
-	unsigned int retries;
1417
-	int rc;
1418
-
1419
-	printf ( "Waiting for Infiniband link-up..." );
1420
-	for ( retries = 20 ; retries ; retries-- ) {
1421
-		if ( ( rc = hermon_get_port_info ( hermon,
1422
-						   &port_info ) ) != 0 )
1423
-			continue;
1424
-		if ( ( ( port_info.port_state__link_speed_supported ) & 0xf )
1425
-		     == 4 ) {
1426
-			printf ( "ok\n" );
1427
-			return 0;
1428
-		}
1429
-		printf ( "." );
1430
-		sleep ( 1 );
1431
-	}
1432
-	printf ( "failed\n" );
1433
-	return -ENODEV;
1434
-};
1435
-
1436
-/**
1437
- * Get MAD parameters
1438
- *
1439
- * @v hermon		Hermon device
1323
+ * @v ibdev		Infiniband device
1324
+ * @v mad		Management datagram
1325
+ * @v len		Length of management datagram
1440 1326
  * @ret rc		Return status code
1441 1327
  */
1442
-static int hermon_get_mad_params ( struct ib_device *ibdev ) {
1328
+static int hermon_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
1329
+			size_t len ) {
1443 1330
 	struct hermon *hermon = ibdev->dev_priv;
1331
+	union hermonprm_mad mad_ifc;
1444 1332
 	int rc;
1445 1333
 
1446
-	/* Get subnet manager LID */
1447
-	if ( ( rc = hermon_get_sm_lid ( hermon, &ibdev->sm_lid ) ) != 0 ) {
1448
-		DBGC ( hermon, "Hermon %p could not determine subnet manager "
1449
-		       "LID: %s\n", hermon, strerror ( rc ) );
1450
-		return rc;
1451
-	}
1334
+	/* Copy in request packet */
1335
+	memset ( &mad_ifc, 0, sizeof ( mad_ifc ) );
1336
+	assert ( len <= sizeof ( mad_ifc.mad ) );
1337
+	memcpy ( &mad_ifc.mad, mad, len );
1452 1338
 
1453
-	/* Get port GID */
1454
-	if ( ( rc = hermon_get_port_gid ( hermon, &ibdev->port_gid ) ) != 0 ) {
1455
-		DBGC ( hermon, "Hermon %p could not determine port GID: %s\n",
1339
+	/* Issue MAD */
1340
+	if ( ( rc = hermon_cmd_mad_ifc ( hermon, ibdev->port,
1341
+					 &mad_ifc ) ) != 0 ) {
1342
+		DBGC ( hermon, "Hermon %p could not issue MAD IFC: %s\n",
1456 1343
 		       hermon, strerror ( rc ) );
1457 1344
 		return rc;
1458 1345
 	}
1459 1346
 
1460
-	/* Get partition key */
1461
-	if ( ( rc = hermon_get_pkey ( hermon, &ibdev->pkey ) ) != 0 ) {
1462
-		DBGC ( hermon, "Hermon %p could not determine partition key: "
1463
-		       "%s\n", hermon, strerror ( rc ) );
1464
-		return rc;
1465
-	}
1347
+	/* Copy out reply packet */
1348
+	memcpy ( mad, &mad_ifc.mad, len );
1466 1349
 
1350
+	if ( mad->status != 0 ) {
1351
+		DBGC ( hermon, "Hermon %p MAD IFC status %04x\n",
1352
+		       hermon, ntohs ( mad->status ) );
1353
+		return -EIO;
1354
+	}
1467 1355
 	return 0;
1468 1356
 }
1469 1357
 
1358
+/** Hermon Infiniband operations */
1359
+static struct ib_device_operations hermon_ib_operations = {
1360
+	.create_cq	= hermon_create_cq,
1361
+	.destroy_cq	= hermon_destroy_cq,
1362
+	.create_qp	= hermon_create_qp,
1363
+	.destroy_qp	= hermon_destroy_qp,
1364
+	.post_send	= hermon_post_send,
1365
+	.post_recv	= hermon_post_recv,
1366
+	.poll_cq	= hermon_poll_cq,
1367
+	.open		= hermon_open,
1368
+	.close		= hermon_close,
1369
+	.mcast_attach	= hermon_mcast_attach,
1370
+	.mcast_detach	= hermon_mcast_detach,
1371
+	.mad		= hermon_mad,
1372
+};
1373
+
1470 1374
 /***************************************************************************
1471 1375
  *
1472 1376
  * Firmware control
@@ -1914,56 +1818,6 @@ static void hermon_free_icm ( struct hermon *hermon ) {
1914 1818
 	hermon->icm = UNULL;
1915 1819
 }
1916 1820
 
1917
-/***************************************************************************
1918
- *
1919
- * Infiniband link-layer operations
1920
- *
1921
- ***************************************************************************
1922
- */
1923
-
1924
-/**
1925
- * Initialise Infiniband link
1926
- *
1927
- * @v hermon		Hermon device
1928
- * @ret rc		Return status code
1929
- */
1930
-static int hermon_init_port ( struct hermon *hermon ) {
1931
-	struct hermonprm_init_port init_port;
1932
-	int rc;
1933
-
1934
-	memset ( &init_port, 0, sizeof ( init_port ) );
1935
-	MLX_FILL_2 ( &init_port, 0,
1936
-		     port_width_cap, 3,
1937
-		     vl_cap, 1 );
1938
-	MLX_FILL_2 ( &init_port, 1,
1939
-		     mtu, HERMON_MTU_2048,
1940
-		     max_gid, 1 );
1941
-	MLX_FILL_1 ( &init_port, 2, max_pkey, 64 );
1942
-	if ( ( rc = hermon_cmd_init_port ( hermon, PXE_IB_PORT,
1943
-					   &init_port ) ) != 0 ) {
1944
-		DBGC ( hermon, "Hermon %p could not intialise port: %s\n",
1945
-		       hermon, strerror ( rc ) );
1946
-		return rc;
1947
-	}
1948
-
1949
-	return 0;
1950
-}
1951
-
1952
-/**
1953
- * Close Infiniband link
1954
- *
1955
- * @v hermon		Hermon device
1956
- */
1957
-static void hermon_close_port ( struct hermon *hermon ) {
1958
-	int rc;
1959
-
1960
-	if ( ( rc = hermon_cmd_close_port ( hermon, PXE_IB_PORT ) ) != 0 ) {
1961
-		DBGC ( hermon, "Hermon %p could not close port: %s\n",
1962
-		       hermon, strerror ( rc ) );
1963
-		/* Nothing we can do about this */
1964
-	}
1965
-}
1966
-
1967 1821
 /***************************************************************************
1968 1822
  *
1969 1823
  * PCI interface
@@ -2030,6 +1884,7 @@ static int hermon_probe ( struct pci_device *pci,
2030 1884
 	ibdev->op = &hermon_ib_operations;
2031 1885
 	pci_set_drvdata ( pci, ibdev );
2032 1886
 	ibdev->dev = &pci->dev;
1887
+	ibdev->port = PXE_IB_PORT;
2033 1888
 	hermon = ibdev->dev_priv;
2034 1889
 	memset ( hermon, 0, sizeof ( *hermon ) );
2035 1890
 
@@ -2084,38 +1939,16 @@ static int hermon_probe ( struct pci_device *pci,
2084 1939
 	if ( ( rc = hermon_setup_mpt ( hermon ) ) != 0 )
2085 1940
 		goto err_setup_mpt;
2086 1941
 
2087
-	/* Bring up IB layer */
2088
-	if ( ( rc = hermon_init_port ( hermon ) ) != 0 )
2089
-		goto err_init_port;
2090
-
2091
-	/* Wait for link */
2092
-	if ( ( rc = hermon_wait_for_link ( hermon ) ) != 0 )
2093
-		goto err_wait_for_link;
2094
-
2095
-	/* Get MAD parameters */
2096
-	if ( ( rc = hermon_get_mad_params ( ibdev ) ) != 0 )
2097
-		goto err_get_mad_params;
2098
-
2099
-	DBGC ( hermon, "Hermon %p port GID is %08lx:%08lx:%08lx:%08lx\n",
2100
-	       hermon, htonl ( ibdev->port_gid.u.dwords[0] ),
2101
-	       htonl ( ibdev->port_gid.u.dwords[1] ),
2102
-	       htonl ( ibdev->port_gid.u.dwords[2] ),
2103
-	       htonl ( ibdev->port_gid.u.dwords[3] ) );
2104
-
2105
-	/* Add IPoIB device */
2106
-	if ( ( rc = ipoib_probe ( ibdev ) ) != 0 ) {
2107
-		DBGC ( hermon, "Hermon %p could not add IPoIB device: %s\n",
1942
+	/* Register Infiniband device */
1943
+	if ( ( rc = register_ibdev ( ibdev ) ) != 0 ) {
1944
+		DBGC ( hermon, "Hermon %p could not register IB device: %s\n",
2108 1945
 		       hermon, strerror ( rc ) );
2109
-		goto err_ipoib_probe;
1946
+		goto err_register_ibdev;
2110 1947
 	}
2111 1948
 
2112 1949
 	return 0;
2113 1950
 
2114
- err_ipoib_probe:
2115
- err_get_mad_params:
2116
- err_wait_for_link:
2117
-	hermon_close_port ( hermon );
2118
- err_init_port:
1951
+ err_register_ibdev:
2119 1952
  err_setup_mpt:
2120 1953
 	hermon_cmd_close_hca ( hermon );
2121 1954
  err_init_hca:
@@ -2142,8 +1975,7 @@ static void hermon_remove ( struct pci_device *pci ) {
2142 1975
 	struct ib_device *ibdev = pci_get_drvdata ( pci );
2143 1976
 	struct hermon *hermon = ibdev->dev_priv;
2144 1977
 
2145
-	ipoib_remove ( ibdev );
2146
-	hermon_close_port ( hermon );
1978
+	unregister_ibdev ( ibdev );
2147 1979
 	hermon_cmd_close_hca ( hermon );
2148 1980
 	hermon_free_icm ( hermon );
2149 1981
 	hermon_stop_firmware ( hermon );

+ 70
- 7
src/include/gpxe/infiniband.h View File

@@ -156,6 +156,8 @@ struct ib_address_vector {
156 156
 	struct ib_gid gid;
157 157
 };
158 158
 
159
+struct ib_mad_hdr;
160
+
159 161
 /**
160 162
  * Infiniband device operations
161 163
  *
@@ -237,6 +239,19 @@ struct ib_device_operations {
237 239
 			     struct ib_completion_queue *cq,
238 240
 			     ib_completer_t complete_send,
239 241
 			     ib_completer_t complete_recv );
242
+	/**
243
+	 * Open port
244
+	 *
245
+	 * @v ibdev		Infiniband device
246
+	 * @ret rc		Return status code
247
+	 */
248
+	int ( * open ) ( struct ib_device *ibdev );
249
+	/**
250
+	 * Close port
251
+	 *
252
+	 * @v ibdev		Infiniband device
253
+	 */
254
+	void ( * close ) ( struct ib_device *ibdev );
240 255
 	/** Attach to multicast group
241 256
 	 *
242 257
 	 * @v ibdev		Infiniband device
@@ -256,20 +271,32 @@ struct ib_device_operations {
256 271
 	void ( * mcast_detach ) ( struct ib_device *ibdev,
257 272
 				  struct ib_queue_pair *qp,
258 273
 				  struct ib_gid *gid );
274
+	/**
275
+	 * Issue management datagram
276
+	 *
277
+	 * @v ibdev		Infiniband device
278
+	 * @v mad		Management datagram
279
+	 * @v len		Length of management datagram
280
+	 * @ret rc		Return status code
281
+	 */
282
+	int ( * mad ) ( struct ib_device *ibdev, struct ib_mad_hdr *mad,
283
+			size_t len );
259 284
 };
260 285
 
261 286
 /** An Infiniband device */
262 287
 struct ib_device {
288
+	/** Underlying device */
289
+	struct device *dev;
290
+	/** Infiniband operations */
291
+	struct ib_device_operations *op;
292
+	/** Port number */
293
+	unsigned int port;
263 294
 	/** Port GID */
264 295
 	struct ib_gid port_gid;
265 296
 	/** Subnet manager LID */
266 297
 	unsigned long sm_lid;
267 298
 	/** Partition key */
268 299
 	unsigned int pkey;
269
-	/** Underlying device */
270
-	struct device *dev;
271
-	/** Infiniband operations */
272
-	struct ib_device_operations *op;
273 300
 	/** Device private data */
274 301
 	void *dev_priv;
275 302
 	/** Owner private data */
@@ -289,6 +316,8 @@ extern void ib_destroy_qp ( struct ib_device *ibdev,
289 316
 extern struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
290 317
 					   unsigned long qpn, int is_send );
291 318
 extern struct ib_device * alloc_ibdev ( size_t priv_size );
319
+extern int register_ibdev ( struct ib_device *ibdev );
320
+extern void unregister_ibdev ( struct ib_device *ibdev );
292 321
 extern void free_ibdev ( struct ib_device *ibdev );
293 322
 
294 323
 /**
@@ -334,6 +363,26 @@ ib_poll_cq ( struct ib_device *ibdev, struct ib_completion_queue *cq,
334 363
 	ibdev->op->poll_cq ( ibdev, cq, complete_send, complete_recv );
335 364
 }
336 365
 
366
+/**
367
+ * Open port
368
+ *
369
+ * @v ibdev		Infiniband device
370
+ * @ret rc		Return status code
371
+ */
372
+static inline __attribute__ (( always_inline )) int
373
+ib_open ( struct ib_device *ibdev ) {
374
+	return ibdev->op->open ( ibdev );
375
+}
376
+
377
+/**
378
+ * Close port
379
+ *
380
+ * @v ibdev		Infiniband device
381
+ */
382
+static inline __attribute__ (( always_inline )) void
383
+ib_close ( struct ib_device *ibdev ) {
384
+	ibdev->op->close ( ibdev );
385
+}
337 386
 
338 387
 /**
339 388
  * Attach to multicast group
@@ -362,14 +411,27 @@ ib_mcast_detach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
362 411
 	ibdev->op->mcast_detach ( ibdev, qp, gid );
363 412
 }
364 413
 
414
+/**
415
+ * Issue management datagram
416
+ *
417
+ * @v ibdev		Infiniband device
418
+ * @v mad		Management datagram
419
+ * @v len		Length of management datagram
420
+ * @ret rc		Return status code
421
+ */
422
+static inline __attribute__ (( always_inline )) int
423
+ib_mad ( struct ib_device *ibdev, struct ib_mad_hdr *mad, size_t len ) {
424
+	return ibdev->op->mad ( ibdev, mad, len );
425
+}
426
+
365 427
 /**
366 428
  * Set Infiniband owner-private data
367 429
  *
368 430
  * @v pci		Infiniband device
369 431
  * @v priv		Private data
370 432
  */
371
-static inline void ib_set_ownerdata ( struct ib_device *ibdev,
372
-				      void *owner_priv ) {
433
+static inline __attribute__ (( always_inline )) void
434
+ib_set_ownerdata ( struct ib_device *ibdev, void *owner_priv ) {
373 435
 	ibdev->owner_priv = owner_priv;
374 436
 }
375 437
 
@@ -379,7 +441,8 @@ static inline void ib_set_ownerdata ( struct ib_device *ibdev,
379 441
  * @v pci		Infiniband device
380 442
  * @ret priv		Private data
381 443
  */
382
-static inline void * ib_get_ownerdata ( struct ib_device *ibdev ) {
444
+static inline __attribute__ (( always_inline )) void *
445
+ib_get_ownerdata ( struct ib_device *ibdev ) {
383 446
 	return ibdev->owner_priv;
384 447
 }
385 448
 

+ 222
- 0
src/net/infiniband.c View File

@@ -20,6 +20,7 @@
20 20
 #include <stdlib.h>
21 21
 #include <stdio.h>
22 22
 #include <string.h>
23
+#include <unistd.h>
23 24
 #include <byteswap.h>
24 25
 #include <errno.h>
25 26
 #include <assert.h>
@@ -27,6 +28,7 @@
27 28
 #include <gpxe/if_arp.h>
28 29
 #include <gpxe/netdevice.h>
29 30
 #include <gpxe/iobuf.h>
31
+#include <gpxe/ipoib.h>
30 32
 #include <gpxe/infiniband.h>
31 33
 
32 34
 /** @file
@@ -184,6 +186,177 @@ struct ib_work_queue * ib_find_wq ( struct ib_completion_queue *cq,
184 186
 	return NULL;
185 187
 }
186 188
 
189
+/***************************************************************************
190
+ *
191
+ * Management datagram operations
192
+ *
193
+ ***************************************************************************
194
+ */
195
+
196
+/**
197
+ * Get port information
198
+ *
199
+ * @v ibdev		Infiniband device
200
+ * @v port_info		Port information datagram to fill in
201
+ * @ret rc		Return status code
202
+ */
203
+static int ib_get_port_info ( struct ib_device *ibdev,
204
+			      struct ib_mad_port_info *port_info ) {
205
+	struct ib_mad_hdr *hdr = &port_info->mad_hdr;
206
+	int rc;
207
+
208
+	/* Construct MAD */
209
+	memset ( port_info, 0, sizeof ( *port_info ) );
210
+	hdr->base_version = IB_MGMT_BASE_VERSION;
211
+	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
212
+	hdr->class_version = 1;
213
+	hdr->method = IB_MGMT_METHOD_GET;
214
+	hdr->attr_id = htons ( IB_SMP_ATTR_PORT_INFO );
215
+	hdr->attr_mod = htonl ( ibdev->port );
216
+
217
+	if ( ( rc = ib_mad ( ibdev, hdr, sizeof ( *port_info ) ) ) != 0 ) {
218
+		DBGC ( ibdev, "IBDEV %p could not get port info: %s\n",
219
+		       ibdev, strerror ( rc ) );
220
+		return rc;
221
+	}
222
+	return 0;
223
+}
224
+
225
+/**
226
+ * Get GUID information
227
+ *
228
+ * @v ibdev		Infiniband device
229
+ * @v guid_info		GUID information datagram to fill in
230
+ * @ret rc		Return status code
231
+ */
232
+static int ib_get_guid_info ( struct ib_device *ibdev,
233
+			      struct ib_mad_guid_info *guid_info ) {
234
+	struct ib_mad_hdr *hdr = &guid_info->mad_hdr;
235
+	int rc;
236
+
237
+	/* Construct MAD */
238
+	memset ( guid_info, 0, sizeof ( *guid_info ) );
239
+	hdr->base_version = IB_MGMT_BASE_VERSION;
240
+	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
241
+	hdr->class_version = 1;
242
+	hdr->method = IB_MGMT_METHOD_GET;
243
+	hdr->attr_id = htons ( IB_SMP_ATTR_GUID_INFO );
244
+
245
+	if ( ( rc = ib_mad ( ibdev, hdr, sizeof ( *guid_info ) ) ) != 0 ) {
246
+		DBGC ( ibdev, "IBDEV %p could not get GUID info: %s\n",
247
+		       ibdev, strerror ( rc ) );
248
+		return rc;
249
+	}
250
+	return 0;
251
+}
252
+
253
+/**
254
+ * Get partition key table
255
+ *
256
+ * @v ibdev		Infiniband device
257
+ * @v guid_info		Partition key table datagram to fill in
258
+ * @ret rc		Return status code
259
+ */
260
+static int ib_get_pkey_table ( struct ib_device *ibdev,
261
+			       struct ib_mad_pkey_table *pkey_table ) {
262
+	struct ib_mad_hdr *hdr = &pkey_table->mad_hdr;
263
+	int rc;
264
+
265
+	/* Construct MAD */
266
+	memset ( pkey_table, 0, sizeof ( *pkey_table ) );
267
+	hdr->base_version = IB_MGMT_BASE_VERSION;
268
+	hdr->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
269
+	hdr->class_version = 1;
270
+	hdr->method = IB_MGMT_METHOD_GET;
271
+	hdr->attr_id = htons ( IB_SMP_ATTR_PKEY_TABLE );
272
+
273
+	if ( ( rc = ib_mad ( ibdev, hdr, sizeof ( *pkey_table ) ) ) != 0 ) {
274
+		DBGC ( ibdev, "IBDEV %p could not get pkey table: %s\n",
275
+		       ibdev, strerror ( rc ) );
276
+		return rc;
277
+	}
278
+	return 0;
279
+}
280
+
281
+/**
282
+ * Wait for link up
283
+ *
284
+ * @v ibdev		Infiniband device
285
+ * @ret rc		Return status code
286
+ *
287
+ * This function shouldn't really exist.  Unfortunately, IB links take
288
+ * a long time to come up, and we can't get various key parameters
289
+ * e.g. our own IPoIB MAC address without information from the subnet
290
+ * manager).  We should eventually make link-up an asynchronous event.
291
+ */
292
+static int ib_wait_for_link ( struct ib_device *ibdev ) {
293
+	struct ib_mad_port_info port_info;
294
+	unsigned int retries;
295
+	int rc;
296
+
297
+	printf ( "Waiting for Infiniband link-up..." );
298
+	for ( retries = 20 ; retries ; retries-- ) {
299
+		if ( ( rc = ib_get_port_info ( ibdev, &port_info ) ) != 0 )
300
+			continue;
301
+		if ( ( ( port_info.port_state__link_speed_supported ) & 0xf )
302
+		     == 4 ) {
303
+			printf ( "ok\n" );
304
+			return 0;
305
+		}
306
+		printf ( "." );
307
+		sleep ( 1 );
308
+	}
309
+	printf ( "failed\n" );
310
+	return -ENODEV;
311
+};
312
+
313
+/**
314
+ * Get MAD parameters
315
+ *
316
+ * @v ibdev		Infiniband device
317
+ * @ret rc		Return status code
318
+ */
319
+static int ib_get_mad_params ( struct ib_device *ibdev ) {
320
+	union {
321
+		/* This union exists just to save stack space */
322
+		struct ib_mad_port_info port_info;
323
+		struct ib_mad_guid_info guid_info;
324
+		struct ib_mad_pkey_table pkey_table;
325
+	} u;
326
+	int rc;
327
+
328
+	/* Port info gives us the first half of the port GID and the SM LID */
329
+	if ( ( rc = ib_get_port_info ( ibdev, &u.port_info ) ) != 0 )
330
+		return rc;
331
+	memcpy ( &ibdev->port_gid.u.bytes[0], u.port_info.gid_prefix, 8 );
332
+	ibdev->sm_lid = ntohs ( u.port_info.mastersm_lid );
333
+
334
+	/* GUID info gives us the second half of the port GID */
335
+	if ( ( rc = ib_get_guid_info ( ibdev, &u.guid_info ) ) != 0 )
336
+		return rc;
337
+	memcpy ( &ibdev->port_gid.u.bytes[8], u.guid_info.gid_local, 8 );
338
+
339
+	/* Get partition key */
340
+	if ( ( rc = ib_get_pkey_table ( ibdev, &u.pkey_table ) ) != 0 )
341
+		return rc;
342
+	ibdev->pkey = ntohs ( u.pkey_table.pkey[0][0] );
343
+
344
+	DBGC ( ibdev, "IBDEV %p port GID is %08lx:%08lx:%08lx:%08lx\n",
345
+	       ibdev, htonl ( ibdev->port_gid.u.dwords[0] ),
346
+	       htonl ( ibdev->port_gid.u.dwords[1] ),
347
+	       htonl ( ibdev->port_gid.u.dwords[2] ),
348
+	       htonl ( ibdev->port_gid.u.dwords[3] ) );
349
+
350
+	return 0;
351
+}
352
+
353
+/***************************************************************************
354
+ *
355
+ * Infiniband device creation/destruction
356
+ *
357
+ ***************************************************************************
358
+ */
359
+
187 360
 /**
188 361
  * Allocate Infiniband device
189 362
  *
@@ -202,6 +375,54 @@ struct ib_device * alloc_ibdev ( size_t priv_size ) {
202 375
 	return ibdev;
203 376
 }
204 377
 
378
+/**
379
+ * Register Infiniband device
380
+ *
381
+ * @v ibdev		Infiniband device
382
+ * @ret rc		Return status code
383
+ */
384
+int register_ibdev ( struct ib_device *ibdev ) {
385
+	int rc;
386
+
387
+	/* Open link */
388
+	if ( ( rc = ib_open ( ibdev ) ) != 0 )
389
+		goto err_open;
390
+
391
+	/* Wait for link */
392
+	if ( ( rc = ib_wait_for_link ( ibdev ) ) != 0 )
393
+		goto err_wait_for_link;
394
+
395
+	/* Get MAD parameters */
396
+	if ( ( rc = ib_get_mad_params ( ibdev ) ) != 0 )
397
+		goto err_get_mad_params;
398
+
399
+	/* Add IPoIB device */
400
+	if ( ( rc = ipoib_probe ( ibdev ) ) != 0 ) {
401
+		DBGC ( ibdev, "IBDEV %p could not add IPoIB device: %s\n",
402
+		       ibdev, strerror ( rc ) );
403
+		goto err_ipoib_probe;
404
+	}
405
+
406
+	return 0;
407
+
408
+ err_ipoib_probe:
409
+ err_get_mad_params:
410
+ err_wait_for_link:
411
+	ib_close ( ibdev );
412
+ err_open:
413
+	return rc;
414
+}
415
+
416
+/**
417
+ * Unregister Infiniband device
418
+ *
419
+ * @v ibdev		Infiniband device
420
+ */
421
+void unregister_ibdev ( struct ib_device *ibdev ) {
422
+	ipoib_remove ( ibdev );
423
+	ib_close ( ibdev );
424
+}
425
+
205 426
 /**
206 427
  * Free Infiniband device
207 428
  *
@@ -210,3 +431,4 @@ struct ib_device * alloc_ibdev ( size_t priv_size ) {
210 431
 void free_ibdev ( struct ib_device *ibdev ) {
211 432
 	free ( ibdev );
212 433
 }
434
+

Loading…
Cancel
Save