aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>2016-02-09 02:47:45 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2016-02-09 22:30:56 -0500
commite4f226b1580b36550727c324b404207f8d2f3b71 (patch)
treeb82bf85d24eff279bb9c2de64898d35f401689d1
parentbe283eeb7f6d9165b3c50f5222123ac25cf0d417 (diff)
powerpc/perf/hv-gpci: Increase request buffer size
The GPCI hcall allows for a 4K buffer but we limit the buffer to 1K. The problem with a 1K buffer is if a request results in returning more values than can be accomodated in the 1K buffer the request will fail. The buffer we are using is currently allocated on the stack and hence limited in size. Instead use a per-CPU 4K buffer like we do with 24x7 counters (hv-24x7.c). While here, rename the macro GPCI_MAX_DATA_BYTES to HGPCI_MAX_DATA_BYTES for consistency with 24x7 counters. Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--arch/powerpc/perf/hv-gpci.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
index 856fe6e03c2a..7aa37236bb70 100644
--- a/arch/powerpc/perf/hv-gpci.c
+++ b/arch/powerpc/perf/hv-gpci.c
@@ -127,8 +127,16 @@ static const struct attribute_group *attr_groups[] = {
127 NULL, 127 NULL,
128}; 128};
129 129
130#define GPCI_MAX_DATA_BYTES \ 130#define HGPCI_REQ_BUFFER_SIZE 4096
131 (1024 - sizeof(struct hv_get_perf_counter_info_params)) 131#define HGPCI_MAX_DATA_BYTES \
132 (HGPCI_REQ_BUFFER_SIZE - sizeof(struct hv_get_perf_counter_info_params))
133
134DEFINE_PER_CPU(char, hv_gpci_reqb[HGPCI_REQ_BUFFER_SIZE]) __aligned(sizeof(uint64_t));
135
136struct hv_gpci_request_buffer {
137 struct hv_get_perf_counter_info_params params;
138 uint8_t bytes[HGPCI_MAX_DATA_BYTES];
139} __packed;
132 140
133static unsigned long single_gpci_request(u32 req, u32 starting_index, 141static unsigned long single_gpci_request(u32 req, u32 starting_index,
134 u16 secondary_index, u8 version_in, u32 offset, u8 length, 142 u16 secondary_index, u8 version_in, u32 offset, u8 length,
@@ -137,24 +145,21 @@ static unsigned long single_gpci_request(u32 req, u32 starting_index,
137 unsigned long ret; 145 unsigned long ret;
138 size_t i; 146 size_t i;
139 u64 count; 147 u64 count;
148 struct hv_gpci_request_buffer *arg;
149
150 arg = (void *)get_cpu_var(hv_gpci_reqb);
151 memset(arg, 0, HGPCI_REQ_BUFFER_SIZE);
140 152
141 struct { 153 arg->params.counter_request = cpu_to_be32(req);
142 struct hv_get_perf_counter_info_params params; 154 arg->params.starting_index = cpu_to_be32(starting_index);
143 uint8_t bytes[GPCI_MAX_DATA_BYTES]; 155 arg->params.secondary_index = cpu_to_be16(secondary_index);
144 } __packed __aligned(sizeof(uint64_t)) arg = { 156 arg->params.counter_info_version_in = version_in;
145 .params = {
146 .counter_request = cpu_to_be32(req),
147 .starting_index = cpu_to_be32(starting_index),
148 .secondary_index = cpu_to_be16(secondary_index),
149 .counter_info_version_in = version_in,
150 }
151 };
152 157
153 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO, 158 ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
154 virt_to_phys(&arg), sizeof(arg)); 159 virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
155 if (ret) { 160 if (ret) {
156 pr_devel("hcall failed: 0x%lx\n", ret); 161 pr_devel("hcall failed: 0x%lx\n", ret);
157 return ret; 162 goto out;
158 } 163 }
159 164
160 /* 165 /*
@@ -163,9 +168,11 @@ static unsigned long single_gpci_request(u32 req, u32 starting_index,
163 */ 168 */
164 count = 0; 169 count = 0;
165 for (i = offset; i < offset + length; i++) 170 for (i = offset; i < offset + length; i++)
166 count |= arg.bytes[i] << (i - offset); 171 count |= arg->bytes[i] << (i - offset);
167 172
168 *value = count; 173 *value = count;
174out:
175 put_cpu_var(hv_gpci_reqb);
169 return ret; 176 return ret;
170} 177}
171 178
@@ -245,10 +252,10 @@ static int h_gpci_event_init(struct perf_event *event)
245 } 252 }
246 253
247 /* last byte within the buffer? */ 254 /* last byte within the buffer? */
248 if ((event_get_offset(event) + length) > GPCI_MAX_DATA_BYTES) { 255 if ((event_get_offset(event) + length) > HGPCI_MAX_DATA_BYTES) {
249 pr_devel("request outside of buffer: %zu > %zu\n", 256 pr_devel("request outside of buffer: %zu > %zu\n",
250 (size_t)event_get_offset(event) + length, 257 (size_t)event_get_offset(event) + length,
251 GPCI_MAX_DATA_BYTES); 258 HGPCI_MAX_DATA_BYTES);
252 return -EINVAL; 259 return -EINVAL;
253 } 260 }
254 261