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

cpm2: Fix race condition in CPM2 GPIO library.

The CPM2 GPIO library code uses the non thread-safe clrbits32/setbits32
macros. This patch protects them with a spinlock.

Signed-off-by: Laurent Pinchart <laurentp@cse-semaphore.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Laurent Pinchart and committed by
Kumar Gala
639d6445 61a4e9e9

+36 -21
+36 -21
arch/powerpc/sysdev/cpm_common.c
··· 254 254 return !!(in_be32(&iop->dat) & pin_mask); 255 255 } 256 256 257 + static void __cpm2_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, 258 + int value) 259 + { 260 + struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); 261 + struct cpm2_ioports __iomem *iop = mm_gc->regs; 262 + 263 + if (value) 264 + cpm2_gc->cpdata |= pin_mask; 265 + else 266 + cpm2_gc->cpdata &= ~pin_mask; 267 + 268 + out_be32(&iop->dat, cpm2_gc->cpdata); 269 + } 270 + 257 271 static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) 272 + { 273 + struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 274 + struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); 275 + unsigned long flags; 276 + u32 pin_mask = 1 << (31 - gpio); 277 + 278 + spin_lock_irqsave(&cpm2_gc->lock, flags); 279 + 280 + __cpm2_gpio32_set(mm_gc, pin_mask, value); 281 + 282 + spin_unlock_irqrestore(&cpm2_gc->lock, flags); 283 + } 284 + 285 + static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 258 286 { 259 287 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 260 288 struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); ··· 292 264 293 265 spin_lock_irqsave(&cpm2_gc->lock, flags); 294 266 295 - if (value) 296 - cpm2_gc->cpdata |= pin_mask; 297 - else 298 - cpm2_gc->cpdata &= ~pin_mask; 299 - 300 - out_be32(&iop->dat, cpm2_gc->cpdata); 267 + setbits32(&iop->dir, pin_mask); 268 + __cpm2_gpio32_set(mm_gc, pin_mask, val); 301 269 302 270 spin_unlock_irqrestore(&cpm2_gc->lock, flags); 303 - } 304 - 305 - static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 306 - { 307 - struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 308 - struct cpm2_ioports __iomem *iop = mm_gc->regs; 309 - u32 pin_mask; 310 - 311 - pin_mask = 1 << (31 - gpio); 312 - 313 - setbits32(&iop->dir, pin_mask); 314 - 315 - cpm2_gpio32_set(gc, gpio, val); 316 271 317 272 return 0; 318 273 } ··· 303 292 static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) 304 293 { 305 294 struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); 295 + struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); 306 296 struct cpm2_ioports __iomem *iop = mm_gc->regs; 307 - u32 pin_mask; 297 + unsigned long flags; 298 + u32 pin_mask = 1 << (31 - gpio); 308 299 309 - pin_mask = 1 << (31 - gpio); 300 + spin_lock_irqsave(&cpm2_gc->lock, flags); 310 301 311 302 clrbits32(&iop->dir, pin_mask); 303 + 304 + spin_unlock_irqrestore(&cpm2_gc->lock, flags); 312 305 313 306 return 0; 314 307 }