diff options
author | sukadev@linux.vnet.ibm.com <sukadev@linux.vnet.ibm.com> | 2014-10-01 02:03:18 -0400 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2014-10-07 01:57:10 -0400 |
commit | 56f12bee55d740dc47eed0ca9d5c72cffdffd6cf (patch) | |
tree | 67352cbe11600450a97f3c49e3a18eb48e8914f4 | |
parent | 48bee8a6c98e34367fa9d5e1be14109c92cbbb3b (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.c | 101 |
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 | ||
76 | static struct kmem_cache *hv_page_cache; | 76 | static 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 | */ | ||
138 | static 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 | |||
158 | static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096, | 78 | static 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 | |||
221 | e_free: | 148 | e_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 | } |