/* XXX This could be per-host device or per-module */
static DEFINE_SPINLOCK(gb_bundles_lock);
+static int __bundle_bind_protocols(struct device *dev, void *data)
+{
+ struct gb_bundle *bundle;
+ struct gb_connection *connection;
+
+ if (!is_gb_bundle(dev))
+ return 0;
+
+ bundle = to_gb_bundle(dev);
+
+ list_for_each_entry(connection, &bundle->connections, bundle_links) {
+ gb_connection_bind_protocol(connection);
+ }
+
+ return 0;
+}
+
+/*
+ * Walk all bundles in the system, and see if any connections are not bound to a
+ * specific prototcol. If they are not, then try to find one for it and bind it
+ * to it.
+ *
+ * This is called after registering a new protocol.
+ */
+void gb_bundle_bind_protocols(void)
+{
+ bus_for_each_dev(&greybus_bus_type, NULL, NULL,
+ __bundle_bind_protocols);
+}
+
/*
* Create a gb_bundle structure to represent a discovered
* bundle. Returns a pointer to the new bundle or a null
.release = gb_connection_release,
};
+
+void gb_connection_bind_protocol(struct gb_connection *connection)
+{
+ struct gb_bundle *bundle;
+ struct gb_protocol *protocol;
+
+ /* If we already have a protocol bound here, just return */
+ if (connection->protocol)
+ return;
+
+ protocol = gb_protocol_get(connection->protocol_id,
+ connection->major,
+ connection->minor);
+ if (!protocol)
+ return;
+ connection->protocol = protocol;
+
+ /*
+ * If we have a valid device_id for the bundle, then we have an active
+ * device, so bring up the connection at the same time.
+ * */
+ bundle = connection->bundle;
+ if (bundle->device_id != 0xff)
+ gb_connection_init(connection);
+}
+
/*
* Set up a Greybus connection, representing the bidirectional link
* between a CPort on a (local) Greybus host device and a CPort on
if (!connection)
return NULL;
- /* XXX Will have to establish connections to get version */
- connection->protocol = gb_protocol_get(protocol_id, major, minor);
- if (!connection->protocol) {
- pr_err("protocol 0x%02hhx not found\n", protocol_id);
- kfree(connection);
- return NULL;
- }
+ connection->protocol_id = protocol_id;
+ connection->major = major;
+ connection->minor = minor;
hd = bundle->intf->hd;
connection->hd = hd;
return NULL;
}
+ /* XXX Will have to establish connections to get version */
+ gb_connection_bind_protocol(connection);
+ if (!connection->protocol)
+ dev_warn(&bundle->dev,
+ "protocol 0x%02hhx handler not found\n", protocol_id);
+
spin_lock_irq(&gb_connections_lock);
list_add_tail(&connection->hd_links, &hd->connections);
list_add_tail(&connection->bundle_links, &bundle->connections);
int ret;
if (!connection->protocol) {
- gb_connection_err(connection, "uninitialized connection");
- return -EIO;
+ dev_warn(&connection->dev, "init without protocol.\n");
+ return 0;
}
/* Need to enable the connection to initialize it */
void gb_connection_exit(struct gb_connection *connection)
{
if (!connection->protocol) {
- gb_connection_err(connection, "uninitialized connection");
+ dev_warn(&connection->dev, "exit without protocol.\n");
return;
}
connection->state = GB_CONNECTION_STATE_DESTROYING;