*/
void gb_connection_destroy(struct gb_connection *connection)
{
+ struct gb_operation *operation;
+ struct gb_operation *next;
+
if (WARN_ON(!connection))
return;
/* XXX Need to wait for any outstanding requests to complete */
WARN_ON(!list_empty(&connection->operations));
+ list_for_each_entry_safe(operation, next, &connection->operations,
+ links) {
+ gb_operation_cancel(operation);
+ }
spin_lock_irq(&gb_connections_lock);
list_del(&connection->interface_links);
_gb_hd_connection_remove(connection);
queue_work(gb_operation_recv_workqueue, &operation->recv_work);
}
+/*
+ * Cancel an operation.
+ */
+void gb_operation_cancel(struct gb_operation *operation)
+{
+ int ret;
+
+ operation->canceled = true;
+ ret = greybus_kill_gbuf(operation->request);
+ if (ret)
+ pr_warn("error %d killing request gbuf\n", ret);
+ if (operation->response) {
+ ret = greybus_kill_gbuf(operation->response);
+ if (ret)
+ pr_warn("error %d killing response gbuf\n", ret);
+ }
+}
+
int gb_operation_init(void)
{
gb_operation_cache = kmem_cache_create("gb_operation_cache",
struct gbuf *request;
struct gbuf *response;
u16 id;
+ bool canceled;
u8 result;
struct work_struct recv_work;
gb_operation_callback callback);
int gb_operation_response_send(struct gb_operation *operation);
+void gb_operation_cancel(struct gb_operation *operation);
int gb_operation_wait(struct gb_operation *operation);
void gb_operation_complete(struct gb_operation *operation);