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

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