diff --git a/qla2x00t-32gbit/Makefile_in-tree b/qla2x00t-32gbit/Makefile_in-tree index 2e7619677..d87f9164f 100644 --- a/qla2x00t-32gbit/Makefile_in-tree +++ b/qla2x00t-32gbit/Makefile_in-tree @@ -1,4 +1,15 @@ # SPDX-License-Identifier: GPL-2.0 + +-include $(KBUILD_EXTMOD)/../build_mode + +echo := $(shell echo "qla2x00t-32gbit build mode: $(BUILD_MODE)" >& 2) + +BUILD_MODE_CFLAGS_ = -DCONFIG_SCST_TRACING -DCONFIG_SCST_DEBUG \ + -DCONFIG_SCST_EXTRACHECKS -fno-inline -fno-inline-functions +BUILD_MODE_CFLAGS_RELEASE = -DCONFIG_SCST_TRACING +BUILD_MODE_CFLAGS_PERF = +ccflags-y += $(BUILD_MODE_CFLAGS_$(BUILD_MODE)) + qla2xxx-y := qla_os.o qla_init.o qla_mbx.o qla_iocb.o qla_isr.o qla_gs.o \ qla_dbg.o qla_sup.o qla_attr.o qla_mid.o qla_dfs.o qla_bsg.o \ qla_nx.o qla_mr.o qla_nx2.o qla_target.o qla_tmpl.o qla_nvme.o diff --git a/qla2x00t-32gbit/qla2x00-target/Makefile b/qla2x00t-32gbit/qla2x00-target/Makefile index bb75f7bfe..17a3562f1 100644 --- a/qla2x00t-32gbit/qla2x00-target/Makefile +++ b/qla2x00t-32gbit/qla2x00-target/Makefile @@ -67,7 +67,7 @@ ccflags-y += -W -Wno-unused-parameter -Wno-missing-field-initializers -include $(KBUILD_EXTMOD)/../../build_mode -echo := $(shell echo "qla2x00t-32gbit build mode: $(BUILD_MODE)" >& 2) +echo := $(shell echo "qla2x00t-32gbit/target build mode: $(BUILD_MODE)" >& 2) BUILD_MODE_CFLAGS_ = -DCONFIG_SCST_TRACING -DCONFIG_SCST_DEBUG \ -DCONFIG_SCST_EXTRACHECKS -fno-inline -fno-inline-functions diff --git a/qla2x00t-32gbit/qla2x00-target/README b/qla2x00t-32gbit/qla2x00-target/README index 190a9846d..6c05debfc 100644 --- a/qla2x00t-32gbit/qla2x00-target/README +++ b/qla2x00t-32gbit/qla2x00-target/README @@ -68,32 +68,3 @@ Call Trace: [] ? retint_restore_args+0x13/0x43 [] ? kthread+0x0/0xc0 [] ? child_rip+0x0/0x30 - -When using RHEL 6 unloading this driver triggers a deadlock: - -INFO: task events/0:35 blocked for more than 120 seconds. - Not tainted 2.6.32-754.11.1.el6.x86_64.debug #1 -"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. -events/0 D ffff880077e24408 12408 35 2 0x00000000 - ffff88007e02fa60 0000000000000046 0000000000000000 7fffffffffffffff - 7fffffffffffffff 00000365a5588f80 ffff88007e028a80 ffff88000d7d93d8 - 0000000100346a5e 00000000000003c8 ffff88007e029040 ffff88007e02ffd8 -Call Trace: - [] schedule_timeout+0x265/0x330 - [] ? wait_for_common+0x4f/0x180 - [] ? wait_for_common+0x4f/0x180 - [] ? default_wake_function+0x0/0x20 - [] wait_for_common+0x12b/0x180 - [] ? default_wake_function+0x0/0x20 - [] wait_for_completion+0x1d/0x20 - [] ? qlt_free_session_done+0x1d6/0x930 [qla2xxx_scst] - [] ? qlt_free_session_done+0x0/0x930 [qla2xxx_scst] - [] ? worker_thread+0x21e/0x3f0 - [] ? worker_thread+0x1cb/0x3f0 - [] ? autoremove_wake_function+0x0/0x40 - [] ? worker_thread+0x0/0x3f0 - [] ? kthread+0xa0/0xc0 - [] ? child_rip+0x20/0x30 - [] ? retint_restore_args+0x13/0x43 - [] ? kthread+0x0/0xc0 - [] ? child_rip+0x0/0x30 diff --git a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c index 82f08ee91..8f173493c 100644 --- a/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c +++ b/qla2x00t-32gbit/qla2x00-target/scst_qla2xxx.c @@ -100,39 +100,6 @@ static bool sqa_is_tgt_enabled(struct scst_tgt *tgt); static ssize_t sqa_add_vtarget(const char *target_name, char *params); static ssize_t sqa_del_vtarget(const char *target_name); -/* - * Function definitions for callbacks from the Cavium low level target - * driver. -*/ -static int sqa_qla2xxx_handle_cmd(scsi_qla_host_t *vha, - struct qla_tgt_cmd *cmd,unsigned char *cdb, - uint32_t data_length, int task_codes, - int data_dir, int bidi); -static void sqa_qla2xxx_handle_data(struct qla_tgt_cmd *cmd); -static int sqa_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun, - uint16_t tmr_func, uint32_t tag); -static void sqa_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd); -static void sqa_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd); -static void sqa_qla2xxx_free_session(struct fc_port *sess); -static void sqa_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id, - uint16_t loop_id, - bool conf_compl_supported); -static int sqa_qla2xxx_check_initiator_node_acl(scsi_qla_host_t *vha, - unsigned char *fc_wwpn, - struct fc_port *qlat_sess); -static struct fc_port *sqa_qla2xxx_find_sess_by_s_id(scsi_qla_host_t *vha, - const uint8_t *s_id); -static struct fc_port *sqa_qla2xxx_find_sess_by_loop_id(scsi_qla_host_t *vha, - const uint16_t loop_id); -static void sqa_qla2xxx_clear_nacl_from_fcport_map(struct fc_port *sess); -static void sqa_qla2xxx_put_sess(struct fc_port *sess); -static void sqa_qla2xxx_shutdown_sess(struct fc_port *sess); -static int sqa_close_session(struct scst_session *scst_sess); -static int sqa_qla2xxx_dif_tags(struct qla_tgt_cmd *, uint16_t *); -static int sqa_qla2xxx_chk_dif_tags(uint32_t); -static void sqa_qla2xxx_add_target(struct scsi_qla_host *vha); -static void sqa_qla2xxx_remove_target(struct scsi_qla_host *vha); - /* Definitions for helper functions. */ static int sqa_get_target_name(uint8_t *wwn, char **ppwwn_name); static int sqa_parse_wwn(const char *ns, u64 *nm); @@ -244,60 +211,6 @@ static char *cmdstate_to_str(uint8_t state) return cmd_str[0].str; /* unknown */ } -/* - * The following structure definition provides descriptive parameeters - * and callbacks which will be used by the SCST target core to - * communicate with this target interface driver. - */ -static struct scst_tgt_template sqa_scst_template = { - .name = "qla2x00t", - .sg_tablesize = 0, - .use_clustering = 1, -#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD - .xmit_response_atomic = 0, - .rdy_to_xfer_atomic = 0, -#else - .xmit_response_atomic = 1, - .rdy_to_xfer_atomic = 1, -#endif - -#if QLA_ENABLE_PI -/* diff cap for individual adapter is set during sqa_qla2xxx_add_target */ - .dif_supported = 0, - .hw_dif_type1_supported = 0, - .hw_dif_type2_supported = 0, - .hw_dif_type3_supported = 0, - .hw_dif_ip_supported = 0, - .hw_dif_same_sg_layout_required = 0, -#endif - - .max_hw_pending_time = SQA_MAX_HW_PENDING_TIME, - .release = sqa_target_release, - - .xmit_response = sqa_xmit_response, - .rdy_to_xfer = sqa_rdy_to_xfer, - - .on_free_cmd = sqa_on_free_cmd, - .task_mgmt_fn_done = sqa_task_mgmt_fn_done, - .close_session = sqa_close_session, - - .get_initiator_port_transport_id = sqa_get_initiator_port_transport_id, - .get_scsi_transport_version = sqa_get_scsi_transport_version, - .get_phys_transport_version = sqa_get_phys_transport_version, - .on_hw_pending_cmd_timeout = sqa_on_hw_pending_cmd_timeout, - .enable_target = sqa_enable_tgt, - .is_target_enabled = sqa_is_tgt_enabled, - .add_target = sqa_add_vtarget, - .del_target = sqa_del_vtarget, - .add_target_parameters = "node_name, parent_host", - .tgtt_attrs = sqa_attrs, - .tgt_attrs = sqa_tgt_attrs, -#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) - .default_trace_flags = SQA_DEFAULT_LOG_FLAGS, - .trace_flags = &trace_flag, -#endif -}; - #if QLA_ENABLE_PI static const int qla_tgt_supported_dif_block_size[]= { @@ -491,32 +404,6 @@ static struct qla_tgt_cmd *sqa_qla2xxx_get_cmd(struct fc_port *sess) return cmd; } -/* - * The following structure defines the callbacks which will be executed - * from functions in the qla_target.c file back to this interface - * driver. - */ -static struct qla_tgt_func_tmpl sqa_qla2xxx_template = { - .handle_cmd = sqa_qla2xxx_handle_cmd, - .handle_data = sqa_qla2xxx_handle_data, - .handle_tmr = sqa_qla2xxx_handle_tmr, - .get_cmd = sqa_qla2xxx_get_cmd, - .free_cmd = sqa_qla2xxx_free_cmd, - .free_mcmd = sqa_qla2xxx_free_mcmd, - .free_session = sqa_qla2xxx_free_session, - .update_sess = sqa_qla2xxx_update_sess, - .check_initiator_node_acl = sqa_qla2xxx_check_initiator_node_acl, - .find_sess_by_s_id = sqa_qla2xxx_find_sess_by_s_id, - .find_sess_by_loop_id = sqa_qla2xxx_find_sess_by_loop_id, - .clear_nacl_from_fcport_map = sqa_qla2xxx_clear_nacl_from_fcport_map, - .put_sess = sqa_qla2xxx_put_sess, - .shutdown_sess = sqa_qla2xxx_shutdown_sess, - .get_dif_tags = sqa_qla2xxx_dif_tags, - .chk_dif_tags = sqa_qla2xxx_chk_dif_tags, - .add_target = sqa_qla2xxx_add_target, - .remove_target = sqa_qla2xxx_remove_target, -}; - static DEFINE_MUTEX(sqa_mutex); @@ -862,11 +749,11 @@ static void sqa_qla2xxx_free_session(struct fc_port *fcport) wwn_to_str(fcport->port_name)); } - scst_unregister_session(scst_sess, 1, sqa_free_session_done); - { DECLARE_COMPLETION_ONSTACK(c); + fcport->unreg_done = &c; + scst_unregister_session(scst_sess, 1, sqa_free_session_done); wait_for_completion(&c); } @@ -1041,7 +928,6 @@ static void sqa_qla2xxx_put_sess(struct fc_port *sess) { TRACE_ENTRY(); - assert_spin_locked(&sess->vha->hw->tgt.sess_lock); kref_put(&sess->sess_kref, sqa_qla2xxx_release_sess); TRACE_EXIT(); @@ -1358,26 +1244,12 @@ static ssize_t sqa_abort_isp_store(struct kobject *kobj, static int sqa_get_target_name(uint8_t *wwn, char **ppwwn_name) { - const int wwn_len = 3*WWN_SIZE+2; - int res = 0; - char *name; + *ppwwn_name = kasprintf(GFP_KERNEL, + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + wwn[0], wwn[1], wwn[2], wwn[3], + wwn[4], wwn[5], wwn[6], wwn[7]); - name = kmalloc(wwn_len, GFP_KERNEL); - if (name == NULL) { - PRINT_ERROR("sqatgt: Allocation of tgt wwn name (size %d) " - "failed", wwn_len); - res = -ENOMEM; - goto out; - } - - sprintf(name, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", - wwn[0], wwn[1], wwn[2], wwn[3], - wwn[4], wwn[5], wwn[6], wwn[7]); - - *ppwwn_name = name; - -out: - return res; + return *ppwwn_name ? 0 : -ENOMEM; } static int sqa_parse_wwn(const char *ns, u64 *nm) @@ -1414,10 +1286,64 @@ static int sqa_parse_wwn(const char *ns, u64 *nm) return 0; } +/* + * The following structure definition provides descriptive parameeters + * and callbacks which will be used by the SCST target core to + * communicate with this target interface driver. + */ +static struct scst_tgt_template sqa_scst_template = { + .name = "qla2x00t", + .sg_tablesize = 0, + .use_clustering = 1, +#ifdef CONFIG_QLA_TGT_DEBUG_WORK_IN_THREAD + .xmit_response_atomic = 0, + .rdy_to_xfer_atomic = 0, +#else + .xmit_response_atomic = 1, + .rdy_to_xfer_atomic = 1, +#endif + +#if QLA_ENABLE_PI +/* diff cap for individual adapter is set during sqa_qla2xxx_add_target */ + .dif_supported = 0, + .hw_dif_type1_supported = 0, + .hw_dif_type2_supported = 0, + .hw_dif_type3_supported = 0, + .hw_dif_ip_supported = 0, + .hw_dif_same_sg_layout_required = 0, +#endif + + .max_hw_pending_time = SQA_MAX_HW_PENDING_TIME, + .release = sqa_target_release, + + .xmit_response = sqa_xmit_response, + .rdy_to_xfer = sqa_rdy_to_xfer, + + .on_free_cmd = sqa_on_free_cmd, + .task_mgmt_fn_done = sqa_task_mgmt_fn_done, + .close_session = sqa_close_session, + + .get_initiator_port_transport_id = sqa_get_initiator_port_transport_id, + .get_scsi_transport_version = sqa_get_scsi_transport_version, + .get_phys_transport_version = sqa_get_phys_transport_version, + .on_hw_pending_cmd_timeout = sqa_on_hw_pending_cmd_timeout, + .enable_target = sqa_enable_tgt, + .is_target_enabled = sqa_is_tgt_enabled, + .add_target = sqa_add_vtarget, + .del_target = sqa_del_vtarget, + .add_target_parameters = "node_name, parent_host", + .tgtt_attrs = sqa_attrs, + .tgt_attrs = sqa_tgt_attrs, +#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING) + .default_trace_flags = SQA_DEFAULT_LOG_FLAGS, + .trace_flags = &trace_flag, +#endif +}; + /* call must hold sqa_mutex */ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) { - char *pwwn; + char *pwwn = NULL; int res; struct scst_tgt *scst_tgt; struct sqa_scst_tgt *sqa_tgt; @@ -1435,7 +1361,6 @@ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) if (!sqa_tgt) { PRINT_ERROR("sqatgt(%ld/%d): alloc sqa_tgt failed", vha->host_no, vha->vp_idx); - kfree(pwwn); res = -ENOMEM; goto done; } @@ -1444,7 +1369,6 @@ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) if (!sqa_tgt->tgt_cmd_map) { PRINT_ERROR("sqatgt(%ld/%d): alloc tgt_cmd_map failed", vha->host_no, vha->vp_idx); - kfree(pwwn); kfree(sqa_tgt); res = -ENOMEM; goto done; @@ -1465,7 +1389,6 @@ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) pr_err("Unable to init se_sess->tgt_tag_pool," " tag_num: %u\n", tag_num); kvfree(sqa_tgt->tgt_cmd_map); - kfree(pwwn); kfree(sqa_tgt); goto done; } @@ -1478,7 +1401,6 @@ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) PRINT_ERROR("sqatgt(%ld/%d): SCST target registration failed.", vha->host_no, vha->vp_idx); res = -ENOMEM; - kfree(pwwn); kfree(sqa_tgt); goto done; } @@ -1491,7 +1413,6 @@ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) scst_tgt_set_hw_dif_type3_supported(scst_tgt, true); } #endif - kfree(pwwn); INIT_LIST_HEAD(&sqa_tgt->list); sqa_tgt->scst_tgt = scst_tgt; sqa_tgt->qla_tgt = vha->vha_tgt.qla_tgt; @@ -1525,7 +1446,8 @@ static int sqa_init_scst_tgt(struct scsi_qla_host *vha) TRACE(TRACE_MGMT, "sqatgt(%ld/%d): Registering target pwwn=%s " "scst_tgt %p sqa_tgt %p", vha->host_no, vha->vp_idx, pwwn, scst_tgt, sqa_tgt); - done: +done: + kfree(pwwn); return res; } @@ -1971,6 +1893,27 @@ static uint16_t sqa_get_phys_transport_version(struct scst_tgt *scst_tgt) return 0x0DA0; } +static int sqa_qla2xxx_chk_dif_tags(uint32_t tag) +{ + return tag & SCST_DIF_CHECK_REF_TAG; +} + +static int sqa_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd, + uint16_t *pfw_prot_opts) +{ + struct scst_cmd *scst_cmd = cmd->scst_cmd; + uint32_t t32=0; + + t32 = scst_get_dif_checks(scst_cmd->cmd_dif_actions); + if (!(t32 & SCST_DIF_CHECK_GUARD_TAG)) + *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK; + + if (!(t32 & SCST_DIF_CHECK_APP_TAG)) + *pfw_prot_opts |= PO_DIS_APP_TAG_VALD; + + return t32; +} + static void sqa_cleanup_hw_pending_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd) { @@ -2047,7 +1990,31 @@ out: return; } - +/* + * The following structure defines the callbacks which will be executed + * from functions in the qla_target.c file back to this interface + * driver. + */ +static struct qla_tgt_func_tmpl sqa_qla2xxx_template = { + .handle_cmd = sqa_qla2xxx_handle_cmd, + .handle_data = sqa_qla2xxx_handle_data, + .handle_tmr = sqa_qla2xxx_handle_tmr, + .get_cmd = sqa_qla2xxx_get_cmd, + .free_cmd = sqa_qla2xxx_free_cmd, + .free_mcmd = sqa_qla2xxx_free_mcmd, + .free_session = sqa_qla2xxx_free_session, + .update_sess = sqa_qla2xxx_update_sess, + .check_initiator_node_acl = sqa_qla2xxx_check_initiator_node_acl, + .find_sess_by_s_id = sqa_qla2xxx_find_sess_by_s_id, + .find_sess_by_loop_id = sqa_qla2xxx_find_sess_by_loop_id, + .clear_nacl_from_fcport_map = sqa_qla2xxx_clear_nacl_from_fcport_map, + .put_sess = sqa_qla2xxx_put_sess, + .shutdown_sess = sqa_qla2xxx_shutdown_sess, + .get_dif_tags = sqa_qla2xxx_dif_tags, + .chk_dif_tags = sqa_qla2xxx_chk_dif_tags, + .add_target = sqa_qla2xxx_add_target, + .remove_target = sqa_qla2xxx_remove_target, +}; static int sqa_lport_callback(struct scsi_qla_host *vha, void* target_lport_ptr, u64 npiv_wwpn, u64 npiv_wwnn) @@ -2311,29 +2278,6 @@ static void __exit sqa_exit(void) return; } -static int -sqa_qla2xxx_chk_dif_tags(uint32_t tag) -{ - return tag & SCST_DIF_CHECK_REF_TAG; -} - -static int -sqa_qla2xxx_dif_tags(struct qla_tgt_cmd *cmd, uint16_t *pfw_prot_opts) -{ - struct scst_cmd *scst_cmd = cmd->scst_cmd; - uint32_t t32=0; - - t32 = scst_get_dif_checks(scst_cmd->cmd_dif_actions); - if (!(t32 & SCST_DIF_CHECK_GUARD_TAG)) - *pfw_prot_opts |= PO_DISABLE_GUARD_CHECK; - - if (!(t32 & SCST_DIF_CHECK_APP_TAG)) - *pfw_prot_opts |= PO_DIS_APP_TAG_VALD; - - return t32; -} - - #ifdef MODULE module_init(sqa_init); module_exit(sqa_exit); diff --git a/qla2x00t-32gbit/qla_def.h b/qla2x00t-32gbit/qla_def.h index 0f984b3fb..b396d2dfe 100644 --- a/qla2x00t-32gbit/qla_def.h +++ b/qla2x00t-32gbit/qla_def.h @@ -2393,7 +2393,6 @@ typedef struct fc_port { #define NVME_FLAG_RESETTING 1 struct fc_port *conflict; - unsigned char logout_completed; int generation; struct se_session *se_sess; @@ -2401,8 +2400,9 @@ typedef struct fc_port { struct qla_tgt *tgt; unsigned long expires; struct list_head del_list_entry; - struct work_struct free_work; struct work_struct reg_work; + struct work_struct post_logout_work; + struct work_struct finish_logout_work; uint64_t jiffies_at_registration; struct qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; struct completion *unreg_done; diff --git a/qla2x00t-32gbit/qla_init.c b/qla2x00t-32gbit/qla_init.c index d020aa2ae..cb1fde02d 100644 --- a/qla2x00t-32gbit/qla_init.c +++ b/qla2x00t-32gbit/qla_init.c @@ -224,7 +224,6 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport, goto done; fcport->flags |= FCF_ASYNC_SENT; - fcport->logout_completed = 0; fcport->disc_state = DSC_LOGIN_PEND; sp->type = SRB_LOGIN_CMD; @@ -1065,7 +1064,6 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport) return rval; fcport->flags |= FCF_ASYNC_SENT; - fcport->logout_completed = 0; sp->type = SRB_PRLI_CMD; sp->name = "prli"; @@ -4724,6 +4722,8 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags) INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn); INIT_WORK(&fcport->reg_work, qla_register_fcport_fn); + INIT_WORK(&fcport->post_logout_work, qlt_post_logout); + INIT_WORK(&fcport->finish_logout_work, qlt_finish_logout); INIT_LIST_HEAD(&fcport->gnl_entry); INIT_LIST_HEAD(&fcport->list); diff --git a/qla2x00t-32gbit/qla_nvme.c b/qla2x00t-32gbit/qla_nvme.c index 56e0d777f..21af641b0 100644 --- a/qla2x00t-32gbit/qla_nvme.c +++ b/qla2x00t-32gbit/qla_nvme.c @@ -142,11 +142,8 @@ static void qla_nvme_sp_ls_done(void *ptr, int res) struct nvmefc_ls_req *fd; struct nvme_private *priv; - if (atomic_read(&sp->ref_count) == 0) { - ql_log(ql_log_warn, sp->fcport->vha, 0x2123, - "SP reference-count to ZERO on LS_done -- sp=%p.\n", sp); + if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - } if (!atomic_dec_and_test(&sp->ref_count)) return; @@ -564,10 +561,8 @@ static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport) } complete(&fcport->nvme_del_done); - if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) { - INIT_WORK(&fcport->free_work, qlt_free_session_done); - schedule_work(&fcport->free_work); - } + if (!test_bit(UNLOADING, &fcport->vha->dpc_flags)) + schedule_work(&fcport->post_logout_work); fcport->nvme_flag &= ~NVME_FLAG_DELETING; ql_log(ql_log_info, fcport->vha, 0x2110, diff --git a/qla2x00t-32gbit/qla_os.c b/qla2x00t-32gbit/qla_os.c index 2a3f71c3f..7f0cfb78d 100644 --- a/qla2x00t-32gbit/qla_os.c +++ b/qla2x00t-32gbit/qla_os.c @@ -807,14 +807,9 @@ qla2x00_sp_compl(void *ptr, int res) cmd->result = res; - if (atomic_read(&sp->ref_count) == 0) { - ql_dbg(ql_dbg_io, sp->vha, 0x3015, - "SP reference-count to ZERO -- sp=%p cmd=%p.\n", - sp, GET_CMD_SP(sp)); - if (ql2xextended_error_logging & ql_dbg_io) - WARN_ON(atomic_read(&sp->ref_count) == 0); + if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - } + if (!atomic_dec_and_test(&sp->ref_count)) return; @@ -916,14 +911,9 @@ qla2xxx_qpair_sp_compl(void *ptr, int res) cmd->result = res; - if (atomic_read(&sp->ref_count) == 0) { - ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3079, - "SP reference-count to ZERO -- sp=%p cmd=%p.\n", - sp, GET_CMD_SP(sp)); - if (ql2xextended_error_logging & ql_dbg_io) - WARN_ON(atomic_read(&sp->ref_count) == 0); + if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - } + if (!atomic_dec_and_test(&sp->ref_count)) return; @@ -5140,8 +5130,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) "%s %s mem alloc fail.\n", __func__, wwn_to_str(e->u.new_sess.port_name)); - if (pla) + if (pla) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } return; } @@ -5251,8 +5243,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e) if (free_fcport) { qla2x00_free_fcport(fcport); - if (pla) + if (pla) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } } } diff --git a/qla2x00t-32gbit/qla_target.c b/qla2x00t-32gbit/qla_target.c index f0d00c864..d6331a5e6 100644 --- a/qla2x00t-32gbit/qla_target.c +++ b/qla2x00t-32gbit/qla_target.c @@ -692,23 +692,21 @@ done: void qla24xx_do_nack_work(struct scsi_qla_host *vha, struct qla_work_evt *e) { fc_port_t *t; - unsigned long flags; switch (e->u.nack.type) { case SRB_NACK_PRLI: t = e->u.nack.fcport; flush_work(&t->del_work); - flush_work(&t->free_work); + flush_work(&t->post_logout_work); + flush_work(&t->finish_logout_work); mutex_lock(&vha->vha_tgt.tgt_mutex); t = qlt_create_sess(vha, e->u.nack.fcport, 0); mutex_unlock(&vha->vha_tgt.tgt_mutex); if (t) { ql_log(ql_log_info, vha, 0xd034, "%s create sess success %p", __func__, t); - spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags); /* create sess has an extra kref */ vha->hw->tgt.tgt_ops->put_sess(e->u.nack.fcport); - spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags); } break; } @@ -720,9 +718,6 @@ void qla24xx_delete_sess_fn(struct work_struct *work) { fc_port_t *fcport = container_of(work, struct fc_port, del_work); struct qla_hw_data *ha = fcport->vha->hw; - unsigned long flags; - - spin_lock_irqsave(&ha->tgt.sess_lock, flags); if (fcport->se_sess) { ha->tgt.tgt_ops->shutdown_sess(fcport); @@ -730,7 +725,6 @@ void qla24xx_delete_sess_fn(struct work_struct *work) } else { qlt_unreg_sess(fcport); } - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); } /* @@ -798,8 +792,9 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport) vha->vp_idx, wwn_to_str(fcport->port_name), sess->loop_id); sess->local = 0; } - ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + + ha->tgt.tgt_ops->put_sess(sess); } /* @@ -813,6 +808,8 @@ qlt_plogi_ack_find_add(struct scsi_qla_host *vha, port_id_t *id, { struct qlt_plogi_ack_t *pla; + lockdep_assert_held(&vha->hw->hardware_lock); + list_for_each_entry(pla, &vha->plogi_ack_list, list) { if (pla->id.b24 == id->b24) { ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x210d, @@ -969,16 +966,13 @@ qlt_send_first_logo(struct scsi_qla_host *vha, qlt_port_logo_t *logo) logo->cmd_count, res); } -void qlt_free_session_done(struct work_struct *work) +void qlt_post_logout(struct work_struct *work) { struct fc_port *sess = container_of(work, struct fc_port, - free_work); - struct qla_tgt *tgt = sess->tgt; + post_logout_work); struct scsi_qla_host *vha = sess->vha; struct qla_hw_data *ha = vha->hw; - unsigned long flags; bool logout_started = false; - scsi_qla_host_t *base_vha; struct qlt_plogi_ack_t *own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; @@ -1036,22 +1030,19 @@ void qlt_free_session_done(struct work_struct *work) if (sess->se_sess != NULL) ha->tgt.tgt_ops->free_session(sess); - if (logout_started) { - bool traced = false; + if (!logout_started) + qlt_finish_logout(&sess->finish_logout_work); +} - while (!READ_ONCE(sess->logout_completed)) { - if (!traced) { - ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086, - "%s: waiting for sess %p logout\n", - __func__, sess); - traced = true; - } - msleep(100); - } - - ql_dbg(ql_dbg_disc, vha, 0xf087, - "%s: sess %p logout completed\n", __func__, sess); - } +void qlt_finish_logout(struct work_struct *work) +{ + struct fc_port *sess = container_of(work, struct fc_port, + finish_logout_work); + struct qla_tgt *tgt = sess->tgt; + struct scsi_qla_host *vha = sess->vha; + struct qla_hw_data *ha = vha->hw; + scsi_qla_host_t *base_vha; + unsigned long flags; if (sess->logo_ack_needed) { sess->logo_ack_needed = 0; @@ -1088,7 +1079,8 @@ void qlt_free_session_done(struct work_struct *work) struct qlt_plogi_ack_t *con = sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]; struct imm_ntfy_from_isp *iocb; - own = sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; + struct qlt_plogi_ack_t *own = + sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN]; if (con) { iocb = &con->iocb; @@ -1186,8 +1178,7 @@ void qlt_unreg_sess(struct fc_port *sess) sess->nvme_flag |= NVME_FLAG_DELETING; schedule_work(&sess->nvme_del_work); } else { - INIT_WORK(&sess->free_work, qlt_free_session_done); - schedule_work(&sess->free_work); + schedule_work(&sess->post_logout_work); } } EXPORT_SYMBOL(qlt_unreg_sess); @@ -1395,7 +1386,6 @@ static struct fc_port *qlt_create_sess( */ sess->logout_on_delete = 1; sess->keep_nport_handle = 0; - sess->logout_completed = 0; if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, &fcport->port_name[0], sess) < 0) { @@ -4292,9 +4282,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) /* * Drop extra session reference from qla_tgt_handle_cmd_for_atio*( */ - spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); return; out_term: @@ -4311,9 +4299,7 @@ out_term: cmd->rel_cmd(cmd); spin_unlock_irqrestore(qpair->qp_lock_ptr, flags); - spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); } static void qlt_do_work(struct work_struct *work) @@ -4518,9 +4504,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, if (!cmd) { ql_dbg(ql_dbg_io, vha, 0x3062, "qla_target(%d): Allocation of cmd failed\n", vha->vp_idx); - spin_lock_irqsave(&ha->tgt.sess_lock, flags); ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); return -EBUSY; } @@ -4734,7 +4718,7 @@ void qlt_logo_completion_handler(fc_port_t *fcport, int rc) fcport->d_id.b.al_pa, rc); } - fcport->logout_completed = 1; + schedule_work(&fcport->finish_logout_work); } /* @@ -4864,6 +4848,8 @@ static int qlt_handle_login(struct scsi_qla_host *vha, struct qlt_plogi_ack_t *pla; unsigned long flags; + lockdep_assert_held(&vha->hw->hardware_lock); + wwn = wwn_to_u64(iocb->u.isp24.port_name); port_id.b.domain = iocb->u.isp24.port_id[2]; @@ -4947,8 +4933,10 @@ static int qlt_handle_login(struct scsi_qla_host *vha, __func__, wwn_to_str(sess->port_name), sec); } - if (!conflict_sess) + if (!conflict_sess) { + list_del(&pla->list); kmem_cache_free(qla_tgt_plogi_cachep, pla); + } qlt_send_term_imm_notif(vha, iocb, 1); goto out; @@ -5036,6 +5024,8 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, int res = 0; unsigned long flags; + lockdep_assert_held(&ha->hardware_lock); + wwn = wwn_to_u64(iocb->u.isp24.port_name); port_id.b.domain = iocb->u.isp24.port_id[2]; @@ -5311,6 +5301,8 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha, int send_notify_ack = 1; uint16_t status; + lockdep_assert_held(&ha->hardware_lock); + status = le16_to_cpu(iocb->u.isp2x.status); switch (status) { case IMM_NTFY_LIP_RESET: @@ -6371,17 +6363,19 @@ static void qlt_abort_work(struct qla_tgt *tgt, } rc = __qlt_24xx_handle_abts(vha, &prm->abts, sess); - ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); + ha->tgt.tgt_ops->put_sess(sess); + if (rc != 0) goto out_term; return; out_term2: + spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); + if (sess) ha->tgt.tgt_ops->put_sess(sess); - spin_unlock_irqrestore(&ha->tgt.sess_lock, flags2); out_term: spin_lock_irqsave(&ha->hardware_lock, flags); @@ -6439,9 +6433,10 @@ static void qlt_tmr_work(struct qla_tgt *tgt, scsilun_to_int((struct scsi_lun *)&a->u.isp24.fcp_cmnd.lun); rc = qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0); - ha->tgt.tgt_ops->put_sess(sess); spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); + ha->tgt.tgt_ops->put_sess(sess); + if (rc != 0) goto out_term; return; diff --git a/qla2x00t-32gbit/qla_target.h b/qla2x00t-32gbit/qla_target.h index 1e8715a7a..fc38fb88c 100644 --- a/qla2x00t-32gbit/qla_target.h +++ b/qla2x00t-32gbit/qla_target.h @@ -1069,7 +1069,9 @@ 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); -extern void qlt_free_session_done(struct work_struct *); +extern void qlt_post_logout(struct work_struct *); +extern void qlt_finish_logout(struct work_struct *work); + /* * This macro is used during early initializations when host->active_mode * is not set. Right now, ha value is ignored. diff --git a/qla2x00t/qla_os.c b/qla2x00t/qla_os.c index 5f8bad65f..6465fdb59 100644 --- a/qla2x00t/qla_os.c +++ b/qla2x00t/qla_os.c @@ -679,14 +679,9 @@ qla2x00_sp_compl(void *data, void *ptr, int res) cmd->result = res; - if (atomic_read(&sp->ref_count) == 0) { - ql_dbg(ql_dbg_io, sp->fcport->vha, 0x3015, - "SP reference-count to ZERO -- sp=%p cmd=%p.\n", - sp, GET_CMD_SP(sp)); - if (ql2xextended_error_logging & ql_dbg_io) - BUG(); + if (WARN_ON(atomic_read(&sp->ref_count) == 0)) return; - } + if (!atomic_dec_and_test(&sp->ref_count)) return;