Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Input: tsc2004/5 - use guard notation when acquiring mutexes/locks

This makes the code more compact and error handling more robust.

Link: https://lore.kernel.org/r/20240711172719.1248373-6-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+81 -101
+81 -101
drivers/input/touchscreen/tsc200x-core.c
··· 136 136 static irqreturn_t tsc200x_irq_thread(int irq, void *_ts) 137 137 { 138 138 struct tsc200x *ts = _ts; 139 - unsigned long flags; 140 139 unsigned int pressure; 141 140 struct tsc200x_data tsdata; 142 141 int error; ··· 181 182 if (unlikely(pressure > MAX_12BIT)) 182 183 goto out; 183 184 184 - spin_lock_irqsave(&ts->lock, flags); 185 - 186 - tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure); 187 - mod_timer(&ts->penup_timer, 188 - jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS)); 189 - 190 - spin_unlock_irqrestore(&ts->lock, flags); 185 + scoped_guard(spinlock_irqsave, &ts->lock) { 186 + tsc200x_update_pen_state(ts, tsdata.x, tsdata.y, pressure); 187 + mod_timer(&ts->penup_timer, 188 + jiffies + msecs_to_jiffies(TSC200X_PENUP_TIME_MS)); 189 + } 191 190 192 191 ts->last_valid_interrupt = jiffies; 193 192 out: ··· 195 198 static void tsc200x_penup_timer(struct timer_list *t) 196 199 { 197 200 struct tsc200x *ts = from_timer(ts, t, penup_timer); 198 - unsigned long flags; 199 201 200 - spin_lock_irqsave(&ts->lock, flags); 202 + guard(spinlock_irqsave)(&ts->lock); 201 203 tsc200x_update_pen_state(ts, 0, 0, 0); 202 - spin_unlock_irqrestore(&ts->lock, flags); 203 204 } 204 205 205 206 static void tsc200x_start_scan(struct tsc200x *ts) ··· 227 232 { 228 233 tsc200x_stop_scan(ts); 229 234 230 - disable_irq(ts->irq); 235 + guard(disable_irq)(&ts->irq); 236 + 231 237 del_timer_sync(&ts->penup_timer); 232 - 233 238 cancel_delayed_work_sync(&ts->esd_work); 234 - 235 - enable_irq(ts->irq); 236 239 } 237 240 238 241 /* must be called with ts->mutex held */ ··· 246 253 } 247 254 } 248 255 249 - static ssize_t tsc200x_selftest_show(struct device *dev, 250 - struct device_attribute *attr, 251 - char *buf) 256 + /* 257 + * Test TSC200X communications via temp high register. 258 + */ 259 + static int tsc200x_do_selftest(struct tsc200x *ts) 252 260 { 253 - struct tsc200x *ts = dev_get_drvdata(dev); 254 - unsigned int temp_high; 255 261 unsigned int temp_high_orig; 256 262 unsigned int temp_high_test; 257 - bool success = true; 263 + unsigned int temp_high; 258 264 int error; 259 - 260 - mutex_lock(&ts->mutex); 261 - 262 - /* 263 - * Test TSC200X communications via temp high register. 264 - */ 265 - __tsc200x_disable(ts); 266 265 267 266 error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high_orig); 268 267 if (error) { 269 - dev_warn(dev, "selftest failed: read error %d\n", error); 270 - success = false; 271 - goto out; 268 + dev_warn(ts->dev, "selftest failed: read error %d\n", error); 269 + return error; 272 270 } 273 271 274 272 temp_high_test = (temp_high_orig - 1) & MAX_12BIT; 275 273 276 274 error = regmap_write(ts->regmap, TSC200X_REG_TEMP_HIGH, temp_high_test); 277 275 if (error) { 278 - dev_warn(dev, "selftest failed: write error %d\n", error); 279 - success = false; 280 - goto out; 276 + dev_warn(ts->dev, "selftest failed: write error %d\n", error); 277 + return error; 281 278 } 282 279 283 280 error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high); 284 281 if (error) { 285 - dev_warn(dev, "selftest failed: read error %d after write\n", 286 - error); 287 - success = false; 288 - goto out; 289 - } 290 - 291 - if (temp_high != temp_high_test) { 292 - dev_warn(dev, "selftest failed: %d != %d\n", 293 - temp_high, temp_high_test); 294 - success = false; 282 + dev_warn(ts->dev, 283 + "selftest failed: read error %d after write\n", error); 284 + return error; 295 285 } 296 286 297 287 /* hardware reset */ 298 288 tsc200x_reset(ts); 299 289 300 - if (!success) 301 - goto out; 290 + if (temp_high != temp_high_test) { 291 + dev_warn(ts->dev, "selftest failed: %d != %d\n", 292 + temp_high, temp_high_test); 293 + return -EINVAL; 294 + } 302 295 303 296 /* test that the reset really happened */ 304 297 error = regmap_read(ts->regmap, TSC200X_REG_TEMP_HIGH, &temp_high); 305 298 if (error) { 306 - dev_warn(dev, "selftest failed: read error %d after reset\n", 307 - error); 308 - success = false; 309 - goto out; 299 + dev_warn(ts->dev, 300 + "selftest failed: read error %d after reset\n", error); 301 + return error; 310 302 } 311 303 312 304 if (temp_high != temp_high_orig) { 313 - dev_warn(dev, "selftest failed after reset: %d != %d\n", 305 + dev_warn(ts->dev, "selftest failed after reset: %d != %d\n", 314 306 temp_high, temp_high_orig); 315 - success = false; 307 + return -EINVAL; 316 308 } 317 309 318 - out: 319 - __tsc200x_enable(ts); 320 - mutex_unlock(&ts->mutex); 310 + return 0; 311 + } 321 312 322 - return sprintf(buf, "%d\n", success); 313 + static ssize_t tsc200x_selftest_show(struct device *dev, 314 + struct device_attribute *attr, 315 + char *buf) 316 + { 317 + struct tsc200x *ts = dev_get_drvdata(dev); 318 + int error; 319 + 320 + scoped_guard(mutex, &ts->mutex) { 321 + __tsc200x_disable(ts); 322 + 323 + error = tsc200x_do_selftest(ts); 324 + 325 + __tsc200x_enable(ts); 326 + } 327 + 328 + return sprintf(buf, "%d\n", !error); 323 329 } 324 330 325 331 static DEVICE_ATTR(selftest, S_IRUGO, tsc200x_selftest_show, NULL); ··· 360 368 int error; 361 369 unsigned int r; 362 370 363 - if (!mutex_trylock(&ts->mutex)) { 364 - /* 365 - * If the mutex is taken, it means that disable or enable is in 366 - * progress. In that case just reschedule the work. If the work 367 - * is not needed, it will be canceled by disable. 368 - */ 369 - goto reschedule; 370 - } 371 - 372 - if (time_is_after_jiffies(ts->last_valid_interrupt + 373 - msecs_to_jiffies(ts->esd_timeout))) 374 - goto out; 375 - 376 - /* We should be able to read register without disabling interrupts. */ 377 - error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r); 378 - if (!error && 379 - !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) { 380 - goto out; 381 - } 382 - 383 371 /* 384 - * If we could not read our known value from configuration register 0 385 - * then we should reset the controller as if from power-up and start 386 - * scanning again. 372 + * If the mutex is taken, it means that disable or enable is in 373 + * progress. In that case just reschedule the work. If the work 374 + * is not needed, it will be canceled by disable. 387 375 */ 388 - dev_info(ts->dev, "TSC200X not responding - resetting\n"); 376 + scoped_guard(mutex_try, &ts->mutex) { 377 + if (time_is_after_jiffies(ts->last_valid_interrupt + 378 + msecs_to_jiffies(ts->esd_timeout))) 379 + break; 389 380 390 - disable_irq(ts->irq); 391 - del_timer_sync(&ts->penup_timer); 381 + /* 382 + * We should be able to read register without disabling 383 + * interrupts. 384 + */ 385 + error = regmap_read(ts->regmap, TSC200X_REG_CFR0, &r); 386 + if (!error && 387 + !((r ^ TSC200X_CFR0_INITVALUE) & TSC200X_CFR0_RW_MASK)) { 388 + break; 389 + } 392 390 393 - tsc200x_update_pen_state(ts, 0, 0, 0); 391 + /* 392 + * If we could not read our known value from configuration 393 + * register 0 then we should reset the controller as if from 394 + * power-up and start scanning again. 395 + */ 396 + dev_info(ts->dev, "TSC200X not responding - resetting\n"); 394 397 395 - tsc200x_reset(ts); 398 + scoped_guard(disable_irq, &ts->irq) { 399 + del_timer_sync(&ts->penup_timer); 400 + tsc200x_update_pen_state(ts, 0, 0, 0); 401 + tsc200x_reset(ts); 402 + } 396 403 397 - enable_irq(ts->irq); 398 - tsc200x_start_scan(ts); 404 + tsc200x_start_scan(ts); 405 + } 399 406 400 - out: 401 - mutex_unlock(&ts->mutex); 402 - reschedule: 403 407 /* re-arm the watchdog */ 404 408 schedule_delayed_work(&ts->esd_work, 405 409 round_jiffies_relative( ··· 406 418 { 407 419 struct tsc200x *ts = input_get_drvdata(input); 408 420 409 - mutex_lock(&ts->mutex); 421 + guard(mutex)(&ts->mutex); 410 422 411 423 if (!ts->suspended) 412 424 __tsc200x_enable(ts); 413 425 414 426 ts->opened = true; 415 - 416 - mutex_unlock(&ts->mutex); 417 427 418 428 return 0; 419 429 } ··· 420 434 { 421 435 struct tsc200x *ts = input_get_drvdata(input); 422 436 423 - mutex_lock(&ts->mutex); 437 + guard(mutex)(&ts->mutex); 424 438 425 439 if (!ts->suspended) 426 440 __tsc200x_disable(ts); 427 441 428 442 ts->opened = false; 429 - 430 - mutex_unlock(&ts->mutex); 431 443 } 432 444 433 445 int tsc200x_probe(struct device *dev, int irq, const struct input_id *tsc_id, ··· 557 573 { 558 574 struct tsc200x *ts = dev_get_drvdata(dev); 559 575 560 - mutex_lock(&ts->mutex); 576 + guard(mutex)(&ts->mutex); 561 577 562 578 if (!ts->suspended && ts->opened) 563 579 __tsc200x_disable(ts); ··· 567 583 if (device_may_wakeup(dev)) 568 584 ts->wake_irq_enabled = enable_irq_wake(ts->irq) == 0; 569 585 570 - mutex_unlock(&ts->mutex); 571 - 572 586 return 0; 573 587 } 574 588 ··· 574 592 { 575 593 struct tsc200x *ts = dev_get_drvdata(dev); 576 594 577 - mutex_lock(&ts->mutex); 595 + guard(mutex)(&ts->mutex); 578 596 579 597 if (ts->wake_irq_enabled) { 580 598 disable_irq_wake(ts->irq); ··· 585 603 __tsc200x_enable(ts); 586 604 587 605 ts->suspended = false; 588 - 589 - mutex_unlock(&ts->mutex); 590 606 591 607 return 0; 592 608 }