hwmon:qpnp-adc: Set adc_drv to NULL on error
Set the adc_drv to NULL during probe error before
we exit. Not setting the adc_drv to NULL can cause
panic on conditions when adc requests are made when
an error occured during probe. Fix it by setting the
adc_drv to NULL since we have checks in the adc read
requests. Also add the adc_drv is valid check in the
work scheduler to ensure against conditions of
receiving an interrupt immediately when a irq_request
is made during probe initialization.
Change-Id: I5d921a67306bb9e401dbe798599c200d9f8eed28
Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 760b164..0290335 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -175,6 +175,9 @@
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
+ if (!iadc || !iadc->iadc_initialized)
+ return;
+
complete(&iadc->adc->adc_rslt_completion);
return;
@@ -727,7 +730,8 @@
GFP_KERNEL);
if (!adc_qpnp) {
dev_err(&spmi->dev, "Unable to allocate memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto fail;
}
iadc->adc = adc_qpnp;
@@ -735,14 +739,14 @@
rc = qpnp_adc_get_devicetree_data(spmi, iadc->adc);
if (rc) {
dev_err(&spmi->dev, "failed to read device tree\n");
- return rc;
+ goto fail;
}
rc = of_property_read_u32(node, "qcom,rsense",
&iadc->rsense);
if (rc) {
pr_err("Invalid rsens reference property\n");
- return -EINVAL;
+ goto fail;
}
rc = devm_request_irq(&spmi->dev, iadc->adc->adc_irq_eoc,
@@ -750,7 +754,7 @@
IRQF_TRIGGER_RISING, "qpnp_iadc_interrupt", iadc);
if (rc) {
dev_err(&spmi->dev, "failed to request adc irq\n");
- return rc;
+ goto fail;
} else
enable_irq_wake(iadc->adc->adc_irq_eoc);
@@ -761,20 +765,20 @@
rc = qpnp_iadc_init_hwmon(spmi);
if (rc) {
dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
- return rc;
+ goto fail;
}
iadc->iadc_hwmon = hwmon_device_register(&iadc->adc->spmi->dev);
rc = qpnp_iadc_version_check();
if (rc) {
dev_err(&spmi->dev, "IADC version not supported\n");
- return rc;
+ goto fail;
}
rc = qpnp_iadc_calibrate_for_trim();
if (rc) {
dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
- return rc;
+ goto fail;
}
iadc->iadc_init_calib = true;
INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
@@ -784,6 +788,9 @@
iadc->iadc_initialized = true;
return 0;
+fail:
+ adc_qpnp = NULL;
+ return rc;
}
static int __devexit qpnp_iadc_remove(struct spmi_device *spmi)