summaryrefslogtreecommitdiff
path: root/drivers/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2024-09-09 17:00:18 +0300
committerTakashi Sakamoto <o-takashi@sakamocchi.jp>2024-09-09 17:00:18 +0300
commitf877f1d81b2ffcac341ff62ae076d7ad5ba83f46 (patch)
tree59972947210c65a5932c97a2dc76fe44f1b4e451 /drivers/firewire
parente97fb38fa1404abef72bac7de2c5bf2bbab4d93b (diff)
downloadlinux-f877f1d81b2ffcac341ff62ae076d7ad5ba83f46.tar.xz
firewire: core: use mutex to coordinate concurrent calls to flush completions
In current implementation, test_and_set_bit_lock() is used to mediate concurrent calls of ohci_flush_iso_completions(). However, the ad-hoc usage of atomic operations is not preferable. This commit uses mutex_trylock() as the similar operations. The core function is responsible for the mediation, instead of 1394 OHCI driver. Link: https://lore.kernel.org/r/20240909140018.65289-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/core-iso.c11
-rw-r--r--drivers/firewire/ohci.c37
2 files changed, 23 insertions, 25 deletions
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 9f41c78878ad..1405d2e9cb2c 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -157,6 +157,7 @@ struct fw_iso_context *fw_iso_context_create(struct fw_card *card,
ctx->callback.sc = callback;
ctx->callback_data = callback_data;
INIT_WORK(&ctx->work, flush_completions_work);
+ mutex_init(&ctx->flushing_completions_mutex);
trace_isoc_outbound_allocate(ctx, channel, speed);
trace_isoc_inbound_single_allocate(ctx, channel, header_size);
@@ -173,6 +174,8 @@ void fw_iso_context_destroy(struct fw_iso_context *ctx)
trace_isoc_inbound_multiple_destroy(ctx);
ctx->card->driver->free_iso_context(ctx);
+
+ mutex_destroy(&ctx->flushing_completions_mutex);
}
EXPORT_SYMBOL(fw_iso_context_destroy);
@@ -226,7 +229,7 @@ EXPORT_SYMBOL(fw_iso_context_queue_flush);
* to process the context asynchronously, fw_iso_context_schedule_flush_completions() is available
* instead.
*
- * Context: Process context.
+ * Context: Process context due to mutex_trylock().
*/
int fw_iso_context_flush_completions(struct fw_iso_context *ctx)
{
@@ -234,7 +237,11 @@ int fw_iso_context_flush_completions(struct fw_iso_context *ctx)
trace_isoc_inbound_single_flush_completions(ctx);
trace_isoc_inbound_multiple_flush_completions(ctx);
- return ctx->card->driver->flush_iso_completions(ctx);
+ scoped_cond_guard(mutex_try, /* nothing to do */, &ctx->flushing_completions_mutex) {
+ return ctx->card->driver->flush_iso_completions(ctx);
+ }
+
+ return 0;
}
EXPORT_SYMBOL(fw_iso_context_flush_completions);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 02ff0363d3ad..b182998a77f4 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -166,7 +166,6 @@ struct iso_context {
struct context context;
void *header;
size_t header_length;
- unsigned long flushing_completions;
u32 mc_buffer_bus;
u16 mc_completed;
u16 last_timestamp;
@@ -3579,31 +3578,23 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base)
static int ohci_flush_iso_completions(struct fw_iso_context *base)
{
struct iso_context *ctx = container_of(base, struct iso_context, base);
- int ret = 0;
- if (!test_and_set_bit_lock(0, &ctx->flushing_completions)) {
- // Note that tasklet softIRQ is not used to process isochronous context anymore.
- context_tasklet((unsigned long)&ctx->context);
+ // Note that tasklet softIRQ is not used to process isochronous context anymore.
+ context_tasklet((unsigned long)&ctx->context);
- switch (base->type) {
- case FW_ISO_CONTEXT_TRANSMIT:
- case FW_ISO_CONTEXT_RECEIVE:
- if (ctx->header_length != 0)
- flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_FLUSH);
- break;
- case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
- if (ctx->mc_completed != 0)
- flush_ir_buffer_fill(ctx);
- break;
- default:
- ret = -ENOSYS;
- }
-
- clear_bit_unlock(0, &ctx->flushing_completions);
- smp_mb__after_atomic();
+ switch (base->type) {
+ case FW_ISO_CONTEXT_TRANSMIT:
+ case FW_ISO_CONTEXT_RECEIVE:
+ if (ctx->header_length != 0)
+ flush_iso_completions(ctx, FW_ISO_CONTEXT_COMPLETIONS_CAUSE_FLUSH);
+ return 0;
+ case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
+ if (ctx->mc_completed != 0)
+ flush_ir_buffer_fill(ctx);
+ return 0;
+ default:
+ return -ENOSYS;
}
-
- return ret;
}
static const struct fw_card_driver ohci_driver = {