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

Input: iforce - use guard notation when acquiring mutex and spinlock

Using guard notation makes the code more compact and error handling
more robust by ensuring that locks are released in all code paths
when control leaves critical section.

Link: https://lore.kernel.org/r/20240904043104.1030257-4-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

+65 -83
+22 -26
drivers/input/joystick/iforce/iforce-ff.c
··· 21 21 unsigned char data[3]; 22 22 23 23 if (!no_alloc) { 24 - mutex_lock(&iforce->mem_mutex); 25 - if (allocate_resource(&(iforce->device_memory), mod_chunk, 2, 26 - iforce->device_memory.start, iforce->device_memory.end, 2L, 27 - NULL, NULL)) { 28 - mutex_unlock(&iforce->mem_mutex); 24 + guard(mutex)(&iforce->mem_mutex); 25 + 26 + if (allocate_resource(&iforce->device_memory, mod_chunk, 2, 27 + iforce->device_memory.start, 28 + iforce->device_memory.end, 29 + 2L, NULL, NULL)) 29 30 return -ENOSPC; 30 - } 31 - mutex_unlock(&iforce->mem_mutex); 32 31 } 33 32 34 33 data[0] = LO(mod_chunk->start); ··· 53 54 period = TIME_SCALE(period); 54 55 55 56 if (!no_alloc) { 56 - mutex_lock(&iforce->mem_mutex); 57 - if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0c, 58 - iforce->device_memory.start, iforce->device_memory.end, 2L, 59 - NULL, NULL)) { 60 - mutex_unlock(&iforce->mem_mutex); 57 + guard(mutex)(&iforce->mem_mutex); 58 + 59 + if (allocate_resource(&iforce->device_memory, mod_chunk, 0x0c, 60 + iforce->device_memory.start, 61 + iforce->device_memory.end, 62 + 2L, NULL, NULL)) 61 63 return -ENOSPC; 62 - } 63 - mutex_unlock(&iforce->mem_mutex); 64 64 } 65 65 66 66 data[0] = LO(mod_chunk->start); ··· 92 94 fade_duration = TIME_SCALE(fade_duration); 93 95 94 96 if (!no_alloc) { 95 - mutex_lock(&iforce->mem_mutex); 97 + guard(mutex)(&iforce->mem_mutex); 98 + 96 99 if (allocate_resource(&(iforce->device_memory), mod_chunk, 0x0e, 97 - iforce->device_memory.start, iforce->device_memory.end, 2L, 98 - NULL, NULL)) { 99 - mutex_unlock(&iforce->mem_mutex); 100 + iforce->device_memory.start, 101 + iforce->device_memory.end, 102 + 2L, NULL, NULL)) 100 103 return -ENOSPC; 101 - } 102 - mutex_unlock(&iforce->mem_mutex); 103 104 } 104 105 105 106 data[0] = LO(mod_chunk->start); ··· 128 131 unsigned char data[10]; 129 132 130 133 if (!no_alloc) { 131 - mutex_lock(&iforce->mem_mutex); 134 + guard(mutex)(&iforce->mem_mutex); 135 + 132 136 if (allocate_resource(&(iforce->device_memory), mod_chunk, 8, 133 - iforce->device_memory.start, iforce->device_memory.end, 2L, 134 - NULL, NULL)) { 135 - mutex_unlock(&iforce->mem_mutex); 137 + iforce->device_memory.start, 138 + iforce->device_memory.end, 139 + 2L, NULL, NULL)) 136 140 return -ENOSPC; 137 - } 138 - mutex_unlock(&iforce->mem_mutex); 139 141 } 140 142 141 143 data[0] = LO(mod_chunk->start);
+22 -29
drivers/input/joystick/iforce/iforce-packets.c
··· 31 31 int c; 32 32 int empty; 33 33 int head, tail; 34 - unsigned long flags; 35 34 36 35 /* 37 36 * Update head and tail of xmit buffer 38 37 */ 39 - spin_lock_irqsave(&iforce->xmit_lock, flags); 38 + scoped_guard(spinlock_irqsave, &iforce->xmit_lock) { 39 + head = iforce->xmit.head; 40 + tail = iforce->xmit.tail; 40 41 41 - head = iforce->xmit.head; 42 - tail = iforce->xmit.tail; 42 + if (CIRC_SPACE(head, tail, XMIT_SIZE) < n + 2) { 43 + dev_warn(&iforce->dev->dev, 44 + "not enough space in xmit buffer to send new packet\n"); 45 + return -1; 46 + } 43 47 44 - 45 - if (CIRC_SPACE(head, tail, XMIT_SIZE) < n+2) { 46 - dev_warn(&iforce->dev->dev, 47 - "not enough space in xmit buffer to send new packet\n"); 48 - spin_unlock_irqrestore(&iforce->xmit_lock, flags); 49 - return -1; 50 - } 51 - 52 - empty = head == tail; 53 - XMIT_INC(iforce->xmit.head, n+2); 48 + empty = head == tail; 49 + XMIT_INC(iforce->xmit.head, n + 2); 54 50 55 51 /* 56 52 * Store packet in xmit buffer 57 53 */ 58 - iforce->xmit.buf[head] = HI(cmd); 59 - XMIT_INC(head, 1); 60 - iforce->xmit.buf[head] = LO(cmd); 61 - XMIT_INC(head, 1); 54 + iforce->xmit.buf[head] = HI(cmd); 55 + XMIT_INC(head, 1); 56 + iforce->xmit.buf[head] = LO(cmd); 57 + XMIT_INC(head, 1); 62 58 63 - c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE); 64 - if (n < c) c=n; 59 + c = CIRC_SPACE_TO_END(head, tail, XMIT_SIZE); 60 + if (n < c) 61 + c = n; 65 62 66 - memcpy(&iforce->xmit.buf[head], 67 - data, 68 - c); 69 - if (n != c) { 70 - memcpy(&iforce->xmit.buf[0], 71 - data + c, 72 - n - c); 63 + memcpy(&iforce->xmit.buf[head], data, c); 64 + if (n != c) 65 + memcpy(&iforce->xmit.buf[0], data + c, n - c); 66 + 67 + XMIT_INC(head, n); 73 68 } 74 - XMIT_INC(head, n); 75 69 76 - spin_unlock_irqrestore(&iforce->xmit_lock, flags); 77 70 /* 78 71 * If necessary, start the transmission 79 72 */
+15 -21
drivers/input/joystick/iforce/iforce-serio.c
··· 28 28 iforce); 29 29 unsigned char cs; 30 30 int i; 31 - unsigned long flags; 32 31 33 32 if (test_and_set_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)) { 34 33 set_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags); 35 34 return; 36 35 } 37 36 38 - spin_lock_irqsave(&iforce->xmit_lock, flags); 37 + guard(spinlock_irqsave)(&iforce->xmit_lock); 39 38 40 - again: 41 - if (iforce->xmit.head == iforce->xmit.tail) { 42 - iforce_clear_xmit_and_wake(iforce); 43 - spin_unlock_irqrestore(&iforce->xmit_lock, flags); 44 - return; 45 - } 39 + do { 40 + if (iforce->xmit.head == iforce->xmit.tail) 41 + break; 46 42 47 - cs = 0x2b; 43 + cs = 0x2b; 48 44 49 - serio_write(iforce_serio->serio, 0x2b); 45 + serio_write(iforce_serio->serio, 0x2b); 50 46 51 - serio_write(iforce_serio->serio, iforce->xmit.buf[iforce->xmit.tail]); 52 - cs ^= iforce->xmit.buf[iforce->xmit.tail]; 53 - XMIT_INC(iforce->xmit.tail, 1); 54 - 55 - for (i=iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) { 56 47 serio_write(iforce_serio->serio, 57 48 iforce->xmit.buf[iforce->xmit.tail]); 58 49 cs ^= iforce->xmit.buf[iforce->xmit.tail]; 59 50 XMIT_INC(iforce->xmit.tail, 1); 60 - } 61 51 62 - serio_write(iforce_serio->serio, cs); 52 + for (i = iforce->xmit.buf[iforce->xmit.tail]; i >= 0; --i) { 53 + serio_write(iforce_serio->serio, 54 + iforce->xmit.buf[iforce->xmit.tail]); 55 + cs ^= iforce->xmit.buf[iforce->xmit.tail]; 56 + XMIT_INC(iforce->xmit.tail, 1); 57 + } 63 58 64 - if (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags)) 65 - goto again; 59 + serio_write(iforce_serio->serio, cs); 60 + 61 + } while (test_and_clear_bit(IFORCE_XMIT_AGAIN, iforce->xmit_flags)); 66 62 67 63 iforce_clear_xmit_and_wake(iforce); 68 - 69 - spin_unlock_irqrestore(&iforce->xmit_lock, flags); 70 64 } 71 65 72 66 static int iforce_serio_get_id(struct iforce *iforce, u8 id,
+6 -7
drivers/input/joystick/iforce/iforce-usb.c
··· 25 25 struct iforce_usb *iforce_usb = container_of(iforce, struct iforce_usb, 26 26 iforce); 27 27 int n, c; 28 - unsigned long flags; 29 28 30 - spin_lock_irqsave(&iforce->xmit_lock, flags); 29 + guard(spinlock_irqsave)(&iforce->xmit_lock); 31 30 32 31 if (iforce->xmit.head == iforce->xmit.tail) { 33 32 iforce_clear_xmit_and_wake(iforce); 34 - spin_unlock_irqrestore(&iforce->xmit_lock, flags); 35 33 return; 36 34 } 37 35 ··· 43 45 44 46 /* Copy rest of data then */ 45 47 c = CIRC_CNT_TO_END(iforce->xmit.head, iforce->xmit.tail, XMIT_SIZE); 46 - if (n < c) c=n; 48 + if (n < c) 49 + c = n; 47 50 48 51 memcpy(iforce_usb->out->transfer_buffer + 1, 49 52 &iforce->xmit.buf[iforce->xmit.tail], ··· 52 53 if (n != c) { 53 54 memcpy(iforce_usb->out->transfer_buffer + 1 + c, 54 55 &iforce->xmit.buf[0], 55 - n-c); 56 + n - c); 56 57 } 57 58 XMIT_INC(iforce->xmit.tail, n); 58 59 59 - if ( (n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC)) ) { 60 + n=usb_submit_urb(iforce_usb->out, GFP_ATOMIC); 61 + if (n) { 60 62 dev_warn(&iforce_usb->intf->dev, 61 63 "usb_submit_urb failed %d\n", n); 62 64 iforce_clear_xmit_and_wake(iforce); ··· 66 66 /* The IFORCE_XMIT_RUNNING bit is not cleared here. That's intended. 67 67 * As long as the urb completion handler is not called, the transmiting 68 68 * is considered to be running */ 69 - spin_unlock_irqrestore(&iforce->xmit_lock, flags); 70 69 } 71 70 72 71 static void iforce_usb_xmit(struct iforce *iforce)