in manifest.c [228:305]
static u32 gb_manifest_parse_cports(struct gb_bundle *bundle)
{
struct gb_interface *intf = bundle->intf;
struct greybus_descriptor_cport *desc_cport;
struct manifest_desc *desc, *next, *tmp;
LIST_HEAD(list);
u8 bundle_id = bundle->id;
u16 cport_id;
u32 count = 0;
int i;
/* Set up all cport descriptors associated with this bundle */
list_for_each_entry_safe(desc, next, &intf->manifest_descs, links) {
if (desc->type != GREYBUS_TYPE_CPORT)
continue;
desc_cport = desc->data;
if (desc_cport->bundle != bundle_id)
continue;
cport_id = le16_to_cpu(desc_cport->id);
if (cport_id > CPORT_ID_MAX)
goto exit;
/* Nothing else should have its cport_id as control cport id */
if (cport_id == GB_CONTROL_CPORT_ID) {
dev_err(&bundle->dev, "invalid cport id found (%02u)\n",
cport_id);
goto exit;
}
/*
* Found one, move it to our temporary list after checking for
* duplicates.
*/
list_for_each_entry(tmp, &list, links) {
desc_cport = tmp->data;
if (cport_id == le16_to_cpu(desc_cport->id)) {
dev_err(&bundle->dev,
"duplicate CPort %u found\n", cport_id);
goto exit;
}
}
list_move_tail(&desc->links, &list);
count++;
}
if (!count)
return 0;
bundle->cport_desc = kcalloc(count, sizeof(*bundle->cport_desc),
GFP_KERNEL);
if (!bundle->cport_desc)
goto exit;
bundle->num_cports = count;
i = 0;
list_for_each_entry_safe(desc, next, &list, links) {
desc_cport = desc->data;
memcpy(&bundle->cport_desc[i++], desc_cport,
sizeof(*desc_cport));
/* Release the cport descriptor */
release_manifest_descriptor(desc);
}
return count;
exit:
release_cport_descriptors(&list, bundle_id);
/*
* Free all cports for this bundle to avoid 'excess descriptors'
* warnings.
*/
release_cport_descriptors(&intf->manifest_descs, bundle_id);
return 0; /* Error; count should also be 0 */
}