Commit 2f2e9f2d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull SCSI target fixes from Nicholas Bellinger:
 "This includes the long awaited series to address a set of bugs around
  active I/O remote-port LUN_RESET, as well as properly handling this
  same case with concurrent fabric driver session disconnect ->
  reconnect.

  Note this set of LUN_RESET bug-fixes has been surviving extended
  testing on both v4.5-rc1 and v3.14.y code over the last weeks, and is
  CC'ed for stable as it's something folks using multiple ESX connected
  hosts with slow backends can certainly trigger.

  The highlights also include:

   - Fix WRITE_SAME/DISCARD emulation 4k sector conversion in
     target/iblock (Mike Christie)

   - Fix TMR abort interaction and AIO type TMR response in qla2xxx
     target (Quinn Tran + Swapnil Nagle)

   - Fix >= v3.17 stale descriptor pointer regression in qla2xxx target
     (Quinn Tran)

   - Fix >= v4.5-rc1 return regression with unmap_zeros_data_store new
     configfs store handler (nab)

   - Add CPU affinity flag + convert qla2xxx to use bit (Quinn + HCH +
     Bart)"

* git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending:
  qla2xxx: use TARGET_SCF_USE_CPUID flag to indiate CPU Affinity
  target/transport: add flag to indicate CPU Affinity is observed
  target: Fix incorrect unmap_zeroes_data_store return
  qla2xxx: Use ATIO type to send correct tmr response
  qla2xxx: Fix stale pointer access.
  target/user: Fix cast from pointer to phys_addr_t
  target: Drop legacy se_cmd->task_stop_comp + REQUEST_STOP usage
  target: Fix race with SCF_SEND_DELAYED_TAS handling
  target: Fix remote-port TMR ABORT + se_cmd fabric stop
  target: Fix TAS handling for multi-session se_node_acls
  target: Fix LUN_RESET active TMR descriptor handling
  target: Fix LUN_RESET active I/O handling for ACK_KREF
  qla2xxx: Fix TMR ABORT interaction issue between qla2xxx and TCM
  qla2xxx: Fix warning reported by static checker
  target: Fix WRITE_SAME/DISCARD conversion to linux 512b sectors
parents 4617c220 5327c7db
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -2204,7 +2204,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
	/* Clear outstanding commands array. */
	for (que = 0; que < ha->max_req_queues; que++) {
		req = ha->req_q_map[que];
		if (!req)
		if (!req || !test_bit(que, ha->req_qid_map))
			continue;
		req->out_ptr = (void *)(req->ring + req->length);
		*req->out_ptr = 0;
@@ -2221,7 +2221,7 @@ qla2x00_init_rings(scsi_qla_host_t *vha)

	for (que = 0; que < ha->max_rsp_queues; que++) {
		rsp = ha->rsp_q_map[que];
		if (!rsp)
		if (!rsp || !test_bit(que, ha->rsp_qid_map))
			continue;
		rsp->in_ptr = (void *)(rsp->ring + rsp->length);
		*rsp->in_ptr = 0;
@@ -4981,7 +4981,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)

	for (i = 1; i < ha->max_rsp_queues; i++) {
		rsp = ha->rsp_q_map[i];
		if (rsp) {
		if (rsp && test_bit(i, ha->rsp_qid_map)) {
			rsp->options &= ~BIT_0;
			ret = qla25xx_init_rsp_que(base_vha, rsp);
			if (ret != QLA_SUCCESS)
@@ -4996,7 +4996,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
	}
	for (i = 1; i < ha->max_req_queues; i++) {
		req = ha->req_q_map[i];
		if (req) {
		if (req && test_bit(i, ha->req_qid_map)) {
			/* Clear outstanding commands array. */
			req->options &= ~BIT_0;
			ret = qla25xx_init_req_que(base_vha, req);
+2 −2
Original line number Diff line number Diff line
@@ -3063,9 +3063,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
		    "MSI-X: Failed to enable support "
		    "-- %d/%d\n Retry with %d vectors.\n",
		    ha->msix_count, ret, ret);
	}
		ha->msix_count = ret;
		ha->max_rsp_queues = ha->msix_count - 1;
	}
	ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
				ha->msix_count, GFP_KERNEL);
	if (!ha->msix_entries) {
+2 −2
Original line number Diff line number Diff line
@@ -600,7 +600,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
	/* Delete request queues */
	for (cnt = 1; cnt < ha->max_req_queues; cnt++) {
		req = ha->req_q_map[cnt];
		if (req) {
		if (req && test_bit(cnt, ha->req_qid_map)) {
			ret = qla25xx_delete_req_que(vha, req);
			if (ret != QLA_SUCCESS) {
				ql_log(ql_log_warn, vha, 0x00ea,
@@ -614,7 +614,7 @@ qla25xx_delete_queues(struct scsi_qla_host *vha)
	/* Delete response queues */
	for (cnt = 1; cnt < ha->max_rsp_queues; cnt++) {
		rsp = ha->rsp_q_map[cnt];
		if (rsp) {
		if (rsp && test_bit(cnt, ha->rsp_qid_map)) {
			ret = qla25xx_delete_rsp_que(vha, rsp);
			if (ret != QLA_SUCCESS) {
				ql_log(ql_log_warn, vha, 0x00eb,
+6 −0
Original line number Diff line number Diff line
@@ -409,6 +409,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
	int cnt;

	for (cnt = 0; cnt < ha->max_req_queues; cnt++) {
		if (!test_bit(cnt, ha->req_qid_map))
			continue;

		req = ha->req_q_map[cnt];
		qla2x00_free_req_que(ha, req);
	}
@@ -416,6 +419,9 @@ static void qla2x00_free_queues(struct qla_hw_data *ha)
	ha->req_q_map = NULL;

	for (cnt = 0; cnt < ha->max_rsp_queues; cnt++) {
		if (!test_bit(cnt, ha->rsp_qid_map))
			continue;

		rsp = ha->rsp_q_map[cnt];
		qla2x00_free_rsp_que(ha, rsp);
	}
+45 −23
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ static void qlt_response_pkt(struct scsi_qla_host *ha, response_t *pkt);
static int qlt_issue_task_mgmt(struct qla_tgt_sess *sess, uint32_t lun,
	int fn, void *iocb, int flags);
static void qlt_send_term_exchange(struct scsi_qla_host *ha, struct qla_tgt_cmd
	*cmd, struct atio_from_isp *atio, int ha_locked);
	*cmd, struct atio_from_isp *atio, int ha_locked, int ul_abort);
static void qlt_reject_free_srr_imm(struct scsi_qla_host *ha,
	struct qla_tgt_srr_imm *imm, int ha_lock);
static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
@@ -1756,7 +1756,7 @@ void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *mcmd)
		qlt_send_notify_ack(vha, &mcmd->orig_iocb.imm_ntfy,
		    0, 0, 0, 0, 0, 0);
	else {
		if (mcmd->se_cmd.se_tmr_req->function == TMR_ABORT_TASK)
		if (mcmd->orig_iocb.atio.u.raw.entry_type == ABTS_RECV_24XX)
			qlt_24xx_send_abts_resp(vha, &mcmd->orig_iocb.abts,
			    mcmd->fc_tm_rsp, false);
		else
@@ -2665,7 +2665,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
			/* no need to terminate. FW already freed exchange. */
			qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
		else
			qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
			qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
		spin_unlock_irqrestore(&ha->hardware_lock, flags);
		return 0;
	}
@@ -3173,7 +3173,8 @@ static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
}

static void qlt_send_term_exchange(struct scsi_qla_host *vha,
	struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked)
	struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked,
	int ul_abort)
{
	unsigned long flags = 0;
	int rc;
@@ -3193,8 +3194,7 @@ static void qlt_send_term_exchange(struct scsi_qla_host *vha,
		qlt_alloc_qfull_cmd(vha, atio, 0, 0);

done:
	if (cmd && (!cmd->aborted ||
	    !cmd->cmd_sent_to_fw)) {
	if (cmd && !ul_abort && !cmd->aborted) {
		if (cmd->sg_mapped)
			qlt_unmap_sg(vha, cmd);
		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)

}

void qlt_abort_cmd(struct qla_tgt_cmd *cmd)
int qlt_abort_cmd(struct qla_tgt_cmd *cmd)
{
	struct qla_tgt *tgt = cmd->tgt;
	struct scsi_qla_host *vha = tgt->vha;
	struct se_cmd *se_cmd = &cmd->se_cmd;
	unsigned long flags;

	ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
	    "qla_target(%d): terminating exchange for aborted cmd=%p "
	    "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
	    se_cmd->tag);

	spin_lock_irqsave(&cmd->cmd_lock, flags);
	if (cmd->aborted) {
		spin_unlock_irqrestore(&cmd->cmd_lock, flags);
		/*
		 * It's normal to see 2 calls in this path:
		 *  1) XFER Rdy completion + CMD_T_ABORT
		 *  2) TCM TMR - drain_state_list
		 */
	        ql_dbg(ql_dbg_tgt_mgt, vha, 0xffff,
			"multiple abort. %p transport_state %x, t_state %x,"
			" se_cmd_flags %x \n", cmd, cmd->se_cmd.transport_state,
			cmd->se_cmd.t_state,cmd->se_cmd.se_cmd_flags);
		return EIO;
	}
	cmd->aborted = 1;
	cmd->cmd_flags |= BIT_6;
	spin_unlock_irqrestore(&cmd->cmd_lock, flags);

	qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
	qlt_send_term_exchange(vha, cmd, &cmd->atio, 0, 1);
	return 0;
}
EXPORT_SYMBOL(qlt_abort_cmd);

@@ -3282,6 +3299,9 @@ void qlt_free_cmd(struct qla_tgt_cmd *cmd)

	BUG_ON(cmd->cmd_in_wq);

	if (cmd->sg_mapped)
		qlt_unmap_sg(cmd->vha, cmd);

	if (!cmd->q_full)
		qlt_decr_num_pend_cmds(cmd->vha);

@@ -3399,7 +3419,7 @@ static int qlt_term_ctio_exchange(struct scsi_qla_host *vha, void *ctio,
		term = 1;

	if (term)
		qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
		qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);

	return term;
}
@@ -3580,12 +3600,13 @@ static void qlt_do_ctio_completion(struct scsi_qla_host *vha, uint32_t handle,
		case CTIO_PORT_LOGGED_OUT:
		case CTIO_PORT_UNAVAILABLE:
		{
			int logged_out = (status & 0xFFFF);
			int logged_out =
				(status & 0xFFFF) == CTIO_PORT_LOGGED_OUT;

			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf059,
			    "qla_target(%d): CTIO with %s status %x "
			    "received (state %x, se_cmd %p)\n", vha->vp_idx,
			    (logged_out == CTIO_PORT_LOGGED_OUT) ?
			    "PORT LOGGED OUT" : "PORT UNAVAILABLE",
			    logged_out ? "PORT LOGGED OUT" : "PORT UNAVAILABLE",
			    status, cmd->state, se_cmd);

			if (logged_out && cmd->sess) {
@@ -3754,6 +3775,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
		goto out_term;
	}

	spin_lock_init(&cmd->cmd_lock);
	cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
	cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
	cmd->unpacked_lun = scsilun_to_int(
@@ -3796,7 +3818,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
	 */
	cmd->cmd_flags |= BIT_2;
	spin_lock_irqsave(&ha->hardware_lock, flags);
	qlt_send_term_exchange(vha, NULL, &cmd->atio, 1);
	qlt_send_term_exchange(vha, NULL, &cmd->atio, 1, 0);

	qlt_decr_num_pend_cmds(vha);
	percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
@@ -3918,7 +3940,7 @@ static void qlt_create_sess_from_atio(struct work_struct *work)

out_term:
	spin_lock_irqsave(&ha->hardware_lock, flags);
	qlt_send_term_exchange(vha, NULL, &op->atio, 1);
	qlt_send_term_exchange(vha, NULL, &op->atio, 1, 0);
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
	kfree(op);

@@ -3982,7 +4004,8 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,

	cmd->cmd_in_wq = 1;
	cmd->cmd_flags |= BIT_0;
	cmd->se_cmd.cpuid = -1;
	cmd->se_cmd.cpuid = ha->msix_count ?
		ha->tgt.rspq_vector_cpuid : WORK_CPU_UNBOUND;

	spin_lock(&vha->cmd_list_lock);
	list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
@@ -3990,7 +4013,6 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha,

	INIT_WORK(&cmd->work, qlt_do_work);
	if (ha->msix_count) {
		cmd->se_cmd.cpuid = ha->tgt.rspq_vector_cpuid;
		if (cmd->atio.u.isp24.fcp_cmnd.rddata)
			queue_work_on(smp_processor_id(), qla_tgt_wq,
			    &cmd->work);
@@ -4771,7 +4793,7 @@ static void qlt_handle_srr(struct scsi_qla_host *vha,
		dump_stack();
	} else {
		cmd->cmd_flags |= BIT_9;
		qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
		qlt_send_term_exchange(vha, cmd, &cmd->atio, 1, 0);
	}
	spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
@@ -4950,7 +4972,7 @@ static void qlt_prepare_srr_imm(struct scsi_qla_host *vha,
				    sctio, sctio->srr_id);
				list_del(&sctio->srr_list_entry);
				qlt_send_term_exchange(vha, sctio->cmd,
				    &sctio->cmd->atio, 1);
				    &sctio->cmd->atio, 1, 0);
				kfree(sctio);
			}
		}
@@ -5123,7 +5145,7 @@ static int __qlt_send_busy(struct scsi_qla_host *vha,
	    atio->u.isp24.fcp_hdr.s_id);
	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
	if (!sess) {
		qlt_send_term_exchange(vha, NULL, atio, 1);
		qlt_send_term_exchange(vha, NULL, atio, 1, 0);
		return 0;
	}
	/* Sending marker isn't necessary, since we called from ISR */
@@ -5406,7 +5428,7 @@ static void qlt_24xx_atio_pkt(struct scsi_qla_host *vha,
#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
				qlt_send_busy(vha, atio, SAM_STAT_BUSY);
#else
				qlt_send_term_exchange(vha, NULL, atio, 1);
				qlt_send_term_exchange(vha, NULL, atio, 1, 0);
#endif

				if (!ha_locked)
@@ -5523,7 +5545,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
#if 1 /* With TERM EXCHANGE some FC cards refuse to boot */
				qlt_send_busy(vha, atio, 0);
#else
				qlt_send_term_exchange(vha, NULL, atio, 1);
				qlt_send_term_exchange(vha, NULL, atio, 1, 0);
#endif
			} else {
				if (tgt->tgt_stop) {
@@ -5532,7 +5554,7 @@ static void qlt_response_pkt(struct scsi_qla_host *vha, response_t *pkt)
					    "command to target, sending TERM "
					    "EXCHANGE for rsp\n");
					qlt_send_term_exchange(vha, NULL,
					    atio, 1);
					    atio, 1, 0);
				} else {
					ql_dbg(ql_dbg_tgt, vha, 0xe060,
					    "qla_target(%d): Unable to send "
@@ -5960,7 +5982,7 @@ static void qlt_tmr_work(struct qla_tgt *tgt,
	return;

out_term:
	qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 0);
	qlt_send_term_exchange(vha, NULL, &prm->tm_iocb2, 1, 0);
	if (sess)
		ha->tgt.tgt_ops->put_sess(sess);
	spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
Loading