/** * struct minidump_region - Minidump region * @name : Name of the region to be dumped * @seq_num: : Use to differentiate regions with same name. * @valid : This entry to be dumped (if set to 1) * @address : Physical address of region to be dumped * @size : Size of the region
*/ struct minidump_region { char name[MAX_REGION_NAME_LENGTH];
__le32 seq_num;
__le32 valid;
__le64 address;
__le64 size;
};
/** * struct minidump_subsystem - Subsystem's SMEM Table of content * @status : Subsystem toc init status * @enabled : if set to 1, this region would be copied during coredump * @encryption_status: Encryption status for this subsystem * @encryption_required : Decides to encrypt the subsystem regions or not * @region_count : Number of regions added in this subsystem toc * @regions_baseptr : regions base pointer of the subsystem
*/ struct minidump_subsystem {
__le32 status;
__le32 enabled;
__le32 encryption_status;
__le32 encryption_required;
__le32 region_count;
__le64 regions_baseptr;
};
/** * struct minidump_global_toc - Global Table of Content * @status : Global Minidump init status * @md_revision : Minidump revision * @enabled : Minidump enable status * @subsystems : Array of subsystems toc
*/ struct minidump_global_toc {
__le32 status;
__le32 md_revision;
__le32 enabled; struct minidump_subsystem subsystems[MAX_NUM_OF_SS];
};
/* Get Global minidump ToC*/
toc = qcom_smem_get(QCOM_SMEM_HOST_ANY, SBL_MINIDUMP_SMEM_ID, NULL);
/* check if global table pointer exists and init is set */ if (IS_ERR(toc) || !toc->status) {
dev_err(&rproc->dev, "Minidump TOC not found in SMEM\n"); return;
}
/* Get subsystem table of contents using the minidump id */
subsystem = &toc->subsystems[minidump_id];
/** * Collect minidump if SS ToC is valid and segment table * is initialized in memory and encryption status is set.
*/ if (subsystem->regions_baseptr == 0 ||
le32_to_cpu(subsystem->status) != 1 ||
le32_to_cpu(subsystem->enabled) != MINIDUMP_SS_ENABLED) { return rproc_coredump(rproc);
}
if (le32_to_cpu(subsystem->encryption_status) != MINIDUMP_SS_ENCR_DONE) {
dev_err(&rproc->dev, "Minidump not ready, skipping\n"); return;
}
/** * Clear out the dump segments populated by parse_fw before * re-populating them with minidump segments.
*/
rproc_coredump_cleanup(rproc);
ret = qcom_add_minidump_segments(rproc, subsystem, rproc_dumpfn_t); if (ret) {
dev_err(&rproc->dev, "Failed with error: %d while adding minidump entries\n", ret); goto clean_minidump;
}
rproc_coredump_using_sections(rproc);
clean_minidump:
qcom_minidump_cleanup(rproc);
}
EXPORT_SYMBOL_GPL(qcom_minidump);
/** * qcom_add_glink_subdev() - try to add a GLINK subdevice to rproc * @rproc: rproc handle to parent the subdevice * @glink: reference to a GLINK subdev context * @ssr_name: identifier of the associated remoteproc for ssr notifications
*/ void qcom_add_glink_subdev(struct rproc *rproc, struct qcom_rproc_glink *glink, constchar *ssr_name)
{ struct device *dev = &rproc->dev;
glink->node = of_get_child_by_name(dev->parent->of_node, "glink-edge"); if (!glink->node) return;
glink->ssr_name = kstrdup_const(ssr_name, GFP_KERNEL); if (!glink->ssr_name) return;
mutex_lock(&qcom_ssr_subsys_lock); /* Match in the global qcom_ssr_subsystem_list with name */
list_for_each_entry(info, &qcom_ssr_subsystem_list, list) if (!strcmp(info->name, name)) goto out;
info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) {
info = ERR_PTR(-ENOMEM); goto out;
}
info->name = kstrdup_const(name, GFP_KERNEL);
srcu_init_notifier_head(&info->notifier_list);
/* Add to global notification list */
list_add_tail(&info->list, &qcom_ssr_subsystem_list);
/** * qcom_register_ssr_notifier() - register SSR notification handler * @name: Subsystem's SSR name * @nb: notifier_block to be invoked upon subsystem's state change * * This registers the @nb notifier block as part the notifier chain for a * remoteproc associated with @name. The notifier block's callback * will be invoked when the remote processor's SSR events occur * (pre/post startup and pre/post shutdown). * * Return: a subsystem cookie on success, ERR_PTR on failure.
*/ void *qcom_register_ssr_notifier(constchar *name, struct notifier_block *nb)
{ struct qcom_ssr_subsystem *info;
info = qcom_ssr_get_subsys(name); if (IS_ERR(info)) return info;
/** * qcom_unregister_ssr_notifier() - unregister SSR notification handler * @notify: subsystem cookie returned from qcom_register_ssr_notifier * @nb: notifier_block to unregister * * This function will unregister the notifier from the particular notifier * chain. * * Return: 0 on success, %ENOENT otherwise.
*/ int qcom_unregister_ssr_notifier(void *notify, struct notifier_block *nb)
{ return srcu_notifier_chain_unregister(notify, nb);
}
EXPORT_SYMBOL_GPL(qcom_unregister_ssr_notifier);
/** * qcom_add_ssr_subdev() - register subdevice as restart notification source * @rproc: rproc handle * @ssr: SSR subdevice handle * @ssr_name: identifier to use for notifications originating from @rproc * * As the @ssr is registered with the @rproc SSR events will be sent to all * registered listeners for the remoteproc when it's SSR events occur * (pre/post startup and pre/post shutdown).
*/ void qcom_add_ssr_subdev(struct rproc *rproc, struct qcom_rproc_ssr *ssr, constchar *ssr_name)
{ struct qcom_ssr_subsystem *info;
info = qcom_ssr_get_subsys(ssr_name); if (IS_ERR(info)) {
dev_err(&rproc->dev, "Failed to add ssr subdevice\n"); return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.