]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/scsi/qla2xxx/qla_bsg.c
Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
[net-next-2.6.git] / drivers / scsi / qla2xxx / qla_bsg.c
CommitLineData
6e98016c
GM
1/*
2 * QLogic Fibre Channel HBA Driver
de7c5d05 3 * Copyright (c) 2003-2010 QLogic Corporation
6e98016c
GM
4 *
5 * See LICENSE.qla2xxx for copyright and licensing details.
6 */
7#include "qla_def.h"
8
9#include <linux/kthread.h>
10#include <linux/vmalloc.h>
11#include <linux/delay.h>
12
13/* BSG support for ELS/CT pass through */
14inline srb_t *
15qla2x00_get_ctx_bsg_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size)
16{
17 srb_t *sp;
18 struct qla_hw_data *ha = vha->hw;
4916392b 19 struct srb_ctx *ctx;
6e98016c
GM
20
21 sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
22 if (!sp)
23 goto done;
24 ctx = kzalloc(size, GFP_KERNEL);
25 if (!ctx) {
26 mempool_free(sp, ha->srb_mempool);
27 sp = NULL;
28 goto done;
29 }
30
31 memset(sp, 0, sizeof(*sp));
32 sp->fcport = fcport;
33 sp->ctx = ctx;
34done:
35 return sp;
36}
37
09ff701a
SR
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;
2f0f3f4f 44 uint32_t *bcode_val_ptr, bcode_val;
09ff701a
SR
45
46 ret = 1;
47 num_valid = 0;
48 bcode = (uint8_t *)pri_cfg;
2f0f3f4f
MI
49 bcode_val_ptr = (uint32_t *)pri_cfg;
50 bcode_val = (uint32_t)(*bcode_val_ptr);
09ff701a 51
2f0f3f4f
MI
52 if (bcode_val == 0xFFFFFFFF) {
53 /* No FCP Priority config data in flash */
54 DEBUG2(printk(KERN_INFO
55 "%s: No FCP priority config data.\n",
56 __func__));
57 return 0;
58 }
59
60 if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' ||
61 bcode[3] != 'S') {
62 /* Invalid FCP priority data header*/
63 DEBUG2(printk(KERN_ERR
64 "%s: Invalid FCP Priority data header. bcode=0x%x\n",
65 __func__, bcode_val));
09ff701a
SR
66 return 0;
67 }
68 if (flag != 1)
69 return ret;
70
71 pri_entry = &pri_cfg->entry[0];
72 for (i = 0; i < pri_cfg->num_entries; i++) {
73 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
74 num_valid++;
75 pri_entry++;
76 }
77
2f0f3f4f
MI
78 if (num_valid == 0) {
79 /* No valid FCP priority data entries */
80 DEBUG2(printk(KERN_ERR
81 "%s: No valid FCP Priority data entries.\n",
82 __func__));
09ff701a 83 ret = 0;
2f0f3f4f
MI
84 } else {
85 /* FCP priority data is valid */
86 DEBUG2(printk(KERN_INFO
87 "%s: Valid FCP priority data. num entries = %d\n",
88 __func__, num_valid));
89 }
09ff701a
SR
90
91 return ret;
92}
93
94static int
95qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
96{
97 struct Scsi_Host *host = bsg_job->shost;
98 scsi_qla_host_t *vha = shost_priv(host);
99 struct qla_hw_data *ha = vha->hw;
100 int ret = 0;
101 uint32_t len;
102 uint32_t oper;
103
104 bsg_job->reply->reply_payload_rcv_len = 0;
105
2f0f3f4f
MI
106 if (!IS_QLA24XX_TYPE(ha) || !IS_QLA25XX(ha)) {
107 ret = -EINVAL;
108 goto exit_fcp_prio_cfg;
109 }
110
09ff701a
SR
111 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
112 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
113 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
114 ret = -EBUSY;
115 goto exit_fcp_prio_cfg;
116 }
117
118 /* Get the sub command */
119 oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
120
121 /* Only set config is allowed if config memory is not allocated */
122 if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
123 ret = -EINVAL;
124 goto exit_fcp_prio_cfg;
125 }
126 switch (oper) {
127 case QLFC_FCP_PRIO_DISABLE:
128 if (ha->flags.fcp_prio_enabled) {
129 ha->flags.fcp_prio_enabled = 0;
130 ha->fcp_prio_cfg->attributes &=
131 ~FCP_PRIO_ATTR_ENABLE;
132 qla24xx_update_all_fcp_prio(vha);
133 bsg_job->reply->result = DID_OK;
134 } else {
135 ret = -EINVAL;
136 bsg_job->reply->result = (DID_ERROR << 16);
137 goto exit_fcp_prio_cfg;
138 }
139 break;
140
141 case QLFC_FCP_PRIO_ENABLE:
142 if (!ha->flags.fcp_prio_enabled) {
143 if (ha->fcp_prio_cfg) {
144 ha->flags.fcp_prio_enabled = 1;
145 ha->fcp_prio_cfg->attributes |=
146 FCP_PRIO_ATTR_ENABLE;
147 qla24xx_update_all_fcp_prio(vha);
148 bsg_job->reply->result = DID_OK;
149 } else {
150 ret = -EINVAL;
151 bsg_job->reply->result = (DID_ERROR << 16);
152 goto exit_fcp_prio_cfg;
153 }
154 }
155 break;
156
157 case QLFC_FCP_PRIO_GET_CONFIG:
158 len = bsg_job->reply_payload.payload_len;
159 if (!len || len > FCP_PRIO_CFG_SIZE) {
160 ret = -EINVAL;
161 bsg_job->reply->result = (DID_ERROR << 16);
162 goto exit_fcp_prio_cfg;
163 }
164
165 bsg_job->reply->result = DID_OK;
166 bsg_job->reply->reply_payload_rcv_len =
167 sg_copy_from_buffer(
168 bsg_job->reply_payload.sg_list,
169 bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
170 len);
171
172 break;
173
174 case QLFC_FCP_PRIO_SET_CONFIG:
175 len = bsg_job->request_payload.payload_len;
176 if (!len || len > FCP_PRIO_CFG_SIZE) {
177 bsg_job->reply->result = (DID_ERROR << 16);
178 ret = -EINVAL;
179 goto exit_fcp_prio_cfg;
180 }
181
182 if (!ha->fcp_prio_cfg) {
183 ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
184 if (!ha->fcp_prio_cfg) {
185 qla_printk(KERN_WARNING, ha,
186 "Unable to allocate memory "
187 "for fcp prio config data (%x).\n",
188 FCP_PRIO_CFG_SIZE);
189 bsg_job->reply->result = (DID_ERROR << 16);
190 ret = -ENOMEM;
191 goto exit_fcp_prio_cfg;
192 }
193 }
194
195 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
196 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
197 bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
198 FCP_PRIO_CFG_SIZE);
199
200 /* validate fcp priority data */
201 if (!qla24xx_fcp_prio_cfg_valid(
202 (struct qla_fcp_prio_cfg *)
203 ha->fcp_prio_cfg, 1)) {
204 bsg_job->reply->result = (DID_ERROR << 16);
205 ret = -EINVAL;
206 /* If buffer was invalidatic int
207 * fcp_prio_cfg is of no use
208 */
209 vfree(ha->fcp_prio_cfg);
210 ha->fcp_prio_cfg = NULL;
211 goto exit_fcp_prio_cfg;
212 }
213
214 ha->flags.fcp_prio_enabled = 0;
215 if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
216 ha->flags.fcp_prio_enabled = 1;
217 qla24xx_update_all_fcp_prio(vha);
218 bsg_job->reply->result = DID_OK;
219 break;
220 default:
221 ret = -EINVAL;
222 break;
223 }
224exit_fcp_prio_cfg:
225 bsg_job->job_done(bsg_job);
226 return ret;
227}
6e98016c
GM
228static int
229qla2x00_process_els(struct fc_bsg_job *bsg_job)
230{
231 struct fc_rport *rport;
08f71e09 232 fc_port_t *fcport = NULL;
6e98016c
GM
233 struct Scsi_Host *host;
234 scsi_qla_host_t *vha;
235 struct qla_hw_data *ha;
236 srb_t *sp;
237 const char *type;
238 int req_sg_cnt, rsp_sg_cnt;
239 int rval = (DRIVER_ERROR << 16);
240 uint16_t nextlid = 0;
4916392b 241 struct srb_ctx *els;
6e98016c 242
08f71e09
HZ
243 if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
244 rport = bsg_job->rport;
245 fcport = *(fc_port_t **) rport->dd_data;
246 host = rport_to_shost(rport);
247 vha = shost_priv(host);
248 ha = vha->hw;
249 type = "FC_BSG_RPT_ELS";
250 } else {
251 host = bsg_job->shost;
252 vha = shost_priv(host);
253 ha = vha->hw;
254 type = "FC_BSG_HST_ELS_NOLOGIN";
255 }
256
257 /* pass through is supported only for ISP 4Gb or higher */
258 if (!IS_FWI2_CAPABLE(ha)) {
259 DEBUG2(qla_printk(KERN_INFO, ha,
260 "scsi(%ld):ELS passthru not supported for ISP23xx based "
261 "adapters\n", vha->host_no));
262 rval = -EPERM;
263 goto done;
264 }
265
6e98016c
GM
266 /* Multiple SG's are not supported for ELS requests */
267 if (bsg_job->request_payload.sg_cnt > 1 ||
268 bsg_job->reply_payload.sg_cnt > 1) {
269 DEBUG2(printk(KERN_INFO
270 "multiple SG's are not supported for ELS requests"
271 " [request_sg_cnt: %x reply_sg_cnt: %x]\n",
272 bsg_job->request_payload.sg_cnt,
273 bsg_job->reply_payload.sg_cnt));
274 rval = -EPERM;
275 goto done;
276 }
277
278 /* ELS request for rport */
279 if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
6e98016c
GM
280 /* make sure the rport is logged in,
281 * if not perform fabric login
282 */
283 if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
284 DEBUG2(qla_printk(KERN_WARNING, ha,
285 "failed to login port %06X for ELS passthru\n",
286 fcport->d_id.b24));
287 rval = -EIO;
288 goto done;
289 }
290 } else {
6e98016c
GM
291 /* Allocate a dummy fcport structure, since functions
292 * preparing the IOCB and mailbox command retrieves port
293 * specific information from fcport structure. For Host based
294 * ELS commands there will be no fcport structure allocated
295 */
296 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
297 if (!fcport) {
298 rval = -ENOMEM;
299 goto done;
300 }
301
302 /* Initialize all required fields of fcport */
303 fcport->vha = vha;
304 fcport->vp_idx = vha->vp_idx;
305 fcport->d_id.b.al_pa =
306 bsg_job->request->rqst_data.h_els.port_id[0];
307 fcport->d_id.b.area =
308 bsg_job->request->rqst_data.h_els.port_id[1];
309 fcport->d_id.b.domain =
310 bsg_job->request->rqst_data.h_els.port_id[2];
311 fcport->loop_id =
312 (fcport->d_id.b.al_pa == 0xFD) ?
313 NPH_FABRIC_CONTROLLER : NPH_F_PORT;
314 }
315
316 if (!vha->flags.online) {
317 DEBUG2(qla_printk(KERN_WARNING, ha,
6c452a45 318 "host not online\n"));
6e98016c
GM
319 rval = -EIO;
320 goto done;
321 }
322
323 req_sg_cnt =
324 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
325 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
326 if (!req_sg_cnt) {
327 rval = -ENOMEM;
328 goto done_free_fcport;
329 }
6c452a45
AV
330
331 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
332 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
6e98016c
GM
333 if (!rsp_sg_cnt) {
334 rval = -ENOMEM;
335 goto done_free_fcport;
336 }
337
338 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
6c452a45 339 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
6e98016c
GM
340 DEBUG2(printk(KERN_INFO
341 "dma mapping resulted in different sg counts \
342 [request_sg_cnt: %x dma_request_sg_cnt: %x\
343 reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
344 bsg_job->request_payload.sg_cnt, req_sg_cnt,
345 bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
346 rval = -EAGAIN;
347 goto done_unmap_sg;
348 }
349
350 /* Alloc SRB structure */
4916392b 351 sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
6e98016c
GM
352 if (!sp) {
353 rval = -ENOMEM;
6c452a45 354 goto done_unmap_sg;
6e98016c
GM
355 }
356
357 els = sp->ctx;
4916392b 358 els->type =
6e98016c
GM
359 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
360 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
3822263e
MI
361 els->name =
362 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
363 "bsg_els_rpt" : "bsg_els_hst");
4916392b 364 els->u.bsg_job = bsg_job;
6e98016c
GM
365
366 DEBUG2(qla_printk(KERN_INFO, ha,
367 "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
368 "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
369 bsg_job->request->rqst_data.h_els.command_code,
370 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
371 fcport->d_id.b.al_pa));
372
373 rval = qla2x00_start_sp(sp);
374 if (rval != QLA_SUCCESS) {
375 kfree(sp->ctx);
376 mempool_free(sp, ha->srb_mempool);
377 rval = -EIO;
378 goto done_unmap_sg;
379 }
380 return rval;
381
382done_unmap_sg:
383 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
384 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
385 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
386 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
387 goto done_free_fcport;
388
389done_free_fcport:
390 if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
391 kfree(fcport);
392done:
393 return rval;
394}
395
396static int
397qla2x00_process_ct(struct fc_bsg_job *bsg_job)
398{
399 srb_t *sp;
400 struct Scsi_Host *host = bsg_job->shost;
401 scsi_qla_host_t *vha = shost_priv(host);
402 struct qla_hw_data *ha = vha->hw;
403 int rval = (DRIVER_ERROR << 16);
404 int req_sg_cnt, rsp_sg_cnt;
405 uint16_t loop_id;
406 struct fc_port *fcport;
407 char *type = "FC_BSG_HST_CT";
4916392b 408 struct srb_ctx *ct;
6e98016c 409
6e98016c
GM
410 req_sg_cnt =
411 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
412 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
6c452a45 413 if (!req_sg_cnt) {
6e98016c
GM
414 rval = -ENOMEM;
415 goto done;
416 }
417
418 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
419 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
420 if (!rsp_sg_cnt) {
421 rval = -ENOMEM;
422 goto done;
423 }
424
425 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
6c452a45 426 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
6e98016c 427 DEBUG2(qla_printk(KERN_WARNING, ha,
6c452a45
AV
428 "[request_sg_cnt: %x dma_request_sg_cnt: %x\
429 reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
430 bsg_job->request_payload.sg_cnt, req_sg_cnt,
431 bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
6e98016c 432 rval = -EAGAIN;
6c452a45 433 goto done_unmap_sg;
6e98016c
GM
434 }
435
436 if (!vha->flags.online) {
437 DEBUG2(qla_printk(KERN_WARNING, ha,
438 "host not online\n"));
439 rval = -EIO;
440 goto done_unmap_sg;
441 }
442
443 loop_id =
444 (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
445 >> 24;
446 switch (loop_id) {
6c452a45
AV
447 case 0xFC:
448 loop_id = cpu_to_le16(NPH_SNS);
449 break;
450 case 0xFA:
451 loop_id = vha->mgmt_svr_loop_id;
452 break;
453 default:
454 DEBUG2(qla_printk(KERN_INFO, ha,
455 "Unknown loop id: %x\n", loop_id));
456 rval = -EINVAL;
457 goto done_unmap_sg;
6e98016c
GM
458 }
459
460 /* Allocate a dummy fcport structure, since functions preparing the
461 * IOCB and mailbox command retrieves port specific information
462 * from fcport structure. For Host based ELS commands there will be
463 * no fcport structure allocated
464 */
465 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
6c452a45 466 if (!fcport) {
6e98016c 467 rval = -ENOMEM;
6c452a45 468 goto done_unmap_sg;
6e98016c
GM
469 }
470
471 /* Initialize all required fields of fcport */
472 fcport->vha = vha;
473 fcport->vp_idx = vha->vp_idx;
474 fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0];
475 fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1];
476 fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2];
477 fcport->loop_id = loop_id;
478
479 /* Alloc SRB structure */
4916392b 480 sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
6e98016c
GM
481 if (!sp) {
482 rval = -ENOMEM;
483 goto done_free_fcport;
484 }
485
486 ct = sp->ctx;
4916392b 487 ct->type = SRB_CT_CMD;
3822263e 488 ct->name = "bsg_ct";
4916392b 489 ct->u.bsg_job = bsg_job;
6e98016c
GM
490
491 DEBUG2(qla_printk(KERN_INFO, ha,
492 "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
493 "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
494 (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
495 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
496 fcport->d_id.b.al_pa));
497
498 rval = qla2x00_start_sp(sp);
499 if (rval != QLA_SUCCESS) {
500 kfree(sp->ctx);
501 mempool_free(sp, ha->srb_mempool);
502 rval = -EIO;
503 goto done_free_fcport;
504 }
505 return rval;
506
507done_free_fcport:
508 kfree(fcport);
509done_unmap_sg:
510 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
511 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
512 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
513 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
514done:
515 return rval;
516}
517
23f2ebd1
SR
518/* Set the port configuration to enable the
519 * internal loopback on ISP81XX
520 */
521static inline int
522qla81xx_set_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
523 uint16_t *new_config)
524{
525 int ret = 0;
526 int rval = 0;
527 struct qla_hw_data *ha = vha->hw;
528
529 if (!IS_QLA81XX(ha))
530 goto done_set_internal;
531
532 new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
533 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
534
535 ha->notify_dcbx_comp = 1;
536 ret = qla81xx_set_port_config(vha, new_config);
537 if (ret != QLA_SUCCESS) {
538 DEBUG2(printk(KERN_ERR
539 "%s(%lu): Set port config failed\n",
540 __func__, vha->host_no));
541 ha->notify_dcbx_comp = 0;
542 rval = -EINVAL;
543 goto done_set_internal;
544 }
545
546 /* Wait for DCBX complete event */
547 if (!wait_for_completion_timeout(&ha->dcbx_comp, (20 * HZ))) {
548 DEBUG2(qla_printk(KERN_WARNING, ha,
549 "State change notificaition not received.\n"));
550 } else
551 DEBUG2(qla_printk(KERN_INFO, ha,
552 "State change RECEIVED\n"));
553
554 ha->notify_dcbx_comp = 0;
555
556done_set_internal:
557 return rval;
558}
559
560/* Set the port configuration to disable the
561 * internal loopback on ISP81XX
562 */
563static inline int
564qla81xx_reset_internal_loopback(scsi_qla_host_t *vha, uint16_t *config,
565 int wait)
566{
567 int ret = 0;
568 int rval = 0;
569 uint16_t new_config[4];
570 struct qla_hw_data *ha = vha->hw;
571
572 if (!IS_QLA81XX(ha))
573 goto done_reset_internal;
574
575 memset(new_config, 0 , sizeof(new_config));
576 if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
577 ENABLE_INTERNAL_LOOPBACK) {
578 new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
579 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
580
581 ha->notify_dcbx_comp = wait;
582 ret = qla81xx_set_port_config(vha, new_config);
583 if (ret != QLA_SUCCESS) {
584 DEBUG2(printk(KERN_ERR
585 "%s(%lu): Set port config failed\n",
586 __func__, vha->host_no));
587 ha->notify_dcbx_comp = 0;
588 rval = -EINVAL;
589 goto done_reset_internal;
590 }
591
592 /* Wait for DCBX complete event */
593 if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
594 (20 * HZ))) {
595 DEBUG2(qla_printk(KERN_WARNING, ha,
596 "State change notificaition not received.\n"));
597 ha->notify_dcbx_comp = 0;
598 rval = -EINVAL;
599 goto done_reset_internal;
600 } else
601 DEBUG2(qla_printk(KERN_INFO, ha,
602 "State change RECEIVED\n"));
603
604 ha->notify_dcbx_comp = 0;
605 }
606done_reset_internal:
607 return rval;
608}
609
6e98016c
GM
610static int
611qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
612{
613 struct Scsi_Host *host = bsg_job->shost;
614 scsi_qla_host_t *vha = shost_priv(host);
615 struct qla_hw_data *ha = vha->hw;
616 int rval;
617 uint8_t command_sent;
618 char *type;
619 struct msg_echo_lb elreq;
620 uint16_t response[MAILBOX_REGISTER_COUNT];
23f2ebd1 621 uint16_t config[4], new_config[4];
6c452a45 622 uint8_t *fw_sts_ptr;
6e98016c
GM
623 uint8_t *req_data = NULL;
624 dma_addr_t req_data_dma;
625 uint32_t req_data_len;
626 uint8_t *rsp_data = NULL;
627 dma_addr_t rsp_data_dma;
628 uint32_t rsp_data_len;
629
630 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
631 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
632 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
633 return -EBUSY;
634
635 if (!vha->flags.online) {
636 DEBUG2(qla_printk(KERN_WARNING, ha, "host not online\n"));
637 return -EIO;
638 }
639
640 elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
641 bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
642 DMA_TO_DEVICE);
643
644 if (!elreq.req_sg_cnt)
645 return -ENOMEM;
646
647 elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
648 bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
649 DMA_FROM_DEVICE);
650
651 if (!elreq.rsp_sg_cnt) {
652 rval = -ENOMEM;
653 goto done_unmap_req_sg;
6c452a45 654 }
6e98016c
GM
655
656 if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
657 (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
658 DEBUG2(printk(KERN_INFO
659 "dma mapping resulted in different sg counts "
660 "[request_sg_cnt: %x dma_request_sg_cnt: %x "
661 "reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
662 bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
663 bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt));
664 rval = -EAGAIN;
665 goto done_unmap_sg;
666 }
667 req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
668 req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
669 &req_data_dma, GFP_KERNEL);
670 if (!req_data) {
671 DEBUG2(printk(KERN_ERR "%s: dma alloc for req_data "
672 "failed for host=%lu\n", __func__, vha->host_no));
673 rval = -ENOMEM;
674 goto done_unmap_sg;
675 }
676
677 rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
678 &rsp_data_dma, GFP_KERNEL);
679 if (!rsp_data) {
680 DEBUG2(printk(KERN_ERR "%s: dma alloc for rsp_data "
681 "failed for host=%lu\n", __func__, vha->host_no));
682 rval = -ENOMEM;
683 goto done_free_dma_req;
684 }
685
686 /* Copy the request buffer in req_data now */
687 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
688 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
689
690 elreq.send_dma = req_data_dma;
691 elreq.rcv_dma = rsp_data_dma;
692 elreq.transfer_size = req_data_len;
693
694 elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
695
23f2ebd1
SR
696 if ((ha->current_topology == ISP_CFG_F ||
697 (IS_QLA81XX(ha) &&
698 le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE
699 && req_data_len == MAX_ELS_FRAME_PAYLOAD)) &&
700 elreq.options == EXTERNAL_LOOPBACK) {
701 type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
6e98016c 702 DEBUG2(qla_printk(KERN_INFO, ha,
23f2ebd1
SR
703 "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
704 command_sent = INT_DEF_LB_ECHO_CMD;
705 rval = qla2x00_echo_test(vha, &elreq, response);
706 } else {
6e98016c 707 if (IS_QLA81XX(ha)) {
23f2ebd1
SR
708 memset(config, 0, sizeof(config));
709 memset(new_config, 0, sizeof(new_config));
710 if (qla81xx_get_port_config(vha, config)) {
711 DEBUG2(printk(KERN_ERR
712 "%s(%lu): Get port config failed\n",
713 __func__, vha->host_no));
714 bsg_job->reply->reply_payload_rcv_len = 0;
715 bsg_job->reply->result = (DID_ERROR << 16);
716 rval = -EPERM;
717 goto done_free_dma_req;
718 }
719
720 if (elreq.options != EXTERNAL_LOOPBACK) {
721 DEBUG2(qla_printk(KERN_INFO, ha,
722 "Internal: current port config = %x\n",
723 config[0]));
724 if (qla81xx_set_internal_loopback(vha, config,
725 new_config)) {
726 bsg_job->reply->reply_payload_rcv_len =
727 0;
728 bsg_job->reply->result =
729 (DID_ERROR << 16);
730 rval = -EPERM;
731 goto done_free_dma_req;
732 }
733 } else {
734 /* For external loopback to work
735 * ensure internal loopback is disabled
736 */
737 if (qla81xx_reset_internal_loopback(vha,
738 config, 1)) {
739 bsg_job->reply->reply_payload_rcv_len =
740 0;
741 bsg_job->reply->result =
742 (DID_ERROR << 16);
743 rval = -EPERM;
744 goto done_free_dma_req;
745 }
746 }
747
748 type = "FC_BSG_HST_VENDOR_LOOPBACK";
749 DEBUG2(qla_printk(KERN_INFO, ha,
750 "scsi(%ld) bsg rqst type: %s\n",
751 vha->host_no, type));
752
753 command_sent = INT_DEF_LB_LOOPBACK_CMD;
754 rval = qla2x00_loopback_test(vha, &elreq, response);
755
756 if (new_config[1]) {
757 /* Revert back to original port config
758 * Also clear internal loopback
759 */
760 qla81xx_reset_internal_loopback(vha,
761 new_config, 0);
762 }
763
6e98016c 764 if (response[0] == MBS_COMMAND_ERROR &&
23f2ebd1 765 response[1] == MBS_LB_RESET) {
6e98016c 766 DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
23f2ebd1 767 "ISP\n", __func__, vha->host_no));
6e98016c
GM
768 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
769 qla2xxx_wake_dpc(vha);
23f2ebd1
SR
770 qla2x00_wait_for_chip_reset(vha);
771 /* Also reset the MPI */
772 if (qla81xx_restart_mpi_firmware(vha) !=
773 QLA_SUCCESS) {
774 qla_printk(KERN_INFO, ha,
775 "MPI reset failed for host%ld.\n",
776 vha->host_no);
777 }
778
779 bsg_job->reply->reply_payload_rcv_len = 0;
780 bsg_job->reply->result = (DID_ERROR << 16);
781 rval = -EIO;
782 goto done_free_dma_req;
6e98016c 783 }
23f2ebd1
SR
784 } else {
785 type = "FC_BSG_HST_VENDOR_LOOPBACK";
786 DEBUG2(qla_printk(KERN_INFO, ha,
787 "scsi(%ld) bsg rqst type: %s\n",
788 vha->host_no, type));
789 command_sent = INT_DEF_LB_LOOPBACK_CMD;
790 rval = qla2x00_loopback_test(vha, &elreq, response);
6e98016c 791 }
6e98016c
GM
792 }
793
794 if (rval) {
795 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
6c452a45 796 "request %s failed\n", vha->host_no, type));
6e98016c
GM
797
798 fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
6c452a45 799 sizeof(struct fc_bsg_reply);
6e98016c
GM
800
801 memcpy(fw_sts_ptr, response, sizeof(response));
802 fw_sts_ptr += sizeof(response);
6c452a45 803 *fw_sts_ptr = command_sent;
6e98016c
GM
804 rval = 0;
805 bsg_job->reply->reply_payload_rcv_len = 0;
806 bsg_job->reply->result = (DID_ERROR << 16);
807 } else {
808 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
809 "request %s completed\n", vha->host_no, type));
810
811 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
812 sizeof(response) + sizeof(uint8_t);
813 bsg_job->reply->reply_payload_rcv_len =
814 bsg_job->reply_payload.payload_len;
815 fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
816 sizeof(struct fc_bsg_reply);
817 memcpy(fw_sts_ptr, response, sizeof(response));
818 fw_sts_ptr += sizeof(response);
819 *fw_sts_ptr = command_sent;
820 bsg_job->reply->result = DID_OK;
821 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
822 bsg_job->reply_payload.sg_cnt, rsp_data,
823 rsp_data_len);
824 }
825 bsg_job->job_done(bsg_job);
826
827 dma_free_coherent(&ha->pdev->dev, rsp_data_len,
828 rsp_data, rsp_data_dma);
829done_free_dma_req:
830 dma_free_coherent(&ha->pdev->dev, req_data_len,
831 req_data, req_data_dma);
832done_unmap_sg:
833 dma_unmap_sg(&ha->pdev->dev,
834 bsg_job->reply_payload.sg_list,
835 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
836done_unmap_req_sg:
837 dma_unmap_sg(&ha->pdev->dev,
838 bsg_job->request_payload.sg_list,
839 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
6c452a45 840 return rval;
6e98016c
GM
841}
842
843static int
844qla84xx_reset(struct fc_bsg_job *bsg_job)
845{
846 struct Scsi_Host *host = bsg_job->shost;
847 scsi_qla_host_t *vha = shost_priv(host);
848 struct qla_hw_data *ha = vha->hw;
849 int rval = 0;
850 uint32_t flag;
851
852 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
853 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
854 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
855 return -EBUSY;
856
857 if (!IS_QLA84XX(ha)) {
858 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
859 "exiting.\n", vha->host_no));
860 return -EINVAL;
861 }
862
863 flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
864
865 rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
866
867 if (rval) {
868 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
869 "request 84xx reset failed\n", vha->host_no));
870 rval = bsg_job->reply->reply_payload_rcv_len = 0;
871 bsg_job->reply->result = (DID_ERROR << 16);
872
873 } else {
874 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
875 "request 84xx reset completed\n", vha->host_no));
876 bsg_job->reply->result = DID_OK;
877 }
878
879 bsg_job->job_done(bsg_job);
880 return rval;
881}
882
883static int
884qla84xx_updatefw(struct fc_bsg_job *bsg_job)
885{
886 struct Scsi_Host *host = bsg_job->shost;
887 scsi_qla_host_t *vha = shost_priv(host);
888 struct qla_hw_data *ha = vha->hw;
889 struct verify_chip_entry_84xx *mn = NULL;
890 dma_addr_t mn_dma, fw_dma;
891 void *fw_buf = NULL;
892 int rval = 0;
893 uint32_t sg_cnt;
894 uint32_t data_len;
895 uint16_t options;
896 uint32_t flag;
897 uint32_t fw_ver;
898
899 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
900 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
901 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
902 return -EBUSY;
903
904 if (!IS_QLA84XX(ha)) {
905 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
906 "exiting.\n", vha->host_no));
907 return -EINVAL;
908 }
909
910 sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
911 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
912 if (!sg_cnt)
913 return -ENOMEM;
914
915 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
916 DEBUG2(printk(KERN_INFO
917 "dma mapping resulted in different sg counts "
918 "request_sg_cnt: %x dma_request_sg_cnt: %x ",
919 bsg_job->request_payload.sg_cnt, sg_cnt));
920 rval = -EAGAIN;
921 goto done_unmap_sg;
922 }
923
924 data_len = bsg_job->request_payload.payload_len;
925 fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
926 &fw_dma, GFP_KERNEL);
927 if (!fw_buf) {
928 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw_buf "
929 "failed for host=%lu\n", __func__, vha->host_no));
930 rval = -ENOMEM;
931 goto done_unmap_sg;
932 }
933
934 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
935 bsg_job->request_payload.sg_cnt, fw_buf, data_len);
936
937 mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
938 if (!mn) {
939 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
940 "failed for host=%lu\n", __func__, vha->host_no));
941 rval = -ENOMEM;
942 goto done_free_fw_buf;
943 }
944
945 flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
946 fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2)));
947
948 memset(mn, 0, sizeof(struct access_chip_84xx));
949 mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
950 mn->entry_count = 1;
951
952 options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
953 if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD)
954 options |= VCO_DIAG_FW;
955
956 mn->options = cpu_to_le16(options);
957 mn->fw_ver = cpu_to_le32(fw_ver);
958 mn->fw_size = cpu_to_le32(data_len);
959 mn->fw_seq_size = cpu_to_le32(data_len);
960 mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma));
961 mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma));
962 mn->dseg_length = cpu_to_le32(data_len);
963 mn->data_seg_cnt = cpu_to_le16(1);
964
965 rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
966
967 if (rval) {
968 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
969 "request 84xx updatefw failed\n", vha->host_no));
970
971 rval = bsg_job->reply->reply_payload_rcv_len = 0;
972 bsg_job->reply->result = (DID_ERROR << 16);
973
974 } else {
975 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
976 "request 84xx updatefw completed\n", vha->host_no));
977
978 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
979 bsg_job->reply->result = DID_OK;
980 }
981
982 bsg_job->job_done(bsg_job);
983 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
984
985done_free_fw_buf:
986 dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma);
987
988done_unmap_sg:
989 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
990 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
991
992 return rval;
993}
994
995static int
996qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
997{
998 struct Scsi_Host *host = bsg_job->shost;
999 scsi_qla_host_t *vha = shost_priv(host);
1000 struct qla_hw_data *ha = vha->hw;
1001 struct access_chip_84xx *mn = NULL;
1002 dma_addr_t mn_dma, mgmt_dma;
1003 void *mgmt_b = NULL;
1004 int rval = 0;
1005 struct qla_bsg_a84_mgmt *ql84_mgmt;
1006 uint32_t sg_cnt;
d5459083 1007 uint32_t data_len = 0;
6e98016c
GM
1008 uint32_t dma_direction = DMA_NONE;
1009
1010 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1011 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1012 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
1013 return -EBUSY;
1014
1015 if (!IS_QLA84XX(ha)) {
1016 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
1017 "exiting.\n", vha->host_no));
1018 return -EINVAL;
1019 }
1020
1021 ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request +
1022 sizeof(struct fc_bsg_request));
1023 if (!ql84_mgmt) {
1024 DEBUG2(printk("%s(%ld): mgmt header not provided, exiting.\n",
1025 __func__, vha->host_no));
1026 return -EINVAL;
1027 }
1028
1029 mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1030 if (!mn) {
1031 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
1032 "failed for host=%lu\n", __func__, vha->host_no));
1033 return -ENOMEM;
1034 }
1035
1036 memset(mn, 0, sizeof(struct access_chip_84xx));
1037 mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
1038 mn->entry_count = 1;
1039
1040 switch (ql84_mgmt->mgmt.cmd) {
1041 case QLA84_MGMT_READ_MEM:
1042 case QLA84_MGMT_GET_INFO:
1043 sg_cnt = dma_map_sg(&ha->pdev->dev,
1044 bsg_job->reply_payload.sg_list,
1045 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1046 if (!sg_cnt) {
1047 rval = -ENOMEM;
1048 goto exit_mgmt;
1049 }
1050
1051 dma_direction = DMA_FROM_DEVICE;
1052
1053 if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
1054 DEBUG2(printk(KERN_INFO
1055 "dma mapping resulted in different sg counts "
1056 "reply_sg_cnt: %x dma_reply_sg_cnt: %x\n",
1057 bsg_job->reply_payload.sg_cnt, sg_cnt));
1058 rval = -EAGAIN;
1059 goto done_unmap_sg;
1060 }
1061
1062 data_len = bsg_job->reply_payload.payload_len;
1063
1064 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1065 &mgmt_dma, GFP_KERNEL);
1066 if (!mgmt_b) {
1067 DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
1068 "failed for host=%lu\n",
1069 __func__, vha->host_no));
1070 rval = -ENOMEM;
1071 goto done_unmap_sg;
1072 }
1073
1074 if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) {
1075 mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
1076 mn->parameter1 =
1077 cpu_to_le32(
1078 ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1079
1080 } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) {
1081 mn->options = cpu_to_le16(ACO_REQUEST_INFO);
1082 mn->parameter1 =
1083 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type);
1084
1085 mn->parameter2 =
1086 cpu_to_le32(
1087 ql84_mgmt->mgmt.mgmtp.u.info.context);
1088 }
1089 break;
1090
1091 case QLA84_MGMT_WRITE_MEM:
1092 sg_cnt = dma_map_sg(&ha->pdev->dev,
1093 bsg_job->request_payload.sg_list,
1094 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1095
1096 if (!sg_cnt) {
1097 rval = -ENOMEM;
1098 goto exit_mgmt;
1099 }
1100
1101 dma_direction = DMA_TO_DEVICE;
1102
1103 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1104 DEBUG2(printk(KERN_INFO
1105 "dma mapping resulted in different sg counts "
1106 "request_sg_cnt: %x dma_request_sg_cnt: %x ",
1107 bsg_job->request_payload.sg_cnt, sg_cnt));
1108 rval = -EAGAIN;
1109 goto done_unmap_sg;
1110 }
1111
1112 data_len = bsg_job->request_payload.payload_len;
1113 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1114 &mgmt_dma, GFP_KERNEL);
1115 if (!mgmt_b) {
1116 DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
1117 "failed for host=%lu\n",
1118 __func__, vha->host_no));
1119 rval = -ENOMEM;
1120 goto done_unmap_sg;
1121 }
1122
1123 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1124 bsg_job->request_payload.sg_cnt, mgmt_b, data_len);
1125
1126 mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
1127 mn->parameter1 =
1128 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1129 break;
1130
1131 case QLA84_MGMT_CHNG_CONFIG:
1132 mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
1133 mn->parameter1 =
1134 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id);
1135
1136 mn->parameter2 =
1137 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0);
1138
1139 mn->parameter3 =
1140 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1);
1141 break;
1142
1143 default:
1144 rval = -EIO;
1145 goto exit_mgmt;
1146 }
1147
1148 if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
1149 mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
1150 mn->dseg_count = cpu_to_le16(1);
1151 mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma));
1152 mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma));
1153 mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len);
1154 }
1155
1156 rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
1157
1158 if (rval) {
1159 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
1160 "request 84xx mgmt failed\n", vha->host_no));
1161
1162 rval = bsg_job->reply->reply_payload_rcv_len = 0;
1163 bsg_job->reply->result = (DID_ERROR << 16);
1164
1165 } else {
1166 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
1167 "request 84xx mgmt completed\n", vha->host_no));
1168
1169 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1170 bsg_job->reply->result = DID_OK;
1171
1172 if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
1173 (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
1174 bsg_job->reply->reply_payload_rcv_len =
1175 bsg_job->reply_payload.payload_len;
1176
1177 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
6c452a45
AV
1178 bsg_job->reply_payload.sg_cnt, mgmt_b,
1179 data_len);
6e98016c
GM
1180 }
1181 }
1182
1183 bsg_job->job_done(bsg_job);
6e98016c
GM
1184
1185done_unmap_sg:
d5459083
HZ
1186 if (mgmt_b)
1187 dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
1188
6e98016c
GM
1189 if (dma_direction == DMA_TO_DEVICE)
1190 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1191 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1192 else if (dma_direction == DMA_FROM_DEVICE)
1193 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1194 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1195
1196exit_mgmt:
1197 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1198
1199 return rval;
1200}
1201
1202static int
1203qla24xx_iidma(struct fc_bsg_job *bsg_job)
1204{
1205 struct Scsi_Host *host = bsg_job->shost;
1206 scsi_qla_host_t *vha = shost_priv(host);
1207 struct qla_hw_data *ha = vha->hw;
1208 int rval = 0;
1209 struct qla_port_param *port_param = NULL;
1210 fc_port_t *fcport = NULL;
1211 uint16_t mb[MAILBOX_REGISTER_COUNT];
1212 uint8_t *rsp_ptr = NULL;
1213
1214 bsg_job->reply->reply_payload_rcv_len = 0;
1215
1216 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1217 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1218 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
1219 return -EBUSY;
1220
1221 if (!IS_IIDMA_CAPABLE(vha->hw)) {
1222 DEBUG2(qla_printk(KERN_WARNING, ha, "%s(%lu): iiDMA not "
1223 "supported\n", __func__, vha->host_no));
1224 return -EINVAL;
1225 }
1226
1227 port_param = (struct qla_port_param *)((char *)bsg_job->request +
1228 sizeof(struct fc_bsg_request));
1229 if (!port_param) {
1230 DEBUG2(printk("%s(%ld): port_param header not provided, "
1231 "exiting.\n", __func__, vha->host_no));
1232 return -EINVAL;
1233 }
1234
1235 if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
1236 DEBUG2(printk(KERN_ERR "%s(%ld): Invalid destination type\n",
1237 __func__, vha->host_no));
1238 return -EINVAL;
1239 }
1240
1241 list_for_each_entry(fcport, &vha->vp_fcports, list) {
1242 if (fcport->port_type != FCT_TARGET)
1243 continue;
1244
1245 if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn,
1246 fcport->port_name, sizeof(fcport->port_name)))
1247 continue;
1248 break;
1249 }
1250
1251 if (!fcport) {
1252 DEBUG2(printk(KERN_ERR "%s(%ld): Failed to find port\n",
1253 __func__, vha->host_no));
1254 return -EINVAL;
1255 }
1256
c9afb9a2
GM
1257 if (atomic_read(&fcport->state) != FCS_ONLINE) {
1258 DEBUG2(printk(KERN_ERR "%s(%ld): Port not online\n",
1259 __func__, vha->host_no));
17cf2c5d
MI
1260 return -EINVAL;
1261 }
1262
9a15eb4b
MI
1263 if (fcport->flags & FCF_LOGIN_NEEDED) {
1264 DEBUG2(printk(KERN_ERR "%s(%ld): Remote port not logged in, "
1265 "flags = 0x%x\n",
1266 __func__, vha->host_no, fcport->flags));
1267 return -EINVAL;
1268 }
1269
6e98016c
GM
1270 if (port_param->mode)
1271 rval = qla2x00_set_idma_speed(vha, fcport->loop_id,
1272 port_param->speed, mb);
1273 else
1274 rval = qla2x00_get_idma_speed(vha, fcport->loop_id,
1275 &port_param->speed, mb);
1276
1277 if (rval) {
1278 DEBUG16(printk(KERN_ERR "scsi(%ld): iIDMA cmd failed for "
6c452a45
AV
1279 "%02x%02x%02x%02x%02x%02x%02x%02x -- "
1280 "%04x %x %04x %04x.\n",
6e98016c
GM
1281 vha->host_no, fcport->port_name[0],
1282 fcport->port_name[1],
1283 fcport->port_name[2], fcport->port_name[3],
1284 fcport->port_name[4], fcport->port_name[5],
1285 fcport->port_name[6], fcport->port_name[7], rval,
1286 fcport->fp_speed, mb[0], mb[1]));
1287 rval = 0;
1288 bsg_job->reply->result = (DID_ERROR << 16);
1289
1290 } else {
1291 if (!port_param->mode) {
1292 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
1293 sizeof(struct qla_port_param);
1294
1295 rsp_ptr = ((uint8_t *)bsg_job->reply) +
1296 sizeof(struct fc_bsg_reply);
1297
1298 memcpy(rsp_ptr, port_param,
1299 sizeof(struct qla_port_param));
1300 }
1301
1302 bsg_job->reply->result = DID_OK;
1303 }
1304
1305 bsg_job->job_done(bsg_job);
1306 return rval;
1307}
1308
f19af163
HZ
1309static int
1310qla2x00_optrom_setup(struct fc_bsg_job *bsg_job, struct qla_hw_data *ha,
1311 uint8_t is_update)
1312{
1313 uint32_t start = 0;
1314 int valid = 0;
1315
1316 bsg_job->reply->reply_payload_rcv_len = 0;
1317
1318 if (unlikely(pci_channel_offline(ha->pdev)))
1319 return -EINVAL;
1320
1321 start = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
1322 if (start > ha->optrom_size)
1323 return -EINVAL;
1324
1325 if (ha->optrom_state != QLA_SWAITING)
1326 return -EBUSY;
1327
1328 ha->optrom_region_start = start;
1329
1330 if (is_update) {
1331 if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
1332 valid = 1;
1333 else if (start == (ha->flt_region_boot * 4) ||
1334 start == (ha->flt_region_fw * 4))
1335 valid = 1;
1336 else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
1337 IS_QLA8XXX_TYPE(ha))
1338 valid = 1;
1339 if (!valid) {
1340 qla_printk(KERN_WARNING, ha,
1341 "Invalid start region 0x%x/0x%x.\n",
1342 start, bsg_job->request_payload.payload_len);
1343 return -EINVAL;
1344 }
1345
1346 ha->optrom_region_size = start +
1347 bsg_job->request_payload.payload_len > ha->optrom_size ?
1348 ha->optrom_size - start :
1349 bsg_job->request_payload.payload_len;
1350 ha->optrom_state = QLA_SWRITING;
1351 } else {
1352 ha->optrom_region_size = start +
1353 bsg_job->reply_payload.payload_len > ha->optrom_size ?
1354 ha->optrom_size - start :
1355 bsg_job->reply_payload.payload_len;
1356 ha->optrom_state = QLA_SREADING;
1357 }
1358
1359 ha->optrom_buffer = vmalloc(ha->optrom_region_size);
1360 if (!ha->optrom_buffer) {
1361 qla_printk(KERN_WARNING, ha,
1362 "Read: Unable to allocate memory for optrom retrieval "
1363 "(%x).\n", ha->optrom_region_size);
1364
1365 ha->optrom_state = QLA_SWAITING;
1366 return -ENOMEM;
1367 }
1368
1369 memset(ha->optrom_buffer, 0, ha->optrom_region_size);
1370 return 0;
1371}
1372
1373static int
1374qla2x00_read_optrom(struct fc_bsg_job *bsg_job)
1375{
1376 struct Scsi_Host *host = bsg_job->shost;
1377 scsi_qla_host_t *vha = shost_priv(host);
1378 struct qla_hw_data *ha = vha->hw;
1379 int rval = 0;
1380
1381 rval = qla2x00_optrom_setup(bsg_job, ha, 0);
1382 if (rval)
1383 return rval;
1384
1385 ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
1386 ha->optrom_region_start, ha->optrom_region_size);
1387
1388 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1389 bsg_job->reply_payload.sg_cnt, ha->optrom_buffer,
1390 ha->optrom_region_size);
1391
1392 bsg_job->reply->reply_payload_rcv_len = ha->optrom_region_size;
1393 bsg_job->reply->result = DID_OK;
1394 vfree(ha->optrom_buffer);
1395 ha->optrom_buffer = NULL;
1396 ha->optrom_state = QLA_SWAITING;
1397 bsg_job->job_done(bsg_job);
1398 return rval;
1399}
1400
1401static int
1402qla2x00_update_optrom(struct fc_bsg_job *bsg_job)
1403{
1404 struct Scsi_Host *host = bsg_job->shost;
1405 scsi_qla_host_t *vha = shost_priv(host);
1406 struct qla_hw_data *ha = vha->hw;
1407 int rval = 0;
1408
1409 rval = qla2x00_optrom_setup(bsg_job, ha, 1);
1410 if (rval)
1411 return rval;
1412
1413 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1414 bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
1415 ha->optrom_region_size);
1416
1417 ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
1418 ha->optrom_region_start, ha->optrom_region_size);
1419
1420 bsg_job->reply->result = DID_OK;
1421 vfree(ha->optrom_buffer);
1422 ha->optrom_buffer = NULL;
1423 ha->optrom_state = QLA_SWAITING;
1424 bsg_job->job_done(bsg_job);
1425 return rval;
1426}
1427
6e98016c
GM
1428static int
1429qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
1430{
1431 switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
1432 case QL_VND_LOOPBACK:
1433 return qla2x00_process_loopback(bsg_job);
1434
1435 case QL_VND_A84_RESET:
1436 return qla84xx_reset(bsg_job);
1437
1438 case QL_VND_A84_UPDATE_FW:
1439 return qla84xx_updatefw(bsg_job);
1440
1441 case QL_VND_A84_MGMT_CMD:
1442 return qla84xx_mgmt_cmd(bsg_job);
1443
1444 case QL_VND_IIDMA:
1445 return qla24xx_iidma(bsg_job);
1446
09ff701a
SR
1447 case QL_VND_FCP_PRIO_CFG_CMD:
1448 return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
1449
f19af163
HZ
1450 case QL_VND_READ_FLASH:
1451 return qla2x00_read_optrom(bsg_job);
1452
1453 case QL_VND_UPDATE_FLASH:
1454 return qla2x00_update_optrom(bsg_job);
1455
6e98016c
GM
1456 default:
1457 bsg_job->reply->result = (DID_ERROR << 16);
1458 bsg_job->job_done(bsg_job);
1459 return -ENOSYS;
1460 }
1461}
1462
1463int
1464qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
1465{
1466 int ret = -EINVAL;
1467
1468 switch (bsg_job->request->msgcode) {
1469 case FC_BSG_RPT_ELS:
1470 case FC_BSG_HST_ELS_NOLOGIN:
1471 ret = qla2x00_process_els(bsg_job);
1472 break;
1473 case FC_BSG_HST_CT:
1474 ret = qla2x00_process_ct(bsg_job);
1475 break;
1476 case FC_BSG_HST_VENDOR:
1477 ret = qla2x00_process_vendor_specific(bsg_job);
1478 break;
1479 case FC_BSG_HST_ADD_RPORT:
1480 case FC_BSG_HST_DEL_RPORT:
1481 case FC_BSG_RPT_CT:
1482 default:
1483 DEBUG2(printk("qla2xxx: unsupported BSG request\n"));
1484 break;
6c452a45 1485 }
6e98016c
GM
1486 return ret;
1487}
1488
1489int
1490qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
1491{
1492 scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
1493 struct qla_hw_data *ha = vha->hw;
1494 srb_t *sp;
1495 int cnt, que;
1496 unsigned long flags;
1497 struct req_que *req;
4916392b 1498 struct srb_ctx *sp_bsg;
6e98016c
GM
1499
1500 /* find the bsg job from the active list of commands */
1501 spin_lock_irqsave(&ha->hardware_lock, flags);
1502 for (que = 0; que < ha->max_req_queues; que++) {
1503 req = ha->req_q_map[que];
1504 if (!req)
1505 continue;
1506
6c452a45 1507 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
6e98016c 1508 sp = req->outstanding_cmds[cnt];
6e98016c 1509 if (sp) {
4916392b 1510 sp_bsg = sp->ctx;
6e98016c 1511
4916392b
MI
1512 if (((sp_bsg->type == SRB_CT_CMD) ||
1513 (sp_bsg->type == SRB_ELS_CMD_HST))
1514 && (sp_bsg->u.bsg_job == bsg_job)) {
6e98016c
GM
1515 if (ha->isp_ops->abort_command(sp)) {
1516 DEBUG2(qla_printk(KERN_INFO, ha,
6c452a45
AV
1517 "scsi(%ld): mbx "
1518 "abort_command failed\n",
1519 vha->host_no));
6e98016c
GM
1520 bsg_job->req->errors =
1521 bsg_job->reply->result = -EIO;
1522 } else {
1523 DEBUG2(qla_printk(KERN_INFO, ha,
6c452a45
AV
1524 "scsi(%ld): mbx "
1525 "abort_command success\n",
1526 vha->host_no));
6e98016c
GM
1527 bsg_job->req->errors =
1528 bsg_job->reply->result = 0;
1529 }
1530 goto done;
1531 }
1532 }
1533 }
1534 }
1535 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1536 DEBUG2(qla_printk(KERN_INFO, ha,
1537 "scsi(%ld) SRB not found to abort\n", vha->host_no));
1538 bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
1539 return 0;
1540
1541done:
1542 spin_unlock_irqrestore(&ha->hardware_lock, flags);
1543 if (bsg_job->request->msgcode == FC_BSG_HST_CT)
1544 kfree(sp->fcport);
1545 kfree(sp->ctx);
1546 mempool_free(sp, ha->srb_mempool);
1547 return 0;
1548}