process watching the file will be woken up, and the new
value can be read. It's a "poor-man's IPC", yes, but
simplifies the Android userspace code immensely.
-
-What: /sys/bus/greybus/device/endoE:M:I:B:C
-Date: October 2015
-KernelVersion: 4.XX
-Contact: Greg Kroah-Hartman <greg@kroah.com>
-Description:
- A cport C within bundle B, C is replaced by a 2-byte
- number representing the cport.
-
-What: /sys/bus/greybus/device/endoE:M:I:B:C/ap_cport_id
-Date: October 2015
-KernelVersion: 4.XX
-Contact: Greg Kroah-Hartman <greg@kroah.com>
-Description:
- The cport ID of the AP, to which cport of the module is
- connected.
-
-What: /sys/bus/greybus/device/endoE:M:I:B:C/protocol_id
-Date: October 2015
-KernelVersion: 4.XX
-Contact: Greg Kroah-Hartman <greg@kroah.com>
-Description:
- The protocol ID of a Greybus cport.
-
-What: /sys/bus/greybus/device/endoE:M:I:B:C/state
-Date: October 2015
-KernelVersion: 4.XX
-Contact: Greg Kroah-Hartman <greg@kroah.com>
-Description:
- The current state of a Greybus connection.
-
- It will be one of the following values:
- 0 - invalid
- 1 - disabled
- 2 - enabled
- 3 - error
- 4 - destroying
}
EXPORT_SYMBOL_GPL(greybus_data_rcvd);
-static ssize_t state_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct gb_connection *connection = to_gb_connection(dev);
- enum gb_connection_state state;
-
- spin_lock_irq(&connection->lock);
- state = connection->state;
- spin_unlock_irq(&connection->lock);
-
- return sprintf(buf, "%d\n", state);
-}
-static DEVICE_ATTR_RO(state);
-
-static ssize_t
-protocol_id_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct gb_connection *connection = to_gb_connection(dev);
-
- if (connection->protocol)
- return sprintf(buf, "%d\n", connection->protocol->id);
- else
- return -EINVAL;
-}
-static DEVICE_ATTR_RO(protocol_id);
-
-static ssize_t
-ap_cport_id_show(struct device *dev, struct device_attribute *attr, char *buf)
-{
- struct gb_connection *connection = to_gb_connection(dev);
- return sprintf(buf, "%hu\n", connection->hd_cport_id);
-}
-static DEVICE_ATTR_RO(ap_cport_id);
-
-static struct attribute *connection_attrs[] = {
- &dev_attr_state.attr,
- &dev_attr_protocol_id.attr,
- &dev_attr_ap_cport_id.attr,
- NULL,
-};
-
-ATTRIBUTE_GROUPS(connection);
+static DEFINE_MUTEX(connection_mutex);
-static void gb_connection_release(struct device *dev)
+static void gb_connection_kref_release(struct kref *kref)
{
- struct gb_connection *connection = to_gb_connection(dev);
+ struct gb_connection *connection;
+ connection = container_of(kref, struct gb_connection, kref);
destroy_workqueue(connection->wq);
kfree(connection);
+ mutex_unlock(&connection_mutex);
}
-struct device_type greybus_connection_type = {
- .name = "greybus_connection",
- .release = gb_connection_release,
-};
-
-
int svc_update_connection(struct gb_interface *intf,
struct gb_connection *connection)
{
if (!bundle)
return -EINVAL;
- device_del(&connection->dev);
connection->bundle = bundle;
- connection->dev.parent = &bundle->dev;
- dev_set_name(&connection->dev, "%s:%d", dev_name(&bundle->dev),
- GB_SVC_CPORT_ID);
-
- WARN_ON(device_add(&connection->dev));
spin_lock_irq(&gb_connections_lock);
list_add(&connection->bundle_links, &bundle->connections);
if (!connection->wq)
goto err_free_connection;
- connection->dev.parent = parent;
- connection->dev.bus = &greybus_bus_type;
- connection->dev.type = &greybus_connection_type;
- connection->dev.groups = connection_groups;
- device_initialize(&connection->dev);
- dev_set_name(&connection->dev, "%s:%d",
- dev_name(parent), cport_id);
-
- retval = device_add(&connection->dev);
- if (retval) {
- connection->hd_cport_id = CPORT_ID_BAD;
- put_device(&connection->dev);
-
- dev_err(parent, "failed to register connection to cport %04hx: %d\n",
- cport_id, retval);
-
- goto err_remove_ida;
- }
+ kref_init(&connection->kref);
spin_lock_irq(&gb_connections_lock);
list_add(&connection->hd_links, &hd->connections);
ida_simple_remove(id_map, connection->hd_cport_id);
connection->hd_cport_id = CPORT_ID_BAD;
- device_unregister(&connection->dev);
+ kref_put_mutex(&connection->kref, gb_connection_kref_release,
+ &connection_mutex);
}
void gb_connection_latency_tag_enable(struct gb_connection *connection)