aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ibmvscsi/ibmvfc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ibmvscsi/ibmvfc.c')
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c85
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 **/
642static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost) 653static 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 **/
668static int ibmvfc_reenable_crq_queue(struct ibmvfc_host *vhost) 681static 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 **/
691static int ibmvfc_reset_crq(struct ibmvfc_host *vhost) 706static 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 **/
822static void ibmvfc_hard_reset_host(struct ibmvfc_host *vhost) 842static 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;