Commit a6887e2874916aff0f56ae8f2cded797fa9b2225
Committed by
James Bottomley
1 parent
a40fc5f0d0
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
[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>
Showing 2 changed files with 116 additions and 66 deletions Side-by-side Diff
drivers/scsi/lpfc/lpfc_hw.h
drivers/scsi/lpfc/lpfc_scsi.c
... | ... | @@ -68,6 +68,10 @@ |
68 | 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 | 75 | static void |
72 | 76 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); |
73 | 77 | static void |
74 | 78 | |
... | ... | @@ -2066,9 +2070,21 @@ |
2066 | 2070 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); |
2067 | 2071 | bf_set(pde6_optx, pde6, txop); |
2068 | 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 | 2078 | if (datadir == DMA_FROM_DEVICE) { |
2070 | - bf_set(pde6_ce, pde6, checking); | |
2071 | - bf_set(pde6_re, pde6, checking); | |
2079 | + if (scsi_prot_flagged(sc, SCSI_PROT_GUARD_CHECK)) | |
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 | 2089 | bf_set(pde6_ai, pde6, 1); |
2074 | 2090 | bf_set(pde6_ae, pde6, 0); |
... | ... | @@ -2221,8 +2237,17 @@ |
2221 | 2237 | bf_set(pde6_type, pde6, LPFC_PDE6_DESCRIPTOR); |
2222 | 2238 | bf_set(pde6_optx, pde6, txop); |
2223 | 2239 | bf_set(pde6_oprx, pde6, rxop); |
2224 | - bf_set(pde6_ce, pde6, checking); | |
2225 | - bf_set(pde6_re, pde6, checking); | |
2240 | + | |
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 | 2251 | bf_set(pde6_ai, pde6, 1); |
2227 | 2252 | bf_set(pde6_ae, pde6, 0); |
2228 | 2253 | bf_set(pde6_apptagval, pde6, 0); |
... | ... | @@ -2385,7 +2410,6 @@ |
2385 | 2410 | struct sli4_sge_diseed *diseed = NULL; |
2386 | 2411 | dma_addr_t physaddr; |
2387 | 2412 | int i = 0, num_sge = 0, status; |
2388 | - int datadir = sc->sc_data_direction; | |
2389 | 2413 | uint32_t reftag; |
2390 | 2414 | unsigned blksize; |
2391 | 2415 | uint8_t txop, rxop; |
2392 | 2416 | |
... | ... | @@ -2423,13 +2447,26 @@ |
2423 | 2447 | diseed->ref_tag = cpu_to_le32(reftag); |
2424 | 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 | 2466 | /* setup DISEED with the rest of the info */ |
2427 | 2467 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); |
2428 | 2468 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); |
2429 | - if (datadir == DMA_FROM_DEVICE) { | |
2430 | - bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | |
2431 | - bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | |
2432 | - } | |
2469 | + | |
2433 | 2470 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); |
2434 | 2471 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); |
2435 | 2472 | |
2436 | 2473 | |
... | ... | @@ -2571,11 +2608,34 @@ |
2571 | 2608 | diseed->ref_tag = cpu_to_le32(reftag); |
2572 | 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 | 2635 | /* setup DISEED with the rest of the info */ |
2575 | 2636 | bf_set(lpfc_sli4_sge_dif_optx, diseed, txop); |
2576 | 2637 | bf_set(lpfc_sli4_sge_dif_oprx, diseed, rxop); |
2577 | - bf_set(lpfc_sli4_sge_dif_ce, diseed, checking); | |
2578 | - bf_set(lpfc_sli4_sge_dif_re, diseed, checking); | |
2638 | + | |
2579 | 2639 | bf_set(lpfc_sli4_sge_dif_ai, diseed, 1); |
2580 | 2640 | bf_set(lpfc_sli4_sge_dif_me, diseed, 0); |
2581 | 2641 | |
... | ... | @@ -2739,6 +2799,47 @@ |
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 | 2843 | * lpfc_bg_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec |
2743 | 2844 | * @phba: The Hba for which this call is being executed. |
2744 | 2845 | * @lpfc_cmd: The scsi buffer which is going to be prep'ed. |
... | ... | @@ -2758,8 +2859,7 @@ |
2758 | 2859 | uint32_t num_bde = 0; |
2759 | 2860 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; |
2760 | 2861 | int prot_group_type = 0; |
2761 | - int diflen, fcpdl; | |
2762 | - unsigned blksize; | |
2862 | + int fcpdl; | |
2763 | 2863 | |
2764 | 2864 | /* |
2765 | 2865 | * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd |
... | ... | @@ -2856,18 +2956,7 @@ |
2856 | 2956 | iocb_cmd->ulpBdeCount = 1; |
2857 | 2957 | iocb_cmd->ulpLe = 1; |
2858 | 2958 | |
2859 | - fcpdl = scsi_bufflen(scsi_cmnd); | |
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 | - } | |
2959 | + fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); | |
2871 | 2960 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); |
2872 | 2961 | |
2873 | 2962 | /* |
... | ... | @@ -2982,7 +3071,7 @@ |
2982 | 3071 | chk_guard = 1; |
2983 | 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 | 3075 | start_app_tag = src->app_tag; |
2987 | 3076 | src = (struct scsi_dif_tuple *)sg_virt(sgpe); |
2988 | 3077 | len = sgpe->length; |
... | ... | @@ -3398,45 +3487,6 @@ |
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 | 3490 | * lpfc_bg_scsi_prep_dma_buf_s4 - DMA mapping for scsi buffer to SLI4 IF spec |
3441 | 3491 | * @phba: The Hba for which this call is being executed. |
3442 | 3492 | * @lpfc_cmd: The scsi buffer which is going to be mapped. |
... | ... | @@ -3564,7 +3614,6 @@ |
3564 | 3614 | } |
3565 | 3615 | |
3566 | 3616 | fcpdl = lpfc_bg_scsi_adjust_dl(phba, lpfc_cmd); |
3567 | - | |
3568 | 3617 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); |
3569 | 3618 | |
3570 | 3619 | /* |