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/lpfc | |
| 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/lpfc')
| -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) { |
