char *buf) \
{ \
struct gb_interface *intf = to_gb_interface(dev); \
- return sprintf(buf, "%"#type"\n", intf->field); \
+ return scnprintf(buf, PAGE_SIZE, "%"#type"\n", intf->field); \
} \
static DEVICE_ATTR_RO(field)
-gb_interface_attr(device_id, d);
-gb_interface_attr(vendor, x);
-gb_interface_attr(product, x);
-gb_interface_attr(unique_id, llX);
+gb_interface_attr(interface_id, u);
+gb_interface_attr(vendor_id, x);
+gb_interface_attr(product_id, x);
gb_interface_attr(vendor_string, s);
gb_interface_attr(product_string, s);
static struct attribute *interface_attrs[] = {
- &dev_attr_device_id.attr,
- &dev_attr_vendor.attr,
- &dev_attr_product.attr,
- &dev_attr_unique_id.attr,
+ &dev_attr_interface_id.attr,
+ &dev_attr_vendor_id.attr,
+ &dev_attr_product_id.attr,
&dev_attr_vendor_string.attr,
&dev_attr_product_string.attr,
NULL,
// FIXME, odds are you don't want to call this function, rework the caller to
// not need it please.
-struct gb_interface *gb_interface_find(struct greybus_host_device *hd,
+struct gb_interface *gb_interface_find(struct gb_host_device *hd,
u8 interface_id)
{
struct gb_interface *intf;
{
struct gb_interface *intf = to_gb_interface(dev);
+ kfree(intf->product_string);
+ kfree(intf->vendor_string);
+
kfree(intf);
}
};
/*
- * Create kernel structures corresponding to a bundle and connection for
- * managing control CPort. Also initialize the bundle, which will request SVC to
- * set route and will initialize the control protocol for this connection.
- */
-static int gb_create_control_connection(struct gb_interface *intf)
-{
- struct gb_bundle *bundle;
-
- bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID,
- GREYBUS_CLASS_CONTROL);
- if (!bundle)
- return -EINVAL;
-
- if (!gb_connection_create(bundle, GB_CONTROL_CPORT_ID,
- GREYBUS_PROTOCOL_CONTROL))
- return -EINVAL;
-
- return 0;
-}
-
-/*
- * A Greybus module represents a user-replicable component on an Ara
+ * A Greybus module represents a user-replaceable component on an Ara
* phone. An interface is the physical connection on that module. A
* module may have more than one interface.
*
* Returns a pointer to the new interfce or a null pointer if a
* failure occurs due to memory exhaustion.
*/
-struct gb_interface *gb_interface_create(struct greybus_host_device *hd,
+struct gb_interface *gb_interface_create(struct gb_host_device *hd,
u8 interface_id)
{
- struct gb_module *module;
struct gb_interface *intf;
int retval;
- intf = gb_interface_find(hd, interface_id);
- if (intf) {
- dev_err(hd->parent, "Duplicate interface with interface-id: %d will not be created\n",
- interface_id);
- return NULL;
- }
-
- module = gb_module_find(hd, endo_get_module_id(hd->endo, interface_id));
- if (!module)
- return NULL;
-
intf = kzalloc(sizeof(*intf), GFP_KERNEL);
if (!intf)
- goto put_module;
+ return NULL;
intf->hd = hd; /* XXX refcount? */
- intf->module = module;
intf->interface_id = interface_id;
INIT_LIST_HEAD(&intf->bundles);
INIT_LIST_HEAD(&intf->manifest_descs);
/* Invalid device id to start with */
intf->device_id = GB_DEVICE_ID_BAD;
- intf->dev.parent = &module->dev;
+ intf->dev.parent = &hd->dev;
intf->dev.bus = &greybus_bus_type;
intf->dev.type = &greybus_interface_type;
intf->dev.groups = interface_groups;
- intf->dev.dma_mask = hd->parent->dma_mask;
+ intf->dev.dma_mask = hd->dev.dma_mask;
device_initialize(&intf->dev);
- dev_set_name(&intf->dev, "%s:%d", dev_name(&module->dev), interface_id);
+ dev_set_name(&intf->dev, "%d-%d", hd->bus_id, interface_id);
retval = device_add(&intf->dev);
if (retval) {
- pr_err("failed to add interface device for id 0x%02hhx\n",
- interface_id);
+ pr_err("failed to add interface %u\n", interface_id);
goto free_intf;
}
free_intf:
put_device(&intf->dev);
- kfree(intf);
-put_module:
- put_device(&module->dev);
return NULL;
}
/*
- * Tear down a previously set up module.
+ * Tear down a previously set up interface.
*/
-static void gb_interface_destroy(struct gb_interface *intf)
+void gb_interface_remove(struct gb_interface *intf)
{
- struct gb_module *module;
struct gb_bundle *bundle;
struct gb_bundle *next;
list_for_each_entry_safe(bundle, next, &intf->bundles, links)
gb_bundle_destroy(bundle);
- kfree(intf->product_string);
- kfree(intf->vendor_string);
+ if (intf->control)
+ gb_connection_destroy(intf->control->connection);
- module = intf->module;
device_unregister(&intf->dev);
- put_device(&module->dev);
+}
+
+void gb_interfaces_remove(struct gb_host_device *hd)
+{
+ struct gb_interface *intf, *temp;
+
+ list_for_each_entry_safe(intf, temp, &hd->interfaces, links)
+ gb_interface_remove(intf);
}
/**
- * gb_interface_add
+ * gb_interface_init
*
* Create connection for control CPort and then request/parse manifest.
* Finally initialize all the bundles to set routes via SVC and initialize all
*/
int gb_interface_init(struct gb_interface *intf, u8 device_id)
{
+ struct gb_connection *connection;
int ret, size;
void *manifest;
intf->device_id = device_id;
/* Establish control CPort connection */
- ret = gb_create_control_connection(intf);
- if (ret) {
- dev_err(&intf->dev, "Failed to create control CPort connection (%d)\n", ret);
- return ret;
+ connection = gb_connection_create_dynamic(intf, NULL,
+ GB_CONTROL_CPORT_ID,
+ GREYBUS_PROTOCOL_CONTROL);
+ if (!connection) {
+ dev_err(&intf->dev, "failed to create control connection\n");
+ return -ENOMEM;
}
/* Get manifest size using control protocol on CPort */
kfree(manifest);
return ret;
}
-
-void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id)
-{
- struct gb_interface *intf = gb_interface_find(hd, interface_id);
-
- if (intf)
- gb_interface_destroy(intf);
- else
- dev_err(hd->parent, "interface id %d not found\n",
- interface_id);
-}
-
-void gb_interfaces_remove(struct greybus_host_device *hd)
-{
- struct gb_interface *intf, *temp;
-
- list_for_each_entry_safe(intf, temp, &hd->interfaces, links)
- gb_interface_destroy(intf);
-}