| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 | 
|  | 2 | #include <asm/byteorder.h> | 
|  | 3 | #include "vphn.h" | 
|  | 4 |  | 
|  | 5 | /* | 
|  | 6 | * The associativity domain numbers are returned from the hypervisor as a | 
|  | 7 | * stream of mixed 16-bit and 32-bit fields. The stream is terminated by the | 
|  | 8 | * special value of "all ones" (aka. 0xffff) and its size may not exceed 48 | 
|  | 9 | * bytes. | 
|  | 10 | * | 
|  | 11 | *    --- 16-bit fields --> | 
|  | 12 | *  _________________________ | 
|  | 13 | *  |  0  |  1  |  2  |  3  |   be_packed[0] | 
|  | 14 | *  ------+-----+-----+------ | 
|  | 15 | *  _________________________ | 
|  | 16 | *  |  4  |  5  |  6  |  7  |   be_packed[1] | 
|  | 17 | *  ------------------------- | 
|  | 18 | *            ... | 
|  | 19 | *  _________________________ | 
|  | 20 | *  | 20  | 21  | 22  | 23  |   be_packed[5] | 
|  | 21 | *  ------------------------- | 
|  | 22 | * | 
|  | 23 | * Convert to the sequence they would appear in the ibm,associativity property. | 
|  | 24 | */ | 
|  | 25 | int vphn_unpack_associativity(const long *packed, __be32 *unpacked) | 
|  | 26 | { | 
|  | 27 | __be64 be_packed[VPHN_REGISTER_COUNT]; | 
|  | 28 | int i, nr_assoc_doms = 0; | 
|  | 29 | const __be16 *field = (const __be16 *) be_packed; | 
|  | 30 | u16 last = 0; | 
|  | 31 | bool is_32bit = false; | 
|  | 32 |  | 
|  | 33 | #define VPHN_FIELD_UNUSED	(0xffff) | 
|  | 34 | #define VPHN_FIELD_MSB		(0x8000) | 
|  | 35 | #define VPHN_FIELD_MASK		(~VPHN_FIELD_MSB) | 
|  | 36 |  | 
|  | 37 | /* Let's fix the values returned by plpar_hcall9() */ | 
|  | 38 | for (i = 0; i < VPHN_REGISTER_COUNT; i++) | 
|  | 39 | be_packed[i] = cpu_to_be64(packed[i]); | 
|  | 40 |  | 
|  | 41 | for (i = 1; i < VPHN_ASSOC_BUFSIZE; i++) { | 
|  | 42 | u16 new = be16_to_cpup(field++); | 
|  | 43 |  | 
|  | 44 | if (is_32bit) { | 
|  | 45 | /* Let's concatenate the 16 bits of this field to the | 
|  | 46 | * 15 lower bits of the previous field | 
|  | 47 | */ | 
|  | 48 | unpacked[++nr_assoc_doms] = | 
|  | 49 | cpu_to_be32(last << 16 | new); | 
|  | 50 | is_32bit = false; | 
|  | 51 | } else if (new == VPHN_FIELD_UNUSED) | 
|  | 52 | /* This is the list terminator */ | 
|  | 53 | break; | 
|  | 54 | else if (new & VPHN_FIELD_MSB) { | 
|  | 55 | /* Data is in the lower 15 bits of this field */ | 
|  | 56 | unpacked[++nr_assoc_doms] = | 
|  | 57 | cpu_to_be32(new & VPHN_FIELD_MASK); | 
|  | 58 | } else { | 
|  | 59 | /* Data is in the lower 15 bits of this field | 
|  | 60 | * concatenated with the next 16 bit field | 
|  | 61 | */ | 
|  | 62 | last = new; | 
|  | 63 | is_32bit = true; | 
|  | 64 | } | 
|  | 65 | } | 
|  | 66 |  | 
|  | 67 | /* The first cell contains the length of the property */ | 
|  | 68 | unpacked[0] = cpu_to_be32(nr_assoc_doms); | 
|  | 69 |  | 
|  | 70 | return nr_assoc_doms; | 
|  | 71 | } |