mirror of
https://github.com/xcat2/xNBA.git
synced 2025-02-19 03:54:38 +00:00
[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>
This commit is contained in:
parent
8cd2b170b6
commit
92ced72080
@ -2136,35 +2136,67 @@ static int hermon_map_vpm ( struct hermon *hermon,
|
||||
const struct hermonprm_virtual_physical_mapping* ),
|
||||
uint64_t va, physaddr_t pa, size_t len ) {
|
||||
struct hermonprm_virtual_physical_mapping mapping;
|
||||
physaddr_t start;
|
||||
physaddr_t low;
|
||||
physaddr_t high;
|
||||
physaddr_t end;
|
||||
size_t size;
|
||||
int rc;
|
||||
|
||||
/* Sanity checks */
|
||||
assert ( ( va & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
|
||||
assert ( ( pa & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
|
||||
assert ( ( len & ( HERMON_PAGE_SIZE - 1 ) ) == 0 );
|
||||
|
||||
/* Calculate starting points */
|
||||
start = pa;
|
||||
end = ( start + len );
|
||||
size = ( 1UL << ( fls ( start ^ end ) - 1 ) );
|
||||
low = high = ( end & ~( size - 1 ) );
|
||||
assert ( start < low );
|
||||
assert ( high <= end );
|
||||
|
||||
/* These mappings tend to generate huge volumes of
|
||||
* uninteresting debug data, which basically makes it
|
||||
* impossible to use debugging otherwise.
|
||||
*/
|
||||
DBG_DISABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
|
||||
|
||||
while ( len ) {
|
||||
/* Map blocks in descending order of size */
|
||||
while ( size >= HERMON_PAGE_SIZE ) {
|
||||
|
||||
/* Find the next candidate block */
|
||||
if ( ( low - size ) >= start ) {
|
||||
low -= size;
|
||||
pa = low;
|
||||
} else if ( ( high + size ) <= end ) {
|
||||
pa = high;
|
||||
high += size;
|
||||
} else {
|
||||
size >>= 1;
|
||||
continue;
|
||||
}
|
||||
assert ( ( va & ( size - 1 ) ) == 0 );
|
||||
assert ( ( pa & ( size - 1 ) ) == 0 );
|
||||
|
||||
/* Map this block */
|
||||
memset ( &mapping, 0, sizeof ( mapping ) );
|
||||
MLX_FILL_1 ( &mapping, 0, va_h, ( va >> 32 ) );
|
||||
MLX_FILL_1 ( &mapping, 1, va_l, ( va >> 12 ) );
|
||||
MLX_FILL_2 ( &mapping, 3,
|
||||
log2size, 0,
|
||||
log2size, ( ( fls ( size ) - 1 ) - 12 ),
|
||||
pa_l, ( pa >> 12 ) );
|
||||
if ( ( rc = map ( hermon, &mapping ) ) != 0 ) {
|
||||
DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
|
||||
DBGC ( hermon, "Hermon %p could not map %llx => %lx: "
|
||||
"%s\n", hermon, va, pa, strerror ( rc ) );
|
||||
DBGC ( hermon, "Hermon %p could not map %08llx+%zx to "
|
||||
"%08lx: %s\n",
|
||||
hermon, va, size, pa, strerror ( rc ) );
|
||||
return rc;
|
||||
}
|
||||
pa += HERMON_PAGE_SIZE;
|
||||
va += HERMON_PAGE_SIZE;
|
||||
len -= HERMON_PAGE_SIZE;
|
||||
va += size;
|
||||
}
|
||||
assert ( low == start );
|
||||
assert ( high == end );
|
||||
|
||||
DBG_ENABLE ( DBGLVL_LOG | DBGLVL_EXTRA );
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user