From patchwork Sun Aug 7 23:31:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guenter Roeck X-Patchwork-Id: 9266581 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 403FF60754 for ; Sun, 7 Aug 2016 23:32:07 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 248DD2624C for ; Sun, 7 Aug 2016 23:32:07 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 01FB827BE5; Sun, 7 Aug 2016 23:32:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 68FFB2624C for ; Sun, 7 Aug 2016 23:32:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751937AbcHGXcF (ORCPT ); Sun, 7 Aug 2016 19:32:05 -0400 Received: from bh-25.webhostbox.net ([208.91.199.152]:55547 "EHLO bh-25.webhostbox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751936AbcHGXcE (ORCPT ); Sun, 7 Aug 2016 19:32:04 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=roeck-us.net; s=default; h=Message-Id:Date:Subject:Cc:To:From; bh=4hQGpqVXS/2ml7kioDY4SDlYluJ/bWY/cKASVE//Mz0=; b=nPDCSTSeKhbe0DHfXThVHJkgta H4n3GYm0JcTmUeSWuWY76hNJbVh8zcg1/GjAR6KvqFQpMnujRdugEXRusd02+hN2qaVNS3xgwZIyL qQD6BAKQtckLa/GVkKSssT0jRdlO0RdRLeGUzZW9n0B6+A7lXmFApCkx9YgX2pp4t0CtxUe0wg4nk 1qXztpM5yXBQS1BoqcJOHO5aZXZ6NZNC8RY/v7hO9BCHchO4e+2GIRgPEl1V3o1md/AwWkXBpv6nW DkLMHVDJ8vdpsZTr+Ps7Fr8+UWG1JVM+S2EcN6V4MgeotLIpFP8pLRXDjZPB965zEwxpZsTijm2/8 nIKVE9cA==; Received: from 108-223-40-66.lightspeed.sntcca.sbcglobal.net ([108.223.40.66]:42010 helo=localhost) by bh-25.webhostbox.net with esmtpa (Exim 4.86_1) (envelope-from ) id 1bWXY2-003b5a-H6; Sun, 07 Aug 2016 23:32:02 +0000 From: Guenter Roeck To: Jean Delvare Cc: linux-hwmon@vger.kernel.org, linux-kernel@vger.kernel.org, Guenter Roeck Subject: [PATCH 1/6] hwmon: (lm95241) Fix overflow problems, write conversion rate to chip Date: Sun, 7 Aug 2016 16:31:55 -0700 Message-Id: <1470612720-30165-1-git-send-email-linux@roeck-us.net> X-Mailer: git-send-email 2.5.0 X-Authenticated_sender: guenter@roeck-us.net X-OutGoing-Spam-Status: No, score=-1.0 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - bh-25.webhostbox.net X-AntiAbuse: Original Domain - vger.kernel.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - roeck-us.net X-Get-Message-Sender-Via: bh-25.webhostbox.net: authenticated_id: guenter@roeck-us.net X-Authenticated-Sender: bh-25.webhostbox.net: guenter@roeck-us.net X-Source: X-Source-Args: X-Source-Dir: Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Writing the update_interval attribute could result in an overflow if a number close to the maximum unsigned long was written. At the same time, even though the chip supports setting the conversion rate, the selected conversion rate was not actually written to the chip. Fix the second problem by selecting valid (supported) conversion rates, and writing the selected conversion rate to the chip. This also fixes the first problem, since arbitrary conversion rates are now converted to actually supported conversion rates. Also, set the default chip conversion rate to 1 second. Previously, the chip was configured for continuous conversion, but readings were only retrieved every seond, which doesn't make much sense. If we only read a value from the chip every second, we can as well save some power and only convert in one-second intervals. Signed-off-by: Guenter Roeck --- drivers/hwmon/lm95241.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index cdf19adaec79..a8cf666fe661 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -59,6 +59,7 @@ static const unsigned short normal_i2c[] = { #define CFG_CR0182 0x10 #define CFG_CR1000 0x20 #define CFG_CR2700 0x30 +#define CFG_CRMASK 0x30 #define R1MS_SHIFT 0 #define R2MS_SHIFT 2 #define R1MS_MASK (0x01 << (R1MS_SHIFT)) @@ -91,7 +92,8 @@ static const u8 lm95241_reg_address[] = { struct lm95241_data { struct i2c_client *client; struct mutex update_lock; - unsigned long last_updated, interval; /* in jiffies */ + unsigned long last_updated; /* in jiffies */ + unsigned long interval; /* in milli-seconds */ char valid; /* zero until following fields are valid */ /* registers values */ u8 temp[ARRAY_SIZE(lm95241_reg_address)]; @@ -118,7 +120,8 @@ static struct lm95241_data *lm95241_update_device(struct device *dev) mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + data->interval) || + if (time_after(jiffies, data->last_updated + + msecs_to_jiffies(data->interval)) || !data->valid) { int i; @@ -276,8 +279,7 @@ static ssize_t show_interval(struct device *dev, struct device_attribute *attr, { struct lm95241_data *data = lm95241_update_device(dev); - return snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval - / HZ); + return snprintf(buf, PAGE_SIZE - 1, "%lu\n", data->interval); } static ssize_t set_interval(struct device *dev, struct device_attribute *attr, @@ -285,11 +287,35 @@ static ssize_t set_interval(struct device *dev, struct device_attribute *attr, { struct lm95241_data *data = dev_get_drvdata(dev); unsigned long val; + int convrate; + u8 config; if (kstrtoul(buf, 10, &val) < 0) return -EINVAL; - data->interval = val * HZ / 1000; + mutex_lock(&data->update_lock); + + config = data->config & ~CFG_CRMASK; + + if (val < 130) { + convrate = 76; + config |= CFG_CR0076; + } else if (val < 590) { + convrate = 182; + config |= CFG_CR0182; + } else if (val < 1850) { + convrate = 1000; + config |= CFG_CR1000; + } else { + convrate = 2700; + config |= CFG_CR2700; + } + + data->interval = convrate; + data->config = config; + i2c_smbus_write_byte_data(data->client, LM95241_REG_RW_CONFIG, + config); + mutex_unlock(&data->update_lock); return count; } @@ -362,8 +388,8 @@ static int lm95241_detect(struct i2c_client *new_client, static void lm95241_init_client(struct i2c_client *client, struct lm95241_data *data) { - data->interval = HZ; /* 1 sec default */ - data->config = CFG_CR0076; + data->interval = 1000; + data->config = CFG_CR1000; data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config);