greybus: svc: create svc along with host device

Create svc device along with host-device and move the svc-connection to
the svc structure.

The svc connection is enabled when registering the host device, but as
the SVC protocol is currently driven by the SVC, we need to defer
registration of the svc device to the connection request handler.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Reviewed-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Johan Hovold 2015-12-07 15:05:37 +01:00 committed by Greg Kroah-Hartman
parent 2c848944c1
commit 7adeaae713
4 changed files with 70 additions and 26 deletions

View File

@ -21,8 +21,8 @@ static void gb_hd_release(struct device *dev)
{
struct gb_host_device *hd = to_gb_host_device(dev);
if (hd->svc_connection)
gb_connection_destroy(hd->svc_connection);
if (hd->svc)
gb_svc_put(hd->svc);
ida_simple_remove(&gb_hd_bus_id_map, hd->bus_id);
ida_destroy(&hd->cport_id_map);
kfree(hd);
@ -95,10 +95,9 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver,
device_initialize(&hd->dev);
dev_set_name(&hd->dev, "greybus%d", hd->bus_id);
hd->svc_connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID,
GREYBUS_PROTOCOL_SVC);
if (!hd->svc_connection) {
dev_err(&hd->dev, "failed to create svc connection\n");
hd->svc = gb_svc_create(hd);
if (!hd->svc) {
dev_err(&hd->dev, "failed to create svc\n");
put_device(&hd->dev);
return ERR_PTR(-ENOMEM);
}
@ -115,7 +114,7 @@ int gb_hd_add(struct gb_host_device *hd)
if (ret)
return ret;
ret = gb_connection_init(hd->svc_connection);
ret = gb_svc_add(hd->svc);
if (ret) {
device_del(&hd->dev);
return ret;
@ -129,7 +128,7 @@ void gb_hd_del(struct gb_host_device *hd)
{
gb_interfaces_remove(hd);
gb_connection_exit(hd->svc_connection);
gb_svc_del(hd->svc);
device_del(&hd->dev);
}

View File

@ -41,8 +41,6 @@ struct gb_host_device {
size_t buffer_size_max;
struct gb_svc *svc;
struct gb_connection *svc_connection;
/* Private data for the host driver */
unsigned long hd_priv[0] __aligned(sizeof(s64));
};

View File

@ -661,6 +661,8 @@ static void gb_svc_release(struct device *dev)
{
struct gb_svc *svc = to_gb_svc(dev);
if (svc->connection)
gb_connection_destroy(svc->connection);
ida_destroy(&svc->device_id_map);
destroy_workqueue(svc->wq);
kfree(svc);
@ -671,19 +673,18 @@ struct device_type greybus_svc_type = {
.release = gb_svc_release,
};
static int gb_svc_connection_init(struct gb_connection *connection)
struct gb_svc *gb_svc_create(struct gb_host_device *hd)
{
struct gb_host_device *hd = connection->hd;
struct gb_svc *svc;
svc = kzalloc(sizeof(*svc), GFP_KERNEL);
if (!svc)
return -ENOMEM;
return NULL;
svc->wq = alloc_workqueue("%s:svc", WQ_UNBOUND, 1, dev_name(&hd->dev));
if (!svc->wq) {
kfree(svc);
return -ENOMEM;
return NULL;
}
svc->dev.parent = &hd->dev;
@ -697,11 +698,60 @@ static int gb_svc_connection_init(struct gb_connection *connection)
ida_init(&svc->device_id_map);
svc->state = GB_SVC_STATE_RESET;
svc->connection = connection;
svc->hd = hd;
connection->private = svc;
hd->svc = svc;
svc->connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID,
GREYBUS_PROTOCOL_SVC);
if (!svc->connection) {
dev_err(&svc->dev, "failed to create connection\n");
put_device(&svc->dev);
return NULL;
}
svc->connection->private = svc;
return svc;
}
int gb_svc_add(struct gb_svc *svc)
{
int ret;
/*
* The SVC protocol is currently driven by the SVC, so the SVC device
* is added from the connection request handler when enough
* information has been received.
*/
ret = gb_connection_init(svc->connection);
if (ret)
return ret;
return 0;
}
void gb_svc_del(struct gb_svc *svc)
{
/*
* The SVC device may have been registered from the request handler.
*/
if (device_is_registered(&svc->dev))
device_del(&svc->dev);
gb_connection_exit(svc->connection);
flush_workqueue(svc->wq);
}
void gb_svc_put(struct gb_svc *svc)
{
put_device(&svc->dev);
}
static int gb_svc_connection_init(struct gb_connection *connection)
{
struct gb_svc *svc = connection->private;
dev_dbg(&svc->dev, "%s\n", __func__);
return 0;
}
@ -710,15 +760,7 @@ static void gb_svc_connection_exit(struct gb_connection *connection)
{
struct gb_svc *svc = connection->private;
if (device_is_registered(&svc->dev))
device_del(&svc->dev);
flush_workqueue(svc->wq);
connection->hd->svc = NULL;
connection->private = NULL;
put_device(&svc->dev);
dev_dbg(&svc->dev, "%s\n", __func__);
}
static struct gb_protocol svc_protocol = {

View File

@ -30,6 +30,11 @@ struct gb_svc {
};
#define to_gb_svc(d) container_of(d, struct gb_svc, d)
struct gb_svc *gb_svc_create(struct gb_host_device *hd);
int gb_svc_add(struct gb_svc *svc);
void gb_svc_del(struct gb_svc *svc);
void gb_svc_put(struct gb_svc *svc);
int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id);
int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id,
u8 intf2_id, u16 cport2_id, bool boot_over_unipro);