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