Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57fa2de1 authored by Georgi Dobrev's avatar Georgi Dobrev Committed by Greg Kroah-Hartman
Browse files

greybus: greybus-driver: Add intf_oops operation



Add intf_oops operation to SVC Protocol. This
operation will notify the AP about a fatal error
in a module. The request has two arguments:
    -u8 intf - the interface in question
    -u8 reason - reason of the error
The response has no payload.
Upon receiving the Request, the driver disables
the Interface.

Signed-off-by: default avatarGeorgi Dobrev <gdobrev@mm-sol.com>
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: default avatarAshwin Chaugule <ashwinch@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 127bada1
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1018,6 +1018,7 @@ struct gb_spi_transfer_response {
#define GB_SVC_TYPE_INTF_ACTIVATE		0x27
#define GB_SVC_TYPE_INTF_RESUME			0x28
#define GB_SVC_TYPE_INTF_MAILBOX_EVENT		0x29
#define GB_SVC_TYPE_INTF_OOPS			0x2a

/* Greybus SVC protocol status values */
#define GB_SVC_OP_SUCCESS			0x00
@@ -1357,6 +1358,12 @@ struct gb_svc_intf_mailbox_event_request {
} __packed;
/* intf_mailbox_event response has no payload */

struct gb_svc_intf_oops_request {
	__u8	intf_id;
	__u8	reason;
} __packed;
/* intf_oops response has no payload */


/* RAW */

+50 −0
Original line number Diff line number Diff line
@@ -1112,6 +1112,37 @@ static void gb_svc_process_module_removed(struct gb_operation *operation)
	gb_module_put(module);
}

static void gb_svc_process_intf_oops(struct gb_operation *operation)
{
	struct gb_svc_intf_oops_request *request;
	struct gb_connection *connection = operation->connection;
	struct gb_svc *svc = gb_connection_get_data(connection);
	struct gb_interface *intf;
	u8 intf_id;
	u8 reason;

	/* The request message size has already been verified. */
	request = operation->request->payload;
	intf_id = request->intf_id;
	reason = request->reason;

	intf = gb_svc_interface_lookup(svc, intf_id);
	if (!intf) {
		dev_warn(&svc->dev, "unexpected interface-oops event %u\n",
			 intf_id);
		return;
	}

	dev_info(&svc->dev, "Deactivating interface %u, interface oops reason = %u\n",
		 intf_id, reason);

	mutex_lock(&intf->mutex);
	intf->disconnected = true;
	gb_interface_disable(intf);
	gb_interface_deactivate(intf);
	mutex_unlock(&intf->mutex);
}

static void gb_svc_process_intf_mailbox_event(struct gb_operation *operation)
{
	struct gb_svc_intf_mailbox_event_request *request;
@@ -1165,6 +1196,9 @@ static void gb_svc_process_deferred_request(struct work_struct *work)
	case GB_SVC_TYPE_INTF_MAILBOX_EVENT:
		gb_svc_process_intf_mailbox_event(operation);
		break;
	case GB_SVC_TYPE_INTF_OOPS:
		gb_svc_process_intf_oops(operation);
		break;
	default:
		dev_err(&svc->dev, "bad deferred request type: 0x%02x\n", type);
	}
@@ -1251,6 +1285,20 @@ static int gb_svc_module_removed_recv(struct gb_operation *op)
	return gb_svc_queue_deferred_request(op);
}

static int gb_svc_intf_oops_recv(struct gb_operation *op)
{
	struct gb_svc *svc = gb_connection_get_data(op->connection);
	struct gb_svc_intf_oops_request *request;

	if (op->request->payload_size < sizeof(*request)) {
		dev_warn(&svc->dev, "short intf-oops request received (%zu < %zu)\n",
			 op->request->payload_size, sizeof(*request));
		return -EINVAL;
	}

	return gb_svc_queue_deferred_request(op);
}

static int gb_svc_intf_mailbox_event_recv(struct gb_operation *op)
{
	struct gb_svc *svc = gb_connection_get_data(op->connection);
@@ -1326,6 +1374,8 @@ static int gb_svc_request_handler(struct gb_operation *op)
		return gb_svc_module_removed_recv(op);
	case GB_SVC_TYPE_INTF_MAILBOX_EVENT:
		return gb_svc_intf_mailbox_event_recv(op);
	case GB_SVC_TYPE_INTF_OOPS:
		return gb_svc_intf_oops_recv(op);
	default:
		dev_warn(&svc->dev, "unsupported request 0x%02x\n", type);
		return -EINVAL;