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. ...
This commit is contained in:
commit
733db573a6
|
@ -199,7 +199,8 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||
buf += "#include <linux/string.h>\n"
|
||||
buf += "#include <linux/configfs.h>\n"
|
||||
buf += "#include <linux/ctype.h>\n"
|
||||
buf += "#include <asm/unaligned.h>\n\n"
|
||||
buf += "#include <asm/unaligned.h>\n"
|
||||
buf += "#include <scsi/scsi_proto.h>\n\n"
|
||||
buf += "#include <target/target_core_base.h>\n"
|
||||
buf += "#include <target/target_core_fabric.h>\n"
|
||||
buf += "#include <target/target_core_fabric_configfs.h>\n"
|
||||
|
@ -230,8 +231,14 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||
buf += " }\n"
|
||||
buf += " tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
|
||||
buf += " tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
|
||||
buf += " ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
|
||||
buf += " &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
|
||||
|
||||
if proto_ident == "FC":
|
||||
buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);\n"
|
||||
elif proto_ident == "SAS":
|
||||
buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
|
||||
elif proto_ident == "iSCSI":
|
||||
buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_ISCSI);\n"
|
||||
|
||||
buf += " if (ret < 0) {\n"
|
||||
buf += " kfree(tpg);\n"
|
||||
buf += " return NULL;\n"
|
||||
|
@ -292,7 +299,7 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||
|
||||
buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
|
||||
buf += " .module = THIS_MODULE,\n"
|
||||
buf += " .name = " + fabric_mod_name + ",\n"
|
||||
buf += " .name = \"" + fabric_mod_name + "\",\n"
|
||||
buf += " .get_fabric_name = " + fabric_mod_name + "_get_fabric_name,\n"
|
||||
buf += " .tpg_get_wwn = " + fabric_mod_name + "_get_fabric_wwn,\n"
|
||||
buf += " .tpg_get_tag = " + fabric_mod_name + "_get_tag,\n"
|
||||
|
@ -322,17 +329,17 @@ def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
|
|||
buf += " .fabric_make_tpg = " + fabric_mod_name + "_make_tpg,\n"
|
||||
buf += " .fabric_drop_tpg = " + fabric_mod_name + "_drop_tpg,\n"
|
||||
buf += "\n"
|
||||
buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
|
||||
buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs,\n"
|
||||
buf += "};\n\n"
|
||||
|
||||
buf += "static int __init " + fabric_mod_name + "_init(void)\n"
|
||||
buf += "{\n"
|
||||
buf += " return target_register_template(" + fabric_mod_name + "_ops);\n"
|
||||
buf += " return target_register_template(&" + fabric_mod_name + "_ops);\n"
|
||||
buf += "};\n\n"
|
||||
|
||||
buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
|
||||
buf += "{\n"
|
||||
buf += " target_unregister_template(" + fabric_mod_name + "_ops);\n"
|
||||
buf += " target_unregister_template(&" + fabric_mod_name + "_ops);\n"
|
||||
buf += "};\n\n"
|
||||
|
||||
buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
|
||||
|
|
|
@ -775,6 +775,17 @@ isert_connect_request(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)
|
|||
ret = isert_rdma_post_recvl(isert_conn);
|
||||
if (ret)
|
||||
goto out_conn_dev;
|
||||
/*
|
||||
* Obtain the second reference now before isert_rdma_accept() to
|
||||
* ensure that any initiator generated REJECT CM event that occurs
|
||||
* asynchronously won't drop the last reference until the error path
|
||||
* in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() ->
|
||||
* isert_free_conn() -> isert_put_conn() -> kref_put().
|
||||
*/
|
||||
if (!kref_get_unless_zero(&isert_conn->kref)) {
|
||||
isert_warn("conn %p connect_release is running\n", isert_conn);
|
||||
goto out_conn_dev;
|
||||
}
|
||||
|
||||
ret = isert_rdma_accept(isert_conn);
|
||||
if (ret)
|
||||
|
@ -836,11 +847,6 @@ isert_connected_handler(struct rdma_cm_id *cma_id)
|
|||
|
||||
isert_info("conn %p\n", isert_conn);
|
||||
|
||||
if (!kref_get_unless_zero(&isert_conn->kref)) {
|
||||
isert_warn("conn %p connect_release is running\n", isert_conn);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&isert_conn->mutex);
|
||||
if (isert_conn->state != ISER_CONN_FULL_FEATURE)
|
||||
isert_conn->state = ISER_CONN_UP;
|
||||
|
|
|
@ -738,7 +738,7 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
|
|||
ql_log(ql_log_info, vha, 0x706f,
|
||||
"Issuing MPI reset.\n");
|
||||
|
||||
if (IS_QLA83XX(ha)) {
|
||||
if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
|
||||
uint32_t idc_control;
|
||||
|
||||
qla83xx_idc_lock(vha, 0);
|
||||
|
|
|
@ -67,10 +67,10 @@
|
|||
* | | | 0xd031-0xd0ff |
|
||||
* | | | 0xd101-0xd1fe |
|
||||
* | | | 0xd214-0xd2fe |
|
||||
* | Target Mode | 0xe079 | |
|
||||
* | Target Mode Management | 0xf072 | 0xf002 |
|
||||
* | Target Mode | 0xe080 | |
|
||||
* | Target Mode Management | 0xf096 | 0xf002 |
|
||||
* | | | 0xf046-0xf049 |
|
||||
* | Target Mode Task Management | 0x1000b | |
|
||||
* | Target Mode Task Management | 0x1000d | |
|
||||
* ----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
|
|
@ -274,6 +274,7 @@
|
|||
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
|
||||
|
||||
struct req_que;
|
||||
struct qla_tgt_sess;
|
||||
|
||||
/*
|
||||
* (sd.h is not exported, hence local inclusion)
|
||||
|
@ -2026,6 +2027,7 @@ typedef struct fc_port {
|
|||
uint16_t port_id;
|
||||
|
||||
unsigned long retry_delay_timestamp;
|
||||
struct qla_tgt_sess *tgt_session;
|
||||
} fc_port_t;
|
||||
|
||||
#include "qla_mr.h"
|
||||
|
@ -3154,13 +3156,13 @@ struct qla_hw_data {
|
|||
/* Bit 21 of fw_attributes decides the MCTP capabilities */
|
||||
#define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \
|
||||
((ha)->fw_attributes_ext[0] & BIT_0))
|
||||
#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha))
|
||||
#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha))
|
||||
#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
|
||||
#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
|
||||
#define IS_PI_DIFB_DIX0_CAPABLE(ha) (0)
|
||||
#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha))
|
||||
#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
|
||||
#define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
|
||||
(((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
|
||||
#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha))
|
||||
#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
|
||||
#define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length)
|
||||
#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha))
|
||||
#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
|
||||
|
@ -3579,6 +3581,16 @@ typedef struct scsi_qla_host {
|
|||
uint16_t fcoe_fcf_idx;
|
||||
uint8_t fcoe_vn_port_mac[6];
|
||||
|
||||
/* list of commands waiting on workqueue */
|
||||
struct list_head qla_cmd_list;
|
||||
struct list_head qla_sess_op_cmd_list;
|
||||
spinlock_t cmd_list_lock;
|
||||
|
||||
/* Counter to detect races between ELS and RSCN events */
|
||||
atomic_t generation_tick;
|
||||
/* Time when global fcport update has been scheduled */
|
||||
int total_fcport_update_gen;
|
||||
|
||||
uint32_t vp_abort_cnt;
|
||||
|
||||
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
|
||||
|
|
|
@ -115,6 +115,8 @@ qla2x00_async_iocb_timeout(void *data)
|
|||
QLA_LOGIO_LOGIN_RETRIED : 0;
|
||||
qla2x00_post_async_login_done_work(fcport->vha, fcport,
|
||||
lio->u.logio.data);
|
||||
} else if (sp->type == SRB_LOGOUT_CMD) {
|
||||
qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,7 +499,10 @@ void
|
|||
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
|
||||
uint16_t *data)
|
||||
{
|
||||
qla2x00_mark_device_lost(vha, fcport, 1, 0);
|
||||
/* Don't re-login in target mode */
|
||||
if (!fcport->tgt_session)
|
||||
qla2x00_mark_device_lost(vha, fcport, 1, 0);
|
||||
qlt_logo_completion_handler(fcport, data[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1538,7 +1543,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
|
|||
mem_size = (ha->fw_memory_size - 0x11000 + 1) *
|
||||
sizeof(uint16_t);
|
||||
} else if (IS_FWI2_CAPABLE(ha)) {
|
||||
if (IS_QLA83XX(ha))
|
||||
if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
|
||||
fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
|
||||
else if (IS_QLA81XX(ha))
|
||||
fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
|
||||
|
@ -1550,7 +1555,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
|
|||
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
|
||||
sizeof(uint32_t);
|
||||
if (ha->mqenable) {
|
||||
if (!IS_QLA83XX(ha))
|
||||
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
|
||||
mq_size = sizeof(struct qla2xxx_mq_chain);
|
||||
/*
|
||||
* Allocate maximum buffer size for all queues.
|
||||
|
@ -2922,21 +2927,14 @@ qla2x00_rport_del(void *data)
|
|||
{
|
||||
fc_port_t *fcport = data;
|
||||
struct fc_rport *rport;
|
||||
scsi_qla_host_t *vha = fcport->vha;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
|
||||
rport = fcport->drport ? fcport->drport: fcport->rport;
|
||||
fcport->drport = NULL;
|
||||
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
|
||||
if (rport) {
|
||||
if (rport)
|
||||
fc_remote_port_delete(rport);
|
||||
/*
|
||||
* Release the target mode FC NEXUS in qla_target.c code
|
||||
* if target mod is enabled.
|
||||
*/
|
||||
qlt_fc_port_deleted(vha, fcport);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3303,6 +3301,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
* Create target mode FC NEXUS in qla_target.c if target mode is
|
||||
* enabled..
|
||||
*/
|
||||
|
||||
qlt_fc_port_added(vha, fcport);
|
||||
|
||||
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
|
||||
|
@ -3341,8 +3340,7 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
|
||||
if (IS_QLAFX00(vha->hw)) {
|
||||
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
|
||||
qla2x00_reg_remote_port(vha, fcport);
|
||||
return;
|
||||
goto reg_port;
|
||||
}
|
||||
fcport->login_retry = 0;
|
||||
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
|
||||
|
@ -3350,7 +3348,16 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
|
|||
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
|
||||
qla2x00_iidma_fcport(vha, fcport);
|
||||
qla24xx_update_fcport_fcp_prio(vha, fcport);
|
||||
qla2x00_reg_remote_port(vha, fcport);
|
||||
|
||||
reg_port:
|
||||
if (qla_ini_mode_enabled(vha))
|
||||
qla2x00_reg_remote_port(vha, fcport);
|
||||
else {
|
||||
/*
|
||||
* Create target mode FC NEXUS in qla_target.c
|
||||
*/
|
||||
qlt_fc_port_added(vha, fcport);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3375,6 +3382,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
|
|||
LIST_HEAD(new_fcports);
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
|
||||
int discovery_gen;
|
||||
|
||||
/* If FL port exists, then SNS is present */
|
||||
if (IS_FWI2_CAPABLE(ha))
|
||||
|
@ -3445,6 +3453,14 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
|
|||
fcport->scan_state = QLA_FCPORT_SCAN;
|
||||
}
|
||||
|
||||
/* Mark the time right before querying FW for connected ports.
|
||||
* This process is long, asynchronous and by the time it's done,
|
||||
* collected information might not be accurate anymore. E.g.
|
||||
* disconnected port might have re-connected and a brand new
|
||||
* session has been created. In this case session's generation
|
||||
* will be newer than discovery_gen. */
|
||||
qlt_do_generation_tick(vha, &discovery_gen);
|
||||
|
||||
rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
|
||||
if (rval != QLA_SUCCESS)
|
||||
break;
|
||||
|
@ -3460,20 +3476,44 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
|
|||
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
|
||||
continue;
|
||||
|
||||
if (fcport->scan_state == QLA_FCPORT_SCAN &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE) {
|
||||
qla2x00_mark_device_lost(vha, fcport,
|
||||
ql2xplogiabsentdevice, 0);
|
||||
if (fcport->loop_id != FC_NO_LOOP_ID &&
|
||||
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
|
||||
fcport->port_type != FCT_INITIATOR &&
|
||||
fcport->port_type != FCT_BROADCAST) {
|
||||
ha->isp_ops->fabric_logout(vha,
|
||||
fcport->loop_id,
|
||||
fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area,
|
||||
fcport->d_id.b.al_pa);
|
||||
qla2x00_clear_loop_id(fcport);
|
||||
if (fcport->scan_state == QLA_FCPORT_SCAN) {
|
||||
if (qla_ini_mode_enabled(base_vha) &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE) {
|
||||
qla2x00_mark_device_lost(vha, fcport,
|
||||
ql2xplogiabsentdevice, 0);
|
||||
if (fcport->loop_id != FC_NO_LOOP_ID &&
|
||||
(fcport->flags & FCF_FCP2_DEVICE) == 0 &&
|
||||
fcport->port_type != FCT_INITIATOR &&
|
||||
fcport->port_type != FCT_BROADCAST) {
|
||||
ha->isp_ops->fabric_logout(vha,
|
||||
fcport->loop_id,
|
||||
fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area,
|
||||
fcport->d_id.b.al_pa);
|
||||
qla2x00_clear_loop_id(fcport);
|
||||
}
|
||||
} else if (!qla_ini_mode_enabled(base_vha)) {
|
||||
/*
|
||||
* In target mode, explicitly kill
|
||||
* sessions and log out of devices
|
||||
* that are gone, so that we don't
|
||||
* end up with an initiator using the
|
||||
* wrong ACL (if the fabric recycles
|
||||
* an FC address and we have a stale
|
||||
* session around) and so that we don't
|
||||
* report initiators that are no longer
|
||||
* on the fabric.
|
||||
*/
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
|
||||
"port gone, logging out/killing session: "
|
||||
"%8phC state 0x%x flags 0x%x fc4_type 0x%x "
|
||||
"scan_state %d\n",
|
||||
fcport->port_name,
|
||||
atomic_read(&fcport->state),
|
||||
fcport->flags, fcport->fc4_type,
|
||||
fcport->scan_state);
|
||||
qlt_fc_port_deleted(vha, fcport,
|
||||
discovery_gen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3494,6 +3534,28 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
|
|||
(fcport->flags & FCF_LOGIN_NEEDED) == 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we're not an initiator, skip looking for devices
|
||||
* and logging in. There's no reason for us to do it,
|
||||
* and it seems to actively cause problems in target
|
||||
* mode if we race with the initiator logging into us
|
||||
* (we might get the "port ID used" status back from
|
||||
* our login command and log out the initiator, which
|
||||
* seems to cause havoc).
|
||||
*/
|
||||
if (!qla_ini_mode_enabled(base_vha)) {
|
||||
if (fcport->scan_state == QLA_FCPORT_FOUND) {
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
|
||||
"port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
|
||||
"scan_state %d (initiator mode disabled; skipping "
|
||||
"login)\n", fcport->port_name,
|
||||
atomic_read(&fcport->state),
|
||||
fcport->flags, fcport->fc4_type,
|
||||
fcport->scan_state);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fcport->loop_id == FC_NO_LOOP_ID) {
|
||||
fcport->loop_id = next_loopid;
|
||||
rval = qla2x00_find_new_loop_id(
|
||||
|
@ -3520,16 +3582,38 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
|
|||
test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
|
||||
break;
|
||||
|
||||
/* Find a new loop ID to use. */
|
||||
fcport->loop_id = next_loopid;
|
||||
rval = qla2x00_find_new_loop_id(base_vha, fcport);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
/* Ran out of IDs to use */
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* If we're not an initiator, skip looking for devices
|
||||
* and logging in. There's no reason for us to do it,
|
||||
* and it seems to actively cause problems in target
|
||||
* mode if we race with the initiator logging into us
|
||||
* (we might get the "port ID used" status back from
|
||||
* our login command and log out the initiator, which
|
||||
* seems to cause havoc).
|
||||
*/
|
||||
if (qla_ini_mode_enabled(base_vha)) {
|
||||
/* Find a new loop ID to use. */
|
||||
fcport->loop_id = next_loopid;
|
||||
rval = qla2x00_find_new_loop_id(base_vha,
|
||||
fcport);
|
||||
if (rval != QLA_SUCCESS) {
|
||||
/* Ran out of IDs to use */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Login and update database */
|
||||
qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
|
||||
/* Login and update database */
|
||||
qla2x00_fabric_dev_login(vha, fcport,
|
||||
&next_loopid);
|
||||
} else {
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
|
||||
"new port %8phC state 0x%x flags 0x%x fc4_type "
|
||||
"0x%x scan_state %d (initiator mode disabled; "
|
||||
"skipping login)\n",
|
||||
fcport->port_name,
|
||||
atomic_read(&fcport->state),
|
||||
fcport->flags, fcport->fc4_type,
|
||||
fcport->scan_state);
|
||||
}
|
||||
|
||||
list_move_tail(&fcport->list, &vha->vp_fcports);
|
||||
}
|
||||
|
@ -3725,11 +3809,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
|
|||
fcport->fp_speed = new_fcport->fp_speed;
|
||||
|
||||
/*
|
||||
* If address the same and state FCS_ONLINE, nothing
|
||||
* changed.
|
||||
* If address the same and state FCS_ONLINE
|
||||
* (or in target mode), nothing changed.
|
||||
*/
|
||||
if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
|
||||
atomic_read(&fcport->state) == FCS_ONLINE) {
|
||||
(atomic_read(&fcport->state) == FCS_ONLINE ||
|
||||
!qla_ini_mode_enabled(base_vha))) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3749,6 +3834,22 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
|
|||
* Log it out if still logged in and mark it for
|
||||
* relogin later.
|
||||
*/
|
||||
if (!qla_ini_mode_enabled(base_vha)) {
|
||||
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
|
||||
"port changed FC ID, %8phC"
|
||||
" old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
|
||||
fcport->port_name,
|
||||
fcport->d_id.b.domain,
|
||||
fcport->d_id.b.area,
|
||||
fcport->d_id.b.al_pa,
|
||||
fcport->loop_id,
|
||||
new_fcport->d_id.b.domain,
|
||||
new_fcport->d_id.b.area,
|
||||
new_fcport->d_id.b.al_pa);
|
||||
fcport->d_id.b24 = new_fcport->d_id.b24;
|
||||
break;
|
||||
}
|
||||
|
||||
fcport->d_id.b24 = new_fcport->d_id.b24;
|
||||
fcport->flags |= FCF_LOGIN_NEEDED;
|
||||
if (fcport->loop_id != FC_NO_LOOP_ID &&
|
||||
|
@ -3768,6 +3869,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
|
|||
if (found)
|
||||
continue;
|
||||
/* If device was not in our fcports list, then add it. */
|
||||
new_fcport->scan_state = QLA_FCPORT_FOUND;
|
||||
list_add_tail(&new_fcport->list, new_fcports);
|
||||
|
||||
/* Allocate a new replacement fcport. */
|
||||
|
@ -4188,6 +4290,14 @@ qla2x00_update_fcports(scsi_qla_host_t *base_vha)
|
|||
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
|
||||
spin_unlock_irqrestore(&ha->vport_slock, flags);
|
||||
qla2x00_rport_del(fcport);
|
||||
|
||||
/*
|
||||
* Release the target mode FC NEXUS in
|
||||
* qla_target.c, if target mod is enabled.
|
||||
*/
|
||||
qlt_fc_port_deleted(vha, fcport,
|
||||
base_vha->total_fcport_update_gen);
|
||||
|
||||
spin_lock_irqsave(&ha->vport_slock, flags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1943,6 +1943,9 @@ qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
|
|||
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
|
||||
logio->control_flags =
|
||||
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
|
||||
if (!sp->fcport->tgt_session ||
|
||||
!sp->fcport->tgt_session->keep_nport_handle)
|
||||
logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
|
||||
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
|
||||
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
|
||||
logio->port_id[1] = sp->fcport->d_id.b.area;
|
||||
|
|
|
@ -2415,7 +2415,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha, uint16_t *cur_xchg_cnt,
|
|||
*orig_iocb_cnt = mcp->mb[10];
|
||||
if (vha->hw->flags.npiv_supported && max_npiv_vports)
|
||||
*max_npiv_vports = mcp->mb[11];
|
||||
if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs)
|
||||
if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) ||
|
||||
IS_QLA27XX(vha->hw)) && max_fcfs)
|
||||
*max_fcfs = mcp->mb[12];
|
||||
}
|
||||
|
||||
|
@ -3898,7 +3899,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
|
|||
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||
if (!(rsp->options & BIT_0)) {
|
||||
WRT_REG_DWORD(rsp->rsp_q_out, 0);
|
||||
if (!IS_QLA83XX(ha))
|
||||
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
|
||||
WRT_REG_DWORD(rsp->rsp_q_in, 0);
|
||||
}
|
||||
|
||||
|
@ -5345,7 +5346,7 @@ qla83xx_restart_nic_firmware(scsi_qla_host_t *vha)
|
|||
mbx_cmd_t *mcp = &mc;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (!IS_QLA83XX(ha))
|
||||
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
|
||||
return QLA_FUNCTION_FAILED;
|
||||
|
||||
ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
|
||||
|
|
|
@ -2504,6 +2504,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ha->mbx_count = MAILBOX_REGISTER_COUNT;
|
||||
req_length = REQUEST_ENTRY_CNT_24XX;
|
||||
rsp_length = RESPONSE_ENTRY_CNT_2300;
|
||||
ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
|
||||
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
|
||||
ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
|
||||
ha->gid_list_info_size = 8;
|
||||
|
@ -3229,11 +3230,15 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *vha, fc_port_t *fcport,
|
|||
spin_lock_irqsave(vha->host->host_lock, flags);
|
||||
fcport->drport = rport;
|
||||
spin_unlock_irqrestore(vha->host->host_lock, flags);
|
||||
qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen);
|
||||
set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
|
||||
qla2xxx_wake_dpc(base_vha);
|
||||
} else {
|
||||
fc_remote_port_delete(rport);
|
||||
qlt_fc_port_deleted(vha, fcport);
|
||||
int now;
|
||||
if (rport)
|
||||
fc_remote_port_delete(rport);
|
||||
qlt_do_generation_tick(vha, &now);
|
||||
qlt_fc_port_deleted(vha, fcport, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3763,8 +3768,11 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
|
|||
INIT_LIST_HEAD(&vha->vp_fcports);
|
||||
INIT_LIST_HEAD(&vha->work_list);
|
||||
INIT_LIST_HEAD(&vha->list);
|
||||
INIT_LIST_HEAD(&vha->qla_cmd_list);
|
||||
INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
|
||||
|
||||
spin_lock_init(&vha->work_lock);
|
||||
spin_lock_init(&vha->cmd_list_lock);
|
||||
|
||||
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
|
||||
ql_dbg(ql_dbg_init, vha, 0x0041,
|
||||
|
|
|
@ -1697,7 +1697,7 @@ qla83xx_select_led_port(struct qla_hw_data *ha)
|
|||
{
|
||||
uint32_t led_select_value = 0;
|
||||
|
||||
if (!IS_QLA83XX(ha))
|
||||
if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
|
||||
goto out;
|
||||
|
||||
if (ha->port_no == 0)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -167,7 +167,24 @@ struct imm_ntfy_from_isp {
|
|||
uint32_t srr_rel_offs;
|
||||
uint16_t srr_ui;
|
||||
uint16_t srr_ox_id;
|
||||
uint8_t reserved_4[19];
|
||||
union {
|
||||
struct {
|
||||
uint8_t node_name[8];
|
||||
} plogi; /* PLOGI/ADISC/PDISC */
|
||||
struct {
|
||||
/* PRLI word 3 bit 0-15 */
|
||||
uint16_t wd3_lo;
|
||||
uint8_t resv0[6];
|
||||
} prli;
|
||||
struct {
|
||||
uint8_t port_id[3];
|
||||
uint8_t resv1;
|
||||
uint16_t nport_handle;
|
||||
uint16_t resv2;
|
||||
} req_els;
|
||||
} u;
|
||||
uint8_t port_name[8];
|
||||
uint8_t resv3[3];
|
||||
uint8_t vp_index;
|
||||
uint32_t reserved_5;
|
||||
uint8_t port_id[3];
|
||||
|
@ -234,6 +251,7 @@ struct nack_to_isp {
|
|||
uint8_t reserved[2];
|
||||
uint16_t ox_id;
|
||||
} __packed;
|
||||
#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
|
||||
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
|
||||
#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
|
||||
|
||||
|
@ -790,13 +808,6 @@ int qla2x00_wait_for_hba_online(struct scsi_qla_host *);
|
|||
#define FC_TM_REJECT 4
|
||||
#define FC_TM_FAILED 5
|
||||
|
||||
/*
|
||||
* Error code of qlt_pre_xmit_response() meaning that cmd's exchange was
|
||||
* terminated, so no more actions is needed and success should be returned
|
||||
* to target.
|
||||
*/
|
||||
#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717
|
||||
|
||||
#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
|
||||
#define pci_dma_lo32(a) (a & 0xffffffff)
|
||||
#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
|
||||
|
@ -874,6 +885,15 @@ struct qla_tgt_sess_op {
|
|||
struct scsi_qla_host *vha;
|
||||
struct atio_from_isp atio;
|
||||
struct work_struct work;
|
||||
struct list_head cmd_list;
|
||||
bool aborted;
|
||||
};
|
||||
|
||||
enum qla_sess_deletion {
|
||||
QLA_SESS_DELETION_NONE = 0,
|
||||
QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
|
||||
* this one */
|
||||
QLA_SESS_DELETION_IN_PROGRESS = 2,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -884,8 +904,15 @@ struct qla_tgt_sess {
|
|||
port_id_t s_id;
|
||||
|
||||
unsigned int conf_compl_supported:1;
|
||||
unsigned int deleted:1;
|
||||
unsigned int deleted:2;
|
||||
unsigned int local:1;
|
||||
unsigned int logout_on_delete:1;
|
||||
unsigned int plogi_ack_needed:1;
|
||||
unsigned int keep_nport_handle:1;
|
||||
|
||||
unsigned char logout_completed;
|
||||
|
||||
int generation;
|
||||
|
||||
struct se_session *se_sess;
|
||||
struct scsi_qla_host *vha;
|
||||
|
@ -897,6 +924,10 @@ struct qla_tgt_sess {
|
|||
|
||||
uint8_t port_name[WWN_SIZE];
|
||||
struct work_struct free_work;
|
||||
|
||||
union {
|
||||
struct imm_ntfy_from_isp tm_iocb;
|
||||
};
|
||||
};
|
||||
|
||||
struct qla_tgt_cmd {
|
||||
|
@ -912,7 +943,6 @@ struct qla_tgt_cmd {
|
|||
unsigned int conf_compl_supported:1;
|
||||
unsigned int sg_mapped:1;
|
||||
unsigned int free_sg:1;
|
||||
unsigned int aborted:1; /* Needed in case of SRR */
|
||||
unsigned int write_data_transferred:1;
|
||||
unsigned int ctx_dsd_alloced:1;
|
||||
unsigned int q_full:1;
|
||||
|
@ -961,6 +991,9 @@ struct qla_tgt_cmd {
|
|||
* BIT_14 - Back end data received/sent.
|
||||
* BIT_15 - SRR prepare ctio
|
||||
* BIT_16 - complete free
|
||||
* BIT_17 - flush - qlt_abort_cmd_on_host_reset
|
||||
* BIT_18 - completion w/abort status
|
||||
* BIT_19 - completion w/unknown status
|
||||
*/
|
||||
uint32_t cmd_flags;
|
||||
};
|
||||
|
@ -1026,6 +1059,10 @@ struct qla_tgt_srr_ctio {
|
|||
struct qla_tgt_cmd *cmd;
|
||||
};
|
||||
|
||||
/* Check for Switch reserved address */
|
||||
#define IS_SW_RESV_ADDR(_s_id) \
|
||||
((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
|
||||
|
||||
#define QLA_TGT_XMIT_DATA 1
|
||||
#define QLA_TGT_XMIT_STATUS 2
|
||||
#define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA)
|
||||
|
@ -1043,7 +1080,7 @@ extern int qlt_lport_register(void *, u64, u64, u64,
|
|||
extern void qlt_lport_deregister(struct scsi_qla_host *);
|
||||
extern void qlt_unreg_sess(struct qla_tgt_sess *);
|
||||
extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
|
||||
extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *);
|
||||
extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
|
||||
extern int __init qlt_init(void);
|
||||
extern void qlt_exit(void);
|
||||
extern void qlt_update_vp_map(struct scsi_qla_host *, int);
|
||||
|
@ -1073,12 +1110,23 @@ static inline void qla_reverse_ini_mode(struct scsi_qla_host *ha)
|
|||
ha->host->active_mode |= MODE_INITIATOR;
|
||||
}
|
||||
|
||||
static inline uint32_t sid_to_key(const uint8_t *s_id)
|
||||
{
|
||||
uint32_t key;
|
||||
|
||||
key = (((unsigned long)s_id[0] << 16) |
|
||||
((unsigned long)s_id[1] << 8) |
|
||||
(unsigned long)s_id[2]);
|
||||
return key;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
|
||||
*/
|
||||
extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
|
||||
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
|
||||
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
|
||||
extern void qlt_abort_cmd(struct qla_tgt_cmd *);
|
||||
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
|
||||
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
|
||||
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
|
||||
|
@ -1109,5 +1157,7 @@ extern void qlt_stop_phase2(struct qla_tgt *);
|
|||
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
|
||||
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
|
||||
extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
|
||||
extern void qlt_logo_completion_handler(fc_port_t *, int);
|
||||
extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
|
||||
|
||||
#endif /* __QLA_TARGET_H */
|
||||
|
|
|
@ -374,7 +374,7 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
|
|||
{
|
||||
struct qla_tgt_cmd *cmd = container_of(se_cmd,
|
||||
struct qla_tgt_cmd, se_cmd);
|
||||
|
||||
cmd->cmd_flags |= BIT_3;
|
||||
cmd->bufflen = se_cmd->data_length;
|
||||
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
|
||||
|
||||
|
@ -405,7 +405,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd)
|
|||
se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) {
|
||||
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
|
||||
wait_for_completion_timeout(&se_cmd->t_transport_stop_comp,
|
||||
3000);
|
||||
3 * HZ);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
|
||||
|
@ -541,12 +541,10 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
|
|||
cmd->cmd_flags |= BIT_4;
|
||||
cmd->bufflen = se_cmd->data_length;
|
||||
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
|
||||
cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
|
||||
|
||||
cmd->sg_cnt = se_cmd->t_data_nents;
|
||||
cmd->sg = se_cmd->t_data_sg;
|
||||
cmd->offset = 0;
|
||||
cmd->cmd_flags |= BIT_3;
|
||||
|
||||
cmd->prot_sg_cnt = se_cmd->t_prot_nents;
|
||||
cmd->prot_sg = se_cmd->t_prot_sg;
|
||||
|
@ -571,7 +569,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
|
|||
cmd->sg_cnt = 0;
|
||||
cmd->offset = 0;
|
||||
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
|
||||
cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
|
||||
if (cmd->cmd_flags & BIT_5) {
|
||||
pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
|
||||
dump_stack();
|
||||
|
@ -636,14 +633,7 @@ static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd)
|
|||
{
|
||||
struct qla_tgt_cmd *cmd = container_of(se_cmd,
|
||||
struct qla_tgt_cmd, se_cmd);
|
||||
struct scsi_qla_host *vha = cmd->vha;
|
||||
struct qla_hw_data *ha = vha->hw;
|
||||
|
||||
if (!cmd->sg_mapped)
|
||||
return;
|
||||
|
||||
pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
|
||||
cmd->sg_mapped = 0;
|
||||
qlt_abort_cmd(cmd);
|
||||
}
|
||||
|
||||
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
|
||||
|
@ -1149,9 +1139,7 @@ static struct qla_tgt_sess *tcm_qla2xxx_find_sess_by_s_id(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
key = (((unsigned long)s_id[0] << 16) |
|
||||
((unsigned long)s_id[1] << 8) |
|
||||
(unsigned long)s_id[2]);
|
||||
key = sid_to_key(s_id);
|
||||
pr_debug("find_sess_by_s_id: 0x%06x\n", key);
|
||||
|
||||
se_nacl = btree_lookup32(&lport->lport_fcport_map, key);
|
||||
|
@ -1186,9 +1174,7 @@ static void tcm_qla2xxx_set_sess_by_s_id(
|
|||
void *slot;
|
||||
int rc;
|
||||
|
||||
key = (((unsigned long)s_id[0] << 16) |
|
||||
((unsigned long)s_id[1] << 8) |
|
||||
(unsigned long)s_id[2]);
|
||||
key = sid_to_key(s_id);
|
||||
pr_debug("set_sess_by_s_id: %06x\n", key);
|
||||
|
||||
slot = btree_lookup32(&lport->lport_fcport_map, key);
|
||||
|
@ -1544,6 +1530,10 @@ static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
|
|||
}
|
||||
|
||||
sess->conf_compl_supported = conf_compl_supported;
|
||||
|
||||
/* Reset logout parameters to default */
|
||||
sess->logout_on_delete = 1;
|
||||
sess->keep_nport_handle = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -3998,7 +3998,13 @@ get_immediate:
|
|||
}
|
||||
|
||||
transport_err:
|
||||
iscsit_take_action_for_connection_exit(conn);
|
||||
/*
|
||||
* Avoid the normal connection failure code-path if this connection
|
||||
* is still within LOGIN mode, and iscsi_np process context is
|
||||
* responsible for cleaning up the early connection failure.
|
||||
*/
|
||||
if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
|
||||
iscsit_take_action_for_connection_exit(conn);
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
@ -4082,7 +4088,7 @@ reject:
|
|||
|
||||
int iscsi_target_rx_thread(void *arg)
|
||||
{
|
||||
int ret;
|
||||
int ret, rc;
|
||||
u8 buffer[ISCSI_HDR_LEN], opcode;
|
||||
u32 checksum = 0, digest = 0;
|
||||
struct iscsi_conn *conn = arg;
|
||||
|
@ -4092,10 +4098,16 @@ int iscsi_target_rx_thread(void *arg)
|
|||
* connection recovery / failure event can be triggered externally.
|
||||
*/
|
||||
allow_signal(SIGINT);
|
||||
/*
|
||||
* Wait for iscsi_post_login_handler() to complete before allowing
|
||||
* incoming iscsi/tcp socket I/O, and/or failing the connection.
|
||||
*/
|
||||
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
|
||||
if (rc < 0)
|
||||
return 0;
|
||||
|
||||
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
|
||||
struct completion comp;
|
||||
int rc;
|
||||
|
||||
init_completion(&comp);
|
||||
rc = wait_for_completion_interruptible(&comp);
|
||||
|
@ -4532,7 +4544,18 @@ static void iscsit_logout_post_handler_closesession(
|
|||
struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
int sleep = cmpxchg(&conn->tx_thread_active, true, false);
|
||||
int sleep = 1;
|
||||
/*
|
||||
* Traditional iscsi/tcp will invoke this logic from TX thread
|
||||
* context during session logout, so clear tx_thread_active and
|
||||
* sleep if iscsit_close_connection() has not already occured.
|
||||
*
|
||||
* Since iser-target invokes this logic from it's own workqueue,
|
||||
* always sleep waiting for RX/TX thread shutdown to complete
|
||||
* within iscsit_close_connection().
|
||||
*/
|
||||
if (conn->conn_transport->transport_type == ISCSI_TCP)
|
||||
sleep = cmpxchg(&conn->tx_thread_active, true, false);
|
||||
|
||||
atomic_set(&conn->conn_logout_remove, 0);
|
||||
complete(&conn->conn_logout_comp);
|
||||
|
@ -4546,7 +4569,10 @@ static void iscsit_logout_post_handler_closesession(
|
|||
static void iscsit_logout_post_handler_samecid(
|
||||
struct iscsi_conn *conn)
|
||||
{
|
||||
int sleep = cmpxchg(&conn->tx_thread_active, true, false);
|
||||
int sleep = 1;
|
||||
|
||||
if (conn->conn_transport->transport_type == ISCSI_TCP)
|
||||
sleep = cmpxchg(&conn->tx_thread_active, true, false);
|
||||
|
||||
atomic_set(&conn->conn_logout_remove, 0);
|
||||
complete(&conn->conn_logout_comp);
|
||||
|
@ -4765,6 +4791,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
|
|||
struct iscsi_session *sess;
|
||||
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
|
||||
struct se_session *se_sess, *se_sess_tmp;
|
||||
LIST_HEAD(free_list);
|
||||
int session_count = 0;
|
||||
|
||||
spin_lock_bh(&se_tpg->session_lock);
|
||||
|
@ -4786,15 +4813,18 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
|
|||
}
|
||||
atomic_set(&sess->session_reinstatement, 1);
|
||||
spin_unlock(&sess->conn_lock);
|
||||
spin_unlock_bh(&se_tpg->session_lock);
|
||||
|
||||
iscsit_free_session(sess);
|
||||
spin_lock_bh(&se_tpg->session_lock);
|
||||
|
||||
session_count++;
|
||||
list_move_tail(&se_sess->sess_list, &free_list);
|
||||
}
|
||||
spin_unlock_bh(&se_tpg->session_lock);
|
||||
|
||||
list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
|
||||
sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
|
||||
|
||||
iscsit_free_session(sess);
|
||||
session_count++;
|
||||
}
|
||||
|
||||
pr_debug("Released %d iSCSI Session(s) from Target Portal"
|
||||
" Group: %hu\n", session_count, tpg->tpgt);
|
||||
return 0;
|
||||
|
|
|
@ -82,6 +82,7 @@ static struct iscsi_login *iscsi_login_init_conn(struct iscsi_conn *conn)
|
|||
init_completion(&conn->conn_logout_comp);
|
||||
init_completion(&conn->rx_half_close_comp);
|
||||
init_completion(&conn->tx_half_close_comp);
|
||||
init_completion(&conn->rx_login_comp);
|
||||
spin_lock_init(&conn->cmd_lock);
|
||||
spin_lock_init(&conn->conn_usage_lock);
|
||||
spin_lock_init(&conn->immed_queue_lock);
|
||||
|
@ -644,7 +645,7 @@ static void iscsi_post_login_start_timers(struct iscsi_conn *conn)
|
|||
iscsit_start_nopin_timer(conn);
|
||||
}
|
||||
|
||||
static int iscsit_start_kthreads(struct iscsi_conn *conn)
|
||||
int iscsit_start_kthreads(struct iscsi_conn *conn)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -679,6 +680,7 @@ static int iscsit_start_kthreads(struct iscsi_conn *conn)
|
|||
|
||||
return 0;
|
||||
out_tx:
|
||||
send_sig(SIGINT, conn->tx_thread, 1);
|
||||
kthread_stop(conn->tx_thread);
|
||||
conn->tx_thread_active = false;
|
||||
out_bitmap:
|
||||
|
@ -689,7 +691,7 @@ out_bitmap:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iscsi_post_login_handler(
|
||||
void iscsi_post_login_handler(
|
||||
struct iscsi_np *np,
|
||||
struct iscsi_conn *conn,
|
||||
u8 zero_tsih)
|
||||
|
@ -699,7 +701,6 @@ int iscsi_post_login_handler(
|
|||
struct se_session *se_sess = sess->se_sess;
|
||||
struct iscsi_portal_group *tpg = sess->tpg;
|
||||
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
|
||||
int rc;
|
||||
|
||||
iscsit_inc_conn_usage_count(conn);
|
||||
|
||||
|
@ -739,10 +740,6 @@ int iscsi_post_login_handler(
|
|||
sess->sess_ops->InitiatorName);
|
||||
spin_unlock_bh(&sess->conn_lock);
|
||||
|
||||
rc = iscsit_start_kthreads(conn);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
iscsi_post_login_start_timers(conn);
|
||||
/*
|
||||
* Determine CPU mask to ensure connection's RX and TX kthreads
|
||||
|
@ -751,15 +748,20 @@ int iscsi_post_login_handler(
|
|||
iscsit_thread_get_cpumask(conn);
|
||||
conn->conn_rx_reset_cpumask = 1;
|
||||
conn->conn_tx_reset_cpumask = 1;
|
||||
|
||||
/*
|
||||
* Wakeup the sleeping iscsi_target_rx_thread() now that
|
||||
* iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state.
|
||||
*/
|
||||
complete(&conn->rx_login_comp);
|
||||
iscsit_dec_conn_usage_count(conn);
|
||||
|
||||
if (stop_timer) {
|
||||
spin_lock_bh(&se_tpg->session_lock);
|
||||
iscsit_stop_time2retain_timer(sess);
|
||||
spin_unlock_bh(&se_tpg->session_lock);
|
||||
}
|
||||
iscsit_dec_session_usage_count(sess);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1);
|
||||
|
@ -800,10 +802,6 @@ int iscsi_post_login_handler(
|
|||
" iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt);
|
||||
spin_unlock_bh(&se_tpg->session_lock);
|
||||
|
||||
rc = iscsit_start_kthreads(conn);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
iscsi_post_login_start_timers(conn);
|
||||
/*
|
||||
* Determine CPU mask to ensure connection's RX and TX kthreads
|
||||
|
@ -812,10 +810,12 @@ int iscsi_post_login_handler(
|
|||
iscsit_thread_get_cpumask(conn);
|
||||
conn->conn_rx_reset_cpumask = 1;
|
||||
conn->conn_tx_reset_cpumask = 1;
|
||||
|
||||
/*
|
||||
* Wakeup the sleeping iscsi_target_rx_thread() now that
|
||||
* iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state.
|
||||
*/
|
||||
complete(&conn->rx_login_comp);
|
||||
iscsit_dec_conn_usage_count(conn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iscsi_handle_login_thread_timeout(unsigned long data)
|
||||
|
@ -1380,23 +1380,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
|||
if (ret < 0)
|
||||
goto new_sess_out;
|
||||
|
||||
if (!conn->sess) {
|
||||
pr_err("struct iscsi_conn session pointer is NULL!\n");
|
||||
goto new_sess_out;
|
||||
}
|
||||
|
||||
iscsi_stop_login_thread_timer(np);
|
||||
|
||||
if (signal_pending(current))
|
||||
goto new_sess_out;
|
||||
|
||||
if (ret == 1) {
|
||||
tpg_np = conn->tpg_np;
|
||||
|
||||
ret = iscsi_post_login_handler(np, conn, zero_tsih);
|
||||
if (ret < 0)
|
||||
goto new_sess_out;
|
||||
|
||||
iscsi_post_login_handler(np, conn, zero_tsih);
|
||||
iscsit_deaccess_np(np, tpg, tpg_np);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
|
|||
extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
|
||||
extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
|
||||
extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *);
|
||||
extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
|
||||
extern int iscsit_start_kthreads(struct iscsi_conn *);
|
||||
extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
|
||||
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
|
||||
bool, bool);
|
||||
extern int iscsi_target_login_thread(void *);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
******************************************************************************/
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <scsi/iscsi_proto.h>
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
@ -361,10 +362,24 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
|
|||
ntohl(login_rsp->statsn), login->rsp_length);
|
||||
|
||||
padding = ((-login->rsp_length) & 3);
|
||||
/*
|
||||
* Before sending the last login response containing the transition
|
||||
* bit for full-feature-phase, go ahead and start up TX/RX threads
|
||||
* now to avoid potential resource allocation failures after the
|
||||
* final login response has been sent.
|
||||
*/
|
||||
if (login->login_complete) {
|
||||
int rc = iscsit_start_kthreads(conn);
|
||||
if (rc) {
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_NO_RESOURCES);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->conn_transport->iscsit_put_login_tx(conn, login,
|
||||
login->rsp_length + padding) < 0)
|
||||
return -1;
|
||||
goto err;
|
||||
|
||||
login->rsp_length = 0;
|
||||
mutex_lock(&sess->cmdsn_mutex);
|
||||
|
@ -373,6 +388,23 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
|
|||
mutex_unlock(&sess->cmdsn_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (login->login_complete) {
|
||||
if (conn->rx_thread && conn->rx_thread_active) {
|
||||
send_sig(SIGINT, conn->rx_thread, 1);
|
||||
kthread_stop(conn->rx_thread);
|
||||
}
|
||||
if (conn->tx_thread && conn->tx_thread_active) {
|
||||
send_sig(SIGINT, conn->tx_thread, 1);
|
||||
kthread_stop(conn->tx_thread);
|
||||
}
|
||||
spin_lock(&iscsit_global->ts_bitmap_lock);
|
||||
bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
|
||||
get_order(1));
|
||||
spin_unlock(&iscsit_global->ts_bitmap_lock);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void iscsi_target_sk_data_ready(struct sock *sk)
|
||||
|
|
|
@ -747,7 +747,7 @@ static ssize_t store_pi_prot_type(struct se_dev_attrib *da,
|
|||
if (!dev->transport->init_prot || !dev->transport->free_prot) {
|
||||
/* 0 is only allowed value for non-supporting backends */
|
||||
if (flag == 0)
|
||||
return 0;
|
||||
return count;
|
||||
|
||||
pr_err("DIF protection not supported by backend: %s\n",
|
||||
dev->transport->name);
|
||||
|
@ -1590,9 +1590,9 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||
u8 type = 0;
|
||||
|
||||
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
|
||||
return 0;
|
||||
return count;
|
||||
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
|
||||
return 0;
|
||||
return count;
|
||||
|
||||
if (dev->export_count) {
|
||||
pr_debug("Unable to process APTPL metadata while"
|
||||
|
@ -1658,22 +1658,32 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||
* PR APTPL Metadata for Reservation
|
||||
*/
|
||||
case Opt_res_holder:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
res_holder = arg;
|
||||
break;
|
||||
case Opt_res_type:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
type = (u8)arg;
|
||||
break;
|
||||
case Opt_res_scope:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
case Opt_res_all_tg_pt:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
all_tg_pt = (int)arg;
|
||||
break;
|
||||
case Opt_mapped_lun:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
mapped_lun = (u64)arg;
|
||||
break;
|
||||
/*
|
||||
|
@ -1701,14 +1711,20 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
|
|||
}
|
||||
break;
|
||||
case Opt_tpgt:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
tpgt = (u16)arg;
|
||||
break;
|
||||
case Opt_port_rtpi:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
break;
|
||||
case Opt_target_lun:
|
||||
match_int(args, &arg);
|
||||
ret = match_int(args, &arg);
|
||||
if (ret)
|
||||
goto out;
|
||||
target_lun = (u64)arg;
|
||||
break;
|
||||
default:
|
||||
|
@ -1985,7 +2001,7 @@ static ssize_t target_core_store_alua_lu_gp(
|
|||
|
||||
lu_gp_mem = dev->dev_alua_lu_gp_mem;
|
||||
if (!lu_gp_mem)
|
||||
return 0;
|
||||
return count;
|
||||
|
||||
if (count > LU_GROUP_NAME_BUF) {
|
||||
pr_err("ALUA LU Group Alias too large!\n");
|
||||
|
|
|
@ -1474,7 +1474,7 @@ core_scsi3_decode_spec_i_port(
|
|||
LIST_HEAD(tid_dest_list);
|
||||
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
|
||||
unsigned char *buf, *ptr, proto_ident;
|
||||
const unsigned char *i_str;
|
||||
const unsigned char *i_str = NULL;
|
||||
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
|
||||
sense_reason_t ret;
|
||||
u32 tpdl, tid_len = 0;
|
||||
|
|
|
@ -333,6 +333,7 @@ static int rd_configure_device(struct se_device *dev)
|
|||
dev->dev_attrib.hw_block_size = RD_BLOCKSIZE;
|
||||
dev->dev_attrib.hw_max_sectors = UINT_MAX;
|
||||
dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH;
|
||||
dev->dev_attrib.is_nonrot = 1;
|
||||
|
||||
rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++;
|
||||
|
||||
|
|
|
@ -454,10 +454,17 @@ spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
|
|||
cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT)
|
||||
buf[4] = 0x5;
|
||||
else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT ||
|
||||
cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT)
|
||||
cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT)
|
||||
buf[4] = 0x4;
|
||||
}
|
||||
|
||||
/* logical unit supports type 1 and type 3 protection */
|
||||
if ((dev->transport->get_device_type(dev) == TYPE_DISK) &&
|
||||
(sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) &&
|
||||
(dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)) {
|
||||
buf[4] |= (0x3 << 3);
|
||||
}
|
||||
|
||||
/* Set HEADSUP, ORDSUP, SIMPSUP */
|
||||
buf[5] = 0x07;
|
||||
|
||||
|
|
|
@ -595,6 +595,7 @@ struct iscsi_conn {
|
|||
int bitmap_id;
|
||||
int rx_thread_active;
|
||||
struct task_struct *rx_thread;
|
||||
struct completion rx_login_comp;
|
||||
int tx_thread_active;
|
||||
struct task_struct *tx_thread;
|
||||
/* list_head for session connection list */
|
||||
|
|
Loading…
Reference in New Issue