diff options
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 85 |
1 files changed, 58 insertions, 27 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index fef49521cbc3..bd96cecaa619 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c | |||
@@ -504,12 +504,23 @@ static void ibmvfc_set_host_action(struct ibmvfc_host *vhost, | |||
504 | if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS) | 504 | if (vhost->action == IBMVFC_HOST_ACTION_ALLOC_TGTS) |
505 | vhost->action = action; | 505 | vhost->action = action; |
506 | break; | 506 | break; |
507 | case IBMVFC_HOST_ACTION_LOGO: | ||
508 | case IBMVFC_HOST_ACTION_INIT: | 507 | case IBMVFC_HOST_ACTION_INIT: |
509 | case IBMVFC_HOST_ACTION_TGT_DEL: | 508 | case IBMVFC_HOST_ACTION_TGT_DEL: |
509 | switch (vhost->action) { | ||
510 | case IBMVFC_HOST_ACTION_RESET: | ||
511 | case IBMVFC_HOST_ACTION_REENABLE: | ||
512 | break; | ||
513 | default: | ||
514 | vhost->action = action; | ||
515 | break; | ||
516 | }; | ||
517 | break; | ||
518 | case IBMVFC_HOST_ACTION_LOGO: | ||
510 | case IBMVFC_HOST_ACTION_QUERY_TGTS: | 519 | case IBMVFC_HOST_ACTION_QUERY_TGTS: |
511 | case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: | 520 | case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: |
512 | case IBMVFC_HOST_ACTION_NONE: | 521 | case IBMVFC_HOST_ACTION_NONE: |
522 | case IBMVFC_HOST_ACTION_RESET: | ||
523 | case IBMVFC_HOST_ACTION_REENABLE: | ||
513 | default: | 524 | default: |
514 | vhost->action = action; | 525 | vhost->action = action; |
515 | break; | 526 | break; |
@@ -641,7 +652,7 @@ static int ibmvfc_send_crq_init_complete(struct ibmvfc_host *vhost) | |||
641 | **/ | 652 | **/ |
642 | static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) | 653 | static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) |
643 | { | 654 | { |
644 | long rc; | 655 | long rc = 0; |
645 | struct vio_dev *vdev = to_vio_dev(vhost->dev); | 656 | struct vio_dev *vdev = to_vio_dev(vhost->dev); |
646 | struct ibmvfc_crq_queue *crq = &vhost->crq; | 657 | struct ibmvfc_crq_queue *crq = &vhost->crq; |
647 | 658 | ||
@@ -649,6 +660,8 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) | |||
649 | free_irq(vdev->irq, vhost); | 660 | free_irq(vdev->irq, vhost); |
650 | tasklet_kill(&vhost->tasklet); | 661 | tasklet_kill(&vhost->tasklet); |
651 | do { | 662 | do { |
663 | if (rc) | ||
664 | msleep(100); | ||
652 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); | 665 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); |
653 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); | 666 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); |
654 | 667 | ||
@@ -667,11 +680,13 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) | |||
667 | **/ | 680 | **/ |
668 | static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) | 681 | static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) |
669 | { | 682 | { |
670 | int rc; | 683 | int rc = 0; |
671 | struct vio_dev *vdev = to_vio_dev(vhost->dev); | 684 | struct vio_dev *vdev = to_vio_dev(vhost->dev); |
672 | 685 | ||
673 | /* Re-enable the CRQ */ | 686 | /* Re-enable the CRQ */ |
674 | do { | 687 | do { |
688 | if (rc) | ||
689 | msleep(100); | ||
675 | rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); | 690 | rc = plpar_hcall_norets(H_ENABLE_CRQ, vdev->unit_address); |
676 | } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc)); | 691 | } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc)); |
677 | 692 | ||
@@ -690,15 +705,19 @@ static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) | |||
690 | **/ | 705 | **/ |
691 | static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) | 706 | static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) |
692 | { | 707 | { |
693 | int rc; | 708 | int rc = 0; |
709 | unsigned long flags; | ||
694 | struct vio_dev *vdev = to_vio_dev(vhost->dev); | 710 | struct vio_dev *vdev = to_vio_dev(vhost->dev); |
695 | struct ibmvfc_crq_queue *crq = &vhost->crq; | 711 | struct ibmvfc_crq_queue *crq = &vhost->crq; |
696 | 712 | ||
697 | /* Close the CRQ */ | 713 | /* Close the CRQ */ |
698 | do { | 714 | do { |
715 | if (rc) | ||
716 | msleep(100); | ||
699 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); | 717 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); |
700 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); | 718 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); |
701 | 719 | ||
720 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
702 | vhost->state = IBMVFC_NO_CRQ; | 721 | vhost->state = IBMVFC_NO_CRQ; |
703 | vhost->logged_in = 0; | 722 | vhost->logged_in = 0; |
704 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); | 723 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); |
@@ -716,6 +735,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) | |||
716 | dev_warn(vhost->dev, "Partner adapter not ready\n"); | 735 | dev_warn(vhost->dev, "Partner adapter not ready\n"); |
717 | else if (rc != 0) | 736 | else if (rc != 0) |
718 | dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc); | 737 | dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc); |
738 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
719 | 739 | ||
720 | return rc; | 740 | return rc; |
721 | } | 741 | } |
@@ -821,17 +841,9 @@ static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code) | |||
821 | **/ | 841 | **/ |
822 | static void ibmvfc_hard_reset_host(struct ibmvfc_host *vhost) | 842 | static void ibmvfc_hard_reset_host(struct ibmvfc_host *vhost) |
823 | { | 843 | { |
824 | int rc; | ||
825 | |||
826 | scsi_block_requests(vhost->host); | ||
827 | ibmvfc_purge_requests(vhost, DID_ERROR); | 844 | ibmvfc_purge_requests(vhost, DID_ERROR); |
828 | if ((rc = ibmvfc_reset_crq(vhost)) || | 845 | ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); |
829 | (rc = ibmvfc_send_crq_init(vhost)) || | 846 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET); |
830 | (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { | ||
831 | dev_err(vhost->dev, "Error after reset rc=%d\n", rc); | ||
832 | ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); | ||
833 | } else | ||
834 | ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); | ||
835 | } | 847 | } |
836 | 848 | ||
837 | /** | 849 | /** |
@@ -2299,6 +2311,7 @@ static int ibmvfc_eh_abort_handler(struct scsi_cmnd *cmd) | |||
2299 | int rc = FAILED; | 2311 | int rc = FAILED; |
2300 | 2312 | ||
2301 | ENTER; | 2313 | ENTER; |
2314 | fc_block_scsi_eh(cmd); | ||
2302 | ibmvfc_wait_while_resetting(vhost); | 2315 | ibmvfc_wait_while_resetting(vhost); |
2303 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); | 2316 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_ABORT_TASK_SET); |
2304 | abort_rc = ibmvfc_abort_task_set(sdev); | 2317 | abort_rc = ibmvfc_abort_task_set(sdev); |
@@ -2325,6 +2338,7 @@ static int ibmvfc_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
2325 | int rc = FAILED; | 2338 | int rc = FAILED; |
2326 | 2339 | ||
2327 | ENTER; | 2340 | ENTER; |
2341 | fc_block_scsi_eh(cmd); | ||
2328 | ibmvfc_wait_while_resetting(vhost); | 2342 | ibmvfc_wait_while_resetting(vhost); |
2329 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); | 2343 | cancel_rc = ibmvfc_cancel_all(sdev, IBMVFC_TMF_LUN_RESET); |
2330 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); | 2344 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_LUN_RESET, "LUN"); |
@@ -2389,6 +2403,7 @@ static int ibmvfc_eh_target_reset_handler(struct scsi_cmnd *cmd) | |||
2389 | unsigned long cancel_rc = 0; | 2403 | unsigned long cancel_rc = 0; |
2390 | 2404 | ||
2391 | ENTER; | 2405 | ENTER; |
2406 | fc_block_scsi_eh(cmd); | ||
2392 | ibmvfc_wait_while_resetting(vhost); | 2407 | ibmvfc_wait_while_resetting(vhost); |
2393 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); | 2408 | starget_for_each_device(starget, &cancel_rc, ibmvfc_dev_cancel_all_reset); |
2394 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); | 2409 | reset_rc = ibmvfc_reset_device(sdev, IBMVFC_TARGET_RESET, "target"); |
@@ -2410,6 +2425,7 @@ static int ibmvfc_eh_host_reset_handler(struct scsi_cmnd *cmd) | |||
2410 | int rc; | 2425 | int rc; |
2411 | struct ibmvfc_host *vhost = shost_priv(cmd->device->host); | 2426 | struct ibmvfc_host *vhost = shost_priv(cmd->device->host); |
2412 | 2427 | ||
2428 | fc_block_scsi_eh(cmd); | ||
2413 | dev_err(vhost->dev, "Resetting connection due to error recovery\n"); | 2429 | dev_err(vhost->dev, "Resetting connection due to error recovery\n"); |
2414 | rc = ibmvfc_issue_fc_host_lip(vhost->host); | 2430 | rc = ibmvfc_issue_fc_host_lip(vhost->host); |
2415 | return rc ? FAILED : SUCCESS; | 2431 | return rc ? FAILED : SUCCESS; |
@@ -2606,22 +2622,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) | |||
2606 | dev_info(vhost->dev, "Re-enabling adapter\n"); | 2622 | dev_info(vhost->dev, "Re-enabling adapter\n"); |
2607 | vhost->client_migrated = 1; | 2623 | vhost->client_migrated = 1; |
2608 | ibmvfc_purge_requests(vhost, DID_REQUEUE); | 2624 | ibmvfc_purge_requests(vhost, DID_REQUEUE); |
2609 | if ((rc = ibmvfc_reenable_crq_queue(vhost)) || | 2625 | ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); |
2610 | (rc = ibmvfc_send_crq_init(vhost))) { | 2626 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_REENABLE); |
2611 | ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); | ||
2612 | dev_err(vhost->dev, "Error after enable (rc=%ld)\n", rc); | ||
2613 | } else | ||
2614 | ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); | ||
2615 | } else { | 2627 | } else { |
2616 | dev_err(vhost->dev, "Virtual adapter failed (rc=%d)\n", crq->format); | 2628 | dev_err(vhost->dev, "Virtual adapter failed (rc=%d)\n", crq->format); |
2617 | |||
2618 | ibmvfc_purge_requests(vhost, DID_ERROR); | 2629 | ibmvfc_purge_requests(vhost, DID_ERROR); |
2619 | if ((rc = ibmvfc_reset_crq(vhost)) || | 2630 | ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); |
2620 | (rc = ibmvfc_send_crq_init(vhost))) { | 2631 | ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_RESET); |
2621 | ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); | ||
2622 | dev_err(vhost->dev, "Error after reset (rc=%ld)\n", rc); | ||
2623 | } else | ||
2624 | ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN); | ||
2625 | } | 2632 | } |
2626 | return; | 2633 | return; |
2627 | case IBMVFC_CRQ_CMD_RSP: | 2634 | case IBMVFC_CRQ_CMD_RSP: |
@@ -4123,6 +4130,8 @@ static int __ibmvfc_work_to_do(struct ibmvfc_host *vhost) | |||
4123 | case IBMVFC_HOST_ACTION_TGT_DEL: | 4130 | case IBMVFC_HOST_ACTION_TGT_DEL: |
4124 | case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: | 4131 | case IBMVFC_HOST_ACTION_TGT_DEL_FAILED: |
4125 | case IBMVFC_HOST_ACTION_QUERY: | 4132 | case IBMVFC_HOST_ACTION_QUERY: |
4133 | case IBMVFC_HOST_ACTION_RESET: | ||
4134 | case IBMVFC_HOST_ACTION_REENABLE: | ||
4126 | default: | 4135 | default: |
4127 | break; | 4136 | break; |
4128 | }; | 4137 | }; |
@@ -4220,6 +4229,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) | |||
4220 | struct ibmvfc_target *tgt; | 4229 | struct ibmvfc_target *tgt; |
4221 | unsigned long flags; | 4230 | unsigned long flags; |
4222 | struct fc_rport *rport; | 4231 | struct fc_rport *rport; |
4232 | int rc; | ||
4223 | 4233 | ||
4224 | ibmvfc_log_ae(vhost, vhost->events_to_log); | 4234 | ibmvfc_log_ae(vhost, vhost->events_to_log); |
4225 | spin_lock_irqsave(vhost->host->host_lock, flags); | 4235 | spin_lock_irqsave(vhost->host->host_lock, flags); |
@@ -4229,6 +4239,27 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) | |||
4229 | case IBMVFC_HOST_ACTION_LOGO_WAIT: | 4239 | case IBMVFC_HOST_ACTION_LOGO_WAIT: |
4230 | case IBMVFC_HOST_ACTION_INIT_WAIT: | 4240 | case IBMVFC_HOST_ACTION_INIT_WAIT: |
4231 | break; | 4241 | break; |
4242 | case IBMVFC_HOST_ACTION_RESET: | ||
4243 | vhost->action = IBMVFC_HOST_ACTION_TGT_DEL; | ||
4244 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
4245 | rc = ibmvfc_reset_crq(vhost); | ||
4246 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
4247 | if (rc || (rc = ibmvfc_send_crq_init(vhost)) || | ||
4248 | (rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) { | ||
4249 | ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); | ||
4250 | dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc); | ||
4251 | } | ||
4252 | break; | ||
4253 | case IBMVFC_HOST_ACTION_REENABLE: | ||
4254 | vhost->action = IBMVFC_HOST_ACTION_TGT_DEL; | ||
4255 | spin_unlock_irqrestore(vhost->host->host_lock, flags); | ||
4256 | rc = ibmvfc_reenable_crq_queue(vhost); | ||
4257 | spin_lock_irqsave(vhost->host->host_lock, flags); | ||
4258 | if (rc || (rc = ibmvfc_send_crq_init(vhost))) { | ||
4259 | ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); | ||
4260 | dev_err(vhost->dev, "Error after enable (rc=%d)\n", rc); | ||
4261 | } | ||
4262 | break; | ||
4232 | case IBMVFC_HOST_ACTION_LOGO: | 4263 | case IBMVFC_HOST_ACTION_LOGO: |
4233 | vhost->job_step(vhost); | 4264 | vhost->job_step(vhost); |
4234 | break; | 4265 | break; |