summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Hovold <johan@hovoldconsulting.com>2015-11-03 17:03:22 (GMT)
committerGreg Kroah-Hartman <gregkh@google.com>2015-11-05 04:25:57 (GMT)
commit7bc6faaca7d829d4e6f5d65909d5068f73b76bda (patch)
tree80ebab1a7366c6aaae4fd197cac39d4cd3b236c3
parent04fdd6a51a5b3b448047b83624dbfac85d3daf9a (diff)
downloadlinux-7bc6faaca7d829d4e6f5d65909d5068f73b76bda.tar.xz
greybus: create host-device compilation unit
Move everything host-device related to hd.c and hd.h. Signed-off-by: Johan Hovold <johan@hovoldconsulting.com> Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
-rw-r--r--drivers/staging/greybus/Makefile1
-rw-r--r--drivers/staging/greybus/core.c100
-rw-r--r--drivers/staging/greybus/greybus.h48
-rw-r--r--drivers/staging/greybus/hd.c115
-rw-r--r--drivers/staging/greybus/hd.h61
5 files changed, 178 insertions, 147 deletions
diff --git a/drivers/staging/greybus/Makefile b/drivers/staging/greybus/Makefile
index b8dc36b..ba60430 100644
--- a/drivers/staging/greybus/Makefile
+++ b/drivers/staging/greybus/Makefile
@@ -1,5 +1,6 @@
greybus-y := core.o \
debugfs.o \
+ hd.o \
manifest.o \
endo.o \
module.o \
diff --git a/drivers/staging/greybus/core.c b/drivers/staging/greybus/core.c
index 726bf64..4396f90 100644
--- a/drivers/staging/greybus/core.c
+++ b/drivers/staging/greybus/core.c
@@ -146,106 +146,6 @@ void greybus_deregister_driver(struct greybus_driver *driver)
}
EXPORT_SYMBOL_GPL(greybus_deregister_driver);
-
-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);
-
- ida_destroy(&hd->cport_id_map);
- kfree(hd);
- mutex_unlock(&hd_mutex);
-}
-
-struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
- struct device *parent,
- size_t buffer_size_max,
- size_t num_cports)
-{
- struct greybus_host_device *hd;
-
- /*
- * Validate that the driver implements all of the callbacks
- * so that we don't have to every time we make them.
- */
- if ((!driver->message_send) || (!driver->message_cancel)) {
- pr_err("Must implement all greybus_host_driver callbacks!\n");
- return ERR_PTR(-EINVAL);
- }
-
- if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) {
- dev_err(parent, "greybus host-device buffers too small\n");
- return ERR_PTR(-EINVAL);
- }
-
- if (num_cports == 0 || num_cports > CPORT_ID_MAX) {
- dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports);
- return ERR_PTR(-EINVAL);
- }
-
- /*
- * Make sure to never allocate messages larger than what the Greybus
- * protocol supports.
- */
- if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) {
- dev_warn(parent, "limiting buffer size to %u\n",
- GB_OPERATION_MESSAGE_SIZE_MAX);
- buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX;
- }
-
- hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
- if (!hd)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&hd->kref);
- hd->parent = parent;
- hd->driver = driver;
- INIT_LIST_HEAD(&hd->interfaces);
- INIT_LIST_HEAD(&hd->connections);
- ida_init(&hd->cport_id_map);
- hd->buffer_size_max = buffer_size_max;
- hd->num_cports = num_cports;
-
- /*
- * Initialize AP's SVC protocol connection:
- *
- * This is required as part of early initialization of the host device
- * as we need this connection in order to start any kind of message
- * exchange between the AP and the SVC. SVC will start with a
- * 'get-version' request followed by a 'svc-hello' message and at that
- * time we will create a fully initialized svc-connection, as we need
- * endo-id and AP's interface id for that.
- */
- if (!gb_ap_svc_connection_create(hd)) {
- kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
- return ERR_PTR(-ENOMEM);
- }
-
- return hd;
-}
-EXPORT_SYMBOL_GPL(greybus_create_hd);
-
-void greybus_remove_hd(struct greybus_host_device *hd)
-{
- /*
- * Tear down all interfaces, modules, and the endo that is associated
- * with this host controller before freeing the memory associated with
- * the host controller.
- */
- gb_interfaces_remove(hd);
- gb_endo_remove(hd->endo);
-
- /* Is the SVC still using the partially uninitialized connection ? */
- if (hd->initial_svc_connection)
- gb_connection_destroy(hd->initial_svc_connection);
-
- kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
-}
-EXPORT_SYMBOL_GPL(greybus_remove_hd);
-
static int __init gb_init(void)
{
int retval;
diff --git a/drivers/staging/greybus/greybus.h b/drivers/staging/greybus/greybus.h
index 219b2ff..8eb63e0 100644
--- a/drivers/staging/greybus/greybus.h
+++ b/drivers/staging/greybus/greybus.h
@@ -25,6 +25,7 @@
#include "greybus_manifest.h"
#include "greybus_protocols.h"
#include "manifest.h"
+#include "hd.h"
#include "endo.h"
#include "svc.h"
#include "firmware.h"
@@ -57,53 +58,6 @@
#define CPORT_ID_MAX 4095 /* UniPro max id is 4095 */
#define CPORT_ID_BAD U16_MAX
-struct greybus_host_device;
-
-/* Greybus "Host driver" structure, needed by a host controller driver to be
- * able to handle both SVC control as well as "real" greybus messages
- */
-struct greybus_host_driver {
- size_t hd_priv_size;
-
- int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id);
- int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id);
- int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id,
- struct gb_message *message, gfp_t gfp_mask);
- void (*message_cancel)(struct gb_message *message);
- int (*latency_tag_enable)(struct greybus_host_device *hd, u16 cport_id);
- int (*latency_tag_disable)(struct greybus_host_device *hd,
- u16 cport_id);
-};
-
-struct greybus_host_device {
- struct kref kref;
- struct device *parent;
- const struct greybus_host_driver *driver;
-
- struct list_head interfaces;
- struct list_head connections;
- struct ida cport_id_map;
-
- /* Number of CPorts supported by the UniPro IP */
- size_t num_cports;
-
- /* Host device buffer constraints */
- size_t buffer_size_max;
-
- struct gb_endo *endo;
- struct gb_connection *initial_svc_connection;
- struct gb_svc *svc;
-
- /* Private data for the host driver */
- unsigned long hd_priv[0] __aligned(sizeof(s64));
-};
-
-struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd,
- struct device *parent,
- size_t buffer_size_max,
- size_t num_cports);
-void greybus_remove_hd(struct greybus_host_device *hd);
-
struct greybus_driver {
const char *name;
diff --git a/drivers/staging/greybus/hd.c b/drivers/staging/greybus/hd.c
new file mode 100644
index 0000000..3ac8507
--- /dev/null
+++ b/drivers/staging/greybus/hd.c
@@ -0,0 +1,115 @@
+/*
+ * Greybus Host Device
+ *
+ * Copyright 2014-2015 Google Inc.
+ * Copyright 2014-2015 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "greybus.h"
+
+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);
+
+ ida_destroy(&hd->cport_id_map);
+ kfree(hd);
+ mutex_unlock(&hd_mutex);
+}
+
+struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *driver,
+ struct device *parent,
+ size_t buffer_size_max,
+ size_t num_cports)
+{
+ struct greybus_host_device *hd;
+
+ /*
+ * Validate that the driver implements all of the callbacks
+ * so that we don't have to every time we make them.
+ */
+ if ((!driver->message_send) || (!driver->message_cancel)) {
+ pr_err("Must implement all greybus_host_driver callbacks!\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) {
+ dev_err(parent, "greybus host-device buffers too small\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (num_cports == 0 || num_cports > CPORT_ID_MAX) {
+ dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+ * Make sure to never allocate messages larger than what the Greybus
+ * protocol supports.
+ */
+ if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) {
+ dev_warn(parent, "limiting buffer size to %u\n",
+ GB_OPERATION_MESSAGE_SIZE_MAX);
+ buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX;
+ }
+
+ hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
+ if (!hd)
+ return ERR_PTR(-ENOMEM);
+
+ kref_init(&hd->kref);
+ hd->parent = parent;
+ hd->driver = driver;
+ INIT_LIST_HEAD(&hd->interfaces);
+ INIT_LIST_HEAD(&hd->connections);
+ ida_init(&hd->cport_id_map);
+ hd->buffer_size_max = buffer_size_max;
+ hd->num_cports = num_cports;
+
+ /*
+ * Initialize AP's SVC protocol connection:
+ *
+ * This is required as part of early initialization of the host device
+ * as we need this connection in order to start any kind of message
+ * exchange between the AP and the SVC. SVC will start with a
+ * 'get-version' request followed by a 'svc-hello' message and at that
+ * time we will create a fully initialized svc-connection, as we need
+ * endo-id and AP's interface id for that.
+ */
+ if (!gb_ap_svc_connection_create(hd)) {
+ kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return hd;
+}
+EXPORT_SYMBOL_GPL(greybus_create_hd);
+
+void greybus_remove_hd(struct greybus_host_device *hd)
+{
+ /*
+ * Tear down all interfaces, modules, and the endo that is associated
+ * with this host controller before freeing the memory associated with
+ * the host controller.
+ */
+ gb_interfaces_remove(hd);
+ gb_endo_remove(hd->endo);
+
+ /* Is the SVC still using the partially uninitialized connection ? */
+ if (hd->initial_svc_connection)
+ gb_connection_destroy(hd->initial_svc_connection);
+
+ kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
+}
+EXPORT_SYMBOL_GPL(greybus_remove_hd);
diff --git a/drivers/staging/greybus/hd.h b/drivers/staging/greybus/hd.h
new file mode 100644
index 0000000..df953d4
--- /dev/null
+++ b/drivers/staging/greybus/hd.h
@@ -0,0 +1,61 @@
+/*
+ * Greybus Host Device
+ *
+ * Copyright 2014-2015 Google Inc.
+ * Copyright 2014-2015 Linaro Ltd.
+ *
+ * Released under the GPLv2 only.
+ */
+
+#ifndef __HD_H
+#define __HD_H
+
+struct greybus_host_device;
+struct gb_message;
+
+/* Greybus "Host driver" structure, needed by a host controller driver to be
+ * able to handle both SVC control as well as "real" greybus messages
+ */
+struct greybus_host_driver {
+ size_t hd_priv_size;
+
+ int (*cport_enable)(struct greybus_host_device *hd, u16 cport_id);
+ int (*cport_disable)(struct greybus_host_device *hd, u16 cport_id);
+ int (*message_send)(struct greybus_host_device *hd, u16 dest_cport_id,
+ struct gb_message *message, gfp_t gfp_mask);
+ void (*message_cancel)(struct gb_message *message);
+ int (*latency_tag_enable)(struct greybus_host_device *hd, u16 cport_id);
+ int (*latency_tag_disable)(struct greybus_host_device *hd,
+ u16 cport_id);
+};
+
+struct greybus_host_device {
+ struct kref kref;
+ struct device *parent;
+ const struct greybus_host_driver *driver;
+
+ struct list_head interfaces;
+ struct list_head connections;
+ struct ida cport_id_map;
+
+ /* Number of CPorts supported by the UniPro IP */
+ size_t num_cports;
+
+ /* Host device buffer constraints */
+ size_t buffer_size_max;
+
+ struct gb_endo *endo;
+ struct gb_connection *initial_svc_connection;
+ struct gb_svc *svc;
+
+ /* Private data for the host driver */
+ unsigned long hd_priv[0] __aligned(sizeof(s64));
+};
+
+struct greybus_host_device *greybus_create_hd(struct greybus_host_driver *hd,
+ struct device *parent,
+ size_t buffer_size_max,
+ size_t num_cports);
+void greybus_remove_hd(struct greybus_host_device *hd);
+
+#endif /* __HD_H */