Commit 9d9d3777 authored by Alexandre Bailon's avatar Alexandre Bailon Committed by Alex Elder

greybus: es2: Add a new bulk in endpoint for APBridgeA RPC

Add a new bulk in endpoint in order to get RPC status
from APbridgeA without to have to poll on control endpoint.

So the new endpoint layout is:
EP0: control EP
EP1 and EP2: muxed endpoints (bulk in and out)
EP3 to EP14: direct muxed endpoints (bulk in and out)
EP15: ARPC bulk in endpoint

Note:
This patch is allocating ARPC URBs but does nothing with them.
The following patch will use them.

Testing Done:
  Tested with an APBridgeA enumerating 16 endpoints.
  Kernel doesn't print Not enough endpoints found in device, aborting!
Signed-off-by: default avatarAlexandre Bailon <abailon@baylibre.com>
Reviewed-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
parent 576bffb5
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
/* Memory sizes for the buffers sent to/from the ES2 controller */ /* Memory sizes for the buffers sent to/from the ES2 controller */
#define ES2_GBUF_MSG_SIZE_MAX 2048 #define ES2_GBUF_MSG_SIZE_MAX 2048
/* Memory sizes for the ARPC buffers */
#define ARPC_IN_SIZE_MAX 128
static const struct usb_device_id id_table[] = { static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x18d1, 0x1eaf) }, { USB_DEVICE(0x18d1, 0x1eaf) },
{ }, { },
...@@ -36,6 +39,12 @@ MODULE_DEVICE_TABLE(usb, id_table); ...@@ -36,6 +39,12 @@ MODULE_DEVICE_TABLE(usb, id_table);
/* Number of bulk in and bulk out couple */ /* Number of bulk in and bulk out couple */
#define NUM_BULKS 7 #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. * 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 * Adjust if we are having stalls in the USB buffer due to not enough urbs in
...@@ -48,6 +57,11 @@ MODULE_DEVICE_TABLE(usb, id_table); ...@@ -48,6 +57,11 @@ MODULE_DEVICE_TABLE(usb, id_table);
*/ */
#define NUM_CPORT_OUT_URB (8 * NUM_BULKS) #define NUM_CPORT_OUT_URB (8 * NUM_BULKS)
/*
* Number of ARPC in urbs in flight at any point in time.
*/
#define NUM_ARPC_IN_URB 2
/* /*
* @endpoint: bulk in endpoint for CPort data * @endpoint: bulk in endpoint for CPort data
* @urb: array of urbs for the CPort in messages * @urb: array of urbs for the CPort in messages
...@@ -85,6 +99,9 @@ struct es2_cport_out { ...@@ -85,6 +99,9 @@ struct es2_cport_out {
* @apb_log_dentry: file system entry for the log file interface * @apb_log_dentry: file system entry for the log file interface
* @apb_log_enable_dentry: file system entry for enabling logging * @apb_log_enable_dentry: file system entry for enabling logging
* @apb_log_fifo: kernel FIFO to carry logged data * @apb_log_fifo: kernel FIFO to carry logged data
* @arpc_urb: array of urbs for the ARPC in messages
* @arpc_buffer: array of buffers for the @arpc_urb urbs
* @arpc_endpoint_in: bulk in endpoint for APBridgeA RPC
*/ */
struct es2_ap_dev { struct es2_ap_dev {
struct usb_device *usb_dev; struct usb_device *usb_dev;
...@@ -106,6 +123,10 @@ struct es2_ap_dev { ...@@ -106,6 +123,10 @@ struct es2_ap_dev {
struct dentry *apb_log_dentry; struct dentry *apb_log_dentry;
struct dentry *apb_log_enable_dentry; struct dentry *apb_log_enable_dentry;
DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE); DECLARE_KFIFO(apb_log_fifo, char, APB1_LOG_SIZE);
__u8 arpc_endpoint_in;
struct urb *arpc_urb[NUM_ARPC_IN_URB];
u8 *arpc_buffer[NUM_ARPC_IN_URB];
}; };
/** /**
...@@ -344,6 +365,45 @@ static void es2_cport_in_disable(struct es2_ap_dev *es2, ...@@ -344,6 +365,45 @@ static void es2_cport_in_disable(struct es2_ap_dev *es2,
} }
} }
static int es2_arpc_in_enable(struct es2_ap_dev *es2)
{
struct urb *urb;
int ret;
int i;
for (i = 0; i < NUM_ARPC_IN_URB; ++i) {
urb = es2->arpc_urb[i];
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
dev_err(&es2->usb_dev->dev,
"failed to submit arpc in-urb: %d\n", ret);
goto err_kill_urbs;
}
}
return 0;
err_kill_urbs:
for (--i; i >= 0; --i) {
urb = es2->arpc_urb[i];
usb_kill_urb(urb);
}
return ret;
}
static void es2_arpc_in_disable(struct es2_ap_dev *es2)
{
struct urb *urb;
int i;
for (i = 0; i < NUM_ARPC_IN_URB; ++i) {
urb = es2->arpc_urb[i];
usb_kill_urb(urb);
}
}
static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask) static struct urb *next_free_urb(struct es2_ap_dev *es2, gfp_t gfp_mask)
{ {
struct urb *urb = NULL; struct urb *urb = NULL;
...@@ -899,6 +959,16 @@ static void es2_destroy(struct es2_ap_dev *es2) ...@@ -899,6 +959,16 @@ static void es2_destroy(struct es2_ap_dev *es2)
es2->cport_out_urb_busy[i] = false; /* just to be anal */ es2->cport_out_urb_busy[i] = false; /* just to be anal */
} }
for (i = 0; i < NUM_ARPC_IN_URB; ++i) {
struct urb *urb = es2->arpc_urb[i];
if (!urb)
break;
usb_free_urb(urb);
kfree(es2->arpc_buffer[i]);
es2->arpc_buffer[i] = NULL;
}
for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) {
struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; struct es2_cport_in *cport_in = &es2->cport_in[bulk_in];
...@@ -991,6 +1061,31 @@ static void cport_out_callback(struct urb *urb) ...@@ -991,6 +1061,31 @@ static void cport_out_callback(struct urb *urb)
free_urb(es2, urb); free_urb(es2, urb);
} }
static void arpc_in_callback(struct urb *urb)
{
struct device *dev = &urb->dev->dev;
int status = check_urb_status(urb);
int retval;
if (status) {
if ((status == -EAGAIN) || (status == -EPROTO))
goto exit;
/* The urb is being unlinked */
if (status == -ENOENT || status == -ESHUTDOWN)
return;
dev_err(dev, "arpc in-urb error %d (dropped)\n", status);
return;
}
exit:
/* put our urb back in the request pool */
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(dev, "failed to resubmit arpc in-urb: %d\n", retval);
}
#define APB1_LOG_MSG_SIZE 64 #define APB1_LOG_MSG_SIZE 64
static void apb_log_get(struct es2_ap_dev *es2, char *buf) static void apb_log_get(struct es2_ap_dev *es2, char *buf)
{ {
...@@ -1225,8 +1320,13 @@ static int ap_probe(struct usb_interface *interface, ...@@ -1225,8 +1320,13 @@ static int ap_probe(struct usb_interface *interface,
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
if (usb_endpoint_is_bulk_in(endpoint)) { if (usb_endpoint_is_bulk_in(endpoint)) {
es2->cport_in[bulk_in++].endpoint = if (bulk_in < NUM_BULKS)
endpoint->bEndpointAddress; 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)) { } else if (usb_endpoint_is_bulk_out(endpoint)) {
es2->cport_out[bulk_out++].endpoint = es2->cport_out[bulk_out++].endpoint =
endpoint->bEndpointAddress; endpoint->bEndpointAddress;
...@@ -1236,7 +1336,7 @@ static int ap_probe(struct usb_interface *interface, ...@@ -1236,7 +1336,7 @@ static int ap_probe(struct usb_interface *interface,
endpoint->bEndpointAddress); endpoint->bEndpointAddress);
} }
} }
if (bulk_in != NUM_BULKS || bulk_out != NUM_BULKS) { if (bulk_in != NUM_BULKS_IN || bulk_out != NUM_BULKS_OUT) {
dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n");
retval = -ENODEV; retval = -ENODEV;
goto error; goto error;
...@@ -1271,6 +1371,32 @@ static int ap_probe(struct usb_interface *interface, ...@@ -1271,6 +1371,32 @@ static int ap_probe(struct usb_interface *interface,
} }
} }
/* Allocate buffers for ARPC in messages */
for (i = 0; i < NUM_ARPC_IN_URB; ++i) {
struct urb *urb;
u8 *buffer;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
retval = -ENOMEM;
goto error;
}
buffer = kmalloc(ARPC_IN_SIZE_MAX, GFP_KERNEL);
if (!buffer) {
retval = -ENOMEM;
goto error;
}
usb_fill_bulk_urb(urb, udev,
usb_rcvbulkpipe(udev,
es2->arpc_endpoint_in),
buffer, ARPC_IN_SIZE_MAX,
arpc_in_callback, es2);
es2->arpc_urb[i] = urb;
es2->arpc_buffer[i] = buffer;
}
/* Allocate urbs for our CPort OUT messages */ /* Allocate urbs for our CPort OUT messages */
for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { for (i = 0; i < NUM_CPORT_OUT_URB; ++i) {
struct urb *urb; struct urb *urb;
...@@ -1291,9 +1417,12 @@ static int ap_probe(struct usb_interface *interface, ...@@ -1291,9 +1417,12 @@ static int ap_probe(struct usb_interface *interface,
gb_debugfs_get(), es2, gb_debugfs_get(), es2,
&apb_log_enable_fops); &apb_log_enable_fops);
if (es2_arpc_in_enable(es2))
goto error;
retval = gb_hd_add(hd); retval = gb_hd_add(hd);
if (retval) if (retval)
goto error; goto err_disable_arpc_in;
for (i = 0; i < NUM_BULKS; ++i) { for (i = 0; i < NUM_BULKS; ++i) {
retval = es2_cport_in_enable(es2, &es2->cport_in[i]); retval = es2_cport_in_enable(es2, &es2->cport_in[i]);
...@@ -1307,6 +1436,8 @@ static int ap_probe(struct usb_interface *interface, ...@@ -1307,6 +1436,8 @@ static int ap_probe(struct usb_interface *interface,
for (--i; i >= 0; --i) for (--i; i >= 0; --i)
es2_cport_in_disable(es2, &es2->cport_in[i]); es2_cport_in_disable(es2, &es2->cport_in[i]);
gb_hd_del(hd); gb_hd_del(hd);
err_disable_arpc_in:
es2_arpc_in_disable(es2);
error: error:
es2_destroy(es2); es2_destroy(es2);
...@@ -1322,6 +1453,7 @@ static void ap_disconnect(struct usb_interface *interface) ...@@ -1322,6 +1453,7 @@ static void ap_disconnect(struct usb_interface *interface)
for (i = 0; i < NUM_BULKS; ++i) for (i = 0; i < NUM_BULKS; ++i)
es2_cport_in_disable(es2, &es2->cport_in[i]); es2_cport_in_disable(es2, &es2->cport_in[i]);
es2_arpc_in_disable(es2);
es2_destroy(es2); es2_destroy(es2);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment