diff options
author | Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> | 2015-03-30 21:53:38 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-04-11 06:49:21 -0400 |
commit | 145264e2129a5e2fca9bc75f666e80424020f9ea (patch) | |
tree | 92e4158a3b1dd63fe5749e37dba4cef853668235 /arch/powerpc | |
parent | ed59190e41b725e1cfd79541f5fc66c20adb0671 (diff) |
powerpc/perf/hv-24x7: Modify definition of request and result buffers
The parameters to the 24x7 HCALL have variable number of elements in them.
Set the minimum number of such elements to 1 rather than 0 and eliminate
the temporary structures.
This would enable us to submit multiple counter requests and process
multiple results from a single HCALL (in a follow on patch).
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/perf/hv-24x7.c | 77 | ||||
-rw-r--r-- | arch/powerpc/perf/hv-24x7.h | 8 |
2 files changed, 41 insertions, 44 deletions
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index 9445a824819e..408e6e9ff449 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c | |||
@@ -142,6 +142,15 @@ static struct attribute_group event_long_desc_group = { | |||
142 | 142 | ||
143 | static struct kmem_cache *hv_page_cache; | 143 | static struct kmem_cache *hv_page_cache; |
144 | 144 | ||
145 | /* | ||
146 | * request_buffer and result_buffer are not required to be 4k aligned, | ||
147 | * but are not allowed to cross any 4k boundary. Aligning them to 4k is | ||
148 | * the simplest way to ensure that. | ||
149 | */ | ||
150 | #define H24x7_DATA_BUFFER_SIZE 4096 | ||
151 | DEFINE_PER_CPU(char, hv_24x7_reqb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096); | ||
152 | DEFINE_PER_CPU(char, hv_24x7_resb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096); | ||
153 | |||
145 | static char *event_name(struct hv_24x7_event_data *ev, int *len) | 154 | static char *event_name(struct hv_24x7_event_data *ev, int *len) |
146 | { | 155 | { |
147 | *len = be16_to_cpu(ev->event_name_len) - 2; | 156 | *len = be16_to_cpu(ev->event_name_len) - 2; |
@@ -976,31 +985,16 @@ static const struct attribute_group *attr_groups[] = { | |||
976 | NULL, | 985 | NULL, |
977 | }; | 986 | }; |
978 | 987 | ||
979 | DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096); | ||
980 | DEFINE_PER_CPU(char, hv_24x7_resb[4096]) __aligned(4096); | ||
981 | |||
982 | static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, | 988 | static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, |
983 | u16 lpar, u64 *res, | 989 | u16 lpar, u64 *count, |
984 | bool success_expected) | 990 | bool success_expected) |
985 | { | 991 | { |
986 | unsigned long ret; | 992 | unsigned long ret; |
987 | 993 | ||
988 | /* | 994 | struct hv_24x7_request_buffer *request_buffer; |
989 | * request_buffer and result_buffer are not required to be 4k aligned, | 995 | struct hv_24x7_data_result_buffer *result_buffer; |
990 | * but are not allowed to cross any 4k boundary. Aligning them to 4k is | 996 | struct hv_24x7_result *resb; |
991 | * the simplest way to ensure that. | 997 | struct hv_24x7_request *req; |
992 | */ | ||
993 | struct reqb { | ||
994 | struct hv_24x7_request_buffer buf; | ||
995 | struct hv_24x7_request req; | ||
996 | } __packed *request_buffer; | ||
997 | |||
998 | struct { | ||
999 | struct hv_24x7_data_result_buffer buf; | ||
1000 | struct hv_24x7_result res; | ||
1001 | struct hv_24x7_result_element elem; | ||
1002 | __be64 result; | ||
1003 | } __packed *result_buffer; | ||
1004 | 998 | ||
1005 | BUILD_BUG_ON(sizeof(*request_buffer) > 4096); | 999 | BUILD_BUG_ON(sizeof(*request_buffer) > 4096); |
1006 | BUILD_BUG_ON(sizeof(*result_buffer) > 4096); | 1000 | BUILD_BUG_ON(sizeof(*result_buffer) > 4096); |
@@ -1011,38 +1005,41 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, | |||
1011 | memset(request_buffer, 0, 4096); | 1005 | memset(request_buffer, 0, 4096); |
1012 | memset(result_buffer, 0, 4096); | 1006 | memset(result_buffer, 0, 4096); |
1013 | 1007 | ||
1014 | *request_buffer = (struct reqb) { | 1008 | request_buffer->interface_version = HV_24X7_IF_VERSION_CURRENT; |
1015 | .buf = { | 1009 | request_buffer->num_requests = 1; |
1016 | .interface_version = HV_24X7_IF_VERSION_CURRENT, | 1010 | |
1017 | .num_requests = 1, | 1011 | req = &request_buffer->requests[0]; |
1018 | }, | ||
1019 | .req = { | ||
1020 | .performance_domain = domain, | ||
1021 | .data_size = cpu_to_be16(8), | ||
1022 | .data_offset = cpu_to_be32(offset), | ||
1023 | .starting_lpar_ix = cpu_to_be16(lpar), | ||
1024 | .max_num_lpars = cpu_to_be16(1), | ||
1025 | .starting_ix = cpu_to_be16(ix), | ||
1026 | .max_ix = cpu_to_be16(1), | ||
1027 | } | ||
1028 | }; | ||
1029 | 1012 | ||
1013 | req->performance_domain = domain; | ||
1014 | req->data_size = cpu_to_be16(8); | ||
1015 | req->data_offset = cpu_to_be32(offset); | ||
1016 | req->starting_lpar_ix = cpu_to_be16(lpar), | ||
1017 | req->max_num_lpars = cpu_to_be16(1); | ||
1018 | req->starting_ix = cpu_to_be16(ix); | ||
1019 | req->max_ix = cpu_to_be16(1); | ||
1020 | |||
1021 | /* | ||
1022 | * NOTE: Due to variable number of array elements in request and | ||
1023 | * result buffer(s), sizeof() is not reliable. Use the actual | ||
1024 | * allocated buffer size, H24x7_DATA_BUFFER_SIZE. | ||
1025 | */ | ||
1030 | ret = plpar_hcall_norets(H_GET_24X7_DATA, | 1026 | ret = plpar_hcall_norets(H_GET_24X7_DATA, |
1031 | virt_to_phys(request_buffer), sizeof(*request_buffer), | 1027 | virt_to_phys(request_buffer), H24x7_DATA_BUFFER_SIZE, |
1032 | virt_to_phys(result_buffer), sizeof(*result_buffer)); | 1028 | virt_to_phys(result_buffer), H24x7_DATA_BUFFER_SIZE); |
1033 | 1029 | ||
1034 | if (ret) { | 1030 | if (ret) { |
1035 | if (success_expected) | 1031 | if (success_expected) |
1036 | pr_err_ratelimited("hcall failed: %d %#x %#x %d => " | 1032 | pr_err_ratelimited("hcall failed: %d %#x %#x %d => " |
1037 | "0x%lx (%ld) detail=0x%x failing ix=%x\n", | 1033 | "0x%lx (%ld) detail=0x%x failing ix=%x\n", |
1038 | domain, offset, ix, lpar, ret, ret, | 1034 | domain, offset, ix, lpar, ret, ret, |
1039 | result_buffer->buf.detailed_rc, | 1035 | result_buffer->detailed_rc, |
1040 | result_buffer->buf.failing_request_ix); | 1036 | result_buffer->failing_request_ix); |
1041 | goto out; | 1037 | goto out; |
1042 | } | 1038 | } |
1043 | 1039 | ||
1044 | *res = be64_to_cpu(result_buffer->result); | 1040 | resb = &result_buffer->results[0]; |
1045 | 1041 | ||
1042 | *count = be64_to_cpu(resb->elements[0].element_data[0]); | ||
1046 | out: | 1043 | out: |
1047 | return ret; | 1044 | return ret; |
1048 | } | 1045 | } |
diff --git a/arch/powerpc/perf/hv-24x7.h b/arch/powerpc/perf/hv-24x7.h index 69cd4e690f58..0f9fa21a29f2 100644 --- a/arch/powerpc/perf/hv-24x7.h +++ b/arch/powerpc/perf/hv-24x7.h | |||
@@ -50,7 +50,7 @@ struct hv_24x7_request_buffer { | |||
50 | __u8 interface_version; | 50 | __u8 interface_version; |
51 | __u8 num_requests; | 51 | __u8 num_requests; |
52 | __u8 reserved[0xE]; | 52 | __u8 reserved[0xE]; |
53 | struct hv_24x7_request requests[]; | 53 | struct hv_24x7_request requests[1]; |
54 | } __packed; | 54 | } __packed; |
55 | 55 | ||
56 | struct hv_24x7_result_element { | 56 | struct hv_24x7_result_element { |
@@ -66,7 +66,7 @@ struct hv_24x7_result_element { | |||
66 | __be32 lpar_cfg_instance_id; | 66 | __be32 lpar_cfg_instance_id; |
67 | 67 | ||
68 | /* size = @result_element_data_size of cointaining result. */ | 68 | /* size = @result_element_data_size of cointaining result. */ |
69 | __u8 element_data[]; | 69 | __u64 element_data[1]; |
70 | } __packed; | 70 | } __packed; |
71 | 71 | ||
72 | struct hv_24x7_result { | 72 | struct hv_24x7_result { |
@@ -87,7 +87,7 @@ struct hv_24x7_result { | |||
87 | /* WARNING: only valid for first result element due to variable sizes | 87 | /* WARNING: only valid for first result element due to variable sizes |
88 | * of result elements */ | 88 | * of result elements */ |
89 | /* struct hv_24x7_result_element[@num_elements_returned] */ | 89 | /* struct hv_24x7_result_element[@num_elements_returned] */ |
90 | struct hv_24x7_result_element elements[]; | 90 | struct hv_24x7_result_element elements[1]; |
91 | } __packed; | 91 | } __packed; |
92 | 92 | ||
93 | struct hv_24x7_data_result_buffer { | 93 | struct hv_24x7_data_result_buffer { |
@@ -103,7 +103,7 @@ struct hv_24x7_data_result_buffer { | |||
103 | __u8 reserved2[0x8]; | 103 | __u8 reserved2[0x8]; |
104 | /* WARNING: only valid for the first result due to variable sizes of | 104 | /* WARNING: only valid for the first result due to variable sizes of |
105 | * results */ | 105 | * results */ |
106 | struct hv_24x7_result results[]; /* [@num_results] */ | 106 | struct hv_24x7_result results[1]; /* [@num_results] */ |
107 | } __packed; | 107 | } __packed; |
108 | 108 | ||
109 | #endif | 109 | #endif |