diff options
author | Georgi Dobrev <gdobrev@mm-sol.com> | 2016-08-09 14:37:32 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-08-10 15:44:03 +0200 |
commit | 57fa2de1e5671c3632c5666ce08e03f1e3dc0242 (patch) | |
tree | d55ded5b87d145f9eb8e546f438b7c7adcb118aa /drivers/staging/greybus/svc.c | |
parent | 127bada1a1951d9624c08eeab99234ced0df900e (diff) |
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 <gdobrev@mm-sol.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Ashwin Chaugule <ashwinch@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/svc.c')
-rw-r--r-- | drivers/staging/greybus/svc.c | 50 |
1 files changed, 50 insertions, 0 deletions
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; |