2015-02-23 18:14:31 +03:00
# include <asm/byteorder.h>
# include "vphn.h"
/*
2015-02-23 18:14:37 +03:00
* The associativity domain numbers are returned from the hypervisor as a
* stream of mixed 16 - bit and 32 - bit fields . The stream is terminated by the
* special value of " all ones " ( aka . 0xffff ) and its size may not exceed 48
* bytes .
*
* - - - 16 - bit fields - - >
* _________________________
* | 0 | 1 | 2 | 3 | be_packed [ 0 ]
* - - - - - - + - - - - - + - - - - - + - - - - - -
* _________________________
* | 4 | 5 | 6 | 7 | be_packed [ 1 ]
* - - - - - - - - - - - - - - - - - - - - - - - - -
* . . .
* _________________________
* | 20 | 21 | 22 | 23 | be_packed [ 5 ]
* - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Convert to the sequence they would appear in the ibm , associativity property .
2015-02-23 18:14:31 +03:00
*/
int vphn_unpack_associativity ( const long * packed , __be32 * unpacked )
{
__be64 be_packed [ VPHN_REGISTER_COUNT ] ;
int i , nr_assoc_doms = 0 ;
const __be16 * field = ( const __be16 * ) be_packed ;
2015-02-23 18:14:37 +03:00
u16 last = 0 ;
bool is_32bit = false ;
2015-02-23 18:14:31 +03:00
# define VPHN_FIELD_UNUSED (0xffff)
# define VPHN_FIELD_MSB (0x8000)
# define VPHN_FIELD_MASK (~VPHN_FIELD_MSB)
2015-02-23 18:14:37 +03:00
/* Let's fix the values returned by plpar_hcall9() */
2015-02-23 18:14:31 +03:00
for ( i = 0 ; i < VPHN_REGISTER_COUNT ; i + + )
be_packed [ i ] = cpu_to_be64 ( packed [ i ] ) ;
for ( i = 1 ; i < VPHN_ASSOC_BUFSIZE ; i + + ) {
2015-02-23 18:14:37 +03:00
u16 new = be16_to_cpup ( field + + ) ;
if ( is_32bit ) {
/* Let's concatenate the 16 bits of this field to the
* 15 lower bits of the previous field
2015-02-23 18:14:31 +03:00
*/
2015-02-23 18:14:37 +03:00
unpacked [ + + nr_assoc_doms ] =
cpu_to_be32 ( last < < 16 | new ) ;
is_32bit = false ;
} else if ( new = = VPHN_FIELD_UNUSED )
/* This is the list terminator */
break ;
else if ( new & VPHN_FIELD_MSB ) {
2015-02-23 18:14:31 +03:00
/* Data is in the lower 15 bits of this field */
2015-02-23 18:14:37 +03:00
unpacked [ + + nr_assoc_doms ] =
cpu_to_be32 ( new & VPHN_FIELD_MASK ) ;
2015-02-23 18:14:31 +03:00
} else {
/* Data is in the lower 15 bits of this field
* concatenated with the next 16 bit field
*/
2015-02-23 18:14:37 +03:00
last = new ;
is_32bit = true ;
2015-02-23 18:14:31 +03:00
}
}
/* The first cell contains the length of the property */
unpacked [ 0 ] = cpu_to_be32 ( nr_assoc_doms ) ;
return nr_assoc_doms ;
}