]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firewire: ohci: use guard macro to serialize operations for isochronous contexts
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 5 Aug 2024 08:54:08 +0000 (17:54 +0900)
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>
Mon, 5 Aug 2024 08:54:08 +0000 (17:54 +0900)
The 1394 OHCI driver uses spinlock to serialize operations for
isochronous contexts.

This commit uses guard macro to maintain the spinlock.

Link: https://lore.kernel.org/r/20240805085408.251763-18-o-takashi@sakamocchi.jp
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
drivers/firewire/ohci.c

index 368420e4b4140f612a419c6d7b27573359937b47..e1d24e0ec991b745ca71d536252c8b4c78e933ad 100644 (file)
@@ -1173,13 +1173,11 @@ static void context_tasklet(unsigned long data)
                        break;
 
                if (old_desc != desc) {
-                       /* If we've advanced to the next buffer, move the
-                        * previous buffer to the free list. */
-                       unsigned long flags;
+                       // If we've advanced to the next buffer, move the previous buffer to the
+                       // free list.
                        old_desc->used = 0;
-                       spin_lock_irqsave(&ctx->ohci->lock, flags);
+                       guard(spinlock_irqsave)(&ctx->ohci->lock);
                        list_move_tail(&old_desc->list, &ctx->buffer_list);
-                       spin_unlock_irqrestore(&ctx->ohci->lock, flags);
                }
                ctx->last = last;
        }
@@ -2122,14 +2120,12 @@ static void bus_reset_work(struct work_struct *work)
                return;
        }
 
-       /* FIXME: Document how the locking works. */
-       spin_lock_irq(&ohci->lock);
-
-       ohci->generation = -1; /* prevent AT packet queueing */
-       context_stop(&ohci->at_request_ctx);
-       context_stop(&ohci->at_response_ctx);
-
-       spin_unlock_irq(&ohci->lock);
+       // FIXME: Document how the locking works.
+       scoped_guard(spinlock_irq, &ohci->lock) {
+               ohci->generation = -1; // prevent AT packet queueing
+               context_stop(&ohci->at_request_ctx);
+               context_stop(&ohci->at_response_ctx);
+       }
 
        /*
         * Per OHCI 1.2 draft, clause 7.2.3.3, hardware may leave unsent
@@ -2704,7 +2700,6 @@ static int ohci_enable_phys_dma(struct fw_card *card,
                                int node_id, int generation)
 {
        struct fw_ohci *ohci = fw_ohci(card);
-       unsigned long flags;
        int n, ret = 0;
 
        if (param_remote_dma)
@@ -2715,12 +2710,10 @@ static int ohci_enable_phys_dma(struct fw_card *card,
         * interrupt bit.  Clear physReqResourceAllBuses on bus reset.
         */
 
-       spin_lock_irqsave(&ohci->lock, flags);
+       guard(spinlock_irqsave)(&ohci->lock);
 
-       if (ohci->generation != generation) {
-               ret = -ESTALE;
-               goto out;
-       }
+       if (ohci->generation != generation)
+               return -ESTALE;
 
        /*
         * Note, if the node ID contains a non-local bus ID, physical DMA is
@@ -2734,8 +2727,6 @@ static int ohci_enable_phys_dma(struct fw_card *card,
                reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32));
 
        flush_writes(ohci);
- out:
-       spin_unlock_irqrestore(&ohci->lock, flags);
 
        return ret;
 }
@@ -3076,55 +3067,53 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
        u32 *mask, regs;
        int index, ret = -EBUSY;
 
-       spin_lock_irq(&ohci->lock);
+       scoped_guard(spinlock_irq, &ohci->lock) {
+               switch (type) {
+               case FW_ISO_CONTEXT_TRANSMIT:
+                       mask     = &ohci->it_context_mask;
+                       callback = handle_it_packet;
+                       index    = ffs(*mask) - 1;
+                       if (index >= 0) {
+                               *mask &= ~(1 << index);
+                               regs = OHCI1394_IsoXmitContextBase(index);
+                               ctx  = &ohci->it_context_list[index];
+                       }
+                       break;
 
-       switch (type) {
-       case FW_ISO_CONTEXT_TRANSMIT:
-               mask     = &ohci->it_context_mask;
-               callback = handle_it_packet;
-               index    = ffs(*mask) - 1;
-               if (index >= 0) {
-                       *mask &= ~(1 << index);
-                       regs = OHCI1394_IsoXmitContextBase(index);
-                       ctx  = &ohci->it_context_list[index];
-               }
-               break;
+               case FW_ISO_CONTEXT_RECEIVE:
+                       channels = &ohci->ir_context_channels;
+                       mask     = &ohci->ir_context_mask;
+                       callback = handle_ir_packet_per_buffer;
+                       index    = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
+                       if (index >= 0) {
+                               *channels &= ~(1ULL << channel);
+                               *mask     &= ~(1 << index);
+                               regs = OHCI1394_IsoRcvContextBase(index);
+                               ctx  = &ohci->ir_context_list[index];
+                       }
+                       break;
 
-       case FW_ISO_CONTEXT_RECEIVE:
-               channels = &ohci->ir_context_channels;
-               mask     = &ohci->ir_context_mask;
-               callback = handle_ir_packet_per_buffer;
-               index    = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
-               if (index >= 0) {
-                       *channels &= ~(1ULL << channel);
-                       *mask     &= ~(1 << index);
-                       regs = OHCI1394_IsoRcvContextBase(index);
-                       ctx  = &ohci->ir_context_list[index];
-               }
-               break;
+               case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
+                       mask     = &ohci->ir_context_mask;
+                       callback = handle_ir_buffer_fill;
+                       index    = !ohci->mc_allocated ? ffs(*mask) - 1 : -1;
+                       if (index >= 0) {
+                               ohci->mc_allocated = true;
+                               *mask &= ~(1 << index);
+                               regs = OHCI1394_IsoRcvContextBase(index);
+                               ctx  = &ohci->ir_context_list[index];
+                       }
+                       break;
 
-       case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
-               mask     = &ohci->ir_context_mask;
-               callback = handle_ir_buffer_fill;
-               index    = !ohci->mc_allocated ? ffs(*mask) - 1 : -1;
-               if (index >= 0) {
-                       ohci->mc_allocated = true;
-                       *mask &= ~(1 << index);
-                       regs = OHCI1394_IsoRcvContextBase(index);
-                       ctx  = &ohci->ir_context_list[index];
+               default:
+                       index = -1;
+                       ret = -ENOSYS;
                }
-               break;
 
-       default:
-               index = -1;
-               ret = -ENOSYS;
+               if (index < 0)
+                       return ERR_PTR(ret);
        }
 
-       spin_unlock_irq(&ohci->lock);
-
-       if (index < 0)
-               return ERR_PTR(ret);
-
        memset(ctx, 0, sizeof(*ctx));
        ctx->header_length = 0;
        ctx->header = (void *) __get_free_page(GFP_KERNEL);
@@ -3146,20 +3135,18 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
  out_with_header:
        free_page((unsigned long)ctx->header);
  out:
-       spin_lock_irq(&ohci->lock);
-
-       switch (type) {
-       case FW_ISO_CONTEXT_RECEIVE:
-               *channels |= 1ULL << channel;
-               break;
+       scoped_guard(spinlock_irq, &ohci->lock) {
+               switch (type) {
+               case FW_ISO_CONTEXT_RECEIVE:
+                       *channels |= 1ULL << channel;
+                       break;
 
-       case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
-               ohci->mc_allocated = false;
-               break;
+               case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
+                       ohci->mc_allocated = false;
+                       break;
+               }
+               *mask |= 1 << index;
        }
-       *mask |= 1 << index;
-
-       spin_unlock_irq(&ohci->lock);
 
        return ERR_PTR(ret);
 }
@@ -3243,14 +3230,13 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
 {
        struct fw_ohci *ohci = fw_ohci(base->card);
        struct iso_context *ctx = container_of(base, struct iso_context, base);
-       unsigned long flags;
        int index;
 
        ohci_stop_iso(base);
        context_release(&ctx->context);
        free_page((unsigned long)ctx->header);
 
-       spin_lock_irqsave(&ohci->lock, flags);
+       guard(spinlock_irqsave)(&ohci->lock);
 
        switch (base->type) {
        case FW_ISO_CONTEXT_TRANSMIT:
@@ -3272,38 +3258,29 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
                ohci->mc_allocated = false;
                break;
        }
-
-       spin_unlock_irqrestore(&ohci->lock, flags);
 }
 
 static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels)
 {
        struct fw_ohci *ohci = fw_ohci(base->card);
-       unsigned long flags;
-       int ret;
 
        switch (base->type) {
        case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
+       {
+               guard(spinlock_irqsave)(&ohci->lock);
 
-               spin_lock_irqsave(&ohci->lock, flags);
-
-               /* Don't allow multichannel to grab other contexts' channels. */
+               // Don't allow multichannel to grab other contexts' channels.
                if (~ohci->ir_context_channels & ~ohci->mc_channels & *channels) {
                        *channels = ohci->ir_context_channels;
-                       ret = -EBUSY;
+                       return -EBUSY;
                } else {
                        set_multichannel_mask(ohci, *channels);
-                       ret = 0;
+                       return 0;
                }
-
-               spin_unlock_irqrestore(&ohci->lock, flags);
-
-               break;
+       }
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
-
-       return ret;
 }
 
 #ifdef CONFIG_PM
@@ -3573,24 +3550,19 @@ static int ohci_queue_iso(struct fw_iso_context *base,
                          unsigned long payload)
 {
        struct iso_context *ctx = container_of(base, struct iso_context, base);
-       unsigned long flags;
-       int ret = -ENOSYS;
 
-       spin_lock_irqsave(&ctx->context.ohci->lock, flags);
+       guard(spinlock_irqsave)(&ctx->context.ohci->lock);
+
        switch (base->type) {
        case FW_ISO_CONTEXT_TRANSMIT:
-               ret = queue_iso_transmit(ctx, packet, buffer, payload);
-               break;
+               return queue_iso_transmit(ctx, packet, buffer, payload);
        case FW_ISO_CONTEXT_RECEIVE:
-               ret = queue_iso_packet_per_buffer(ctx, packet, buffer, payload);
-               break;
+               return queue_iso_packet_per_buffer(ctx, packet, buffer, payload);
        case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
-               ret = queue_iso_buffer_fill(ctx, packet, buffer, payload);
-               break;
+               return queue_iso_buffer_fill(ctx, packet, buffer, payload);
+       default:
+               return -ENOSYS;
        }
-       spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
-
-       return ret;
 }
 
 static void ohci_flush_queue_iso(struct fw_iso_context *base)