aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/mpt2sas/mpt2sas_scsih.c
diff options
context:
space:
mode:
authorEric Moore <eric.moore@lsi.com>2009-05-18 14:59:41 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-05-23 16:44:16 -0400
commit3c621b3ee1432e7a2aca4a3b670b1d05f19ecf9c (patch)
treed8decff739834f1e9930a3e332cf770bf0d7372b /drivers/scsi/mpt2sas/mpt2sas_scsih.c
parent6fcf41d1d8796f41b893754324704e23971c2ea1 (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.c118
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 */
2401static 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 */
2457static 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);