aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c125
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,