struct ap_msg {
u8 *data;
- int size;
+ size_t size;
+ struct greybus_host_device *hd;
struct list_head list;
};
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;
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());
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);
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;
}
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);
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/kthread.h>
#include <linux/device.h>
#include "greybus.h"
// 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)
{
}
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)
{
}
+/* 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;
/* 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 */
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 = {
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
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 {
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 */
/* 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);