diff options
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.c | 55 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/qla_target.h | 59 | ||||
-rw-r--r-- | drivers/scsi/qla2xxx/tcm_qla2xxx.c | 73 |
3 files changed, 142 insertions, 45 deletions
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 2c71305d2563..74eb776d2faa 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c | |||
@@ -105,7 +105,7 @@ static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt); | |||
105 | static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, | 105 | static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun, |
106 | int fn, void *iocb, int flags); | 106 | int fn, void *iocb, int flags); |
107 | static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd | 107 | static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd |
108 | *cmd, struct atio_from_isp *atio, int ha_locked); | 108 | *cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort); |
109 | static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha, | 109 | static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha, |
110 | struct qla_tgt_srr_imm *imm, int ha_lock); | 110 | struct qla_tgt_srr_imm *imm, int ha_lock); |
111 | static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, | 111 | static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, |
@@ -2665,7 +2665,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type, | |||
2665 | /* no need to terminate. FW already freed exchange. */ | 2665 | /* no need to terminate. FW already freed exchange. */ |
2666 | qlt_abort_cmd_on_host_reset(cmd->vha, cmd); | 2666 | qlt_abort_cmd_on_host_reset(cmd->vha, cmd); |
2667 | else | 2667 | else |
2668 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); | 2668 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); |
2669 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 2669 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
2670 | return 0; | 2670 | return 0; |
2671 | } | 2671 | } |
@@ -3173,7 +3173,8 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha, | |||
3173 | } | 3173 | } |
3174 | 3174 | ||
3175 | static void qlt_send_term_exchange(struct scsi_qla_host *vha, | 3175 | static void qlt_send_term_exchange(struct scsi_qla_host *vha, |
3176 | struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked) | 3176 | struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked, |
3177 | int ul_abort) | ||
3177 | { | 3178 | { |
3178 | unsigned long flags = 0; | 3179 | unsigned long flags = 0; |
3179 | int rc; | 3180 | int rc; |
@@ -3193,8 +3194,7 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha, | |||
3193 | qlt_alloc_qfull_cmd(vha, atio, 0, 0); | 3194 | qlt_alloc_qfull_cmd(vha, atio, 0, 0); |
3194 | 3195 | ||
3195 | done: | 3196 | done: |
3196 | if (cmd && (!cmd->aborted || | 3197 | if (cmd && !ul_abort && !cmd->aborted) { |
3197 | !cmd->cmd_sent_to_fw)) { | ||
3198 | if (cmd->sg_mapped) | 3198 | if (cmd->sg_mapped) |
3199 | qlt_unmap_sg(vha, cmd); | 3199 | qlt_unmap_sg(vha, cmd); |
3200 | vha->hw->tgt.tgt_ops->free_cmd(cmd); | 3200 | vha->hw->tgt.tgt_ops->free_cmd(cmd); |
@@ -3253,21 +3253,38 @@ static void qlt_chk_exch_leak_thresh_hold(struct scsi_qla_host *vha) | |||
3253 | 3253 | ||
3254 | } | 3254 | } |
3255 | 3255 | ||
3256 | void qlt_abort_cmd(struct qla_tgt_cmd *cmd) | 3256 | int qlt_abort_cmd(struct qla_tgt_cmd *cmd) |
3257 | { | 3257 | { |
3258 | struct qla_tgt *tgt = cmd->tgt; | 3258 | struct qla_tgt *tgt = cmd->tgt; |
3259 | struct scsi_qla_host *vha = tgt->vha; | 3259 | struct scsi_qla_host *vha = tgt->vha; |
3260 | struct se_cmd *se_cmd = &cmd->se_cmd; | 3260 | struct se_cmd *se_cmd = &cmd->se_cmd; |
3261 | unsigned long flags; | ||
3261 | 3262 | ||
3262 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, | 3263 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014, |
3263 | "qla_target(%d): terminating exchange for aborted cmd=%p " | 3264 | "qla_target(%d): terminating exchange for aborted cmd=%p " |
3264 | "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd, | 3265 | "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd, |
3265 | se_cmd->tag); | 3266 | se_cmd->tag); |
3266 | 3267 | ||
3268 | spin_lock_irqsave(&cmd->cmd_lock, flags); | ||
3269 | if (cmd->aborted) { | ||
3270 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); | ||
3271 | /* | ||
3272 | * It's normal to see 2 calls in this path: | ||
3273 | * 1) XFER Rdy completion + CMD_T_ABORT | ||
3274 | * 2) TCM TMR - drain_state_list | ||
3275 | */ | ||
3276 | ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff, | ||
3277 | "multiple abort. %p transport_state %x, t_state %x," | ||
3278 | " se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state, | ||
3279 | cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags); | ||
3280 | return EIO; | ||
3281 | } | ||
3267 | cmd->aborted = 1; | 3282 | cmd->aborted = 1; |
3268 | cmd->cmd_flags |= BIT_6; | 3283 | cmd->cmd_flags |= BIT_6; |
3284 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); | ||
3269 | 3285 | ||
3270 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 0); | 3286 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1); |
3287 | return 0; | ||
3271 | } | 3288 | } |
3272 | EXPORT_SYMBOL(qlt_abort_cmd); | 3289 | EXPORT_SYMBOL(qlt_abort_cmd); |
3273 | 3290 | ||
@@ -3282,6 +3299,9 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd) | |||
3282 | 3299 | ||
3283 | BUG_ON(cmd->cmd_in_wq); | 3300 | BUG_ON(cmd->cmd_in_wq); |
3284 | 3301 | ||
3302 | if (cmd->sg_mapped) | ||
3303 | qlt_unmap_sg(cmd->vha, cmd); | ||
3304 | |||
3285 | if (!cmd->q_full) | 3305 | if (!cmd->q_full) |
3286 | qlt_decr_num_pend_cmds(cmd->vha); | 3306 | qlt_decr_num_pend_cmds(cmd->vha); |
3287 | 3307 | ||
@@ -3399,7 +3419,7 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio, | |||
3399 | term = 1; | 3419 | term = 1; |
3400 | 3420 | ||
3401 | if (term) | 3421 | if (term) |
3402 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); | 3422 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); |
3403 | 3423 | ||
3404 | return term; | 3424 | return term; |
3405 | } | 3425 | } |
@@ -3755,6 +3775,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd) | |||
3755 | goto out_term; | 3775 | goto out_term; |
3756 | } | 3776 | } |
3757 | 3777 | ||
3778 | spin_lock_init(&cmd->cmd_lock); | ||
3758 | cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; | 3779 | cdb = &atio->u.isp24.fcp_cmnd.cdb[0]; |
3759 | cmd->se_cmd.tag = atio->u.isp24.exchange_addr; | 3780 | cmd->se_cmd.tag = atio->u.isp24.exchange_addr; |
3760 | cmd->unpacked_lun = scsilun_to_int( | 3781 | cmd->unpacked_lun = scsilun_to_int( |
@@ -3797,7 +3818,7 @@ out_term: | |||
3797 | */ | 3818 | */ |
3798 | cmd->cmd_flags |= BIT_2; | 3819 | cmd->cmd_flags |= BIT_2; |
3799 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3820 | spin_lock_irqsave(&ha->hardware_lock, flags); |
3800 | qlt_send_term_exchange(vha, NULL, &cmd->atio, 1); | 3821 | qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0); |
3801 | 3822 | ||
3802 | qlt_decr_num_pend_cmds(vha); | 3823 | qlt_decr_num_pend_cmds(vha); |
3803 | percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); | 3824 | percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag); |
@@ -3919,7 +3940,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work) | |||
3919 | 3940 | ||
3920 | out_term: | 3941 | out_term: |
3921 | spin_lock_irqsave(&ha->hardware_lock, flags); | 3942 | spin_lock_irqsave(&ha->hardware_lock, flags); |
3922 | qlt_send_term_exchange(vha, NULL, &op->atio, 1); | 3943 | qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0); |
3923 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 3944 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
3924 | kfree(op); | 3945 | kfree(op); |
3925 | 3946 | ||
@@ -4772,7 +4793,7 @@ out_reject: | |||
4772 | dump_stack(); | 4793 | dump_stack(); |
4773 | } else { | 4794 | } else { |
4774 | cmd->cmd_flags |= BIT_9; | 4795 | cmd->cmd_flags |= BIT_9; |
4775 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1); | 4796 | qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0); |
4776 | } | 4797 | } |
4777 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 4798 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
4778 | } | 4799 | } |
@@ -4951,7 +4972,7 @@ static void qlt_prepare_srr_imm(struct scsi_qla_host *vha, | |||
4951 | sctio, sctio->srr_id); | 4972 | sctio, sctio->srr_id); |
4952 | list_del(&sctio->srr_list_entry); | 4973 | list_del(&sctio->srr_list_entry); |
4953 | qlt_send_term_exchange(vha, sctio->cmd, | 4974 | qlt_send_term_exchange(vha, sctio->cmd, |
4954 | &sctio->cmd->atio, 1); | 4975 | &sctio->cmd->atio, 1, 0); |
4955 | kfree(sctio); | 4976 | kfree(sctio); |
4956 | } | 4977 | } |
4957 | } | 4978 | } |
@@ -5124,7 +5145,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha, | |||
5124 | atio->u.isp24.fcp_hdr.s_id); | 5145 | atio->u.isp24.fcp_hdr.s_id); |
5125 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); | 5146 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); |
5126 | if (!sess) { | 5147 | if (!sess) { |
5127 | qlt_send_term_exchange(vha, NULL, atio, 1); | 5148 | qlt_send_term_exchange(vha, NULL, atio, 1, 0); |
5128 | return 0; | 5149 | return 0; |
5129 | } | 5150 | } |
5130 | /* Sending marker isn't necessary, since we called from ISR */ | 5151 | /* Sending marker isn't necessary, since we called from ISR */ |
@@ -5407,7 +5428,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha, | |||
5407 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ | 5428 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ |
5408 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); | 5429 | qlt_send_busy(vha, atio, SAM_STAT_BUSY); |
5409 | #else | 5430 | #else |
5410 | qlt_send_term_exchange(vha, NULL, atio, 1); | 5431 | qlt_send_term_exchange(vha, NULL, atio, 1, 0); |
5411 | #endif | 5432 | #endif |
5412 | 5433 | ||
5413 | if (!ha_locked) | 5434 | if (!ha_locked) |
@@ -5524,7 +5545,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) | |||
5524 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ | 5545 | #if 1 /* With TERM EXCHANGE some FC cards refuse to boot */ |
5525 | qlt_send_busy(vha, atio, 0); | 5546 | qlt_send_busy(vha, atio, 0); |
5526 | #else | 5547 | #else |
5527 | qlt_send_term_exchange(vha, NULL, atio, 1); | 5548 | qlt_send_term_exchange(vha, NULL, atio, 1, 0); |
5528 | #endif | 5549 | #endif |
5529 | } else { | 5550 | } else { |
5530 | if (tgt->tgt_stop) { | 5551 | if (tgt->tgt_stop) { |
@@ -5533,7 +5554,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt) | |||
5533 | "command to target, sending TERM " | 5554 | "command to target, sending TERM " |
5534 | "EXCHANGE for rsp\n"); | 5555 | "EXCHANGE for rsp\n"); |
5535 | qlt_send_term_exchange(vha, NULL, | 5556 | qlt_send_term_exchange(vha, NULL, |
5536 | atio, 1); | 5557 | atio, 1, 0); |
5537 | } else { | 5558 | } else { |
5538 | ql_dbg(ql_dbg_tgt, vha, 0xe060, | 5559 | ql_dbg(ql_dbg_tgt, vha, 0xe060, |
5539 | "qla_target(%d): Unable to send " | 5560 | "qla_target(%d): Unable to send " |
@@ -5961,7 +5982,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt, | |||
5961 | return; | 5982 | return; |
5962 | 5983 | ||
5963 | out_term: | 5984 | out_term: |
5964 | qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0); | 5985 | qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0); |
5965 | if (sess) | 5986 | if (sess) |
5966 | ha->tgt.tgt_ops->put_sess(sess); | 5987 | ha->tgt.tgt_ops->put_sess(sess); |
5967 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); | 5988 | spin_unlock_irqrestore(&ha->tgt.sess_lock, flags); |
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 71b2865ba3c8..22a6a767fe07 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h | |||
@@ -943,6 +943,36 @@ struct qla_tgt_sess { | |||
943 | qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; | 943 | qlt_plogi_ack_t *plogi_link[QLT_PLOGI_LINK_MAX]; |
944 | }; | 944 | }; |
945 | 945 | ||
946 | typedef enum { | ||
947 | /* | ||
948 | * BIT_0 - Atio Arrival / schedule to work | ||
949 | * BIT_1 - qlt_do_work | ||
950 | * BIT_2 - qlt_do work failed | ||
951 | * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending | ||
952 | * BIT_4 - read respond/tcm_qla2xx_queue_data_in | ||
953 | * BIT_5 - status respond / tcm_qla2xx_queue_status | ||
954 | * BIT_6 - tcm request to abort/Term exchange. | ||
955 | * pre_xmit_response->qlt_send_term_exchange | ||
956 | * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response) | ||
957 | * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer) | ||
958 | * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange) | ||
959 | * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data | ||
960 | |||
961 | * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd | ||
962 | * BIT_13 - Bad completion - | ||
963 | * qlt_ctio_do_completion --> qlt_term_ctio_exchange | ||
964 | * BIT_14 - Back end data received/sent. | ||
965 | * BIT_15 - SRR prepare ctio | ||
966 | * BIT_16 - complete free | ||
967 | * BIT_17 - flush - qlt_abort_cmd_on_host_reset | ||
968 | * BIT_18 - completion w/abort status | ||
969 | * BIT_19 - completion w/unknown status | ||
970 | * BIT_20 - tcm_qla2xxx_free_cmd | ||
971 | */ | ||
972 | CMD_FLAG_DATA_WORK = BIT_11, | ||
973 | CMD_FLAG_DATA_WORK_FREE = BIT_21, | ||
974 | } cmd_flags_t; | ||
975 | |||
946 | struct qla_tgt_cmd { | 976 | struct qla_tgt_cmd { |
947 | struct se_cmd se_cmd; | 977 | struct se_cmd se_cmd; |
948 | struct qla_tgt_sess *sess; | 978 | struct qla_tgt_sess *sess; |
@@ -952,6 +982,7 @@ struct qla_tgt_cmd { | |||
952 | /* Sense buffer that will be mapped into outgoing status */ | 982 | /* Sense buffer that will be mapped into outgoing status */ |
953 | unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; | 983 | unsigned char sense_buffer[TRANSPORT_SENSE_BUFFER]; |
954 | 984 | ||
985 | spinlock_t cmd_lock; | ||
955 | /* to save extra sess dereferences */ | 986 | /* to save extra sess dereferences */ |
956 | unsigned int conf_compl_supported:1; | 987 | unsigned int conf_compl_supported:1; |
957 | unsigned int sg_mapped:1; | 988 | unsigned int sg_mapped:1; |
@@ -986,30 +1017,8 @@ struct qla_tgt_cmd { | |||
986 | 1017 | ||
987 | uint64_t jiffies_at_alloc; | 1018 | uint64_t jiffies_at_alloc; |
988 | uint64_t jiffies_at_free; | 1019 | uint64_t jiffies_at_free; |
989 | /* BIT_0 - Atio Arrival / schedule to work | 1020 | |
990 | * BIT_1 - qlt_do_work | 1021 | cmd_flags_t cmd_flags; |
991 | * BIT_2 - qlt_do work failed | ||
992 | * BIT_3 - xfer rdy/tcm_qla2xxx_write_pending | ||
993 | * BIT_4 - read respond/tcm_qla2xx_queue_data_in | ||
994 | * BIT_5 - status respond / tcm_qla2xx_queue_status | ||
995 | * BIT_6 - tcm request to abort/Term exchange. | ||
996 | * pre_xmit_response->qlt_send_term_exchange | ||
997 | * BIT_7 - SRR received (qlt_handle_srr->qlt_xmit_response) | ||
998 | * BIT_8 - SRR received (qlt_handle_srr->qlt_rdy_to_xfer) | ||
999 | * BIT_9 - SRR received (qla_handle_srr->qlt_send_term_exchange) | ||
1000 | * BIT_10 - Data in - hanlde_data->tcm_qla2xxx_handle_data | ||
1001 | * BIT_11 - Data actually going to TCM : tcm_qla2xx_handle_data_work | ||
1002 | * BIT_12 - good completion - qlt_ctio_do_completion -->free_cmd | ||
1003 | * BIT_13 - Bad completion - | ||
1004 | * qlt_ctio_do_completion --> qlt_term_ctio_exchange | ||
1005 | * BIT_14 - Back end data received/sent. | ||
1006 | * BIT_15 - SRR prepare ctio | ||
1007 | * BIT_16 - complete free | ||
1008 | * BIT_17 - flush - qlt_abort_cmd_on_host_reset | ||
1009 | * BIT_18 - completion w/abort status | ||
1010 | * BIT_19 - completion w/unknown status | ||
1011 | */ | ||
1012 | uint32_t cmd_flags; | ||
1013 | }; | 1022 | }; |
1014 | 1023 | ||
1015 | struct qla_tgt_sess_work_param { | 1024 | struct qla_tgt_sess_work_param { |
@@ -1148,7 +1157,7 @@ static inline void sid_to_portid(const uint8_t *s_id, port_id_t *p) | |||
1148 | extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); | 1157 | extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *); |
1149 | extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); | 1158 | extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *); |
1150 | extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); | 1159 | extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t); |
1151 | extern void qlt_abort_cmd(struct qla_tgt_cmd *); | 1160 | extern int qlt_abort_cmd(struct qla_tgt_cmd *); |
1152 | extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); | 1161 | extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *); |
1153 | extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); | 1162 | extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *); |
1154 | extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); | 1163 | extern void qlt_free_cmd(struct qla_tgt_cmd *cmd); |
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index faf0a126627f..3eecdd1bc6fb 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c | |||
@@ -298,6 +298,10 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) | |||
298 | { | 298 | { |
299 | cmd->vha->tgt_counters.core_qla_free_cmd++; | 299 | cmd->vha->tgt_counters.core_qla_free_cmd++; |
300 | cmd->cmd_in_wq = 1; | 300 | cmd->cmd_in_wq = 1; |
301 | |||
302 | BUG_ON(cmd->cmd_flags & BIT_20); | ||
303 | cmd->cmd_flags |= BIT_20; | ||
304 | |||
301 | INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free); | 305 | INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free); |
302 | queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); | 306 | queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); |
303 | } | 307 | } |
@@ -374,6 +378,20 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd) | |||
374 | { | 378 | { |
375 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | 379 | struct qla_tgt_cmd *cmd = container_of(se_cmd, |
376 | struct qla_tgt_cmd, se_cmd); | 380 | struct qla_tgt_cmd, se_cmd); |
381 | |||
382 | if (cmd->aborted) { | ||
383 | /* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task | ||
384 | * can get ahead of this cmd. tcm_qla2xxx_aborted_task | ||
385 | * already kick start the free. | ||
386 | */ | ||
387 | pr_debug("write_pending aborted cmd[%p] refcount %d " | ||
388 | "transport_state %x, t_state %x, se_cmd_flags %x\n", | ||
389 | cmd,cmd->se_cmd.cmd_kref.refcount.counter, | ||
390 | cmd->se_cmd.transport_state, | ||
391 | cmd->se_cmd.t_state, | ||
392 | cmd->se_cmd.se_cmd_flags); | ||
393 | return 0; | ||
394 | } | ||
377 | cmd->cmd_flags |= BIT_3; | 395 | cmd->cmd_flags |= BIT_3; |
378 | cmd->bufflen = se_cmd->data_length; | 396 | cmd->bufflen = se_cmd->data_length; |
379 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); | 397 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); |
@@ -405,7 +423,7 @@ static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd) | |||
405 | se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { | 423 | se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) { |
406 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | 424 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
407 | wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, | 425 | wait_for_completion_timeout(&se_cmd->t_transport_stop_comp, |
408 | 3 * HZ); | 426 | 50); |
409 | return 0; | 427 | return 0; |
410 | } | 428 | } |
411 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); | 429 | spin_unlock_irqrestore(&se_cmd->t_state_lock, flags); |
@@ -465,13 +483,25 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd, | |||
465 | static void tcm_qla2xxx_handle_data_work(struct work_struct *work) | 483 | static void tcm_qla2xxx_handle_data_work(struct work_struct *work) |
466 | { | 484 | { |
467 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); | 485 | struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work); |
486 | unsigned long flags; | ||
468 | 487 | ||
469 | /* | 488 | /* |
470 | * Ensure that the complete FCP WRITE payload has been received. | 489 | * Ensure that the complete FCP WRITE payload has been received. |
471 | * Otherwise return an exception via CHECK_CONDITION status. | 490 | * Otherwise return an exception via CHECK_CONDITION status. |
472 | */ | 491 | */ |
473 | cmd->cmd_in_wq = 0; | 492 | cmd->cmd_in_wq = 0; |
474 | cmd->cmd_flags |= BIT_11; | 493 | |
494 | spin_lock_irqsave(&cmd->cmd_lock, flags); | ||
495 | cmd->cmd_flags |= CMD_FLAG_DATA_WORK; | ||
496 | if (cmd->aborted) { | ||
497 | cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE; | ||
498 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); | ||
499 | |||
500 | tcm_qla2xxx_free_cmd(cmd); | ||
501 | return; | ||
502 | } | ||
503 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); | ||
504 | |||
475 | cmd->vha->tgt_counters.qla_core_ret_ctio++; | 505 | cmd->vha->tgt_counters.qla_core_ret_ctio++; |
476 | if (!cmd->write_data_transferred) { | 506 | if (!cmd->write_data_transferred) { |
477 | /* | 507 | /* |
@@ -546,6 +576,20 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd) | |||
546 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | 576 | struct qla_tgt_cmd *cmd = container_of(se_cmd, |
547 | struct qla_tgt_cmd, se_cmd); | 577 | struct qla_tgt_cmd, se_cmd); |
548 | 578 | ||
579 | if (cmd->aborted) { | ||
580 | /* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task | ||
581 | * can get ahead of this cmd. tcm_qla2xxx_aborted_task | ||
582 | * already kick start the free. | ||
583 | */ | ||
584 | pr_debug("queue_data_in aborted cmd[%p] refcount %d " | ||
585 | "transport_state %x, t_state %x, se_cmd_flags %x\n", | ||
586 | cmd,cmd->se_cmd.cmd_kref.refcount.counter, | ||
587 | cmd->se_cmd.transport_state, | ||
588 | cmd->se_cmd.t_state, | ||
589 | cmd->se_cmd.se_cmd_flags); | ||
590 | return 0; | ||
591 | } | ||
592 | |||
549 | cmd->cmd_flags |= BIT_4; | 593 | cmd->cmd_flags |= BIT_4; |
550 | cmd->bufflen = se_cmd->data_length; | 594 | cmd->bufflen = se_cmd->data_length; |
551 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); | 595 | cmd->dma_data_direction = target_reverse_dma_direction(se_cmd); |
@@ -637,11 +681,34 @@ static void tcm_qla2xxx_queue_tm_rsp(struct se_cmd *se_cmd) | |||
637 | qlt_xmit_tm_rsp(mcmd); | 681 | qlt_xmit_tm_rsp(mcmd); |
638 | } | 682 | } |
639 | 683 | ||
684 | |||
685 | #define DATA_WORK_NOT_FREE(_flags) \ | ||
686 | (( _flags & (CMD_FLAG_DATA_WORK|CMD_FLAG_DATA_WORK_FREE)) == \ | ||
687 | CMD_FLAG_DATA_WORK) | ||
640 | static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) | 688 | static void tcm_qla2xxx_aborted_task(struct se_cmd *se_cmd) |
641 | { | 689 | { |
642 | struct qla_tgt_cmd *cmd = container_of(se_cmd, | 690 | struct qla_tgt_cmd *cmd = container_of(se_cmd, |
643 | struct qla_tgt_cmd, se_cmd); | 691 | struct qla_tgt_cmd, se_cmd); |
644 | qlt_abort_cmd(cmd); | 692 | unsigned long flags; |
693 | |||
694 | if (qlt_abort_cmd(cmd)) | ||
695 | return; | ||
696 | |||
697 | spin_lock_irqsave(&cmd->cmd_lock, flags); | ||
698 | if ((cmd->state == QLA_TGT_STATE_NEW)|| | ||
699 | ((cmd->state == QLA_TGT_STATE_DATA_IN) && | ||
700 | DATA_WORK_NOT_FREE(cmd->cmd_flags)) ) { | ||
701 | |||
702 | cmd->cmd_flags |= CMD_FLAG_DATA_WORK_FREE; | ||
703 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); | ||
704 | /* Cmd have not reached firmware. | ||
705 | * Use this trigger to free it. */ | ||
706 | tcm_qla2xxx_free_cmd(cmd); | ||
707 | return; | ||
708 | } | ||
709 | spin_unlock_irqrestore(&cmd->cmd_lock, flags); | ||
710 | return; | ||
711 | |||
645 | } | 712 | } |
646 | 713 | ||
647 | static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, | 714 | static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *, |