#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. */
 }
 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)
 {
        struct gb_connection *connection = to_gb_connection(dev);
 
        destroy_workqueue(connection->wq);
+       kfifo_free(&connection->ts_kfifo);
        kfree(connection);
 }
 
        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;
                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);
 
        return connection;
 
+err_free_kfifo:
+       kfifo_free(&connection->ts_kfifo);
 err_free_connection:
        kfree(connection);
 err_remove_ida:
 
 #define __CONNECTION_H
 
 #include <linux/list.h>
+#include <linux/kfifo.h>
 
 enum gb_connection_state {
        GB_CONNECTION_STATE_INVALID     = 0,
        struct list_head                operations;
 
        struct workqueue_struct         *wq;
+       struct kfifo                    ts_kfifo;
 
        atomic_t                        op_cycle;
 
 
 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);