From 3c2e2266a5bd2d1cef258e6e54dca1d99946379f Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sat, 26 Mar 2016 12:28:05 -0700 Subject: [PATCH] hwmon: (max1111) Return -ENODEV from max1111_read_channel if not instantiated 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 : [] lr : [] psr: 20000013 ... [] (max1111_read_channel) from [] (sharpsl_pm_pxa_read_max1111+0x2c/0x3c) [] (sharpsl_pm_pxa_read_max1111) from [] (spitzpm_read_devdata+0x5c/0xc4) [] (spitzpm_read_devdata) from [] (sharpsl_check_battery_temp+0x78/0x110) [] (sharpsl_check_battery_temp) from [] (sharpsl_charge_toggle+0x48/0x110) [] (sharpsl_charge_toggle) from [] (process_one_work+0x14c/0x48c) [] (process_one_work) from [] (worker_thread+0x3c/0x5d4) [] (worker_thread) from [] (kthread+0xd0/0xec) [] (kthread) from [] (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 Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/max1111.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 36544c4f653c6..303d0c9df907a 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); } EXPORT_SYMBOL(max1111_read_channel); @@ -258,6 +261,9 @@ static int max1111_remove(struct spi_device *spi) { struct max1111_data *data = spi_get_drvdata(spi); +#ifdef CONFIG_SHARPSL_PM + the_max1111 = NULL; +#endif hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);