aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>2015-03-30 21:53:38 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2015-04-11 06:49:21 -0400
commit145264e2129a5e2fca9bc75f666e80424020f9ea (patch)
tree92e4158a3b1dd63fe5749e37dba4cef853668235 /arch/powerpc
parented59190e41b725e1cfd79541f5fc66c20adb0671 (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.c77
-rw-r--r--arch/powerpc/perf/hv-24x7.h8
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
143static struct kmem_cache *hv_page_cache; 143static 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
151DEFINE_PER_CPU(char, hv_24x7_reqb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096);
152DEFINE_PER_CPU(char, hv_24x7_resb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096);
153
145static char *event_name(struct hv_24x7_event_data *ev, int *len) 154static 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
979DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096);
980DEFINE_PER_CPU(char, hv_24x7_resb[4096]) __aligned(4096);
981
982static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, 988static 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]);
1046out: 1043out:
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
56struct hv_24x7_result_element { 56struct 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
72struct hv_24x7_result { 72struct 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
93struct hv_24x7_data_result_buffer { 93struct 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