static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
static void qla2x00_status_entry(scsi_qla_host_t *, struct rsp_que *, void *);
static void qla2x00_status_cont_entry(struct rsp_que *, sts_cont_entry_t *);
-static void qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
+static int qla2x00_error_entry(scsi_qla_host_t *, struct rsp_que *,
sts_entry_t *);
/**
return;
}
+ if (sp->cmd_type != TYPE_SRB) {
+ req->outstanding_cmds[handle] = NULL;
+ ql_dbg(ql_dbg_io, vha, 0x3015,
+ "Unknown sp->cmd_type %x %p).\n",
+ sp->cmd_type, sp);
+ return;
+ }
+
if (unlikely((state_flags & BIT_1) && (sp->type == SRB_BIDI_CMD))) {
qla25xx_process_bidir_status_iocb(vha, pkt, req, handle);
return;
* qla2x00_error_entry() - Process an error entry.
* @ha: SCSI driver HA context
* @pkt: Entry pointer
+ * return : 1=allow further error analysis. 0=no additional error analysis.
*/
-static void
+static int
qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
{
srb_t *sp;
if (pkt->entry_status & RF_BUSY)
res = DID_BUS_BUSY << 16;
- if (pkt->entry_type == NOTIFY_ACK_TYPE &&
- pkt->handle == QLA_TGT_SKIP_HANDLE)
- return;
+ if ((pkt->handle & ~QLA_TGT_HANDLE_MASK) == QLA_TGT_SKIP_HANDLE)
+ return 0;
- sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
- if (sp) {
- sp->done(sp, res);
- return;
+ switch (pkt->entry_type) {
+ case NOTIFY_ACK_TYPE:
+ case STATUS_TYPE:
+ case STATUS_CONT_TYPE:
+ case LOGINOUT_PORT_IOCB_TYPE:
+ case CT_IOCB_TYPE:
+ case ELS_IOCB_TYPE:
+ case ABORT_IOCB_TYPE:
+ case MBX_IOCB_TYPE:
+ sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
+ if (sp) {
+ sp->done(sp, res);
+ return 0;
+ }
+ break;
+
+ case ABTS_RESP_24XX:
+ case CTIO_TYPE7:
+ case CTIO_CRC2:
+ default:
+ return 1;
}
fatal:
ql_log(ql_log_warn, vha, 0x5030,
"Error entry - invalid handle/queue (%04x).\n", que);
+ return 0;
}
/**
}
if (pkt->entry_status != 0) {
- qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt);
-
- if (qlt_24xx_process_response_error(vha, pkt))
+ if (qla2x00_error_entry(vha, rsp, (sts_entry_t *) pkt))
goto process_err;
((response_t *)pkt)->signature = RESPONSE_PROCESSED;
srb_t *sp;
struct qla_hw_data *ha = vha->hw;
struct req_que *req;
-
- qlt_host_reset_handler(ha);
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_tgt_cmd *cmd;
+ uint8_t trace = 0;
spin_lock_irqsave(&ha->hardware_lock, flags);
for (que = 0; que < ha->max_req_queues; que++) {
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
sp = req->outstanding_cmds[cnt];
if (sp) {
- /* Don't abort commands in adapter during EEH
- * recovery as it's not accessible/responding.
- */
- if (GET_CMD_SP(sp) && !ha->flags.eeh_busy &&
- (sp->type == SRB_SCSI_CMD)) {
- /* Get a reference to the sp and drop the lock.
- * The reference ensures this sp->done() call
- * - and not the call in qla2xxx_eh_abort() -
- * ends the SCSI command (with result 'res').
+ req->outstanding_cmds[cnt] = NULL;
+ if (sp->cmd_type == TYPE_SRB) {
+ /*
+ * Don't abort commands in adapter
+ * during EEH recovery as it's not
+ * accessible/responding.
*/
- sp_get(sp);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
- status = qla2xxx_eh_abort(GET_CMD_SP(sp));
- spin_lock_irqsave(&ha->hardware_lock, flags);
- /* Get rid of extra reference if immediate exit
- * from ql2xxx_eh_abort */
- if (status == FAILED && (qla2x00_isp_reg_stat(ha)))
- atomic_dec(&sp->ref_count);
+ if (GET_CMD_SP(sp) &&
+ !ha->flags.eeh_busy &&
+ (sp->type == SRB_SCSI_CMD)) {
+ /*
+ * Get a reference to the sp
+ * and drop the lock. The
+ * reference ensures this
+ * sp->done() call and not the
+ * call in qla2xxx_eh_abort()
+ * ends the SCSI command (with
+ * result 'res').
+ */
+ sp_get(sp);
+ spin_unlock_irqrestore(
+ &ha->hardware_lock, flags);
+ status = qla2xxx_eh_abort(
+ GET_CMD_SP(sp));
+ spin_lock_irqsave(
+ &ha->hardware_lock, flags);
+ /*
+ * Get rid of extra reference
+ * if immediate exit from
+ * ql2xxx_eh_abort
+ */
+ if (status == FAILED &&
+ (qla2x00_isp_reg_stat(ha)))
+ atomic_dec(
+ &sp->ref_count);
+ }
+ sp->done(sp, res);
+ } else {
+ if (!vha->hw->tgt.tgt_ops || !tgt ||
+ qla_ini_mode_enabled(vha)) {
+ if (!trace)
+ ql_dbg(ql_dbg_tgt_mgt,
+ vha, 0xf003,
+ "HOST-ABORT-HNDLR: dpc_flags=%lx. Target mode disabled\n",
+ vha->dpc_flags);
+ continue;
+ }
+ cmd = (struct qla_tgt_cmd *)sp;
+ qlt_abort_cmd_on_host_reset(cmd->vha,
+ cmd);
}
- req->outstanding_cmds[cnt] = NULL;
- sp->done(sp, res);
}
}
}
sp = req->outstanding_cmds[index];
if (!sp)
continue;
+ if (sp->cmd_type != TYPE_SRB)
+ continue;
if (sp->type != SRB_SCSI_CMD)
continue;
sfcp = sp->fcport;
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, int ul_abort);
-static void qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha,
- struct qla_tgt_cmd *cmd);
static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
struct atio_from_isp *atio, uint16_t status, int qfull);
static void qlt_disable_vha(struct scsi_qla_host *vha);
/* ha->hardware_lock supposed to be held on entry */
static inline uint32_t qlt_make_handle(struct scsi_qla_host *vha)
{
- struct qla_hw_data *ha = vha->hw;
uint32_t h;
+ int index;
+ uint8_t found = 0;
+ struct req_que *req = vha->req;
+
+ h = req->current_outstanding_cmd;
- h = ha->tgt.current_handle;
- /* always increment cmd handle */
- do {
- ++h;
- if (h > DEFAULT_OUTSTANDING_COMMANDS)
- h = 1; /* 0 is QLA_TGT_NULL_HANDLE */
- if (h == ha->tgt.current_handle) {
- ql_dbg(ql_dbg_io, vha, 0x305b,
- "qla_target(%d): Ran out of "
- "empty cmd slots in ha %p\n", vha->vp_idx, ha);
- h = QLA_TGT_NULL_HANDLE;
+ for (index = 1; index < req->num_outstanding_cmds; index++) {
+ h++;
+ if (h == req->num_outstanding_cmds)
+ h = 1;
+
+ if (h == QLA_TGT_SKIP_HANDLE)
+ continue;
+
+ if (!req->outstanding_cmds[h]) {
+ found = 1;
break;
}
- } while ((h == QLA_TGT_NULL_HANDLE) ||
- (h == QLA_TGT_SKIP_HANDLE) ||
- (ha->tgt.cmds[h-1] != NULL));
+ }
- if (h != QLA_TGT_NULL_HANDLE)
- ha->tgt.current_handle = h;
+ if (found) {
+ req->current_outstanding_cmd = h;
+ } else {
+ ql_dbg(ql_dbg_io, vha, 0x305b,
+ "qla_target(%d): Ran out of empty cmd slots\n",
+ vha->vp_idx);
+ h = QLA_TGT_NULL_HANDLE;
+ }
return h;
}
{
uint32_t h;
struct ctio7_to_24xx *pkt;
- struct qla_hw_data *ha = vha->hw;
struct atio_from_isp *atio = &prm->cmd->atio;
uint16_t temp;
* the session and, so, the command.
*/
return -EAGAIN;
- } else
- ha->tgt.cmds[h - 1] = prm->cmd;
+ } else {
+ vha->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
+ }
pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = prm->cmd->loop_id;
*/
return -EAGAIN;
} else
- ha->tgt.cmds[h-1] = prm->cmd;
+ vha->req->outstanding_cmds[h] = (srb_t *)prm->cmd;
pkt->handle = h | CTIO_COMPLETION_HANDLE_MARK;
pkt->nport_handle = cpu_to_le16(prm->cmd->loop_id);
crc_queuing_error:
/* Cleanup will be performed by the caller */
- vha->hw->tgt.cmds[h - 1] = NULL;
+ vha->req->outstanding_cmds[h] = NULL;
return QLA_FUNCTION_FAILED;
}
return term;
}
-/* ha->hardware_lock supposed to be held on entry */
-static inline struct qla_tgt_cmd *qlt_get_cmd(struct scsi_qla_host *vha,
- uint32_t handle)
-{
- struct qla_hw_data *ha = vha->hw;
-
- handle--;
- if (ha->tgt.cmds[handle] != NULL) {
- struct qla_tgt_cmd *cmd = ha->tgt.cmds[handle];
- ha->tgt.cmds[handle] = NULL;
- return cmd;
- } else
- return NULL;
-}
/* ha->hardware_lock supposed to be held on entry */
static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
uint32_t handle, void *ctio)
{
struct qla_tgt_cmd *cmd = NULL;
+ struct req_que *req = vha->req;
/* Clear out internal marks */
- handle &= ~(CTIO_COMPLETION_HANDLE_MARK |
- CTIO_INTERMEDIATE_HANDLE_MARK);
+ handle &= ~QLA_TGT_HANDLE_MASK;
if (handle != QLA_TGT_NULL_HANDLE) {
if (unlikely(handle == QLA_TGT_SKIP_HANDLE))
return NULL;
- /* handle-1 is actually used */
- if (unlikely(handle > DEFAULT_OUTSTANDING_COMMANDS)) {
+ handle &= QLA_CMD_HANDLE_MASK;
+
+ if (unlikely(handle > req->num_outstanding_cmds)) {
ql_dbg(ql_dbg_tgt, vha, 0xe052,
"qla_target(%d): Wrong handle %x received\n",
vha->vp_idx, handle);
return NULL;
}
- cmd = qlt_get_cmd(vha, handle);
- if (unlikely(cmd == NULL)) {
- ql_dbg(ql_dbg_tgt, vha, 0xe053,
- "qla_target(%d): Suspicious: unable to "
- "find the command with handle %x\n", vha->vp_idx,
- handle);
+ cmd = (struct qla_tgt_cmd *)req->outstanding_cmds[handle];
+ if (unlikely((cmd == NULL) ||
+ (cmd->cmd_type != TYPE_TGT_CMD))) {
+ ql_dbg(ql_dbg_async, vha, 0xe053,
+ "qla_target(%d): Suspicious: unable to find the command with handle %x cmd %p\n",
+ vha->vp_idx, handle, cmd);
return NULL;
}
+ req->outstanding_cmds[handle] = NULL;
} else if (ctio != NULL) {
/* We can't get loop ID from CTIO7 */
ql_dbg(ql_dbg_tgt, vha, 0xe054,
}
/* hardware_lock should be held by caller. */
-static void
+void
qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
{
struct qla_hw_data *ha = vha->hw;
ha->tgt.tgt_ops->free_cmd(cmd);
}
-void
-qlt_host_reset_handler(struct qla_hw_data *ha)
-{
- struct qla_tgt_cmd *cmd;
- unsigned long flags;
- scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
- scsi_qla_host_t *vha = NULL;
- struct qla_tgt *tgt = base_vha->vha_tgt.qla_tgt;
- uint32_t i;
-
- if (!base_vha->hw->tgt.tgt_ops)
- return;
-
- if (!tgt || qla_ini_mode_enabled(base_vha)) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf003,
- "Target mode disabled\n");
- return;
- }
-
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xff10,
- "HOST-ABORT-HNDLR: base_vha->dpc_flags=%lx.\n",
- base_vha->dpc_flags);
-
- spin_lock_irqsave(&ha->hardware_lock, flags);
- for (i = 1; i < DEFAULT_OUTSTANDING_COMMANDS + 1; i++) {
- cmd = qlt_get_cmd(base_vha, i);
- if (!cmd)
- continue;
- /* ha->tgt.cmds entry is cleared by qlt_get_cmd. */
- vha = cmd->vha;
- qlt_abort_cmd_on_host_reset(vha, cmd);
- }
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
-}
-
-
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
cmd = &((struct qla_tgt_cmd *)se_sess->sess_cmd_map)[tag];
memset(cmd, 0, sizeof(struct qla_tgt_cmd));
-
+ cmd->cmd_type = TYPE_TGT_CMD;
memcpy(&cmd->atio, atio, sizeof(*atio));
cmd->state = QLA_TGT_STATE_NEW;
cmd->tgt = vha->vha_tgt.qla_tgt;
ha->msix_count += 1; /* For ATIO Q */
}
-int
-qlt_24xx_process_response_error(struct scsi_qla_host *vha,
- struct sts_entry_24xx *pkt)
-{
- switch (pkt->entry_type) {
- case ABTS_RECV_24XX:
- case ABTS_RESP_24XX:
- case CTIO_TYPE7:
- case NOTIFY_ACK_TYPE:
- case CTIO_CRC2:
- return 1;
- default:
- return 0;
- }
-}
void
qlt_modify_vp_config(struct scsi_qla_host *vha,