diff options
author | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-02-03 17:08:58 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2008-02-16 09:40:34 -0500 |
commit | e0e60215552d4d40caf581a8d3247203fe948fe7 (patch) | |
tree | 654aa22d8d13692fe8aa30ea9cd7301fccdb5e67 | |
parent | d94a983526cb868658c958ab689410dc1c6a31f3 (diff) |
firewire: fw-sbp2: wait for completion of fetch agent reset
Like the old sbp2 driver, wait for the write transaction to the
AGENT_RESET to complete before proceeding (after login, after reconnect,
or in SCSI error handling).
There is one occasion where AGENT_RESET is written to from atomic
context when getting DEAD status for a command ORB. There we still
continue without waiting for the transaction to complete because this
is more difficult to fix...
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r-- | drivers/firewire/fw-sbp2.c | 39 |
1 files changed, 28 insertions, 11 deletions
diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c index 4a118fbc7b24..32b50f13e7a8 100644 --- a/drivers/firewire/fw-sbp2.c +++ b/drivers/firewire/fw-sbp2.c | |||
@@ -603,29 +603,46 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, | |||
603 | 603 | ||
604 | static void | 604 | static void |
605 | complete_agent_reset_write(struct fw_card *card, int rcode, | 605 | complete_agent_reset_write(struct fw_card *card, int rcode, |
606 | void *payload, size_t length, void *data) | 606 | void *payload, size_t length, void *done) |
607 | { | 607 | { |
608 | struct fw_transaction *t = data; | 608 | complete(done); |
609 | } | ||
610 | |||
611 | static void sbp2_agent_reset(struct sbp2_logical_unit *lu) | ||
612 | { | ||
613 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); | ||
614 | DECLARE_COMPLETION_ONSTACK(done); | ||
615 | struct fw_transaction t; | ||
616 | static u32 z; | ||
609 | 617 | ||
610 | kfree(t); | 618 | fw_send_request(device->card, &t, TCODE_WRITE_QUADLET_REQUEST, |
619 | lu->tgt->node_id, lu->generation, device->max_speed, | ||
620 | lu->command_block_agent_address + SBP2_AGENT_RESET, | ||
621 | &z, sizeof(z), complete_agent_reset_write, &done); | ||
622 | wait_for_completion(&done); | ||
611 | } | 623 | } |
612 | 624 | ||
613 | static int sbp2_agent_reset(struct sbp2_logical_unit *lu) | 625 | static void |
626 | complete_agent_reset_write_no_wait(struct fw_card *card, int rcode, | ||
627 | void *payload, size_t length, void *data) | ||
628 | { | ||
629 | kfree(data); | ||
630 | } | ||
631 | |||
632 | static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) | ||
614 | { | 633 | { |
615 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); | 634 | struct fw_device *device = fw_device(lu->tgt->unit->device.parent); |
616 | struct fw_transaction *t; | 635 | struct fw_transaction *t; |
617 | static u32 zero; | 636 | static u32 z; |
618 | 637 | ||
619 | t = kzalloc(sizeof(*t), GFP_ATOMIC); | 638 | t = kmalloc(sizeof(*t), GFP_ATOMIC); |
620 | if (t == NULL) | 639 | if (t == NULL) |
621 | return -ENOMEM; | 640 | return; |
622 | 641 | ||
623 | fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, | 642 | fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST, |
624 | lu->tgt->node_id, lu->generation, device->max_speed, | 643 | lu->tgt->node_id, lu->generation, device->max_speed, |
625 | lu->command_block_agent_address + SBP2_AGENT_RESET, | 644 | lu->command_block_agent_address + SBP2_AGENT_RESET, |
626 | &zero, sizeof(zero), complete_agent_reset_write, t); | 645 | &z, sizeof(z), complete_agent_reset_write_no_wait, t); |
627 | |||
628 | return 0; | ||
629 | } | 646 | } |
630 | 647 | ||
631 | static void sbp2_release_target(struct kref *kref) | 648 | static void sbp2_release_target(struct kref *kref) |
@@ -1086,7 +1103,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status) | |||
1086 | 1103 | ||
1087 | if (status != NULL) { | 1104 | if (status != NULL) { |
1088 | if (STATUS_GET_DEAD(*status)) | 1105 | if (STATUS_GET_DEAD(*status)) |
1089 | sbp2_agent_reset(orb->lu); | 1106 | sbp2_agent_reset_no_wait(orb->lu); |
1090 | 1107 | ||
1091 | switch (STATUS_GET_RESPONSE(*status)) { | 1108 | switch (STATUS_GET_RESPONSE(*status)) { |
1092 | case SBP2_STATUS_REQUEST_COMPLETE: | 1109 | case SBP2_STATUS_REQUEST_COMPLETE: |