]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
greybus: Merge branch 'master' into svc to keep it up to date.
authorGreg Kroah-Hartman <gregkh@google.com>
Thu, 30 Jul 2015 19:21:33 +0000 (12:21 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Thu, 30 Jul 2015 19:21:33 +0000 (12:21 -0700)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/Makefile
drivers/staging/greybus/ap.c [deleted file]
drivers/staging/greybus/connection.c
drivers/staging/greybus/core.c
drivers/staging/greybus/es1.c
drivers/staging/greybus/es2.c
drivers/staging/greybus/greybus.h
drivers/staging/greybus/greybus_protocols.h
drivers/staging/greybus/interface.c
drivers/staging/greybus/svc.c
drivers/staging/greybus/svc_msg.h [deleted file]

index 1467c5b3fcd85e87d62ef846ba72d3078ebe44bf..d14bf4d21983cdcac1b6544301b32ea16e70e5bb 100644 (file)
@@ -1,6 +1,5 @@
 greybus-y :=   core.o          \
                debugfs.o       \
-               ap.o            \
                manifest.o      \
                endo.o          \
                module.o        \
diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c
deleted file mode 100644 (file)
index fc23817..0000000
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Greybus "AP" message loop handling
- *
- * Copyright 2014 Google Inc.
- * Copyright 2014 Linaro Ltd.
- *
- * Released under the GPLv2 only.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/device.h>
-#include "svc_msg.h"
-#include "greybus_manifest.h"
-#include "greybus.h"
-
-struct ap_msg {
-       u8 *data;
-       size_t size;
-       struct greybus_host_device *hd;
-       struct work_struct event;
-};
-
-static struct workqueue_struct *ap_workqueue;
-
-static struct svc_msg *svc_msg_alloc(enum svc_function_id id)
-{
-       struct svc_msg *svc_msg;
-
-       svc_msg = kzalloc((sizeof *svc_msg), GFP_KERNEL);
-       if (!svc_msg)
-               return NULL;
-
-       // FIXME - verify we are only sending function IDs we should be
-       svc_msg->header.function_id = id;
-       return svc_msg;
-}
-
-static void svc_msg_free(struct svc_msg *svc_msg)
-{
-       kfree(svc_msg);
-}
-
-static int svc_msg_send(struct svc_msg *svc_msg, struct greybus_host_device *hd)
-{
-       int retval;
-
-       // FIXME - Do we need to do more than just pass it to the hd and then
-       // free it?
-       retval = hd->driver->submit_svc(svc_msg, hd);
-
-       svc_msg_free(svc_msg);
-       return retval;
-}
-
-static void svc_handshake(struct svc_function_handshake *handshake,
-                         int payload_length, struct greybus_host_device *hd)
-{
-       struct svc_msg *svc_msg;
-
-       if (payload_length != sizeof(*handshake)) {
-               dev_err(hd->parent,
-                       "Illegal size of svc handshake message %d\n",
-                       payload_length);
-               return;
-       }
-
-       /* A new SVC communication channel, let's verify a supported version */
-       if ((handshake->version_major != GREYBUS_VERSION_MAJOR) ||
-           (handshake->version_minor != GREYBUS_VERSION_MINOR)) {
-               dev_warn(hd->parent,
-                       "received invalid greybus version %u.%u\n",
-                       handshake->version_major, handshake->version_minor);
-               return;
-       }
-
-       /* Validate that the handshake came from the SVC */
-       if (handshake->handshake_type != SVC_HANDSHAKE_SVC_HELLO) {
-               /* we don't know what to do with this, log it and return */
-               dev_dbg(hd->parent, "received invalid handshake type %d\n",
-                       handshake->handshake_type);
-               return;
-       }
-
-       /* Send back a AP_HELLO message */
-       svc_msg = svc_msg_alloc(SVC_FUNCTION_HANDSHAKE);
-       if (!svc_msg)
-               return;
-
-       svc_msg->header.message_type = SVC_MSG_DATA;
-       svc_msg->header.payload_length =
-               cpu_to_le16(sizeof(*handshake));
-       svc_msg->handshake.version_major = GREYBUS_VERSION_MAJOR;
-       svc_msg->handshake.version_minor = GREYBUS_VERSION_MINOR;
-       svc_msg->handshake.handshake_type = SVC_HANDSHAKE_AP_HELLO;
-
-       (void)svc_msg_send(svc_msg, hd);
-}
-
-static void svc_management(struct svc_function_unipro_management *management,
-                          int payload_length, struct greybus_host_device *hd)
-{
-       struct gb_interface *intf;
-       int ret;
-
-       if (payload_length != sizeof(*management)) {
-               dev_err(hd->parent,
-                       "Illegal size of svc management message %d\n",
-                       payload_length);
-               return;
-       }
-
-       switch (management->management_packet_type) {
-       case SVC_MANAGEMENT_AP_ID:
-               hd->device_id = management->ap_id.device_id;
-               break;
-       case SVC_MANAGEMENT_LINK_UP:
-               intf = gb_interface_find(hd, management->link_up.interface_id);
-               if (!intf) {
-                       dev_err(hd->parent, "Interface ID %d not found\n",
-                               management->link_up.interface_id);
-                       return;
-               }
-               ret = gb_interface_init(intf, management->link_up.device_id);
-               if (ret) {
-                       dev_err(hd->parent,
-                               "error %d initializing interface %hhu\n",
-                               ret, management->link_up.interface_id);
-                       return;
-               }
-               break;
-       default:
-               dev_err(hd->parent, "Unhandled UniPro management message\n");
-       }
-}
-
-static void svc_hotplug(struct svc_function_hotplug *hotplug,
-                       int payload_length, struct greybus_host_device *hd)
-{
-       u8 interface_id = hotplug->interface_id;
-
-       switch (hotplug->hotplug_event) {
-       case SVC_HOTPLUG_EVENT:
-               /* Add a new interface to the system */
-               if (payload_length != sizeof(*hotplug)) {
-                       dev_err(hd->parent,
-                               "Illegal size of svc hotplug message %d\n",
-                               payload_length);
-                       return;
-               }
-               dev_dbg(hd->parent, "interface id %d added\n", interface_id);
-               gb_interface_create(hd, interface_id);
-               break;
-
-       case SVC_HOTUNPLUG_EVENT:
-               /* Remove a interface from the system */
-               if (payload_length != sizeof(*hotplug)) {
-                       dev_err(hd->parent,
-                               "Illegal size of svc hotunplug message %d\n",
-                               payload_length);
-                       return;
-               }
-               dev_dbg(hd->parent, "interface id %d removed\n", interface_id);
-               gb_interface_remove(hd, interface_id);
-               break;
-
-       default:
-               dev_err(hd->parent,
-                       "Received invalid hotplug message type %d\n",
-                       hotplug->hotplug_event);
-               break;
-       }
-}
-
-static void svc_power(struct svc_function_power *power,
-                     int payload_length, struct greybus_host_device *hd)
-{
-       u8 interface_id = power->interface_id;
-
-       /*
-        * The AP is only allowed to get a Battery Status message, not a Battery
-        * Status Request
-        */
-       if (power->power_type != SVC_POWER_BATTERY_STATUS) {
-               dev_err(hd->parent, "Received invalid power type %d\n",
-                       power->power_type);
-               return;
-       }
-
-       /*
-        * As struct struct svc_function_power_battery_status_request is 0 bytes
-        * big, we can just check the union of the whole structure to validate
-        * the size of this message.
-        */
-       if (payload_length != sizeof(*power)) {
-               dev_err(hd->parent,
-                       "Illegal size of svc power message %d\n",
-                       payload_length);
-               return;
-       }
-
-       dev_dbg(hd->parent, "power status for interface id %d is %d\n",
-               interface_id, power->status.status);
-
-       // FIXME - do something with the power information, like update our
-       // battery information...
-}
-
-static void svc_epm(struct svc_function_epm *epm,
-                   int payload_length, struct greybus_host_device *hd)
-{
-       /* What?  An AP should not get this message */
-       dev_err(hd->parent, "Got an EPM message???\n");
-}
-
-static void svc_suspend(struct svc_function_suspend *suspend,
-                       int payload_length, struct greybus_host_device *hd)
-{
-       /* What?  An AP should not get this message */
-       dev_err(hd->parent, "Got an suspend message???\n");
-}
-
-static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg)
-{
-       struct svc_msg *svc_msg;
-       struct svc_msg_header *header;
-       struct greybus_host_device *hd = ap_msg->hd;
-
-       svc_msg = (struct svc_msg *)ap_msg->data;
-       header = &svc_msg->header;
-
-       /* Validate the message type */
-       if (header->message_type != SVC_MSG_DATA) {
-               dev_err(hd->parent, "message type %d received?\n",
-                       header->message_type);
-               return NULL;
-       }
-
-       /*
-        * The validation of the size of the message buffer happens in each
-        * svc_* function, due to the different types of messages, keeping the
-        * logic for each message only in one place.
-        */
-
-       return svc_msg;
-}
-
-static void ap_process_event(struct work_struct *work)
-{
-       struct svc_msg *svc_msg;
-       struct greybus_host_device *hd;
-       struct ap_msg *ap_msg;
-       int payload_length;
-
-       ap_msg = container_of(work, struct ap_msg, event);
-       hd = ap_msg->hd;
-
-       /* Turn the "raw" data into a real message */
-       svc_msg = convert_ap_message(ap_msg);
-       if (!svc_msg)
-               return;
-
-       payload_length = le16_to_cpu(svc_msg->header.payload_length);
-
-       /* Look at the message to figure out what to do with it */
-       switch (svc_msg->header.function_id) {
-       case SVC_FUNCTION_HANDSHAKE:
-               svc_handshake(&svc_msg->handshake, payload_length, hd);
-               break;
-       case SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT:
-               svc_management(&svc_msg->management, payload_length, hd);
-               break;
-       case SVC_FUNCTION_HOTPLUG:
-               svc_hotplug(&svc_msg->hotplug, payload_length, hd);
-               break;
-       case SVC_FUNCTION_POWER:
-               svc_power(&svc_msg->power, payload_length, hd);
-               break;
-       case SVC_FUNCTION_EPM:
-               svc_epm(&svc_msg->epm, payload_length, hd);
-               break;
-       case SVC_FUNCTION_SUSPEND:
-               svc_suspend(&svc_msg->suspend, payload_length, hd);
-               break;
-       default:
-               dev_err(hd->parent, "received invalid SVC function ID %d\n",
-                       svc_msg->header.function_id);
-       }
-
-       /* clean the message up */
-       kfree(ap_msg->data);
-       kfree(ap_msg);
-}
-
-int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int size)
-{
-       struct ap_msg *ap_msg;
-
-       /*
-        * Totally naive copy the message into a new structure that we slowly
-        * create and add it to the list.  Let's get this working, the odds of
-        * this being any "slow path" for AP messages is really low at this
-        * point in time, but you never know, so this comment is here to point
-        * out that maybe we should use a slab allocator, or even just not copy
-        * the data, but use it directly and force the urbs to be "new" each
-        * time.
-        */
-
-       /* Note - this can, and will, be called in interrupt context. */
-       ap_msg = kmalloc(sizeof(*ap_msg), GFP_ATOMIC);
-       if (!ap_msg)
-               return -ENOMEM;
-       ap_msg->data = kmalloc(size, GFP_ATOMIC);
-       if (!ap_msg->data) {
-               kfree(ap_msg);
-               return -ENOMEM;
-       }
-       memcpy(ap_msg->data, data, size);
-       ap_msg->size = size;
-       ap_msg->hd = hd;
-
-       INIT_WORK(&ap_msg->event, ap_process_event);
-       queue_work(ap_workqueue, &ap_msg->event);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(greybus_svc_in);
-
-int __init gb_ap_init(void)
-{
-       ap_workqueue = alloc_ordered_workqueue("greybus_ap", 0);
-       if (!ap_workqueue)
-               return -ENOMEM;
-
-       return 0;
-}
-
-void gb_ap_exit(void)
-{
-       destroy_workqueue(ap_workqueue);
-       ap_workqueue = NULL;
-}
-
-
index 3b553e68235934dd2be53c29970a45da8ebc505c..e7f9c2f82982187f1d2c3feda60be003029fe4ad 100644 (file)
@@ -251,7 +251,12 @@ gb_connection_create_range(struct greybus_host_device *hd,
 
        spin_unlock_irq(&gb_connections_lock);
 
-       /* XXX Will have to establish connections to get version */
+       if (hd_cport_id != GB_SVC_CPORT_ID) {
+               gb_svc_connection_create(hd->svc,
+                                        hd->endo->ap_intf_id, hd_cport_id,
+                                        bundle->intf->interface_id, cport_id);
+       }
+
        gb_connection_bind_protocol(connection);
        if (!connection->protocol)
                dev_warn(&connection->dev,
index 225fa4fb5268223aab67d7a2c149f82c84963535..9f105fb12ede7db9e80c6a57af4dc68482b04b23 100644 (file)
@@ -176,8 +176,7 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
         * Validate that the driver implements all of the callbacks
         * so that we don't have to every time we make them.
         */
-       if ((!driver->message_send) || (!driver->message_cancel) ||
-           (!driver->submit_svc)) {
+       if ((!driver->message_send) || (!driver->message_cancel)) {
                pr_err("Must implement all greybus_host_driver callbacks!\n");
                return ERR_PTR(-EINVAL);
        }
@@ -209,6 +208,21 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
        ida_init(&hd->cport_id_map);
        hd->buffer_size_max = buffer_size_max;
 
+       /*
+        * Initialize AP's SVC protocol connection:
+        *
+        * This is required as part of early initialization of the host device
+        * as we need this connection in order to start any kind of message
+        * exchange between the AP and the SVC. SVC will start with a
+        * 'get-version' request followed by a 'svc-hello' message and at that
+        * time we will create a fully initialized svc-connection, as we need
+        * endo-id and AP's interface id for that.
+        */
+       if (!gb_ap_svc_connection_create(hd)) {
+               kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
+               return ERR_PTR(-ENOMEM);
+       }
+
        return hd;
 }
 EXPORT_SYMBOL_GPL(greybus_create_hd);
@@ -270,12 +284,6 @@ static int __init gb_init(void)
                goto error_bus;
        }
 
-       retval = gb_ap_init();
-       if (retval) {
-               pr_err("gb_ap_init failed (%d)\n", retval);
-               goto error_ap;
-       }
-
        retval = gb_operation_init();
        if (retval) {
                pr_err("gb_operation_init failed (%d)\n", retval);
@@ -309,8 +317,6 @@ error_control:
 error_endo:
        gb_operation_exit();
 error_operation:
-       gb_ap_exit();
-error_ap:
        bus_unregister(&greybus_bus_type);
 error_bus:
        gb_debugfs_cleanup();
@@ -325,7 +331,6 @@ static void __exit gb_exit(void)
        gb_control_protocol_exit();
        gb_endo_exit();
        gb_operation_exit();
-       gb_ap_exit();
        bus_unregister(&greybus_bus_type);
        gb_debugfs_cleanup();
 }
index 0cb7a3c7ef72a0e7120aaba8cae79b1722e5b691..c1fab375bb0b2eb191c49bc01e3238532990f417 100644 (file)
 #include <asm/unaligned.h>
 
 #include "greybus.h"
-#include "svc_msg.h"
 #include "kernel_ver.h"
 
 /* Memory sizes for the buffers sent to/from the ES1 controller */
-#define ES1_SVC_MSG_SIZE       (sizeof(struct svc_msg) + SZ_64K)
 #define ES1_GBUF_MSG_SIZE_MAX  2048
 
 static const struct usb_device_id id_table[] = {
@@ -58,11 +56,8 @@ static DEFINE_KFIFO(apb1_log_fifo, char, APB1_LOG_SIZE);
  * @usb_intf: pointer to the USB interface we are bound to.
  * @hd: pointer to our greybus_host_device structure
  * @control_endpoint: endpoint to send data to SVC
- * @svc_endpoint: endpoint for SVC data in
  * @cport_in_endpoint: bulk in endpoint for CPort data
  * @cport-out_endpoint: bulk out endpoint for CPort data
- * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint
- * @svc_urb: urb for SVC messages coming in on @svc_endpoint
  * @cport_in_urb: array of urbs for the CPort in messages
  * @cport_in_buffer: array of buffers for the @cport_in_urb urbs
  * @cport_out_urb: array of urbs for the CPort out messages
@@ -78,13 +73,9 @@ struct es1_ap_dev {
        struct greybus_host_device *hd;
 
        __u8 control_endpoint;
-       __u8 svc_endpoint;
        __u8 cport_in_endpoint;
        __u8 cport_out_endpoint;
 
-       u8 *svc_buffer;
-       struct urb *svc_urb;
-
        struct urb *cport_in_urb[NUM_CPORT_IN_URB];
        u8 *cport_in_buffer[NUM_CPORT_IN_URB];
        struct urb *cport_out_urb[NUM_CPORT_OUT_URB];
@@ -103,26 +94,6 @@ static void usb_log_enable(struct es1_ap_dev *es1);
 static void usb_log_disable(struct es1_ap_dev *es1);
 
 #define ES1_TIMEOUT    500     /* 500 ms for the SVC to do something */
-static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd)
-{
-       struct es1_ap_dev *es1 = hd_to_es1(hd);
-       int retval;
-
-       /* SVC messages go down our control pipe */
-       retval = usb_control_msg(es1->usb_dev,
-                                usb_sndctrlpipe(es1->usb_dev,
-                                                es1->control_endpoint),
-                                REQUEST_SVC,
-                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                                0x00, 0x00,
-                                (char *)svc_msg,
-                                sizeof(*svc_msg),
-                                ES1_TIMEOUT);
-       if (retval != sizeof(*svc_msg))
-               return retval;
-
-       return 0;
-}
 
 static struct urb *next_free_urb(struct es1_ap_dev *es1, gfp_t gfp_mask)
 {
@@ -303,7 +274,6 @@ static struct greybus_host_driver es1_driver = {
        .hd_priv_size           = sizeof(struct es1_ap_dev),
        .message_send           = message_send,
        .message_cancel         = message_cancel,
-       .submit_svc             = submit_svc,
 };
 
 /* Common function to report consistent warnings based on URB status */
@@ -367,12 +337,6 @@ static void ap_disconnect(struct usb_interface *interface)
                es1->cport_in_buffer[i] = NULL;
        }
 
-       usb_kill_urb(es1->svc_urb);
-       usb_free_urb(es1->svc_urb);
-       es1->svc_urb = NULL;
-       kfree(es1->svc_buffer);
-       es1->svc_buffer = NULL;
-
        usb_set_intfdata(interface, NULL);
        udev = es1->usb_dev;
        greybus_remove_hd(es1->hd);
@@ -380,33 +344,6 @@ static void ap_disconnect(struct usb_interface *interface)
        usb_put_dev(udev);
 }
 
-/* Callback for when we get a SVC message */
-static void svc_in_callback(struct urb *urb)
-{
-       struct greybus_host_device *hd = urb->context;
-       struct device *dev = &urb->dev->dev;
-       int status = check_urb_status(urb);
-       int retval;
-
-       if (status) {
-               if ((status == -EAGAIN) || (status == -EPROTO))
-                       goto exit;
-               dev_err(dev, "urb svc in error %d (dropped)\n", status);
-               return;
-       }
-
-       /* We have a message, create a new message structure, add it to the
-        * list, and wake up our thread that will process the messages.
-        */
-       greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length);
-
-exit:
-       /* resubmit the urb to get more messages */
-       retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval)
-               dev_err(dev, "Can not submit urb for AP data: %d\n", retval);
-}
-
 static void cport_in_callback(struct urb *urb)
 {
        struct greybus_host_device *hd = urb->context;
@@ -610,14 +547,10 @@ static int ap_probe(struct usb_interface *interface,
        struct usb_device *udev;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
-       bool int_in_found = false;
        bool bulk_in_found = false;
        bool bulk_out_found = false;
        int retval = -ENOMEM;
        int i;
-       u16 endo_id = 0x4755;   // FIXME - get endo "ID" from the SVC
-       u8 ap_intf_id = 0x01;   // FIXME - get endo "ID" from the SVC
-       u8 svc_interval = 0;
 
        /* We need to fit a CPort ID in one byte of a message header */
        BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX);
@@ -646,11 +579,7 @@ static int ap_probe(struct usb_interface *interface,
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
 
-               if (usb_endpoint_is_int_in(endpoint)) {
-                       es1->svc_endpoint = endpoint->bEndpointAddress;
-                       svc_interval = endpoint->bInterval;
-                       int_in_found = true;
-               } else if (usb_endpoint_is_bulk_in(endpoint)) {
+               if (usb_endpoint_is_bulk_in(endpoint)) {
                        es1->cport_in_endpoint = endpoint->bEndpointAddress;
                        bulk_in_found = true;
                } else if (usb_endpoint_is_bulk_out(endpoint)) {
@@ -662,27 +591,12 @@ static int ap_probe(struct usb_interface *interface,
                                endpoint->bEndpointAddress);
                }
        }
-       if ((int_in_found == false) ||
-           (bulk_in_found == false) ||
+       if ((bulk_in_found == false) ||
            (bulk_out_found == false)) {
                dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n");
                goto error;
        }
 
-       /* Create our buffer and URB to get SVC messages, and start it up */
-       es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL);
-       if (!es1->svc_buffer)
-               goto error;
-
-       es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!es1->svc_urb)
-               goto error;
-
-       usb_fill_int_urb(es1->svc_urb, udev,
-                        usb_rcvintpipe(udev, es1->svc_endpoint),
-                        es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback,
-                        hd, svc_interval);
-
        /* Allocate buffers for our cport in messages and start them up */
        for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
                struct urb *urb;
@@ -718,22 +632,6 @@ static int ap_probe(struct usb_interface *interface,
                es1->cport_out_urb_busy[i] = false;     /* just to be anal */
        }
 
-       /*
-        * XXX Soon this will be initiated later, with a combination
-        * XXX of a Control protocol probe operation and a
-        * XXX subsequent Control protocol connected operation for
-        * XXX the SVC connection.  At that point we know we're
-        * XXX properly connected to an Endo.
-        */
-       retval = greybus_endo_setup(hd, endo_id, ap_intf_id);
-       if (retval)
-               goto error;
-
-       /* Start up our svc urb, which allows events to start flowing */
-       retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL);
-       if (retval)
-               goto error;
-
        apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable",
                                                        (S_IWUSR | S_IRUGO),
                                                        gb_debugfs_get(), es1,
index 323721a2e2aa0ec3ab22dab6468991061187e91f..558345cd80af4385ae40042cd3d2c3c7df467aaa 100644 (file)
 #include <asm/unaligned.h>
 
 #include "greybus.h"
-#include "svc_msg.h"
 #include "kernel_ver.h"
 
 /* Memory sizes for the buffers sent to/from the ES1 controller */
-#define ES1_SVC_MSG_SIZE       (sizeof(struct svc_msg) + SZ_64K)
 #define ES1_GBUF_MSG_SIZE_MAX  2048
 
 static const struct usb_device_id id_table[] = {
@@ -85,10 +83,7 @@ struct es1_cport_out {
  * @usb_intf: pointer to the USB interface we are bound to.
  * @hd: pointer to our greybus_host_device structure
  * @control_endpoint: endpoint to send data to SVC
- * @svc_endpoint: endpoint for SVC data in
 
- * @svc_buffer: buffer for SVC messages coming in on @svc_endpoint
- * @svc_urb: urb for SVC messages coming in on @svc_endpoint
  * @cport_in: endpoint, urbs and buffer for cport in messages
  * @cport_out: endpoint for for cport out messages
  * @cport_out_urb: array of urbs for the CPort out messages
@@ -104,10 +99,6 @@ struct es1_ap_dev {
        struct greybus_host_device *hd;
 
        __u8 control_endpoint;
-       __u8 svc_endpoint;
-
-       u8 *svc_buffer;
-       struct urb *svc_urb;
 
        struct es1_cport_in cport_in[NUM_BULKS];
        struct es1_cport_out cport_out[NUM_BULKS];
@@ -142,26 +133,6 @@ static int cport_to_ep(struct es1_ap_dev *es1, u16 cport_id)
 }
 
 #define ES1_TIMEOUT    500     /* 500 ms for the SVC to do something */
-static int submit_svc(struct svc_msg *svc_msg, struct greybus_host_device *hd)
-{
-       struct es1_ap_dev *es1 = hd_to_es1(hd);
-       int retval;
-
-       /* SVC messages go down our control pipe */
-       retval = usb_control_msg(es1->usb_dev,
-                                usb_sndctrlpipe(es1->usb_dev,
-                                                es1->control_endpoint),
-                                REQUEST_SVC,
-                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                                0x00, 0x00,
-                                (char *)svc_msg,
-                                sizeof(*svc_msg),
-                                ES1_TIMEOUT);
-       if (retval != sizeof(*svc_msg))
-               return retval;
-
-       return 0;
-}
 
 static int ep_in_use(struct es1_ap_dev *es1, int bulk_ep_set)
 {
@@ -399,7 +370,6 @@ static struct greybus_host_driver es1_driver = {
        .hd_priv_size           = sizeof(struct es1_ap_dev),
        .message_send           = message_send,
        .message_cancel         = message_cancel,
-       .submit_svc             = submit_svc,
 };
 
 /* Common function to report consistent warnings based on URB status */
@@ -467,12 +437,6 @@ static void ap_disconnect(struct usb_interface *interface)
                }
        }
 
-       usb_kill_urb(es1->svc_urb);
-       usb_free_urb(es1->svc_urb);
-       es1->svc_urb = NULL;
-       kfree(es1->svc_buffer);
-       es1->svc_buffer = NULL;
-
        usb_set_intfdata(interface, NULL);
        udev = es1->usb_dev;
        greybus_remove_hd(es1->hd);
@@ -480,33 +444,6 @@ static void ap_disconnect(struct usb_interface *interface)
        usb_put_dev(udev);
 }
 
-/* Callback for when we get a SVC message */
-static void svc_in_callback(struct urb *urb)
-{
-       struct greybus_host_device *hd = urb->context;
-       struct device *dev = &urb->dev->dev;
-       int status = check_urb_status(urb);
-       int retval;
-
-       if (status) {
-               if ((status == -EAGAIN) || (status == -EPROTO))
-                       goto exit;
-               dev_err(dev, "urb svc in error %d (dropped)\n", status);
-               return;
-       }
-
-       /* We have a message, create a new message structure, add it to the
-        * list, and wake up our thread that will process the messages.
-        */
-       greybus_svc_in(hd, urb->transfer_buffer, urb->actual_length);
-
-exit:
-       /* resubmit the urb to get more messages */
-       retval = usb_submit_urb(urb, GFP_ATOMIC);
-       if (retval)
-               dev_err(dev, "Can not submit urb for AP data: %d\n", retval);
-}
-
 static void cport_in_callback(struct urb *urb)
 {
        struct greybus_host_device *hd = urb->context;
@@ -710,14 +647,10 @@ static int ap_probe(struct usb_interface *interface,
        struct usb_device *udev;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
-       bool int_in_found = false;
        int bulk_in = 0;
        int bulk_out = 0;
        int retval = -ENOMEM;
        int i;
-       u16 endo_id = 0x4755;   // FIXME - get endo "ID" from the SVC
-       u8 ap_intf_id = 0x01;   // FIXME - get endo "ID" from the SVC
-       u8 svc_interval = 0;
 
        /* We need to fit a CPort ID in one byte of a message header */
        BUILD_BUG_ON(CPORT_ID_MAX > U8_MAX);
@@ -746,11 +679,7 @@ static int ap_probe(struct usb_interface *interface,
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
 
-               if (usb_endpoint_is_int_in(endpoint)) {
-                       es1->svc_endpoint = endpoint->bEndpointAddress;
-                       svc_interval = endpoint->bInterval;
-                       int_in_found = true;
-               } else if (usb_endpoint_is_bulk_in(endpoint)) {
+               if (usb_endpoint_is_bulk_in(endpoint)) {
                        es1->cport_in[bulk_in++].endpoint =
                                endpoint->bEndpointAddress;
                } else if (usb_endpoint_is_bulk_out(endpoint)) {
@@ -762,27 +691,12 @@ static int ap_probe(struct usb_interface *interface,
                                endpoint->bEndpointAddress);
                }
        }
-       if ((int_in_found == false) ||
-           (bulk_in == 0) ||
+       if ((bulk_in == 0) ||
            (bulk_out == 0)) {
                dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n");
                goto error;
        }
 
-       /* Create our buffer and URB to get SVC messages, and start it up */
-       es1->svc_buffer = kmalloc(ES1_SVC_MSG_SIZE, GFP_KERNEL);
-       if (!es1->svc_buffer)
-               goto error;
-
-       es1->svc_urb = usb_alloc_urb(0, GFP_KERNEL);
-       if (!es1->svc_urb)
-               goto error;
-
-       usb_fill_int_urb(es1->svc_urb, udev,
-                        usb_rcvintpipe(udev, es1->svc_endpoint),
-                        es1->svc_buffer, ES1_SVC_MSG_SIZE, svc_in_callback,
-                        hd, svc_interval);
-
        /* Allocate buffers for our cport in messages and start them up */
        for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) {
                struct es1_cport_in *cport_in = &es1->cport_in[bulk_in];
@@ -822,22 +736,6 @@ static int ap_probe(struct usb_interface *interface,
                es1->cport_out_urb_busy[i] = false;     /* just to be anal */
        }
 
-       /*
-        * XXX Soon this will be initiated later, with a combination
-        * XXX of a Control protocol probe operation and a
-        * XXX subsequent Control protocol connected operation for
-        * XXX the SVC connection.  At that point we know we're
-        * XXX properly connected to an Endo.
-        */
-       retval = greybus_endo_setup(hd, endo_id, ap_intf_id);
-       if (retval)
-               goto error;
-
-       /* Start up our svc urb, which allows events to start flowing */
-       retval = usb_submit_urb(es1->svc_urb, GFP_KERNEL);
-       if (retval)
-               goto error;
-
        apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable",
                                                        (S_IWUSR | S_IRUGO),
                                                        gb_debugfs_get(), es1,
index 2214f447df2bda8d5acfda1e937a563cbc2bc48e..cdade1e9b4c7c3c1274f6218065c3e062ea85264 100644 (file)
@@ -73,7 +73,6 @@
  */
 
 struct greybus_host_device;
-struct svc_msg;
 
 /* Greybus "Host driver" structure, needed by a host controller driver to be
  * able to handle both SVC control as well as "real" greybus messages
@@ -84,8 +83,6 @@ struct greybus_host_driver {
        int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id,
                        struct gb_message *message, gfp_t gfp_mask);
        void (*message_cancel)(struct gb_message *message);
-       int (*submit_svc)(struct svc_msg *svc_msg,
-                           struct greybus_host_device *hd);
 };
 
 struct greybus_host_device {
@@ -103,6 +100,7 @@ struct greybus_host_device {
 
        struct gb_endo *endo;
        struct gb_connection *initial_svc_connection;
+       struct gb_svc *svc;
 
        /* Private data for the host driver */
        unsigned long hd_priv[0] __aligned(sizeof(s64));
@@ -155,9 +153,6 @@ void greybus_deregister_driver(struct greybus_driver *driver);
 
 int greybus_disabled(void);
 
-int greybus_svc_in(struct greybus_host_device *hd, u8 *data, int length);
-int gb_ap_init(void);
-void gb_ap_exit(void);
 void gb_debugfs_init(void);
 void gb_debugfs_cleanup(void);
 struct dentry *gb_debugfs_get(void);
index 61fe9dce6ec0d4ff7c533d1b8c9634f79e4bfcc5..e2d38dfe06b60f9740111968eaa0fb99f65e321c 100644 (file)
@@ -64,9 +64,9 @@
  * CONTROL and SVC protocols for communication between AP and SVC.
  */
 #define GB_SVC_BUNDLE_ID                       0
-#define GB_SVC_CPORT_ID                                2
+#define GB_SVC_CPORT_ID                                0
 #define GB_CONTROL_BUNDLE_ID                   0
-#define GB_CONTROL_CPORT_ID                    2
+#define GB_CONTROL_CPORT_ID                    0
 
 
 /* Control Protocol */
@@ -563,6 +563,7 @@ struct gb_spi_transfer_response {
 #define GB_SVC_TYPE_INTF_RESET         0x06
 #define GB_SVC_TYPE_CONN_CREATE                0x07
 #define GB_SVC_TYPE_CONN_DESTROY       0x08
+#define GB_SVC_TYPE_ROUTE_CREATE       0x0b
 
 /* SVC version request/response have same payload as gb_protocol_version_response */
 
@@ -605,6 +606,8 @@ struct gb_svc_conn_create_request {
        __u16   cport1_id;
        __u8    intf2_id;
        __u16   cport2_id;
+       __u8    tc;
+       __u8    flags;
 };
 /* connection create response has no payload */
 
@@ -616,6 +619,13 @@ struct gb_svc_conn_destroy_request {
 };
 /* connection destroy response has no payload */
 
+struct gb_svc_route_create_request {
+       __u8    intf1_id;
+       __u8    dev1_id;
+       __u8    intf2_id;
+       __u8    dev2_id;
+};
+
 /* UART */
 
 /* Version of the Greybus UART protocol we support */
index f1e2956b25a7a305e0f58567afad982716f9868e..4a26bf6f714ca79205d0abead9ce40c8feae183e 100644 (file)
@@ -183,7 +183,7 @@ put_module:
 /*
  * Tear down a previously set up module.
  */
-void gb_interface_destroy(struct gb_interface *intf)
+static void interface_destroy(struct gb_interface *intf)
 {
        struct gb_module *module;
        struct gb_bundle *bundle;
@@ -279,7 +279,7 @@ void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id)
        struct gb_interface *intf = gb_interface_find(hd, interface_id);
 
        if (intf)
-               gb_interface_destroy(intf);
+               interface_destroy(intf);
        else
                dev_err(hd->parent, "interface id %d not found\n",
                        interface_id);
@@ -290,5 +290,5 @@ void gb_interfaces_remove(struct greybus_host_device *hd)
        struct gb_interface *intf, *temp;
 
        list_for_each_entry_safe(intf, temp, &hd->interfaces, links)
-               gb_interface_destroy(intf);
+               interface_destroy(intf);
 }
index 5f2b2b43b939cd0bd1565ca2441ec3764b0caaaa..784b7709b432210a109f3f8acac7b1759a7e0d67 100644 (file)
@@ -9,6 +9,10 @@
 
 #include "greybus.h"
 
+#define CPORT_FLAGS_E2EFC       (1)
+#define CPORT_FLAGS_CSD_N       (2)
+#define CPORT_FLAGS_CSV_N       (4)
+
 struct gb_svc {
        struct gb_connection    *connection;
        u8                      version_major;
@@ -36,7 +40,6 @@ gb_ap_svc_connection_create(struct greybus_host_device *hd)
 
        return connection;
 }
-EXPORT_SYMBOL_GPL(gb_ap_svc_connection_create);
 
 /*
  * We know endo-type and AP's interface id now, lets create a proper svc
@@ -98,6 +101,12 @@ static int connection_create_operation(struct gb_svc *svc,
        request.cport1_id = cport1_id;
        request.intf2_id = intf2_id;
        request.cport2_id = cport2_id;
+       /*
+        * XXX: fix connections paramaters to TC0 and all CPort flags
+        * for now.
+        */
+       request.tc = 0;
+       request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC;
 
        return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE,
                                 &request, sizeof(request), NULL, 0);
@@ -118,6 +127,20 @@ static int connection_destroy_operation(struct gb_svc *svc,
                                 &request, sizeof(request), NULL, 0);
 }
 
+static int route_create_operation(struct gb_svc *svc, u8 intf1_id, u8 dev1_id,
+                                 u8 intf2_id, u8 dev2_id)
+{
+       struct gb_svc_route_create_request request;
+
+       request.intf1_id = intf1_id;
+       request.dev1_id = dev1_id;
+       request.intf2_id = intf2_id;
+       request.dev2_id = dev2_id;
+
+       return gb_operation_sync(svc->connection, GB_SVC_TYPE_ROUTE_CREATE,
+                                &request, sizeof(request), NULL, 0);
+}
+
 int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id)
 {
        return intf_device_id_operation(svc, intf_id, device_id);
@@ -148,6 +171,13 @@ int gb_svc_connection_destroy(struct gb_svc *svc,
 }
 EXPORT_SYMBOL_GPL(gb_svc_connection_destroy);
 
+int gb_svc_route_create(struct gb_svc *svc, u8 intf1_id, u8 dev1_id,
+                       u8 intf2_id, u8 dev2_id) {
+       return route_create_operation(svc, intf1_id, dev1_id,
+                                     intf2_id, dev2_id);
+}
+EXPORT_SYMBOL_GPL(gb_svc_route_create);
+
 static int gb_svc_version_request(struct gb_operation *op)
 {
        struct gb_connection *connection = op->connection;
@@ -288,6 +318,25 @@ static int gb_svc_intf_hotplug_recv(struct gb_operation *op)
                goto ida_put;
        }
 
+       /*
+        * Create a two-way route between the AP and the new interface
+        */
+       ret = route_create_operation(svc, hd->endo->ap_intf_id,
+                                    GB_DEVICE_ID_AP, intf_id, device_id);
+       if (ret) {
+               dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n",
+                       __func__, intf_id, device_id, ret);
+               goto ida_put;
+       }
+
+       ret = route_create_operation(svc, intf_id, device_id,
+                                    hd->endo->ap_intf_id, GB_DEVICE_ID_AP);
+       if (ret) {
+               dev_err(dev, "%s: Route create operation failed, interface %hhu device_id %hhu (%d)\n",
+                       __func__, intf_id, device_id, ret);
+               goto ida_put;
+       }
+
        ret = gb_interface_init(intf, device_id);
        if (ret) {
                dev_err(dev, "%s: Failed to initialize interface, interface %hhu device_id %hhu (%d)\n",
@@ -390,6 +439,7 @@ static int gb_svc_connection_init(struct gb_connection *connection)
        if (!svc)
                return -ENOMEM;
 
+       connection->hd->svc = svc;
        svc->connection = connection;
        connection->private = svc;
 
@@ -405,6 +455,7 @@ static void gb_svc_connection_exit(struct gb_connection *connection)
 {
        struct gb_svc *svc = connection->private;
 
+       connection->hd->svc = NULL;
        connection->private = NULL;
        kfree(svc);
 }
diff --git a/drivers/staging/greybus/svc_msg.h b/drivers/staging/greybus/svc_msg.h
deleted file mode 100644 (file)
index 3c628c5..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Greybus AP <-> SVC message structure format.
- *
- * See "Greybus Application Protocol" document (version 0.1) for
- * details on these values and structures.
- *
- * Copyright 2014 Google Inc.
- * Copyright 2014 Linaro Ltd.
- *
- * Released under the GPLv2 and BSD license.
- */
-
-#ifndef __SVC_MSG_H
-#define __SVC_MSG_H
-
-enum svc_function_id {
-       SVC_FUNCTION_HANDSHAKE                  = 0x00,
-       SVC_FUNCTION_UNIPRO_NETWORK_MANAGEMENT  = 0x01,
-       SVC_FUNCTION_HOTPLUG                    = 0x02,
-       SVC_FUNCTION_POWER                      = 0x03,
-       SVC_FUNCTION_EPM                        = 0x04,
-       SVC_FUNCTION_SUSPEND                    = 0x05,
-};
-
-enum svc_msg_type {
-       SVC_MSG_DATA                            = 0x00,
-       SVC_MSG_ERROR                           = 0xff,
-};
-
-struct svc_msg_header {
-       __u8    function_id;    /* enum svc_function_id */
-       __u8    message_type;
-       __le16  payload_length;
-} __packed;
-
-enum svc_function_handshake_type {
-       SVC_HANDSHAKE_SVC_HELLO         = 0x00,
-       SVC_HANDSHAKE_AP_HELLO          = 0x01,
-       SVC_HANDSHAKE_MODULE_HELLO      = 0x02,
-};
-
-struct svc_function_handshake {
-       __u8    version_major;
-       __u8    version_minor;
-       __u8    handshake_type; /* enum svc_function_handshake_type */
-} __packed;
-
-struct svc_function_unipro_set_route {
-       __u8    device_id;
-} __packed;
-
-struct svc_function_unipro_link_up {
-       __u8    interface_id;   /* Interface id within the Endo */
-       __u8    device_id;
-} __packed;
-
-struct svc_function_ap_id {
-       __u8    interface_id;
-       __u8    device_id;
-} __packed;
-
-enum svc_function_management_event {
-       SVC_MANAGEMENT_AP_ID            = 0x00,
-       SVC_MANAGEMENT_LINK_UP          = 0x01,
-       SVC_MANAGEMENT_SET_ROUTE        = 0x02,
-};
-
-struct svc_function_unipro_management {
-       __u8    management_packet_type; /* enum svc_function_management_event */
-       union {
-               struct svc_function_ap_id               ap_id;
-               struct svc_function_unipro_link_up      link_up;
-               struct svc_function_unipro_set_route    set_route;
-       };
-} __packed;
-
-enum svc_function_hotplug_event {
-       SVC_HOTPLUG_EVENT       = 0x00,
-       SVC_HOTUNPLUG_EVENT     = 0x01,
-};
-
-struct svc_function_hotplug {
-       __u8    hotplug_event;  /* enum svc_function_hotplug_event */
-       __u8    interface_id;   /* Interface id within the Endo */
-} __packed;
-
-enum svc_function_power_type {
-       SVC_POWER_BATTERY_STATUS                = 0x00,
-       SVC_POWER_BATTERY_STATUS_REQUEST        = 0x01,
-};
-
-enum svc_function_battery_status {
-       SVC_BATTERY_UNKNOWN             = 0x00,
-       SVC_BATTERY_CHARGING            = 0x01,
-       SVC_BATTERY_DISCHARGING         = 0x02,
-       SVC_BATTERY_NOT_CHARGING        = 0x03,
-       SVC_BATTERY_FULL                = 0x04,
-};
-
-struct svc_function_power_battery_status {
-       __le16  charge_full;
-       __le16  charge_now;
-       __u8    status; /* enum svc_function_battery_status */
-} __packed;
-
-struct svc_function_power_battery_status_request {
-} __packed;
-
-/* XXX
- * Each interface carries power, so it's possible these things
- * are associated with each UniPro device and not just the module.
- * For now it's safe to assume it's per-module.
- */
-struct svc_function_power {
-       __u8    power_type;     /* enum svc_function_power_type */
-       __u8    interface_id;
-       union {
-               struct svc_function_power_battery_status                status;
-               struct svc_function_power_battery_status_request        request;
-       };
-} __packed;
-
-enum svc_function_epm_command_type {
-       SVC_EPM_ENABLE  = 0x00,
-       SVC_EPM_DISABLE = 0x01,
-};
-
-/* EPM's are associated with the module */
-struct svc_function_epm {
-       __u8    epm_command_type;       /* enum svc_function_epm_command_type */
-       __u8    module_id;
-} __packed;
-
-enum svc_function_suspend_command_type {
-       SVC_SUSPEND_FIXME_1     = 0x00, // FIXME
-       SVC_SUSPEND_FIXME_2     = 0x01,
-};
-
-/* We'll want independent control for multi-interface modules */
-struct svc_function_suspend {
-       __u8    suspend_command_type;   /* enum function_suspend_command_type */
-       __u8    device_id;
-} __packed;
-
-struct svc_msg {
-       struct svc_msg_header   header;
-       union {
-               struct svc_function_handshake           handshake;
-               struct svc_function_unipro_management   management;
-               struct svc_function_hotplug             hotplug;
-               struct svc_function_power               power;
-               struct svc_function_epm                 epm;
-               struct svc_function_suspend             suspend;
-       };
-} __packed;
-
-#endif /* __SVC_MSG_H */