Commit 5a3be769 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman
Browse files

greybus: operation: split incoming and outgoing cancellation



Split incoming and outgoing operation-cancellation helpers.

Incoming operations are only cancelled as part of connection tear down
and is specifically not needed in the driver API.

Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 0eb8c115
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -238,7 +238,11 @@ static void gb_connection_cancel_operations(struct gb_connection *connection,
		gb_operation_get(operation);
		spin_unlock_irq(&connection->lock);

		if (gb_operation_is_incoming(operation))
			gb_operation_cancel_incoming(operation, errno);
		else
			gb_operation_cancel(operation, errno);

		gb_operation_put(operation);

		spin_lock_irq(&connection->lock);
+33 −17
Original line number Diff line number Diff line
@@ -922,34 +922,50 @@ void gb_connection_recv(struct gb_connection *connection,
}

/*
 * Cancel an operation synchronously, and record the given error to indicate
 * why.
 * Cancel an outgoing operation synchronously, and record the given error to
 * indicate why.
 */
void gb_operation_cancel(struct gb_operation *operation, int errno)
{
	if (gb_operation_is_incoming(operation)) {
	if (WARN_ON(gb_operation_is_incoming(operation)))
		return;

	if (gb_operation_result_set(operation, errno)) {
		gb_message_cancel(operation->request);
		queue_work(gb_operation_workqueue, &operation->work);
	}

	atomic_inc(&operation->waiters);
	wait_event(gb_operation_cancellation_queue,
			!gb_operation_is_active(operation));
	atomic_dec(&operation->waiters);
}
EXPORT_SYMBOL_GPL(gb_operation_cancel);

/*
 * Cancel an incoming operation synchronously. Called during connection tear
 * down.
 */
void gb_operation_cancel_incoming(struct gb_operation *operation, int errno)
{
	if (WARN_ON(!gb_operation_is_incoming(operation)))
		return;

	if (!gb_operation_is_unidirectional(operation)) {
		/*
			 * Make sure the request handler has submitted the
			 * response before cancelling it.
		 * Make sure the request handler has submitted the response
		 * before cancelling it.
		 */
		flush_work(&operation->work);
		if (!gb_operation_result_set(operation, errno))
			gb_message_cancel(operation->response);
	}
	} else {
		if (gb_operation_result_set(operation, errno)) {
			gb_message_cancel(operation->request);
			queue_work(gb_operation_workqueue, &operation->work);
		}
	}

	atomic_inc(&operation->waiters);
	wait_event(gb_operation_cancellation_queue,
			!gb_operation_is_active(operation));
	atomic_dec(&operation->waiters);
}
EXPORT_SYMBOL_GPL(gb_operation_cancel);

/**
 * gb_operation_sync: implement a "simple" synchronous gb operation.
+1 −0
Original line number Diff line number Diff line
@@ -171,6 +171,7 @@ int gb_operation_request_send(struct gb_operation *operation,
int gb_operation_request_send_sync(struct gb_operation *operation);

void gb_operation_cancel(struct gb_operation *operation, int errno);
void gb_operation_cancel_incoming(struct gb_operation *operation, int errno);

void greybus_message_sent(struct greybus_host_device *hd,
				struct gb_message *message, int status);