4 * Copyright 2014-2015 Google Inc.
5 * Copyright 2014-2015 Linaro Ltd.
7 * Released under the GPLv2 only.
10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/kernel.h>
13 #include <linux/slab.h>
17 static DEFINE_MUTEX(hd_mutex);
20 static void free_hd(struct kref *kref)
22 struct gb_host_device *hd;
24 hd = container_of(kref, struct gb_host_device, kref);
26 ida_destroy(&hd->cport_id_map);
28 mutex_unlock(&hd_mutex);
31 struct gb_host_device *greybus_create_hd(struct greybus_host_driver *driver,
32 struct device *parent,
33 size_t buffer_size_max,
36 struct gb_host_device *hd;
39 * Validate that the driver implements all of the callbacks
40 * so that we don't have to every time we make them.
42 if ((!driver->message_send) || (!driver->message_cancel)) {
43 pr_err("Must implement all greybus_host_driver callbacks!\n");
44 return ERR_PTR(-EINVAL);
47 if (buffer_size_max < GB_OPERATION_MESSAGE_SIZE_MIN) {
48 dev_err(parent, "greybus host-device buffers too small\n");
49 return ERR_PTR(-EINVAL);
52 if (num_cports == 0 || num_cports > CPORT_ID_MAX) {
53 dev_err(parent, "Invalid number of CPorts: %zu\n", num_cports);
54 return ERR_PTR(-EINVAL);
58 * Make sure to never allocate messages larger than what the Greybus
61 if (buffer_size_max > GB_OPERATION_MESSAGE_SIZE_MAX) {
62 dev_warn(parent, "limiting buffer size to %u\n",
63 GB_OPERATION_MESSAGE_SIZE_MAX);
64 buffer_size_max = GB_OPERATION_MESSAGE_SIZE_MAX;
67 hd = kzalloc(sizeof(*hd) + driver->hd_priv_size, GFP_KERNEL);
69 return ERR_PTR(-ENOMEM);
74 INIT_LIST_HEAD(&hd->interfaces);
75 INIT_LIST_HEAD(&hd->connections);
76 ida_init(&hd->cport_id_map);
77 hd->buffer_size_max = buffer_size_max;
78 hd->num_cports = num_cports;
81 * Initialize AP's SVC protocol connection:
83 * This is required as part of early initialization of the host device
84 * as we need this connection in order to start any kind of message
85 * exchange between the AP and the SVC. SVC will start with a
86 * 'get-version' request followed by a 'svc-hello' message and at that
87 * time we will create a fully initialized svc-connection, as we need
88 * endo-id and AP's interface id for that.
90 if (!gb_ap_svc_connection_create(hd)) {
91 kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
92 return ERR_PTR(-ENOMEM);
97 EXPORT_SYMBOL_GPL(greybus_create_hd);
99 void greybus_remove_hd(struct gb_host_device *hd)
102 * Tear down all interfaces, modules, and the endo that is associated
103 * with this host controller before freeing the memory associated with
104 * the host controller.
106 gb_interfaces_remove(hd);
107 gb_endo_remove(hd->endo);
109 /* Is the SVC still using the partially uninitialized connection ? */
110 if (hd->initial_svc_connection)
111 gb_connection_destroy(hd->initial_svc_connection);
113 kref_put_mutex(&hd->kref, free_hd, &hd_mutex);
115 EXPORT_SYMBOL_GPL(greybus_remove_hd);