greybus: connection: add a timestamp kfifo to track connection handoff
authorBryan O'Donoghue <bryan.odonoghue@linaro.org>
Tue, 11 Aug 2015 12:50:51 +0000 (13:50 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 12 Aug 2015 03:00:40 +0000 (20:00 -0700)
For the ES2 test activity it may be beneficial to have a performance
metric that doesn't include any of the greybus stack malloc, workqueues
etc. In order to faciltate, this patch adds a simple kfifo structure to
hold two timestamp values. One timestamp will represent the last reasonable
point a greybus outbound timestamp can be taken, the other timestamp will
represent the first reasonable point an inbound timestamp can be taken. In
order to facilitate this model, tracking the timestamps in the connection
structure appears to be the best place to keep store of this data.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/connection.c
drivers/staging/greybus/connection.h

index 3765aa87ef2de7a9746b7287d8ad8b47d26daab7..0ec5b0dcc145c59fafe2edfdf7c9bb4ae723012c 100644 (file)
 
 #include "greybus.h"
 
+#define GB_CONNECTION_TS_KFIFO_ELEMENTS        2
+#define GB_CONNECTION_TS_KFIFO_LEN \
+       (GB_CONNECTION_TS_KFIFO_ELEMENTS * sizeof(struct timeval))
+
 static DEFINE_SPINLOCK(gb_connections_lock);
 
 /* This is only used at initialization time; no locking is required. */
@@ -63,6 +67,29 @@ void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id,
 }
 EXPORT_SYMBOL_GPL(greybus_data_rcvd);
 
+void gb_connection_push_timestamp(struct gb_connection *connection)
+{
+       struct timeval tv;
+
+       do_gettimeofday(&tv);
+       kfifo_in_locked(&connection->ts_kfifo, (void *)&tv,
+                       sizeof(struct timeval), &connection->lock);
+}
+EXPORT_SYMBOL_GPL(gb_connection_push_timestamp);
+
+int gb_connection_pop_timestamp(struct gb_connection *connection,
+                               struct timeval *tv)
+{
+       int retval;
+
+       if (!kfifo_len(&connection->ts_kfifo))
+               return -ENOMEM;
+       retval = kfifo_out_locked(&connection->ts_kfifo, (void *)tv,
+                                 sizeof(*tv), &connection->lock);
+       return retval;
+}
+EXPORT_SYMBOL_GPL(gb_connection_pop_timestamp);
+
 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
@@ -102,6 +129,7 @@ static void gb_connection_release(struct device *dev)
        struct gb_connection *connection = to_gb_connection(dev);
 
        destroy_workqueue(connection->wq);
+       kfifo_free(&connection->ts_kfifo);
        kfree(connection);
 }
 
@@ -222,6 +250,10 @@ gb_connection_create_range(struct greybus_host_device *hd,
        if (!connection->wq)
                goto err_free_connection;
 
+       if (kfifo_alloc(&connection->ts_kfifo, GB_CONNECTION_TS_KFIFO_LEN,
+                       GFP_KERNEL))
+               goto err_free_connection;
+
        connection->dev.parent = parent;
        connection->dev.bus = &greybus_bus_type;
        connection->dev.type = &greybus_connection_type;
@@ -238,7 +270,7 @@ gb_connection_create_range(struct greybus_host_device *hd,
                pr_err("failed to add connection device for cport 0x%04hx\n",
                        cport_id);
 
-               goto err_free_connection;
+               goto err_free_kfifo;
        }
 
        spin_lock_irq(&gb_connections_lock);
@@ -259,6 +291,8 @@ gb_connection_create_range(struct greybus_host_device *hd,
 
        return connection;
 
+err_free_kfifo:
+       kfifo_free(&connection->ts_kfifo);
 err_free_connection:
        kfree(connection);
 err_remove_ida:
index 0dbbc202e9539087bb1e0b0630bfda496755f1aa..a26a48033fc6bfbdfed433aaaed2f5c0230f231e 100644 (file)
@@ -11,6 +11,7 @@
 #define __CONNECTION_H
 
 #include <linux/list.h>
+#include <linux/kfifo.h>
 
 enum gb_connection_state {
        GB_CONNECTION_STATE_INVALID     = 0,
@@ -42,6 +43,7 @@ struct gb_connection {
        struct list_head                operations;
 
        struct workqueue_struct         *wq;
+       struct kfifo                    ts_kfifo;
 
        atomic_t                        op_cycle;
 
@@ -65,6 +67,9 @@ void gb_hd_connections_exit(struct greybus_host_device *hd);
 
 void greybus_data_rcvd(struct greybus_host_device *hd, u16 cport_id,
                        u8 *data, size_t length);
+void gb_connection_push_timestamp(struct gb_connection *connection);
+int gb_connection_pop_timestamp(struct gb_connection *connection,
+                               struct timeval *tv);
 
 void gb_connection_bind_protocol(struct gb_connection *connection);