nvme-fc: Fail transport errors with NVME_SC_HOST_PATH
[linux-2.6-microblaze.git] / drivers / nvme / host / fc.c
index 232d809..265f89e 100644 (file)
@@ -1608,9 +1608,13 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                                sizeof(op->rsp_iu), DMA_FROM_DEVICE);
 
        if (opstate == FCPOP_STATE_ABORTED)
-               status = cpu_to_le16(NVME_SC_ABORT_REQ << 1);
-       else if (freq->status)
-               status = cpu_to_le16(NVME_SC_INTERNAL << 1);
+               status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+       else if (freq->status) {
+               status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+               dev_info(ctrl->ctrl.device,
+                       "NVME-FC{%d}: io failed due to lldd error %d\n",
+                       ctrl->cnum, freq->status);
+       }
 
        /*
         * For the linux implementation, if we have an unsuccesful
@@ -1637,8 +1641,13 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                 * no payload in the CQE by the transport.
                 */
                if (freq->transferred_length !=
-                       be32_to_cpu(op->cmd_iu.data_len)) {
-                       status = cpu_to_le16(NVME_SC_INTERNAL << 1);
+                   be32_to_cpu(op->cmd_iu.data_len)) {
+                       status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+                       dev_info(ctrl->ctrl.device,
+                               "NVME-FC{%d}: io failed due to bad transfer "
+                               "length: %d vs expected %d\n",
+                               ctrl->cnum, freq->transferred_length,
+                               be32_to_cpu(op->cmd_iu.data_len));
                        goto done;
                }
                result.u64 = 0;
@@ -1655,7 +1664,17 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                                        freq->transferred_length ||
                             op->rsp_iu.status_code ||
                             sqe->common.command_id != cqe->command_id)) {
-                       status = cpu_to_le16(NVME_SC_INTERNAL << 1);
+                       status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+                       dev_info(ctrl->ctrl.device,
+                               "NVME-FC{%d}: io failed due to bad NVMe_ERSP: "
+                               "iu len %d, xfr len %d vs %d, status code "
+                               "%d, cmdid %d vs %d\n",
+                               ctrl->cnum, be16_to_cpu(op->rsp_iu.iu_len),
+                               be32_to_cpu(op->rsp_iu.xfrd_len),
+                               freq->transferred_length,
+                               op->rsp_iu.status_code,
+                               sqe->common.command_id,
+                               cqe->command_id);
                        goto done;
                }
                result = cqe->result;
@@ -1663,7 +1682,11 @@ nvme_fc_fcpio_done(struct nvmefc_fcp_req *req)
                break;
 
        default:
-               status = cpu_to_le16(NVME_SC_INTERNAL << 1);
+               status = cpu_to_le16(NVME_SC_HOST_PATH_ERROR << 1);
+               dev_info(ctrl->ctrl.device,
+                       "NVME-FC{%d}: io failed due to odd NVMe_xRSP iu "
+                       "len %d\n",
+                       ctrl->cnum, freq->rcv_rsplen);
                goto done;
        }
 
@@ -2006,6 +2029,7 @@ nvme_fc_ctrl_free(struct kref *ref)
 
        blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
        blk_cleanup_queue(ctrl->ctrl.admin_q);
+       blk_cleanup_queue(ctrl->ctrl.fabrics_q);
        blk_mq_free_tag_set(&ctrl->admin_tag_set);
 
        kfree(ctrl->queues);
@@ -2107,7 +2131,6 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
                struct nvme_fc_fcp_op *op)
 {
        struct nvmefc_fcp_req *freq = &op->fcp_req;
-       enum dma_data_direction dir;
        int ret;
 
        freq->sg_cnt = 0;
@@ -2124,9 +2147,8 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
 
        op->nents = blk_rq_map_sg(rq->q, rq, freq->sg_table.sgl);
        WARN_ON(op->nents > blk_rq_nr_phys_segments(rq));
-       dir = (rq_data_dir(rq) == WRITE) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
        freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
-                               op->nents, dir);
+                               op->nents, rq_dma_dir(rq));
        if (unlikely(freq->sg_cnt <= 0)) {
                sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE);
                freq->sg_cnt = 0;
@@ -2149,8 +2171,7 @@ nvme_fc_unmap_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
                return;
 
        fc_dma_unmap_sg(ctrl->lport->dev, freq->sg_table.sgl, op->nents,
-                               ((rq_data_dir(rq) == WRITE) ?
-                                       DMA_TO_DEVICE : DMA_FROM_DEVICE));
+                       rq_dma_dir(rq));
 
        nvme_cleanup_cmd(rq);
 
@@ -2633,8 +2654,6 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        if (ret)
                goto out_delete_hw_queue;
 
-       blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
-
        ret = nvmf_connect_admin_queue(&ctrl->ctrl);
        if (ret)
                goto out_disconnect_admin_queue;
@@ -2648,23 +2667,15 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
         * prior connection values
         */
 
-       ret = nvmf_reg_read64(&ctrl->ctrl, NVME_REG_CAP, &ctrl->ctrl.cap);
-       if (ret) {
-               dev_err(ctrl->ctrl.device,
-                       "prop_get NVME_REG_CAP failed\n");
-               goto out_disconnect_admin_queue;
-       }
-
-       ctrl->ctrl.sqsize =
-               min_t(int, NVME_CAP_MQES(ctrl->ctrl.cap), ctrl->ctrl.sqsize);
-
-       ret = nvme_enable_ctrl(&ctrl->ctrl, ctrl->ctrl.cap);
+       ret = nvme_enable_ctrl(&ctrl->ctrl);
        if (ret)
                goto out_disconnect_admin_queue;
 
        ctrl->ctrl.max_hw_sectors =
                (ctrl->lport->ops->max_sgl_segments - 1) << (PAGE_SHIFT - 9);
 
+       blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
+
        ret = nvme_init_identify(&ctrl->ctrl);
        if (ret)
                goto out_disconnect_admin_queue;
@@ -2774,6 +2785,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
                nvme_stop_queues(&ctrl->ctrl);
                blk_mq_tagset_busy_iter(&ctrl->tag_set,
                                nvme_fc_terminate_exchange, &ctrl->ctrl);
+               blk_mq_tagset_wait_completed_request(&ctrl->tag_set);
        }
 
        /*
@@ -2796,6 +2808,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
        blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
        blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
                                nvme_fc_terminate_exchange, &ctrl->ctrl);
+       blk_mq_tagset_wait_completed_request(&ctrl->admin_tag_set);
 
        /* kill the aens as they are a separate path */
        nvme_fc_abort_aen_ops(ctrl);
@@ -3109,10 +3122,16 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
                goto out_free_queues;
        ctrl->ctrl.admin_tagset = &ctrl->admin_tag_set;
 
+       ctrl->ctrl.fabrics_q = blk_mq_init_queue(&ctrl->admin_tag_set);
+       if (IS_ERR(ctrl->ctrl.fabrics_q)) {
+               ret = PTR_ERR(ctrl->ctrl.fabrics_q);
+               goto out_free_admin_tag_set;
+       }
+
        ctrl->ctrl.admin_q = blk_mq_init_queue(&ctrl->admin_tag_set);
        if (IS_ERR(ctrl->ctrl.admin_q)) {
                ret = PTR_ERR(ctrl->ctrl.admin_q);
-               goto out_free_admin_tag_set;
+               goto out_cleanup_fabrics_q;
        }
 
        /*
@@ -3184,6 +3203,8 @@ fail_ctrl:
 
 out_cleanup_admin_q:
        blk_cleanup_queue(ctrl->ctrl.admin_q);
+out_cleanup_fabrics_q:
+       blk_cleanup_queue(ctrl->ctrl.fabrics_q);
 out_free_admin_tag_set:
        blk_mq_free_tag_set(&ctrl->admin_tag_set);
 out_free_queues: