Commit 0f6f8749 authored by Marcelo Diop-Gonzalez's avatar Marcelo Diop-Gonzalez Committed by Greg Kroah-Hartman
Browse files

staging: vchiq: Have vchiq_dump_* functions return an error code



These functions currently modify the struct dump_context passed
to them, and set context->actual to -EFAULT in case of error.
The issue is that this is never returned to the user (except
accidentally when things align so that that happens). So, have
these functions return 0 on success and the appropriate error
code otherwise, and return nonzero errors to the user.

Reviewed-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: default avatarMarcelo Diop-Gonzalez <marcgonzalez@google.com>
Reviewed-by: default avatarNicolas Saenz Julienne <nsaenzjulienne@suse.de>
Link: https://lore.kernel.org/r/20191120202102.249121-5-marcgonzalez@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0046b33c
Loading
Loading
Loading
Loading
+2 −3
Original line number Diff line number Diff line
@@ -247,15 +247,14 @@ vchiq_complete_bulk(struct vchiq_bulk *bulk)
			      bulk->actual);
}

void
vchiq_dump_platform_state(void *dump_context)
int vchiq_dump_platform_state(void *dump_context)
{
	char buf[80];
	int len;

	len = snprintf(buf, sizeof(buf),
		"  Platform: 2835 (VC master)");
	vchiq_dump(dump_context, buf, len + 1);
	return vchiq_dump(dump_context, buf, len + 1);
}

enum vchiq_status
+20 −15
Original line number Diff line number Diff line
@@ -2072,14 +2072,13 @@ out:
*
***************************************************************************/

void
vchiq_dump(void *dump_context, const char *str, int len)
int vchiq_dump(void *dump_context, const char *str, int len)
{
	struct dump_context *context = (struct dump_context *)dump_context;
	int copy_bytes;

	if (context->actual >= context->space)
		return;
		return 0;

	if (context->offset > 0) {
		int skip_bytes = min_t(int, len, context->offset);
@@ -2088,14 +2087,14 @@ vchiq_dump(void *dump_context, const char *str, int len)
		len -= skip_bytes;
		context->offset -= skip_bytes;
		if (context->offset > 0)
			return;
			return 0;
	}
	copy_bytes = min_t(int, len, context->space - context->actual);
	if (copy_bytes == 0)
		return;
		return 0;
	if (copy_to_user(context->buf + context->actual, str,
			 copy_bytes))
		context->actual = -EFAULT;
		return -EFAULT;
	context->actual += copy_bytes;
	len -= copy_bytes;

@@ -2109,8 +2108,9 @@ vchiq_dump(void *dump_context, const char *str, int len)

		if (copy_to_user(context->buf + context->actual - 1,
				 &cr, 1))
			context->actual = -EFAULT;
			return -EFAULT;
	}
	return 0;
}

/****************************************************************************
@@ -2119,8 +2119,7 @@ vchiq_dump(void *dump_context, const char *str, int len)
*
***************************************************************************/

void
vchiq_dump_platform_instances(void *dump_context)
int vchiq_dump_platform_instances(void *dump_context)
{
	struct vchiq_state *state = vchiq_get_state();
	char buf[80];
@@ -2145,6 +2144,7 @@ vchiq_dump_platform_instances(void *dump_context)
	for (i = 0; i < state->unused_service; i++) {
		struct vchiq_service *service = state->services[i];
		struct vchiq_instance *instance;
		int err;

		if (!service || service->base.callback != service_callback)
			continue;
@@ -2162,9 +2162,12 @@ vchiq_dump_platform_instances(void *dump_context)
			       instance->completion_remove,
			       MAX_COMPLETIONS);

		vchiq_dump(dump_context, buf, len + 1);
		err = vchiq_dump(dump_context, buf, len + 1);
		if (err)
			return err;
		instance->mark = 1;
	}
	return 0;
}

/****************************************************************************
@@ -2173,8 +2176,7 @@ vchiq_dump_platform_instances(void *dump_context)
*
***************************************************************************/

void
vchiq_dump_platform_service_state(void *dump_context,
int vchiq_dump_platform_service_state(void *dump_context,
				      struct vchiq_service *service)
{
	struct user_service *user_service =
@@ -2196,7 +2198,7 @@ vchiq_dump_platform_service_state(void *dump_context,
				" (dequeue pending)");
	}

	vchiq_dump(dump_context, buf, len + 1);
	return vchiq_dump(dump_context, buf, len + 1);
}

/****************************************************************************
@@ -2210,13 +2212,16 @@ vchiq_read(struct file *file, char __user *buf,
	size_t count, loff_t *ppos)
{
	struct dump_context context;
	int err;

	context.buf = buf;
	context.actual = 0;
	context.space = count;
	context.offset = *ppos;

	vchiq_dump_state(&context, &g_state);
	err = vchiq_dump_state(&context, &g_state);
	if (err)
		return err;

	*ppos += context.actual;

+76 −28
Original line number Diff line number Diff line
@@ -3298,7 +3298,7 @@ vchiq_set_service_option(unsigned int handle,
	return status;
}

static void
static int
vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state,
			struct vchiq_shared_state *shared, const char *label)
{
@@ -3318,16 +3318,21 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state,
	int i;
	char buf[80];
	int len;
	int err;

	len = scnprintf(buf, sizeof(buf),
		"  %s: slots %d-%d tx_pos=%x recycle=%x",
		label, shared->slot_first, shared->slot_last,
		shared->tx_pos, shared->slot_queue_recycle);
	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	len = scnprintf(buf, sizeof(buf),
		"    Slots claimed:");
	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	for (i = shared->slot_first; i <= shared->slot_last; i++) {
		struct vchiq_slot_info slot_info =
@@ -3336,27 +3341,34 @@ vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state,
			len = scnprintf(buf, sizeof(buf),
				"      %d: %d/%d", i, slot_info.use_count,
				slot_info.release_count);
			vchiq_dump(dump_context, buf, len + 1);
			err = vchiq_dump(dump_context, buf, len + 1);
			if (err)
				return err;
		}
	}

	for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) {
		len = scnprintf(buf, sizeof(buf), "    DEBUG: %s = %d(%x)",
			debug_names[i], shared->debug[i], shared->debug[i]);
		vchiq_dump(dump_context, buf, len + 1);
		err = vchiq_dump(dump_context, buf, len + 1);
		if (err)
			return err;
	}
	return 0;
}

void
vchiq_dump_state(void *dump_context, struct vchiq_state *state)
int vchiq_dump_state(void *dump_context, struct vchiq_state *state)
{
	char buf[80];
	int len;
	int i;
	int err;

	len = scnprintf(buf, sizeof(buf), "State %d: %s", state->id,
		conn_state_names[state->conn_state]);
	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	len = scnprintf(buf, sizeof(buf),
		"  tx_pos=%x(@%pK), rx_pos=%x(@%pK)",
@@ -3364,12 +3376,16 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state)
		state->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK),
		state->rx_pos,
		state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK));
	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	len = scnprintf(buf, sizeof(buf),
		"  Version: %d (min %d)",
		VCHIQ_VERSION, VCHIQ_VERSION_MIN);
	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	if (VCHIQ_ENABLE_STATS) {
		len = scnprintf(buf, sizeof(buf),
@@ -3377,7 +3393,9 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state)
			"error_count=%d",
			state->stats.ctrl_tx_count, state->stats.ctrl_rx_count,
			state->stats.error_count);
		vchiq_dump(dump_context, buf, len + 1);
		err = vchiq_dump(dump_context, buf, len + 1);
		if (err)
			return err;
	}

	len = scnprintf(buf, sizeof(buf),
@@ -3388,30 +3406,49 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state)
		state->data_quota - state->data_use_count,
		state->local->slot_queue_recycle - state->slot_queue_available,
		state->stats.slot_stalls, state->stats.data_stalls);
	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	vchiq_dump_platform_state(dump_context);
	err = vchiq_dump_platform_state(dump_context);
	if (err)
		return err;

	vchiq_dump_shared_state(dump_context, state, state->local, "Local");
	vchiq_dump_shared_state(dump_context, state, state->remote, "Remote");
	err = vchiq_dump_shared_state(dump_context,
				      state,
				      state->local,
				      "Local");
	if (err)
		return err;
	err = vchiq_dump_shared_state(dump_context,
				      state,
				      state->remote,
				      "Remote");
	if (err)
		return err;

	vchiq_dump_platform_instances(dump_context);
	err = vchiq_dump_platform_instances(dump_context);
	if (err)
		return err;

	for (i = 0; i < state->unused_service; i++) {
		struct vchiq_service *service = find_service_by_port(state, i);

		if (service) {
			vchiq_dump_service_state(dump_context, service);
			err = vchiq_dump_service_state(dump_context, service);
			unlock_service(service);
			if (err)
				return err;
		}
	}
	return 0;
}

void
vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
int vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
{
	char buf[80];
	int len;
	int err;

	len = scnprintf(buf, sizeof(buf), "Service %u: %s (ref %u)",
		service->localport, srvstate_names[service->srvstate],
@@ -3444,7 +3481,9 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
			service_quota->slot_use_count,
			service_quota->slot_quota);

		vchiq_dump(dump_context, buf, len + 1);
		err = vchiq_dump(dump_context, buf, len + 1);
		if (err)
			return err;

		tx_pending = service->bulk_tx.local_insert -
			service->bulk_tx.remote_insert;
@@ -3463,7 +3502,9 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
			BULK_INDEX(service->bulk_rx.remove)].size : 0);

		if (VCHIQ_ENABLE_STATS) {
			vchiq_dump(dump_context, buf, len + 1);
			err = vchiq_dump(dump_context, buf, len + 1);
			if (err)
				return err;

			len = scnprintf(buf, sizeof(buf),
				"  Ctrl: tx_count=%d, tx_bytes=%llu, "
@@ -3472,7 +3513,9 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
				service->stats.ctrl_tx_bytes,
				service->stats.ctrl_rx_count,
				service->stats.ctrl_rx_bytes);
			vchiq_dump(dump_context, buf, len + 1);
			err = vchiq_dump(dump_context, buf, len + 1);
			if (err)
				return err;

			len = scnprintf(buf, sizeof(buf),
				"  Bulk: tx_count=%d, tx_bytes=%llu, "
@@ -3481,7 +3524,9 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
				service->stats.bulk_tx_bytes,
				service->stats.bulk_rx_count,
				service->stats.bulk_rx_bytes);
			vchiq_dump(dump_context, buf, len + 1);
			err = vchiq_dump(dump_context, buf, len + 1);
			if (err)
				return err;

			len = scnprintf(buf, sizeof(buf),
				"  %d quota stalls, %d slot stalls, "
@@ -3494,10 +3539,13 @@ vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
		}
	}

	vchiq_dump(dump_context, buf, len + 1);
	err = vchiq_dump(dump_context, buf, len + 1);
	if (err)
		return err;

	if (service->srvstate != VCHIQ_SRVSTATE_FREE)
		vchiq_dump_platform_service_state(dump_context, service);
		err = vchiq_dump_platform_service_state(dump_context, service);
	return err;
}

void
+6 −6
Original line number Diff line number Diff line
@@ -526,10 +526,10 @@ vchiq_bulk_transfer(unsigned int handle, void *offset, int size,
		    void *userdata, enum vchiq_bulk_mode mode,
		    enum vchiq_bulk_dir dir);

extern void
extern int
vchiq_dump_state(void *dump_context, struct vchiq_state *state);

extern void
extern int
vchiq_dump_service_state(void *dump_context, struct vchiq_service *service);

extern void
@@ -602,16 +602,16 @@ vchiq_platform_resume(struct vchiq_state *state);
extern void
vchiq_platform_resumed(struct vchiq_state *state);

extern void
extern int
vchiq_dump(void *dump_context, const char *str, int len);

extern void
extern int
vchiq_dump_platform_state(void *dump_context);

extern void
extern int
vchiq_dump_platform_instances(void *dump_context);

extern void
extern int
vchiq_dump_platform_service_state(void *dump_context,
	struct vchiq_service *service);