From 45f3678bcff37889b8fe81a7b1ea21b09a25803d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 14 Sep 2014 11:40:35 -0700 Subject: [PATCH] greybus: gbuf: cport in buffer stream logic --- drivers/staging/greybus/ap.c | 6 +-- drivers/staging/greybus/core.c | 21 ++++++++--- drivers/staging/greybus/gbuf.c | 62 ++++++++++++++++++++++++++++--- drivers/staging/greybus/greybus.h | 6 ++- 4 files changed, 79 insertions(+), 16 deletions(-) diff --git a/drivers/staging/greybus/ap.c b/drivers/staging/greybus/ap.c index 0fc3ff70f317..4c1065030745 100644 --- a/drivers/staging/greybus/ap.c +++ b/drivers/staging/greybus/ap.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #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); } diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c index bad40bafae4c..f987086ae6ec 100644 --- a/drivers/staging/greybus/core.c +++ b/drivers/staging/greybus/core.c @@ -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(); } diff --git a/drivers/staging/greybus/gbuf.c b/drivers/staging/greybus/gbuf.c index b06d779254c5..3affdbfa0479 100644 --- a/drivers/staging/greybus/gbuf.c +++ b/drivers/staging/greybus/gbuf.c @@ -15,6 +15,7 @@ #include #include #include +#include #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); } diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h index 55cb48f264ac..ecda30dd308a 100644 --- a/drivers/staging/greybus/greybus.h +++ b/drivers/staging/greybus/greybus.h @@ -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, -- 2.39.5