aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsukadev@linux.vnet.ibm.com <sukadev@linux.vnet.ibm.com>2014-10-01 02:03:18 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2014-10-07 01:57:10 -0400
commit56f12bee55d740dc47eed0ca9d5c72cffdffd6cf (patch)
tree67352cbe11600450a97f3c49e3a18eb48e8914f4
parent48bee8a6c98e34367fa9d5e1be14109c92cbbb3b (diff)
powerpc/perf/hv-24x7: Simplify catalog_read()
catalog_read() implements the read interface for the sysfs file /sys/bus/event_source/devices/hv_24x7/interface/catalog It essentially takes a buffer, an offset and count as parameters to the read() call. It makes a hypervisor call to read a specific page from the catalog and copy the required bytes into the given buffer. Each call to catalog_read() returns at most one 4K page. Given these requirements, we should be able to simplify the catalog_read(). 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-24x7.c101
1 files changed, 14 insertions, 87 deletions
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 697759d8eb16..6c8710dd90c9 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -75,86 +75,6 @@ static struct attribute_group format_group = {
75 75
76static struct kmem_cache *hv_page_cache; 76static struct kmem_cache *hv_page_cache;
77 77
78/*
79 * read_offset_data - copy data from one buffer to another while treating the
80 * source buffer as a small view on the total avaliable
81 * source data.
82 *
83 * @dest: buffer to copy into
84 * @dest_len: length of @dest in bytes
85 * @requested_offset: the offset within the source data we want. Must be > 0
86 * @src: buffer to copy data from
87 * @src_len: length of @src in bytes
88 * @source_offset: the offset in the sorce data that (src,src_len) refers to.
89 * Must be > 0
90 *
91 * returns the number of bytes copied.
92 *
93 * The following ascii art shows the various buffer possitioning we need to
94 * handle, assigns some arbitrary varibles to points on the buffer, and then
95 * shows how we fiddle with those values to get things we care about (copy
96 * start in src and copy len)
97 *
98 * s = @src buffer
99 * d = @dest buffer
100 * '.' areas in d are written to.
101 *
102 * u
103 * x w v z
104 * d |.........|
105 * s |----------------------|
106 *
107 * u
108 * x w z v
109 * d |........------|
110 * s |------------------|
111 *
112 * x w u,z,v
113 * d |........|
114 * s |------------------|
115 *
116 * x,w u,v,z
117 * d |..................|
118 * s |------------------|
119 *
120 * x u
121 * w v z
122 * d |........|
123 * s |------------------|
124 *
125 * x z w v
126 * d |------|
127 * s |------|
128 *
129 * x = source_offset
130 * w = requested_offset
131 * z = source_offset + src_len
132 * v = requested_offset + dest_len
133 *
134 * w_offset_in_s = w - x = requested_offset - source_offset
135 * z_offset_in_s = z - x = src_len
136 * v_offset_in_s = v - x = request_offset + dest_len - src_len
137 */
138static ssize_t read_offset_data(void *dest, size_t dest_len,
139 loff_t requested_offset, void *src,
140 size_t src_len, loff_t source_offset)
141{
142 size_t w_offset_in_s = requested_offset - source_offset;
143 size_t z_offset_in_s = src_len;
144 size_t v_offset_in_s = requested_offset + dest_len - src_len;
145 size_t u_offset_in_s = min(z_offset_in_s, v_offset_in_s);
146 size_t copy_len = u_offset_in_s - w_offset_in_s;
147
148 if (requested_offset < 0 || source_offset < 0)
149 return -EINVAL;
150
151 if (z_offset_in_s <= w_offset_in_s)
152 return 0;
153
154 memcpy(dest, src + w_offset_in_s, copy_len);
155 return copy_len;
156}
157
158static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096, 78static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096,
159 unsigned long version, 79 unsigned long version,
160 unsigned long index) 80 unsigned long index)
@@ -183,8 +103,10 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
183{ 103{
184 unsigned long hret; 104 unsigned long hret;
185 ssize_t ret = 0; 105 ssize_t ret = 0;
186 size_t catalog_len = 0, catalog_page_len = 0, page_count = 0; 106 size_t catalog_len = 0, catalog_page_len = 0;
187 loff_t page_offset = 0; 107 loff_t page_offset = 0;
108 loff_t offset_in_page;
109 size_t copy_len;
188 uint64_t catalog_version_num = 0; 110 uint64_t catalog_version_num = 0;
189 void *page = kmem_cache_alloc(hv_page_cache, GFP_USER); 111 void *page = kmem_cache_alloc(hv_page_cache, GFP_USER);
190 struct hv_24x7_catalog_page_0 *page_0 = page; 112 struct hv_24x7_catalog_page_0 *page_0 = page;
@@ -202,7 +124,7 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
202 catalog_len = catalog_page_len * 4096; 124 catalog_len = catalog_page_len * 4096;
203 125
204 page_offset = offset / 4096; 126 page_offset = offset / 4096;
205 page_count = count / 4096; 127 offset_in_page = offset % 4096;
206 128
207 if (page_offset >= catalog_page_len) 129 if (page_offset >= catalog_page_len)
208 goto e_free; 130 goto e_free;
@@ -216,8 +138,13 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
216 } 138 }
217 } 139 }
218 140
219 ret = read_offset_data(buf, count, offset, 141 copy_len = 4096 - offset_in_page;
220 page, 4096, page_offset * 4096); 142 if (copy_len > count)
143 copy_len = count;
144
145 memcpy(buf, page+offset_in_page, copy_len);
146 ret = copy_len;
147
221e_free: 148e_free:
222 if (hret) 149 if (hret)
223 pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:" 150 pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
@@ -225,9 +152,9 @@ e_free:
225 catalog_version_num, page_offset, hret); 152 catalog_version_num, page_offset, hret);
226 kmem_cache_free(hv_page_cache, page); 153 kmem_cache_free(hv_page_cache, page);
227 154
228 pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n", 155 pr_devel("catalog_read: offset=%lld(%lld) count=%zu "
229 offset, page_offset, count, page_count, catalog_len, 156 "catalog_len=%zu(%zu) => %zd\n", offset, page_offset,
230 catalog_page_len, ret); 157 count, catalog_len, catalog_page_len, ret);
231 158
232 return ret; 159 return ret;
233} 160}