]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
greybus: greybus-driver: Add intf_oops operation
authorGeorgi Dobrev <gdobrev@mm-sol.com>
Tue, 9 Aug 2016 21:37:32 +0000 (14:37 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 10 Aug 2016 13:44:03 +0000 (15:44 +0200)
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>
drivers/staging/greybus/greybus_protocols.h
drivers/staging/greybus/svc.c

index d43b367471132882fe98ac3199ba483d335c0455..19ca1dbd996984a40d8168cbed76b9397a5970a5 100644 (file)
@@ -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 */
 
index 1170515a2a4e6be25c47040eb717baa28c9bc04c..c5aedd55e90d31d5c16c40e149cb003f9e8b77f6 100644 (file)
@@ -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;