#include <linux/workqueue.h>
#include "greybus.h"
+#include "greybus_trace.h"
static void gb_connection_kref_release(struct kref *kref);
static void gb_connection_get(struct gb_connection *connection)
{
kref_get(&connection->kref);
+
+ trace_gb_connection_get(connection);
}
static void gb_connection_put(struct gb_connection *connection)
{
+ trace_gb_connection_put(connection);
+
kref_put(&connection->kref, gb_connection_kref_release);
}
connection = container_of(kref, struct gb_connection, kref);
+ trace_gb_connection_release(connection);
+
kfree(connection);
}
mutex_unlock(&gb_connection_mutex);
+ trace_gb_connection_create(connection);
+
return connection;
err_free_connection:
goto out_unlock;
ret = _gb_connection_enable(connection, true);
+ if (!ret)
+ trace_gb_connection_enable(connection);
+
out_unlock:
mutex_unlock(&connection->mutex);
goto out_unlock;
ret = _gb_connection_enable(connection, false);
+ if (!ret)
+ trace_gb_connection_enable(connection);
+
out_unlock:
mutex_unlock(&connection->mutex);
gb_connection_flush_incoming_operations(connection, -ESHUTDOWN);
spin_unlock_irq(&connection->lock);
+ trace_gb_connection_disable(connection);
+
out_unlock:
mutex_unlock(&connection->mutex);
}
connection->state = GB_CONNECTION_STATE_DISABLED;
+ trace_gb_connection_disable(connection);
+
/* control-connection tear down is deferred when mode switching */
if (!connection->mode_switch) {
gb_connection_svc_connection_destroy(connection);
gb_connection_svc_connection_destroy(connection);
gb_connection_hd_cport_disable(connection);
+ trace_gb_connection_disable(connection);
+
out_unlock:
mutex_unlock(&connection->mutex);
}
struct gb_message;
struct gb_operation;
+struct gb_connection;
struct gb_bundle;
struct gb_host_device;
#undef DEFINE_OPERATION_EVENT
+DECLARE_EVENT_CLASS(gb_connection,
+
+ TP_PROTO(struct gb_connection *connection),
+
+ TP_ARGS(connection),
+
+ TP_STRUCT__entry(
+ __field(int, hd_bus_id)
+ __field(u8, bundle_id)
+ /* name contains "hd_cport_id/intf_id:cport_id" */
+ __dynamic_array(char, name, sizeof(connection->name))
+ __field(enum gb_connection_state, state)
+ __field(unsigned long, flags)
+ ),
+
+ TP_fast_assign(
+ __entry->hd_bus_id = connection->hd->bus_id;
+ __entry->bundle_id = connection->bundle ?
+ connection->bundle->id : BUNDLE_ID_NONE;
+ memcpy(__get_str(name), connection->name,
+ sizeof(connection->name));
+ __entry->state = connection->state;
+ __entry->flags = connection->flags;
+ ),
+
+ TP_printk("hd_bus_id=%d bundle_id=0x%02x name=\"%s\" state=%u flags=0x%lx",
+ __entry->hd_bus_id, __entry->bundle_id, __get_str(name),
+ (unsigned int)__entry->state, __entry->flags)
+);
+
+#define DEFINE_CONNECTION_EVENT(name) \
+ DEFINE_EVENT(gb_connection, name, \
+ TP_PROTO(struct gb_connection *connection), \
+ TP_ARGS(connection))
+
+/*
+ * Occurs after a new connection is successfully created.
+ */
+DEFINE_CONNECTION_EVENT(gb_connection_create);
+
+/*
+ * Occurs when the last reference to a connection has been dropped,
+ * before its resources are freed.
+ */
+DEFINE_CONNECTION_EVENT(gb_connection_release);
+
+/*
+ * Occurs when a new reference to connection is added, currently
+ * only when a message over the connection is received.
+ */
+DEFINE_CONNECTION_EVENT(gb_connection_get);
+
+/*
+ * Occurs when a new reference to connection is dropped, after a
+ * a received message is handled, or when the connection is
+ * destroyed.
+ */
+DEFINE_CONNECTION_EVENT(gb_connection_put);
+
+/*
+ * Occurs when a request to enable a connection is made, either for
+ * transmit only, or for both transmit and receive.
+ */
+DEFINE_CONNECTION_EVENT(gb_connection_enable);
+
+/*
+ * Occurs when a request to disable a connection is made, either for
+ * receive only, or for both transmit and receive. Also occurs when
+ * a request to forcefully disable a connection is made.
+ */
+DEFINE_CONNECTION_EVENT(gb_connection_disable);
+
+#undef DEFINE_CONNECTION_EVENT
+
DECLARE_EVENT_CLASS(gb_bundle,
TP_PROTO(struct gb_bundle *bundle),