2 * Greybus protocol handling
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
14 /* Global list of registered protocols */
15 static DEFINE_SPINLOCK(gb_protocols_lock);
16 static LIST_HEAD(gb_protocols);
18 /* Caller must hold gb_protocols_lock */
19 static struct gb_protocol *gb_protocol_find(u8 id, u8 major, u8 minor)
21 struct gb_protocol *protocol;
23 list_for_each_entry(protocol, &gb_protocols, links) {
24 if (protocol->id < id)
26 if (protocol->id > id)
29 if (protocol->major > major)
31 if (protocol->major < major)
34 if (protocol->minor > minor)
36 if (protocol->minor < minor)
44 int __gb_protocol_register(struct gb_protocol *protocol, struct module *module)
46 struct gb_protocol *existing;
48 u8 major = protocol->major;
49 u8 minor = protocol->minor;
51 protocol->owner = module;
54 * The protocols list is sorted first by protocol id (low to
55 * high), then by major version (high to low), and finally
56 * by minor version (high to low). Searching only by
57 * protocol id will produce the newest implemented version
60 spin_lock_irq(&gb_protocols_lock);
62 list_for_each_entry(existing, &gb_protocols, links) {
63 if (existing->id < id)
65 if (existing->id > id)
68 if (existing->major > major)
70 if (existing->major < major)
73 if (existing->minor > minor)
75 if (existing->minor < minor)
78 /* A matching protocol has already been registered */
79 spin_unlock_irq(&gb_protocols_lock);
85 * We need to insert the protocol here, before the existing one
86 * (or before the head if we searched the whole list)
88 list_add_tail(&protocol->links, &existing->links);
89 spin_unlock_irq(&gb_protocols_lock);
91 pr_info("Registered %s protocol.\n", protocol->name);
94 * Go try to bind any unbound connections, as we have a
95 * new protocol in the system
97 gb_bundle_bind_protocols();
101 EXPORT_SYMBOL_GPL(__gb_protocol_register);
104 * De-register a previously registered protocol.
106 * XXX Currently this fails (and reports an error to the caller) if
107 * XXX the protocol is currently in use. We may want to forcefully
108 * XXX kill off a protocol and all its active users at some point.
109 * XXX But I think that's better handled by quiescing modules that
110 * XXX have users and having those users drop their reference.
112 * Returns true if successful, false otherwise.
114 int gb_protocol_deregister(struct gb_protocol *protocol)
116 u8 protocol_count = 0;
121 spin_lock_irq(&gb_protocols_lock);
122 protocol = gb_protocol_find(protocol->id, protocol->major,
125 protocol_count = protocol->count;
127 list_del(&protocol->links);
129 spin_unlock_irq(&gb_protocols_lock);
132 pr_info("Deregistered %s protocol.\n", protocol->name);
134 return protocol && !protocol_count;
136 EXPORT_SYMBOL_GPL(gb_protocol_deregister);
138 /* Returns the requested protocol if available, or a null pointer */
139 struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor)
141 struct gb_protocol *protocol;
144 spin_lock_irq(&gb_protocols_lock);
145 protocol = gb_protocol_find(id, major, minor);
147 if (!try_module_get(protocol->owner)) {
150 protocol_count = protocol->count;
151 if (protocol_count != U8_MAX)
155 spin_unlock_irq(&gb_protocols_lock);
158 WARN_ON(protocol_count == U8_MAX);
160 pr_err("protocol id %hhu version %hhu.%hhu not found\n",
166 int gb_protocol_get_version(struct gb_connection *connection, int type,
167 void *request, int request_size,
168 struct gb_protocol_version_response *response,
173 retval = gb_operation_sync(connection, type, request, request_size,
174 response, sizeof(*response));
178 if (response->major > major) {
179 dev_err(&connection->dev,
180 "unsupported major version (%hhu > %hhu)\n",
181 response->major, major);
185 dev_dbg(&connection->dev, "version_major = %u version_minor = %u\n",
186 response->major, response->minor);
190 EXPORT_SYMBOL_GPL(gb_protocol_get_version);
192 void gb_protocol_put(struct gb_protocol *protocol)
200 major = protocol->major;
201 minor = protocol->minor;
203 spin_lock_irq(&gb_protocols_lock);
204 protocol = gb_protocol_find(id, major, minor);
206 protocol_count = protocol->count;
209 module_put(protocol->owner);
211 spin_unlock_irq(&gb_protocols_lock);
213 WARN_ON(!protocol_count);
215 pr_err("protocol id %hhu version %hhu.%hhu not found\n",