aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_iocb.c
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2009-08-20 14:06:05 -0400
committerJames Bottomley <James.Bottomley@suse.de>2009-09-05 10:41:57 -0400
commitac280b670e6d6666667aba02324e2fc50bd96ae7 (patch)
tree4d0d9187b26513ef9f820ab140f29a4f49f678b8 /drivers/scsi/qla2xxx/qla_iocb.c
parentcf53b069f52ae3f83dec1acd339e3c3a2e979478 (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.c202
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
866static void *
867qla2x00_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(&reg->isp25mq.req_q_out);
896 else if (IS_FWI2_CAPABLE(ha))
897 cnt = RD_REG_DWORD(&reg->isp24.req_q_out);
898 else
899 cnt = qla2x00_debounce_register(
900 ISP_REQ_Q_OUT(ha, &reg->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
922queuing_error:
923 return pkt;
924}
925
926static void
927qla2x00_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(&reg->isp25mq.req_q_in, req->ring_index);
945 RD_REG_DWORD(&ioreg->hccr);
946 } else if (IS_FWI2_CAPABLE(ha)) {
947 WRT_REG_DWORD(&reg->isp24.req_q_in, req->ring_index);
948 RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
949 } else {
950 WRT_REG_WORD(ISP_REQ_Q_IN(ha, &reg->isp), req->ring_index);
951 RD_REG_WORD_RELAXED(ISP_REQ_Q_IN(ha, &reg->isp));
952 }
953}
954
955static void
956qla24xx_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
973static void
974qla2x00_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
997static void
998qla24xx_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
1010static void
1011qla2x00_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
1028int
1029qla2x00_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);
1061done:
1062 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1063 return rval;
1064}