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: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Marcelo Diop-Gonzalez <marcgonzalez@google.com>
Reviewed-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Link: https://lore.kernel.org/r/20191120202102.249121-5-marcgonzalez@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Marcelo Diop-Gonzalez 2019-11-20 15:21:02 -05:00 committed by Greg Kroah-Hartman
parent 0046b33ce5
commit 0f6f874987
4 changed files with 101 additions and 49 deletions

View File

@ -247,15 +247,14 @@ vchiq_complete_bulk(struct vchiq_bulk *bulk)
bulk->actual); bulk->actual);
} }
void int vchiq_dump_platform_state(void *dump_context)
vchiq_dump_platform_state(void *dump_context)
{ {
char buf[80]; char buf[80];
int len; int len;
len = snprintf(buf, sizeof(buf), len = snprintf(buf, sizeof(buf),
" Platform: 2835 (VC master)"); " Platform: 2835 (VC master)");
vchiq_dump(dump_context, buf, len + 1); return vchiq_dump(dump_context, buf, len + 1);
} }
enum vchiq_status enum vchiq_status

View File

@ -2072,14 +2072,13 @@ out:
* *
***************************************************************************/ ***************************************************************************/
void int vchiq_dump(void *dump_context, const char *str, int len)
vchiq_dump(void *dump_context, const char *str, int len)
{ {
struct dump_context *context = (struct dump_context *)dump_context; struct dump_context *context = (struct dump_context *)dump_context;
int copy_bytes; int copy_bytes;
if (context->actual >= context->space) if (context->actual >= context->space)
return; return 0;
if (context->offset > 0) { if (context->offset > 0) {
int skip_bytes = min_t(int, len, context->offset); 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; len -= skip_bytes;
context->offset -= skip_bytes; context->offset -= skip_bytes;
if (context->offset > 0) if (context->offset > 0)
return; return 0;
} }
copy_bytes = min_t(int, len, context->space - context->actual); copy_bytes = min_t(int, len, context->space - context->actual);
if (copy_bytes == 0) if (copy_bytes == 0)
return; return 0;
if (copy_to_user(context->buf + context->actual, str, if (copy_to_user(context->buf + context->actual, str,
copy_bytes)) copy_bytes))
context->actual = -EFAULT; return -EFAULT;
context->actual += copy_bytes; context->actual += copy_bytes;
len -= 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, if (copy_to_user(context->buf + context->actual - 1,
&cr, 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 int vchiq_dump_platform_instances(void *dump_context)
vchiq_dump_platform_instances(void *dump_context)
{ {
struct vchiq_state *state = vchiq_get_state(); struct vchiq_state *state = vchiq_get_state();
char buf[80]; char buf[80];
@ -2145,6 +2144,7 @@ vchiq_dump_platform_instances(void *dump_context)
for (i = 0; i < state->unused_service; i++) { for (i = 0; i < state->unused_service; i++) {
struct vchiq_service *service = state->services[i]; struct vchiq_service *service = state->services[i];
struct vchiq_instance *instance; struct vchiq_instance *instance;
int err;
if (!service || service->base.callback != service_callback) if (!service || service->base.callback != service_callback)
continue; continue;
@ -2162,9 +2162,12 @@ vchiq_dump_platform_instances(void *dump_context)
instance->completion_remove, instance->completion_remove,
MAX_COMPLETIONS); MAX_COMPLETIONS);
vchiq_dump(dump_context, buf, len + 1); err = vchiq_dump(dump_context, buf, len + 1);
if (err)
return err;
instance->mark = 1; instance->mark = 1;
} }
return 0;
} }
/**************************************************************************** /****************************************************************************
@ -2173,9 +2176,8 @@ vchiq_dump_platform_instances(void *dump_context)
* *
***************************************************************************/ ***************************************************************************/
void int vchiq_dump_platform_service_state(void *dump_context,
vchiq_dump_platform_service_state(void *dump_context, struct vchiq_service *service)
struct vchiq_service *service)
{ {
struct user_service *user_service = struct user_service *user_service =
(struct user_service *)service->base.userdata; (struct user_service *)service->base.userdata;
@ -2196,7 +2198,7 @@ vchiq_dump_platform_service_state(void *dump_context,
" (dequeue pending)"); " (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) size_t count, loff_t *ppos)
{ {
struct dump_context context; struct dump_context context;
int err;
context.buf = buf; context.buf = buf;
context.actual = 0; context.actual = 0;
context.space = count; context.space = count;
context.offset = *ppos; context.offset = *ppos;
vchiq_dump_state(&context, &g_state); err = vchiq_dump_state(&context, &g_state);
if (err)
return err;
*ppos += context.actual; *ppos += context.actual;

View File

@ -3298,7 +3298,7 @@ vchiq_set_service_option(unsigned int handle,
return status; return status;
} }
static void static int
vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state, vchiq_dump_shared_state(void *dump_context, struct vchiq_state *state,
struct vchiq_shared_state *shared, const char *label) 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; int i;
char buf[80]; char buf[80];
int len; int len;
int err;
len = scnprintf(buf, sizeof(buf), len = scnprintf(buf, sizeof(buf),
" %s: slots %d-%d tx_pos=%x recycle=%x", " %s: slots %d-%d tx_pos=%x recycle=%x",
label, shared->slot_first, shared->slot_last, label, shared->slot_first, shared->slot_last,
shared->tx_pos, shared->slot_queue_recycle); 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), len = scnprintf(buf, sizeof(buf),
" Slots claimed:"); " 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++) { for (i = shared->slot_first; i <= shared->slot_last; i++) {
struct vchiq_slot_info slot_info = 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), len = scnprintf(buf, sizeof(buf),
" %d: %d/%d", i, slot_info.use_count, " %d: %d/%d", i, slot_info.use_count,
slot_info.release_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++) { for (i = 1; i < shared->debug[DEBUG_ENTRIES]; i++) {
len = scnprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)", len = scnprintf(buf, sizeof(buf), " DEBUG: %s = %d(%x)",
debug_names[i], shared->debug[i], shared->debug[i]); 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 int vchiq_dump_state(void *dump_context, struct vchiq_state *state)
vchiq_dump_state(void *dump_context, struct vchiq_state *state)
{ {
char buf[80]; char buf[80];
int len; int len;
int i; int i;
int err;
len = scnprintf(buf, sizeof(buf), "State %d: %s", state->id, len = scnprintf(buf, sizeof(buf), "State %d: %s", state->id,
conn_state_names[state->conn_state]); 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), len = scnprintf(buf, sizeof(buf),
" tx_pos=%x(@%pK), rx_pos=%x(@%pK)", " 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->tx_data + (state->local_tx_pos & VCHIQ_SLOT_MASK),
state->rx_pos, state->rx_pos,
state->rx_data + (state->rx_pos & VCHIQ_SLOT_MASK)); 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), len = scnprintf(buf, sizeof(buf),
" Version: %d (min %d)", " Version: %d (min %d)",
VCHIQ_VERSION, VCHIQ_VERSION_MIN); 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) { if (VCHIQ_ENABLE_STATS) {
len = scnprintf(buf, sizeof(buf), len = scnprintf(buf, sizeof(buf),
@ -3377,7 +3393,9 @@ vchiq_dump_state(void *dump_context, struct vchiq_state *state)
"error_count=%d", "error_count=%d",
state->stats.ctrl_tx_count, state->stats.ctrl_rx_count, state->stats.ctrl_tx_count, state->stats.ctrl_rx_count,
state->stats.error_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), 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->data_quota - state->data_use_count,
state->local->slot_queue_recycle - state->slot_queue_available, state->local->slot_queue_recycle - state->slot_queue_available,
state->stats.slot_stalls, state->stats.data_stalls); 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"); err = vchiq_dump_shared_state(dump_context,
vchiq_dump_shared_state(dump_context, state, state->remote, "Remote"); 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++) { for (i = 0; i < state->unused_service; i++) {
struct vchiq_service *service = find_service_by_port(state, i); struct vchiq_service *service = find_service_by_port(state, i);
if (service) { if (service) {
vchiq_dump_service_state(dump_context, service); err = vchiq_dump_service_state(dump_context, service);
unlock_service(service); unlock_service(service);
if (err)
return err;
} }
} }
return 0;
} }
void int vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
vchiq_dump_service_state(void *dump_context, struct vchiq_service *service)
{ {
char buf[80]; char buf[80];
int len; int len;
int err;
len = scnprintf(buf, sizeof(buf), "Service %u: %s (ref %u)", len = scnprintf(buf, sizeof(buf), "Service %u: %s (ref %u)",
service->localport, srvstate_names[service->srvstate], 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_use_count,
service_quota->slot_quota); 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 - tx_pending = service->bulk_tx.local_insert -
service->bulk_tx.remote_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); BULK_INDEX(service->bulk_rx.remove)].size : 0);
if (VCHIQ_ENABLE_STATS) { 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), len = scnprintf(buf, sizeof(buf),
" Ctrl: tx_count=%d, tx_bytes=%llu, " " 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_tx_bytes,
service->stats.ctrl_rx_count, service->stats.ctrl_rx_count,
service->stats.ctrl_rx_bytes); 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), len = scnprintf(buf, sizeof(buf),
" Bulk: tx_count=%d, tx_bytes=%llu, " " 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_tx_bytes,
service->stats.bulk_rx_count, service->stats.bulk_rx_count,
service->stats.bulk_rx_bytes); 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), len = scnprintf(buf, sizeof(buf),
" %d quota stalls, %d slot stalls, " " %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) 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 void

View File

@ -526,10 +526,10 @@ vchiq_bulk_transfer(unsigned int handle, void *offset, int size,
void *userdata, enum vchiq_bulk_mode mode, void *userdata, enum vchiq_bulk_mode mode,
enum vchiq_bulk_dir dir); enum vchiq_bulk_dir dir);
extern void extern int
vchiq_dump_state(void *dump_context, struct vchiq_state *state); 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); vchiq_dump_service_state(void *dump_context, struct vchiq_service *service);
extern void extern void
@ -602,16 +602,16 @@ vchiq_platform_resume(struct vchiq_state *state);
extern void extern void
vchiq_platform_resumed(struct vchiq_state *state); vchiq_platform_resumed(struct vchiq_state *state);
extern void extern int
vchiq_dump(void *dump_context, const char *str, int len); vchiq_dump(void *dump_context, const char *str, int len);
extern void extern int
vchiq_dump_platform_state(void *dump_context); vchiq_dump_platform_state(void *dump_context);
extern void extern int
vchiq_dump_platform_instances(void *dump_context); vchiq_dump_platform_instances(void *dump_context);
extern void extern int
vchiq_dump_platform_service_state(void *dump_context, vchiq_dump_platform_service_state(void *dump_context,
struct vchiq_service *service); struct vchiq_service *service);