2 * Greybus protocol handling
4 * Copyright 2014 Google Inc.
5 * Copyright 2014 Linaro Ltd.
7 * Released under the GPLv2 only.
12 /* Global list of registered protocols */
13 static DEFINE_SPINLOCK(gb_protocols_lock);
14 static LIST_HEAD(gb_protocols);
16 /* Caller must hold gb_protocols_lock */
17 static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor)
19 struct gb_protocol *protocol;
21 list_for_each_entry(protocol, &gb_protocols, links) {
22 if (protocol->id < id)
24 if (protocol->id > id)
27 if (protocol->major > major)
29 if (protocol->major < major)
32 if (protocol->minor > minor)
34 if (protocol->minor < minor)
42 int __gb_protocol_register(struct gb_protocol *protocol, struct module *module)
44 struct gb_protocol *existing;
46 u8 major = protocol->major;
47 u8 minor = protocol->minor;
49 protocol->owner = module;
52 * The protocols list is sorted first by protocol id (low to
53 * high), then by major version (high to low), and finally
54 * by minor version (high to low). Searching only by
55 * protocol id will produce the newest implemented version
58 spin_lock_irq(&gb_protocols_lock);
60 list_for_each_entry(existing, &gb_protocols, links) {
61 if (existing->id < id)
63 if (existing->id > id)
66 if (existing->major > major)
68 if (existing->major < major)
71 if (existing->minor > minor)
73 if (existing->minor < minor)
76 /* A matching protocol has already been registered */
77 spin_unlock_irq(&gb_protocols_lock);
83 * We need to insert the protocol here, before the existing one
84 * (or before the head if we searched the whole list)
86 list_add_tail(&protocol->links, &existing->links);
87 spin_unlock_irq(&gb_protocols_lock);
90 * Go try to bind any unbound connections, as we have a
91 * new protocol in the system
93 gb_bundle_bind_protocols();
97 EXPORT_SYMBOL_GPL(__gb_protocol_register);
100 * De-register a previously registered protocol.
102 * XXX Currently this fails (and reports an error to the caller) if
103 * XXX the protocol is currently in use. We may want to forcefully
104 * XXX kill off a protocol and all its active users at some point.
105 * XXX But I think that's better handled by quiescing modules that
106 * XXX have users and having those users drop their reference.
108 * Returns true if successful, false otherwise.
110 int gb_protocol_deregister(struct gb_protocol *protocol)
112 u8 protocol_count = 0;
117 spin_lock_irq(&gb_protocols_lock);
118 protocol = _gb_protocol_find(protocol->id, protocol->major,
121 protocol_count = protocol->count;
123 list_del(&protocol->links);
125 spin_unlock_irq(&gb_protocols_lock);
127 return protocol && !protocol_count;
129 EXPORT_SYMBOL_GPL(gb_protocol_deregister);
131 /* Returns the requested protocol if available, or a null pointer */
132 struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor)
134 struct gb_protocol *protocol;
137 spin_lock_irq(&gb_protocols_lock);
138 protocol = _gb_protocol_find(id, major, minor);
140 if (!try_module_get(protocol->owner)) {
143 protocol_count = protocol->count;
144 if (protocol_count != U8_MAX)
148 spin_unlock_irq(&gb_protocols_lock);
151 WARN_ON(protocol_count == U8_MAX);
153 pr_err("protocol id %hhu version %hhu.%hhu not found\n",
159 void gb_protocol_put(struct gb_protocol *protocol)
161 u8 major = protocol->major;
162 u8 minor = protocol->minor;
165 spin_lock_irq(&gb_protocols_lock);
166 protocol = _gb_protocol_find(protocol->id, protocol->major,
169 protocol_count = protocol->count;
172 module_put(protocol->owner);
174 spin_unlock_irq(&gb_protocols_lock);
176 WARN_ON(!protocol_count);
178 pr_err("protocol id %hhu version %hhu.%hhu not found\n",
179 protocol->id, major, minor);