Commit a6887e2874916aff0f56ae8f2cded797fa9b2225

Authored by James Smart
Committed by James Bottomley
1 parent a40fc5f0d0

[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
... ... @@ -1667,6 +1667,7 @@
1667 1667 #define BG_OP_IN_CSUM_OUT_CSUM 0x5
1668 1668 #define BG_OP_IN_CRC_OUT_CSUM 0x6
1669 1669 #define BG_OP_IN_CSUM_OUT_CRC 0x7
  1670 +#define BG_OP_RAW_MODE 0x8
1670 1671  
1671 1672 struct lpfc_pde5 {
1672 1673 uint32_t word0;
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 /*