aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla2xxx/qla_bsg.c
diff options
context:
space:
mode:
authorSarang Radke <sarang.radke@qlogic.com>2010-03-19 20:03:59 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-04-11 10:45:50 -0400
commit09ff701a177b116c6c15b6e501e58fbfb306b424 (patch)
treefd99933ea29dbc36fc6636f5278d237dbee89b96 /drivers/scsi/qla2xxx/qla_bsg.c
parent6e98016ca077c5c751167bfdb1a3a2a3bee581cf (diff)
[SCSI] qla2xxx: Add APEX support.
Allows priority setting for FCP_CMNDs. 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_bsg.c')
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index c20292fde720..3c3a86ca6cbd 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -35,6 +35,166 @@ done:
35 return sp; 35 return sp;
36} 36}
37 37
38int
39qla24xx_fcp_prio_cfg_valid(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
40{
41 int i, ret, num_valid;
42 uint8_t *bcode;
43 struct qla_fcp_prio_entry *pri_entry;
44
45 ret = 1;
46 num_valid = 0;
47 bcode = (uint8_t *)pri_cfg;
48
49 if (bcode[0x0] != 'H' || bcode[0x1] != 'Q' || bcode[0x2] != 'O' ||
50 bcode[0x3] != 'S') {
51 return 0;
52 }
53 if (flag != 1)
54 return ret;
55
56 pri_entry = &pri_cfg->entry[0];
57 for (i = 0; i < pri_cfg->num_entries; i++) {
58 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
59 num_valid++;
60 pri_entry++;
61 }
62
63 if (num_valid == 0)
64 ret = 0;
65
66 return ret;
67}
68
69static int
70qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
71{
72 struct Scsi_Host *host = bsg_job->shost;
73 scsi_qla_host_t *vha = shost_priv(host);
74 struct qla_hw_data *ha = vha->hw;
75 int ret = 0;
76 uint32_t len;
77 uint32_t oper;
78
79 bsg_job->reply->reply_payload_rcv_len = 0;
80
81 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
82 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
83 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
84 ret = -EBUSY;
85 goto exit_fcp_prio_cfg;
86 }
87
88 /* Get the sub command */
89 oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
90
91 /* Only set config is allowed if config memory is not allocated */
92 if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
93 ret = -EINVAL;
94 goto exit_fcp_prio_cfg;
95 }
96 switch (oper) {
97 case QLFC_FCP_PRIO_DISABLE:
98 if (ha->flags.fcp_prio_enabled) {
99 ha->flags.fcp_prio_enabled = 0;
100 ha->fcp_prio_cfg->attributes &=
101 ~FCP_PRIO_ATTR_ENABLE;
102 qla24xx_update_all_fcp_prio(vha);
103 bsg_job->reply->result = DID_OK;
104 } else {
105 ret = -EINVAL;
106 bsg_job->reply->result = (DID_ERROR << 16);
107 goto exit_fcp_prio_cfg;
108 }
109 break;
110
111 case QLFC_FCP_PRIO_ENABLE:
112 if (!ha->flags.fcp_prio_enabled) {
113 if (ha->fcp_prio_cfg) {
114 ha->flags.fcp_prio_enabled = 1;
115 ha->fcp_prio_cfg->attributes |=
116 FCP_PRIO_ATTR_ENABLE;
117 qla24xx_update_all_fcp_prio(vha);
118 bsg_job->reply->result = DID_OK;
119 } else {
120 ret = -EINVAL;
121 bsg_job->reply->result = (DID_ERROR << 16);
122 goto exit_fcp_prio_cfg;
123 }
124 }
125 break;
126
127 case QLFC_FCP_PRIO_GET_CONFIG:
128 len = bsg_job->reply_payload.payload_len;
129 if (!len || len > FCP_PRIO_CFG_SIZE) {
130 ret = -EINVAL;
131 bsg_job->reply->result = (DID_ERROR << 16);
132 goto exit_fcp_prio_cfg;
133 }
134
135 bsg_job->reply->result = DID_OK;
136 bsg_job->reply->reply_payload_rcv_len =
137 sg_copy_from_buffer(
138 bsg_job->reply_payload.sg_list,
139 bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
140 len);
141
142 break;
143
144 case QLFC_FCP_PRIO_SET_CONFIG:
145 len = bsg_job->request_payload.payload_len;
146 if (!len || len > FCP_PRIO_CFG_SIZE) {
147 bsg_job->reply->result = (DID_ERROR << 16);
148 ret = -EINVAL;
149 goto exit_fcp_prio_cfg;
150 }
151
152 if (!ha->fcp_prio_cfg) {
153 ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
154 if (!ha->fcp_prio_cfg) {
155 qla_printk(KERN_WARNING, ha,
156 "Unable to allocate memory "
157 "for fcp prio config data (%x).\n",
158 FCP_PRIO_CFG_SIZE);
159 bsg_job->reply->result = (DID_ERROR << 16);
160 ret = -ENOMEM;
161 goto exit_fcp_prio_cfg;
162 }
163 }
164
165 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
166 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
167 bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
168 FCP_PRIO_CFG_SIZE);
169
170 /* validate fcp priority data */
171 if (!qla24xx_fcp_prio_cfg_valid(
172 (struct qla_fcp_prio_cfg *)
173 ha->fcp_prio_cfg, 1)) {
174 bsg_job->reply->result = (DID_ERROR << 16);
175 ret = -EINVAL;
176 /* If buffer was invalidatic int
177 * fcp_prio_cfg is of no use
178 */
179 vfree(ha->fcp_prio_cfg);
180 ha->fcp_prio_cfg = NULL;
181 goto exit_fcp_prio_cfg;
182 }
183
184 ha->flags.fcp_prio_enabled = 0;
185 if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
186 ha->flags.fcp_prio_enabled = 1;
187 qla24xx_update_all_fcp_prio(vha);
188 bsg_job->reply->result = DID_OK;
189 break;
190 default:
191 ret = -EINVAL;
192 break;
193 }
194exit_fcp_prio_cfg:
195 bsg_job->job_done(bsg_job);
196 return ret;
197}
38static int 198static int
39qla2x00_process_els(struct fc_bsg_job *bsg_job) 199qla2x00_process_els(struct fc_bsg_job *bsg_job)
40{ 200{
@@ -948,6 +1108,9 @@ qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
948 case QL_VND_IIDMA: 1108 case QL_VND_IIDMA:
949 return qla24xx_iidma(bsg_job); 1109 return qla24xx_iidma(bsg_job);
950 1110
1111 case QL_VND_FCP_PRIO_CFG_CMD:
1112 return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
1113
951 default: 1114 default:
952 bsg_job->reply->result = (DID_ERROR << 16); 1115 bsg_job->reply->result = (DID_ERROR << 16);
953 bsg_job->job_done(bsg_job); 1116 bsg_job->job_done(bsg_job);