Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] lpfc 8.3.39: Fixed BlockGuard error reporting

Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

James Smart and committed by
James Bottomley
737d4248 16a3a208

+255 -25
+1
drivers/scsi/lpfc/lpfc_logmsg.h
··· 37 37 #define LOG_EVENT 0x00010000 /* CT,TEMP,DUMP, logging */ 38 38 #define LOG_FIP 0x00020000 /* FIP events */ 39 39 #define LOG_FCP_UNDER 0x00040000 /* FCP underruns errors */ 40 + #define LOG_SCSI_CMD 0x00080000 /* ALL SCSI commands */ 40 41 #define LOG_ALL_MSG 0xffffffff /* LOG all messages */ 41 42 42 43 #define lpfc_printf_vlog(vport, level, mask, fmt, arg...) \
+254 -25
drivers/scsi/lpfc/lpfc_scsi.c
··· 24 24 #include <linux/export.h> 25 25 #include <linux/delay.h> 26 26 #include <asm/unaligned.h> 27 + #include <linux/crc-t10dif.h> 28 + #include <net/checksum.h> 27 29 28 30 #include <scsi/scsi.h> 29 31 #include <scsi/scsi_device.h> ··· 50 48 #define LPFC_RESET_WAIT 2 51 49 #define LPFC_ABORT_WAIT 2 52 50 53 - int _dump_buf_done; 51 + int _dump_buf_done = 1; 54 52 55 53 static char *dif_op_str[] = { 56 54 "PROT_NORMAL", ··· 2822 2820 } 2823 2821 2824 2822 /* 2823 + * This function calcuates the T10 DIF guard tag 2824 + * on the specified data using a CRC algorithmn 2825 + * using crc_t10dif. 2826 + */ 2827 + uint16_t 2828 + lpfc_bg_crc(uint8_t *data, int count) 2829 + { 2830 + uint16_t crc = 0; 2831 + uint16_t x; 2832 + 2833 + crc = crc_t10dif(data, count); 2834 + x = cpu_to_be16(crc); 2835 + return x; 2836 + } 2837 + 2838 + /* 2839 + * This function calcuates the T10 DIF guard tag 2840 + * on the specified data using a CSUM algorithmn 2841 + * using ip_compute_csum. 2842 + */ 2843 + uint16_t 2844 + lpfc_bg_csum(uint8_t *data, int count) 2845 + { 2846 + uint16_t ret; 2847 + 2848 + ret = ip_compute_csum(data, count); 2849 + return ret; 2850 + } 2851 + 2852 + /* 2853 + * This function examines the protection data to try to determine 2854 + * what type of T10-DIF error occurred. 2855 + */ 2856 + void 2857 + lpfc_calc_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) 2858 + { 2859 + struct scatterlist *sgpe; /* s/g prot entry */ 2860 + struct scatterlist *sgde; /* s/g data entry */ 2861 + struct scsi_cmnd *cmd = lpfc_cmd->pCmd; 2862 + struct scsi_dif_tuple *src = NULL; 2863 + uint8_t *data_src = NULL; 2864 + uint16_t guard_tag, guard_type; 2865 + uint16_t start_app_tag, app_tag; 2866 + uint32_t start_ref_tag, ref_tag; 2867 + int prot, protsegcnt; 2868 + int err_type, len, data_len; 2869 + int chk_ref, chk_app, chk_guard; 2870 + uint16_t sum; 2871 + unsigned blksize; 2872 + 2873 + err_type = BGS_GUARD_ERR_MASK; 2874 + sum = 0; 2875 + guard_tag = 0; 2876 + 2877 + /* First check to see if there is protection data to examine */ 2878 + prot = scsi_get_prot_op(cmd); 2879 + if ((prot == SCSI_PROT_READ_STRIP) || 2880 + (prot == SCSI_PROT_WRITE_INSERT) || 2881 + (prot == SCSI_PROT_NORMAL)) 2882 + goto out; 2883 + 2884 + /* Currently the driver just supports ref_tag and guard_tag checking */ 2885 + chk_ref = 1; 2886 + chk_app = 0; 2887 + chk_guard = 0; 2888 + 2889 + /* Setup a ptr to the protection data provided by the SCSI host */ 2890 + sgpe = scsi_prot_sglist(cmd); 2891 + protsegcnt = lpfc_cmd->prot_seg_cnt; 2892 + 2893 + if (sgpe && protsegcnt) { 2894 + 2895 + /* 2896 + * We will only try to verify guard tag if the segment 2897 + * data length is a multiple of the blksize. 2898 + */ 2899 + sgde = scsi_sglist(cmd); 2900 + blksize = lpfc_cmd_blksize(cmd); 2901 + data_src = (uint8_t *)sg_virt(sgde); 2902 + data_len = sgde->length; 2903 + if ((data_len & (blksize - 1)) == 0) 2904 + chk_guard = 1; 2905 + guard_type = scsi_host_get_guard(cmd->device->host); 2906 + 2907 + start_ref_tag = scsi_get_lba(cmd); 2908 + start_app_tag = src->app_tag; 2909 + src = (struct scsi_dif_tuple *)sg_virt(sgpe); 2910 + len = sgpe->length; 2911 + while (src && protsegcnt) { 2912 + while (len) { 2913 + 2914 + /* 2915 + * First check to see if a protection data 2916 + * check is valid 2917 + */ 2918 + if ((src->ref_tag == 0xffffffff) || 2919 + (src->app_tag == 0xffff)) { 2920 + start_ref_tag++; 2921 + goto skipit; 2922 + } 2923 + 2924 + /* App Tag checking */ 2925 + app_tag = src->app_tag; 2926 + if (chk_app && (app_tag != start_app_tag)) { 2927 + err_type = BGS_APPTAG_ERR_MASK; 2928 + goto out; 2929 + } 2930 + 2931 + /* Reference Tag checking */ 2932 + ref_tag = be32_to_cpu(src->ref_tag); 2933 + if (chk_ref && (ref_tag != start_ref_tag)) { 2934 + err_type = BGS_REFTAG_ERR_MASK; 2935 + goto out; 2936 + } 2937 + start_ref_tag++; 2938 + 2939 + /* Guard Tag checking */ 2940 + if (chk_guard) { 2941 + guard_tag = src->guard_tag; 2942 + if (guard_type == SHOST_DIX_GUARD_IP) 2943 + sum = lpfc_bg_csum(data_src, 2944 + blksize); 2945 + else 2946 + sum = lpfc_bg_crc(data_src, 2947 + blksize); 2948 + if ((guard_tag != sum)) { 2949 + err_type = BGS_GUARD_ERR_MASK; 2950 + goto out; 2951 + } 2952 + } 2953 + skipit: 2954 + len -= sizeof(struct scsi_dif_tuple); 2955 + if (len < 0) 2956 + len = 0; 2957 + src++; 2958 + 2959 + data_src += blksize; 2960 + data_len -= blksize; 2961 + 2962 + /* 2963 + * Are we at the end of the Data segment? 2964 + * The data segment is only used for Guard 2965 + * tag checking. 2966 + */ 2967 + if (chk_guard && (data_len == 0)) { 2968 + chk_guard = 0; 2969 + sgde = sg_next(sgde); 2970 + if (!sgde) 2971 + goto out; 2972 + 2973 + data_src = (uint8_t *)sg_virt(sgde); 2974 + data_len = sgde->length; 2975 + if ((data_len & (blksize - 1)) == 0) 2976 + chk_guard = 1; 2977 + } 2978 + } 2979 + 2980 + /* Goto the next Protection data segment */ 2981 + sgpe = sg_next(sgpe); 2982 + if (sgpe) { 2983 + src = (struct scsi_dif_tuple *)sg_virt(sgpe); 2984 + len = sgpe->length; 2985 + } else { 2986 + src = NULL; 2987 + } 2988 + protsegcnt--; 2989 + } 2990 + } 2991 + out: 2992 + if (err_type == BGS_GUARD_ERR_MASK) { 2993 + scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 2994 + 0x10, 0x1); 2995 + cmd->result = DRIVER_SENSE << 24 2996 + | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); 2997 + phba->bg_guard_err_cnt++; 2998 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2999 + "9069 BLKGRD: LBA %lx grd_tag error %x != %x\n", 3000 + (unsigned long)scsi_get_lba(cmd), 3001 + sum, guard_tag); 3002 + 3003 + } else if (err_type == BGS_REFTAG_ERR_MASK) { 3004 + scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 3005 + 0x10, 0x3); 3006 + cmd->result = DRIVER_SENSE << 24 3007 + | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); 3008 + 3009 + phba->bg_reftag_err_cnt++; 3010 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 3011 + "9066 BLKGRD: LBA %lx ref_tag error %x != %x\n", 3012 + (unsigned long)scsi_get_lba(cmd), 3013 + ref_tag, start_ref_tag); 3014 + 3015 + } else if (err_type == BGS_APPTAG_ERR_MASK) { 3016 + scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, 3017 + 0x10, 0x2); 3018 + cmd->result = DRIVER_SENSE << 24 3019 + | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); 3020 + 3021 + phba->bg_apptag_err_cnt++; 3022 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 3023 + "9041 BLKGRD: LBA %lx app_tag error %x != %x\n", 3024 + (unsigned long)scsi_get_lba(cmd), 3025 + app_tag, start_app_tag); 3026 + } 3027 + } 3028 + 3029 + 3030 + /* 2825 3031 * This function checks for BlockGuard errors detected by 2826 3032 * the HBA. In case of errors, the ASC/ASCQ fields in the 2827 3033 * sense buffer will be set accordingly, paired with ··· 3051 2841 uint32_t bghm = bgf->bghm; 3052 2842 uint32_t bgstat = bgf->bgstat; 3053 2843 uint64_t failing_sector = 0; 3054 - 3055 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9069 BLKGRD: BG ERROR in cmd" 3056 - " 0x%x lba 0x%llx blk cnt 0x%x " 3057 - "bgstat=0x%x bghm=0x%x\n", 3058 - cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd), 3059 - blk_rq_sectors(cmd->request), bgstat, bghm); 3060 2844 3061 2845 spin_lock(&_dump_buf_lock); 3062 2846 if (!_dump_buf_done) { ··· 3074 2870 3075 2871 if (lpfc_bgs_get_invalid_prof(bgstat)) { 3076 2872 cmd->result = ScsiResult(DID_ERROR, 0); 3077 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9072 BLKGRD: Invalid" 3078 - " BlockGuard profile. bgstat:0x%x\n", 3079 - bgstat); 2873 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2874 + "9072 BLKGRD: Invalid BG Profile in cmd" 2875 + " 0x%x lba 0x%llx blk cnt 0x%x " 2876 + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], 2877 + (unsigned long long)scsi_get_lba(cmd), 2878 + blk_rq_sectors(cmd->request), bgstat, bghm); 3080 2879 ret = (-1); 3081 2880 goto out; 3082 2881 } 3083 2882 3084 2883 if (lpfc_bgs_get_uninit_dif_block(bgstat)) { 3085 2884 cmd->result = ScsiResult(DID_ERROR, 0); 3086 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9073 BLKGRD: " 3087 - "Invalid BlockGuard DIF Block. bgstat:0x%x\n", 3088 - bgstat); 2885 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2886 + "9073 BLKGRD: Invalid BG PDIF Block in cmd" 2887 + " 0x%x lba 0x%llx blk cnt 0x%x " 2888 + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], 2889 + (unsigned long long)scsi_get_lba(cmd), 2890 + blk_rq_sectors(cmd->request), bgstat, bghm); 3089 2891 ret = (-1); 3090 2892 goto out; 3091 2893 } ··· 3104 2894 cmd->result = DRIVER_SENSE << 24 3105 2895 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); 3106 2896 phba->bg_guard_err_cnt++; 3107 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, 3108 - "9055 BLKGRD: guard_tag error\n"); 2897 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2898 + "9055 BLKGRD: Guard Tag error in cmd" 2899 + " 0x%x lba 0x%llx blk cnt 0x%x " 2900 + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], 2901 + (unsigned long long)scsi_get_lba(cmd), 2902 + blk_rq_sectors(cmd->request), bgstat, bghm); 3109 2903 } 3110 2904 3111 2905 if (lpfc_bgs_get_reftag_err(bgstat)) { ··· 3121 2907 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); 3122 2908 3123 2909 phba->bg_reftag_err_cnt++; 3124 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, 3125 - "9056 BLKGRD: ref_tag error\n"); 2910 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2911 + "9056 BLKGRD: Ref Tag error in cmd" 2912 + " 0x%x lba 0x%llx blk cnt 0x%x " 2913 + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], 2914 + (unsigned long long)scsi_get_lba(cmd), 2915 + blk_rq_sectors(cmd->request), bgstat, bghm); 3126 2916 } 3127 2917 3128 2918 if (lpfc_bgs_get_apptag_err(bgstat)) { ··· 3138 2920 | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); 3139 2921 3140 2922 phba->bg_apptag_err_cnt++; 3141 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, 3142 - "9061 BLKGRD: app_tag error\n"); 2923 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2924 + "9061 BLKGRD: App Tag error in cmd" 2925 + " 0x%x lba 0x%llx blk cnt 0x%x " 2926 + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], 2927 + (unsigned long long)scsi_get_lba(cmd), 2928 + blk_rq_sectors(cmd->request), bgstat, bghm); 3143 2929 } 3144 2930 3145 2931 if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { ··· 3182 2960 3183 2961 if (!ret) { 3184 2962 /* No error was reported - problem in FW? */ 3185 - cmd->result = ScsiResult(DID_ERROR, 0); 3186 - lpfc_printf_log(phba, KERN_ERR, LOG_BG, 3187 - "9057 BLKGRD: Unknown error reported!\n"); 3188 - } 2963 + lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_BG, 2964 + "9057 BLKGRD: Unknown error in cmd" 2965 + " 0x%x lba 0x%llx blk cnt 0x%x " 2966 + "bgstat=x%x bghm=x%x\n", cmd->cmnd[0], 2967 + (unsigned long long)scsi_get_lba(cmd), 2968 + blk_rq_sectors(cmd->request), bgstat, bghm); 3189 2969 2970 + /* Calcuate what type of error it was */ 2971 + lpfc_calc_bg_err(phba, lpfc_cmd); 2972 + } 3190 2973 out: 3191 2974 return ret; 3192 2975 } ··· 4584 4357 4585 4358 if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { 4586 4359 if (vport->phba->cfg_enable_bg) { 4587 - lpfc_printf_vlog(vport, KERN_INFO, LOG_BG, 4360 + lpfc_printf_vlog(vport, 4361 + KERN_INFO, LOG_SCSI_CMD, 4588 4362 "9033 BLKGRD: rcvd %s cmd:x%x " 4589 4363 "sector x%llx cnt %u pt %x\n", 4590 4364 dif_op_str[scsi_get_prot_op(cmnd)], ··· 4597 4369 err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); 4598 4370 } else { 4599 4371 if (vport->phba->cfg_enable_bg) { 4600 - lpfc_printf_vlog(vport, KERN_INFO, LOG_BG, 4372 + lpfc_printf_vlog(vport, 4373 + KERN_INFO, LOG_SCSI_CMD, 4601 4374 "9038 BLKGRD: rcvd PROT_NORMAL cmd: " 4602 4375 "x%x sector x%llx cnt %u pt %x\n", 4603 4376 cmnd->cmnd[0],