diff options
author | Eric Moore <eric.moore@lsi.com> | 2009-05-18 14:59:41 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-05-23 16:44:16 -0400 |
commit | 3c621b3ee1432e7a2aca4a3b670b1d05f19ecf9c (patch) | |
tree | d8decff739834f1e9930a3e332cf770bf0d7372b /drivers/scsi/mpt2sas/mpt2sas_scsih.c | |
parent | 6fcf41d1d8796f41b893754324704e23971c2ea1 (diff) |
[SCSI] mpt2sas: T10 DIF Support
This add support for type 1 and 3 DIF support per the Oracle API.
Signed-off-by: Eric Moore <eric.moore@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/mpt2sas/mpt2sas_scsih.c')
-rw-r--r-- | drivers/scsi/mpt2sas/mpt2sas_scsih.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index e3a7967259e7..5394f6196416 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -2390,6 +2390,106 @@ mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase) | |||
2390 | } | 2390 | } |
2391 | 2391 | ||
2392 | /** | 2392 | /** |
2393 | * _scsih_setup_eedp - setup MPI request for EEDP transfer | ||
2394 | * @scmd: pointer to scsi command object | ||
2395 | * @mpi_request: pointer to the SCSI_IO reqest message frame | ||
2396 | * | ||
2397 | * Supporting protection 1 and 3. | ||
2398 | * | ||
2399 | * Returns nothing | ||
2400 | */ | ||
2401 | static void | ||
2402 | _scsih_setup_eedp(struct scsi_cmnd *scmd, Mpi2SCSIIORequest_t *mpi_request) | ||
2403 | { | ||
2404 | u16 eedp_flags; | ||
2405 | unsigned char prot_op = scsi_get_prot_op(scmd); | ||
2406 | unsigned char prot_type = scsi_get_prot_type(scmd); | ||
2407 | |||
2408 | if (prot_type == SCSI_PROT_DIF_TYPE0 || | ||
2409 | prot_type == SCSI_PROT_DIF_TYPE2 || | ||
2410 | prot_op == SCSI_PROT_NORMAL) | ||
2411 | return; | ||
2412 | |||
2413 | if (prot_op == SCSI_PROT_READ_STRIP) | ||
2414 | eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP; | ||
2415 | else if (prot_op == SCSI_PROT_WRITE_INSERT) | ||
2416 | eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; | ||
2417 | else | ||
2418 | return; | ||
2419 | |||
2420 | mpi_request->EEDPBlockSize = scmd->device->sector_size; | ||
2421 | |||
2422 | switch (prot_type) { | ||
2423 | case SCSI_PROT_DIF_TYPE1: | ||
2424 | |||
2425 | /* | ||
2426 | * enable ref/guard checking | ||
2427 | * auto increment ref tag | ||
2428 | */ | ||
2429 | mpi_request->EEDPFlags = eedp_flags | | ||
2430 | MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | | ||
2431 | MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | | ||
2432 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
2433 | mpi_request->CDB.EEDP32.PrimaryReferenceTag = | ||
2434 | cpu_to_be32(scsi_get_lba(scmd)); | ||
2435 | |||
2436 | break; | ||
2437 | |||
2438 | case SCSI_PROT_DIF_TYPE3: | ||
2439 | |||
2440 | /* | ||
2441 | * enable guard checking | ||
2442 | */ | ||
2443 | mpi_request->EEDPFlags = eedp_flags | | ||
2444 | MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; | ||
2445 | |||
2446 | break; | ||
2447 | } | ||
2448 | } | ||
2449 | |||
2450 | /** | ||
2451 | * _scsih_eedp_error_handling - return sense code for EEDP errors | ||
2452 | * @scmd: pointer to scsi command object | ||
2453 | * @ioc_status: ioc status | ||
2454 | * | ||
2455 | * Returns nothing | ||
2456 | */ | ||
2457 | static void | ||
2458 | _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) | ||
2459 | { | ||
2460 | u8 ascq; | ||
2461 | u8 sk; | ||
2462 | u8 host_byte; | ||
2463 | |||
2464 | switch (ioc_status) { | ||
2465 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
2466 | ascq = 0x01; | ||
2467 | break; | ||
2468 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
2469 | ascq = 0x02; | ||
2470 | break; | ||
2471 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
2472 | ascq = 0x03; | ||
2473 | break; | ||
2474 | default: | ||
2475 | ascq = 0x00; | ||
2476 | break; | ||
2477 | } | ||
2478 | |||
2479 | if (scmd->sc_data_direction == DMA_TO_DEVICE) { | ||
2480 | sk = ILLEGAL_REQUEST; | ||
2481 | host_byte = DID_ABORT; | ||
2482 | } else { | ||
2483 | sk = ABORTED_COMMAND; | ||
2484 | host_byte = DID_OK; | ||
2485 | } | ||
2486 | |||
2487 | scsi_build_sense_buffer(0, scmd->sense_buffer, sk, 0x10, ascq); | ||
2488 | scmd->result = DRIVER_SENSE << 24 | (host_byte << 16) | | ||
2489 | SAM_STAT_CHECK_CONDITION; | ||
2490 | } | ||
2491 | |||
2492 | /** | ||
2393 | * scsih_qcmd - main scsi request entry point | 2493 | * scsih_qcmd - main scsi request entry point |
2394 | * @scmd: pointer to scsi command object | 2494 | * @scmd: pointer to scsi command object |
2395 | * @done: function pointer to be invoked on completion | 2495 | * @done: function pointer to be invoked on completion |
@@ -2470,6 +2570,7 @@ scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2470 | } | 2570 | } |
2471 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 2571 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
2472 | memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); | 2572 | memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); |
2573 | _scsih_setup_eedp(scmd, mpi_request); | ||
2473 | mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; | 2574 | mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; |
2474 | if (sas_device_priv_data->sas_target->flags & | 2575 | if (sas_device_priv_data->sas_target->flags & |
2475 | MPT_TARGET_FLAGS_RAID_COMPONENT) | 2576 | MPT_TARGET_FLAGS_RAID_COMPONENT) |
@@ -2604,6 +2705,15 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, | |||
2604 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: | 2705 | case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: |
2605 | desc_ioc_state = "scsi ext terminated"; | 2706 | desc_ioc_state = "scsi ext terminated"; |
2606 | break; | 2707 | break; |
2708 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
2709 | desc_ioc_state = "eedp guard error"; | ||
2710 | break; | ||
2711 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
2712 | desc_ioc_state = "eedp ref tag error"; | ||
2713 | break; | ||
2714 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
2715 | desc_ioc_state = "eedp app tag error"; | ||
2716 | break; | ||
2607 | default: | 2717 | default: |
2608 | desc_ioc_state = "unknown"; | 2718 | desc_ioc_state = "unknown"; |
2609 | break; | 2719 | break; |
@@ -2939,6 +3049,11 @@ scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
2939 | scmd->result = DID_RESET << 16; | 3049 | scmd->result = DID_RESET << 16; |
2940 | break; | 3050 | break; |
2941 | 3051 | ||
3052 | case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: | ||
3053 | case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: | ||
3054 | case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: | ||
3055 | _scsih_eedp_error_handling(scmd, ioc_status); | ||
3056 | break; | ||
2942 | case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: | 3057 | case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: |
2943 | case MPI2_IOCSTATUS_INVALID_FUNCTION: | 3058 | case MPI2_IOCSTATUS_INVALID_FUNCTION: |
2944 | case MPI2_IOCSTATUS_INVALID_SGL: | 3059 | case MPI2_IOCSTATUS_INVALID_SGL: |
@@ -5503,6 +5618,9 @@ scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5503 | goto out_add_shost_fail; | 5618 | goto out_add_shost_fail; |
5504 | } | 5619 | } |
5505 | 5620 | ||
5621 | scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION | ||
5622 | | SHOST_DIF_TYPE3_PROTECTION); | ||
5623 | |||
5506 | /* event thread */ | 5624 | /* event thread */ |
5507 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), | 5625 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), |
5508 | "fw_event%d", ioc->id); | 5626 | "fw_event%d", ioc->id); |