mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-06 13:16:22 +00:00
scsi: lpfc: Add support for 32 byte CDBs
The driver's I/O path is updated to support 32 byte CDBs. Changes to accommodate 32 byte CDBs include: - Updating various size fields to allow for the larger 32 byte CDB. - Starting the FCP command payload at an earlier offset in WQE submission to fit the 32 byte CDB. - Redefining relevant structs to __le32/__be32 data types for proper cpu endianness macro usage. Signed-off-by: Justin Tee <justin.tee@broadcom.com> Link: https://lore.kernel.org/r/20240429221547.6842-7-justintee8345@gmail.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
e780c9423b
commit
af20bb73ac
@ -2146,6 +2146,14 @@ struct sli4_sge { /* SLI-4 */
|
||||
uint32_t sge_len;
|
||||
};
|
||||
|
||||
struct sli4_sge_le {
|
||||
__le32 addr_hi;
|
||||
__le32 addr_lo;
|
||||
|
||||
__le32 word2;
|
||||
__le32 sge_len;
|
||||
};
|
||||
|
||||
struct sli4_hybrid_sgl {
|
||||
struct list_head list_node;
|
||||
struct sli4_sge *dma_sgl;
|
||||
|
@ -4773,7 +4773,10 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
|
||||
shost->max_id = LPFC_MAX_TARGET;
|
||||
shost->max_lun = vport->cfg_max_luns;
|
||||
shost->this_id = -1;
|
||||
shost->max_cmd_len = 16;
|
||||
if (phba->sli_rev == LPFC_SLI_REV4)
|
||||
shost->max_cmd_len = LPFC_FCP_CDB_LEN_32;
|
||||
else
|
||||
shost->max_cmd_len = LPFC_FCP_CDB_LEN;
|
||||
|
||||
if (phba->sli_rev == LPFC_SLI_REV4) {
|
||||
if (!phba->cfg_fcp_mq_threshold ||
|
||||
@ -8231,7 +8234,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
* our max amount and we need to limit lpfc_sg_seg_cnt
|
||||
* to minimize the risk of running out.
|
||||
*/
|
||||
phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
|
||||
phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd32) +
|
||||
sizeof(struct fcp_rsp) + max_buf_size;
|
||||
|
||||
/* Total SGEs for scsi_sg_list and scsi_sg_prot_list */
|
||||
@ -8253,7 +8256,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
* the FCP rsp, a SGE for each, and a SGE for up to
|
||||
* cfg_sg_seg_cnt data segments.
|
||||
*/
|
||||
phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd) +
|
||||
phba->cfg_sg_dma_buf_size = sizeof(struct fcp_cmnd32) +
|
||||
sizeof(struct fcp_rsp) +
|
||||
((phba->cfg_sg_seg_cnt + extra) *
|
||||
sizeof(struct sli4_sge));
|
||||
@ -8316,7 +8319,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
|
||||
phba->lpfc_cmd_rsp_buf_pool =
|
||||
dma_pool_create("lpfc_cmd_rsp_buf_pool",
|
||||
&phba->pcidev->dev,
|
||||
sizeof(struct fcp_cmnd) +
|
||||
sizeof(struct fcp_cmnd32) +
|
||||
sizeof(struct fcp_rsp),
|
||||
i, 0);
|
||||
if (!phba->lpfc_cmd_rsp_buf_pool) {
|
||||
|
@ -600,7 +600,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
|
||||
{
|
||||
struct lpfc_io_buf *lpfc_cmd;
|
||||
struct lpfc_sli4_hdw_queue *qp;
|
||||
struct sli4_sge *sgl;
|
||||
struct sli4_sge_le *sgl;
|
||||
dma_addr_t pdma_phys_fcp_rsp;
|
||||
dma_addr_t pdma_phys_fcp_cmd;
|
||||
uint32_t cpu, idx;
|
||||
@ -651,23 +651,23 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
|
||||
* The balance are sg list bdes. Initialize the
|
||||
* first two and leave the rest for queuecommand.
|
||||
*/
|
||||
sgl = (struct sli4_sge *)lpfc_cmd->dma_sgl;
|
||||
sgl = (struct sli4_sge_le *)lpfc_cmd->dma_sgl;
|
||||
pdma_phys_fcp_cmd = tmp->fcp_cmd_rsp_dma_handle;
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_cmd));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_cmd));
|
||||
sgl->word2 = le32_to_cpu(sgl->word2);
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 0);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd));
|
||||
bf_set_le32(lpfc_sli4_sge_last, sgl, 0);
|
||||
if (cmnd && cmnd->cmd_len > LPFC_FCP_CDB_LEN)
|
||||
sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd32));
|
||||
else
|
||||
sgl->sge_len = cpu_to_le32(sizeof(struct fcp_cmnd));
|
||||
|
||||
sgl++;
|
||||
|
||||
/* Setup the physical region for the FCP RSP */
|
||||
pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd);
|
||||
pdma_phys_fcp_rsp = pdma_phys_fcp_cmd + sizeof(struct fcp_cmnd32);
|
||||
sgl->addr_hi = cpu_to_le32(putPaddrHigh(pdma_phys_fcp_rsp));
|
||||
sgl->addr_lo = cpu_to_le32(putPaddrLow(pdma_phys_fcp_rsp));
|
||||
sgl->word2 = le32_to_cpu(sgl->word2);
|
||||
bf_set(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->word2 = cpu_to_le32(sgl->word2);
|
||||
bf_set_le32(lpfc_sli4_sge_last, sgl, 1);
|
||||
sgl->sge_len = cpu_to_le32(sizeof(struct fcp_rsp));
|
||||
|
||||
if (lpfc_ndlp_check_qdepth(phba, ndlp)) {
|
||||
@ -2608,7 +2608,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba,
|
||||
iocb_cmd->ulpLe = 1;
|
||||
|
||||
fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
|
||||
fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
|
||||
fcp_cmnd->fcpDl = cpu_to_be32(fcpdl);
|
||||
|
||||
/*
|
||||
* Due to difference in data length between DIF/non-DIF paths,
|
||||
@ -3225,14 +3225,18 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
|
||||
* explicitly reinitialized.
|
||||
* all iocb memory resources are reused.
|
||||
*/
|
||||
fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
|
||||
if (scsi_cmnd->cmd_len > LPFC_FCP_CDB_LEN)
|
||||
((struct fcp_cmnd32 *)fcp_cmnd)->fcpDl =
|
||||
cpu_to_be32(scsi_bufflen(scsi_cmnd));
|
||||
else
|
||||
fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
|
||||
/* Set first-burst provided it was successfully negotiated */
|
||||
if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag) &&
|
||||
vport->cfg_first_burst_size &&
|
||||
scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) {
|
||||
u32 init_len, total_len;
|
||||
|
||||
total_len = be32_to_cpu(fcp_cmnd->fcpDl);
|
||||
total_len = scsi_bufflen(scsi_cmnd);
|
||||
init_len = min(total_len, vport->cfg_first_burst_size);
|
||||
|
||||
/* Word 4 & 5 */
|
||||
@ -3420,7 +3424,10 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
|
||||
}
|
||||
|
||||
fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd);
|
||||
fcp_cmnd->fcpDl = be32_to_cpu(fcpdl);
|
||||
if (lpfc_cmd->pCmd->cmd_len > LPFC_FCP_CDB_LEN)
|
||||
((struct fcp_cmnd32 *)fcp_cmnd)->fcpDl = cpu_to_be32(fcpdl);
|
||||
else
|
||||
fcp_cmnd->fcpDl = cpu_to_be32(fcpdl);
|
||||
|
||||
/* Set first-burst provided it was successfully negotiated */
|
||||
if (!test_bit(HBA_FCOE_MODE, &phba->hba_flag) &&
|
||||
@ -3428,7 +3435,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
|
||||
scsi_cmnd->sc_data_direction == DMA_TO_DEVICE) {
|
||||
u32 init_len, total_len;
|
||||
|
||||
total_len = be32_to_cpu(fcp_cmnd->fcpDl);
|
||||
total_len = fcpdl;
|
||||
init_len = min(total_len, vport->cfg_first_burst_size);
|
||||
|
||||
/* Word 4 & 5 */
|
||||
@ -3436,8 +3443,7 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba,
|
||||
wqe->fcp_iwrite.total_xfer_len = total_len;
|
||||
} else {
|
||||
/* Word 4 */
|
||||
wqe->fcp_iwrite.total_xfer_len =
|
||||
be32_to_cpu(fcp_cmnd->fcpDl);
|
||||
wqe->fcp_iwrite.total_xfer_len = fcpdl;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3894,7 +3900,10 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
|
||||
fcprsp->rspInfo3);
|
||||
|
||||
scsi_set_resid(cmnd, 0);
|
||||
fcpDl = be32_to_cpu(fcpcmd->fcpDl);
|
||||
if (cmnd->cmd_len > LPFC_FCP_CDB_LEN)
|
||||
fcpDl = be32_to_cpu(((struct fcp_cmnd32 *)fcpcmd)->fcpDl);
|
||||
else
|
||||
fcpDl = be32_to_cpu(fcpcmd->fcpDl);
|
||||
if (resp_info & RESID_UNDER) {
|
||||
scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId));
|
||||
|
||||
@ -4723,6 +4732,14 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
|
||||
bf_set(wqe_iod, &wqe->fcp_iread.wqe_com,
|
||||
LPFC_WQE_IOD_NONE);
|
||||
}
|
||||
|
||||
/* Additional fcp cdb length field calculation.
|
||||
* LPFC_FCP_CDB_LEN_32 - normal 16 byte cdb length,
|
||||
* then divide by 4 for the word count.
|
||||
* shift 2 because of the RDDATA/WRDATA.
|
||||
*/
|
||||
if (scsi_cmnd->cmd_len > LPFC_FCP_CDB_LEN)
|
||||
fcp_cmnd->fcpCntl3 |= 4 << 2;
|
||||
} else {
|
||||
/* From the icmnd template, initialize words 4 - 11 */
|
||||
memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
|
||||
@ -4743,7 +4760,7 @@ static int lpfc_scsi_prep_cmnd_buf_s4(struct lpfc_vport *vport,
|
||||
|
||||
/* Word 3 */
|
||||
bf_set(payload_offset_len, &wqe->fcp_icmd,
|
||||
sizeof(struct fcp_cmnd) + sizeof(struct fcp_rsp));
|
||||
sizeof(struct fcp_cmnd32) + sizeof(struct fcp_rsp));
|
||||
|
||||
/* Word 6 */
|
||||
bf_set(wqe_ctxt_tag, &wqe->generic.wqe_com,
|
||||
@ -4798,7 +4815,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_io_buf *lpfc_cmd,
|
||||
int_to_scsilun(lpfc_cmd->pCmd->device->lun,
|
||||
&lpfc_cmd->fcp_cmnd->fcp_lun);
|
||||
|
||||
ptr = &fcp_cmnd->fcpCdb[0];
|
||||
ptr = &((struct fcp_cmnd32 *)fcp_cmnd)->fcpCdb[0];
|
||||
memcpy(ptr, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
|
||||
if (scsi_cmnd->cmd_len < LPFC_FCP_CDB_LEN) {
|
||||
ptr += scsi_cmnd->cmd_len;
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
struct lpfc_hba;
|
||||
#define LPFC_FCP_CDB_LEN 16
|
||||
#define LPFC_FCP_CDB_LEN_32 32
|
||||
|
||||
#define list_remove_head(list, entry, type, member) \
|
||||
do { \
|
||||
@ -99,17 +100,11 @@ struct fcp_rsp {
|
||||
#define SNSCOD_BADCMD 0x20 /* sense code is byte 13 ([12]) */
|
||||
};
|
||||
|
||||
struct fcp_cmnd {
|
||||
struct scsi_lun fcp_lun;
|
||||
|
||||
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
|
||||
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
|
||||
#define SIMPLE_Q 0x00
|
||||
#define HEAD_OF_Q 0x01
|
||||
#define ORDERED_Q 0x02
|
||||
#define ACA_Q 0x04
|
||||
#define UNTAGGED 0x05
|
||||
uint8_t fcpCntl2; /* FCP_CTL byte 2 task management codes */
|
||||
#define FCP_ABORT_TASK_SET 0x02 /* Bit 1 */
|
||||
#define FCP_CLEAR_TASK_SET 0x04 /* bit 2 */
|
||||
#define FCP_BUS_RESET 0x08 /* bit 3 */
|
||||
@ -117,12 +112,31 @@ struct fcp_cmnd {
|
||||
#define FCP_TARGET_RESET 0x20 /* bit 5 */
|
||||
#define FCP_CLEAR_ACA 0x40 /* bit 6 */
|
||||
#define FCP_TERMINATE_TASK 0x80 /* bit 7 */
|
||||
uint8_t fcpCntl3;
|
||||
#define WRITE_DATA 0x01 /* Bit 0 */
|
||||
#define READ_DATA 0x02 /* Bit 1 */
|
||||
|
||||
struct fcp_cmnd {
|
||||
struct scsi_lun fcp_lun;
|
||||
|
||||
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
|
||||
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
|
||||
uint8_t fcpCntl2; /* FCP_CTL byte 2 task management codes */
|
||||
uint8_t fcpCntl3;
|
||||
|
||||
uint8_t fcpCdb[LPFC_FCP_CDB_LEN]; /* SRB cdb field is copied here */
|
||||
uint32_t fcpDl; /* Total transfer length */
|
||||
__be32 fcpDl; /* Total transfer length */
|
||||
|
||||
};
|
||||
struct fcp_cmnd32 {
|
||||
struct scsi_lun fcp_lun;
|
||||
|
||||
uint8_t fcpCntl0; /* FCP_CNTL byte 0 (reserved) */
|
||||
uint8_t fcpCntl1; /* FCP_CNTL byte 1 task codes */
|
||||
uint8_t fcpCntl2; /* FCP_CTL byte 2 task management codes */
|
||||
uint8_t fcpCntl3;
|
||||
|
||||
uint8_t fcpCdb[LPFC_FCP_CDB_LEN_32]; /* SRB cdb field is copied here */
|
||||
__be32 fcpDl; /* Total transfer length */
|
||||
|
||||
};
|
||||
|
||||
|
@ -10595,18 +10595,18 @@ lpfc_prep_embed_io(struct lpfc_hba *phba, struct lpfc_io_buf *lpfc_cmd)
|
||||
BUFF_TYPE_BDE_IMMED;
|
||||
wqe->generic.bde.tus.f.bdeSize = sgl->sge_len;
|
||||
wqe->generic.bde.addrHigh = 0;
|
||||
wqe->generic.bde.addrLow = 88; /* Word 22 */
|
||||
wqe->generic.bde.addrLow = 72; /* Word 18 */
|
||||
|
||||
bf_set(wqe_wqes, &wqe->fcp_iwrite.wqe_com, 1);
|
||||
bf_set(wqe_dbde, &wqe->fcp_iwrite.wqe_com, 0);
|
||||
|
||||
/* Word 22-29 FCP CMND Payload */
|
||||
ptr = &wqe->words[22];
|
||||
memcpy(ptr, fcp_cmnd, sizeof(struct fcp_cmnd));
|
||||
/* Word 18-29 FCP CMND Payload */
|
||||
ptr = &wqe->words[18];
|
||||
memcpy(ptr, fcp_cmnd, sgl->sge_len);
|
||||
} else {
|
||||
/* Word 0-2 - Inline BDE */
|
||||
wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_64;
|
||||
wqe->generic.bde.tus.f.bdeSize = sizeof(struct fcp_cmnd);
|
||||
wqe->generic.bde.tus.f.bdeSize = sgl->sge_len;
|
||||
wqe->generic.bde.addrHigh = sgl->addr_hi;
|
||||
wqe->generic.bde.addrLow = sgl->addr_lo;
|
||||
|
||||
@ -22469,7 +22469,7 @@ lpfc_get_cmd_rsp_buf_per_hdwq(struct lpfc_hba *phba,
|
||||
}
|
||||
|
||||
tmp->fcp_rsp = (struct fcp_rsp *)((uint8_t *)tmp->fcp_cmnd +
|
||||
sizeof(struct fcp_cmnd));
|
||||
sizeof(struct fcp_cmnd32));
|
||||
|
||||
spin_lock_irqsave(&hdwq->hdwq_lock, iflags);
|
||||
list_add_tail(&tmp->list_node, &lpfc_buf->dma_cmd_rsp_list);
|
||||
|
Loading…
Reference in New Issue
Block a user