aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_isr.c
diff options
context:
space:
mode:
authorArun Easi <arun.easi@qlogic.com>2011-08-16 14:29:22 -0400
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 09:55:46 -0400
commit8cb2049c744809193ed3707a37c09676a24599ee (patch)
treeb9523a9a1be8f2610547036d849880d588f0a694 /drivers/scsi/qla2xxx/qla_isr.c
parent01350d05539d1c95ef3568d062d864ab76ae7670 (diff)
[SCSI] qla2xxx: T10 DIF - Handle uninitalized sectors.
Driver needs to update protection bytes for uninitialized sectors as they are not DMA-d. Signed-off-by: Arun Easi <arun.easi@qlogic.com> Reviewed-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c90
1 files changed, 75 insertions, 15 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index b16b7725dee0..53339f10a598 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1435,25 +1435,27 @@ struct scsi_dif_tuple {
1435 * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST 1435 * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST
1436 * to indicate to the kernel that the HBA detected error. 1436 * to indicate to the kernel that the HBA detected error.
1437 */ 1437 */
1438static inline void 1438static inline int
1439qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) 1439qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1440{ 1440{
1441 struct scsi_qla_host *vha = sp->fcport->vha; 1441 struct scsi_qla_host *vha = sp->fcport->vha;
1442 struct scsi_cmnd *cmd = sp->cmd; 1442 struct scsi_cmnd *cmd = sp->cmd;
1443 struct scsi_dif_tuple *ep = 1443 uint8_t *ap = &sts24->data[12];
1444 (struct scsi_dif_tuple *)&sts24->data[20]; 1444 uint8_t *ep = &sts24->data[20];
1445 struct scsi_dif_tuple *ap =
1446 (struct scsi_dif_tuple *)&sts24->data[12];
1447 uint32_t e_ref_tag, a_ref_tag; 1445 uint32_t e_ref_tag, a_ref_tag;
1448 uint16_t e_app_tag, a_app_tag; 1446 uint16_t e_app_tag, a_app_tag;
1449 uint16_t e_guard, a_guard; 1447 uint16_t e_guard, a_guard;
1450 1448
1451 e_ref_tag = be32_to_cpu(ep->ref_tag); 1449 /*
1452 a_ref_tag = be32_to_cpu(ap->ref_tag); 1450 * swab32 of the "data" field in the beginning of qla2x00_status_entry()
1453 e_app_tag = be16_to_cpu(ep->app_tag); 1451 * would make guard field appear at offset 2
1454 a_app_tag = be16_to_cpu(ap->app_tag); 1452 */
1455 e_guard = be16_to_cpu(ep->guard); 1453 a_guard = le16_to_cpu(*(uint16_t *)(ap + 2));
1456 a_guard = be16_to_cpu(ap->guard); 1454 a_app_tag = le16_to_cpu(*(uint16_t *)(ap + 0));
1455 a_ref_tag = le32_to_cpu(*(uint32_t *)(ap + 4));
1456 e_guard = le16_to_cpu(*(uint16_t *)(ep + 2));
1457 e_app_tag = le16_to_cpu(*(uint16_t *)(ep + 0));
1458 e_ref_tag = le32_to_cpu(*(uint32_t *)(ep + 4));
1457 1459
1458 ql_dbg(ql_dbg_io, vha, 0x3023, 1460 ql_dbg(ql_dbg_io, vha, 0x3023,
1459 "iocb(s) %p Returned STATUS.\n", sts24); 1461 "iocb(s) %p Returned STATUS.\n", sts24);
@@ -1465,6 +1467,63 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1465 cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag, 1467 cmd->cmnd[0], (u64)scsi_get_lba(cmd), a_ref_tag, e_ref_tag,
1466 a_app_tag, e_app_tag, a_guard, e_guard); 1468 a_app_tag, e_app_tag, a_guard, e_guard);
1467 1469
1470 /*
1471 * Ignore sector if:
1472 * For type 3: ref & app tag is all 'f's
1473 * For type 0,1,2: app tag is all 'f's
1474 */
1475 if ((a_app_tag == 0xffff) &&
1476 ((scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3) ||
1477 (a_ref_tag == 0xffffffff))) {
1478 uint32_t blocks_done, resid;
1479 sector_t lba_s = scsi_get_lba(cmd);
1480
1481 /* 2TB boundary case covered automatically with this */
1482 blocks_done = e_ref_tag - (uint32_t)lba_s + 1;
1483
1484 resid = scsi_bufflen(cmd) - (blocks_done *
1485 cmd->device->sector_size);
1486
1487 scsi_set_resid(cmd, resid);
1488 cmd->result = DID_OK << 16;
1489
1490 /* Update protection tag */
1491 if (scsi_prot_sg_count(cmd)) {
1492 uint32_t i, j = 0, k = 0, num_ent;
1493 struct scatterlist *sg;
1494 struct sd_dif_tuple *spt;
1495
1496 /* Patch the corresponding protection tags */
1497 scsi_for_each_prot_sg(cmd, sg,
1498 scsi_prot_sg_count(cmd), i) {
1499 num_ent = sg_dma_len(sg) / 8;
1500 if (k + num_ent < blocks_done) {
1501 k += num_ent;
1502 continue;
1503 }
1504 j = blocks_done - k - 1;
1505 k = blocks_done;
1506 break;
1507 }
1508
1509 if (k != blocks_done) {
1510 qla_printk(KERN_WARNING, sp->fcport->vha->hw,
1511 "unexpected tag values tag:lba=%x:%lx)\n",
1512 e_ref_tag, lba_s);
1513 return 1;
1514 }
1515
1516 spt = page_address(sg_page(sg)) + sg->offset;
1517 spt += j;
1518
1519 spt->app_tag = 0xffff;
1520 if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE3)
1521 spt->ref_tag = 0xffffffff;
1522 }
1523
1524 return 0;
1525 }
1526
1468 /* check guard */ 1527 /* check guard */
1469 if (e_guard != a_guard) { 1528 if (e_guard != a_guard) {
1470 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 1529 scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
@@ -1472,7 +1531,7 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1472 set_driver_byte(cmd, DRIVER_SENSE); 1531 set_driver_byte(cmd, DRIVER_SENSE);
1473 set_host_byte(cmd, DID_ABORT); 1532 set_host_byte(cmd, DID_ABORT);
1474 cmd->result |= SAM_STAT_CHECK_CONDITION << 1; 1533 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1475 return; 1534 return 1;
1476 } 1535 }
1477 1536
1478 /* check appl tag */ 1537 /* check appl tag */
@@ -1482,7 +1541,7 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1482 set_driver_byte(cmd, DRIVER_SENSE); 1541 set_driver_byte(cmd, DRIVER_SENSE);
1483 set_host_byte(cmd, DID_ABORT); 1542 set_host_byte(cmd, DID_ABORT);
1484 cmd->result |= SAM_STAT_CHECK_CONDITION << 1; 1543 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1485 return; 1544 return 1;
1486 } 1545 }
1487 1546
1488 /* check ref tag */ 1547 /* check ref tag */
@@ -1492,8 +1551,9 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24)
1492 set_driver_byte(cmd, DRIVER_SENSE); 1551 set_driver_byte(cmd, DRIVER_SENSE);
1493 set_host_byte(cmd, DID_ABORT); 1552 set_host_byte(cmd, DID_ABORT);
1494 cmd->result |= SAM_STAT_CHECK_CONDITION << 1; 1553 cmd->result |= SAM_STAT_CHECK_CONDITION << 1;
1495 return; 1554 return 1;
1496 } 1555 }
1556 return 1;
1497} 1557}
1498 1558
1499/** 1559/**
@@ -1767,7 +1827,7 @@ check_scsi_status:
1767 break; 1827 break;
1768 1828
1769 case CS_DIF_ERROR: 1829 case CS_DIF_ERROR:
1770 qla2x00_handle_dif_error(sp, sts24); 1830 logit = qla2x00_handle_dif_error(sp, sts24);
1771 break; 1831 break;
1772 default: 1832 default:
1773 cp->result = DID_ERROR << 16; 1833 cp->result = DID_ERROR << 16;