aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/firewire/core-card.c6
-rw-r--r--drivers/firewire/core-cdev.c2
-rw-r--r--drivers/firewire/core-device.c30
-rw-r--r--drivers/firewire/core-transaction.c12
-rw-r--r--drivers/firewire/core.h2
5 files changed, 36 insertions, 16 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index f05fc7bfceeb..bb8c4d22b03e 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -228,8 +228,8 @@ void fw_schedule_bus_reset(struct fw_card *card, bool delayed, bool short_reset)
228 228
229 /* Use an arbitrary short delay to combine multiple reset requests. */ 229 /* Use an arbitrary short delay to combine multiple reset requests. */
230 fw_card_get(card); 230 fw_card_get(card);
231 if (!schedule_delayed_work(&card->br_work, 231 if (!queue_delayed_work(fw_wq, &card->br_work,
232 delayed ? DIV_ROUND_UP(HZ, 100) : 0)) 232 delayed ? DIV_ROUND_UP(HZ, 100) : 0))
233 fw_card_put(card); 233 fw_card_put(card);
234} 234}
235EXPORT_SYMBOL(fw_schedule_bus_reset); 235EXPORT_SYMBOL(fw_schedule_bus_reset);
@@ -241,7 +241,7 @@ static void br_work(struct work_struct *work)
241 /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */ 241 /* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
242 if (card->reset_jiffies != 0 && 242 if (card->reset_jiffies != 0 &&
243 time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) { 243 time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
244 if (!schedule_delayed_work(&card->br_work, 2 * HZ)) 244 if (!queue_delayed_work(fw_wq, &card->br_work, 2 * HZ))
245 fw_card_put(card); 245 fw_card_put(card);
246 return; 246 return;
247 } 247 }
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 64768c2194f1..aa1131d26e30 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -149,7 +149,7 @@ static void release_iso_resource(struct client *, struct client_resource *);
149static void schedule_iso_resource(struct iso_resource *r, unsigned long delay) 149static void schedule_iso_resource(struct iso_resource *r, unsigned long delay)
150{ 150{
151 client_get(r->client); 151 client_get(r->client);
152 if (!schedule_delayed_work(&r->work, delay)) 152 if (!queue_delayed_work(fw_wq, &r->work, delay))
153 client_put(r->client); 153 client_put(r->client);
154} 154}
155 155
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 9a262439e3a7..ef900d923f15 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -725,6 +725,14 @@ struct fw_device *fw_device_get_by_devt(dev_t devt)
725 return device; 725 return device;
726} 726}
727 727
728struct workqueue_struct *fw_wq;
729
730static void fw_schedule_device_work(struct fw_device *device,
731 unsigned long delay)
732{
733 queue_delayed_work(fw_wq, &device->work, delay);
734}
735
728/* 736/*
729 * These defines control the retry behavior for reading the config 737 * These defines control the retry behavior for reading the config
730 * rom. It shouldn't be necessary to tweak these; if the device 738 * rom. It shouldn't be necessary to tweak these; if the device
@@ -750,7 +758,7 @@ static void fw_device_shutdown(struct work_struct *work)
750 if (time_before64(get_jiffies_64(), 758 if (time_before64(get_jiffies_64(),
751 device->card->reset_jiffies + SHUTDOWN_DELAY) 759 device->card->reset_jiffies + SHUTDOWN_DELAY)
752 && !list_empty(&device->card->link)) { 760 && !list_empty(&device->card->link)) {
753 schedule_delayed_work(&device->work, SHUTDOWN_DELAY); 761 fw_schedule_device_work(device, SHUTDOWN_DELAY);
754 return; 762 return;
755 } 763 }
756 764
@@ -862,7 +870,7 @@ static int lookup_existing_device(struct device *dev, void *data)
862 fw_notify("rediscovered device %s\n", dev_name(dev)); 870 fw_notify("rediscovered device %s\n", dev_name(dev));
863 871
864 PREPARE_DELAYED_WORK(&old->work, fw_device_update); 872 PREPARE_DELAYED_WORK(&old->work, fw_device_update);
865 schedule_delayed_work(&old->work, 0); 873 fw_schedule_device_work(old, 0);
866 874
867 if (current_node == card->root_node) 875 if (current_node == card->root_node)
868 fw_schedule_bm_work(card, 0); 876 fw_schedule_bm_work(card, 0);
@@ -953,7 +961,7 @@ static void fw_device_init(struct work_struct *work)
953 if (device->config_rom_retries < MAX_RETRIES && 961 if (device->config_rom_retries < MAX_RETRIES &&
954 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 962 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
955 device->config_rom_retries++; 963 device->config_rom_retries++;
956 schedule_delayed_work(&device->work, RETRY_DELAY); 964 fw_schedule_device_work(device, RETRY_DELAY);
957 } else { 965 } else {
958 if (device->node->link_on) 966 if (device->node->link_on)
959 fw_notify("giving up on config rom for node id %x\n", 967 fw_notify("giving up on config rom for node id %x\n",
@@ -1019,7 +1027,7 @@ static void fw_device_init(struct work_struct *work)
1019 FW_DEVICE_INITIALIZING, 1027 FW_DEVICE_INITIALIZING,
1020 FW_DEVICE_RUNNING) == FW_DEVICE_GONE) { 1028 FW_DEVICE_RUNNING) == FW_DEVICE_GONE) {
1021 PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); 1029 PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
1022 schedule_delayed_work(&device->work, SHUTDOWN_DELAY); 1030 fw_schedule_device_work(device, SHUTDOWN_DELAY);
1023 } else { 1031 } else {
1024 if (device->config_rom_retries) 1032 if (device->config_rom_retries)
1025 fw_notify("created device %s: GUID %08x%08x, S%d00, " 1033 fw_notify("created device %s: GUID %08x%08x, S%d00, "
@@ -1098,7 +1106,7 @@ static void fw_device_refresh(struct work_struct *work)
1098 if (device->config_rom_retries < MAX_RETRIES / 2 && 1106 if (device->config_rom_retries < MAX_RETRIES / 2 &&
1099 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 1107 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
1100 device->config_rom_retries++; 1108 device->config_rom_retries++;
1101 schedule_delayed_work(&device->work, RETRY_DELAY / 2); 1109 fw_schedule_device_work(device, RETRY_DELAY / 2);
1102 1110
1103 return; 1111 return;
1104 } 1112 }
@@ -1131,7 +1139,7 @@ static void fw_device_refresh(struct work_struct *work)
1131 if (device->config_rom_retries < MAX_RETRIES && 1139 if (device->config_rom_retries < MAX_RETRIES &&
1132 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { 1140 atomic_read(&device->state) == FW_DEVICE_INITIALIZING) {
1133 device->config_rom_retries++; 1141 device->config_rom_retries++;
1134 schedule_delayed_work(&device->work, RETRY_DELAY); 1142 fw_schedule_device_work(device, RETRY_DELAY);
1135 1143
1136 return; 1144 return;
1137 } 1145 }
@@ -1158,7 +1166,7 @@ static void fw_device_refresh(struct work_struct *work)
1158 gone: 1166 gone:
1159 atomic_set(&device->state, FW_DEVICE_GONE); 1167 atomic_set(&device->state, FW_DEVICE_GONE);
1160 PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); 1168 PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
1161 schedule_delayed_work(&device->work, SHUTDOWN_DELAY); 1169 fw_schedule_device_work(device, SHUTDOWN_DELAY);
1162 out: 1170 out:
1163 if (node_id == card->root_node->node_id) 1171 if (node_id == card->root_node->node_id)
1164 fw_schedule_bm_work(card, 0); 1172 fw_schedule_bm_work(card, 0);
@@ -1214,7 +1222,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
1214 * first config rom scan half a second after bus reset. 1222 * first config rom scan half a second after bus reset.
1215 */ 1223 */
1216 INIT_DELAYED_WORK(&device->work, fw_device_init); 1224 INIT_DELAYED_WORK(&device->work, fw_device_init);
1217 schedule_delayed_work(&device->work, INITIAL_DELAY); 1225 fw_schedule_device_work(device, INITIAL_DELAY);
1218 break; 1226 break;
1219 1227
1220 case FW_NODE_INITIATED_RESET: 1228 case FW_NODE_INITIATED_RESET:
@@ -1230,7 +1238,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
1230 FW_DEVICE_RUNNING, 1238 FW_DEVICE_RUNNING,
1231 FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) { 1239 FW_DEVICE_INITIALIZING) == FW_DEVICE_RUNNING) {
1232 PREPARE_DELAYED_WORK(&device->work, fw_device_refresh); 1240 PREPARE_DELAYED_WORK(&device->work, fw_device_refresh);
1233 schedule_delayed_work(&device->work, 1241 fw_schedule_device_work(device,
1234 device->is_local ? 0 : INITIAL_DELAY); 1242 device->is_local ? 0 : INITIAL_DELAY);
1235 } 1243 }
1236 break; 1244 break;
@@ -1245,7 +1253,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
1245 device->generation = card->generation; 1253 device->generation = card->generation;
1246 if (atomic_read(&device->state) == FW_DEVICE_RUNNING) { 1254 if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
1247 PREPARE_DELAYED_WORK(&device->work, fw_device_update); 1255 PREPARE_DELAYED_WORK(&device->work, fw_device_update);
1248 schedule_delayed_work(&device->work, 0); 1256 fw_schedule_device_work(device, 0);
1249 } 1257 }
1250 break; 1258 break;
1251 1259
@@ -1270,7 +1278,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
1270 if (atomic_xchg(&device->state, 1278 if (atomic_xchg(&device->state,
1271 FW_DEVICE_GONE) == FW_DEVICE_RUNNING) { 1279 FW_DEVICE_GONE) == FW_DEVICE_RUNNING) {
1272 PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown); 1280 PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);
1273 schedule_delayed_work(&device->work, 1281 fw_schedule_device_work(device,
1274 list_empty(&card->link) ? 0 : SHUTDOWN_DELAY); 1282 list_empty(&card->link) ? 0 : SHUTDOWN_DELAY);
1275 } 1283 }
1276 break; 1284 break;
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
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 0fe4e4e6eda7..00ea7730c6a7 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -140,6 +140,8 @@ void fw_cdev_handle_phy_packet(struct fw_card *card, struct fw_packet *p);
140extern struct rw_semaphore fw_device_rwsem; 140extern struct rw_semaphore fw_device_rwsem;
141extern struct idr fw_device_idr; 141extern struct idr fw_device_idr;
142extern int fw_cdev_major; 142extern int fw_cdev_major;
143struct workqueue_struct;
144extern struct workqueue_struct *fw_wq;
143 145
144struct fw_device *fw_device_get_by_devt(dev_t devt); 146struct fw_device *fw_device_get_by_devt(dev_t devt);
145int fw_device_set_broadcast_channel(struct device *dev, void *gen); 147int fw_device_set_broadcast_channel(struct device *dev, void *gen);