Commit 5dda7e5a authored by Johan Hovold's avatar Johan Hovold Committed by Greg Kroah-Hartman

greybus: legacy: add legacy-protocol bundle driver

Add the first Greybus bundle driver that will be used when transitioning
from legacy Greybus protocols to bundle drivers.

The legacy-protocol driver initially binds to all current bundle classes.

In order to avoid having to update current module-loading scripts, keep
this driver internal to greybus core at least until modalias support is
added. Note that this prevents unloading any protocol drivers without
first tearing down the host device due to a circular module dependency.
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 5b032710
...@@ -9,7 +9,8 @@ greybus-y := core.o \ ...@@ -9,7 +9,8 @@ greybus-y := core.o \
control.o \ control.o \
svc.o \ svc.o \
firmware.o \ firmware.o \
operation.o operation.o \
legacy.o
gb-phy-y := gpbridge.o \ gb-phy-y := gpbridge.o \
sdio.o \ sdio.o \
......
...@@ -152,21 +152,11 @@ int gb_bundle_add(struct gb_bundle *bundle) ...@@ -152,21 +152,11 @@ int gb_bundle_add(struct gb_bundle *bundle)
return 0; return 0;
} }
static void gb_bundle_connections_exit(struct gb_bundle *bundle)
{
struct gb_connection *connection;
list_for_each_entry(connection, &bundle->connections, bundle_links)
gb_connection_exit(connection);
}
/* /*
* Tear down a previously set up bundle. * Tear down a previously set up bundle.
*/ */
void gb_bundle_destroy(struct gb_bundle *bundle) void gb_bundle_destroy(struct gb_bundle *bundle)
{ {
gb_bundle_connections_exit(bundle);
if (device_is_registered(&bundle->dev)) if (device_is_registered(&bundle->dev))
device_del(&bundle->dev); device_del(&bundle->dev);
......
...@@ -464,6 +464,7 @@ int gb_connection_init(struct gb_connection *connection) ...@@ -464,6 +464,7 @@ int gb_connection_init(struct gb_connection *connection)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(gb_connection_init);
void gb_connection_exit(struct gb_connection *connection) void gb_connection_exit(struct gb_connection *connection)
{ {
...@@ -482,6 +483,7 @@ void gb_connection_exit(struct gb_connection *connection) ...@@ -482,6 +483,7 @@ void gb_connection_exit(struct gb_connection *connection)
gb_connection_unbind_protocol(connection); gb_connection_unbind_protocol(connection);
} }
EXPORT_SYMBOL_GPL(gb_connection_exit);
/* /*
* Tear down a previously set up connection. * Tear down a previously set up connection.
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#define CREATE_TRACE_POINTS #define CREATE_TRACE_POINTS
#include "greybus.h" #include "greybus.h"
#include "greybus_trace.h" #include "greybus_trace.h"
#include "legacy.h"
EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send); EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_send);
EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv); EXPORT_TRACEPOINT_SYMBOL_GPL(gb_host_device_recv);
...@@ -240,8 +241,16 @@ static int __init gb_init(void) ...@@ -240,8 +241,16 @@ static int __init gb_init(void)
goto error_firmware; goto error_firmware;
} }
retval = gb_legacy_init();
if (retval) {
pr_err("gb_legacy_init failed\n");
goto error_legacy;
}
return 0; /* Success */ return 0; /* Success */
error_legacy:
gb_firmware_protocol_exit();
error_firmware: error_firmware:
gb_svc_protocol_exit(); gb_svc_protocol_exit();
error_svc: error_svc:
...@@ -261,6 +270,7 @@ module_init(gb_init); ...@@ -261,6 +270,7 @@ module_init(gb_init);
static void __exit gb_exit(void) static void __exit gb_exit(void)
{ {
gb_legacy_exit();
gb_firmware_protocol_exit(); gb_firmware_protocol_exit();
gb_svc_protocol_exit(); gb_svc_protocol_exit();
gb_control_protocol_exit(); gb_control_protocol_exit();
......
...@@ -183,7 +183,6 @@ void gb_interfaces_remove(struct gb_host_device *hd) ...@@ -183,7 +183,6 @@ void gb_interfaces_remove(struct gb_host_device *hd)
int gb_interface_init(struct gb_interface *intf, u8 device_id) int gb_interface_init(struct gb_interface *intf, u8 device_id)
{ {
struct gb_bundle *bundle, *tmp; struct gb_bundle *bundle, *tmp;
struct gb_connection *connection;
int ret, size; int ret, size;
void *manifest; void *manifest;
...@@ -242,15 +241,6 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) ...@@ -242,15 +241,6 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id)
gb_bundle_destroy(bundle); gb_bundle_destroy(bundle);
continue; continue;
} }
list_for_each_entry(connection, &bundle->connections,
bundle_links) {
ret = gb_connection_init(connection);
if (ret)
break;
}
if (ret)
gb_bundle_destroy(bundle);
} }
ret = 0; ret = 0;
......
/*
* Greybus legacy-protocol driver
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#include "greybus.h"
#include "legacy.h"
static int legacy_probe(struct gb_bundle *bundle,
const struct greybus_bundle_id *id)
{
struct gb_connection *connection;
int ret;
dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__,
bundle->class);
list_for_each_entry(connection, &bundle->connections, bundle_links) {
dev_dbg(&bundle->dev, "enabling connection %s\n",
connection->name);
ret = gb_connection_init(connection);
if (ret)
goto err_connections_disable;
}
return 0;
err_connections_disable:
list_for_each_entry_reverse(connection, &bundle->connections,
bundle_links) {
gb_connection_exit(connection);
}
return ret;
}
static void legacy_disconnect(struct gb_bundle *bundle)
{
struct gb_connection *connection;
dev_dbg(&bundle->dev, "%s - bundle class = 0x%02x\n", __func__,
bundle->class);
list_for_each_entry_reverse(connection, &bundle->connections,
bundle_links) {
gb_connection_exit(connection);
}
}
static const struct greybus_bundle_id legacy_id_table[] = {
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_HID) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_POWER_SUPPLY) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_DISPLAY) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SENSOR) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LIGHTS) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_VIBRATOR) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_LOOPBACK) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_MGMT) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_AUDIO_DATA) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SVC) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_FIRMWARE) },
{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_RAW) },
{ }
};
MODULE_DEVICE_TABLE(greybus, legacy_id_table);
static struct greybus_driver legacy_driver = {
.name = "legacy",
.probe = legacy_probe,
.disconnect = legacy_disconnect,
.id_table = legacy_id_table,
};
int gb_legacy_init(void)
{
return greybus_register(&legacy_driver);
}
void gb_legacy_exit(void)
{
greybus_deregister(&legacy_driver);
}
/*
* Greybus legacy-protocol driver
*
* Copyright 2015 Google Inc.
* Copyright 2015 Linaro Ltd.
*
* Released under the GPLv2 only.
*/
#ifndef __LEGACY_H
#define __LEGACY_H
int gb_legacy_init(void);
void gb_legacy_exit(void);
#endif /* __LEGACY_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