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);
}