diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-08-25 08:05:28 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-10-16 18:00:03 -0400 |
commit | 5a3c2be6c9a5641a06c71c906645d676fa4d3fdc (patch) | |
tree | 6c639fecc4f8e7b613e79065b5edb4a3293287d8 | |
parent | 1b34e97441384d527c438a6ee597bfc800373bce (diff) |
firewire: fw-sbp2: add support for multiple logical units per target
Fixes "New firewire stack only recognizing half of a chain of drives",
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=242254
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r-- | drivers/firewire/fw-device.h | 5 | ||||
-rw-r--r-- | drivers/firewire/fw-sbp2.c | 575 |
2 files changed, 324 insertions, 256 deletions
diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h index d13e6a69707f..894d4a92a18e 100644 --- a/drivers/firewire/fw-device.h +++ b/drivers/firewire/fw-device.h | |||
@@ -102,11 +102,6 @@ fw_unit(struct device *dev) | |||
102 | #define CSR_INSTANCE 0x18 | 102 | #define CSR_INSTANCE 0x18 |
103 | #define CSR_DIRECTORY_ID 0x20 | 103 | #define CSR_DIRECTORY_ID 0x20 |
104 | 104 | ||
105 | #define SBP2_COMMAND_SET_SPECIFIER 0x38 | ||
106 | #define SBP2_COMMAND_SET 0x39 | ||
107 | #define SBP2_COMMAND_SET_REVISION 0x3b | ||
108 | #define SBP2_FIRMWARE_REVISION 0x3c | ||
109 | |||
110 | struct fw_csr_iterator { | 105 | struct fw_csr_iterator { |
111 | u32 *p; | 106 | u32 *p; |
112 | u32 *end; | 107 | u32 *end; |
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 7ecc154a8274..1efc67b1d26e 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
@@ -41,7 +41,6 @@ | |||
41 | 41 | ||
42 | #include <scsi/scsi.h> | 42 | #include <scsi/scsi.h> |
43 | #include <scsi/scsi_cmnd.h> | 43 | #include <scsi/scsi_cmnd.h> |
44 | #include <scsi/scsi_dbg.h> | ||
45 | #include <scsi/scsi_device.h> | 44 | #include <scsi/scsi_device.h> |
46 | #include <scsi/scsi_host.h> | 45 | #include <scsi/scsi_host.h> |
47 | 46 | ||
@@ -66,31 +65,49 @@ typedef void (*scsi_done_fn_t)(struct scsi_cmnd *); | |||
66 | 65 | ||
67 | static const char sbp2_driver_name[] = "sbp2"; | 66 | static const char sbp2_driver_name[] = "sbp2"; |
68 | 67 | ||
69 | struct sbp2_device { | 68 | /* |
70 | struct kref kref; | 69 | * We create one struct sbp2_logical_unit per SBP-2 Logical Unit Number Entry |
71 | struct fw_unit *unit; | 70 | * and one struct scsi_device per sbp2_logical_unit. |
71 | */ | ||
72 | struct sbp2_logical_unit { | ||
73 | struct sbp2_target *tgt; | ||
74 | struct list_head link; | ||
75 | struct scsi_device *sdev; | ||
72 | struct fw_address_handler address_handler; | 76 | struct fw_address_handler address_handler; |
73 | struct list_head orb_list; | 77 | struct list_head orb_list; |
74 | u64 management_agent_address; | 78 | |
75 | u64 command_block_agent_address; | 79 | u64 command_block_agent_address; |
76 | u32 workarounds; | 80 | u16 lun; |
77 | int login_id; | 81 | int login_id; |
78 | 82 | ||
79 | /* | 83 | /* |
80 | * We cache these addresses and only update them once we've | 84 | * The generation is updated once we've logged in or reconnected |
81 | * logged in or reconnected to the sbp2 device. That way, any | 85 | * to the logical unit. Thus, I/O to the device will automatically |
82 | * IO to the device will automatically fail and get retried if | 86 | * fail and get retried if it happens in a window where the device |
83 | * it happens in a window where the device is not ready to | 87 | * is not ready, e.g. after a bus reset but before we reconnect. |
84 | * handle it (e.g. after a bus reset but before we reconnect). | ||
85 | */ | 88 | */ |
86 | int node_id; | ||
87 | int address_high; | ||
88 | int generation; | 89 | int generation; |
89 | |||
90 | int retries; | 90 | int retries; |
91 | struct delayed_work work; | 91 | struct delayed_work work; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | /* | ||
95 | * We create one struct sbp2_target per IEEE 1212 Unit Directory | ||
96 | * and one struct Scsi_Host per sbp2_target. | ||
97 | */ | ||
98 | struct sbp2_target { | ||
99 | struct kref kref; | ||
100 | struct fw_unit *unit; | ||
101 | |||
102 | u64 management_agent_address; | ||
103 | int directory_id; | ||
104 | int node_id; | ||
105 | int address_high; | ||
106 | |||
107 | unsigned workarounds; | ||
108 | struct list_head lu_list; | ||
109 | }; | ||
110 | |||
94 | #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 | 111 | #define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000 |
95 | #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ | 112 | #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ |
96 | #define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */ | 113 | #define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */ |
@@ -101,10 +118,9 @@ struct sbp2_device { | |||
101 | #define SBP2_DIRECTION_FROM_MEDIA 0x1 | 118 | #define SBP2_DIRECTION_FROM_MEDIA 0x1 |
102 | 119 | ||
103 | /* Unit directory keys */ | 120 | /* Unit directory keys */ |
104 | #define SBP2_COMMAND_SET_SPECIFIER 0x38 | 121 | #define SBP2_CSR_FIRMWARE_REVISION 0x3c |
105 | #define SBP2_COMMAND_SET 0x39 | 122 | #define SBP2_CSR_LOGICAL_UNIT_NUMBER 0x14 |
106 | #define SBP2_COMMAND_SET_REVISION 0x3b | 123 | #define SBP2_CSR_LOGICAL_UNIT_DIRECTORY 0xd4 |
107 | #define SBP2_FIRMWARE_REVISION 0x3c | ||
108 | 124 | ||
109 | /* Flags for detected oddities and brokeness */ | 125 | /* Flags for detected oddities and brokeness */ |
110 | #define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 | 126 | #define SBP2_WORKAROUND_128K_MAX_TRANS 0x1 |
@@ -219,7 +235,7 @@ struct sbp2_command_orb { | |||
219 | } request; | 235 | } request; |
220 | struct scsi_cmnd *cmd; | 236 | struct scsi_cmnd *cmd; |
221 | scsi_done_fn_t done; | 237 | scsi_done_fn_t done; |
222 | struct fw_unit *unit; | 238 | struct sbp2_logical_unit *lu; |
223 | 239 | ||
224 | struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8))); | 240 | struct sbp2_pointer page_table[SG_ALL] __attribute__((aligned(8))); |
225 | dma_addr_t page_table_bus; | 241 | dma_addr_t page_table_bus; |
@@ -295,7 +311,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, | |||
295 | unsigned long long offset, | 311 | unsigned long long offset, |
296 | void *payload, size_t length, void *callback_data) | 312 | void *payload, size_t length, void *callback_data) |
297 | { | 313 | { |
298 | struct sbp2_device *sd = callback_data; | 314 | struct sbp2_logical_unit *lu = callback_data; |
299 | struct sbp2_orb *orb; | 315 | struct sbp2_orb *orb; |
300 | struct sbp2_status status; | 316 | struct sbp2_status status; |
301 | size_t header_size; | 317 | size_t header_size; |
@@ -319,7 +335,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, | |||
319 | 335 | ||
320 | /* Lookup the orb corresponding to this status write. */ | 336 | /* Lookup the orb corresponding to this status write. */ |
321 | spin_lock_irqsave(&card->lock, flags); | 337 | spin_lock_irqsave(&card->lock, flags); |
322 | list_for_each_entry(orb, &sd->orb_list, link) { | 338 | list_for_each_entry(orb, &lu->orb_list, link) { |
323 | if (STATUS_GET_ORB_HIGH(status) == 0 && | 339 | if (STATUS_GET_ORB_HIGH(status) == 0 && |
324 | STATUS_GET_ORB_LOW(status) == orb->request_bus) { | 340 | STATUS_GET_ORB_LOW(status) == orb->request_bus) { |
325 | orb->rcode = RCODE_COMPLETE; | 341 | orb->rcode = RCODE_COMPLETE; |
@@ -329,7 +345,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request, | |||
329 | } | 345 | } |
330 | spin_unlock_irqrestore(&card->lock, flags); | 346 | spin_unlock_irqrestore(&card->lock, flags); |
331 | 347 | ||
332 | if (&orb->link != &sd->orb_list) | 348 | if (&orb->link != &lu->orb_list) |
333 | orb->callback(orb, &status); | 349 | orb->callback(orb, &status); |
334 | else | 350 | else |
335 | fw_error("status write for unknown orb\n"); | 351 | fw_error("status write for unknown orb\n"); |
@@ -371,11 +387,10 @@ complete_transaction(struct fw_card *card, int rcode, | |||
371 | } | 387 | } |
372 | 388 | ||
373 | static void | 389 | static void |
374 | sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, | 390 | sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, |
375 | int node_id, int generation, u64 offset) | 391 | int node_id, int generation, u64 offset) |
376 | { | 392 | { |
377 | struct fw_device *device = fw_device(unit->device.parent); | 393 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
378 | struct sbp2_device *sd = unit->device.driver_data; | ||
379 | unsigned long flags; | 394 | unsigned long flags; |
380 | 395 | ||
381 | orb->pointer.high = 0; | 396 | orb->pointer.high = 0; |
@@ -383,7 +398,7 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, | |||
383 | fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer)); | 398 | fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer)); |
384 | 399 | ||
385 | spin_lock_irqsave(&device->card->lock, flags); | 400 | spin_lock_irqsave(&device->card->lock, flags); |
386 | list_add_tail(&orb->link, &sd->orb_list); | 401 | list_add_tail(&orb->link, &lu->orb_list); |
387 | spin_unlock_irqrestore(&device->card->lock, flags); | 402 | spin_unlock_irqrestore(&device->card->lock, flags); |
388 | 403 | ||
389 | /* Take a ref for the orb list and for the transaction callback. */ | 404 | /* Take a ref for the orb list and for the transaction callback. */ |
@@ -396,10 +411,9 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit, | |||
396 | complete_transaction, orb); | 411 | complete_transaction, orb); |
397 | } | 412 | } |
398 | 413 | ||
399 | static int sbp2_cancel_orbs(struct fw_unit *unit) | 414 | static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) |
400 | { | 415 | { |
401 | struct fw_device *device = fw_device(unit->device.parent); | 416 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
402 | struct sbp2_device *sd = unit->device.driver_data; | ||
403 | struct sbp2_orb *orb, *next; | 417 | struct sbp2_orb *orb, *next; |
404 | struct list_head list; | 418 | struct list_head list; |
405 | unsigned long flags; | 419 | unsigned long flags; |
@@ -407,7 +421,7 @@ static int sbp2_cancel_orbs(struct fw_unit *unit) | |||
407 | 421 | ||
408 | INIT_LIST_HEAD(&list); | 422 | INIT_LIST_HEAD(&list); |
409 | spin_lock_irqsave(&device->card->lock, flags); | 423 | spin_lock_irqsave(&device->card->lock, flags); |
410 | list_splice_init(&sd->orb_list, &list); | 424 | list_splice_init(&lu->orb_list, &list); |
411 | spin_unlock_irqrestore(&device->card->lock, flags); | 425 | spin_unlock_irqrestore(&device->card->lock, flags); |
412 | 426 | ||
413 | list_for_each_entry_safe(orb, next, &list, link) { | 427 | list_for_each_entry_safe(orb, next, &list, link) { |
@@ -434,11 +448,11 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
434 | } | 448 | } |
435 | 449 | ||
436 | static int | 450 | static int |
437 | sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, | 451 | sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, |
438 | int function, int lun, void *response) | 452 | int generation, int function, int lun_or_login_id, |
453 | void *response) | ||
439 | { | 454 | { |
440 | struct fw_device *device = fw_device(unit->device.parent); | 455 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
441 | struct sbp2_device *sd = unit->device.driver_data; | ||
442 | struct sbp2_management_orb *orb; | 456 | struct sbp2_management_orb *orb; |
443 | int retval = -ENOMEM; | 457 | int retval = -ENOMEM; |
444 | 458 | ||
@@ -459,12 +473,12 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, | |||
459 | orb->request.misc = | 473 | orb->request.misc = |
460 | MANAGEMENT_ORB_NOTIFY | | 474 | MANAGEMENT_ORB_NOTIFY | |
461 | MANAGEMENT_ORB_FUNCTION(function) | | 475 | MANAGEMENT_ORB_FUNCTION(function) | |
462 | MANAGEMENT_ORB_LUN(lun); | 476 | MANAGEMENT_ORB_LUN(lun_or_login_id); |
463 | orb->request.length = | 477 | orb->request.length = |
464 | MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)); | 478 | MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response)); |
465 | 479 | ||
466 | orb->request.status_fifo.high = sd->address_handler.offset >> 32; | 480 | orb->request.status_fifo.high = lu->address_handler.offset >> 32; |
467 | orb->request.status_fifo.low = sd->address_handler.offset; | 481 | orb->request.status_fifo.low = lu->address_handler.offset; |
468 | 482 | ||
469 | if (function == SBP2_LOGIN_REQUEST) { | 483 | if (function == SBP2_LOGIN_REQUEST) { |
470 | orb->request.misc |= | 484 | orb->request.misc |= |
@@ -483,14 +497,14 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation, | |||
483 | if (dma_mapping_error(orb->base.request_bus)) | 497 | if (dma_mapping_error(orb->base.request_bus)) |
484 | goto fail_mapping_request; | 498 | goto fail_mapping_request; |
485 | 499 | ||
486 | sbp2_send_orb(&orb->base, unit, | 500 | sbp2_send_orb(&orb->base, lu, node_id, generation, |
487 | node_id, generation, sd->management_agent_address); | 501 | lu->tgt->management_agent_address); |
488 | 502 | ||
489 | wait_for_completion_timeout(&orb->done, | 503 | wait_for_completion_timeout(&orb->done, |
490 | msecs_to_jiffies(SBP2_ORB_TIMEOUT)); | 504 | msecs_to_jiffies(SBP2_ORB_TIMEOUT)); |
491 | 505 | ||
492 | retval = -EIO; | 506 | retval = -EIO; |
493 | if (sbp2_cancel_orbs(unit) == 0) { | 507 | if (sbp2_cancel_orbs(lu) == 0) { |
494 | fw_error("orb reply timed out, rcode=0x%02x\n", | 508 | fw_error("orb reply timed out, rcode=0x%02x\n", |
495 | orb->base.rcode); | 509 | orb->base.rcode); |
496 | goto out; | 510 | goto out; |
@@ -535,10 +549,9 @@ complete_agent_reset_write(struct fw_card *card, int rcode, | |||
535 | kfree(t); | 549 | kfree(t); |
536 | } | 550 | } |
537 | 551 | ||
538 | static int sbp2_agent_reset(struct fw_unit *unit) | 552 | static int sbp2_agent_reset(struct sbp2_logical_unit *lu) |
539 | { | 553 | { |
540 | struct fw_device *device = fw_device(unit->device.parent); | 554 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
541 | struct sbp2_device *sd = unit->device.driver_data; | ||
542 | struct fw_transaction *t; | 555 | struct fw_transaction *t; |
543 | static u32 zero; | 556 | static u32 zero; |
544 | 557 | ||
@@ -547,181 +560,261 @@ static int sbp2_agent_reset(struct fw_unit *unit) | |||
547 | return -ENOMEM; | 560 | return -ENOMEM; |
548 | 561 | ||
549 | fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, | 562 | fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, |
550 | sd->node_id, sd->generation, device->max_speed, | 563 | lu->tgt->node_id, lu->generation, device->max_speed, |
551 | sd->command_block_agent_address + SBP2_AGENT_RESET, | 564 | lu->command_block_agent_address + SBP2_AGENT_RESET, |
552 | &zero, sizeof(zero), complete_agent_reset_write, t); | 565 | &zero, sizeof(zero), complete_agent_reset_write, t); |
553 | 566 | ||
554 | return 0; | 567 | return 0; |
555 | } | 568 | } |
556 | 569 | ||
557 | static void sbp2_reconnect(struct work_struct *work); | 570 | static void sbp2_release_target(struct kref *kref) |
558 | static struct scsi_host_template scsi_driver_template; | ||
559 | |||
560 | static void release_sbp2_device(struct kref *kref) | ||
561 | { | 571 | { |
562 | struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref); | 572 | struct sbp2_target *tgt = container_of(kref, struct sbp2_target, kref); |
563 | struct Scsi_Host *host = | 573 | struct sbp2_logical_unit *lu, *next; |
564 | container_of((void *)sd, struct Scsi_Host, hostdata[0]); | 574 | struct Scsi_Host *shost = |
565 | 575 | container_of((void *)tgt, struct Scsi_Host, hostdata[0]); | |
566 | scsi_remove_host(host); | 576 | |
567 | sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation, | 577 | list_for_each_entry_safe(lu, next, &tgt->lu_list, link) { |
568 | SBP2_LOGOUT_REQUEST, sd->login_id, NULL); | 578 | if (lu->sdev) |
569 | fw_core_remove_address_handler(&sd->address_handler); | 579 | scsi_remove_device(lu->sdev); |
570 | fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id); | 580 | |
571 | put_device(&sd->unit->device); | 581 | sbp2_send_management_orb(lu, tgt->node_id, lu->generation, |
572 | scsi_host_put(host); | 582 | SBP2_LOGOUT_REQUEST, lu->login_id, NULL); |
583 | fw_core_remove_address_handler(&lu->address_handler); | ||
584 | list_del(&lu->link); | ||
585 | kfree(lu); | ||
586 | } | ||
587 | scsi_remove_host(shost); | ||
588 | fw_notify("released %s\n", tgt->unit->device.bus_id); | ||
589 | |||
590 | put_device(&tgt->unit->device); | ||
591 | scsi_host_put(shost); | ||
573 | } | 592 | } |
574 | 593 | ||
594 | static void sbp2_reconnect(struct work_struct *work); | ||
595 | |||
575 | static void sbp2_login(struct work_struct *work) | 596 | static void sbp2_login(struct work_struct *work) |
576 | { | 597 | { |
577 | struct sbp2_device *sd = | 598 | struct sbp2_logical_unit *lu = |
578 | container_of(work, struct sbp2_device, work.work); | 599 | container_of(work, struct sbp2_logical_unit, work.work); |
579 | struct Scsi_Host *host = | 600 | struct Scsi_Host *shost = |
580 | container_of((void *)sd, struct Scsi_Host, hostdata[0]); | 601 | container_of((void *)lu->tgt, struct Scsi_Host, hostdata[0]); |
581 | struct fw_unit *unit = sd->unit; | 602 | struct scsi_device *sdev; |
603 | struct scsi_lun eight_bytes_lun; | ||
604 | struct fw_unit *unit = lu->tgt->unit; | ||
582 | struct fw_device *device = fw_device(unit->device.parent); | 605 | struct fw_device *device = fw_device(unit->device.parent); |
583 | struct sbp2_login_response response; | 606 | struct sbp2_login_response response; |
584 | int generation, node_id, local_node_id, lun, retval; | 607 | int generation, node_id, local_node_id; |
585 | |||
586 | /* FIXME: Make this work for multi-lun devices. */ | ||
587 | lun = 0; | ||
588 | 608 | ||
589 | generation = device->card->generation; | 609 | generation = device->card->generation; |
590 | node_id = device->node->node_id; | 610 | node_id = device->node->node_id; |
591 | local_node_id = device->card->local_node->node_id; | 611 | local_node_id = device->card->local_node->node_id; |
592 | 612 | ||
593 | if (sbp2_send_management_orb(unit, node_id, generation, | 613 | if (sbp2_send_management_orb(lu, node_id, generation, |
594 | SBP2_LOGIN_REQUEST, lun, &response) < 0) { | 614 | SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) { |
595 | if (sd->retries++ < 5) { | 615 | if (lu->retries++ < 5) { |
596 | schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); | 616 | schedule_delayed_work(&lu->work, DIV_ROUND_UP(HZ, 5)); |
597 | } else { | 617 | } else { |
598 | fw_error("failed to login to %s\n", | 618 | fw_error("failed to login to %s LUN %04x\n", |
599 | unit->device.bus_id); | 619 | unit->device.bus_id, lu->lun); |
600 | kref_put(&sd->kref, release_sbp2_device); | 620 | kref_put(&lu->tgt->kref, sbp2_release_target); |
601 | } | 621 | } |
602 | return; | 622 | return; |
603 | } | 623 | } |
604 | 624 | ||
605 | sd->generation = generation; | 625 | lu->generation = generation; |
606 | sd->node_id = node_id; | 626 | lu->tgt->node_id = node_id; |
607 | sd->address_high = local_node_id << 16; | 627 | lu->tgt->address_high = local_node_id << 16; |
608 | 628 | ||
609 | /* Get command block agent offset and login id. */ | 629 | /* Get command block agent offset and login id. */ |
610 | sd->command_block_agent_address = | 630 | lu->command_block_agent_address = |
611 | ((u64) (response.command_block_agent.high & 0xffff) << 32) | | 631 | ((u64) (response.command_block_agent.high & 0xffff) << 32) | |
612 | response.command_block_agent.low; | 632 | response.command_block_agent.low; |
613 | sd->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); | 633 | lu->login_id = LOGIN_RESPONSE_GET_LOGIN_ID(response); |
614 | 634 | ||
615 | fw_notify("logged in to sbp2 unit %s (%d retries)\n", | 635 | fw_notify("logged in to %s LUN %04x (%d retries)\n", |
616 | unit->device.bus_id, sd->retries); | 636 | unit->device.bus_id, lu->lun, lu->retries); |
617 | fw_notify(" - management_agent_address: 0x%012llx\n", | ||
618 | (unsigned long long) sd->management_agent_address); | ||
619 | fw_notify(" - command_block_agent_address: 0x%012llx\n", | ||
620 | (unsigned long long) sd->command_block_agent_address); | ||
621 | fw_notify(" - status write address: 0x%012llx\n", | ||
622 | (unsigned long long) sd->address_handler.offset); | ||
623 | 637 | ||
624 | #if 0 | 638 | #if 0 |
625 | /* FIXME: The linux1394 sbp2 does this last step. */ | 639 | /* FIXME: The linux1394 sbp2 does this last step. */ |
626 | sbp2_set_busy_timeout(scsi_id); | 640 | sbp2_set_busy_timeout(scsi_id); |
627 | #endif | 641 | #endif |
628 | 642 | ||
629 | PREPARE_DELAYED_WORK(&sd->work, sbp2_reconnect); | 643 | PREPARE_DELAYED_WORK(&lu->work, sbp2_reconnect); |
630 | sbp2_agent_reset(unit); | 644 | sbp2_agent_reset(lu); |
645 | |||
646 | memset(&eight_bytes_lun, 0, sizeof(eight_bytes_lun)); | ||
647 | eight_bytes_lun.scsi_lun[0] = (lu->lun >> 8) & 0xff; | ||
648 | eight_bytes_lun.scsi_lun[1] = lu->lun & 0xff; | ||
631 | 649 | ||
632 | /* FIXME: Loop over luns here. */ | 650 | sdev = __scsi_add_device(shost, 0, 0, |
633 | lun = 0; | 651 | scsilun_to_int(&eight_bytes_lun), lu); |
634 | retval = scsi_add_device(host, 0, 0, lun); | 652 | if (IS_ERR(sdev)) { |
635 | if (retval < 0) { | 653 | sbp2_send_management_orb(lu, node_id, generation, |
636 | sbp2_send_management_orb(unit, sd->node_id, sd->generation, | 654 | SBP2_LOGOUT_REQUEST, lu->login_id, NULL); |
637 | SBP2_LOGOUT_REQUEST, sd->login_id, | ||
638 | NULL); | ||
639 | /* | 655 | /* |
640 | * Set this back to sbp2_login so we fall back and | 656 | * Set this back to sbp2_login so we fall back and |
641 | * retry login on bus reset. | 657 | * retry login on bus reset. |
642 | */ | 658 | */ |
643 | PREPARE_DELAYED_WORK(&sd->work, sbp2_login); | 659 | PREPARE_DELAYED_WORK(&lu->work, sbp2_login); |
660 | } else { | ||
661 | lu->sdev = sdev; | ||
662 | scsi_device_put(sdev); | ||
644 | } | 663 | } |
645 | kref_put(&sd->kref, release_sbp2_device); | 664 | kref_put(&lu->tgt->kref, sbp2_release_target); |
646 | } | 665 | } |
647 | 666 | ||
648 | static int sbp2_probe(struct device *dev) | 667 | static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry) |
649 | { | 668 | { |
650 | struct fw_unit *unit = fw_unit(dev); | 669 | struct sbp2_logical_unit *lu; |
651 | struct fw_device *device = fw_device(unit->device.parent); | ||
652 | struct sbp2_device *sd; | ||
653 | struct fw_csr_iterator ci; | ||
654 | struct Scsi_Host *host; | ||
655 | int i, key, value, err; | ||
656 | u32 model, firmware_revision; | ||
657 | 670 | ||
658 | err = -ENOMEM; | 671 | lu = kmalloc(sizeof(*lu), GFP_KERNEL); |
659 | host = scsi_host_alloc(&scsi_driver_template, sizeof(*sd)); | 672 | if (!lu) |
660 | if (host == NULL) | 673 | return -ENOMEM; |
661 | goto fail; | ||
662 | 674 | ||
663 | sd = (struct sbp2_device *) host->hostdata; | 675 | lu->address_handler.length = 0x100; |
664 | unit->device.driver_data = sd; | 676 | lu->address_handler.address_callback = sbp2_status_write; |
665 | sd->unit = unit; | 677 | lu->address_handler.callback_data = lu; |
666 | INIT_LIST_HEAD(&sd->orb_list); | ||
667 | kref_init(&sd->kref); | ||
668 | 678 | ||
669 | sd->address_handler.length = 0x100; | 679 | if (fw_core_add_address_handler(&lu->address_handler, |
670 | sd->address_handler.address_callback = sbp2_status_write; | 680 | &fw_high_memory_region) < 0) { |
671 | sd->address_handler.callback_data = sd; | 681 | kfree(lu); |
682 | return -ENOMEM; | ||
683 | } | ||
672 | 684 | ||
673 | err = fw_core_add_address_handler(&sd->address_handler, | 685 | lu->tgt = tgt; |
674 | &fw_high_memory_region); | 686 | lu->sdev = NULL; |
675 | if (err < 0) | 687 | lu->lun = lun_entry & 0xffff; |
676 | goto fail_host; | 688 | lu->retries = 0; |
689 | INIT_LIST_HEAD(&lu->orb_list); | ||
690 | INIT_DELAYED_WORK(&lu->work, sbp2_login); | ||
677 | 691 | ||
678 | err = fw_device_enable_phys_dma(device); | 692 | list_add_tail(&lu->link, &tgt->lu_list); |
679 | if (err < 0) | 693 | return 0; |
680 | goto fail_address_handler; | 694 | } |
681 | 695 | ||
682 | err = scsi_add_host(host, &unit->device); | 696 | static int sbp2_scan_logical_unit_dir(struct sbp2_target *tgt, u32 *directory) |
683 | if (err < 0) | 697 | { |
684 | goto fail_address_handler; | 698 | struct fw_csr_iterator ci; |
699 | int key, value; | ||
685 | 700 | ||
686 | /* | 701 | fw_csr_iterator_init(&ci, directory); |
687 | * Scan unit directory to get management agent address, | 702 | while (fw_csr_iterator_next(&ci, &key, &value)) |
688 | * firmware revison and model. Initialize firmware_revision | 703 | if (key == SBP2_CSR_LOGICAL_UNIT_NUMBER && |
689 | * and model to values that wont match anything in our table. | 704 | sbp2_add_logical_unit(tgt, value) < 0) |
690 | */ | 705 | return -ENOMEM; |
691 | firmware_revision = 0xff000000; | 706 | return 0; |
692 | model = 0xff000000; | 707 | } |
693 | fw_csr_iterator_init(&ci, unit->directory); | 708 | |
709 | static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory, | ||
710 | u32 *model, u32 *firmware_revision) | ||
711 | { | ||
712 | struct fw_csr_iterator ci; | ||
713 | int key, value; | ||
714 | |||
715 | fw_csr_iterator_init(&ci, directory); | ||
694 | while (fw_csr_iterator_next(&ci, &key, &value)) { | 716 | while (fw_csr_iterator_next(&ci, &key, &value)) { |
695 | switch (key) { | 717 | switch (key) { |
718 | |||
696 | case CSR_DEPENDENT_INFO | CSR_OFFSET: | 719 | case CSR_DEPENDENT_INFO | CSR_OFFSET: |
697 | sd->management_agent_address = | 720 | tgt->management_agent_address = |
698 | 0xfffff0000000ULL + 4 * value; | 721 | CSR_REGISTER_BASE + 4 * value; |
699 | break; | 722 | break; |
700 | case SBP2_FIRMWARE_REVISION: | 723 | |
701 | firmware_revision = value; | 724 | case CSR_DIRECTORY_ID: |
725 | tgt->directory_id = value; | ||
702 | break; | 726 | break; |
727 | |||
703 | case CSR_MODEL: | 728 | case CSR_MODEL: |
704 | model = value; | 729 | *model = value; |
730 | break; | ||
731 | |||
732 | case SBP2_CSR_FIRMWARE_REVISION: | ||
733 | *firmware_revision = value; | ||
734 | break; | ||
735 | |||
736 | case SBP2_CSR_LOGICAL_UNIT_NUMBER: | ||
737 | if (sbp2_add_logical_unit(tgt, value) < 0) | ||
738 | return -ENOMEM; | ||
739 | break; | ||
740 | |||
741 | case SBP2_CSR_LOGICAL_UNIT_DIRECTORY: | ||
742 | if (sbp2_scan_logical_unit_dir(tgt, ci.p + value) < 0) | ||
743 | return -ENOMEM; | ||
705 | break; | 744 | break; |
706 | } | 745 | } |
707 | } | 746 | } |
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, | ||
751 | u32 firmware_revision) | ||
752 | { | ||
753 | int i; | ||
754 | |||
755 | tgt->workarounds = 0; | ||
708 | 756 | ||
709 | for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { | 757 | for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { |
758 | |||
710 | if (sbp2_workarounds_table[i].firmware_revision != | 759 | if (sbp2_workarounds_table[i].firmware_revision != |
711 | (firmware_revision & 0xffffff00)) | 760 | (firmware_revision & 0xffffff00)) |
712 | continue; | 761 | continue; |
762 | |||
713 | if (sbp2_workarounds_table[i].model != model && | 763 | if (sbp2_workarounds_table[i].model != model && |
714 | sbp2_workarounds_table[i].model != ~0) | 764 | sbp2_workarounds_table[i].model != ~0) |
715 | continue; | 765 | continue; |
716 | sd->workarounds |= sbp2_workarounds_table[i].workarounds; | 766 | |
767 | tgt->workarounds |= sbp2_workarounds_table[i].workarounds; | ||
717 | break; | 768 | break; |
718 | } | 769 | } |
719 | 770 | ||
720 | if (sd->workarounds) | 771 | if (tgt->workarounds) |
721 | fw_notify("Workarounds for node %s: 0x%x " | 772 | fw_notify("Workarounds for %s: 0x%x " |
722 | "(firmware_revision 0x%06x, model_id 0x%06x)\n", | 773 | "(firmware_revision 0x%06x, model_id 0x%06x)\n", |
723 | unit->device.bus_id, | 774 | tgt->unit->device.bus_id, |
724 | sd->workarounds, firmware_revision, model); | 775 | tgt->workarounds, firmware_revision, model); |
776 | } | ||
777 | |||
778 | static struct scsi_host_template scsi_driver_template; | ||
779 | |||
780 | static int sbp2_probe(struct device *dev) | ||
781 | { | ||
782 | struct fw_unit *unit = fw_unit(dev); | ||
783 | struct fw_device *device = fw_device(unit->device.parent); | ||
784 | struct sbp2_target *tgt; | ||
785 | struct sbp2_logical_unit *lu; | ||
786 | struct Scsi_Host *shost; | ||
787 | u32 model, firmware_revision; | ||
788 | |||
789 | shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt)); | ||
790 | if (shost == NULL) | ||
791 | return -ENOMEM; | ||
792 | |||
793 | tgt = (struct sbp2_target *)shost->hostdata; | ||
794 | unit->device.driver_data = tgt; | ||
795 | tgt->unit = unit; | ||
796 | kref_init(&tgt->kref); | ||
797 | INIT_LIST_HEAD(&tgt->lu_list); | ||
798 | |||
799 | if (fw_device_enable_phys_dma(device) < 0) | ||
800 | goto fail_shost_put; | ||
801 | |||
802 | if (scsi_add_host(shost, &unit->device) < 0) | ||
803 | goto fail_shost_put; | ||
804 | |||
805 | /* Initialize to values that won't match anything in our table. */ | ||
806 | firmware_revision = 0xff000000; | ||
807 | model = 0xff000000; | ||
808 | |||
809 | /* implicit directory ID */ | ||
810 | tgt->directory_id = ((unit->directory - device->config_rom) * 4 | ||
811 | + CSR_CONFIG_ROM) & 0xffffff; | ||
812 | |||
813 | if (sbp2_scan_unit_dir(tgt, unit->directory, &model, | ||
814 | &firmware_revision) < 0) | ||
815 | goto fail_tgt_put; | ||
816 | |||
817 | sbp2_init_workarounds(tgt, model, firmware_revision); | ||
725 | 818 | ||
726 | get_device(&unit->device); | 819 | get_device(&unit->device); |
727 | 820 | ||
@@ -730,35 +823,34 @@ static int sbp2_probe(struct device *dev) | |||
730 | * reschedule retries. Always get the ref before scheduling | 823 | * reschedule retries. Always get the ref before scheduling |
731 | * work. | 824 | * work. |
732 | */ | 825 | */ |
733 | INIT_DELAYED_WORK(&sd->work, sbp2_login); | 826 | list_for_each_entry(lu, &tgt->lu_list, link) |
734 | if (schedule_delayed_work(&sd->work, 0)) | 827 | if (schedule_delayed_work(&lu->work, 0)) |
735 | kref_get(&sd->kref); | 828 | kref_get(&tgt->kref); |
736 | |||
737 | return 0; | 829 | return 0; |
738 | 830 | ||
739 | fail_address_handler: | 831 | fail_tgt_put: |
740 | fw_core_remove_address_handler(&sd->address_handler); | 832 | kref_put(&tgt->kref, sbp2_release_target); |
741 | fail_host: | 833 | return -ENOMEM; |
742 | scsi_host_put(host); | 834 | |
743 | fail: | 835 | fail_shost_put: |
744 | return err; | 836 | scsi_host_put(shost); |
837 | return -ENOMEM; | ||
745 | } | 838 | } |
746 | 839 | ||
747 | static int sbp2_remove(struct device *dev) | 840 | static int sbp2_remove(struct device *dev) |
748 | { | 841 | { |
749 | struct fw_unit *unit = fw_unit(dev); | 842 | struct fw_unit *unit = fw_unit(dev); |
750 | struct sbp2_device *sd = unit->device.driver_data; | 843 | struct sbp2_target *tgt = unit->device.driver_data; |
751 | |||
752 | kref_put(&sd->kref, release_sbp2_device); | ||
753 | 844 | ||
845 | kref_put(&tgt->kref, sbp2_release_target); | ||
754 | return 0; | 846 | return 0; |
755 | } | 847 | } |
756 | 848 | ||
757 | static void sbp2_reconnect(struct work_struct *work) | 849 | static void sbp2_reconnect(struct work_struct *work) |
758 | { | 850 | { |
759 | struct sbp2_device *sd = | 851 | struct sbp2_logical_unit *lu = |
760 | container_of(work, struct sbp2_device, work.work); | 852 | container_of(work, struct sbp2_logical_unit, work.work); |
761 | struct fw_unit *unit = sd->unit; | 853 | struct fw_unit *unit = lu->tgt->unit; |
762 | struct fw_device *device = fw_device(unit->device.parent); | 854 | struct fw_device *device = fw_device(unit->device.parent); |
763 | int generation, node_id, local_node_id; | 855 | int generation, node_id, local_node_id; |
764 | 856 | ||
@@ -766,40 +858,49 @@ static void sbp2_reconnect(struct work_struct *work) | |||
766 | node_id = device->node->node_id; | 858 | node_id = device->node->node_id; |
767 | local_node_id = device->card->local_node->node_id; | 859 | local_node_id = device->card->local_node->node_id; |
768 | 860 | ||
769 | if (sbp2_send_management_orb(unit, node_id, generation, | 861 | if (sbp2_send_management_orb(lu, node_id, generation, |
770 | SBP2_RECONNECT_REQUEST, | 862 | SBP2_RECONNECT_REQUEST, |
771 | sd->login_id, NULL) < 0) { | 863 | lu->login_id, NULL) < 0) { |
772 | if (sd->retries++ >= 5) { | 864 | if (lu->retries++ >= 5) { |
773 | fw_error("failed to reconnect to %s\n", | 865 | fw_error("failed to reconnect to %s\n", |
774 | unit->device.bus_id); | 866 | unit->device.bus_id); |
775 | /* Fall back and try to log in again. */ | 867 | /* Fall back and try to log in again. */ |
776 | sd->retries = 0; | 868 | lu->retries = 0; |
777 | PREPARE_DELAYED_WORK(&sd->work, sbp2_login); | 869 | PREPARE_DELAYED_WORK(&lu->work, sbp2_login); |
778 | } | 870 | } |
779 | schedule_delayed_work(&sd->work, DIV_ROUND_UP(HZ, 5)); | 871 | schedule_delayed_work(&lu->work, DIV_ROUND_UP(HZ, 5)); |
780 | return; | 872 | return; |
781 | } | 873 | } |
782 | 874 | ||
783 | sd->generation = generation; | 875 | lu->generation = generation; |
784 | sd->node_id = node_id; | 876 | lu->tgt->node_id = node_id; |
785 | sd->address_high = local_node_id << 16; | 877 | lu->tgt->address_high = local_node_id << 16; |
786 | 878 | ||
787 | fw_notify("reconnected to unit %s (%d retries)\n", | 879 | fw_notify("reconnected to %s LUN %04x (%d retries)\n", |
788 | unit->device.bus_id, sd->retries); | 880 | unit->device.bus_id, lu->lun, lu->retries); |
789 | sbp2_agent_reset(unit); | 881 | |
790 | sbp2_cancel_orbs(unit); | 882 | sbp2_agent_reset(lu); |
791 | kref_put(&sd->kref, release_sbp2_device); | 883 | sbp2_cancel_orbs(lu); |
884 | |||
885 | kref_put(&lu->tgt->kref, sbp2_release_target); | ||
792 | } | 886 | } |
793 | 887 | ||
794 | static void sbp2_update(struct fw_unit *unit) | 888 | static void sbp2_update(struct fw_unit *unit) |
795 | { | 889 | { |
796 | struct fw_device *device = fw_device(unit->device.parent); | 890 | struct sbp2_target *tgt = unit->device.driver_data; |
797 | struct sbp2_device *sd = unit->device.driver_data; | 891 | struct sbp2_logical_unit *lu; |
798 | 892 | ||
799 | sd->retries = 0; | 893 | fw_device_enable_phys_dma(fw_device(unit->device.parent)); |
800 | fw_device_enable_phys_dma(device); | 894 | |
801 | if (schedule_delayed_work(&sd->work, 0)) | 895 | /* |
802 | kref_get(&sd->kref); | 896 | * Fw-core serializes sbp2_update() against sbp2_remove(). |
897 | * Iteration over tgt->lu_list is therefore safe here. | ||
898 | */ | ||
899 | list_for_each_entry(lu, &tgt->lu_list, link) { | ||
900 | lu->retries = 0; | ||
901 | if (schedule_delayed_work(&lu->work, 0)) | ||
902 | kref_get(&tgt->kref); | ||
903 | } | ||
803 | } | 904 | } |
804 | 905 | ||
805 | #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e | 906 | #define SBP2_UNIT_SPEC_ID_ENTRY 0x0000609e |
@@ -869,13 +970,12 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
869 | { | 970 | { |
870 | struct sbp2_command_orb *orb = | 971 | struct sbp2_command_orb *orb = |
871 | container_of(base_orb, struct sbp2_command_orb, base); | 972 | container_of(base_orb, struct sbp2_command_orb, base); |
872 | struct fw_unit *unit = orb->unit; | 973 | struct fw_device *device = fw_device(orb->lu->tgt->unit->device.parent); |
873 | struct fw_device *device = fw_device(unit->device.parent); | ||
874 | int result; | 974 | int result; |
875 | 975 | ||
876 | if (status != NULL) { | 976 | if (status != NULL) { |
877 | if (STATUS_GET_DEAD(*status)) | 977 | if (STATUS_GET_DEAD(*status)) |
878 | sbp2_agent_reset(unit); | 978 | sbp2_agent_reset(orb->lu); |
879 | 979 | ||
880 | switch (STATUS_GET_RESPONSE(*status)) { | 980 | switch (STATUS_GET_RESPONSE(*status)) { |
881 | case SBP2_STATUS_REQUEST_COMPLETE: | 981 | case SBP2_STATUS_REQUEST_COMPLETE: |
@@ -919,12 +1019,10 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
919 | orb->done(orb->cmd); | 1019 | orb->done(orb->cmd); |
920 | } | 1020 | } |
921 | 1021 | ||
922 | static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) | 1022 | static int |
1023 | sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device, | ||
1024 | struct sbp2_logical_unit *lu) | ||
923 | { | 1025 | { |
924 | struct sbp2_device *sd = | ||
925 | (struct sbp2_device *)orb->cmd->device->host->hostdata; | ||
926 | struct fw_unit *unit = sd->unit; | ||
927 | struct fw_device *device = fw_device(unit->device.parent); | ||
928 | struct scatterlist *sg; | 1026 | struct scatterlist *sg; |
929 | int sg_len, l, i, j, count; | 1027 | int sg_len, l, i, j, count; |
930 | dma_addr_t sg_addr; | 1028 | dma_addr_t sg_addr; |
@@ -943,10 +1041,9 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) | |||
943 | * tables. | 1041 | * tables. |
944 | */ | 1042 | */ |
945 | if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { | 1043 | if (count == 1 && sg_dma_len(sg) < SBP2_MAX_SG_ELEMENT_LENGTH) { |
946 | orb->request.data_descriptor.high = sd->address_high; | 1044 | orb->request.data_descriptor.high = lu->tgt->address_high; |
947 | orb->request.data_descriptor.low = sg_dma_address(sg); | 1045 | orb->request.data_descriptor.low = sg_dma_address(sg); |
948 | orb->request.misc |= | 1046 | orb->request.misc |= COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); |
949 | COMMAND_ORB_DATA_SIZE(sg_dma_len(sg)); | ||
950 | return 0; | 1047 | return 0; |
951 | } | 1048 | } |
952 | 1049 | ||
@@ -990,7 +1087,7 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) | |||
990 | * initiator (i.e. us), but data_descriptor can refer to data | 1087 | * initiator (i.e. us), but data_descriptor can refer to data |
991 | * on other nodes so we need to put our ID in descriptor.high. | 1088 | * on other nodes so we need to put our ID in descriptor.high. |
992 | */ | 1089 | */ |
993 | orb->request.data_descriptor.high = sd->address_high; | 1090 | orb->request.data_descriptor.high = lu->tgt->address_high; |
994 | orb->request.data_descriptor.low = orb->page_table_bus; | 1091 | orb->request.data_descriptor.low = orb->page_table_bus; |
995 | orb->request.misc |= | 1092 | orb->request.misc |= |
996 | COMMAND_ORB_PAGE_TABLE_PRESENT | | 1093 | COMMAND_ORB_PAGE_TABLE_PRESENT | |
@@ -1009,12 +1106,11 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb) | |||
1009 | 1106 | ||
1010 | static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) | 1107 | static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) |
1011 | { | 1108 | { |
1012 | struct sbp2_device *sd = | 1109 | struct sbp2_logical_unit *lu = cmd->device->hostdata; |
1013 | (struct sbp2_device *)cmd->device->host->hostdata; | 1110 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
1014 | struct fw_unit *unit = sd->unit; | ||
1015 | struct fw_device *device = fw_device(unit->device.parent); | ||
1016 | struct sbp2_command_orb *orb; | 1111 | struct sbp2_command_orb *orb; |
1017 | unsigned max_payload; | 1112 | unsigned max_payload; |
1113 | int retval = SCSI_MLQUEUE_HOST_BUSY; | ||
1018 | 1114 | ||
1019 | /* | 1115 | /* |
1020 | * Bidirectional commands are not yet implemented, and unknown | 1116 | * Bidirectional commands are not yet implemented, and unknown |
@@ -1030,14 +1126,14 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) | |||
1030 | orb = kzalloc(sizeof(*orb), GFP_ATOMIC); | 1126 | orb = kzalloc(sizeof(*orb), GFP_ATOMIC); |
1031 | if (orb == NULL) { | 1127 | if (orb == NULL) { |
1032 | fw_notify("failed to alloc orb\n"); | 1128 | fw_notify("failed to alloc orb\n"); |
1033 | goto fail_alloc; | 1129 | return SCSI_MLQUEUE_HOST_BUSY; |
1034 | } | 1130 | } |
1035 | 1131 | ||
1036 | /* Initialize rcode to something not RCODE_COMPLETE. */ | 1132 | /* Initialize rcode to something not RCODE_COMPLETE. */ |
1037 | orb->base.rcode = -1; | 1133 | orb->base.rcode = -1; |
1038 | kref_init(&orb->base.kref); | 1134 | kref_init(&orb->base.kref); |
1039 | 1135 | ||
1040 | orb->unit = unit; | 1136 | orb->lu = lu; |
1041 | orb->done = done; | 1137 | orb->done = done; |
1042 | orb->cmd = cmd; | 1138 | orb->cmd = cmd; |
1043 | 1139 | ||
@@ -1063,8 +1159,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) | |||
1063 | orb->request.misc |= | 1159 | orb->request.misc |= |
1064 | COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); | 1160 | COMMAND_ORB_DIRECTION(SBP2_DIRECTION_TO_MEDIA); |
1065 | 1161 | ||
1066 | if (scsi_sg_count(cmd) && sbp2_command_orb_map_scatterlist(orb) < 0) | 1162 | if (scsi_sg_count(cmd) && sbp2_map_scatterlist(orb, device, lu) < 0) |
1067 | goto fail_mapping; | 1163 | goto out; |
1068 | 1164 | ||
1069 | fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); | 1165 | fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request)); |
1070 | 1166 | ||
@@ -1077,49 +1173,47 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done) | |||
1077 | dma_map_single(device->card->device, &orb->request, | 1173 | dma_map_single(device->card->device, &orb->request, |
1078 | sizeof(orb->request), DMA_TO_DEVICE); | 1174 | sizeof(orb->request), DMA_TO_DEVICE); |
1079 | if (dma_mapping_error(orb->base.request_bus)) | 1175 | if (dma_mapping_error(orb->base.request_bus)) |
1080 | goto fail_mapping; | 1176 | goto out; |
1081 | |||
1082 | sbp2_send_orb(&orb->base, unit, sd->node_id, sd->generation, | ||
1083 | sd->command_block_agent_address + SBP2_ORB_POINTER); | ||
1084 | |||
1085 | kref_put(&orb->base.kref, free_orb); | ||
1086 | return 0; | ||
1087 | 1177 | ||
1088 | fail_mapping: | 1178 | sbp2_send_orb(&orb->base, lu, lu->tgt->node_id, lu->generation, |
1179 | lu->command_block_agent_address + SBP2_ORB_POINTER); | ||
1180 | retval = 0; | ||
1181 | out: | ||
1089 | kref_put(&orb->base.kref, free_orb); | 1182 | kref_put(&orb->base.kref, free_orb); |
1090 | fail_alloc: | 1183 | return retval; |
1091 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1092 | } | 1184 | } |
1093 | 1185 | ||
1094 | static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) | 1186 | static int sbp2_scsi_slave_alloc(struct scsi_device *sdev) |
1095 | { | 1187 | { |
1096 | struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; | 1188 | struct sbp2_logical_unit *lu = sdev->hostdata; |
1097 | 1189 | ||
1098 | sdev->allow_restart = 1; | 1190 | sdev->allow_restart = 1; |
1099 | 1191 | ||
1100 | if (sd->workarounds & SBP2_WORKAROUND_INQUIRY_36) | 1192 | if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36) |
1101 | sdev->inquiry_len = 36; | 1193 | sdev->inquiry_len = 36; |
1194 | |||
1102 | return 0; | 1195 | return 0; |
1103 | } | 1196 | } |
1104 | 1197 | ||
1105 | static int sbp2_scsi_slave_configure(struct scsi_device *sdev) | 1198 | static int sbp2_scsi_slave_configure(struct scsi_device *sdev) |
1106 | { | 1199 | { |
1107 | struct sbp2_device *sd = (struct sbp2_device *)sdev->host->hostdata; | 1200 | struct sbp2_logical_unit *lu = sdev->hostdata; |
1108 | struct fw_unit *unit = sd->unit; | ||
1109 | 1201 | ||
1110 | sdev->use_10_for_rw = 1; | 1202 | sdev->use_10_for_rw = 1; |
1111 | 1203 | ||
1112 | if (sdev->type == TYPE_ROM) | 1204 | if (sdev->type == TYPE_ROM) |
1113 | sdev->use_10_for_ms = 1; | 1205 | sdev->use_10_for_ms = 1; |
1206 | |||
1114 | if (sdev->type == TYPE_DISK && | 1207 | if (sdev->type == TYPE_DISK && |
1115 | sd->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) | 1208 | lu->tgt->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) |
1116 | sdev->skip_ms_page_8 = 1; | 1209 | sdev->skip_ms_page_8 = 1; |
1117 | if (sd->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) { | 1210 | |
1118 | fw_notify("setting fix_capacity for %s\n", unit->device.bus_id); | 1211 | if (lu->tgt->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) |
1119 | sdev->fix_capacity = 1; | 1212 | sdev->fix_capacity = 1; |
1120 | } | 1213 | |
1121 | if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) | 1214 | if (lu->tgt->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS) |
1122 | blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); | 1215 | blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512); |
1216 | |||
1123 | return 0; | 1217 | return 0; |
1124 | } | 1218 | } |
1125 | 1219 | ||
@@ -1129,13 +1223,11 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev) | |||
1129 | */ | 1223 | */ |
1130 | static int sbp2_scsi_abort(struct scsi_cmnd *cmd) | 1224 | static int sbp2_scsi_abort(struct scsi_cmnd *cmd) |
1131 | { | 1225 | { |
1132 | struct sbp2_device *sd = | 1226 | struct sbp2_logical_unit *lu = cmd->device->hostdata; |
1133 | (struct sbp2_device *)cmd->device->host->hostdata; | ||
1134 | struct fw_unit *unit = sd->unit; | ||
1135 | 1227 | ||
1136 | fw_notify("sbp2_scsi_abort\n"); | 1228 | fw_notify("sbp2_scsi_abort\n"); |
1137 | sbp2_agent_reset(unit); | 1229 | sbp2_agent_reset(lu); |
1138 | sbp2_cancel_orbs(unit); | 1230 | sbp2_cancel_orbs(lu); |
1139 | 1231 | ||
1140 | return SUCCESS; | 1232 | return SUCCESS; |
1141 | } | 1233 | } |
@@ -1152,37 +1244,18 @@ sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, | |||
1152 | char *buf) | 1244 | char *buf) |
1153 | { | 1245 | { |
1154 | struct scsi_device *sdev = to_scsi_device(dev); | 1246 | struct scsi_device *sdev = to_scsi_device(dev); |
1155 | struct sbp2_device *sd; | 1247 | struct sbp2_logical_unit *lu; |
1156 | struct fw_unit *unit; | ||
1157 | struct fw_device *device; | 1248 | struct fw_device *device; |
1158 | u32 directory_id; | ||
1159 | struct fw_csr_iterator ci; | ||
1160 | int key, value, lun; | ||
1161 | 1249 | ||
1162 | if (!sdev) | 1250 | if (!sdev) |
1163 | return 0; | 1251 | return 0; |
1164 | sd = (struct sbp2_device *)sdev->host->hostdata; | ||
1165 | unit = sd->unit; | ||
1166 | device = fw_device(unit->device.parent); | ||
1167 | |||
1168 | /* implicit directory ID */ | ||
1169 | directory_id = ((unit->directory - device->config_rom) * 4 | ||
1170 | + CSR_CONFIG_ROM) & 0xffffff; | ||
1171 | |||
1172 | /* explicit directory ID, overrides implicit ID if present */ | ||
1173 | fw_csr_iterator_init(&ci, unit->directory); | ||
1174 | while (fw_csr_iterator_next(&ci, &key, &value)) | ||
1175 | if (key == CSR_DIRECTORY_ID) { | ||
1176 | directory_id = value; | ||
1177 | break; | ||
1178 | } | ||
1179 | 1252 | ||
1180 | /* FIXME: Make this work for multi-lun devices. */ | 1253 | lu = sdev->hostdata; |
1181 | lun = 0; | 1254 | device = fw_device(lu->tgt->unit->device.parent); |
1182 | 1255 | ||
1183 | return sprintf(buf, "%08x%08x:%06x:%04x\n", | 1256 | return sprintf(buf, "%08x%08x:%06x:%04x\n", |
1184 | device->config_rom[3], device->config_rom[4], | 1257 | device->config_rom[3], device->config_rom[4], |
1185 | directory_id, lun); | 1258 | lu->tgt->directory_id, lu->lun); |
1186 | } | 1259 | } |
1187 | 1260 | ||
1188 | static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); | 1261 | static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); |