Commit 50dfb878 authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

greybus: connection: move legacy-protocol handling to legacy driver

Move legacy protocol and connection handling to the legacy driver.

Rename the former global functions using a common legacy_ prefix.

Note that all legacy protocols suffer from a connection initialisation
race in that the protocol-specific initialisation, which includes
allocation of protocol-specific state containers, can not happen until
*after* the connection has been enabled. This is a major flaw in the
original design that we can now finally address by converting the legacy
protocol drivers into proper bundle (class) drivers.
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarJohan Hovold <johan@hovoldconsulting.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 84427943
...@@ -12,10 +12,6 @@ ...@@ -12,10 +12,6 @@
#include "greybus.h" #include "greybus.h"
static int gb_connection_bind_protocol(struct gb_connection *connection);
static void gb_connection_unbind_protocol(struct gb_connection *connection);
static DEFINE_SPINLOCK(gb_connections_lock); static DEFINE_SPINLOCK(gb_connections_lock);
/* This is only used at initialization time; no locking is required. */ /* This is only used at initialization time; no locking is required. */
...@@ -340,24 +336,6 @@ gb_connection_control_disconnected(struct gb_connection *connection) ...@@ -340,24 +336,6 @@ gb_connection_control_disconnected(struct gb_connection *connection)
} }
} }
/*
* Request protocol version supported by the module.
*/
static int gb_connection_protocol_get_version(struct gb_connection *connection)
{
int ret;
ret = gb_protocol_get_version(connection);
if (ret) {
dev_err(&connection->hd->dev,
"%s: failed to get protocol version: %d\n",
connection->name, ret);
return ret;
}
return 0;
}
/* /*
* Cancel all active operations on a connection. * Cancel all active operations on a connection.
* *
...@@ -526,63 +504,6 @@ void gb_connection_disable(struct gb_connection *connection) ...@@ -526,63 +504,6 @@ void gb_connection_disable(struct gb_connection *connection)
} }
EXPORT_SYMBOL_GPL(gb_connection_disable); EXPORT_SYMBOL_GPL(gb_connection_disable);
static int gb_legacy_request_handler(struct gb_operation *operation)
{
struct gb_protocol *protocol = operation->connection->protocol;
return protocol->request_recv(operation->type, operation);
}
int gb_connection_legacy_init(struct gb_connection *connection)
{
gb_request_handler_t handler;
int ret;
ret = gb_connection_bind_protocol(connection);
if (ret)
return ret;
if (connection->protocol->request_recv)
handler = gb_legacy_request_handler;
else
handler = NULL;
ret = gb_connection_enable(connection, handler);
if (ret)
goto err_unbind_protocol;
ret = gb_connection_protocol_get_version(connection);
if (ret)
goto err_disable;
ret = connection->protocol->connection_init(connection);
if (ret)
goto err_disable;
return 0;
err_disable:
gb_connection_disable(connection);
err_unbind_protocol:
gb_connection_unbind_protocol(connection);
return ret;
}
EXPORT_SYMBOL_GPL(gb_connection_legacy_init);
void gb_connection_legacy_exit(struct gb_connection *connection)
{
if (connection->state == GB_CONNECTION_STATE_DISABLED)
return;
gb_connection_disable(connection);
connection->protocol->connection_exit(connection);
gb_connection_unbind_protocol(connection);
}
EXPORT_SYMBOL_GPL(gb_connection_legacy_exit);
/* /*
* Tear down a previously set up connection. * Tear down a previously set up connection.
*/ */
...@@ -639,31 +560,3 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection) ...@@ -639,31 +560,3 @@ void gb_connection_latency_tag_disable(struct gb_connection *connection)
} }
} }
EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable); EXPORT_SYMBOL_GPL(gb_connection_latency_tag_disable);
static int gb_connection_bind_protocol(struct gb_connection *connection)
{
struct gb_protocol *protocol;
protocol = gb_protocol_get(connection->protocol_id,
connection->major,
connection->minor);
if (!protocol) {
dev_err(&connection->hd->dev,
"protocol 0x%02x version %u.%u not found\n",
connection->protocol_id,
connection->major, connection->minor);
return -EPROTONOSUPPORT;
}
connection->protocol = protocol;
return 0;
}
static void gb_connection_unbind_protocol(struct gb_connection *connection)
{
struct gb_protocol *protocol = connection->protocol;
gb_protocol_put(protocol);
connection->protocol = NULL;
}
...@@ -78,9 +78,6 @@ static inline int gb_connection_enable_tx(struct gb_connection *connection) ...@@ -78,9 +78,6 @@ static inline int gb_connection_enable_tx(struct gb_connection *connection)
void gb_connection_disable_rx(struct gb_connection *connection); void gb_connection_disable_rx(struct gb_connection *connection);
void gb_connection_disable(struct gb_connection *connection); void gb_connection_disable(struct gb_connection *connection);
int gb_connection_legacy_init(struct gb_connection *connection);
void gb_connection_legacy_exit(struct gb_connection *connection);
void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id, void greybus_data_rcvd(struct gb_host_device *hd, u16 cport_id,
u8 *data, size_t length); u8 *data, size_t length);
......
...@@ -9,6 +9,106 @@ ...@@ -9,6 +9,106 @@
#include "greybus.h" #include "greybus.h"
#include "legacy.h" #include "legacy.h"
#include "protocol.h"
static int legacy_connection_get_version(struct gb_connection *connection)
{
int ret;
ret = gb_protocol_get_version(connection);
if (ret) {
dev_err(&connection->hd->dev,
"%s: failed to get protocol version: %d\n",
connection->name, ret);
return ret;
}
return 0;
}
static int legacy_connection_bind_protocol(struct gb_connection *connection)
{
struct gb_protocol *protocol;
protocol = gb_protocol_get(connection->protocol_id,
connection->major,
connection->minor);
if (!protocol) {
dev_err(&connection->hd->dev,
"protocol 0x%02x version %u.%u not found\n",
connection->protocol_id,
connection->major, connection->minor);
return -EPROTONOSUPPORT;
}
connection->protocol = protocol;
return 0;
}
static void legacy_connection_unbind_protocol(struct gb_connection *connection)
{
struct gb_protocol *protocol = connection->protocol;
gb_protocol_put(protocol);
connection->protocol = NULL;
}
static int legacy_request_handler(struct gb_operation *operation)
{
struct gb_protocol *protocol = operation->connection->protocol;
return protocol->request_recv(operation->type, operation);
}
static int legacy_connection_init(struct gb_connection *connection)
{
gb_request_handler_t handler;
int ret;
ret = legacy_connection_bind_protocol(connection);
if (ret)
return ret;
if (connection->protocol->request_recv)
handler = legacy_request_handler;
else
handler = NULL;
ret = gb_connection_enable(connection, handler);
if (ret)
goto err_unbind_protocol;
ret = legacy_connection_get_version(connection);
if (ret)
goto err_disable;
ret = connection->protocol->connection_init(connection);
if (ret)
goto err_disable;
return 0;
err_disable:
gb_connection_disable(connection);
err_unbind_protocol:
legacy_connection_unbind_protocol(connection);
return ret;
}
static void legacy_connection_exit(struct gb_connection *connection)
{
if (connection->state == GB_CONNECTION_STATE_DISABLED)
return;
gb_connection_disable(connection);
connection->protocol->connection_exit(connection);
legacy_connection_unbind_protocol(connection);
}
static int legacy_probe(struct gb_bundle *bundle, static int legacy_probe(struct gb_bundle *bundle,
const struct greybus_bundle_id *id) const struct greybus_bundle_id *id)
...@@ -23,7 +123,7 @@ static int legacy_probe(struct gb_bundle *bundle, ...@@ -23,7 +123,7 @@ static int legacy_probe(struct gb_bundle *bundle,
dev_dbg(&bundle->dev, "enabling connection %s\n", dev_dbg(&bundle->dev, "enabling connection %s\n",
connection->name); connection->name);
ret = gb_connection_legacy_init(connection); ret = legacy_connection_init(connection);
if (ret) if (ret)
goto err_connections_disable; goto err_connections_disable;
} }
...@@ -33,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle, ...@@ -33,7 +133,7 @@ static int legacy_probe(struct gb_bundle *bundle,
err_connections_disable: err_connections_disable:
list_for_each_entry_reverse(connection, &bundle->connections, list_for_each_entry_reverse(connection, &bundle->connections,
bundle_links) { bundle_links) {
gb_connection_legacy_exit(connection); legacy_connection_exit(connection);
} }
return ret; return ret;
...@@ -48,7 +148,7 @@ static void legacy_disconnect(struct gb_bundle *bundle) ...@@ -48,7 +148,7 @@ static void legacy_disconnect(struct gb_bundle *bundle)
list_for_each_entry_reverse(connection, &bundle->connections, list_for_each_entry_reverse(connection, &bundle->connections,
bundle_links) { bundle_links) {
gb_connection_legacy_exit(connection); legacy_connection_exit(connection);
} }
} }
......
...@@ -141,6 +141,7 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor) ...@@ -141,6 +141,7 @@ struct gb_protocol *gb_protocol_get(u8 id, u8 major, u8 minor)
return protocol; return protocol;
} }
EXPORT_SYMBOL_GPL(gb_protocol_get);
int gb_protocol_get_version(struct gb_connection *connection) int gb_protocol_get_version(struct gb_connection *connection)
{ {
...@@ -197,3 +198,4 @@ void gb_protocol_put(struct gb_protocol *protocol) ...@@ -197,3 +198,4 @@ void gb_protocol_put(struct gb_protocol *protocol)
out: out:
spin_unlock_irq(&gb_protocols_lock); spin_unlock_irq(&gb_protocols_lock);
} }
EXPORT_SYMBOL_GPL(gb_protocol_put);
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