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

iio: dummy: Use automatic lock and direct mode cleanup.

Given we now have iio_device_claim_direct_scoped() to perform automatic
releasing of direct mode at exit from the scope that follows it, this can
be used in conjunction with guard(mutex) etc remove a lot of special case
handling.

Note that in this particular example code, there is no real reason you can't
read channels via sysfs at the same time as filling the software buffer.
To make it look more like a real driver constrain raw and processed
channel reads from occurring whilst the buffer is in use.

Reviewed-by: David Lechner <dlechner@baylibre.com>
Reviewed-by: Nuno Sa <nuno.a@analog.com>
Link: https://lore.kernel.org/r/20240128150537.44592-3-jic23@kernel.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

+93 -100
+93 -100
drivers/iio/dummy/iio_simple_dummy.c
··· 283 283 long mask) 284 284 { 285 285 struct iio_dummy_state *st = iio_priv(indio_dev); 286 - int ret = -EINVAL; 287 286 288 - mutex_lock(&st->lock); 289 287 switch (mask) { 290 288 case IIO_CHAN_INFO_RAW: /* magic value - channel value read */ 291 - switch (chan->type) { 292 - case IIO_VOLTAGE: 293 - if (chan->output) { 294 - /* Set integer part to cached value */ 295 - *val = st->dac_val; 296 - ret = IIO_VAL_INT; 297 - } else if (chan->differential) { 298 - if (chan->channel == 1) 299 - *val = st->differential_adc_val[0]; 300 - else 301 - *val = st->differential_adc_val[1]; 302 - ret = IIO_VAL_INT; 303 - } else { 304 - *val = st->single_ended_adc_val; 305 - ret = IIO_VAL_INT; 306 - } 307 - break; 308 - case IIO_ACCEL: 309 - *val = st->accel_val; 310 - ret = IIO_VAL_INT; 311 - break; 312 - default: 313 - break; 314 - } 315 - break; 316 - case IIO_CHAN_INFO_PROCESSED: 317 - switch (chan->type) { 318 - case IIO_STEPS: 319 - *val = st->steps; 320 - ret = IIO_VAL_INT; 321 - break; 322 - case IIO_ACTIVITY: 323 - switch (chan->channel2) { 324 - case IIO_MOD_RUNNING: 325 - *val = st->activity_running; 326 - ret = IIO_VAL_INT; 327 - break; 328 - case IIO_MOD_WALKING: 329 - *val = st->activity_walking; 330 - ret = IIO_VAL_INT; 331 - break; 289 + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { 290 + guard(mutex)(&st->lock); 291 + switch (chan->type) { 292 + case IIO_VOLTAGE: 293 + if (chan->output) { 294 + /* Set integer part to cached value */ 295 + *val = st->dac_val; 296 + return IIO_VAL_INT; 297 + } else if (chan->differential) { 298 + if (chan->channel == 1) 299 + *val = st->differential_adc_val[0]; 300 + else 301 + *val = st->differential_adc_val[1]; 302 + return IIO_VAL_INT; 303 + } else { 304 + *val = st->single_ended_adc_val; 305 + return IIO_VAL_INT; 306 + } 307 + 308 + case IIO_ACCEL: 309 + *val = st->accel_val; 310 + return IIO_VAL_INT; 332 311 default: 333 - break; 312 + return -EINVAL; 334 313 } 335 - break; 336 - default: 337 - break; 338 314 } 339 - break; 315 + unreachable(); 316 + case IIO_CHAN_INFO_PROCESSED: 317 + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { 318 + guard(mutex)(&st->lock); 319 + switch (chan->type) { 320 + case IIO_STEPS: 321 + *val = st->steps; 322 + return IIO_VAL_INT; 323 + case IIO_ACTIVITY: 324 + switch (chan->channel2) { 325 + case IIO_MOD_RUNNING: 326 + *val = st->activity_running; 327 + return IIO_VAL_INT; 328 + case IIO_MOD_WALKING: 329 + *val = st->activity_walking; 330 + return IIO_VAL_INT; 331 + default: 332 + return -EINVAL; 333 + } 334 + default: 335 + return -EINVAL; 336 + } 337 + } 338 + unreachable(); 340 339 case IIO_CHAN_INFO_OFFSET: 341 340 /* only single ended adc -> 7 */ 342 341 *val = 7; 343 - ret = IIO_VAL_INT; 344 - break; 342 + return IIO_VAL_INT; 345 343 case IIO_CHAN_INFO_SCALE: 346 344 switch (chan->type) { 347 345 case IIO_VOLTAGE: ··· 348 350 /* only single ended adc -> 0.001333 */ 349 351 *val = 0; 350 352 *val2 = 1333; 351 - ret = IIO_VAL_INT_PLUS_MICRO; 352 - break; 353 + return IIO_VAL_INT_PLUS_MICRO; 353 354 case 1: 354 355 /* all differential adc -> 0.000001344 */ 355 356 *val = 0; 356 357 *val2 = 1344; 357 - ret = IIO_VAL_INT_PLUS_NANO; 358 + return IIO_VAL_INT_PLUS_NANO; 359 + default: 360 + return -EINVAL; 358 361 } 359 - break; 360 362 default: 361 - break; 363 + return -EINVAL; 362 364 } 363 - break; 364 - case IIO_CHAN_INFO_CALIBBIAS: 365 + case IIO_CHAN_INFO_CALIBBIAS: { 366 + guard(mutex)(&st->lock); 365 367 /* only the acceleration axis - read from cache */ 366 368 *val = st->accel_calibbias; 367 - ret = IIO_VAL_INT; 368 - break; 369 - case IIO_CHAN_INFO_CALIBSCALE: 369 + return IIO_VAL_INT; 370 + } 371 + case IIO_CHAN_INFO_CALIBSCALE: { 372 + guard(mutex)(&st->lock); 370 373 *val = st->accel_calibscale->val; 371 374 *val2 = st->accel_calibscale->val2; 372 - ret = IIO_VAL_INT_PLUS_MICRO; 373 - break; 375 + return IIO_VAL_INT_PLUS_MICRO; 376 + } 374 377 case IIO_CHAN_INFO_SAMP_FREQ: 375 378 *val = 3; 376 379 *val2 = 33; 377 - ret = IIO_VAL_INT_PLUS_NANO; 378 - break; 379 - case IIO_CHAN_INFO_ENABLE: 380 + return IIO_VAL_INT_PLUS_NANO; 381 + case IIO_CHAN_INFO_ENABLE: { 382 + guard(mutex)(&st->lock); 380 383 switch (chan->type) { 381 384 case IIO_STEPS: 382 385 *val = st->steps_enabled; 383 - ret = IIO_VAL_INT; 384 - break; 386 + return IIO_VAL_INT; 385 387 default: 386 - break; 388 + return -EINVAL; 387 389 } 388 - break; 389 - case IIO_CHAN_INFO_CALIBHEIGHT: 390 + } 391 + case IIO_CHAN_INFO_CALIBHEIGHT: { 392 + guard(mutex)(&st->lock); 390 393 switch (chan->type) { 391 394 case IIO_STEPS: 392 395 *val = st->height; 393 - ret = IIO_VAL_INT; 394 - break; 396 + return IIO_VAL_INT; 395 397 default: 396 - break; 398 + return -EINVAL; 397 399 } 398 - break; 399 - 400 - default: 401 - break; 402 400 } 403 - mutex_unlock(&st->lock); 404 - return ret; 401 + default: 402 + return -EINVAL; 403 + } 405 404 } 406 405 407 406 /** ··· 421 426 long mask) 422 427 { 423 428 int i; 424 - int ret = 0; 425 429 struct iio_dummy_state *st = iio_priv(indio_dev); 426 430 427 431 switch (mask) { ··· 430 436 if (chan->output == 0) 431 437 return -EINVAL; 432 438 433 - /* Locking not required as writing single value */ 434 - mutex_lock(&st->lock); 435 - st->dac_val = val; 436 - mutex_unlock(&st->lock); 439 + scoped_guard(mutex, &st->lock) { 440 + /* Locking not required as writing single value */ 441 + st->dac_val = val; 442 + } 437 443 return 0; 438 444 default: 439 445 return -EINVAL; ··· 441 447 case IIO_CHAN_INFO_PROCESSED: 442 448 switch (chan->type) { 443 449 case IIO_STEPS: 444 - mutex_lock(&st->lock); 445 - st->steps = val; 446 - mutex_unlock(&st->lock); 450 + scoped_guard(mutex, &st->lock) { 451 + st->steps = val; 452 + } 447 453 return 0; 448 454 case IIO_ACTIVITY: 449 455 if (val < 0) ··· 464 470 default: 465 471 return -EINVAL; 466 472 } 467 - case IIO_CHAN_INFO_CALIBSCALE: 468 - mutex_lock(&st->lock); 473 + case IIO_CHAN_INFO_CALIBSCALE: { 474 + guard(mutex)(&st->lock); 469 475 /* Compare against table - hard matching here */ 470 476 for (i = 0; i < ARRAY_SIZE(dummy_scales); i++) 471 477 if (val == dummy_scales[i].val && 472 478 val2 == dummy_scales[i].val2) 473 479 break; 474 480 if (i == ARRAY_SIZE(dummy_scales)) 475 - ret = -EINVAL; 476 - else 477 - st->accel_calibscale = &dummy_scales[i]; 478 - mutex_unlock(&st->lock); 479 - return ret; 481 + return -EINVAL; 482 + st->accel_calibscale = &dummy_scales[i]; 483 + return 0; 484 + } 480 485 case IIO_CHAN_INFO_CALIBBIAS: 481 - mutex_lock(&st->lock); 482 - st->accel_calibbias = val; 483 - mutex_unlock(&st->lock); 486 + scoped_guard(mutex, &st->lock) { 487 + st->accel_calibbias = val; 488 + } 484 489 return 0; 485 490 case IIO_CHAN_INFO_ENABLE: 486 491 switch (chan->type) { 487 492 case IIO_STEPS: 488 - mutex_lock(&st->lock); 489 - st->steps_enabled = val; 490 - mutex_unlock(&st->lock); 493 + scoped_guard(mutex, &st->lock) { 494 + st->steps_enabled = val; 495 + } 491 496 return 0; 492 497 default: 493 498 return -EINVAL;