aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx
diff options
context:
space:
mode:
authorRoland Dreier <roland@purestorage.com>2015-07-14 16:00:42 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2015-07-24 17:19:38 -0400
commitb2032fd567326ad0b2d443bb6d96d2580ec670a5 (patch)
treefd20379f0d7beb08eb27c791569c4c3b344378f9 /drivers/scsi/qla2xxx
parent9fce12540cb9f91e7f1f539a80b70f0b388bdae0 (diff)
qla2xxx: kill sessions/log out initiator on RSCN and port down events
To fix some issues talking to ESX, this patch modifies the qla2xxx driver so that it never logs into remote ports. This has the side effect of getting rid of the "rports" entirely, which means we never log out of initiators and never tear down sessions when an initiator goes away. This is mostly OK, except that we can run into trouble if we have initiator A assigned FC address X:Y:Z by the fabric talking to us, and then initiator A goes away. Some time (could be a long time) later, initiator B comes along and also gets FC address X:Y:Z (which is available again, because initiator A is gone). If initiator B starts talking to us, then we'll still have the session for initiator A, and since we look up incoming IO based on the FC address X:Y:Z, initiator B will end up using ACLs for initiator A. Fix this by: 1. Handling RSCN events somewhat differently; instead of completely skipping the processing of fcports, we look through the list, and if an fcport disappears, we tell the target code the tear down the session and tell the HBA FW to release the N_Port handle. 2. Handling "port down" events by flushing all of our sessions. The firmware was already releasing the N_Port handle but we want the target code to drop all the sessions too. Cc: <stable@vger.kernel.org> # v3.18+ Signed-off-by: Roland Dreier <roland@purestorage.com> Signed-off-by: Alexei Potashnik <alexei@purestorage.com> Acked-by: Quinn Tran <quinn.tran@qlogic.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c137
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c9
3 files changed, 117 insertions, 31 deletions
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 0e6ee3ca30e6..e9ae6b924c70 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -68,7 +68,7 @@
68 * | | | 0xd101-0xd1fe | 68 * | | | 0xd101-0xd1fe |
69 * | | | 0xd214-0xd2fe | 69 * | | | 0xd214-0xd2fe |
70 * | Target Mode | 0xe079 | | 70 * | Target Mode | 0xe079 | |
71 * | Target Mode Management | 0xf072 | 0xf002 | 71 * | Target Mode Management | 0xf080 | 0xf002 |
72 * | | | 0xf046-0xf049 | 72 * | | | 0xf046-0xf049 |
73 * | Target Mode Task Management | 0x1000b | | 73 * | Target Mode Task Management | 0x1000b | |
74 * ---------------------------------------------------------------------- 74 * ----------------------------------------------------------------------
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 17c3bd919cf6..e166c468a8b2 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -3464,20 +3464,43 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
3464 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) 3464 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
3465 continue; 3465 continue;
3466 3466
3467 if (fcport->scan_state == QLA_FCPORT_SCAN && 3467 if (fcport->scan_state == QLA_FCPORT_SCAN) {
3468 atomic_read(&fcport->state) == FCS_ONLINE) { 3468 if (qla_ini_mode_enabled(base_vha) &&
3469 qla2x00_mark_device_lost(vha, fcport, 3469 atomic_read(&fcport->state) == FCS_ONLINE) {
3470 ql2xplogiabsentdevice, 0); 3470 qla2x00_mark_device_lost(vha, fcport,
3471 if (fcport->loop_id != FC_NO_LOOP_ID && 3471 ql2xplogiabsentdevice, 0);
3472 (fcport->flags & FCF_FCP2_DEVICE) == 0 && 3472 if (fcport->loop_id != FC_NO_LOOP_ID &&
3473 fcport->port_type != FCT_INITIATOR && 3473 (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
3474 fcport->port_type != FCT_BROADCAST) { 3474 fcport->port_type != FCT_INITIATOR &&
3475 ha->isp_ops->fabric_logout(vha, 3475 fcport->port_type != FCT_BROADCAST) {
3476 fcport->loop_id, 3476 ha->isp_ops->fabric_logout(vha,
3477 fcport->d_id.b.domain, 3477 fcport->loop_id,
3478 fcport->d_id.b.area, 3478 fcport->d_id.b.domain,
3479 fcport->d_id.b.al_pa); 3479 fcport->d_id.b.area,
3480 qla2x00_clear_loop_id(fcport); 3480 fcport->d_id.b.al_pa);
3481 qla2x00_clear_loop_id(fcport);
3482 }
3483 } else if (!qla_ini_mode_enabled(base_vha)) {
3484 /*
3485 * In target mode, explicitly kill
3486 * sessions and log out of devices
3487 * that are gone, so that we don't
3488 * end up with an initiator using the
3489 * wrong ACL (if the fabric recycles
3490 * an FC address and we have a stale
3491 * session around) and so that we don't
3492 * report initiators that are no longer
3493 * on the fabric.
3494 */
3495 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
3496 "port gone, logging out/killing session: "
3497 "%8phC state 0x%x flags 0x%x fc4_type 0x%x "
3498 "scan_state %d\n",
3499 fcport->port_name,
3500 atomic_read(&fcport->state),
3501 fcport->flags, fcport->fc4_type,
3502 fcport->scan_state);
3503 qlt_fc_port_deleted(vha, fcport);
3481 } 3504 }
3482 } 3505 }
3483 } 3506 }
@@ -3498,6 +3521,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
3498 (fcport->flags & FCF_LOGIN_NEEDED) == 0) 3521 (fcport->flags & FCF_LOGIN_NEEDED) == 0)
3499 continue; 3522 continue;
3500 3523
3524 /*
3525 * If we're not an initiator, skip looking for devices
3526 * and logging in. There's no reason for us to do it,
3527 * and it seems to actively cause problems in target
3528 * mode if we race with the initiator logging into us
3529 * (we might get the "port ID used" status back from
3530 * our login command and log out the initiator, which
3531 * seems to cause havoc).
3532 */
3533 if (!qla_ini_mode_enabled(base_vha)) {
3534 if (fcport->scan_state == QLA_FCPORT_FOUND) {
3535 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
3536 "port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
3537 "scan_state %d (initiator mode disabled; skipping "
3538 "login)\n", fcport->port_name,
3539 atomic_read(&fcport->state),
3540 fcport->flags, fcport->fc4_type,
3541 fcport->scan_state);
3542 }
3543 continue;
3544 }
3545
3501 if (fcport->loop_id == FC_NO_LOOP_ID) { 3546 if (fcport->loop_id == FC_NO_LOOP_ID) {
3502 fcport->loop_id = next_loopid; 3547 fcport->loop_id = next_loopid;
3503 rval = qla2x00_find_new_loop_id( 3548 rval = qla2x00_find_new_loop_id(
@@ -3524,16 +3569,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
3524 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) 3569 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
3525 break; 3570 break;
3526 3571
3527 /* Find a new loop ID to use. */ 3572 /*
3528 fcport->loop_id = next_loopid; 3573 * If we're not an initiator, skip looking for devices
3529 rval = qla2x00_find_new_loop_id(base_vha, fcport); 3574 * and logging in. There's no reason for us to do it,
3530 if (rval != QLA_SUCCESS) { 3575 * and it seems to actively cause problems in target
3531 /* Ran out of IDs to use */ 3576 * mode if we race with the initiator logging into us
3532 break; 3577 * (we might get the "port ID used" status back from
3533 } 3578 * our login command and log out the initiator, which
3579 * seems to cause havoc).
3580 */
3581 if (qla_ini_mode_enabled(base_vha)) {
3582 /* Find a new loop ID to use. */
3583 fcport->loop_id = next_loopid;
3584 rval = qla2x00_find_new_loop_id(base_vha,
3585 fcport);
3586 if (rval != QLA_SUCCESS) {
3587 /* Ran out of IDs to use */
3588 break;
3589 }
3534 3590
3535 /* Login and update database */ 3591 /* Login and update database */
3536 qla2x00_fabric_dev_login(vha, fcport, &next_loopid); 3592 qla2x00_fabric_dev_login(vha, fcport,
3593 &next_loopid);
3594 } else {
3595 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
3596 "new port %8phC state 0x%x flags 0x%x fc4_type "
3597 "0x%x scan_state %d (initiator mode disabled; "
3598 "skipping login)\n",
3599 fcport->port_name,
3600 atomic_read(&fcport->state),
3601 fcport->flags, fcport->fc4_type,
3602 fcport->scan_state);
3603 }
3537 3604
3538 list_move_tail(&fcport->list, &vha->vp_fcports); 3605 list_move_tail(&fcport->list, &vha->vp_fcports);
3539 } 3606 }
@@ -3729,11 +3796,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
3729 fcport->fp_speed = new_fcport->fp_speed; 3796 fcport->fp_speed = new_fcport->fp_speed;
3730 3797
3731 /* 3798 /*
3732 * If address the same and state FCS_ONLINE, nothing 3799 * If address the same and state FCS_ONLINE
3733 * changed. 3800 * (or in target mode), nothing changed.
3734 */ 3801 */
3735 if (fcport->d_id.b24 == new_fcport->d_id.b24 && 3802 if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
3736 atomic_read(&fcport->state) == FCS_ONLINE) { 3803 (atomic_read(&fcport->state) == FCS_ONLINE ||
3804 !qla_ini_mode_enabled(base_vha))) {
3737 break; 3805 break;
3738 } 3806 }
3739 3807
@@ -3753,6 +3821,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
3753 * Log it out if still logged in and mark it for 3821 * Log it out if still logged in and mark it for
3754 * relogin later. 3822 * relogin later.
3755 */ 3823 */
3824 if (!qla_ini_mode_enabled(base_vha)) {
3825 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
3826 "port changed FC ID, %8phC"
3827 " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
3828 fcport->port_name,
3829 fcport->d_id.b.domain,
3830 fcport->d_id.b.area,
3831 fcport->d_id.b.al_pa,
3832 fcport->loop_id,
3833 new_fcport->d_id.b.domain,
3834 new_fcport->d_id.b.area,
3835 new_fcport->d_id.b.al_pa);
3836 fcport->d_id.b24 = new_fcport->d_id.b24;
3837 break;
3838 }
3839
3756 fcport->d_id.b24 = new_fcport->d_id.b24; 3840 fcport->d_id.b24 = new_fcport->d_id.b24;
3757 fcport->flags |= FCF_LOGIN_NEEDED; 3841 fcport->flags |= FCF_LOGIN_NEEDED;
3758 if (fcport->loop_id != FC_NO_LOOP_ID && 3842 if (fcport->loop_id != FC_NO_LOOP_ID &&
@@ -3772,6 +3856,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
3772 if (found) 3856 if (found)
3773 continue; 3857 continue;
3774 /* If device was not in our fcports list, then add it. */ 3858 /* If device was not in our fcports list, then add it. */
3859 new_fcport->scan_state = QLA_FCPORT_FOUND;
3775 list_add_tail(&new_fcport->list, new_fcports); 3860 list_add_tail(&new_fcport->list, new_fcports);
3776 3861
3777 /* Allocate a new replacement fcport. */ 3862 /* Allocate a new replacement fcport. */
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 17d656b3af6a..d9dd354fcd28 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -113,6 +113,7 @@ static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
113static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, 113static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
114 struct atio_from_isp *atio, uint16_t status, int qfull); 114 struct atio_from_isp *atio, uint16_t status, int qfull);
115static void qlt_disable_vha(struct scsi_qla_host *vha); 115static void qlt_disable_vha(struct scsi_qla_host *vha);
116static void qlt_clear_tgt_db(struct qla_tgt *tgt);
116/* 117/*
117 * Global Variables 118 * Global Variables
118 */ 119 */
@@ -431,10 +432,10 @@ static int qlt_reset(struct scsi_qla_host *vha, void *iocb, int mcmd)
431 432
432 loop_id = le16_to_cpu(n->u.isp24.nport_handle); 433 loop_id = le16_to_cpu(n->u.isp24.nport_handle);
433 if (loop_id == 0xFFFF) { 434 if (loop_id == 0xFFFF) {
434#if 0 /* FIXME: Re-enable Global event handling.. */
435 /* Global event */ 435 /* Global event */
436 atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); 436 atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
437 qlt_clear_tgt_db(ha->tgt.qla_tgt); 437 qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
438#if 0 /* FIXME: do we need to choose a session here? */
438 if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { 439 if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
439 sess = list_entry(ha->tgt.qla_tgt->sess_list.next, 440 sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
440 typeof(*sess), sess_list_entry); 441 typeof(*sess), sess_list_entry);
@@ -788,7 +789,7 @@ void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
788 if (!vha->hw->tgt.tgt_ops) 789 if (!vha->hw->tgt.tgt_ops)
789 return; 790 return;
790 791
791 if (!tgt || (fcport->port_type != FCT_INITIATOR)) 792 if (!tgt)
792 return; 793 return;
793 794
794 if (tgt->tgt_stop) { 795 if (tgt->tgt_stop) {