Commit 6ae7fa45 authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

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: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 6b09938a
...@@ -157,13 +157,16 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, ...@@ -157,13 +157,16 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
struct gb_connection *connection; struct gb_connection *connection;
struct greybus_host_device *hd; struct greybus_host_device *hd;
int retval; int retval;
u8 major = 0;
u8 minor = 1;
connection = kzalloc(sizeof(*connection), GFP_KERNEL); connection = kzalloc(sizeof(*connection), GFP_KERNEL);
if (!connection) if (!connection)
return NULL; return NULL;
INIT_LIST_HEAD(&connection->protocol_links); 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); pr_err("protocol 0x%02hhx not found\n", protocol_id);
kfree(connection); kfree(connection);
return NULL; return NULL;
......
...@@ -13,30 +13,31 @@ static DEFINE_SPINLOCK(gb_protocols_lock); ...@@ -13,30 +13,31 @@ static DEFINE_SPINLOCK(gb_protocols_lock);
static LIST_HEAD(gb_protocols); static LIST_HEAD(gb_protocols);
/* Caller must hold gb_protocols_lock */ /* 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; struct gb_protocol *protocol;
list_for_each_entry(protocol, &gb_protocols, links) 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 protocol;
return NULL; return NULL;
} }
/* This is basically for debug */ /* 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; struct gb_protocol *protocol;
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
protocol = _gb_protocol_find(id); protocol = _gb_protocol_find(id, major, minor);
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
return protocol; return protocol;
} }
/* Returns true if protocol was succesfully registered, false otherwise */ /* 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 *protocol;
struct gb_protocol *existing; struct gb_protocol *existing;
...@@ -46,10 +47,12 @@ bool gb_protocol_register(u8 id) ...@@ -46,10 +47,12 @@ bool gb_protocol_register(u8 id)
if (!protocol) if (!protocol)
return false; return false;
protocol->id = id; protocol->id = id;
protocol->major = major;
protocol->minor = minor;
INIT_LIST_HEAD(&protocol->connections); INIT_LIST_HEAD(&protocol->connections);
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
existing = _gb_protocol_find(id); existing = _gb_protocol_find(id, major, minor);
if (!existing) if (!existing)
list_add(&protocol->links, &gb_protocols); list_add(&protocol->links, &gb_protocols);
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
...@@ -77,7 +80,8 @@ bool gb_protocol_deregister(struct gb_protocol *protocol) ...@@ -77,7 +80,8 @@ bool gb_protocol_deregister(struct gb_protocol *protocol)
} }
/* Returns true if successful, false otherwise */ /* 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; struct gb_protocol *protocol;
...@@ -90,7 +94,7 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id) ...@@ -90,7 +94,7 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id)
} }
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
protocol = _gb_protocol_find(id); protocol = _gb_protocol_find(id, major, minor);
if (protocol) if (protocol)
list_add(&connection->protocol_links, &protocol->connections); list_add(&connection->protocol_links, &protocol->connections);
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
...@@ -102,6 +106,8 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id) ...@@ -102,6 +106,8 @@ bool gb_protocol_get(struct gb_connection *connection, u8 id)
void gb_protocol_put(struct gb_connection *connection) void gb_protocol_put(struct gb_connection *connection)
{ {
struct gb_protocol *protocol = connection->protocol; struct gb_protocol *protocol = connection->protocol;
u8 major = protocol->major;
u8 minor = protocol->minor;
/* Sanity checks */ /* Sanity checks */
if (list_empty(&connection->protocol_links)) { if (list_empty(&connection->protocol_links)) {
...@@ -109,9 +115,12 @@ void gb_protocol_put(struct gb_connection *connection) ...@@ -109,9 +115,12 @@ void gb_protocol_put(struct gb_connection *connection)
"connection protocol not recorded"); "connection protocol not recorded");
return; return;
} }
if (!protocol || gb_protocol_find(protocol->id) != protocol) { if (!protocol) {
gb_connection_err(connection, gb_connection_err(connection, "connection has no protocol");
"connection has undefined protocol"); return;
}
if (gb_protocol_find(protocol->id, major, minor) != protocol) {
gb_connection_err(connection, "connection protocol not found");
return; return;
} }
......
...@@ -11,16 +11,25 @@ ...@@ -11,16 +11,25 @@
#include "greybus.h" #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 { struct gb_protocol {
u8 id; u8 id;
struct list_head connections; /* protocol users */ u8 major;
struct list_head links; /* global list */ 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_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); void gb_protocol_put(struct gb_connection *connection);
#endif /* __PROTOCOL_H */ #endif /* __PROTOCOL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment