diff options
-rw-r--r-- | drivers/firewire/core-card.c | 5 | ||||
-rw-r--r-- | drivers/firewire/core-cdev.c | 38 | ||||
-rw-r--r-- | drivers/firewire/sbp2.c | 9 |
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 | ||
212 | void fw_schedule_bm_work(struct fw_card *card, unsigned long delay) | 212 | void 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 | ||
132 | static void schedule_iso_resource(struct iso_resource *); | ||
133 | static void release_iso_resource(struct client *, struct client_resource *); | 132 | static void release_iso_resource(struct client *, struct client_resource *); |
134 | 133 | ||
134 | static 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 | |||
141 | static 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 | ||
314 | static int schedule_reallocations(int id, void *p, void *data) | 327 | static 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 | ||
1121 | static 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 | |||
1128 | static void release_iso_resource(struct client *client, | 1128 | static 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 | ||
823 | static struct workqueue_struct *sbp2_wq; | 823 | static void sbp2_target_get(struct sbp2_target *tgt) |
824 | { | ||
825 | kref_get(&tgt->kref); | ||
826 | } | ||
824 | 827 | ||
825 | static void sbp2_target_put(struct sbp2_target *tgt) | 828 | static 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 | ||
833 | static 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 | */ |
834 | static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) | 839 | static 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 | } |