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;
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,
}
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;
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;
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);
}
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));
};
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;
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;
/*
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;
}
hd->svc = svc;
- WARN_ON(connection->hd->initial_svc_connection);
- connection->hd->initial_svc_connection = connection;
-
return 0;
}
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 */