]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/staging/greybus/manifest.c
greybus: Random spell fixes
[karo-tx-linux.git] / drivers / staging / greybus / manifest.c
index 2c3cf7486c15a73599945bfd25db73f1b5851f34..28abd2ad395e914da398246df2510622c46c6ae8 100644 (file)
@@ -46,7 +46,7 @@ static void release_manifest_descriptors(void)
 
 /*
  * Validate the given descriptor.  Its reported size must fit within
- * the number of bytes reamining, and it must have a recognized
+ * the number of bytes remaining, and it must have a recognized
  * type.  Check that the reported size is at least as big as what
  * we expect to see.  (It could be bigger, perhaps for a new version
  * of the format.)
@@ -80,13 +80,8 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size)
                        return -EINVAL;
                }
                break;
-       case GREYBUS_TYPE_DEVICE:
-               break;
-       case GREYBUS_TYPE_CLASS:
-               pr_err("class descriptor found (ignoring)\n");
-               break;
        case GREYBUS_TYPE_STRING:
-               expected_size = sizeof(struct greybus_descriptor_header);
+               expected_size = sizeof(*desc_header);
                expected_size += sizeof(struct greybus_descriptor_string);
                expected_size += (size_t)desc->string.length;
                if (desc_size < expected_size) {
@@ -95,6 +90,8 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size)
                        return -EINVAL;
                }
                break;
+       case GREYBUS_TYPE_INTERFACE:
+               break;
        case GREYBUS_TYPE_CPORT:
                if (desc_size < sizeof(struct greybus_descriptor_cport)) {
                        pr_err("cport descriptor too small (%u)\n",
@@ -102,6 +99,9 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size)
                        return -EINVAL;
                }
                break;
+       case GREYBUS_TYPE_CLASS:
+               pr_warn("class descriptor found (ignoring)\n");
+               break;
        case GREYBUS_TYPE_INVALID:
        default:
                pr_err("invalid descriptor type (%hhu)\n", desc_header->type);
@@ -113,7 +113,7 @@ static int identify_descriptor(struct greybus_descriptor *desc, size_t size)
                return -ENOMEM;
 
        descriptor->size = desc_size;
-       descriptor->data = desc;
+       descriptor->data = (u8 *)desc + sizeof(*desc_header);
        descriptor->type = desc_header->type;
        list_add_tail(&descriptor->links, &manifest_descs);
 
@@ -143,13 +143,11 @@ static char *gb_string_get(u8 string_id)
                return NULL;
 
        list_for_each_entry(descriptor, &manifest_descs, links) {
-               struct greybus_descriptor *desc;
 
                if (descriptor->type != GREYBUS_TYPE_STRING)
                        continue;
 
-               desc = descriptor->data;
-               desc_string = &desc->string;
+               desc_string = descriptor->data;
                if (desc_string->id == string_id) {
                        found = true;
                        break;
@@ -171,6 +169,49 @@ static char *gb_string_get(u8 string_id)
        return string;
 }
 
+/*
+ * Find cport descriptors in the manifest and set up data structures
+ * for the functions that use them.  Returns the number of interfaces
+ * set up for the given module, or 0 if there is an error.
+ */
+static u32 gb_manifest_parse_cports(struct gb_interface *interface)
+{
+       u32 count = 0;
+
+       while (true) {
+               struct manifest_desc *descriptor;
+               struct greybus_descriptor_cport *desc_cport;
+               u8 protocol_id;
+               u16 cport_id;
+               bool found = false;
+
+               /* Find a cport descriptor */
+               list_for_each_entry(descriptor, &manifest_descs, links) {
+                       if (descriptor->type == GREYBUS_TYPE_CPORT) {
+                               desc_cport = descriptor->data;
+                               if (desc_cport->interface == interface->id) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+               }
+               if (!found)
+                       break;
+
+               /* Found one.  Set up its function structure */
+               protocol_id = desc_cport->protocol_id;
+               cport_id = le16_to_cpu(desc_cport->id);
+               if (!gb_connection_create(interface, cport_id, protocol_id))
+                       return 0;       /* Error */
+
+               count++;
+               /* Release the cport descriptor */
+               release_manifest_descriptor(descriptor);
+       }
+
+       return count;
+}
+
 /*
  * Find interface descriptors in the manifest and set up their data
  * structures.  Returns the number of interfaces set up for the
@@ -188,7 +229,7 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod)
 
                /* Find an interface descriptor */
                list_for_each_entry(descriptor, &manifest_descs, links) {
-                       if (descriptor->type == GREYBUS_TYPE_DEVICE) {
+                       if (descriptor->type == GREYBUS_TYPE_INTERFACE) {
                                found = true;
                                break;
                        }
@@ -201,6 +242,11 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod)
                interface = gb_interface_create(gmod, desc_interface->id);
                if (!interface)
                        return 0;       /* Error */
+
+               /* Now go set up this interface's functions and cports */
+               if (!gb_manifest_parse_cports(interface))
+                       return 0;       /* Error parsing cports */
+
                count++;
 
                /* Done with this interface descriptor */
@@ -210,33 +256,25 @@ static u32 gb_manifest_parse_interfaces(struct gb_module *gmod)
        return count;
 }
 
-struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc)
+static bool gb_manifest_parse_module(struct gb_module *gmod,
+                                       struct manifest_desc *module_desc)
 {
-       struct greybus_descriptor *desc = module_desc->data;
-       struct greybus_descriptor_module *desc_module = &desc->module;
-       struct gb_module *gmod;
-
-       gmod = kzalloc(sizeof(*gmod), GFP_KERNEL);
-       if (!gmod)
-               return NULL;
+       struct greybus_descriptor_module *desc_module = module_desc->data;
 
        /* Handle the strings first--they can fail */
        gmod->vendor_string = gb_string_get(desc_module->vendor_stringid);
-       if (IS_ERR(gmod->vendor_string)) {
-               kfree(gmod);
-               return NULL;
-       }
+       if (IS_ERR(gmod->vendor_string))
+               return false;
+
        gmod->product_string = gb_string_get(desc_module->product_stringid);
        if (IS_ERR(gmod->product_string)) {
-               kfree(gmod->vendor_string);
-               kfree(gmod);
-               return NULL;
+               goto out_free_vendor_string;
        }
 
        gmod->vendor = le16_to_cpu(desc_module->vendor);
        gmod->product = le16_to_cpu(desc_module->product);
        gmod->version = le16_to_cpu(desc_module->version);
-       gmod->serial_number = le64_to_cpu(desc_module->serial_number);
+       gmod->unique_id = le64_to_cpu(desc_module->unique_id);
 
        /* Release the module descriptor, now that we're done with it */
        release_manifest_descriptor(module_desc);
@@ -244,11 +282,18 @@ struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc)
        /* A module must have at least one interface descriptor */
        if (!gb_manifest_parse_interfaces(gmod)) {
                pr_err("manifest interface descriptors not valid\n");
-               gb_module_destroy(gmod);
-               return NULL;
+               goto out_err;
        }
 
-       return gmod;
+       return true;
+out_err:
+       kfree(gmod->product_string);
+       gmod->product_string = NULL;
+out_free_vendor_string:
+       kfree(gmod->vendor_string);
+       gmod->vendor_string = NULL;
+
+       return false;
 }
 
 /*
@@ -272,25 +317,27 @@ struct gb_module *gb_manifest_parse_module(struct manifest_desc *module_desc)
  * After that we look for the module's interfaces--there must be at
  * least one of those.
  *
- * Return a pointer to an initialized gb_module structure
- * representing the content of the module manifest, or a null
- * pointer if an error occurs.
+ * Returns true if parsing was successful, false otherwise.
  */
-struct gb_module *gb_manifest_parse(void *data, size_t size)
+bool gb_manifest_parse(struct gb_module *gmod, void *data, size_t size)
 {
        struct greybus_manifest *manifest;
        struct greybus_manifest_header *header;
        struct greybus_descriptor *desc;
        struct manifest_desc *descriptor;
        struct manifest_desc *module_desc = NULL;
-       struct gb_module *gmod;
        u16 manifest_size;
        u32 found = 0;
+       bool result;
+
+       /* Manifest descriptor list should be empty here */
+       if (WARN_ON(!list_empty(&manifest_descs)))
+               return false;
 
        /* we have to have at _least_ the manifest header */
        if (size <= sizeof(manifest->header)) {
                pr_err("short manifest (%zu)\n", size);
-               return NULL;
+               return false;
        }
 
        /* Make sure the size is right */
@@ -300,7 +347,7 @@ struct gb_module *gb_manifest_parse(void *data, size_t size)
        if (manifest_size != size) {
                pr_err("manifest size mismatch %zu != %hu\n",
                        size, manifest_size);
-               return NULL;
+               return false;
        }
 
        /* Validate major/minor number */
@@ -308,7 +355,7 @@ struct gb_module *gb_manifest_parse(void *data, size_t size)
                pr_err("manifest version too new (%hhu.%hhu > %hhu.%hhu)\n",
                        header->version_major, header->version_minor,
                        GREYBUS_VERSION_MAJOR, GREYBUS_VERSION_MINOR);
-               return NULL;
+               return false;
        }
 
        /* OK, find all the descriptors */
@@ -321,7 +368,8 @@ struct gb_module *gb_manifest_parse(void *data, size_t size)
                if (desc_size <= 0) {
                        if (!desc_size)
                                pr_err("zero-sized manifest descriptor\n");
-                       goto out_err;
+                       result = false;
+                       goto out;
                }
                desc = (struct greybus_descriptor *)((char *)desc + desc_size);
                size -= desc_size;
@@ -336,24 +384,21 @@ struct gb_module *gb_manifest_parse(void *data, size_t size)
        if (found != 1) {
                pr_err("manifest must have 1 module descriptor (%u found)\n",
                        found);
-               goto out_err;
+               result = false;
+               goto out;
        }
 
        /* Parse the module manifest, starting with the module descriptor */
-       gmod = gb_manifest_parse_module(module_desc);
+       result = gb_manifest_parse_module(gmod, module_desc);
 
        /*
         * We really should have no remaining descriptors, but we
         * don't know what newer format manifests might leave.
         */
-       if (!list_empty(&manifest_descs)) {
+       if (result && !list_empty(&manifest_descs))
                pr_info("excess descriptors in module manifest\n");
-               release_manifest_descriptors();
-       }
-
-       return gmod;
-out_err:
+out:
        release_manifest_descriptors();
 
-       return NULL;
+       return result;
 }