diff options
author | James Smart <James.Smart@Emulex.Com> | 2008-12-04 22:40:02 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-12-29 12:24:28 -0500 |
commit | e2a0a9d69ce224c6f5b72515d81150e6bf4a905a (patch) | |
tree | fdd6d82431841c31c80cbabc24927fbb94c59cd6 /drivers/scsi/lpfc/lpfc_scsi.c | |
parent | 81301a9b05c3690bf32bf4ef37d941f0f870a7ba (diff) |
[SCSI] lpfc 8.3.0 : Add BlockGuard support (T10-DIF) code
Add SCSI data path, error handling, and debugfs code to complete
BlockGuard support.
Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_scsi.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 874 |
1 files changed, 858 insertions, 16 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 5f697ace9706..83a8e7eed628 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -18,13 +18,14 @@ | |||
18 | * more details, a copy of which can be found in the file COPYING * | 18 | * more details, a copy of which can be found in the file COPYING * |
19 | * included with this package. * | 19 | * included with this package. * |
20 | *******************************************************************/ | 20 | *******************************************************************/ |
21 | |||
22 | #include <linux/pci.h> | 21 | #include <linux/pci.h> |
23 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
24 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <asm/unaligned.h> | ||
25 | 25 | ||
26 | #include <scsi/scsi.h> | 26 | #include <scsi/scsi.h> |
27 | #include <scsi/scsi_device.h> | 27 | #include <scsi/scsi_device.h> |
28 | #include <scsi/scsi_eh.h> | ||
28 | #include <scsi/scsi_host.h> | 29 | #include <scsi/scsi_host.h> |
29 | #include <scsi/scsi_tcq.h> | 30 | #include <scsi/scsi_tcq.h> |
30 | #include <scsi/scsi_transport_fc.h> | 31 | #include <scsi/scsi_transport_fc.h> |
@@ -43,6 +44,73 @@ | |||
43 | #define LPFC_RESET_WAIT 2 | 44 | #define LPFC_RESET_WAIT 2 |
44 | #define LPFC_ABORT_WAIT 2 | 45 | #define LPFC_ABORT_WAIT 2 |
45 | 46 | ||
47 | int _dump_buf_done; | ||
48 | |||
49 | static char *dif_op_str[] = { | ||
50 | "SCSI_PROT_NORMAL", | ||
51 | "SCSI_PROT_READ_INSERT", | ||
52 | "SCSI_PROT_WRITE_STRIP", | ||
53 | "SCSI_PROT_READ_STRIP", | ||
54 | "SCSI_PROT_WRITE_INSERT", | ||
55 | "SCSI_PROT_READ_PASS", | ||
56 | "SCSI_PROT_WRITE_PASS", | ||
57 | "SCSI_PROT_READ_CONVERT", | ||
58 | "SCSI_PROT_WRITE_CONVERT" | ||
59 | }; | ||
60 | |||
61 | static void | ||
62 | lpfc_debug_save_data(struct scsi_cmnd *cmnd) | ||
63 | { | ||
64 | void *src, *dst; | ||
65 | struct scatterlist *sgde = scsi_sglist(cmnd); | ||
66 | |||
67 | if (!_dump_buf_data) { | ||
68 | printk(KERN_ERR "BLKGRD ERROR %s _dump_buf_data is NULL\n", | ||
69 | __func__); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | |||
74 | if (!sgde) { | ||
75 | printk(KERN_ERR "BLKGRD ERROR: data scatterlist is null\n"); | ||
76 | return; | ||
77 | } | ||
78 | |||
79 | dst = (void *) _dump_buf_data; | ||
80 | while (sgde) { | ||
81 | src = sg_virt(sgde); | ||
82 | memcpy(dst, src, sgde->length); | ||
83 | dst += sgde->length; | ||
84 | sgde = sg_next(sgde); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | lpfc_debug_save_dif(struct scsi_cmnd *cmnd) | ||
90 | { | ||
91 | void *src, *dst; | ||
92 | struct scatterlist *sgde = scsi_prot_sglist(cmnd); | ||
93 | |||
94 | if (!_dump_buf_dif) { | ||
95 | printk(KERN_ERR "BLKGRD ERROR %s _dump_buf_data is NULL\n", | ||
96 | __func__); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | if (!sgde) { | ||
101 | printk(KERN_ERR "BLKGRD ERROR: prot scatterlist is null\n"); | ||
102 | return; | ||
103 | } | ||
104 | |||
105 | dst = _dump_buf_dif; | ||
106 | while (sgde) { | ||
107 | src = sg_virt(sgde); | ||
108 | memcpy(dst, src, sgde->length); | ||
109 | dst += sgde->length; | ||
110 | sgde = sg_next(sgde); | ||
111 | } | ||
112 | } | ||
113 | |||
46 | /** | 114 | /** |
47 | * lpfc_update_stats: Update statistical data for the command completion. | 115 | * lpfc_update_stats: Update statistical data for the command completion. |
48 | * @phba: Pointer to HBA object. | 116 | * @phba: Pointer to HBA object. |
@@ -463,7 +531,8 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport) | |||
463 | */ | 531 | */ |
464 | iocb = &psb->cur_iocbq.iocb; | 532 | iocb = &psb->cur_iocbq.iocb; |
465 | iocb->un.fcpi64.bdl.ulpIoTag32 = 0; | 533 | iocb->un.fcpi64.bdl.ulpIoTag32 = 0; |
466 | if (phba->sli_rev == 3) { | 534 | if ((phba->sli_rev == 3) && |
535 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) { | ||
467 | /* fill in immediate fcp command BDE */ | 536 | /* fill in immediate fcp command BDE */ |
468 | iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_IMMED; | 537 | iocb->un.fcpi64.bdl.bdeFlags = BUFF_TYPE_BDE_IMMED; |
469 | iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd); | 538 | iocb->un.fcpi64.bdl.bdeSize = sizeof(struct fcp_cmnd); |
@@ -516,6 +585,7 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba) | |||
516 | if (lpfc_cmd) { | 585 | if (lpfc_cmd) { |
517 | lpfc_cmd->seg_cnt = 0; | 586 | lpfc_cmd->seg_cnt = 0; |
518 | lpfc_cmd->nonsg_phys = 0; | 587 | lpfc_cmd->nonsg_phys = 0; |
588 | lpfc_cmd->prot_seg_cnt = 0; | ||
519 | } | 589 | } |
520 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); | 590 | spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag); |
521 | return lpfc_cmd; | 591 | return lpfc_cmd; |
@@ -590,7 +660,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
590 | lpfc_cmd->seg_cnt = nseg; | 660 | lpfc_cmd->seg_cnt = nseg; |
591 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { | 661 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { |
592 | printk(KERN_ERR "%s: Too many sg segments from " | 662 | printk(KERN_ERR "%s: Too many sg segments from " |
593 | "dma_map_sg. Config %d, seg_cnt %d", | 663 | "dma_map_sg. Config %d, seg_cnt %d\n", |
594 | __func__, phba->cfg_sg_seg_cnt, | 664 | __func__, phba->cfg_sg_seg_cnt, |
595 | lpfc_cmd->seg_cnt); | 665 | lpfc_cmd->seg_cnt); |
596 | scsi_dma_unmap(scsi_cmnd); | 666 | scsi_dma_unmap(scsi_cmnd); |
@@ -609,6 +679,7 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
609 | scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) { | 679 | scsi_for_each_sg(scsi_cmnd, sgel, nseg, num_bde) { |
610 | physaddr = sg_dma_address(sgel); | 680 | physaddr = sg_dma_address(sgel); |
611 | if (phba->sli_rev == 3 && | 681 | if (phba->sli_rev == 3 && |
682 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && | ||
612 | nseg <= LPFC_EXT_DATA_BDE_COUNT) { | 683 | nseg <= LPFC_EXT_DATA_BDE_COUNT) { |
613 | data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | 684 | data_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; |
614 | data_bde->tus.f.bdeSize = sg_dma_len(sgel); | 685 | data_bde->tus.f.bdeSize = sg_dma_len(sgel); |
@@ -634,7 +705,8 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
634 | * explicitly reinitialized and for SLI-3 the extended bde count is | 705 | * explicitly reinitialized and for SLI-3 the extended bde count is |
635 | * explicitly reinitialized since all iocb memory resources are reused. | 706 | * explicitly reinitialized since all iocb memory resources are reused. |
636 | */ | 707 | */ |
637 | if (phba->sli_rev == 3) { | 708 | if (phba->sli_rev == 3 && |
709 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) { | ||
638 | if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { | 710 | if (num_bde > LPFC_EXT_DATA_BDE_COUNT) { |
639 | /* | 711 | /* |
640 | * The extended IOCB format can only fit 3 BDE or a BPL. | 712 | * The extended IOCB format can only fit 3 BDE or a BPL. |
@@ -661,9 +733,685 @@ lpfc_scsi_prep_dma_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
661 | ((num_bde + 2) * sizeof(struct ulp_bde64)); | 733 | ((num_bde + 2) * sizeof(struct ulp_bde64)); |
662 | } | 734 | } |
663 | fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); | 735 | fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd)); |
736 | |||
737 | /* | ||
738 | * Due to difference in data length between DIF/non-DIF paths, | ||
739 | * we need to set word 4 of IOCB here | ||
740 | */ | ||
741 | iocb_cmd->un.fcpi.fcpi_parm = le32_to_cpu(scsi_bufflen(scsi_cmnd)); | ||
664 | return 0; | 742 | return 0; |
665 | } | 743 | } |
666 | 744 | ||
745 | /* | ||
746 | * Given a scsi cmnd, determine the BlockGuard profile to be used | ||
747 | * with the cmd | ||
748 | */ | ||
749 | static int | ||
750 | lpfc_sc_to_sli_prof(struct scsi_cmnd *sc) | ||
751 | { | ||
752 | uint8_t guard_type = scsi_host_get_guard(sc->device->host); | ||
753 | uint8_t ret_prof = LPFC_PROF_INVALID; | ||
754 | |||
755 | if (guard_type == SHOST_DIX_GUARD_IP) { | ||
756 | switch (scsi_get_prot_op(sc)) { | ||
757 | case SCSI_PROT_READ_INSERT: | ||
758 | case SCSI_PROT_WRITE_STRIP: | ||
759 | ret_prof = LPFC_PROF_AST2; | ||
760 | break; | ||
761 | |||
762 | case SCSI_PROT_READ_STRIP: | ||
763 | case SCSI_PROT_WRITE_INSERT: | ||
764 | ret_prof = LPFC_PROF_A1; | ||
765 | break; | ||
766 | |||
767 | case SCSI_PROT_READ_CONVERT: | ||
768 | case SCSI_PROT_WRITE_CONVERT: | ||
769 | ret_prof = LPFC_PROF_AST1; | ||
770 | break; | ||
771 | |||
772 | case SCSI_PROT_READ_PASS: | ||
773 | case SCSI_PROT_WRITE_PASS: | ||
774 | case SCSI_PROT_NORMAL: | ||
775 | default: | ||
776 | printk(KERN_ERR "Bad op/guard:%d/%d combination\n", | ||
777 | scsi_get_prot_op(sc), guard_type); | ||
778 | break; | ||
779 | |||
780 | } | ||
781 | } else if (guard_type == SHOST_DIX_GUARD_CRC) { | ||
782 | switch (scsi_get_prot_op(sc)) { | ||
783 | case SCSI_PROT_READ_STRIP: | ||
784 | case SCSI_PROT_WRITE_INSERT: | ||
785 | ret_prof = LPFC_PROF_A1; | ||
786 | break; | ||
787 | |||
788 | case SCSI_PROT_READ_PASS: | ||
789 | case SCSI_PROT_WRITE_PASS: | ||
790 | ret_prof = LPFC_PROF_C1; | ||
791 | break; | ||
792 | |||
793 | case SCSI_PROT_READ_CONVERT: | ||
794 | case SCSI_PROT_WRITE_CONVERT: | ||
795 | case SCSI_PROT_READ_INSERT: | ||
796 | case SCSI_PROT_WRITE_STRIP: | ||
797 | case SCSI_PROT_NORMAL: | ||
798 | default: | ||
799 | printk(KERN_ERR "Bad op/guard:%d/%d combination\n", | ||
800 | scsi_get_prot_op(sc), guard_type); | ||
801 | break; | ||
802 | } | ||
803 | } else { | ||
804 | /* unsupported format */ | ||
805 | BUG(); | ||
806 | } | ||
807 | |||
808 | return ret_prof; | ||
809 | } | ||
810 | |||
811 | struct scsi_dif_tuple { | ||
812 | __be16 guard_tag; /* Checksum */ | ||
813 | __be16 app_tag; /* Opaque storage */ | ||
814 | __be32 ref_tag; /* Target LBA or indirect LBA */ | ||
815 | }; | ||
816 | |||
817 | static inline unsigned | ||
818 | lpfc_cmd_blksize(struct scsi_cmnd *sc) | ||
819 | { | ||
820 | return sc->device->sector_size; | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * lpfc_get_cmd_dif_parms - Extract DIF parameters from SCSI command | ||
825 | * @sc: in: SCSI command | ||
826 | * @apptagmask out: app tag mask | ||
827 | * @apptagval out: app tag value | ||
828 | * @reftag out: ref tag (reference tag) | ||
829 | * | ||
830 | * Description: | ||
831 | * Extract DIF paramters from the command if possible. Otherwise, | ||
832 | * use default paratmers. | ||
833 | * | ||
834 | **/ | ||
835 | static inline void | ||
836 | lpfc_get_cmd_dif_parms(struct scsi_cmnd *sc, uint16_t *apptagmask, | ||
837 | uint16_t *apptagval, uint32_t *reftag) | ||
838 | { | ||
839 | struct scsi_dif_tuple *spt; | ||
840 | unsigned char op = scsi_get_prot_op(sc); | ||
841 | unsigned int protcnt = scsi_prot_sg_count(sc); | ||
842 | static int cnt; | ||
843 | |||
844 | if (protcnt && (op == SCSI_PROT_WRITE_STRIP || | ||
845 | op == SCSI_PROT_WRITE_PASS || | ||
846 | op == SCSI_PROT_WRITE_CONVERT)) { | ||
847 | |||
848 | cnt++; | ||
849 | spt = page_address(sg_page(scsi_prot_sglist(sc))) + | ||
850 | scsi_prot_sglist(sc)[0].offset; | ||
851 | *apptagmask = 0; | ||
852 | *apptagval = 0; | ||
853 | *reftag = cpu_to_be32(spt->ref_tag); | ||
854 | |||
855 | } else { | ||
856 | /* SBC defines ref tag to be lower 32bits of LBA */ | ||
857 | *reftag = (uint32_t) (0xffffffff & scsi_get_lba(sc)); | ||
858 | *apptagmask = 0; | ||
859 | *apptagval = 0; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | /* | ||
864 | * This function sets up buffer list for protection groups of | ||
865 | * type LPFC_PG_TYPE_NO_DIF | ||
866 | * | ||
867 | * This is usually used when the HBA is instructed to generate | ||
868 | * DIFs and insert them into data stream (or strip DIF from | ||
869 | * incoming data stream) | ||
870 | * | ||
871 | * The buffer list consists of just one protection group described | ||
872 | * below: | ||
873 | * +-------------------------+ | ||
874 | * start of prot group --> | PDE_1 | | ||
875 | * +-------------------------+ | ||
876 | * | Data BDE | | ||
877 | * +-------------------------+ | ||
878 | * |more Data BDE's ... (opt)| | ||
879 | * +-------------------------+ | ||
880 | * | ||
881 | * @sc: pointer to scsi command we're working on | ||
882 | * @bpl: pointer to buffer list for protection groups | ||
883 | * @datacnt: number of segments of data that have been dma mapped | ||
884 | * | ||
885 | * Note: Data s/g buffers have been dma mapped | ||
886 | */ | ||
887 | static int | ||
888 | lpfc_bg_setup_bpl(struct lpfc_hba *phba, struct scsi_cmnd *sc, | ||
889 | struct ulp_bde64 *bpl, int datasegcnt) | ||
890 | { | ||
891 | struct scatterlist *sgde = NULL; /* s/g data entry */ | ||
892 | struct lpfc_pde *pde1 = NULL; | ||
893 | dma_addr_t physaddr; | ||
894 | int i = 0, num_bde = 0; | ||
895 | int datadir = sc->sc_data_direction; | ||
896 | int prof = LPFC_PROF_INVALID; | ||
897 | unsigned blksize; | ||
898 | uint32_t reftag; | ||
899 | uint16_t apptagmask, apptagval; | ||
900 | |||
901 | pde1 = (struct lpfc_pde *) bpl; | ||
902 | prof = lpfc_sc_to_sli_prof(sc); | ||
903 | |||
904 | if (prof == LPFC_PROF_INVALID) | ||
905 | goto out; | ||
906 | |||
907 | /* extract some info from the scsi command for PDE1*/ | ||
908 | blksize = lpfc_cmd_blksize(sc); | ||
909 | lpfc_get_cmd_dif_parms(sc, &apptagmask, &apptagval, &reftag); | ||
910 | |||
911 | /* setup PDE1 with what we have */ | ||
912 | lpfc_pde_set_bg_parms(pde1, LPFC_PDE1_DESCRIPTOR, prof, blksize, | ||
913 | BG_EC_STOP_ERR); | ||
914 | lpfc_pde_set_dif_parms(pde1, apptagmask, apptagval, reftag); | ||
915 | |||
916 | num_bde++; | ||
917 | bpl++; | ||
918 | |||
919 | /* assumption: caller has already run dma_map_sg on command data */ | ||
920 | scsi_for_each_sg(sc, sgde, datasegcnt, i) { | ||
921 | physaddr = sg_dma_address(sgde); | ||
922 | bpl->addrLow = le32_to_cpu(putPaddrLow(physaddr)); | ||
923 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(physaddr)); | ||
924 | bpl->tus.f.bdeSize = sg_dma_len(sgde); | ||
925 | if (datadir == DMA_TO_DEVICE) | ||
926 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
927 | else | ||
928 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I; | ||
929 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | ||
930 | bpl++; | ||
931 | num_bde++; | ||
932 | } | ||
933 | |||
934 | out: | ||
935 | return num_bde; | ||
936 | } | ||
937 | |||
938 | /* | ||
939 | * This function sets up buffer list for protection groups of | ||
940 | * type LPFC_PG_TYPE_DIF_BUF | ||
941 | * | ||
942 | * This is usually used when DIFs are in their own buffers, | ||
943 | * separate from the data. The HBA can then by instructed | ||
944 | * to place the DIFs in the outgoing stream. For read operations, | ||
945 | * The HBA could extract the DIFs and place it in DIF buffers. | ||
946 | * | ||
947 | * The buffer list for this type consists of one or more of the | ||
948 | * protection groups described below: | ||
949 | * +-------------------------+ | ||
950 | * start of first prot group --> | PDE_1 | | ||
951 | * +-------------------------+ | ||
952 | * | PDE_3 (Prot BDE) | | ||
953 | * +-------------------------+ | ||
954 | * | Data BDE | | ||
955 | * +-------------------------+ | ||
956 | * |more Data BDE's ... (opt)| | ||
957 | * +-------------------------+ | ||
958 | * start of new prot group --> | PDE_1 | | ||
959 | * +-------------------------+ | ||
960 | * | ... | | ||
961 | * +-------------------------+ | ||
962 | * | ||
963 | * @sc: pointer to scsi command we're working on | ||
964 | * @bpl: pointer to buffer list for protection groups | ||
965 | * @datacnt: number of segments of data that have been dma mapped | ||
966 | * @protcnt: number of segment of protection data that have been dma mapped | ||
967 | * | ||
968 | * Note: It is assumed that both data and protection s/g buffers have been | ||
969 | * mapped for DMA | ||
970 | */ | ||
971 | static int | ||
972 | lpfc_bg_setup_bpl_prot(struct lpfc_hba *phba, struct scsi_cmnd *sc, | ||
973 | struct ulp_bde64 *bpl, int datacnt, int protcnt) | ||
974 | { | ||
975 | struct scatterlist *sgde = NULL; /* s/g data entry */ | ||
976 | struct scatterlist *sgpe = NULL; /* s/g prot entry */ | ||
977 | struct lpfc_pde *pde1 = NULL; | ||
978 | struct ulp_bde64 *prot_bde = NULL; | ||
979 | dma_addr_t dataphysaddr, protphysaddr; | ||
980 | unsigned short curr_data = 0, curr_prot = 0; | ||
981 | unsigned int split_offset, protgroup_len; | ||
982 | unsigned int protgrp_blks, protgrp_bytes; | ||
983 | unsigned int remainder, subtotal; | ||
984 | int prof = LPFC_PROF_INVALID; | ||
985 | int datadir = sc->sc_data_direction; | ||
986 | unsigned char pgdone = 0, alldone = 0; | ||
987 | unsigned blksize; | ||
988 | uint32_t reftag; | ||
989 | uint16_t apptagmask, apptagval; | ||
990 | int num_bde = 0; | ||
991 | |||
992 | sgpe = scsi_prot_sglist(sc); | ||
993 | sgde = scsi_sglist(sc); | ||
994 | |||
995 | if (!sgpe || !sgde) { | ||
996 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
997 | "9020 Invalid s/g entry: data=0x%p prot=0x%p\n", | ||
998 | sgpe, sgde); | ||
999 | return 0; | ||
1000 | } | ||
1001 | |||
1002 | prof = lpfc_sc_to_sli_prof(sc); | ||
1003 | if (prof == LPFC_PROF_INVALID) | ||
1004 | goto out; | ||
1005 | |||
1006 | /* extract some info from the scsi command for PDE1*/ | ||
1007 | blksize = lpfc_cmd_blksize(sc); | ||
1008 | lpfc_get_cmd_dif_parms(sc, &apptagmask, &apptagval, &reftag); | ||
1009 | |||
1010 | split_offset = 0; | ||
1011 | do { | ||
1012 | /* setup the first PDE_1 */ | ||
1013 | pde1 = (struct lpfc_pde *) bpl; | ||
1014 | |||
1015 | lpfc_pde_set_bg_parms(pde1, LPFC_PDE1_DESCRIPTOR, prof, blksize, | ||
1016 | BG_EC_STOP_ERR); | ||
1017 | lpfc_pde_set_dif_parms(pde1, apptagmask, apptagval, reftag); | ||
1018 | |||
1019 | num_bde++; | ||
1020 | bpl++; | ||
1021 | |||
1022 | /* setup the first BDE that points to protection buffer */ | ||
1023 | prot_bde = (struct ulp_bde64 *) bpl; | ||
1024 | protphysaddr = sg_dma_address(sgpe); | ||
1025 | prot_bde->addrLow = le32_to_cpu(putPaddrLow(protphysaddr)); | ||
1026 | prot_bde->addrHigh = le32_to_cpu(putPaddrHigh(protphysaddr)); | ||
1027 | protgroup_len = sg_dma_len(sgpe); | ||
1028 | |||
1029 | |||
1030 | /* must be integer multiple of the DIF block length */ | ||
1031 | BUG_ON(protgroup_len % 8); | ||
1032 | |||
1033 | protgrp_blks = protgroup_len / 8; | ||
1034 | protgrp_bytes = protgrp_blks * blksize; | ||
1035 | |||
1036 | prot_bde->tus.f.bdeSize = protgroup_len; | ||
1037 | if (datadir == DMA_TO_DEVICE) | ||
1038 | prot_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
1039 | else | ||
1040 | prot_bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64I; | ||
1041 | prot_bde->tus.w = le32_to_cpu(bpl->tus.w); | ||
1042 | |||
1043 | curr_prot++; | ||
1044 | num_bde++; | ||
1045 | |||
1046 | /* setup BDE's for data blocks associated with DIF data */ | ||
1047 | pgdone = 0; | ||
1048 | subtotal = 0; /* total bytes processed for current prot grp */ | ||
1049 | while (!pgdone) { | ||
1050 | if (!sgde) { | ||
1051 | printk(KERN_ERR "%s Invalid data segment\n", | ||
1052 | __func__); | ||
1053 | return 0; | ||
1054 | } | ||
1055 | bpl++; | ||
1056 | dataphysaddr = sg_dma_address(sgde) + split_offset; | ||
1057 | bpl->addrLow = le32_to_cpu(putPaddrLow(dataphysaddr)); | ||
1058 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(dataphysaddr)); | ||
1059 | |||
1060 | remainder = sg_dma_len(sgde) - split_offset; | ||
1061 | |||
1062 | if ((subtotal + remainder) <= protgrp_bytes) { | ||
1063 | /* we can use this whole buffer */ | ||
1064 | bpl->tus.f.bdeSize = remainder; | ||
1065 | split_offset = 0; | ||
1066 | |||
1067 | if ((subtotal + remainder) == protgrp_bytes) | ||
1068 | pgdone = 1; | ||
1069 | } else { | ||
1070 | /* must split this buffer with next prot grp */ | ||
1071 | bpl->tus.f.bdeSize = protgrp_bytes - subtotal; | ||
1072 | split_offset += bpl->tus.f.bdeSize; | ||
1073 | } | ||
1074 | |||
1075 | subtotal += bpl->tus.f.bdeSize; | ||
1076 | |||
1077 | if (datadir == DMA_TO_DEVICE) | ||
1078 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64; | ||
1079 | else | ||
1080 | bpl->tus.f.bdeFlags = BUFF_TYPE_BDE_64I; | ||
1081 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | ||
1082 | |||
1083 | num_bde++; | ||
1084 | curr_data++; | ||
1085 | |||
1086 | if (split_offset) | ||
1087 | break; | ||
1088 | |||
1089 | /* Move to the next s/g segment if possible */ | ||
1090 | sgde = sg_next(sgde); | ||
1091 | } | ||
1092 | |||
1093 | /* are we done ? */ | ||
1094 | if (curr_prot == protcnt) { | ||
1095 | alldone = 1; | ||
1096 | } else if (curr_prot < protcnt) { | ||
1097 | /* advance to next prot buffer */ | ||
1098 | sgpe = sg_next(sgpe); | ||
1099 | bpl++; | ||
1100 | |||
1101 | /* update the reference tag */ | ||
1102 | reftag += protgrp_blks; | ||
1103 | } else { | ||
1104 | /* if we're here, we have a bug */ | ||
1105 | printk(KERN_ERR "BLKGRD: bug in %s\n", __func__); | ||
1106 | } | ||
1107 | |||
1108 | } while (!alldone); | ||
1109 | |||
1110 | out: | ||
1111 | |||
1112 | |||
1113 | return num_bde; | ||
1114 | } | ||
1115 | /* | ||
1116 | * Given a SCSI command that supports DIF, determine composition of protection | ||
1117 | * groups involved in setting up buffer lists | ||
1118 | * | ||
1119 | * Returns: | ||
1120 | * for DIF (for both read and write) | ||
1121 | * */ | ||
1122 | static int | ||
1123 | lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc) | ||
1124 | { | ||
1125 | int ret = LPFC_PG_TYPE_INVALID; | ||
1126 | unsigned char op = scsi_get_prot_op(sc); | ||
1127 | |||
1128 | switch (op) { | ||
1129 | case SCSI_PROT_READ_STRIP: | ||
1130 | case SCSI_PROT_WRITE_INSERT: | ||
1131 | ret = LPFC_PG_TYPE_NO_DIF; | ||
1132 | break; | ||
1133 | case SCSI_PROT_READ_INSERT: | ||
1134 | case SCSI_PROT_WRITE_STRIP: | ||
1135 | case SCSI_PROT_READ_PASS: | ||
1136 | case SCSI_PROT_WRITE_PASS: | ||
1137 | case SCSI_PROT_WRITE_CONVERT: | ||
1138 | case SCSI_PROT_READ_CONVERT: | ||
1139 | ret = LPFC_PG_TYPE_DIF_BUF; | ||
1140 | break; | ||
1141 | default: | ||
1142 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
1143 | "9021 Unsupported protection op:%d\n", op); | ||
1144 | break; | ||
1145 | } | ||
1146 | |||
1147 | return ret; | ||
1148 | } | ||
1149 | |||
1150 | /* | ||
1151 | * This is the protection/DIF aware version of | ||
1152 | * lpfc_scsi_prep_dma_buf(). It may be a good idea to combine the | ||
1153 | * two functions eventually, but for now, it's here | ||
1154 | */ | ||
1155 | static int | ||
1156 | lpfc_bg_scsi_prep_dma_buf(struct lpfc_hba *phba, | ||
1157 | struct lpfc_scsi_buf *lpfc_cmd) | ||
1158 | { | ||
1159 | struct scsi_cmnd *scsi_cmnd = lpfc_cmd->pCmd; | ||
1160 | struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd; | ||
1161 | struct ulp_bde64 *bpl = lpfc_cmd->fcp_bpl; | ||
1162 | IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb; | ||
1163 | uint32_t num_bde = 0; | ||
1164 | int datasegcnt, protsegcnt, datadir = scsi_cmnd->sc_data_direction; | ||
1165 | int prot_group_type = 0; | ||
1166 | int diflen, fcpdl; | ||
1167 | unsigned blksize; | ||
1168 | |||
1169 | /* | ||
1170 | * Start the lpfc command prep by bumping the bpl beyond fcp_cmnd | ||
1171 | * fcp_rsp regions to the first data bde entry | ||
1172 | */ | ||
1173 | bpl += 2; | ||
1174 | if (scsi_sg_count(scsi_cmnd)) { | ||
1175 | /* | ||
1176 | * The driver stores the segment count returned from pci_map_sg | ||
1177 | * because this a count of dma-mappings used to map the use_sg | ||
1178 | * pages. They are not guaranteed to be the same for those | ||
1179 | * architectures that implement an IOMMU. | ||
1180 | */ | ||
1181 | datasegcnt = dma_map_sg(&phba->pcidev->dev, | ||
1182 | scsi_sglist(scsi_cmnd), | ||
1183 | scsi_sg_count(scsi_cmnd), datadir); | ||
1184 | if (unlikely(!datasegcnt)) | ||
1185 | return 1; | ||
1186 | |||
1187 | lpfc_cmd->seg_cnt = datasegcnt; | ||
1188 | if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) { | ||
1189 | printk(KERN_ERR "%s: Too many sg segments from " | ||
1190 | "dma_map_sg. Config %d, seg_cnt %d\n", | ||
1191 | __func__, phba->cfg_sg_seg_cnt, | ||
1192 | lpfc_cmd->seg_cnt); | ||
1193 | scsi_dma_unmap(scsi_cmnd); | ||
1194 | return 1; | ||
1195 | } | ||
1196 | |||
1197 | prot_group_type = lpfc_prot_group_type(phba, scsi_cmnd); | ||
1198 | |||
1199 | switch (prot_group_type) { | ||
1200 | case LPFC_PG_TYPE_NO_DIF: | ||
1201 | num_bde = lpfc_bg_setup_bpl(phba, scsi_cmnd, bpl, | ||
1202 | datasegcnt); | ||
1203 | /* we shoud have 2 or more entries in buffer list */ | ||
1204 | if (num_bde < 2) | ||
1205 | goto err; | ||
1206 | break; | ||
1207 | case LPFC_PG_TYPE_DIF_BUF:{ | ||
1208 | /* | ||
1209 | * This type indicates that protection buffers are | ||
1210 | * passed to the driver, so that needs to be prepared | ||
1211 | * for DMA | ||
1212 | */ | ||
1213 | protsegcnt = dma_map_sg(&phba->pcidev->dev, | ||
1214 | scsi_prot_sglist(scsi_cmnd), | ||
1215 | scsi_prot_sg_count(scsi_cmnd), datadir); | ||
1216 | if (unlikely(!protsegcnt)) { | ||
1217 | scsi_dma_unmap(scsi_cmnd); | ||
1218 | return 1; | ||
1219 | } | ||
1220 | |||
1221 | lpfc_cmd->prot_seg_cnt = protsegcnt; | ||
1222 | if (lpfc_cmd->prot_seg_cnt | ||
1223 | > phba->cfg_prot_sg_seg_cnt) { | ||
1224 | printk(KERN_ERR "%s: Too many prot sg segments " | ||
1225 | "from dma_map_sg. Config %d," | ||
1226 | "prot_seg_cnt %d\n", __func__, | ||
1227 | phba->cfg_prot_sg_seg_cnt, | ||
1228 | lpfc_cmd->prot_seg_cnt); | ||
1229 | dma_unmap_sg(&phba->pcidev->dev, | ||
1230 | scsi_prot_sglist(scsi_cmnd), | ||
1231 | scsi_prot_sg_count(scsi_cmnd), | ||
1232 | datadir); | ||
1233 | scsi_dma_unmap(scsi_cmnd); | ||
1234 | return 1; | ||
1235 | } | ||
1236 | |||
1237 | num_bde = lpfc_bg_setup_bpl_prot(phba, scsi_cmnd, bpl, | ||
1238 | datasegcnt, protsegcnt); | ||
1239 | /* we shoud have 3 or more entries in buffer list */ | ||
1240 | if (num_bde < 3) | ||
1241 | goto err; | ||
1242 | break; | ||
1243 | } | ||
1244 | case LPFC_PG_TYPE_INVALID: | ||
1245 | default: | ||
1246 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
1247 | "9022 Unexpected protection group %i\n", | ||
1248 | prot_group_type); | ||
1249 | return 1; | ||
1250 | } | ||
1251 | } | ||
1252 | |||
1253 | /* | ||
1254 | * Finish initializing those IOCB fields that are dependent on the | ||
1255 | * scsi_cmnd request_buffer. Note that the bdeSize is explicitly | ||
1256 | * reinitialized since all iocb memory resources are used many times | ||
1257 | * for transmit, receive, and continuation bpl's. | ||
1258 | */ | ||
1259 | iocb_cmd->un.fcpi64.bdl.bdeSize = (2 * sizeof(struct ulp_bde64)); | ||
1260 | iocb_cmd->un.fcpi64.bdl.bdeSize += (num_bde * sizeof(struct ulp_bde64)); | ||
1261 | iocb_cmd->ulpBdeCount = 1; | ||
1262 | iocb_cmd->ulpLe = 1; | ||
1263 | |||
1264 | fcpdl = scsi_bufflen(scsi_cmnd); | ||
1265 | |||
1266 | if (scsi_get_prot_type(scsi_cmnd) == SCSI_PROT_DIF_TYPE1) { | ||
1267 | /* | ||
1268 | * We are in DIF Type 1 mode | ||
1269 | * Every data block has a 8 byte DIF (trailer) | ||
1270 | * attached to it. Must ajust FCP data length | ||
1271 | */ | ||
1272 | blksize = lpfc_cmd_blksize(scsi_cmnd); | ||
1273 | diflen = (fcpdl / blksize) * 8; | ||
1274 | fcpdl += diflen; | ||
1275 | } | ||
1276 | fcp_cmnd->fcpDl = be32_to_cpu(fcpdl); | ||
1277 | |||
1278 | /* | ||
1279 | * Due to difference in data length between DIF/non-DIF paths, | ||
1280 | * we need to set word 4 of IOCB here | ||
1281 | */ | ||
1282 | iocb_cmd->un.fcpi.fcpi_parm = fcpdl; | ||
1283 | |||
1284 | return 0; | ||
1285 | err: | ||
1286 | lpfc_printf_log(phba, KERN_ERR, LOG_FCP, | ||
1287 | "9023 Could not setup all needed BDE's" | ||
1288 | "prot_group_type=%d, num_bde=%d\n", | ||
1289 | prot_group_type, num_bde); | ||
1290 | return 1; | ||
1291 | } | ||
1292 | |||
1293 | /* | ||
1294 | * This function checks for BlockGuard errors detected by | ||
1295 | * the HBA. In case of errors, the ASC/ASCQ fields in the | ||
1296 | * sense buffer will be set accordingly, paired with | ||
1297 | * ILLEGAL_REQUEST to signal to the kernel that the HBA | ||
1298 | * detected corruption. | ||
1299 | * | ||
1300 | * Returns: | ||
1301 | * 0 - No error found | ||
1302 | * 1 - BlockGuard error found | ||
1303 | * -1 - Internal error (bad profile, ...etc) | ||
1304 | */ | ||
1305 | static int | ||
1306 | lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | ||
1307 | struct lpfc_iocbq *pIocbOut) | ||
1308 | { | ||
1309 | struct scsi_cmnd *cmd = lpfc_cmd->pCmd; | ||
1310 | struct sli3_bg_fields *bgf = &pIocbOut->iocb.unsli3.sli3_bg; | ||
1311 | int ret = 0; | ||
1312 | uint32_t bghm = bgf->bghm; | ||
1313 | uint32_t bgstat = bgf->bgstat; | ||
1314 | uint64_t failing_sector = 0; | ||
1315 | |||
1316 | printk(KERN_ERR "BG ERROR in cmd 0x%x lba 0x%llx blk cnt 0x%lx " | ||
1317 | "bgstat=0x%x bghm=0x%x\n", | ||
1318 | cmd->cmnd[0], (u64)scsi_get_lba(cmd), | ||
1319 | cmd->request->nr_sectors, bgstat, bghm); | ||
1320 | |||
1321 | spin_lock(&_dump_buf_lock); | ||
1322 | if (!_dump_buf_done) { | ||
1323 | printk(KERN_ERR "Saving Data for %u blocks to debugfs\n", | ||
1324 | (cmd->cmnd[7] << 8 | cmd->cmnd[8])); | ||
1325 | lpfc_debug_save_data(cmd); | ||
1326 | |||
1327 | /* If we have a prot sgl, save the DIF buffer */ | ||
1328 | if (lpfc_prot_group_type(phba, cmd) == | ||
1329 | LPFC_PG_TYPE_DIF_BUF) { | ||
1330 | printk(KERN_ERR "Saving DIF for %u blocks to debugfs\n", | ||
1331 | (cmd->cmnd[7] << 8 | cmd->cmnd[8])); | ||
1332 | lpfc_debug_save_dif(cmd); | ||
1333 | } | ||
1334 | |||
1335 | _dump_buf_done = 1; | ||
1336 | } | ||
1337 | spin_unlock(&_dump_buf_lock); | ||
1338 | |||
1339 | if (lpfc_bgs_get_invalid_prof(bgstat)) { | ||
1340 | cmd->result = ScsiResult(DID_ERROR, 0); | ||
1341 | printk(KERN_ERR "Invalid BlockGuard profile. bgstat:0x%x\n", | ||
1342 | bgstat); | ||
1343 | ret = (-1); | ||
1344 | goto out; | ||
1345 | } | ||
1346 | |||
1347 | if (lpfc_bgs_get_uninit_dif_block(bgstat)) { | ||
1348 | cmd->result = ScsiResult(DID_ERROR, 0); | ||
1349 | printk(KERN_ERR "Invalid BlockGuard DIF Block. bgstat:0x%x\n", | ||
1350 | bgstat); | ||
1351 | ret = (-1); | ||
1352 | goto out; | ||
1353 | } | ||
1354 | |||
1355 | if (lpfc_bgs_get_guard_err(bgstat)) { | ||
1356 | ret = 1; | ||
1357 | |||
1358 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1359 | 0x10, 0x1); | ||
1360 | cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 | ||
1361 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | ||
1362 | phba->bg_guard_err_cnt++; | ||
1363 | printk(KERN_ERR "BLKGRD: guard_tag error\n"); | ||
1364 | } | ||
1365 | |||
1366 | if (lpfc_bgs_get_reftag_err(bgstat)) { | ||
1367 | ret = 1; | ||
1368 | |||
1369 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1370 | 0x10, 0x3); | ||
1371 | cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 | ||
1372 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | ||
1373 | |||
1374 | phba->bg_reftag_err_cnt++; | ||
1375 | printk(KERN_ERR "BLKGRD: ref_tag error\n"); | ||
1376 | } | ||
1377 | |||
1378 | if (lpfc_bgs_get_apptag_err(bgstat)) { | ||
1379 | ret = 1; | ||
1380 | |||
1381 | scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST, | ||
1382 | 0x10, 0x2); | ||
1383 | cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24 | ||
1384 | | ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION); | ||
1385 | |||
1386 | phba->bg_apptag_err_cnt++; | ||
1387 | printk(KERN_ERR "BLKGRD: app_tag error\n"); | ||
1388 | } | ||
1389 | |||
1390 | if (lpfc_bgs_get_hi_water_mark_present(bgstat)) { | ||
1391 | /* | ||
1392 | * setup sense data descriptor 0 per SPC-4 as an information | ||
1393 | * field, and put the failing LBA in it | ||
1394 | */ | ||
1395 | cmd->sense_buffer[8] = 0; /* Information */ | ||
1396 | cmd->sense_buffer[9] = 0xa; /* Add. length */ | ||
1397 | do_div(bghm, cmd->device->sector_size); | ||
1398 | |||
1399 | failing_sector = scsi_get_lba(cmd); | ||
1400 | failing_sector += bghm; | ||
1401 | |||
1402 | put_unaligned_be64(failing_sector, &cmd->sense_buffer[10]); | ||
1403 | } | ||
1404 | |||
1405 | if (!ret) { | ||
1406 | /* No error was reported - problem in FW? */ | ||
1407 | cmd->result = ScsiResult(DID_ERROR, 0); | ||
1408 | printk(KERN_ERR "BLKGRD: no errors reported!\n"); | ||
1409 | } | ||
1410 | |||
1411 | out: | ||
1412 | return ret; | ||
1413 | } | ||
1414 | |||
667 | /** | 1415 | /** |
668 | * lpfc_send_scsi_error_event: Posts an event when there is SCSI error. | 1416 | * lpfc_send_scsi_error_event: Posts an event when there is SCSI error. |
669 | * @phba: Pointer to hba context object. | 1417 | * @phba: Pointer to hba context object. |
@@ -775,6 +1523,10 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb) | |||
775 | */ | 1523 | */ |
776 | if (psb->seg_cnt > 0) | 1524 | if (psb->seg_cnt > 0) |
777 | scsi_dma_unmap(psb->pCmd); | 1525 | scsi_dma_unmap(psb->pCmd); |
1526 | if (psb->prot_seg_cnt > 0) | ||
1527 | dma_unmap_sg(&phba->pcidev->dev, scsi_prot_sglist(psb->pCmd), | ||
1528 | scsi_prot_sg_count(psb->pCmd), | ||
1529 | psb->pCmd->sc_data_direction); | ||
778 | } | 1530 | } |
779 | 1531 | ||
780 | /** | 1532 | /** |
@@ -828,7 +1580,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
828 | logit = LOG_FCP; | 1580 | logit = LOG_FCP; |
829 | 1581 | ||
830 | lpfc_printf_vlog(vport, KERN_WARNING, logit, | 1582 | lpfc_printf_vlog(vport, KERN_WARNING, logit, |
831 | "0730 FCP command x%x failed: x%x SNS x%x x%x " | 1583 | "9024 FCP command x%x failed: x%x SNS x%x x%x " |
832 | "Data: x%x x%x x%x x%x x%x\n", | 1584 | "Data: x%x x%x x%x x%x x%x\n", |
833 | cmnd->cmnd[0], scsi_status, | 1585 | cmnd->cmnd[0], scsi_status, |
834 | be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info, | 1586 | be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info, |
@@ -851,7 +1603,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
851 | scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId)); | 1603 | scsi_set_resid(cmnd, be32_to_cpu(fcprsp->rspResId)); |
852 | 1604 | ||
853 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | 1605 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, |
854 | "0716 FCP Read Underrun, expected %d, " | 1606 | "9025 FCP Read Underrun, expected %d, " |
855 | "residual %d Data: x%x x%x x%x\n", | 1607 | "residual %d Data: x%x x%x x%x\n", |
856 | be32_to_cpu(fcpcmd->fcpDl), | 1608 | be32_to_cpu(fcpcmd->fcpDl), |
857 | scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0], | 1609 | scsi_get_resid(cmnd), fcpi_parm, cmnd->cmnd[0], |
@@ -867,7 +1619,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
867 | (scsi_get_resid(cmnd) != fcpi_parm)) { | 1619 | (scsi_get_resid(cmnd) != fcpi_parm)) { |
868 | lpfc_printf_vlog(vport, KERN_WARNING, | 1620 | lpfc_printf_vlog(vport, KERN_WARNING, |
869 | LOG_FCP | LOG_FCP_ERROR, | 1621 | LOG_FCP | LOG_FCP_ERROR, |
870 | "0735 FCP Read Check Error " | 1622 | "9026 FCP Read Check Error " |
871 | "and Underrun Data: x%x x%x x%x x%x\n", | 1623 | "and Underrun Data: x%x x%x x%x x%x\n", |
872 | be32_to_cpu(fcpcmd->fcpDl), | 1624 | be32_to_cpu(fcpcmd->fcpDl), |
873 | scsi_get_resid(cmnd), fcpi_parm, | 1625 | scsi_get_resid(cmnd), fcpi_parm, |
@@ -886,7 +1638,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
886 | (scsi_bufflen(cmnd) - scsi_get_resid(cmnd) | 1638 | (scsi_bufflen(cmnd) - scsi_get_resid(cmnd) |
887 | < cmnd->underflow)) { | 1639 | < cmnd->underflow)) { |
888 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, | 1640 | lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, |
889 | "0717 FCP command x%x residual " | 1641 | "9027 FCP command x%x residual " |
890 | "underrun converted to error " | 1642 | "underrun converted to error " |
891 | "Data: x%x x%x x%x\n", | 1643 | "Data: x%x x%x x%x\n", |
892 | cmnd->cmnd[0], scsi_bufflen(cmnd), | 1644 | cmnd->cmnd[0], scsi_bufflen(cmnd), |
@@ -895,7 +1647,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
895 | } | 1647 | } |
896 | } else if (resp_info & RESID_OVER) { | 1648 | } else if (resp_info & RESID_OVER) { |
897 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 1649 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, |
898 | "0720 FCP command x%x residual overrun error. " | 1650 | "9028 FCP command x%x residual overrun error. " |
899 | "Data: x%x x%x \n", cmnd->cmnd[0], | 1651 | "Data: x%x x%x \n", cmnd->cmnd[0], |
900 | scsi_bufflen(cmnd), scsi_get_resid(cmnd)); | 1652 | scsi_bufflen(cmnd), scsi_get_resid(cmnd)); |
901 | host_status = DID_ERROR; | 1653 | host_status = DID_ERROR; |
@@ -907,7 +1659,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
907 | } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm && | 1659 | } else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm && |
908 | (cmnd->sc_data_direction == DMA_FROM_DEVICE)) { | 1660 | (cmnd->sc_data_direction == DMA_FROM_DEVICE)) { |
909 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, | 1661 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR, |
910 | "0734 FCP Read Check Error Data: " | 1662 | "9029 FCP Read Check Error Data: " |
911 | "x%x x%x x%x x%x\n", | 1663 | "x%x x%x x%x x%x\n", |
912 | be32_to_cpu(fcpcmd->fcpDl), | 1664 | be32_to_cpu(fcpcmd->fcpDl), |
913 | be32_to_cpu(fcprsp->rspResId), | 1665 | be32_to_cpu(fcprsp->rspResId), |
@@ -960,7 +1712,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
960 | lpfc_cmd->status = IOSTAT_DEFAULT; | 1712 | lpfc_cmd->status = IOSTAT_DEFAULT; |
961 | 1713 | ||
962 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, | 1714 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, |
963 | "0729 FCP cmd x%x failed <%d/%d> " | 1715 | "9030 FCP cmd x%x failed <%d/%d> " |
964 | "status: x%x result: x%x Data: x%x x%x\n", | 1716 | "status: x%x result: x%x Data: x%x x%x\n", |
965 | cmd->cmnd[0], | 1717 | cmd->cmnd[0], |
966 | cmd->device ? cmd->device->id : 0xffff, | 1718 | cmd->device ? cmd->device->id : 0xffff, |
@@ -1008,7 +1760,28 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
1008 | lpfc_cmd->result == IOERR_ABORT_REQUESTED) { | 1760 | lpfc_cmd->result == IOERR_ABORT_REQUESTED) { |
1009 | cmd->result = ScsiResult(DID_REQUEUE, 0); | 1761 | cmd->result = ScsiResult(DID_REQUEUE, 0); |
1010 | break; | 1762 | break; |
1011 | } /* else: fall through */ | 1763 | } |
1764 | |||
1765 | if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED || | ||
1766 | lpfc_cmd->result == IOERR_TX_DMA_FAILED) && | ||
1767 | pIocbOut->iocb.unsli3.sli3_bg.bgstat) { | ||
1768 | if (scsi_get_prot_op(cmd) != SCSI_PROT_NORMAL) { | ||
1769 | /* | ||
1770 | * This is a response for a BG enabled | ||
1771 | * cmd. Parse BG error | ||
1772 | */ | ||
1773 | lpfc_parse_bg_err(phba, lpfc_cmd, | ||
1774 | pIocbOut); | ||
1775 | break; | ||
1776 | } else { | ||
1777 | lpfc_printf_vlog(vport, KERN_WARNING, | ||
1778 | LOG_BG, | ||
1779 | "9031 non-zero BGSTAT " | ||
1780 | "on unprotected cmd"); | ||
1781 | } | ||
1782 | } | ||
1783 | |||
1784 | /* else: fall through */ | ||
1012 | default: | 1785 | default: |
1013 | cmd->result = ScsiResult(DID_ERROR, 0); | 1786 | cmd->result = ScsiResult(DID_ERROR, 0); |
1014 | break; | 1787 | break; |
@@ -1243,7 +2016,6 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
1243 | } else { | 2016 | } else { |
1244 | iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR; | 2017 | iocb_cmd->ulpCommand = CMD_FCP_IREAD64_CR; |
1245 | iocb_cmd->ulpPU = PARM_READ_CHECK; | 2018 | iocb_cmd->ulpPU = PARM_READ_CHECK; |
1246 | iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd); | ||
1247 | fcp_cmnd->fcpCntl3 = READ_DATA; | 2019 | fcp_cmnd->fcpCntl3 = READ_DATA; |
1248 | phba->fc4InputRequests++; | 2020 | phba->fc4InputRequests++; |
1249 | } | 2021 | } |
@@ -1254,7 +2026,8 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
1254 | fcp_cmnd->fcpCntl3 = 0; | 2026 | fcp_cmnd->fcpCntl3 = 0; |
1255 | phba->fc4ControlRequests++; | 2027 | phba->fc4ControlRequests++; |
1256 | } | 2028 | } |
1257 | if (phba->sli_rev == 3) | 2029 | if (phba->sli_rev == 3 && |
2030 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) | ||
1258 | lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); | 2031 | lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); |
1259 | /* | 2032 | /* |
1260 | * Finish initializing those IOCB fields that are independent | 2033 | * Finish initializing those IOCB fields that are independent |
@@ -1312,7 +2085,8 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, | |||
1312 | memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); | 2085 | memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd)); |
1313 | int_to_scsilun(lun, &fcp_cmnd->fcp_lun); | 2086 | int_to_scsilun(lun, &fcp_cmnd->fcp_lun); |
1314 | fcp_cmnd->fcpCntl2 = task_mgmt_cmd; | 2087 | fcp_cmnd->fcpCntl2 = task_mgmt_cmd; |
1315 | if (vport->phba->sli_rev == 3) | 2088 | if (vport->phba->sli_rev == 3 && |
2089 | !(vport->phba->sli3_options & LPFC_SLI3_BG_ENABLED)) | ||
1316 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); | 2090 | lpfc_fcpcmd_to_iocb(piocb->unsli3.fcp_ext.icd, fcp_cmnd); |
1317 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; | 2091 | piocb->ulpCommand = CMD_FCP_ICMND64_CR; |
1318 | piocb->ulpContext = ndlp->nlp_rpi; | 2092 | piocb->ulpContext = ndlp->nlp_rpi; |
@@ -1541,6 +2315,17 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
1541 | goto out_fail_command; | 2315 | goto out_fail_command; |
1542 | } | 2316 | } |
1543 | 2317 | ||
2318 | if (!(phba->sli3_options & LPFC_SLI3_BG_ENABLED) && | ||
2319 | scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { | ||
2320 | |||
2321 | printk(KERN_ERR "BLKGRD ERROR: rcvd protected cmd:%02x op:%02x " | ||
2322 | "str=%s without registering for BlockGuard - " | ||
2323 | "Rejecting command\n", | ||
2324 | cmnd->cmnd[0], scsi_get_prot_op(cmnd), | ||
2325 | dif_op_str[scsi_get_prot_op(cmnd)]); | ||
2326 | goto out_fail_command; | ||
2327 | } | ||
2328 | |||
1544 | /* | 2329 | /* |
1545 | * Catch race where our node has transitioned, but the | 2330 | * Catch race where our node has transitioned, but the |
1546 | * transport is still transitioning. | 2331 | * transport is still transitioning. |
@@ -1574,7 +2359,64 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
1574 | cmnd->host_scribble = (unsigned char *)lpfc_cmd; | 2359 | cmnd->host_scribble = (unsigned char *)lpfc_cmd; |
1575 | cmnd->scsi_done = done; | 2360 | cmnd->scsi_done = done; |
1576 | 2361 | ||
1577 | err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd); | 2362 | if (scsi_get_prot_op(cmnd) != SCSI_PROT_NORMAL) { |
2363 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2364 | "9033 BLKGRD: rcvd protected cmd:%02x op:%02x " | ||
2365 | "str=%s\n", | ||
2366 | cmnd->cmnd[0], scsi_get_prot_op(cmnd), | ||
2367 | dif_op_str[scsi_get_prot_op(cmnd)]); | ||
2368 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2369 | "9034 BLKGRD: CDB: %02x %02x %02x %02x %02x " | ||
2370 | "%02x %02x %02x %02x %02x \n", | ||
2371 | cmnd->cmnd[0], cmnd->cmnd[1], cmnd->cmnd[2], | ||
2372 | cmnd->cmnd[3], cmnd->cmnd[4], cmnd->cmnd[5], | ||
2373 | cmnd->cmnd[6], cmnd->cmnd[7], cmnd->cmnd[8], | ||
2374 | cmnd->cmnd[9]); | ||
2375 | if (cmnd->cmnd[0] == READ_10) | ||
2376 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2377 | "9035 BLKGRD: READ @ sector %llu, " | ||
2378 | "count %lu\n", | ||
2379 | (u64)scsi_get_lba(cmnd), | ||
2380 | cmnd->request->nr_sectors); | ||
2381 | else if (cmnd->cmnd[0] == WRITE_10) | ||
2382 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2383 | "9036 BLKGRD: WRITE @ sector %llu, " | ||
2384 | "count %lu cmd=%p\n", | ||
2385 | (u64)scsi_get_lba(cmnd), | ||
2386 | cmnd->request->nr_sectors, | ||
2387 | cmnd); | ||
2388 | |||
2389 | err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); | ||
2390 | } else { | ||
2391 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2392 | "9038 BLKGRD: rcvd unprotected cmd:%02x op:%02x" | ||
2393 | " str=%s\n", | ||
2394 | cmnd->cmnd[0], scsi_get_prot_op(cmnd), | ||
2395 | dif_op_str[scsi_get_prot_op(cmnd)]); | ||
2396 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2397 | "9039 BLKGRD: CDB: %02x %02x %02x %02x %02x " | ||
2398 | "%02x %02x %02x %02x %02x \n", | ||
2399 | cmnd->cmnd[0], cmnd->cmnd[1], cmnd->cmnd[2], | ||
2400 | cmnd->cmnd[3], cmnd->cmnd[4], cmnd->cmnd[5], | ||
2401 | cmnd->cmnd[6], cmnd->cmnd[7], cmnd->cmnd[8], | ||
2402 | cmnd->cmnd[9]); | ||
2403 | if (cmnd->cmnd[0] == READ_10) | ||
2404 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2405 | "9040 dbg: READ @ sector %llu, " | ||
2406 | "count %lu\n", (u64)scsi_get_lba(cmnd), | ||
2407 | cmnd->request->nr_sectors); | ||
2408 | else if (cmnd->cmnd[0] == WRITE_10) | ||
2409 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2410 | "9041 dbg: WRITE @ sector %llu, " | ||
2411 | "count %lu cmd=%p\n", | ||
2412 | (u64)scsi_get_lba(cmnd), | ||
2413 | cmnd->request->nr_sectors, cmnd); | ||
2414 | else | ||
2415 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | ||
2416 | "9042 dbg: parser not implemented\n"); | ||
2417 | err = lpfc_scsi_prep_dma_buf(phba, lpfc_cmd); | ||
2418 | } | ||
2419 | |||
1578 | if (err) | 2420 | if (err) |
1579 | goto out_host_busy_free_buf; | 2421 | goto out_host_busy_free_buf; |
1580 | 2422 | ||