Browse Source

Starting the firmware directly now works.

tags/v0.9.3
Michael Brown 17 years ago
parent
commit
dc3165b746
2 changed files with 159 additions and 24 deletions
  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 View File

7
  *
7
  *
8
  */
8
  */
9
 
9
 
10
+#include <stdint.h>
11
+#include <gpxe/uaccess.h>
12
+
10
 /*
13
 /*
11
  * Hardware constants
14
  * Hardware constants
12
  *
15
  *
45
 #define ARBEL_HCR_READ_MGM		0x0025
48
 #define ARBEL_HCR_READ_MGM		0x0025
46
 #define ARBEL_HCR_WRITE_MGM		0x0026
49
 #define ARBEL_HCR_WRITE_MGM		0x0026
47
 #define ARBEL_HCR_MGID_HASH		0x0027
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
 /* Service types */
55
 /* Service types */
50
 #define ARBEL_ST_UD			0x03
56
 #define ARBEL_ST_UD			0x03
87
 struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
93
 struct MLX_DECLARE_STRUCT ( arbelprm_recv_wqe_segment_next );
88
 struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
94
 struct MLX_DECLARE_STRUCT ( arbelprm_send_doorbell );
89
 struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
95
 struct MLX_DECLARE_STRUCT ( arbelprm_ud_address_vector );
96
+struct MLX_DECLARE_STRUCT ( arbelprm_virtual_physical_mapping );
90
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
97
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_ctrl_send );
91
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
98
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_data_ptr );
92
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
99
 struct MLX_DECLARE_STRUCT ( arbelprm_wqe_segment_next );
240
 
247
 
241
 /** An Arbel device */
248
 /** An Arbel device */
242
 struct arbel {
249
 struct arbel {
243
-	/** Configuration registers */
250
+	/** PCI configuration registers */
244
 	void *config;
251
 	void *config;
252
+	/** PCI user Access Region */
253
+	void *uar;
254
+
245
 	/** Command input mailbox */
255
 	/** Command input mailbox */
246
 	void *mailbox_in;
256
 	void *mailbox_in;
247
 	/** Command output mailbox */
257
 	/** Command output mailbox */
248
 	void *mailbox_out;
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
 	/** Doorbell records */
263
 	/** Doorbell records */
253
 	union arbelprm_doorbell_record *db_rec;
264
 	union arbelprm_doorbell_record *db_rec;
254
 	/** Reserved LKey
265
 	/** Reserved LKey

+ 145
- 21
src/drivers/net/mlx_ipoib/mt25218.c View File

315
 			   0, gid, 0, hash );
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
  * Completion queue operations
343
  * Completion queue operations
958
 	}
981
 	}
959
 	qp = wq->qp;
982
 	qp = wq->qp;
960
 	arbel_qp = qp->dev_priv;
983
 	arbel_qp = qp->dev_priv;
984
+	arbel_send_wq = &arbel_qp->send;
985
+	arbel_recv_wq = &arbel_qp->recv;
961
 
986
 
962
 	/* Identify work queue entry index */
987
 	/* Identify work queue entry index */
963
 	if ( is_send ) {
988
 	if ( is_send ) {
964
-		arbel_send_wq = &arbel_qp->send;
965
 		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) /
989
 		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_send_wq->wqe ) ) /
966
 			    sizeof ( arbel_send_wq->wqe[0] ) );
990
 			    sizeof ( arbel_send_wq->wqe[0] ) );
967
 		assert ( wqe_idx < qp->send.num_wqes );
991
 		assert ( wqe_idx < qp->send.num_wqes );
968
 	} else {
992
 	} else {
969
-		arbel_recv_wq = &arbel_qp->recv;
970
 		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) /
993
 		wqe_idx = ( ( wqe_adr - virt_to_bus ( arbel_recv_wq->wqe ) ) /
971
 			    sizeof ( arbel_recv_wq->wqe[0] ) );
994
 			    sizeof ( arbel_recv_wq->wqe[0] ) );
972
 		assert ( wqe_idx < qp->recv.num_wqes );
995
 		assert ( wqe_idx < qp->recv.num_wqes );
1177
 	.mcast_detach	= arbel_mcast_detach,
1200
 	.mcast_detach	= arbel_mcast_detach,
1178
 };
1201
 };
1179
 
1202
 
1203
+/***************************************************************************
1204
+ *
1205
+ * MAD IFC operations
1206
+ *
1207
+ ***************************************************************************
1208
+ */
1180
 
1209
 
1181
 static int arbel_mad_ifc ( struct arbel *arbel,
1210
 static int arbel_mad_ifc ( struct arbel *arbel,
1182
 			   union arbelprm_mad *mad ) {
1211
 			   union arbelprm_mad *mad ) {
1301
 	return 0;
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
  * Probe PCI device
1430
  * Probe PCI device
1306
  *
1431
  *
1311
 static int arbel_probe ( struct pci_device *pci,
1436
 static int arbel_probe ( struct pci_device *pci,
1312
 			 const struct pci_device_id *id __unused ) {
1437
 			 const struct pci_device_id *id __unused ) {
1313
 	struct ib_device *ibdev;
1438
 	struct ib_device *ibdev;
1314
-	struct arbelprm_query_fw fw;
1315
 	struct arbelprm_query_dev_lim dev_lim;
1439
 	struct arbelprm_query_dev_lim dev_lim;
1316
 	struct arbel *arbel;
1440
 	struct arbel *arbel;
1317
 	udqp_t qph;
1441
 	udqp_t qph;
1329
 	arbel = ibdev->dev_priv;
1453
 	arbel = ibdev->dev_priv;
1330
 	memset ( arbel, 0, sizeof ( *arbel ) );
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
 	/* Allocate space for mailboxes */
1466
 	/* Allocate space for mailboxes */
1333
 	arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
1467
 	arbel->mailbox_in = malloc_dma ( ARBEL_MBOX_SIZE, ARBEL_MBOX_ALIGN );
1334
 	if ( ! arbel->mailbox_in ) {
1468
 	if ( ! arbel->mailbox_in ) {
1341
 		goto err_mailbox_out;
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
 	/* Initialise hardware */
1485
 	/* Initialise hardware */
1365
 	if ( ( rc = ib_driver_init ( pci, &qph ) ) != 0 )
1486
 	if ( ( rc = ib_driver_init ( pci, &qph ) ) != 0 )
1425
  err_query_dev_lim:
1546
  err_query_dev_lim:
1426
 	ib_driver_close ( 0 );
1547
 	ib_driver_close ( 0 );
1427
  err_ib_driver_init:
1548
  err_ib_driver_init:
1428
- err_query_fw:
1549
+
1550
+	arbel_stop_firmware ( arbel );
1551
+ err_start_firmware:
1429
 	free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
1552
 	free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
1430
  err_mailbox_out:
1553
  err_mailbox_out:
1431
 	free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
1554
 	free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
1446
 
1569
 
1447
 	ipoib_remove ( ibdev );
1570
 	ipoib_remove ( ibdev );
1448
 	ib_driver_close ( 0 );
1571
 	ib_driver_close ( 0 );
1572
+	arbel_stop_firmware ( arbel );
1449
 	free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
1573
 	free_dma ( arbel->mailbox_out, ARBEL_MBOX_SIZE );
1450
 	free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
1574
 	free_dma ( arbel->mailbox_in, ARBEL_MBOX_SIZE );
1451
 	free_ibdev ( ibdev );
1575
 	free_ibdev ( ibdev );

Loading…
Cancel
Save