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) { | |
47d99948 CL |
45 | /* |
46 | * Let's concatenate the 16 bits of this field to the | |
3338a65b | 47 | * 15 lower bits of the previous field |
4b6cfb2a | 48 | */ |
3338a65b GK |
49 | unpacked[++nr_assoc_doms] = |
50 | cpu_to_be32(last << 16 | new); | |
51 | is_32bit = false; | |
52 | } else if (new == VPHN_FIELD_UNUSED) | |
53 | /* This is the list terminator */ | |
54 | break; | |
55 | else if (new & VPHN_FIELD_MSB) { | |
4b6cfb2a | 56 | /* Data is in the lower 15 bits of this field */ |
3338a65b GK |
57 | unpacked[++nr_assoc_doms] = |
58 | cpu_to_be32(new & VPHN_FIELD_MASK); | |
4b6cfb2a | 59 | } else { |
47d99948 CL |
60 | /* |
61 | * Data is in the lower 15 bits of this field | |
4b6cfb2a GK |
62 | * concatenated with the next 16 bit field |
63 | */ | |
3338a65b GK |
64 | last = new; |
65 | is_32bit = true; | |
4b6cfb2a GK |
66 | } |
67 | } | |
68 | ||
69 | /* The first cell contains the length of the property */ | |
70 | unpacked[0] = cpu_to_be32(nr_assoc_doms); | |
71 | ||
72 | return nr_assoc_doms; | |
73 | } |