powerpc/perf/hv-24x7: Modify definition of request and result buffers
authorSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Tue, 31 Mar 2015 01:53:38 +0000 (18:53 -0700)
committerMichael Ellerman <mpe@ellerman.id.au>
Sat, 11 Apr 2015 10:49:21 +0000 (20:49 +1000)
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>
arch/powerpc/perf/hv-24x7.c
arch/powerpc/perf/hv-24x7.h

index 9445a824819ea7f919fdc4191b561e07c07bd49c..408e6e9ff4496ef7757f764f154a8c03a5874da6 100644 (file)
@@ -142,6 +142,15 @@ static struct attribute_group event_long_desc_group = {
 
 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)
 {
        *len = be16_to_cpu(ev->event_name_len) - 2;
@@ -976,31 +985,16 @@ static const struct attribute_group *attr_groups[] = {
        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,
-                                        u16 lpar, u64 *res,
+                                        u16 lpar, u64 *count,
                                         bool success_expected)
 {
        unsigned long ret;
 
-       /*
-        * 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.
-        */
-       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;
+       struct hv_24x7_request_buffer *request_buffer;
+       struct hv_24x7_data_result_buffer *result_buffer;
+       struct hv_24x7_result *resb;
+       struct hv_24x7_request *req;
 
        BUILD_BUG_ON(sizeof(*request_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,
        memset(request_buffer, 0, 4096);
        memset(result_buffer, 0, 4096);
 
-       *request_buffer = (struct reqb) {
-               .buf = {
-                       .interface_version = HV_24X7_IF_VERSION_CURRENT,
-                       .num_requests = 1,
-               },
-               .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),
-               }
-       };
+       request_buffer->interface_version = HV_24X7_IF_VERSION_CURRENT;
+       request_buffer->num_requests = 1;
+
+       req = &request_buffer->requests[0];
 
+       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,
-                       virt_to_phys(request_buffer), sizeof(*request_buffer),
-                       virt_to_phys(result_buffer),  sizeof(*result_buffer));
+                       virt_to_phys(request_buffer), H24x7_DATA_BUFFER_SIZE,
+                       virt_to_phys(result_buffer),  H24x7_DATA_BUFFER_SIZE);
 
        if (ret) {
                if (success_expected)
                        pr_err_ratelimited("hcall failed: %d %#x %#x %d => "
                                "0x%lx (%ld) detail=0x%x failing ix=%x\n",
                                domain, offset, ix, lpar, ret, ret,
-                               result_buffer->buf.detailed_rc,
-                               result_buffer->buf.failing_request_ix);
+                               result_buffer->detailed_rc,
+                               result_buffer->failing_request_ix);
                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:
        return ret;
 }
index 69cd4e690f587717732a1270eadf9688ff406487..0f9fa21a29f23bddd5d367b0fc20daef71b53002 100644 (file)
@@ -50,7 +50,7 @@ struct hv_24x7_request_buffer {
        __u8 interface_version;
        __u8 num_requests;
        __u8 reserved[0xE];
-       struct hv_24x7_request requests[];
+       struct hv_24x7_request requests[1];
 } __packed;
 
 struct hv_24x7_result_element {
@@ -66,7 +66,7 @@ struct hv_24x7_result_element {
        __be32 lpar_cfg_instance_id;
 
        /* size = @result_element_data_size of cointaining result. */
-       __u8 element_data[];
+       __u64 element_data[1];
 } __packed;
 
 struct hv_24x7_result {
@@ -87,7 +87,7 @@ struct hv_24x7_result {
        /* WARNING: only valid for first result element due to variable sizes
         *          of result elements */
        /* struct hv_24x7_result_element[@num_elements_returned] */
-       struct hv_24x7_result_element elements[];
+       struct hv_24x7_result_element elements[1];
 } __packed;
 
 struct hv_24x7_data_result_buffer {
@@ -103,7 +103,7 @@ struct hv_24x7_data_result_buffer {
        __u8 reserved2[0x8];
        /* WARNING: only valid for the first result due to variable sizes of
         *          results */
-       struct hv_24x7_result results[]; /* [@num_results] */
+       struct hv_24x7_result results[1]; /* [@num_results] */
 } __packed;
 
 #endif