greybus: es1: handle cport data in and out
authorGreg Kroah-Hartman <greg@kroah.com>
Sat, 13 Sep 2014 18:09:35 +0000 (11:09 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Sat, 13 Sep 2014 18:09:35 +0000 (11:09 -0700)
drivers/staging/greybus/ap.c
drivers/staging/greybus/es1-ap-usb.c
drivers/staging/greybus/gbuf.c
drivers/staging/greybus/greybus.h

index 53ad66c..e606a45 100644 (file)
@@ -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)
 {
index cf2987e..6635194 100644 (file)
@@ -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);
+
 }
 
 /*
index 1bf9226..e12a625 100644 (file)
@@ -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);
index 573274b..1badfa8 100644 (file)
@@ -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 */