Move validation of line handle flags into helper function. This reduces the size and complexity of linehandle_create and allows the validation to be reused elsewhere.
Unified · Split
| @@ -428,6 +428,54 @@ struct linehandle_state { · 427 unmodified lines | ||
| 428 | 428 | GPIOHANDLE_REQUEST_OPEN_DRAIN | \ |
| 429 | 429 | GPIOHANDLE_REQUEST_OPEN_SOURCE) |
| 430 | 430 | |
| 431 | +static int linehandle_validate_flags(u32 flags) | |
| 432 | +{ | |
| 433 | + /* Return an error if an unknown flag is set */ | |
| 434 | + if (flags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) | |
| 435 | + return -EINVAL; | |
| 436 | + | |
| 437 | + /* | |
| 438 | + * Do not allow both INPUT & OUTPUT flags to be set as they are | |
| 439 | + * contradictory. | |
| 440 | + */ | |
| 441 | + if ((flags & GPIOHANDLE_REQUEST_INPUT) && | |
| 442 | + (flags & GPIOHANDLE_REQUEST_OUTPUT)) | |
| 443 | + return -EINVAL; | |
| 444 | + | |
| 445 | + /* | |
| 446 | + * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If | |
| 447 | + * the hardware actually supports enabling both at the same time the | |
| 448 | + * electrical result would be disastrous. | |
| 449 | + */ | |
| 450 | + if ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) && | |
| 451 | + (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) | |
| 452 | + return -EINVAL; | |
| 453 | + | |
| 454 | + /* OPEN_DRAIN and OPEN_SOURCE flags only make sense for output mode. */ | |
| 455 | + if (!(flags & GPIOHANDLE_REQUEST_OUTPUT) && | |
| 456 | + ((flags & GPIOHANDLE_REQUEST_OPEN_DRAIN) || | |
| 457 | + (flags & GPIOHANDLE_REQUEST_OPEN_SOURCE))) | |
| 458 | + return -EINVAL; | |
| 459 | + | |
| 460 | + /* Bias flags only allowed for input or output mode. */ | |
| 461 | + if (!((flags & GPIOHANDLE_REQUEST_INPUT) || | |
| 462 | + (flags & GPIOHANDLE_REQUEST_OUTPUT)) && | |
| 463 | + ((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) || | |
| 464 | + (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) || | |
| 465 | + (flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN))) | |
| 466 | + return -EINVAL; | |
| 467 | + | |
| 468 | + /* Only one bias flag can be set. */ | |
| 469 | + if (((flags & GPIOHANDLE_REQUEST_BIAS_DISABLE) && | |
| 470 | + (flags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | | |
| 471 | + GPIOHANDLE_REQUEST_BIAS_PULL_UP))) || | |
| 472 | + ((flags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) && | |
| 473 | + (flags & GPIOHANDLE_REQUEST_BIAS_PULL_UP))) | |
| 474 | + return -EINVAL; | |
| 475 | + | |
| 476 | + return 0; | |
| 477 | +} | |
| 478 | + | |
| 431 | 479 | static long linehandle_ioctl(struct file *filep, unsigned int cmd, |
| 432 | 480 | unsigned long arg) |
| 433 | 481 | { |
| @@ -529,48 +577,9 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) · 95 unmodified lines | ||
| 529 | 577 | |
| 530 | 578 | lflags = handlereq.flags; |
| 531 | 579 | |
| 532 | − /* Return an error if an unknown flag is set */ | |
| 533 | − if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) | |
| 534 | − return -EINVAL; | |
| 535 | − | |
| 536 | − /* | |
| 537 | − * Do not allow both INPUT & OUTPUT flags to be set as they are | |
| 538 | − * contradictory. | |
| 539 | − */ | |
| 540 | − if ((lflags & GPIOHANDLE_REQUEST_INPUT) && | |
| 541 | − (lflags & GPIOHANDLE_REQUEST_OUTPUT)) | |
| 542 | − return -EINVAL; | |
| 543 | − | |
| 544 | − /* | |
| 545 | − * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If | |
| 546 | − * the hardware actually supports enabling both at the same time the | |
| 547 | − * electrical result would be disastrous. | |
| 548 | − */ | |
| 549 | − if ((lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) && | |
| 550 | − (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) | |
| 551 | − return -EINVAL; | |
| 552 | − | |
| 553 | − /* OPEN_DRAIN and OPEN_SOURCE flags only make sense for output mode. */ | |
| 554 | − if (!(lflags & GPIOHANDLE_REQUEST_OUTPUT) && | |
| 555 | − ((lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) || | |
| 556 | − (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE))) | |
| 557 | − return -EINVAL; | |
| 558 | − | |
| 559 | − /* Bias flags only allowed for input or output mode. */ | |
| 560 | − if (!((lflags & GPIOHANDLE_REQUEST_INPUT) || | |
| 561 | − (lflags & GPIOHANDLE_REQUEST_OUTPUT)) && | |
| 562 | − ((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) || | |
| 563 | − (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP) || | |
| 564 | − (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN))) | |
| 565 | − return -EINVAL; | |
| 566 | − | |
| 567 | − /* Only one bias flag can be set. */ | |
| 568 | − if (((lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE) && | |
| 569 | − (lflags & (GPIOHANDLE_REQUEST_BIAS_PULL_DOWN | | |
| 570 | − GPIOHANDLE_REQUEST_BIAS_PULL_UP))) || | |
| 571 | − ((lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN) && | |
| 572 | − (lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP))) | |
| 573 | − return -EINVAL; | |
| 580 | + ret = linehandle_validate_flags(lflags); | |
| 581 | + if (ret) | |
| 582 | + return ret; | |
| 574 | 583 | |
| 575 | 584 | lh = kzalloc(sizeof(*lh), GFP_KERNEL); |
| 576 | 585 | if (!lh) |