Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
[pandora-kernel.git] / drivers / scsi / qla2xxx / qla_bsg.c
1 /*
2  * QLogic Fibre Channel HBA Driver
3  * Copyright (c)  2003-2008 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(struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
40 {
41         int i, ret, num_valid;
42         uint8_t *bcode;
43         struct qla_fcp_prio_entry *pri_entry;
44
45         ret = 1;
46         num_valid = 0;
47         bcode = (uint8_t *)pri_cfg;
48
49         if (bcode[0x0] != 'H' || bcode[0x1] != 'Q' || bcode[0x2] != 'O' ||
50                         bcode[0x3] != 'S') {
51                 return 0;
52         }
53         if (flag != 1)
54                 return ret;
55
56         pri_entry = &pri_cfg->entry[0];
57         for (i = 0; i < pri_cfg->num_entries; i++) {
58                 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
59                         num_valid++;
60                 pri_entry++;
61         }
62
63         if (num_valid == 0)
64                 ret = 0;
65
66         return ret;
67 }
68
69 static int
70 qla24xx_proc_fcp_prio_cfg_cmd(struct fc_bsg_job *bsg_job)
71 {
72         struct Scsi_Host *host = bsg_job->shost;
73         scsi_qla_host_t *vha = shost_priv(host);
74         struct qla_hw_data *ha = vha->hw;
75         int ret = 0;
76         uint32_t len;
77         uint32_t oper;
78
79         bsg_job->reply->reply_payload_rcv_len = 0;
80
81         if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
82                 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
83                 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
84                 ret = -EBUSY;
85                 goto exit_fcp_prio_cfg;
86         }
87
88         /* Get the sub command */
89         oper = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
90
91         /* Only set config is allowed if config memory is not allocated */
92         if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
93                 ret = -EINVAL;
94                 goto exit_fcp_prio_cfg;
95         }
96         switch (oper) {
97         case QLFC_FCP_PRIO_DISABLE:
98                 if (ha->flags.fcp_prio_enabled) {
99                         ha->flags.fcp_prio_enabled = 0;
100                         ha->fcp_prio_cfg->attributes &=
101                                 ~FCP_PRIO_ATTR_ENABLE;
102                         qla24xx_update_all_fcp_prio(vha);
103                         bsg_job->reply->result = DID_OK;
104                 } else {
105                         ret = -EINVAL;
106                         bsg_job->reply->result = (DID_ERROR << 16);
107                         goto exit_fcp_prio_cfg;
108                 }
109                 break;
110
111         case QLFC_FCP_PRIO_ENABLE:
112                 if (!ha->flags.fcp_prio_enabled) {
113                         if (ha->fcp_prio_cfg) {
114                                 ha->flags.fcp_prio_enabled = 1;
115                                 ha->fcp_prio_cfg->attributes |=
116                                     FCP_PRIO_ATTR_ENABLE;
117                                 qla24xx_update_all_fcp_prio(vha);
118                                 bsg_job->reply->result = DID_OK;
119                         } else {
120                                 ret = -EINVAL;
121                                 bsg_job->reply->result = (DID_ERROR << 16);
122                                 goto exit_fcp_prio_cfg;
123                         }
124                 }
125                 break;
126
127         case QLFC_FCP_PRIO_GET_CONFIG:
128                 len = bsg_job->reply_payload.payload_len;
129                 if (!len || len > FCP_PRIO_CFG_SIZE) {
130                         ret = -EINVAL;
131                         bsg_job->reply->result = (DID_ERROR << 16);
132                         goto exit_fcp_prio_cfg;
133                 }
134
135                 bsg_job->reply->result = DID_OK;
136                 bsg_job->reply->reply_payload_rcv_len =
137                         sg_copy_from_buffer(
138                         bsg_job->reply_payload.sg_list,
139                         bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
140                         len);
141
142                 break;
143
144         case QLFC_FCP_PRIO_SET_CONFIG:
145                 len = bsg_job->request_payload.payload_len;
146                 if (!len || len > FCP_PRIO_CFG_SIZE) {
147                         bsg_job->reply->result = (DID_ERROR << 16);
148                         ret = -EINVAL;
149                         goto exit_fcp_prio_cfg;
150                 }
151
152                 if (!ha->fcp_prio_cfg) {
153                         ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
154                         if (!ha->fcp_prio_cfg) {
155                                 qla_printk(KERN_WARNING, ha,
156                                         "Unable to allocate memory "
157                                         "for fcp prio config data (%x).\n",
158                                         FCP_PRIO_CFG_SIZE);
159                                 bsg_job->reply->result = (DID_ERROR << 16);
160                                 ret = -ENOMEM;
161                                 goto exit_fcp_prio_cfg;
162                         }
163                 }
164
165                 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
166                 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
167                 bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
168                         FCP_PRIO_CFG_SIZE);
169
170                 /* validate fcp priority data */
171                 if (!qla24xx_fcp_prio_cfg_valid(
172                         (struct qla_fcp_prio_cfg *)
173                         ha->fcp_prio_cfg, 1)) {
174                         bsg_job->reply->result = (DID_ERROR << 16);
175                         ret = -EINVAL;
176                         /* If buffer was invalidatic int
177                          * fcp_prio_cfg is of no use
178                          */
179                         vfree(ha->fcp_prio_cfg);
180                         ha->fcp_prio_cfg = NULL;
181                         goto exit_fcp_prio_cfg;
182                 }
183
184                 ha->flags.fcp_prio_enabled = 0;
185                 if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
186                         ha->flags.fcp_prio_enabled = 1;
187                 qla24xx_update_all_fcp_prio(vha);
188                 bsg_job->reply->result = DID_OK;
189                 break;
190         default:
191                 ret = -EINVAL;
192                 break;
193         }
194 exit_fcp_prio_cfg:
195         bsg_job->job_done(bsg_job);
196         return ret;
197 }
198 static int
199 qla2x00_process_els(struct fc_bsg_job *bsg_job)
200 {
201         struct fc_rport *rport;
202         fc_port_t *fcport;
203         struct Scsi_Host *host;
204         scsi_qla_host_t *vha;
205         struct qla_hw_data *ha;
206         srb_t *sp;
207         const char *type;
208         int req_sg_cnt, rsp_sg_cnt;
209         int rval =  (DRIVER_ERROR << 16);
210         uint16_t nextlid = 0;
211         struct srb_ctx *els;
212
213         /*  Multiple SG's are not supported for ELS requests */
214         if (bsg_job->request_payload.sg_cnt > 1 ||
215                 bsg_job->reply_payload.sg_cnt > 1) {
216                 DEBUG2(printk(KERN_INFO
217                         "multiple SG's are not supported for ELS requests"
218                         " [request_sg_cnt: %x reply_sg_cnt: %x]\n",
219                         bsg_job->request_payload.sg_cnt,
220                         bsg_job->reply_payload.sg_cnt));
221                 rval = -EPERM;
222                 goto done;
223         }
224
225         /* ELS request for rport */
226         if (bsg_job->request->msgcode == FC_BSG_RPT_ELS) {
227                 rport = bsg_job->rport;
228                 fcport = *(fc_port_t **) rport->dd_data;
229                 host = rport_to_shost(rport);
230                 vha = shost_priv(host);
231                 ha = vha->hw;
232                 type = "FC_BSG_RPT_ELS";
233
234                 /* make sure the rport is logged in,
235                  * if not perform fabric login
236                  */
237                 if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
238                         DEBUG2(qla_printk(KERN_WARNING, ha,
239                         "failed to login port %06X for ELS passthru\n",
240                         fcport->d_id.b24));
241                         rval = -EIO;
242                         goto done;
243                 }
244         } else {
245                 host = bsg_job->shost;
246                 vha = shost_priv(host);
247                 ha = vha->hw;
248                 type = "FC_BSG_HST_ELS_NOLOGIN";
249
250                 /* Allocate a dummy fcport structure, since functions
251                  * preparing the IOCB and mailbox command retrieves port
252                  * specific information from fcport structure. For Host based
253                  * ELS commands there will be no fcport structure allocated
254                  */
255                 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
256                 if (!fcport) {
257                         rval = -ENOMEM;
258                         goto done;
259                 }
260
261                 /* Initialize all required  fields of fcport */
262                 fcport->vha = vha;
263                 fcport->vp_idx = vha->vp_idx;
264                 fcport->d_id.b.al_pa =
265                         bsg_job->request->rqst_data.h_els.port_id[0];
266                 fcport->d_id.b.area =
267                         bsg_job->request->rqst_data.h_els.port_id[1];
268                 fcport->d_id.b.domain =
269                         bsg_job->request->rqst_data.h_els.port_id[2];
270                 fcport->loop_id =
271                         (fcport->d_id.b.al_pa == 0xFD) ?
272                         NPH_FABRIC_CONTROLLER : NPH_F_PORT;
273         }
274
275         if (!vha->flags.online) {
276                 DEBUG2(qla_printk(KERN_WARNING, ha,
277                 "host not online\n"));
278                 rval = -EIO;
279                 goto done;
280         }
281
282         req_sg_cnt =
283                 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
284                 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
285         if (!req_sg_cnt) {
286                 rval = -ENOMEM;
287                 goto done_free_fcport;
288         }
289
290         rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
291                 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
292         if (!rsp_sg_cnt) {
293                 rval = -ENOMEM;
294                 goto done_free_fcport;
295         }
296
297         if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
298                 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
299                 DEBUG2(printk(KERN_INFO
300                         "dma mapping resulted in different sg counts \
301                         [request_sg_cnt: %x dma_request_sg_cnt: %x\
302                         reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
303                         bsg_job->request_payload.sg_cnt, req_sg_cnt,
304                         bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
305                 rval = -EAGAIN;
306                 goto done_unmap_sg;
307         }
308
309         /* Alloc SRB structure */
310         sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
311         if (!sp) {
312                 rval = -ENOMEM;
313                 goto done_unmap_sg;
314         }
315
316         els = sp->ctx;
317         els->type =
318                 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
319                 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
320         els->name =
321                 (bsg_job->request->msgcode == FC_BSG_RPT_ELS ?
322                 "bsg_els_rpt" : "bsg_els_hst");
323         els->u.bsg_job = bsg_job;
324
325         DEBUG2(qla_printk(KERN_INFO, ha,
326                 "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
327                 "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
328                 bsg_job->request->rqst_data.h_els.command_code,
329                 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
330                 fcport->d_id.b.al_pa));
331
332         rval = qla2x00_start_sp(sp);
333         if (rval != QLA_SUCCESS) {
334                 kfree(sp->ctx);
335                 mempool_free(sp, ha->srb_mempool);
336                 rval = -EIO;
337                 goto done_unmap_sg;
338         }
339         return rval;
340
341 done_unmap_sg:
342         dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
343                 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
344         dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
345                 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
346         goto done_free_fcport;
347
348 done_free_fcport:
349         if (bsg_job->request->msgcode == FC_BSG_HST_ELS_NOLOGIN)
350                 kfree(fcport);
351 done:
352         return rval;
353 }
354
355 static int
356 qla2x00_process_ct(struct fc_bsg_job *bsg_job)
357 {
358         srb_t *sp;
359         struct Scsi_Host *host = bsg_job->shost;
360         scsi_qla_host_t *vha = shost_priv(host);
361         struct qla_hw_data *ha = vha->hw;
362         int rval = (DRIVER_ERROR << 16);
363         int req_sg_cnt, rsp_sg_cnt;
364         uint16_t loop_id;
365         struct fc_port *fcport;
366         char  *type = "FC_BSG_HST_CT";
367         struct srb_ctx *ct;
368
369         /* pass through is supported only for ISP 4Gb or higher */
370         if (!IS_FWI2_CAPABLE(ha)) {
371                 DEBUG2(qla_printk(KERN_INFO, ha,
372                     "scsi(%ld):Firmware is not capable to support FC "
373                     "CT pass thru\n", vha->host_no));
374                 rval = -EPERM;
375                 goto done;
376         }
377
378         req_sg_cnt =
379                 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
380                         bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
381         if (!req_sg_cnt) {
382                 rval = -ENOMEM;
383                 goto done;
384         }
385
386         rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
387                 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
388         if (!rsp_sg_cnt) {
389                 rval = -ENOMEM;
390                 goto done;
391         }
392
393         if ((req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
394             (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
395                 DEBUG2(qla_printk(KERN_WARNING, ha,
396                     "[request_sg_cnt: %x dma_request_sg_cnt: %x\
397                     reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
398                     bsg_job->request_payload.sg_cnt, req_sg_cnt,
399                     bsg_job->reply_payload.sg_cnt, rsp_sg_cnt));
400                 rval = -EAGAIN;
401                 goto done_unmap_sg;
402         }
403
404         if (!vha->flags.online) {
405                 DEBUG2(qla_printk(KERN_WARNING, ha,
406                         "host not online\n"));
407                 rval = -EIO;
408                 goto done_unmap_sg;
409         }
410
411         loop_id =
412                 (bsg_job->request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
413                         >> 24;
414         switch (loop_id) {
415         case 0xFC:
416                 loop_id = cpu_to_le16(NPH_SNS);
417                 break;
418         case 0xFA:
419                 loop_id = vha->mgmt_svr_loop_id;
420                 break;
421         default:
422                 DEBUG2(qla_printk(KERN_INFO, ha,
423                     "Unknown loop id: %x\n", loop_id));
424                 rval = -EINVAL;
425                 goto done_unmap_sg;
426         }
427
428         /* Allocate a dummy fcport structure, since functions preparing the
429          * IOCB and mailbox command retrieves port specific information
430          * from fcport structure. For Host based ELS commands there will be
431          * no fcport structure allocated
432          */
433         fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
434         if (!fcport) {
435                 rval = -ENOMEM;
436                 goto done_unmap_sg;
437         }
438
439         /* Initialize all required  fields of fcport */
440         fcport->vha = vha;
441         fcport->vp_idx = vha->vp_idx;
442         fcport->d_id.b.al_pa = bsg_job->request->rqst_data.h_ct.port_id[0];
443         fcport->d_id.b.area = bsg_job->request->rqst_data.h_ct.port_id[1];
444         fcport->d_id.b.domain = bsg_job->request->rqst_data.h_ct.port_id[2];
445         fcport->loop_id = loop_id;
446
447         /* Alloc SRB structure */
448         sp = qla2x00_get_ctx_bsg_sp(vha, fcport, sizeof(struct srb_ctx));
449         if (!sp) {
450                 rval = -ENOMEM;
451                 goto done_free_fcport;
452         }
453
454         ct = sp->ctx;
455         ct->type = SRB_CT_CMD;
456         ct->name = "bsg_ct";
457         ct->u.bsg_job = bsg_job;
458
459         DEBUG2(qla_printk(KERN_INFO, ha,
460                 "scsi(%ld:%x): bsg rqst type: %s els type: %x - loop-id=%x "
461                 "portid=%02x%02x%02x.\n", vha->host_no, sp->handle, type,
462                 (bsg_job->request->rqst_data.h_ct.preamble_word2 >> 16),
463                 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
464                 fcport->d_id.b.al_pa));
465
466         rval = qla2x00_start_sp(sp);
467         if (rval != QLA_SUCCESS) {
468                 kfree(sp->ctx);
469                 mempool_free(sp, ha->srb_mempool);
470                 rval = -EIO;
471                 goto done_free_fcport;
472         }
473         return rval;
474
475 done_free_fcport:
476         kfree(fcport);
477 done_unmap_sg:
478         dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
479                 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
480         dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
481                 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
482 done:
483         return rval;
484 }
485
486 static int
487 qla2x00_process_loopback(struct fc_bsg_job *bsg_job)
488 {
489         struct Scsi_Host *host = bsg_job->shost;
490         scsi_qla_host_t *vha = shost_priv(host);
491         struct qla_hw_data *ha = vha->hw;
492         int rval;
493         uint8_t command_sent;
494         char *type;
495         struct msg_echo_lb elreq;
496         uint16_t response[MAILBOX_REGISTER_COUNT];
497         uint8_t *fw_sts_ptr;
498         uint8_t *req_data = NULL;
499         dma_addr_t req_data_dma;
500         uint32_t req_data_len;
501         uint8_t *rsp_data = NULL;
502         dma_addr_t rsp_data_dma;
503         uint32_t rsp_data_len;
504
505         if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
506                 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
507                 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
508                 return -EBUSY;
509
510         if (!vha->flags.online) {
511                 DEBUG2(qla_printk(KERN_WARNING, ha, "host not online\n"));
512                 return -EIO;
513         }
514
515         elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
516                 bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
517                 DMA_TO_DEVICE);
518
519         if (!elreq.req_sg_cnt)
520                 return -ENOMEM;
521
522         elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
523                 bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
524                 DMA_FROM_DEVICE);
525
526         if (!elreq.rsp_sg_cnt) {
527                 rval = -ENOMEM;
528                 goto done_unmap_req_sg;
529         }
530
531         if ((elreq.req_sg_cnt !=  bsg_job->request_payload.sg_cnt) ||
532                 (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
533                 DEBUG2(printk(KERN_INFO
534                         "dma mapping resulted in different sg counts "
535                         "[request_sg_cnt: %x dma_request_sg_cnt: %x "
536                         "reply_sg_cnt: %x dma_reply_sg_cnt: %x]\n",
537                         bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
538                         bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt));
539                 rval = -EAGAIN;
540                 goto done_unmap_sg;
541         }
542         req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
543         req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
544                 &req_data_dma, GFP_KERNEL);
545         if (!req_data) {
546                 DEBUG2(printk(KERN_ERR "%s: dma alloc for req_data "
547                         "failed for host=%lu\n", __func__, vha->host_no));
548                 rval = -ENOMEM;
549                 goto done_unmap_sg;
550         }
551
552         rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
553                 &rsp_data_dma, GFP_KERNEL);
554         if (!rsp_data) {
555                 DEBUG2(printk(KERN_ERR "%s: dma alloc for rsp_data "
556                         "failed for host=%lu\n", __func__, vha->host_no));
557                 rval = -ENOMEM;
558                 goto done_free_dma_req;
559         }
560
561         /* Copy the request buffer in req_data now */
562         sg_copy_to_buffer(bsg_job->request_payload.sg_list,
563                 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
564
565         elreq.send_dma = req_data_dma;
566         elreq.rcv_dma = rsp_data_dma;
567         elreq.transfer_size = req_data_len;
568
569         elreq.options = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
570
571         if (ha->current_topology != ISP_CFG_F) {
572                 type = "FC_BSG_HST_VENDOR_LOOPBACK";
573                 DEBUG2(qla_printk(KERN_INFO, ha,
574                         "scsi(%ld) bsg rqst type: %s\n",
575                         vha->host_no, type));
576
577                 command_sent = INT_DEF_LB_LOOPBACK_CMD;
578                 rval = qla2x00_loopback_test(vha, &elreq, response);
579                 if (IS_QLA81XX(ha)) {
580                         if (response[0] == MBS_COMMAND_ERROR &&
581                                 response[1] == MBS_LB_RESET) {
582                                 DEBUG2(printk(KERN_ERR "%s(%ld): ABORTing "
583                                 "ISP\n", __func__, vha->host_no));
584                                 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
585                                 qla2xxx_wake_dpc(vha);
586                         }
587                 }
588         } else {
589                 type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
590                 DEBUG2(qla_printk(KERN_INFO, ha,
591                     "scsi(%ld) bsg rqst type: %s\n", vha->host_no, type));
592                 command_sent = INT_DEF_LB_ECHO_CMD;
593                 rval = qla2x00_echo_test(vha, &elreq, response);
594         }
595
596         if (rval) {
597                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
598                     "request %s failed\n", vha->host_no, type));
599
600                 fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
601                     sizeof(struct fc_bsg_reply);
602
603                 memcpy(fw_sts_ptr, response, sizeof(response));
604                 fw_sts_ptr += sizeof(response);
605                 *fw_sts_ptr = command_sent;
606                 rval = 0;
607                 bsg_job->reply->reply_payload_rcv_len = 0;
608                 bsg_job->reply->result = (DID_ERROR << 16);
609         } else {
610                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
611                         "request %s completed\n", vha->host_no, type));
612
613                 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
614                         sizeof(response) + sizeof(uint8_t);
615                 bsg_job->reply->reply_payload_rcv_len =
616                         bsg_job->reply_payload.payload_len;
617                 fw_sts_ptr = ((uint8_t *)bsg_job->req->sense) +
618                         sizeof(struct fc_bsg_reply);
619                 memcpy(fw_sts_ptr, response, sizeof(response));
620                 fw_sts_ptr += sizeof(response);
621                 *fw_sts_ptr = command_sent;
622                 bsg_job->reply->result = DID_OK;
623                 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
624                         bsg_job->reply_payload.sg_cnt, rsp_data,
625                         rsp_data_len);
626         }
627         bsg_job->job_done(bsg_job);
628
629         dma_free_coherent(&ha->pdev->dev, rsp_data_len,
630                 rsp_data, rsp_data_dma);
631 done_free_dma_req:
632         dma_free_coherent(&ha->pdev->dev, req_data_len,
633                 req_data, req_data_dma);
634 done_unmap_sg:
635         dma_unmap_sg(&ha->pdev->dev,
636             bsg_job->reply_payload.sg_list,
637             bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
638 done_unmap_req_sg:
639         dma_unmap_sg(&ha->pdev->dev,
640             bsg_job->request_payload.sg_list,
641             bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
642         return rval;
643 }
644
645 static int
646 qla84xx_reset(struct fc_bsg_job *bsg_job)
647 {
648         struct Scsi_Host *host = bsg_job->shost;
649         scsi_qla_host_t *vha = shost_priv(host);
650         struct qla_hw_data *ha = vha->hw;
651         int rval = 0;
652         uint32_t flag;
653
654         if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
655             test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
656             test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
657                 return -EBUSY;
658
659         if (!IS_QLA84XX(ha)) {
660                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
661                    "exiting.\n", vha->host_no));
662                 return -EINVAL;
663         }
664
665         flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
666
667         rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
668
669         if (rval) {
670                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
671                     "request 84xx reset failed\n", vha->host_no));
672                 rval = bsg_job->reply->reply_payload_rcv_len = 0;
673                 bsg_job->reply->result = (DID_ERROR << 16);
674
675         } else {
676                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
677                     "request 84xx reset completed\n", vha->host_no));
678                 bsg_job->reply->result = DID_OK;
679         }
680
681         bsg_job->job_done(bsg_job);
682         return rval;
683 }
684
685 static int
686 qla84xx_updatefw(struct fc_bsg_job *bsg_job)
687 {
688         struct Scsi_Host *host = bsg_job->shost;
689         scsi_qla_host_t *vha = shost_priv(host);
690         struct qla_hw_data *ha = vha->hw;
691         struct verify_chip_entry_84xx *mn = NULL;
692         dma_addr_t mn_dma, fw_dma;
693         void *fw_buf = NULL;
694         int rval = 0;
695         uint32_t sg_cnt;
696         uint32_t data_len;
697         uint16_t options;
698         uint32_t flag;
699         uint32_t fw_ver;
700
701         if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
702                 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
703                 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
704                 return -EBUSY;
705
706         if (!IS_QLA84XX(ha)) {
707                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
708                         "exiting.\n", vha->host_no));
709                 return -EINVAL;
710         }
711
712         sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
713                 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
714         if (!sg_cnt)
715                 return -ENOMEM;
716
717         if (sg_cnt != bsg_job->request_payload.sg_cnt) {
718                 DEBUG2(printk(KERN_INFO
719                         "dma mapping resulted in different sg counts "
720                         "request_sg_cnt: %x dma_request_sg_cnt: %x ",
721                         bsg_job->request_payload.sg_cnt, sg_cnt));
722                 rval = -EAGAIN;
723                 goto done_unmap_sg;
724         }
725
726         data_len = bsg_job->request_payload.payload_len;
727         fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
728                 &fw_dma, GFP_KERNEL);
729         if (!fw_buf) {
730                 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw_buf "
731                         "failed for host=%lu\n", __func__, vha->host_no));
732                 rval = -ENOMEM;
733                 goto done_unmap_sg;
734         }
735
736         sg_copy_to_buffer(bsg_job->request_payload.sg_list,
737                 bsg_job->request_payload.sg_cnt, fw_buf, data_len);
738
739         mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
740         if (!mn) {
741                 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
742                         "failed for host=%lu\n", __func__, vha->host_no));
743                 rval = -ENOMEM;
744                 goto done_free_fw_buf;
745         }
746
747         flag = bsg_job->request->rqst_data.h_vendor.vendor_cmd[1];
748         fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2)));
749
750         memset(mn, 0, sizeof(struct access_chip_84xx));
751         mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
752         mn->entry_count = 1;
753
754         options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
755         if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD)
756                 options |= VCO_DIAG_FW;
757
758         mn->options = cpu_to_le16(options);
759         mn->fw_ver =  cpu_to_le32(fw_ver);
760         mn->fw_size =  cpu_to_le32(data_len);
761         mn->fw_seq_size =  cpu_to_le32(data_len);
762         mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma));
763         mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma));
764         mn->dseg_length = cpu_to_le32(data_len);
765         mn->data_seg_cnt = cpu_to_le16(1);
766
767         rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
768
769         if (rval) {
770                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
771                         "request 84xx updatefw failed\n", vha->host_no));
772
773                 rval = bsg_job->reply->reply_payload_rcv_len = 0;
774                 bsg_job->reply->result = (DID_ERROR << 16);
775
776         } else {
777                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
778                         "request 84xx updatefw completed\n", vha->host_no));
779
780                 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
781                 bsg_job->reply->result = DID_OK;
782         }
783
784         bsg_job->job_done(bsg_job);
785         dma_pool_free(ha->s_dma_pool, mn, mn_dma);
786
787 done_free_fw_buf:
788         dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma);
789
790 done_unmap_sg:
791         dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
792                 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
793
794         return rval;
795 }
796
797 static int
798 qla84xx_mgmt_cmd(struct fc_bsg_job *bsg_job)
799 {
800         struct Scsi_Host *host = bsg_job->shost;
801         scsi_qla_host_t *vha = shost_priv(host);
802         struct qla_hw_data *ha = vha->hw;
803         struct access_chip_84xx *mn = NULL;
804         dma_addr_t mn_dma, mgmt_dma;
805         void *mgmt_b = NULL;
806         int rval = 0;
807         struct qla_bsg_a84_mgmt *ql84_mgmt;
808         uint32_t sg_cnt;
809         uint32_t data_len = 0;
810         uint32_t dma_direction = DMA_NONE;
811
812         if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
813                 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
814                 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
815                 return -EBUSY;
816
817         if (!IS_QLA84XX(ha)) {
818                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld): Not 84xx, "
819                         "exiting.\n", vha->host_no));
820                 return -EINVAL;
821         }
822
823         ql84_mgmt = (struct qla_bsg_a84_mgmt *)((char *)bsg_job->request +
824                 sizeof(struct fc_bsg_request));
825         if (!ql84_mgmt) {
826                 DEBUG2(printk("%s(%ld): mgmt header not provided, exiting.\n",
827                         __func__, vha->host_no));
828                 return -EINVAL;
829         }
830
831         mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
832         if (!mn) {
833                 DEBUG2(printk(KERN_ERR "%s: dma alloc for fw buffer "
834                         "failed for host=%lu\n", __func__, vha->host_no));
835                 return -ENOMEM;
836         }
837
838         memset(mn, 0, sizeof(struct access_chip_84xx));
839         mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
840         mn->entry_count = 1;
841
842         switch (ql84_mgmt->mgmt.cmd) {
843         case QLA84_MGMT_READ_MEM:
844         case QLA84_MGMT_GET_INFO:
845                 sg_cnt = dma_map_sg(&ha->pdev->dev,
846                         bsg_job->reply_payload.sg_list,
847                         bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
848                 if (!sg_cnt) {
849                         rval = -ENOMEM;
850                         goto exit_mgmt;
851                 }
852
853                 dma_direction = DMA_FROM_DEVICE;
854
855                 if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
856                         DEBUG2(printk(KERN_INFO
857                                 "dma mapping resulted in different sg counts "
858                                 "reply_sg_cnt: %x dma_reply_sg_cnt: %x\n",
859                                 bsg_job->reply_payload.sg_cnt, sg_cnt));
860                         rval = -EAGAIN;
861                         goto done_unmap_sg;
862                 }
863
864                 data_len = bsg_job->reply_payload.payload_len;
865
866                 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
867                     &mgmt_dma, GFP_KERNEL);
868                 if (!mgmt_b) {
869                         DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
870                                 "failed for host=%lu\n",
871                                 __func__, vha->host_no));
872                         rval = -ENOMEM;
873                         goto done_unmap_sg;
874                 }
875
876                 if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) {
877                         mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
878                         mn->parameter1 =
879                                 cpu_to_le32(
880                                 ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
881
882                 } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) {
883                         mn->options = cpu_to_le16(ACO_REQUEST_INFO);
884                         mn->parameter1 =
885                                 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type);
886
887                         mn->parameter2 =
888                                 cpu_to_le32(
889                                 ql84_mgmt->mgmt.mgmtp.u.info.context);
890                 }
891                 break;
892
893         case QLA84_MGMT_WRITE_MEM:
894                 sg_cnt = dma_map_sg(&ha->pdev->dev,
895                         bsg_job->request_payload.sg_list,
896                         bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
897
898                 if (!sg_cnt) {
899                         rval = -ENOMEM;
900                         goto exit_mgmt;
901                 }
902
903                 dma_direction = DMA_TO_DEVICE;
904
905                 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
906                         DEBUG2(printk(KERN_INFO
907                                 "dma mapping resulted in different sg counts "
908                                 "request_sg_cnt: %x dma_request_sg_cnt: %x ",
909                                 bsg_job->request_payload.sg_cnt, sg_cnt));
910                         rval = -EAGAIN;
911                         goto done_unmap_sg;
912                 }
913
914                 data_len = bsg_job->request_payload.payload_len;
915                 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
916                         &mgmt_dma, GFP_KERNEL);
917                 if (!mgmt_b) {
918                         DEBUG2(printk(KERN_ERR "%s: dma alloc for mgmt_b "
919                                 "failed for host=%lu\n",
920                                 __func__, vha->host_no));
921                         rval = -ENOMEM;
922                         goto done_unmap_sg;
923                 }
924
925                 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
926                         bsg_job->request_payload.sg_cnt, mgmt_b, data_len);
927
928                 mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
929                 mn->parameter1 =
930                         cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
931                 break;
932
933         case QLA84_MGMT_CHNG_CONFIG:
934                 mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
935                 mn->parameter1 =
936                         cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id);
937
938                 mn->parameter2 =
939                         cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0);
940
941                 mn->parameter3 =
942                         cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1);
943                 break;
944
945         default:
946                 rval = -EIO;
947                 goto exit_mgmt;
948         }
949
950         if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
951                 mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
952                 mn->dseg_count = cpu_to_le16(1);
953                 mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma));
954                 mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma));
955                 mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len);
956         }
957
958         rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
959
960         if (rval) {
961                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
962                         "request 84xx mgmt failed\n", vha->host_no));
963
964                 rval = bsg_job->reply->reply_payload_rcv_len = 0;
965                 bsg_job->reply->result = (DID_ERROR << 16);
966
967         } else {
968                 DEBUG2(qla_printk(KERN_WARNING, ha, "scsi(%ld) Vendor "
969                         "request 84xx mgmt completed\n", vha->host_no));
970
971                 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
972                 bsg_job->reply->result = DID_OK;
973
974                 if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
975                         (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
976                         bsg_job->reply->reply_payload_rcv_len =
977                                 bsg_job->reply_payload.payload_len;
978
979                         sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
980                                 bsg_job->reply_payload.sg_cnt, mgmt_b,
981                                 data_len);
982                 }
983         }
984
985         bsg_job->job_done(bsg_job);
986
987 done_unmap_sg:
988         if (mgmt_b)
989                 dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
990
991         if (dma_direction == DMA_TO_DEVICE)
992                 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
993                         bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
994         else if (dma_direction == DMA_FROM_DEVICE)
995                 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
996                         bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
997
998 exit_mgmt:
999         dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1000
1001         return rval;
1002 }
1003
1004 static int
1005 qla24xx_iidma(struct fc_bsg_job *bsg_job)
1006 {
1007         struct Scsi_Host *host = bsg_job->shost;
1008         scsi_qla_host_t *vha = shost_priv(host);
1009         struct qla_hw_data *ha = vha->hw;
1010         int rval = 0;
1011         struct qla_port_param *port_param = NULL;
1012         fc_port_t *fcport = NULL;
1013         uint16_t mb[MAILBOX_REGISTER_COUNT];
1014         uint8_t *rsp_ptr = NULL;
1015
1016         bsg_job->reply->reply_payload_rcv_len = 0;
1017
1018         if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1019                 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1020                 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))
1021                 return -EBUSY;
1022
1023         if (!IS_IIDMA_CAPABLE(vha->hw)) {
1024                 DEBUG2(qla_printk(KERN_WARNING, ha, "%s(%lu): iiDMA not "
1025                         "supported\n",  __func__, vha->host_no));
1026                 return -EINVAL;
1027         }
1028
1029         port_param = (struct qla_port_param *)((char *)bsg_job->request +
1030                 sizeof(struct fc_bsg_request));
1031         if (!port_param) {
1032                 DEBUG2(printk("%s(%ld): port_param header not provided, "
1033                         "exiting.\n", __func__, vha->host_no));
1034                 return -EINVAL;
1035         }
1036
1037         if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
1038                 DEBUG2(printk(KERN_ERR "%s(%ld): Invalid destination type\n",
1039                         __func__, vha->host_no));
1040                 return -EINVAL;
1041         }
1042
1043         list_for_each_entry(fcport, &vha->vp_fcports, list) {
1044                 if (fcport->port_type != FCT_TARGET)
1045                         continue;
1046
1047                 if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn,
1048                         fcport->port_name, sizeof(fcport->port_name)))
1049                         continue;
1050                 break;
1051         }
1052
1053         if (!fcport) {
1054                 DEBUG2(printk(KERN_ERR "%s(%ld): Failed to find port\n",
1055                         __func__, vha->host_no));
1056                 return -EINVAL;
1057         }
1058
1059         if (port_param->mode)
1060                 rval = qla2x00_set_idma_speed(vha, fcport->loop_id,
1061                         port_param->speed, mb);
1062         else
1063                 rval = qla2x00_get_idma_speed(vha, fcport->loop_id,
1064                         &port_param->speed, mb);
1065
1066         if (rval) {
1067                 DEBUG16(printk(KERN_ERR "scsi(%ld): iIDMA cmd failed for "
1068                         "%02x%02x%02x%02x%02x%02x%02x%02x -- "
1069                         "%04x %x %04x %04x.\n",
1070                         vha->host_no, fcport->port_name[0],
1071                         fcport->port_name[1],
1072                         fcport->port_name[2], fcport->port_name[3],
1073                         fcport->port_name[4], fcport->port_name[5],
1074                         fcport->port_name[6], fcport->port_name[7], rval,
1075                         fcport->fp_speed, mb[0], mb[1]));
1076                 rval = 0;
1077                 bsg_job->reply->result = (DID_ERROR << 16);
1078
1079         } else {
1080                 if (!port_param->mode) {
1081                         bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
1082                                 sizeof(struct qla_port_param);
1083
1084                         rsp_ptr = ((uint8_t *)bsg_job->reply) +
1085                                 sizeof(struct fc_bsg_reply);
1086
1087                         memcpy(rsp_ptr, port_param,
1088                                 sizeof(struct qla_port_param));
1089                 }
1090
1091                 bsg_job->reply->result = DID_OK;
1092         }
1093
1094         bsg_job->job_done(bsg_job);
1095         return rval;
1096 }
1097
1098 static int
1099 qla2x00_process_vendor_specific(struct fc_bsg_job *bsg_job)
1100 {
1101         switch (bsg_job->request->rqst_data.h_vendor.vendor_cmd[0]) {
1102         case QL_VND_LOOPBACK:
1103                 return qla2x00_process_loopback(bsg_job);
1104
1105         case QL_VND_A84_RESET:
1106                 return qla84xx_reset(bsg_job);
1107
1108         case QL_VND_A84_UPDATE_FW:
1109                 return qla84xx_updatefw(bsg_job);
1110
1111         case QL_VND_A84_MGMT_CMD:
1112                 return qla84xx_mgmt_cmd(bsg_job);
1113
1114         case QL_VND_IIDMA:
1115                 return qla24xx_iidma(bsg_job);
1116
1117         case QL_VND_FCP_PRIO_CFG_CMD:
1118                 return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
1119
1120         default:
1121                 bsg_job->reply->result = (DID_ERROR << 16);
1122                 bsg_job->job_done(bsg_job);
1123                 return -ENOSYS;
1124         }
1125 }
1126
1127 int
1128 qla24xx_bsg_request(struct fc_bsg_job *bsg_job)
1129 {
1130         int ret = -EINVAL;
1131
1132         switch (bsg_job->request->msgcode) {
1133         case FC_BSG_RPT_ELS:
1134         case FC_BSG_HST_ELS_NOLOGIN:
1135                 ret = qla2x00_process_els(bsg_job);
1136                 break;
1137         case FC_BSG_HST_CT:
1138                 ret = qla2x00_process_ct(bsg_job);
1139                 break;
1140         case FC_BSG_HST_VENDOR:
1141                 ret = qla2x00_process_vendor_specific(bsg_job);
1142                 break;
1143         case FC_BSG_HST_ADD_RPORT:
1144         case FC_BSG_HST_DEL_RPORT:
1145         case FC_BSG_RPT_CT:
1146         default:
1147                 DEBUG2(printk("qla2xxx: unsupported BSG request\n"));
1148                 break;
1149         }
1150         return ret;
1151 }
1152
1153 int
1154 qla24xx_bsg_timeout(struct fc_bsg_job *bsg_job)
1155 {
1156         scsi_qla_host_t *vha = shost_priv(bsg_job->shost);
1157         struct qla_hw_data *ha = vha->hw;
1158         srb_t *sp;
1159         int cnt, que;
1160         unsigned long flags;
1161         struct req_que *req;
1162         struct srb_ctx *sp_bsg;
1163
1164         /* find the bsg job from the active list of commands */
1165         spin_lock_irqsave(&ha->hardware_lock, flags);
1166         for (que = 0; que < ha->max_req_queues; que++) {
1167                 req = ha->req_q_map[que];
1168                 if (!req)
1169                         continue;
1170
1171                 for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
1172                         sp = req->outstanding_cmds[cnt];
1173                         if (sp) {
1174                                 sp_bsg = sp->ctx;
1175
1176                                 if (((sp_bsg->type == SRB_CT_CMD) ||
1177                                         (sp_bsg->type == SRB_ELS_CMD_HST))
1178                                         && (sp_bsg->u.bsg_job == bsg_job)) {
1179                                         if (ha->isp_ops->abort_command(sp)) {
1180                                                 DEBUG2(qla_printk(KERN_INFO, ha,
1181                                                     "scsi(%ld): mbx "
1182                                                     "abort_command failed\n",
1183                                                     vha->host_no));
1184                                                 bsg_job->req->errors =
1185                                                 bsg_job->reply->result = -EIO;
1186                                         } else {
1187                                                 DEBUG2(qla_printk(KERN_INFO, ha,
1188                                                     "scsi(%ld): mbx "
1189                                                     "abort_command success\n",
1190                                                     vha->host_no));
1191                                                 bsg_job->req->errors =
1192                                                 bsg_job->reply->result = 0;
1193                                         }
1194                                         goto done;
1195                                 }
1196                         }
1197                 }
1198         }
1199         spin_unlock_irqrestore(&ha->hardware_lock, flags);
1200         DEBUG2(qla_printk(KERN_INFO, ha,
1201                 "scsi(%ld) SRB not found to abort\n", vha->host_no));
1202         bsg_job->req->errors = bsg_job->reply->result = -ENXIO;
1203         return 0;
1204
1205 done:
1206         spin_unlock_irqrestore(&ha->hardware_lock, flags);
1207         if (bsg_job->request->msgcode == FC_BSG_HST_CT)
1208                 kfree(sp->fcport);
1209         kfree(sp->ctx);
1210         mempool_free(sp, ha->srb_mempool);
1211         return 0;
1212 }