Ver código fonte

Starting the firmware directly now works.

tags/v0.9.3
Michael Brown 16 anos atrás
pai
commit
dc3165b746
2 arquivos alterados com 159 adições e 24 exclusões
  1. 14
    3
      src/drivers/net/mlx_ipoib/arbel.h
  2. 145
    21
      src/drivers/net/mlx_ipoib/mt25218.c

+ 14
- 3
src/drivers/net/mlx_ipoib/arbel.h Ver arquivo

@@ -7,6 +7,9 @@
7 7
  *
8 8
  */
9 9
 
10
+#include <stdint.h>
11
+#include <gpxe/uaccess.h>
12
+
10 13
 /*
11 14
  * Hardware constants
12 15
  *
@@ -45,6 +48,9 @@
45 48
 #define ARBEL_HCR_READ_MGM		0x0025
46 49
 #define ARBEL_HCR_WRITE_MGM		0x0026
47 50
 #define ARBEL_HCR_MGID_HASH		0x0027
51
+#define ARBEL_HCR_RUN_FW		0x0ff6
52
+#define ARBEL_HCR_UNMAP_FA		0x0ffe
53
+#define ARBEL_HCR_MAP_FA		0x0fff
48 54
 
49 55
 /* Service types */
50 56
 #define ARBEL_ST_UD			0x03
@@ -87,6 +93,7 @@ struct MLX_DECLARE_STRUCT ( arbelprm_queue_pair_ee_context_entry );
87 93
 struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
88 94
 struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
89 95
 struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
96
+struct MLX_DECLARE_STRUCT ( arbelprm_virtual_physical_mapping );
90 97
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
91 98
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
92 99
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
@@ -240,15 +247,19 @@ typedef uint32_t arbel_bitmask_t;
240 247
 
241 248
 /** An Arbel device */
242 249
 struct arbel {
243
-	/** Configuration registers */
250
+	/** PCI configuration registers */
244 251
 	void *config;
252
+	/** PCI user Access Region */
253
+	void *uar;
254
+
245 255
 	/** Command input mailbox */
246 256
 	void *mailbox_in;
247 257
 	/** Command output mailbox */
248 258
 	void *mailbox_out;
249 259
 
250
-	/** User Access Region */
251
-	void *uar;
260
+	/** Firmware area in external memory */
261
+	userptr_t firmware_area;
262
+
252 263
 	/** Doorbell records */
253 264
 	union arbelprm_doorbell_record *db_rec;
254 265
 	/** Reserved LKey

+ 145
- 21
src/drivers/net/mlx_ipoib/mt25218.c Ver arquivo

@@ -315,6 +315,29 @@ arbel_cmd_mgid_hash ( struct arbel *arbel, const struct ib_gid *gid,
315 315
 			   0, gid, 0, hash );
316 316
 }
317 317
 
318
+static inline int
319
+arbel_cmd_run_fw ( struct arbel *arbel ) {
320
+	return arbel_cmd ( arbel,
321
+			   ARBEL_HCR_VOID_CMD ( ARBEL_HCR_RUN_FW ),
322
+			   0, NULL, 0, NULL );
323
+}
324
+
325
+static inline int
326
+arbel_cmd_unmap_fa ( struct arbel *arbel ) {
327
+	return arbel_cmd ( arbel,
328
+			   ARBEL_HCR_VOID_CMD ( ARBEL_HCR_UNMAP_FA ),
329
+			   0, NULL, 0, NULL );
330
+}
331
+
332
+static inline int
333
+arbel_cmd_map_fa ( struct arbel *arbel,
334
+		   const struct arbelprm_virtual_physical_mapping *map_fa ) {
335
+	return arbel_cmd ( arbel,
336
+			   ARBEL_HCR_IN_CMD ( ARBEL_HCR_MAP_FA,
337
+					      1, sizeof ( *map_fa ) ),
338
+			   0, map_fa, 1, NULL );
339
+}
340
+
318 341
 /***************************************************************************
319 342
  *
320 343
  * Completion queue operations
@@ -958,15 +981,15 @@ static int arbel_complete ( struct ib_device *ibdev,
958 981
 	}
959 982
 	qp = wq->qp;
960 983
 	arbel_qp = qp->dev_priv;
984
+	arbel_send_wq = &arbel_qp->send;
985
+	arbel_recv_wq = &arbel_qp->recv;
961 986
 
962 987
 	/* Identify work queue entry index */
963 988
 	if ( is_send ) {
964
-		arbel_send_wq = &arbel_qp->send;
965 989
 		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) /
966 990
 			    sizeof ( arbel_send_wq->wqe[0] ) );
967 991
 		assert ( wqe_idx < qp->send.num_wqes );
968 992
 	} else {
969
-		arbel_recv_wq = &arbel_qp->recv;
970 993
 		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) /
971 994
 			    sizeof ( arbel_recv_wq->wqe[0] ) );
972 995
 		assert ( wqe_idx < qp->recv.num_wqes );
@@ -1177,6 +1200,12 @@ static struct ib_device_operations arbel_ib_operations = {
1177 1200
 	.mcast_detach	= arbel_mcast_detach,
1178 1201
 };
1179 1202
 
1203
+/***************************************************************************
1204
+ *
1205
+ * MAD IFC operations
1206
+ *
1207
+ ***************************************************************************
1208
+ */
1180 1209
 
1181 1210
 static int arbel_mad_ifc ( struct arbel *arbel,
1182 1211
 			   union arbelprm_mad *mad ) {
@@ -1301,6 +1330,102 @@ static int arbel_get_pkey ( struct arbel *arbel, unsigned int *pkey ) {
1301 1330
 	return 0;
1302 1331
 }
1303 1332
 
1333
+/***************************************************************************
1334
+ *
1335
+ * Firmware control
1336
+ *
1337
+ ***************************************************************************
1338
+ */
1339
+
1340
+/**
1341
+ * Start firmware running
1342
+ *
1343
+ * @v arbel		Arbel device
1344
+ * @ret rc		Return status code
1345
+ */
1346
+static int arbel_start_firmware ( struct arbel *arbel ) {
1347
+	struct arbelprm_query_fw fw;
1348
+	struct arbelprm_virtual_physical_mapping map_fa;
1349
+	unsigned int fw_pages;
1350
+	unsigned int log2_fw_pages;
1351
+	size_t fw_size;
1352
+	physaddr_t fw_base;
1353
+	int rc;
1354
+
1355
+	/* Get firmware parameters */
1356
+	if ( ( rc = arbel_cmd_query_fw ( arbel, &fw ) ) != 0 ) {
1357
+		DBGC ( arbel, "Arbel %p could not query firmware: %s\n",
1358
+		       arbel, strerror ( rc ) );
1359
+		goto err_query_fw;
1360
+	}
1361
+	DBGC ( arbel, "Arbel %p firmware version %ld.%ld.%ld\n", arbel,
1362
+	       MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
1363
+	       MLX_GET ( &fw, fw_rev_subminor ) );
1364
+	fw_pages = MLX_GET ( &fw, fw_pages );
1365
+	log2_fw_pages = fls ( fw_pages - 1 );
1366
+	fw_pages = ( 1 << log2_fw_pages );
1367
+	DBGC ( arbel, "Arbel %p requires %d kB for firmware\n",
1368
+	       arbel, ( fw_pages * 4 ) );
1369
+
1370
+	/* Allocate firmware pages and map firmware area */
1371
+	fw_size = ( fw_pages * 4096 );
1372
+	arbel->firmware_area = umalloc ( fw_size );
1373
+	if ( ! arbel->firmware_area ) {
1374
+		rc = -ENOMEM;
1375
+		goto err_alloc_fa;
1376
+	}
1377
+	fw_base = ( user_to_phys ( arbel->firmware_area, fw_size ) &
1378
+		    ~( fw_size - 1 ) );
1379
+	DBGC ( arbel, "Arbel %p firmware area at physical [%lx,%lx)\n",
1380
+	       arbel, fw_base, ( fw_base + fw_size ) );
1381
+	memset ( &map_fa, 0, sizeof ( map_fa ) );
1382
+	MLX_FILL_2 ( &map_fa, 3,
1383
+		     log2size, log2_fw_pages,
1384
+		     pa_l, ( fw_base >> 12 ) );
1385
+	if ( ( rc = arbel_cmd_map_fa ( arbel, &map_fa ) ) != 0 ) {
1386
+		DBGC ( arbel, "Arbel %p could not map firmware: %s\n",
1387
+		       arbel, strerror ( rc ) );
1388
+		goto err_map_fa;
1389
+	}
1390
+
1391
+	/* Start firmware */
1392
+	if ( ( rc = arbel_cmd_run_fw ( arbel ) ) != 0 ) {
1393
+		DBGC ( arbel, "Arbel %p could not run firmware: %s\n",
1394
+		       arbel, strerror ( rc ) );
1395
+		goto err_run_fw;
1396
+	}
1397
+
1398
+	DBGC ( arbel, "Arbel %p firmware started\n", arbel );
1399
+	return 0;
1400
+
1401
+ err_run_fw:
1402
+	arbel_cmd_unmap_fa ( arbel );
1403
+ err_map_fa:
1404
+	ufree ( arbel->firmware_area );
1405
+	arbel->firmware_area = UNULL;
1406
+ err_alloc_fa:
1407
+ err_query_fw:
1408
+	return rc;
1409
+}
1410
+
1411
+/**
1412
+ * Stop firmware running
1413
+ *
1414
+ * @v arbel		Arbel device
1415
+ */
1416
+static void arbel_stop_firmware ( struct arbel *arbel ) {
1417
+	int rc;
1418
+
1419
+	if ( ( rc = arbel_cmd_unmap_fa ( arbel ) ) != 0 ) {
1420
+		DBGC ( arbel, "Arbel %p FATAL could not stop firmware: %s\n",
1421
+		       arbel, strerror ( rc ) );
1422
+		/* Leak memory and return; at least we avoid corruption */
1423
+		return;
1424
+	}
1425
+	ufree ( arbel->firmware_area );
1426
+	arbel->firmware_area = UNULL;
1427
+}
1428
+
1304 1429
 /**
1305 1430
  * Probe PCI device
1306 1431
  *
@@ -1311,7 +1436,6 @@ static int arbel_get_pkey ( struct arbel *arbel, unsigned int *pkey ) {
1311 1436
 static int arbel_probe ( struct pci_device *pci,
1312 1437
 			 const struct pci_device_id *id __unused ) {
1313 1438
 	struct ib_device *ibdev;
1314
-	struct arbelprm_query_fw fw;
1315 1439
 	struct arbelprm_query_dev_lim dev_lim;
1316 1440
 	struct arbel *arbel;
1317 1441
 	udqp_t qph;
@@ -1329,6 +1453,16 @@ static int arbel_probe ( struct pci_device *pci,
1329 1453
 	arbel = ibdev->dev_priv;
1330 1454
 	memset ( arbel, 0, sizeof ( *arbel ) );
1331 1455
 
1456
+	/* Fix up PCI device */
1457
+	adjust_pci_device ( pci );
1458
+
1459
+	/* Get PCI BARs */
1460
+	arbel->config = ioremap ( pci_bar_start ( pci, ARBEL_PCI_CONFIG_BAR ),
1461
+				  ARBEL_PCI_CONFIG_BAR_SIZE );
1462
+	arbel->uar = ioremap ( ( pci_bar_start ( pci, ARBEL_PCI_UAR_BAR ) +
1463
+				 ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ),
1464
+			       ARBEL_PCI_UAR_SIZE );
1465
+
1332 1466
 	/* Allocate space for mailboxes */
1333 1467
 	arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
1334 1468
 	if ( ! arbel->mailbox_in ) {
@@ -1341,25 +1475,12 @@ static int arbel_probe ( struct pci_device *pci,
1341 1475
 		goto err_mailbox_out;
1342 1476
 	}
1343 1477
 
1344
-	/* Fix up PCI device */
1345
-	adjust_pci_device ( pci );
1478
+	/* Start firmware */
1479
+	if ( ( rc = arbel_start_firmware ( arbel ) ) != 0 )
1480
+		goto err_start_firmware;
1346 1481
 
1347
-	/* Get PCI BARs */
1348
-	arbel->config = ioremap ( pci_bar_start ( pci, ARBEL_PCI_CONFIG_BAR ),
1349
-				  ARBEL_PCI_CONFIG_BAR_SIZE );
1350
-	arbel->uar = ioremap ( ( pci_bar_start ( pci, ARBEL_PCI_UAR_BAR ) +
1351
-				 ARBEL_PCI_UAR_IDX * ARBEL_PCI_UAR_SIZE ),
1352
-			       ARBEL_PCI_UAR_SIZE );
1353 1482
 
1354
-	/* Initialise firmware */
1355
-	if ( ( rc = arbel_cmd_query_fw ( arbel, &fw ) ) != 0 ) {
1356
-		DBGC ( arbel, "Arbel %p could not query firmware: %s\n",
1357
-		       arbel, strerror ( rc ) );
1358
-		goto err_query_fw;
1359
-	}
1360
-	DBGC ( arbel, "Arbel %p firmware version %ld.%ld.%ld\n", arbel,
1361
-	       MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
1362
-	       MLX_GET ( &fw, fw_rev_subminor ) );
1483
+	while ( 1 ) {}
1363 1484
 
1364 1485
 	/* Initialise hardware */
1365 1486
 	if ( ( rc = ib_driver_init ( pci, &qph ) ) != 0 )
@@ -1425,7 +1546,9 @@ static int arbel_probe ( struct pci_device *pci,
1425 1546
  err_query_dev_lim:
1426 1547
 	ib_driver_close ( 0 );
1427 1548
  err_ib_driver_init:
1428
- err_query_fw:
1549
+
1550
+	arbel_stop_firmware ( arbel );
1551
+ err_start_firmware:
1429 1552
 	free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
1430 1553
  err_mailbox_out:
1431 1554
 	free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
@@ -1446,6 +1569,7 @@ static void arbel_remove ( struct pci_device *pci ) {
1446 1569
 
1447 1570
 	ipoib_remove ( ibdev );
1448 1571
 	ib_driver_close ( 0 );
1572
+	arbel_stop_firmware ( arbel );
1449 1573
 	free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
1450 1574
 	free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
1451 1575
 	free_ibdev ( ibdev );

Carregando…
Cancelar
Salvar