Commit bad75002 authored by Arun Easi's avatar Arun Easi Committed by James Bottomley

[SCSI] qla2xxx: T10 DIF support added.

Signed-off-by: default avatarDuane Grigsby <duane.grigsby@qlogic.com>
Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 3822263e
......@@ -1726,6 +1726,22 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable)
fc_vport_set_state(fc_vport, FC_VPORT_LINKDOWN);
}
if (IS_QLA25XX(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4) {
vha->flags.difdix_supported = 1;
DEBUG18(qla_printk(KERN_INFO, ha,
"Registering for DIF/DIX type 1 and 3"
" protection.\n"));
scsi_host_set_prot(vha->host,
SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE3_PROTECTION
| SHOST_DIX_TYPE1_PROTECTION
| SHOST_DIX_TYPE3_PROTECTION);
scsi_host_set_guard(vha->host, SHOST_DIX_GUARD_CRC);
} else
vha->flags.difdix_supported = 0;
}
if (scsi_add_host_with_dma(vha->host, &fc_vport->dev,
&ha->pdev->dev)) {
DEBUG15(printk("scsi(%ld): scsi_add_host failure for VP[%d].\n",
......
......@@ -1663,4 +1663,62 @@ qla2x00_dump_buffer(uint8_t * b, uint32_t size)
printk("\n");
}
void
qla2x00_dump_buffer_zipped(uint8_t *b, uint32_t size)
{
uint32_t cnt;
uint8_t c;
uint8_t last16[16], cur16[16];
uint32_t lc = 0, num_same16 = 0, j;
printk(KERN_DEBUG " 0 1 2 3 4 5 6 7 8 9 "
"Ah Bh Ch Dh Eh Fh\n");
printk(KERN_DEBUG "----------------------------------------"
"----------------------\n");
for (cnt = 0; cnt < size;) {
c = *b++;
cur16[lc++] = c;
cnt++;
if (cnt % 16)
continue;
/* We have 16 now */
lc = 0;
if (num_same16 == 0) {
memcpy(last16, cur16, 16);
num_same16++;
continue;
}
if (memcmp(cur16, last16, 16) == 0) {
num_same16++;
continue;
}
for (j = 0; j < 16; j++)
printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]);
printk(KERN_DEBUG "\n");
if (num_same16 > 1)
printk(KERN_DEBUG "> prev pattern repeats (%u)"
"more times\n", num_same16-1);
memcpy(last16, cur16, 16);
num_same16 = 1;
}
if (num_same16) {
for (j = 0; j < 16; j++)
printk(KERN_DEBUG "%02x ", (uint32_t)last16[j]);
printk(KERN_DEBUG "\n");
if (num_same16 > 1)
printk(KERN_DEBUG "> prev pattern repeats (%u)"
"more times\n", num_same16-1);
}
if (lc) {
for (j = 0; j < lc; j++)
printk(KERN_DEBUG "%02x ", (uint32_t)cur16[j]);
printk(KERN_DEBUG "\n");
}
}
......@@ -27,6 +27,9 @@
/* #define QL_DEBUG_LEVEL_15 */ /* Output NPIV trace msgs */
/* #define QL_DEBUG_LEVEL_16 */ /* Output ISP84XX trace msgs */
/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */
/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */
/*
* Macros use for debugging the driver.
......@@ -139,6 +142,13 @@
#define DEBUG17(x) do {} while (0)
#endif
#if defined(QL_DEBUG_LEVEL_18)
#define DEBUG18(x) do {if (ql2xextended_error_logging) x; } while (0)
#else
#define DEBUG18(x) do {} while (0)
#endif
/*
* Firmware Dump structure definition
*/
......
......@@ -188,6 +188,16 @@
struct req_que;
/*
* (sd.h is not exported, hence local inclusion)
* Data Integrity Field tuple.
*/
struct sd_dif_tuple {
__be16 guard_tag; /* Checksum */
__be16 app_tag; /* Opaque storage */
__be32 ref_tag; /* Target LBA or indirect LBA */
};
/*
* SCSI Request Block
*/
......@@ -208,8 +218,14 @@ typedef struct srb {
/*
* SRB flag definitions
*/
#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */
#define SRB_FCP_CMND_DMA_VALID BIT_12 /* FCP command in IOCB */
#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */
#define SRB_FCP_CMND_DMA_VALID BIT_12 /* DIF: DSD List valid */
#define SRB_CRC_CTX_DMA_VALID BIT_2 /* DIF: context DMA valid */
#define SRB_CRC_PROT_DMA_VALID BIT_4 /* DIF: prot DMA valid */
#define SRB_CRC_CTX_DSD_VALID BIT_5 /* DIF: dsd_list valid */
/* To identify if a srb is of T10-CRC type. @sp => srb_t pointer */
#define IS_PROT_IO(sp) (sp->flags & SRB_CRC_CTX_DSD_VALID)
/*
* SRB extensions.
......@@ -1330,6 +1346,66 @@ typedef struct {
uint32_t dseg_4_length; /* Data segment 4 length. */
} cont_a64_entry_t;
#define PO_MODE_DIF_INSERT 0
#define PO_MODE_DIF_REMOVE BIT_0
#define PO_MODE_DIF_PASS BIT_1
#define PO_MODE_DIF_REPLACE (BIT_0 + BIT_1)
#define PO_ENABLE_DIF_BUNDLING BIT_8
#define PO_ENABLE_INCR_GUARD_SEED BIT_3
#define PO_DISABLE_INCR_REF_TAG BIT_5
#define PO_DISABLE_GUARD_CHECK BIT_4
/*
* ISP queue - 64-Bit addressing, continuation crc entry structure definition.
*/
struct crc_context {
uint32_t handle; /* System handle. */
uint32_t ref_tag;
uint16_t app_tag;
uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/
uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/
uint16_t guard_seed; /* Initial Guard Seed */
uint16_t prot_opts; /* Requested Data Protection Mode */
uint16_t blk_size; /* Data size in bytes */
uint16_t runt_blk_guard; /* Guard value for runt block (tape
* only) */
uint32_t byte_count; /* Total byte count/ total data
* transfer count */
union {
struct {
uint32_t reserved_1;
uint16_t reserved_2;
uint16_t reserved_3;
uint32_t reserved_4;
uint32_t data_address[2];
uint32_t data_length;
uint32_t reserved_5[2];
uint32_t reserved_6;
} nobundling;
struct {
uint32_t dif_byte_count; /* Total DIF byte
* count */
uint16_t reserved_1;
uint16_t dseg_count; /* Data segment count */
uint32_t reserved_2;
uint32_t data_address[2];
uint32_t data_length;
uint32_t dif_address[2];
uint32_t dif_length; /* Data segment 0
* length */
} bundling;
} u;
struct fcp_cmnd fcp_cmnd;
dma_addr_t crc_ctx_dma;
/* List of DMA context transfers */
struct list_head dsd_list;
/* This structure should not exceed 512 bytes */
};
#define CRC_CONTEXT_LEN_FW (offsetof(struct crc_context, fcp_cmnd.lun))
#define CRC_CONTEXT_FCPCMND_OFF (offsetof(struct crc_context, fcp_cmnd.lun))
/*
* ISP queue - status entry structure definition.
*/
......@@ -1390,6 +1466,7 @@ typedef struct {
#define CS_ABORTED 0x5 /* System aborted command. */
#define CS_TIMEOUT 0x6 /* Timeout error. */
#define CS_DATA_OVERRUN 0x7 /* Data overrun. */
#define CS_DIF_ERROR 0xC /* DIF error detected */
#define CS_DATA_UNDERRUN 0x15 /* Data Underrun. */
#define CS_QUEUE_FULL 0x1C /* Queue Full. */
......@@ -2732,6 +2809,7 @@ typedef struct scsi_qla_host {
uint32_t management_server_logged_in :1;
uint32_t process_response_queue :1;
uint32_t difdix_supported:1;
} flags;
atomic_t loop_state;
......@@ -2883,6 +2961,8 @@ typedef struct scsi_qla_host {
#define OPTROM_BURST_SIZE 0x1000
#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4)
#define QLA_DSDS_PER_IOCB 37
#include "qla_gbl.h"
#include "qla_dbg.h"
#include "qla_inline.h"
......
......@@ -400,6 +400,7 @@ struct cmd_type_6 {
struct scsi_lun lun; /* FCP LUN (BE). */
uint16_t control_flags; /* Control flags. */
#define CF_DIF_SEG_DESCR_ENABLE BIT_3
#define CF_DATA_SEG_DESCR_ENABLE BIT_2
#define CF_READ_DATA BIT_1
#define CF_WRITE_DATA BIT_0
......@@ -466,6 +467,43 @@ struct cmd_type_7 {
uint32_t dseg_0_len; /* Data segment 0 length. */
};
#define COMMAND_TYPE_CRC_2 0x6A /* Command Type CRC_2 (Type 6)
* (T10-DIF) */
struct cmd_type_crc_2 {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
uint8_t sys_define; /* System defined. */
uint8_t entry_status; /* Entry Status. */
uint32_t handle; /* System handle. */
uint16_t nport_handle; /* N_PORT handle. */
uint16_t timeout; /* Command timeout. */
uint16_t dseg_count; /* Data segment count. */
uint16_t fcp_rsp_dseg_len; /* FCP_RSP DSD length. */
struct scsi_lun lun; /* FCP LUN (BE). */
uint16_t control_flags; /* Control flags. */
uint16_t fcp_cmnd_dseg_len; /* Data segment length. */
uint32_t fcp_cmnd_dseg_address[2]; /* Data segment address. */
uint32_t fcp_rsp_dseg_address[2]; /* Data segment address. */
uint32_t byte_count; /* Total byte count. */
uint8_t port_id[3]; /* PortID of destination port. */
uint8_t vp_index;
uint32_t crc_context_address[2]; /* Data segment address. */
uint16_t crc_context_len; /* Data segment length. */
uint16_t reserved_1; /* MUST be set to 0. */
};
/*
* ISP queue - status entry structure definition.
*/
......@@ -496,10 +534,17 @@ struct sts_entry_24xx {
uint32_t sense_len; /* FCP SENSE length. */
uint32_t rsp_data_len; /* FCP response data length. */
uint8_t data[28]; /* FCP response/sense information. */
/*
* If DIF Error is set in comp_status, these additional fields are
* defined:
* &data[10] : uint8_t report_runt_bg[2]; - computed guard
* &data[12] : uint8_t actual_dif[8]; - DIF Data recieved
* &data[20] : uint8_t expected_dif[8]; - DIF Data computed
*/
};
/*
* Status entry completion status
*/
......
......@@ -94,6 +94,8 @@ extern int ql2xshiftctondsd;
extern int ql2xdbwr;
extern int ql2xdontresethba;
extern int ql2xasynctmfenable;
extern int ql2xenabledif;
extern int ql2xenablehba_err_chk;
extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
......@@ -179,6 +181,7 @@ extern int qla2x00_start_sp(srb_t *);
extern void qla2x00_ctx_sp_free(srb_t *);
extern uint16_t qla24xx_calc_iocbs(uint16_t);
extern void qla24xx_build_scsi_iocbs(srb_t *, struct cmd_type_7 *, uint16_t);
extern int qla24xx_dif_start_scsi(srb_t *);
/*
......@@ -423,6 +426,7 @@ extern void qla25xx_fw_dump(scsi_qla_host_t *, int);
extern void qla81xx_fw_dump(scsi_qla_host_t *, int);
extern void qla2x00_dump_regs(scsi_qla_host_t *);
extern void qla2x00_dump_buffer(uint8_t *, uint32_t);
extern void qla2x00_dump_buffer_zipped(uint8_t *, uint32_t);
/*
* Global Function Prototypes in qla_gs.c source file.
......
......@@ -67,3 +67,19 @@ qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
}
static inline void
qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp)
{
struct dsd_dma *dsd_ptr, *tdsd_ptr;
/* clean up allocated prev pool */
list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
&((struct crc_context *)sp->ctx)->dsd_list, list) {
dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
dsd_ptr->dsd_list_dma);
list_del(&dsd_ptr->list);
kfree(dsd_ptr);
}
INIT_LIST_HEAD(&((struct crc_context *)sp->ctx)->dsd_list);
}
This diff is collapsed.
......@@ -10,6 +10,7 @@
#include <linux/slab.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_bsg_fc.h>
#include <scsi/scsi_eh.h>
static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t);
static void qla2x00_process_completed_request(struct scsi_qla_host *,
......@@ -1364,6 +1365,78 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len,
DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
}
struct scsi_dif_tuple {
__be16 guard; /* Checksum */
__be16 app_tag; /* APPL identifer */
__be32 ref_tag; /* Target LBA or indirect LBA */
};
/*
* Checks the guard or meta-data for the type of error
* detected by the HBA. In case of errors, we set the
* ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
* to indicate to the kernel that the HBA detected error.
*/
static inline void
qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
{
struct scsi_cmnd *cmd = sp->cmd;
struct scsi_dif_tuple *ep =
(struct scsi_dif_tuple *)&sts24->data[20];
struct scsi_dif_tuple *ap =
(struct scsi_dif_tuple *)&sts24->data[12];
uint32_t e_ref_tag, a_ref_tag;
uint16_t e_app_tag, a_app_tag;
uint16_t e_guard, a_guard;
e_ref_tag = be32_to_cpu(ep->ref_tag);
a_ref_tag = be32_to_cpu(ap->ref_tag);
e_app_tag = be16_to_cpu(ep->app_tag);
a_app_tag = be16_to_cpu(ap->app_tag);
e_guard = be16_to_cpu(ep->guard);
a_guard = be16_to_cpu(ap->guard);
DEBUG18(printk(KERN_DEBUG
"%s(): iocb(s) %p Returned STATUS\n", __func__, sts24));
DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref"
" tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app"
" tag=0x%x, act guard=0x%x, exp guard=0x%x\n",
cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
a_app_tag, e_app_tag, a_guard, e_guard));
/* check guard */
if (e_guard != a_guard) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x1);
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
return;
}
/* check appl tag */
if (e_app_tag != a_app_tag) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x2);
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
return;
}
/* check ref tag */
if (e_ref_tag != a_ref_tag) {
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x3);
set_driver_byte(cmd, DRIVER_SENSE);
set_host_byte(cmd, DID_ABORT);
cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
return;
}
}
/**
* qla2x00_status_entry() - Process a Status IOCB entry.
* @ha: SCSI driver HA context
......@@ -1630,6 +1703,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
case CS_ABORTED:
cp->result = DID_RESET << 16;
break;
case CS_DIF_ERROR:
qla2x00_handle_dif_error(sp, sts24);
break;
default:
cp->result = DID_ERROR << 16;
break;
......
......@@ -92,6 +92,19 @@ module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xmaxqdepth,
"Maximum queue depth to report for target devices.");
/* Do not change the value of this after module load */
int ql2xenabledif = 1;
module_param(ql2xenabledif, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenabledif,
" Enable T10-CRC-DIF "
" Default is 0 - No DIF Support. 1 - Enable it");
int ql2xenablehba_err_chk;
module_param(ql2xenablehba_err_chk, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xenablehba_err_chk,
" Enable T10-CRC-DIF Error isolation by HBA"
" Default is 0 - Error isolation disabled, 1 - Enable it");
int ql2xiidmaenable=1;
module_param(ql2xiidmaenable, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xiidmaenable,
......@@ -537,6 +550,14 @@ qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
if (fcport->drport)
goto qc24_target_busy;
if (!vha->flags.difdix_supported &&
scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) {
DEBUG2(qla_printk(KERN_ERR, ha,
"DIF Cap Not Reg, fail DIF capable cmd's:%x\n",
cmd->cmnd[0]));
cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
if (atomic_read(&fcport->state) != FCS_ONLINE) {
if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
atomic_read(&base_vha->loop_state) == LOOP_DEAD) {
......@@ -776,7 +797,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
if (sp == NULL)
continue;
if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID))
if ((sp->ctx) && !(sp->flags & SRB_FCP_CMND_DMA_VALID) &&
!IS_PROT_IO(sp))
continue;
if (sp->cmd != cmd)
continue;
......@@ -842,7 +864,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
sp = req->outstanding_cmds[cnt];
if (!sp)
continue;
if (sp->ctx)
if ((sp->ctx) && !IS_PROT_IO(sp))
continue;
if (vha->vp_idx != sp->fcport->vha->vp_idx)
continue;
......@@ -1189,7 +1211,8 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
if (sp) {
req->outstanding_cmds[cnt] = NULL;
if (!sp->ctx ||
(sp->flags & SRB_FCP_CMND_DMA_VALID)) {
(sp->flags & SRB_FCP_CMND_DMA_VALID) ||
IS_PROT_IO(sp)) {
sp->cmd->result = res;
qla2x00_sp_compl(ha, sp);
} else {
......@@ -1553,7 +1576,7 @@ static struct isp_operations qla25xx_isp_ops = {
.read_optrom = qla25xx_read_optrom_data,
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
.start_scsi = qla24xx_dif_start_scsi,
.abort_isp = qla2x00_abort_isp,
};
......@@ -2185,6 +2208,22 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
DEBUG2(printk("DEBUG: detect hba %ld at address = %p\n",
base_vha->host_no, ha));
if (IS_QLA25XX(ha) && ql2xenabledif) {
if (ha->fw_attributes & BIT_4) {
base_vha->flags.difdix_supported = 1;
DEBUG18(qla_printk(KERN_INFO, ha,
"Registering for DIF/DIX type 1 and 3"
" protection.\n"));
scsi_host_set_prot(host,
SHOST_DIF_TYPE1_PROTECTION
| SHOST_DIF_TYPE3_PROTECTION
| SHOST_DIX_TYPE1_PROTECTION
| SHOST_DIX_TYPE3_PROTECTION);
scsi_host_set_guard(host, SHOST_DIX_GUARD_CRC);
} else
base_vha->flags.difdix_supported = 0;
}
ha->isp_ops->enable_intrs(ha);
ret = scsi_add_host(host, &pdev->dev);
......@@ -2546,7 +2585,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
if (!ha->s_dma_pool)
goto fail_free_nvram;
if (IS_QLA82XX(ha)) {
if (IS_QLA82XX(ha) || ql2xenabledif) {
ha->dl_dma_pool = dma_pool_create(name, &ha->pdev->dev,
DSD_LIST_DMA_POOL_SIZE, 8, 0);
if (!ha->dl_dma_pool) {
......@@ -2678,12 +2717,12 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
ha->ms_iocb = NULL;
ha->ms_iocb_dma = 0;
fail_dma_pool:
if (IS_QLA82XX(ha)) {
if (IS_QLA82XX(ha) || ql2xenabledif) {
dma_pool_destroy(ha->fcp_cmnd_dma_pool);
ha->fcp_cmnd_dma_pool = NULL;
}
fail_dl_dma_pool:
if (IS_QLA82XX(ha)) {
if (IS_QLA82XX(ha) || ql2xenabledif) {
dma_pool_destroy(ha->dl_dma_pool);
ha->dl_dma_pool = NULL;
}
......@@ -3346,11 +3385,31 @@ static void
qla2x00_sp_free_dma(srb_t *sp)
{
struct scsi_cmnd *cmd = sp->cmd;
struct qla_hw_data *ha = sp->fcport->vha->hw;
if (sp->flags & SRB_DMA_VALID) {
scsi_dma_unmap(cmd);
sp->flags &= ~SRB_DMA_VALID;
}
if (sp->flags & SRB_CRC_PROT_DMA_VALID) {
dma_unmap_sg(&ha->pdev->dev, scsi_prot_sglist(cmd),
scsi_prot_sg_count(cmd), cmd->sc_data_direction);
sp->flags &= ~SRB_CRC_PROT_DMA_VALID;
}
if (sp->flags & SRB_CRC_CTX_DSD_VALID) {
/* List assured to be having elements */
qla2x00_clean_dsd_pool(ha, sp);
sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
}
if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
dma_pool_free(ha->dl_dma_pool, sp->ctx,
((struct crc_context *)sp->ctx)->crc_ctx_dma);
sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
}
CMD_SP(cmd) = NULL;
}
......@@ -3464,7 +3523,7 @@ qla2x00_timer(scsi_qla_host_t *vha)
sp = req->outstanding_cmds[index];
if (!sp)
continue;
if (sp->ctx)
if (sp->ctx && !IS_PROT_IO(sp))
continue;
sfcp = sp->fcport;
if (!(sfcp->flags & FCF_FCP2_DEVICE))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment