greybus: hd: fix svc-connection handling

Create the svc connection when registering the host-device and
remove the current svc connection hacks that "upgraded" the svc
connection once the endo id and ap interface id was known.

Note that the old implementation was partly based on a misunderstanding
as it was the remote interface id, rather than the local AP interface id,
that used to define a connection (but we also needed the endo_id).

The remote interface is no longer needed as static connections, such as
the svc connection, are now simply defined by the host-device and host
cport id.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
Johan Hovold 2015-11-25 15:59:18 +01:00 коммит произвёл Greg Kroah-Hartman
Родитель 87757e325a
Коммит 5ef323846f
6 изменённых файлов: 17 добавлений и 98 удалений

Просмотреть файл

@ -77,24 +77,6 @@ static void gb_connection_kref_release(struct kref *kref)
mutex_unlock(&connection_mutex);
}
int svc_update_connection(struct gb_interface *intf,
struct gb_connection *connection)
{
struct gb_bundle *bundle;
bundle = gb_bundle_create(intf, GB_SVC_BUNDLE_ID, GREYBUS_CLASS_SVC);
if (!bundle)
return -EINVAL;
connection->bundle = bundle;
spin_lock_irq(&gb_connections_lock);
list_add(&connection->bundle_links, &bundle->connections);
spin_unlock_irq(&gb_connections_lock);
return 0;
}
static void gb_connection_init_name(struct gb_connection *connection)
{
u16 hd_cport_id = connection->hd_cport_id;

Просмотреть файл

@ -51,9 +51,6 @@ struct gb_connection {
void *private;
};
int svc_update_connection(struct gb_interface *intf,
struct gb_connection *connection);
struct gb_connection *gb_connection_create_static(struct gb_host_device *hd,
u16 hd_cport_id, u8 protocol_id);
struct gb_connection *gb_connection_create_dynamic(struct gb_interface *intf,

Просмотреть файл

@ -98,6 +98,18 @@ struct gb_host_device *gb_hd_create(struct gb_hd_driver *driver,
}
EXPORT_SYMBOL_GPL(gb_hd_create);
static int gb_hd_create_svc_connection(struct gb_host_device *hd)
{
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");
return -ENOMEM;
}
return 0;
}
int gb_hd_add(struct gb_host_device *hd)
{
int ret;
@ -106,19 +118,10 @@ int gb_hd_add(struct gb_host_device *hd)
if (ret)
return ret;
/*
* Initialize AP's SVC protocol connection:
*
* This is required as part of early initialization of the host device
* as we need this connection in order to start any kind of message
* exchange between the AP and the SVC. SVC will start with a
* 'get-version' request followed by a 'svc-hello' message and at that
* time we will create a fully initialized svc-connection, as we need
* endo-id and AP's interface id for that.
*/
if (!gb_ap_svc_connection_create(hd)) {
ret = gb_hd_create_svc_connection(hd);
if (ret) {
device_del(&hd->dev);
return -ENOMEM;
return ret;
}
return 0;
@ -135,9 +138,7 @@ void gb_hd_del(struct gb_host_device *hd)
gb_interfaces_remove(hd);
gb_endo_remove(hd->endo);
/* Is the SVC still using the partially uninitialized connection ? */
if (hd->initial_svc_connection)
gb_connection_destroy(hd->initial_svc_connection);
gb_connection_destroy(hd->svc_connection);
device_del(&hd->dev);
}

Просмотреть файл

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

Просмотреть файл

@ -49,51 +49,6 @@ static struct attribute *svc_attrs[] = {
};
ATTRIBUTE_GROUPS(svc);
/*
* AP's SVC cport is required early to get messages from the SVC. This happens
* even before the Endo is created and hence any modules or interfaces.
*
* This is a temporary connection, used only at initial bootup.
*/
struct gb_connection *
gb_ap_svc_connection_create(struct gb_host_device *hd)
{
struct gb_connection *connection;
connection = gb_connection_create_static(hd, GB_SVC_CPORT_ID,
GREYBUS_PROTOCOL_SVC);
return connection;
}
/*
* We know endo-type and AP's interface id now, lets create a proper svc
* connection (and its interface/bundle) now and get rid of the initial
* 'partially' initialized one svc connection.
*/
static struct gb_interface *
gb_ap_interface_create(struct gb_host_device *hd,
struct gb_connection *connection, u8 interface_id)
{
struct gb_interface *intf;
struct device *dev = &hd->endo->dev;
intf = gb_interface_create(hd, interface_id);
if (!intf) {
dev_err(dev, "%s: Failed to create interface with id %hhu\n",
__func__, interface_id);
return NULL;
}
intf->device_id = GB_DEVICE_ID_AP;
svc_update_connection(intf, connection);
/* Its no longer a partially initialized connection */
hd->initial_svc_connection = NULL;
return intf;
}
static int gb_svc_intf_device_id(struct gb_svc *svc, u8 intf_id, u8 device_id)
{
struct gb_svc_intf_device_id_request request;
@ -360,7 +315,6 @@ static int gb_svc_hello(struct gb_operation *op)
struct gb_svc *svc = connection->private;
struct gb_host_device *hd = connection->hd;
struct gb_svc_hello_request *hello_request;
struct gb_interface *intf;
int ret;
/*
@ -389,16 +343,6 @@ static int gb_svc_hello(struct gb_operation *op)
if (ret)
return ret;
/*
* Endo and its modules are ready now, fix AP's partially initialized
* svc protocol and its connection.
*/
intf = gb_ap_interface_create(hd, connection, svc->ap_intf_id);
if (!intf) {
gb_endo_remove(hd->endo);
return ret;
}
return 0;
}
@ -720,9 +664,6 @@ static int gb_svc_connection_init(struct gb_connection *connection)
hd->svc = svc;
WARN_ON(connection->hd->initial_svc_connection);
connection->hd->initial_svc_connection = connection;
return 0;
}

Просмотреть файл

@ -41,6 +41,4 @@ int gb_svc_dme_peer_set(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector,
int gb_svc_protocol_init(void);
void gb_svc_protocol_exit(void);
struct gb_connection *gb_ap_svc_connection_create(struct gb_host_device *hd);
#endif /* __SVC_H */