aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJochen Friedrich <jochen@scram.de>2008-08-27 06:32:25 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-09-16 14:43:24 -0400
commitf1eaf16a9e843aa915b86594b60ec6cd66c9eac7 (patch)
tree6c5caddb00117c566dd5c4a7e9eb654dfdaa6b10 /arch
parent1a9314a0f6f71cf13ddf9e58f1d4f507a5265056 (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.c74
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
549static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) 549static 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
563static 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)
569static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 577static 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)
584static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) 595static 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
658static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) 673static 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
687static 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)
678static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 701static 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)
693static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) 719static 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