Commit 68f1fc4d authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

greybus: more hd work

parent a39879fc
...@@ -22,7 +22,8 @@ ...@@ -22,7 +22,8 @@
struct ap_msg { struct ap_msg {
u8 *data; u8 *data;
int size; size_t size;
struct greybus_host_device *hd;
struct list_head list; struct list_head list;
}; };
...@@ -31,6 +32,21 @@ static spinlock_t ap_msg_list_lock; ...@@ -31,6 +32,21 @@ static spinlock_t ap_msg_list_lock;
static struct task_struct *ap_thread; static struct task_struct *ap_thread;
static wait_queue_head_t ap_wait; 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) static struct ap_msg *get_ap_msg(void)
{ {
struct ap_msg *ap_msg; struct ap_msg *ap_msg;
...@@ -49,6 +65,7 @@ static struct ap_msg *get_ap_msg(void) ...@@ -49,6 +65,7 @@ static struct ap_msg *get_ap_msg(void)
static int ap_process_loop(void *data) static int ap_process_loop(void *data)
{ {
struct ap_msg *ap_msg; struct ap_msg *ap_msg;
struct svc_msg *svc_msg;
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
wait_event_interruptible(ap_wait, kthread_should_stop()); wait_event_interruptible(ap_wait, kthread_should_stop());
...@@ -61,7 +78,12 @@ static int ap_process_loop(void *data) ...@@ -61,7 +78,12 @@ static int ap_process_loop(void *data)
if (!ap_msg) if (!ap_msg)
continue; 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 */ /* clean the message up */
kfree(ap_msg->data); kfree(ap_msg->data);
...@@ -70,7 +92,7 @@ static int ap_process_loop(void *data) ...@@ -70,7 +92,7 @@ static int ap_process_loop(void *data)
return 0; 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; struct ap_msg *ap_msg;
unsigned long flags; unsigned long flags;
...@@ -96,6 +118,7 @@ int gb_new_ap_msg(u8 *data, int size) ...@@ -96,6 +118,7 @@ int gb_new_ap_msg(u8 *data, int size)
} }
memcpy(ap_msg->data, data, size); memcpy(ap_msg->data, data, size);
ap_msg->size = size; ap_msg->size = size;
ap_msg->hd = hd;
spin_lock_irqsave(&ap_msg_list_lock, flags); spin_lock_irqsave(&ap_msg_list_lock, flags);
list_add(&ap_msg->list, &ap_msg_list); list_add(&ap_msg->list, &ap_msg_list);
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/device.h> #include <linux/device.h>
#include "greybus.h" #include "greybus.h"
...@@ -449,6 +448,17 @@ void greybus_remove_device(struct greybus_device *gdev) ...@@ -449,6 +448,17 @@ void greybus_remove_device(struct greybus_device *gdev)
// FIXME - device_remove(&gdev->dev); // 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 greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
struct device *parent) struct device *parent)
{ {
...@@ -464,6 +474,12 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver ...@@ -464,6 +474,12 @@ struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver
} }
EXPORT_SYMBOL_GPL(greybus_create_hd); 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) static int __init gb_init(void)
{ {
......
...@@ -82,15 +82,30 @@ static void free_gbuf(struct gbuf *gbuf) ...@@ -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 = { static struct greybus_host_driver es1_driver = {
.hd_priv_size = sizeof(struct es1_ap_dev), .hd_priv_size = sizeof(struct es1_ap_dev),
.alloc_gbuf = alloc_gbuf, .alloc_gbuf = alloc_gbuf,
.free_gbuf = free_gbuf, .free_gbuf = free_gbuf,
.ap_msg = ap_msg,
}; };
void ap_in_callback(struct urb *urb) void ap_in_callback(struct urb *urb)
{ {
struct es1_ap_dev *es1 = urb->context;
struct device *dev = &urb->dev->dev; struct device *dev = &urb->dev->dev;
int status = urb->status; int status = urb->status;
int retval; int retval;
...@@ -115,7 +130,7 @@ void ap_in_callback(struct urb *urb) ...@@ -115,7 +130,7 @@ void ap_in_callback(struct urb *urb)
/* We have a message, create a new message structure, add it to the /* We have a message, create a new message structure, add it to the
* list, and wake up our thread that will process the messages. * 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: exit:
/* resubmit the urb to get more messages */ /* resubmit the urb to get more messages */
...@@ -211,8 +226,7 @@ static void ap_disconnect(struct usb_interface *interface) ...@@ -211,8 +226,7 @@ static void ap_disconnect(struct usb_interface *interface)
usb_put_dev(es1->usb_dev); usb_put_dev(es1->usb_dev);
kfree(es1->ap_buffer); kfree(es1->ap_buffer);
// FIXME greybus_remove_hd(es1->hd);
//greybus_destroy_hd(es1->hd);
} }
static struct usb_driver es1_ap_driver = { static struct usb_driver es1_ap_driver = {
......
...@@ -92,6 +92,7 @@ struct gb_sdio_host; ...@@ -92,6 +92,7 @@ struct gb_sdio_host;
struct gb_tty; struct gb_tty;
struct gb_usb_device; struct gb_usb_device;
struct greybus_host_device; struct greybus_host_device;
struct svc_msg;
/* Greybus "Host driver" structure, needed by a host controller driver to be /* Greybus "Host driver" structure, needed by a host controller driver to be
* able to handle both SVC control as well as "real" greybus messages * able to handle both SVC control as well as "real" greybus messages
...@@ -102,6 +103,7 @@ struct greybus_host_driver { ...@@ -102,6 +103,7 @@ struct greybus_host_driver {
int (*start)(struct greybus_host_device *hd); int (*start)(struct greybus_host_device *hd);
int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask); int (*alloc_gbuf)(struct gbuf *gbuf, unsigned int size, gfp_t gfp_mask);
void (*free_gbuf)(struct gbuf *gbuf); void (*free_gbuf)(struct gbuf *gbuf);
void (*ap_msg)(struct svc_msg *svc_msg, struct greybus_host_device *hd);
}; };
struct greybus_host_device { struct greybus_host_device {
...@@ -115,6 +117,7 @@ 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 greybus_host_device *greybus_create_hd(struct greybus_host_driver *host_driver,
struct device *parent); struct device *parent);
void greybus_remove_hd(struct greybus_host_device *hd);
/* Increase these values if needed */ /* Increase these values if needed */
...@@ -213,7 +216,7 @@ const u8 *greybus_string(struct greybus_device *gdev, int id); ...@@ -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. */ /* 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); int gb_thread_init(void);
void gb_thread_destroy(void); void gb_thread_destroy(void);
int gb_debugfs_init(void); int gb_debugfs_init(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment