diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 879 |
1 files changed, 843 insertions, 36 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 8299a9891bf..8ef94536541 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -145,7 +145,49 @@ qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *vha) | |||
145 | return (cont_pkt); | 145 | return (cont_pkt); |
146 | } | 146 | } |
147 | 147 | ||
148 | /** | 148 | static inline int |
149 | qla24xx_configure_prot_mode(srb_t *sp, uint16_t *fw_prot_opts) | ||
150 | { | ||
151 | uint8_t guard = scsi_host_get_guard(sp->cmd->device->host); | ||
152 | |||
153 | /* We only support T10 DIF right now */ | ||
154 | if (guard != SHOST_DIX_GUARD_CRC) { | ||
155 | DEBUG2(printk(KERN_ERR "Unsupported guard: %d\n", guard)); | ||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | /* We always use DIFF Bundling for best performance */ | ||
160 | *fw_prot_opts = 0; | ||
161 | |||
162 | /* Translate SCSI opcode to a protection opcode */ | ||
163 | switch (scsi_get_prot_op(sp->cmd)) { | ||
164 | case SCSI_PROT_READ_STRIP: | ||
165 | *fw_prot_opts |= PO_MODE_DIF_REMOVE; | ||
166 | break; | ||
167 | case SCSI_PROT_WRITE_INSERT: | ||
168 | *fw_prot_opts |= PO_MODE_DIF_INSERT; | ||
169 | break; | ||
170 | case SCSI_PROT_READ_INSERT: | ||
171 | *fw_prot_opts |= PO_MODE_DIF_INSERT; | ||
172 | break; | ||
173 | case SCSI_PROT_WRITE_STRIP: | ||
174 | *fw_prot_opts |= PO_MODE_DIF_REMOVE; | ||
175 | break; | ||
176 | case SCSI_PROT_READ_PASS: | ||
177 | *fw_prot_opts |= PO_MODE_DIF_PASS; | ||
178 | break; | ||
179 | case SCSI_PROT_WRITE_PASS: | ||
180 | *fw_prot_opts |= PO_MODE_DIF_PASS; | ||
181 | break; | ||
182 | default: /* Normal Request */ | ||
183 | *fw_prot_opts |= PO_MODE_DIF_PASS; | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | return scsi_prot_sg_count(sp->cmd); | ||
188 | } | ||
189 | |||
190 | /* | ||
149 | * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit | 191 | * qla2x00_build_scsi_iocbs_32() - Build IOCB command utilizing 32bit |
150 | * capable IOCB types. | 192 | * capable IOCB types. |
151 | * | 193 | * |
@@ -506,7 +548,10 @@ qla2x00_req_pkt(struct scsi_qla_host *vha, struct req_que *req, | |||
506 | cnt = (uint16_t) | 548 | cnt = (uint16_t) |
507 | RD_REG_DWORD(®->isp25mq.req_q_out); | 549 | RD_REG_DWORD(®->isp25mq.req_q_out); |
508 | else { | 550 | else { |
509 | if (IS_FWI2_CAPABLE(ha)) | 551 | if (IS_QLA82XX(ha)) |
552 | cnt = (uint16_t)RD_REG_DWORD( | ||
553 | ®->isp82.req_q_out); | ||
554 | else if (IS_FWI2_CAPABLE(ha)) | ||
510 | cnt = (uint16_t)RD_REG_DWORD( | 555 | cnt = (uint16_t)RD_REG_DWORD( |
511 | ®->isp24.req_q_out); | 556 | ®->isp24.req_q_out); |
512 | else | 557 | else |
@@ -579,11 +624,29 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) | |||
579 | req->ring_ptr++; | 624 | req->ring_ptr++; |
580 | 625 | ||
581 | /* Set chip new ring index. */ | 626 | /* Set chip new ring index. */ |
582 | if (ha->mqenable) { | 627 | if (IS_QLA82XX(ha)) { |
628 | uint32_t dbval = 0x04 | (ha->portnum << 5); | ||
629 | |||
630 | /* write, read and verify logic */ | ||
631 | dbval = dbval | (req->id << 8) | (req->ring_index << 16); | ||
632 | if (ql2xdbwr) | ||
633 | qla82xx_wr_32(ha, ha->nxdb_wr_ptr, dbval); | ||
634 | else { | ||
635 | WRT_REG_DWORD( | ||
636 | (unsigned long __iomem *)ha->nxdb_wr_ptr, | ||
637 | dbval); | ||
638 | wmb(); | ||
639 | while (RD_REG_DWORD(ha->nxdb_rd_ptr) != dbval) { | ||
640 | WRT_REG_DWORD((unsigned long __iomem *) | ||
641 | ha->nxdb_wr_ptr, dbval); | ||
642 | wmb(); | ||
643 | } | ||
644 | } | ||
645 | } else if (ha->mqenable) { | ||
646 | /* Set chip new ring index. */ | ||
583 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | 647 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); |
584 | RD_REG_DWORD(&ioreg->hccr); | 648 | RD_REG_DWORD(&ioreg->hccr); |
585 | } | 649 | } else { |
586 | else { | ||
587 | if (IS_FWI2_CAPABLE(ha)) { | 650 | if (IS_FWI2_CAPABLE(ha)) { |
588 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | 651 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); |
589 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | 652 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); |
@@ -604,7 +667,7 @@ qla2x00_isp_cmd(struct scsi_qla_host *vha, struct req_que *req) | |||
604 | * | 667 | * |
605 | * Returns the number of IOCB entries needed to store @dsds. | 668 | * Returns the number of IOCB entries needed to store @dsds. |
606 | */ | 669 | */ |
607 | static inline uint16_t | 670 | inline uint16_t |
608 | qla24xx_calc_iocbs(uint16_t dsds) | 671 | qla24xx_calc_iocbs(uint16_t dsds) |
609 | { | 672 | { |
610 | uint16_t iocbs; | 673 | uint16_t iocbs; |
@@ -615,6 +678,8 @@ qla24xx_calc_iocbs(uint16_t dsds) | |||
615 | if ((dsds - 1) % 5) | 678 | if ((dsds - 1) % 5) |
616 | iocbs++; | 679 | iocbs++; |
617 | } | 680 | } |
681 | DEBUG3(printk(KERN_DEBUG "%s(): Required PKT(s) = %d\n", | ||
682 | __func__, iocbs)); | ||
618 | return iocbs; | 683 | return iocbs; |
619 | } | 684 | } |
620 | 685 | ||
@@ -626,7 +691,7 @@ qla24xx_calc_iocbs(uint16_t dsds) | |||
626 | * @cmd_pkt: Command type 3 IOCB | 691 | * @cmd_pkt: Command type 3 IOCB |
627 | * @tot_dsds: Total number of segments to transfer | 692 | * @tot_dsds: Total number of segments to transfer |
628 | */ | 693 | */ |
629 | static inline void | 694 | inline void |
630 | qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | 695 | qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, |
631 | uint16_t tot_dsds) | 696 | uint16_t tot_dsds) |
632 | { | 697 | { |
@@ -695,6 +760,453 @@ qla24xx_build_scsi_iocbs(srb_t *sp, struct cmd_type_7 *cmd_pkt, | |||
695 | } | 760 | } |
696 | } | 761 | } |
697 | 762 | ||
763 | struct fw_dif_context { | ||
764 | uint32_t ref_tag; | ||
765 | uint16_t app_tag; | ||
766 | uint8_t ref_tag_mask[4]; /* Validation/Replacement Mask*/ | ||
767 | uint8_t app_tag_mask[2]; /* Validation/Replacement Mask*/ | ||
768 | }; | ||
769 | |||
770 | /* | ||
771 | * qla24xx_set_t10dif_tags_from_cmd - Extract Ref and App tags from SCSI command | ||
772 | * | ||
773 | */ | ||
774 | static inline void | ||
775 | qla24xx_set_t10dif_tags(struct scsi_cmnd *cmd, struct fw_dif_context *pkt, | ||
776 | unsigned int protcnt) | ||
777 | { | ||
778 | struct sd_dif_tuple *spt; | ||
779 | unsigned char op = scsi_get_prot_op(cmd); | ||
780 | |||
781 | switch (scsi_get_prot_type(cmd)) { | ||
782 | /* For TYPE 0 protection: no checking */ | ||
783 | case SCSI_PROT_DIF_TYPE0: | ||
784 | pkt->ref_tag_mask[0] = 0x00; | ||
785 | pkt->ref_tag_mask[1] = 0x00; | ||
786 | pkt->ref_tag_mask[2] = 0x00; | ||
787 | pkt->ref_tag_mask[3] = 0x00; | ||
788 | break; | ||
789 | |||
790 | /* | ||
791 | * For TYPE 2 protection: 16 bit GUARD + 32 bit REF tag has to | ||
792 | * match LBA in CDB + N | ||
793 | */ | ||
794 | case SCSI_PROT_DIF_TYPE2: | ||
795 | break; | ||
796 | |||
797 | /* For Type 3 protection: 16 bit GUARD only */ | ||
798 | case SCSI_PROT_DIF_TYPE3: | ||
799 | pkt->ref_tag_mask[0] = pkt->ref_tag_mask[1] = | ||
800 | pkt->ref_tag_mask[2] = pkt->ref_tag_mask[3] = | ||
801 | 0x00; | ||
802 | break; | ||
803 | |||
804 | /* | ||
805 | * For TYpe 1 protection: 16 bit GUARD tag, 32 bit REF tag, and | ||
806 | * 16 bit app tag. | ||
807 | */ | ||
808 | case SCSI_PROT_DIF_TYPE1: | ||
809 | if (!ql2xenablehba_err_chk) | ||
810 | break; | ||
811 | |||
812 | if (protcnt && (op == SCSI_PROT_WRITE_STRIP || | ||
813 | op == SCSI_PROT_WRITE_PASS)) { | ||
814 | spt = page_address(sg_page(scsi_prot_sglist(cmd))) + | ||
815 | scsi_prot_sglist(cmd)[0].offset; | ||
816 | DEBUG18(printk(KERN_DEBUG | ||
817 | "%s(): LBA from user %p, lba = 0x%x\n", | ||
818 | __func__, spt, (int)spt->ref_tag)); | ||
819 | pkt->ref_tag = swab32(spt->ref_tag); | ||
820 | pkt->app_tag_mask[0] = 0x0; | ||
821 | pkt->app_tag_mask[1] = 0x0; | ||
822 | } else { | ||
823 | pkt->ref_tag = cpu_to_le32((uint32_t) | ||
824 | (0xffffffff & scsi_get_lba(cmd))); | ||
825 | pkt->app_tag = __constant_cpu_to_le16(0); | ||
826 | pkt->app_tag_mask[0] = 0x0; | ||
827 | pkt->app_tag_mask[1] = 0x0; | ||
828 | } | ||
829 | /* enable ALL bytes of the ref tag */ | ||
830 | pkt->ref_tag_mask[0] = 0xff; | ||
831 | pkt->ref_tag_mask[1] = 0xff; | ||
832 | pkt->ref_tag_mask[2] = 0xff; | ||
833 | pkt->ref_tag_mask[3] = 0xff; | ||
834 | break; | ||
835 | } | ||
836 | |||
837 | DEBUG18(printk(KERN_DEBUG | ||
838 | "%s(): Setting protection Tags: (BIG) ref tag = 0x%x," | ||
839 | " app tag = 0x%x, prot SG count %d , cmd lba 0x%x," | ||
840 | " prot_type=%u\n", __func__, pkt->ref_tag, pkt->app_tag, protcnt, | ||
841 | (int)scsi_get_lba(cmd), scsi_get_prot_type(cmd))); | ||
842 | } | ||
843 | |||
844 | |||
845 | static int | ||
846 | qla24xx_walk_and_build_sglist(struct qla_hw_data *ha, srb_t *sp, uint32_t *dsd, | ||
847 | uint16_t tot_dsds) | ||
848 | { | ||
849 | void *next_dsd; | ||
850 | uint8_t avail_dsds = 0; | ||
851 | uint32_t dsd_list_len; | ||
852 | struct dsd_dma *dsd_ptr; | ||
853 | struct scatterlist *sg; | ||
854 | uint32_t *cur_dsd = dsd; | ||
855 | int i; | ||
856 | uint16_t used_dsds = tot_dsds; | ||
857 | |||
858 | uint8_t *cp; | ||
859 | |||
860 | scsi_for_each_sg(sp->cmd, sg, tot_dsds, i) { | ||
861 | dma_addr_t sle_dma; | ||
862 | |||
863 | /* Allocate additional continuation packets? */ | ||
864 | if (avail_dsds == 0) { | ||
865 | avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? | ||
866 | QLA_DSDS_PER_IOCB : used_dsds; | ||
867 | dsd_list_len = (avail_dsds + 1) * 12; | ||
868 | used_dsds -= avail_dsds; | ||
869 | |||
870 | /* allocate tracking DS */ | ||
871 | dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); | ||
872 | if (!dsd_ptr) | ||
873 | return 1; | ||
874 | |||
875 | /* allocate new list */ | ||
876 | dsd_ptr->dsd_addr = next_dsd = | ||
877 | dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, | ||
878 | &dsd_ptr->dsd_list_dma); | ||
879 | |||
880 | if (!next_dsd) { | ||
881 | /* | ||
882 | * Need to cleanup only this dsd_ptr, rest | ||
883 | * will be done by sp_free_dma() | ||
884 | */ | ||
885 | kfree(dsd_ptr); | ||
886 | return 1; | ||
887 | } | ||
888 | |||
889 | list_add_tail(&dsd_ptr->list, | ||
890 | &((struct crc_context *)sp->ctx)->dsd_list); | ||
891 | |||
892 | sp->flags |= SRB_CRC_CTX_DSD_VALID; | ||
893 | |||
894 | /* add new list to cmd iocb or last list */ | ||
895 | *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); | ||
896 | *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); | ||
897 | *cur_dsd++ = dsd_list_len; | ||
898 | cur_dsd = (uint32_t *)next_dsd; | ||
899 | } | ||
900 | sle_dma = sg_dma_address(sg); | ||
901 | DEBUG18(printk("%s(): %p, sg entry %d - addr =0x%x 0x%x," | ||
902 | " len =%d\n", __func__ , cur_dsd, i, LSD(sle_dma), | ||
903 | MSD(sle_dma), sg_dma_len(sg))); | ||
904 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
905 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
906 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
907 | avail_dsds--; | ||
908 | |||
909 | if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { | ||
910 | cp = page_address(sg_page(sg)) + sg->offset; | ||
911 | DEBUG18(printk("%s(): User Data buffer= %p:\n", | ||
912 | __func__ , cp)); | ||
913 | } | ||
914 | } | ||
915 | /* Null termination */ | ||
916 | *cur_dsd++ = 0; | ||
917 | *cur_dsd++ = 0; | ||
918 | *cur_dsd++ = 0; | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | static int | ||
923 | qla24xx_walk_and_build_prot_sglist(struct qla_hw_data *ha, srb_t *sp, | ||
924 | uint32_t *dsd, | ||
925 | uint16_t tot_dsds) | ||
926 | { | ||
927 | void *next_dsd; | ||
928 | uint8_t avail_dsds = 0; | ||
929 | uint32_t dsd_list_len; | ||
930 | struct dsd_dma *dsd_ptr; | ||
931 | struct scatterlist *sg; | ||
932 | int i; | ||
933 | struct scsi_cmnd *cmd; | ||
934 | uint32_t *cur_dsd = dsd; | ||
935 | uint16_t used_dsds = tot_dsds; | ||
936 | |||
937 | uint8_t *cp; | ||
938 | |||
939 | |||
940 | cmd = sp->cmd; | ||
941 | scsi_for_each_prot_sg(cmd, sg, tot_dsds, i) { | ||
942 | dma_addr_t sle_dma; | ||
943 | |||
944 | /* Allocate additional continuation packets? */ | ||
945 | if (avail_dsds == 0) { | ||
946 | avail_dsds = (used_dsds > QLA_DSDS_PER_IOCB) ? | ||
947 | QLA_DSDS_PER_IOCB : used_dsds; | ||
948 | dsd_list_len = (avail_dsds + 1) * 12; | ||
949 | used_dsds -= avail_dsds; | ||
950 | |||
951 | /* allocate tracking DS */ | ||
952 | dsd_ptr = kzalloc(sizeof(struct dsd_dma), GFP_ATOMIC); | ||
953 | if (!dsd_ptr) | ||
954 | return 1; | ||
955 | |||
956 | /* allocate new list */ | ||
957 | dsd_ptr->dsd_addr = next_dsd = | ||
958 | dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, | ||
959 | &dsd_ptr->dsd_list_dma); | ||
960 | |||
961 | if (!next_dsd) { | ||
962 | /* | ||
963 | * Need to cleanup only this dsd_ptr, rest | ||
964 | * will be done by sp_free_dma() | ||
965 | */ | ||
966 | kfree(dsd_ptr); | ||
967 | return 1; | ||
968 | } | ||
969 | |||
970 | list_add_tail(&dsd_ptr->list, | ||
971 | &((struct crc_context *)sp->ctx)->dsd_list); | ||
972 | |||
973 | sp->flags |= SRB_CRC_CTX_DSD_VALID; | ||
974 | |||
975 | /* add new list to cmd iocb or last list */ | ||
976 | *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma)); | ||
977 | *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma)); | ||
978 | *cur_dsd++ = dsd_list_len; | ||
979 | cur_dsd = (uint32_t *)next_dsd; | ||
980 | } | ||
981 | sle_dma = sg_dma_address(sg); | ||
982 | if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { | ||
983 | DEBUG18(printk(KERN_DEBUG | ||
984 | "%s(): %p, sg entry %d - addr =0x%x" | ||
985 | "0x%x, len =%d\n", __func__ , cur_dsd, i, | ||
986 | LSD(sle_dma), MSD(sle_dma), sg_dma_len(sg))); | ||
987 | } | ||
988 | *cur_dsd++ = cpu_to_le32(LSD(sle_dma)); | ||
989 | *cur_dsd++ = cpu_to_le32(MSD(sle_dma)); | ||
990 | *cur_dsd++ = cpu_to_le32(sg_dma_len(sg)); | ||
991 | |||
992 | if (scsi_get_prot_op(sp->cmd) == SCSI_PROT_WRITE_PASS) { | ||
993 | cp = page_address(sg_page(sg)) + sg->offset; | ||
994 | DEBUG18(printk("%s(): Protection Data buffer = %p:\n", | ||
995 | __func__ , cp)); | ||
996 | } | ||
997 | avail_dsds--; | ||
998 | } | ||
999 | /* Null termination */ | ||
1000 | *cur_dsd++ = 0; | ||
1001 | *cur_dsd++ = 0; | ||
1002 | *cur_dsd++ = 0; | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | /** | ||
1007 | * qla24xx_build_scsi_crc_2_iocbs() - Build IOCB command utilizing Command | ||
1008 | * Type 6 IOCB types. | ||
1009 | * | ||
1010 | * @sp: SRB command to process | ||
1011 | * @cmd_pkt: Command type 3 IOCB | ||
1012 | * @tot_dsds: Total number of segments to transfer | ||
1013 | */ | ||
1014 | static inline int | ||
1015 | qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, | ||
1016 | uint16_t tot_dsds, uint16_t tot_prot_dsds, uint16_t fw_prot_opts) | ||
1017 | { | ||
1018 | uint32_t *cur_dsd, *fcp_dl; | ||
1019 | scsi_qla_host_t *vha; | ||
1020 | struct scsi_cmnd *cmd; | ||
1021 | struct scatterlist *cur_seg; | ||
1022 | int sgc; | ||
1023 | uint32_t total_bytes; | ||
1024 | uint32_t data_bytes; | ||
1025 | uint32_t dif_bytes; | ||
1026 | uint8_t bundling = 1; | ||
1027 | uint16_t blk_size; | ||
1028 | uint8_t *clr_ptr; | ||
1029 | struct crc_context *crc_ctx_pkt = NULL; | ||
1030 | struct qla_hw_data *ha; | ||
1031 | uint8_t additional_fcpcdb_len; | ||
1032 | uint16_t fcp_cmnd_len; | ||
1033 | struct fcp_cmnd *fcp_cmnd; | ||
1034 | dma_addr_t crc_ctx_dma; | ||
1035 | |||
1036 | cmd = sp->cmd; | ||
1037 | |||
1038 | sgc = 0; | ||
1039 | /* Update entry type to indicate Command Type CRC_2 IOCB */ | ||
1040 | *((uint32_t *)(&cmd_pkt->entry_type)) = | ||
1041 | __constant_cpu_to_le32(COMMAND_TYPE_CRC_2); | ||
1042 | |||
1043 | /* No data transfer */ | ||
1044 | data_bytes = scsi_bufflen(cmd); | ||
1045 | if (!data_bytes || cmd->sc_data_direction == DMA_NONE) { | ||
1046 | DEBUG18(printk(KERN_INFO "%s: Zero data bytes or DMA-NONE %d\n", | ||
1047 | __func__, data_bytes)); | ||
1048 | cmd_pkt->byte_count = __constant_cpu_to_le32(0); | ||
1049 | return QLA_SUCCESS; | ||
1050 | } | ||
1051 | |||
1052 | vha = sp->fcport->vha; | ||
1053 | ha = vha->hw; | ||
1054 | |||
1055 | DEBUG18(printk(KERN_DEBUG | ||
1056 | "%s(%ld): Executing cmd sp %p, pid=%ld, prot_op=%u.\n", __func__, | ||
1057 | vha->host_no, sp, cmd->serial_number, scsi_get_prot_op(sp->cmd))); | ||
1058 | |||
1059 | cmd_pkt->vp_index = sp->fcport->vp_idx; | ||
1060 | |||
1061 | /* Set transfer direction */ | ||
1062 | if (cmd->sc_data_direction == DMA_TO_DEVICE) { | ||
1063 | cmd_pkt->control_flags = | ||
1064 | __constant_cpu_to_le16(CF_WRITE_DATA); | ||
1065 | } else if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
1066 | cmd_pkt->control_flags = | ||
1067 | __constant_cpu_to_le16(CF_READ_DATA); | ||
1068 | } | ||
1069 | |||
1070 | tot_prot_dsds = scsi_prot_sg_count(cmd); | ||
1071 | if (!tot_prot_dsds) | ||
1072 | bundling = 0; | ||
1073 | |||
1074 | /* Allocate CRC context from global pool */ | ||
1075 | crc_ctx_pkt = sp->ctx = dma_pool_alloc(ha->dl_dma_pool, | ||
1076 | GFP_ATOMIC, &crc_ctx_dma); | ||
1077 | |||
1078 | if (!crc_ctx_pkt) | ||
1079 | goto crc_queuing_error; | ||
1080 | |||
1081 | /* Zero out CTX area. */ | ||
1082 | clr_ptr = (uint8_t *)crc_ctx_pkt; | ||
1083 | memset(clr_ptr, 0, sizeof(*crc_ctx_pkt)); | ||
1084 | |||
1085 | crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma; | ||
1086 | |||
1087 | sp->flags |= SRB_CRC_CTX_DMA_VALID; | ||
1088 | |||
1089 | /* Set handle */ | ||
1090 | crc_ctx_pkt->handle = cmd_pkt->handle; | ||
1091 | |||
1092 | INIT_LIST_HEAD(&crc_ctx_pkt->dsd_list); | ||
1093 | |||
1094 | qla24xx_set_t10dif_tags(cmd, (struct fw_dif_context *) | ||
1095 | &crc_ctx_pkt->ref_tag, tot_prot_dsds); | ||
1096 | |||
1097 | cmd_pkt->crc_context_address[0] = cpu_to_le32(LSD(crc_ctx_dma)); | ||
1098 | cmd_pkt->crc_context_address[1] = cpu_to_le32(MSD(crc_ctx_dma)); | ||
1099 | cmd_pkt->crc_context_len = CRC_CONTEXT_LEN_FW; | ||
1100 | |||
1101 | /* Determine SCSI command length -- align to 4 byte boundary */ | ||
1102 | if (cmd->cmd_len > 16) { | ||
1103 | DEBUG18(printk(KERN_INFO "%s(): **** SCSI CMD > 16\n", | ||
1104 | __func__)); | ||
1105 | additional_fcpcdb_len = cmd->cmd_len - 16; | ||
1106 | if ((cmd->cmd_len % 4) != 0) { | ||
1107 | /* SCSI cmd > 16 bytes must be multiple of 4 */ | ||
1108 | goto crc_queuing_error; | ||
1109 | } | ||
1110 | fcp_cmnd_len = 12 + cmd->cmd_len + 4; | ||
1111 | } else { | ||
1112 | additional_fcpcdb_len = 0; | ||
1113 | fcp_cmnd_len = 12 + 16 + 4; | ||
1114 | } | ||
1115 | |||
1116 | fcp_cmnd = &crc_ctx_pkt->fcp_cmnd; | ||
1117 | |||
1118 | fcp_cmnd->additional_cdb_len = additional_fcpcdb_len; | ||
1119 | if (cmd->sc_data_direction == DMA_TO_DEVICE) | ||
1120 | fcp_cmnd->additional_cdb_len |= 1; | ||
1121 | else if (cmd->sc_data_direction == DMA_FROM_DEVICE) | ||
1122 | fcp_cmnd->additional_cdb_len |= 2; | ||
1123 | |||
1124 | int_to_scsilun(sp->cmd->device->lun, &fcp_cmnd->lun); | ||
1125 | memcpy(fcp_cmnd->cdb, cmd->cmnd, cmd->cmd_len); | ||
1126 | cmd_pkt->fcp_cmnd_dseg_len = cpu_to_le16(fcp_cmnd_len); | ||
1127 | cmd_pkt->fcp_cmnd_dseg_address[0] = cpu_to_le32( | ||
1128 | LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); | ||
1129 | cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32( | ||
1130 | MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF)); | ||
1131 | fcp_cmnd->task_attribute = 0; | ||
1132 | fcp_cmnd->task_managment = 0; | ||
1133 | |||
1134 | cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ | ||
1135 | |||
1136 | DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data" | ||
1137 | "entries %d, data bytes %d, Protection entries %d\n", | ||
1138 | __func__, vha->host_no, tot_dsds, (tot_dsds-tot_prot_dsds), | ||
1139 | data_bytes, tot_prot_dsds)); | ||
1140 | |||
1141 | /* Compute dif len and adjust data len to incude protection */ | ||
1142 | total_bytes = data_bytes; | ||
1143 | dif_bytes = 0; | ||
1144 | blk_size = cmd->device->sector_size; | ||
1145 | if (scsi_get_prot_type(cmd) == SCSI_PROT_DIF_TYPE1) { | ||
1146 | dif_bytes = (data_bytes / blk_size) * 8; | ||
1147 | total_bytes += dif_bytes; | ||
1148 | } | ||
1149 | |||
1150 | if (!ql2xenablehba_err_chk) | ||
1151 | fw_prot_opts |= 0x10; /* Disable Guard tag checking */ | ||
1152 | |||
1153 | if (!bundling) { | ||
1154 | cur_dsd = (uint32_t *) &crc_ctx_pkt->u.nobundling.data_address; | ||
1155 | } else { | ||
1156 | /* | ||
1157 | * Configure Bundling if we need to fetch interlaving | ||
1158 | * protection PCI accesses | ||
1159 | */ | ||
1160 | fw_prot_opts |= PO_ENABLE_DIF_BUNDLING; | ||
1161 | crc_ctx_pkt->u.bundling.dif_byte_count = cpu_to_le32(dif_bytes); | ||
1162 | crc_ctx_pkt->u.bundling.dseg_count = cpu_to_le16(tot_dsds - | ||
1163 | tot_prot_dsds); | ||
1164 | cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.data_address; | ||
1165 | } | ||
1166 | |||
1167 | /* Finish the common fields of CRC pkt */ | ||
1168 | crc_ctx_pkt->blk_size = cpu_to_le16(blk_size); | ||
1169 | crc_ctx_pkt->prot_opts = cpu_to_le16(fw_prot_opts); | ||
1170 | crc_ctx_pkt->byte_count = cpu_to_le32(data_bytes); | ||
1171 | crc_ctx_pkt->guard_seed = __constant_cpu_to_le16(0); | ||
1172 | /* Fibre channel byte count */ | ||
1173 | cmd_pkt->byte_count = cpu_to_le32(total_bytes); | ||
1174 | fcp_dl = (uint32_t *)(crc_ctx_pkt->fcp_cmnd.cdb + 16 + | ||
1175 | additional_fcpcdb_len); | ||
1176 | *fcp_dl = htonl(total_bytes); | ||
1177 | |||
1178 | DEBUG18(printk(KERN_INFO "%s(%ld): dif bytes = 0x%x (%d), total bytes" | ||
1179 | " = 0x%x (%d), dat block size =0x%x (%d)\n", __func__, | ||
1180 | vha->host_no, dif_bytes, dif_bytes, total_bytes, total_bytes, | ||
1181 | crc_ctx_pkt->blk_size, crc_ctx_pkt->blk_size)); | ||
1182 | |||
1183 | /* Walks data segments */ | ||
1184 | |||
1185 | cmd_pkt->control_flags |= | ||
1186 | __constant_cpu_to_le16(CF_DATA_SEG_DESCR_ENABLE); | ||
1187 | if (qla24xx_walk_and_build_sglist(ha, sp, cur_dsd, | ||
1188 | (tot_dsds - tot_prot_dsds))) | ||
1189 | goto crc_queuing_error; | ||
1190 | |||
1191 | if (bundling && tot_prot_dsds) { | ||
1192 | /* Walks dif segments */ | ||
1193 | cur_seg = scsi_prot_sglist(cmd); | ||
1194 | cmd_pkt->control_flags |= | ||
1195 | __constant_cpu_to_le16(CF_DIF_SEG_DESCR_ENABLE); | ||
1196 | cur_dsd = (uint32_t *) &crc_ctx_pkt->u.bundling.dif_address; | ||
1197 | if (qla24xx_walk_and_build_prot_sglist(ha, sp, cur_dsd, | ||
1198 | tot_prot_dsds)) | ||
1199 | goto crc_queuing_error; | ||
1200 | } | ||
1201 | return QLA_SUCCESS; | ||
1202 | |||
1203 | crc_queuing_error: | ||
1204 | DEBUG18(qla_printk(KERN_INFO, ha, | ||
1205 | "CMD sent FAILED crc_q error:sp = %p\n", sp)); | ||
1206 | /* Cleanup will be performed by the caller */ | ||
1207 | |||
1208 | return QLA_FUNCTION_FAILED; | ||
1209 | } | ||
698 | 1210 | ||
699 | /** | 1211 | /** |
700 | * qla24xx_start_scsi() - Send a SCSI command to the ISP | 1212 | * qla24xx_start_scsi() - Send a SCSI command to the ISP |
@@ -848,6 +1360,191 @@ queuing_error: | |||
848 | return QLA_FUNCTION_FAILED; | 1360 | return QLA_FUNCTION_FAILED; |
849 | } | 1361 | } |
850 | 1362 | ||
1363 | |||
1364 | /** | ||
1365 | * qla24xx_dif_start_scsi() - Send a SCSI command to the ISP | ||
1366 | * @sp: command to send to the ISP | ||
1367 | * | ||
1368 | * Returns non-zero if a failure occurred, else zero. | ||
1369 | */ | ||
1370 | int | ||
1371 | qla24xx_dif_start_scsi(srb_t *sp) | ||
1372 | { | ||
1373 | int nseg; | ||
1374 | unsigned long flags; | ||
1375 | uint32_t *clr_ptr; | ||
1376 | uint32_t index; | ||
1377 | uint32_t handle; | ||
1378 | uint16_t cnt; | ||
1379 | uint16_t req_cnt = 0; | ||
1380 | uint16_t tot_dsds; | ||
1381 | uint16_t tot_prot_dsds; | ||
1382 | uint16_t fw_prot_opts = 0; | ||
1383 | struct req_que *req = NULL; | ||
1384 | struct rsp_que *rsp = NULL; | ||
1385 | struct scsi_cmnd *cmd = sp->cmd; | ||
1386 | struct scsi_qla_host *vha = sp->fcport->vha; | ||
1387 | struct qla_hw_data *ha = vha->hw; | ||
1388 | struct cmd_type_crc_2 *cmd_pkt; | ||
1389 | uint32_t status = 0; | ||
1390 | |||
1391 | #define QDSS_GOT_Q_SPACE BIT_0 | ||
1392 | |||
1393 | /* Only process protection in this routine */ | ||
1394 | if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) | ||
1395 | return qla24xx_start_scsi(sp); | ||
1396 | |||
1397 | /* Setup device pointers. */ | ||
1398 | |||
1399 | qla25xx_set_que(sp, &rsp); | ||
1400 | req = vha->req; | ||
1401 | |||
1402 | /* So we know we haven't pci_map'ed anything yet */ | ||
1403 | tot_dsds = 0; | ||
1404 | |||
1405 | /* Send marker if required */ | ||
1406 | if (vha->marker_needed != 0) { | ||
1407 | if (qla2x00_marker(vha, req, rsp, 0, 0, MK_SYNC_ALL) != | ||
1408 | QLA_SUCCESS) | ||
1409 | return QLA_FUNCTION_FAILED; | ||
1410 | vha->marker_needed = 0; | ||
1411 | } | ||
1412 | |||
1413 | /* Acquire ring specific lock */ | ||
1414 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1415 | |||
1416 | /* Check for room in outstanding command list. */ | ||
1417 | handle = req->current_outstanding_cmd; | ||
1418 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
1419 | handle++; | ||
1420 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
1421 | handle = 1; | ||
1422 | if (!req->outstanding_cmds[handle]) | ||
1423 | break; | ||
1424 | } | ||
1425 | |||
1426 | if (index == MAX_OUTSTANDING_COMMANDS) | ||
1427 | goto queuing_error; | ||
1428 | |||
1429 | /* Compute number of required data segments */ | ||
1430 | /* Map the sg table so we have an accurate count of sg entries needed */ | ||
1431 | if (scsi_sg_count(cmd)) { | ||
1432 | nseg = dma_map_sg(&ha->pdev->dev, scsi_sglist(cmd), | ||
1433 | scsi_sg_count(cmd), cmd->sc_data_direction); | ||
1434 | if (unlikely(!nseg)) | ||
1435 | goto queuing_error; | ||
1436 | else | ||
1437 | sp->flags |= SRB_DMA_VALID; | ||
1438 | } else | ||
1439 | nseg = 0; | ||
1440 | |||
1441 | /* number of required data segments */ | ||
1442 | tot_dsds = nseg; | ||
1443 | |||
1444 | /* Compute number of required protection segments */ | ||
1445 | if (qla24xx_configure_prot_mode(sp, &fw_prot_opts)) { | ||
1446 | nseg = dma_map_sg(&ha->pdev->dev, scsi_prot_sglist(cmd), | ||
1447 | scsi_prot_sg_count(cmd), cmd->sc_data_direction); | ||
1448 | if (unlikely(!nseg)) | ||
1449 | goto queuing_error; | ||
1450 | else | ||
1451 | sp->flags |= SRB_CRC_PROT_DMA_VALID; | ||
1452 | } else { | ||
1453 | nseg = 0; | ||
1454 | } | ||
1455 | |||
1456 | req_cnt = 1; | ||
1457 | /* Total Data and protection sg segment(s) */ | ||
1458 | tot_prot_dsds = nseg; | ||
1459 | tot_dsds += nseg; | ||
1460 | if (req->cnt < (req_cnt + 2)) { | ||
1461 | cnt = RD_REG_DWORD_RELAXED(req->req_q_out); | ||
1462 | |||
1463 | if (req->ring_index < cnt) | ||
1464 | req->cnt = cnt - req->ring_index; | ||
1465 | else | ||
1466 | req->cnt = req->length - | ||
1467 | (req->ring_index - cnt); | ||
1468 | } | ||
1469 | |||
1470 | if (req->cnt < (req_cnt + 2)) | ||
1471 | goto queuing_error; | ||
1472 | |||
1473 | status |= QDSS_GOT_Q_SPACE; | ||
1474 | |||
1475 | /* Build header part of command packet (excluding the OPCODE). */ | ||
1476 | req->current_outstanding_cmd = handle; | ||
1477 | req->outstanding_cmds[handle] = sp; | ||
1478 | sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; | ||
1479 | req->cnt -= req_cnt; | ||
1480 | |||
1481 | /* Fill-in common area */ | ||
1482 | cmd_pkt = (struct cmd_type_crc_2 *)req->ring_ptr; | ||
1483 | cmd_pkt->handle = MAKE_HANDLE(req->id, handle); | ||
1484 | |||
1485 | clr_ptr = (uint32_t *)cmd_pkt + 2; | ||
1486 | memset(clr_ptr, 0, REQUEST_ENTRY_SIZE - 8); | ||
1487 | |||
1488 | /* Set NPORT-ID and LUN number*/ | ||
1489 | cmd_pkt->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1490 | cmd_pkt->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
1491 | cmd_pkt->port_id[1] = sp->fcport->d_id.b.area; | ||
1492 | cmd_pkt->port_id[2] = sp->fcport->d_id.b.domain; | ||
1493 | |||
1494 | int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun); | ||
1495 | host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun)); | ||
1496 | |||
1497 | /* Total Data and protection segment(s) */ | ||
1498 | cmd_pkt->dseg_count = cpu_to_le16(tot_dsds); | ||
1499 | |||
1500 | /* Build IOCB segments and adjust for data protection segments */ | ||
1501 | if (qla24xx_build_scsi_crc_2_iocbs(sp, (struct cmd_type_crc_2 *) | ||
1502 | req->ring_ptr, tot_dsds, tot_prot_dsds, fw_prot_opts) != | ||
1503 | QLA_SUCCESS) | ||
1504 | goto queuing_error; | ||
1505 | |||
1506 | cmd_pkt->entry_count = (uint8_t)req_cnt; | ||
1507 | /* Specify response queue number where completion should happen */ | ||
1508 | cmd_pkt->entry_status = (uint8_t) rsp->id; | ||
1509 | cmd_pkt->timeout = __constant_cpu_to_le16(0); | ||
1510 | wmb(); | ||
1511 | |||
1512 | /* Adjust ring index. */ | ||
1513 | req->ring_index++; | ||
1514 | if (req->ring_index == req->length) { | ||
1515 | req->ring_index = 0; | ||
1516 | req->ring_ptr = req->ring; | ||
1517 | } else | ||
1518 | req->ring_ptr++; | ||
1519 | |||
1520 | /* Set chip new ring index. */ | ||
1521 | WRT_REG_DWORD(req->req_q_in, req->ring_index); | ||
1522 | RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr); | ||
1523 | |||
1524 | /* Manage unprocessed RIO/ZIO commands in response queue. */ | ||
1525 | if (vha->flags.process_response_queue && | ||
1526 | rsp->ring_ptr->signature != RESPONSE_PROCESSED) | ||
1527 | qla24xx_process_response_queue(vha, rsp); | ||
1528 | |||
1529 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1530 | |||
1531 | return QLA_SUCCESS; | ||
1532 | |||
1533 | queuing_error: | ||
1534 | if (status & QDSS_GOT_Q_SPACE) { | ||
1535 | req->outstanding_cmds[handle] = NULL; | ||
1536 | req->cnt += req_cnt; | ||
1537 | } | ||
1538 | /* Cleanup will be performed by the caller (queuecommand) */ | ||
1539 | |||
1540 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1541 | |||
1542 | DEBUG18(qla_printk(KERN_INFO, ha, | ||
1543 | "CMD sent FAILED SCSI prot_op:%02x\n", scsi_get_prot_op(cmd))); | ||
1544 | return QLA_FUNCTION_FAILED; | ||
1545 | } | ||
1546 | |||
1547 | |||
851 | static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) | 1548 | static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) |
852 | { | 1549 | { |
853 | struct scsi_cmnd *cmd = sp->cmd; | 1550 | struct scsi_cmnd *cmd = sp->cmd; |
@@ -931,37 +1628,45 @@ qla2x00_start_iocbs(srb_t *sp) | |||
931 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | 1628 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); |
932 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; | 1629 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; |
933 | 1630 | ||
934 | /* Adjust ring index. */ | 1631 | if (IS_QLA82XX(ha)) { |
935 | req->ring_index++; | 1632 | qla82xx_start_iocbs(sp); |
936 | if (req->ring_index == req->length) { | ||
937 | req->ring_index = 0; | ||
938 | req->ring_ptr = req->ring; | ||
939 | } else | ||
940 | req->ring_ptr++; | ||
941 | |||
942 | /* Set chip new ring index. */ | ||
943 | if (ha->mqenable) { | ||
944 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | ||
945 | RD_REG_DWORD(&ioreg->hccr); | ||
946 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
947 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | ||
948 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | ||
949 | } else { | 1633 | } else { |
950 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), req->ring_index); | 1634 | /* Adjust ring index. */ |
951 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | 1635 | req->ring_index++; |
1636 | if (req->ring_index == req->length) { | ||
1637 | req->ring_index = 0; | ||
1638 | req->ring_ptr = req->ring; | ||
1639 | } else | ||
1640 | req->ring_ptr++; | ||
1641 | |||
1642 | /* Set chip new ring index. */ | ||
1643 | if (ha->mqenable) { | ||
1644 | WRT_REG_DWORD(®->isp25mq.req_q_in, req->ring_index); | ||
1645 | RD_REG_DWORD(&ioreg->hccr); | ||
1646 | } else if (IS_QLA82XX(ha)) { | ||
1647 | qla82xx_start_iocbs(sp); | ||
1648 | } else if (IS_FWI2_CAPABLE(ha)) { | ||
1649 | WRT_REG_DWORD(®->isp24.req_q_in, req->ring_index); | ||
1650 | RD_REG_DWORD_RELAXED(®->isp24.req_q_in); | ||
1651 | } else { | ||
1652 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), | ||
1653 | req->ring_index); | ||
1654 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | ||
1655 | } | ||
952 | } | 1656 | } |
953 | } | 1657 | } |
954 | 1658 | ||
955 | static void | 1659 | static void |
956 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) | 1660 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) |
957 | { | 1661 | { |
958 | struct srb_logio *lio = sp->ctx; | 1662 | struct srb_ctx *ctx = sp->ctx; |
1663 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
959 | 1664 | ||
960 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | 1665 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; |
961 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); | 1666 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); |
962 | if (lio->flags & SRB_LOGIN_COND_PLOGI) | 1667 | if (lio->u.logio.flags & SRB_LOGIN_COND_PLOGI) |
963 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); | 1668 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); |
964 | if (lio->flags & SRB_LOGIN_SKIP_PRLI) | 1669 | if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI) |
965 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); | 1670 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); |
966 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | 1671 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); |
967 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | 1672 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; |
@@ -974,14 +1679,15 @@ static void | |||
974 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) | 1679 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) |
975 | { | 1680 | { |
976 | struct qla_hw_data *ha = sp->fcport->vha->hw; | 1681 | struct qla_hw_data *ha = sp->fcport->vha->hw; |
977 | struct srb_logio *lio = sp->ctx; | 1682 | struct srb_ctx *ctx = sp->ctx; |
1683 | struct srb_iocb *lio = ctx->u.iocb_cmd; | ||
978 | uint16_t opts; | 1684 | uint16_t opts; |
979 | 1685 | ||
980 | mbx->entry_type = MBX_IOCB_TYPE;; | 1686 | mbx->entry_type = MBX_IOCB_TYPE;; |
981 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | 1687 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); |
982 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); | 1688 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); |
983 | opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0; | 1689 | opts = lio->u.logio.flags & SRB_LOGIN_COND_PLOGI ? BIT_0 : 0; |
984 | opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0; | 1690 | opts |= lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI ? BIT_1 : 0; |
985 | if (HAS_EXTENDED_IDS(ha)) { | 1691 | if (HAS_EXTENDED_IDS(ha)) { |
986 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | 1692 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); |
987 | mbx->mb10 = cpu_to_le16(opts); | 1693 | mbx->mb10 = cpu_to_le16(opts); |
@@ -1026,9 +1732,97 @@ qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | |||
1026 | } | 1732 | } |
1027 | 1733 | ||
1028 | static void | 1734 | static void |
1735 | qla24xx_adisc_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
1736 | { | ||
1737 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1738 | logio->control_flags = cpu_to_le16(LCF_COMMAND_ADISC); | ||
1739 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1740 | logio->vp_index = sp->fcport->vp_idx; | ||
1741 | } | ||
1742 | |||
1743 | static void | ||
1744 | qla2x00_adisc_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
1745 | { | ||
1746 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1747 | |||
1748 | mbx->entry_type = MBX_IOCB_TYPE; | ||
1749 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
1750 | mbx->mb0 = cpu_to_le16(MBC_GET_PORT_DATABASE); | ||
1751 | if (HAS_EXTENDED_IDS(ha)) { | ||
1752 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | ||
1753 | mbx->mb10 = cpu_to_le16(BIT_0); | ||
1754 | } else { | ||
1755 | mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | BIT_0); | ||
1756 | } | ||
1757 | mbx->mb2 = cpu_to_le16(MSW(ha->async_pd_dma)); | ||
1758 | mbx->mb3 = cpu_to_le16(LSW(ha->async_pd_dma)); | ||
1759 | mbx->mb6 = cpu_to_le16(MSW(MSD(ha->async_pd_dma))); | ||
1760 | mbx->mb7 = cpu_to_le16(LSW(MSD(ha->async_pd_dma))); | ||
1761 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
1762 | } | ||
1763 | |||
1764 | static void | ||
1765 | qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) | ||
1766 | { | ||
1767 | uint32_t flags; | ||
1768 | unsigned int lun; | ||
1769 | struct fc_port *fcport = sp->fcport; | ||
1770 | scsi_qla_host_t *vha = fcport->vha; | ||
1771 | struct qla_hw_data *ha = vha->hw; | ||
1772 | struct srb_ctx *ctx = sp->ctx; | ||
1773 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | ||
1774 | struct req_que *req = vha->req; | ||
1775 | |||
1776 | flags = iocb->u.tmf.flags; | ||
1777 | lun = iocb->u.tmf.lun; | ||
1778 | |||
1779 | tsk->entry_type = TSK_MGMT_IOCB_TYPE; | ||
1780 | tsk->entry_count = 1; | ||
1781 | tsk->handle = MAKE_HANDLE(req->id, tsk->handle); | ||
1782 | tsk->nport_handle = cpu_to_le16(fcport->loop_id); | ||
1783 | tsk->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); | ||
1784 | tsk->control_flags = cpu_to_le32(flags); | ||
1785 | tsk->port_id[0] = fcport->d_id.b.al_pa; | ||
1786 | tsk->port_id[1] = fcport->d_id.b.area; | ||
1787 | tsk->port_id[2] = fcport->d_id.b.domain; | ||
1788 | tsk->vp_index = fcport->vp_idx; | ||
1789 | |||
1790 | if (flags == TCF_LUN_RESET) { | ||
1791 | int_to_scsilun(lun, &tsk->lun); | ||
1792 | host_to_fcp_swap((uint8_t *)&tsk->lun, | ||
1793 | sizeof(tsk->lun)); | ||
1794 | } | ||
1795 | } | ||
1796 | |||
1797 | static void | ||
1798 | qla24xx_marker_iocb(srb_t *sp, struct mrk_entry_24xx *mrk) | ||
1799 | { | ||
1800 | uint16_t lun; | ||
1801 | uint8_t modif; | ||
1802 | struct fc_port *fcport = sp->fcport; | ||
1803 | scsi_qla_host_t *vha = fcport->vha; | ||
1804 | struct srb_ctx *ctx = sp->ctx; | ||
1805 | struct srb_iocb *iocb = ctx->u.iocb_cmd; | ||
1806 | struct req_que *req = vha->req; | ||
1807 | |||
1808 | lun = iocb->u.marker.lun; | ||
1809 | modif = iocb->u.marker.modif; | ||
1810 | mrk->entry_type = MARKER_TYPE; | ||
1811 | mrk->modifier = modif; | ||
1812 | if (modif != MK_SYNC_ALL) { | ||
1813 | mrk->nport_handle = cpu_to_le16(fcport->loop_id); | ||
1814 | mrk->lun[1] = LSB(lun); | ||
1815 | mrk->lun[2] = MSB(lun); | ||
1816 | host_to_fcp_swap(mrk->lun, sizeof(mrk->lun)); | ||
1817 | mrk->vp_index = vha->vp_idx; | ||
1818 | mrk->handle = MAKE_HANDLE(req->id, mrk->handle); | ||
1819 | } | ||
1820 | } | ||
1821 | |||
1822 | static void | ||
1029 | qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | 1823 | qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) |
1030 | { | 1824 | { |
1031 | struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; | 1825 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; |
1032 | 1826 | ||
1033 | els_iocb->entry_type = ELS_IOCB_TYPE; | 1827 | els_iocb->entry_type = ELS_IOCB_TYPE; |
1034 | els_iocb->entry_count = 1; | 1828 | els_iocb->entry_count = 1; |
@@ -1041,8 +1835,10 @@ qla24xx_els_iocb(srb_t *sp, struct els_entry_24xx *els_iocb) | |||
1041 | els_iocb->sof_type = EST_SOFI3; | 1835 | els_iocb->sof_type = EST_SOFI3; |
1042 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); | 1836 | els_iocb->rx_dsd_count = __constant_cpu_to_le16(bsg_job->reply_payload.sg_cnt); |
1043 | 1837 | ||
1044 | els_iocb->opcode =(((struct srb_bsg*)sp->ctx)->ctx.type == SRB_ELS_CMD_RPT) ? | 1838 | els_iocb->opcode = |
1045 | bsg_job->request->rqst_data.r_els.els_code : bsg_job->request->rqst_data.h_els.command_code; | 1839 | (((struct srb_ctx *)sp->ctx)->type == SRB_ELS_CMD_RPT) ? |
1840 | bsg_job->request->rqst_data.r_els.els_code : | ||
1841 | bsg_job->request->rqst_data.h_els.command_code; | ||
1046 | els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; | 1842 | els_iocb->port_id[0] = sp->fcport->d_id.b.al_pa; |
1047 | els_iocb->port_id[1] = sp->fcport->d_id.b.area; | 1843 | els_iocb->port_id[1] = sp->fcport->d_id.b.area; |
1048 | els_iocb->port_id[2] = sp->fcport->d_id.b.domain; | 1844 | els_iocb->port_id[2] = sp->fcport->d_id.b.domain; |
@@ -1076,7 +1872,7 @@ qla24xx_ct_iocb(srb_t *sp, struct ct_entry_24xx *ct_iocb) | |||
1076 | int index; | 1872 | int index; |
1077 | uint16_t tot_dsds; | 1873 | uint16_t tot_dsds; |
1078 | scsi_qla_host_t *vha = sp->fcport->vha; | 1874 | scsi_qla_host_t *vha = sp->fcport->vha; |
1079 | struct fc_bsg_job *bsg_job = ((struct srb_bsg*)sp->ctx)->bsg_job; | 1875 | struct fc_bsg_job *bsg_job = ((struct srb_ctx *)sp->ctx)->u.bsg_job; |
1080 | int loop_iterartion = 0; | 1876 | int loop_iterartion = 0; |
1081 | int cont_iocb_prsnt = 0; | 1877 | int cont_iocb_prsnt = 0; |
1082 | int entry_count = 1; | 1878 | int entry_count = 1; |
@@ -1157,12 +1953,12 @@ qla2x00_start_sp(srb_t *sp) | |||
1157 | switch (ctx->type) { | 1953 | switch (ctx->type) { |
1158 | case SRB_LOGIN_CMD: | 1954 | case SRB_LOGIN_CMD: |
1159 | IS_FWI2_CAPABLE(ha) ? | 1955 | IS_FWI2_CAPABLE(ha) ? |
1160 | qla24xx_login_iocb(sp, pkt): | 1956 | qla24xx_login_iocb(sp, pkt) : |
1161 | qla2x00_login_iocb(sp, pkt); | 1957 | qla2x00_login_iocb(sp, pkt); |
1162 | break; | 1958 | break; |
1163 | case SRB_LOGOUT_CMD: | 1959 | case SRB_LOGOUT_CMD: |
1164 | IS_FWI2_CAPABLE(ha) ? | 1960 | IS_FWI2_CAPABLE(ha) ? |
1165 | qla24xx_logout_iocb(sp, pkt): | 1961 | qla24xx_logout_iocb(sp, pkt) : |
1166 | qla2x00_logout_iocb(sp, pkt); | 1962 | qla2x00_logout_iocb(sp, pkt); |
1167 | break; | 1963 | break; |
1168 | case SRB_ELS_CMD_RPT: | 1964 | case SRB_ELS_CMD_RPT: |
@@ -1172,6 +1968,17 @@ qla2x00_start_sp(srb_t *sp) | |||
1172 | case SRB_CT_CMD: | 1968 | case SRB_CT_CMD: |
1173 | qla24xx_ct_iocb(sp, pkt); | 1969 | qla24xx_ct_iocb(sp, pkt); |
1174 | break; | 1970 | break; |
1971 | case SRB_ADISC_CMD: | ||
1972 | IS_FWI2_CAPABLE(ha) ? | ||
1973 | qla24xx_adisc_iocb(sp, pkt) : | ||
1974 | qla2x00_adisc_iocb(sp, pkt); | ||
1975 | break; | ||
1976 | case SRB_TM_CMD: | ||
1977 | qla24xx_tm_iocb(sp, pkt); | ||
1978 | break; | ||
1979 | case SRB_MARKER_CMD: | ||
1980 | qla24xx_marker_iocb(sp, pkt); | ||
1981 | break; | ||
1175 | default: | 1982 | default: |
1176 | break; | 1983 | break; |
1177 | } | 1984 | } |