Commit 145264e2 authored by Sukadev Bhattiprolu's avatar Sukadev Bhattiprolu Committed by Michael Ellerman

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: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent ed59190e
...@@ -142,6 +142,15 @@ static struct attribute_group event_long_desc_group = { ...@@ -142,6 +142,15 @@ static struct attribute_group event_long_desc_group = {
static struct kmem_cache *hv_page_cache; static struct kmem_cache *hv_page_cache;
/*
* request_buffer and result_buffer are not required to be 4k aligned,
* but are not allowed to cross any 4k boundary. Aligning them to 4k is
* the simplest way to ensure that.
*/
#define H24x7_DATA_BUFFER_SIZE 4096
DEFINE_PER_CPU(char, hv_24x7_reqb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096);
DEFINE_PER_CPU(char, hv_24x7_resb[H24x7_DATA_BUFFER_SIZE]) __aligned(4096);
static char *event_name(struct hv_24x7_event_data *ev, int *len) static char *event_name(struct hv_24x7_event_data *ev, int *len)
{ {
*len = be16_to_cpu(ev->event_name_len) - 2; *len = be16_to_cpu(ev->event_name_len) - 2;
...@@ -976,31 +985,16 @@ static const struct attribute_group *attr_groups[] = { ...@@ -976,31 +985,16 @@ static const struct attribute_group *attr_groups[] = {
NULL, NULL,
}; };
DEFINE_PER_CPU(char, hv_24x7_reqb[4096]) __aligned(4096);
DEFINE_PER_CPU(char, hv_24x7_resb[4096]) __aligned(4096);
static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix,
u16 lpar, u64 *res, u16 lpar, u64 *count,
bool success_expected) bool success_expected)
{ {
unsigned long ret; unsigned long ret;
/* struct hv_24x7_request_buffer *request_buffer;
* request_buffer and result_buffer are not required to be 4k aligned, struct hv_24x7_data_result_buffer *result_buffer;
* but are not allowed to cross any 4k boundary. Aligning them to 4k is struct hv_24x7_result *resb;
* the simplest way to ensure that. struct hv_24x7_request *req;
*/
struct reqb {
struct hv_24x7_request_buffer buf;
struct hv_24x7_request req;
} __packed *request_buffer;
struct {
struct hv_24x7_data_result_buffer buf;
struct hv_24x7_result res;
struct hv_24x7_result_element elem;
__be64 result;
} __packed *result_buffer;
BUILD_BUG_ON(sizeof(*request_buffer) > 4096); BUILD_BUG_ON(sizeof(*request_buffer) > 4096);
BUILD_BUG_ON(sizeof(*result_buffer) > 4096); BUILD_BUG_ON(sizeof(*result_buffer) > 4096);
...@@ -1011,38 +1005,41 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix, ...@@ -1011,38 +1005,41 @@ static unsigned long single_24x7_request(u8 domain, u32 offset, u16 ix,
memset(request_buffer, 0, 4096); memset(request_buffer, 0, 4096);
memset(result_buffer, 0, 4096); memset(result_buffer, 0, 4096);
*request_buffer = (struct reqb) { request_buffer->interface_version = HV_24X7_IF_VERSION_CURRENT;
.buf = { request_buffer->num_requests = 1;
.interface_version = HV_24X7_IF_VERSION_CURRENT,
.num_requests = 1, req = &request_buffer->requests[0];
},
.req = {
.performance_domain = domain,
.data_size = cpu_to_be16(8),
.data_offset = cpu_to_be32(offset),
.starting_lpar_ix = cpu_to_be16(lpar),
.max_num_lpars = cpu_to_be16(1),
.starting_ix = cpu_to_be16(ix),
.max_ix = cpu_to_be16(1),
}
};
req->performance_domain = domain;
req->data_size = cpu_to_be16(8);
req->data_offset = cpu_to_be32(offset);
req->starting_lpar_ix = cpu_to_be16(lpar),
req->max_num_lpars = cpu_to_be16(1);
req->starting_ix = cpu_to_be16(ix);
req->max_ix = cpu_to_be16(1);
/*
* NOTE: Due to variable number of array elements in request and
* result buffer(s), sizeof() is not reliable. Use the actual
* allocated buffer size, H24x7_DATA_BUFFER_SIZE.
*/
ret = plpar_hcall_norets(H_GET_24X7_DATA, ret = plpar_hcall_norets(H_GET_24X7_DATA,
virt_to_phys(request_buffer), sizeof(*request_buffer), virt_to_phys(request_buffer), H24x7_DATA_BUFFER_SIZE,
virt_to_phys(result_buffer), sizeof(*result_buffer)); virt_to_phys(result_buffer), H24x7_DATA_BUFFER_SIZE);
if (ret) { if (ret) {
if (success_expected) if (success_expected)
pr_err_ratelimited("hcall failed: %d %#x %#x %d => " pr_err_ratelimited("hcall failed: %d %#x %#x %d => "
"0x%lx (%ld) detail=0x%x failing ix=%x\n", "0x%lx (%ld) detail=0x%x failing ix=%x\n",
domain, offset, ix, lpar, ret, ret, domain, offset, ix, lpar, ret, ret,
result_buffer->buf.detailed_rc, result_buffer->detailed_rc,
result_buffer->buf.failing_request_ix); result_buffer->failing_request_ix);
goto out; goto out;
} }
*res = be64_to_cpu(result_buffer->result); resb = &result_buffer->results[0];
*count = be64_to_cpu(resb->elements[0].element_data[0]);
out: out:
return ret; return ret;
} }
......
...@@ -50,7 +50,7 @@ struct hv_24x7_request_buffer { ...@@ -50,7 +50,7 @@ struct hv_24x7_request_buffer {
__u8 interface_version; __u8 interface_version;
__u8 num_requests; __u8 num_requests;
__u8 reserved[0xE]; __u8 reserved[0xE];
struct hv_24x7_request requests[]; struct hv_24x7_request requests[1];
} __packed; } __packed;
struct hv_24x7_result_element { struct hv_24x7_result_element {
...@@ -66,7 +66,7 @@ struct hv_24x7_result_element { ...@@ -66,7 +66,7 @@ struct hv_24x7_result_element {
__be32 lpar_cfg_instance_id; __be32 lpar_cfg_instance_id;
/* size = @result_element_data_size of cointaining result. */ /* size = @result_element_data_size of cointaining result. */
__u8 element_data[]; __u64 element_data[1];
} __packed; } __packed;
struct hv_24x7_result { struct hv_24x7_result {
...@@ -87,7 +87,7 @@ struct hv_24x7_result { ...@@ -87,7 +87,7 @@ struct hv_24x7_result {
/* WARNING: only valid for first result element due to variable sizes /* WARNING: only valid for first result element due to variable sizes
* of result elements */ * of result elements */
/* struct hv_24x7_result_element[@num_elements_returned] */ /* struct hv_24x7_result_element[@num_elements_returned] */
struct hv_24x7_result_element elements[]; struct hv_24x7_result_element elements[1];
} __packed; } __packed;
struct hv_24x7_data_result_buffer { struct hv_24x7_data_result_buffer {
...@@ -103,7 +103,7 @@ struct hv_24x7_data_result_buffer { ...@@ -103,7 +103,7 @@ struct hv_24x7_data_result_buffer {
__u8 reserved2[0x8]; __u8 reserved2[0x8];
/* WARNING: only valid for the first result due to variable sizes of /* WARNING: only valid for the first result due to variable sizes of
* results */ * results */
struct hv_24x7_result results[]; /* [@num_results] */ struct hv_24x7_result results[1]; /* [@num_results] */
} __packed; } __packed;
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment