Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending

Pull SCSI target fixes from Nicholas Bellinger:
"This series is larger than what I'd normally be conformable with
sending for a -rc5 PULL request..

However, the bulk of the series is localized to qla2xxx target
specific fixes that address a number of real-world correctness issues,
that have been outstanding on the list for ~6 weeks now. They where
submitted + verified + acked by the HW LLD vendor, contributed by a
major production customer of the code, and are marked for v3.18.y
stable code.

That said, I don't see a good reason to wait another month to get
these fixes into mainline.

Beyond the qla2xx specific fixes, this series also includes:

- bugfix for a long standing use-after-free in iscsi-target during
TPG shutdown + demo-mode sessions.

- bugfix for a >= v4.0 regression OOPs in iscsi-target during a
iscsi_start_kthreads() failure.

- bugfix for a >= v4.0 regression hang in iscsi-target for iser
explicit session/connection logout.

- bugfix for a iser-target bug where a early CMA REJECTED status
during login triggers a NULL pointer dereference OOPs.

- bugfixes for a handful of v4.2-rc1 specific regressions related to
the larger set of recent backend configfs attribute changes.

A big thanks to QLogic + Pure Storage for the qla2xxx target bugfixes"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (28 commits)
Documentation/target: Fix tcm_mod_builder.py build breakage
iser-target: Fix REJECT CM event use-after-free OOPs
iscsi-target: Fix iser explicit logout TX kthread leak
iscsi-target: Fix iscsit_start_kthreads failure OOPs
iscsi-target: Fix use-after-free during TPG session shutdown
qla2xxx: terminate exchange when command is aborted by LIO
qla2xxx: drop cmds/tmrs arrived while session is being deleted
qla2xxx: disable scsi_transport_fc registration in target mode
qla2xxx: added sess generations to detect RSCN update races
qla2xxx: Abort stale cmds on qla_tgt_wq when plogi arrives
qla2xxx: delay plogi/prli ack until existing sessions are deleted
qla2xxx: cleanup cmd in qla workqueue before processing TMR
qla2xxx: kill sessions/log out initiator on RSCN and port down events
qla2xxx: fix command initialization in target mode.
qla2xxx: Remove msleep in qlt_send_term_exchange
qla2xxx: adjust debug flags
qla2xxx: release request queue reservation.
qla2xxx: Add flush after updating ATIOQ consumer index.
qla2xxx: Enable target mode for ISP27XX
qla2xxx: Fix hardware lock/unlock issue causing kernel panic.
...

+1106 -221
+14 -7
Documentation/target/tcm_mod_builder.py
··· 199 199 buf += "#include <linux/string.h>\n" 200 200 buf += "#include <linux/configfs.h>\n" 201 201 buf += "#include <linux/ctype.h>\n" 202 - buf += "#include <asm/unaligned.h>\n\n" 202 + buf += "#include <asm/unaligned.h>\n" 203 + buf += "#include <scsi/scsi_proto.h>\n\n" 203 204 buf += "#include <target/target_core_base.h>\n" 204 205 buf += "#include <target/target_core_fabric.h>\n" 205 206 buf += "#include <target/target_core_fabric_configfs.h>\n" ··· 231 230 buf += " }\n" 232 231 buf += " tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n" 233 232 buf += " tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n" 234 - buf += " ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n" 235 - buf += " &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n" 233 + 234 + if proto_ident == "FC": 235 + buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);\n" 236 + elif proto_ident == "SAS": 237 + buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n" 238 + elif proto_ident == "iSCSI": 239 + buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_ISCSI);\n" 240 + 236 241 buf += " if (ret < 0) {\n" 237 242 buf += " kfree(tpg);\n" 238 243 buf += " return NULL;\n" ··· 299 292 300 293 buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n" 301 294 buf += " .module = THIS_MODULE,\n" 302 - buf += " .name = " + fabric_mod_name + ",\n" 295 + buf += " .name = \"" + fabric_mod_name + "\",\n" 303 296 buf += " .get_fabric_name = " + fabric_mod_name + "_get_fabric_name,\n" 304 297 buf += " .tpg_get_wwn = " + fabric_mod_name + "_get_fabric_wwn,\n" 305 298 buf += " .tpg_get_tag = " + fabric_mod_name + "_get_tag,\n" ··· 329 322 buf += " .fabric_make_tpg = " + fabric_mod_name + "_make_tpg,\n" 330 323 buf += " .fabric_drop_tpg = " + fabric_mod_name + "_drop_tpg,\n" 331 324 buf += "\n" 332 - buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs;\n" 325 + buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs,\n" 333 326 buf += "};\n\n" 334 327 335 328 buf += "static int __init " + fabric_mod_name + "_init(void)\n" 336 329 buf += "{\n" 337 - buf += " return target_register_template(" + fabric_mod_name + "_ops);\n" 330 + buf += " return target_register_template(&" + fabric_mod_name + "_ops);\n" 338 331 buf += "};\n\n" 339 332 340 333 buf += "static void __exit " + fabric_mod_name + "_exit(void)\n" 341 334 buf += "{\n" 342 - buf += " target_unregister_template(" + fabric_mod_name + "_ops);\n" 335 + buf += " target_unregister_template(&" + fabric_mod_name + "_ops);\n" 343 336 buf += "};\n\n" 344 337 345 338 buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
+11 -5
drivers/infiniband/ulp/isert/ib_isert.c
··· 775 775 ret = isert_rdma_post_recvl(isert_conn); 776 776 if (ret) 777 777 goto out_conn_dev; 778 + /* 779 + * Obtain the second reference now before isert_rdma_accept() to 780 + * ensure that any initiator generated REJECT CM event that occurs 781 + * asynchronously won't drop the last reference until the error path 782 + * in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() -> 783 + * isert_free_conn() -> isert_put_conn() -> kref_put(). 784 + */ 785 + if (!kref_get_unless_zero(&isert_conn->kref)) { 786 + isert_warn("conn %p connect_release is running\n", isert_conn); 787 + goto out_conn_dev; 788 + } 778 789 779 790 ret = isert_rdma_accept(isert_conn); 780 791 if (ret) ··· 846 835 struct isert_conn *isert_conn = cma_id->qp->qp_context; 847 836 848 837 isert_info("conn %p\n", isert_conn); 849 - 850 - if (!kref_get_unless_zero(&isert_conn->kref)) { 851 - isert_warn("conn %p connect_release is running\n", isert_conn); 852 - return; 853 - } 854 838 855 839 mutex_lock(&isert_conn->mutex); 856 840 if (isert_conn->state != ISER_CONN_FULL_FEATURE)
+1 -1
drivers/scsi/qla2xxx/qla_attr.c
··· 738 738 ql_log(ql_log_info, vha, 0x706f, 739 739 "Issuing MPI reset.\n"); 740 740 741 - if (IS_QLA83XX(ha)) { 741 + if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) { 742 742 uint32_t idc_control; 743 743 744 744 qla83xx_idc_lock(vha, 0);
+3 -3
drivers/scsi/qla2xxx/qla_dbg.c
··· 67 67 * | | | 0xd031-0xd0ff | 68 68 * | | | 0xd101-0xd1fe | 69 69 * | | | 0xd214-0xd2fe | 70 - * | Target Mode | 0xe079 | | 71 - * | Target Mode Management | 0xf072 | 0xf002 | 70 + * | Target Mode | 0xe080 | | 71 + * | Target Mode Management | 0xf096 | 0xf002 | 72 72 * | | | 0xf046-0xf049 | 73 - * | Target Mode Task Management | 0x1000b | | 73 + * | Target Mode Task Management | 0x1000d | | 74 74 * ---------------------------------------------------------------------- 75 75 */ 76 76
+16 -4
drivers/scsi/qla2xxx/qla_def.h
··· 274 274 #define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/ 275 275 276 276 struct req_que; 277 + struct qla_tgt_sess; 277 278 278 279 /* 279 280 * (sd.h is not exported, hence local inclusion) ··· 2027 2026 uint16_t port_id; 2028 2027 2029 2028 unsigned long retry_delay_timestamp; 2029 + struct qla_tgt_sess *tgt_session; 2030 2030 } fc_port_t; 2031 2031 2032 2032 #include "qla_mr.h" ··· 3156 3154 /* Bit 21 of fw_attributes decides the MCTP capabilities */ 3157 3155 #define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \ 3158 3156 ((ha)->fw_attributes_ext[0] & BIT_0)) 3159 - #define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha)) 3160 - #define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha)) 3157 + #define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) 3158 + #define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) 3161 3159 #define IS_PI_DIFB_DIX0_CAPABLE(ha) (0) 3162 - #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha)) 3160 + #define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) 3163 3161 #define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \ 3164 3162 (((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22)) 3165 - #define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha)) 3163 + #define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) 3166 3164 #define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length) 3167 3165 #define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha)) 3168 3166 #define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha)) ··· 3580 3578 uint16_t fcoe_vlan_id; 3581 3579 uint16_t fcoe_fcf_idx; 3582 3580 uint8_t fcoe_vn_port_mac[6]; 3581 + 3582 + /* list of commands waiting on workqueue */ 3583 + struct list_head qla_cmd_list; 3584 + struct list_head qla_sess_op_cmd_list; 3585 + spinlock_t cmd_list_lock; 3586 + 3587 + /* Counter to detect races between ELS and RSCN events */ 3588 + atomic_t generation_tick; 3589 + /* Time when global fcport update has been scheduled */ 3590 + int total_fcport_update_gen; 3583 3591 3584 3592 uint32_t vp_abort_cnt; 3585 3593
+150 -40
drivers/scsi/qla2xxx/qla_init.c
··· 115 115 QLA_LOGIO_LOGIN_RETRIED : 0; 116 116 qla2x00_post_async_login_done_work(fcport->vha, fcport, 117 117 lio->u.logio.data); 118 + } else if (sp->type == SRB_LOGOUT_CMD) { 119 + qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT); 118 120 } 119 121 } 120 122 ··· 499 497 qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport, 500 498 uint16_t *data) 501 499 { 502 - qla2x00_mark_device_lost(vha, fcport, 1, 0); 500 + /* Don't re-login in target mode */ 501 + if (!fcport->tgt_session) 502 + qla2x00_mark_device_lost(vha, fcport, 1, 0); 503 + qlt_logo_completion_handler(fcport, data[0]); 503 504 return; 504 505 } 505 506 ··· 1543 1538 mem_size = (ha->fw_memory_size - 0x11000 + 1) * 1544 1539 sizeof(uint16_t); 1545 1540 } else if (IS_FWI2_CAPABLE(ha)) { 1546 - if (IS_QLA83XX(ha)) 1541 + if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) 1547 1542 fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem); 1548 1543 else if (IS_QLA81XX(ha)) 1549 1544 fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem); ··· 1555 1550 mem_size = (ha->fw_memory_size - 0x100000 + 1) * 1556 1551 sizeof(uint32_t); 1557 1552 if (ha->mqenable) { 1558 - if (!IS_QLA83XX(ha)) 1553 + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) 1559 1554 mq_size = sizeof(struct qla2xxx_mq_chain); 1560 1555 /* 1561 1556 * Allocate maximum buffer size for all queues. ··· 2927 2922 { 2928 2923 fc_port_t *fcport = data; 2929 2924 struct fc_rport *rport; 2930 - scsi_qla_host_t *vha = fcport->vha; 2931 2925 unsigned long flags; 2932 2926 2933 2927 spin_lock_irqsave(fcport->vha->host->host_lock, flags); 2934 2928 rport = fcport->drport ? fcport->drport: fcport->rport; 2935 2929 fcport->drport = NULL; 2936 2930 spin_unlock_irqrestore(fcport->vha->host->host_lock, flags); 2937 - if (rport) { 2931 + if (rport) 2938 2932 fc_remote_port_delete(rport); 2939 - /* 2940 - * Release the target mode FC NEXUS in qla_target.c code 2941 - * if target mod is enabled. 2942 - */ 2943 - qlt_fc_port_deleted(vha, fcport); 2944 - } 2945 2933 } 2946 2934 2947 2935 /** ··· 3301 3303 * Create target mode FC NEXUS in qla_target.c if target mode is 3302 3304 * enabled.. 3303 3305 */ 3306 + 3304 3307 qlt_fc_port_added(vha, fcport); 3305 3308 3306 3309 spin_lock_irqsave(fcport->vha->host->host_lock, flags); ··· 3340 3341 3341 3342 if (IS_QLAFX00(vha->hw)) { 3342 3343 qla2x00_set_fcport_state(fcport, FCS_ONLINE); 3343 - qla2x00_reg_remote_port(vha, fcport); 3344 - return; 3344 + goto reg_port; 3345 3345 } 3346 3346 fcport->login_retry = 0; 3347 3347 fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT); ··· 3348 3350 qla2x00_set_fcport_state(fcport, FCS_ONLINE); 3349 3351 qla2x00_iidma_fcport(vha, fcport); 3350 3352 qla24xx_update_fcport_fcp_prio(vha, fcport); 3351 - qla2x00_reg_remote_port(vha, fcport); 3353 + 3354 + reg_port: 3355 + if (qla_ini_mode_enabled(vha)) 3356 + qla2x00_reg_remote_port(vha, fcport); 3357 + else { 3358 + /* 3359 + * Create target mode FC NEXUS in qla_target.c 3360 + */ 3361 + qlt_fc_port_added(vha, fcport); 3362 + } 3352 3363 } 3353 3364 3354 3365 /* ··· 3382 3375 LIST_HEAD(new_fcports); 3383 3376 struct qla_hw_data *ha = vha->hw; 3384 3377 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); 3378 + int discovery_gen; 3385 3379 3386 3380 /* If FL port exists, then SNS is present */ 3387 3381 if (IS_FWI2_CAPABLE(ha)) ··· 3453 3445 fcport->scan_state = QLA_FCPORT_SCAN; 3454 3446 } 3455 3447 3448 + /* Mark the time right before querying FW for connected ports. 3449 + * This process is long, asynchronous and by the time it's done, 3450 + * collected information might not be accurate anymore. E.g. 3451 + * disconnected port might have re-connected and a brand new 3452 + * session has been created. In this case session's generation 3453 + * will be newer than discovery_gen. */ 3454 + qlt_do_generation_tick(vha, &discovery_gen); 3455 + 3456 3456 rval = qla2x00_find_all_fabric_devs(vha, &new_fcports); 3457 3457 if (rval != QLA_SUCCESS) 3458 3458 break; ··· 3476 3460 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) 3477 3461 continue; 3478 3462 3479 - if (fcport->scan_state == QLA_FCPORT_SCAN && 3480 - atomic_read(&fcport->state) == FCS_ONLINE) { 3481 - qla2x00_mark_device_lost(vha, fcport, 3482 - ql2xplogiabsentdevice, 0); 3483 - if (fcport->loop_id != FC_NO_LOOP_ID && 3484 - (fcport->flags & FCF_FCP2_DEVICE) == 0 && 3485 - fcport->port_type != FCT_INITIATOR && 3486 - fcport->port_type != FCT_BROADCAST) { 3487 - ha->isp_ops->fabric_logout(vha, 3488 - fcport->loop_id, 3489 - fcport->d_id.b.domain, 3490 - fcport->d_id.b.area, 3491 - fcport->d_id.b.al_pa); 3492 - qla2x00_clear_loop_id(fcport); 3463 + if (fcport->scan_state == QLA_FCPORT_SCAN) { 3464 + if (qla_ini_mode_enabled(base_vha) && 3465 + atomic_read(&fcport->state) == FCS_ONLINE) { 3466 + qla2x00_mark_device_lost(vha, fcport, 3467 + ql2xplogiabsentdevice, 0); 3468 + if (fcport->loop_id != FC_NO_LOOP_ID && 3469 + (fcport->flags & FCF_FCP2_DEVICE) == 0 && 3470 + fcport->port_type != FCT_INITIATOR && 3471 + fcport->port_type != FCT_BROADCAST) { 3472 + ha->isp_ops->fabric_logout(vha, 3473 + fcport->loop_id, 3474 + fcport->d_id.b.domain, 3475 + fcport->d_id.b.area, 3476 + fcport->d_id.b.al_pa); 3477 + qla2x00_clear_loop_id(fcport); 3478 + } 3479 + } else if (!qla_ini_mode_enabled(base_vha)) { 3480 + /* 3481 + * In target mode, explicitly kill 3482 + * sessions and log out of devices 3483 + * that are gone, so that we don't 3484 + * end up with an initiator using the 3485 + * wrong ACL (if the fabric recycles 3486 + * an FC address and we have a stale 3487 + * session around) and so that we don't 3488 + * report initiators that are no longer 3489 + * on the fabric. 3490 + */ 3491 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077, 3492 + "port gone, logging out/killing session: " 3493 + "%8phC state 0x%x flags 0x%x fc4_type 0x%x " 3494 + "scan_state %d\n", 3495 + fcport->port_name, 3496 + atomic_read(&fcport->state), 3497 + fcport->flags, fcport->fc4_type, 3498 + fcport->scan_state); 3499 + qlt_fc_port_deleted(vha, fcport, 3500 + discovery_gen); 3493 3501 } 3494 3502 } 3495 3503 } ··· 3533 3493 if ((fcport->flags & FCF_FABRIC_DEVICE) == 0 || 3534 3494 (fcport->flags & FCF_LOGIN_NEEDED) == 0) 3535 3495 continue; 3496 + 3497 + /* 3498 + * If we're not an initiator, skip looking for devices 3499 + * and logging in. There's no reason for us to do it, 3500 + * and it seems to actively cause problems in target 3501 + * mode if we race with the initiator logging into us 3502 + * (we might get the "port ID used" status back from 3503 + * our login command and log out the initiator, which 3504 + * seems to cause havoc). 3505 + */ 3506 + if (!qla_ini_mode_enabled(base_vha)) { 3507 + if (fcport->scan_state == QLA_FCPORT_FOUND) { 3508 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078, 3509 + "port %8phC state 0x%x flags 0x%x fc4_type 0x%x " 3510 + "scan_state %d (initiator mode disabled; skipping " 3511 + "login)\n", fcport->port_name, 3512 + atomic_read(&fcport->state), 3513 + fcport->flags, fcport->fc4_type, 3514 + fcport->scan_state); 3515 + } 3516 + continue; 3517 + } 3536 3518 3537 3519 if (fcport->loop_id == FC_NO_LOOP_ID) { 3538 3520 fcport->loop_id = next_loopid; ··· 3582 3520 test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags)) 3583 3521 break; 3584 3522 3585 - /* Find a new loop ID to use. */ 3586 - fcport->loop_id = next_loopid; 3587 - rval = qla2x00_find_new_loop_id(base_vha, fcport); 3588 - if (rval != QLA_SUCCESS) { 3589 - /* Ran out of IDs to use */ 3590 - break; 3591 - } 3523 + /* 3524 + * If we're not an initiator, skip looking for devices 3525 + * and logging in. There's no reason for us to do it, 3526 + * and it seems to actively cause problems in target 3527 + * mode if we race with the initiator logging into us 3528 + * (we might get the "port ID used" status back from 3529 + * our login command and log out the initiator, which 3530 + * seems to cause havoc). 3531 + */ 3532 + if (qla_ini_mode_enabled(base_vha)) { 3533 + /* Find a new loop ID to use. */ 3534 + fcport->loop_id = next_loopid; 3535 + rval = qla2x00_find_new_loop_id(base_vha, 3536 + fcport); 3537 + if (rval != QLA_SUCCESS) { 3538 + /* Ran out of IDs to use */ 3539 + break; 3540 + } 3592 3541 3593 - /* Login and update database */ 3594 - qla2x00_fabric_dev_login(vha, fcport, &next_loopid); 3542 + /* Login and update database */ 3543 + qla2x00_fabric_dev_login(vha, fcport, 3544 + &next_loopid); 3545 + } else { 3546 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079, 3547 + "new port %8phC state 0x%x flags 0x%x fc4_type " 3548 + "0x%x scan_state %d (initiator mode disabled; " 3549 + "skipping login)\n", 3550 + fcport->port_name, 3551 + atomic_read(&fcport->state), 3552 + fcport->flags, fcport->fc4_type, 3553 + fcport->scan_state); 3554 + } 3595 3555 3596 3556 list_move_tail(&fcport->list, &vha->vp_fcports); 3597 3557 } ··· 3809 3725 fcport->fp_speed = new_fcport->fp_speed; 3810 3726 3811 3727 /* 3812 - * If address the same and state FCS_ONLINE, nothing 3813 - * changed. 3728 + * If address the same and state FCS_ONLINE 3729 + * (or in target mode), nothing changed. 3814 3730 */ 3815 3731 if (fcport->d_id.b24 == new_fcport->d_id.b24 && 3816 - atomic_read(&fcport->state) == FCS_ONLINE) { 3732 + (atomic_read(&fcport->state) == FCS_ONLINE || 3733 + !qla_ini_mode_enabled(base_vha))) { 3817 3734 break; 3818 3735 } 3819 3736 ··· 3834 3749 * Log it out if still logged in and mark it for 3835 3750 * relogin later. 3836 3751 */ 3752 + if (!qla_ini_mode_enabled(base_vha)) { 3753 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080, 3754 + "port changed FC ID, %8phC" 3755 + " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n", 3756 + fcport->port_name, 3757 + fcport->d_id.b.domain, 3758 + fcport->d_id.b.area, 3759 + fcport->d_id.b.al_pa, 3760 + fcport->loop_id, 3761 + new_fcport->d_id.b.domain, 3762 + new_fcport->d_id.b.area, 3763 + new_fcport->d_id.b.al_pa); 3764 + fcport->d_id.b24 = new_fcport->d_id.b24; 3765 + break; 3766 + } 3767 + 3837 3768 fcport->d_id.b24 = new_fcport->d_id.b24; 3838 3769 fcport->flags |= FCF_LOGIN_NEEDED; 3839 3770 if (fcport->loop_id != FC_NO_LOOP_ID && ··· 3869 3768 if (found) 3870 3769 continue; 3871 3770 /* If device was not in our fcports list, then add it. */ 3771 + new_fcport->scan_state = QLA_FCPORT_FOUND; 3872 3772 list_add_tail(&new_fcport->list, new_fcports); 3873 3773 3874 3774 /* Allocate a new replacement fcport. */ ··· 4290 4188 atomic_read(&fcport->state) != FCS_UNCONFIGURED) { 4291 4189 spin_unlock_irqrestore(&ha->vport_slock, flags); 4292 4190 qla2x00_rport_del(fcport); 4191 + 4192 + /* 4193 + * Release the target mode FC NEXUS in 4194 + * qla_target.c, if target mod is enabled. 4195 + */ 4196 + qlt_fc_port_deleted(vha, fcport, 4197 + base_vha->total_fcport_update_gen); 4198 + 4293 4199 spin_lock_irqsave(&ha->vport_slock, flags); 4294 4200 } 4295 4201 }
+3
drivers/scsi/qla2xxx/qla_iocb.c
··· 1943 1943 logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; 1944 1944 logio->control_flags = 1945 1945 cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); 1946 + if (!sp->fcport->tgt_session || 1947 + !sp->fcport->tgt_session->keep_nport_handle) 1948 + logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT); 1946 1949 logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); 1947 1950 logio->port_id[0] = sp->fcport->d_id.b.al_pa; 1948 1951 logio->port_id[1] = sp->fcport->d_id.b.area;
+4 -3
drivers/scsi/qla2xxx/qla_mbx.c
··· 2415 2415 *orig_iocb_cnt = mcp->mb[10]; 2416 2416 if (vha->hw->flags.npiv_supported && max_npiv_vports) 2417 2417 *max_npiv_vports = mcp->mb[11]; 2418 - if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs) 2418 + if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) || 2419 + IS_QLA27XX(vha->hw)) && max_fcfs) 2419 2420 *max_fcfs = mcp->mb[12]; 2420 2421 } 2421 2422 ··· 3899 3898 spin_lock_irqsave(&ha->hardware_lock, flags); 3900 3899 if (!(rsp->options & BIT_0)) { 3901 3900 WRT_REG_DWORD(rsp->rsp_q_out, 0); 3902 - if (!IS_QLA83XX(ha)) 3901 + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) 3903 3902 WRT_REG_DWORD(rsp->rsp_q_in, 0); 3904 3903 } 3905 3904 ··· 5346 5345 mbx_cmd_t *mcp = &mc; 5347 5346 struct qla_hw_data *ha = vha->hw; 5348 5347 5349 - if (!IS_QLA83XX(ha)) 5348 + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) 5350 5349 return QLA_FUNCTION_FAILED; 5351 5350 5352 5351 ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
+10 -2
drivers/scsi/qla2xxx/qla_os.c
··· 2504 2504 ha->mbx_count = MAILBOX_REGISTER_COUNT; 2505 2505 req_length = REQUEST_ENTRY_CNT_24XX; 2506 2506 rsp_length = RESPONSE_ENTRY_CNT_2300; 2507 + ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX; 2507 2508 ha->max_loop_id = SNS_LAST_LOOP_ID_2300; 2508 2509 ha->init_cb_size = sizeof(struct mid_init_cb_81xx); 2509 2510 ha->gid_list_info_size = 8; ··· 3230 3229 spin_lock_irqsave(vha->host->host_lock, flags); 3231 3230 fcport->drport = rport; 3232 3231 spin_unlock_irqrestore(vha->host->host_lock, flags); 3232 + qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen); 3233 3233 set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); 3234 3234 qla2xxx_wake_dpc(base_vha); 3235 3235 } else { 3236 - fc_remote_port_delete(rport); 3237 - qlt_fc_port_deleted(vha, fcport); 3236 + int now; 3237 + if (rport) 3238 + fc_remote_port_delete(rport); 3239 + qlt_do_generation_tick(vha, &now); 3240 + qlt_fc_port_deleted(vha, fcport, now); 3238 3241 } 3239 3242 } 3240 3243 ··· 3768 3763 INIT_LIST_HEAD(&vha->vp_fcports); 3769 3764 INIT_LIST_HEAD(&vha->work_list); 3770 3765 INIT_LIST_HEAD(&vha->list); 3766 + INIT_LIST_HEAD(&vha->qla_cmd_list); 3767 + INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list); 3771 3768 3772 3769 spin_lock_init(&vha->work_lock); 3770 + spin_lock_init(&vha->cmd_list_lock); 3773 3771 3774 3772 sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no); 3775 3773 ql_dbg(ql_dbg_init, vha, 0x0041,
+1 -1
drivers/scsi/qla2xxx/qla_sup.c
··· 1697 1697 { 1698 1698 uint32_t led_select_value = 0; 1699 1699 1700 - if (!IS_QLA83XX(ha)) 1700 + if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha)) 1701 1701 goto out; 1702 1702 1703 1703 if (ha->port_no == 0)
+692 -71
drivers/scsi/qla2xxx/qla_target.c
··· 113 113 static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha, 114 114 struct atio_from_isp *atio, uint16_t status, int qfull); 115 115 static void qlt_disable_vha(struct scsi_qla_host *vha); 116 + static void qlt_clear_tgt_db(struct qla_tgt *tgt); 117 + static void qlt_send_notify_ack(struct scsi_qla_host *vha, 118 + struct imm_ntfy_from_isp *ntfy, 119 + uint32_t add_flags, uint16_t resp_code, int resp_code_valid, 120 + uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan); 116 121 /* 117 122 * Global Variables 118 123 */ ··· 126 121 static struct workqueue_struct *qla_tgt_wq; 127 122 static DEFINE_MUTEX(qla_tgt_mutex); 128 123 static LIST_HEAD(qla_tgt_glist); 124 + 125 + /* This API intentionally takes dest as a parameter, rather than returning 126 + * int value to avoid caller forgetting to issue wmb() after the store */ 127 + void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest) 128 + { 129 + scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev); 130 + *dest = atomic_inc_return(&base_vha->generation_tick); 131 + /* memory barrier */ 132 + wmb(); 133 + } 129 134 130 135 /* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */ 131 136 static struct qla_tgt_sess *qlt_find_sess_by_port_name( ··· 396 381 struct qla_tgt *tgt = sess->tgt; 397 382 struct scsi_qla_host *vha = sess->vha; 398 383 struct qla_hw_data *ha = vha->hw; 384 + unsigned long flags; 385 + bool logout_started = false; 386 + fc_port_t fcport; 387 + 388 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084, 389 + "%s: se_sess %p / sess %p from port %8phC loop_id %#04x" 390 + " s_id %02x:%02x:%02x logout %d keep %d plogi %d\n", 391 + __func__, sess->se_sess, sess, sess->port_name, sess->loop_id, 392 + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, 393 + sess->logout_on_delete, sess->keep_nport_handle, 394 + sess->plogi_ack_needed); 399 395 400 396 BUG_ON(!tgt); 397 + 398 + if (sess->logout_on_delete) { 399 + int rc; 400 + 401 + memset(&fcport, 0, sizeof(fcport)); 402 + fcport.loop_id = sess->loop_id; 403 + fcport.d_id = sess->s_id; 404 + memcpy(fcport.port_name, sess->port_name, WWN_SIZE); 405 + fcport.vha = vha; 406 + fcport.tgt_session = sess; 407 + 408 + rc = qla2x00_post_async_logout_work(vha, &fcport, NULL); 409 + if (rc != QLA_SUCCESS) 410 + ql_log(ql_log_warn, vha, 0xf085, 411 + "Schedule logo failed sess %p rc %d\n", 412 + sess, rc); 413 + else 414 + logout_started = true; 415 + } 416 + 401 417 /* 402 418 * Release the target session for FC Nexus from fabric module code. 403 419 */ 404 420 if (sess->se_sess != NULL) 405 421 ha->tgt.tgt_ops->free_session(sess); 422 + 423 + if (logout_started) { 424 + bool traced = false; 425 + 426 + while (!ACCESS_ONCE(sess->logout_completed)) { 427 + if (!traced) { 428 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086, 429 + "%s: waiting for sess %p logout\n", 430 + __func__, sess); 431 + traced = true; 432 + } 433 + msleep(100); 434 + } 435 + 436 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087, 437 + "%s: sess %p logout completed\n", 438 + __func__, sess); 439 + } 440 + 441 + spin_lock_irqsave(&ha->hardware_lock, flags); 442 + 443 + if (sess->plogi_ack_needed) 444 + qlt_send_notify_ack(vha, &sess->tm_iocb, 445 + 0, 0, 0, 0, 0, 0); 446 + 447 + list_del(&sess->sess_list_entry); 448 + 449 + spin_unlock_irqrestore(&ha->hardware_lock, flags); 406 450 407 451 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001, 408 452 "Unregistration of sess %p finished\n", sess); ··· 483 409 484 410 vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess); 485 411 486 - list_del(&sess->sess_list_entry); 487 - if (sess->deleted) 488 - list_del(&sess->del_list_entry); 412 + if (!list_empty(&sess->del_list_entry)) 413 + list_del_init(&sess->del_list_entry); 414 + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; 489 415 490 416 INIT_WORK(&sess->free_work, qlt_free_session_done); 491 417 schedule_work(&sess->free_work); ··· 505 431 506 432 loop_id = le16_to_cpu(n->u.isp24.nport_handle); 507 433 if (loop_id == 0xFFFF) { 508 - #if 0 /* FIXME: Re-enable Global event handling.. */ 509 434 /* Global event */ 510 - atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count); 511 - qlt_clear_tgt_db(ha->tgt.qla_tgt); 435 + atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count); 436 + qlt_clear_tgt_db(vha->vha_tgt.qla_tgt); 437 + #if 0 /* FIXME: do we need to choose a session here? */ 512 438 if (!list_empty(&ha->tgt.qla_tgt->sess_list)) { 513 439 sess = list_entry(ha->tgt.qla_tgt->sess_list.next, 514 440 typeof(*sess), sess_list_entry); ··· 563 489 struct qla_tgt *tgt = sess->tgt; 564 490 uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5; 565 491 566 - if (sess->deleted) 567 - return; 492 + if (sess->deleted) { 493 + /* Upgrade to unconditional deletion in case it was temporary */ 494 + if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING) 495 + list_del(&sess->del_list_entry); 496 + else 497 + return; 498 + } 568 499 569 500 ql_dbg(ql_dbg_tgt, sess->vha, 0xe001, 570 501 "Scheduling sess %p for deletion\n", sess); 571 - list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); 572 - sess->deleted = 1; 573 502 574 - if (immediate) 503 + if (immediate) { 575 504 dev_loss_tmo = 0; 505 + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; 506 + list_add(&sess->del_list_entry, &tgt->del_sess_list); 507 + } else { 508 + sess->deleted = QLA_SESS_DELETION_PENDING; 509 + list_add_tail(&sess->del_list_entry, &tgt->del_sess_list); 510 + } 576 511 577 512 sess->expires = jiffies + dev_loss_tmo * HZ; 578 513 579 514 ql_dbg(ql_dbg_tgt, sess->vha, 0xe048, 580 - "qla_target(%d): session for port %8phC (loop ID %d) scheduled for " 581 - "deletion in %u secs (expires: %lu) immed: %d\n", 582 - sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo, 583 - sess->expires, immediate); 515 + "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)" 516 + " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n", 517 + sess->vha->vp_idx, sess->port_name, sess->loop_id, 518 + sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, 519 + dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete, 520 + sess->generation); 584 521 585 522 if (immediate) 586 - schedule_delayed_work(&tgt->sess_del_work, 0); 523 + mod_delayed_work(system_wq, &tgt->sess_del_work, 0); 587 524 else 588 525 schedule_delayed_work(&tgt->sess_del_work, 589 526 sess->expires - jiffies); ··· 663 578 /* ha->hardware_lock supposed to be held on entry */ 664 579 static void qlt_undelete_sess(struct qla_tgt_sess *sess) 665 580 { 666 - BUG_ON(!sess->deleted); 581 + BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING); 667 582 668 - list_del(&sess->del_list_entry); 583 + list_del_init(&sess->del_list_entry); 669 584 sess->deleted = 0; 670 585 } 671 586 ··· 684 599 del_list_entry); 685 600 elapsed = jiffies; 686 601 if (time_after_eq(elapsed, sess->expires)) { 687 - qlt_undelete_sess(sess); 602 + /* No turning back */ 603 + list_del_init(&sess->del_list_entry); 604 + sess->deleted = QLA_SESS_DELETION_IN_PROGRESS; 688 605 689 606 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004, 690 607 "Timeout: sess %p about to be deleted\n", ··· 730 643 fcport->d_id.b.al_pa, fcport->d_id.b.area, 731 644 fcport->loop_id); 732 645 646 + /* Cannot undelete at this point */ 647 + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 648 + spin_unlock_irqrestore(&ha->hardware_lock, 649 + flags); 650 + return NULL; 651 + } 652 + 733 653 if (sess->deleted) 734 654 qlt_undelete_sess(sess); 735 655 ··· 746 652 747 653 if (sess->local && !local) 748 654 sess->local = 0; 655 + 656 + qlt_do_generation_tick(vha, &sess->generation); 657 + 749 658 spin_unlock_irqrestore(&ha->hardware_lock, flags); 750 659 751 660 return sess; ··· 770 673 sess->s_id = fcport->d_id; 771 674 sess->loop_id = fcport->loop_id; 772 675 sess->local = local; 676 + INIT_LIST_HEAD(&sess->del_list_entry); 677 + 678 + /* Under normal circumstances we want to logout from firmware when 679 + * session eventually ends and release corresponding nport handle. 680 + * In the exception cases (e.g. when new PLOGI is waiting) corresponding 681 + * code will adjust these flags as necessary. */ 682 + sess->logout_on_delete = 1; 683 + sess->keep_nport_handle = 0; 773 684 774 685 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006, 775 686 "Adding sess %p to tgt %p via ->check_initiator_node_acl()\n", ··· 810 705 spin_lock_irqsave(&ha->hardware_lock, flags); 811 706 list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list); 812 707 vha->vha_tgt.qla_tgt->sess_count++; 708 + qlt_do_generation_tick(vha, &sess->generation); 813 709 spin_unlock_irqrestore(&ha->hardware_lock, flags); 814 710 815 711 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b, ··· 824 718 } 825 719 826 720 /* 827 - * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port() 721 + * Called from qla2x00_reg_remote_port() 828 722 */ 829 723 void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) 830 724 { ··· 856 750 mutex_unlock(&vha->vha_tgt.tgt_mutex); 857 751 858 752 spin_lock_irqsave(&ha->hardware_lock, flags); 753 + } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 754 + /* Point of no return */ 755 + spin_unlock_irqrestore(&ha->hardware_lock, flags); 756 + return; 859 757 } else { 860 758 kref_get(&sess->se_sess->sess_kref); 861 759 ··· 890 780 spin_unlock_irqrestore(&ha->hardware_lock, flags); 891 781 } 892 782 893 - void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport) 783 + /* 784 + * max_gen - specifies maximum session generation 785 + * at which this deletion requestion is still valid 786 + */ 787 + void 788 + qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen) 894 789 { 895 - struct qla_hw_data *ha = vha->hw; 896 790 struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 897 791 struct qla_tgt_sess *sess; 898 - unsigned long flags; 899 792 900 793 if (!vha->hw->tgt.tgt_ops) 901 794 return; 902 795 903 - if (!tgt || (fcport->port_type != FCT_INITIATOR)) 796 + if (!tgt) 904 797 return; 905 798 906 - spin_lock_irqsave(&ha->hardware_lock, flags); 907 799 if (tgt->tgt_stop) { 908 - spin_unlock_irqrestore(&ha->hardware_lock, flags); 909 800 return; 910 801 } 911 802 sess = qlt_find_sess_by_port_name(tgt, fcport->port_name); 912 803 if (!sess) { 913 - spin_unlock_irqrestore(&ha->hardware_lock, flags); 804 + return; 805 + } 806 + 807 + if (max_gen - sess->generation < 0) { 808 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092, 809 + "Ignoring stale deletion request for se_sess %p / sess %p" 810 + " for port %8phC, req_gen %d, sess_gen %d\n", 811 + sess->se_sess, sess, sess->port_name, max_gen, 812 + sess->generation); 914 813 return; 915 814 } 916 815 ··· 927 808 928 809 sess->local = 1; 929 810 qlt_schedule_sess_for_deletion(sess, false); 930 - spin_unlock_irqrestore(&ha->hardware_lock, flags); 931 811 } 932 812 933 813 static inline int test_tgt_sess_count(struct qla_tgt *tgt) ··· 1293 1175 FCP_TMF_CMPL, true); 1294 1176 } 1295 1177 1178 + static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag) 1179 + { 1180 + struct qla_tgt_sess_op *op; 1181 + struct qla_tgt_cmd *cmd; 1182 + 1183 + spin_lock(&vha->cmd_list_lock); 1184 + 1185 + list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { 1186 + if (tag == op->atio.u.isp24.exchange_addr) { 1187 + op->aborted = true; 1188 + spin_unlock(&vha->cmd_list_lock); 1189 + return 1; 1190 + } 1191 + } 1192 + 1193 + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { 1194 + if (tag == cmd->atio.u.isp24.exchange_addr) { 1195 + cmd->state = QLA_TGT_STATE_ABORTED; 1196 + spin_unlock(&vha->cmd_list_lock); 1197 + return 1; 1198 + } 1199 + } 1200 + 1201 + spin_unlock(&vha->cmd_list_lock); 1202 + return 0; 1203 + } 1204 + 1205 + /* drop cmds for the given lun 1206 + * XXX only looks for cmds on the port through which lun reset was recieved 1207 + * XXX does not go through the list of other port (which may have cmds 1208 + * for the same lun) 1209 + */ 1210 + static void abort_cmds_for_lun(struct scsi_qla_host *vha, 1211 + uint32_t lun, uint8_t *s_id) 1212 + { 1213 + struct qla_tgt_sess_op *op; 1214 + struct qla_tgt_cmd *cmd; 1215 + uint32_t key; 1216 + 1217 + key = sid_to_key(s_id); 1218 + spin_lock(&vha->cmd_list_lock); 1219 + list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { 1220 + uint32_t op_key; 1221 + uint32_t op_lun; 1222 + 1223 + op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); 1224 + op_lun = scsilun_to_int( 1225 + (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun); 1226 + if (op_key == key && op_lun == lun) 1227 + op->aborted = true; 1228 + } 1229 + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { 1230 + uint32_t cmd_key; 1231 + uint32_t cmd_lun; 1232 + 1233 + cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); 1234 + cmd_lun = scsilun_to_int( 1235 + (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun); 1236 + if (cmd_key == key && cmd_lun == lun) 1237 + cmd->state = QLA_TGT_STATE_ABORTED; 1238 + } 1239 + spin_unlock(&vha->cmd_list_lock); 1240 + } 1241 + 1296 1242 /* ha->hardware_lock supposed to be held on entry */ 1297 1243 static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha, 1298 1244 struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess) ··· 1381 1199 } 1382 1200 spin_unlock(&se_sess->sess_cmd_lock); 1383 1201 1384 - if (!found_lun) 1385 - return -ENOENT; 1202 + /* cmd not in LIO lists, look in qla list */ 1203 + if (!found_lun) { 1204 + if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) { 1205 + /* send TASK_ABORT response immediately */ 1206 + qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false); 1207 + return 0; 1208 + } else { 1209 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081, 1210 + "unable to find cmd in driver or LIO for tag 0x%x\n", 1211 + abts->exchange_addr_to_abort); 1212 + return -ENOENT; 1213 + } 1214 + } 1386 1215 1387 1216 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f, 1388 1217 "qla_target(%d): task abort (tag=%d)\n", ··· 1474 1281 qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, 1475 1282 false); 1476 1283 } 1284 + return; 1285 + } 1286 + 1287 + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 1288 + qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false); 1477 1289 return; 1478 1290 } 1479 1291 ··· 1923 1725 struct scsi_qla_host *vha = tgt->vha; 1924 1726 struct qla_hw_data *ha = vha->hw; 1925 1727 struct se_cmd *se_cmd = &cmd->se_cmd; 1926 - 1927 - if (unlikely(cmd->aborted)) { 1928 - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, 1929 - "qla_target(%d): terminating exchange for aborted cmd=%p (se_cmd=%p, tag=%lld)", 1930 - vha->vp_idx, cmd, se_cmd, se_cmd->tag); 1931 - 1932 - cmd->state = QLA_TGT_STATE_ABORTED; 1933 - cmd->cmd_flags |= BIT_6; 1934 - 1935 - qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); 1936 - 1937 - /* !! At this point cmd could be already freed !! */ 1938 - return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED; 1939 - } 1940 1728 1941 1729 prm->cmd = cmd; 1942 1730 prm->tgt = tgt; ··· 2485 2301 unsigned long flags = 0; 2486 2302 int res; 2487 2303 2304 + spin_lock_irqsave(&ha->hardware_lock, flags); 2305 + if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 2306 + cmd->state = QLA_TGT_STATE_PROCESSED; 2307 + if (cmd->sess->logout_completed) 2308 + /* no need to terminate. FW already freed exchange. */ 2309 + qlt_abort_cmd_on_host_reset(cmd->vha, cmd); 2310 + else 2311 + qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); 2312 + spin_unlock_irqrestore(&ha->hardware_lock, flags); 2313 + return 0; 2314 + } 2315 + spin_unlock_irqrestore(&ha->hardware_lock, flags); 2316 + 2488 2317 memset(&prm, 0, sizeof(prm)); 2489 2318 qlt_check_srr_debug(cmd, &xmit_type); 2490 2319 ··· 2510 2313 res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status, 2511 2314 &full_req_cnt); 2512 2315 if (unlikely(res != 0)) { 2513 - if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED) 2514 - return 0; 2515 - 2516 2316 return res; 2517 2317 } 2518 2318 ··· 2539 2345 res = qlt_build_ctio_crc2_pkt(&prm, vha); 2540 2346 else 2541 2347 res = qlt_24xx_build_ctio_pkt(&prm, vha); 2542 - if (unlikely(res != 0)) 2348 + if (unlikely(res != 0)) { 2349 + vha->req->cnt += full_req_cnt; 2543 2350 goto out_unmap_unlock; 2544 - 2351 + } 2545 2352 2546 2353 pkt = (struct ctio7_to_24xx *)prm.pkt; 2547 2354 ··· 2656 2461 2657 2462 spin_lock_irqsave(&ha->hardware_lock, flags); 2658 2463 2659 - if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) { 2464 + if (qla2x00_reset_active(vha) || (cmd->reset_count != ha->chip_reset) || 2465 + (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) { 2660 2466 /* 2661 2467 * Either a chip reset is active or this request was from 2662 2468 * previous life, just abort the processing. ··· 2681 2485 else 2682 2486 res = qlt_24xx_build_ctio_pkt(&prm, vha); 2683 2487 2684 - if (unlikely(res != 0)) 2488 + if (unlikely(res != 0)) { 2489 + vha->req->cnt += prm.req_cnt; 2685 2490 goto out_unlock_free_unmap; 2491 + } 2492 + 2686 2493 pkt = (struct ctio7_to_24xx *)prm.pkt; 2687 2494 pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT | 2688 2495 CTIO7_FLAGS_STATUS_MODE_0); ··· 2850 2651 2851 2652 /* If hardware_lock held on entry, might drop it, then reaquire */ 2852 2653 /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ 2654 + static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha, 2655 + struct imm_ntfy_from_isp *ntfy) 2656 + { 2657 + struct nack_to_isp *nack; 2658 + struct qla_hw_data *ha = vha->hw; 2659 + request_t *pkt; 2660 + int ret = 0; 2661 + 2662 + ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c, 2663 + "Sending TERM ELS CTIO (ha=%p)\n", ha); 2664 + 2665 + pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL); 2666 + if (pkt == NULL) { 2667 + ql_dbg(ql_dbg_tgt, vha, 0xe080, 2668 + "qla_target(%d): %s failed: unable to allocate " 2669 + "request packet\n", vha->vp_idx, __func__); 2670 + return -ENOMEM; 2671 + } 2672 + 2673 + pkt->entry_type = NOTIFY_ACK_TYPE; 2674 + pkt->entry_count = 1; 2675 + pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; 2676 + 2677 + nack = (struct nack_to_isp *)pkt; 2678 + nack->ox_id = ntfy->ox_id; 2679 + 2680 + nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; 2681 + if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { 2682 + nack->u.isp24.flags = ntfy->u.isp24.flags & 2683 + __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); 2684 + } 2685 + 2686 + /* terminate */ 2687 + nack->u.isp24.flags |= 2688 + __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE); 2689 + 2690 + nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; 2691 + nack->u.isp24.status = ntfy->u.isp24.status; 2692 + nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode; 2693 + nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle; 2694 + nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address; 2695 + nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs; 2696 + nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui; 2697 + nack->u.isp24.vp_index = ntfy->u.isp24.vp_index; 2698 + 2699 + qla2x00_start_iocbs(vha, vha->req); 2700 + return ret; 2701 + } 2702 + 2703 + static void qlt_send_term_imm_notif(struct scsi_qla_host *vha, 2704 + struct imm_ntfy_from_isp *imm, int ha_locked) 2705 + { 2706 + unsigned long flags = 0; 2707 + int rc; 2708 + 2709 + if (qlt_issue_marker(vha, ha_locked) < 0) 2710 + return; 2711 + 2712 + if (ha_locked) { 2713 + rc = __qlt_send_term_imm_notif(vha, imm); 2714 + 2715 + #if 0 /* Todo */ 2716 + if (rc == -ENOMEM) 2717 + qlt_alloc_qfull_cmd(vha, imm, 0, 0); 2718 + #endif 2719 + goto done; 2720 + } 2721 + 2722 + spin_lock_irqsave(&vha->hw->hardware_lock, flags); 2723 + rc = __qlt_send_term_imm_notif(vha, imm); 2724 + 2725 + #if 0 /* Todo */ 2726 + if (rc == -ENOMEM) 2727 + qlt_alloc_qfull_cmd(vha, imm, 0, 0); 2728 + #endif 2729 + 2730 + done: 2731 + if (!ha_locked) 2732 + spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); 2733 + } 2734 + 2735 + /* If hardware_lock held on entry, might drop it, then reaquire */ 2736 + /* This function sends the appropriate CTIO to ISP 2xxx or 24xx */ 2853 2737 static int __qlt_send_term_exchange(struct scsi_qla_host *vha, 2854 2738 struct qla_tgt_cmd *cmd, 2855 2739 struct atio_from_isp *atio) ··· 2997 2715 static void qlt_send_term_exchange(struct scsi_qla_host *vha, 2998 2716 struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) 2999 2717 { 3000 - unsigned long flags; 2718 + unsigned long flags = 0; 3001 2719 int rc; 3002 2720 3003 2721 if (qlt_issue_marker(vha, ha_locked) < 0) ··· 3013 2731 rc = __qlt_send_term_exchange(vha, cmd, atio); 3014 2732 if (rc == -ENOMEM) 3015 2733 qlt_alloc_qfull_cmd(vha, atio, 0, 0); 3016 - spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); 3017 2734 3018 2735 done: 3019 2736 if (cmd && ((cmd->state != QLA_TGT_STATE_ABORTED) || 3020 2737 !cmd->cmd_sent_to_fw)) { 3021 - if (!ha_locked && !in_interrupt()) 3022 - msleep(250); /* just in case */ 3023 - 3024 - qlt_unmap_sg(vha, cmd); 2738 + if (cmd->sg_mapped) 2739 + qlt_unmap_sg(vha, cmd); 3025 2740 vha->hw->tgt.tgt_ops->free_cmd(cmd); 3026 2741 } 2742 + 2743 + if (!ha_locked) 2744 + spin_unlock_irqrestore(&vha->hw->hardware_lock, flags); 2745 + 3027 2746 return; 3028 2747 } 3029 2748 ··· 3074 2791 } 3075 2792 3076 2793 } 2794 + 2795 + void qlt_abort_cmd(struct qla_tgt_cmd *cmd) 2796 + { 2797 + struct qla_tgt *tgt = cmd->tgt; 2798 + struct scsi_qla_host *vha = tgt->vha; 2799 + struct se_cmd *se_cmd = &cmd->se_cmd; 2800 + 2801 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, 2802 + "qla_target(%d): terminating exchange for aborted cmd=%p " 2803 + "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd, 2804 + se_cmd->tag); 2805 + 2806 + cmd->state = QLA_TGT_STATE_ABORTED; 2807 + cmd->cmd_flags |= BIT_6; 2808 + 2809 + qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); 2810 + } 2811 + EXPORT_SYMBOL(qlt_abort_cmd); 3077 2812 3078 2813 void qlt_free_cmd(struct qla_tgt_cmd *cmd) 3079 2814 { ··· 3316 3015 dump_stack(); 3317 3016 } 3318 3017 3319 - cmd->cmd_flags |= BIT_12; 3018 + cmd->cmd_flags |= BIT_17; 3320 3019 ha->tgt.tgt_ops->free_cmd(cmd); 3321 3020 } 3322 3021 ··· 3478 3177 skip_term: 3479 3178 3480 3179 if (cmd->state == QLA_TGT_STATE_PROCESSED) { 3481 - ; 3180 + cmd->cmd_flags |= BIT_12; 3482 3181 } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) { 3483 3182 int rx_status = 0; 3484 3183 ··· 3492 3191 ha->tgt.tgt_ops->handle_data(cmd); 3493 3192 return; 3494 3193 } else if (cmd->state == QLA_TGT_STATE_ABORTED) { 3194 + cmd->cmd_flags |= BIT_18; 3495 3195 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e, 3496 3196 "Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag); 3497 3197 } else { 3198 + cmd->cmd_flags |= BIT_19; 3498 3199 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c, 3499 3200 "qla_target(%d): A command in state (%d) should " 3500 3201 "not return a CTIO complete\n", vha->vp_idx, cmd->state); ··· 3507 3204 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01f, "Finishing failed CTIO\n"); 3508 3205 dump_stack(); 3509 3206 } 3510 - 3511 3207 3512 3208 ha->tgt.tgt_ops->free_cmd(cmd); 3513 3209 } ··· 3565 3263 if (tgt->tgt_stop) 3566 3264 goto out_term; 3567 3265 3266 + if (cmd->state == QLA_TGT_STATE_ABORTED) { 3267 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082, 3268 + "cmd with tag %u is aborted\n", 3269 + cmd->atio.u.isp24.exchange_addr); 3270 + goto out_term; 3271 + } 3272 + 3568 3273 cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; 3569 3274 cmd->se_cmd.tag = atio->u.isp24.exchange_addr; 3570 3275 cmd->unpacked_lun = scsilun_to_int( ··· 3625 3316 static void qlt_do_work(struct work_struct *work) 3626 3317 { 3627 3318 struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); 3319 + scsi_qla_host_t *vha = cmd->vha; 3320 + unsigned long flags; 3321 + 3322 + spin_lock_irqsave(&vha->cmd_list_lock, flags); 3323 + list_del(&cmd->cmd_list); 3324 + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); 3628 3325 3629 3326 __qlt_do_work(cmd); 3630 3327 } ··· 3660 3345 cmd->loop_id = sess->loop_id; 3661 3346 cmd->conf_compl_supported = sess->conf_compl_supported; 3662 3347 3348 + cmd->cmd_flags = 0; 3349 + cmd->jiffies_at_alloc = get_jiffies_64(); 3350 + 3351 + cmd->reset_count = vha->hw->chip_reset; 3352 + 3663 3353 return cmd; 3664 3354 } 3665 3355 ··· 3682 3362 unsigned long flags; 3683 3363 uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id; 3684 3364 3365 + spin_lock_irqsave(&vha->cmd_list_lock, flags); 3366 + list_del(&op->cmd_list); 3367 + spin_unlock_irqrestore(&vha->cmd_list_lock, flags); 3368 + 3369 + if (op->aborted) { 3370 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083, 3371 + "sess_op with tag %u is aborted\n", 3372 + op->atio.u.isp24.exchange_addr); 3373 + goto out_term; 3374 + } 3375 + 3685 3376 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022, 3686 - "qla_target(%d): Unable to find wwn login" 3687 - " (s_id %x:%x:%x), trying to create it manually\n", 3688 - vha->vp_idx, s_id[0], s_id[1], s_id[2]); 3377 + "qla_target(%d): Unable to find wwn login" 3378 + " (s_id %x:%x:%x), trying to create it manually\n", 3379 + vha->vp_idx, s_id[0], s_id[1], s_id[2]); 3689 3380 3690 3381 if (op->atio.u.raw.entry_count > 1) { 3691 3382 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023, 3692 - "Dropping multy entry atio %p\n", &op->atio); 3383 + "Dropping multy entry atio %p\n", &op->atio); 3693 3384 goto out_term; 3694 3385 } 3695 3386 ··· 3765 3434 3766 3435 memcpy(&op->atio, atio, sizeof(*atio)); 3767 3436 op->vha = vha; 3437 + 3438 + spin_lock(&vha->cmd_list_lock); 3439 + list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list); 3440 + spin_unlock(&vha->cmd_list_lock); 3441 + 3768 3442 INIT_WORK(&op->work, qlt_create_sess_from_atio); 3769 3443 queue_work(qla_tgt_wq, &op->work); 3770 3444 return 0; 3771 3445 } 3446 + 3447 + /* Another WWN used to have our s_id. Our PLOGI scheduled its 3448 + * session deletion, but it's still in sess_del_work wq */ 3449 + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 3450 + ql_dbg(ql_dbg_io, vha, 0x3061, 3451 + "New command while old session %p is being deleted\n", 3452 + sess); 3453 + return -EFAULT; 3454 + } 3455 + 3772 3456 /* 3773 3457 * Do kref_get() before returning + dropping qla_hw_data->hardware_lock. 3774 3458 */ ··· 3797 3451 return -ENOMEM; 3798 3452 } 3799 3453 3800 - cmd->cmd_flags = 0; 3801 - cmd->jiffies_at_alloc = get_jiffies_64(); 3802 - 3803 - cmd->reset_count = vha->hw->chip_reset; 3804 - 3805 3454 cmd->cmd_in_wq = 1; 3806 3455 cmd->cmd_flags |= BIT_0; 3456 + 3457 + spin_lock(&vha->cmd_list_lock); 3458 + list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list); 3459 + spin_unlock(&vha->cmd_list_lock); 3460 + 3807 3461 INIT_WORK(&cmd->work, qlt_do_work); 3808 3462 queue_work(qla_tgt_wq, &cmd->work); 3809 3463 return 0; ··· 3817 3471 struct scsi_qla_host *vha = sess->vha; 3818 3472 struct qla_hw_data *ha = vha->hw; 3819 3473 struct qla_tgt_mgmt_cmd *mcmd; 3474 + struct atio_from_isp *a = (struct atio_from_isp *)iocb; 3820 3475 int res; 3821 3476 uint8_t tmr_func; 3822 3477 ··· 3858 3511 ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002, 3859 3512 "qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx); 3860 3513 tmr_func = TMR_LUN_RESET; 3514 + abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); 3861 3515 break; 3862 3516 3863 3517 case QLA_TGT_CLEAR_TS: ··· 3947 3599 sizeof(struct atio_from_isp)); 3948 3600 } 3949 3601 3602 + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) 3603 + return -EFAULT; 3604 + 3950 3605 return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); 3951 3606 } 3952 3607 ··· 4015 3664 return __qlt_abort_task(vha, iocb, sess); 4016 3665 } 4017 3666 3667 + void qlt_logo_completion_handler(fc_port_t *fcport, int rc) 3668 + { 3669 + if (fcport->tgt_session) { 3670 + if (rc != MBS_COMMAND_COMPLETE) { 3671 + ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093, 3672 + "%s: se_sess %p / sess %p from" 3673 + " port %8phC loop_id %#04x s_id %02x:%02x:%02x" 3674 + " LOGO failed: %#x\n", 3675 + __func__, 3676 + fcport->tgt_session->se_sess, 3677 + fcport->tgt_session, 3678 + fcport->port_name, fcport->loop_id, 3679 + fcport->d_id.b.domain, fcport->d_id.b.area, 3680 + fcport->d_id.b.al_pa, rc); 3681 + } 3682 + 3683 + fcport->tgt_session->logout_completed = 1; 3684 + } 3685 + } 3686 + 3687 + static void qlt_swap_imm_ntfy_iocb(struct imm_ntfy_from_isp *a, 3688 + struct imm_ntfy_from_isp *b) 3689 + { 3690 + struct imm_ntfy_from_isp tmp; 3691 + memcpy(&tmp, a, sizeof(struct imm_ntfy_from_isp)); 3692 + memcpy(a, b, sizeof(struct imm_ntfy_from_isp)); 3693 + memcpy(b, &tmp, sizeof(struct imm_ntfy_from_isp)); 3694 + } 3695 + 3696 + /* 3697 + * ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) 3698 + * 3699 + * Schedules sessions with matching port_id/loop_id but different wwn for 3700 + * deletion. Returns existing session with matching wwn if present. 3701 + * Null otherwise. 3702 + */ 3703 + static struct qla_tgt_sess * 3704 + qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn, 3705 + port_id_t port_id, uint16_t loop_id) 3706 + { 3707 + struct qla_tgt_sess *sess = NULL, *other_sess; 3708 + uint64_t other_wwn; 3709 + 3710 + list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) { 3711 + 3712 + other_wwn = wwn_to_u64(other_sess->port_name); 3713 + 3714 + if (wwn == other_wwn) { 3715 + WARN_ON(sess); 3716 + sess = other_sess; 3717 + continue; 3718 + } 3719 + 3720 + /* find other sess with nport_id collision */ 3721 + if (port_id.b24 == other_sess->s_id.b24) { 3722 + if (loop_id != other_sess->loop_id) { 3723 + ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c, 3724 + "Invalidating sess %p loop_id %d wwn %llx.\n", 3725 + other_sess, other_sess->loop_id, other_wwn); 3726 + 3727 + /* 3728 + * logout_on_delete is set by default, but another 3729 + * session that has the same s_id/loop_id combo 3730 + * might have cleared it when requested this session 3731 + * deletion, so don't touch it 3732 + */ 3733 + qlt_schedule_sess_for_deletion(other_sess, true); 3734 + } else { 3735 + /* 3736 + * Another wwn used to have our s_id/loop_id 3737 + * combo - kill the session, but don't log out 3738 + */ 3739 + sess->logout_on_delete = 0; 3740 + qlt_schedule_sess_for_deletion(other_sess, 3741 + true); 3742 + } 3743 + continue; 3744 + } 3745 + 3746 + /* find other sess with nport handle collision */ 3747 + if (loop_id == other_sess->loop_id) { 3748 + ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d, 3749 + "Invalidating sess %p loop_id %d wwn %llx.\n", 3750 + other_sess, other_sess->loop_id, other_wwn); 3751 + 3752 + /* Same loop_id but different s_id 3753 + * Ok to kill and logout */ 3754 + qlt_schedule_sess_for_deletion(other_sess, true); 3755 + } 3756 + } 3757 + 3758 + return sess; 3759 + } 3760 + 3761 + /* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */ 3762 + static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id) 3763 + { 3764 + struct qla_tgt_sess_op *op; 3765 + struct qla_tgt_cmd *cmd; 3766 + uint32_t key; 3767 + int count = 0; 3768 + 3769 + key = (((u32)s_id->b.domain << 16) | 3770 + ((u32)s_id->b.area << 8) | 3771 + ((u32)s_id->b.al_pa)); 3772 + 3773 + spin_lock(&vha->cmd_list_lock); 3774 + list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) { 3775 + uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id); 3776 + if (op_key == key) { 3777 + op->aborted = true; 3778 + count++; 3779 + } 3780 + } 3781 + list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) { 3782 + uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id); 3783 + if (cmd_key == key) { 3784 + cmd->state = QLA_TGT_STATE_ABORTED; 3785 + count++; 3786 + } 3787 + } 3788 + spin_unlock(&vha->cmd_list_lock); 3789 + 3790 + return count; 3791 + } 3792 + 4018 3793 /* 4019 3794 * ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire 4020 3795 */ 4021 3796 static int qlt_24xx_handle_els(struct scsi_qla_host *vha, 4022 3797 struct imm_ntfy_from_isp *iocb) 4023 3798 { 3799 + struct qla_tgt *tgt = vha->vha_tgt.qla_tgt; 3800 + struct qla_hw_data *ha = vha->hw; 3801 + struct qla_tgt_sess *sess = NULL; 3802 + uint64_t wwn; 3803 + port_id_t port_id; 3804 + uint16_t loop_id; 3805 + uint16_t wd3_lo; 4024 3806 int res = 0; 3807 + 3808 + wwn = wwn_to_u64(iocb->u.isp24.port_name); 3809 + 3810 + port_id.b.domain = iocb->u.isp24.port_id[2]; 3811 + port_id.b.area = iocb->u.isp24.port_id[1]; 3812 + port_id.b.al_pa = iocb->u.isp24.port_id[0]; 3813 + port_id.b.rsvd_1 = 0; 3814 + 3815 + loop_id = le16_to_cpu(iocb->u.isp24.nport_handle); 4025 3816 4026 3817 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026, 4027 3818 "qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n", 4028 3819 vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode); 4029 3820 3821 + /* res = 1 means ack at the end of thread 3822 + * res = 0 means ack async/later. 3823 + */ 4030 3824 switch (iocb->u.isp24.status_subcode) { 4031 3825 case ELS_PLOGI: 4032 - case ELS_FLOGI: 3826 + 3827 + /* Mark all stale commands in qla_tgt_wq for deletion */ 3828 + abort_cmds_for_s_id(vha, &port_id); 3829 + 3830 + if (wwn) 3831 + sess = qlt_find_sess_invalidate_other(tgt, wwn, 3832 + port_id, loop_id); 3833 + 3834 + if (!sess || IS_SW_RESV_ADDR(sess->s_id)) { 3835 + res = 1; 3836 + break; 3837 + } 3838 + 3839 + if (sess->plogi_ack_needed) { 3840 + /* 3841 + * Initiator sent another PLOGI before last PLOGI could 3842 + * finish. Swap plogi iocbs and terminate old one 3843 + * without acking, new one will get acked when session 3844 + * deletion completes. 3845 + */ 3846 + ql_log(ql_log_warn, sess->vha, 0xf094, 3847 + "sess %p received double plogi.\n", sess); 3848 + 3849 + qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb); 3850 + 3851 + qlt_send_term_imm_notif(vha, iocb, 1); 3852 + 3853 + res = 0; 3854 + break; 3855 + } 3856 + 3857 + res = 0; 3858 + 3859 + /* 3860 + * Save immediate Notif IOCB for Ack when sess is done 3861 + * and being deleted. 3862 + */ 3863 + memcpy(&sess->tm_iocb, iocb, sizeof(sess->tm_iocb)); 3864 + sess->plogi_ack_needed = 1; 3865 + 3866 + /* 3867 + * Under normal circumstances we want to release nport handle 3868 + * during LOGO process to avoid nport handle leaks inside FW. 3869 + * The exception is when LOGO is done while another PLOGI with 3870 + * the same nport handle is waiting as might be the case here. 3871 + * Note: there is always a possibily of a race where session 3872 + * deletion has already started for other reasons (e.g. ACL 3873 + * removal) and now PLOGI arrives: 3874 + * 1. if PLOGI arrived in FW after nport handle has been freed, 3875 + * FW must have assigned this PLOGI a new/same handle and we 3876 + * can proceed ACK'ing it as usual when session deletion 3877 + * completes. 3878 + * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT 3879 + * bit reached it, the handle has now been released. We'll 3880 + * get an error when we ACK this PLOGI. Nothing will be sent 3881 + * back to initiator. Initiator should eventually retry 3882 + * PLOGI and situation will correct itself. 3883 + */ 3884 + sess->keep_nport_handle = ((sess->loop_id == loop_id) && 3885 + (sess->s_id.b24 == port_id.b24)); 3886 + qlt_schedule_sess_for_deletion(sess, true); 3887 + break; 3888 + 4033 3889 case ELS_PRLI: 3890 + wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo); 3891 + 3892 + if (wwn) 3893 + sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id, 3894 + loop_id); 3895 + 3896 + if (sess != NULL) { 3897 + if (sess->deleted) { 3898 + /* 3899 + * Impatient initiator sent PRLI before last 3900 + * PLOGI could finish. Will force him to re-try, 3901 + * while last one finishes. 3902 + */ 3903 + ql_log(ql_log_warn, sess->vha, 0xf095, 3904 + "sess %p PRLI received, before plogi ack.\n", 3905 + sess); 3906 + qlt_send_term_imm_notif(vha, iocb, 1); 3907 + res = 0; 3908 + break; 3909 + } 3910 + 3911 + /* 3912 + * This shouldn't happen under normal circumstances, 3913 + * since we have deleted the old session during PLOGI 3914 + */ 3915 + ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096, 3916 + "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n", 3917 + sess->loop_id, sess, iocb->u.isp24.nport_handle); 3918 + 3919 + sess->local = 0; 3920 + sess->loop_id = loop_id; 3921 + sess->s_id = port_id; 3922 + 3923 + if (wd3_lo & BIT_7) 3924 + sess->conf_compl_supported = 1; 3925 + 3926 + } 3927 + res = 1; /* send notify ack */ 3928 + 3929 + /* Make session global (not used in fabric mode) */ 3930 + if (ha->current_topology != ISP_CFG_F) { 3931 + set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); 3932 + set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); 3933 + qla2xxx_wake_dpc(vha); 3934 + } else { 3935 + /* todo: else - create sess here. */ 3936 + res = 1; /* send notify ack */ 3937 + } 3938 + 3939 + break; 3940 + 4034 3941 case ELS_LOGO: 4035 3942 case ELS_PRLO: 4036 3943 res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS); ··· 4306 3697 break; 4307 3698 } 4308 3699 3700 + case ELS_FLOGI: /* should never happen */ 4309 3701 default: 4310 3702 ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061, 4311 3703 "qla_target(%d): Unsupported ELS command %x " ··· 5622 5012 if (!sess) 5623 5013 goto out_term; 5624 5014 } else { 5015 + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 5016 + sess = NULL; 5017 + goto out_term; 5018 + } 5019 + 5625 5020 kref_get(&sess->se_sess->sess_kref); 5626 5021 } 5627 5022 ··· 5681 5066 if (!sess) 5682 5067 goto out_term; 5683 5068 } else { 5069 + if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) { 5070 + sess = NULL; 5071 + goto out_term; 5072 + } 5073 + 5684 5074 kref_get(&sess->se_sess->sess_kref); 5685 5075 } 5686 5076 ··· 6172 5552 6173 5553 /* Adjust ring index */ 6174 5554 WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index); 5555 + RD_REG_DWORD_RELAXED(ISP_ATIO_Q_OUT(vha)); 6175 5556 } 6176 5557 6177 5558 void ··· 6414 5793 if (!QLA_TGT_MODE_ENABLED()) 6415 5794 return; 6416 5795 6417 - if (ha->mqenable || IS_QLA83XX(ha)) { 5796 + if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) { 6418 5797 ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in; 6419 5798 ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out; 6420 5799 } else {
+61 -11
drivers/scsi/qla2xxx/qla_target.h
··· 167 167 uint32_t srr_rel_offs; 168 168 uint16_t srr_ui; 169 169 uint16_t srr_ox_id; 170 - uint8_t reserved_4[19]; 170 + union { 171 + struct { 172 + uint8_t node_name[8]; 173 + } plogi; /* PLOGI/ADISC/PDISC */ 174 + struct { 175 + /* PRLI word 3 bit 0-15 */ 176 + uint16_t wd3_lo; 177 + uint8_t resv0[6]; 178 + } prli; 179 + struct { 180 + uint8_t port_id[3]; 181 + uint8_t resv1; 182 + uint16_t nport_handle; 183 + uint16_t resv2; 184 + } req_els; 185 + } u; 186 + uint8_t port_name[8]; 187 + uint8_t resv3[3]; 171 188 uint8_t vp_index; 172 189 uint32_t reserved_5; 173 190 uint8_t port_id[3]; ··· 251 234 uint8_t reserved[2]; 252 235 uint16_t ox_id; 253 236 } __packed; 237 + #define NOTIFY_ACK_FLAGS_TERMINATE BIT_3 254 238 #define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0 255 239 #define NOTIFY_ACK_SRR_FLAGS_REJECT 1 256 240 ··· 808 790 #define FC_TM_REJECT 4 809 791 #define FC_TM_FAILED 5 810 792 811 - /* 812 - * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was 813 - * terminated, so no more actions is needed and success should be returned 814 - * to target. 815 - */ 816 - #define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717 817 - 818 793 #if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G) 819 794 #define pci_dma_lo32(a) (a & 0xffffffff) 820 795 #define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff) ··· 885 874 struct scsi_qla_host *vha; 886 875 struct atio_from_isp atio; 887 876 struct work_struct work; 877 + struct list_head cmd_list; 878 + bool aborted; 879 + }; 880 + 881 + enum qla_sess_deletion { 882 + QLA_SESS_DELETION_NONE = 0, 883 + QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of 884 + * this one */ 885 + QLA_SESS_DELETION_IN_PROGRESS = 2, 888 886 }; 889 887 890 888 /* ··· 904 884 port_id_t s_id; 905 885 906 886 unsigned int conf_compl_supported:1; 907 - unsigned int deleted:1; 887 + unsigned int deleted:2; 908 888 unsigned int local:1; 889 + unsigned int logout_on_delete:1; 890 + unsigned int plogi_ack_needed:1; 891 + unsigned int keep_nport_handle:1; 892 + 893 + unsigned char logout_completed; 894 + 895 + int generation; 909 896 910 897 struct se_session *se_sess; 911 898 struct scsi_qla_host *vha; ··· 924 897 925 898 uint8_t port_name[WWN_SIZE]; 926 899 struct work_struct free_work; 900 + 901 + union { 902 + struct imm_ntfy_from_isp tm_iocb; 903 + }; 927 904 }; 928 905 929 906 struct qla_tgt_cmd { ··· 943 912 unsigned int conf_compl_supported:1; 944 913 unsigned int sg_mapped:1; 945 914 unsigned int free_sg:1; 946 - unsigned int aborted:1; /* Needed in case of SRR */ 947 915 unsigned int write_data_transferred:1; 948 916 unsigned int ctx_dsd_alloced:1; 949 917 unsigned int q_full:1; ··· 991 961 * BIT_14 - Back end data received/sent. 992 962 * BIT_15 - SRR prepare ctio 993 963 * BIT_16 - complete free 964 + * BIT_17 - flush - qlt_abort_cmd_on_host_reset 965 + * BIT_18 - completion w/abort status 966 + * BIT_19 - completion w/unknown status 994 967 */ 995 968 uint32_t cmd_flags; 996 969 }; ··· 1059 1026 struct qla_tgt_cmd *cmd; 1060 1027 }; 1061 1028 1029 + /* Check for Switch reserved address */ 1030 + #define IS_SW_RESV_ADDR(_s_id) \ 1031 + ((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc)) 1032 + 1062 1033 #define QLA_TGT_XMIT_DATA 1 1063 1034 #define QLA_TGT_XMIT_STATUS 2 1064 1035 #define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA) ··· 1080 1043 extern void qlt_lport_deregister(struct scsi_qla_host *); 1081 1044 extern void qlt_unreg_sess(struct qla_tgt_sess *); 1082 1045 extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *); 1083 - extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *); 1046 + extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int); 1084 1047 extern int __init qlt_init(void); 1085 1048 extern void qlt_exit(void); 1086 1049 extern void qlt_update_vp_map(struct scsi_qla_host *, int); ··· 1110 1073 ha->host->active_mode |= MODE_INITIATOR; 1111 1074 } 1112 1075 1076 + static inline uint32_t sid_to_key(const uint8_t *s_id) 1077 + { 1078 + uint32_t key; 1079 + 1080 + key = (((unsigned long)s_id[0] << 16) | 1081 + ((unsigned long)s_id[1] << 8) | 1082 + (unsigned long)s_id[2]); 1083 + return key; 1084 + } 1085 + 1113 1086 /* 1114 1087 * Exported symbols from qla_target.c LLD logic used by qla2xxx code.. 1115 1088 */ 1116 1089 extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); 1117 1090 extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); 1118 1091 extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); 1092 + extern void qlt_abort_cmd(struct qla_tgt_cmd *); 1119 1093 extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); 1120 1094 extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); 1121 1095 extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); ··· 1157 1109 extern irqreturn_t qla83xx_msix_atio_q(int, void *); 1158 1110 extern void qlt_83xx_iospace_config(struct qla_hw_data *); 1159 1111 extern int qlt_free_qfull_cmds(struct scsi_qla_host *); 1112 + extern void qlt_logo_completion_handler(fc_port_t *, int); 1113 + extern void qlt_do_generation_tick(struct scsi_qla_host *, int *); 1160 1114 1161 1115 #endif /* __QLA_TARGET_H */
+9 -19
drivers/scsi/qla2xxx/tcm_qla2xxx.c
··· 374 374 { 375 375 struct qla_tgt_cmd *cmd = container_of(se_cmd, 376 376 struct qla_tgt_cmd, se_cmd); 377 - 377 + cmd->cmd_flags |= BIT_3; 378 378 cmd->bufflen = se_cmd->data_length; 379 379 cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); 380 380 ··· 405 405 se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { 406 406 spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); 407 407 wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, 408 - 3000); 408 + 3 * HZ); 409 409 return 0; 410 410 } 411 411 spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); ··· 541 541 cmd->cmd_flags |= BIT_4; 542 542 cmd->bufflen = se_cmd->data_length; 543 543 cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); 544 - cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); 545 544 546 545 cmd->sg_cnt = se_cmd->t_data_nents; 547 546 cmd->sg = se_cmd->t_data_sg; 548 547 cmd->offset = 0; 549 - cmd->cmd_flags |= BIT_3; 550 548 551 549 cmd->prot_sg_cnt = se_cmd->t_prot_nents; 552 550 cmd->prot_sg = se_cmd->t_prot_sg; ··· 569 571 cmd->sg_cnt = 0; 570 572 cmd->offset = 0; 571 573 cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); 572 - cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED); 573 574 if (cmd->cmd_flags & BIT_5) { 574 575 pr_crit("Bit_5 already set for cmd = %p.\n", cmd); 575 576 dump_stack(); ··· 633 636 { 634 637 struct qla_tgt_cmd *cmd = container_of(se_cmd, 635 638 struct qla_tgt_cmd, se_cmd); 636 - struct scsi_qla_host *vha = cmd->vha; 637 - struct qla_hw_data *ha = vha->hw; 638 - 639 - if (!cmd->sg_mapped) 640 - return; 641 - 642 - pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction); 643 - cmd->sg_mapped = 0; 639 + qlt_abort_cmd(cmd); 644 640 } 645 641 646 642 static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, ··· 1139 1149 return NULL; 1140 1150 } 1141 1151 1142 - key = (((unsigned long)s_id[0] << 16) | 1143 - ((unsigned long)s_id[1] << 8) | 1144 - (unsigned long)s_id[2]); 1152 + key = sid_to_key(s_id); 1145 1153 pr_debug("find_sess_by_s_id: 0x%06x\n", key); 1146 1154 1147 1155 se_nacl = btree_lookup32(&lport->lport_fcport_map, key); ··· 1174 1186 void *slot; 1175 1187 int rc; 1176 1188 1177 - key = (((unsigned long)s_id[0] << 16) | 1178 - ((unsigned long)s_id[1] << 8) | 1179 - (unsigned long)s_id[2]); 1189 + key = sid_to_key(s_id); 1180 1190 pr_debug("set_sess_by_s_id: %06x\n", key); 1181 1191 1182 1192 slot = btree_lookup32(&lport->lport_fcport_map, key); ··· 1530 1544 } 1531 1545 1532 1546 sess->conf_compl_supported = conf_compl_supported; 1547 + 1548 + /* Reset logout parameters to default */ 1549 + sess->logout_on_delete = 1; 1550 + sess->keep_nport_handle = 0; 1533 1551 } 1534 1552 1535 1553 /*
+40 -10
drivers/target/iscsi/iscsi_target.c
··· 3998 3998 } 3999 3999 4000 4000 transport_err: 4001 - iscsit_take_action_for_connection_exit(conn); 4001 + /* 4002 + * Avoid the normal connection failure code-path if this connection 4003 + * is still within LOGIN mode, and iscsi_np process context is 4004 + * responsible for cleaning up the early connection failure. 4005 + */ 4006 + if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN) 4007 + iscsit_take_action_for_connection_exit(conn); 4002 4008 out: 4003 4009 return 0; 4004 4010 } ··· 4088 4082 4089 4083 int iscsi_target_rx_thread(void *arg) 4090 4084 { 4091 - int ret; 4085 + int ret, rc; 4092 4086 u8 buffer[ISCSI_HDR_LEN], opcode; 4093 4087 u32 checksum = 0, digest = 0; 4094 4088 struct iscsi_conn *conn = arg; ··· 4098 4092 * connection recovery / failure event can be triggered externally. 4099 4093 */ 4100 4094 allow_signal(SIGINT); 4095 + /* 4096 + * Wait for iscsi_post_login_handler() to complete before allowing 4097 + * incoming iscsi/tcp socket I/O, and/or failing the connection. 4098 + */ 4099 + rc = wait_for_completion_interruptible(&conn->rx_login_comp); 4100 + if (rc < 0) 4101 + return 0; 4101 4102 4102 4103 if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { 4103 4104 struct completion comp; 4104 - int rc; 4105 4105 4106 4106 init_completion(&comp); 4107 4107 rc = wait_for_completion_interruptible(&comp); ··· 4544 4532 struct iscsi_conn *conn) 4545 4533 { 4546 4534 struct iscsi_session *sess = conn->sess; 4547 - int sleep = cmpxchg(&conn->tx_thread_active, true, false); 4535 + int sleep = 1; 4536 + /* 4537 + * Traditional iscsi/tcp will invoke this logic from TX thread 4538 + * context during session logout, so clear tx_thread_active and 4539 + * sleep if iscsit_close_connection() has not already occured. 4540 + * 4541 + * Since iser-target invokes this logic from it's own workqueue, 4542 + * always sleep waiting for RX/TX thread shutdown to complete 4543 + * within iscsit_close_connection(). 4544 + */ 4545 + if (conn->conn_transport->transport_type == ISCSI_TCP) 4546 + sleep = cmpxchg(&conn->tx_thread_active, true, false); 4548 4547 4549 4548 atomic_set(&conn->conn_logout_remove, 0); 4550 4549 complete(&conn->conn_logout_comp); ··· 4569 4546 static void iscsit_logout_post_handler_samecid( 4570 4547 struct iscsi_conn *conn) 4571 4548 { 4572 - int sleep = cmpxchg(&conn->tx_thread_active, true, false); 4549 + int sleep = 1; 4550 + 4551 + if (conn->conn_transport->transport_type == ISCSI_TCP) 4552 + sleep = cmpxchg(&conn->tx_thread_active, true, false); 4573 4553 4574 4554 atomic_set(&conn->conn_logout_remove, 0); 4575 4555 complete(&conn->conn_logout_comp); ··· 4791 4765 struct iscsi_session *sess; 4792 4766 struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; 4793 4767 struct se_session *se_sess, *se_sess_tmp; 4768 + LIST_HEAD(free_list); 4794 4769 int session_count = 0; 4795 4770 4796 4771 spin_lock_bh(&se_tpg->session_lock); ··· 4813 4786 } 4814 4787 atomic_set(&sess->session_reinstatement, 1); 4815 4788 spin_unlock(&sess->conn_lock); 4816 - spin_unlock_bh(&se_tpg->session_lock); 4817 4789 4818 - iscsit_free_session(sess); 4819 - spin_lock_bh(&se_tpg->session_lock); 4820 - 4821 - session_count++; 4790 + list_move_tail(&se_sess->sess_list, &free_list); 4822 4791 } 4823 4792 spin_unlock_bh(&se_tpg->session_lock); 4793 + 4794 + list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) { 4795 + sess = (struct iscsi_session *)se_sess->fabric_sess_ptr; 4796 + 4797 + iscsit_free_session(sess); 4798 + session_count++; 4799 + } 4824 4800 4825 4801 pr_debug("Released %d iSCSI Session(s) from Target Portal" 4826 4802 " Group: %hu\n", session_count, tpg->tpgt);
+17 -28
drivers/target/iscsi/iscsi_target_login.c
··· 82 82 init_completion(&conn->conn_logout_comp); 83 83 init_completion(&conn->rx_half_close_comp); 84 84 init_completion(&conn->tx_half_close_comp); 85 + init_completion(&conn->rx_login_comp); 85 86 spin_lock_init(&conn->cmd_lock); 86 87 spin_lock_init(&conn->conn_usage_lock); 87 88 spin_lock_init(&conn->immed_queue_lock); ··· 645 644 iscsit_start_nopin_timer(conn); 646 645 } 647 646 648 - static int iscsit_start_kthreads(struct iscsi_conn *conn) 647 + int iscsit_start_kthreads(struct iscsi_conn *conn) 649 648 { 650 649 int ret = 0; 651 650 ··· 680 679 681 680 return 0; 682 681 out_tx: 682 + send_sig(SIGINT, conn->tx_thread, 1); 683 683 kthread_stop(conn->tx_thread); 684 684 conn->tx_thread_active = false; 685 685 out_bitmap: ··· 691 689 return ret; 692 690 } 693 691 694 - int iscsi_post_login_handler( 692 + void iscsi_post_login_handler( 695 693 struct iscsi_np *np, 696 694 struct iscsi_conn *conn, 697 695 u8 zero_tsih) ··· 701 699 struct se_session *se_sess = sess->se_sess; 702 700 struct iscsi_portal_group *tpg = sess->tpg; 703 701 struct se_portal_group *se_tpg = &tpg->tpg_se_tpg; 704 - int rc; 705 702 706 703 iscsit_inc_conn_usage_count(conn); 707 704 ··· 740 739 sess->sess_ops->InitiatorName); 741 740 spin_unlock_bh(&sess->conn_lock); 742 741 743 - rc = iscsit_start_kthreads(conn); 744 - if (rc) 745 - return rc; 746 - 747 742 iscsi_post_login_start_timers(conn); 748 743 /* 749 744 * Determine CPU mask to ensure connection's RX and TX kthreads ··· 748 751 iscsit_thread_get_cpumask(conn); 749 752 conn->conn_rx_reset_cpumask = 1; 750 753 conn->conn_tx_reset_cpumask = 1; 751 - 754 + /* 755 + * Wakeup the sleeping iscsi_target_rx_thread() now that 756 + * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. 757 + */ 758 + complete(&conn->rx_login_comp); 752 759 iscsit_dec_conn_usage_count(conn); 760 + 753 761 if (stop_timer) { 754 762 spin_lock_bh(&se_tpg->session_lock); 755 763 iscsit_stop_time2retain_timer(sess); 756 764 spin_unlock_bh(&se_tpg->session_lock); 757 765 } 758 766 iscsit_dec_session_usage_count(sess); 759 - return 0; 767 + return; 760 768 } 761 769 762 770 iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1); ··· 802 800 " iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt); 803 801 spin_unlock_bh(&se_tpg->session_lock); 804 802 805 - rc = iscsit_start_kthreads(conn); 806 - if (rc) 807 - return rc; 808 - 809 803 iscsi_post_login_start_timers(conn); 810 804 /* 811 805 * Determine CPU mask to ensure connection's RX and TX kthreads ··· 810 812 iscsit_thread_get_cpumask(conn); 811 813 conn->conn_rx_reset_cpumask = 1; 812 814 conn->conn_tx_reset_cpumask = 1; 813 - 815 + /* 816 + * Wakeup the sleeping iscsi_target_rx_thread() now that 817 + * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state. 818 + */ 819 + complete(&conn->rx_login_comp); 814 820 iscsit_dec_conn_usage_count(conn); 815 - 816 - return 0; 817 821 } 818 822 819 823 static void iscsi_handle_login_thread_timeout(unsigned long data) ··· 1380 1380 if (ret < 0) 1381 1381 goto new_sess_out; 1382 1382 1383 - if (!conn->sess) { 1384 - pr_err("struct iscsi_conn session pointer is NULL!\n"); 1385 - goto new_sess_out; 1386 - } 1387 - 1388 1383 iscsi_stop_login_thread_timer(np); 1389 - 1390 - if (signal_pending(current)) 1391 - goto new_sess_out; 1392 1384 1393 1385 if (ret == 1) { 1394 1386 tpg_np = conn->tpg_np; 1395 1387 1396 - ret = iscsi_post_login_handler(np, conn, zero_tsih); 1397 - if (ret < 0) 1398 - goto new_sess_out; 1399 - 1388 + iscsi_post_login_handler(np, conn, zero_tsih); 1400 1389 iscsit_deaccess_np(np, tpg, tpg_np); 1401 1390 } 1402 1391
+2 -1
drivers/target/iscsi/iscsi_target_login.h
··· 12 12 extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *); 13 13 extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32); 14 14 extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *); 15 - extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); 15 + extern int iscsit_start_kthreads(struct iscsi_conn *); 16 + extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8); 16 17 extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *, 17 18 bool, bool); 18 19 extern int iscsi_target_login_thread(void *);
+33 -1
drivers/target/iscsi/iscsi_target_nego.c
··· 17 17 ******************************************************************************/ 18 18 19 19 #include <linux/ctype.h> 20 + #include <linux/kthread.h> 20 21 #include <scsi/iscsi_proto.h> 21 22 #include <target/target_core_base.h> 22 23 #include <target/target_core_fabric.h> ··· 362 361 ntohl(login_rsp->statsn), login->rsp_length); 363 362 364 363 padding = ((-login->rsp_length) & 3); 364 + /* 365 + * Before sending the last login response containing the transition 366 + * bit for full-feature-phase, go ahead and start up TX/RX threads 367 + * now to avoid potential resource allocation failures after the 368 + * final login response has been sent. 369 + */ 370 + if (login->login_complete) { 371 + int rc = iscsit_start_kthreads(conn); 372 + if (rc) { 373 + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, 374 + ISCSI_LOGIN_STATUS_NO_RESOURCES); 375 + return -1; 376 + } 377 + } 365 378 366 379 if (conn->conn_transport->iscsit_put_login_tx(conn, login, 367 380 login->rsp_length + padding) < 0) 368 - return -1; 381 + goto err; 369 382 370 383 login->rsp_length = 0; 371 384 mutex_lock(&sess->cmdsn_mutex); ··· 388 373 mutex_unlock(&sess->cmdsn_mutex); 389 374 390 375 return 0; 376 + 377 + err: 378 + if (login->login_complete) { 379 + if (conn->rx_thread && conn->rx_thread_active) { 380 + send_sig(SIGINT, conn->rx_thread, 1); 381 + kthread_stop(conn->rx_thread); 382 + } 383 + if (conn->tx_thread && conn->tx_thread_active) { 384 + send_sig(SIGINT, conn->tx_thread, 1); 385 + kthread_stop(conn->tx_thread); 386 + } 387 + spin_lock(&iscsit_global->ts_bitmap_lock); 388 + bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id, 389 + get_order(1)); 390 + spin_unlock(&iscsit_global->ts_bitmap_lock); 391 + } 392 + return -1; 391 393 } 392 394 393 395 static void iscsi_target_sk_data_ready(struct sock *sk)
+28 -12
drivers/target/target_core_configfs.c
··· 747 747 if (!dev->transport->init_prot || !dev->transport->free_prot) { 748 748 /* 0 is only allowed value for non-supporting backends */ 749 749 if (flag == 0) 750 - return 0; 750 + return count; 751 751 752 752 pr_err("DIF protection not supported by backend: %s\n", 753 753 dev->transport->name); ··· 1590 1590 u8 type = 0; 1591 1591 1592 1592 if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) 1593 - return 0; 1593 + return count; 1594 1594 if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS) 1595 - return 0; 1595 + return count; 1596 1596 1597 1597 if (dev->export_count) { 1598 1598 pr_debug("Unable to process APTPL metadata while" ··· 1658 1658 * PR APTPL Metadata for Reservation 1659 1659 */ 1660 1660 case Opt_res_holder: 1661 - match_int(args, &arg); 1661 + ret = match_int(args, &arg); 1662 + if (ret) 1663 + goto out; 1662 1664 res_holder = arg; 1663 1665 break; 1664 1666 case Opt_res_type: 1665 - match_int(args, &arg); 1667 + ret = match_int(args, &arg); 1668 + if (ret) 1669 + goto out; 1666 1670 type = (u8)arg; 1667 1671 break; 1668 1672 case Opt_res_scope: 1669 - match_int(args, &arg); 1673 + ret = match_int(args, &arg); 1674 + if (ret) 1675 + goto out; 1670 1676 break; 1671 1677 case Opt_res_all_tg_pt: 1672 - match_int(args, &arg); 1678 + ret = match_int(args, &arg); 1679 + if (ret) 1680 + goto out; 1673 1681 all_tg_pt = (int)arg; 1674 1682 break; 1675 1683 case Opt_mapped_lun: 1676 - match_int(args, &arg); 1684 + ret = match_int(args, &arg); 1685 + if (ret) 1686 + goto out; 1677 1687 mapped_lun = (u64)arg; 1678 1688 break; 1679 1689 /* ··· 1711 1701 } 1712 1702 break; 1713 1703 case Opt_tpgt: 1714 - match_int(args, &arg); 1704 + ret = match_int(args, &arg); 1705 + if (ret) 1706 + goto out; 1715 1707 tpgt = (u16)arg; 1716 1708 break; 1717 1709 case Opt_port_rtpi: 1718 - match_int(args, &arg); 1710 + ret = match_int(args, &arg); 1711 + if (ret) 1712 + goto out; 1719 1713 break; 1720 1714 case Opt_target_lun: 1721 - match_int(args, &arg); 1715 + ret = match_int(args, &arg); 1716 + if (ret) 1717 + goto out; 1722 1718 target_lun = (u64)arg; 1723 1719 break; 1724 1720 default: ··· 2001 1985 2002 1986 lu_gp_mem = dev->dev_alua_lu_gp_mem; 2003 1987 if (!lu_gp_mem) 2004 - return 0; 1988 + return count; 2005 1989 2006 1990 if (count > LU_GROUP_NAME_BUF) { 2007 1991 pr_err("ALUA LU Group Alias too large!\n");
+1 -1
drivers/target/target_core_pr.c
··· 1474 1474 LIST_HEAD(tid_dest_list); 1475 1475 struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp; 1476 1476 unsigned char *buf, *ptr, proto_ident; 1477 - const unsigned char *i_str; 1477 + const unsigned char *i_str = NULL; 1478 1478 char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN]; 1479 1479 sense_reason_t ret; 1480 1480 u32 tpdl, tid_len = 0;
+1
drivers/target/target_core_rd.c
··· 333 333 dev->dev_attrib.hw_block_size = RD_BLOCKSIZE; 334 334 dev->dev_attrib.hw_max_sectors = UINT_MAX; 335 335 dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH; 336 + dev->dev_attrib.is_nonrot = 1; 336 337 337 338 rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++; 338 339
+8 -1
drivers/target/target_core_spc.c
··· 454 454 cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT) 455 455 buf[4] = 0x5; 456 456 else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT || 457 - cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT) 457 + cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT) 458 458 buf[4] = 0x4; 459 + } 460 + 461 + /* logical unit supports type 1 and type 3 protection */ 462 + if ((dev->transport->get_device_type(dev) == TYPE_DISK) && 463 + (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) && 464 + (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)) { 465 + buf[4] |= (0x3 << 3); 459 466 } 460 467 461 468 /* Set HEADSUP, ORDSUP, SIMPSUP */
+1
include/target/iscsi/iscsi_target_core.h
··· 595 595 int bitmap_id; 596 596 int rx_thread_active; 597 597 struct task_struct *rx_thread; 598 + struct completion rx_login_comp; 598 599 int tx_thread_active; 599 600 struct task_struct *tx_thread; 600 601 /* list_head for session connection list */