Commit 0e447657 authored by Alex Elder's avatar Alex Elder Committed by Greg Kroah-Hartman

greybus: count rather than list protocol users

We don't really need a list of protocol users, we can just keep
track of how many there are.  Get rid of the list and use a count
instead.

Also, have gb_protocol_get() return the protocol rather than assigning
a passed-in connection pointer's protocol.  Make a comparable change
to the gb_protocol_put() interface.

Get rid of gb_protocol_find() (the version that locks), because it
is no longer needed.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 6ae7fa45
...@@ -164,9 +164,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, ...@@ -164,9 +164,9 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
if (!connection) if (!connection)
return NULL; return NULL;
INIT_LIST_HEAD(&connection->protocol_links);
/* XXX Will have to establish connections to get version */ /* XXX Will have to establish connections to get version */
if (!gb_protocol_get(connection, protocol_id, major, minor)) { connection->protocol = gb_protocol_get(protocol_id, major, minor);
if (!connection->protocol) {
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;
...@@ -175,7 +175,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, ...@@ -175,7 +175,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
hd = interface->gmod->hd; hd = interface->gmod->hd;
connection->hd = hd; connection->hd = hd;
if (!gb_connection_hd_cport_id_alloc(connection)) { if (!gb_connection_hd_cport_id_alloc(connection)) {
gb_protocol_put(connection); gb_protocol_put(connection->protocol);
kfree(connection); kfree(connection);
return NULL; return NULL;
} }
...@@ -198,7 +198,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, ...@@ -198,7 +198,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface,
pr_err("failed to add connection device for cport 0x%04hx\n", pr_err("failed to add connection device for cport 0x%04hx\n",
cport_id); cport_id);
gb_connection_hd_cport_id_free(connection); gb_connection_hd_cport_id_free(connection);
gb_protocol_put(connection); gb_protocol_put(connection->protocol);
put_device(&connection->dev); put_device(&connection->dev);
return NULL; return NULL;
} }
...@@ -239,8 +239,7 @@ void gb_connection_destroy(struct gb_connection *connection) ...@@ -239,8 +239,7 @@ void gb_connection_destroy(struct gb_connection *connection)
spin_unlock_irq(&gb_connections_lock); spin_unlock_irq(&gb_connections_lock);
gb_connection_hd_cport_id_free(connection); gb_connection_hd_cport_id_free(connection);
/* kref_put(connection->hd); */ gb_protocol_put(connection->protocol);
gb_protocol_put(connection);
device_del(&connection->dev); device_del(&connection->dev);
} }
......
...@@ -41,7 +41,6 @@ struct gb_connection { ...@@ -41,7 +41,6 @@ struct gb_connection {
struct list_head interface_links; struct list_head interface_links;
struct gb_protocol *protocol; struct gb_protocol *protocol;
struct list_head protocol_links;
enum gb_connection_state state; enum gb_connection_state state;
......
...@@ -24,18 +24,6 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor) ...@@ -24,18 +24,6 @@ static struct gb_protocol *_gb_protocol_find(u8 id, u8 major, u8 minor)
return NULL; return NULL;
} }
/* This is basically for debug */
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, major, minor);
spin_unlock_irq(&gb_protocols_lock);
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, u8 major, u8 minor) bool gb_protocol_register(u8 id, u8 major, u8 minor)
{ {
...@@ -49,7 +37,6 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) ...@@ -49,7 +37,6 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor)
protocol->id = id; protocol->id = id;
protocol->major = major; protocol->major = major;
protocol->minor = minor; protocol->minor = minor;
INIT_LIST_HEAD(&protocol->connections);
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
existing = _gb_protocol_find(id, major, minor); existing = _gb_protocol_find(id, major, minor);
...@@ -68,64 +55,64 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor) ...@@ -68,64 +55,64 @@ bool gb_protocol_register(u8 id, u8 major, u8 minor)
/* Returns true if successful, false otherwise */ /* Returns true if successful, false otherwise */
bool gb_protocol_deregister(struct gb_protocol *protocol) bool gb_protocol_deregister(struct gb_protocol *protocol)
{ {
u8 protocol_count;
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
if (list_empty(&protocol->connections)) protocol = _gb_protocol_find(protocol->id, protocol->major,
list_del(&protocol->links); protocol->minor);
else if (protocol) {
protocol = NULL; /* Protocol is still in use */ protocol_count = protocol->count;
if (!protocol_count)
list_del(&protocol->links);
}
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
kfree(protocol); kfree(protocol);
return protocol != NULL; return protocol && !protocol_count;
} }
/* Returns true if successful, false otherwise */ /* Returns the requested protocol if available, or a null pointer */
bool struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor)
gb_protocol_get(struct gb_connection *connection, u8 id, u8 major, u8 minor)
{ {
struct gb_protocol *protocol; struct gb_protocol *protocol;
u8 protocol_count;
/* Sanity */
if (!list_empty(&connection->protocol_links) ||
!connection->protocol->id) {
gb_connection_err(connection,
"connection already has protocol");
return false;
}
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
protocol = _gb_protocol_find(id, major, minor); protocol = _gb_protocol_find(id, major, minor);
if (protocol) if (protocol) {
list_add(&connection->protocol_links, &protocol->connections); protocol_count = protocol->count;
if (protocol_count != U8_MAX)
protocol->count++;
}
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
connection->protocol = protocol;
return protocol != NULL; if (protocol)
WARN_ON(protocol_count == U8_MAX);
else
pr_err("protocol id %hhu version %hhu.%hhu not found\n",
id, major, minor);
return protocol;
} }
void gb_protocol_put(struct gb_connection *connection) void gb_protocol_put(struct gb_protocol *protocol)
{ {
struct gb_protocol *protocol = connection->protocol;
u8 major = protocol->major; u8 major = protocol->major;
u8 minor = protocol->minor; u8 minor = protocol->minor;
u8 protocol_count;
/* Sanity checks */
if (list_empty(&connection->protocol_links)) {
gb_connection_err(connection,
"connection protocol not recorded");
return;
}
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;
}
spin_lock_irq(&gb_protocols_lock); spin_lock_irq(&gb_protocols_lock);
list_del(&connection->protocol_links); protocol = _gb_protocol_find(protocol->id, protocol->major,
connection->protocol = NULL; protocol->minor);
if (protocol) {
protocol_count = protocol->count;
if (protocol_count)
protocol->count--;
}
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
if (protocol)
WARN_ON(!protocol_count);
else
pr_err("protocol id %hhu version %hhu.%hhu not found\n",
protocol->id, major, minor);
} }
...@@ -20,16 +20,15 @@ struct gb_protocol { ...@@ -20,16 +20,15 @@ struct gb_protocol {
u8 id; u8 id;
u8 major; u8 major;
u8 minor; u8 minor;
u8 count;
struct list_head connections; /* protocol users */
struct list_head links; /* global list */ struct list_head links; /* global list */
}; };
bool gb_protocol_register(u8 id, u8 major, u8 minor); 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, struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor);
u8 major, u8 minor); void gb_protocol_put(struct gb_protocol *protocol);
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