diff options
author | Jochen Friedrich <jochen@scram.de> | 2008-08-27 06:32:25 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2008-09-16 14:43:24 -0400 |
commit | f1eaf16a9e843aa915b86594b60ec6cd66c9eac7 (patch) | |
tree | 6c5caddb00117c566dd5c4a7e9eb654dfdaa6b10 /arch | |
parent | 1a9314a0f6f71cf13ddf9e58f1d4f507a5265056 (diff) |
powerpc/cpm1: Fix race condition in CPM1 GPIO library.
The CPM1 GPIO library code uses the non thread-safe clrbits32/setbits32
macros. This patch protects them with a spinlock.
Based on the CPM2 patch from Laurent Pinchart <laurentp@cse-semaphore.com>,
commit 639d64456e20cbfc866b18dc03cf9f9babc9c7cd.
Signed-off-by: Jochen Friedrich <jochen@scram.de>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/sysdev/cpm1.c | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 4a04823e8423..490473ce8103 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c | |||
@@ -546,15 +546,11 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio) | |||
546 | return !!(in_be16(&iop->dat) & pin_mask); | 546 | return !!(in_be16(&iop->dat) & pin_mask); |
547 | } | 547 | } |
548 | 548 | ||
549 | static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | 549 | static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, |
550 | int value) | ||
550 | { | 551 | { |
551 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
552 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | 552 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); |
553 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | 553 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; |
554 | unsigned long flags; | ||
555 | u16 pin_mask = 1 << (15 - gpio); | ||
556 | |||
557 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
558 | 554 | ||
559 | if (value) | 555 | if (value) |
560 | cpm1_gc->cpdata |= pin_mask; | 556 | cpm1_gc->cpdata |= pin_mask; |
@@ -562,6 +558,18 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
562 | cpm1_gc->cpdata &= ~pin_mask; | 558 | cpm1_gc->cpdata &= ~pin_mask; |
563 | 559 | ||
564 | out_be16(&iop->dat, cpm1_gc->cpdata); | 560 | out_be16(&iop->dat, cpm1_gc->cpdata); |
561 | } | ||
562 | |||
563 | static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
564 | { | ||
565 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
566 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
567 | unsigned long flags; | ||
568 | u16 pin_mask = 1 << (15 - gpio); | ||
569 | |||
570 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
571 | |||
572 | __cpm1_gpio16_set(mm_gc, pin_mask, value); | ||
565 | 573 | ||
566 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | 574 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
567 | } | 575 | } |
@@ -569,14 +577,17 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
569 | static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | 577 | static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
570 | { | 578 | { |
571 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 579 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
580 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
572 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | 581 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; |
573 | u16 pin_mask; | 582 | unsigned long flags; |
583 | u16 pin_mask = 1 << (15 - gpio); | ||
574 | 584 | ||
575 | pin_mask = 1 << (15 - gpio); | 585 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
576 | 586 | ||
577 | setbits16(&iop->dir, pin_mask); | 587 | setbits16(&iop->dir, pin_mask); |
588 | __cpm1_gpio16_set(mm_gc, pin_mask, val); | ||
578 | 589 | ||
579 | cpm1_gpio16_set(gc, gpio, val); | 590 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
580 | 591 | ||
581 | return 0; | 592 | return 0; |
582 | } | 593 | } |
@@ -584,13 +595,17 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
584 | static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) | 595 | static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) |
585 | { | 596 | { |
586 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 597 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
598 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
587 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | 599 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; |
588 | u16 pin_mask; | 600 | unsigned long flags; |
601 | u16 pin_mask = 1 << (15 - gpio); | ||
589 | 602 | ||
590 | pin_mask = 1 << (15 - gpio); | 603 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
591 | 604 | ||
592 | clrbits16(&iop->dir, pin_mask); | 605 | clrbits16(&iop->dir, pin_mask); |
593 | 606 | ||
607 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | ||
608 | |||
594 | return 0; | 609 | return 0; |
595 | } | 610 | } |
596 | 611 | ||
@@ -655,15 +670,11 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio) | |||
655 | return !!(in_be32(&iop->dat) & pin_mask); | 670 | return !!(in_be32(&iop->dat) & pin_mask); |
656 | } | 671 | } |
657 | 672 | ||
658 | static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | 673 | static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, |
674 | int value) | ||
659 | { | 675 | { |
660 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
661 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | 676 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); |
662 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | 677 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; |
663 | unsigned long flags; | ||
664 | u32 pin_mask = 1 << (31 - gpio); | ||
665 | |||
666 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
667 | 678 | ||
668 | if (value) | 679 | if (value) |
669 | cpm1_gc->cpdata |= pin_mask; | 680 | cpm1_gc->cpdata |= pin_mask; |
@@ -671,6 +682,18 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
671 | cpm1_gc->cpdata &= ~pin_mask; | 682 | cpm1_gc->cpdata &= ~pin_mask; |
672 | 683 | ||
673 | out_be32(&iop->dat, cpm1_gc->cpdata); | 684 | out_be32(&iop->dat, cpm1_gc->cpdata); |
685 | } | ||
686 | |||
687 | static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
688 | { | ||
689 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
690 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
691 | unsigned long flags; | ||
692 | u32 pin_mask = 1 << (31 - gpio); | ||
693 | |||
694 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
695 | |||
696 | __cpm1_gpio32_set(mm_gc, pin_mask, value); | ||
674 | 697 | ||
675 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | 698 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
676 | } | 699 | } |
@@ -678,14 +701,17 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | |||
678 | static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | 701 | static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) |
679 | { | 702 | { |
680 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 703 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
704 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
681 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | 705 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; |
682 | u32 pin_mask; | 706 | unsigned long flags; |
707 | u32 pin_mask = 1 << (31 - gpio); | ||
683 | 708 | ||
684 | pin_mask = 1 << (31 - gpio); | 709 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
685 | 710 | ||
686 | setbits32(&iop->dir, pin_mask); | 711 | setbits32(&iop->dir, pin_mask); |
712 | __cpm1_gpio32_set(mm_gc, pin_mask, val); | ||
687 | 713 | ||
688 | cpm1_gpio32_set(gc, gpio, val); | 714 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); |
689 | 715 | ||
690 | return 0; | 716 | return 0; |
691 | } | 717 | } |
@@ -693,13 +719,17 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | |||
693 | static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) | 719 | static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) |
694 | { | 720 | { |
695 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | 721 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); |
722 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
696 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | 723 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; |
697 | u32 pin_mask; | 724 | unsigned long flags; |
725 | u32 pin_mask = 1 << (31 - gpio); | ||
698 | 726 | ||
699 | pin_mask = 1 << (31 - gpio); | 727 | spin_lock_irqsave(&cpm1_gc->lock, flags); |
700 | 728 | ||
701 | clrbits32(&iop->dir, pin_mask); | 729 | clrbits32(&iop->dir, pin_mask); |
702 | 730 | ||
731 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | ||
732 | |||
703 | return 0; | 733 | return 0; |
704 | } | 734 | } |
705 | 735 | ||