greybus: identify protocol by id *and* version
authorAlex Elder <elder@linaro.org>
Wed, 5 Nov 2014 22:12:50 +0000 (16:12 -0600)
committerGreg Kroah-Hartman <greg@kroah.com>
Wed, 5 Nov 2014 22:21:24 +0000 (14:21 -0800)
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>
drivers/staging/greybus/connection.c
drivers/staging/greybus/protocol.c
drivers/staging/greybus/protocol.h

index 1a8f53ef34cf69d5368e99f1d7549882adc4dd9b..703c286f56315133b30b2189c25a52e0233a4a93 100644 (file)
@@ -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;
index e0bcd4bc28a598e60d5df1df71723a8d10aef359..704b180f0ffb66f496a6fe38dbd81b27fcb6fcd4 100644 (file)
@@ -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;
        }
 
index d244e9d3eca1770fb82b58a4c82c299830f600ea..d53f67def77931e17a0049069776a751ba0356e0 100644 (file)
 
 #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 */