diff options
author | James Smart <james.smart@emulex.com> | 2013-04-17 20:18:07 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-05-02 16:02:40 -0400 |
commit | a6887e2874916aff0f56ae8f2cded797fa9b2225 (patch) | |
tree | a1df62951bea3f1c8b97902d5d75ea747a42f73f /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | a40fc5f0d052d468f66da5fab3be0adb6cb6443d (diff) |
[SCSI] lpfc 8.3.39: Fixed BlockGuard to take advantage of rdprotect/wrprotect info when available
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 181 |
1 files changed, 115 insertions, 66 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index be11bb9cb176..44995de74a62 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -68,6 +68,10 @@ struct scsi_dif_tuple { | |||
68 | __be32 ref_tag; /* Target LBA or indirect LBA */ | 68 | __be32 ref_tag; /* Target LBA or indirect LBA */ |
69 | }; | 69 | }; |
70 | 70 | ||
71 | #if !defined(SCSI_PROT_GUARD_CHECK) || !defined(SCSI_PROT_REF_CHECK) | ||
72 | #define scsi_prot_flagged(sc, flg) sc | ||
73 | #endif | ||
74 | |||
71 | static void | 75 | static void |
72 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); | 76 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); |
73 | static void | 77 | static void |
@@ -2066,9 +2070,21 @@ lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
2066 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); | 2070 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); |
2067 | bf_set(pde6_optx, pde6, txop); | 2071 | bf_set(pde6_optx, pde6, txop); |
2068 | bf_set(pde6_oprx, pde6, rxop); | 2072 | bf_set(pde6_oprx, pde6, rxop); |
2073 | |||
2074 | /* | ||
2075 | * We only need to check the data on READs, for WRITEs | ||
2076 | * protection data is automatically generated, not checked. | ||
2077 | */ | ||
2069 | if (datadir == DMA_FROM_DEVICE) { | 2078 | if (datadir == DMA_FROM_DEVICE) { |
2070 | bf_set(pde6_ce, pde6, checking); | 2079 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) |
2071 | bf_set(pde6_re, pde6, checking); | 2080 | bf_set(pde6_ce, pde6, checking); |
2081 | else | ||
2082 | bf_set(pde6_ce, pde6, 0); | ||
2083 | |||
2084 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
2085 | bf_set(pde6_re, pde6, checking); | ||
2086 | else | ||
2087 | bf_set(pde6_re, pde6, 0); | ||
2072 | } | 2088 | } |
2073 | bf_set(pde6_ai, pde6, 1); | 2089 | bf_set(pde6_ai, pde6, 1); |
2074 | bf_set(pde6_ae, pde6, 0); | 2090 | bf_set(pde6_ae, pde6, 0); |
@@ -2221,8 +2237,17 @@ lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
2221 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); | 2237 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); |
2222 | bf_set(pde6_optx, pde6, txop); | 2238 | bf_set(pde6_optx, pde6, txop); |
2223 | bf_set(pde6_oprx, pde6, rxop); | 2239 | bf_set(pde6_oprx, pde6, rxop); |
2224 | bf_set(pde6_ce, pde6, checking); | 2240 | |
2225 | bf_set(pde6_re, pde6, checking); | 2241 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) |
2242 | bf_set(pde6_ce, pde6, checking); | ||
2243 | else | ||
2244 | bf_set(pde6_ce, pde6, 0); | ||
2245 | |||
2246 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
2247 | bf_set(pde6_re, pde6, checking); | ||
2248 | else | ||
2249 | bf_set(pde6_re, pde6, 0); | ||
2250 | |||
2226 | bf_set(pde6_ai, pde6, 1); | 2251 | bf_set(pde6_ai, pde6, 1); |
2227 | bf_set(pde6_ae, pde6, 0); | 2252 | bf_set(pde6_ae, pde6, 0); |
2228 | bf_set(pde6_apptagval, pde6, 0); | 2253 | bf_set(pde6_apptagval, pde6, 0); |
@@ -2385,7 +2410,6 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
2385 | struct sli4_sge_diseed *diseed = NULL; | 2410 | struct sli4_sge_diseed *diseed = NULL; |
2386 | dma_addr_t physaddr; | 2411 | dma_addr_t physaddr; |
2387 | int i = 0, num_sge = 0, status; | 2412 | int i = 0, num_sge = 0, status; |
2388 | int datadir = sc->sc_data_direction; | ||
2389 | uint32_t reftag; | 2413 | uint32_t reftag; |
2390 | unsigned blksize; | 2414 | unsigned blksize; |
2391 | uint8_t txop, rxop; | 2415 | uint8_t txop, rxop; |
@@ -2423,13 +2447,26 @@ lpfc_bg_setup_sgl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
2423 | diseed->ref_tag = cpu_to_le32(reftag); | 2447 | diseed->ref_tag = cpu_to_le32(reftag); |
2424 | diseed->ref_tag_tran = diseed->ref_tag; | 2448 | diseed->ref_tag_tran = diseed->ref_tag; |
2425 | 2449 | ||
2450 | /* | ||
2451 | * We only need to check the data on READs, for WRITEs | ||
2452 | * protection data is automatically generated, not checked. | ||
2453 | */ | ||
2454 | if (sc->sc_data_direction == DMA_FROM_DEVICE) { | ||
2455 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) | ||
2456 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | ||
2457 | else | ||
2458 | bf_set(lpfc_sli4_sge_dif_ce, diseed, 0); | ||
2459 | |||
2460 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
2461 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
2462 | else | ||
2463 | bf_set(lpfc_sli4_sge_dif_re, diseed, 0); | ||
2464 | } | ||
2465 | |||
2426 | /* setup DISEED with the rest of the info */ | 2466 | /* setup DISEED with the rest of the info */ |
2427 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); | 2467 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); |
2428 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); | 2468 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); |
2429 | if (datadir == DMA_FROM_DEVICE) { | 2469 | |
2430 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | ||
2431 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
2432 | } | ||
2433 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); | 2470 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); |
2434 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); | 2471 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); |
2435 | 2472 | ||
@@ -2571,11 +2608,34 @@ lpfc_bg_setup_sgl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | |||
2571 | diseed->ref_tag = cpu_to_le32(reftag); | 2608 | diseed->ref_tag = cpu_to_le32(reftag); |
2572 | diseed->ref_tag_tran = diseed->ref_tag; | 2609 | diseed->ref_tag_tran = diseed->ref_tag; |
2573 | 2610 | ||
2611 | if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) { | ||
2612 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | ||
2613 | |||
2614 | } else { | ||
2615 | bf_set(lpfc_sli4_sge_dif_ce, diseed, 0); | ||
2616 | /* | ||
2617 | * When in this mode, the hardware will replace | ||
2618 | * the guard tag from the host with a | ||
2619 | * newly generated good CRC for the wire. | ||
2620 | * Switch to raw mode here to avoid this | ||
2621 | * behavior. What the host sends gets put on the wire. | ||
2622 | */ | ||
2623 | if (txop == BG_OP_IN_CRC_OUT_CRC) { | ||
2624 | txop = BG_OP_RAW_MODE; | ||
2625 | rxop = BG_OP_RAW_MODE; | ||
2626 | } | ||
2627 | } | ||
2628 | |||
2629 | |||
2630 | if (scsi_prot_flagged(sc, SCSI_PROT_REF_CHECK)) | ||
2631 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
2632 | else | ||
2633 | bf_set(lpfc_sli4_sge_dif_re, diseed, 0); | ||
2634 | |||
2574 | /* setup DISEED with the rest of the info */ | 2635 | /* setup DISEED with the rest of the info */ |
2575 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); | 2636 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); |
2576 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); | 2637 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); |
2577 | bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | 2638 | |
2578 | bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | ||
2579 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); | 2639 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); |
2580 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); | 2640 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); |
2581 | 2641 | ||
@@ -2739,6 +2799,47 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc) | |||
2739 | } | 2799 | } |
2740 | 2800 | ||
2741 | /** | 2801 | /** |
2802 | * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard | ||
2803 | * @phba: The Hba for which this call is being executed. | ||
2804 | * @lpfc_cmd: The scsi buffer which is going to be adjusted. | ||
2805 | * | ||
2806 | * Adjust the data length to account for how much data | ||
2807 | * is actually on the wire. | ||
2808 | * | ||
2809 | * returns the adjusted data length | ||
2810 | **/ | ||
2811 | static int | ||
2812 | lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba, | ||
2813 | struct lpfc_scsi_buf *lpfc_cmd) | ||
2814 | { | ||
2815 | struct scsi_cmnd *sc = lpfc_cmd->pCmd; | ||
2816 | int fcpdl; | ||
2817 | |||
2818 | fcpdl = scsi_bufflen(sc); | ||
2819 | |||
2820 | /* Check if there is protection data on the wire */ | ||
2821 | if (sc->sc_data_direction == DMA_FROM_DEVICE) { | ||
2822 | /* Read */ | ||
2823 | if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT) | ||
2824 | return fcpdl; | ||
2825 | |||
2826 | } else { | ||
2827 | /* Write */ | ||
2828 | if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP) | ||
2829 | return fcpdl; | ||
2830 | } | ||
2831 | |||
2832 | /* | ||
2833 | * If we are in DIF Type 1 mode every data block has a 8 byte | ||
2834 | * DIF (trailer) attached to it. Must ajust FCP data length. | ||
2835 | */ | ||
2836 | if (scsi_prot_flagged(sc, SCSI_PROT_TRANSFER_PI)) | ||
2837 | fcpdl += (fcpdl / lpfc_cmd_blksize(sc)) * 8; | ||
2838 | |||
2839 | return fcpdl; | ||
2840 | } | ||
2841 | |||
2842 | /** | ||
2742 | * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec | 2843 | * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec |
2743 | * @phba: The Hba for which this call is being executed. | 2844 | * @phba: The Hba for which this call is being executed. |
2744 | * @lpfc_cmd: The scsi buffer which is going to be prep'ed. | 2845 | * @lpfc_cmd: The scsi buffer which is going to be prep'ed. |
@@ -2758,8 +2859,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
2758 | uint32_t num_bde = 0; | 2859 | uint32_t num_bde = 0; |
2759 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; | 2860 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; |
2760 | int prot_group_type = 0; | 2861 | int prot_group_type = 0; |
2761 | int diflen, fcpdl; | 2862 | int fcpdl; |
2762 | unsigned blksize; | ||
2763 | 2863 | ||
2764 | /* | 2864 | /* |
2765 | * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd | 2865 | * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd |
@@ -2856,18 +2956,7 @@ lpfc_bg_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, | |||
2856 | iocb_cmd->ulpBdeCount = 1; | 2956 | iocb_cmd->ulpBdeCount = 1; |
2857 | iocb_cmd->ulpLe = 1; | 2957 | iocb_cmd->ulpLe = 1; |
2858 | 2958 | ||
2859 | fcpdl = scsi_bufflen(scsi_cmnd); | 2959 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); |
2860 | |||
2861 | if (scsi_get_prot_type(scsi_cmnd) == SCSI_PROT_DIF_TYPE1) { | ||
2862 | /* | ||
2863 | * We are in DIF Type 1 mode | ||
2864 | * Every data block has a 8 byte DIF (trailer) | ||
2865 | * attached to it. Must ajust FCP data length | ||
2866 | */ | ||
2867 | blksize = lpfc_cmd_blksize(scsi_cmnd); | ||
2868 | diflen = (fcpdl / blksize) * 8; | ||
2869 | fcpdl += diflen; | ||
2870 | } | ||
2871 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); | 2960 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); |
2872 | 2961 | ||
2873 | /* | 2962 | /* |
@@ -2982,7 +3071,7 @@ lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
2982 | chk_guard = 1; | 3071 | chk_guard = 1; |
2983 | guard_type = scsi_host_get_guard(cmd->device->host); | 3072 | guard_type = scsi_host_get_guard(cmd->device->host); |
2984 | 3073 | ||
2985 | start_ref_tag = scsi_get_lba(cmd); | 3074 | start_ref_tag = (uint32_t)scsi_get_lba(cmd); /* Truncate LBA */ |
2986 | start_app_tag = src->app_tag; | 3075 | start_app_tag = src->app_tag; |
2987 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); | 3076 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); |
2988 | len = sgpe->length; | 3077 | len = sgpe->length; |
@@ -3398,45 +3487,6 @@ lpfc_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
3398 | } | 3487 | } |
3399 | 3488 | ||
3400 | /** | 3489 | /** |
3401 | * lpfc_bg_scsi_adjust_dl - Adjust SCSI data length for BlockGuard | ||
3402 | * @phba: The Hba for which this call is being executed. | ||
3403 | * @lpfc_cmd: The scsi buffer which is going to be adjusted. | ||
3404 | * | ||
3405 | * Adjust the data length to account for how much data | ||
3406 | * is actually on the wire. | ||
3407 | * | ||
3408 | * returns the adjusted data length | ||
3409 | **/ | ||
3410 | static int | ||
3411 | lpfc_bg_scsi_adjust_dl(struct lpfc_hba *phba, | ||
3412 | struct lpfc_scsi_buf *lpfc_cmd) | ||
3413 | { | ||
3414 | struct scsi_cmnd *sc = lpfc_cmd->pCmd; | ||
3415 | int diflen, fcpdl; | ||
3416 | unsigned blksize; | ||
3417 | |||
3418 | fcpdl = scsi_bufflen(sc); | ||
3419 | |||
3420 | /* Check if there is protection data on the wire */ | ||
3421 | if (sc->sc_data_direction == DMA_FROM_DEVICE) { | ||
3422 | /* Read */ | ||
3423 | if (scsi_get_prot_op(sc) == SCSI_PROT_READ_INSERT) | ||
3424 | return fcpdl; | ||
3425 | |||
3426 | } else { | ||
3427 | /* Write */ | ||
3428 | if (scsi_get_prot_op(sc) == SCSI_PROT_WRITE_STRIP) | ||
3429 | return fcpdl; | ||
3430 | } | ||
3431 | |||
3432 | /* If protection data on the wire, adjust the count accordingly */ | ||
3433 | blksize = lpfc_cmd_blksize(sc); | ||
3434 | diflen = (fcpdl / blksize) * 8; | ||
3435 | fcpdl += diflen; | ||
3436 | return fcpdl; | ||
3437 | } | ||
3438 | |||
3439 | /** | ||
3440 | * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec | 3490 | * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec |
3441 | * @phba: The Hba for which this call is being executed. | 3491 | * @phba: The Hba for which this call is being executed. |
3442 | * @lpfc_cmd: The scsi buffer which is going to be mapped. | 3492 | * @lpfc_cmd: The scsi buffer which is going to be mapped. |
@@ -3564,7 +3614,6 @@ lpfc_bg_scsi_prep_dma_buf_s4(struct lpfc_hba *phba, | |||
3564 | } | 3614 | } |
3565 | 3615 | ||
3566 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); | 3616 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); |
3567 | |||
3568 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); | 3617 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); |
3569 | 3618 | ||
3570 | /* | 3619 | /* |