From 57fa2de1e5671c3632c5666ce08e03f1e3dc0242 Mon Sep 17 00:00:00 2001 From: Georgi Dobrev Date: Tue, 9 Aug 2016 14:37:32 -0700 Subject: [PATCH] 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: Georgi Dobrev Reviewed-by: Viresh Kumar Reviewed-by: Ashwin Chaugule Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/greybus_protocols.h | 7 +++ drivers/staging/greybus/svc.c | 50 +++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index d43b36747113..19ca1dbd9969 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -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 */ diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index 1170515a2a4e..c5aedd55e90d 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -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; -- 2.39.5