Skip to content

Commit d7dfb07

Browse files
committed
Merge tag 'firewire-updates-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394
Pull firewire updates from Takashi Sakamoto: "In the FireWire subsystem, tasklets have been used as the bottom half of 1394 OHCi hardIRQ. In recent kernel updates, BH workqueues have become available, and some developers have proposed replacing the tasklet with a BH workqueue. As a first step towards dropping tasklet use, the 1394 OHCI isochronous context can use regular workqueues. In this context, the batch of packets is processed in the specific queue, thus the timing jitter caused by task scheduling is not so critical. Additionally, DMA transmission can be scheduled per-packet basis, therefore the context can be sleep between the operation of transmissions. Furthermore, in-kernel protocol implementation involves some CPU-bound tasks, which can sometimes consumes CPU time so long. These characteristics suggest that normal workqueues are suitable, through BH workqueues are not. The replacement with a workqueue allows unit drivers to process the content of packets in non-atomic context. It brings some reliefs to some drivers in sound subsystem that spin-lock is not mandatory anymore during isochronous packet processing. Summary: - Replace tasklet with workqueue for isochronous context - Replace IDR with XArray - Utilize guard macro where possible - Print deprecation warning when enabling debug parameter of firewire-ohci module - Switch to nonatomic PCM operation" * tag 'firewire-updates-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394: (55 commits) firewire: core: rename cause flag of tracepoints event firewire: core: update documentation of kernel APIs for flushing completions firewire: core: add helper function to retire descriptors Revert "firewire: core: move workqueue handler from 1394 OHCI driver to core function" Revert "firewire: core: use mutex to coordinate concurrent calls to flush completions" firewire: core: use mutex to coordinate concurrent calls to flush completions firewire: core: move workqueue handler from 1394 OHCI driver to core function firewire: core: fulfill documentation of fw_iso_context_flush_completions() firewire: core: expose kernel API to schedule work item to process isochronous context firewire: core: use WARN_ON_ONCE() to avoid superfluous dumps ALSA: firewire: use nonatomic PCM operation firewire: core: non-atomic memory allocation for isochronous event to user client firewire: ohci: operate IT/IR events in sleepable work process instead of tasklet softIRQ firewire: core: add local API to queue work item to workqueue specific to isochronous contexts firewire: core: allocate workqueue to handle isochronous contexts in card firewire: ohci: obsolete direct usage of printk_ratelimit() firewire: ohci: deprecate debug parameter firewire: core: update fw_device outside of device_find_child() firewire: ohci: fix error path to detect initiated reset in TI TSB41BA3D phy firewire: core/ohci: minor refactoring for computation of configuration ROM size ...
2 parents 3a37872 + f1cba52 commit d7dfb07

File tree

23 files changed

+1065
-774
lines changed

23 files changed

+1065
-774
lines changed

Documentation/driver-api/firewire.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ Firewire core transaction interfaces
4343
Firewire Isochronous I/O interfaces
4444
===================================
4545

46+
.. kernel-doc:: include/linux/firewire.h
47+
:functions: fw_iso_context_schedule_flush_completions
4648
.. kernel-doc:: drivers/firewire/core-iso.c
4749
:export:
4850

drivers/firewire/core-card.c

Lines changed: 54 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ static size_t required_space(struct fw_descriptor *desc)
168168
int fw_core_add_descriptor(struct fw_descriptor *desc)
169169
{
170170
size_t i;
171-
int ret;
172171

173172
/*
174173
* Check descriptor is valid; the length of all blocks in the
@@ -182,38 +181,32 @@ int fw_core_add_descriptor(struct fw_descriptor *desc)
182181
if (i != desc->length)
183182
return -EINVAL;
184183

185-
mutex_lock(&card_mutex);
184+
guard(mutex)(&card_mutex);
186185

187-
if (config_rom_length + required_space(desc) > 256) {
188-
ret = -EBUSY;
189-
} else {
190-
list_add_tail(&desc->link, &descriptor_list);
191-
config_rom_length += required_space(desc);
192-
descriptor_count++;
193-
if (desc->immediate > 0)
194-
descriptor_count++;
195-
update_config_roms();
196-
ret = 0;
197-
}
186+
if (config_rom_length + required_space(desc) > 256)
187+
return -EBUSY;
198188

199-
mutex_unlock(&card_mutex);
189+
list_add_tail(&desc->link, &descriptor_list);
190+
config_rom_length += required_space(desc);
191+
descriptor_count++;
192+
if (desc->immediate > 0)
193+
descriptor_count++;
194+
update_config_roms();
200195

201-
return ret;
196+
return 0;
202197
}
203198
EXPORT_SYMBOL(fw_core_add_descriptor);
204199

205200
void fw_core_remove_descriptor(struct fw_descriptor *desc)
206201
{
207-
mutex_lock(&card_mutex);
202+
guard(mutex)(&card_mutex);
208203

209204
list_del(&desc->link);
210205
config_rom_length -= required_space(desc);
211206
descriptor_count--;
212207
if (desc->immediate > 0)
213208
descriptor_count--;
214209
update_config_roms();
215-
216-
mutex_unlock(&card_mutex);
217210
}
218211
EXPORT_SYMBOL(fw_core_remove_descriptor);
219212

@@ -381,11 +374,11 @@ static void bm_work(struct work_struct *work)
381374

382375
bm_id = be32_to_cpu(transaction_data[0]);
383376

384-
spin_lock_irq(&card->lock);
385-
if (rcode == RCODE_COMPLETE && generation == card->generation)
386-
card->bm_node_id =
387-
bm_id == 0x3f ? local_id : 0xffc0 | bm_id;
388-
spin_unlock_irq(&card->lock);
377+
scoped_guard(spinlock_irq, &card->lock) {
378+
if (rcode == RCODE_COMPLETE && generation == card->generation)
379+
card->bm_node_id =
380+
bm_id == 0x3f ? local_id : 0xffc0 | bm_id;
381+
}
389382

390383
if (rcode == RCODE_COMPLETE && bm_id != 0x3f) {
391384
/* Somebody else is BM. Only act as IRM. */
@@ -578,25 +571,47 @@ void fw_card_initialize(struct fw_card *card,
578571
}
579572
EXPORT_SYMBOL(fw_card_initialize);
580573

581-
int fw_card_add(struct fw_card *card,
582-
u32 max_receive, u32 link_speed, u64 guid)
574+
int fw_card_add(struct fw_card *card, u32 max_receive, u32 link_speed, u64 guid,
575+
unsigned int supported_isoc_contexts)
583576
{
577+
struct workqueue_struct *isoc_wq;
584578
int ret;
585579

580+
// This workqueue should be:
581+
// * != WQ_BH Sleepable.
582+
// * == WQ_UNBOUND Any core can process data for isoc context. The
583+
// implementation of unit protocol could consumes the core
584+
// longer somehow.
585+
// * != WQ_MEM_RECLAIM Not used for any backend of block device.
586+
// * == WQ_FREEZABLE Isochronous communication is at regular interval in real
587+
// time, thus should be drained if possible at freeze phase.
588+
// * == WQ_HIGHPRI High priority to process semi-realtime timestamped data.
589+
// * == WQ_SYSFS Parameters are available via sysfs.
590+
// * max_active == n_it + n_ir A hardIRQ could notify events for multiple isochronous
591+
// contexts if they are scheduled to the same cycle.
592+
isoc_wq = alloc_workqueue("firewire-isoc-card%u",
593+
WQ_UNBOUND | WQ_FREEZABLE | WQ_HIGHPRI | WQ_SYSFS,
594+
supported_isoc_contexts, card->index);
595+
if (!isoc_wq)
596+
return -ENOMEM;
597+
586598
card->max_receive = max_receive;
587599
card->link_speed = link_speed;
588600
card->guid = guid;
589601

590-
mutex_lock(&card_mutex);
602+
guard(mutex)(&card_mutex);
591603

592604
generate_config_rom(card, tmp_config_rom);
593605
ret = card->driver->enable(card, tmp_config_rom, config_rom_length);
594-
if (ret == 0)
595-
list_add_tail(&card->link, &card_list);
606+
if (ret < 0) {
607+
destroy_workqueue(isoc_wq);
608+
return ret;
609+
}
596610

597-
mutex_unlock(&card_mutex);
611+
card->isoc_wq = isoc_wq;
612+
list_add_tail(&card->link, &card_list);
598613

599-
return ret;
614+
return 0;
600615
}
601616
EXPORT_SYMBOL(fw_card_add);
602617

@@ -714,29 +729,31 @@ EXPORT_SYMBOL_GPL(fw_card_release);
714729
void fw_core_remove_card(struct fw_card *card)
715730
{
716731
struct fw_card_driver dummy_driver = dummy_driver_template;
717-
unsigned long flags;
732+
733+
might_sleep();
718734

719735
card->driver->update_phy_reg(card, 4,
720736
PHY_LINK_ACTIVE | PHY_CONTENDER, 0);
721737
fw_schedule_bus_reset(card, false, true);
722738

723-
mutex_lock(&card_mutex);
724-
list_del_init(&card->link);
725-
mutex_unlock(&card_mutex);
739+
scoped_guard(mutex, &card_mutex)
740+
list_del_init(&card->link);
726741

727742
/* Switch off most of the card driver interface. */
728743
dummy_driver.free_iso_context = card->driver->free_iso_context;
729744
dummy_driver.stop_iso = card->driver->stop_iso;
730745
card->driver = &dummy_driver;
746+
drain_workqueue(card->isoc_wq);
731747

732-
spin_lock_irqsave(&card->lock, flags);
733-
fw_destroy_nodes(card);
734-
spin_unlock_irqrestore(&card->lock, flags);
748+
scoped_guard(spinlock_irqsave, &card->lock)
749+
fw_destroy_nodes(card);
735750

736751
/* Wait for all users, especially device workqueue jobs, to finish. */
737752
fw_card_put(card);
738753
wait_for_completion(&card->done);
739754

755+
destroy_workqueue(card->isoc_wq);
756+
740757
WARN_ON(!list_empty(&card->transaction_list));
741758
}
742759
EXPORT_SYMBOL(fw_core_remove_card);

0 commit comments

Comments
 (0)