From a520ce89fcf838acce1c8b2d52f02825d0d37796 Mon Sep 17 00:00:00 2001 From: Takashi Sakamoto Date: Sun, 20 Sep 2026 17:36:56 +0900 Subject: [PATCH] firewire: cdev: use mutex for phy receiver list In the cdev layer, the list of phy packet receivers is currently protected by a spinlock. This requires GFP_ATOMIC for memory allocation when enumerating the list in fw_cdev_handle_phy_packet(). However, the function is guaranteed to be invoked in process context, so GFP_KERNEL can be used by switching from the spinlock to a mutex. Link: https://lore.kernel.org/r/20260920083659.191855-3-o-takashi@sakamocchi.jp Signed-off-by: Takashi Sakamoto --- drivers/firewire/core-cdev.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 1b5d75f7e075..b211396e592a 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -47,7 +47,7 @@ #define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5 #define FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP 6 -static DEFINE_SPINLOCK(phy_receiver_list_lock); +static DEFINE_MUTEX(phy_receiver_list_mutex); static LIST_HEAD(phy_receiver_list); struct client { @@ -1761,9 +1761,7 @@ static int ioctl_receive_phy_packets(struct client *client, union ioctl_arg *arg if (!client->device->is_local) return -ENOSYS; - // NOTE: This can be without irq when we can guarantee that __fw_send_request() for local - // destination never runs in any type of IRQ context. - scoped_guard(spinlock_irq, &phy_receiver_list_lock) + scoped_guard(mutex, &phy_receiver_list_mutex) list_move_tail(&client->phy_receiver_link, &phy_receiver_list); client->phy_receiver_closure = a->closure; @@ -1775,18 +1773,14 @@ void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p) { struct client *client; - // NOTE: This can be without irqsave when we can guarantee that __fw_send_request() for local - // destination never runs in any type of IRQ context. - guard(spinlock_irqsave)(&phy_receiver_list_lock); + guard(mutex)(&phy_receiver_list_mutex); list_for_each_entry(client, &phy_receiver_list, phy_receiver_link) { - struct inbound_phy_packet_event *e; - if (client->device->card != card) continue; - e = kmalloc(sizeof(*e) + 8, GFP_ATOMIC); - if (e == NULL) + struct inbound_phy_packet_event *e = kmalloc(sizeof(*e) + 8, GFP_KERNEL); + if (!e) break; if (client->version < FW_CDEV_VERSION_EVENT_ASYNC_TSTAMP) { @@ -1953,9 +1947,7 @@ static int fw_device_op_release(struct inode *inode, struct file *file) struct client_resource *resource; unsigned long index; - // NOTE: This can be without irq when we can guarantee that __fw_send_request() for local - // destination never runs in any type of IRQ context. - scoped_guard(spinlock_irq, &phy_receiver_list_lock) + scoped_guard(mutex, &phy_receiver_list_mutex) list_del(&client->phy_receiver_link); scoped_guard(mutex, &client->device->client_list_mutex)