Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
4b6cfb2a GK |
2 | #include <asm/byteorder.h> |
3 | #include "vphn.h" | |
4 | ||
5 | /* | |
3338a65b GK |
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. | |
4b6cfb2a GK |
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; | |
3338a65b GK |
30 | u16 last = 0; |
31 | bool is_32bit = false; | |
4b6cfb2a GK |
32 | |
33 | #define VPHN_FIELD_UNUSED (0xffff) | |
34 | #define VPHN_FIELD_MSB (0x8000) | |
35 | #define VPHN_FIELD_MASK (~VPHN_FIELD_MSB) | |
36 | ||
3338a65b | 37 | /* Let's fix the values returned by plpar_hcall9() */ |
4b6cfb2a GK |
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++) { | |
3338a65b GK |
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 | |
4b6cfb2a | 47 | */ |
3338a65b GK |
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) { | |
4b6cfb2a | 55 | /* Data is in the lower 15 bits of this field */ |
3338a65b GK |
56 | unpacked[++nr_assoc_doms] = |
57 | cpu_to_be32(new & VPHN_FIELD_MASK); | |
4b6cfb2a GK |
58 | } else { |
59 | /* Data is in the lower 15 bits of this field | |
60 | * concatenated with the next 16 bit field | |
61 | */ | |
3338a65b GK |
62 | last = new; |
63 | is_32bit = true; | |
4b6cfb2a GK |
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 | } |