[PATCH] hwmon: (max1111) Return -ENODEV from max1111_read_channel if not instantiated

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


arm:pxa_defconfig can result in the following crash if the max1111 driver
is not instantiated.

Unhandled fault: page domain fault (0x01b) at 0x00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: : 1b [#1] PREEMPT ARM
Modules linked in:
CPU: 0 PID: 300 Comm: kworker/0:1 Not tainted 4.5.0-01301-g1701f680407c #10
Hardware name: SHARP Akita
Workqueue: events sharpsl_charge_toggle
task: c390a000 ti: c391e000 task.ti: c391e000
PC is at max1111_read_channel+0x20/0x30
LR is at sharpsl_pm_pxa_read_max1111+0x2c/0x3c
pc : [<c03aaab0>]    lr : [<c0024b50>]    psr: 20000013
[<c03aaab0>] (max1111_read_channel) from [<c0024b50>]
[<c0024b50>] (sharpsl_pm_pxa_read_max1111) from [<c00262e0>]
[<c00262e0>] (spitzpm_read_devdata) from [<c0024094>]
[<c0024094>] (sharpsl_check_battery_temp) from [<c0024f9c>]
[<c0024f9c>] (sharpsl_charge_toggle) from [<c004429c>]
[<c004429c>] (process_one_work) from [<c0044618>] (worker_thread+0x3c/0x5d4)
[<c0044618>] (worker_thread) from [<c004a238>] (kthread+0xd0/0xec)
[<c004a238>] (kthread) from [<c000a670>] (ret_from_fork+0x14/0x24)

This can occur because the SPI controller driver (SPI_PXA2XX) is built as
module and thus not necessarily loaded. While building SPI_PXA2XX into the
kernel would make the problem disappear, it appears prudent to ensure that
the driver is instantiated before accessing its data structures.

Cc: Arnd Bergmann <arnd@xxxxxxxx>
Signed-off-by: Guenter Roeck <linux@xxxxxxxxxxxx>
The means to read voltages from outside the driver seems broken,
but that is a different issue.

Apologies if you get this twice; may have gotten lost the first time around.

 drivers/hwmon/max1111.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
index 36544c4f653c..303d0c9df907 100644
--- a/drivers/hwmon/max1111.c
+++ b/drivers/hwmon/max1111.c
@@ -85,6 +85,9 @@ static struct max1111_data *the_max1111;
 int max1111_read_channel(int channel)
+	if (!the_max1111 || !the_max1111->spi)
+		return -ENODEV;
 	return max1111_read(&the_max1111->spi->dev, channel);
@@ -258,6 +261,9 @@ static int max1111_remove(struct spi_device *spi)
 	struct max1111_data *data = spi_get_drvdata(spi);
+	the_max1111 = NULL;
 	sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group);
 	sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);

lm-sensors mailing list

[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux