aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_iocb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_iocb.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c206
1 files changed, 205 insertions, 1 deletions
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 13396beae2ce..c5ccac0bef76 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -350,6 +350,7 @@ qla2x00_start_scsi(srb_t *sp)
350 /* Build command packet */ 350 /* Build command packet */
351 req->current_outstanding_cmd = handle; 351 req->current_outstanding_cmd = handle;
352 req->outstanding_cmds[handle] = sp; 352 req->outstanding_cmds[handle] = sp;
353 sp->handle = handle;
353 sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; 354 sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
354 req->cnt -= req_cnt; 355 req->cnt -= req_cnt;
355 356
@@ -778,6 +779,7 @@ qla24xx_start_scsi(srb_t *sp)
778 /* Build command packet. */ 779 /* Build command packet. */
779 req->current_outstanding_cmd = handle; 780 req->current_outstanding_cmd = handle;
780 req->outstanding_cmds[handle] = sp; 781 req->outstanding_cmds[handle] = sp;
782 sp->handle = handle;
781 sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle; 783 sp->cmd->host_scribble = (unsigned char *)(unsigned long)handle;
782 req->cnt -= req_cnt; 784 req->cnt -= req_cnt;
783 785
@@ -852,9 +854,211 @@ static void qla25xx_set_que(srb_t *sp, struct rsp_que **rsp)
852 struct qla_hw_data *ha = sp->fcport->vha->hw; 854 struct qla_hw_data *ha = sp->fcport->vha->hw;
853 int affinity = cmd->request->cpu; 855 int affinity = cmd->request->cpu;
854 856
855 if (ql2xmultique_tag && affinity >= 0 && 857 if (ha->flags.cpu_affinity_enabled && affinity >= 0 &&
856 affinity < ha->max_rsp_queues - 1) 858 affinity < ha->max_rsp_queues - 1)
857 *rsp = ha->rsp_q_map[affinity + 1]; 859 *rsp = ha->rsp_q_map[affinity + 1];
858 else 860 else
859 *rsp = ha->rsp_q_map[0]; 861 *rsp = ha->rsp_q_map[0];
860} 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}