Lines Matching full:operation

22 /* Workqueue to handle Greybus operation completions. */
29 * Protects updates to operation->errno.
33 static int gb_operation_response_send(struct gb_operation *operation,
37 * Increment operation active count and add to connection list unless the
40 * Caller holds operation reference.
42 static int gb_operation_get_active(struct gb_operation *operation) in gb_operation_get_active() argument
44 struct gb_connection *connection = operation->connection; in gb_operation_get_active()
52 if (gb_operation_is_incoming(operation)) in gb_operation_get_active()
56 if (!gb_operation_is_core(operation)) in gb_operation_get_active()
63 if (operation->active++ == 0) in gb_operation_get_active()
64 list_add_tail(&operation->links, &connection->operations); in gb_operation_get_active()
66 trace_gb_operation_get_active(operation); in gb_operation_get_active()
78 /* Caller holds operation reference. */
79 static void gb_operation_put_active(struct gb_operation *operation) in gb_operation_put_active() argument
81 struct gb_connection *connection = operation->connection; in gb_operation_put_active()
86 trace_gb_operation_put_active(operation); in gb_operation_put_active()
88 if (--operation->active == 0) { in gb_operation_put_active()
89 list_del(&operation->links); in gb_operation_put_active()
90 if (atomic_read(&operation->waiters)) in gb_operation_put_active()
96 static bool gb_operation_is_active(struct gb_operation *operation) in gb_operation_is_active() argument
98 struct gb_connection *connection = operation->connection; in gb_operation_is_active()
103 ret = operation->active; in gb_operation_is_active()
110 * Set an operation's result.
112 * Initially an outgoing operation's errno value is -EBADR.
114 * valid value operation->errno can be set to is -EINPROGRESS,
130 * value to set for an operation in initial state is -EINPROGRESS.
132 * operation result.
134 static bool gb_operation_result_set(struct gb_operation *operation, int result) in gb_operation_result_set() argument
148 prev = operation->errno; in gb_operation_result_set()
150 operation->errno = result; in gb_operation_result_set()
152 operation->errno = -EILSEQ; in gb_operation_result_set()
161 * will be the final result of the operation. Subsequent in gb_operation_result_set()
172 prev = operation->errno; in gb_operation_result_set()
174 operation->errno = result; /* First and final result */ in gb_operation_result_set()
180 int gb_operation_result(struct gb_operation *operation) in gb_operation_result() argument
182 int result = operation->errno; in gb_operation_result()
192 * Looks up an outgoing operation on a connection and returns a refcounted
198 struct gb_operation *operation; in gb_operation_find_outgoing() local
203 list_for_each_entry(operation, &connection->operations, links) in gb_operation_find_outgoing()
204 if (operation->id == operation_id && in gb_operation_find_outgoing()
205 !gb_operation_is_incoming(operation)) { in gb_operation_find_outgoing()
206 gb_operation_get(operation); in gb_operation_find_outgoing()
212 return found ? operation : NULL; in gb_operation_find_outgoing()
217 struct gb_connection *connection = message->operation->connection; in gb_message_send()
231 struct gb_host_device *hd = message->operation->connection->hd; in gb_message_cancel()
236 static void gb_operation_request_handle(struct gb_operation *operation) in gb_operation_request_handle() argument
238 struct gb_connection *connection = operation->connection; in gb_operation_request_handle()
243 status = connection->handler(operation); in gb_operation_request_handle()
247 connection->name, operation->type); in gb_operation_request_handle()
252 ret = gb_operation_response_send(operation, status); in gb_operation_request_handle()
256 connection->name, status, operation->type, ret); in gb_operation_request_handle()
262 * Process operation work.
264 * For incoming requests, call the protocol request handler. The operation
267 * For outgoing requests, the operation result value should have
268 * been set before queueing this. The operation callback function
274 struct gb_operation *operation; in gb_operation_work() local
277 operation = container_of(work, struct gb_operation, work); in gb_operation_work()
279 if (gb_operation_is_incoming(operation)) { in gb_operation_work()
280 gb_operation_request_handle(operation); in gb_operation_work()
282 ret = del_timer_sync(&operation->timer); in gb_operation_work()
285 if (gb_operation_result(operation) == -ETIMEDOUT) in gb_operation_work()
286 gb_message_cancel(operation->request); in gb_operation_work()
289 operation->callback(operation); in gb_operation_work()
292 gb_operation_put_active(operation); in gb_operation_work()
293 gb_operation_put(operation); in gb_operation_work()
298 struct gb_operation *operation = from_timer(operation, t, timer); in gb_operation_timeout() local
300 if (gb_operation_result_set(operation, -ETIMEDOUT)) { in gb_operation_timeout()
305 queue_work(gb_operation_completion_wq, &operation->work); in gb_operation_timeout()
331 * For a request, the operation id gets filled in in gb_operation_message_init()
347 * Allocate a message to be used for an operation request or response.
349 * for an outgoing operation is outbound, as is the response message
350 * for an incoming operation. The message header for an outbound
383 /* Initialize the message. Operation id is filled in later. */ in gb_operation_message_alloc()
434 * Map a Linux errno value (from operation->errno) into the value
468 bool gb_operation_response_alloc(struct gb_operation *operation, in gb_operation_response_alloc() argument
471 struct gb_host_device *hd = operation->connection->hd; in gb_operation_response_alloc()
476 type = operation->type | GB_MESSAGE_TYPE_RESPONSE; in gb_operation_response_alloc()
480 response->operation = operation; in gb_operation_response_alloc()
485 * that's left is the operation id, which we copy from the in gb_operation_response_alloc()
488 request_header = operation->request->header; in gb_operation_response_alloc()
490 operation->response = response; in gb_operation_response_alloc()
497 * Create a Greybus operation to be sent over the given connection.
515 * Returns a pointer to the new operation or a null pointer if an
524 struct gb_operation *operation; in gb_operation_create_common() local
526 operation = kmem_cache_zalloc(gb_operation_cache, gfp_flags); in gb_operation_create_common()
527 if (!operation) in gb_operation_create_common()
529 operation->connection = connection; in gb_operation_create_common()
531 operation->request = gb_operation_message_alloc(hd, type, request_size, in gb_operation_create_common()
533 if (!operation->request) in gb_operation_create_common()
535 operation->request->operation = operation; in gb_operation_create_common()
539 if (!gb_operation_response_alloc(operation, response_size, in gb_operation_create_common()
544 timer_setup(&operation->timer, gb_operation_timeout, 0); in gb_operation_create_common()
547 operation->flags = op_flags; in gb_operation_create_common()
548 operation->type = type; in gb_operation_create_common()
549 operation->errno = -EBADR; /* Initial value--means "never set" */ in gb_operation_create_common()
551 INIT_WORK(&operation->work, gb_operation_work); in gb_operation_create_common()
552 init_completion(&operation->completion); in gb_operation_create_common()
553 kref_init(&operation->kref); in gb_operation_create_common()
554 atomic_set(&operation->waiters, 0); in gb_operation_create_common()
556 return operation; in gb_operation_create_common()
559 gb_operation_message_free(operation->request); in gb_operation_create_common()
561 kmem_cache_free(gb_operation_cache, operation); in gb_operation_create_common()
567 * Create a new operation associated with the given connection. The
571 * invalid operation type for all protocols, and this is enforced
580 struct gb_operation *operation; in gb_operation_create_flags() local
590 operation = gb_operation_create_common(connection, type, in gb_operation_create_flags()
593 if (operation) in gb_operation_create_flags()
594 trace_gb_operation_create(operation); in gb_operation_create_flags()
596 return operation; in gb_operation_create_flags()
606 struct gb_operation *operation; in gb_operation_create_core() local
610 operation = gb_operation_create_common(connection, type, in gb_operation_create_core()
613 if (operation) in gb_operation_create_core()
614 trace_gb_operation_create_core(operation); in gb_operation_create_core()
616 return operation; in gb_operation_create_core()
633 struct gb_operation *operation; in gb_operation_create_incoming() local
643 operation = gb_operation_create_common(connection, type, in gb_operation_create_incoming()
647 if (!operation) in gb_operation_create_incoming()
650 operation->id = id; in gb_operation_create_incoming()
651 memcpy(operation->request->header, data, size); in gb_operation_create_incoming()
652 trace_gb_operation_create_incoming(operation); in gb_operation_create_incoming()
654 return operation; in gb_operation_create_incoming()
658 * Get an additional reference on an operation.
660 void gb_operation_get(struct gb_operation *operation) in gb_operation_get() argument
662 kref_get(&operation->kref); in gb_operation_get()
667 * Destroy a previously created operation.
671 struct gb_operation *operation; in _gb_operation_destroy() local
673 operation = container_of(kref, struct gb_operation, kref); in _gb_operation_destroy()
675 trace_gb_operation_destroy(operation); in _gb_operation_destroy()
677 if (operation->response) in _gb_operation_destroy()
678 gb_operation_message_free(operation->response); in _gb_operation_destroy()
679 gb_operation_message_free(operation->request); in _gb_operation_destroy()
681 kmem_cache_free(gb_operation_cache, operation); in _gb_operation_destroy()
685 * Drop a reference on an operation, and destroy it when the last
688 void gb_operation_put(struct gb_operation *operation) in gb_operation_put() argument
690 if (WARN_ON(!operation)) in gb_operation_put()
693 kref_put(&operation->kref, _gb_operation_destroy); in gb_operation_put()
698 static void gb_operation_sync_callback(struct gb_operation *operation) in gb_operation_sync_callback() argument
700 complete(&operation->completion); in gb_operation_sync_callback()
704 * gb_operation_request_send() - send an operation request message
705 * @operation: the operation to initiate
706 * @callback: the operation completion callback
707 * @timeout: operation timeout in milliseconds, or zero for no timeout
712 * arrived, a unidirectional request has been sent, or the operation is
713 * cancelled, indicating that the operation is complete. The callback function
714 * can fetch the result of the operation using gb_operation_result() if
720 int gb_operation_request_send(struct gb_operation *operation, in gb_operation_request_send() argument
725 struct gb_connection *connection = operation->connection; in gb_operation_request_send()
739 * of an operation has been set. in gb_operation_request_send()
741 operation->callback = callback; in gb_operation_request_send()
744 * Assign the operation's id, and store it in the request header. in gb_operation_request_send()
745 * Zero is a reserved operation id for unidirectional operations. in gb_operation_request_send()
747 if (gb_operation_is_unidirectional(operation)) { in gb_operation_request_send()
748 operation->id = 0; in gb_operation_request_send()
751 operation->id = (u16)(cycle % U16_MAX + 1); in gb_operation_request_send()
754 header = operation->request->header; in gb_operation_request_send()
755 header->operation_id = cpu_to_le16(operation->id); in gb_operation_request_send()
757 gb_operation_result_set(operation, -EINPROGRESS); in gb_operation_request_send()
760 * Get an extra reference on the operation. It'll be dropped when the in gb_operation_request_send()
761 * operation completes. in gb_operation_request_send()
763 gb_operation_get(operation); in gb_operation_request_send()
764 ret = gb_operation_get_active(operation); in gb_operation_request_send()
768 ret = gb_message_send(operation->request, gfp); in gb_operation_request_send()
773 operation->timer.expires = jiffies + msecs_to_jiffies(timeout); in gb_operation_request_send()
774 add_timer(&operation->timer); in gb_operation_request_send()
780 gb_operation_put_active(operation); in gb_operation_request_send()
782 gb_operation_put(operation); in gb_operation_request_send()
789 * Send a synchronous operation. This function is expected to
792 * operation.
794 int gb_operation_request_send_sync_timeout(struct gb_operation *operation, in gb_operation_request_send_sync_timeout() argument
799 ret = gb_operation_request_send(operation, gb_operation_sync_callback, in gb_operation_request_send_sync_timeout()
804 ret = wait_for_completion_interruptible(&operation->completion); in gb_operation_request_send_sync_timeout()
806 /* Cancel the operation if interrupted */ in gb_operation_request_send_sync_timeout()
807 gb_operation_cancel(operation, -ECANCELED); in gb_operation_request_send_sync_timeout()
810 return gb_operation_result(operation); in gb_operation_request_send_sync_timeout()
815 * Send a response for an incoming operation request. A non-zero
816 * errno indicates a failed operation.
823 static int gb_operation_response_send(struct gb_operation *operation, in gb_operation_response_send() argument
826 struct gb_connection *connection = operation->connection; in gb_operation_response_send()
829 if (!operation->response && in gb_operation_response_send()
830 !gb_operation_is_unidirectional(operation)) { in gb_operation_response_send()
831 if (!gb_operation_response_alloc(operation, 0, GFP_KERNEL)) in gb_operation_response_send()
836 if (!gb_operation_result_set(operation, errno)) { in gb_operation_response_send()
842 if (gb_operation_is_unidirectional(operation)) in gb_operation_response_send()
846 gb_operation_get(operation); in gb_operation_response_send()
847 ret = gb_operation_get_active(operation); in gb_operation_response_send()
852 operation->response->header->result = gb_operation_errno_map(errno); in gb_operation_response_send()
854 ret = gb_message_send(operation->response, GFP_KERNEL); in gb_operation_response_send()
861 gb_operation_put_active(operation); in gb_operation_response_send()
863 gb_operation_put(operation); in gb_operation_response_send()
874 struct gb_operation *operation = message->operation; in greybus_message_sent() local
875 struct gb_connection *connection = operation->connection; in greybus_message_sent()
879 * reference to the operation. If an error occurred, report in greybus_message_sent()
882 * For requests, if there's no error and the operation in not in greybus_message_sent()
885 * operation is unidrectional, record the result of the operation and in greybus_message_sent()
888 if (message == operation->response) { in greybus_message_sent()
892 connection->name, operation->type, status); in greybus_message_sent()
895 gb_operation_put_active(operation); in greybus_message_sent()
896 gb_operation_put(operation); in greybus_message_sent()
897 } else if (status || gb_operation_is_unidirectional(operation)) { in greybus_message_sent()
898 if (gb_operation_result_set(operation, status)) { in greybus_message_sent()
900 &operation->work); in greybus_message_sent()
917 struct gb_operation *operation; in gb_connection_recv_request() local
925 operation = gb_operation_create_incoming(connection, operation_id, in gb_connection_recv_request()
927 if (!operation) { in gb_connection_recv_request()
929 "%s: can't create incoming operation\n", in gb_connection_recv_request()
934 ret = gb_operation_get_active(operation); in gb_connection_recv_request()
936 gb_operation_put(operation); in gb_connection_recv_request()
939 trace_gb_message_recv_request(operation->request); in gb_connection_recv_request()
942 * The initial reference to the operation will be dropped when the in gb_connection_recv_request()
945 if (gb_operation_result_set(operation, -EINPROGRESS)) in gb_connection_recv_request()
946 queue_work(connection->wq, &operation->work); in gb_connection_recv_request()
950 * We've received data that appears to be an operation response
951 * message. Look up the operation, and record that we've received
961 struct gb_operation *operation; in gb_connection_recv_response() local
976 operation = gb_operation_find_outgoing(connection, operation_id); in gb_connection_recv_response()
977 if (!operation) { in gb_connection_recv_response()
985 message = operation->response; in gb_connection_recv_response()
994 if (gb_operation_short_response_allowed(operation)) { in gb_connection_recv_response()
1010 if (gb_operation_result_set(operation, errno)) { in gb_connection_recv_response()
1015 queue_work(gb_operation_completion_wq, &operation->work); in gb_connection_recv_response()
1018 gb_operation_put(operation); in gb_connection_recv_response()
1055 return; /* XXX Should still complete operation */ in gb_connection_recv()
1068 * Cancel an outgoing operation synchronously, and record the given error to
1071 void gb_operation_cancel(struct gb_operation *operation, int errno) in gb_operation_cancel() argument
1073 if (WARN_ON(gb_operation_is_incoming(operation))) in gb_operation_cancel()
1076 if (gb_operation_result_set(operation, errno)) { in gb_operation_cancel()
1077 gb_message_cancel(operation->request); in gb_operation_cancel()
1078 queue_work(gb_operation_completion_wq, &operation->work); in gb_operation_cancel()
1080 trace_gb_message_cancel_outgoing(operation->request); in gb_operation_cancel()
1082 atomic_inc(&operation->waiters); in gb_operation_cancel()
1084 !gb_operation_is_active(operation)); in gb_operation_cancel()
1085 atomic_dec(&operation->waiters); in gb_operation_cancel()
1090 * Cancel an incoming operation synchronously. Called during connection tear
1093 void gb_operation_cancel_incoming(struct gb_operation *operation, int errno) in gb_operation_cancel_incoming() argument
1095 if (WARN_ON(!gb_operation_is_incoming(operation))) in gb_operation_cancel_incoming()
1098 if (!gb_operation_is_unidirectional(operation)) { in gb_operation_cancel_incoming()
1103 flush_work(&operation->work); in gb_operation_cancel_incoming()
1104 if (!gb_operation_result_set(operation, errno)) in gb_operation_cancel_incoming()
1105 gb_message_cancel(operation->response); in gb_operation_cancel_incoming()
1107 trace_gb_message_cancel_incoming(operation->response); in gb_operation_cancel_incoming()
1109 atomic_inc(&operation->waiters); in gb_operation_cancel_incoming()
1111 !gb_operation_is_active(operation)); in gb_operation_cancel_incoming()
1112 atomic_dec(&operation->waiters); in gb_operation_cancel_incoming()
1116 * gb_operation_sync_timeout() - implement a "simple" synchronous operation
1118 * @type: the type of operation to send
1123 * @timeout: operation timeout in milliseconds
1125 * This function implements a simple synchronous Greybus operation. It sends
1126 * the provided operation request and waits (sleeps) until the corresponding
1127 * operation response message has been successfully received, or an error
1133 * @response_size number of bytes will be copied into @response if the operation
1143 struct gb_operation *operation; in gb_operation_sync_timeout() local
1150 operation = gb_operation_create(connection, type, in gb_operation_sync_timeout()
1153 if (!operation) in gb_operation_sync_timeout()
1157 memcpy(operation->request->payload, request, request_size); in gb_operation_sync_timeout()
1159 ret = gb_operation_request_send_sync_timeout(operation, timeout); in gb_operation_sync_timeout()
1162 "%s: synchronous operation id 0x%04x of type 0x%02x failed: %d\n", in gb_operation_sync_timeout()
1163 connection->name, operation->id, type, ret); in gb_operation_sync_timeout()
1166 memcpy(response, operation->response->payload, in gb_operation_sync_timeout()
1171 gb_operation_put(operation); in gb_operation_sync_timeout()
1178 * gb_operation_unidirectional_timeout() - initiate a unidirectional operation
1180 * @type: type of operation to send
1185 * Initiate a unidirectional operation by sending a request message and
1188 * Note that successful send of a unidirectional operation does not imply that
1196 struct gb_operation *operation; in gb_operation_unidirectional_timeout() local
1202 operation = gb_operation_create_flags(connection, type, in gb_operation_unidirectional_timeout()
1206 if (!operation) in gb_operation_unidirectional_timeout()
1210 memcpy(operation->request->payload, request, request_size); in gb_operation_unidirectional_timeout()
1212 ret = gb_operation_request_send_sync_timeout(operation, timeout); in gb_operation_unidirectional_timeout()
1215 "%s: unidirectional operation of type 0x%02x failed: %d\n", in gb_operation_unidirectional_timeout()
1219 gb_operation_put(operation); in gb_operation_unidirectional_timeout()