diff --git a/drivers/staging/greybus/loopback.c b/drivers/staging/greybus/loopback.c index f3ae2e9fc1bbc0d1ada70c9365a330a2098c592c..c022edbfb135e43de4ca9ed9598ecbf206b8649a 100644 --- a/drivers/staging/greybus/loopback.c +++ b/drivers/staging/greybus/loopback.c @@ -81,6 +81,7 @@ struct gb_loopback { atomic_t outstanding_operations; /* Per connection stats */ + struct timeval ts; struct gb_loopback_stats latency; struct gb_loopback_stats throughput; struct gb_loopback_stats requests_per_second; @@ -520,7 +521,6 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) gb_loopback_push_latency_ts(gb, &op_async->ts, &te); gb->elapsed_nsecs = gb_loopback_calc_latency(&op_async->ts, &te); - gb_loopback_calculate_stats(gb); } if (op_async->pending) { @@ -529,6 +529,7 @@ static void gb_loopback_async_operation_callback(struct gb_operation *operation) del_timer_sync(&op_async->timer); gb_loopback_async_operation_put(op_async); } + gb_loopback_calculate_stats(gb); mutex_unlock(&gb->mutex); dev_dbg(&gb->connection->bundle->dev, "complete operation %d\n", @@ -846,6 +847,7 @@ static void gb_loopback_reset_stats(struct gb_loopback *gb) /* Should be initialized at least once per transaction set */ gb->apbridge_latency_ts = 0; gb->gpbridge_latency_ts = 0; + memset(&gb->ts, 0, sizeof(struct timeval)); } static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) @@ -860,15 +862,15 @@ static void gb_loopback_update_stats(struct gb_loopback_stats *stats, u32 val) static void gb_loopback_requests_update(struct gb_loopback *gb, u32 latency) { - u32 req = USEC_PER_SEC; + u64 req = gb->requests_completed * USEC_PER_SEC; do_div(req, latency); - gb_loopback_update_stats(&gb->requests_per_second, req); + gb_loopback_update_stats(&gb->requests_per_second, (u32)req); } static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) { - u32 throughput; + u64 throughput; u32 aggregate_size = sizeof(struct gb_operation_msg_hdr) * 2; switch (gb->type) { @@ -887,14 +889,13 @@ static void gb_loopback_throughput_update(struct gb_loopback *gb, u32 latency) return; } - /* Calculate bytes per second */ - throughput = USEC_PER_SEC; + aggregate_size *= gb->requests_completed; + throughput = aggregate_size * USEC_PER_SEC; do_div(throughput, latency); - throughput *= aggregate_size; - gb_loopback_update_stats(&gb->throughput, throughput); + gb_loopback_update_stats(&gb->throughput, (u32)throughput); } -static void gb_loopback_calculate_stats(struct gb_loopback *gb) +static void gb_loopback_calculate_latency_stats(struct gb_loopback *gb) { u32 lat; @@ -907,10 +908,6 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) /* Raw latency log on a per thread basis */ kfifo_in(&gb->kfifo_lat, (unsigned char *)&lat, sizeof(lat)); - /* Log throughput and requests using latency as benchmark */ - gb_loopback_throughput_update(gb, lat); - gb_loopback_requests_update(gb, lat); - /* Log the firmware supplied latency values */ gb_loopback_update_stats(&gb->apbridge_unipro_latency, gb->apbridge_latency_ts); @@ -918,6 +915,27 @@ static void gb_loopback_calculate_stats(struct gb_loopback *gb) gb->gpbridge_latency_ts); } +static void gb_loopback_calculate_stats(struct gb_loopback *gb) +{ + u64 nlat; + u32 lat; + struct timeval te; + + gb_loopback_calculate_latency_stats(gb); + + if (gb->iteration_count == gb->iteration_max) { + do_gettimeofday(&te); + nlat = gb_loopback_calc_latency(&gb->ts, &te); + lat = gb_loopback_nsec_to_usec_latency(nlat); + + gb_loopback_throughput_update(gb, lat); + gb_loopback_requests_update(gb, lat); + + memset(&gb->ts, 0, sizeof(struct timeval)); + gb->type = 0; + } +} + static void gb_loopback_async_wait_to_send(struct gb_loopback *gb) { if (!(gb->async && gb->outstanding_operations_max)) @@ -955,8 +973,10 @@ static int gb_loopback_fn(void *data) /* Optionally terminate */ if (send_count == gb->iteration_max) { - gb->type = 0; - send_count = 0; + if (!gb->async) + send_count = 0; + else if (gb->iteration_count == gb->iteration_max) + send_count = 0; mutex_unlock(&gb->mutex); continue; } @@ -965,10 +985,15 @@ static int gb_loopback_fn(void *data) type = gb->type; mutex_unlock(&gb->mutex); + if (gb->ts.tv_usec == 0 && gb->ts.tv_sec == 0) + do_gettimeofday(&gb->ts); + /* Else operations to perform */ if (gb->async) { if (type == GB_LOOPBACK_TYPE_PING) { error = gb_loopback_async_ping(gb); + if (!error) + gb->requests_completed++; gb_loopback_calculate_stats(gb); } else if (type == GB_LOOPBACK_TYPE_TRANSFER) { error = gb_loopback_async_transfer(gb, size); @@ -989,6 +1014,8 @@ static int gb_loopback_fn(void *data) if (error) gb->error++; + else + gb->requests_completed++; gb->iteration_count++; gb_loopback_calculate_stats(gb); }