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

source code of linux/drivers/scsi/qla2xxx/qla_bsg.c