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>
diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c
index 1a8f53e..703c286 100644
--- a/drivers/staging/greybus/connection.c
+++ b/drivers/staging/greybus/connection.c
@@ -157,13 +157,16 @@
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;
diff --git a/drivers/staging/greybus/protocol.c b/drivers/staging/greybus/protocol.c
index e0bcd4b..704b180 100644
--- a/drivers/staging/greybus/protocol.c
+++ b/drivers/staging/greybus/protocol.c
@@ -13,30 +13,31 @@
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 @@
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 @@
}
/* 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 @@
}
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 @@
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 @@
"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;
}
diff --git a/drivers/staging/greybus/protocol.h b/drivers/staging/greybus/protocol.h
index d244e9d..d53f67d 100644
--- a/drivers/staging/greybus/protocol.h
+++ b/drivers/staging/greybus/protocol.h
@@ -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 */