Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56f12bee authored by sukadev@linux.vnet.ibm.com's avatar sukadev@linux.vnet.ibm.com Committed by Michael Ellerman
Browse files

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: default avatarSukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 48bee8a6
Loading
Loading
Loading
Loading
+14 −87
Original line number Original line Diff line number Diff line
@@ -75,86 +75,6 @@ static struct attribute_group format_group = {


static struct kmem_cache *hv_page_cache;
static struct kmem_cache *hv_page_cache;


/*
 * read_offset_data - copy data from one buffer to another while treating the
 *                    source buffer as a small view on the total avaliable
 *                    source data.
 *
 * @dest: buffer to copy into
 * @dest_len: length of @dest in bytes
 * @requested_offset: the offset within the source data we want. Must be > 0
 * @src: buffer to copy data from
 * @src_len: length of @src in bytes
 * @source_offset: the offset in the sorce data that (src,src_len) refers to.
 *                 Must be > 0
 *
 * returns the number of bytes copied.
 *
 * The following ascii art shows the various buffer possitioning we need to
 * handle, assigns some arbitrary varibles to points on the buffer, and then
 * shows how we fiddle with those values to get things we care about (copy
 * start in src and copy len)
 *
 * s = @src buffer
 * d = @dest buffer
 * '.' areas in d are written to.
 *
 *                       u
 *   x         w	 v  z
 * d           |.........|
 * s |----------------------|
 *
 *                      u
 *   x         w	z     v
 * d           |........------|
 * s |------------------|
 *
 *   x         w        u,z,v
 * d           |........|
 * s |------------------|
 *
 *   x,w                u,v,z
 * d |..................|
 * s |------------------|
 *
 *   x        u
 *   w        v		z
 * d |........|
 * s |------------------|
 *
 *   x      z   w      v
 * d            |------|
 * s |------|
 *
 * x = source_offset
 * w = requested_offset
 * z = source_offset + src_len
 * v = requested_offset + dest_len
 *
 * w_offset_in_s = w - x = requested_offset - source_offset
 * z_offset_in_s = z - x = src_len
 * v_offset_in_s = v - x = request_offset + dest_len - src_len
 */
static ssize_t read_offset_data(void *dest, size_t dest_len,
				loff_t requested_offset, void *src,
				size_t src_len, loff_t source_offset)
{
	size_t w_offset_in_s = requested_offset - source_offset;
	size_t z_offset_in_s = src_len;
	size_t v_offset_in_s = requested_offset + dest_len - src_len;
	size_t u_offset_in_s = min(z_offset_in_s, v_offset_in_s);
	size_t copy_len = u_offset_in_s - w_offset_in_s;

	if (requested_offset < 0 || source_offset < 0)
		return -EINVAL;

	if (z_offset_in_s <= w_offset_in_s)
		return 0;

	memcpy(dest, src + w_offset_in_s, copy_len);
	return copy_len;
}

static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096,
static unsigned long h_get_24x7_catalog_page_(unsigned long phys_4096,
					      unsigned long version,
					      unsigned long version,
					      unsigned long index)
					      unsigned long index)
@@ -183,8 +103,10 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
{
{
	unsigned long hret;
	unsigned long hret;
	ssize_t ret = 0;
	ssize_t ret = 0;
	size_t catalog_len = 0, catalog_page_len = 0, page_count = 0;
	size_t catalog_len = 0, catalog_page_len = 0;
	loff_t page_offset = 0;
	loff_t page_offset = 0;
	loff_t offset_in_page;
	size_t copy_len;
	uint64_t catalog_version_num = 0;
	uint64_t catalog_version_num = 0;
	void *page = kmem_cache_alloc(hv_page_cache, GFP_USER);
	void *page = kmem_cache_alloc(hv_page_cache, GFP_USER);
	struct hv_24x7_catalog_page_0 *page_0 = page;
	struct hv_24x7_catalog_page_0 *page_0 = page;
@@ -202,7 +124,7 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
	catalog_len = catalog_page_len * 4096;
	catalog_len = catalog_page_len * 4096;


	page_offset = offset / 4096;
	page_offset = offset / 4096;
	page_count  = count  / 4096;
	offset_in_page = offset % 4096;


	if (page_offset >= catalog_page_len)
	if (page_offset >= catalog_page_len)
		goto e_free;
		goto e_free;
@@ -216,8 +138,13 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
		}
		}
	}
	}


	ret = read_offset_data(buf, count, offset,
	copy_len = 4096 - offset_in_page;
				page, 4096, page_offset * 4096);
	if (copy_len > count)
		copy_len = count;

	memcpy(buf, page+offset_in_page, copy_len);
	ret = copy_len;

e_free:
e_free:
	if (hret)
	if (hret)
		pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
		pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:"
@@ -225,9 +152,9 @@ static ssize_t catalog_read(struct file *filp, struct kobject *kobj,
		       catalog_version_num, page_offset, hret);
		       catalog_version_num, page_offset, hret);
	kmem_cache_free(hv_page_cache, page);
	kmem_cache_free(hv_page_cache, page);


	pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n",
	pr_devel("catalog_read: offset=%lld(%lld) count=%zu "
			offset, page_offset, count, page_count, catalog_len,
			"catalog_len=%zu(%zu) => %zd\n", offset, page_offset,
			catalog_page_len, ret);
			count, catalog_len, catalog_page_len, ret);


	return ret;
	return ret;
}
}