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

media: gpio-ir-tx: spinlock is not needed to disable interrupts

During bit-banging the IR on a gpio pin, we cannot be scheduled or have
anything interrupt us, else the generated signal will be incorrect.
Therefore, we need to disable interrupts on the local cpu. This also
disables preemption.

local_irq_disable() does exactly what we need and does not require a
spinlock.

Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Sean Young and committed by
Mauro Carvalho Chehab
1451b932 a2e2d73f

+5 -11
+5 -11
drivers/media/rc/gpio-ir-tx.c
··· 19 19 struct gpio_desc *gpio; 20 20 unsigned int carrier; 21 21 unsigned int duty_cycle; 22 - /* we need a spinlock to hold the cpu while transmitting */ 23 - spinlock_t lock; 24 22 }; 25 23 26 24 static const struct of_device_id gpio_ir_tx_of_match[] = { ··· 51 53 static void gpio_ir_tx_unmodulated(struct gpio_ir *gpio_ir, uint *txbuf, 52 54 uint count) 53 55 { 54 - unsigned long flags; 55 56 ktime_t edge; 56 57 s32 delta; 57 58 int i; 58 59 59 - spin_lock_irqsave(&gpio_ir->lock, flags); 60 + local_irq_disable(); 60 61 61 62 edge = ktime_get(); 62 63 ··· 69 72 } 70 73 71 74 gpiod_set_value(gpio_ir->gpio, 0); 72 - 73 - spin_unlock_irqrestore(&gpio_ir->lock, flags); 74 75 } 75 76 76 77 static void gpio_ir_tx_modulated(struct gpio_ir *gpio_ir, uint *txbuf, 77 78 uint count) 78 79 { 79 - unsigned long flags; 80 80 ktime_t edge; 81 81 /* 82 82 * delta should never exceed 0.5 seconds (IR_MAX_DURATION) and on ··· 89 95 space = DIV_ROUND_CLOSEST((100 - gpio_ir->duty_cycle) * 90 96 (NSEC_PER_SEC / 100), gpio_ir->carrier); 91 97 92 - spin_lock_irqsave(&gpio_ir->lock, flags); 98 + local_irq_disable(); 93 99 94 100 edge = ktime_get(); 95 101 ··· 122 128 edge = last; 123 129 } 124 130 } 125 - 126 - spin_unlock_irqrestore(&gpio_ir->lock, flags); 127 131 } 128 132 129 133 static int gpio_ir_tx(struct rc_dev *dev, unsigned int *txbuf, 130 134 unsigned int count) 131 135 { 132 136 struct gpio_ir *gpio_ir = dev->priv; 137 + unsigned long flags; 133 138 139 + local_irq_save(flags); 134 140 if (gpio_ir->carrier) 135 141 gpio_ir_tx_modulated(gpio_ir, txbuf, count); 136 142 else 137 143 gpio_ir_tx_unmodulated(gpio_ir, txbuf, count); 144 + local_irq_restore(flags); 138 145 139 146 return count; 140 147 } ··· 171 176 172 177 gpio_ir->carrier = 38000; 173 178 gpio_ir->duty_cycle = 50; 174 - spin_lock_init(&gpio_ir->lock); 175 179 176 180 rc = devm_rc_register_device(&pdev->dev, rcdev); 177 181 if (rc < 0)