Kaynağa Gözat

[hermon] Minimise the number of VPM mapping operations

Mapping a single page at a time causes a several-second delay at
device initialisation time.  Reduce this by mapping multiple pages at
a time, using the largest block sizes possible given the alignment
constraints.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 yıl önce
ebeveyn
işleme
92ced72080
1 değiştirilmiş dosya ile 39 ekleme ve 7 silme
  1. 39
    7
      src/drivers/infiniband/hermon.c

+ 39
- 7
src/drivers/infiniband/hermon.c Dosyayı Görüntüle

@@ -2136,35 +2136,67 @@ static int hermon_map_vpm ( struct hermon *hermon,
2136 2136
 			    const struct hermonprm_virtual_physical_mapping* ),
2137 2137
 			    uint64_t va, physaddr_t pa, size_t len ) {
2138 2138
 	struct hermonprm_virtual_physical_mapping mapping;
2139
+	physaddr_t start;
2140
+	physaddr_t low;
2141
+	physaddr_t high;
2142
+	physaddr_t end;
2143
+	size_t size;
2139 2144
 	int rc;
2140 2145
 
2146
+	/* Sanity checks */
2141 2147
 	assert ( ( va & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
2142 2148
 	assert ( ( pa & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
2143 2149
 	assert ( ( len & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
2144 2150
 
2151
+	/* Calculate starting points */
2152
+	start = pa;
2153
+	end = ( start + len );
2154
+	size = ( 1UL << ( fls ( start ^ end ) - 1 ) );
2155
+	low = high = ( end & ~( size - 1 ) );
2156
+	assert ( start < low );
2157
+	assert ( high <= end );
2158
+
2145 2159
 	/* These mappings tend to generate huge volumes of
2146 2160
 	 * uninteresting debug data, which basically makes it
2147 2161
 	 * impossible to use debugging otherwise.
2148 2162
 	 */
2149 2163
 	DBG_DISABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
2150 2164
 
2151
-	while ( len ) {
2165
+	/* Map blocks in descending order of size */
2166
+	while ( size >= HERMON_PAGE_SIZE ) {
2167
+
2168
+		/* Find the next candidate block */
2169
+		if ( ( low - size ) >= start ) {
2170
+			low -= size;
2171
+			pa = low;
2172
+		} else if ( ( high + size ) <= end ) {
2173
+			pa = high;
2174
+			high += size;
2175
+		} else {
2176
+			size >>= 1;
2177
+			continue;
2178
+		}
2179
+		assert ( ( va & ( size - 1 ) ) == 0 );
2180
+		assert ( ( pa & ( size - 1 ) ) == 0 );
2181
+
2182
+		/* Map this block */
2152 2183
 		memset ( &mapping, 0, sizeof ( mapping ) );
2153 2184
 		MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
2154 2185
 		MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
2155 2186
 		MLX_FILL_2 ( &mapping, 3,
2156
-			     log2size, 0,
2187
+			     log2size, ( ( fls ( size ) - 1 ) - 12 ),
2157 2188
 			     pa_l, ( pa >> 12 ) );
2158 2189
 		if ( ( rc = map ( hermon, &mapping ) ) != 0 ) {
2159 2190
 			DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
2160
-			DBGC ( hermon, "Hermon %p could not map %llx => %lx: "
2161
-			       "%s\n", hermon, va, pa, strerror ( rc ) );
2191
+			DBGC ( hermon, "Hermon %p could not map %08llx+%zx to "
2192
+			       "%08lx: %s\n",
2193
+			       hermon, va, size, pa, strerror ( rc ) );
2162 2194
 			return rc;
2163 2195
 		}
2164
-		pa += HERMON_PAGE_SIZE;
2165
-		va += HERMON_PAGE_SIZE;
2166
-		len -= HERMON_PAGE_SIZE;
2196
+		va += size;
2167 2197
 	}
2198
+	assert ( low == start );
2199
+	assert ( high == end );
2168 2200
 
2169 2201
 	DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
2170 2202
 	return 0;

Loading…
İptal
Kaydet