diff options
author | Guenter Roeck <guenter.roeck@ericsson.com> | 2012-04-22 23:58:51 -0400 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2012-05-20 22:41:49 -0400 |
commit | dbe43a62762d2a6430cf6ed65d3459ce1e8ed46c (patch) | |
tree | ec2d53d1747a522dd6bb2277ddea04ffe0f9a790 /drivers/hwmon | |
parent | 425d247680d050fe3ee7e53b9cf0240bf6b4b351 (diff) |
hwmon: (ntc_thermistor) Optimize and fix build warning
The following build warning is seen in some configurations:
drivers/hwmon/ntc_thermistor.c: In function 'ntc_show_temp':
drivers/hwmon/ntc_thermistor.c:293: warning: 'temp' may be used uninitialized in this function
Fix the problem by re-arranging the code to overload return values with error
codes, and by avoiding error returns whenever possible.
Specifically,
Simplify lookup_comp() to not return an error. Instead, return i_low == i_high
if there is an exact match, or if the ohm value is outside the lookup table
range.
Modify get_temp_mC() to not return an error. Since it only returns an error
after lookup_comp() returned an error, this is quite straightforward after above
change.
Separate ntc_thermistor_read() into a function to read the resistor value (which
can return an error), and the call to get_temp_mC() which doesn't. Call the
functions directly from ntc_show_temp().
Code was tested using a test program, comparing the result of the old and new
versions of get_temp_mC() for resistor values between 0 and 2,000,000 ohm.
As a side effect, this patch reduces code size by approximately 400 bytes on
x86_64.
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Cc: Donggeun Kim <dg77.kim@samsung.com>
Reviewed-by: Robert Coulson <robert.coulson@ericsson.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r-- | drivers/hwmon/ntc_thermistor.c | 164 |
1 files changed, 80 insertions, 84 deletions
diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index b31bf1d3172a..ea163866789a 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c | |||
@@ -134,8 +134,7 @@ static inline u64 div64_u64_safe(u64 dividend, u64 divisor) | |||
134 | return div64_u64(dividend, divisor); | 134 | return div64_u64(dividend, divisor); |
135 | } | 135 | } |
136 | 136 | ||
137 | static unsigned int get_ohm_of_thermistor(struct ntc_data *data, | 137 | static int get_ohm_of_thermistor(struct ntc_data *data, unsigned int uV) |
138 | unsigned int uV) | ||
139 | { | 138 | { |
140 | struct ntc_thermistor_platform_data *pdata = data->pdata; | 139 | struct ntc_thermistor_platform_data *pdata = data->pdata; |
141 | u64 mV = uV / 1000; | 140 | u64 mV = uV / 1000; |
@@ -146,12 +145,12 @@ static unsigned int get_ohm_of_thermistor(struct ntc_data *data, | |||
146 | 145 | ||
147 | if (mV == 0) { | 146 | if (mV == 0) { |
148 | if (pdata->connect == NTC_CONNECTED_POSITIVE) | 147 | if (pdata->connect == NTC_CONNECTED_POSITIVE) |
149 | return UINT_MAX; | 148 | return INT_MAX; |
150 | return 0; | 149 | return 0; |
151 | } | 150 | } |
152 | if (mV >= pmV) | 151 | if (mV >= pmV) |
153 | return (pdata->connect == NTC_CONNECTED_POSITIVE) ? | 152 | return (pdata->connect == NTC_CONNECTED_POSITIVE) ? |
154 | 0 : UINT_MAX; | 153 | 0 : INT_MAX; |
155 | 154 | ||
156 | if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0) | 155 | if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0) |
157 | N = div64_u64_safe(pdO * (pmV - mV), mV); | 156 | N = div64_u64_safe(pdO * (pmV - mV), mV); |
@@ -163,113 +162,109 @@ static unsigned int get_ohm_of_thermistor(struct ntc_data *data, | |||
163 | else | 162 | else |
164 | N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV); | 163 | N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV); |
165 | 164 | ||
166 | return (unsigned int) N; | 165 | if (N > INT_MAX) |
166 | N = INT_MAX; | ||
167 | return N; | ||
167 | } | 168 | } |
168 | 169 | ||
169 | static int lookup_comp(struct ntc_data *data, | 170 | static void lookup_comp(struct ntc_data *data, unsigned int ohm, |
170 | unsigned int ohm, int *i_low, int *i_high) | 171 | int *i_low, int *i_high) |
171 | { | 172 | { |
172 | int start, end, mid = -1; | 173 | int start, end, mid; |
174 | |||
175 | /* | ||
176 | * Handle special cases: Resistance is higher than or equal to | ||
177 | * resistance in first table entry, or resistance is lower or equal | ||
178 | * to resistance in last table entry. | ||
179 | * In these cases, return i_low == i_high, either pointing to the | ||
180 | * beginning or to the end of the table depending on the condition. | ||
181 | */ | ||
182 | if (ohm >= data->comp[0].ohm) { | ||
183 | *i_low = 0; | ||
184 | *i_high = 0; | ||
185 | return; | ||
186 | } | ||
187 | if (ohm <= data->comp[data->n_comp - 1].ohm) { | ||
188 | *i_low = data->n_comp - 1; | ||
189 | *i_high = data->n_comp - 1; | ||
190 | return; | ||
191 | } | ||
173 | 192 | ||
174 | /* Do a binary search on compensation table */ | 193 | /* Do a binary search on compensation table */ |
175 | start = 0; | 194 | start = 0; |
176 | end = data->n_comp; | 195 | end = data->n_comp; |
177 | 196 | while (start < end) { | |
178 | while (end > start) { | ||
179 | mid = start + (end - start) / 2; | 197 | mid = start + (end - start) / 2; |
180 | if (data->comp[mid].ohm < ohm) | 198 | /* |
199 | * start <= mid < end | ||
200 | * data->comp[start].ohm > ohm >= data->comp[end].ohm | ||
201 | * | ||
202 | * We could check for "ohm == data->comp[mid].ohm" here, but | ||
203 | * that is a quite unlikely condition, and we would have to | ||
204 | * check again after updating start. Check it at the end instead | ||
205 | * for simplicity. | ||
206 | */ | ||
207 | if (ohm >= data->comp[mid].ohm) { | ||
181 | end = mid; | 208 | end = mid; |
182 | else if (data->comp[mid].ohm > ohm) | ||
183 | start = mid + 1; | ||
184 | else | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | if (mid == 0) { | ||
189 | if (data->comp[mid].ohm > ohm) { | ||
190 | *i_high = mid; | ||
191 | *i_low = mid + 1; | ||
192 | return 0; | ||
193 | } else { | 209 | } else { |
194 | *i_low = mid; | 210 | start = mid + 1; |
195 | *i_high = -1; | 211 | /* |
196 | return -EINVAL; | 212 | * ohm >= data->comp[start].ohm might be true here, |
197 | } | 213 | * since we set start to mid + 1. In that case, we are |
198 | } | 214 | * done. We could keep going, but the condition is quite |
199 | if (mid == (data->n_comp - 1)) { | 215 | * likely to occur, so it is worth checking for it. |
200 | if (data->comp[mid].ohm <= ohm) { | 216 | */ |
201 | *i_low = mid; | 217 | if (ohm >= data->comp[start].ohm) |
202 | *i_high = mid - 1; | 218 | end = start; |
203 | return 0; | ||
204 | } else { | ||
205 | *i_low = -1; | ||
206 | *i_high = mid; | ||
207 | return -EINVAL; | ||
208 | } | 219 | } |
220 | /* | ||
221 | * start <= end | ||
222 | * data->comp[start].ohm >= ohm >= data->comp[end].ohm | ||
223 | */ | ||
209 | } | 224 | } |
210 | 225 | /* | |
211 | if (data->comp[mid].ohm <= ohm) { | 226 | * start == end |
212 | *i_low = mid; | 227 | * ohm >= data->comp[end].ohm |
213 | *i_high = mid - 1; | 228 | */ |
214 | } else { | 229 | *i_low = end; |
215 | *i_low = mid + 1; | 230 | if (ohm == data->comp[end].ohm) |
216 | *i_high = mid; | 231 | *i_high = end; |
217 | } | 232 | else |
218 | 233 | *i_high = end - 1; | |
219 | return 0; | ||
220 | } | 234 | } |
221 | 235 | ||
222 | static int get_temp_mC(struct ntc_data *data, unsigned int ohm, int *temp) | 236 | static int get_temp_mC(struct ntc_data *data, unsigned int ohm) |
223 | { | 237 | { |
224 | int low, high; | 238 | int low, high; |
225 | int ret; | 239 | int temp; |
226 | 240 | ||
227 | ret = lookup_comp(data, ohm, &low, &high); | 241 | lookup_comp(data, ohm, &low, &high); |
228 | if (ret) { | 242 | if (low == high) { |
229 | /* Unable to use linear approximation */ | 243 | /* Unable to use linear approximation */ |
230 | if (low != -1) | 244 | temp = data->comp[low].temp_C * 1000; |
231 | *temp = data->comp[low].temp_C * 1000; | ||
232 | else if (high != -1) | ||
233 | *temp = data->comp[high].temp_C * 1000; | ||
234 | else | ||
235 | return ret; | ||
236 | } else { | 245 | } else { |
237 | *temp = data->comp[low].temp_C * 1000 + | 246 | temp = data->comp[low].temp_C * 1000 + |
238 | ((data->comp[high].temp_C - data->comp[low].temp_C) * | 247 | ((data->comp[high].temp_C - data->comp[low].temp_C) * |
239 | 1000 * ((int)ohm - (int)data->comp[low].ohm)) / | 248 | 1000 * ((int)ohm - (int)data->comp[low].ohm)) / |
240 | ((int)data->comp[high].ohm - (int)data->comp[low].ohm); | 249 | ((int)data->comp[high].ohm - (int)data->comp[low].ohm); |
241 | } | 250 | } |
242 | 251 | return temp; | |
243 | return 0; | ||
244 | } | 252 | } |
245 | 253 | ||
246 | static int ntc_thermistor_read(struct ntc_data *data, int *temp) | 254 | static int ntc_thermistor_get_ohm(struct ntc_data *data) |
247 | { | 255 | { |
248 | int ret; | 256 | int read_uV; |
249 | int read_ohm, read_uV; | 257 | |
250 | unsigned int ohm = 0; | 258 | if (data->pdata->read_ohm) |
251 | 259 | return data->pdata->read_ohm(); | |
252 | if (data->pdata->read_ohm) { | ||
253 | read_ohm = data->pdata->read_ohm(); | ||
254 | if (read_ohm < 0) | ||
255 | return read_ohm; | ||
256 | ohm = (unsigned int)read_ohm; | ||
257 | } | ||
258 | 260 | ||
259 | if (data->pdata->read_uV) { | 261 | if (data->pdata->read_uV) { |
260 | read_uV = data->pdata->read_uV(); | 262 | read_uV = data->pdata->read_uV(); |
261 | if (read_uV < 0) | 263 | if (read_uV < 0) |
262 | return read_uV; | 264 | return read_uV; |
263 | ohm = get_ohm_of_thermistor(data, (unsigned int)read_uV); | 265 | return get_ohm_of_thermistor(data, read_uV); |
264 | } | ||
265 | |||
266 | ret = get_temp_mC(data, ohm, temp); | ||
267 | if (ret) { | ||
268 | dev_dbg(data->dev, "Sensor reading function not available.\n"); | ||
269 | return ret; | ||
270 | } | 266 | } |
271 | 267 | return -EINVAL; | |
272 | return 0; | ||
273 | } | 268 | } |
274 | 269 | ||
275 | static ssize_t ntc_show_name(struct device *dev, | 270 | static ssize_t ntc_show_name(struct device *dev, |
@@ -290,12 +285,13 @@ static ssize_t ntc_show_temp(struct device *dev, | |||
290 | struct device_attribute *attr, char *buf) | 285 | struct device_attribute *attr, char *buf) |
291 | { | 286 | { |
292 | struct ntc_data *data = dev_get_drvdata(dev); | 287 | struct ntc_data *data = dev_get_drvdata(dev); |
293 | int temp, ret; | 288 | int ohm; |
294 | 289 | ||
295 | ret = ntc_thermistor_read(data, &temp); | 290 | ohm = ntc_thermistor_get_ohm(data); |
296 | if (ret) | 291 | if (ohm < 0) |
297 | return ret; | 292 | return ohm; |
298 | return sprintf(buf, "%d\n", temp); | 293 | |
294 | return sprintf(buf, "%d\n", get_temp_mC(data, ohm)); | ||
299 | } | 295 | } |
300 | 296 | ||
301 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0); | 297 | static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0); |