greybus: gbuf: cport in buffer stream logic
authorGreg Kroah-Hartman <greg@kroah.com>
Sun, 14 Sep 2014 18:40:35 +0000 (11:40 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Sun, 14 Sep 2014 18:40:35 +0000 (11:40 -0700)
drivers/staging/greybus/ap.c
drivers/staging/greybus/core.c
drivers/staging/greybus/gbuf.c
drivers/staging/greybus/greybus.h

index 0fc3ff7..4c10650 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
-#include <linux/kthread.h>
+#include <linux/workqueue.h>
 #include <linux/device.h>
 #include "svc_msg.h"
 #include "greybus_manifest.h"
@@ -252,7 +252,7 @@ int gb_new_ap_msg(u8 *data, int size, struct greybus_host_device *hd)
 }
 EXPORT_SYMBOL_GPL(gb_new_ap_msg);
 
-int gb_thread_init(void)
+int gb_ap_init(void)
 {
        ap_workqueue = alloc_workqueue("greybus_ap", 0, 1);
        if (!ap_workqueue)
@@ -261,7 +261,7 @@ int gb_thread_init(void)
        return 0;
 }
 
-void gb_thread_destroy(void)
+void gb_ap_exit(void)
 {
        destroy_workqueue(ap_workqueue);
 }
index bad40ba..f987086 100644 (file)
@@ -527,13 +527,17 @@ static int __init gb_init(void)
                goto error_bus;
        }
 
-       retval = gb_thread_init();
+       retval = gb_ap_init();
        if (retval) {
-               pr_err("gb_thread_init failed\n");
-               goto error_thread;
+               pr_err("gb_ap_init failed\n");
+               goto error_ap;
        }
 
-       // FIXME - more gb core init goes here
+       retval = gb_gbuf_init();
+       if (retval) {
+               pr_err("gb_gbuf_init failed\n");
+               goto error_gbuf;
+       }
 
        retval = gb_tty_init();
        if (retval) {
@@ -544,9 +548,12 @@ static int __init gb_init(void)
        return 0;
 
 error_tty:
-       gb_thread_destroy();
+       gb_gbuf_exit();
+
+error_gbuf:
+       gb_ap_exit();
 
-error_thread:
+error_ap:
        bus_unregister(&greybus_bus_type);
 
 error_bus:
@@ -558,6 +565,8 @@ error_bus:
 static void __exit gb_exit(void)
 {
        gb_tty_exit();
+       gb_gbuf_exit();
+       gb_ap_exit();
        bus_unregister(&greybus_bus_type);
        gb_debugfs_cleanup();
 }
index b06d779..3affdbf 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kref.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/workqueue.h>
 
 #include "greybus.h"
 
@@ -155,16 +156,42 @@ int gb_register_cport_complete(struct greybus_device *gdev,
        return 0;
 }
 
-void gb_deregister_cport_handler(int cport)
+void gb_deregister_cport_complete(int cport)
 {
        cport_handler[cport].handler = NULL;
 }
 
+struct cport_msg {
+       struct gbuf *gbuf;
+       struct work_struct event;
+};
+
+static struct workqueue_struct *cport_workqueue;
+
+static void cport_process_event(struct work_struct *work)
+{
+       struct cport_msg *cm;
+       struct gbuf *gbuf;
+
+       cm = container_of(work, struct cport_msg, event);
+
+       gbuf = cm->gbuf;
+
+       /* call the gbuf handler */
+       gbuf->complete(gbuf);
+
+       /* free all the memory */
+       kfree(gbuf->transfer_buffer);
+       kfree(gbuf);
+       kfree(cm);
+}
+
 void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data,
                           size_t length)
 {
        struct gb_cport_handler *ch;
        struct gbuf *gbuf;
+       struct cport_msg *cm;
 
        /* first check to see if we have a cport handler for this cport */
        ch = &cport_handler[cport];
@@ -183,17 +210,42 @@ void greybus_cport_in_data(struct greybus_host_device *hd, int cport, u8 *data,
                pr_err("can't allocate gbuf???\n");
                return;
        }
-       /* Set the data pointers */
+       gbuf->hdpriv = hd;
+
+       /*
+        * FIXME:
+        * Very dumb copy data method for now, if this is slow (odds are it will
+        * be, we should move to a model where the hd "owns" all buffers, but we
+        * want something up and working first for now.
+        */
+       gbuf->transfer_buffer = kmalloc(length, GFP_ATOMIC);
+       if (!gbuf->transfer_buffer) {
+               kfree(gbuf);
+               return;
+       }
+       memcpy(gbuf->transfer_buffer, data, length);
+       gbuf->transfer_buffer_length = length;
 
-       // FIXME - implement...
+       /* Again with the slow allocate... */
+       cm = kmalloc(sizeof(*cm), GFP_ATOMIC);
+
+       /* Queue up the cport message to be handled in user context */
+       cm->gbuf = gbuf;
+       INIT_WORK(&cm->event, cport_process_event);
+       queue_work(cport_workqueue, &cm->event);
 }
 EXPORT_SYMBOL_GPL(greybus_cport_in_data);
 
-int greybus_gbuf_init(void)
+int gb_gbuf_init(void)
 {
+       cport_workqueue = alloc_workqueue("greybus_gbuf", 0, 1);
+       if (!cport_workqueue)
+               return -ENOMEM;
+
        return 0;
 }
 
-void greybus_gbuf_exit(void)
+void gb_gbuf_exit(void)
 {
+       destroy_workqueue(cport_workqueue);
 }
index 55cb48f..ecda30d 100644 (file)
@@ -229,10 +229,12 @@ 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, struct greybus_host_device *hd);
-int gb_thread_init(void);
-void gb_thread_destroy(void);
+int gb_ap_init(void);
+void gb_ap_exit(void);
 int gb_debugfs_init(void);
 void gb_debugfs_cleanup(void);
+int gb_gbuf_init(void);
+void gb_gbuf_exit(void);
 
 int gb_register_cport_complete(struct greybus_device *gdev,
                               gbuf_complete_t handler, int cport,