From 7bd132d9798b36da42ff0c5ef2958c1b1c034b4b Mon Sep 17 00:00:00 2001 From: Meghana Ashok Date: Thu, 13 Apr 2017 16:03:18 +0530 Subject: [PATCH] soc: qcom: pil: Use subsys_set_error to indicate firmware errors Use subsys_set_error() to indicate invalid firmware image that prevented subsystem from coming up. Userspace helper applications will find this useful to take suitable recovery action. Change-Id: Ie03e4f2652692f30d32bbe80b39fb49ba95ea728 Signed-off-by: Meghana Ashok [fixed minor conflicts] Signed-off-by: Srivatsa Vaddagiri --- drivers/soc/qcom/peripheral-loader.c | 13 ++++++++++++- drivers/soc/qcom/peripheral-loader.h | 1 + drivers/soc/qcom/pil-q6v5-mss.c | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c index 3415338a1294..ed8006cacc08 100644 --- a/drivers/soc/qcom/peripheral-loader.c +++ b/drivers/soc/qcom/peripheral-loader.c @@ -66,6 +66,7 @@ static int proxy_timeout_ms = -1; module_param(proxy_timeout_ms, int, S_IRUGO | S_IWUSR); static bool disable_timeouts; +static const char firmware_error_msg[] = "firmware_error\n"; /** * struct pil_mdt - Representation of .mdt file in memory * @hdr: ELF32 header @@ -673,12 +674,14 @@ static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg) if (ret < 0) { pil_err(desc, "Failed to locate blob %s or blob is too big(rc:%d)\n", fw_name, ret); + subsys_set_error(desc->subsys_dev, firmware_error_msg); return ret; } if (ret != seg->filesz) { pil_err(desc, "Blob size %u doesn't match %lu\n", ret, seg->filesz); + subsys_set_error(desc->subsys_dev, firmware_error_msg); return -EPERM; } ret = 0; @@ -707,9 +710,11 @@ static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg) if (desc->ops->verify_blob) { ret = desc->ops->verify_blob(desc, seg->paddr, seg->sz); - if (ret) + if (ret) { pil_err(desc, "Blob%u failed verification(rc:%d)\n", num, ret); + subsys_set_error(desc->subsys_dev, firmware_error_msg); + } } return ret; @@ -790,6 +795,7 @@ int pil_boot(struct pil_desc *desc) if (fw->size < sizeof(*ehdr)) { pil_err(desc, "Not big enough to be an elf header\n"); + subsys_set_error(desc->subsys_dev, firmware_error_msg); ret = -EIO; goto release_fw; } @@ -799,18 +805,21 @@ int pil_boot(struct pil_desc *desc) if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) { pil_err(desc, "Not an elf header\n"); + subsys_set_error(desc->subsys_dev, firmware_error_msg); ret = -EIO; goto release_fw; } if (ehdr->e_phnum == 0) { pil_err(desc, "No loadable segments\n"); + subsys_set_error(desc->subsys_dev, firmware_error_msg); ret = -EIO; goto release_fw; } if (sizeof(struct elf32_phdr) * ehdr->e_phnum + sizeof(struct elf32_hdr) > fw->size) { pil_err(desc, "Program headers not within mdt\n"); + subsys_set_error(desc->subsys_dev, firmware_error_msg); ret = -EIO; goto release_fw; } @@ -830,6 +839,7 @@ int pil_boot(struct pil_desc *desc) ret = desc->ops->init_image(desc, fw->data, fw->size); if (ret) { pil_err(desc, "Initializing image failed(rc:%d)\n", ret); + subsys_set_error(desc->subsys_dev, firmware_error_msg); goto err_boot; } @@ -887,6 +897,7 @@ int pil_boot(struct pil_desc *desc) ret = desc->ops->auth_and_reset(desc); if (ret) { pil_err(desc, "Failed to bring out of reset(rc:%d)\n", ret); + subsys_set_error(desc->subsys_dev, firmware_error_msg); goto err_auth_and_reset; } pil_info(desc, "Brought out of reset\n"); diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h index 9521cf726069..0cd2aeae1edd 100644 --- a/drivers/soc/qcom/peripheral-loader.h +++ b/drivers/soc/qcom/peripheral-loader.h @@ -44,6 +44,7 @@ struct pil_desc { const char *name; const char *fw_name; struct device *dev; + struct subsys_device *subsys_dev; const struct pil_reset_ops *ops; struct module *owner; unsigned long proxy_timeout; diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c index 793edc5b67ed..bbcff5923c53 100644 --- a/drivers/soc/qcom/pil-q6v5-mss.c +++ b/drivers/soc/qcom/pil-q6v5-mss.c @@ -222,6 +222,7 @@ static int pil_subsys_init(struct modem_data *drv, goto err_subsys; } + drv->q6->desc.subsys_dev = drv->subsys; drv->ramdump_dev = create_ramdump_device("modem", &pdev->dev); if (!drv->ramdump_dev) { pr_err("%s: Unable to create a modem ramdump device.\n",