diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 125 |
1 files changed, 71 insertions, 54 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 8523b278ec9d..243de1d324b7 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1,7 +1,7 @@ /******************************************************************* * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters. * - * Copyright (C) 2004-2012 Emulex. All rights reserved. * + * Copyright (C) 2004-2013 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex. * * www.emulex.com * * Portions Copyright (C) 2004-2005 Christoph Hellwig * @@ -68,14 +68,12 @@ struct scsi_dif_tuple { __be32 ref_tag; /* Target LBA or indirect LBA */ }; -#if !defined(SCSI_PROT_GUARD_CHECK) || !defined(SCSI_PROT_REF_CHECK) -#define scsi_prot_flagged(sc, flg) sc -#endif - static void lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); static void lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); +static int +lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc); static void lpfc_debug_save_data(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) @@ -134,6 +132,30 @@ lpfc_debug_save_dif(struct lpfc_hba *phba, struct scsi_cmnd *cmnd) } } +static inline unsigned +lpfc_cmd_blksize(struct scsi_cmnd *sc) +{ + return sc->device->sector_size; +} + +#define LPFC_CHECK_PROTECT_GUARD 1 +#define LPFC_CHECK_PROTECT_REF 2 +static inline unsigned +lpfc_cmd_protect(struct scsi_cmnd *sc, int flag) +{ + return 1; +} + +static inline unsigned +lpfc_cmd_guard_csum(struct scsi_cmnd *sc) +{ + if (lpfc_prot_group_type(NULL, sc) == LPFC_PG_TYPE_NO_DIF) + return 0; + if (scsi_host_get_guard(sc->device->host) == SHOST_DIX_GUARD_IP) + return 1; + return 0; +} + /** * lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge. * @phba: Pointer to HBA object. @@ -1144,13 +1166,14 @@ lpfc_get_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) static struct lpfc_scsi_buf* lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) { - struct lpfc_scsi_buf *lpfc_cmd ; + struct lpfc_scsi_buf *lpfc_cmd, *lpfc_cmd_next; unsigned long gflag = 0; unsigned long pflag = 0; int found = 0; spin_lock_irqsave(&phba->scsi_buf_list_get_lock, gflag); - list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get, list) { + list_for_each_entry_safe(lpfc_cmd, lpfc_cmd_next, + &phba->lpfc_scsi_buf_list_get, list) { if (lpfc_test_rrq_active(phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag)) continue; @@ -1164,8 +1187,8 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) &phba->lpfc_scsi_buf_list_get); INIT_LIST_HEAD(&phba->lpfc_scsi_buf_list_put); spin_unlock_irqrestore(&phba->scsi_buf_list_put_lock, pflag); - list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list_get, - list) { + list_for_each_entry_safe(lpfc_cmd, lpfc_cmd_next, + &phba->lpfc_scsi_buf_list_get, list) { if (lpfc_test_rrq_active( phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag)) continue; @@ -1409,12 +1432,6 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) return 0; } -static inline unsigned -lpfc_cmd_blksize(struct scsi_cmnd *sc) -{ - return sc->device->sector_size; -} - #ifdef CONFIG_SCSI_LPFC_DEBUG_FS /* Return if if error injection is detected by Initiator */ @@ -1847,10 +1864,9 @@ static int lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, uint8_t *txop, uint8_t *rxop) { - uint8_t guard_type = scsi_host_get_guard(sc->device->host); uint8_t ret = 0; - if (guard_type == SHOST_DIX_GUARD_IP) { + if (lpfc_cmd_guard_csum(sc)) { switch (scsi_get_prot_op(sc)) { case SCSI_PROT_READ_INSERT: case SCSI_PROT_WRITE_STRIP: @@ -1928,10 +1944,9 @@ static int lpfc_bg_err_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, uint8_t *txop, uint8_t *rxop) { - uint8_t guard_type = scsi_host_get_guard(sc->device->host); uint8_t ret = 0; - if (guard_type == SHOST_DIX_GUARD_IP) { + if (lpfc_cmd_guard_csum(sc)) { switch (scsi_get_prot_op(sc)) { case SCSI_PROT_READ_INSERT: case SCSI_PROT_WRITE_STRIP: @@ -2078,12 +2093,12 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, * protection data is automatically generated, not checked. */ if (datadir == DMA_FROM_DEVICE) { - if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD)) bf_set(pde6_ce, pde6, checking); else bf_set(pde6_ce, pde6, 0); - if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF)) bf_set(pde6_re, pde6, checking); else bf_set(pde6_re, pde6, 0); @@ -2240,12 +2255,12 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, bf_set(pde6_optx, pde6, txop); bf_set(pde6_oprx, pde6, rxop); - if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD)) bf_set(pde6_ce, pde6, checking); else bf_set(pde6_ce, pde6, 0); - if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF)) bf_set(pde6_re, pde6, checking); else bf_set(pde6_re, pde6, 0); @@ -2454,12 +2469,12 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, * protection data is automatically generated, not checked. */ if (sc->sc_data_direction == DMA_FROM_DEVICE) { - if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD)) bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); else bf_set(lpfc_sli4_sge_dif_ce, diseed, 0); - if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF)) bf_set(lpfc_sli4_sge_dif_re, diseed, checking); else bf_set(lpfc_sli4_sge_dif_re, diseed, 0); @@ -2610,7 +2625,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, diseed->ref_tag = cpu_to_le32(reftag); diseed->ref_tag_tran = diseed->ref_tag; - if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) { + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_GUARD)) { bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); } else { @@ -2629,7 +2644,7 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, } - if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) + if (lpfc_cmd_protect(sc, LPFC_CHECK_PROTECT_REF)) bf_set(lpfc_sli4_sge_dif_re, diseed, checking); else bf_set(lpfc_sli4_sge_dif_re, diseed, 0); @@ -2792,11 +2807,12 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc) ret = LPFC_PG_TYPE_DIF_BUF; break; default: - lpfc_printf_log(phba, KERN_ERR, LOG_FCP, - "9021 Unsupported protection op:%d\n", op); + if (phba) + lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + "9021 Unsupported protection op:%d\n", + op); break; } - return ret; } @@ -2821,22 +2837,22 @@ lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba, /* Check if there is protection data on the wire */ if (sc->sc_data_direction == DMA_FROM_DEVICE) { - /* Read */ + /* Read check for protection data */ if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT) return fcpdl; } else { - /* Write */ + /* Write check for protection data */ if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP) return fcpdl; } /* * If we are in DIF Type 1 mode every data block has a 8 byte - * DIF (trailer) attached to it. Must ajust FCP data length. + * DIF (trailer) attached to it. Must ajust FCP data length + * to account for the protection data. */ - if (scsi_prot_flagged(sc, SCSI_PROT_TRANSFER_PI)) - fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8; + fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8; return fcpdl; } @@ -3073,9 +3089,9 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) chk_guard = 1; guard_type = scsi_host_get_guard(cmd->device->host); + src = (struct scsi_dif_tuple *)sg_virt(sgpe); start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */ start_app_tag = src->app_tag; - src = (struct scsi_dif_tuple *)sg_virt(sgpe); len = sgpe->length; while (src && protsegcnt) { while (len) { @@ -3090,25 +3106,10 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) goto skipit; } - /* App Tag checking */ - app_tag = src->app_tag; - if (chk_app && (app_tag != start_app_tag)) { - err_type = BGS_APPTAG_ERR_MASK; - goto out; - } - - /* Reference Tag checking */ - ref_tag = be32_to_cpu(src->ref_tag); - if (chk_ref && (ref_tag != start_ref_tag)) { - err_type = BGS_REFTAG_ERR_MASK; - goto out; - } - start_ref_tag++; - - /* Guard Tag checking */ + /* First Guard Tag checking */ if (chk_guard) { guard_tag = src->guard_tag; - if (guard_type == SHOST_DIX_GUARD_IP) + if (lpfc_cmd_guard_csum(cmd)) sum = lpfc_bg_csum(data_src, blksize); else @@ -3119,6 +3120,21 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) goto out; } } + + /* Reference Tag checking */ + ref_tag = be32_to_cpu(src->ref_tag); + if (chk_ref && (ref_tag != start_ref_tag)) { + err_type = BGS_REFTAG_ERR_MASK; + goto out; + } + start_ref_tag++; + + /* App Tag checking */ + app_tag = src->app_tag; + if (chk_app && (app_tag != start_app_tag)) { + err_type = BGS_APPTAG_ERR_MASK; + goto out; + } skipit: len -= sizeof(struct scsi_dif_tuple); if (len < 0) @@ -4074,7 +4090,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, cmd->device ? cmd->device->id : 0xffff, cmd->device ? cmd->device->lun : 0xffff, lpfc_cmd->status, lpfc_cmd->result, - vport->fc_myDID, pnode->nlp_DID, + vport->fc_myDID, + (pnode) ? pnode->nlp_DID : 0, phba->sli_rev == LPFC_SLI_REV4 ? lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, pIocbOut->iocb.ulpContext, |