1
2
3
4
5
6#include "qla_def.h"
7#include "qla_gbl.h"
8
9#include <linux/kthread.h>
10#include <linux/vmalloc.h>
11#include <linux/delay.h>
12#include <linux/bsg-lib.h>
13
14static void qla2xxx_free_fcport_work(struct work_struct *work)
15{
16 struct fc_port *fcport = container_of(work, typeof(*fcport),
17 free_work);
18
19 qla2x00_free_fcport(fcport);
20}
21
22
23void qla2x00_bsg_job_done(srb_t *sp, int res)
24{
25 struct bsg_job *bsg_job = sp->u.bsg_job;
26 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
27
28 bsg_reply->result = res;
29 bsg_job_done(bsg_job, bsg_reply->result,
30 bsg_reply->reply_payload_rcv_len);
31 sp->free(sp);
32}
33
34void qla2x00_bsg_sp_free(srb_t *sp)
35{
36 struct qla_hw_data *ha = sp->vha->hw;
37 struct bsg_job *bsg_job = sp->u.bsg_job;
38 struct fc_bsg_request *bsg_request = bsg_job->request;
39 struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
40
41 if (sp->type == SRB_FXIOCB_BCMD) {
42 piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
43 &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
44
45 if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
46 dma_unmap_sg(&ha->pdev->dev,
47 bsg_job->request_payload.sg_list,
48 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
49
50 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
51 dma_unmap_sg(&ha->pdev->dev,
52 bsg_job->reply_payload.sg_list,
53 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
54 } else {
55 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
56 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
57
58 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
59 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
60 }
61
62 if (sp->type == SRB_CT_CMD ||
63 sp->type == SRB_FXIOCB_BCMD ||
64 sp->type == SRB_ELS_CMD_HST) {
65 INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work);
66 queue_work(ha->wq, &sp->fcport->free_work);
67 }
68
69 qla2x00_rel_sp(sp);
70}
71
72int
73qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
74 struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
75{
76 int i, ret, num_valid;
77 uint8_t *bcode;
78 struct qla_fcp_prio_entry *pri_entry;
79 uint32_t *bcode_val_ptr, bcode_val;
80
81 ret = 1;
82 num_valid = 0;
83 bcode = (uint8_t *)pri_cfg;
84 bcode_val_ptr = (uint32_t *)pri_cfg;
85 bcode_val = (uint32_t)(*bcode_val_ptr);
86
87 if (bcode_val == 0xFFFFFFFF) {
88
89 ql_dbg(ql_dbg_user, vha, 0x7051,
90 "No FCP Priority config data.\n");
91 return 0;
92 }
93
94 if (memcmp(bcode, "HQOS", 4)) {
95
96 ql_dbg(ql_dbg_user, vha, 0x7052,
97 "Invalid FCP Priority data header. bcode=0x%x.\n",
98 bcode_val);
99 return 0;
100 }
101 if (flag != 1)
102 return ret;
103
104 pri_entry = &pri_cfg->entry[0];
105 for (i = 0; i < pri_cfg->num_entries; i++) {
106 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
107 num_valid++;
108 pri_entry++;
109 }
110
111 if (num_valid == 0) {
112
113 ql_dbg(ql_dbg_user, vha, 0x7053,
114 "No valid FCP Priority data entries.\n");
115 ret = 0;
116 } else {
117
118 ql_dbg(ql_dbg_user, vha, 0x7054,
119 "Valid FCP priority data. num entries = %d.\n",
120 num_valid);
121 }
122
123 return ret;
124}
125
126static int
127qla24xx_proc_fcp_prio_cfg_cmd(struct bsg_job *bsg_job)
128{
129 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
130 struct fc_bsg_request *bsg_request = bsg_job->request;
131 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
132 scsi_qla_host_t *vha = shost_priv(host);
133 struct qla_hw_data *ha = vha->hw;
134 int ret = 0;
135 uint32_t len;
136 uint32_t oper;
137
138 if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_P3P_TYPE(ha))) {
139 ret = -EINVAL;
140 goto exit_fcp_prio_cfg;
141 }
142
143
144 oper = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
145
146
147 if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
148 ret = -EINVAL;
149 goto exit_fcp_prio_cfg;
150 }
151 switch (oper) {
152 case QLFC_FCP_PRIO_DISABLE:
153 if (ha->flags.fcp_prio_enabled) {
154 ha->flags.fcp_prio_enabled = 0;
155 ha->fcp_prio_cfg->attributes &=
156 ~FCP_PRIO_ATTR_ENABLE;
157 qla24xx_update_all_fcp_prio(vha);
158 bsg_reply->result = DID_OK;
159 } else {
160 ret = -EINVAL;
161 bsg_reply->result = (DID_ERROR << 16);
162 goto exit_fcp_prio_cfg;
163 }
164 break;
165
166 case QLFC_FCP_PRIO_ENABLE:
167 if (!ha->flags.fcp_prio_enabled) {
168 if (ha->fcp_prio_cfg) {
169 ha->flags.fcp_prio_enabled = 1;
170 ha->fcp_prio_cfg->attributes |=
171 FCP_PRIO_ATTR_ENABLE;
172 qla24xx_update_all_fcp_prio(vha);
173 bsg_reply->result = DID_OK;
174 } else {
175 ret = -EINVAL;
176 bsg_reply->result = (DID_ERROR << 16);
177 goto exit_fcp_prio_cfg;
178 }
179 }
180 break;
181
182 case QLFC_FCP_PRIO_GET_CONFIG:
183 len = bsg_job->reply_payload.payload_len;
184 if (!len || len > FCP_PRIO_CFG_SIZE) {
185 ret = -EINVAL;
186 bsg_reply->result = (DID_ERROR << 16);
187 goto exit_fcp_prio_cfg;
188 }
189
190 bsg_reply->result = DID_OK;
191 bsg_reply->reply_payload_rcv_len =
192 sg_copy_from_buffer(
193 bsg_job->reply_payload.sg_list,
194 bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
195 len);
196
197 break;
198
199 case QLFC_FCP_PRIO_SET_CONFIG:
200 len = bsg_job->request_payload.payload_len;
201 if (!len || len > FCP_PRIO_CFG_SIZE) {
202 bsg_reply->result = (DID_ERROR << 16);
203 ret = -EINVAL;
204 goto exit_fcp_prio_cfg;
205 }
206
207 if (!ha->fcp_prio_cfg) {
208 ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
209 if (!ha->fcp_prio_cfg) {
210 ql_log(ql_log_warn, vha, 0x7050,
211 "Unable to allocate memory for fcp prio "
212 "config data (%x).\n", FCP_PRIO_CFG_SIZE);
213 bsg_reply->result = (DID_ERROR << 16);
214 ret = -ENOMEM;
215 goto exit_fcp_prio_cfg;
216 }
217 }
218
219 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
220 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
221 bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
222 FCP_PRIO_CFG_SIZE);
223
224
225
226 if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1)) {
227 bsg_reply->result = (DID_ERROR << 16);
228 ret = -EINVAL;
229
230
231
232 vfree(ha->fcp_prio_cfg);
233 ha->fcp_prio_cfg = NULL;
234 goto exit_fcp_prio_cfg;
235 }
236
237 ha->flags.fcp_prio_enabled = 0;
238 if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
239 ha->flags.fcp_prio_enabled = 1;
240 qla24xx_update_all_fcp_prio(vha);
241 bsg_reply->result = DID_OK;
242 break;
243 default:
244 ret = -EINVAL;
245 break;
246 }
247exit_fcp_prio_cfg:
248 if (!ret)
249 bsg_job_done(bsg_job, bsg_reply->result,
250 bsg_reply->reply_payload_rcv_len);
251 return ret;
252}
253
254static int
255qla2x00_process_els(struct bsg_job *bsg_job)
256{
257 struct fc_bsg_request *bsg_request = bsg_job->request;
258 struct fc_rport *rport;
259 fc_port_t *fcport = NULL;
260 struct Scsi_Host *host;
261 scsi_qla_host_t *vha;
262 struct qla_hw_data *ha;
263 srb_t *sp;
264 const char *type;
265 int req_sg_cnt, rsp_sg_cnt;
266 int rval = (DID_ERROR << 16);
267 uint16_t nextlid = 0;
268
269 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
270 rport = fc_bsg_to_rport(bsg_job);
271 fcport = *(fc_port_t **) rport->dd_data;
272 host = rport_to_shost(rport);
273 vha = shost_priv(host);
274 ha = vha->hw;
275 type = "FC_BSG_RPT_ELS";
276 } else {
277 host = fc_bsg_to_shost(bsg_job);
278 vha = shost_priv(host);
279 ha = vha->hw;
280 type = "FC_BSG_HST_ELS_NOLOGIN";
281 }
282
283 if (!vha->flags.online) {
284 ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
285 rval = -EIO;
286 goto done;
287 }
288
289
290 if (!IS_FWI2_CAPABLE(ha)) {
291 ql_dbg(ql_dbg_user, vha, 0x7001,
292 "ELS passthru not supported for ISP23xx based adapters.\n");
293 rval = -EPERM;
294 goto done;
295 }
296
297
298 if (bsg_job->request_payload.sg_cnt > 1 ||
299 bsg_job->reply_payload.sg_cnt > 1) {
300 ql_dbg(ql_dbg_user, vha, 0x7002,
301 "Multiple SG's are not supported for ELS requests, "
302 "request_sg_cnt=%x reply_sg_cnt=%x.\n",
303 bsg_job->request_payload.sg_cnt,
304 bsg_job->reply_payload.sg_cnt);
305 rval = -EPERM;
306 goto done;
307 }
308
309
310 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
311
312
313
314 if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
315 ql_dbg(ql_dbg_user, vha, 0x7003,
316 "Failed to login port %06X for ELS passthru.\n",
317 fcport->d_id.b24);
318 rval = -EIO;
319 goto done;
320 }
321 } else {
322
323
324
325
326
327 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
328 if (!fcport) {
329 rval = -ENOMEM;
330 goto done;
331 }
332
333
334 fcport->vha = vha;
335 fcport->d_id.b.al_pa =
336 bsg_request->rqst_data.h_els.port_id[0];
337 fcport->d_id.b.area =
338 bsg_request->rqst_data.h_els.port_id[1];
339 fcport->d_id.b.domain =
340 bsg_request->rqst_data.h_els.port_id[2];
341 fcport->loop_id =
342 (fcport->d_id.b.al_pa == 0xFD) ?
343 NPH_FABRIC_CONTROLLER : NPH_F_PORT;
344 }
345
346 req_sg_cnt =
347 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
348 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
349 if (!req_sg_cnt) {
350 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
351 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
352 rval = -ENOMEM;
353 goto done_free_fcport;
354 }
355
356 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
357 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
358 if (!rsp_sg_cnt) {
359 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
360 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
361 rval = -ENOMEM;
362 goto done_free_fcport;
363 }
364
365 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
366 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
367 ql_log(ql_log_warn, vha, 0x7008,
368 "dma mapping resulted in different sg counts, "
369 "request_sg_cnt: %x dma_request_sg_cnt:%x reply_sg_cnt:%x "
370 "dma_reply_sg_cnt:%x.\n", bsg_job->request_payload.sg_cnt,
371 req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
372 rval = -EAGAIN;
373 goto done_unmap_sg;
374 }
375
376
377 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
378 if (!sp) {
379 rval = -ENOMEM;
380 goto done_unmap_sg;
381 }
382
383 sp->type =
384 (bsg_request->msgcode == FC_BSG_RPT_ELS ?
385 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
386 sp->name =
387 (bsg_request->msgcode == FC_BSG_RPT_ELS ?
388 "bsg_els_rpt" : "bsg_els_hst");
389 sp->u.bsg_job = bsg_job;
390 sp->free = qla2x00_bsg_sp_free;
391 sp->done = qla2x00_bsg_job_done;
392
393 ql_dbg(ql_dbg_user, vha, 0x700a,
394 "bsg rqst type: %s els type: %x - loop-id=%x "
395 "portid=%-2x%02x%02x.\n", type,
396 bsg_request->rqst_data.h_els.command_code, fcport->loop_id,
397 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
398
399 rval = qla2x00_start_sp(sp);
400 if (rval != QLA_SUCCESS) {
401 ql_log(ql_log_warn, vha, 0x700e,
402 "qla2x00_start_sp failed = %d\n", rval);
403 qla2x00_rel_sp(sp);
404 rval = -EIO;
405 goto done_unmap_sg;
406 }
407 return rval;
408
409done_unmap_sg:
410 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
411 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
412 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
413 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
414 goto done_free_fcport;
415
416done_free_fcport:
417 if (bsg_request->msgcode == FC_BSG_RPT_ELS)
418 qla2x00_free_fcport(fcport);
419done:
420 return rval;
421}
422
423static inline uint16_t
424qla24xx_calc_ct_iocbs(uint16_t dsds)
425{
426 uint16_t iocbs;
427
428 iocbs = 1;
429 if (dsds > 2) {
430 iocbs += (dsds - 2) / 5;
431 if ((dsds - 2) % 5)
432 iocbs++;
433 }
434 return iocbs;
435}
436
437static int
438qla2x00_process_ct(struct bsg_job *bsg_job)
439{
440 srb_t *sp;
441 struct fc_bsg_request *bsg_request = bsg_job->request;
442 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
443 scsi_qla_host_t *vha = shost_priv(host);
444 struct qla_hw_data *ha = vha->hw;
445 int rval = (DID_ERROR << 16);
446 int req_sg_cnt, rsp_sg_cnt;
447 uint16_t loop_id;
448 struct fc_port *fcport;
449 char *type = "FC_BSG_HST_CT";
450
451 req_sg_cnt =
452 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
453 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
454 if (!req_sg_cnt) {
455 ql_log(ql_log_warn, vha, 0x700f,
456 "dma_map_sg return %d for request\n", req_sg_cnt);
457 rval = -ENOMEM;
458 goto done;
459 }
460
461 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
462 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
463 if (!rsp_sg_cnt) {
464 ql_log(ql_log_warn, vha, 0x7010,
465 "dma_map_sg return %d for reply\n", rsp_sg_cnt);
466 rval = -ENOMEM;
467 goto done;
468 }
469
470 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
471 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
472 ql_log(ql_log_warn, vha, 0x7011,
473 "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
474 "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
475 req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
476 rval = -EAGAIN;
477 goto done_unmap_sg;
478 }
479
480 if (!vha->flags.online) {
481 ql_log(ql_log_warn, vha, 0x7012,
482 "Host is not online.\n");
483 rval = -EIO;
484 goto done_unmap_sg;
485 }
486
487 loop_id =
488 (bsg_request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
489 >> 24;
490 switch (loop_id) {
491 case 0xFC:
492 loop_id = NPH_SNS;
493 break;
494 case 0xFA:
495 loop_id = vha->mgmt_svr_loop_id;
496 break;
497 default:
498 ql_dbg(ql_dbg_user, vha, 0x7013,
499 "Unknown loop id: %x.\n", loop_id);
500 rval = -EINVAL;
501 goto done_unmap_sg;
502 }
503
504
505
506
507
508
509 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
510 if (!fcport) {
511 ql_log(ql_log_warn, vha, 0x7014,
512 "Failed to allocate fcport.\n");
513 rval = -ENOMEM;
514 goto done_unmap_sg;
515 }
516
517
518 fcport->vha = vha;
519 fcport->d_id.b.al_pa = bsg_request->rqst_data.h_ct.port_id[0];
520 fcport->d_id.b.area = bsg_request->rqst_data.h_ct.port_id[1];
521 fcport->d_id.b.domain = bsg_request->rqst_data.h_ct.port_id[2];
522 fcport->loop_id = loop_id;
523
524
525 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
526 if (!sp) {
527 ql_log(ql_log_warn, vha, 0x7015,
528 "qla2x00_get_sp failed.\n");
529 rval = -ENOMEM;
530 goto done_free_fcport;
531 }
532
533 sp->type = SRB_CT_CMD;
534 sp->name = "bsg_ct";
535 sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
536 sp->u.bsg_job = bsg_job;
537 sp->free = qla2x00_bsg_sp_free;
538 sp->done = qla2x00_bsg_job_done;
539
540 ql_dbg(ql_dbg_user, vha, 0x7016,
541 "bsg rqst type: %s else type: %x - "
542 "loop-id=%x portid=%02x%02x%02x.\n", type,
543 (bsg_request->rqst_data.h_ct.preamble_word2 >> 16),
544 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
545 fcport->d_id.b.al_pa);
546
547 rval = qla2x00_start_sp(sp);
548 if (rval != QLA_SUCCESS) {
549 ql_log(ql_log_warn, vha, 0x7017,
550 "qla2x00_start_sp failed=%d.\n", rval);
551 qla2x00_rel_sp(sp);
552 rval = -EIO;
553 goto done_free_fcport;
554 }
555 return rval;
556
557done_free_fcport:
558 qla2x00_free_fcport(fcport);
559done_unmap_sg:
560 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
561 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
562 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
563 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
564done:
565 return rval;
566}
567
568
569static inline int
570qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
571 int wait, int wait2)
572{
573 int ret = 0;
574 int rval = 0;
575 uint16_t new_config[4];
576 struct qla_hw_data *ha = vha->hw;
577
578 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha))
579 goto done_reset_internal;
580
581 memset(new_config, 0 , sizeof(new_config));
582 if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
583 ENABLE_INTERNAL_LOOPBACK ||
584 (config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
585 ENABLE_EXTERNAL_LOOPBACK) {
586 new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
587 ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
588 (new_config[0] & INTERNAL_LOOPBACK_MASK));
589 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
590
591 ha->notify_dcbx_comp = wait;
592 ha->notify_lb_portup_comp = wait2;
593
594 ret = qla81xx_set_port_config(vha, new_config);
595 if (ret != QLA_SUCCESS) {
596 ql_log(ql_log_warn, vha, 0x7025,
597 "Set port config failed.\n");
598 ha->notify_dcbx_comp = 0;
599 ha->notify_lb_portup_comp = 0;
600 rval = -EINVAL;
601 goto done_reset_internal;
602 }
603
604
605 if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
606 (DCBX_COMP_TIMEOUT * HZ))) {
607 ql_dbg(ql_dbg_user, vha, 0x7026,
608 "DCBX completion not received.\n");
609 ha->notify_dcbx_comp = 0;
610 ha->notify_lb_portup_comp = 0;
611 rval = -EINVAL;
612 goto done_reset_internal;
613 } else
614 ql_dbg(ql_dbg_user, vha, 0x7027,
615 "DCBX completion received.\n");
616
617 if (wait2 &&
618 !wait_for_completion_timeout(&ha->lb_portup_comp,
619 (LB_PORTUP_COMP_TIMEOUT * HZ))) {
620 ql_dbg(ql_dbg_user, vha, 0x70c5,
621 "Port up completion not received.\n");
622 ha->notify_lb_portup_comp = 0;
623 rval = -EINVAL;
624 goto done_reset_internal;
625 } else
626 ql_dbg(ql_dbg_user, vha, 0x70c6,
627 "Port up completion received.\n");
628
629 ha->notify_dcbx_comp = 0;
630 ha->notify_lb_portup_comp = 0;
631 }
632done_reset_internal:
633 return rval;
634}
635
636
637
638
639
640static inline int
641qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
642 uint16_t *new_config, uint16_t mode)
643{
644 int ret = 0;
645 int rval = 0;
646 unsigned long rem_tmo = 0, current_tmo = 0;
647 struct qla_hw_data *ha = vha->hw;
648
649 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha))
650 goto done_set_internal;
651
652 if (mode == INTERNAL_LOOPBACK)
653 new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
654 else if (mode == EXTERNAL_LOOPBACK)
655 new_config[0] = config[0] | (ENABLE_EXTERNAL_LOOPBACK << 1);
656 ql_dbg(ql_dbg_user, vha, 0x70be,
657 "new_config[0]=%02x\n", (new_config[0] & INTERNAL_LOOPBACK_MASK));
658
659 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3);
660
661 ha->notify_dcbx_comp = 1;
662 ret = qla81xx_set_port_config(vha, new_config);
663 if (ret != QLA_SUCCESS) {
664 ql_log(ql_log_warn, vha, 0x7021,
665 "set port config failed.\n");
666 ha->notify_dcbx_comp = 0;
667 rval = -EINVAL;
668 goto done_set_internal;
669 }
670
671
672 current_tmo = DCBX_COMP_TIMEOUT * HZ;
673 while (1) {
674 rem_tmo = wait_for_completion_timeout(&ha->dcbx_comp,
675 current_tmo);
676 if (!ha->idc_extend_tmo || rem_tmo) {
677 ha->idc_extend_tmo = 0;
678 break;
679 }
680 current_tmo = ha->idc_extend_tmo * HZ;
681 ha->idc_extend_tmo = 0;
682 }
683
684 if (!rem_tmo) {
685 ql_dbg(ql_dbg_user, vha, 0x7022,
686 "DCBX completion not received.\n");
687 ret = qla81xx_reset_loopback_mode(vha, new_config, 0, 0);
688
689
690
691
692 if (ret) {
693 qla2xxx_dump_fw(vha);
694 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
695 }
696 rval = -EINVAL;
697 } else {
698 if (ha->flags.idc_compl_status) {
699 ql_dbg(ql_dbg_user, vha, 0x70c3,
700 "Bad status in IDC Completion AEN\n");
701 rval = -EINVAL;
702 ha->flags.idc_compl_status = 0;
703 } else
704 ql_dbg(ql_dbg_user, vha, 0x7023,
705 "DCBX completion received.\n");
706 }
707
708 ha->notify_dcbx_comp = 0;
709 ha->idc_extend_tmo = 0;
710
711done_set_internal:
712 return rval;
713}
714
715static int
716qla2x00_process_loopback(struct bsg_job *bsg_job)
717{
718 struct fc_bsg_request *bsg_request = bsg_job->request;
719 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
720 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
721 scsi_qla_host_t *vha = shost_priv(host);
722 struct qla_hw_data *ha = vha->hw;
723 int rval;
724 uint8_t command_sent;
725 char *type;
726 struct msg_echo_lb elreq;
727 uint16_t response[MAILBOX_REGISTER_COUNT];
728 uint16_t config[4], new_config[4];
729 uint8_t *fw_sts_ptr;
730 void *req_data = NULL;
731 dma_addr_t req_data_dma;
732 uint32_t req_data_len;
733 uint8_t *rsp_data = NULL;
734 dma_addr_t rsp_data_dma;
735 uint32_t rsp_data_len;
736
737 if (!vha->flags.online) {
738 ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
739 return -EIO;
740 }
741
742 memset(&elreq, 0, sizeof(elreq));
743
744 elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
745 bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
746 DMA_TO_DEVICE);
747
748 if (!elreq.req_sg_cnt) {
749 ql_log(ql_log_warn, vha, 0x701a,
750 "dma_map_sg returned %d for request.\n", elreq.req_sg_cnt);
751 return -ENOMEM;
752 }
753
754 elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
755 bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
756 DMA_FROM_DEVICE);
757
758 if (!elreq.rsp_sg_cnt) {
759 ql_log(ql_log_warn, vha, 0x701b,
760 "dma_map_sg returned %d for reply.\n", elreq.rsp_sg_cnt);
761 rval = -ENOMEM;
762 goto done_unmap_req_sg;
763 }
764
765 if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
766 (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
767 ql_log(ql_log_warn, vha, 0x701c,
768 "dma mapping resulted in different sg counts, "
769 "request_sg_cnt: %x dma_request_sg_cnt: %x "
770 "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
771 bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
772 bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt);
773 rval = -EAGAIN;
774 goto done_unmap_sg;
775 }
776 req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
777 req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
778 &req_data_dma, GFP_KERNEL);
779 if (!req_data) {
780 ql_log(ql_log_warn, vha, 0x701d,
781 "dma alloc failed for req_data.\n");
782 rval = -ENOMEM;
783 goto done_unmap_sg;
784 }
785
786 rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
787 &rsp_data_dma, GFP_KERNEL);
788 if (!rsp_data) {
789 ql_log(ql_log_warn, vha, 0x7004,
790 "dma alloc failed for rsp_data.\n");
791 rval = -ENOMEM;
792 goto done_free_dma_req;
793 }
794
795
796 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
797 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
798
799 elreq.send_dma = req_data_dma;
800 elreq.rcv_dma = rsp_data_dma;
801 elreq.transfer_size = req_data_len;
802
803 elreq.options = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
804 elreq.iteration_count =
805 bsg_request->rqst_data.h_vendor.vendor_cmd[2];
806
807 if (atomic_read(&vha->loop_state) == LOOP_READY &&
808 ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) ||
809 ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
810 get_unaligned_le32(req_data) == ELS_OPCODE_BYTE &&
811 req_data_len == MAX_ELS_FRAME_PAYLOAD &&
812 elreq.options == EXTERNAL_LOOPBACK))) {
813 type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
814 ql_dbg(ql_dbg_user, vha, 0x701e,
815 "BSG request type: %s.\n", type);
816 command_sent = INT_DEF_LB_ECHO_CMD;
817 rval = qla2x00_echo_test(vha, &elreq, response);
818 } else {
819 if (IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) {
820 memset(config, 0, sizeof(config));
821 memset(new_config, 0, sizeof(new_config));
822
823 if (qla81xx_get_port_config(vha, config)) {
824 ql_log(ql_log_warn, vha, 0x701f,
825 "Get port config failed.\n");
826 rval = -EPERM;
827 goto done_free_dma_rsp;
828 }
829
830 if ((config[0] & INTERNAL_LOOPBACK_MASK) != 0) {
831 ql_dbg(ql_dbg_user, vha, 0x70c4,
832 "Loopback operation already in "
833 "progress.\n");
834 rval = -EAGAIN;
835 goto done_free_dma_rsp;
836 }
837
838 ql_dbg(ql_dbg_user, vha, 0x70c0,
839 "elreq.options=%04x\n", elreq.options);
840
841 if (elreq.options == EXTERNAL_LOOPBACK)
842 if (IS_QLA8031(ha) || IS_QLA8044(ha))
843 rval = qla81xx_set_loopback_mode(vha,
844 config, new_config, elreq.options);
845 else
846 rval = qla81xx_reset_loopback_mode(vha,
847 config, 1, 0);
848 else
849 rval = qla81xx_set_loopback_mode(vha, config,
850 new_config, elreq.options);
851
852 if (rval) {
853 rval = -EPERM;
854 goto done_free_dma_rsp;
855 }
856
857 type = "FC_BSG_HST_VENDOR_LOOPBACK";
858 ql_dbg(ql_dbg_user, vha, 0x7028,
859 "BSG request type: %s.\n", type);
860
861 command_sent = INT_DEF_LB_LOOPBACK_CMD;
862 rval = qla2x00_loopback_test(vha, &elreq, response);
863
864 if (response[0] == MBS_COMMAND_ERROR &&
865 response[1] == MBS_LB_RESET) {
866 ql_log(ql_log_warn, vha, 0x7029,
867 "MBX command error, Aborting ISP.\n");
868 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
869 qla2xxx_wake_dpc(vha);
870 qla2x00_wait_for_chip_reset(vha);
871
872 if (IS_QLA81XX(ha)) {
873 if (qla81xx_restart_mpi_firmware(vha) !=
874 QLA_SUCCESS) {
875 ql_log(ql_log_warn, vha, 0x702a,
876 "MPI reset failed.\n");
877 }
878 }
879
880 rval = -EIO;
881 goto done_free_dma_rsp;
882 }
883
884 if (new_config[0]) {
885 int ret;
886
887
888
889
890 ret = qla81xx_reset_loopback_mode(vha,
891 new_config, 0, 1);
892 if (ret) {
893
894
895
896
897
898 qla2xxx_dump_fw(vha);
899 set_bit(ISP_ABORT_NEEDED,
900 &vha->dpc_flags);
901 }
902
903 }
904
905 } else {
906 type = "FC_BSG_HST_VENDOR_LOOPBACK";
907 ql_dbg(ql_dbg_user, vha, 0x702b,
908 "BSG request type: %s.\n", type);
909 command_sent = INT_DEF_LB_LOOPBACK_CMD;
910 rval = qla2x00_loopback_test(vha, &elreq, response);
911 }
912 }
913
914 if (rval) {
915 ql_log(ql_log_warn, vha, 0x702c,
916 "Vendor request %s failed.\n", type);
917
918 rval = 0;
919 bsg_reply->result = (DID_ERROR << 16);
920 bsg_reply->reply_payload_rcv_len = 0;
921 } else {
922 ql_dbg(ql_dbg_user, vha, 0x702d,
923 "Vendor request %s completed.\n", type);
924 bsg_reply->result = (DID_OK << 16);
925 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
926 bsg_job->reply_payload.sg_cnt, rsp_data,
927 rsp_data_len);
928 }
929
930 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
931 sizeof(response) + sizeof(uint8_t);
932 fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply);
933 memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), response,
934 sizeof(response));
935 fw_sts_ptr += sizeof(response);
936 *fw_sts_ptr = command_sent;
937
938done_free_dma_rsp:
939 dma_free_coherent(&ha->pdev->dev, rsp_data_len,
940 rsp_data, rsp_data_dma);
941done_free_dma_req:
942 dma_free_coherent(&ha->pdev->dev, req_data_len,
943 req_data, req_data_dma);
944done_unmap_sg:
945 dma_unmap_sg(&ha->pdev->dev,
946 bsg_job->reply_payload.sg_list,
947 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
948done_unmap_req_sg:
949 dma_unmap_sg(&ha->pdev->dev,
950 bsg_job->request_payload.sg_list,
951 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
952 if (!rval)
953 bsg_job_done(bsg_job, bsg_reply->result,
954 bsg_reply->reply_payload_rcv_len);
955 return rval;
956}
957
958static int
959qla84xx_reset(struct bsg_job *bsg_job)
960{
961 struct fc_bsg_request *bsg_request = bsg_job->request;
962 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
963 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
964 scsi_qla_host_t *vha = shost_priv(host);
965 struct qla_hw_data *ha = vha->hw;
966 int rval = 0;
967 uint32_t flag;
968
969 if (!IS_QLA84XX(ha)) {
970 ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
971 return -EINVAL;
972 }
973
974 flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
975
976 rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
977
978 if (rval) {
979 ql_log(ql_log_warn, vha, 0x7030,
980 "Vendor request 84xx reset failed.\n");
981 rval = (DID_ERROR << 16);
982
983 } else {
984 ql_dbg(ql_dbg_user, vha, 0x7031,
985 "Vendor request 84xx reset completed.\n");
986 bsg_reply->result = DID_OK;
987 bsg_job_done(bsg_job, bsg_reply->result,
988 bsg_reply->reply_payload_rcv_len);
989 }
990
991 return rval;
992}
993
994static int
995qla84xx_updatefw(struct bsg_job *bsg_job)
996{
997 struct fc_bsg_request *bsg_request = bsg_job->request;
998 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
999 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1000 scsi_qla_host_t *vha = shost_priv(host);
1001 struct qla_hw_data *ha = vha->hw;
1002 struct verify_chip_entry_84xx *mn = NULL;
1003 dma_addr_t mn_dma, fw_dma;
1004 void *fw_buf = NULL;
1005 int rval = 0;
1006 uint32_t sg_cnt;
1007 uint32_t data_len;
1008 uint16_t options;
1009 uint32_t flag;
1010 uint32_t fw_ver;
1011
1012 if (!IS_QLA84XX(ha)) {
1013 ql_dbg(ql_dbg_user, vha, 0x7032,
1014 "Not 84xx, exiting.\n");
1015 return -EINVAL;
1016 }
1017
1018 sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1019 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1020 if (!sg_cnt) {
1021 ql_log(ql_log_warn, vha, 0x7033,
1022 "dma_map_sg returned %d for request.\n", sg_cnt);
1023 return -ENOMEM;
1024 }
1025
1026 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1027 ql_log(ql_log_warn, vha, 0x7034,
1028 "DMA mapping resulted in different sg counts, "
1029 "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1030 bsg_job->request_payload.sg_cnt, sg_cnt);
1031 rval = -EAGAIN;
1032 goto done_unmap_sg;
1033 }
1034
1035 data_len = bsg_job->request_payload.payload_len;
1036 fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
1037 &fw_dma, GFP_KERNEL);
1038 if (!fw_buf) {
1039 ql_log(ql_log_warn, vha, 0x7035,
1040 "DMA alloc failed for fw_buf.\n");
1041 rval = -ENOMEM;
1042 goto done_unmap_sg;
1043 }
1044
1045 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1046 bsg_job->request_payload.sg_cnt, fw_buf, data_len);
1047
1048 mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1049 if (!mn) {
1050 ql_log(ql_log_warn, vha, 0x7036,
1051 "DMA alloc failed for fw buffer.\n");
1052 rval = -ENOMEM;
1053 goto done_free_fw_buf;
1054 }
1055
1056 flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1057 fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2);
1058
1059 mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
1060 mn->entry_count = 1;
1061
1062 options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
1063 if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD)
1064 options |= VCO_DIAG_FW;
1065
1066 mn->options = cpu_to_le16(options);
1067 mn->fw_ver = cpu_to_le32(fw_ver);
1068 mn->fw_size = cpu_to_le32(data_len);
1069 mn->fw_seq_size = cpu_to_le32(data_len);
1070 put_unaligned_le64(fw_dma, &mn->dsd.address);
1071 mn->dsd.length = cpu_to_le32(data_len);
1072 mn->data_seg_cnt = cpu_to_le16(1);
1073
1074 rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
1075
1076 if (rval) {
1077 ql_log(ql_log_warn, vha, 0x7037,
1078 "Vendor request 84xx updatefw failed.\n");
1079
1080 rval = (DID_ERROR << 16);
1081 } else {
1082 ql_dbg(ql_dbg_user, vha, 0x7038,
1083 "Vendor request 84xx updatefw completed.\n");
1084
1085 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1086 bsg_reply->result = DID_OK;
1087 }
1088
1089 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1090
1091done_free_fw_buf:
1092 dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma);
1093
1094done_unmap_sg:
1095 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1096 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1097
1098 if (!rval)
1099 bsg_job_done(bsg_job, bsg_reply->result,
1100 bsg_reply->reply_payload_rcv_len);
1101 return rval;
1102}
1103
1104static int
1105qla84xx_mgmt_cmd(struct bsg_job *bsg_job)
1106{
1107 struct fc_bsg_request *bsg_request = bsg_job->request;
1108 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1109 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1110 scsi_qla_host_t *vha = shost_priv(host);
1111 struct qla_hw_data *ha = vha->hw;
1112 struct access_chip_84xx *mn = NULL;
1113 dma_addr_t mn_dma, mgmt_dma;
1114 void *mgmt_b = NULL;
1115 int rval = 0;
1116 struct qla_bsg_a84_mgmt *ql84_mgmt;
1117 uint32_t sg_cnt;
1118 uint32_t data_len = 0;
1119 uint32_t dma_direction = DMA_NONE;
1120
1121 if (!IS_QLA84XX(ha)) {
1122 ql_log(ql_log_warn, vha, 0x703a,
1123 "Not 84xx, exiting.\n");
1124 return -EINVAL;
1125 }
1126
1127 mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1128 if (!mn) {
1129 ql_log(ql_log_warn, vha, 0x703c,
1130 "DMA alloc failed for fw buffer.\n");
1131 return -ENOMEM;
1132 }
1133
1134 mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
1135 mn->entry_count = 1;
1136 ql84_mgmt = (void *)bsg_request + sizeof(struct fc_bsg_request);
1137 switch (ql84_mgmt->mgmt.cmd) {
1138 case QLA84_MGMT_READ_MEM:
1139 case QLA84_MGMT_GET_INFO:
1140 sg_cnt = dma_map_sg(&ha->pdev->dev,
1141 bsg_job->reply_payload.sg_list,
1142 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1143 if (!sg_cnt) {
1144 ql_log(ql_log_warn, vha, 0x703d,
1145 "dma_map_sg returned %d for reply.\n", sg_cnt);
1146 rval = -ENOMEM;
1147 goto exit_mgmt;
1148 }
1149
1150 dma_direction = DMA_FROM_DEVICE;
1151
1152 if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
1153 ql_log(ql_log_warn, vha, 0x703e,
1154 "DMA mapping resulted in different sg counts, "
1155 "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
1156 bsg_job->reply_payload.sg_cnt, sg_cnt);
1157 rval = -EAGAIN;
1158 goto done_unmap_sg;
1159 }
1160
1161 data_len = bsg_job->reply_payload.payload_len;
1162
1163 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1164 &mgmt_dma, GFP_KERNEL);
1165 if (!mgmt_b) {
1166 ql_log(ql_log_warn, vha, 0x703f,
1167 "DMA alloc failed for mgmt_b.\n");
1168 rval = -ENOMEM;
1169 goto done_unmap_sg;
1170 }
1171
1172 if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) {
1173 mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
1174 mn->parameter1 =
1175 cpu_to_le32(
1176 ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1177
1178 } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) {
1179 mn->options = cpu_to_le16(ACO_REQUEST_INFO);
1180 mn->parameter1 =
1181 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type);
1182
1183 mn->parameter2 =
1184 cpu_to_le32(
1185 ql84_mgmt->mgmt.mgmtp.u.info.context);
1186 }
1187 break;
1188
1189 case QLA84_MGMT_WRITE_MEM:
1190 sg_cnt = dma_map_sg(&ha->pdev->dev,
1191 bsg_job->request_payload.sg_list,
1192 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1193
1194 if (!sg_cnt) {
1195 ql_log(ql_log_warn, vha, 0x7040,
1196 "dma_map_sg returned %d.\n", sg_cnt);
1197 rval = -ENOMEM;
1198 goto exit_mgmt;
1199 }
1200
1201 dma_direction = DMA_TO_DEVICE;
1202
1203 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1204 ql_log(ql_log_warn, vha, 0x7041,
1205 "DMA mapping resulted in different sg counts, "
1206 "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1207 bsg_job->request_payload.sg_cnt, sg_cnt);
1208 rval = -EAGAIN;
1209 goto done_unmap_sg;
1210 }
1211
1212 data_len = bsg_job->request_payload.payload_len;
1213 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1214 &mgmt_dma, GFP_KERNEL);
1215 if (!mgmt_b) {
1216 ql_log(ql_log_warn, vha, 0x7042,
1217 "DMA alloc failed for mgmt_b.\n");
1218 rval = -ENOMEM;
1219 goto done_unmap_sg;
1220 }
1221
1222 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1223 bsg_job->request_payload.sg_cnt, mgmt_b, data_len);
1224
1225 mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
1226 mn->parameter1 =
1227 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1228 break;
1229
1230 case QLA84_MGMT_CHNG_CONFIG:
1231 mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
1232 mn->parameter1 =
1233 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id);
1234
1235 mn->parameter2 =
1236 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0);
1237
1238 mn->parameter3 =
1239 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1);
1240 break;
1241
1242 default:
1243 rval = -EIO;
1244 goto exit_mgmt;
1245 }
1246
1247 if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
1248 mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
1249 mn->dseg_count = cpu_to_le16(1);
1250 put_unaligned_le64(mgmt_dma, &mn->dsd.address);
1251 mn->dsd.length = cpu_to_le32(ql84_mgmt->mgmt.len);
1252 }
1253
1254 rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
1255
1256 if (rval) {
1257 ql_log(ql_log_warn, vha, 0x7043,
1258 "Vendor request 84xx mgmt failed.\n");
1259
1260 rval = (DID_ERROR << 16);
1261
1262 } else {
1263 ql_dbg(ql_dbg_user, vha, 0x7044,
1264 "Vendor request 84xx mgmt completed.\n");
1265
1266 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1267 bsg_reply->result = DID_OK;
1268
1269 if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
1270 (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
1271 bsg_reply->reply_payload_rcv_len =
1272 bsg_job->reply_payload.payload_len;
1273
1274 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1275 bsg_job->reply_payload.sg_cnt, mgmt_b,
1276 data_len);
1277 }
1278 }
1279
1280done_unmap_sg:
1281 if (mgmt_b)
1282 dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
1283
1284 if (dma_direction == DMA_TO_DEVICE)
1285 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1286 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1287 else if (dma_direction == DMA_FROM_DEVICE)
1288 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1289 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1290
1291exit_mgmt:
1292 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1293
1294 if (!rval)
1295 bsg_job_done(bsg_job, bsg_reply->result,
1296 bsg_reply->reply_payload_rcv_len);
1297 return rval;
1298}
1299
1300static int
1301qla24xx_iidma(struct bsg_job *bsg_job)
1302{
1303 struct fc_bsg_request *bsg_request = bsg_job->request;
1304 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1305 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1306 scsi_qla_host_t *vha = shost_priv(host);
1307 int rval = 0;
1308 struct qla_port_param *port_param = NULL;
1309 fc_port_t *fcport = NULL;
1310 int found = 0;
1311 uint16_t mb[MAILBOX_REGISTER_COUNT];
1312 uint8_t *rsp_ptr = NULL;
1313
1314 if (!IS_IIDMA_CAPABLE(vha->hw)) {
1315 ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
1316 return -EINVAL;
1317 }
1318
1319 port_param = (void *)bsg_request + sizeof(struct fc_bsg_request);
1320 if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
1321 ql_log(ql_log_warn, vha, 0x7048,
1322 "Invalid destination type.\n");
1323 return -EINVAL;
1324 }
1325
1326 list_for_each_entry(fcport, &vha->vp_fcports, list) {
1327 if (fcport->port_type != FCT_TARGET)
1328 continue;
1329
1330 if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn,
1331 fcport->port_name, sizeof(fcport->port_name)))
1332 continue;
1333
1334 found = 1;
1335 break;
1336 }
1337
1338 if (!found) {
1339 ql_log(ql_log_warn, vha, 0x7049,
1340 "Failed to find port.\n");
1341 return -EINVAL;
1342 }
1343
1344 if (atomic_read(&fcport->state) != FCS_ONLINE) {
1345 ql_log(ql_log_warn, vha, 0x704a,
1346 "Port is not online.\n");
1347 return -EINVAL;
1348 }
1349
1350 if (fcport->flags & FCF_LOGIN_NEEDED) {
1351 ql_log(ql_log_warn, vha, 0x704b,
1352 "Remote port not logged in flags = 0x%x.\n", fcport->flags);
1353 return -EINVAL;
1354 }
1355
1356 if (port_param->mode)
1357 rval = qla2x00_set_idma_speed(vha, fcport->loop_id,
1358 port_param->speed, mb);
1359 else
1360 rval = qla2x00_get_idma_speed(vha, fcport->loop_id,
1361 &port_param->speed, mb);
1362
1363 if (rval) {
1364 ql_log(ql_log_warn, vha, 0x704c,
1365 "iiDMA cmd failed for %8phN -- "
1366 "%04x %x %04x %04x.\n", fcport->port_name,
1367 rval, fcport->fp_speed, mb[0], mb[1]);
1368 rval = (DID_ERROR << 16);
1369 } else {
1370 if (!port_param->mode) {
1371 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
1372 sizeof(struct qla_port_param);
1373
1374 rsp_ptr = ((uint8_t *)bsg_reply) +
1375 sizeof(struct fc_bsg_reply);
1376
1377 memcpy(rsp_ptr, port_param,
1378 sizeof(struct qla_port_param));
1379 }
1380
1381 bsg_reply->result = DID_OK;
1382 bsg_job_done(bsg_job, bsg_reply->result,
1383 bsg_reply->reply_payload_rcv_len);
1384 }
1385
1386 return rval;
1387}
1388
1389static int
1390qla2x00_optrom_setup(struct bsg_job *bsg_job, scsi_qla_host_t *vha,
1391 uint8_t is_update)
1392{
1393 struct fc_bsg_request *bsg_request = bsg_job->request;
1394 uint32_t start = 0;
1395 int valid = 0;
1396 struct qla_hw_data *ha = vha->hw;
1397
1398 if (unlikely(pci_channel_offline(ha->pdev)))
1399 return -EINVAL;
1400
1401 start = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1402 if (start > ha->optrom_size) {
1403 ql_log(ql_log_warn, vha, 0x7055,
1404 "start %d > optrom_size %d.\n", start, ha->optrom_size);
1405 return -EINVAL;
1406 }
1407
1408 if (ha->optrom_state != QLA_SWAITING) {
1409 ql_log(ql_log_info, vha, 0x7056,
1410 "optrom_state %d.\n", ha->optrom_state);
1411 return -EBUSY;
1412 }
1413
1414 ha->optrom_region_start = start;
1415 ql_dbg(ql_dbg_user, vha, 0x7057, "is_update=%d.\n", is_update);
1416 if (is_update) {
1417 if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
1418 valid = 1;
1419 else if (start == (ha->flt_region_boot * 4) ||
1420 start == (ha->flt_region_fw * 4))
1421 valid = 1;
1422 else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
1423 IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
1424 IS_QLA28XX(ha))
1425 valid = 1;
1426 if (!valid) {
1427 ql_log(ql_log_warn, vha, 0x7058,
1428 "Invalid start region 0x%x/0x%x.\n", start,
1429 bsg_job->request_payload.payload_len);
1430 return -EINVAL;
1431 }
1432
1433 ha->optrom_region_size = start +
1434 bsg_job->request_payload.payload_len > ha->optrom_size ?
1435 ha->optrom_size - start :
1436 bsg_job->request_payload.payload_len;
1437 ha->optrom_state = QLA_SWRITING;
1438 } else {
1439 ha->optrom_region_size = start +
1440 bsg_job->reply_payload.payload_len > ha->optrom_size ?
1441 ha->optrom_size - start :
1442 bsg_job->reply_payload.payload_len;
1443 ha->optrom_state = QLA_SREADING;
1444 }
1445
1446 ha->optrom_buffer = vzalloc(ha->optrom_region_size);
1447 if (!ha->optrom_buffer) {
1448 ql_log(ql_log_warn, vha, 0x7059,
1449 "Read: Unable to allocate memory for optrom retrieval "
1450 "(%x)\n", ha->optrom_region_size);
1451
1452 ha->optrom_state = QLA_SWAITING;
1453 return -ENOMEM;
1454 }
1455
1456 return 0;
1457}
1458
1459static int
1460qla2x00_read_optrom(struct bsg_job *bsg_job)
1461{
1462 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1463 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1464 scsi_qla_host_t *vha = shost_priv(host);
1465 struct qla_hw_data *ha = vha->hw;
1466 int rval = 0;
1467
1468 if (ha->flags.nic_core_reset_hdlr_active)
1469 return -EBUSY;
1470
1471 mutex_lock(&ha->optrom_mutex);
1472 rval = qla2x00_optrom_setup(bsg_job, vha, 0);
1473 if (rval) {
1474 mutex_unlock(&ha->optrom_mutex);
1475 return rval;
1476 }
1477
1478 ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
1479 ha->optrom_region_start, ha->optrom_region_size);
1480
1481 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1482 bsg_job->reply_payload.sg_cnt, ha->optrom_buffer,
1483 ha->optrom_region_size);
1484
1485 bsg_reply->reply_payload_rcv_len = ha->optrom_region_size;
1486 bsg_reply->result = DID_OK;
1487 vfree(ha->optrom_buffer);
1488 ha->optrom_buffer = NULL;
1489 ha->optrom_state = QLA_SWAITING;
1490 mutex_unlock(&ha->optrom_mutex);
1491 bsg_job_done(bsg_job, bsg_reply->result,
1492 bsg_reply->reply_payload_rcv_len);
1493 return rval;
1494}
1495
1496static int
1497qla2x00_update_optrom(struct bsg_job *bsg_job)
1498{
1499 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1500 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1501 scsi_qla_host_t *vha = shost_priv(host);
1502 struct qla_hw_data *ha = vha->hw;
1503 int rval = 0;
1504
1505 mutex_lock(&ha->optrom_mutex);
1506 rval = qla2x00_optrom_setup(bsg_job, vha, 1);
1507 if (rval) {
1508 mutex_unlock(&ha->optrom_mutex);
1509 return rval;
1510 }
1511
1512
1513 ha->flags.isp82xx_no_md_cap = 1;
1514
1515 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1516 bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
1517 ha->optrom_region_size);
1518
1519 rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
1520 ha->optrom_region_start, ha->optrom_region_size);
1521
1522 if (rval) {
1523 bsg_reply->result = -EINVAL;
1524 rval = -EINVAL;
1525 } else {
1526 bsg_reply->result = DID_OK;
1527 }
1528 vfree(ha->optrom_buffer);
1529 ha->optrom_buffer = NULL;
1530 ha->optrom_state = QLA_SWAITING;
1531 mutex_unlock(&ha->optrom_mutex);
1532 bsg_job_done(bsg_job, bsg_reply->result,
1533 bsg_reply->reply_payload_rcv_len);
1534 return rval;
1535}
1536
1537static int
1538qla2x00_update_fru_versions(struct bsg_job *bsg_job)
1539{
1540 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1541 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1542 scsi_qla_host_t *vha = shost_priv(host);
1543 struct qla_hw_data *ha = vha->hw;
1544 int rval = 0;
1545 uint8_t bsg[DMA_POOL_SIZE];
1546 struct qla_image_version_list *list = (void *)bsg;
1547 struct qla_image_version *image;
1548 uint32_t count;
1549 dma_addr_t sfp_dma;
1550 void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1551
1552 if (!sfp) {
1553 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1554 EXT_STATUS_NO_MEMORY;
1555 goto done;
1556 }
1557
1558 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1559 bsg_job->request_payload.sg_cnt, list, sizeof(bsg));
1560
1561 image = list->version;
1562 count = list->count;
1563 while (count--) {
1564 memcpy(sfp, &image->field_info, sizeof(image->field_info));
1565 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1566 image->field_address.device, image->field_address.offset,
1567 sizeof(image->field_info), image->field_address.option);
1568 if (rval) {
1569 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1570 EXT_STATUS_MAILBOX;
1571 goto dealloc;
1572 }
1573 image++;
1574 }
1575
1576 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1577
1578dealloc:
1579 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1580
1581done:
1582 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1583 bsg_reply->result = DID_OK << 16;
1584 bsg_job_done(bsg_job, bsg_reply->result,
1585 bsg_reply->reply_payload_rcv_len);
1586
1587 return 0;
1588}
1589
1590static int
1591qla2x00_read_fru_status(struct bsg_job *bsg_job)
1592{
1593 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1594 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1595 scsi_qla_host_t *vha = shost_priv(host);
1596 struct qla_hw_data *ha = vha->hw;
1597 int rval = 0;
1598 uint8_t bsg[DMA_POOL_SIZE];
1599 struct qla_status_reg *sr = (void *)bsg;
1600 dma_addr_t sfp_dma;
1601 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1602
1603 if (!sfp) {
1604 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1605 EXT_STATUS_NO_MEMORY;
1606 goto done;
1607 }
1608
1609 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1610 bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
1611
1612 rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1613 sr->field_address.device, sr->field_address.offset,
1614 sizeof(sr->status_reg), sr->field_address.option);
1615 sr->status_reg = *sfp;
1616
1617 if (rval) {
1618 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1619 EXT_STATUS_MAILBOX;
1620 goto dealloc;
1621 }
1622
1623 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1624 bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr));
1625
1626 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1627
1628dealloc:
1629 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1630
1631done:
1632 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1633 bsg_reply->reply_payload_rcv_len = sizeof(*sr);
1634 bsg_reply->result = DID_OK << 16;
1635 bsg_job_done(bsg_job, bsg_reply->result,
1636 bsg_reply->reply_payload_rcv_len);
1637
1638 return 0;
1639}
1640
1641static int
1642qla2x00_write_fru_status(struct bsg_job *bsg_job)
1643{
1644 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1645 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1646 scsi_qla_host_t *vha = shost_priv(host);
1647 struct qla_hw_data *ha = vha->hw;
1648 int rval = 0;
1649 uint8_t bsg[DMA_POOL_SIZE];
1650 struct qla_status_reg *sr = (void *)bsg;
1651 dma_addr_t sfp_dma;
1652 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1653
1654 if (!sfp) {
1655 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1656 EXT_STATUS_NO_MEMORY;
1657 goto done;
1658 }
1659
1660 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1661 bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
1662
1663 *sfp = sr->status_reg;
1664 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1665 sr->field_address.device, sr->field_address.offset,
1666 sizeof(sr->status_reg), sr->field_address.option);
1667
1668 if (rval) {
1669 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1670 EXT_STATUS_MAILBOX;
1671 goto dealloc;
1672 }
1673
1674 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1675
1676dealloc:
1677 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1678
1679done:
1680 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1681 bsg_reply->result = DID_OK << 16;
1682 bsg_job_done(bsg_job, bsg_reply->result,
1683 bsg_reply->reply_payload_rcv_len);
1684
1685 return 0;
1686}
1687
1688static int
1689qla2x00_write_i2c(struct bsg_job *bsg_job)
1690{
1691 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1692 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1693 scsi_qla_host_t *vha = shost_priv(host);
1694 struct qla_hw_data *ha = vha->hw;
1695 int rval = 0;
1696 uint8_t bsg[DMA_POOL_SIZE];
1697 struct qla_i2c_access *i2c = (void *)bsg;
1698 dma_addr_t sfp_dma;
1699 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1700
1701 if (!sfp) {
1702 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1703 EXT_STATUS_NO_MEMORY;
1704 goto done;
1705 }
1706
1707 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1708 bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1709
1710 memcpy(sfp, i2c->buffer, i2c->length);
1711 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1712 i2c->device, i2c->offset, i2c->length, i2c->option);
1713
1714 if (rval) {
1715 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1716 EXT_STATUS_MAILBOX;
1717 goto dealloc;
1718 }
1719
1720 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1721
1722dealloc:
1723 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1724
1725done:
1726 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1727 bsg_reply->result = DID_OK << 16;
1728 bsg_job_done(bsg_job, bsg_reply->result,
1729 bsg_reply->reply_payload_rcv_len);
1730
1731 return 0;
1732}
1733
1734static int
1735qla2x00_read_i2c(struct bsg_job *bsg_job)
1736{
1737 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1738 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1739 scsi_qla_host_t *vha = shost_priv(host);
1740 struct qla_hw_data *ha = vha->hw;
1741 int rval = 0;
1742 uint8_t bsg[DMA_POOL_SIZE];
1743 struct qla_i2c_access *i2c = (void *)bsg;
1744 dma_addr_t sfp_dma;
1745 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1746
1747 if (!sfp) {
1748 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1749 EXT_STATUS_NO_MEMORY;
1750 goto done;
1751 }
1752
1753 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1754 bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1755
1756 rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1757 i2c->device, i2c->offset, i2c->length, i2c->option);
1758
1759 if (rval) {
1760 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1761 EXT_STATUS_MAILBOX;
1762 goto dealloc;
1763 }
1764
1765 memcpy(i2c->buffer, sfp, i2c->length);
1766 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1767 bsg_job->reply_payload.sg_cnt, i2c, sizeof(*i2c));
1768
1769 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1770
1771dealloc:
1772 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1773
1774done:
1775 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1776 bsg_reply->reply_payload_rcv_len = sizeof(*i2c);
1777 bsg_reply->result = DID_OK << 16;
1778 bsg_job_done(bsg_job, bsg_reply->result,
1779 bsg_reply->reply_payload_rcv_len);
1780
1781 return 0;
1782}
1783
1784static int
1785qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
1786{
1787 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1788 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1789 scsi_qla_host_t *vha = shost_priv(host);
1790 struct qla_hw_data *ha = vha->hw;
1791 uint32_t rval = EXT_STATUS_OK;
1792 uint16_t req_sg_cnt = 0;
1793 uint16_t rsp_sg_cnt = 0;
1794 uint16_t nextlid = 0;
1795 uint32_t tot_dsds;
1796 srb_t *sp = NULL;
1797 uint32_t req_data_len;
1798 uint32_t rsp_data_len;
1799
1800
1801 if (!IS_BIDI_CAPABLE(ha)) {
1802 ql_log(ql_log_warn, vha, 0x70a0,
1803 "This adapter is not supported\n");
1804 rval = EXT_STATUS_NOT_SUPPORTED;
1805 goto done;
1806 }
1807
1808 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1809 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1810 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
1811 rval = EXT_STATUS_BUSY;
1812 goto done;
1813 }
1814
1815
1816 if (!vha->flags.online) {
1817 ql_log(ql_log_warn, vha, 0x70a1,
1818 "Host is not online\n");
1819 rval = EXT_STATUS_DEVICE_OFFLINE;
1820 goto done;
1821 }
1822
1823
1824 if (vha->device_flags & DFLG_NO_CABLE) {
1825 ql_log(ql_log_warn, vha, 0x70a2,
1826 "Cable is unplugged...\n");
1827 rval = EXT_STATUS_INVALID_CFG;
1828 goto done;
1829 }
1830
1831
1832 if (ha->current_topology != ISP_CFG_F) {
1833 ql_log(ql_log_warn, vha, 0x70a3,
1834 "Host is not connected to the switch\n");
1835 rval = EXT_STATUS_INVALID_CFG;
1836 goto done;
1837 }
1838
1839
1840 if (ha->operating_mode != P2P) {
1841 ql_log(ql_log_warn, vha, 0x70a4,
1842 "Host operating mode is not P2p\n");
1843 rval = EXT_STATUS_INVALID_CFG;
1844 goto done;
1845 }
1846
1847 mutex_lock(&ha->selflogin_lock);
1848 if (vha->self_login_loop_id == 0) {
1849
1850 vha->bidir_fcport.vha = vha;
1851 vha->bidir_fcport.d_id.b.al_pa = vha->d_id.b.al_pa;
1852 vha->bidir_fcport.d_id.b.area = vha->d_id.b.area;
1853 vha->bidir_fcport.d_id.b.domain = vha->d_id.b.domain;
1854 vha->bidir_fcport.loop_id = vha->loop_id;
1855
1856 if (qla2x00_fabric_login(vha, &(vha->bidir_fcport), &nextlid)) {
1857 ql_log(ql_log_warn, vha, 0x70a7,
1858 "Failed to login port %06X for bidirectional IOCB\n",
1859 vha->bidir_fcport.d_id.b24);
1860 mutex_unlock(&ha->selflogin_lock);
1861 rval = EXT_STATUS_MAILBOX;
1862 goto done;
1863 }
1864 vha->self_login_loop_id = nextlid - 1;
1865
1866 }
1867
1868 mutex_unlock(&ha->selflogin_lock);
1869
1870 vha->bidir_fcport.loop_id = vha->self_login_loop_id;
1871
1872 req_sg_cnt = dma_map_sg(&ha->pdev->dev,
1873 bsg_job->request_payload.sg_list,
1874 bsg_job->request_payload.sg_cnt,
1875 DMA_TO_DEVICE);
1876
1877 if (!req_sg_cnt) {
1878 rval = EXT_STATUS_NO_MEMORY;
1879 goto done;
1880 }
1881
1882 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
1883 bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
1884 DMA_FROM_DEVICE);
1885
1886 if (!rsp_sg_cnt) {
1887 rval = EXT_STATUS_NO_MEMORY;
1888 goto done_unmap_req_sg;
1889 }
1890
1891 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
1892 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
1893 ql_dbg(ql_dbg_user, vha, 0x70a9,
1894 "Dma mapping resulted in different sg counts "
1895 "[request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt: "
1896 "%x dma_reply_sg_cnt: %x]\n",
1897 bsg_job->request_payload.sg_cnt, req_sg_cnt,
1898 bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
1899 rval = EXT_STATUS_NO_MEMORY;
1900 goto done_unmap_sg;
1901 }
1902
1903 req_data_len = bsg_job->request_payload.payload_len;
1904 rsp_data_len = bsg_job->reply_payload.payload_len;
1905
1906 if (req_data_len != rsp_data_len) {
1907 rval = EXT_STATUS_BUSY;
1908 ql_log(ql_log_warn, vha, 0x70aa,
1909 "req_data_len != rsp_data_len\n");
1910 goto done_unmap_sg;
1911 }
1912
1913
1914 sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL);
1915 if (!sp) {
1916 ql_dbg(ql_dbg_user, vha, 0x70ac,
1917 "Alloc SRB structure failed\n");
1918 rval = EXT_STATUS_NO_MEMORY;
1919 goto done_unmap_sg;
1920 }
1921
1922
1923 sp->u.bsg_job = bsg_job;
1924 sp->free = qla2x00_bsg_sp_free;
1925 sp->type = SRB_BIDI_CMD;
1926 sp->done = qla2x00_bsg_job_done;
1927
1928
1929 tot_dsds = rsp_sg_cnt + req_sg_cnt;
1930
1931 rval = qla2x00_start_bidir(sp, vha, tot_dsds);
1932 if (rval != EXT_STATUS_OK)
1933 goto done_free_srb;
1934
1935 return rval;
1936
1937done_free_srb:
1938 mempool_free(sp, ha->srb_mempool);
1939done_unmap_sg:
1940 dma_unmap_sg(&ha->pdev->dev,
1941 bsg_job->reply_payload.sg_list,
1942 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1943done_unmap_req_sg:
1944 dma_unmap_sg(&ha->pdev->dev,
1945 bsg_job->request_payload.sg_list,
1946 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1947done:
1948
1949
1950
1951
1952 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
1953 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1954 bsg_reply->reply_payload_rcv_len = 0;
1955 bsg_reply->result = (DID_OK) << 16;
1956 bsg_job_done(bsg_job, bsg_reply->result,
1957 bsg_reply->reply_payload_rcv_len);
1958
1959 return 0;
1960}
1961
1962static int
1963qlafx00_mgmt_cmd(struct bsg_job *bsg_job)
1964{
1965 struct fc_bsg_request *bsg_request = bsg_job->request;
1966 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1967 scsi_qla_host_t *vha = shost_priv(host);
1968 struct qla_hw_data *ha = vha->hw;
1969 int rval = (DID_ERROR << 16);
1970 struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
1971 srb_t *sp;
1972 int req_sg_cnt = 0, rsp_sg_cnt = 0;
1973 struct fc_port *fcport;
1974 char *type = "FC_BSG_HST_FX_MGMT";
1975
1976
1977 piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
1978 &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1979
1980
1981 ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf,
1982 piocb_rqst, sizeof(*piocb_rqst));
1983
1984 if (!vha->flags.online) {
1985 ql_log(ql_log_warn, vha, 0x70d0,
1986 "Host is not online.\n");
1987 rval = -EIO;
1988 goto done;
1989 }
1990
1991 if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) {
1992 req_sg_cnt = dma_map_sg(&ha->pdev->dev,
1993 bsg_job->request_payload.sg_list,
1994 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1995 if (!req_sg_cnt) {
1996 ql_log(ql_log_warn, vha, 0x70c7,
1997 "dma_map_sg return %d for request\n", req_sg_cnt);
1998 rval = -ENOMEM;
1999 goto done;
2000 }
2001 }
2002
2003 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) {
2004 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
2005 bsg_job->reply_payload.sg_list,
2006 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2007 if (!rsp_sg_cnt) {
2008 ql_log(ql_log_warn, vha, 0x70c8,
2009 "dma_map_sg return %d for reply\n", rsp_sg_cnt);
2010 rval = -ENOMEM;
2011 goto done_unmap_req_sg;
2012 }
2013 }
2014
2015 ql_dbg(ql_dbg_user, vha, 0x70c9,
2016 "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
2017 "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
2018 req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
2019
2020
2021
2022
2023
2024
2025 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
2026 if (!fcport) {
2027 ql_log(ql_log_warn, vha, 0x70ca,
2028 "Failed to allocate fcport.\n");
2029 rval = -ENOMEM;
2030 goto done_unmap_rsp_sg;
2031 }
2032
2033
2034 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
2035 if (!sp) {
2036 ql_log(ql_log_warn, vha, 0x70cb,
2037 "qla2x00_get_sp failed.\n");
2038 rval = -ENOMEM;
2039 goto done_free_fcport;
2040 }
2041
2042
2043 fcport->vha = vha;
2044 fcport->loop_id = le32_to_cpu(piocb_rqst->dataword);
2045
2046 sp->type = SRB_FXIOCB_BCMD;
2047 sp->name = "bsg_fx_mgmt";
2048 sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
2049 sp->u.bsg_job = bsg_job;
2050 sp->free = qla2x00_bsg_sp_free;
2051 sp->done = qla2x00_bsg_job_done;
2052
2053 ql_dbg(ql_dbg_user, vha, 0x70cc,
2054 "bsg rqst type: %s fx_mgmt_type: %x id=%x\n",
2055 type, piocb_rqst->func_type, fcport->loop_id);
2056
2057 rval = qla2x00_start_sp(sp);
2058 if (rval != QLA_SUCCESS) {
2059 ql_log(ql_log_warn, vha, 0x70cd,
2060 "qla2x00_start_sp failed=%d.\n", rval);
2061 mempool_free(sp, ha->srb_mempool);
2062 rval = -EIO;
2063 goto done_free_fcport;
2064 }
2065 return rval;
2066
2067done_free_fcport:
2068 qla2x00_free_fcport(fcport);
2069
2070done_unmap_rsp_sg:
2071 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
2072 dma_unmap_sg(&ha->pdev->dev,
2073 bsg_job->reply_payload.sg_list,
2074 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2075done_unmap_req_sg:
2076 if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
2077 dma_unmap_sg(&ha->pdev->dev,
2078 bsg_job->request_payload.sg_list,
2079 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2080
2081done:
2082 return rval;
2083}
2084
2085static int
2086qla26xx_serdes_op(struct bsg_job *bsg_job)
2087{
2088 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2089 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2090 scsi_qla_host_t *vha = shost_priv(host);
2091 int rval = 0;
2092 struct qla_serdes_reg sr;
2093
2094 memset(&sr, 0, sizeof(sr));
2095
2096 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2097 bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
2098
2099 switch (sr.cmd) {
2100 case INT_SC_SERDES_WRITE_REG:
2101 rval = qla2x00_write_serdes_word(vha, sr.addr, sr.val);
2102 bsg_reply->reply_payload_rcv_len = 0;
2103 break;
2104 case INT_SC_SERDES_READ_REG:
2105 rval = qla2x00_read_serdes_word(vha, sr.addr, &sr.val);
2106 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2107 bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
2108 bsg_reply->reply_payload_rcv_len = sizeof(sr);
2109 break;
2110 default:
2111 ql_dbg(ql_dbg_user, vha, 0x708c,
2112 "Unknown serdes cmd %x.\n", sr.cmd);
2113 rval = -EINVAL;
2114 break;
2115 }
2116
2117 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2118 rval ? EXT_STATUS_MAILBOX : 0;
2119
2120 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2121 bsg_reply->result = DID_OK << 16;
2122 bsg_job_done(bsg_job, bsg_reply->result,
2123 bsg_reply->reply_payload_rcv_len);
2124 return 0;
2125}
2126
2127static int
2128qla8044_serdes_op(struct bsg_job *bsg_job)
2129{
2130 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2131 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2132 scsi_qla_host_t *vha = shost_priv(host);
2133 int rval = 0;
2134 struct qla_serdes_reg_ex sr;
2135
2136 memset(&sr, 0, sizeof(sr));
2137
2138 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2139 bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
2140
2141 switch (sr.cmd) {
2142 case INT_SC_SERDES_WRITE_REG:
2143 rval = qla8044_write_serdes_word(vha, sr.addr, sr.val);
2144 bsg_reply->reply_payload_rcv_len = 0;
2145 break;
2146 case INT_SC_SERDES_READ_REG:
2147 rval = qla8044_read_serdes_word(vha, sr.addr, &sr.val);
2148 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2149 bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
2150 bsg_reply->reply_payload_rcv_len = sizeof(sr);
2151 break;
2152 default:
2153 ql_dbg(ql_dbg_user, vha, 0x7020,
2154 "Unknown serdes cmd %x.\n", sr.cmd);
2155 rval = -EINVAL;
2156 break;
2157 }
2158
2159 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2160 rval ? EXT_STATUS_MAILBOX : 0;
2161
2162 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2163 bsg_reply->result = DID_OK << 16;
2164 bsg_job_done(bsg_job, bsg_reply->result,
2165 bsg_reply->reply_payload_rcv_len);
2166 return 0;
2167}
2168
2169static int
2170qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job)
2171{
2172 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2173 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2174 scsi_qla_host_t *vha = shost_priv(host);
2175 struct qla_hw_data *ha = vha->hw;
2176 struct qla_flash_update_caps cap;
2177
2178 if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha))
2179 return -EPERM;
2180
2181 memset(&cap, 0, sizeof(cap));
2182 cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 |
2183 (uint64_t)ha->fw_attributes_ext[0] << 32 |
2184 (uint64_t)ha->fw_attributes_h << 16 |
2185 (uint64_t)ha->fw_attributes;
2186
2187 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2188 bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap));
2189 bsg_reply->reply_payload_rcv_len = sizeof(cap);
2190
2191 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2192 EXT_STATUS_OK;
2193
2194 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2195 bsg_reply->result = DID_OK << 16;
2196 bsg_job_done(bsg_job, bsg_reply->result,
2197 bsg_reply->reply_payload_rcv_len);
2198 return 0;
2199}
2200
2201static int
2202qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job)
2203{
2204 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2205 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2206 scsi_qla_host_t *vha = shost_priv(host);
2207 struct qla_hw_data *ha = vha->hw;
2208 uint64_t online_fw_attr = 0;
2209 struct qla_flash_update_caps cap;
2210
2211 if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
2212 return -EPERM;
2213
2214 memset(&cap, 0, sizeof(cap));
2215 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2216 bsg_job->request_payload.sg_cnt, &cap, sizeof(cap));
2217
2218 online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 |
2219 (uint64_t)ha->fw_attributes_ext[0] << 32 |
2220 (uint64_t)ha->fw_attributes_h << 16 |
2221 (uint64_t)ha->fw_attributes;
2222
2223 if (online_fw_attr != cap.capabilities) {
2224 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2225 EXT_STATUS_INVALID_PARAM;
2226 return -EINVAL;
2227 }
2228
2229 if (cap.outage_duration < MAX_LOOP_TIMEOUT) {
2230 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2231 EXT_STATUS_INVALID_PARAM;
2232 return -EINVAL;
2233 }
2234
2235 bsg_reply->reply_payload_rcv_len = 0;
2236
2237 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2238 EXT_STATUS_OK;
2239
2240 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2241 bsg_reply->result = DID_OK << 16;
2242 bsg_job_done(bsg_job, bsg_reply->result,
2243 bsg_reply->reply_payload_rcv_len);
2244 return 0;
2245}
2246
2247static int
2248qla27xx_get_bbcr_data(struct bsg_job *bsg_job)
2249{
2250 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2251 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2252 scsi_qla_host_t *vha = shost_priv(host);
2253 struct qla_hw_data *ha = vha->hw;
2254 struct qla_bbcr_data bbcr;
2255 uint16_t loop_id, topo, sw_cap;
2256 uint8_t domain, area, al_pa, state;
2257 int rval;
2258
2259 if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
2260 return -EPERM;
2261
2262 memset(&bbcr, 0, sizeof(bbcr));
2263
2264 if (vha->flags.bbcr_enable)
2265 bbcr.status = QLA_BBCR_STATUS_ENABLED;
2266 else
2267 bbcr.status = QLA_BBCR_STATUS_DISABLED;
2268
2269 if (bbcr.status == QLA_BBCR_STATUS_ENABLED) {
2270 rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
2271 &area, &domain, &topo, &sw_cap);
2272 if (rval != QLA_SUCCESS) {
2273 bbcr.status = QLA_BBCR_STATUS_UNKNOWN;
2274 bbcr.state = QLA_BBCR_STATE_OFFLINE;
2275 bbcr.mbx1 = loop_id;
2276 goto done;
2277 }
2278
2279 state = (vha->bbcr >> 12) & 0x1;
2280
2281 if (state) {
2282 bbcr.state = QLA_BBCR_STATE_OFFLINE;
2283 bbcr.offline_reason_code = QLA_BBCR_REASON_LOGIN_REJECT;
2284 } else {
2285 bbcr.state = QLA_BBCR_STATE_ONLINE;
2286 bbcr.negotiated_bbscn = (vha->bbcr >> 8) & 0xf;
2287 }
2288
2289 bbcr.configured_bbscn = vha->bbcr & 0xf;
2290 }
2291
2292done:
2293 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2294 bsg_job->reply_payload.sg_cnt, &bbcr, sizeof(bbcr));
2295 bsg_reply->reply_payload_rcv_len = sizeof(bbcr);
2296
2297 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2298
2299 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2300 bsg_reply->result = DID_OK << 16;
2301 bsg_job_done(bsg_job, bsg_reply->result,
2302 bsg_reply->reply_payload_rcv_len);
2303 return 0;
2304}
2305
2306static int
2307qla2x00_get_priv_stats(struct bsg_job *bsg_job)
2308{
2309 struct fc_bsg_request *bsg_request = bsg_job->request;
2310 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2311 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2312 scsi_qla_host_t *vha = shost_priv(host);
2313 struct qla_hw_data *ha = vha->hw;
2314 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
2315 struct link_statistics *stats = NULL;
2316 dma_addr_t stats_dma;
2317 int rval;
2318 uint32_t *cmd = bsg_request->rqst_data.h_vendor.vendor_cmd;
2319 uint options = cmd[0] == QL_VND_GET_PRIV_STATS_EX ? cmd[1] : 0;
2320
2321 if (test_bit(UNLOADING, &vha->dpc_flags))
2322 return -ENODEV;
2323
2324 if (unlikely(pci_channel_offline(ha->pdev)))
2325 return -ENODEV;
2326
2327 if (qla2x00_reset_active(vha))
2328 return -EBUSY;
2329
2330 if (!IS_FWI2_CAPABLE(ha))
2331 return -EPERM;
2332
2333 stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
2334 GFP_KERNEL);
2335 if (!stats) {
2336 ql_log(ql_log_warn, vha, 0x70e2,
2337 "Failed to allocate memory for stats.\n");
2338 return -ENOMEM;
2339 }
2340
2341 rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options);
2342
2343 if (rval == QLA_SUCCESS) {
2344 ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5,
2345 stats, sizeof(*stats));
2346 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2347 bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats));
2348 }
2349
2350 bsg_reply->reply_payload_rcv_len = sizeof(*stats);
2351 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2352 rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
2353
2354 bsg_job->reply_len = sizeof(*bsg_reply);
2355 bsg_reply->result = DID_OK << 16;
2356 bsg_job_done(bsg_job, bsg_reply->result,
2357 bsg_reply->reply_payload_rcv_len);
2358
2359 dma_free_coherent(&ha->pdev->dev, sizeof(*stats),
2360 stats, stats_dma);
2361
2362 return 0;
2363}
2364
2365static int
2366qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
2367{
2368 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2369 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2370 scsi_qla_host_t *vha = shost_priv(host);
2371 int rval;
2372 struct qla_dport_diag *dd;
2373
2374 if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
2375 !IS_QLA28XX(vha->hw))
2376 return -EPERM;
2377
2378 dd = kmalloc(sizeof(*dd), GFP_KERNEL);
2379 if (!dd) {
2380 ql_log(ql_log_warn, vha, 0x70db,
2381 "Failed to allocate memory for dport.\n");
2382 return -ENOMEM;
2383 }
2384
2385 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2386 bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
2387
2388 rval = qla26xx_dport_diagnostics(
2389 vha, dd->buf, sizeof(dd->buf), dd->options);
2390 if (rval == QLA_SUCCESS) {
2391 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2392 bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
2393 }
2394
2395 bsg_reply->reply_payload_rcv_len = sizeof(*dd);
2396 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2397 rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
2398
2399 bsg_job->reply_len = sizeof(*bsg_reply);
2400 bsg_reply->result = DID_OK << 16;
2401 bsg_job_done(bsg_job, bsg_reply->result,
2402 bsg_reply->reply_payload_rcv_len);
2403
2404 kfree(dd);
2405
2406 return 0;
2407}
2408
2409static int
2410qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
2411{
2412 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2413 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2414 struct qla_hw_data *ha = vha->hw;
2415 struct qla_active_regions regions = { };
2416 struct active_regions active_regions = { };
2417
2418 qla27xx_get_active_image(vha, &active_regions);
2419 regions.global_image = active_regions.global;
2420
2421 if (IS_QLA28XX(ha)) {
2422 qla28xx_get_aux_images(vha, &active_regions);
2423 regions.board_config = active_regions.aux.board_config;
2424 regions.vpd_nvram = active_regions.aux.vpd_nvram;
2425 regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
2426 regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3;
2427 }
2428
2429 ql_dbg(ql_dbg_user, vha, 0x70e1,
2430 "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n",
2431 __func__, vha->host_no, regions.global_image,
2432 regions.board_config, regions.vpd_nvram,
2433 regions.npiv_config_0_1, regions.npiv_config_2_3);
2434
2435 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2436 bsg_job->reply_payload.sg_cnt, ®ions, sizeof(regions));
2437
2438 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2439 bsg_reply->reply_payload_rcv_len = sizeof(regions);
2440 bsg_reply->result = DID_OK << 16;
2441 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2442 bsg_job_done(bsg_job, bsg_reply->result,
2443 bsg_reply->reply_payload_rcv_len);
2444
2445 return 0;
2446}
2447
2448static int
2449qla2x00_manage_host_stats(struct bsg_job *bsg_job)
2450{
2451 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2452 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2453 struct ql_vnd_mng_host_stats_param *req_data;
2454 struct ql_vnd_mng_host_stats_resp rsp_data;
2455 u32 req_data_len;
2456 int ret = 0;
2457
2458 if (!vha->flags.online) {
2459 ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
2460 return -EIO;
2461 }
2462
2463 req_data_len = bsg_job->request_payload.payload_len;
2464
2465 if (req_data_len != sizeof(struct ql_vnd_mng_host_stats_param)) {
2466 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2467 return -EIO;
2468 }
2469
2470 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2471 if (!req_data) {
2472 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2473 return -ENOMEM;
2474 }
2475
2476
2477 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2478 bsg_job->request_payload.sg_cnt, req_data,
2479 req_data_len);
2480
2481 switch (req_data->action) {
2482 case QLA_STOP:
2483 ret = qla2xxx_stop_stats(vha->host, req_data->stat_type);
2484 break;
2485 case QLA_START:
2486 ret = qla2xxx_start_stats(vha->host, req_data->stat_type);
2487 break;
2488 case QLA_CLEAR:
2489 ret = qla2xxx_reset_stats(vha->host, req_data->stat_type);
2490 break;
2491 default:
2492 ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
2493 ret = -EIO;
2494 break;
2495 }
2496
2497 kfree(req_data);
2498
2499
2500 rsp_data.status = ret;
2501 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2502
2503 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2504 bsg_reply->reply_payload_rcv_len =
2505 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2506 bsg_job->reply_payload.sg_cnt,
2507 &rsp_data,
2508 sizeof(struct ql_vnd_mng_host_stats_resp));
2509
2510 bsg_reply->result = DID_OK;
2511 bsg_job_done(bsg_job, bsg_reply->result,
2512 bsg_reply->reply_payload_rcv_len);
2513
2514 return ret;
2515}
2516
2517static int
2518qla2x00_get_host_stats(struct bsg_job *bsg_job)
2519{
2520 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2521 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2522 struct ql_vnd_stats_param *req_data;
2523 struct ql_vnd_host_stats_resp rsp_data;
2524 u32 req_data_len;
2525 int ret = 0;
2526 u64 ini_entry_count = 0;
2527 u64 entry_count = 0;
2528 u64 tgt_num = 0;
2529 u64 tmp_stat_type = 0;
2530 u64 response_len = 0;
2531 void *data;
2532
2533 req_data_len = bsg_job->request_payload.payload_len;
2534
2535 if (req_data_len != sizeof(struct ql_vnd_stats_param)) {
2536 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2537 return -EIO;
2538 }
2539
2540 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2541 if (!req_data) {
2542 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2543 return -ENOMEM;
2544 }
2545
2546
2547 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2548 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
2549
2550
2551 tmp_stat_type = req_data->stat_type;
2552
2553 if (tmp_stat_type & QLA2XX_TGT_SHT_LNK_DOWN) {
2554
2555 tgt_num = qla2x00_get_num_tgts(vha);
2556
2557 tmp_stat_type &= ~(1 << 17);
2558 }
2559
2560
2561 ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
2562
2563
2564 entry_count = ini_entry_count + tgt_num;
2565
2566 response_len = sizeof(struct ql_vnd_host_stats_resp) +
2567 (sizeof(struct ql_vnd_stat_entry) * entry_count);
2568
2569 if (response_len > bsg_job->reply_payload.payload_len) {
2570 rsp_data.status = EXT_STATUS_BUFFER_TOO_SMALL;
2571 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
2572 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2573
2574 bsg_reply->reply_payload_rcv_len =
2575 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2576 bsg_job->reply_payload.sg_cnt, &rsp_data,
2577 sizeof(struct ql_vnd_mng_host_stats_resp));
2578
2579 bsg_reply->result = DID_OK;
2580 bsg_job_done(bsg_job, bsg_reply->result,
2581 bsg_reply->reply_payload_rcv_len);
2582 goto host_stat_out;
2583 }
2584
2585 data = kzalloc(response_len, GFP_KERNEL);
2586
2587 ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
2588 data, response_len);
2589
2590 rsp_data.status = EXT_STATUS_OK;
2591 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2592
2593 bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2594 bsg_job->reply_payload.sg_cnt,
2595 data, response_len);
2596 bsg_reply->result = DID_OK;
2597 bsg_job_done(bsg_job, bsg_reply->result,
2598 bsg_reply->reply_payload_rcv_len);
2599
2600 kfree(data);
2601host_stat_out:
2602 kfree(req_data);
2603 return ret;
2604}
2605
2606static struct fc_rport *
2607qla2xxx_find_rport(scsi_qla_host_t *vha, uint32_t tgt_num)
2608{
2609 fc_port_t *fcport = NULL;
2610
2611 list_for_each_entry(fcport, &vha->vp_fcports, list) {
2612 if (fcport->rport->number == tgt_num)
2613 return fcport->rport;
2614 }
2615 return NULL;
2616}
2617
2618static int
2619qla2x00_get_tgt_stats(struct bsg_job *bsg_job)
2620{
2621 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2622 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2623 struct ql_vnd_tgt_stats_param *req_data;
2624 u32 req_data_len;
2625 int ret = 0;
2626 u64 response_len = 0;
2627 struct ql_vnd_tgt_stats_resp *data = NULL;
2628 struct fc_rport *rport = NULL;
2629
2630 if (!vha->flags.online) {
2631 ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
2632 return -EIO;
2633 }
2634
2635 req_data_len = bsg_job->request_payload.payload_len;
2636
2637 if (req_data_len != sizeof(struct ql_vnd_stat_entry)) {
2638 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2639 return -EIO;
2640 }
2641
2642 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2643 if (!req_data) {
2644 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2645 return -ENOMEM;
2646 }
2647
2648
2649 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2650 bsg_job->request_payload.sg_cnt,
2651 req_data, req_data_len);
2652
2653 response_len = sizeof(struct ql_vnd_tgt_stats_resp) +
2654 sizeof(struct ql_vnd_stat_entry);
2655
2656
2657 data = kzalloc(response_len, GFP_KERNEL);
2658 if (!data) {
2659 kfree(req_data);
2660 return -ENOMEM;
2661 }
2662
2663 if (response_len > bsg_job->reply_payload.payload_len) {
2664 data->status = EXT_STATUS_BUFFER_TOO_SMALL;
2665 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
2666 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2667
2668 bsg_reply->reply_payload_rcv_len =
2669 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2670 bsg_job->reply_payload.sg_cnt, data,
2671 sizeof(struct ql_vnd_tgt_stats_resp));
2672
2673 bsg_reply->result = DID_OK;
2674 bsg_job_done(bsg_job, bsg_reply->result,
2675 bsg_reply->reply_payload_rcv_len);
2676 goto tgt_stat_out;
2677 }
2678
2679 rport = qla2xxx_find_rport(vha, req_data->tgt_id);
2680 if (!rport) {
2681 ql_log(ql_log_warn, vha, 0x0000, "target %d not found.\n", req_data->tgt_id);
2682 ret = EXT_STATUS_INVALID_PARAM;
2683 data->status = EXT_STATUS_INVALID_PARAM;
2684 goto reply;
2685 }
2686
2687 ret = qla2xxx_get_tgt_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
2688 rport, (void *)data, response_len);
2689
2690 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2691reply:
2692 bsg_reply->reply_payload_rcv_len =
2693 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2694 bsg_job->reply_payload.sg_cnt, data,
2695 response_len);
2696 bsg_reply->result = DID_OK;
2697 bsg_job_done(bsg_job, bsg_reply->result,
2698 bsg_reply->reply_payload_rcv_len);
2699
2700tgt_stat_out:
2701 kfree(data);
2702 kfree(req_data);
2703
2704 return ret;
2705}
2706
2707static int
2708qla2x00_manage_host_port(struct bsg_job *bsg_job)
2709{
2710 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2711 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2712 struct ql_vnd_mng_host_port_param *req_data;
2713 struct ql_vnd_mng_host_port_resp rsp_data;
2714 u32 req_data_len;
2715 int ret = 0;
2716
2717 req_data_len = bsg_job->request_payload.payload_len;
2718
2719 if (req_data_len != sizeof(struct ql_vnd_mng_host_port_param)) {
2720 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2721 return -EIO;
2722 }
2723
2724 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2725 if (!req_data) {
2726 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2727 return -ENOMEM;
2728 }
2729
2730
2731 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2732 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
2733
2734 switch (req_data->action) {
2735 case QLA_ENABLE:
2736 ret = qla2xxx_enable_port(vha->host);
2737 break;
2738 case QLA_DISABLE:
2739 ret = qla2xxx_disable_port(vha->host);
2740 break;
2741 default:
2742 ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
2743 ret = -EIO;
2744 break;
2745 }
2746
2747 kfree(req_data);
2748
2749
2750 rsp_data.status = ret;
2751 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2752 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_port_resp);
2753
2754 bsg_reply->reply_payload_rcv_len =
2755 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2756 bsg_job->reply_payload.sg_cnt, &rsp_data,
2757 sizeof(struct ql_vnd_mng_host_port_resp));
2758 bsg_reply->result = DID_OK;
2759 bsg_job_done(bsg_job, bsg_reply->result,
2760 bsg_reply->reply_payload_rcv_len);
2761
2762 return ret;
2763}
2764
2765static int
2766qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
2767{
2768 struct fc_bsg_request *bsg_request = bsg_job->request;
2769
2770 switch (bsg_request->rqst_data.h_vendor.vendor_cmd[0]) {
2771 case QL_VND_LOOPBACK:
2772 return qla2x00_process_loopback(bsg_job);
2773
2774 case QL_VND_A84_RESET:
2775 return qla84xx_reset(bsg_job);
2776
2777 case QL_VND_A84_UPDATE_FW:
2778 return qla84xx_updatefw(bsg_job);
2779
2780 case QL_VND_A84_MGMT_CMD:
2781 return qla84xx_mgmt_cmd(bsg_job);
2782
2783 case QL_VND_IIDMA:
2784 return qla24xx_iidma(bsg_job);
2785
2786 case QL_VND_FCP_PRIO_CFG_CMD:
2787 return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
2788
2789 case QL_VND_READ_FLASH:
2790 return qla2x00_read_optrom(bsg_job);
2791
2792 case QL_VND_UPDATE_FLASH:
2793 return qla2x00_update_optrom(bsg_job);
2794
2795 case QL_VND_SET_FRU_VERSION:
2796 return qla2x00_update_fru_versions(bsg_job);
2797
2798 case QL_VND_READ_FRU_STATUS:
2799 return qla2x00_read_fru_status(bsg_job);
2800
2801 case QL_VND_WRITE_FRU_STATUS:
2802 return qla2x00_write_fru_status(bsg_job);
2803
2804 case QL_VND_WRITE_I2C:
2805 return qla2x00_write_i2c(bsg_job);
2806
2807 case QL_VND_READ_I2C:
2808 return qla2x00_read_i2c(bsg_job);
2809
2810 case QL_VND_DIAG_IO_CMD:
2811 return qla24xx_process_bidir_cmd(bsg_job);
2812
2813 case QL_VND_FX00_MGMT_CMD:
2814 return qlafx00_mgmt_cmd(bsg_job);
2815
2816 case QL_VND_SERDES_OP:
2817 return qla26xx_serdes_op(bsg_job);
2818
2819 case QL_VND_SERDES_OP_EX:
2820 return qla8044_serdes_op(bsg_job);
2821
2822 case QL_VND_GET_FLASH_UPDATE_CAPS:
2823 return qla27xx_get_flash_upd_cap(bsg_job);
2824
2825 case QL_VND_SET_FLASH_UPDATE_CAPS:
2826 return qla27xx_set_flash_upd_cap(bsg_job);
2827
2828 case QL_VND_GET_BBCR_DATA:
2829 return qla27xx_get_bbcr_data(bsg_job);
2830
2831 case QL_VND_GET_PRIV_STATS:
2832 case QL_VND_GET_PRIV_STATS_EX:
2833 return qla2x00_get_priv_stats(bsg_job);
2834
2835 case QL_VND_DPORT_DIAGNOSTICS:
2836 return qla2x00_do_dport_diagnostics(bsg_job);
2837
2838 case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
2839 return qla2x00_get_flash_image_status(bsg_job);
2840
2841 case QL_VND_MANAGE_HOST_STATS:
2842 return qla2x00_manage_host_stats(bsg_job);
2843
2844 case QL_VND_GET_HOST_STATS:
2845 return qla2x00_get_host_stats(bsg_job);
2846
2847 case QL_VND_GET_TGT_STATS:
2848 return qla2x00_get_tgt_stats(bsg_job);
2849
2850 case QL_VND_MANAGE_HOST_PORT:
2851 return qla2x00_manage_host_port(bsg_job);
2852
2853 default:
2854 return -ENOSYS;
2855 }
2856}
2857
2858int
2859qla24xx_bsg_request(struct bsg_job *bsg_job)
2860{
2861 struct fc_bsg_request *bsg_request = bsg_job->request;
2862 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2863 int ret = -EINVAL;
2864 struct fc_rport *rport;
2865 struct Scsi_Host *host;
2866 scsi_qla_host_t *vha;
2867
2868
2869 bsg_reply->reply_payload_rcv_len = 0;
2870
2871 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
2872 rport = fc_bsg_to_rport(bsg_job);
2873 host = rport_to_shost(rport);
2874 vha = shost_priv(host);
2875 } else {
2876 host = fc_bsg_to_shost(bsg_job);
2877 vha = shost_priv(host);
2878 }
2879
2880
2881 if (bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_MANAGE_HOST_PORT ||
2882 bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_GET_HOST_STATS)
2883 goto skip_chip_chk;
2884
2885 if (vha->hw->flags.port_isolated) {
2886 bsg_reply->result = DID_ERROR;
2887
2888 return -EPERM;
2889 }
2890
2891 if (qla2x00_chip_is_down(vha)) {
2892 ql_dbg(ql_dbg_user, vha, 0x709f,
2893 "BSG: ISP abort active/needed -- cmd=%d.\n",
2894 bsg_request->msgcode);
2895 return -EBUSY;
2896 }
2897
2898skip_chip_chk:
2899 ql_dbg(ql_dbg_user, vha, 0x7000,
2900 "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode);
2901
2902 switch (bsg_request->msgcode) {
2903 case FC_BSG_RPT_ELS:
2904 case FC_BSG_HST_ELS_NOLOGIN:
2905 ret = qla2x00_process_els(bsg_job);
2906 break;
2907 case FC_BSG_HST_CT:
2908 ret = qla2x00_process_ct(bsg_job);
2909 break;
2910 case FC_BSG_HST_VENDOR:
2911 ret = qla2x00_process_vendor_specific(bsg_job);
2912 break;
2913 case FC_BSG_HST_ADD_RPORT:
2914 case FC_BSG_HST_DEL_RPORT:
2915 case FC_BSG_RPT_CT:
2916 default:
2917 ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
2918 break;
2919 }
2920 return ret;
2921}
2922
2923int
2924qla24xx_bsg_timeout(struct bsg_job *bsg_job)
2925{
2926 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2927 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2928 struct qla_hw_data *ha = vha->hw;
2929 srb_t *sp;
2930 int cnt, que;
2931 unsigned long flags;
2932 struct req_que *req;
2933
2934
2935 spin_lock_irqsave(&ha->hardware_lock, flags);
2936 for (que = 0; que < ha->max_req_queues; que++) {
2937 req = ha->req_q_map[que];
2938 if (!req)
2939 continue;
2940
2941 for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
2942 sp = req->outstanding_cmds[cnt];
2943 if (sp) {
2944 if (((sp->type == SRB_CT_CMD) ||
2945 (sp->type == SRB_ELS_CMD_HST) ||
2946 (sp->type == SRB_FXIOCB_BCMD))
2947 && (sp->u.bsg_job == bsg_job)) {
2948 req->outstanding_cmds[cnt] = NULL;
2949 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2950 if (ha->isp_ops->abort_command(sp)) {
2951 ql_log(ql_log_warn, vha, 0x7089,
2952 "mbx abort_command "
2953 "failed.\n");
2954 bsg_reply->result = -EIO;
2955 } else {
2956 ql_dbg(ql_dbg_user, vha, 0x708a,
2957 "mbx abort_command "
2958 "success.\n");
2959 bsg_reply->result = 0;
2960 }
2961 spin_lock_irqsave(&ha->hardware_lock, flags);
2962 goto done;
2963 }
2964 }
2965 }
2966 }
2967 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2968 ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
2969 bsg_reply->result = -ENXIO;
2970 return 0;
2971
2972done:
2973 spin_unlock_irqrestore(&ha->hardware_lock, flags);
2974 sp->free(sp);
2975 return 0;
2976}
2977