|
@@ -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:
|