diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 588 |
1 files changed, 382 insertions, 206 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 47bf60a9490a..42ce4e1fe744 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * QLogic Fibre Channel HBA Driver * Copyright (c) 2003-2014 QLogic Corporation - * - * See LICENSE.qla2xxx for copyright and licensing details. */ #include "qla_def.h" #include "qla_target.h" @@ -44,7 +43,7 @@ qla2x00_get_cmd_direction(srb_t *sp) * qla2x00_calc_iocbs_32() - Determine number of Command Type 2 and * Continuation Type 0 IOCBs to allocate. * - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of IOCB entries needed to store @dsds. */ @@ -66,7 +65,7 @@ qla2x00_calc_iocbs_32(uint16_t dsds) * qla2x00_calc_iocbs_64() - Determine number of Command Type 3 and * Continuation Type 1 IOCBs to allocate. * - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of IOCB entries needed to store @dsds. */ @@ -119,7 +118,7 @@ qla2x00_prep_cont_type0_iocb(struct scsi_qla_host *vha) * * Returns a pointer to the continuation type 1 IOCB packet. */ -static inline cont_a64_entry_t * +cont_a64_entry_t * qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha, struct req_que *req) { cont_a64_entry_t *cont_pkt; @@ -146,7 +145,6 @@ inline int qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) { struct scsi_cmnd *cmd = GET_CMD_SP(sp); - uint8_t guard = scsi_host_get_guard(cmd->device->host); /* We always use DIFF Bundling for best performance */ *fw_prot_opts = 0; @@ -167,7 +165,7 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) break; case SCSI_PROT_READ_PASS: case SCSI_PROT_WRITE_PASS: - if (guard & SHOST_DIX_GUARD_IP) + if (cmd->prot_flags & SCSI_PROT_IP_CHECKSUM) *fw_prot_opts |= PO_MODE_DIF_TCP_CKSUM; else *fw_prot_opts |= PO_MODE_DIF_PASS; @@ -177,6 +175,9 @@ qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) break; } + if (!(cmd->prot_flags & SCSI_PROT_GUARD_CHECK)) + *fw_prot_opts |= PO_DISABLE_GUARD_CHECK; + return scsi_prot_sg_count(cmd); } @@ -376,7 +377,7 @@ qla2x00_start_scsi(srb_t *sp) /* Calculate the number of request entries needed. */ req_cnt = ha->isp_ops->calc_req_entries(tot_dsds); if (req->cnt < (req_cnt + 2)) { - cnt = RD_REG_WORD_RELAXED(ISP_REQ_Q_OUT(ha, reg)); + cnt = rd_reg_word_relaxed(ISP_REQ_Q_OUT(ha, reg)); if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -428,8 +429,8 @@ qla2x00_start_scsi(srb_t *sp) sp->flags |= SRB_DMA_VALID; /* Set chip new ring index. */ - WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), req->ring_index); - RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */ + wrt_reg_word(ISP_REQ_Q_IN(ha, reg), req->ring_index); + rd_reg_word_relaxed(ISP_REQ_Q_IN(ha, reg)); /* PCI Posting. */ /* Manage unprocessed RIO/ZIO commands in response queue. */ if (vha->flags.process_response_queue && @@ -472,27 +473,27 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) /* Set chip new ring index. */ if (ha->mqenable || IS_QLA27XX(ha) || IS_QLA28XX(ha)) { - WRT_REG_DWORD(req->req_q_in, req->ring_index); + wrt_reg_dword(req->req_q_in, req->ring_index); } else if (IS_QLA83XX(ha)) { - WRT_REG_DWORD(req->req_q_in, req->ring_index); - RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr); + wrt_reg_dword(req->req_q_in, req->ring_index); + rd_reg_dword_relaxed(&ha->iobase->isp24.hccr); } else if (IS_QLAFX00(ha)) { - WRT_REG_DWORD(®->ispfx00.req_q_in, req->ring_index); - RD_REG_DWORD_RELAXED(®->ispfx00.req_q_in); + wrt_reg_dword(®->ispfx00.req_q_in, req->ring_index); + rd_reg_dword_relaxed(®->ispfx00.req_q_in); QLAFX00_SET_HST_INTR(ha, ha->rqstq_intr_code); } else if (IS_FWI2_CAPABLE(ha)) { - WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); - RD_REG_DWORD_RELAXED(®->isp24.req_q_in); + wrt_reg_dword(®->isp24.req_q_in, req->ring_index); + rd_reg_dword_relaxed(®->isp24.req_q_in); } else { - WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), + wrt_reg_word(ISP_REQ_Q_IN(ha, ®->isp), req->ring_index); - RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); + rd_reg_word_relaxed(ISP_REQ_Q_IN(ha, ®->isp)); } } } /** - * qla2x00_marker() - Send a marker IOCB to the firmware. + * __qla2x00_marker() - Send a marker IOCB to the firmware. * @vha: HA context * @qpair: queue pair pointer * @loop_id: loop ID @@ -530,7 +531,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct qla_qpair *qpair, int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; - mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle); + mrk24->handle = make_handle(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); mrk->lun = cpu_to_le16((uint16_t)lun); @@ -594,6 +595,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, uint32_t dsd_list_len; struct dsd_dma *dsd_ptr; struct ct6_dsd *ctx; + struct qla_qpair *qpair = sp->qpair; cmd = GET_CMD_SP(sp); @@ -612,12 +614,12 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->control_flags = cpu_to_le16(CF_WRITE_DATA); - vha->qla_stats.output_bytes += scsi_bufflen(cmd); - vha->qla_stats.output_requests++; + qpair->counters.output_bytes += scsi_bufflen(cmd); + qpair->counters.output_requests++; } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cmd_pkt->control_flags = cpu_to_le16(CF_READ_DATA); - vha->qla_stats.input_bytes += scsi_bufflen(cmd); - vha->qla_stats.input_requests++; + qpair->counters.input_bytes += scsi_bufflen(cmd); + qpair->counters.input_requests++; } cur_seg = scsi_sglist(cmd); @@ -661,7 +663,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, cur_dsd->address = 0; cur_dsd->length = 0; cur_dsd++; - cmd_pkt->control_flags |= CF_DATA_SEG_DESCR_ENABLE; + cmd_pkt->control_flags |= cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE); return 0; } @@ -669,7 +671,7 @@ qla24xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt, * qla24xx_calc_dsd_lists() - Determine number of DSD list required * for Command Type 6. * - * @dsds: number of data segment decriptors needed + * @dsds: number of data segment descriptors needed * * Returns the number of dsd list needed to store @dsds. */ @@ -704,6 +706,7 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, struct scsi_cmnd *cmd; struct scatterlist *sg; int i; + struct qla_qpair *qpair = sp->qpair; cmd = GET_CMD_SP(sp); @@ -721,12 +724,12 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, /* Set transfer direction */ if (cmd->sc_data_direction == DMA_TO_DEVICE) { cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_WRITE_DATA); - vha->qla_stats.output_bytes += scsi_bufflen(cmd); - vha->qla_stats.output_requests++; + qpair->counters.output_bytes += scsi_bufflen(cmd); + qpair->counters.output_requests++; } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { cmd_pkt->task_mgmt_flags = cpu_to_le16(TMF_READ_DATA); - vha->qla_stats.input_bytes += scsi_bufflen(cmd); - vha->qla_stats.input_requests++; + qpair->counters.input_bytes += scsi_bufflen(cmd); + qpair->counters.input_requests++; } /* One DSD is available in the Command Type 3 IOCB */ @@ -755,8 +758,8 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, } struct fw_dif_context { - uint32_t ref_tag; - uint16_t app_tag; + __le32 ref_tag; + __le16 app_tag; uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/ uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/ }; @@ -771,74 +774,19 @@ qla24xx_set_t10dif_tags(srb_t *sp, struct fw_dif_context *pkt, { struct scsi_cmnd *cmd = GET_CMD_SP(sp); - switch (scsi_get_prot_type(cmd)) { - case SCSI_PROT_DIF_TYPE0: - /* - * No check for ql2xenablehba_err_chk, as it would be an - * I/O error if hba tag generation is not done. - */ - pkt->ref_tag = cpu_to_le32((uint32_t) - (0xffffffff & scsi_get_lba(cmd))); - - if (!qla2x00_hba_err_chk_enabled(sp)) - break; + pkt->ref_tag = cpu_to_le32(scsi_prot_ref_tag(cmd)); + if (cmd->prot_flags & SCSI_PROT_REF_CHECK && + qla2x00_hba_err_chk_enabled(sp)) { pkt->ref_tag_mask[0] = 0xff; pkt->ref_tag_mask[1] = 0xff; pkt->ref_tag_mask[2] = 0xff; pkt->ref_tag_mask[3] = 0xff; - break; - - /* - * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to - * match LBA in CDB + N - */ - case SCSI_PROT_DIF_TYPE2: - pkt->app_tag = cpu_to_le16(0); - pkt->app_tag_mask[0] = 0x0; - pkt->app_tag_mask[1] = 0x0; - - pkt->ref_tag = cpu_to_le32((uint32_t) - (0xffffffff & scsi_get_lba(cmd))); - - if (!qla2x00_hba_err_chk_enabled(sp)) - break; - - /* enable ALL bytes of the ref tag */ - pkt->ref_tag_mask[0] = 0xff; - pkt->ref_tag_mask[1] = 0xff; - pkt->ref_tag_mask[2] = 0xff; - pkt->ref_tag_mask[3] = 0xff; - break; - - /* For Type 3 protection: 16 bit GUARD only */ - case SCSI_PROT_DIF_TYPE3: - pkt->ref_tag_mask[0] = pkt->ref_tag_mask[1] = - pkt->ref_tag_mask[2] = pkt->ref_tag_mask[3] = - 0x00; - break; - - /* - * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and - * 16 bit app tag. - */ - case SCSI_PROT_DIF_TYPE1: - pkt->ref_tag = cpu_to_le32((uint32_t) - (0xffffffff & scsi_get_lba(cmd))); - pkt->app_tag = cpu_to_le16(0); - pkt->app_tag_mask[0] = 0x0; - pkt->app_tag_mask[1] = 0x0; - - if (!qla2x00_hba_err_chk_enabled(sp)) - break; - - /* enable ALL bytes of the ref tag */ - pkt->ref_tag_mask[0] = 0xff; - pkt->ref_tag_mask[1] = 0xff; - pkt->ref_tag_mask[2] = 0xff; - pkt->ref_tag_mask[3] = 0xff; - break; } + + pkt->app_tag = cpu_to_le16(0); + pkt->app_tag_mask[0] = 0x0; + pkt->app_tag_mask[1] = 0x0; } int @@ -904,7 +852,7 @@ qla24xx_walk_and_build_sglist_no_difb(struct qla_hw_data *ha, srb_t *sp, memset(&sgx, 0, sizeof(struct qla2_sgx)); if (sp) { cmd = GET_CMD_SP(sp); - prot_int = cmd->device->sector_size; + prot_int = scsi_prot_interval(cmd); sgx.tot_bytes = scsi_bufflen(cmd); sgx.cur_sg = scsi_sglist(cmd); @@ -1389,7 +1337,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts) { struct dsd64 *cur_dsd; - uint32_t *fcp_dl; + __be32 *fcp_dl; scsi_qla_host_t *vha; struct scsi_cmnd *cmd; uint32_t total_bytes = 0; @@ -1456,7 +1404,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, &crc_ctx_pkt->ref_tag, tot_prot_dsds); put_unaligned_le64(crc_ctx_dma, &cmd_pkt->crc_context_address); - cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW; + cmd_pkt->crc_context_len = cpu_to_le16(CRC_CONTEXT_LEN_FW); /* Determine SCSI command length -- align to 4 byte boundary */ if (cmd->cmd_len > 16) { @@ -1545,7 +1493,7 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, crc_ctx_pkt->guard_seed = cpu_to_le16(0); /* Fibre channel byte count */ cmd_pkt->byte_count = cpu_to_le32(total_bytes); - fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 + + fcp_dl = (__be32 *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 + additional_fcpcdb_len); *fcp_dl = htonl(total_bytes); @@ -1599,12 +1547,17 @@ qla24xx_start_scsi(srb_t *sp) uint16_t req_cnt; uint16_t tot_dsds; struct req_que *req = NULL; + struct rsp_que *rsp; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct scsi_qla_host *vha = sp->vha; struct qla_hw_data *ha = vha->hw; + if (sp->fcport->edif.enable && (sp->fcport->flags & FCF_FCSP_DEVICE)) + return qla28xx_start_scsi_edif(sp); + /* Setup device pointers. */ req = vha->req; + rsp = req->rsp; /* So we know we haven't pci_map'ed anything yet */ tot_dsds = 0; @@ -1635,9 +1588,21 @@ qla24xx_start_scsi(srb_t *sp) tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + + sp->iores.res_type = RESOURCE_INI; + sp->iores.iocb_cnt = req_cnt; + if (qla_get_iocbs(sp->qpair, &sp->iores)) + goto queuing_error; + if (req->cnt < (req_cnt + 2)) { - cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : - RD_REG_DWORD_RELAXED(req->req_q_out); + if (IS_SHADOW_REG_CAPABLE(ha)) { + cnt = *req->out_ptr; + } else { + cnt = rd_reg_dword_relaxed(req->req_q_out); + if (qla2x00_check_reg16_for_disconnect(vha, cnt)) + goto queuing_error; + } + if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -1655,7 +1620,7 @@ qla24xx_start_scsi(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -1695,10 +1660,16 @@ qla24xx_start_scsi(srb_t *sp) } else req->ring_ptr++; + sp->qpair->cmd_cnt++; sp->flags |= SRB_DMA_VALID; /* Set chip new ring index. */ - WRT_REG_DWORD(req->req_q_in, req->ring_index); + wrt_reg_dword(req->req_q_in, req->ring_index); + + /* Manage unprocessed RIO/ZIO commands in response queue. */ + if (vha->flags.process_response_queue && + rsp->ring_ptr->signature != RESPONSE_PROCESSED) + qla24xx_process_response_queue(vha, rsp); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_SUCCESS; @@ -1707,6 +1678,7 @@ queuing_error: if (tot_dsds) scsi_dma_unmap(cmd); + qla_put_iocbs(sp->qpair, &sp->iores); spin_unlock_irqrestore(&ha->hardware_lock, flags); return QLA_FUNCTION_FAILED; @@ -1820,9 +1792,20 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Total Data and protection sg segment(s) */ tot_prot_dsds = nseg; tot_dsds += nseg; + + sp->iores.res_type = RESOURCE_INI; + sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + if (qla_get_iocbs(sp->qpair, &sp->iores)) + goto queuing_error; + if (req->cnt < (req_cnt + 2)) { - cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : - RD_REG_DWORD_RELAXED(req->req_q_out); + if (IS_SHADOW_REG_CAPABLE(ha)) { + cnt = *req->out_ptr; + } else { + cnt = rd_reg_dword_relaxed(req->req_q_out); + if (qla2x00_check_reg16_for_disconnect(vha, cnt)) + goto queuing_error; + } if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -1843,7 +1826,7 @@ qla24xx_dif_start_scsi(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -1880,8 +1863,14 @@ qla24xx_dif_start_scsi(srb_t *sp) } else req->ring_ptr++; + sp->qpair->cmd_cnt++; /* Set chip new ring index. */ - WRT_REG_DWORD(req->req_q_in, req->ring_index); + wrt_reg_dword(req->req_q_in, req->ring_index); + + /* Manage unprocessed RIO/ZIO commands in response queue. */ + if (vha->flags.process_response_queue && + rsp->ring_ptr->signature != RESPONSE_PROCESSED) + qla24xx_process_response_queue(vha, rsp); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1894,7 +1883,9 @@ queuing_error: } /* Cleanup will be performed by the caller (queuecommand) */ + qla_put_iocbs(sp->qpair, &sp->iores); spin_unlock_irqrestore(&ha->hardware_lock, flags); + return QLA_FUNCTION_FAILED; } @@ -1916,16 +1907,21 @@ qla2xxx_start_scsi_mq(srb_t *sp) uint16_t req_cnt; uint16_t tot_dsds; struct req_que *req = NULL; + struct rsp_que *rsp; struct scsi_cmnd *cmd = GET_CMD_SP(sp); struct scsi_qla_host *vha = sp->fcport->vha; struct qla_hw_data *ha = vha->hw; struct qla_qpair *qpair = sp->qpair; + if (sp->fcport->edif.enable && (sp->fcport->flags & FCF_FCSP_DEVICE)) + return qla28xx_start_scsi_edif(sp); + /* Acquire qpair specific lock */ spin_lock_irqsave(&qpair->qp_lock, flags); /* Setup qpair pointers */ req = qpair->req; + rsp = qpair->rsp; /* So we know we haven't pci_map'ed anything yet */ tot_dsds = 0; @@ -1955,9 +1951,21 @@ qla2xxx_start_scsi_mq(srb_t *sp) tot_dsds = nseg; req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + + sp->iores.res_type = RESOURCE_INI; + sp->iores.iocb_cnt = req_cnt; + if (qla_get_iocbs(sp->qpair, &sp->iores)) + goto queuing_error; + if (req->cnt < (req_cnt + 2)) { - cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : - RD_REG_DWORD_RELAXED(req->req_q_out); + if (IS_SHADOW_REG_CAPABLE(ha)) { + cnt = *req->out_ptr; + } else { + cnt = rd_reg_dword_relaxed(req->req_q_out); + if (qla2x00_check_reg16_for_disconnect(vha, cnt)) + goto queuing_error; + } + if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -1975,7 +1983,7 @@ qla2xxx_start_scsi_mq(srb_t *sp) req->cnt -= req_cnt; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -2015,10 +2023,16 @@ qla2xxx_start_scsi_mq(srb_t *sp) } else req->ring_ptr++; + sp->qpair->cmd_cnt++; sp->flags |= SRB_DMA_VALID; /* Set chip new ring index. */ - WRT_REG_DWORD(req->req_q_in, req->ring_index); + wrt_reg_dword(req->req_q_in, req->ring_index); + + /* Manage unprocessed RIO/ZIO commands in response queue. */ + if (vha->flags.process_response_queue && + rsp->ring_ptr->signature != RESPONSE_PROCESSED) + qla24xx_process_response_queue(vha, rsp); spin_unlock_irqrestore(&qpair->qp_lock, flags); return QLA_SUCCESS; @@ -2027,6 +2041,7 @@ queuing_error: if (tot_dsds) scsi_dma_unmap(cmd); + qla_put_iocbs(sp->qpair, &sp->iores); spin_unlock_irqrestore(&qpair->qp_lock, flags); return QLA_FUNCTION_FAILED; @@ -2155,9 +2170,21 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) /* Total Data and protection sg segment(s) */ tot_prot_dsds = nseg; tot_dsds += nseg; + + sp->iores.res_type = RESOURCE_INI; + sp->iores.iocb_cnt = qla24xx_calc_iocbs(vha, tot_dsds); + if (qla_get_iocbs(sp->qpair, &sp->iores)) + goto queuing_error; + if (req->cnt < (req_cnt + 2)) { - cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : - RD_REG_DWORD_RELAXED(req->req_q_out); + if (IS_SHADOW_REG_CAPABLE(ha)) { + cnt = *req->out_ptr; + } else { + cnt = rd_reg_dword_relaxed(req->req_q_out); + if (qla2x00_check_reg16_for_disconnect(vha, cnt)) + goto queuing_error; + } + if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -2178,7 +2205,7 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) /* Fill-in common area */ cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); clr_ptr = (uint32_t *)cmd_pkt + 2; memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); @@ -2213,8 +2240,9 @@ qla2xxx_dif_start_scsi_mq(srb_t *sp) } else req->ring_ptr++; + sp->qpair->cmd_cnt++; /* Set chip new ring index. */ - WRT_REG_DWORD(req->req_q_in, req->ring_index); + wrt_reg_dword(req->req_q_in, req->ring_index); /* Manage unprocessed RIO/ZIO commands in response queue. */ if (vha->flags.process_response_queue && @@ -2232,7 +2260,9 @@ queuing_error: } /* Cleanup will be performed by the caller (queuecommand) */ + qla_put_iocbs(sp->qpair, &sp->iores); spin_unlock_irqrestore(&qpair->qp_lock, flags); + return QLA_FUNCTION_FAILED; } @@ -2266,17 +2296,22 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) cnt = *req->out_ptr; else if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) - cnt = RD_REG_DWORD(®->isp25mq.req_q_out); + cnt = rd_reg_dword(®->isp25mq.req_q_out); else if (IS_P3P_TYPE(ha)) - cnt = RD_REG_DWORD(®->isp82.req_q_out); + cnt = rd_reg_dword(reg->isp82.req_q_out); else if (IS_FWI2_CAPABLE(ha)) - cnt = RD_REG_DWORD(®->isp24.req_q_out); + cnt = rd_reg_dword(®->isp24.req_q_out); else if (IS_QLAFX00(ha)) - cnt = RD_REG_DWORD(®->ispfx00.req_q_out); + cnt = rd_reg_dword(®->ispfx00.req_q_out); else cnt = qla2x00_debounce_register( ISP_REQ_Q_OUT(ha, ®->isp)); + if (!qpair->use_shadow_reg && cnt == ISP_REG16_DISCONNECT) { + qla_schedule_eeh_work(vha); + return NULL; + } + if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -2305,8 +2340,8 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp) pkt = req->ring_ptr; memset(pkt, 0, REQUEST_ENTRY_SIZE); if (IS_QLAFX00(ha)) { - WRT_REG_BYTE((void __iomem *)&pkt->entry_count, req_cnt); - WRT_REG_WORD((void __iomem *)&pkt->handle, handle); + wrt_reg_byte((u8 __force __iomem *)&pkt->entry_count, req_cnt); + wrt_reg_dword((__le32 __force __iomem *)&pkt->handle, handle); } else { pkt->entry_count = req_cnt; pkt->handle = handle; @@ -2344,9 +2379,21 @@ qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI); if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI) { - logio->control_flags |= LCF_NVME_PRLI; + logio->control_flags |= cpu_to_le16(LCF_NVME_PRLI); if (sp->vha->flags.nvme_first_burst) - logio->io_parameter[0] = NVME_PRLI_SP_FIRST_BURST; + logio->io_parameter[0] = + cpu_to_le32(NVME_PRLI_SP_FIRST_BURST); + if (sp->vha->flags.nvme2_enabled) { + /* Set service parameter BIT_7 for NVME CONF support */ + logio->io_parameter[0] |= + cpu_to_le32(NVME_PRLI_SP_CONF); + /* Set service parameter BIT_8 for SLER support */ + logio->io_parameter[0] |= + cpu_to_le32(NVME_PRLI_SP_SLER); + /* Set service parameter BIT_9 for PI control support */ + logio->io_parameter[0] |= + cpu_to_le32(NVME_PRLI_SP_PI_CTRL); + } } logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); @@ -2362,6 +2409,8 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) struct srb_iocb *lio = &sp->u.iocb_cmd; logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; + logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); + if (lio->u.logio.flags & SRB_LOGIN_PRLI_ONLY) { logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI); } else { @@ -2370,6 +2419,12 @@ qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI) logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); + if (lio->u.logio.flags & SRB_LOGIN_FCSP) { + logio->control_flags |= + cpu_to_le16(LCF_COMMON_FEAT | LCF_SKIP_PRLI); + logio->io_parameter[0] = + cpu_to_le32(LIO_COMM_FEAT_FCSP | LIO_COMM_FEAT_CIO); + } } logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); logio->port_id[0] = sp->fcport->d_id.b.al_pa; @@ -2489,7 +2544,7 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) tsk->entry_type = TSK_MGMT_IOCB_TYPE; tsk->entry_count = 1; - tsk->handle = MAKE_HANDLE(req->id, tsk->handle); + tsk->handle = make_handle(req->id, tsk->handle); tsk->nport_handle = cpu_to_le16(fcport->loop_id); tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); tsk->control_flags = cpu_to_le32(flags); @@ -2505,11 +2560,38 @@ qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) } } -void qla2x00_init_timer(srb_t *sp, unsigned long tmo) +static void +qla2x00_async_done(struct srb *sp, int res) +{ + if (del_timer(&sp->u.iocb_cmd.timer)) { + /* + * Successfully cancelled the timeout handler + * ref: TMR + */ + if (kref_put(&sp->cmd_kref, qla2x00_sp_release)) + return; + } + sp->async_done(sp, res); +} + +void +qla2x00_sp_release(struct kref *kref) +{ + struct srb *sp = container_of(kref, struct srb, cmd_kref); + + sp->free(sp); +} + +void +qla2x00_init_async_sp(srb_t *sp, unsigned long tmo, + void (*done)(struct srb *sp, int res)) { timer_setup(&sp->u.iocb_cmd.timer, qla2x00_sp_timeout, 0); - sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; + sp->done = qla2x00_async_done; + sp->async_done = done; sp->free = qla2x00_sp_free; + sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; + sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ; if (IS_QLAFX00(sp->vha->hw) && sp->type == SRB_FXIOCB_DCMD) init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp); sp->start_timer = 1; @@ -2596,7 +2678,9 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, return -ENOMEM; } - /* Alloc SRB structure */ + /* Alloc SRB structure + * ref: INIT + */ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) { kfree(fcport); @@ -2617,18 +2701,19 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, sp->type = SRB_ELS_DCMD; sp->name = "ELS_DCMD"; sp->fcport = fcport; - elsio->timeout = qla2x00_els_dcmd_iocb_timeout; - qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT); - init_completion(&sp->u.iocb_cmd.u.els_logo.comp); - sp->done = qla2x00_els_dcmd_sp_done; + qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT, + qla2x00_els_dcmd_sp_done); sp->free = qla2x00_els_dcmd_sp_free; + sp->u.iocb_cmd.timeout = qla2x00_els_dcmd_iocb_timeout; + init_completion(&sp->u.iocb_cmd.u.els_logo.comp); elsio->u.els_logo.els_logo_pyld = dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, &elsio->u.els_logo.els_logo_pyld_dma, GFP_KERNEL); if (!elsio->u.els_logo.els_logo_pyld) { - sp->free(sp); + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); return QLA_FUNCTION_FAILED; } @@ -2651,7 +2736,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { - sp->free(sp); + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); return QLA_FUNCTION_FAILED; } @@ -2662,7 +2748,8 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode, wait_for_completion(&elsio->u.els_logo.comp); - sp->free(sp); + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); return rval; } @@ -2678,27 +2765,30 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->entry_status = 0; els_iocb->handle = sp->handle; els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); - els_iocb->tx_dsd_count = 1; + els_iocb->tx_dsd_count = cpu_to_le16(1); els_iocb->vp_index = vha->vp_idx; els_iocb->sof_type = EST_SOFI3; els_iocb->rx_dsd_count = 0; els_iocb->opcode = elsio->u.els_logo.els_cmd; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; /* For SID the byte order is different than DID */ els_iocb->s_id[1] = vha->d_id.b.al_pa; els_iocb->s_id[2] = vha->d_id.b.area; els_iocb->s_id[0] = vha->d_id.b.domain; if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) { - els_iocb->control_flags = 0; + if (vha->hw->flags.edif_enabled) + els_iocb->control_flags = cpu_to_le16(ECF_SEC_LOGIN); + else + els_iocb->control_flags = 0; els_iocb->tx_byte_count = els_iocb->tx_len = cpu_to_le32(sizeof(struct els_plogi_payload)); put_unaligned_le64(elsio->u.els_plogi.els_plogi_pyld_dma, &els_iocb->tx_address); - els_iocb->rx_dsd_count = 1; + els_iocb->rx_dsd_count = cpu_to_le16(1); els_iocb->rx_byte_count = els_iocb->rx_len = cpu_to_le32(sizeof(struct els_plogi_payload)); put_unaligned_le64(elsio->u.els_plogi.els_resp_pyld_dma, @@ -2710,7 +2800,6 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) (uint8_t *)els_iocb, sizeof(*els_iocb)); } else { - els_iocb->control_flags = 1 << 13; els_iocb->tx_byte_count = cpu_to_le32(sizeof(struct els_logo_payload)); put_unaligned_le64(elsio->u.els_logo.els_logo_pyld_dma, @@ -2730,7 +2819,7 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) sp->vha->qla_stats.control_requests++; } -static void +void qla2x00_els_dcmd2_iocb_timeout(void *data) { srb_t *sp = data; @@ -2785,7 +2874,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) struct qla_work_evt *e; struct fc_port *conflict_fcport; port_id_t cid; /* conflict Nport id */ - u32 *fw_status = sp->u.iocb_cmd.u.els_plogi.fw_status; + const __le32 *fw_status = sp->u.iocb_cmd.u.els_plogi.fw_status; u16 lid; ql_dbg(ql_dbg_disc, vha, 0x3072, @@ -2793,12 +2882,14 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name); fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE); - del_timer(&sp->u.iocb_cmd.timer); + /* For edif, set logout on delete to ensure any residual key from FW is flushed.*/ + fcport->logout_on_delete = 1; + fcport->chip_reset = vha->hw->base_qpair->chip_reset; if (sp->flags & SRB_WAKEUP_ON_COMP) complete(&lio->u.els_plogi.comp); else { - switch (fw_status[0]) { + switch (le32_to_cpu(fw_status[0])) { case CS_DATA_UNDERRUN: case CS_COMPLETE: memset(&ea, 0, sizeof(ea)); @@ -2808,9 +2899,9 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) break; case CS_IOCB_ERROR: - switch (fw_status[1]) { + switch (le32_to_cpu(fw_status[1])) { case LSC_SCODE_PORTID_USED: - lid = fw_status[2] & 0xffff; + lid = le32_to_cpu(fw_status[2]) & 0xffff; qlt_find_sess_invalidate_other(vha, wwn_to_u64(fcport->port_name), fcport->d_id, lid, &conflict_fcport); @@ -2844,9 +2935,11 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) break; case LSC_SCODE_NPORT_USED: - cid.b.domain = (fw_status[2] >> 16) & 0xff; - cid.b.area = (fw_status[2] >> 8) & 0xff; - cid.b.al_pa = fw_status[2] & 0xff; + cid.b.domain = (le32_to_cpu(fw_status[2]) >> 16) + & 0xff; + cid.b.area = (le32_to_cpu(fw_status[2]) >> 8) + & 0xff; + cid.b.al_pa = le32_to_cpu(fw_status[2]) & 0xff; cid.b.rsvd_1 = 0; ql_dbg(ql_dbg_disc, vha, 0x20ec, @@ -2868,8 +2961,9 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); + break; } - /* fall through */ + fallthrough; default: ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %8phC cmd error fw_status 0x%x 0x%x 0x%x\n", @@ -2877,9 +2971,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) fw_status[0], fw_status[1], fw_status[2]); fcport->flags &= ~FCF_ASYNC_SENT; - qla2x00_set_fcport_disc_state(fcport, - DSC_LOGIN_FAILED); - set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + qlt_schedule_sess_for_deletion(fcport); break; } break; @@ -2891,8 +2983,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) fw_status[0], fw_status[1], fw_status[2]); sp->fcport->flags &= ~FCF_ASYNC_SENT; - qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_FAILED); - set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + qlt_schedule_sess_for_deletion(fcport); break; } @@ -2901,7 +2992,8 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) struct srb_iocb *elsio = &sp->u.iocb_cmd; qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi); - sp->free(sp); + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); return; } e->u.iosb.sp = sp; @@ -2919,7 +3011,9 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, int rval = QLA_SUCCESS; void *ptr, *resp_ptr; - /* Alloc SRB structure */ + /* Alloc SRB structure + * ref: INIT + */ sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL); if (!sp) { ql_log(ql_log_info, vha, 0x70e6, @@ -2932,24 +3026,22 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, qla2x00_set_fcport_disc_state(fcport, DSC_LOGIN_PEND); elsio = &sp->u.iocb_cmd; ql_dbg(ql_dbg_io, vha, 0x3073, - "Enter: PLOGI portid=%06x\n", fcport->d_id.b24); + "%s Enter: PLOGI portid=%06x\n", __func__, fcport->d_id.b24); - sp->type = SRB_ELS_DCMD; - sp->name = "ELS_DCMD"; - sp->fcport = fcport; - - elsio->timeout = qla2x00_els_dcmd2_iocb_timeout; - init_completion(&elsio->u.els_plogi.comp); if (wait) sp->flags = SRB_WAKEUP_ON_COMP; - qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT + 2); + sp->type = SRB_ELS_DCMD; + sp->name = "ELS_DCMD"; + sp->fcport = fcport; + qla2x00_init_async_sp(sp, ELS_DCMD_TIMEOUT + 2, + qla2x00_els_dcmd2_sp_done); + sp->u.iocb_cmd.timeout = qla2x00_els_dcmd2_iocb_timeout; - sp->done = qla2x00_els_dcmd2_sp_done; elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE; ptr = elsio->u.els_plogi.els_plogi_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.tx_size, &elsio->u.els_plogi.els_plogi_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_plogi_pyld) { @@ -2958,7 +3050,7 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, } resp_ptr = elsio->u.els_plogi.els_resp_pyld = - dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE, + dma_alloc_coherent(&ha->pdev->dev, elsio->u.els_plogi.rx_size, &elsio->u.els_plogi.els_resp_pyld_dma, GFP_KERNEL); if (!elsio->u.els_plogi.els_resp_pyld) { @@ -2971,17 +3063,23 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, memset(ptr, 0, sizeof(struct els_plogi_payload)); memset(resp_ptr, 0, sizeof(struct els_plogi_payload)); memcpy(elsio->u.els_plogi.els_plogi_pyld->data, - &ha->plogi_els_payld.data, - sizeof(elsio->u.els_plogi.els_plogi_pyld->data)); + &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE); elsio->u.els_plogi.els_cmd = els_opcode; elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode; + if (els_opcode == ELS_DCMD_PLOGI && DBELL_ACTIVE(vha)) { + struct fc_els_flogi *p = ptr; + + p->fl_csp.sp_features |= cpu_to_be16(FC_SP_FT_SEC); + } + ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n"); ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x0109, (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, sizeof(*elsio->u.els_plogi.els_plogi_pyld)); + init_completion(&elsio->u.els_plogi.comp); rval = qla2x00_start_sp(sp); if (rval != QLA_SUCCESS) { rval = QLA_FUNCTION_FAILED; @@ -3004,11 +3102,49 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode, out: fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE); qla2x00_els_dcmd2_free(vha, &elsio->u.els_plogi); - sp->free(sp); + /* ref: INIT */ + kref_put(&sp->cmd_kref, qla2x00_sp_release); done: return rval; } +/* it is assume qpair lock is held */ +void qla_els_pt_iocb(struct scsi_qla_host *vha, + struct els_entry_24xx *els_iocb, + struct qla_els_pt_arg *a) +{ + els_iocb->entry_type = ELS_IOCB_TYPE; + els_iocb->entry_count = 1; + els_iocb->sys_define = 0; + els_iocb->entry_status = 0; + els_iocb->handle = QLA_SKIP_HANDLE; + els_iocb->nport_handle = a->nport_handle; + els_iocb->rx_xchg_address = a->rx_xchg_address; + els_iocb->tx_dsd_count = cpu_to_le16(1); + els_iocb->vp_index = a->vp_idx; + els_iocb->sof_type = EST_SOFI3; + els_iocb->rx_dsd_count = cpu_to_le16(0); + els_iocb->opcode = a->els_opcode; + + els_iocb->d_id[0] = a->did.b.al_pa; + els_iocb->d_id[1] = a->did.b.area; + els_iocb->d_id[2] = a->did.b.domain; + /* For SID the byte order is different than DID */ + els_iocb->s_id[1] = vha->d_id.b.al_pa; + els_iocb->s_id[2] = vha->d_id.b.area; + els_iocb->s_id[0] = vha->d_id.b.domain; + + els_iocb->control_flags = cpu_to_le16(a->control_flags); + + els_iocb->tx_byte_count = cpu_to_le32(a->tx_byte_count); + els_iocb->tx_len = cpu_to_le32(a->tx_len); + put_unaligned_le64(a->tx_addr, &els_iocb->tx_address); + + els_iocb->rx_byte_count = cpu_to_le32(a->rx_byte_count); + els_iocb->rx_len = cpu_to_le32(a->rx_len); + put_unaligned_le64(a->rx_addr, &els_iocb->rx_address); +} + static void qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) { @@ -3020,7 +3156,7 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) els_iocb->sys_define = 0; els_iocb->entry_status = 0; els_iocb->handle = sp->handle; - els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); + els_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); els_iocb->tx_dsd_count = cpu_to_le16(bsg_job->request_payload.sg_cnt); els_iocb->vp_index = sp->vha->vp_idx; els_iocb->sof_type = EST_SOFI3; @@ -3030,9 +3166,9 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) sp->type == SRB_ELS_CMD_RPT ? bsg_request->rqst_data.r_els.els_code : bsg_request->rqst_data.h_els.command_code; - els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; - els_iocb->port_id[1] = sp->fcport->d_id.b.area; - els_iocb->port_id[2] = sp->fcport->d_id.b.domain; + els_iocb->d_id[0] = sp->fcport->d_id.b.al_pa; + els_iocb->d_id[1] = sp->fcport->d_id.b.area; + els_iocb->d_id[2] = sp->fcport->d_id.b.domain; els_iocb->control_flags = 0; els_iocb->rx_byte_count = cpu_to_le32(bsg_job->reply_payload.payload_len); @@ -3214,7 +3350,7 @@ qla82xx_start_scsi(srb_t *sp) uint16_t tot_dsds; struct device_reg_82xx __iomem *reg; uint32_t dbval; - uint32_t *fcp_dl; + __be32 *fcp_dl; uint8_t additional_cdb_len; struct ct6_dsd *ctx; struct scsi_qla_host *vha = sp->vha; @@ -3308,7 +3444,7 @@ sufficient_dsds: req_cnt = 1; if (req->cnt < (req_cnt + 2)) { - cnt = (uint16_t)RD_REG_DWORD_RELAXED( + cnt = (uint16_t)rd_reg_dword_relaxed( ®->req_q_out[0]); if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; @@ -3358,7 +3494,7 @@ sufficient_dsds: } cmd_pkt = (struct cmd_type_6 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0). */ @@ -3396,7 +3532,7 @@ sufficient_dsds: memcpy(ctx->fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); - fcp_dl = (uint32_t *)(ctx->fcp_cmnd->cdb + 16 + + fcp_dl = (__be32 *)(ctx->fcp_cmnd->cdb + 16 + additional_cdb_len); *fcp_dl = htonl((uint32_t)scsi_bufflen(cmd)); @@ -3417,7 +3553,7 @@ sufficient_dsds: req_cnt = qla24xx_calc_iocbs(vha, tot_dsds); if (req->cnt < (req_cnt + 2)) { - cnt = (uint16_t)RD_REG_DWORD_RELAXED( + cnt = (uint16_t)rd_reg_dword_relaxed( ®->req_q_out[0]); if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; @@ -3429,7 +3565,7 @@ sufficient_dsds: goto queuing_error; cmd_pkt = (struct cmd_type_7 *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ @@ -3493,10 +3629,10 @@ sufficient_dsds: if (ql2xdbwr) qla82xx_wr_32(ha, (uintptr_t __force)ha->nxdb_wr_ptr, dbval); else { - WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval); + wrt_reg_dword(ha->nxdb_wr_ptr, dbval); wmb(); - while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { - WRT_REG_DWORD(ha->nxdb_wr_ptr, dbval); + while (rd_reg_dword(ha->nxdb_rd_ptr) != dbval) { + wrt_reg_dword(ha->nxdb_wr_ptr, dbval); wmb(); } } @@ -3530,11 +3666,12 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) struct srb_iocb *aio = &sp->u.iocb_cmd; scsi_qla_host_t *vha = sp->vha; struct req_que *req = sp->qpair->req; + srb_t *orig_sp = sp->cmd_sp; memset(abt_iocb, 0, sizeof(struct abort_entry_24xx)); abt_iocb->entry_type = ABORT_IOCB_TYPE; abt_iocb->entry_count = 1; - abt_iocb->handle = cpu_to_le32(MAKE_HANDLE(req->id, sp->handle)); + abt_iocb->handle = make_handle(req->id, sp->handle); if (sp->fcport) { abt_iocb->nport_handle = cpu_to_le16(sp->fcport->loop_id); abt_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; @@ -3542,10 +3679,15 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb) abt_iocb->port_id[2] = sp->fcport->d_id.b.domain; } abt_iocb->handle_to_abort = - cpu_to_le32(MAKE_HANDLE(aio->u.abt.req_que_no, - aio->u.abt.cmd_hndl)); + make_handle(le16_to_cpu(aio->u.abt.req_que_no), + aio->u.abt.cmd_hndl); abt_iocb->vp_index = vha->vp_idx; - abt_iocb->req_que_no = cpu_to_le16(aio->u.abt.req_que_no); + abt_iocb->req_que_no = aio->u.abt.req_que_no; + + /* need to pass original sp */ + if (orig_sp) + qla_nvme_abort_set_option(abt_iocb, orig_sp); + /* Send the command to the firmware */ wmb(); } @@ -3560,7 +3702,7 @@ qla2x00_mb_iocb(srb_t *sp, struct mbx_24xx_entry *mbx) sz = min(ARRAY_SIZE(mbx->mb), ARRAY_SIZE(sp->u.iocb_cmd.u.mbx.out_mb)); for (i = 0; i < sz; i++) - mbx->mb[i] = cpu_to_le16(sp->u.iocb_cmd.u.mbx.out_mb[i]); + mbx->mb[i] = sp->u.iocb_cmd.u.mbx.out_mb[i]; } static void @@ -3584,7 +3726,7 @@ static void qla2x00_send_notify_ack_iocb(srb_t *sp, nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle; if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) { nack->u.isp24.flags = ntfy->u.isp24.flags & - cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB); + cpu_to_le16(NOTIFY24XX_FLAGS_PUREX_IOCB); } nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id; nack->u.isp24.status = ntfy->u.isp24.status; @@ -3597,37 +3739,44 @@ static void qla2x00_send_notify_ack_iocb(srb_t *sp, nack->u.isp24.srr_reject_code = 0; nack->u.isp24.srr_reject_code_expl = 0; nack->u.isp24.vp_index = ntfy->u.isp24.vp_index; + + if (ntfy->u.isp24.status_subcode == ELS_PLOGI && + (le16_to_cpu(ntfy->u.isp24.flags) & NOTIFY24XX_FLAGS_FCSP) && + sp->vha->hw->flags.edif_enabled) { + ql_dbg(ql_dbg_disc, sp->vha, 0x3074, + "%s PLOGI NACK sent with FC SECURITY bit, hdl=%x, loopid=%x, to pid %06x\n", + sp->name, sp->handle, sp->fcport->loop_id, + sp->fcport->d_id.b24); + nack->u.isp24.flags |= cpu_to_le16(NOTIFY_ACK_FLAGS_FCSP); + } } /* * Build NVME LS request */ -static int +static void qla_nvme_ls(srb_t *sp, struct pt_ls4_request *cmd_pkt) { struct srb_iocb *nvme; - int rval = QLA_SUCCESS; nvme = &sp->u.iocb_cmd; cmd_pkt->entry_type = PT_LS4_REQUEST; cmd_pkt->entry_count = 1; - cmd_pkt->control_flags = CF_LS4_ORIGINATOR << CF_LS4_SHIFT; + cmd_pkt->control_flags = cpu_to_le16(CF_LS4_ORIGINATOR << CF_LS4_SHIFT); cmd_pkt->timeout = cpu_to_le16(nvme->u.nvme.timeout_sec); cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); cmd_pkt->vp_index = sp->fcport->vha->vp_idx; - cmd_pkt->tx_dseg_count = 1; - cmd_pkt->tx_byte_count = nvme->u.nvme.cmd_len; - cmd_pkt->dsd[0].length = nvme->u.nvme.cmd_len; + cmd_pkt->tx_dseg_count = cpu_to_le16(1); + cmd_pkt->tx_byte_count = cpu_to_le32(nvme->u.nvme.cmd_len); + cmd_pkt->dsd[0].length = cpu_to_le32(nvme->u.nvme.cmd_len); put_unaligned_le64(nvme->u.nvme.cmd_dma, &cmd_pkt->dsd[0].address); - cmd_pkt->rx_dseg_count = 1; - cmd_pkt->rx_byte_count = nvme->u.nvme.rsp_len; - cmd_pkt->dsd[1].length = nvme->u.nvme.rsp_len; + cmd_pkt->rx_dseg_count = cpu_to_le16(1); + cmd_pkt->rx_byte_count = cpu_to_le32(nvme->u.nvme.rsp_len); + cmd_pkt->dsd[1].length = cpu_to_le32(nvme->u.nvme.rsp_len); put_unaligned_le64(nvme->u.nvme.rsp_dma, &cmd_pkt->dsd[1].address); - - return rval; } static void @@ -3674,6 +3823,9 @@ qla2x00_start_sp(srb_t *sp) void *pkt; unsigned long flags; + if (vha->hw->flags.eeh_busy) + return -EIO; + spin_lock_irqsave(qp->qp_lock_ptr, flags); pkt = __qla2x00_alloc_iocbs(sp->qpair, sp); if (!pkt) { @@ -3701,6 +3853,10 @@ qla2x00_start_sp(srb_t *sp) case SRB_ELS_CMD_HST: qla24xx_els_iocb(sp, pkt); break; + case SRB_ELS_CMD_HST_NOLOGIN: + qla_els_pt_iocb(sp->vha, pkt, &sp->u.bsg_cmd.u.els_arg); + ((struct els_entry_24xx *)pkt)->handle = sp->handle; + break; case SRB_CT_CMD: IS_FWI2_CAPABLE(ha) ? qla24xx_ct_iocb(sp, pkt) : @@ -3748,12 +3904,25 @@ qla2x00_start_sp(srb_t *sp) case SRB_PRLO_CMD: qla24xx_prlo_iocb(sp, pkt); break; + case SRB_SA_UPDATE: + qla24xx_sa_update_iocb(sp, pkt); + break; + case SRB_SA_REPLACE: + qla24xx_sa_replace_iocb(sp, pkt); + break; default: break; } - if (sp->start_timer) + if (sp->start_timer) { + /* ref: TMR timer ref + * this code should be just before start_iocbs function + * This will make sure that caller function don't to do + * kref_put even on failure + */ + kref_get(&sp->cmd_kref); add_timer(&sp->u.iocb_cmd.timer); + } wmb(); qla2x00_start_iocbs(vha, qp->req); @@ -3891,8 +4060,14 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) /* Check for room on request queue. */ if (req->cnt < req_cnt + 2) { - cnt = IS_SHADOW_REG_CAPABLE(ha) ? *req->out_ptr : - RD_REG_DWORD_RELAXED(req->req_q_out); + if (IS_SHADOW_REG_CAPABLE(ha)) { + cnt = *req->out_ptr; + } else { + cnt = rd_reg_dword_relaxed(req->req_q_out); + if (qla2x00_check_reg16_for_disconnect(vha, cnt)) + goto queuing_error; + } + if (req->ring_index < cnt) req->cnt = cnt - req->ring_index; else @@ -3905,7 +4080,7 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) } cmd_pkt = (struct cmd_bidir *)req->ring_ptr; - cmd_pkt->handle = MAKE_HANDLE(req->id, handle); + cmd_pkt->handle = make_handle(req->id, handle); /* Zero out remaining portion of packet. */ /* tagged queuing modifier -- default is TSK_SIMPLE (0).*/ @@ -3931,5 +4106,6 @@ qla2x00_start_bidir(srb_t *sp, struct scsi_qla_host *vha, uint32_t tot_dsds) qla2x00_start_iocbs(vha, req); queuing_error: spin_unlock_irqrestore(&ha->hardware_lock, flags); + return rval; } |