diff options
author | Andrew Vasquez <andrew.vasquez@qlogic.com> | 2009-08-20 14:06:05 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-09-05 10:41:57 -0400 |
commit | ac280b670e6d6666667aba02324e2fc50bd96ae7 (patch) | |
tree | 4d0d9187b26513ef9f820ab140f29a4f49f678b8 /drivers/scsi/qla2xxx/qla_iocb.c | |
parent | cf53b069f52ae3f83dec1acd339e3c3a2e979478 (diff) |
[SCSI] qla2xxx: Add asynchronous-login support.
ISPs which support this feature include 23xx and above.
Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_iocb.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index d37554ecd313..c5ccac0bef76 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c | |||
@@ -860,3 +860,205 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp) | |||
860 | else | 860 | else |
861 | *rsp = ha->rsp_q_map[0]; | 861 | *rsp = ha->rsp_q_map[0]; |
862 | } | 862 | } |
863 | |||
864 | /* Generic Control-SRB manipulation functions. */ | ||
865 | |||
866 | static void * | ||
867 | qla2x00_alloc_iocbs(srb_t *sp) | ||
868 | { | ||
869 | scsi_qla_host_t *vha = sp->fcport->vha; | ||
870 | struct qla_hw_data *ha = vha->hw; | ||
871 | struct req_que *req = ha->req_q_map[0]; | ||
872 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | ||
873 | uint32_t index, handle; | ||
874 | request_t *pkt; | ||
875 | uint16_t cnt, req_cnt; | ||
876 | |||
877 | pkt = NULL; | ||
878 | req_cnt = 1; | ||
879 | |||
880 | /* Check for room in outstanding command list. */ | ||
881 | handle = req->current_outstanding_cmd; | ||
882 | for (index = 1; index < MAX_OUTSTANDING_COMMANDS; index++) { | ||
883 | handle++; | ||
884 | if (handle == MAX_OUTSTANDING_COMMANDS) | ||
885 | handle = 1; | ||
886 | if (!req->outstanding_cmds[handle]) | ||
887 | break; | ||
888 | } | ||
889 | if (index == MAX_OUTSTANDING_COMMANDS) | ||
890 | goto queuing_error; | ||
891 | |||
892 | /* Check for room on request queue. */ | ||
893 | if (req->cnt < req_cnt) { | ||
894 | if (ha->mqenable) | ||
895 | cnt = RD_REG_DWORD(®->isp25mq.req_q_out); | ||
896 | else if (IS_FWI2_CAPABLE(ha)) | ||
897 | cnt = RD_REG_DWORD(®->isp24.req_q_out); | ||
898 | else | ||
899 | cnt = qla2x00_debounce_register( | ||
900 | ISP_REQ_Q_OUT(ha, ®->isp)); | ||
901 | |||
902 | if (req->ring_index < cnt) | ||
903 | req->cnt = cnt - req->ring_index; | ||
904 | else | ||
905 | req->cnt = req->length - | ||
906 | (req->ring_index - cnt); | ||
907 | } | ||
908 | if (req->cnt < req_cnt) | ||
909 | goto queuing_error; | ||
910 | |||
911 | /* Prep packet */ | ||
912 | req->current_outstanding_cmd = handle; | ||
913 | req->outstanding_cmds[handle] = sp; | ||
914 | req->cnt -= req_cnt; | ||
915 | |||
916 | pkt = req->ring_ptr; | ||
917 | memset(pkt, 0, REQUEST_ENTRY_SIZE); | ||
918 | pkt->entry_count = req_cnt; | ||
919 | pkt->handle = handle; | ||
920 | sp->handle = handle; | ||
921 | |||
922 | queuing_error: | ||
923 | return pkt; | ||
924 | } | ||
925 | |||
926 | static void | ||
927 | qla2x00_start_iocbs(srb_t *sp) | ||
928 | { | ||
929 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
930 | struct req_que *req = ha->req_q_map[0]; | ||
931 | device_reg_t __iomem *reg = ISP_QUE_REG(ha, req->id); | ||
932 | struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp; | ||
933 | |||
934 | /* Adjust ring index. */ | ||
935 | req->ring_index++; | ||
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 { | ||
950 | WRT_REG_WORD(ISP_REQ_Q_IN(ha, ®->isp), req->ring_index); | ||
951 | RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, ®->isp)); | ||
952 | } | ||
953 | } | ||
954 | |||
955 | static void | ||
956 | qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
957 | { | ||
958 | struct srb_logio *lio = sp->ctx; | ||
959 | |||
960 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
961 | logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI); | ||
962 | if (lio->flags & SRB_LOGIN_COND_PLOGI) | ||
963 | logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI); | ||
964 | if (lio->flags & SRB_LOGIN_SKIP_PRLI) | ||
965 | logio->control_flags |= cpu_to_le16(LCF_SKIP_PRLI); | ||
966 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
967 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
968 | logio->port_id[1] = sp->fcport->d_id.b.area; | ||
969 | logio->port_id[2] = sp->fcport->d_id.b.domain; | ||
970 | logio->vp_index = sp->fcport->vp_idx; | ||
971 | } | ||
972 | |||
973 | static void | ||
974 | qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
975 | { | ||
976 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
977 | struct srb_logio *lio = sp->ctx; | ||
978 | uint16_t opts; | ||
979 | |||
980 | mbx->entry_type = MBX_IOCB_TYPE;; | ||
981 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
982 | mbx->mb0 = cpu_to_le16(MBC_LOGIN_FABRIC_PORT); | ||
983 | opts = lio->flags & SRB_LOGIN_COND_PLOGI ? BIT_0: 0; | ||
984 | opts |= lio->flags & SRB_LOGIN_SKIP_PRLI ? BIT_1: 0; | ||
985 | if (HAS_EXTENDED_IDS(ha)) { | ||
986 | mbx->mb1 = cpu_to_le16(sp->fcport->loop_id); | ||
987 | mbx->mb10 = cpu_to_le16(opts); | ||
988 | } else { | ||
989 | mbx->mb1 = cpu_to_le16((sp->fcport->loop_id << 8) | opts); | ||
990 | } | ||
991 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | ||
992 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | ||
993 | sp->fcport->d_id.b.al_pa); | ||
994 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
995 | } | ||
996 | |||
997 | static void | ||
998 | qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio) | ||
999 | { | ||
1000 | logio->entry_type = LOGINOUT_PORT_IOCB_TYPE; | ||
1001 | logio->control_flags = | ||
1002 | cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO); | ||
1003 | logio->nport_handle = cpu_to_le16(sp->fcport->loop_id); | ||
1004 | logio->port_id[0] = sp->fcport->d_id.b.al_pa; | ||
1005 | logio->port_id[1] = sp->fcport->d_id.b.area; | ||
1006 | logio->port_id[2] = sp->fcport->d_id.b.domain; | ||
1007 | logio->vp_index = sp->fcport->vp_idx; | ||
1008 | } | ||
1009 | |||
1010 | static void | ||
1011 | qla2x00_logout_iocb(srb_t *sp, struct mbx_entry *mbx) | ||
1012 | { | ||
1013 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1014 | |||
1015 | mbx->entry_type = MBX_IOCB_TYPE;; | ||
1016 | SET_TARGET_ID(ha, mbx->loop_id, sp->fcport->loop_id); | ||
1017 | mbx->mb0 = cpu_to_le16(MBC_LOGOUT_FABRIC_PORT); | ||
1018 | mbx->mb1 = HAS_EXTENDED_IDS(ha) ? | ||
1019 | cpu_to_le16(sp->fcport->loop_id): | ||
1020 | cpu_to_le16(sp->fcport->loop_id << 8); | ||
1021 | mbx->mb2 = cpu_to_le16(sp->fcport->d_id.b.domain); | ||
1022 | mbx->mb3 = cpu_to_le16(sp->fcport->d_id.b.area << 8 | | ||
1023 | sp->fcport->d_id.b.al_pa); | ||
1024 | mbx->mb9 = cpu_to_le16(sp->fcport->vp_idx); | ||
1025 | /* Implicit: mbx->mbx10 = 0. */ | ||
1026 | } | ||
1027 | |||
1028 | int | ||
1029 | qla2x00_start_sp(srb_t *sp) | ||
1030 | { | ||
1031 | int rval; | ||
1032 | struct qla_hw_data *ha = sp->fcport->vha->hw; | ||
1033 | void *pkt; | ||
1034 | struct srb_ctx *ctx = sp->ctx; | ||
1035 | unsigned long flags; | ||
1036 | |||
1037 | rval = QLA_FUNCTION_FAILED; | ||
1038 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
1039 | pkt = qla2x00_alloc_iocbs(sp); | ||
1040 | if (!pkt) | ||
1041 | goto done; | ||
1042 | |||
1043 | rval = QLA_SUCCESS; | ||
1044 | switch (ctx->type) { | ||
1045 | case SRB_LOGIN_CMD: | ||
1046 | IS_FWI2_CAPABLE(ha) ? | ||
1047 | qla24xx_login_iocb(sp, pkt): | ||
1048 | qla2x00_login_iocb(sp, pkt); | ||
1049 | break; | ||
1050 | case SRB_LOGOUT_CMD: | ||
1051 | IS_FWI2_CAPABLE(ha) ? | ||
1052 | qla24xx_logout_iocb(sp, pkt): | ||
1053 | qla2x00_logout_iocb(sp, pkt); | ||
1054 | break; | ||
1055 | default: | ||
1056 | break; | ||
1057 | } | ||
1058 | |||
1059 | wmb(); | ||
1060 | qla2x00_start_iocbs(sp); | ||
1061 | done: | ||
1062 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
1063 | return rval; | ||
1064 | } | ||