diff options
author | James Smart <james.smart@emulex.com> | 2011-07-22 18:36:25 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-07-27 07:06:29 -0400 |
commit | 7c56b9fd3b6d2d933075d12abee67ceb7c90d04a (patch) | |
tree | 71edc723c736cdf55a738f8b56f83513238caebc /drivers/scsi | |
parent | 154fbf06485bbb6c28f1f7ebf462e4895613033c (diff) |
[SCSI] lpfc 8.3.25: T10 DIF Fixes
T10 DIF Fixes
- Fix the case where the SCSI Host supplies the CRC and driver to controller
protection is on.
- Only support T10 DIF type 1. LBA always goes in ref tag and app tag is not
checked.
- Change the format of the sense data passed up to the SCSI layer to match the
Descriptor Format Sense Data found in SPC-4 sections 4.5.2.1 and 4.5.2.2.
- Fix Slip PDE implementation.
- Remove BUG() in else casein lpfc_sc_to_bg_opcodes.
Signed-off-by: Alex Iannicelli <alex.iannicelli@emulex.com>
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_attr.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 97 |
2 files changed, 33 insertions, 68 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 135a53baa735..29ccb1519226 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -3678,7 +3678,9 @@ LPFC_ATTR_R(enable_bg, 0, 0, 1, "Enable BlockGuard Support"); | |||
3678 | # - Default will result in registering capabilities for all profiles. | 3678 | # - Default will result in registering capabilities for all profiles. |
3679 | # | 3679 | # |
3680 | */ | 3680 | */ |
3681 | unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION; | 3681 | unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION | |
3682 | SHOST_DIX_TYPE0_PROTECTION | | ||
3683 | SHOST_DIX_TYPE1_PROTECTION; | ||
3682 | 3684 | ||
3683 | module_param(lpfc_prot_mask, uint, S_IRUGO); | 3685 | module_param(lpfc_prot_mask, uint, S_IRUGO); |
3684 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); | 3686 | MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask"); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 3ccc97496ebf..eadd241eeff1 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1302,13 +1302,13 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1302 | case SCSI_PROT_NORMAL: | 1302 | case SCSI_PROT_NORMAL: |
1303 | default: | 1303 | default: |
1304 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 1304 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, |
1305 | "9063 BLKGRD: Bad op/guard:%d/%d combination\n", | 1305 | "9063 BLKGRD: Bad op/guard:%d/IP combination\n", |
1306 | scsi_get_prot_op(sc), guard_type); | 1306 | scsi_get_prot_op(sc)); |
1307 | ret = 1; | 1307 | ret = 1; |
1308 | break; | 1308 | break; |
1309 | 1309 | ||
1310 | } | 1310 | } |
1311 | } else if (guard_type == SHOST_DIX_GUARD_CRC) { | 1311 | } else { |
1312 | switch (scsi_get_prot_op(sc)) { | 1312 | switch (scsi_get_prot_op(sc)) { |
1313 | case SCSI_PROT_READ_STRIP: | 1313 | case SCSI_PROT_READ_STRIP: |
1314 | case SCSI_PROT_WRITE_INSERT: | 1314 | case SCSI_PROT_WRITE_INSERT: |
@@ -1324,17 +1324,18 @@ lpfc_sc_to_bg_opcodes(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1324 | 1324 | ||
1325 | case SCSI_PROT_READ_INSERT: | 1325 | case SCSI_PROT_READ_INSERT: |
1326 | case SCSI_PROT_WRITE_STRIP: | 1326 | case SCSI_PROT_WRITE_STRIP: |
1327 | *txop = BG_OP_IN_CRC_OUT_NODIF; | ||
1328 | *rxop = BG_OP_IN_NODIF_OUT_CRC; | ||
1329 | break; | ||
1330 | |||
1327 | case SCSI_PROT_NORMAL: | 1331 | case SCSI_PROT_NORMAL: |
1328 | default: | 1332 | default: |
1329 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, | 1333 | lpfc_printf_log(phba, KERN_ERR, LOG_BG, |
1330 | "9075 BLKGRD: Bad op/guard:%d/%d combination\n", | 1334 | "9075 BLKGRD: Bad op/guard:%d/CRC combination\n", |
1331 | scsi_get_prot_op(sc), guard_type); | 1335 | scsi_get_prot_op(sc)); |
1332 | ret = 1; | 1336 | ret = 1; |
1333 | break; | 1337 | break; |
1334 | } | 1338 | } |
1335 | } else { | ||
1336 | /* unsupported format */ | ||
1337 | BUG(); | ||
1338 | } | 1339 | } |
1339 | 1340 | ||
1340 | return ret; | 1341 | return ret; |
@@ -1352,45 +1353,6 @@ lpfc_cmd_blksize(struct scsi_cmnd *sc) | |||
1352 | return sc->device->sector_size; | 1353 | return sc->device->sector_size; |
1353 | } | 1354 | } |
1354 | 1355 | ||
1355 | /** | ||
1356 | * lpfc_get_cmd_dif_parms - Extract DIF parameters from SCSI command | ||
1357 | * @sc: in: SCSI command | ||
1358 | * @apptagmask: out: app tag mask | ||
1359 | * @apptagval: out: app tag value | ||
1360 | * @reftag: out: ref tag (reference tag) | ||
1361 | * | ||
1362 | * Description: | ||
1363 | * Extract DIF parameters from the command if possible. Otherwise, | ||
1364 | * use default parameters. | ||
1365 | * | ||
1366 | **/ | ||
1367 | static inline void | ||
1368 | lpfc_get_cmd_dif_parms(struct scsi_cmnd *sc, uint16_t *apptagmask, | ||
1369 | uint16_t *apptagval, uint32_t *reftag) | ||
1370 | { | ||
1371 | struct scsi_dif_tuple *spt; | ||
1372 | unsigned char op = scsi_get_prot_op(sc); | ||
1373 | unsigned int protcnt = scsi_prot_sg_count(sc); | ||
1374 | static int cnt; | ||
1375 | |||
1376 | if (protcnt && (op == SCSI_PROT_WRITE_STRIP || | ||
1377 | op == SCSI_PROT_WRITE_PASS)) { | ||
1378 | |||
1379 | cnt++; | ||
1380 | spt = page_address(sg_page(scsi_prot_sglist(sc))) + | ||
1381 | scsi_prot_sglist(sc)[0].offset; | ||
1382 | *apptagmask = 0; | ||
1383 | *apptagval = 0; | ||
1384 | *reftag = cpu_to_be32(spt->ref_tag); | ||
1385 | |||
1386 | } else { | ||
1387 | /* SBC defines ref tag to be lower 32bits of LBA */ | ||
1388 | *reftag = (uint32_t) (0xffffffff & scsi_get_lba(sc)); | ||
1389 | *apptagmask = 0; | ||
1390 | *apptagval = 0; | ||
1391 | } | ||
1392 | } | ||
1393 | |||
1394 | /* | 1356 | /* |
1395 | * This function sets up buffer list for protection groups of | 1357 | * This function sets up buffer list for protection groups of |
1396 | * type LPFC_PG_TYPE_NO_DIF | 1358 | * type LPFC_PG_TYPE_NO_DIF |
@@ -1427,9 +1389,8 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1427 | dma_addr_t physaddr; | 1389 | dma_addr_t physaddr; |
1428 | int i = 0, num_bde = 0, status; | 1390 | int i = 0, num_bde = 0, status; |
1429 | int datadir = sc->sc_data_direction; | 1391 | int datadir = sc->sc_data_direction; |
1430 | unsigned blksize; | ||
1431 | uint32_t reftag; | 1392 | uint32_t reftag; |
1432 | uint16_t apptagmask, apptagval; | 1393 | unsigned blksize; |
1433 | uint8_t txop, rxop; | 1394 | uint8_t txop, rxop; |
1434 | 1395 | ||
1435 | status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop); | 1396 | status = lpfc_sc_to_bg_opcodes(phba, sc, &txop, &rxop); |
@@ -1438,17 +1399,16 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1438 | 1399 | ||
1439 | /* extract some info from the scsi command for pde*/ | 1400 | /* extract some info from the scsi command for pde*/ |
1440 | blksize = lpfc_cmd_blksize(sc); | 1401 | blksize = lpfc_cmd_blksize(sc); |
1441 | lpfc_get_cmd_dif_parms(sc, &apptagmask, &apptagval, &reftag); | 1402 | reftag = scsi_get_lba(sc) & 0xffffffff; |
1442 | 1403 | ||
1443 | /* setup PDE5 with what we have */ | 1404 | /* setup PDE5 with what we have */ |
1444 | pde5 = (struct lpfc_pde5 *) bpl; | 1405 | pde5 = (struct lpfc_pde5 *) bpl; |
1445 | memset(pde5, 0, sizeof(struct lpfc_pde5)); | 1406 | memset(pde5, 0, sizeof(struct lpfc_pde5)); |
1446 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); | 1407 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); |
1447 | pde5->reftag = reftag; | ||
1448 | 1408 | ||
1449 | /* Endianness conversion if necessary for PDE5 */ | 1409 | /* Endianness conversion if necessary for PDE5 */ |
1450 | pde5->word0 = cpu_to_le32(pde5->word0); | 1410 | pde5->word0 = cpu_to_le32(pde5->word0); |
1451 | pde5->reftag = cpu_to_le32(pde5->reftag); | 1411 | pde5->reftag = cpu_to_le32(reftag); |
1452 | 1412 | ||
1453 | /* advance bpl and increment bde count */ | 1413 | /* advance bpl and increment bde count */ |
1454 | num_bde++; | 1414 | num_bde++; |
@@ -1463,10 +1423,10 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1463 | if (datadir == DMA_FROM_DEVICE) { | 1423 | if (datadir == DMA_FROM_DEVICE) { |
1464 | bf_set(pde6_ce, pde6, 1); | 1424 | bf_set(pde6_ce, pde6, 1); |
1465 | bf_set(pde6_re, pde6, 1); | 1425 | bf_set(pde6_re, pde6, 1); |
1466 | bf_set(pde6_ae, pde6, 1); | ||
1467 | } | 1426 | } |
1468 | bf_set(pde6_ai, pde6, 1); | 1427 | bf_set(pde6_ai, pde6, 1); |
1469 | bf_set(pde6_apptagval, pde6, apptagval); | 1428 | bf_set(pde6_ae, pde6, 0); |
1429 | bf_set(pde6_apptagval, pde6, 0); | ||
1470 | 1430 | ||
1471 | /* Endianness conversion if necessary for PDE6 */ | 1431 | /* Endianness conversion if necessary for PDE6 */ |
1472 | pde6->word0 = cpu_to_le32(pde6->word0); | 1432 | pde6->word0 = cpu_to_le32(pde6->word0); |
@@ -1551,7 +1511,6 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1551 | unsigned char pgdone = 0, alldone = 0; | 1511 | unsigned char pgdone = 0, alldone = 0; |
1552 | unsigned blksize; | 1512 | unsigned blksize; |
1553 | uint32_t reftag; | 1513 | uint32_t reftag; |
1554 | uint16_t apptagmask, apptagval; | ||
1555 | uint8_t txop, rxop; | 1514 | uint8_t txop, rxop; |
1556 | int num_bde = 0; | 1515 | int num_bde = 0; |
1557 | 1516 | ||
@@ -1571,7 +1530,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1571 | 1530 | ||
1572 | /* extract some info from the scsi command */ | 1531 | /* extract some info from the scsi command */ |
1573 | blksize = lpfc_cmd_blksize(sc); | 1532 | blksize = lpfc_cmd_blksize(sc); |
1574 | lpfc_get_cmd_dif_parms(sc, &apptagmask, &apptagval, &reftag); | 1533 | reftag = scsi_get_lba(sc) & 0xffffffff; |
1575 | 1534 | ||
1576 | split_offset = 0; | 1535 | split_offset = 0; |
1577 | do { | 1536 | do { |
@@ -1579,11 +1538,10 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1579 | pde5 = (struct lpfc_pde5 *) bpl; | 1538 | pde5 = (struct lpfc_pde5 *) bpl; |
1580 | memset(pde5, 0, sizeof(struct lpfc_pde5)); | 1539 | memset(pde5, 0, sizeof(struct lpfc_pde5)); |
1581 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); | 1540 | bf_set(pde5_type, pde5, LPFC_PDE5_DESCRIPTOR); |
1582 | pde5->reftag = reftag; | ||
1583 | 1541 | ||
1584 | /* Endianness conversion if necessary for PDE5 */ | 1542 | /* Endianness conversion if necessary for PDE5 */ |
1585 | pde5->word0 = cpu_to_le32(pde5->word0); | 1543 | pde5->word0 = cpu_to_le32(pde5->word0); |
1586 | pde5->reftag = cpu_to_le32(pde5->reftag); | 1544 | pde5->reftag = cpu_to_le32(reftag); |
1587 | 1545 | ||
1588 | /* advance bpl and increment bde count */ | 1546 | /* advance bpl and increment bde count */ |
1589 | num_bde++; | 1547 | num_bde++; |
@@ -1597,9 +1555,9 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1597 | bf_set(pde6_oprx, pde6, rxop); | 1555 | bf_set(pde6_oprx, pde6, rxop); |
1598 | bf_set(pde6_ce, pde6, 1); | 1556 | bf_set(pde6_ce, pde6, 1); |
1599 | bf_set(pde6_re, pde6, 1); | 1557 | bf_set(pde6_re, pde6, 1); |
1600 | bf_set(pde6_ae, pde6, 1); | ||
1601 | bf_set(pde6_ai, pde6, 1); | 1558 | bf_set(pde6_ai, pde6, 1); |
1602 | bf_set(pde6_apptagval, pde6, apptagval); | 1559 | bf_set(pde6_ae, pde6, 0); |
1560 | bf_set(pde6_apptagval, pde6, 0); | ||
1603 | 1561 | ||
1604 | /* Endianness conversion if necessary for PDE6 */ | 1562 | /* Endianness conversion if necessary for PDE6 */ |
1605 | pde6->word0 = cpu_to_le32(pde6->word0); | 1563 | pde6->word0 = cpu_to_le32(pde6->word0); |
@@ -1621,8 +1579,8 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1621 | memset(pde7, 0, sizeof(struct lpfc_pde7)); | 1579 | memset(pde7, 0, sizeof(struct lpfc_pde7)); |
1622 | bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR); | 1580 | bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR); |
1623 | 1581 | ||
1624 | pde7->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr)); | 1582 | pde7->addrHigh = le32_to_cpu(putPaddrHigh(protphysaddr)); |
1625 | pde7->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr)); | 1583 | pde7->addrLow = le32_to_cpu(putPaddrLow(protphysaddr)); |
1626 | 1584 | ||
1627 | protgrp_blks = protgroup_len / 8; | 1585 | protgrp_blks = protgroup_len / 8; |
1628 | protgrp_bytes = protgrp_blks * blksize; | 1586 | protgrp_bytes = protgrp_blks * blksize; |
@@ -1632,7 +1590,7 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
1632 | protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff); | 1590 | protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff); |
1633 | protgroup_offset += protgroup_remainder; | 1591 | protgroup_offset += protgroup_remainder; |
1634 | protgrp_blks = protgroup_remainder / 8; | 1592 | protgrp_blks = protgroup_remainder / 8; |
1635 | protgrp_bytes = protgroup_remainder * blksize; | 1593 | protgrp_bytes = protgrp_blks * blksize; |
1636 | } else { | 1594 | } else { |
1637 | protgroup_offset = 0; | 1595 | protgroup_offset = 0; |
1638 | curr_prot++; | 1596 | curr_prot++; |
@@ -2006,16 +1964,21 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
2006 | if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { | 1964 | if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { |
2007 | /* | 1965 | /* |
2008 | * setup sense data descriptor 0 per SPC-4 as an information | 1966 | * setup sense data descriptor 0 per SPC-4 as an information |
2009 | * field, and put the failing LBA in it | 1967 | * field, and put the failing LBA in it. |
1968 | * This code assumes there was also a guard/app/ref tag error | ||
1969 | * indication. | ||
2010 | */ | 1970 | */ |
2011 | cmd->sense_buffer[8] = 0; /* Information */ | 1971 | cmd->sense_buffer[7] = 0xc; /* Additional sense length */ |
2012 | cmd->sense_buffer[9] = 0xa; /* Add. length */ | 1972 | cmd->sense_buffer[8] = 0; /* Information descriptor type */ |
1973 | cmd->sense_buffer[9] = 0xa; /* Additional descriptor length */ | ||
1974 | cmd->sense_buffer[10] = 0x80; /* Validity bit */ | ||
2013 | bghm /= cmd->device->sector_size; | 1975 | bghm /= cmd->device->sector_size; |
2014 | 1976 | ||
2015 | failing_sector = scsi_get_lba(cmd); | 1977 | failing_sector = scsi_get_lba(cmd); |
2016 | failing_sector += bghm; | 1978 | failing_sector += bghm; |
2017 | 1979 | ||
2018 | put_unaligned_be64(failing_sector, &cmd->sense_buffer[10]); | 1980 | /* Descriptor Information */ |
1981 | put_unaligned_be64(failing_sector, &cmd->sense_buffer[12]); | ||
2019 | } | 1982 | } |
2020 | 1983 | ||
2021 | if (!ret) { | 1984 | if (!ret) { |