aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/core-transaction.c
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2010-10-13 07:39:46 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-05-10 16:53:45 -0400
commit6ea9e7bbfc389a12d52646449a201fe933ccd663 (patch)
treef84e89a394d45db4f30e1286966f69be62f203da /drivers/firewire/core-transaction.c
parent13882a82ee1646336c3996c93b4a560a55d2a419 (diff)
firewire: core: use non-reentrant workqueue with rescuer
firewire-core manages the following types of work items: fw_card.br_work: - resets the bus on a card and possibly sends a PHY packet before that - does not sleep for long or not at all - is scheduled via fw_schedule_bus_reset() by - firewire-ohci's pci_probe method - firewire-ohci's set_config_rom method, called by kernelspace protocol drivers and userspace drivers which add/remove Configuration ROM descriptors - userspace drivers which use the bus reset ioctl - itself if the last reset happened less than 2 seconds ago fw_card.bm_work: - performs bus management duties - usually does not (but may in corner cases) sleep for long - is scheduled via fw_schedule_bm_work() by - firewire-ohci's self-ID-complete IRQ handler tasklet - firewire-core's fw_device.work instances whenever the root node device was (successfully or unsuccessfully) discovered, refreshed, or rediscovered - itself in case of resource allocation failures or in order to obey the 125ms bus manager arbitration interval fw_device.work: - performs node probe, update, shutdown, revival, removal; including kernel driver probe, update, shutdown and bus reset notification to userspace drivers - usually sleeps moderately long, in corner cases very long - is scheduled by - firewire-ohci's self-ID-complete IRQ handler tasklet via the core's fw_node_event - firewire-ohci's pci_remove method via core's fw_destroy_nodes/ fw_node_event - itself during retries, e.g. while a node is powering up iso_resource.work: - accesses registers at the Isochronous Resource Manager node - usually does not (but may in corner cases) sleep for long - is scheduled via schedule_iso_resource() by - the owning userspace driver at addition and removal of the resource - firewire-core's fw_device.work instances after bus reset - itself in case of resource allocation if necessary to obey the 1000ms reallocation period after bus reset fw_card.br_work instances should not, and instances of the others must not, be executed in parallel by multiple CPUs -- but were not protected against that. Hence allocate a non-reentrant workqueue for them. fw_device.work may be used in the memory reclaim path in case of SBP-2 device updates. Hence we need a workqueue with rescuer and cannot use system_nrt_wq. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Reviewed-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/firewire/core-transaction.c')
-rw-r--r--drivers/firewire/core-transaction.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c
index 77275fdf6c1f..d4c28a217b2c 100644
--- a/drivers/firewire/core-transaction.c
+++ b/drivers/firewire/core-transaction.c
@@ -36,6 +36,7 @@
36#include <linux/string.h> 36#include <linux/string.h>
37#include <linux/timer.h> 37#include <linux/timer.h>
38#include <linux/types.h> 38#include <linux/types.h>
39#include <linux/workqueue.h>
39 40
40#include <asm/byteorder.h> 41#include <asm/byteorder.h>
41 42
@@ -1213,13 +1214,21 @@ static int __init fw_core_init(void)
1213{ 1214{
1214 int ret; 1215 int ret;
1215 1216
1217 fw_wq = alloc_workqueue(KBUILD_MODNAME,
1218 WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
1219 if (!fw_wq)
1220 return -ENOMEM;
1221
1216 ret = bus_register(&fw_bus_type); 1222 ret = bus_register(&fw_bus_type);
1217 if (ret < 0) 1223 if (ret < 0) {
1224 destroy_workqueue(fw_wq);
1218 return ret; 1225 return ret;
1226 }
1219 1227
1220 fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops); 1228 fw_cdev_major = register_chrdev(0, "firewire", &fw_device_ops);
1221 if (fw_cdev_major < 0) { 1229 if (fw_cdev_major < 0) {
1222 bus_unregister(&fw_bus_type); 1230 bus_unregister(&fw_bus_type);
1231 destroy_workqueue(fw_wq);
1223 return fw_cdev_major; 1232 return fw_cdev_major;
1224 } 1233 }
1225 1234
@@ -1235,6 +1244,7 @@ static void __exit fw_core_cleanup(void)
1235{ 1244{
1236 unregister_chrdev(fw_cdev_major, "firewire"); 1245 unregister_chrdev(fw_cdev_major, "firewire");
1237 bus_unregister(&fw_bus_type); 1246 bus_unregister(&fw_bus_type);
1247 destroy_workqueue(fw_wq);
1238 idr_destroy(&fw_device_idr); 1248 idr_destroy(&fw_device_idr);
1239} 1249}
1240 1250