greybus: more hd work
authorGreg Kroah-Hartman <greg@kroah.com>
Sun, 7 Sep 2014 20:12:11 +0000 (13:12 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Sun, 7 Sep 2014 20:12:11 +0000 (13:12 -0700)
drivers/staging/greybus/ap.c
drivers/staging/greybus/core.c
drivers/staging/greybus/es1-ap-usb.c
drivers/staging/greybus/greybus.h

index 5b06b19..2fb2cc1 100644 (file)
@@ -22,7 +22,8 @@
 
 struct ap_msg {
        u8 *data;
-       int size;
+       size_t size;
+       struct greybus_host_device *hd;
        struct list_head list;
 };
 
@@ -31,6 +32,21 @@ static spinlock_t ap_msg_list_lock;
 static struct task_struct *ap_thread;
 static wait_queue_head_t ap_wait;
 
+
+static struct svc_msg *convert_ap_message(struct ap_msg *ap_msg)
+{
+       struct svc_msg *svc_msg;
+
+       // FIXME - validate message, right now we are trusting the size and data
+       // from the AP, what could go wrong?  :)
+       // for now, just cast the pointer and run away...
+
+       svc_msg = (struct svc_msg *)ap_msg->data;
+       return svc_msg;
+}
+
+
+
 static struct ap_msg *get_ap_msg(void)
 {
        struct ap_msg *ap_msg;
@@ -49,6 +65,7 @@ static struct ap_msg *get_ap_msg(void)
 static int ap_process_loop(void *data)
 {
        struct ap_msg *ap_msg;
+       struct svc_msg *svc_msg;
 
        while (!kthread_should_stop()) {
                wait_event_interruptible(ap_wait, kthread_should_stop());
@@ -61,7 +78,12 @@ static int ap_process_loop(void *data)
                if (!ap_msg)
                        continue;
 
-               // FIXME - process the message
+               /* Turn the "raw" data into a real message */
+               svc_msg = convert_ap_message(ap_msg);
+               if (svc_msg) {
+                       /* Pass the message to the host controller */
+                       ap_msg->hd->driver->ap_msg(svc_msg, ap_msg->hd);
+               }
 
                /* clean the message up */
                kfree(ap_msg->data);
@@ -70,7 +92,7 @@ static int ap_process_loop(void *data)
        return 0;
 }
 
-int gb_new_ap_msg(u8 *data, int size)
+int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd)
 {
        struct ap_msg *ap_msg;
        unsigned long flags;
@@ -96,6 +118,7 @@ int gb_new_ap_msg(u8 *data, int size)
        }
        memcpy(ap_msg->data, data, size);
        ap_msg->size = size;
+       ap_msg->hd = hd;
 
        spin_lock_irqsave(&ap_msg_list_lock, flags);
        list_add(&ap_msg->list, &ap_msg_list);
index 517b260..5c633a3 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/kthread.h>
 #include <linux/device.h>
 
 #include "greybus.h"
@@ -449,6 +448,17 @@ void greybus_remove_device(struct greybus_device *gdev)
        // FIXME - device_remove(&gdev->dev);
 }
 
+static DEFINE_MUTEX(hd_mutex);
+
+static void free_hd(struct kref *kref)
+{
+       struct greybus_host_device *hd;
+
+       hd = container_of(kref, struct greybus_host_device, kref);
+
+       kfree(hd);
+}
+
 struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
                                              struct device *parent)
 {
@@ -464,6 +474,12 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
 }
 EXPORT_SYMBOL_GPL(greybus_create_hd);
 
+void greybus_remove_hd(struct greybus_host_device *hd)
+{
+       kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
+}
+EXPORT_SYMBOL_GPL(greybus_remove_hd);
+
 
 static int __init gb_init(void)
 {
index a08e4dd..8589273 100644 (file)
@@ -82,15 +82,30 @@ static void free_gbuf(struct gbuf *gbuf)
 }
 
 
+/* Main message loop for ap messages */
+/* Odds are, most of this logic can move to core.c someday, but as we only have
+ * one host controller driver for now, let's leave it here */
+static void ap_msg(struct svc_msg *svc_msg, struct greybus_host_device *hd)
+{
+       struct es1_ap_dev *es1 = hd_to_es1(hd);
+
+       /* Look at the message to figure out what to do with it */
+
+
+}
+
+
 static struct greybus_host_driver es1_driver = {
        .hd_priv_size = sizeof(struct es1_ap_dev),
        .alloc_gbuf = alloc_gbuf,
        .free_gbuf = free_gbuf,
+       .ap_msg = ap_msg,
 };
 
 
 void ap_in_callback(struct urb *urb)
 {
+       struct es1_ap_dev *es1 = urb->context;
        struct device *dev = &urb->dev->dev;
        int status = urb->status;
        int retval;
@@ -115,7 +130,7 @@ void ap_in_callback(struct urb *urb)
        /* We have a message, create a new message structure, add it to the
         * list, and wake up our thread that will process the messages.
         */
-       gb_new_ap_msg(urb->transfer_buffer, urb->actual_length);
+       gb_new_ap_msg(urb->transfer_buffer, urb->actual_length, es1->hd);
 
 exit:
        /* resubmit the urb to get more messages */
@@ -211,8 +226,7 @@ static void ap_disconnect(struct usb_interface *interface)
        usb_put_dev(es1->usb_dev);
        kfree(es1->ap_buffer);
 
-       // FIXME
-       //greybus_destroy_hd(es1->hd);
+       greybus_remove_hd(es1->hd);
 }
 
 static struct usb_driver es1_ap_driver = {
index 95225f2..2f67df5 100644 (file)
@@ -92,6 +92,7 @@ struct gb_sdio_host;
 struct gb_tty;
 struct gb_usb_device;
 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
@@ -102,6 +103,7 @@ struct greybus_host_driver {
        int (*start)(struct greybus_host_device *hd);
        int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask);
        void (*free_gbuf)(struct gbuf *gbuf);
+       void (*ap_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd);
 };
 
 struct greybus_host_device {
@@ -115,6 +117,7 @@ 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);
 
 
 /* Increase these values if needed */
@@ -213,7 +216,7 @@ const u8 *greybus_string(struct greybus_device *gdev, int id);
 
 /* Internal functions to gb module, move to internal .h file eventually. */
 
-int gb_new_ap_msg(u8 *data, int length);
+int gb_new_ap_msg(u8 *data, int length, struct greybus_host_device *hd);
 int gb_thread_init(void);
 void gb_thread_destroy(void);
 int gb_debugfs_init(void);