瀏覽代碼

[hermon] Allocate only as much memory as is needed for ICM and ICM AUX

Use individual page mappings rather than a single whole-region
mapping, to avoid the waste of memory that occurs due to the
constraint that each mapped block must be aligned on its own size.
tags/v0.9.5
Michael Brown 15 年之前
父節點
當前提交
39047c5636
共有 1 個檔案被更改,包括 62 行新增47 行删除
  1. 62
    47
      src/drivers/infiniband/hermon.c

+ 62
- 47
src/drivers/infiniband/hermon.c 查看文件

@@ -1652,6 +1652,47 @@ static struct ib_device_operations hermon_ib_operations = {
1652 1652
  ***************************************************************************
1653 1653
  */
1654 1654
 
1655
+/**
1656
+ * Map virtual to physical address for firmware usage
1657
+ *
1658
+ * @v hermon		Hermon device
1659
+ * @v map		Mapping function
1660
+ * @v va		Virtual address
1661
+ * @v pa		Physical address
1662
+ * @v len		Length of region
1663
+ * @ret rc		Return status code
1664
+ */
1665
+static int hermon_map_vpm ( struct hermon *hermon,
1666
+			    int ( *map ) ( struct hermon *hermon,
1667
+			    const struct hermonprm_virtual_physical_mapping* ),
1668
+			    uint64_t va, physaddr_t pa, size_t len ) {
1669
+	struct hermonprm_virtual_physical_mapping mapping;
1670
+	int rc;
1671
+
1672
+	assert ( ( va & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
1673
+	assert ( ( pa & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
1674
+	assert ( ( len & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
1675
+
1676
+	while ( len ) {
1677
+		memset ( &mapping, 0, sizeof ( mapping ) );
1678
+		MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
1679
+		MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
1680
+		MLX_FILL_2 ( &mapping, 3,
1681
+			     log2size, 0,
1682
+			     pa_l, ( pa >> 12 ) );
1683
+		if ( ( rc = map ( hermon, &mapping ) ) != 0 ) {
1684
+			DBGC ( hermon, "Hermon %p could not map %llx => %lx: "
1685
+			       "%s\n", hermon, va, pa, strerror ( rc ) );
1686
+			return rc;
1687
+		}
1688
+		pa += HERMON_PAGE_SIZE;
1689
+		va += HERMON_PAGE_SIZE;
1690
+		len -= HERMON_PAGE_SIZE;
1691
+	}
1692
+
1693
+	return 0;
1694
+}
1695
+
1655 1696
 /**
1656 1697
  * Start firmware running
1657 1698
  *
@@ -1660,9 +1701,7 @@ static struct ib_device_operations hermon_ib_operations = {
1660 1701
  */
1661 1702
 static int hermon_start_firmware ( struct hermon *hermon ) {
1662 1703
 	struct hermonprm_query_fw fw;
1663
-	struct hermonprm_virtual_physical_mapping map_fa;
1664 1704
 	unsigned int fw_pages;
1665
-	unsigned int log2_fw_pages;
1666 1705
 	size_t fw_size;
1667 1706
 	physaddr_t fw_base;
1668 1707
 	int rc;
@@ -1677,27 +1716,21 @@ static int hermon_start_firmware ( struct hermon *hermon ) {
1677 1716
 	       MLX_GET ( &fw, fw_rev_major ), MLX_GET ( &fw, fw_rev_minor ),
1678 1717
 	       MLX_GET ( &fw, fw_rev_subminor ) );
1679 1718
 	fw_pages = MLX_GET ( &fw, fw_pages );
1680
-	log2_fw_pages = fls ( fw_pages - 1 );
1681
-	fw_pages = ( 1 << log2_fw_pages );
1682
-	DBGC ( hermon, "Hermon %p requires %d kB for firmware\n",
1683
-	       hermon, ( fw_pages * 4 ) );
1719
+	DBGC ( hermon, "Hermon %p requires %d pages (%d kB) for firmware\n",
1720
+	       hermon, fw_pages, ( fw_pages * ( HERMON_PAGE_SIZE / 1024 ) ) );
1684 1721
 
1685 1722
 	/* Allocate firmware pages and map firmware area */
1686 1723
 	fw_size = ( fw_pages * HERMON_PAGE_SIZE );
1687
-	hermon->firmware_area = umalloc ( fw_size * 2 );
1724
+	hermon->firmware_area = umalloc ( fw_size );
1688 1725
 	if ( ! hermon->firmware_area ) {
1689 1726
 		rc = -ENOMEM;
1690 1727
 		goto err_alloc_fa;
1691 1728
 	}
1692
-	fw_base = ( user_to_phys ( hermon->firmware_area, fw_size ) &
1693
-		    ~( fw_size - 1 ) );
1729
+	fw_base = user_to_phys ( hermon->firmware_area, 0 );
1694 1730
 	DBGC ( hermon, "Hermon %p firmware area at physical [%lx,%lx)\n",
1695 1731
 	       hermon, fw_base, ( fw_base + fw_size ) );
1696
-	memset ( &map_fa, 0, sizeof ( map_fa ) );
1697
-	MLX_FILL_2 ( &map_fa, 3,
1698
-		     log2size, log2_fw_pages,
1699
-		     pa_l, ( fw_base >> 12 ) );
1700
-	if ( ( rc = hermon_cmd_map_fa ( hermon, &map_fa ) ) != 0 ) {
1732
+	if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_fa,
1733
+				     0, fw_base, fw_size ) ) != 0 ) {
1701 1734
 		DBGC ( hermon, "Hermon %p could not map firmware: %s\n",
1702 1735
 		       hermon, strerror ( rc ) );
1703 1736
 		goto err_map_fa;
@@ -1714,8 +1747,8 @@ static int hermon_start_firmware ( struct hermon *hermon ) {
1714 1747
 	return 0;
1715 1748
 
1716 1749
  err_run_fw:
1717
-	hermon_cmd_unmap_fa ( hermon );
1718 1750
  err_map_fa:
1751
+	hermon_cmd_unmap_fa ( hermon );
1719 1752
 	ufree ( hermon->firmware_area );
1720 1753
 	hermon->firmware_area = UNULL;
1721 1754
  err_alloc_fa:
@@ -1816,8 +1849,6 @@ static int hermon_alloc_icm ( struct hermon *hermon,
1816 1849
 			      struct hermonprm_init_hca *init_hca ) {
1817 1850
 	struct hermonprm_scalar_parameter icm_size;
1818 1851
 	struct hermonprm_scalar_parameter icm_aux_size;
1819
-	struct hermonprm_virtual_physical_mapping map_icm_aux;
1820
-	struct hermonprm_virtual_physical_mapping map_icm;
1821 1852
 	uint64_t icm_offset = 0;
1822 1853
 	unsigned int log_num_qps, log_num_srqs, log_num_cqs, log_num_eqs;
1823 1854
 	unsigned int log_num_mtts, log_num_mpts;
@@ -2000,13 +2031,11 @@ static int hermon_alloc_icm ( struct hermon *hermon,
2000 2031
 		goto err_set_icm_size;
2001 2032
 	}
2002 2033
 	icm_aux_len = ( MLX_GET ( &icm_aux_size, value ) * HERMON_PAGE_SIZE );
2003
-	/* Must round up to nearest power of two :( */
2004
-	icm_aux_len = ( 1 << fls ( icm_aux_len - 1 ) );
2005 2034
 
2006 2035
 	/* Allocate ICM data and auxiliary area */
2007 2036
 	DBGC ( hermon, "Hermon %p requires %zd kB ICM and %zd kB AUX ICM\n",
2008 2037
 	       hermon, ( icm_len / 1024 ), ( icm_aux_len / 1024 ) );
2009
-	hermon->icm = umalloc ( 2 * icm_aux_len + icm_len );
2038
+	hermon->icm = umalloc ( icm_aux_len + icm_len );
2010 2039
 	if ( ! hermon->icm ) {
2011 2040
 		rc = -ENOMEM;
2012 2041
 		goto err_alloc;
@@ -2014,39 +2043,25 @@ static int hermon_alloc_icm ( struct hermon *hermon,
2014 2043
 	icm_phys = user_to_phys ( hermon->icm, 0 );
2015 2044
 
2016 2045
 	/* Map ICM auxiliary area */
2017
-	icm_phys = ( ( icm_phys + icm_aux_len - 1 ) & ~( icm_aux_len - 1 ) );
2018
-	memset ( &map_icm_aux, 0, sizeof ( map_icm_aux ) );
2019
-	MLX_FILL_2 ( &map_icm_aux, 3,
2020
-		     log2size, fls ( ( icm_aux_len / HERMON_PAGE_SIZE ) - 1 ),
2021
-		     pa_l, ( icm_phys >> 12 ) );
2022
-	DBGC ( hermon, "Hermon %p mapping ICM AUX (2^%d pages) => %08lx\n",
2023
-	       hermon, fls ( ( icm_aux_len / HERMON_PAGE_SIZE ) - 1 ),
2024
-	       icm_phys );
2025
-	if ( ( rc = hermon_cmd_map_icm_aux ( hermon, &map_icm_aux ) ) != 0 ) {
2046
+	DBGC ( hermon, "Hermon %p mapping ICM AUX => %08lx\n",
2047
+	       hermon, icm_phys );
2048
+	if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_icm_aux,
2049
+				     0, icm_phys, icm_aux_len ) ) != 0 ) {
2026 2050
 		DBGC ( hermon, "Hermon %p could not map AUX ICM: %s\n",
2027
-		       hermon, strerror ( rc ) );
2051
+		       hermon, strerror ( rc ) );		
2028 2052
 		goto err_map_icm_aux;
2029 2053
 	}
2030 2054
 	icm_phys += icm_aux_len;
2031 2055
 
2032 2056
 	/* MAP ICM area */
2033 2057
 	for ( i = 0 ; i < HERMON_ICM_NUM_REGIONS ; i++ ) {
2034
-		memset ( &map_icm, 0, sizeof ( map_icm ) );
2035
-		MLX_FILL_1 ( &map_icm, 0,
2036
-			     va_h, ( hermon->icm_map[i].offset >> 32 ) );
2037
-		MLX_FILL_1 ( &map_icm, 1,
2038
-			     va_l, ( hermon->icm_map[i].offset >> 12 ) );
2039
-		MLX_FILL_2 ( &map_icm, 3,
2040
-			     log2size,
2041
-			     fls ( ( hermon->icm_map[i].len /
2042
-				     HERMON_PAGE_SIZE ) - 1 ),
2043
-			     pa_l, ( icm_phys >> 12 ) );
2044
-		DBGC ( hermon, "Hermon %p mapping ICM %llx+%zx (2^%d pages) "
2045
-		       "=> %08lx\n", hermon, hermon->icm_map[i].offset,
2046
-		       hermon->icm_map[i].len,
2047
-		       fls ( ( hermon->icm_map[i].len /
2048
-			       HERMON_PAGE_SIZE ) - 1 ), icm_phys );
2049
-		if ( ( rc = hermon_cmd_map_icm ( hermon, &map_icm ) ) != 0 ) {
2058
+		DBGC ( hermon, "Hermon %p mapping ICM %llx+%zx => %08lx\n",
2059
+		       hermon, hermon->icm_map[i].offset,
2060
+		       hermon->icm_map[i].len, icm_phys );
2061
+		if ( ( rc = hermon_map_vpm ( hermon, hermon_cmd_map_icm,
2062
+					     hermon->icm_map[i].offset,
2063
+					     icm_phys,
2064
+					     hermon->icm_map[i].len ) ) != 0 ){
2050 2065
 			DBGC ( hermon, "Hermon %p could not map ICM: %s\n",
2051 2066
 			       hermon, strerror ( rc ) );
2052 2067
 			goto err_map_icm;
@@ -2058,8 +2073,8 @@ static int hermon_alloc_icm ( struct hermon *hermon,
2058 2073
 
2059 2074
  err_map_icm:
2060 2075
 	assert ( i == 0 ); /* We don't handle partial failure at present */
2061
-	hermon_cmd_unmap_icm_aux ( hermon );
2062 2076
  err_map_icm_aux:
2077
+	hermon_cmd_unmap_icm_aux ( hermon );
2063 2078
 	ufree ( hermon->icm );
2064 2079
 	hermon->icm = UNULL;
2065 2080
  err_alloc:

Loading…
取消
儲存