Skip to content

Commit 2727cf9

Browse files
jwrdegoedeksacilotto
authored andcommitted
misc: lis3lv02d: Fix false-positive WARN on various HP models
BugLink: https://bugs.launchpad.net/bugs/1929615 commit 3641762 upstream. Before this commit lis3lv02d_get_pwron_wait() had a WARN_ONCE() to catch a potential divide by 0. WARN macros should only be used to catch internal kernel bugs and that is not the case here. We have been receiving a lot of bug reports about kernel backtraces caused by this WARN. The div value being checked comes from the lis3->odrs[] array. Which is sized to be a power-of-2 matching the number of bits in lis3->odr_mask. The only lis3 model where this array is not entirely filled with non zero values. IOW the only model where we can hit the div == 0 check is the 3dc ("8 bits 3DC sensor") model: int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000}; Note the 0 value at index 0, according to the datasheet an odr index of 0 means "Power-down mode". HP typically uses a lis3 accelerometer for HDD fall protection. What I believe is happening here is that on newer HP devices, which only contain a SDD, the BIOS is leaving the lis3 device powered-down since it is not used for HDD fall protection. Note that the lis3_3dc_rates array initializer only specifies 10 values, which matches the datasheet. So it also contains 6 zero values at the end. Replace the WARN with a normal check, which treats an odr index of 0 as power-down and uses a normal dev_err() to report the error in case odr index point past the initialized part of the array. Fixes: 1510dd5 ("lis3lv02d: avoid divide by zero due to unchecked") Cc: [email protected] Signed-off-by: Hans de Goede <[email protected]> BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=785814 BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1817027 BugLink: https://bugs.centos.org/view.php?id=10720 Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Kamal Mostafa <[email protected]> Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
1 parent 0a1b664 commit 2727cf9

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

drivers/misc/lis3lv02d/lis3lv02d.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,23 +208,31 @@ static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
208208
static int lis3_3dlh_rates[4] = {50, 100, 400, 1000};
209209

210210
/* ODR is Output Data Rate */
211-
static int lis3lv02d_get_odr(struct lis3lv02d *lis3)
211+
static int lis3lv02d_get_odr_index(struct lis3lv02d *lis3)
212212
{
213213
u8 ctrl;
214214
int shift;
215215

216216
lis3->read(lis3, CTRL_REG1, &ctrl);
217217
ctrl &= lis3->odr_mask;
218218
shift = ffs(lis3->odr_mask) - 1;
219-
return lis3->odrs[(ctrl >> shift)];
219+
return (ctrl >> shift);
220220
}
221221

222222
static int lis3lv02d_get_pwron_wait(struct lis3lv02d *lis3)
223223
{
224-
int div = lis3lv02d_get_odr(lis3);
224+
int odr_idx = lis3lv02d_get_odr_index(lis3);
225+
int div = lis3->odrs[odr_idx];
225226

226-
if (WARN_ONCE(div == 0, "device returned spurious data"))
227+
if (div == 0) {
228+
if (odr_idx == 0) {
229+
/* Power-down mode, not sampling no need to sleep */
230+
return 0;
231+
}
232+
233+
dev_err(&lis3->pdev->dev, "Error unknown odrs-index: %d\n", odr_idx);
227234
return -ENXIO;
235+
}
228236

229237
/* LIS3 power on delay is quite long */
230238
msleep(lis3->pwron_delay / div);
@@ -807,9 +815,12 @@ static ssize_t lis3lv02d_rate_show(struct device *dev,
807815
struct device_attribute *attr, char *buf)
808816
{
809817
struct lis3lv02d *lis3 = dev_get_drvdata(dev);
818+
int odr_idx;
810819

811820
lis3lv02d_sysfs_poweron(lis3);
812-
return sprintf(buf, "%d\n", lis3lv02d_get_odr(lis3));
821+
822+
odr_idx = lis3lv02d_get_odr_index(lis3);
823+
return sprintf(buf, "%d\n", lis3->odrs[odr_idx]);
813824
}
814825

815826
static ssize_t lis3lv02d_rate_set(struct device *dev,

0 commit comments

Comments
 (0)