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