Skip to content

Commit e4c8b80

Browse files
committed
firewire: ohci: use guard macro to serialize operations for isochronous contexts
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>
1 parent 86baade commit e4c8b80

1 file changed

Lines changed: 77 additions & 105 deletions

File tree

drivers/firewire/ohci.c

Lines changed: 77 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,13 +1173,11 @@ static void context_tasklet(unsigned long data)
11731173
break;
11741174

11751175
if (old_desc != desc) {
1176-
/* If we've advanced to the next buffer, move the
1177-
* previous buffer to the free list. */
1178-
unsigned long flags;
1176+
// If we've advanced to the next buffer, move the previous buffer to the
1177+
// free list.
11791178
old_desc->used = 0;
1180-
spin_lock_irqsave(&ctx->ohci->lock, flags);
1179+
guard(spinlock_irqsave)(&ctx->ohci->lock);
11811180
list_move_tail(&old_desc->list, &ctx->buffer_list);
1182-
spin_unlock_irqrestore(&ctx->ohci->lock, flags);
11831181
}
11841182
ctx->last = last;
11851183
}
@@ -2122,14 +2120,12 @@ static void bus_reset_work(struct work_struct *work)
21222120
return;
21232121
}
21242122

2125-
/* FIXME: Document how the locking works. */
2126-
spin_lock_irq(&ohci->lock);
2127-
2128-
ohci->generation = -1; /* prevent AT packet queueing */
2129-
context_stop(&ohci->at_request_ctx);
2130-
context_stop(&ohci->at_response_ctx);
2131-
2132-
spin_unlock_irq(&ohci->lock);
2123+
// FIXME: Document how the locking works.
2124+
scoped_guard(spinlock_irq, &ohci->lock) {
2125+
ohci->generation = -1; // prevent AT packet queueing
2126+
context_stop(&ohci->at_request_ctx);
2127+
context_stop(&ohci->at_response_ctx);
2128+
}
21332129

21342130
/*
21352131
* 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,
27042700
int node_id, int generation)
27052701
{
27062702
struct fw_ohci *ohci = fw_ohci(card);
2707-
unsigned long flags;
27082703
int n, ret = 0;
27092704

27102705
if (param_remote_dma)
@@ -2715,12 +2710,10 @@ static int ohci_enable_phys_dma(struct fw_card *card,
27152710
* interrupt bit. Clear physReqResourceAllBuses on bus reset.
27162711
*/
27172712

2718-
spin_lock_irqsave(&ohci->lock, flags);
2713+
guard(spinlock_irqsave)(&ohci->lock);
27192714

2720-
if (ohci->generation != generation) {
2721-
ret = -ESTALE;
2722-
goto out;
2723-
}
2715+
if (ohci->generation != generation)
2716+
return -ESTALE;
27242717

27252718
/*
27262719
* 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,
27342727
reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 1 << (n - 32));
27352728

27362729
flush_writes(ohci);
2737-
out:
2738-
spin_unlock_irqrestore(&ohci->lock, flags);
27392730

27402731
return ret;
27412732
}
@@ -3076,55 +3067,53 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
30763067
u32 *mask, regs;
30773068
int index, ret = -EBUSY;
30783069

3079-
spin_lock_irq(&ohci->lock);
3070+
scoped_guard(spinlock_irq, &ohci->lock) {
3071+
switch (type) {
3072+
case FW_ISO_CONTEXT_TRANSMIT:
3073+
mask = &ohci->it_context_mask;
3074+
callback = handle_it_packet;
3075+
index = ffs(*mask) - 1;
3076+
if (index >= 0) {
3077+
*mask &= ~(1 << index);
3078+
regs = OHCI1394_IsoXmitContextBase(index);
3079+
ctx = &ohci->it_context_list[index];
3080+
}
3081+
break;
30803082

3081-
switch (type) {
3082-
case FW_ISO_CONTEXT_TRANSMIT:
3083-
mask = &ohci->it_context_mask;
3084-
callback = handle_it_packet;
3085-
index = ffs(*mask) - 1;
3086-
if (index >= 0) {
3087-
*mask &= ~(1 << index);
3088-
regs = OHCI1394_IsoXmitContextBase(index);
3089-
ctx = &ohci->it_context_list[index];
3090-
}
3091-
break;
3083+
case FW_ISO_CONTEXT_RECEIVE:
3084+
channels = &ohci->ir_context_channels;
3085+
mask = &ohci->ir_context_mask;
3086+
callback = handle_ir_packet_per_buffer;
3087+
index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
3088+
if (index >= 0) {
3089+
*channels &= ~(1ULL << channel);
3090+
*mask &= ~(1 << index);
3091+
regs = OHCI1394_IsoRcvContextBase(index);
3092+
ctx = &ohci->ir_context_list[index];
3093+
}
3094+
break;
30923095

3093-
case FW_ISO_CONTEXT_RECEIVE:
3094-
channels = &ohci->ir_context_channels;
3095-
mask = &ohci->ir_context_mask;
3096-
callback = handle_ir_packet_per_buffer;
3097-
index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
3098-
if (index >= 0) {
3099-
*channels &= ~(1ULL << channel);
3100-
*mask &= ~(1 << index);
3101-
regs = OHCI1394_IsoRcvContextBase(index);
3102-
ctx = &ohci->ir_context_list[index];
3103-
}
3104-
break;
3096+
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3097+
mask = &ohci->ir_context_mask;
3098+
callback = handle_ir_buffer_fill;
3099+
index = !ohci->mc_allocated ? ffs(*mask) - 1 : -1;
3100+
if (index >= 0) {
3101+
ohci->mc_allocated = true;
3102+
*mask &= ~(1 << index);
3103+
regs = OHCI1394_IsoRcvContextBase(index);
3104+
ctx = &ohci->ir_context_list[index];
3105+
}
3106+
break;
31053107

3106-
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3107-
mask = &ohci->ir_context_mask;
3108-
callback = handle_ir_buffer_fill;
3109-
index = !ohci->mc_allocated ? ffs(*mask) - 1 : -1;
3110-
if (index >= 0) {
3111-
ohci->mc_allocated = true;
3112-
*mask &= ~(1 << index);
3113-
regs = OHCI1394_IsoRcvContextBase(index);
3114-
ctx = &ohci->ir_context_list[index];
3108+
default:
3109+
index = -1;
3110+
ret = -ENOSYS;
31153111
}
3116-
break;
31173112

3118-
default:
3119-
index = -1;
3120-
ret = -ENOSYS;
3113+
if (index < 0)
3114+
return ERR_PTR(ret);
31213115
}
31223116

3123-
spin_unlock_irq(&ohci->lock);
3124-
3125-
if (index < 0)
3126-
return ERR_PTR(ret);
3127-
31283117
memset(ctx, 0, sizeof(*ctx));
31293118
ctx->header_length = 0;
31303119
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,
31463135
out_with_header:
31473136
free_page((unsigned long)ctx->header);
31483137
out:
3149-
spin_lock_irq(&ohci->lock);
3150-
3151-
switch (type) {
3152-
case FW_ISO_CONTEXT_RECEIVE:
3153-
*channels |= 1ULL << channel;
3154-
break;
3138+
scoped_guard(spinlock_irq, &ohci->lock) {
3139+
switch (type) {
3140+
case FW_ISO_CONTEXT_RECEIVE:
3141+
*channels |= 1ULL << channel;
3142+
break;
31553143

3156-
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3157-
ohci->mc_allocated = false;
3158-
break;
3144+
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3145+
ohci->mc_allocated = false;
3146+
break;
3147+
}
3148+
*mask |= 1 << index;
31593149
}
3160-
*mask |= 1 << index;
3161-
3162-
spin_unlock_irq(&ohci->lock);
31633150

31643151
return ERR_PTR(ret);
31653152
}
@@ -3243,14 +3230,13 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
32433230
{
32443231
struct fw_ohci *ohci = fw_ohci(base->card);
32453232
struct iso_context *ctx = container_of(base, struct iso_context, base);
3246-
unsigned long flags;
32473233
int index;
32483234

32493235
ohci_stop_iso(base);
32503236
context_release(&ctx->context);
32513237
free_page((unsigned long)ctx->header);
32523238

3253-
spin_lock_irqsave(&ohci->lock, flags);
3239+
guard(spinlock_irqsave)(&ohci->lock);
32543240

32553241
switch (base->type) {
32563242
case FW_ISO_CONTEXT_TRANSMIT:
@@ -3272,38 +3258,29 @@ static void ohci_free_iso_context(struct fw_iso_context *base)
32723258
ohci->mc_allocated = false;
32733259
break;
32743260
}
3275-
3276-
spin_unlock_irqrestore(&ohci->lock, flags);
32773261
}
32783262

32793263
static int ohci_set_iso_channels(struct fw_iso_context *base, u64 *channels)
32803264
{
32813265
struct fw_ohci *ohci = fw_ohci(base->card);
3282-
unsigned long flags;
3283-
int ret;
32843266

32853267
switch (base->type) {
32863268
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3269+
{
3270+
guard(spinlock_irqsave)(&ohci->lock);
32873271

3288-
spin_lock_irqsave(&ohci->lock, flags);
3289-
3290-
/* Don't allow multichannel to grab other contexts' channels. */
3272+
// Don't allow multichannel to grab other contexts' channels.
32913273
if (~ohci->ir_context_channels & ~ohci->mc_channels & *channels) {
32923274
*channels = ohci->ir_context_channels;
3293-
ret = -EBUSY;
3275+
return -EBUSY;
32943276
} else {
32953277
set_multichannel_mask(ohci, *channels);
3296-
ret = 0;
3278+
return 0;
32973279
}
3298-
3299-
spin_unlock_irqrestore(&ohci->lock, flags);
3300-
3301-
break;
3280+
}
33023281
default:
3303-
ret = -EINVAL;
3282+
return -EINVAL;
33043283
}
3305-
3306-
return ret;
33073284
}
33083285

33093286
#ifdef CONFIG_PM
@@ -3573,24 +3550,19 @@ static int ohci_queue_iso(struct fw_iso_context *base,
35733550
unsigned long payload)
35743551
{
35753552
struct iso_context *ctx = container_of(base, struct iso_context, base);
3576-
unsigned long flags;
3577-
int ret = -ENOSYS;
35783553

3579-
spin_lock_irqsave(&ctx->context.ohci->lock, flags);
3554+
guard(spinlock_irqsave)(&ctx->context.ohci->lock);
3555+
35803556
switch (base->type) {
35813557
case FW_ISO_CONTEXT_TRANSMIT:
3582-
ret = queue_iso_transmit(ctx, packet, buffer, payload);
3583-
break;
3558+
return queue_iso_transmit(ctx, packet, buffer, payload);
35843559
case FW_ISO_CONTEXT_RECEIVE:
3585-
ret = queue_iso_packet_per_buffer(ctx, packet, buffer, payload);
3586-
break;
3560+
return queue_iso_packet_per_buffer(ctx, packet, buffer, payload);
35873561
case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3588-
ret = queue_iso_buffer_fill(ctx, packet, buffer, payload);
3589-
break;
3562+
return queue_iso_buffer_fill(ctx, packet, buffer, payload);
3563+
default:
3564+
return -ENOSYS;
35903565
}
3591-
spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
3592-
3593-
return ret;
35943566
}
35953567

35963568
static void ohci_flush_queue_iso(struct fw_iso_context *base)

0 commit comments

Comments
 (0)