diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-02 15:38:17 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-03-02 15:38:17 -0500 |
commit | 038f2f725503b55ab76cfd2645915a85594710fe (patch) | |
tree | dfed2103875ec09f4bb4e7031e6eb370f8095c58 | |
parent | 8d07a67cface19ac07d7324f38bda7bbb06bbdb2 (diff) | |
parent | 855c603d61ede7e2810217f15f0d574b4f29c891 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6:
firewire: fix crash in automatic module unloading
firewire: potentially invalid pointers used in fw_card_bm_work
firewire: fw-sbp2: better fix for NULL pointer dereference in scsi_remove_device
-rw-r--r-- | drivers/firewire/fw-card.c | 61 | ||||
-rw-r--r-- | drivers/firewire/fw-device.c | 21 | ||||
-rw-r--r-- | drivers/firewire/fw-device.h | 16 | ||||
-rw-r--r-- | drivers/firewire/fw-sbp2.c | 50 | ||||
-rw-r--r-- | drivers/firewire/fw-topology.c | 1 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 2 |
6 files changed, 97 insertions, 54 deletions
diff --git a/drivers/firewire/fw-card.c b/drivers/firewire/fw-card.c index 3e9719948a8e..a03462750b95 100644 --- a/drivers/firewire/fw-card.c +++ b/drivers/firewire/fw-card.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/errno.h> | 20 | #include <linux/errno.h> |
21 | #include <linux/delay.h> | ||
21 | #include <linux/device.h> | 22 | #include <linux/device.h> |
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
23 | #include <linux/crc-itu-t.h> | 24 | #include <linux/crc-itu-t.h> |
@@ -214,17 +215,29 @@ static void | |||
214 | fw_card_bm_work(struct work_struct *work) | 215 | fw_card_bm_work(struct work_struct *work) |
215 | { | 216 | { |
216 | struct fw_card *card = container_of(work, struct fw_card, work.work); | 217 | struct fw_card *card = container_of(work, struct fw_card, work.work); |
217 | struct fw_device *root; | 218 | struct fw_device *root_device; |
219 | struct fw_node *root_node, *local_node; | ||
218 | struct bm_data bmd; | 220 | struct bm_data bmd; |
219 | unsigned long flags; | 221 | unsigned long flags; |
220 | int root_id, new_root_id, irm_id, gap_count, generation, grace; | 222 | int root_id, new_root_id, irm_id, gap_count, generation, grace; |
221 | int do_reset = 0; | 223 | int do_reset = 0; |
222 | 224 | ||
223 | spin_lock_irqsave(&card->lock, flags); | 225 | spin_lock_irqsave(&card->lock, flags); |
226 | local_node = card->local_node; | ||
227 | root_node = card->root_node; | ||
228 | |||
229 | if (local_node == NULL) { | ||
230 | spin_unlock_irqrestore(&card->lock, flags); | ||
231 | return; | ||
232 | } | ||
233 | fw_node_get(local_node); | ||
234 | fw_node_get(root_node); | ||
224 | 235 | ||
225 | generation = card->generation; | 236 | generation = card->generation; |
226 | root = card->root_node->data; | 237 | root_device = root_node->data; |
227 | root_id = card->root_node->node_id; | 238 | if (root_device) |
239 | fw_device_get(root_device); | ||
240 | root_id = root_node->node_id; | ||
228 | grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); | 241 | grace = time_after(jiffies, card->reset_jiffies + DIV_ROUND_UP(HZ, 10)); |
229 | 242 | ||
230 | if (card->bm_generation + 1 == generation || | 243 | if (card->bm_generation + 1 == generation || |
@@ -243,14 +256,14 @@ fw_card_bm_work(struct work_struct *work) | |||
243 | 256 | ||
244 | irm_id = card->irm_node->node_id; | 257 | irm_id = card->irm_node->node_id; |
245 | if (!card->irm_node->link_on) { | 258 | if (!card->irm_node->link_on) { |
246 | new_root_id = card->local_node->node_id; | 259 | new_root_id = local_node->node_id; |
247 | fw_notify("IRM has link off, making local node (%02x) root.\n", | 260 | fw_notify("IRM has link off, making local node (%02x) root.\n", |
248 | new_root_id); | 261 | new_root_id); |
249 | goto pick_me; | 262 | goto pick_me; |
250 | } | 263 | } |
251 | 264 | ||
252 | bmd.lock.arg = cpu_to_be32(0x3f); | 265 | bmd.lock.arg = cpu_to_be32(0x3f); |
253 | bmd.lock.data = cpu_to_be32(card->local_node->node_id); | 266 | bmd.lock.data = cpu_to_be32(local_node->node_id); |
254 | 267 | ||
255 | spin_unlock_irqrestore(&card->lock, flags); | 268 | spin_unlock_irqrestore(&card->lock, flags); |
256 | 269 | ||
@@ -267,12 +280,12 @@ fw_card_bm_work(struct work_struct *work) | |||
267 | * Another bus reset happened. Just return, | 280 | * Another bus reset happened. Just return, |
268 | * the BM work has been rescheduled. | 281 | * the BM work has been rescheduled. |
269 | */ | 282 | */ |
270 | return; | 283 | goto out; |
271 | } | 284 | } |
272 | 285 | ||
273 | if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) | 286 | if (bmd.rcode == RCODE_COMPLETE && bmd.old != 0x3f) |
274 | /* Somebody else is BM, let them do the work. */ | 287 | /* Somebody else is BM, let them do the work. */ |
275 | return; | 288 | goto out; |
276 | 289 | ||
277 | spin_lock_irqsave(&card->lock, flags); | 290 | spin_lock_irqsave(&card->lock, flags); |
278 | if (bmd.rcode != RCODE_COMPLETE) { | 291 | if (bmd.rcode != RCODE_COMPLETE) { |
@@ -282,7 +295,7 @@ fw_card_bm_work(struct work_struct *work) | |||
282 | * do a bus reset and pick the local node as | 295 | * do a bus reset and pick the local node as |
283 | * root, and thus, IRM. | 296 | * root, and thus, IRM. |
284 | */ | 297 | */ |
285 | new_root_id = card->local_node->node_id; | 298 | new_root_id = local_node->node_id; |
286 | fw_notify("BM lock failed, making local node (%02x) root.\n", | 299 | fw_notify("BM lock failed, making local node (%02x) root.\n", |
287 | new_root_id); | 300 | new_root_id); |
288 | goto pick_me; | 301 | goto pick_me; |
@@ -295,7 +308,7 @@ fw_card_bm_work(struct work_struct *work) | |||
295 | */ | 308 | */ |
296 | spin_unlock_irqrestore(&card->lock, flags); | 309 | spin_unlock_irqrestore(&card->lock, flags); |
297 | schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); | 310 | schedule_delayed_work(&card->work, DIV_ROUND_UP(HZ, 10)); |
298 | return; | 311 | goto out; |
299 | } | 312 | } |
300 | 313 | ||
301 | /* | 314 | /* |
@@ -305,20 +318,20 @@ fw_card_bm_work(struct work_struct *work) | |||
305 | */ | 318 | */ |
306 | card->bm_generation = generation; | 319 | card->bm_generation = generation; |
307 | 320 | ||
308 | if (root == NULL) { | 321 | if (root_device == NULL) { |
309 | /* | 322 | /* |
310 | * Either link_on is false, or we failed to read the | 323 | * Either link_on is false, or we failed to read the |
311 | * config rom. In either case, pick another root. | 324 | * config rom. In either case, pick another root. |
312 | */ | 325 | */ |
313 | new_root_id = card->local_node->node_id; | 326 | new_root_id = local_node->node_id; |
314 | } else if (atomic_read(&root->state) != FW_DEVICE_RUNNING) { | 327 | } else if (atomic_read(&root_device->state) != FW_DEVICE_RUNNING) { |
315 | /* | 328 | /* |
316 | * If we haven't probed this device yet, bail out now | 329 | * If we haven't probed this device yet, bail out now |
317 | * and let's try again once that's done. | 330 | * and let's try again once that's done. |
318 | */ | 331 | */ |
319 | spin_unlock_irqrestore(&card->lock, flags); | 332 | spin_unlock_irqrestore(&card->lock, flags); |
320 | return; | 333 | goto out; |
321 | } else if (root->config_rom[2] & BIB_CMC) { | 334 | } else if (root_device->config_rom[2] & BIB_CMC) { |
322 | /* | 335 | /* |
323 | * FIXME: I suppose we should set the cmstr bit in the | 336 | * FIXME: I suppose we should set the cmstr bit in the |
324 | * STATE_CLEAR register of this node, as described in | 337 | * STATE_CLEAR register of this node, as described in |
@@ -332,7 +345,7 @@ fw_card_bm_work(struct work_struct *work) | |||
332 | * successfully read the config rom, but it's not | 345 | * successfully read the config rom, but it's not |
333 | * cycle master capable. | 346 | * cycle master capable. |
334 | */ | 347 | */ |
335 | new_root_id = card->local_node->node_id; | 348 | new_root_id = local_node->node_id; |
336 | } | 349 | } |
337 | 350 | ||
338 | pick_me: | 351 | pick_me: |
@@ -341,8 +354,8 @@ fw_card_bm_work(struct work_struct *work) | |||
341 | * the typically much larger 1394b beta repeater delays though. | 354 | * the typically much larger 1394b beta repeater delays though. |
342 | */ | 355 | */ |
343 | if (!card->beta_repeaters_present && | 356 | if (!card->beta_repeaters_present && |
344 | card->root_node->max_hops < ARRAY_SIZE(gap_count_table)) | 357 | root_node->max_hops < ARRAY_SIZE(gap_count_table)) |
345 | gap_count = gap_count_table[card->root_node->max_hops]; | 358 | gap_count = gap_count_table[root_node->max_hops]; |
346 | else | 359 | else |
347 | gap_count = 63; | 360 | gap_count = 63; |
348 | 361 | ||
@@ -364,6 +377,11 @@ fw_card_bm_work(struct work_struct *work) | |||
364 | fw_send_phy_config(card, new_root_id, generation, gap_count); | 377 | fw_send_phy_config(card, new_root_id, generation, gap_count); |
365 | fw_core_initiate_bus_reset(card, 1); | 378 | fw_core_initiate_bus_reset(card, 1); |
366 | } | 379 | } |
380 | out: | ||
381 | if (root_device) | ||
382 | fw_device_put(root_device); | ||
383 | fw_node_put(root_node); | ||
384 | fw_node_put(local_node); | ||
367 | } | 385 | } |
368 | 386 | ||
369 | static void | 387 | static void |
@@ -381,6 +399,7 @@ fw_card_initialize(struct fw_card *card, const struct fw_card_driver *driver, | |||
381 | static atomic_t index = ATOMIC_INIT(-1); | 399 | static atomic_t index = ATOMIC_INIT(-1); |
382 | 400 | ||
383 | kref_init(&card->kref); | 401 | kref_init(&card->kref); |
402 | atomic_set(&card->device_count, 0); | ||
384 | card->index = atomic_inc_return(&index); | 403 | card->index = atomic_inc_return(&index); |
385 | card->driver = driver; | 404 | card->driver = driver; |
386 | card->device = device; | 405 | card->device = device; |
@@ -511,8 +530,14 @@ fw_core_remove_card(struct fw_card *card) | |||
511 | card->driver = &dummy_driver; | 530 | card->driver = &dummy_driver; |
512 | 531 | ||
513 | fw_destroy_nodes(card); | 532 | fw_destroy_nodes(card); |
514 | flush_scheduled_work(); | 533 | /* |
534 | * Wait for all device workqueue jobs to finish. Otherwise the | ||
535 | * firewire-core module could be unloaded before the jobs ran. | ||
536 | */ | ||
537 | while (atomic_read(&card->device_count) > 0) | ||
538 | msleep(100); | ||
515 | 539 | ||
540 | cancel_delayed_work_sync(&card->work); | ||
516 | fw_flush_transactions(card); | 541 | fw_flush_transactions(card); |
517 | del_timer_sync(&card->flush_timer); | 542 | del_timer_sync(&card->flush_timer); |
518 | 543 | ||
diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 2ab13e0f3469..870125a3638e 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c | |||
@@ -150,21 +150,10 @@ struct bus_type fw_bus_type = { | |||
150 | }; | 150 | }; |
151 | EXPORT_SYMBOL(fw_bus_type); | 151 | EXPORT_SYMBOL(fw_bus_type); |
152 | 152 | ||
153 | struct fw_device *fw_device_get(struct fw_device *device) | ||
154 | { | ||
155 | get_device(&device->device); | ||
156 | |||
157 | return device; | ||
158 | } | ||
159 | |||
160 | void fw_device_put(struct fw_device *device) | ||
161 | { | ||
162 | put_device(&device->device); | ||
163 | } | ||
164 | |||
165 | static void fw_device_release(struct device *dev) | 153 | static void fw_device_release(struct device *dev) |
166 | { | 154 | { |
167 | struct fw_device *device = fw_device(dev); | 155 | struct fw_device *device = fw_device(dev); |
156 | struct fw_card *card = device->card; | ||
168 | unsigned long flags; | 157 | unsigned long flags; |
169 | 158 | ||
170 | /* | 159 | /* |
@@ -176,9 +165,9 @@ static void fw_device_release(struct device *dev) | |||
176 | spin_unlock_irqrestore(&device->card->lock, flags); | 165 | spin_unlock_irqrestore(&device->card->lock, flags); |
177 | 166 | ||
178 | fw_node_put(device->node); | 167 | fw_node_put(device->node); |
179 | fw_card_put(device->card); | ||
180 | kfree(device->config_rom); | 168 | kfree(device->config_rom); |
181 | kfree(device); | 169 | kfree(device); |
170 | atomic_dec(&card->device_count); | ||
182 | } | 171 | } |
183 | 172 | ||
184 | int fw_device_enable_phys_dma(struct fw_device *device) | 173 | int fw_device_enable_phys_dma(struct fw_device *device) |
@@ -668,7 +657,8 @@ static void fw_device_init(struct work_struct *work) | |||
668 | */ | 657 | */ |
669 | 658 | ||
670 | if (read_bus_info_block(device, device->generation) < 0) { | 659 | if (read_bus_info_block(device, device->generation) < 0) { |
671 | if (device->config_rom_retries < MAX_RETRIES) { | 660 | if (device->config_rom_retries < MAX_RETRIES && |
661 | atomic_read(&device->state) == FW_DEVICE_INITIALIZING) { | ||
672 | device->config_rom_retries++; | 662 | device->config_rom_retries++; |
673 | schedule_delayed_work(&device->work, RETRY_DELAY); | 663 | schedule_delayed_work(&device->work, RETRY_DELAY); |
674 | } else { | 664 | } else { |
@@ -805,7 +795,8 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event) | |||
805 | */ | 795 | */ |
806 | device_initialize(&device->device); | 796 | device_initialize(&device->device); |
807 | atomic_set(&device->state, FW_DEVICE_INITIALIZING); | 797 | atomic_set(&device->state, FW_DEVICE_INITIALIZING); |
808 | device->card = fw_card_get(card); | 798 | atomic_inc(&card->device_count); |
799 | device->card = card; | ||
809 | device->node = fw_node_get(node); | 800 | device->node = fw_node_get(node); |
810 | device->node_id = node->node_id; | 801 | device->node_id = node->node_id; |
811 | device->generation = card->generation; | 802 | device->generation = card->generation; |
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index 43808c02793e..78ecd3991b7f 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h | |||
@@ -76,9 +76,21 @@ fw_device_is_shutdown(struct fw_device *device) | |||
76 | return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN; | 76 | return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN; |
77 | } | 77 | } |
78 | 78 | ||
79 | struct fw_device *fw_device_get(struct fw_device *device); | 79 | static inline struct fw_device * |
80 | fw_device_get(struct fw_device *device) | ||
81 | { | ||
82 | get_device(&device->device); | ||
83 | |||
84 | return device; | ||
85 | } | ||
86 | |||
87 | static inline void | ||
88 | fw_device_put(struct fw_device *device) | ||
89 | { | ||
90 | put_device(&device->device); | ||
91 | } | ||
92 | |||
80 | struct fw_device *fw_device_get_by_devt(dev_t devt); | 93 | struct fw_device *fw_device_get_by_devt(dev_t devt); |
81 | void fw_device_put(struct fw_device *device); | ||
82 | int fw_device_enable_phys_dma(struct fw_device *device); | 94 | int fw_device_enable_phys_dma(struct fw_device *device); |
83 | 95 | ||
84 | void fw_device_cdev_update(struct fw_device *device); | 96 | void fw_device_cdev_update(struct fw_device *device); |
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 5259491580fc..03069a454c07 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
@@ -122,7 +122,6 @@ static const char sbp2_driver_name[] = "sbp2"; | |||
122 | struct sbp2_logical_unit { | 122 | struct sbp2_logical_unit { |
123 | struct sbp2_target *tgt; | 123 | struct sbp2_target *tgt; |
124 | struct list_head link; | 124 | struct list_head link; |
125 | struct scsi_device *sdev; | ||
126 | struct fw_address_handler address_handler; | 125 | struct fw_address_handler address_handler; |
127 | struct list_head orb_list; | 126 | struct list_head orb_list; |
128 | 127 | ||
@@ -139,6 +138,7 @@ struct sbp2_logical_unit { | |||
139 | int generation; | 138 | int generation; |
140 | int retries; | 139 | int retries; |
141 | struct delayed_work work; | 140 | struct delayed_work work; |
141 | bool has_sdev; | ||
142 | bool blocked; | 142 | bool blocked; |
143 | }; | 143 | }; |
144 | 144 | ||
@@ -751,20 +751,34 @@ static void sbp2_unblock(struct sbp2_target *tgt) | |||
751 | scsi_unblock_requests(shost); | 751 | scsi_unblock_requests(shost); |
752 | } | 752 | } |
753 | 753 | ||
754 | static int sbp2_lun2int(u16 lun) | ||
755 | { | ||
756 | struct scsi_lun eight_bytes_lun; | ||
757 | |||
758 | memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun)); | ||
759 | eight_bytes_lun.scsi_lun[0] = (lun >> 8) & 0xff; | ||
760 | eight_bytes_lun.scsi_lun[1] = lun & 0xff; | ||
761 | |||
762 | return scsilun_to_int(&eight_bytes_lun); | ||
763 | } | ||
764 | |||
754 | static void sbp2_release_target(struct kref *kref) | 765 | static void sbp2_release_target(struct kref *kref) |
755 | { | 766 | { |
756 | struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref); | 767 | struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref); |
757 | struct sbp2_logical_unit *lu, *next; | 768 | struct sbp2_logical_unit *lu, *next; |
758 | struct Scsi_Host *shost = | 769 | struct Scsi_Host *shost = |
759 | container_of((void *)tgt, struct Scsi_Host, hostdata[0]); | 770 | container_of((void *)tgt, struct Scsi_Host, hostdata[0]); |
771 | struct scsi_device *sdev; | ||
772 | struct fw_device *device = fw_device(tgt->unit->device.parent); | ||
760 | 773 | ||
761 | /* prevent deadlocks */ | 774 | /* prevent deadlocks */ |
762 | sbp2_unblock(tgt); | 775 | sbp2_unblock(tgt); |
763 | 776 | ||
764 | list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { | 777 | list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { |
765 | if (lu->sdev) { | 778 | sdev = scsi_device_lookup(shost, 0, 0, sbp2_lun2int(lu->lun)); |
766 | scsi_remove_device(lu->sdev); | 779 | if (sdev) { |
767 | scsi_device_put(lu->sdev); | 780 | scsi_remove_device(sdev); |
781 | scsi_device_put(sdev); | ||
768 | } | 782 | } |
769 | sbp2_send_management_orb(lu, tgt->node_id, lu->generation, | 783 | sbp2_send_management_orb(lu, tgt->node_id, lu->generation, |
770 | SBP2_LOGOUT_REQUEST, lu->login_id, NULL); | 784 | SBP2_LOGOUT_REQUEST, lu->login_id, NULL); |
@@ -778,6 +792,7 @@ static void sbp2_release_target(struct kref *kref) | |||
778 | 792 | ||
779 | put_device(&tgt->unit->device); | 793 | put_device(&tgt->unit->device); |
780 | scsi_host_put(shost); | 794 | scsi_host_put(shost); |
795 | fw_device_put(device); | ||
781 | } | 796 | } |
782 | 797 | ||
783 | static struct workqueue_struct *sbp2_wq; | 798 | static struct workqueue_struct *sbp2_wq; |
@@ -807,7 +822,6 @@ static void sbp2_login(struct work_struct *work) | |||
807 | struct fw_device *device = fw_device(tgt->unit->device.parent); | 822 | struct fw_device *device = fw_device(tgt->unit->device.parent); |
808 | struct Scsi_Host *shost; | 823 | struct Scsi_Host *shost; |
809 | struct scsi_device *sdev; | 824 | struct scsi_device *sdev; |
810 | struct scsi_lun eight_bytes_lun; | ||
811 | struct sbp2_login_response response; | 825 | struct sbp2_login_response response; |
812 | int generation, node_id, local_node_id; | 826 | int generation, node_id, local_node_id; |
813 | 827 | ||
@@ -820,7 +834,7 @@ static void sbp2_login(struct work_struct *work) | |||
820 | local_node_id = device->card->node_id; | 834 | local_node_id = device->card->node_id; |
821 | 835 | ||
822 | /* If this is a re-login attempt, log out, or we might be rejected. */ | 836 | /* If this is a re-login attempt, log out, or we might be rejected. */ |
823 | if (lu->sdev) | 837 | if (lu->has_sdev) |
824 | sbp2_send_management_orb(lu, device->node_id, generation, | 838 | sbp2_send_management_orb(lu, device->node_id, generation, |
825 | SBP2_LOGOUT_REQUEST, lu->login_id, NULL); | 839 | SBP2_LOGOUT_REQUEST, lu->login_id, NULL); |
826 | 840 | ||
@@ -859,7 +873,7 @@ static void sbp2_login(struct work_struct *work) | |||
859 | sbp2_agent_reset(lu); | 873 | sbp2_agent_reset(lu); |
860 | 874 | ||
861 | /* This was a re-login. */ | 875 | /* This was a re-login. */ |
862 | if (lu->sdev) { | 876 | if (lu->has_sdev) { |
863 | sbp2_cancel_orbs(lu); | 877 | sbp2_cancel_orbs(lu); |
864 | sbp2_conditionally_unblock(lu); | 878 | sbp2_conditionally_unblock(lu); |
865 | goto out; | 879 | goto out; |
@@ -868,13 +882,8 @@ static void sbp2_login(struct work_struct *work) | |||
868 | if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) | 882 | if (lu->tgt->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY) |
869 | ssleep(SBP2_INQUIRY_DELAY); | 883 | ssleep(SBP2_INQUIRY_DELAY); |
870 | 884 | ||
871 | memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun)); | ||
872 | eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff; | ||
873 | eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff; | ||
874 | shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); | 885 | shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); |
875 | 886 | sdev = __scsi_add_device(shost, 0, 0, sbp2_lun2int(lu->lun), lu); | |
876 | sdev = __scsi_add_device(shost, 0, 0, | ||
877 | scsilun_to_int(&eight_bytes_lun), lu); | ||
878 | /* | 887 | /* |
879 | * FIXME: We are unable to perform reconnects while in sbp2_login(). | 888 | * FIXME: We are unable to perform reconnects while in sbp2_login(). |
880 | * Therefore __scsi_add_device() will get into trouble if a bus reset | 889 | * Therefore __scsi_add_device() will get into trouble if a bus reset |
@@ -896,7 +905,8 @@ static void sbp2_login(struct work_struct *work) | |||
896 | } | 905 | } |
897 | 906 | ||
898 | /* No error during __scsi_add_device() */ | 907 | /* No error during __scsi_add_device() */ |
899 | lu->sdev = sdev; | 908 | lu->has_sdev = true; |
909 | scsi_device_put(sdev); | ||
900 | sbp2_allow_block(lu); | 910 | sbp2_allow_block(lu); |
901 | goto out; | 911 | goto out; |
902 | 912 | ||
@@ -934,11 +944,11 @@ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) | |||
934 | return -ENOMEM; | 944 | return -ENOMEM; |
935 | } | 945 | } |
936 | 946 | ||
937 | lu->tgt = tgt; | 947 | lu->tgt = tgt; |
938 | lu->sdev = NULL; | 948 | lu->lun = lun_entry & 0xffff; |
939 | lu->lun = lun_entry & 0xffff; | 949 | lu->retries = 0; |
940 | lu->retries = 0; | 950 | lu->has_sdev = false; |
941 | lu->blocked = false; | 951 | lu->blocked = false; |
942 | ++tgt->dont_block; | 952 | ++tgt->dont_block; |
943 | INIT_LIST_HEAD(&lu->orb_list); | 953 | INIT_LIST_HEAD(&lu->orb_list); |
944 | INIT_DELAYED_WORK(&lu->work, sbp2_login); | 954 | INIT_DELAYED_WORK(&lu->work, sbp2_login); |
@@ -1080,6 +1090,8 @@ static int sbp2_probe(struct device *dev) | |||
1080 | if (scsi_add_host(shost, &unit->device) < 0) | 1090 | if (scsi_add_host(shost, &unit->device) < 0) |
1081 | goto fail_shost_put; | 1091 | goto fail_shost_put; |
1082 | 1092 | ||
1093 | fw_device_get(device); | ||
1094 | |||
1083 | /* Initialize to values that won't match anything in our table. */ | 1095 | /* Initialize to values that won't match anything in our table. */ |
1084 | firmware_revision = 0xff000000; | 1096 | firmware_revision = 0xff000000; |
1085 | model = 0xff000000; | 1097 | model = 0xff000000; |
diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c index 172c1867e9aa..e47bb040197a 100644 --- a/drivers/firewire/fw-topology.c +++ b/drivers/firewire/fw-topology.c | |||
@@ -383,6 +383,7 @@ void fw_destroy_nodes(struct fw_card *card) | |||
383 | card->color++; | 383 | card->color++; |
384 | if (card->local_node != NULL) | 384 | if (card->local_node != NULL) |
385 | for_each_fw_node(card, card->local_node, report_lost_node); | 385 | for_each_fw_node(card, card->local_node, report_lost_node); |
386 | card->local_node = NULL; | ||
386 | spin_unlock_irqrestore(&card->lock, flags); | 387 | spin_unlock_irqrestore(&card->lock, flags); |
387 | } | 388 | } |
388 | 389 | ||
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index fa7967b57408..09cb72870454 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
28 | #include <linux/firewire-constants.h> | 28 | #include <linux/firewire-constants.h> |
29 | #include <asm/atomic.h> | ||
29 | 30 | ||
30 | #define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) | 31 | #define TCODE_IS_READ_REQUEST(tcode) (((tcode) & ~1) == 4) |
31 | #define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) | 32 | #define TCODE_IS_BLOCK_PACKET(tcode) (((tcode) & 1) != 0) |
@@ -219,6 +220,7 @@ extern struct bus_type fw_bus_type; | |||
219 | struct fw_card { | 220 | struct fw_card { |
220 | const struct fw_card_driver *driver; | 221 | const struct fw_card_driver *driver; |
221 | struct device *device; | 222 | struct device *device; |
223 | atomic_t device_count; | ||
222 | struct kref kref; | 224 | struct kref kref; |
223 | 225 | ||
224 | int node_id; | 226 | int node_id; |