summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorGreg Kroah-Hartman2014-09-13 20:09:35 +0200
committerGreg Kroah-Hartman2014-09-13 20:09:35 +0200
commit9c8d3afdb58cf96a0e784e2e0a62923fe8855e4d (patch)
tree9221998ee8a10d44a45314011221c461c90e583d /drivers
parentgreybus: es1: allocate cport out urbs properly (diff)
downloadkernel-qcow2-linux-9c8d3afdb58cf96a0e784e2e0a62923fe8855e4d.tar.gz
kernel-qcow2-linux-9c8d3afdb58cf96a0e784e2e0a62923fe8855e4d.tar.xz
kernel-qcow2-linux-9c8d3afdb58cf96a0e784e2e0a62923fe8855e4d.zip
greybus: es1: handle cport data in and out
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/greybus/ap.c6
-rw-r--r--drivers/staging/greybus/es1-ap-usb.c58
-rw-r--r--drivers/staging/greybus/gbuf.c9
-rw-r--r--drivers/staging/greybus/greybus.h3
4 files changed, 71 insertions, 5 deletions
diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c
index 53ad66c6c3d7..e606a4557ab2 100644
--- a/drivers/staging/greybus/ap.c
+++ b/drivers/staging/greybus/ap.c
@@ -298,6 +298,12 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd)
}
EXPORT_SYMBOL_GPL(gb_new_ap_msg);
+void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data,
+ size_t length)
+{
+ // FIXME - implement...
+}
+EXPORT_SYMBOL_GPL(greybus_cport_in_data);
int gb_thread_init(void)
{
diff --git a/drivers/staging/greybus/es1-ap-usb.c b/drivers/staging/greybus/es1-ap-usb.c
index cf2987ef94e9..6635194e4a9a 100644
--- a/drivers/staging/greybus/es1-ap-usb.c
+++ b/drivers/staging/greybus/es1-ap-usb.c
@@ -233,7 +233,11 @@ exit:
static void cport_in_callback(struct urb *urb)
{
struct device *dev = &urb->dev->dev;
+ struct es1_ap_dev *es1 = urb->context;
int status = urb->status;
+ int retval;
+ u8 cport;
+ u8 *data;
switch (status) {
case 0:
@@ -252,15 +256,40 @@ static void cport_in_callback(struct urb *urb)
goto exit;
}
- // FIXME - handle the CPort in data
+ /* The size has to be more then just an "empty" transfer */
+ if (urb->actual_length <= 2) {
+ dev_err(dev, "%s: \"short\" cport in transfer of %d bytes?\n",
+ __func__, urb->actual_length);
+ goto exit;
+ }
+
+ /*
+ * The CPort number is the first byte of the data stream, the rest of
+ * the stream is "real" data
+ */
+ data = urb->transfer_buffer;
+ cport = data[0];
+ data = &data[1];
+
+ /* Pass this data to the greybus core */
+ greybus_cport_in_data(es1->hd, cport, data, urb->actual_length - 1);
+
exit:
- return;
+ /* put our urb back in the request pool */
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(dev, "%s: error %d in submitting urb.\n",
+ __func__, retval);
}
static void cport_out_callback(struct urb *urb)
{
struct device *dev = &urb->dev->dev;
+ struct gbuf *gbuf = urb->context;
+ struct es1_ap_dev *es1 = gbuf->hdpriv;
+ unsigned long flags;
int status = urb->status;
+ int i;
switch (status) {
case 0:
@@ -273,15 +302,34 @@ static void cport_out_callback(struct urb *urb)
case -ESHUTDOWN:
case -EILSEQ:
/* device is gone, stop sending */
- return;
+ goto exit;
default:
dev_err(dev, "%s: unknown status %d\n", __func__, status);
goto exit;
}
- // FIXME - handle the CPort out data callback
+ // FIXME - do we care about errors going back up?
+
+ /* Tell the core the gbuf is properly sent */
+ greybus_gbuf_finished(gbuf);
+
exit:
- return;
+ /*
+ * See if this was an urb in our pool, if so mark it "free", otherwise we
+ * need to free it ourselves.
+ */
+ spin_lock_irqsave(&es1->cport_out_urb_lock, flags);
+ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) {
+ if (urb == es1->cport_out_urb[i]) {
+ es1->cport_out_urb_busy[i] = false;
+ urb = NULL;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&es1->cport_out_urb_lock, flags);
+ if (urb)
+ usb_free_urb(urb);
+
}
/*
diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c
index 1bf92262a629..e12a625131de 100644
--- a/drivers/staging/greybus/gbuf.c
+++ b/drivers/staging/greybus/gbuf.c
@@ -98,10 +98,19 @@ EXPORT_SYMBOL_GPL(greybus_get_gbuf);
int greybus_submit_gbuf(struct gbuf *gbuf, gfp_t mem_flags)
{
+ // FIXME - implement
return -ENOMEM;
}
int greybus_kill_gbuf(struct gbuf *gbuf)
{
+ // FIXME - implement
return -ENOMEM;
}
+
+/* Can be called in interrupt context, do the work and get out of here */
+void greybus_gbuf_finished(struct gbuf *gbuf)
+{
+ // FIXME - implement
+}
+EXPORT_SYMBOL_GPL(greybus_gbuf_finished);
diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h
index 573274b6267d..1badfa8cfd36 100644
--- a/drivers/staging/greybus/greybus.h
+++ b/drivers/staging/greybus/greybus.h
@@ -126,6 +126,9 @@ struct greybus_host_device {
struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver,
struct device *parent);
void greybus_remove_hd(struct greybus_host_device *hd);
+void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data,
+ size_t length);
+void greybus_gbuf_finished(struct gbuf *gbuf);
/* Increase these values if needed */