aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-card.c5
-rw-r--r--drivers/firewire/core-cdev.c38
-rw-r--r--drivers/firewire/sbp2.c9
3 files changed, 27 insertions, 25 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index e4864e894e4f..33898b63cdf7 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -211,11 +211,8 @@ static const char gap_count_table[] = {
211 211
212void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) 212void fw_schedule_bm_work(struct fw_card *card, unsigned long delay)
213{ 213{
214 int scheduled;
215
216 fw_card_get(card); 214 fw_card_get(card);
217 scheduled = schedule_delayed_work(&card->work, delay); 215 if (!schedule_delayed_work(&card->work, delay))
218 if (!scheduled)
219 fw_card_put(card); 216 fw_card_put(card);
220} 217}
221 218
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 0516acd55ab9..c5f63a939651 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -129,9 +129,22 @@ struct iso_resource {
129 struct iso_resource_event *e_alloc, *e_dealloc; 129 struct iso_resource_event *e_alloc, *e_dealloc;
130}; 130};
131 131
132static void schedule_iso_resource(struct iso_resource *);
133static void release_iso_resource(struct client *, struct client_resource *); 132static void release_iso_resource(struct client *, struct client_resource *);
134 133
134static void schedule_iso_resource(struct iso_resource *r, unsigned long delay)
135{
136 client_get(r->client);
137 if (!schedule_delayed_work(&r->work, delay))
138 client_put(r->client);
139}
140
141static void schedule_if_iso_resource(struct client_resource *resource)
142{
143 if (resource->release == release_iso_resource)
144 schedule_iso_resource(container_of(resource,
145 struct iso_resource, resource), 0);
146}
147
135/* 148/*
136 * dequeue_event() just kfree()'s the event, so the event has to be 149 * dequeue_event() just kfree()'s the event, so the event has to be
137 * the first field in a struct XYZ_event. 150 * the first field in a struct XYZ_event.
@@ -313,11 +326,8 @@ static void for_each_client(struct fw_device *device,
313 326
314static int schedule_reallocations(int id, void *p, void *data) 327static int schedule_reallocations(int id, void *p, void *data)
315{ 328{
316 struct client_resource *r = p; 329 schedule_if_iso_resource(p);
317 330
318 if (r->release == release_iso_resource)
319 schedule_iso_resource(container_of(r,
320 struct iso_resource, resource));
321 return 0; 331 return 0;
322} 332}
323 333
@@ -413,9 +423,7 @@ static int add_client_resource(struct client *client,
413 &resource->handle); 423 &resource->handle);
414 if (ret >= 0) { 424 if (ret >= 0) {
415 client_get(client); 425 client_get(client);
416 if (resource->release == release_iso_resource) 426 schedule_if_iso_resource(resource);
417 schedule_iso_resource(container_of(resource,
418 struct iso_resource, resource));
419 } 427 }
420 spin_unlock_irqrestore(&client->lock, flags); 428 spin_unlock_irqrestore(&client->lock, flags);
421 429
@@ -1032,8 +1040,7 @@ static void iso_resource_work(struct work_struct *work)
1032 /* Allow 1000ms grace period for other reallocations. */ 1040 /* Allow 1000ms grace period for other reallocations. */
1033 if (todo == ISO_RES_ALLOC && 1041 if (todo == ISO_RES_ALLOC &&
1034 time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) { 1042 time_is_after_jiffies(client->device->card->reset_jiffies + HZ)) {
1035 if (schedule_delayed_work(&r->work, DIV_ROUND_UP(HZ, 3))) 1043 schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
1036 client_get(client);
1037 skip = true; 1044 skip = true;
1038 } else { 1045 } else {
1039 /* We could be called twice within the same generation. */ 1046 /* We could be called twice within the same generation. */
@@ -1118,13 +1125,6 @@ static void iso_resource_work(struct work_struct *work)
1118 client_put(client); 1125 client_put(client);
1119} 1126}
1120 1127
1121static void schedule_iso_resource(struct iso_resource *r)
1122{
1123 client_get(r->client);
1124 if (!schedule_delayed_work(&r->work, 0))
1125 client_put(r->client);
1126}
1127
1128static void release_iso_resource(struct client *client, 1128static void release_iso_resource(struct client *client,
1129 struct client_resource *resource) 1129 struct client_resource *resource)
1130{ 1130{
@@ -1133,7 +1133,7 @@ static void release_iso_resource(struct client *client,
1133 1133
1134 spin_lock_irq(&client->lock); 1134 spin_lock_irq(&client->lock);
1135 r->todo = ISO_RES_DEALLOC; 1135 r->todo = ISO_RES_DEALLOC;
1136 schedule_iso_resource(r); 1136 schedule_iso_resource(r, 0);
1137 spin_unlock_irq(&client->lock); 1137 spin_unlock_irq(&client->lock);
1138} 1138}
1139 1139
@@ -1179,7 +1179,7 @@ static int init_iso_resource(struct client *client,
1179 } else { 1179 } else {
1180 r->resource.release = NULL; 1180 r->resource.release = NULL;
1181 r->resource.handle = -1; 1181 r->resource.handle = -1;
1182 schedule_iso_resource(r); 1182 schedule_iso_resource(r, 0);
1183 } 1183 }
1184 request->handle = r->resource.handle; 1184 request->handle = r->resource.handle;
1185 1185
diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c
index 98dbbda3ad41..d485cdd8cbac 100644
--- a/drivers/firewire/sbp2.c
+++ b/drivers/firewire/sbp2.c
@@ -820,20 +820,25 @@ static void sbp2_release_target(struct kref *kref)
820 fw_device_put(device); 820 fw_device_put(device);
821} 821}
822 822
823static struct workqueue_struct *sbp2_wq; 823static void sbp2_target_get(struct sbp2_target *tgt)
824{
825 kref_get(&tgt->kref);
826}
824 827
825static void sbp2_target_put(struct sbp2_target *tgt) 828static void sbp2_target_put(struct sbp2_target *tgt)
826{ 829{
827 kref_put(&tgt->kref, sbp2_release_target); 830 kref_put(&tgt->kref, sbp2_release_target);
828} 831}
829 832
833static struct workqueue_struct *sbp2_wq;
834
830/* 835/*
831 * Always get the target's kref when scheduling work on one its units. 836 * Always get the target's kref when scheduling work on one its units.
832 * Each workqueue job is responsible to call sbp2_target_put() upon return. 837 * Each workqueue job is responsible to call sbp2_target_put() upon return.
833 */ 838 */
834static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) 839static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
835{ 840{
836 kref_get(&lu->tgt->kref); 841 sbp2_target_get(lu->tgt);
837 if (!queue_delayed_work(sbp2_wq, &lu->work, delay)) 842 if (!queue_delayed_work(sbp2_wq, &lu->work, delay))
838 sbp2_target_put(lu->tgt); 843 sbp2_target_put(lu->tgt);
839} 844}