greybus: es2: fix up usb probe error messages
[cascardo/linux.git] / drivers / staging / greybus / es2.c
index 6ada1ee..6cb13fc 100644 (file)
 #include <linux/list.h>
 #include <asm/unaligned.h>
 
+#include "arpc.h"
 #include "greybus.h"
 #include "greybus_trace.h"
 #include "kernel_ver.h"
 #include "connection.h"
 
+
+/* Default timeout for USB vendor requests. */
+#define ES2_USB_CTRL_TIMEOUT   500
+
+/* Default timeout for ARPC CPort requests */
+#define ES2_ARPC_CPORT_TIMEOUT 500
+
 /* Fixed CPort numbers */
 #define ES2_CPORT_CDSI0                16
 #define ES2_CPORT_CDSI1                17
@@ -38,15 +46,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 #define APB1_LOG_SIZE          SZ_16K
 
-/* Number of bulk in and bulk out couple */
-#define NUM_BULKS              7
-
-/* Expected number of bulk out endpoints */
-#define NUM_BULKS_OUT          NUM_BULKS
-
-/* Expected number of bulk in endpoints (including ARPC endpoint) */
-#define NUM_BULKS_IN           (NUM_BULKS + 1)
-
 /*
  * Number of CPort IN urbs in flight at any point in time.
  * Adjust if we are having stalls in the USB buffer due to not enough urbs in
@@ -57,7 +56,7 @@ MODULE_DEVICE_TABLE(usb, id_table);
 /* Number of CPort OUT urbs in flight at any point in time.
  * Adjust if we get messages saying we are out of urbs in the system log.
  */
-#define NUM_CPORT_OUT_URB      (8 * NUM_BULKS)
+#define NUM_CPORT_OUT_URB      8
 
 /*
  * Number of ARPC in urbs in flight at any point in time.
@@ -75,13 +74,6 @@ struct es2_cport_in {
        u8 *buffer[NUM_CPORT_IN_URB];
 };
 
-/*
- * @endpoint: bulk out endpoint for CPort data
- */
-struct es2_cport_out {
-       __u8 endpoint;
-};
-
 /**
  * es2_ap_dev - ES2 USB Bridge to AP structure
  * @usb_dev: pointer to the USB device we are.
@@ -89,7 +81,7 @@ struct es2_cport_out {
  * @hd: pointer to our gb_host_device structure
 
  * @cport_in: endpoint, urbs and buffer for cport in messages
- * @cport_out: endpoint for for cport out messages
+ * @cport_out_endpoint: endpoint for for cport out messages
  * @cport_out_urb: array of urbs for the CPort out messages
  * @cport_out_urb_busy: array of flags to see if the @cport_out_urb is busy or
  *                     not.
@@ -113,8 +105,8 @@ struct es2_ap_dev {
        struct usb_interface *usb_intf;
        struct gb_host_device *hd;
 
-       struct es2_cport_in cport_in[NUM_BULKS];
-       struct es2_cport_out cport_out[NUM_BULKS];
+       struct es2_cport_in cport_in;
+       __u8 cport_out_endpoint;
        struct urb *cport_out_urb[NUM_CPORT_OUT_URB];
        bool cport_out_urb_busy[NUM_CPORT_OUT_URB];
        bool cport_out_urb_cancelled[NUM_CPORT_OUT_URB];
@@ -122,8 +114,6 @@ struct es2_ap_dev {
 
        bool cdsi1_in_use;
 
-       int *cport_to_ep;
-
        struct task_struct *apb_log_task;
        struct dentry *apb_log_dentry;
        struct dentry *apb_log_enable_dentry;
@@ -138,18 +128,6 @@ struct es2_ap_dev {
        struct list_head arpcs;
 };
 
-/**
- * cport_to_ep - information about cport to endpoints mapping
- * @cport_id: the id of cport to map to endpoints
- * @endpoint_in: the endpoint number to use for in transfer
- * @endpoint_out: he endpoint number to use for out transfer
- */
-struct cport_to_ep {
-       __le16 cport_id;
-       __u8 endpoint_in;
-       __u8 endpoint_out;
-};
-
 /**
  * timesync_enable_request - Enable timesync in an APBridge
  * @count: number of TimeSync Pulses to expect
@@ -192,75 +170,6 @@ static void usb_log_disable(struct es2_ap_dev *es2);
 static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload,
                     size_t size, int *result, unsigned int timeout);
 
-/* Get the endpoints pair mapped to the cport */
-static int cport_to_ep_pair(struct es2_ap_dev *es2, u16 cport_id)
-{
-       if (cport_id >= es2->hd->num_cports)
-               return 0;
-       return es2->cport_to_ep[cport_id];
-}
-
-#define ES2_TIMEOUT    500     /* 500 ms for the SVC to do something */
-
-/* Disable for now until we work all of this out to keep a warning-free build */
-#if 0
-/* Test if the endpoints pair is already mapped to a cport */
-static int ep_pair_in_use(struct es2_ap_dev *es2, int ep_pair)
-{
-       int i;
-
-       for (i = 0; i < es2->hd->num_cports; i++) {
-               if (es2->cport_to_ep[i] == ep_pair)
-                       return 1;
-       }
-       return 0;
-}
-
-/* Configure the endpoint mapping and send the request to APBridge */
-static int map_cport_to_ep(struct es2_ap_dev *es2,
-                               u16 cport_id, int ep_pair)
-{
-       int retval;
-       struct cport_to_ep *cport_to_ep;
-
-       if (ep_pair < 0 || ep_pair >= NUM_BULKS)
-               return -EINVAL;
-       if (cport_id >= es2->hd->num_cports)
-               return -EINVAL;
-       if (ep_pair && ep_pair_in_use(es2, ep_pair))
-               return -EINVAL;
-
-       cport_to_ep = kmalloc(sizeof(*cport_to_ep), GFP_KERNEL);
-       if (!cport_to_ep)
-               return -ENOMEM;
-
-       es2->cport_to_ep[cport_id] = ep_pair;
-       cport_to_ep->cport_id = cpu_to_le16(cport_id);
-       cport_to_ep->endpoint_in = es2->cport_in[ep_pair].endpoint;
-       cport_to_ep->endpoint_out = es2->cport_out[ep_pair].endpoint;
-
-       retval = usb_control_msg(es2->usb_dev,
-                                usb_sndctrlpipe(es2->usb_dev, 0),
-                                GB_APB_REQUEST_EP_MAPPING,
-                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                                0x00, 0x00,
-                                (char *)cport_to_ep,
-                                sizeof(*cport_to_ep),
-                                ES2_TIMEOUT);
-       if (retval == sizeof(*cport_to_ep))
-               retval = 0;
-       kfree(cport_to_ep);
-
-       return retval;
-}
-
-/* Unmap a cport: use the muxed endpoints pair */
-static int unmap_cport(struct es2_ap_dev *es2, u16 cport_id)
-{
-       return map_cport_to_ep(es2, cport_id, 0);
-}
-#endif
-
 static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd)
 {
        struct usb_device *udev = es2->usb_dev;
@@ -276,7 +185,7 @@ static int output_sync(struct es2_ap_dev *es2, void *req, u16 size, u8 cmd)
                                 cmd,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE,
-                                0, 0, data, size, ES2_TIMEOUT);
+                                0, 0, data, size, ES2_USB_CTRL_TIMEOUT);
        if (retval < 0)
                dev_err(&udev->dev, "%s: return error %d\n", __func__, retval);
        else
@@ -513,7 +422,6 @@ static int message_send(struct gb_host_device *hd, u16 cport_id,
        size_t buffer_size;
        int retval;
        struct urb *urb;
-       int ep_pair;
        unsigned long flags;
 
        /*
@@ -540,10 +448,9 @@ static int message_send(struct gb_host_device *hd, u16 cport_id,
 
        buffer_size = sizeof(*message->header) + message->payload_size;
 
-       ep_pair = cport_to_ep_pair(es2, cport_id);
        usb_fill_bulk_urb(urb, udev,
                          usb_sndbulkpipe(udev,
-                                         es2->cport_out[ep_pair].endpoint),
+                                         es2->cport_out_endpoint),
                          message->buffer, buffer_size,
                          cport_out_callback, message);
        urb->transfer_flags |= URB_ZERO_PACKET;
@@ -605,32 +512,6 @@ static void message_cancel(struct gb_message *message)
        usb_free_urb(urb);
 }
 
-static int cport_reset(struct gb_host_device *hd, u16 cport_id)
-{
-       struct es2_ap_dev *es2 = hd_to_es2(hd);
-       struct usb_device *udev = es2->usb_dev;
-       struct arpc_cport_reset req;
-       int retval;
-       int result;
-
-       switch (cport_id) {
-       case GB_SVC_CPORT_ID:
-       case ES2_CPORT_CDSI0:
-       case ES2_CPORT_CDSI1:
-               return 0;
-       }
-
-       req.cport_id = cpu_to_le16(cport_id);
-       retval = arpc_sync(es2, ARPC_CPORT_RESET, &req, sizeof(req),
-                          &result, ES2_TIMEOUT);
-       if (retval == -EREMOTEIO) {
-               dev_err(&udev->dev, "failed to reset cport %u: %d\n", cport_id,
-                       result);
-       }
-
-       return retval;
-}
-
 static int es2_cport_allocate(struct gb_host_device *hd, int cport_id,
                                unsigned long flags)
 {
@@ -690,25 +571,29 @@ static int cport_enable(struct gb_host_device *hd, u16 cport_id,
        struct es2_ap_dev *es2 = hd_to_es2(hd);
        struct usb_device *udev = es2->usb_dev;
        struct gb_apb_request_cport_flags *req;
+       u32 connection_flags;
        int ret;
 
        req = kzalloc(sizeof(*req), GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
+       connection_flags = 0;
        if (flags & GB_CONNECTION_FLAG_CONTROL)
-               req->flags |= GB_APB_CPORT_FLAG_CONTROL;
+               connection_flags |= GB_APB_CPORT_FLAG_CONTROL;
        if (flags & GB_CONNECTION_FLAG_HIGH_PRIO)
-               req->flags |= GB_APB_CPORT_FLAG_HIGH_PRIO;
+               connection_flags |= GB_APB_CPORT_FLAG_HIGH_PRIO;
+
+       req->flags = cpu_to_le32(connection_flags);
 
        dev_dbg(&hd->dev, "%s - cport = %u, flags = %02x\n", __func__,
-                       cport_id, req->flags);
+                       cport_id, connection_flags);
 
        ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
                                GB_APB_REQUEST_CPORT_FLAGS,
                                USB_DIR_OUT | USB_TYPE_VENDOR |
                                USB_RECIP_INTERFACE, cport_id, 0,
-                               req, sizeof(*req), ES2_TIMEOUT);
+                               req, sizeof(*req), ES2_USB_CTRL_TIMEOUT);
        if (ret != sizeof(*req)) {
                dev_err(&udev->dev, "failed to set cport flags for port %d\n",
                                cport_id);
@@ -725,85 +610,149 @@ out:
        return ret;
 }
 
-static int cport_disable(struct gb_host_device *hd, u16 cport_id)
+static int es2_cport_connected(struct gb_host_device *hd, u16 cport_id)
 {
-       int retval;
+       struct es2_ap_dev *es2 = hd_to_es2(hd);
+       struct device *dev = &es2->usb_dev->dev;
+       struct arpc_cport_connected_req req;
+       int ret;
 
-       retval = cport_reset(hd, cport_id);
-       if (retval)
-               return retval;
+       req.cport_id = cpu_to_le16(cport_id);
+       ret = arpc_sync(es2, ARPC_TYPE_CPORT_CONNECTED, &req, sizeof(req),
+                       NULL, ES2_ARPC_CPORT_TIMEOUT);
+       if (ret) {
+               dev_err(dev, "failed to set connected state for cport %u: %d\n",
+                               cport_id, ret);
+               return ret;
+       }
 
        return 0;
 }
 
-static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id)
+static int es2_cport_flush(struct gb_host_device *hd, u16 cport_id)
 {
-       int retval;
        struct es2_ap_dev *es2 = hd_to_es2(hd);
-       struct usb_device *udev = es2->usb_dev;
+       struct device *dev = &es2->usb_dev->dev;
+       struct arpc_cport_flush_req req;
+       int ret;
 
-       retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                GB_APB_REQUEST_LATENCY_TAG_EN,
-                                USB_DIR_OUT | USB_TYPE_VENDOR |
-                                USB_RECIP_INTERFACE, cport_id, 0, NULL,
-                                0, ES2_TIMEOUT);
+       req.cport_id = cpu_to_le16(cport_id);
+       ret = arpc_sync(es2, ARPC_TYPE_CPORT_FLUSH, &req, sizeof(req),
+                       NULL, ES2_ARPC_CPORT_TIMEOUT);
+       if (ret) {
+               dev_err(dev, "failed to flush cport %u: %d\n", cport_id, ret);
+               return ret;
+       }
 
-       if (retval < 0)
-               dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n",
-                       cport_id);
-       return retval;
+       return 0;
 }
 
-static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id)
+static int es2_cport_shutdown(struct gb_host_device *hd, u16 cport_id,
+                               u8 phase, unsigned int timeout)
 {
-       int retval;
        struct es2_ap_dev *es2 = hd_to_es2(hd);
-       struct usb_device *udev = es2->usb_dev;
+       struct device *dev = &es2->usb_dev->dev;
+       struct arpc_cport_shutdown_req req;
+       int result;
+       int ret;
 
-       retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                GB_APB_REQUEST_LATENCY_TAG_DIS,
-                                USB_DIR_OUT | USB_TYPE_VENDOR |
-                                USB_RECIP_INTERFACE, cport_id, 0, NULL,
-                                0, ES2_TIMEOUT);
+       if (timeout > U16_MAX)
+               return -EINVAL;
 
-       if (retval < 0)
-               dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n",
-                       cport_id);
-       return retval;
+       req.cport_id = cpu_to_le16(cport_id);
+       req.timeout = cpu_to_le16(timeout);
+       req.phase = phase;
+       ret = arpc_sync(es2, ARPC_TYPE_CPORT_SHUTDOWN, &req, sizeof(req),
+                       &result, ES2_ARPC_CPORT_TIMEOUT + timeout);
+       if (ret) {
+               dev_err(dev, "failed to send shutdown over cport %u: %d (%d)\n",
+                               cport_id, ret, result);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int es2_cport_quiesce(struct gb_host_device *hd, u16 cport_id,
+                               size_t peer_space, unsigned int timeout)
+{
+       struct es2_ap_dev *es2 = hd_to_es2(hd);
+       struct device *dev = &es2->usb_dev->dev;
+       struct arpc_cport_quiesce_req req;
+       int result;
+       int ret;
+
+       if (peer_space > U16_MAX)
+               return -EINVAL;
+
+       if (timeout > U16_MAX)
+               return -EINVAL;
+
+       req.cport_id = cpu_to_le16(cport_id);
+       req.peer_space = cpu_to_le16(peer_space);
+       req.timeout = cpu_to_le16(timeout);
+       ret = arpc_sync(es2, ARPC_TYPE_CPORT_QUIESCE, &req, sizeof(req),
+                       &result, ES2_ARPC_CPORT_TIMEOUT + timeout);
+       if (ret) {
+               dev_err(dev, "failed to quiesce cport %u: %d (%d)\n",
+                               cport_id, ret, result);
+               return ret;
+       }
+
+       return 0;
 }
 
-static int cport_features_enable(struct gb_host_device *hd, u16 cport_id)
+static int es2_cport_clear(struct gb_host_device *hd, u16 cport_id)
+{
+       struct es2_ap_dev *es2 = hd_to_es2(hd);
+       struct device *dev = &es2->usb_dev->dev;
+       struct arpc_cport_clear_req req;
+       int ret;
+
+       req.cport_id = cpu_to_le16(cport_id);
+       ret = arpc_sync(es2, ARPC_TYPE_CPORT_CLEAR, &req, sizeof(req),
+                       NULL, ES2_ARPC_CPORT_TIMEOUT);
+       if (ret) {
+               dev_err(dev, "failed to clear cport %u: %d\n", cport_id, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int latency_tag_enable(struct gb_host_device *hd, u16 cport_id)
 {
        int retval;
        struct es2_ap_dev *es2 = hd_to_es2(hd);
        struct usb_device *udev = es2->usb_dev;
 
        retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                GB_APB_REQUEST_CPORT_FEAT_EN,
+                                GB_APB_REQUEST_LATENCY_TAG_EN,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, cport_id, 0, NULL,
-                                0, ES2_TIMEOUT);
+                                0, ES2_USB_CTRL_TIMEOUT);
+
        if (retval < 0)
-               dev_err(&udev->dev, "Cannot enable CPort features for cport %u: %d\n",
-                       cport_id, retval);
+               dev_err(&udev->dev, "Cannot enable latency tag for cport %d\n",
+                       cport_id);
        return retval;
 }
 
-static int cport_features_disable(struct gb_host_device *hd, u16 cport_id)
+static int latency_tag_disable(struct gb_host_device *hd, u16 cport_id)
 {
        int retval;
        struct es2_ap_dev *es2 = hd_to_es2(hd);
        struct usb_device *udev = es2->usb_dev;
 
        retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                GB_APB_REQUEST_CPORT_FEAT_DIS,
+                                GB_APB_REQUEST_LATENCY_TAG_DIS,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, cport_id, 0, NULL,
-                                0, ES2_TIMEOUT);
+                                0, ES2_USB_CTRL_TIMEOUT);
+
        if (retval < 0)
-               dev_err(&udev->dev,
-                       "Cannot disable CPort features for cport %u: %d\n",
-                       cport_id, retval);
+               dev_err(&udev->dev, "Cannot disable latency tag for cport %d\n",
+                       cport_id);
        return retval;
 }
 
@@ -824,10 +773,10 @@ static int timesync_enable(struct gb_host_device *hd, u8 count,
        request->strobe_delay = cpu_to_le32(strobe_delay);
        request->refclk = cpu_to_le32(refclk);
        retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                REQUEST_TIMESYNC_ENABLE,
+                                GB_APB_REQUEST_TIMESYNC_ENABLE,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, 0, 0, request,
-                                sizeof(*request), ES2_TIMEOUT);
+                                sizeof(*request), ES2_USB_CTRL_TIMEOUT);
        if (retval < 0)
                dev_err(&udev->dev, "Cannot enable timesync %d\n", retval);
 
@@ -842,10 +791,10 @@ static int timesync_disable(struct gb_host_device *hd)
        struct usb_device *udev = es2->usb_dev;
 
        retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                REQUEST_TIMESYNC_DISABLE,
+                                GB_APB_REQUEST_TIMESYNC_DISABLE,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, 0, 0, NULL,
-                                0, ES2_TIMEOUT);
+                                0, ES2_USB_CTRL_TIMEOUT);
        if (retval < 0)
                dev_err(&udev->dev, "Cannot disable timesync %d\n", retval);
 
@@ -867,10 +816,10 @@ static int timesync_authoritative(struct gb_host_device *hd, u64 *frame_time)
                request->frame_time[i] = cpu_to_le64(frame_time[i]);
 
        retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                REQUEST_TIMESYNC_AUTHORITATIVE,
+                                GB_APB_REQUEST_TIMESYNC_AUTHORITATIVE,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, 0, 0, request,
-                                sizeof(*request), ES2_TIMEOUT);
+                                sizeof(*request), ES2_USB_CTRL_TIMEOUT);
        if (retval < 0)
                dev_err(&udev->dev, "Cannot timesync authoritative out %d\n", retval);
 
@@ -890,10 +839,11 @@ static int timesync_get_last_event(struct gb_host_device *hd, u64 *frame_time)
                return -ENOMEM;
 
        retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
-                                REQUEST_TIMESYNC_GET_LAST_EVENT,
+                                GB_APB_REQUEST_TIMESYNC_GET_LAST_EVENT,
                                 USB_DIR_IN | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, 0, 0, response_frame_time,
-                                sizeof(*response_frame_time), ES2_TIMEOUT);
+                                sizeof(*response_frame_time),
+                                ES2_USB_CTRL_TIMEOUT);
 
        if (retval != sizeof(*response_frame_time)) {
                dev_err(&udev->dev, "Cannot get last TimeSync event: %d\n",
@@ -918,12 +868,14 @@ static struct gb_hd_driver es2_driver = {
        .cport_allocate                 = es2_cport_allocate,
        .cport_release                  = es2_cport_release,
        .cport_enable                   = cport_enable,
-       .cport_disable                  = cport_disable,
+       .cport_connected                = es2_cport_connected,
+       .cport_flush                    = es2_cport_flush,
+       .cport_shutdown                 = es2_cport_shutdown,
+       .cport_quiesce                  = es2_cport_quiesce,
+       .cport_clear                    = es2_cport_clear,
        .latency_tag_enable             = latency_tag_enable,
        .latency_tag_disable            = latency_tag_disable,
        .output                         = output,
-       .cport_features_enable          = cport_features_enable,
-       .cport_features_disable         = cport_features_disable,
        .timesync_enable                = timesync_enable,
        .timesync_disable               = timesync_disable,
        .timesync_authoritative         = timesync_authoritative,
@@ -959,7 +911,7 @@ static int check_urb_status(struct urb *urb)
 static void es2_destroy(struct es2_ap_dev *es2)
 {
        struct usb_device *udev;
-       int bulk_in;
+       struct urb *urb;
        int i;
 
        debugfs_remove(es2->apb_log_enable_dentry);
@@ -967,10 +919,7 @@ static void es2_destroy(struct es2_ap_dev *es2)
 
        /* Tear down everything! */
        for (i = 0; i < NUM_CPORT_OUT_URB; ++i) {
-               struct urb *urb = es2->cport_out_urb[i];
-
-               if (!urb)
-                       break;
+               urb = es2->cport_out_urb[i];
                usb_kill_urb(urb);
                usb_free_urb(urb);
                es2->cport_out_urb[i] = NULL;
@@ -978,31 +927,17 @@ static void es2_destroy(struct es2_ap_dev *es2)
        }
 
        for (i = 0; i < NUM_ARPC_IN_URB; ++i) {
-               struct urb *urb = es2->arpc_urb[i];
-
-               if (!urb)
-                       break;
-               usb_free_urb(urb);
+               usb_free_urb(es2->arpc_urb[i]);
                kfree(es2->arpc_buffer[i]);
                es2->arpc_buffer[i] = NULL;
        }
 
-       for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) {
-               struct es2_cport_in *cport_in = &es2->cport_in[bulk_in];
-
-               for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
-                       struct urb *urb = cport_in->urb[i];
-
-                       if (!urb)
-                               break;
-                       usb_free_urb(urb);
-                       kfree(cport_in->buffer[i]);
-                       cport_in->buffer[i] = NULL;
-               }
+       for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
+               usb_free_urb(es2->cport_in.urb[i]);
+               kfree(es2->cport_in.buffer[i]);
+               es2->cport_in.buffer[i] = NULL;
        }
 
-       kfree(es2->cport_to_ep);
-
        /* release reserved CDSI0 and CDSI1 cports */
        gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI1);
        gb_hd_cport_release_reserved(es2->hd, ES2_CPORT_CDSI0);
@@ -1096,7 +1031,7 @@ static struct arpc *arpc_alloc(void *payload, u16 size, u8 type)
                goto err_free_rpc;
 
        rpc->resp = kzalloc(sizeof(*rpc->resp), GFP_KERNEL);
-       if (!rpc->req)
+       if (!rpc->resp)
                goto err_free_req;
 
        rpc->req->type = type;
@@ -1122,7 +1057,7 @@ static void arpc_free(struct arpc *rpc)
        kfree(rpc);
 }
 
-static struct arpc *arpc_find(struct es2_ap_dev *es2, u8 id)
+static struct arpc *arpc_find(struct es2_ap_dev *es2, __le16 id)
 {
        struct arpc *rpc;
 
@@ -1137,8 +1072,8 @@ static struct arpc *arpc_find(struct es2_ap_dev *es2, u8 id)
 static void arpc_add(struct es2_ap_dev *es2, struct arpc *rpc)
 {
        rpc->active = true;
-       rpc->req->id = (u16)(es2->arpc_id_cycle++);
-       list_add_tail(&es2->arpcs, &rpc->list);
+       rpc->req->id = cpu_to_le16(es2->arpc_id_cycle++);
+       list_add_tail(&rpc->list, &es2->arpcs);
 }
 
 static void arpc_del(struct es2_ap_dev *es2, struct arpc *rpc)
@@ -1155,13 +1090,13 @@ static int arpc_send(struct es2_ap_dev *es2, struct arpc *rpc, int timeout)
        int retval;
 
        retval = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                                APBA_REQUEST_ARPC_RUN,
+                                GB_APB_REQUEST_ARPC_RUN,
                                 USB_DIR_OUT | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE,
                                 0, 0,
-                                rpc->req, rpc->req->size,
-                                ES2_TIMEOUT);
-       if (retval != rpc->req->size) {
+                                rpc->req, le16_to_cpu(rpc->req->size),
+                                ES2_USB_CTRL_TIMEOUT);
+       if (retval != le16_to_cpu(rpc->req->size)) {
                dev_err(&udev->dev,
                        "failed to send ARPC request %d: %d\n",
                        rpc->req->type, retval);
@@ -1180,6 +1115,9 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload,
        unsigned long flags;
        int retval;
 
+       if (result)
+               *result = 0;
+
        rpc = arpc_alloc(payload, size, type);
        if (!rpc)
                return -ENOMEM;
@@ -1201,11 +1139,13 @@ static int arpc_sync(struct es2_ap_dev *es2, u8 type, void *payload,
                goto out_arpc_del;
        }
 
-       *result = rpc->resp->result;
-       if (*result)
+       if (rpc->resp->result) {
                retval = -EREMOTEIO;
-       else
+               if (result)
+                       *result = rpc->resp->result;
+       } else {
                retval = 0;
+       }
 
 out_arpc_del:
        spin_lock_irqsave(&es2->arpc_lock, flags);
@@ -1252,8 +1192,8 @@ static void arpc_in_callback(struct urb *urb)
        spin_lock_irqsave(&es2->arpc_lock, flags);
        rpc = arpc_find(es2, resp->id);
        if (!rpc) {
-               dev_err(dev, "invalid arpc response id received: %d\n",
-                       resp->id);
+               dev_err(dev, "invalid arpc response id received: %u\n",
+                       le16_to_cpu(resp->id));
                spin_unlock_irqrestore(&es2->arpc_lock, flags);
                goto exit;
        }
@@ -1275,7 +1215,6 @@ static void apb_log_get(struct es2_ap_dev *es2, char *buf)
 {
        int retval;
 
-       /* SVC messages go down our control pipe */
        do {
                retval = usb_control_msg(es2->usb_dev,
                                        usb_rcvctrlpipe(es2->usb_dev, 0),
@@ -1284,7 +1223,7 @@ static void apb_log_get(struct es2_ap_dev *es2, char *buf)
                                        0x00, 0x00,
                                        buf,
                                        APB1_LOG_MSG_SIZE,
-                                       ES2_TIMEOUT);
+                                       ES2_USB_CTRL_TIMEOUT);
                if (retval > 0)
                        kfifo_in(&es2->apb_log_fifo, buf, retval);
        } while (retval > 0);
@@ -1411,7 +1350,7 @@ static int apb_get_cport_count(struct usb_device *udev)
                                 GB_APB_REQUEST_CPORT_COUNT,
                                 USB_DIR_IN | USB_TYPE_VENDOR |
                                 USB_RECIP_INTERFACE, 0, 0, cport_count,
-                                sizeof(*cport_count), ES2_TIMEOUT);
+                                sizeof(*cport_count), ES2_USB_CTRL_TIMEOUT);
        if (retval != sizeof(*cport_count)) {
                dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n",
                        retval);
@@ -1449,11 +1388,13 @@ static int ap_probe(struct usb_interface *interface,
        struct usb_device *udev;
        struct usb_host_interface *iface_desc;
        struct usb_endpoint_descriptor *endpoint;
-       int bulk_in = 0;
-       int bulk_out = 0;
+       __u8 ep_addr;
        int retval;
        int i;
        int num_cports;
+       bool bulk_out_found = false;
+       bool bulk_in_found = false;
+       bool arpc_in_found = false;
 
        udev = usb_get_dev(interface_to_usbdev(interface));
 
@@ -1491,68 +1432,71 @@ static int ap_probe(struct usb_interface *interface,
        if (retval)
                goto error;
 
-       es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep),
-                                  GFP_KERNEL);
-       if (!es2->cport_to_ep) {
-               retval = -ENOMEM;
-               goto error;
-       }
-
        /* find all bulk endpoints */
        iface_desc = interface->cur_altsetting;
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
+               ep_addr = endpoint->bEndpointAddress;
 
                if (usb_endpoint_is_bulk_in(endpoint)) {
-                       if (bulk_in < NUM_BULKS)
-                               es2->cport_in[bulk_in].endpoint =
-                                       endpoint->bEndpointAddress;
-                       else
-                               es2->arpc_endpoint_in =
-                                       endpoint->bEndpointAddress;
-                       bulk_in++;
-               } else if (usb_endpoint_is_bulk_out(endpoint)) {
-                       es2->cport_out[bulk_out++].endpoint =
-                               endpoint->bEndpointAddress;
-               } else {
-                       dev_err(&udev->dev,
-                               "Unknown endpoint type found, address 0x%02x\n",
-                               endpoint->bEndpointAddress);
+                       if (!bulk_in_found) {
+                               es2->cport_in.endpoint = ep_addr;
+                               bulk_in_found = true;
+                       } else if (!arpc_in_found) {
+                               es2->arpc_endpoint_in = ep_addr;
+                               arpc_in_found = true;
+                       } else {
+                               dev_warn(&udev->dev,
+                                        "Unused bulk IN endpoint found: 0x%02x\n",
+                                        ep_addr);
+                       }
+                       continue;
+               }
+               if (usb_endpoint_is_bulk_out(endpoint)) {
+                       if (!bulk_out_found) {
+                               es2->cport_out_endpoint = ep_addr;
+                               bulk_out_found = true;
+                       } else {
+                               dev_warn(&udev->dev,
+                                        "Unused bulk OUT endpoint found: 0x%02x\n",
+                                        ep_addr);
+                       }
+                       continue;
                }
+               dev_warn(&udev->dev,
+                        "Unknown endpoint type found, address 0x%02x\n",
+                        ep_addr);
        }
-       if (bulk_in != NUM_BULKS_IN || bulk_out != NUM_BULKS_OUT) {
+       if (!bulk_in_found || !arpc_in_found || !bulk_out_found) {
                dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n");
                retval = -ENODEV;
                goto error;
        }
 
        /* Allocate buffers for our cport in messages */
-       for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) {
-               struct es2_cport_in *cport_in = &es2->cport_in[bulk_in];
-
-               for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
-                       struct urb *urb;
-                       u8 *buffer;
+       for (i = 0; i < NUM_CPORT_IN_URB; ++i) {
+               struct urb *urb;
+               u8 *buffer;
 
-                       urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!urb) {
-                               retval = -ENOMEM;
-                               goto error;
-                       }
-                       buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL);
-                       if (!buffer) {
-                               retval = -ENOMEM;
-                               goto error;
-                       }
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       retval = -ENOMEM;
+                       goto error;
+               }
+               es2->cport_in.urb[i] = urb;
 
-                       usb_fill_bulk_urb(urb, udev,
-                                         usb_rcvbulkpipe(udev,
-                                                         cport_in->endpoint),
-                                         buffer, ES2_GBUF_MSG_SIZE_MAX,
-                                         cport_in_callback, hd);
-                       cport_in->urb[i] = urb;
-                       cport_in->buffer[i] = buffer;
+               buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL);
+               if (!buffer) {
+                       retval = -ENOMEM;
+                       goto error;
                }
+
+               usb_fill_bulk_urb(urb, udev,
+                                 usb_rcvbulkpipe(udev, es2->cport_in.endpoint),
+                                 buffer, ES2_GBUF_MSG_SIZE_MAX,
+                                 cport_in_callback, hd);
+
+               es2->cport_in.buffer[i] = buffer;
        }
 
        /* Allocate buffers for ARPC in messages */
@@ -1565,6 +1509,8 @@ static int ap_probe(struct usb_interface *interface,
                        retval = -ENOMEM;
                        goto error;
                }
+               es2->arpc_urb[i] = urb;
+
                buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL);
                if (!buffer) {
                        retval = -ENOMEM;
@@ -1577,7 +1523,6 @@ static int ap_probe(struct usb_interface *interface,
                                  buffer, ARPC_IN_SIZE_MAX,
                                  arpc_in_callback, es2);
 
-               es2->arpc_urb[i] = urb;
                es2->arpc_buffer[i] = buffer;
        }
 
@@ -1611,17 +1556,13 @@ static int ap_probe(struct usb_interface *interface,
        if (retval)
                goto err_disable_arpc_in;
 
-       for (i = 0; i < NUM_BULKS; ++i) {
-               retval = es2_cport_in_enable(es2, &es2->cport_in[i]);
-               if (retval)
-                       goto err_disable_cport_in;
-       }
+       retval = es2_cport_in_enable(es2, &es2->cport_in);
+       if (retval)
+               goto err_hd_del;
 
        return 0;
 
-err_disable_cport_in:
-       for (--i; i >= 0; --i)
-               es2_cport_in_disable(es2, &es2->cport_in[i]);
+err_hd_del:
        gb_hd_del(hd);
 err_disable_arpc_in:
        es2_arpc_in_disable(es2);
@@ -1634,12 +1575,10 @@ error:
 static void ap_disconnect(struct usb_interface *interface)
 {
        struct es2_ap_dev *es2 = usb_get_intfdata(interface);
-       int i;
 
        gb_hd_del(es2->hd);
 
-       for (i = 0; i < NUM_BULKS; ++i)
-               es2_cport_in_disable(es2, &es2->cport_in[i]);
+       es2_cport_in_disable(es2, &es2->cport_in);
        es2_arpc_in_disable(es2);
 
        es2_destroy(es2);