From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933127Ab1KCMJD (ORCPT ); Thu, 3 Nov 2011 08:09:03 -0400 Received: from cantor2.suse.de ([195.135.220.15]:47646 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932747Ab1KCMJC (ORCPT ); Thu, 3 Nov 2011 08:09:02 -0400 Date: Thu, 03 Nov 2011 13:09:00 +0100 Message-ID: From: Takashi Iwai To: Eric Piel Cc: Andrew Morton , linux-kernel@vger.kernel.org Subject: [PATCH] lis3lv02d: Avoid zero-division User-Agent: Wanderlust/2.15.6 (Almost Unreal) SEMI/1.14.6 (Maruoka) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.7 Emacs/23.3 (x86_64-suse-linux-gnu) MULE/6.0 (HANACHIRUSATO) MIME-Version: 1.0 (generated by SEMI 1.14.6 - "Maruoka") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In some weird situation, HP DriveGuard chip can't read ODR value correctly, and it results in a zero-division Oops in lis3lv02d driver. This patch fixes the Oops by checking the value appopriately, and skips if any weird value is read. Cc: Signed-off-by: Takashi Iwai --- drivers/misc/lis3lv02d/lis3lv02d.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index 8b51cd6..c4eb2f3 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c @@ -228,6 +228,14 @@ static int lis3lv02d_set_odr(int rate) return -EINVAL; } +static void lis3lv02d_power_delay(struct lis3lv02d *lis3) +{ + int odr = lis3lv02d_get_odr(); + if (odr <= 0) + return; + msleep(lis3->pwron_delay / odr); +} + static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) { u8 ctlreg, reg; @@ -266,7 +274,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) lis3->read(lis3, ctlreg, ®); lis3->write(lis3, ctlreg, (reg | selftest)); - msleep(lis3->pwron_delay / lis3lv02d_get_odr()); + lis3lv02d_power_delay(lis3); /* Read directly to avoid axis remap */ x = lis3->read_data(lis3, OUTX); @@ -275,7 +283,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3]) /* back to normal settings */ lis3->write(lis3, ctlreg, reg); - msleep(lis3->pwron_delay / lis3lv02d_get_odr()); + lis3lv02d_power_delay(lis3); results[0] = x - lis3->read_data(lis3, OUTX); results[1] = y - lis3->read_data(lis3, OUTY); @@ -385,7 +393,7 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3) } /* LIS3 power on delay is quite long */ - msleep(lis3->pwron_delay / lis3lv02d_get_odr()); + lis3lv02d_power_delay(lis3); if (lis3->reg_ctrl) lis3_context_restore(lis3); -- 1.7.7