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