qla2xxx: Add Host reset handling in target mode.
authorArun Easi <arun.easi@qlogic.com>
Thu, 25 Sep 2014 10:14:51 +0000 (06:14 -0400)
committerChristoph Hellwig <hch@lst.de>
Thu, 25 Sep 2014 12:25:07 +0000 (14:25 +0200)
Signed-off-by: Arun Easi <arun.easi@qlogic.com>
Signed-off-by: Saurav Kashyap <saurav.kashyap@qlogic.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_target.c

index 5f25cf0db56884514776716d0d97eaf2e24e697e..83d47ab3fd1e29f99c4fdfd840567c1d2c2d2f7a 100644 (file)
@@ -68,7 +68,7 @@
  * |                              |                    | 0xd101-0xd1fe |
  * |                              |                    | 0xd214-0xd2fe |
  * | Target Mode                 |       0xe078       |                |
- * | Target Mode Management      |       0xf072       | 0xf002-0xf003  |
+ * | Target Mode Management      |       0xf072       | 0xf002         |
  * |                              |                    | 0xf046-0xf049  |
  * | Target Mode Task Management  |      0x1000b      |                |
  * ----------------------------------------------------------------------
index 0f851deec0e895650a5cfc74519a397d91ede6d4..42ea4477c2ecb45d53c06b36e987218a6f4b06da 100644 (file)
@@ -766,4 +766,5 @@ extern void qla82xx_mbx_completion(scsi_qla_host_t *, uint16_t);
 extern int qla8044_abort_isp(scsi_qla_host_t *);
 extern int qla8044_check_fw_alive(struct scsi_qla_host *);
 
+extern void qlt_host_reset_handler(struct qla_hw_data *ha);
 #endif /* _QLA_GBL_H */
index 2c3c6afe88a3e7aa72f7390acb99b86bb2c80280..08e5bbb12f0b85be73d7eb6b80a51304043e3335 100644 (file)
@@ -1363,6 +1363,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
        struct qla_hw_data *ha = vha->hw;
        struct req_que *req;
 
+       qlt_host_reset_handler(ha);
+
        spin_lock_irqsave(&ha->hardware_lock, flags);
        for (que = 0; que < ha->max_req_queues; que++) {
                req = ha->req_q_map[que];
index 1a546bc2bdd4bc170349456e7b6d7f0793904666..de45126ade87424de69735abcc8ab1b93237e9b6 100644 (file)
@@ -2843,6 +2843,80 @@ static struct qla_tgt_cmd *qlt_ctio_to_cmd(struct scsi_qla_host *vha,
        return cmd;
 }
 
+/* hardware_lock should be held by caller. */
+static void
+qlt_abort_cmd_on_host_reset(struct scsi_qla_host *vha, struct qla_tgt_cmd *cmd)
+{
+       struct qla_hw_data *ha = vha->hw;
+       uint32_t handle;
+
+       if (cmd->sg_mapped)
+               qlt_unmap_sg(vha, cmd);
+
+       handle = qlt_make_handle(vha);
+
+       /* TODO: fix debug message type and ids. */
+       if (cmd->state == QLA_TGT_STATE_PROCESSED) {
+               ql_dbg(ql_dbg_io, vha, 0xff00,
+                   "HOST-ABORT: handle=%d, state=PROCESSED.\n", handle);
+       } else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
+               cmd->write_data_transferred = 0;
+               cmd->state = QLA_TGT_STATE_DATA_IN;
+
+               ql_dbg(ql_dbg_io, vha, 0xff01,
+                   "HOST-ABORT: handle=%d, state=DATA_IN.\n", handle);
+
+               ha->tgt.tgt_ops->handle_data(cmd);
+               return;
+       } else if (cmd->state == QLA_TGT_STATE_ABORTED) {
+               ql_dbg(ql_dbg_io, vha, 0xff02,
+                   "HOST-ABORT: handle=%d, state=ABORTED.\n", handle);
+       } else {
+               ql_dbg(ql_dbg_io, vha, 0xff03,
+                   "HOST-ABORT: handle=%d, state=BAD(%d).\n", handle,
+                   cmd->state);
+               dump_stack();
+       }
+
+       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
  */