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 | } |
