diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_isr.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_isr.c | 109 |
1 files changed, 84 insertions, 25 deletions
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index b16b7725dee0..646fc5263d50 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -719,7 +719,6 @@ skip_rio: | |||
719 | vha->flags.rscn_queue_overflow = 1; | 719 | vha->flags.rscn_queue_overflow = 1; |
720 | } | 720 | } |
721 | 721 | ||
722 | atomic_set(&vha->loop_state, LOOP_UPDATE); | ||
723 | atomic_set(&vha->loop_down_timer, 0); | 722 | atomic_set(&vha->loop_down_timer, 0); |
724 | vha->flags.management_server_logged_in = 0; | 723 | vha->flags.management_server_logged_in = 0; |
725 | 724 | ||
@@ -1435,25 +1434,27 @@ struct scsi_dif_tuple { | |||
1435 | * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST | 1434 | * ASC/ASCQ fields in the sense buffer with ILLEGAL_REQUEST |
1436 | * to indicate to the kernel that the HBA detected error. | 1435 | * to indicate to the kernel that the HBA detected error. |
1437 | */ | 1436 | */ |
1438 | static inline void | 1437 | static inline int |
1439 | qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) | 1438 | qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) |
1440 | { | 1439 | { |
1441 | struct scsi_qla_host *vha = sp->fcport->vha; | 1440 | struct scsi_qla_host *vha = sp->fcport->vha; |
1442 | struct scsi_cmnd *cmd = sp->cmd; | 1441 | struct scsi_cmnd *cmd = sp->cmd; |
1443 | struct scsi_dif_tuple *ep = | 1442 | uint8_t *ap = &sts24->data[12]; |
1444 | (struct scsi_dif_tuple *)&sts24->data[20]; | 1443 | 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; | 1444 | uint32_t e_ref_tag, a_ref_tag; |
1448 | uint16_t e_app_tag, a_app_tag; | 1445 | uint16_t e_app_tag, a_app_tag; |
1449 | uint16_t e_guard, a_guard; | 1446 | uint16_t e_guard, a_guard; |
1450 | 1447 | ||
1451 | e_ref_tag = be32_to_cpu(ep->ref_tag); | 1448 | /* |
1452 | a_ref_tag = be32_to_cpu(ap->ref_tag); | 1449 | * swab32 of the "data" field in the beginning of qla2x00_status_entry() |
1453 | e_app_tag = be16_to_cpu(ep->app_tag); | 1450 | * would make guard field appear at offset 2 |
1454 | a_app_tag = be16_to_cpu(ap->app_tag); | 1451 | */ |
1455 | e_guard = be16_to_cpu(ep->guard); | 1452 | a_guard = le16_to_cpu(*(uint16_t *)(ap + 2)); |
1456 | a_guard = be16_to_cpu(ap->guard); | 1453 | a_app_tag = le16_to_cpu(*(uint16_t *)(ap + 0)); |
1454 | a_ref_tag = le32_to_cpu(*(uint32_t *)(ap + 4)); | ||
1455 | e_guard = le16_to_cpu(*(uint16_t *)(ep + 2)); | ||
1456 | e_app_tag = le16_to_cpu(*(uint16_t *)(ep + 0)); | ||
1457 | e_ref_tag = le32_to_cpu(*(uint32_t *)(ep + 4)); | ||
1457 | 1458 | ||
1458 | ql_dbg(ql_dbg_io, vha, 0x3023, | 1459 | ql_dbg(ql_dbg_io, vha, 0x3023, |
1459 | "iocb(s) %p Returned STATUS.\n", sts24); | 1460 | "iocb(s) %p Returned STATUS.\n", sts24); |
@@ -1465,6 +1466,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, | 1466 | 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); | 1467 | a_app_tag, e_app_tag, a_guard, e_guard); |
1467 | 1468 | ||
1469 | /* | ||
1470 | * Ignore sector if: | ||
1471 | * For type 3: ref & app tag is all 'f's | ||
1472 | * For type 0,1,2: app tag is all 'f's | ||
1473 | */ | ||
1474 | if ((a_app_tag == 0xffff) && | ||
1475 | ((scsi_get_prot_type(cmd) != SCSI_PROT_DIF_TYPE3) || | ||
1476 | (a_ref_tag == 0xffffffff))) { | ||
1477 | uint32_t blocks_done, resid; | ||
1478 | sector_t lba_s = scsi_get_lba(cmd); | ||
1479 | |||
1480 | /* 2TB boundary case covered automatically with this */ | ||
1481 | blocks_done = e_ref_tag - (uint32_t)lba_s + 1; | ||
1482 | |||
1483 | resid = scsi_bufflen(cmd) - (blocks_done * | ||
1484 | cmd->device->sector_size); | ||
1485 | |||
1486 | scsi_set_resid(cmd, resid); | ||
1487 | cmd->result = DID_OK << 16; | ||
1488 | |||
1489 | /* Update protection tag */ | ||
1490 | if (scsi_prot_sg_count(cmd)) { | ||
1491 | uint32_t i, j = 0, k = 0, num_ent; | ||
1492 | struct scatterlist *sg; | ||
1493 | struct sd_dif_tuple *spt; | ||
1494 | |||
1495 | /* Patch the corresponding protection tags */ | ||
1496 | scsi_for_each_prot_sg(cmd, sg, | ||
1497 | scsi_prot_sg_count(cmd), i) { | ||
1498 | num_ent = sg_dma_len(sg) / 8; | ||
1499 | if (k + num_ent < blocks_done) { | ||
1500 | k += num_ent; | ||
1501 | continue; | ||
1502 | } | ||
1503 | j = blocks_done - k - 1; | ||
1504 | k = blocks_done; | ||
1505 | break; | ||
1506 | } | ||
1507 | |||
1508 | if (k != blocks_done) { | ||
1509 | qla_printk(KERN_WARNING, sp->fcport->vha->hw, | ||
1510 | "unexpected tag values tag:lba=%x:%lx)\n", | ||
1511 | e_ref_tag, lba_s); | ||
1512 | return 1; | ||
1513 | } | ||
1514 | |||
1515 | spt = page_address(sg_page(sg)) + sg->offset; | ||
1516 | spt += j; | ||
1517 | |||
1518 | spt->app_tag = 0xffff; | ||
1519 | if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE3) | ||
1520 | spt->ref_tag = 0xffffffff; | ||
1521 | } | ||
1522 | |||
1523 | return 0; | ||
1524 | } | ||
1525 | |||
1468 | /* check guard */ | 1526 | /* check guard */ |
1469 | if (e_guard != a_guard) { | 1527 | if (e_guard != a_guard) { |
1470 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | 1528 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, |
@@ -1472,28 +1530,30 @@ qla2x00_handle_dif_error(srb_t *sp, struct sts_entry_24xx *sts24) | |||
1472 | set_driver_byte(cmd, DRIVER_SENSE); | 1530 | set_driver_byte(cmd, DRIVER_SENSE); |
1473 | set_host_byte(cmd, DID_ABORT); | 1531 | set_host_byte(cmd, DID_ABORT); |
1474 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | 1532 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; |
1475 | return; | 1533 | return 1; |
1476 | } | 1534 | } |
1477 | 1535 | ||
1478 | /* check appl tag */ | 1536 | /* check ref tag */ |
1479 | if (e_app_tag != a_app_tag) { | 1537 | if (e_ref_tag != a_ref_tag) { |
1480 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | 1538 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, |
1481 | 0x10, 0x2); | 1539 | 0x10, 0x3); |
1482 | set_driver_byte(cmd, DRIVER_SENSE); | 1540 | set_driver_byte(cmd, DRIVER_SENSE); |
1483 | set_host_byte(cmd, DID_ABORT); | 1541 | set_host_byte(cmd, DID_ABORT); |
1484 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | 1542 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; |
1485 | return; | 1543 | return 1; |
1486 | } | 1544 | } |
1487 | 1545 | ||
1488 | /* check ref tag */ | 1546 | /* check appl tag */ |
1489 | if (e_ref_tag != a_ref_tag) { | 1547 | if (e_app_tag != a_app_tag) { |
1490 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | 1548 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, |
1491 | 0x10, 0x3); | 1549 | 0x10, 0x2); |
1492 | set_driver_byte(cmd, DRIVER_SENSE); | 1550 | set_driver_byte(cmd, DRIVER_SENSE); |
1493 | set_host_byte(cmd, DID_ABORT); | 1551 | set_host_byte(cmd, DID_ABORT); |
1494 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; | 1552 | cmd->result |= SAM_STAT_CHECK_CONDITION << 1; |
1495 | return; | 1553 | return 1; |
1496 | } | 1554 | } |
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; |
@@ -2468,11 +2528,10 @@ qla2x00_request_irqs(struct qla_hw_data *ha, struct rsp_que *rsp) | |||
2468 | goto skip_msi; | 2528 | goto skip_msi; |
2469 | } | 2529 | } |
2470 | 2530 | ||
2471 | if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX || | 2531 | if (IS_QLA2432(ha) && (ha->pdev->revision < QLA_MSIX_CHIP_REV_24XX)) { |
2472 | !QLA_MSIX_FW_MODE_1(ha->fw_attributes))) { | ||
2473 | ql_log(ql_log_warn, vha, 0x0035, | 2532 | ql_log(ql_log_warn, vha, 0x0035, |
2474 | "MSI-X; Unsupported ISP2432 (0x%X, 0x%X).\n", | 2533 | "MSI-X; Unsupported ISP2432 (0x%X, 0x%X).\n", |
2475 | ha->pdev->revision, ha->fw_attributes); | 2534 | ha->pdev->revision, QLA_MSIX_CHIP_REV_24XX); |
2476 | goto skip_msix; | 2535 | goto skip_msix; |
2477 | } | 2536 | } |
2478 | 2537 | ||