greybus: identify protocol by id *and* version
Right now we only look up a protocol based on its protocol id. Add support for maintaining a major and minor version as well, and use them when looking up a protocol. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
This commit is contained in:
parent
6b09938a48
commit
6ae7fa4520
@ -157,13 +157,16 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
|
||||
struct gb_connection *connection;
|
||||
struct greybus_host_device *hd;
|
||||
int retval;
|
||||
u8 major = 0;
|
||||
u8 minor = 1;
|
||||
|
||||
connection = kzalloc(sizeof(*connection), GFP_KERNEL);
|
||||
if (!connection)
|
||||
return NULL;
|
||||
|
||||
INIT_LIST_HEAD(&connection->protocol_links);
|
||||
if (!gb_protocol_get(connection, protocol_id)) {
|
||||
/* XXX Will have to establish connections to get version */
|
||||
if (!gb_protocol_get(connection, protocol_id, major, minor)) {
|
||||
pr_err("protocol 0x%02hhx not found\n", protocol_id);
|
||||
kfree(connection);
|
||||
return NULL;
|
||||
|
@ -13,30 +13,31 @@ static DEFINE_SPINLOCK(gb_protocols_lock);
|
||||
static LIST_HEAD(gb_protocols);
|
||||
|
||||
/* Caller must hold gb_protocols_lock */
|
||||
static struct gb_protocol *_gb_protocol_find(u8 id)
|
||||
static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor)
|
||||
{
|
||||
struct gb_protocol *protocol;
|
||||
|
||||
list_for_each_entry(protocol, &gb_protocols, links)
|
||||
if (protocol->id == id)
|
||||
if (protocol->id == id && protocol->major == major
|
||||
&& protocol->minor == minor)
|
||||
return protocol;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This is basically for debug */
|
||||
static struct gb_protocol *gb_protocol_find(u8 id)
|
||||
static struct gb_protocol *gb_protocol_find(u8 id, u8 major, u8 minor)
|
||||
{
|
||||
struct gb_protocol *protocol;
|
||||
|
||||
spin_lock_irq(&gb_protocols_lock);
|
||||
protocol = _gb_protocol_find(id);
|
||||
protocol = _gb_protocol_find(id, major, minor);
|
||||
spin_unlock_irq(&gb_protocols_lock);
|
||||
|
||||
return protocol;
|
||||
}
|
||||
|
||||
/* Returns true if protocol was succesfully registered, false otherwise */
|
||||
bool gb_protocol_register(u8 id)
|
||||
bool gb_protocol_register(u8 id, u8 major, u8 minor)
|
||||
{
|
||||
struct gb_protocol *protocol;
|
||||
struct gb_protocol *existing;
|
||||
@ -46,10 +47,12 @@ bool gb_protocol_register(u8 id)
|
||||
if (!protocol)
|
||||
return false;
|
||||
protocol->id = id;
|
||||
protocol->major = major;
|
||||
protocol->minor = minor;
|
||||
INIT_LIST_HEAD(&protocol->connections);
|
||||
|
||||
spin_lock_irq(&gb_protocols_lock);
|
||||
existing = _gb_protocol_find(id);
|
||||
existing = _gb_protocol_find(id, major, minor);
|
||||
if (!existing)
|
||||
list_add(&protocol->links, &gb_protocols);
|
||||
spin_unlock_irq(&gb_protocols_lock);
|
||||
@ -77,7 +80,8 @@ bool gb_protocol_deregister(struct gb_protocol *protocol)
|
||||
}
|
||||
|
||||
/* Returns true if successful, false otherwise */
|
||||
bool gb_protocol_get(struct gb_connection *connection, u8 id)
|
||||
bool
|
||||
gb_protocol_get(struct gb_connection *connection, u8 id, u8 major, u8 minor)
|
||||
{
|
||||
struct gb_protocol *protocol;
|
||||
|
||||
@ -90,7 +94,7 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id)
|
||||
}
|
||||
|
||||
spin_lock_irq(&gb_protocols_lock);
|
||||
protocol = _gb_protocol_find(id);
|
||||
protocol = _gb_protocol_find(id, major, minor);
|
||||
if (protocol)
|
||||
list_add(&connection->protocol_links, &protocol->connections);
|
||||
spin_unlock_irq(&gb_protocols_lock);
|
||||
@ -102,6 +106,8 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id)
|
||||
void gb_protocol_put(struct gb_connection *connection)
|
||||
{
|
||||
struct gb_protocol *protocol = connection->protocol;
|
||||
u8 major = protocol->major;
|
||||
u8 minor = protocol->minor;
|
||||
|
||||
/* Sanity checks */
|
||||
if (list_empty(&connection->protocol_links)) {
|
||||
@ -109,9 +115,12 @@ void gb_protocol_put(struct gb_connection *connection)
|
||||
"connection protocol not recorded");
|
||||
return;
|
||||
}
|
||||
if (!protocol || gb_protocol_find(protocol->id) != protocol) {
|
||||
gb_connection_err(connection,
|
||||
"connection has undefined protocol");
|
||||
if (!protocol) {
|
||||
gb_connection_err(connection, "connection has no protocol");
|
||||
return;
|
||||
}
|
||||
if (gb_protocol_find(protocol->id, major, minor) != protocol) {
|
||||
gb_connection_err(connection, "connection protocol not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -11,16 +11,25 @@
|
||||
|
||||
#include "greybus.h"
|
||||
|
||||
/*
|
||||
* Protocols having the same id but different major and/or minor
|
||||
* version numbers are treated as distinct protocols. If it makes
|
||||
* sense someday we could group protocols having the same id.
|
||||
*/
|
||||
struct gb_protocol {
|
||||
u8 id;
|
||||
struct list_head connections; /* protocol users */
|
||||
struct list_head links; /* global list */
|
||||
u8 id;
|
||||
u8 major;
|
||||
u8 minor;
|
||||
|
||||
struct list_head connections; /* protocol users */
|
||||
struct list_head links; /* global list */
|
||||
};
|
||||
|
||||
bool gb_protocol_register(u8 id);
|
||||
bool gb_protocol_register(u8 id, u8 major, u8 minor);
|
||||
bool gb_protocol_deregister(struct gb_protocol *protocol);
|
||||
|
||||
bool gb_protocol_get(struct gb_connection *connection, u8 id);
|
||||
bool gb_protocol_get(struct gb_connection *connection, u8 id,
|
||||
u8 major, u8 minor);
|
||||
void gb_protocol_put(struct gb_connection *connection);
|
||||
|
||||
#endif /* __PROTOCOL_H */
|
||||
|
Loading…
x
Reference in New Issue
Block a user