static void gb_connection_recv_response()

in operation.c [957:1019]


static void gb_connection_recv_response(struct gb_connection *connection,
				const struct gb_operation_msg_hdr *header,
				void *data, size_t size)
{
	struct gb_operation *operation;
	struct gb_message *message;
	size_t message_size;
	u16 operation_id;
	int errno;

	operation_id = le16_to_cpu(header->operation_id);

	if (!operation_id) {
		dev_err_ratelimited(&connection->hd->dev,
				    "%s: invalid response id 0 received\n",
				    connection->name);
		return;
	}

	operation = gb_operation_find_outgoing(connection, operation_id);
	if (!operation) {
		dev_err_ratelimited(&connection->hd->dev,
				    "%s: unexpected response id 0x%04x received\n",
				    connection->name, operation_id);
		return;
	}

	errno = gb_operation_status_map(header->result);
	message = operation->response;
	message_size = sizeof(*header) + message->payload_size;
	if (!errno && size > message_size) {
		dev_err_ratelimited(&connection->hd->dev,
				    "%s: malformed response 0x%02x received (%zu > %zu)\n",
				    connection->name, header->type,
				    size, message_size);
		errno = -EMSGSIZE;
	} else if (!errno && size < message_size) {
		if (gb_operation_short_response_allowed(operation)) {
			message->payload_size = size - sizeof(*header);
		} else {
			dev_err_ratelimited(&connection->hd->dev,
					    "%s: short response 0x%02x received (%zu < %zu)\n",
					    connection->name, header->type,
					    size, message_size);
			errno = -EMSGSIZE;
		}
	}

	/* We must ignore the payload if a bad status is returned */
	if (errno)
		size = sizeof(*header);

	/* The rest will be handled in work queue context */
	if (gb_operation_result_set(operation, errno)) {
		memcpy(message->buffer, data, size);

		trace_gb_message_recv_response(message);

		queue_work(gb_operation_completion_wq, &operation->work);
	}

	gb_operation_put(operation);
}