diff options
author | Arun Easi <arun.easi@qlogic.com> | 2010-05-04 18:01:30 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-05-16 18:21:59 -0400 |
commit | bad750028917a7b804623701d0674e46c6012c18 (patch) | |
tree | f8c4032b480e3c93b906e313eb6d371565b4b66d /drivers/scsi/qla2xxx/qla_isr.c | |
parent | 3822263eb1e74821ad1ae886ddd2184ae9395ff7 (diff) |
[SCSI] qla2xxx: T10 DIF support added.
Signed-off-by: Duane Grigsby <duane.grigsby@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index eed71ea1d947..be3d8bed2ecf 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
11 | #include <scsi/scsi_tcq.h> | 11 | #include <scsi/scsi_tcq.h> |
12 | #include <scsi/scsi_bsg_fc.h> | 12 | #include <scsi/scsi_bsg_fc.h> |
13 | #include <scsi/scsi_eh.h> | ||
13 | 14 | ||
14 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); | 15 | static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); |
15 | static void qla2x00_process_completed_request(struct scsi_qla_host *, | 16 | 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, | |||
1364 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len)); | 1365 | DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len)); |
1365 | } | 1366 | } |
1366 | 1367 | ||
1368 | struct scsi_dif_tuple { | ||
1369 | __be16 guard; /* Checksum */ | ||
1370 | __be16 app_tag; /* APPL identifer */ | ||
1371 | __be32 ref_tag; /* Target LBA or indirect LBA */ | ||
1372 | }; | ||
1373 | |||
1374 | /* | ||
1375 | * Checks the guard or meta-data for the type of error | ||
1376 | * detected by the HBA. In case of errors, we set the | ||
1377 | * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST | ||
1378 | * to indicate to the kernel that the HBA detected error. | ||
1379 | */ | ||
1380 | static inline void | ||
1381 | qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) | ||
1382 | { | ||
1383 | struct scsi_cmnd *cmd = sp->cmd; | ||
1384 | struct scsi_dif_tuple *ep = | ||
1385 | (struct scsi_dif_tuple *)&sts24->data[20]; | ||
1386 | struct scsi_dif_tuple *ap = | ||
1387 | (struct scsi_dif_tuple *)&sts24->data[12]; | ||
1388 | uint32_t e_ref_tag, a_ref_tag; | ||
1389 | uint16_t e_app_tag, a_app_tag; | ||
1390 | uint16_t e_guard, a_guard; | ||
1391 | |||
1392 | e_ref_tag = be32_to_cpu(ep->ref_tag); | ||
1393 | a_ref_tag = be32_to_cpu(ap->ref_tag); | ||
1394 | e_app_tag = be16_to_cpu(ep->app_tag); | ||
1395 | a_app_tag = be16_to_cpu(ap->app_tag); | ||
1396 | e_guard = be16_to_cpu(ep->guard); | ||
1397 | a_guard = be16_to_cpu(ap->guard); | ||
1398 | |||
1399 | DEBUG18(printk(KERN_DEBUG | ||
1400 | "%s(): iocb(s) %p Returned STATUS\n", __func__, sts24)); | ||
1401 | |||
1402 | DEBUG18(printk(KERN_ERR "DIF ERROR in cmd 0x%x lba 0x%llx act ref" | ||
1403 | " tag=0x%x, exp ref_tag=0x%x, act app tag=0x%x, exp app" | ||
1404 | " tag=0x%x, act guard=0x%x, exp guard=0x%x\n", | ||
1405 | cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag, | ||
1406 | a_app_tag, e_app_tag, a_guard, e_guard)); | ||
1407 | |||
1408 | |||
1409 | /* check guard */ | ||
1410 | if (e_guard != a_guard) { | ||
1411 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1412 | 0x10, 0x1); | ||
1413 | set_driver_byte(cmd, DRIVER_SENSE); | ||
1414 | set_host_byte(cmd, DID_ABORT); | ||
1415 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | ||
1416 | return; | ||
1417 | } | ||
1418 | |||
1419 | /* check appl tag */ | ||
1420 | if (e_app_tag != a_app_tag) { | ||
1421 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1422 | 0x10, 0x2); | ||
1423 | set_driver_byte(cmd, DRIVER_SENSE); | ||
1424 | set_host_byte(cmd, DID_ABORT); | ||
1425 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | ||
1426 | return; | ||
1427 | } | ||
1428 | |||
1429 | /* check ref tag */ | ||
1430 | if (e_ref_tag != a_ref_tag) { | ||
1431 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1432 | 0x10, 0x3); | ||
1433 | set_driver_byte(cmd, DRIVER_SENSE); | ||
1434 | set_host_byte(cmd, DID_ABORT); | ||
1435 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | ||
1436 | return; | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1367 | /** | 1440 | /** |
1368 | * qla2x00_status_entry() - Process a Status IOCB entry. | 1441 | * qla2x00_status_entry() - Process a Status IOCB entry. |
1369 | * @ha: SCSI driver HA context | 1442 | * @ha: SCSI driver HA context |
@@ -1630,6 +1703,10 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt) | |||
1630 | case CS_ABORTED: | 1703 | case CS_ABORTED: |
1631 | cp->result = DID_RESET << 16; | 1704 | cp->result = DID_RESET << 16; |
1632 | break; | 1705 | break; |
1706 | |||
1707 | case CS_DIF_ERROR: | ||
1708 | qla2x00_handle_dif_error(sp, sts24); | ||
1709 | break; | ||
1633 | default: | 1710 | default: |
1634 | cp->result = DID_ERROR << 16; | 1711 | cp->result = DID_ERROR << 16; |
1635 | break; | 1712 | break; |