0001
0002
0003
0004
0005
0006 #include "qla_def.h"
0007 #include "qla_gbl.h"
0008
0009 #include <linux/kthread.h>
0010 #include <linux/vmalloc.h>
0011 #include <linux/delay.h>
0012 #include <linux/bsg-lib.h>
0013
0014 static void qla2xxx_free_fcport_work(struct work_struct *work)
0015 {
0016 struct fc_port *fcport = container_of(work, typeof(*fcport),
0017 free_work);
0018
0019 qla2x00_free_fcport(fcport);
0020 }
0021
0022
0023 void qla2x00_bsg_job_done(srb_t *sp, int res)
0024 {
0025 struct bsg_job *bsg_job = sp->u.bsg_job;
0026 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
0027
0028 ql_dbg(ql_dbg_user, sp->vha, 0x7009,
0029 "%s: sp hdl %x, result=%x bsg ptr %p\n",
0030 __func__, sp->handle, res, bsg_job);
0031
0032
0033 kref_put(&sp->cmd_kref, qla2x00_sp_release);
0034
0035 bsg_reply->result = res;
0036 bsg_job_done(bsg_job, bsg_reply->result,
0037 bsg_reply->reply_payload_rcv_len);
0038 }
0039
0040 void qla2x00_bsg_sp_free(srb_t *sp)
0041 {
0042 struct qla_hw_data *ha = sp->vha->hw;
0043 struct bsg_job *bsg_job = sp->u.bsg_job;
0044 struct fc_bsg_request *bsg_request = bsg_job->request;
0045 struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
0046
0047 if (sp->type == SRB_FXIOCB_BCMD) {
0048 piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
0049 &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
0050
0051 if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
0052 dma_unmap_sg(&ha->pdev->dev,
0053 bsg_job->request_payload.sg_list,
0054 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0055
0056 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
0057 dma_unmap_sg(&ha->pdev->dev,
0058 bsg_job->reply_payload.sg_list,
0059 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0060 } else {
0061
0062 if (sp->remap.remapped) {
0063 dma_pool_free(ha->purex_dma_pool, sp->remap.rsp.buf,
0064 sp->remap.rsp.dma);
0065 dma_pool_free(ha->purex_dma_pool, sp->remap.req.buf,
0066 sp->remap.req.dma);
0067 } else {
0068 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
0069 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0070
0071 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
0072 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0073 }
0074 }
0075
0076 if (sp->type == SRB_CT_CMD ||
0077 sp->type == SRB_FXIOCB_BCMD ||
0078 sp->type == SRB_ELS_CMD_HST) {
0079 INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work);
0080 queue_work(ha->wq, &sp->fcport->free_work);
0081 }
0082
0083 qla2x00_rel_sp(sp);
0084 }
0085
0086 int
0087 qla24xx_fcp_prio_cfg_valid(scsi_qla_host_t *vha,
0088 struct qla_fcp_prio_cfg *pri_cfg, uint8_t flag)
0089 {
0090 int i, ret, num_valid;
0091 uint8_t *bcode;
0092 struct qla_fcp_prio_entry *pri_entry;
0093 uint32_t *bcode_val_ptr, bcode_val;
0094
0095 ret = 1;
0096 num_valid = 0;
0097 bcode = (uint8_t *)pri_cfg;
0098 bcode_val_ptr = (uint32_t *)pri_cfg;
0099 bcode_val = (uint32_t)(*bcode_val_ptr);
0100
0101 if (bcode_val == 0xFFFFFFFF) {
0102
0103 ql_dbg(ql_dbg_user, vha, 0x7051,
0104 "No FCP Priority config data.\n");
0105 return 0;
0106 }
0107
0108 if (memcmp(bcode, "HQOS", 4)) {
0109
0110 ql_dbg(ql_dbg_user, vha, 0x7052,
0111 "Invalid FCP Priority data header. bcode=0x%x.\n",
0112 bcode_val);
0113 return 0;
0114 }
0115 if (flag != 1)
0116 return ret;
0117
0118 pri_entry = &pri_cfg->entry[0];
0119 for (i = 0; i < pri_cfg->num_entries; i++) {
0120 if (pri_entry->flags & FCP_PRIO_ENTRY_TAG_VALID)
0121 num_valid++;
0122 pri_entry++;
0123 }
0124
0125 if (num_valid == 0) {
0126
0127 ql_dbg(ql_dbg_user, vha, 0x7053,
0128 "No valid FCP Priority data entries.\n");
0129 ret = 0;
0130 } else {
0131
0132 ql_dbg(ql_dbg_user, vha, 0x7054,
0133 "Valid FCP priority data. num entries = %d.\n",
0134 num_valid);
0135 }
0136
0137 return ret;
0138 }
0139
0140 static int
0141 qla24xx_proc_fcp_prio_cfg_cmd(struct bsg_job *bsg_job)
0142 {
0143 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
0144 struct fc_bsg_request *bsg_request = bsg_job->request;
0145 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
0146 scsi_qla_host_t *vha = shost_priv(host);
0147 struct qla_hw_data *ha = vha->hw;
0148 int ret = 0;
0149 uint32_t len;
0150 uint32_t oper;
0151
0152 if (!(IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || IS_P3P_TYPE(ha))) {
0153 ret = -EINVAL;
0154 goto exit_fcp_prio_cfg;
0155 }
0156
0157
0158 oper = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
0159
0160
0161 if (!ha->fcp_prio_cfg && (oper != QLFC_FCP_PRIO_SET_CONFIG)) {
0162 ret = -EINVAL;
0163 goto exit_fcp_prio_cfg;
0164 }
0165 switch (oper) {
0166 case QLFC_FCP_PRIO_DISABLE:
0167 if (ha->flags.fcp_prio_enabled) {
0168 ha->flags.fcp_prio_enabled = 0;
0169 ha->fcp_prio_cfg->attributes &=
0170 ~FCP_PRIO_ATTR_ENABLE;
0171 qla24xx_update_all_fcp_prio(vha);
0172 bsg_reply->result = DID_OK;
0173 } else {
0174 ret = -EINVAL;
0175 bsg_reply->result = (DID_ERROR << 16);
0176 goto exit_fcp_prio_cfg;
0177 }
0178 break;
0179
0180 case QLFC_FCP_PRIO_ENABLE:
0181 if (!ha->flags.fcp_prio_enabled) {
0182 if (ha->fcp_prio_cfg) {
0183 ha->flags.fcp_prio_enabled = 1;
0184 ha->fcp_prio_cfg->attributes |=
0185 FCP_PRIO_ATTR_ENABLE;
0186 qla24xx_update_all_fcp_prio(vha);
0187 bsg_reply->result = DID_OK;
0188 } else {
0189 ret = -EINVAL;
0190 bsg_reply->result = (DID_ERROR << 16);
0191 goto exit_fcp_prio_cfg;
0192 }
0193 }
0194 break;
0195
0196 case QLFC_FCP_PRIO_GET_CONFIG:
0197 len = bsg_job->reply_payload.payload_len;
0198 if (!len || len > FCP_PRIO_CFG_SIZE) {
0199 ret = -EINVAL;
0200 bsg_reply->result = (DID_ERROR << 16);
0201 goto exit_fcp_prio_cfg;
0202 }
0203
0204 bsg_reply->result = DID_OK;
0205 bsg_reply->reply_payload_rcv_len =
0206 sg_copy_from_buffer(
0207 bsg_job->reply_payload.sg_list,
0208 bsg_job->reply_payload.sg_cnt, ha->fcp_prio_cfg,
0209 len);
0210
0211 break;
0212
0213 case QLFC_FCP_PRIO_SET_CONFIG:
0214 len = bsg_job->request_payload.payload_len;
0215 if (!len || len > FCP_PRIO_CFG_SIZE) {
0216 bsg_reply->result = (DID_ERROR << 16);
0217 ret = -EINVAL;
0218 goto exit_fcp_prio_cfg;
0219 }
0220
0221 if (!ha->fcp_prio_cfg) {
0222 ha->fcp_prio_cfg = vmalloc(FCP_PRIO_CFG_SIZE);
0223 if (!ha->fcp_prio_cfg) {
0224 ql_log(ql_log_warn, vha, 0x7050,
0225 "Unable to allocate memory for fcp prio "
0226 "config data (%x).\n", FCP_PRIO_CFG_SIZE);
0227 bsg_reply->result = (DID_ERROR << 16);
0228 ret = -ENOMEM;
0229 goto exit_fcp_prio_cfg;
0230 }
0231 }
0232
0233 memset(ha->fcp_prio_cfg, 0, FCP_PRIO_CFG_SIZE);
0234 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
0235 bsg_job->request_payload.sg_cnt, ha->fcp_prio_cfg,
0236 FCP_PRIO_CFG_SIZE);
0237
0238
0239
0240 if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1)) {
0241 bsg_reply->result = (DID_ERROR << 16);
0242 ret = -EINVAL;
0243
0244
0245
0246 vfree(ha->fcp_prio_cfg);
0247 ha->fcp_prio_cfg = NULL;
0248 goto exit_fcp_prio_cfg;
0249 }
0250
0251 ha->flags.fcp_prio_enabled = 0;
0252 if (ha->fcp_prio_cfg->attributes & FCP_PRIO_ATTR_ENABLE)
0253 ha->flags.fcp_prio_enabled = 1;
0254 qla24xx_update_all_fcp_prio(vha);
0255 bsg_reply->result = DID_OK;
0256 break;
0257 default:
0258 ret = -EINVAL;
0259 break;
0260 }
0261 exit_fcp_prio_cfg:
0262 if (!ret)
0263 bsg_job_done(bsg_job, bsg_reply->result,
0264 bsg_reply->reply_payload_rcv_len);
0265 return ret;
0266 }
0267
0268 static int
0269 qla2x00_process_els(struct bsg_job *bsg_job)
0270 {
0271 struct fc_bsg_request *bsg_request = bsg_job->request;
0272 struct fc_rport *rport;
0273 fc_port_t *fcport = NULL;
0274 struct Scsi_Host *host;
0275 scsi_qla_host_t *vha;
0276 struct qla_hw_data *ha;
0277 srb_t *sp;
0278 const char *type;
0279 int req_sg_cnt, rsp_sg_cnt;
0280 int rval = (DID_ERROR << 16);
0281 uint16_t nextlid = 0;
0282 uint32_t els_cmd = 0;
0283
0284 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
0285 rport = fc_bsg_to_rport(bsg_job);
0286 fcport = *(fc_port_t **) rport->dd_data;
0287 host = rport_to_shost(rport);
0288 vha = shost_priv(host);
0289 ha = vha->hw;
0290 type = "FC_BSG_RPT_ELS";
0291 } else {
0292 host = fc_bsg_to_shost(bsg_job);
0293 vha = shost_priv(host);
0294 ha = vha->hw;
0295 type = "FC_BSG_HST_ELS_NOLOGIN";
0296 els_cmd = bsg_request->rqst_data.h_els.command_code;
0297 if (els_cmd == ELS_AUTH_ELS)
0298 return qla_edif_process_els(vha, bsg_job);
0299 }
0300
0301 if (!vha->flags.online) {
0302 ql_log(ql_log_warn, vha, 0x7005, "Host not online.\n");
0303 rval = -EIO;
0304 goto done;
0305 }
0306
0307
0308 if (!IS_FWI2_CAPABLE(ha)) {
0309 ql_dbg(ql_dbg_user, vha, 0x7001,
0310 "ELS passthru not supported for ISP23xx based adapters.\n");
0311 rval = -EPERM;
0312 goto done;
0313 }
0314
0315
0316 if (bsg_job->request_payload.sg_cnt > 1 ||
0317 bsg_job->reply_payload.sg_cnt > 1) {
0318 ql_dbg(ql_dbg_user, vha, 0x7002,
0319 "Multiple SG's are not supported for ELS requests, "
0320 "request_sg_cnt=%x reply_sg_cnt=%x.\n",
0321 bsg_job->request_payload.sg_cnt,
0322 bsg_job->reply_payload.sg_cnt);
0323 rval = -EPERM;
0324 goto done;
0325 }
0326
0327
0328 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
0329
0330
0331
0332 if (qla2x00_fabric_login(vha, fcport, &nextlid)) {
0333 ql_dbg(ql_dbg_user, vha, 0x7003,
0334 "Failed to login port %06X for ELS passthru.\n",
0335 fcport->d_id.b24);
0336 rval = -EIO;
0337 goto done;
0338 }
0339 } else {
0340
0341
0342
0343
0344
0345 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
0346 if (!fcport) {
0347 rval = -ENOMEM;
0348 goto done;
0349 }
0350
0351
0352 fcport->vha = vha;
0353 fcport->d_id.b.al_pa =
0354 bsg_request->rqst_data.h_els.port_id[0];
0355 fcport->d_id.b.area =
0356 bsg_request->rqst_data.h_els.port_id[1];
0357 fcport->d_id.b.domain =
0358 bsg_request->rqst_data.h_els.port_id[2];
0359 fcport->loop_id =
0360 (fcport->d_id.b.al_pa == 0xFD) ?
0361 NPH_FABRIC_CONTROLLER : NPH_F_PORT;
0362 }
0363
0364 req_sg_cnt =
0365 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
0366 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0367 if (!req_sg_cnt) {
0368 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
0369 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0370 rval = -ENOMEM;
0371 goto done_free_fcport;
0372 }
0373
0374 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
0375 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0376 if (!rsp_sg_cnt) {
0377 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
0378 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0379 rval = -ENOMEM;
0380 goto done_free_fcport;
0381 }
0382
0383 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
0384 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
0385 ql_log(ql_log_warn, vha, 0x7008,
0386 "dma mapping resulted in different sg counts, "
0387 "request_sg_cnt: %x dma_request_sg_cnt:%x reply_sg_cnt:%x "
0388 "dma_reply_sg_cnt:%x.\n", bsg_job->request_payload.sg_cnt,
0389 req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
0390 rval = -EAGAIN;
0391 goto done_unmap_sg;
0392 }
0393
0394
0395 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
0396 if (!sp) {
0397 rval = -ENOMEM;
0398 goto done_unmap_sg;
0399 }
0400
0401 sp->type =
0402 (bsg_request->msgcode == FC_BSG_RPT_ELS ?
0403 SRB_ELS_CMD_RPT : SRB_ELS_CMD_HST);
0404 sp->name =
0405 (bsg_request->msgcode == FC_BSG_RPT_ELS ?
0406 "bsg_els_rpt" : "bsg_els_hst");
0407 sp->u.bsg_job = bsg_job;
0408 sp->free = qla2x00_bsg_sp_free;
0409 sp->done = qla2x00_bsg_job_done;
0410
0411 ql_dbg(ql_dbg_user, vha, 0x700a,
0412 "bsg rqst type: %s els type: %x - loop-id=%x "
0413 "portid=%-2x%02x%02x.\n", type,
0414 bsg_request->rqst_data.h_els.command_code, fcport->loop_id,
0415 fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa);
0416
0417 rval = qla2x00_start_sp(sp);
0418 if (rval != QLA_SUCCESS) {
0419 ql_log(ql_log_warn, vha, 0x700e,
0420 "qla2x00_start_sp failed = %d\n", rval);
0421 qla2x00_rel_sp(sp);
0422 rval = -EIO;
0423 goto done_unmap_sg;
0424 }
0425 return rval;
0426
0427 done_unmap_sg:
0428 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
0429 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0430 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
0431 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0432 goto done_free_fcport;
0433
0434 done_free_fcport:
0435 if (bsg_request->msgcode != FC_BSG_RPT_ELS)
0436 qla2x00_free_fcport(fcport);
0437 done:
0438 return rval;
0439 }
0440
0441 static inline uint16_t
0442 qla24xx_calc_ct_iocbs(uint16_t dsds)
0443 {
0444 uint16_t iocbs;
0445
0446 iocbs = 1;
0447 if (dsds > 2) {
0448 iocbs += (dsds - 2) / 5;
0449 if ((dsds - 2) % 5)
0450 iocbs++;
0451 }
0452 return iocbs;
0453 }
0454
0455 static int
0456 qla2x00_process_ct(struct bsg_job *bsg_job)
0457 {
0458 srb_t *sp;
0459 struct fc_bsg_request *bsg_request = bsg_job->request;
0460 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
0461 scsi_qla_host_t *vha = shost_priv(host);
0462 struct qla_hw_data *ha = vha->hw;
0463 int rval = (DID_ERROR << 16);
0464 int req_sg_cnt, rsp_sg_cnt;
0465 uint16_t loop_id;
0466 struct fc_port *fcport;
0467 char *type = "FC_BSG_HST_CT";
0468
0469 req_sg_cnt =
0470 dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
0471 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0472 if (!req_sg_cnt) {
0473 ql_log(ql_log_warn, vha, 0x700f,
0474 "dma_map_sg return %d for request\n", req_sg_cnt);
0475 rval = -ENOMEM;
0476 goto done;
0477 }
0478
0479 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
0480 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0481 if (!rsp_sg_cnt) {
0482 ql_log(ql_log_warn, vha, 0x7010,
0483 "dma_map_sg return %d for reply\n", rsp_sg_cnt);
0484 rval = -ENOMEM;
0485 goto done;
0486 }
0487
0488 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
0489 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
0490 ql_log(ql_log_warn, vha, 0x7011,
0491 "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
0492 "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
0493 req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
0494 rval = -EAGAIN;
0495 goto done_unmap_sg;
0496 }
0497
0498 if (!vha->flags.online) {
0499 ql_log(ql_log_warn, vha, 0x7012,
0500 "Host is not online.\n");
0501 rval = -EIO;
0502 goto done_unmap_sg;
0503 }
0504
0505 loop_id =
0506 (bsg_request->rqst_data.h_ct.preamble_word1 & 0xFF000000)
0507 >> 24;
0508 switch (loop_id) {
0509 case 0xFC:
0510 loop_id = NPH_SNS;
0511 break;
0512 case 0xFA:
0513 loop_id = vha->mgmt_svr_loop_id;
0514 break;
0515 default:
0516 ql_dbg(ql_dbg_user, vha, 0x7013,
0517 "Unknown loop id: %x.\n", loop_id);
0518 rval = -EINVAL;
0519 goto done_unmap_sg;
0520 }
0521
0522
0523
0524
0525
0526
0527 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
0528 if (!fcport) {
0529 ql_log(ql_log_warn, vha, 0x7014,
0530 "Failed to allocate fcport.\n");
0531 rval = -ENOMEM;
0532 goto done_unmap_sg;
0533 }
0534
0535
0536 fcport->vha = vha;
0537 fcport->d_id.b.al_pa = bsg_request->rqst_data.h_ct.port_id[0];
0538 fcport->d_id.b.area = bsg_request->rqst_data.h_ct.port_id[1];
0539 fcport->d_id.b.domain = bsg_request->rqst_data.h_ct.port_id[2];
0540 fcport->loop_id = loop_id;
0541
0542
0543 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
0544 if (!sp) {
0545 ql_log(ql_log_warn, vha, 0x7015,
0546 "qla2x00_get_sp failed.\n");
0547 rval = -ENOMEM;
0548 goto done_free_fcport;
0549 }
0550
0551 sp->type = SRB_CT_CMD;
0552 sp->name = "bsg_ct";
0553 sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
0554 sp->u.bsg_job = bsg_job;
0555 sp->free = qla2x00_bsg_sp_free;
0556 sp->done = qla2x00_bsg_job_done;
0557
0558 ql_dbg(ql_dbg_user, vha, 0x7016,
0559 "bsg rqst type: %s else type: %x - "
0560 "loop-id=%x portid=%02x%02x%02x.\n", type,
0561 (bsg_request->rqst_data.h_ct.preamble_word2 >> 16),
0562 fcport->loop_id, fcport->d_id.b.domain, fcport->d_id.b.area,
0563 fcport->d_id.b.al_pa);
0564
0565 rval = qla2x00_start_sp(sp);
0566 if (rval != QLA_SUCCESS) {
0567 ql_log(ql_log_warn, vha, 0x7017,
0568 "qla2x00_start_sp failed=%d.\n", rval);
0569 qla2x00_rel_sp(sp);
0570 rval = -EIO;
0571 goto done_free_fcport;
0572 }
0573 return rval;
0574
0575 done_free_fcport:
0576 qla2x00_free_fcport(fcport);
0577 done_unmap_sg:
0578 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
0579 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0580 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
0581 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0582 done:
0583 return rval;
0584 }
0585
0586
0587 static inline int
0588 qla81xx_reset_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
0589 int wait, int wait2)
0590 {
0591 int ret = 0;
0592 int rval = 0;
0593 uint16_t new_config[4];
0594 struct qla_hw_data *ha = vha->hw;
0595
0596 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha))
0597 goto done_reset_internal;
0598
0599 memset(new_config, 0 , sizeof(new_config));
0600 if ((config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
0601 ENABLE_INTERNAL_LOOPBACK ||
0602 (config[0] & INTERNAL_LOOPBACK_MASK) >> 1 ==
0603 ENABLE_EXTERNAL_LOOPBACK) {
0604 new_config[0] = config[0] & ~INTERNAL_LOOPBACK_MASK;
0605 ql_dbg(ql_dbg_user, vha, 0x70bf, "new_config[0]=%02x\n",
0606 (new_config[0] & INTERNAL_LOOPBACK_MASK));
0607 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3) ;
0608
0609 ha->notify_dcbx_comp = wait;
0610 ha->notify_lb_portup_comp = wait2;
0611
0612 ret = qla81xx_set_port_config(vha, new_config);
0613 if (ret != QLA_SUCCESS) {
0614 ql_log(ql_log_warn, vha, 0x7025,
0615 "Set port config failed.\n");
0616 ha->notify_dcbx_comp = 0;
0617 ha->notify_lb_portup_comp = 0;
0618 rval = -EINVAL;
0619 goto done_reset_internal;
0620 }
0621
0622
0623 if (wait && !wait_for_completion_timeout(&ha->dcbx_comp,
0624 (DCBX_COMP_TIMEOUT * HZ))) {
0625 ql_dbg(ql_dbg_user, vha, 0x7026,
0626 "DCBX completion not received.\n");
0627 ha->notify_dcbx_comp = 0;
0628 ha->notify_lb_portup_comp = 0;
0629 rval = -EINVAL;
0630 goto done_reset_internal;
0631 } else
0632 ql_dbg(ql_dbg_user, vha, 0x7027,
0633 "DCBX completion received.\n");
0634
0635 if (wait2 &&
0636 !wait_for_completion_timeout(&ha->lb_portup_comp,
0637 (LB_PORTUP_COMP_TIMEOUT * HZ))) {
0638 ql_dbg(ql_dbg_user, vha, 0x70c5,
0639 "Port up completion not received.\n");
0640 ha->notify_lb_portup_comp = 0;
0641 rval = -EINVAL;
0642 goto done_reset_internal;
0643 } else
0644 ql_dbg(ql_dbg_user, vha, 0x70c6,
0645 "Port up completion received.\n");
0646
0647 ha->notify_dcbx_comp = 0;
0648 ha->notify_lb_portup_comp = 0;
0649 }
0650 done_reset_internal:
0651 return rval;
0652 }
0653
0654
0655
0656
0657
0658 static inline int
0659 qla81xx_set_loopback_mode(scsi_qla_host_t *vha, uint16_t *config,
0660 uint16_t *new_config, uint16_t mode)
0661 {
0662 int ret = 0;
0663 int rval = 0;
0664 unsigned long rem_tmo = 0, current_tmo = 0;
0665 struct qla_hw_data *ha = vha->hw;
0666
0667 if (!IS_QLA81XX(ha) && !IS_QLA8031(ha) && !IS_QLA8044(ha))
0668 goto done_set_internal;
0669
0670 if (mode == INTERNAL_LOOPBACK)
0671 new_config[0] = config[0] | (ENABLE_INTERNAL_LOOPBACK << 1);
0672 else if (mode == EXTERNAL_LOOPBACK)
0673 new_config[0] = config[0] | (ENABLE_EXTERNAL_LOOPBACK << 1);
0674 ql_dbg(ql_dbg_user, vha, 0x70be,
0675 "new_config[0]=%02x\n", (new_config[0] & INTERNAL_LOOPBACK_MASK));
0676
0677 memcpy(&new_config[1], &config[1], sizeof(uint16_t) * 3);
0678
0679 ha->notify_dcbx_comp = 1;
0680 ret = qla81xx_set_port_config(vha, new_config);
0681 if (ret != QLA_SUCCESS) {
0682 ql_log(ql_log_warn, vha, 0x7021,
0683 "set port config failed.\n");
0684 ha->notify_dcbx_comp = 0;
0685 rval = -EINVAL;
0686 goto done_set_internal;
0687 }
0688
0689
0690 current_tmo = DCBX_COMP_TIMEOUT * HZ;
0691 while (1) {
0692 rem_tmo = wait_for_completion_timeout(&ha->dcbx_comp,
0693 current_tmo);
0694 if (!ha->idc_extend_tmo || rem_tmo) {
0695 ha->idc_extend_tmo = 0;
0696 break;
0697 }
0698 current_tmo = ha->idc_extend_tmo * HZ;
0699 ha->idc_extend_tmo = 0;
0700 }
0701
0702 if (!rem_tmo) {
0703 ql_dbg(ql_dbg_user, vha, 0x7022,
0704 "DCBX completion not received.\n");
0705 ret = qla81xx_reset_loopback_mode(vha, new_config, 0, 0);
0706
0707
0708
0709
0710 if (ret) {
0711 qla2xxx_dump_fw(vha);
0712 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
0713 }
0714 rval = -EINVAL;
0715 } else {
0716 if (ha->flags.idc_compl_status) {
0717 ql_dbg(ql_dbg_user, vha, 0x70c3,
0718 "Bad status in IDC Completion AEN\n");
0719 rval = -EINVAL;
0720 ha->flags.idc_compl_status = 0;
0721 } else
0722 ql_dbg(ql_dbg_user, vha, 0x7023,
0723 "DCBX completion received.\n");
0724 }
0725
0726 ha->notify_dcbx_comp = 0;
0727 ha->idc_extend_tmo = 0;
0728
0729 done_set_internal:
0730 return rval;
0731 }
0732
0733 static int
0734 qla2x00_process_loopback(struct bsg_job *bsg_job)
0735 {
0736 struct fc_bsg_request *bsg_request = bsg_job->request;
0737 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
0738 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
0739 scsi_qla_host_t *vha = shost_priv(host);
0740 struct qla_hw_data *ha = vha->hw;
0741 int rval;
0742 uint8_t command_sent;
0743 char *type;
0744 struct msg_echo_lb elreq;
0745 uint16_t response[MAILBOX_REGISTER_COUNT];
0746 uint16_t config[4], new_config[4];
0747 uint8_t *fw_sts_ptr;
0748 void *req_data = NULL;
0749 dma_addr_t req_data_dma;
0750 uint32_t req_data_len;
0751 uint8_t *rsp_data = NULL;
0752 dma_addr_t rsp_data_dma;
0753 uint32_t rsp_data_len;
0754
0755 if (!vha->flags.online) {
0756 ql_log(ql_log_warn, vha, 0x7019, "Host is not online.\n");
0757 return -EIO;
0758 }
0759
0760 memset(&elreq, 0, sizeof(elreq));
0761
0762 elreq.req_sg_cnt = dma_map_sg(&ha->pdev->dev,
0763 bsg_job->request_payload.sg_list, bsg_job->request_payload.sg_cnt,
0764 DMA_TO_DEVICE);
0765
0766 if (!elreq.req_sg_cnt) {
0767 ql_log(ql_log_warn, vha, 0x701a,
0768 "dma_map_sg returned %d for request.\n", elreq.req_sg_cnt);
0769 return -ENOMEM;
0770 }
0771
0772 elreq.rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
0773 bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
0774 DMA_FROM_DEVICE);
0775
0776 if (!elreq.rsp_sg_cnt) {
0777 ql_log(ql_log_warn, vha, 0x701b,
0778 "dma_map_sg returned %d for reply.\n", elreq.rsp_sg_cnt);
0779 rval = -ENOMEM;
0780 goto done_unmap_req_sg;
0781 }
0782
0783 if ((elreq.req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
0784 (elreq.rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
0785 ql_log(ql_log_warn, vha, 0x701c,
0786 "dma mapping resulted in different sg counts, "
0787 "request_sg_cnt: %x dma_request_sg_cnt: %x "
0788 "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
0789 bsg_job->request_payload.sg_cnt, elreq.req_sg_cnt,
0790 bsg_job->reply_payload.sg_cnt, elreq.rsp_sg_cnt);
0791 rval = -EAGAIN;
0792 goto done_unmap_sg;
0793 }
0794 req_data_len = rsp_data_len = bsg_job->request_payload.payload_len;
0795 req_data = dma_alloc_coherent(&ha->pdev->dev, req_data_len,
0796 &req_data_dma, GFP_KERNEL);
0797 if (!req_data) {
0798 ql_log(ql_log_warn, vha, 0x701d,
0799 "dma alloc failed for req_data.\n");
0800 rval = -ENOMEM;
0801 goto done_unmap_sg;
0802 }
0803
0804 rsp_data = dma_alloc_coherent(&ha->pdev->dev, rsp_data_len,
0805 &rsp_data_dma, GFP_KERNEL);
0806 if (!rsp_data) {
0807 ql_log(ql_log_warn, vha, 0x7004,
0808 "dma alloc failed for rsp_data.\n");
0809 rval = -ENOMEM;
0810 goto done_free_dma_req;
0811 }
0812
0813
0814 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
0815 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
0816
0817 elreq.send_dma = req_data_dma;
0818 elreq.rcv_dma = rsp_data_dma;
0819 elreq.transfer_size = req_data_len;
0820
0821 elreq.options = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
0822 elreq.iteration_count =
0823 bsg_request->rqst_data.h_vendor.vendor_cmd[2];
0824
0825 if (atomic_read(&vha->loop_state) == LOOP_READY &&
0826 ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) ||
0827 ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) &&
0828 get_unaligned_le32(req_data) == ELS_OPCODE_BYTE &&
0829 req_data_len == MAX_ELS_FRAME_PAYLOAD &&
0830 elreq.options == EXTERNAL_LOOPBACK))) {
0831 type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
0832 ql_dbg(ql_dbg_user, vha, 0x701e,
0833 "BSG request type: %s.\n", type);
0834 command_sent = INT_DEF_LB_ECHO_CMD;
0835 rval = qla2x00_echo_test(vha, &elreq, response);
0836 } else {
0837 if (IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) {
0838 memset(config, 0, sizeof(config));
0839 memset(new_config, 0, sizeof(new_config));
0840
0841 if (qla81xx_get_port_config(vha, config)) {
0842 ql_log(ql_log_warn, vha, 0x701f,
0843 "Get port config failed.\n");
0844 rval = -EPERM;
0845 goto done_free_dma_rsp;
0846 }
0847
0848 if ((config[0] & INTERNAL_LOOPBACK_MASK) != 0) {
0849 ql_dbg(ql_dbg_user, vha, 0x70c4,
0850 "Loopback operation already in "
0851 "progress.\n");
0852 rval = -EAGAIN;
0853 goto done_free_dma_rsp;
0854 }
0855
0856 ql_dbg(ql_dbg_user, vha, 0x70c0,
0857 "elreq.options=%04x\n", elreq.options);
0858
0859 if (elreq.options == EXTERNAL_LOOPBACK)
0860 if (IS_QLA8031(ha) || IS_QLA8044(ha))
0861 rval = qla81xx_set_loopback_mode(vha,
0862 config, new_config, elreq.options);
0863 else
0864 rval = qla81xx_reset_loopback_mode(vha,
0865 config, 1, 0);
0866 else
0867 rval = qla81xx_set_loopback_mode(vha, config,
0868 new_config, elreq.options);
0869
0870 if (rval) {
0871 rval = -EPERM;
0872 goto done_free_dma_rsp;
0873 }
0874
0875 type = "FC_BSG_HST_VENDOR_LOOPBACK";
0876 ql_dbg(ql_dbg_user, vha, 0x7028,
0877 "BSG request type: %s.\n", type);
0878
0879 command_sent = INT_DEF_LB_LOOPBACK_CMD;
0880 rval = qla2x00_loopback_test(vha, &elreq, response);
0881
0882 if (response[0] == MBS_COMMAND_ERROR &&
0883 response[1] == MBS_LB_RESET) {
0884 ql_log(ql_log_warn, vha, 0x7029,
0885 "MBX command error, Aborting ISP.\n");
0886 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
0887 qla2xxx_wake_dpc(vha);
0888 qla2x00_wait_for_chip_reset(vha);
0889
0890 if (IS_QLA81XX(ha)) {
0891 if (qla81xx_restart_mpi_firmware(vha) !=
0892 QLA_SUCCESS) {
0893 ql_log(ql_log_warn, vha, 0x702a,
0894 "MPI reset failed.\n");
0895 }
0896 }
0897
0898 rval = -EIO;
0899 goto done_free_dma_rsp;
0900 }
0901
0902 if (new_config[0]) {
0903 int ret;
0904
0905
0906
0907
0908 ret = qla81xx_reset_loopback_mode(vha,
0909 new_config, 0, 1);
0910 if (ret) {
0911
0912
0913
0914
0915
0916 qla2xxx_dump_fw(vha);
0917 set_bit(ISP_ABORT_NEEDED,
0918 &vha->dpc_flags);
0919 }
0920
0921 }
0922
0923 } else {
0924 type = "FC_BSG_HST_VENDOR_LOOPBACK";
0925 ql_dbg(ql_dbg_user, vha, 0x702b,
0926 "BSG request type: %s.\n", type);
0927 command_sent = INT_DEF_LB_LOOPBACK_CMD;
0928 rval = qla2x00_loopback_test(vha, &elreq, response);
0929 }
0930 }
0931
0932 if (rval) {
0933 ql_log(ql_log_warn, vha, 0x702c,
0934 "Vendor request %s failed.\n", type);
0935
0936 rval = 0;
0937 bsg_reply->result = (DID_ERROR << 16);
0938 bsg_reply->reply_payload_rcv_len = 0;
0939 } else {
0940 ql_dbg(ql_dbg_user, vha, 0x702d,
0941 "Vendor request %s completed.\n", type);
0942 bsg_reply->result = (DID_OK << 16);
0943 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
0944 bsg_job->reply_payload.sg_cnt, rsp_data,
0945 rsp_data_len);
0946 }
0947
0948 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
0949 sizeof(response) + sizeof(uint8_t);
0950 fw_sts_ptr = bsg_job->reply + sizeof(struct fc_bsg_reply);
0951 memcpy(bsg_job->reply + sizeof(struct fc_bsg_reply), response,
0952 sizeof(response));
0953 fw_sts_ptr += sizeof(response);
0954 *fw_sts_ptr = command_sent;
0955
0956 done_free_dma_rsp:
0957 dma_free_coherent(&ha->pdev->dev, rsp_data_len,
0958 rsp_data, rsp_data_dma);
0959 done_free_dma_req:
0960 dma_free_coherent(&ha->pdev->dev, req_data_len,
0961 req_data, req_data_dma);
0962 done_unmap_sg:
0963 dma_unmap_sg(&ha->pdev->dev,
0964 bsg_job->reply_payload.sg_list,
0965 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
0966 done_unmap_req_sg:
0967 dma_unmap_sg(&ha->pdev->dev,
0968 bsg_job->request_payload.sg_list,
0969 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
0970 if (!rval)
0971 bsg_job_done(bsg_job, bsg_reply->result,
0972 bsg_reply->reply_payload_rcv_len);
0973 return rval;
0974 }
0975
0976 static int
0977 qla84xx_reset(struct bsg_job *bsg_job)
0978 {
0979 struct fc_bsg_request *bsg_request = bsg_job->request;
0980 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
0981 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
0982 scsi_qla_host_t *vha = shost_priv(host);
0983 struct qla_hw_data *ha = vha->hw;
0984 int rval = 0;
0985 uint32_t flag;
0986
0987 if (!IS_QLA84XX(ha)) {
0988 ql_dbg(ql_dbg_user, vha, 0x702f, "Not 84xx, exiting.\n");
0989 return -EINVAL;
0990 }
0991
0992 flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
0993
0994 rval = qla84xx_reset_chip(vha, flag == A84_ISSUE_RESET_DIAG_FW);
0995
0996 if (rval) {
0997 ql_log(ql_log_warn, vha, 0x7030,
0998 "Vendor request 84xx reset failed.\n");
0999 rval = (DID_ERROR << 16);
1000
1001 } else {
1002 ql_dbg(ql_dbg_user, vha, 0x7031,
1003 "Vendor request 84xx reset completed.\n");
1004 bsg_reply->result = DID_OK;
1005 bsg_job_done(bsg_job, bsg_reply->result,
1006 bsg_reply->reply_payload_rcv_len);
1007 }
1008
1009 return rval;
1010 }
1011
1012 static int
1013 qla84xx_updatefw(struct bsg_job *bsg_job)
1014 {
1015 struct fc_bsg_request *bsg_request = bsg_job->request;
1016 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1017 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1018 scsi_qla_host_t *vha = shost_priv(host);
1019 struct qla_hw_data *ha = vha->hw;
1020 struct verify_chip_entry_84xx *mn = NULL;
1021 dma_addr_t mn_dma, fw_dma;
1022 void *fw_buf = NULL;
1023 int rval = 0;
1024 uint32_t sg_cnt;
1025 uint32_t data_len;
1026 uint16_t options;
1027 uint32_t flag;
1028 uint32_t fw_ver;
1029
1030 if (!IS_QLA84XX(ha)) {
1031 ql_dbg(ql_dbg_user, vha, 0x7032,
1032 "Not 84xx, exiting.\n");
1033 return -EINVAL;
1034 }
1035
1036 sg_cnt = dma_map_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1037 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1038 if (!sg_cnt) {
1039 ql_log(ql_log_warn, vha, 0x7033,
1040 "dma_map_sg returned %d for request.\n", sg_cnt);
1041 return -ENOMEM;
1042 }
1043
1044 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1045 ql_log(ql_log_warn, vha, 0x7034,
1046 "DMA mapping resulted in different sg counts, "
1047 "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1048 bsg_job->request_payload.sg_cnt, sg_cnt);
1049 rval = -EAGAIN;
1050 goto done_unmap_sg;
1051 }
1052
1053 data_len = bsg_job->request_payload.payload_len;
1054 fw_buf = dma_alloc_coherent(&ha->pdev->dev, data_len,
1055 &fw_dma, GFP_KERNEL);
1056 if (!fw_buf) {
1057 ql_log(ql_log_warn, vha, 0x7035,
1058 "DMA alloc failed for fw_buf.\n");
1059 rval = -ENOMEM;
1060 goto done_unmap_sg;
1061 }
1062
1063 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1064 bsg_job->request_payload.sg_cnt, fw_buf, data_len);
1065
1066 mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1067 if (!mn) {
1068 ql_log(ql_log_warn, vha, 0x7036,
1069 "DMA alloc failed for fw buffer.\n");
1070 rval = -ENOMEM;
1071 goto done_free_fw_buf;
1072 }
1073
1074 flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1075 fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2);
1076
1077 mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
1078 mn->entry_count = 1;
1079
1080 options = VCO_FORCE_UPDATE | VCO_END_OF_DATA;
1081 if (flag == A84_ISSUE_UPDATE_DIAGFW_CMD)
1082 options |= VCO_DIAG_FW;
1083
1084 mn->options = cpu_to_le16(options);
1085 mn->fw_ver = cpu_to_le32(fw_ver);
1086 mn->fw_size = cpu_to_le32(data_len);
1087 mn->fw_seq_size = cpu_to_le32(data_len);
1088 put_unaligned_le64(fw_dma, &mn->dsd.address);
1089 mn->dsd.length = cpu_to_le32(data_len);
1090 mn->data_seg_cnt = cpu_to_le16(1);
1091
1092 rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
1093
1094 if (rval) {
1095 ql_log(ql_log_warn, vha, 0x7037,
1096 "Vendor request 84xx updatefw failed.\n");
1097
1098 rval = (DID_ERROR << 16);
1099 } else {
1100 ql_dbg(ql_dbg_user, vha, 0x7038,
1101 "Vendor request 84xx updatefw completed.\n");
1102
1103 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1104 bsg_reply->result = DID_OK;
1105 }
1106
1107 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1108
1109 done_free_fw_buf:
1110 dma_free_coherent(&ha->pdev->dev, data_len, fw_buf, fw_dma);
1111
1112 done_unmap_sg:
1113 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1114 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1115
1116 if (!rval)
1117 bsg_job_done(bsg_job, bsg_reply->result,
1118 bsg_reply->reply_payload_rcv_len);
1119 return rval;
1120 }
1121
1122 static int
1123 qla84xx_mgmt_cmd(struct bsg_job *bsg_job)
1124 {
1125 struct fc_bsg_request *bsg_request = bsg_job->request;
1126 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1127 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1128 scsi_qla_host_t *vha = shost_priv(host);
1129 struct qla_hw_data *ha = vha->hw;
1130 struct access_chip_84xx *mn = NULL;
1131 dma_addr_t mn_dma, mgmt_dma;
1132 void *mgmt_b = NULL;
1133 int rval = 0;
1134 struct qla_bsg_a84_mgmt *ql84_mgmt;
1135 uint32_t sg_cnt;
1136 uint32_t data_len = 0;
1137 uint32_t dma_direction = DMA_NONE;
1138
1139 if (!IS_QLA84XX(ha)) {
1140 ql_log(ql_log_warn, vha, 0x703a,
1141 "Not 84xx, exiting.\n");
1142 return -EINVAL;
1143 }
1144
1145 mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, &mn_dma);
1146 if (!mn) {
1147 ql_log(ql_log_warn, vha, 0x703c,
1148 "DMA alloc failed for fw buffer.\n");
1149 return -ENOMEM;
1150 }
1151
1152 mn->entry_type = ACCESS_CHIP_IOCB_TYPE;
1153 mn->entry_count = 1;
1154 ql84_mgmt = (void *)bsg_request + sizeof(struct fc_bsg_request);
1155 switch (ql84_mgmt->mgmt.cmd) {
1156 case QLA84_MGMT_READ_MEM:
1157 case QLA84_MGMT_GET_INFO:
1158 sg_cnt = dma_map_sg(&ha->pdev->dev,
1159 bsg_job->reply_payload.sg_list,
1160 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1161 if (!sg_cnt) {
1162 ql_log(ql_log_warn, vha, 0x703d,
1163 "dma_map_sg returned %d for reply.\n", sg_cnt);
1164 rval = -ENOMEM;
1165 goto exit_mgmt;
1166 }
1167
1168 dma_direction = DMA_FROM_DEVICE;
1169
1170 if (sg_cnt != bsg_job->reply_payload.sg_cnt) {
1171 ql_log(ql_log_warn, vha, 0x703e,
1172 "DMA mapping resulted in different sg counts, "
1173 "reply_sg_cnt: %x dma_reply_sg_cnt: %x.\n",
1174 bsg_job->reply_payload.sg_cnt, sg_cnt);
1175 rval = -EAGAIN;
1176 goto done_unmap_sg;
1177 }
1178
1179 data_len = bsg_job->reply_payload.payload_len;
1180
1181 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1182 &mgmt_dma, GFP_KERNEL);
1183 if (!mgmt_b) {
1184 ql_log(ql_log_warn, vha, 0x703f,
1185 "DMA alloc failed for mgmt_b.\n");
1186 rval = -ENOMEM;
1187 goto done_unmap_sg;
1188 }
1189
1190 if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) {
1191 mn->options = cpu_to_le16(ACO_DUMP_MEMORY);
1192 mn->parameter1 =
1193 cpu_to_le32(
1194 ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1195
1196 } else if (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO) {
1197 mn->options = cpu_to_le16(ACO_REQUEST_INFO);
1198 mn->parameter1 =
1199 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.info.type);
1200
1201 mn->parameter2 =
1202 cpu_to_le32(
1203 ql84_mgmt->mgmt.mgmtp.u.info.context);
1204 }
1205 break;
1206
1207 case QLA84_MGMT_WRITE_MEM:
1208 sg_cnt = dma_map_sg(&ha->pdev->dev,
1209 bsg_job->request_payload.sg_list,
1210 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1211
1212 if (!sg_cnt) {
1213 ql_log(ql_log_warn, vha, 0x7040,
1214 "dma_map_sg returned %d.\n", sg_cnt);
1215 rval = -ENOMEM;
1216 goto exit_mgmt;
1217 }
1218
1219 dma_direction = DMA_TO_DEVICE;
1220
1221 if (sg_cnt != bsg_job->request_payload.sg_cnt) {
1222 ql_log(ql_log_warn, vha, 0x7041,
1223 "DMA mapping resulted in different sg counts, "
1224 "request_sg_cnt: %x dma_request_sg_cnt: %x.\n",
1225 bsg_job->request_payload.sg_cnt, sg_cnt);
1226 rval = -EAGAIN;
1227 goto done_unmap_sg;
1228 }
1229
1230 data_len = bsg_job->request_payload.payload_len;
1231 mgmt_b = dma_alloc_coherent(&ha->pdev->dev, data_len,
1232 &mgmt_dma, GFP_KERNEL);
1233 if (!mgmt_b) {
1234 ql_log(ql_log_warn, vha, 0x7042,
1235 "DMA alloc failed for mgmt_b.\n");
1236 rval = -ENOMEM;
1237 goto done_unmap_sg;
1238 }
1239
1240 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1241 bsg_job->request_payload.sg_cnt, mgmt_b, data_len);
1242
1243 mn->options = cpu_to_le16(ACO_LOAD_MEMORY);
1244 mn->parameter1 =
1245 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.mem.start_addr);
1246 break;
1247
1248 case QLA84_MGMT_CHNG_CONFIG:
1249 mn->options = cpu_to_le16(ACO_CHANGE_CONFIG_PARAM);
1250 mn->parameter1 =
1251 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.id);
1252
1253 mn->parameter2 =
1254 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param0);
1255
1256 mn->parameter3 =
1257 cpu_to_le32(ql84_mgmt->mgmt.mgmtp.u.config.param1);
1258 break;
1259
1260 default:
1261 rval = -EIO;
1262 goto exit_mgmt;
1263 }
1264
1265 if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
1266 mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
1267 mn->dseg_count = cpu_to_le16(1);
1268 put_unaligned_le64(mgmt_dma, &mn->dsd.address);
1269 mn->dsd.length = cpu_to_le32(ql84_mgmt->mgmt.len);
1270 }
1271
1272 rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
1273
1274 if (rval) {
1275 ql_log(ql_log_warn, vha, 0x7043,
1276 "Vendor request 84xx mgmt failed.\n");
1277
1278 rval = (DID_ERROR << 16);
1279
1280 } else {
1281 ql_dbg(ql_dbg_user, vha, 0x7044,
1282 "Vendor request 84xx mgmt completed.\n");
1283
1284 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1285 bsg_reply->result = DID_OK;
1286
1287 if ((ql84_mgmt->mgmt.cmd == QLA84_MGMT_READ_MEM) ||
1288 (ql84_mgmt->mgmt.cmd == QLA84_MGMT_GET_INFO)) {
1289 bsg_reply->reply_payload_rcv_len =
1290 bsg_job->reply_payload.payload_len;
1291
1292 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1293 bsg_job->reply_payload.sg_cnt, mgmt_b,
1294 data_len);
1295 }
1296 }
1297
1298 done_unmap_sg:
1299 if (mgmt_b)
1300 dma_free_coherent(&ha->pdev->dev, data_len, mgmt_b, mgmt_dma);
1301
1302 if (dma_direction == DMA_TO_DEVICE)
1303 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
1304 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1305 else if (dma_direction == DMA_FROM_DEVICE)
1306 dma_unmap_sg(&ha->pdev->dev, bsg_job->reply_payload.sg_list,
1307 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1308
1309 exit_mgmt:
1310 dma_pool_free(ha->s_dma_pool, mn, mn_dma);
1311
1312 if (!rval)
1313 bsg_job_done(bsg_job, bsg_reply->result,
1314 bsg_reply->reply_payload_rcv_len);
1315 return rval;
1316 }
1317
1318 static int
1319 qla24xx_iidma(struct bsg_job *bsg_job)
1320 {
1321 struct fc_bsg_request *bsg_request = bsg_job->request;
1322 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1323 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1324 scsi_qla_host_t *vha = shost_priv(host);
1325 int rval = 0;
1326 struct qla_port_param *port_param = NULL;
1327 fc_port_t *fcport = NULL;
1328 int found = 0;
1329 uint16_t mb[MAILBOX_REGISTER_COUNT];
1330 uint8_t *rsp_ptr = NULL;
1331
1332 if (!IS_IIDMA_CAPABLE(vha->hw)) {
1333 ql_log(ql_log_info, vha, 0x7046, "iiDMA not supported.\n");
1334 return -EINVAL;
1335 }
1336
1337 port_param = (void *)bsg_request + sizeof(struct fc_bsg_request);
1338 if (port_param->fc_scsi_addr.dest_type != EXT_DEF_TYPE_WWPN) {
1339 ql_log(ql_log_warn, vha, 0x7048,
1340 "Invalid destination type.\n");
1341 return -EINVAL;
1342 }
1343
1344 list_for_each_entry(fcport, &vha->vp_fcports, list) {
1345 if (fcport->port_type != FCT_TARGET)
1346 continue;
1347
1348 if (memcmp(port_param->fc_scsi_addr.dest_addr.wwpn,
1349 fcport->port_name, sizeof(fcport->port_name)))
1350 continue;
1351
1352 found = 1;
1353 break;
1354 }
1355
1356 if (!found) {
1357 ql_log(ql_log_warn, vha, 0x7049,
1358 "Failed to find port.\n");
1359 return -EINVAL;
1360 }
1361
1362 if (atomic_read(&fcport->state) != FCS_ONLINE) {
1363 ql_log(ql_log_warn, vha, 0x704a,
1364 "Port is not online.\n");
1365 return -EINVAL;
1366 }
1367
1368 if (fcport->flags & FCF_LOGIN_NEEDED) {
1369 ql_log(ql_log_warn, vha, 0x704b,
1370 "Remote port not logged in flags = 0x%x.\n", fcport->flags);
1371 return -EINVAL;
1372 }
1373
1374 if (port_param->mode)
1375 rval = qla2x00_set_idma_speed(vha, fcport->loop_id,
1376 port_param->speed, mb);
1377 else
1378 rval = qla2x00_get_idma_speed(vha, fcport->loop_id,
1379 &port_param->speed, mb);
1380
1381 if (rval) {
1382 ql_log(ql_log_warn, vha, 0x704c,
1383 "iiDMA cmd failed for %8phN -- "
1384 "%04x %x %04x %04x.\n", fcport->port_name,
1385 rval, fcport->fp_speed, mb[0], mb[1]);
1386 rval = (DID_ERROR << 16);
1387 } else {
1388 if (!port_param->mode) {
1389 bsg_job->reply_len = sizeof(struct fc_bsg_reply) +
1390 sizeof(struct qla_port_param);
1391
1392 rsp_ptr = ((uint8_t *)bsg_reply) +
1393 sizeof(struct fc_bsg_reply);
1394
1395 memcpy(rsp_ptr, port_param,
1396 sizeof(struct qla_port_param));
1397 }
1398
1399 bsg_reply->result = DID_OK;
1400 bsg_job_done(bsg_job, bsg_reply->result,
1401 bsg_reply->reply_payload_rcv_len);
1402 }
1403
1404 return rval;
1405 }
1406
1407 static int
1408 qla2x00_optrom_setup(struct bsg_job *bsg_job, scsi_qla_host_t *vha,
1409 uint8_t is_update)
1410 {
1411 struct fc_bsg_request *bsg_request = bsg_job->request;
1412 uint32_t start = 0;
1413 int valid = 0;
1414 struct qla_hw_data *ha = vha->hw;
1415
1416 if (unlikely(pci_channel_offline(ha->pdev)))
1417 return -EINVAL;
1418
1419 start = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1420 if (start > ha->optrom_size) {
1421 ql_log(ql_log_warn, vha, 0x7055,
1422 "start %d > optrom_size %d.\n", start, ha->optrom_size);
1423 return -EINVAL;
1424 }
1425
1426 if (ha->optrom_state != QLA_SWAITING) {
1427 ql_log(ql_log_info, vha, 0x7056,
1428 "optrom_state %d.\n", ha->optrom_state);
1429 return -EBUSY;
1430 }
1431
1432 ha->optrom_region_start = start;
1433 ql_dbg(ql_dbg_user, vha, 0x7057, "is_update=%d.\n", is_update);
1434 if (is_update) {
1435 if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0)
1436 valid = 1;
1437 else if (start == (ha->flt_region_boot * 4) ||
1438 start == (ha->flt_region_fw * 4))
1439 valid = 1;
1440 else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) ||
1441 IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) ||
1442 IS_QLA28XX(ha))
1443 valid = 1;
1444 if (!valid) {
1445 ql_log(ql_log_warn, vha, 0x7058,
1446 "Invalid start region 0x%x/0x%x.\n", start,
1447 bsg_job->request_payload.payload_len);
1448 return -EINVAL;
1449 }
1450
1451 ha->optrom_region_size = start +
1452 bsg_job->request_payload.payload_len > ha->optrom_size ?
1453 ha->optrom_size - start :
1454 bsg_job->request_payload.payload_len;
1455 ha->optrom_state = QLA_SWRITING;
1456 } else {
1457 ha->optrom_region_size = start +
1458 bsg_job->reply_payload.payload_len > ha->optrom_size ?
1459 ha->optrom_size - start :
1460 bsg_job->reply_payload.payload_len;
1461 ha->optrom_state = QLA_SREADING;
1462 }
1463
1464 ha->optrom_buffer = vzalloc(ha->optrom_region_size);
1465 if (!ha->optrom_buffer) {
1466 ql_log(ql_log_warn, vha, 0x7059,
1467 "Read: Unable to allocate memory for optrom retrieval "
1468 "(%x)\n", ha->optrom_region_size);
1469
1470 ha->optrom_state = QLA_SWAITING;
1471 return -ENOMEM;
1472 }
1473
1474 return 0;
1475 }
1476
1477 static int
1478 qla2x00_read_optrom(struct bsg_job *bsg_job)
1479 {
1480 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1481 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1482 scsi_qla_host_t *vha = shost_priv(host);
1483 struct qla_hw_data *ha = vha->hw;
1484 int rval = 0;
1485
1486 if (ha->flags.nic_core_reset_hdlr_active)
1487 return -EBUSY;
1488
1489 mutex_lock(&ha->optrom_mutex);
1490 rval = qla2x00_optrom_setup(bsg_job, vha, 0);
1491 if (rval) {
1492 mutex_unlock(&ha->optrom_mutex);
1493 return rval;
1494 }
1495
1496 ha->isp_ops->read_optrom(vha, ha->optrom_buffer,
1497 ha->optrom_region_start, ha->optrom_region_size);
1498
1499 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1500 bsg_job->reply_payload.sg_cnt, ha->optrom_buffer,
1501 ha->optrom_region_size);
1502
1503 bsg_reply->reply_payload_rcv_len = ha->optrom_region_size;
1504 bsg_reply->result = DID_OK;
1505 vfree(ha->optrom_buffer);
1506 ha->optrom_buffer = NULL;
1507 ha->optrom_state = QLA_SWAITING;
1508 mutex_unlock(&ha->optrom_mutex);
1509 bsg_job_done(bsg_job, bsg_reply->result,
1510 bsg_reply->reply_payload_rcv_len);
1511 return rval;
1512 }
1513
1514 static int
1515 qla2x00_update_optrom(struct bsg_job *bsg_job)
1516 {
1517 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1518 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1519 scsi_qla_host_t *vha = shost_priv(host);
1520 struct qla_hw_data *ha = vha->hw;
1521 int rval = 0;
1522
1523 mutex_lock(&ha->optrom_mutex);
1524 rval = qla2x00_optrom_setup(bsg_job, vha, 1);
1525 if (rval) {
1526 mutex_unlock(&ha->optrom_mutex);
1527 return rval;
1528 }
1529
1530
1531 ha->flags.isp82xx_no_md_cap = 1;
1532
1533 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1534 bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
1535 ha->optrom_region_size);
1536
1537 rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
1538 ha->optrom_region_start, ha->optrom_region_size);
1539
1540 if (rval) {
1541 bsg_reply->result = -EINVAL;
1542 rval = -EINVAL;
1543 } else {
1544 bsg_reply->result = DID_OK;
1545 }
1546 vfree(ha->optrom_buffer);
1547 ha->optrom_buffer = NULL;
1548 ha->optrom_state = QLA_SWAITING;
1549 mutex_unlock(&ha->optrom_mutex);
1550 bsg_job_done(bsg_job, bsg_reply->result,
1551 bsg_reply->reply_payload_rcv_len);
1552 return rval;
1553 }
1554
1555 static int
1556 qla2x00_update_fru_versions(struct bsg_job *bsg_job)
1557 {
1558 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1559 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1560 scsi_qla_host_t *vha = shost_priv(host);
1561 struct qla_hw_data *ha = vha->hw;
1562 int rval = 0;
1563 uint8_t bsg[DMA_POOL_SIZE];
1564 struct qla_image_version_list *list = (void *)bsg;
1565 struct qla_image_version *image;
1566 uint32_t count;
1567 dma_addr_t sfp_dma;
1568 void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1569
1570 if (!sfp) {
1571 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1572 EXT_STATUS_NO_MEMORY;
1573 goto done;
1574 }
1575
1576 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1577 bsg_job->request_payload.sg_cnt, list, sizeof(bsg));
1578
1579 image = list->version;
1580 count = list->count;
1581 while (count--) {
1582 memcpy(sfp, &image->field_info, sizeof(image->field_info));
1583 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1584 image->field_address.device, image->field_address.offset,
1585 sizeof(image->field_info), image->field_address.option);
1586 if (rval) {
1587 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1588 EXT_STATUS_MAILBOX;
1589 goto dealloc;
1590 }
1591 image++;
1592 }
1593
1594 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1595
1596 dealloc:
1597 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1598
1599 done:
1600 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1601 bsg_reply->result = DID_OK << 16;
1602 bsg_job_done(bsg_job, bsg_reply->result,
1603 bsg_reply->reply_payload_rcv_len);
1604
1605 return 0;
1606 }
1607
1608 static int
1609 qla2x00_read_fru_status(struct bsg_job *bsg_job)
1610 {
1611 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1612 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1613 scsi_qla_host_t *vha = shost_priv(host);
1614 struct qla_hw_data *ha = vha->hw;
1615 int rval = 0;
1616 uint8_t bsg[DMA_POOL_SIZE];
1617 struct qla_status_reg *sr = (void *)bsg;
1618 dma_addr_t sfp_dma;
1619 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1620
1621 if (!sfp) {
1622 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1623 EXT_STATUS_NO_MEMORY;
1624 goto done;
1625 }
1626
1627 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1628 bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
1629
1630 rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1631 sr->field_address.device, sr->field_address.offset,
1632 sizeof(sr->status_reg), sr->field_address.option);
1633 sr->status_reg = *sfp;
1634
1635 if (rval) {
1636 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1637 EXT_STATUS_MAILBOX;
1638 goto dealloc;
1639 }
1640
1641 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1642 bsg_job->reply_payload.sg_cnt, sr, sizeof(*sr));
1643
1644 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1645
1646 dealloc:
1647 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1648
1649 done:
1650 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1651 bsg_reply->reply_payload_rcv_len = sizeof(*sr);
1652 bsg_reply->result = DID_OK << 16;
1653 bsg_job_done(bsg_job, bsg_reply->result,
1654 bsg_reply->reply_payload_rcv_len);
1655
1656 return 0;
1657 }
1658
1659 static int
1660 qla2x00_write_fru_status(struct bsg_job *bsg_job)
1661 {
1662 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1663 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1664 scsi_qla_host_t *vha = shost_priv(host);
1665 struct qla_hw_data *ha = vha->hw;
1666 int rval = 0;
1667 uint8_t bsg[DMA_POOL_SIZE];
1668 struct qla_status_reg *sr = (void *)bsg;
1669 dma_addr_t sfp_dma;
1670 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1671
1672 if (!sfp) {
1673 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1674 EXT_STATUS_NO_MEMORY;
1675 goto done;
1676 }
1677
1678 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1679 bsg_job->request_payload.sg_cnt, sr, sizeof(*sr));
1680
1681 *sfp = sr->status_reg;
1682 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1683 sr->field_address.device, sr->field_address.offset,
1684 sizeof(sr->status_reg), sr->field_address.option);
1685
1686 if (rval) {
1687 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1688 EXT_STATUS_MAILBOX;
1689 goto dealloc;
1690 }
1691
1692 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1693
1694 dealloc:
1695 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1696
1697 done:
1698 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1699 bsg_reply->result = DID_OK << 16;
1700 bsg_job_done(bsg_job, bsg_reply->result,
1701 bsg_reply->reply_payload_rcv_len);
1702
1703 return 0;
1704 }
1705
1706 static int
1707 qla2x00_write_i2c(struct bsg_job *bsg_job)
1708 {
1709 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1710 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1711 scsi_qla_host_t *vha = shost_priv(host);
1712 struct qla_hw_data *ha = vha->hw;
1713 int rval = 0;
1714 uint8_t bsg[DMA_POOL_SIZE];
1715 struct qla_i2c_access *i2c = (void *)bsg;
1716 dma_addr_t sfp_dma;
1717 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1718
1719 if (!sfp) {
1720 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1721 EXT_STATUS_NO_MEMORY;
1722 goto done;
1723 }
1724
1725 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1726 bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1727
1728 memcpy(sfp, i2c->buffer, i2c->length);
1729 rval = qla2x00_write_sfp(vha, sfp_dma, sfp,
1730 i2c->device, i2c->offset, i2c->length, i2c->option);
1731
1732 if (rval) {
1733 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1734 EXT_STATUS_MAILBOX;
1735 goto dealloc;
1736 }
1737
1738 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1739
1740 dealloc:
1741 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1742
1743 done:
1744 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1745 bsg_reply->result = DID_OK << 16;
1746 bsg_job_done(bsg_job, bsg_reply->result,
1747 bsg_reply->reply_payload_rcv_len);
1748
1749 return 0;
1750 }
1751
1752 static int
1753 qla2x00_read_i2c(struct bsg_job *bsg_job)
1754 {
1755 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1756 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1757 scsi_qla_host_t *vha = shost_priv(host);
1758 struct qla_hw_data *ha = vha->hw;
1759 int rval = 0;
1760 uint8_t bsg[DMA_POOL_SIZE];
1761 struct qla_i2c_access *i2c = (void *)bsg;
1762 dma_addr_t sfp_dma;
1763 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1764
1765 if (!sfp) {
1766 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1767 EXT_STATUS_NO_MEMORY;
1768 goto done;
1769 }
1770
1771 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
1772 bsg_job->request_payload.sg_cnt, i2c, sizeof(*i2c));
1773
1774 rval = qla2x00_read_sfp(vha, sfp_dma, sfp,
1775 i2c->device, i2c->offset, i2c->length, i2c->option);
1776
1777 if (rval) {
1778 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
1779 EXT_STATUS_MAILBOX;
1780 goto dealloc;
1781 }
1782
1783 memcpy(i2c->buffer, sfp, i2c->length);
1784 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
1785 bsg_job->reply_payload.sg_cnt, i2c, sizeof(*i2c));
1786
1787 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = 0;
1788
1789 dealloc:
1790 dma_pool_free(ha->s_dma_pool, sfp, sfp_dma);
1791
1792 done:
1793 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1794 bsg_reply->reply_payload_rcv_len = sizeof(*i2c);
1795 bsg_reply->result = DID_OK << 16;
1796 bsg_job_done(bsg_job, bsg_reply->result,
1797 bsg_reply->reply_payload_rcv_len);
1798
1799 return 0;
1800 }
1801
1802 static int
1803 qla24xx_process_bidir_cmd(struct bsg_job *bsg_job)
1804 {
1805 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
1806 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1807 scsi_qla_host_t *vha = shost_priv(host);
1808 struct qla_hw_data *ha = vha->hw;
1809 uint32_t rval = EXT_STATUS_OK;
1810 uint16_t req_sg_cnt = 0;
1811 uint16_t rsp_sg_cnt = 0;
1812 uint16_t nextlid = 0;
1813 uint32_t tot_dsds;
1814 srb_t *sp = NULL;
1815 uint32_t req_data_len;
1816 uint32_t rsp_data_len;
1817
1818
1819 if (!IS_BIDI_CAPABLE(ha)) {
1820 ql_log(ql_log_warn, vha, 0x70a0,
1821 "This adapter is not supported\n");
1822 rval = EXT_STATUS_NOT_SUPPORTED;
1823 goto done;
1824 }
1825
1826 if (test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
1827 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
1828 test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
1829 rval = EXT_STATUS_BUSY;
1830 goto done;
1831 }
1832
1833
1834 if (!vha->flags.online) {
1835 ql_log(ql_log_warn, vha, 0x70a1,
1836 "Host is not online\n");
1837 rval = EXT_STATUS_DEVICE_OFFLINE;
1838 goto done;
1839 }
1840
1841
1842 if (vha->device_flags & DFLG_NO_CABLE) {
1843 ql_log(ql_log_warn, vha, 0x70a2,
1844 "Cable is unplugged...\n");
1845 rval = EXT_STATUS_INVALID_CFG;
1846 goto done;
1847 }
1848
1849
1850 if (ha->current_topology != ISP_CFG_F) {
1851 ql_log(ql_log_warn, vha, 0x70a3,
1852 "Host is not connected to the switch\n");
1853 rval = EXT_STATUS_INVALID_CFG;
1854 goto done;
1855 }
1856
1857
1858 if (ha->operating_mode != P2P) {
1859 ql_log(ql_log_warn, vha, 0x70a4,
1860 "Host operating mode is not P2p\n");
1861 rval = EXT_STATUS_INVALID_CFG;
1862 goto done;
1863 }
1864
1865 mutex_lock(&ha->selflogin_lock);
1866 if (vha->self_login_loop_id == 0) {
1867
1868 vha->bidir_fcport.vha = vha;
1869 vha->bidir_fcport.d_id.b.al_pa = vha->d_id.b.al_pa;
1870 vha->bidir_fcport.d_id.b.area = vha->d_id.b.area;
1871 vha->bidir_fcport.d_id.b.domain = vha->d_id.b.domain;
1872 vha->bidir_fcport.loop_id = vha->loop_id;
1873
1874 if (qla2x00_fabric_login(vha, &(vha->bidir_fcport), &nextlid)) {
1875 ql_log(ql_log_warn, vha, 0x70a7,
1876 "Failed to login port %06X for bidirectional IOCB\n",
1877 vha->bidir_fcport.d_id.b24);
1878 mutex_unlock(&ha->selflogin_lock);
1879 rval = EXT_STATUS_MAILBOX;
1880 goto done;
1881 }
1882 vha->self_login_loop_id = nextlid - 1;
1883
1884 }
1885
1886 mutex_unlock(&ha->selflogin_lock);
1887
1888 vha->bidir_fcport.loop_id = vha->self_login_loop_id;
1889
1890 req_sg_cnt = dma_map_sg(&ha->pdev->dev,
1891 bsg_job->request_payload.sg_list,
1892 bsg_job->request_payload.sg_cnt,
1893 DMA_TO_DEVICE);
1894
1895 if (!req_sg_cnt) {
1896 rval = EXT_STATUS_NO_MEMORY;
1897 goto done;
1898 }
1899
1900 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
1901 bsg_job->reply_payload.sg_list, bsg_job->reply_payload.sg_cnt,
1902 DMA_FROM_DEVICE);
1903
1904 if (!rsp_sg_cnt) {
1905 rval = EXT_STATUS_NO_MEMORY;
1906 goto done_unmap_req_sg;
1907 }
1908
1909 if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
1910 (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
1911 ql_dbg(ql_dbg_user, vha, 0x70a9,
1912 "Dma mapping resulted in different sg counts "
1913 "[request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt: "
1914 "%x dma_reply_sg_cnt: %x]\n",
1915 bsg_job->request_payload.sg_cnt, req_sg_cnt,
1916 bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
1917 rval = EXT_STATUS_NO_MEMORY;
1918 goto done_unmap_sg;
1919 }
1920
1921 req_data_len = bsg_job->request_payload.payload_len;
1922 rsp_data_len = bsg_job->reply_payload.payload_len;
1923
1924 if (req_data_len != rsp_data_len) {
1925 rval = EXT_STATUS_BUSY;
1926 ql_log(ql_log_warn, vha, 0x70aa,
1927 "req_data_len != rsp_data_len\n");
1928 goto done_unmap_sg;
1929 }
1930
1931
1932 sp = qla2x00_get_sp(vha, &(vha->bidir_fcport), GFP_KERNEL);
1933 if (!sp) {
1934 ql_dbg(ql_dbg_user, vha, 0x70ac,
1935 "Alloc SRB structure failed\n");
1936 rval = EXT_STATUS_NO_MEMORY;
1937 goto done_unmap_sg;
1938 }
1939
1940
1941 sp->u.bsg_job = bsg_job;
1942 sp->free = qla2x00_bsg_sp_free;
1943 sp->type = SRB_BIDI_CMD;
1944 sp->done = qla2x00_bsg_job_done;
1945
1946
1947 tot_dsds = rsp_sg_cnt + req_sg_cnt;
1948
1949 rval = qla2x00_start_bidir(sp, vha, tot_dsds);
1950 if (rval != EXT_STATUS_OK)
1951 goto done_free_srb;
1952
1953 return rval;
1954
1955 done_free_srb:
1956 mempool_free(sp, ha->srb_mempool);
1957 done_unmap_sg:
1958 dma_unmap_sg(&ha->pdev->dev,
1959 bsg_job->reply_payload.sg_list,
1960 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
1961 done_unmap_req_sg:
1962 dma_unmap_sg(&ha->pdev->dev,
1963 bsg_job->request_payload.sg_list,
1964 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
1965 done:
1966
1967
1968
1969
1970 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = rval;
1971 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
1972 bsg_reply->reply_payload_rcv_len = 0;
1973 bsg_reply->result = (DID_OK) << 16;
1974 bsg_job_done(bsg_job, bsg_reply->result,
1975 bsg_reply->reply_payload_rcv_len);
1976
1977 return 0;
1978 }
1979
1980 static int
1981 qlafx00_mgmt_cmd(struct bsg_job *bsg_job)
1982 {
1983 struct fc_bsg_request *bsg_request = bsg_job->request;
1984 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
1985 scsi_qla_host_t *vha = shost_priv(host);
1986 struct qla_hw_data *ha = vha->hw;
1987 int rval = (DID_ERROR << 16);
1988 struct qla_mt_iocb_rqst_fx00 *piocb_rqst;
1989 srb_t *sp;
1990 int req_sg_cnt = 0, rsp_sg_cnt = 0;
1991 struct fc_port *fcport;
1992 char *type = "FC_BSG_HST_FX_MGMT";
1993
1994
1995 piocb_rqst = (struct qla_mt_iocb_rqst_fx00 *)
1996 &bsg_request->rqst_data.h_vendor.vendor_cmd[1];
1997
1998
1999 ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf,
2000 piocb_rqst, sizeof(*piocb_rqst));
2001
2002 if (!vha->flags.online) {
2003 ql_log(ql_log_warn, vha, 0x70d0,
2004 "Host is not online.\n");
2005 rval = -EIO;
2006 goto done;
2007 }
2008
2009 if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID) {
2010 req_sg_cnt = dma_map_sg(&ha->pdev->dev,
2011 bsg_job->request_payload.sg_list,
2012 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2013 if (!req_sg_cnt) {
2014 ql_log(ql_log_warn, vha, 0x70c7,
2015 "dma_map_sg return %d for request\n", req_sg_cnt);
2016 rval = -ENOMEM;
2017 goto done;
2018 }
2019 }
2020
2021 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) {
2022 rsp_sg_cnt = dma_map_sg(&ha->pdev->dev,
2023 bsg_job->reply_payload.sg_list,
2024 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2025 if (!rsp_sg_cnt) {
2026 ql_log(ql_log_warn, vha, 0x70c8,
2027 "dma_map_sg return %d for reply\n", rsp_sg_cnt);
2028 rval = -ENOMEM;
2029 goto done_unmap_req_sg;
2030 }
2031 }
2032
2033 ql_dbg(ql_dbg_user, vha, 0x70c9,
2034 "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
2035 "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
2036 req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
2037
2038
2039
2040
2041
2042
2043 fcport = qla2x00_alloc_fcport(vha, GFP_KERNEL);
2044 if (!fcport) {
2045 ql_log(ql_log_warn, vha, 0x70ca,
2046 "Failed to allocate fcport.\n");
2047 rval = -ENOMEM;
2048 goto done_unmap_rsp_sg;
2049 }
2050
2051
2052 sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
2053 if (!sp) {
2054 ql_log(ql_log_warn, vha, 0x70cb,
2055 "qla2x00_get_sp failed.\n");
2056 rval = -ENOMEM;
2057 goto done_free_fcport;
2058 }
2059
2060
2061 fcport->vha = vha;
2062 fcport->loop_id = le32_to_cpu(piocb_rqst->dataword);
2063
2064 sp->type = SRB_FXIOCB_BCMD;
2065 sp->name = "bsg_fx_mgmt";
2066 sp->iocbs = qla24xx_calc_ct_iocbs(req_sg_cnt + rsp_sg_cnt);
2067 sp->u.bsg_job = bsg_job;
2068 sp->free = qla2x00_bsg_sp_free;
2069 sp->done = qla2x00_bsg_job_done;
2070
2071 ql_dbg(ql_dbg_user, vha, 0x70cc,
2072 "bsg rqst type: %s fx_mgmt_type: %x id=%x\n",
2073 type, piocb_rqst->func_type, fcport->loop_id);
2074
2075 rval = qla2x00_start_sp(sp);
2076 if (rval != QLA_SUCCESS) {
2077 ql_log(ql_log_warn, vha, 0x70cd,
2078 "qla2x00_start_sp failed=%d.\n", rval);
2079 mempool_free(sp, ha->srb_mempool);
2080 rval = -EIO;
2081 goto done_free_fcport;
2082 }
2083 return rval;
2084
2085 done_free_fcport:
2086 qla2x00_free_fcport(fcport);
2087
2088 done_unmap_rsp_sg:
2089 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
2090 dma_unmap_sg(&ha->pdev->dev,
2091 bsg_job->reply_payload.sg_list,
2092 bsg_job->reply_payload.sg_cnt, DMA_FROM_DEVICE);
2093 done_unmap_req_sg:
2094 if (piocb_rqst->flags & SRB_FXDISC_REQ_DMA_VALID)
2095 dma_unmap_sg(&ha->pdev->dev,
2096 bsg_job->request_payload.sg_list,
2097 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
2098
2099 done:
2100 return rval;
2101 }
2102
2103 static int
2104 qla26xx_serdes_op(struct bsg_job *bsg_job)
2105 {
2106 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2107 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2108 scsi_qla_host_t *vha = shost_priv(host);
2109 int rval = 0;
2110 struct qla_serdes_reg sr;
2111
2112 memset(&sr, 0, sizeof(sr));
2113
2114 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2115 bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
2116
2117 switch (sr.cmd) {
2118 case INT_SC_SERDES_WRITE_REG:
2119 rval = qla2x00_write_serdes_word(vha, sr.addr, sr.val);
2120 bsg_reply->reply_payload_rcv_len = 0;
2121 break;
2122 case INT_SC_SERDES_READ_REG:
2123 rval = qla2x00_read_serdes_word(vha, sr.addr, &sr.val);
2124 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2125 bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
2126 bsg_reply->reply_payload_rcv_len = sizeof(sr);
2127 break;
2128 default:
2129 ql_dbg(ql_dbg_user, vha, 0x708c,
2130 "Unknown serdes cmd %x.\n", sr.cmd);
2131 rval = -EINVAL;
2132 break;
2133 }
2134
2135 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2136 rval ? EXT_STATUS_MAILBOX : 0;
2137
2138 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2139 bsg_reply->result = DID_OK << 16;
2140 bsg_job_done(bsg_job, bsg_reply->result,
2141 bsg_reply->reply_payload_rcv_len);
2142 return 0;
2143 }
2144
2145 static int
2146 qla8044_serdes_op(struct bsg_job *bsg_job)
2147 {
2148 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2149 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2150 scsi_qla_host_t *vha = shost_priv(host);
2151 int rval = 0;
2152 struct qla_serdes_reg_ex sr;
2153
2154 memset(&sr, 0, sizeof(sr));
2155
2156 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2157 bsg_job->request_payload.sg_cnt, &sr, sizeof(sr));
2158
2159 switch (sr.cmd) {
2160 case INT_SC_SERDES_WRITE_REG:
2161 rval = qla8044_write_serdes_word(vha, sr.addr, sr.val);
2162 bsg_reply->reply_payload_rcv_len = 0;
2163 break;
2164 case INT_SC_SERDES_READ_REG:
2165 rval = qla8044_read_serdes_word(vha, sr.addr, &sr.val);
2166 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2167 bsg_job->reply_payload.sg_cnt, &sr, sizeof(sr));
2168 bsg_reply->reply_payload_rcv_len = sizeof(sr);
2169 break;
2170 default:
2171 ql_dbg(ql_dbg_user, vha, 0x7020,
2172 "Unknown serdes cmd %x.\n", sr.cmd);
2173 rval = -EINVAL;
2174 break;
2175 }
2176
2177 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2178 rval ? EXT_STATUS_MAILBOX : 0;
2179
2180 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2181 bsg_reply->result = DID_OK << 16;
2182 bsg_job_done(bsg_job, bsg_reply->result,
2183 bsg_reply->reply_payload_rcv_len);
2184 return 0;
2185 }
2186
2187 static int
2188 qla27xx_get_flash_upd_cap(struct bsg_job *bsg_job)
2189 {
2190 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2191 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2192 scsi_qla_host_t *vha = shost_priv(host);
2193 struct qla_hw_data *ha = vha->hw;
2194 struct qla_flash_update_caps cap;
2195
2196 if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha))
2197 return -EPERM;
2198
2199 memset(&cap, 0, sizeof(cap));
2200 cap.capabilities = (uint64_t)ha->fw_attributes_ext[1] << 48 |
2201 (uint64_t)ha->fw_attributes_ext[0] << 32 |
2202 (uint64_t)ha->fw_attributes_h << 16 |
2203 (uint64_t)ha->fw_attributes;
2204
2205 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2206 bsg_job->reply_payload.sg_cnt, &cap, sizeof(cap));
2207 bsg_reply->reply_payload_rcv_len = sizeof(cap);
2208
2209 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2210 EXT_STATUS_OK;
2211
2212 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2213 bsg_reply->result = DID_OK << 16;
2214 bsg_job_done(bsg_job, bsg_reply->result,
2215 bsg_reply->reply_payload_rcv_len);
2216 return 0;
2217 }
2218
2219 static int
2220 qla27xx_set_flash_upd_cap(struct bsg_job *bsg_job)
2221 {
2222 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2223 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2224 scsi_qla_host_t *vha = shost_priv(host);
2225 struct qla_hw_data *ha = vha->hw;
2226 uint64_t online_fw_attr = 0;
2227 struct qla_flash_update_caps cap;
2228
2229 if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
2230 return -EPERM;
2231
2232 memset(&cap, 0, sizeof(cap));
2233 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2234 bsg_job->request_payload.sg_cnt, &cap, sizeof(cap));
2235
2236 online_fw_attr = (uint64_t)ha->fw_attributes_ext[1] << 48 |
2237 (uint64_t)ha->fw_attributes_ext[0] << 32 |
2238 (uint64_t)ha->fw_attributes_h << 16 |
2239 (uint64_t)ha->fw_attributes;
2240
2241 if (online_fw_attr != cap.capabilities) {
2242 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2243 EXT_STATUS_INVALID_PARAM;
2244 return -EINVAL;
2245 }
2246
2247 if (cap.outage_duration < MAX_LOOP_TIMEOUT) {
2248 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2249 EXT_STATUS_INVALID_PARAM;
2250 return -EINVAL;
2251 }
2252
2253 bsg_reply->reply_payload_rcv_len = 0;
2254
2255 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2256 EXT_STATUS_OK;
2257
2258 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2259 bsg_reply->result = DID_OK << 16;
2260 bsg_job_done(bsg_job, bsg_reply->result,
2261 bsg_reply->reply_payload_rcv_len);
2262 return 0;
2263 }
2264
2265 static int
2266 qla27xx_get_bbcr_data(struct bsg_job *bsg_job)
2267 {
2268 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2269 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2270 scsi_qla_host_t *vha = shost_priv(host);
2271 struct qla_hw_data *ha = vha->hw;
2272 struct qla_bbcr_data bbcr;
2273 uint16_t loop_id, topo, sw_cap;
2274 uint8_t domain, area, al_pa, state;
2275 int rval;
2276
2277 if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
2278 return -EPERM;
2279
2280 memset(&bbcr, 0, sizeof(bbcr));
2281
2282 if (vha->flags.bbcr_enable)
2283 bbcr.status = QLA_BBCR_STATUS_ENABLED;
2284 else
2285 bbcr.status = QLA_BBCR_STATUS_DISABLED;
2286
2287 if (bbcr.status == QLA_BBCR_STATUS_ENABLED) {
2288 rval = qla2x00_get_adapter_id(vha, &loop_id, &al_pa,
2289 &area, &domain, &topo, &sw_cap);
2290 if (rval != QLA_SUCCESS) {
2291 bbcr.status = QLA_BBCR_STATUS_UNKNOWN;
2292 bbcr.state = QLA_BBCR_STATE_OFFLINE;
2293 bbcr.mbx1 = loop_id;
2294 goto done;
2295 }
2296
2297 state = (vha->bbcr >> 12) & 0x1;
2298
2299 if (state) {
2300 bbcr.state = QLA_BBCR_STATE_OFFLINE;
2301 bbcr.offline_reason_code = QLA_BBCR_REASON_LOGIN_REJECT;
2302 } else {
2303 bbcr.state = QLA_BBCR_STATE_ONLINE;
2304 bbcr.negotiated_bbscn = (vha->bbcr >> 8) & 0xf;
2305 }
2306
2307 bbcr.configured_bbscn = vha->bbcr & 0xf;
2308 }
2309
2310 done:
2311 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2312 bsg_job->reply_payload.sg_cnt, &bbcr, sizeof(bbcr));
2313 bsg_reply->reply_payload_rcv_len = sizeof(bbcr);
2314
2315 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2316
2317 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2318 bsg_reply->result = DID_OK << 16;
2319 bsg_job_done(bsg_job, bsg_reply->result,
2320 bsg_reply->reply_payload_rcv_len);
2321 return 0;
2322 }
2323
2324 static int
2325 qla2x00_get_priv_stats(struct bsg_job *bsg_job)
2326 {
2327 struct fc_bsg_request *bsg_request = bsg_job->request;
2328 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2329 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2330 scsi_qla_host_t *vha = shost_priv(host);
2331 struct qla_hw_data *ha = vha->hw;
2332 struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
2333 struct link_statistics *stats = NULL;
2334 dma_addr_t stats_dma;
2335 int rval;
2336 uint32_t *cmd = bsg_request->rqst_data.h_vendor.vendor_cmd;
2337 uint options = cmd[0] == QL_VND_GET_PRIV_STATS_EX ? cmd[1] : 0;
2338
2339 if (test_bit(UNLOADING, &vha->dpc_flags))
2340 return -ENODEV;
2341
2342 if (unlikely(pci_channel_offline(ha->pdev)))
2343 return -ENODEV;
2344
2345 if (qla2x00_reset_active(vha))
2346 return -EBUSY;
2347
2348 if (!IS_FWI2_CAPABLE(ha))
2349 return -EPERM;
2350
2351 stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
2352 GFP_KERNEL);
2353 if (!stats) {
2354 ql_log(ql_log_warn, vha, 0x70e2,
2355 "Failed to allocate memory for stats.\n");
2356 return -ENOMEM;
2357 }
2358
2359 rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options);
2360
2361 if (rval == QLA_SUCCESS) {
2362 ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5,
2363 stats, sizeof(*stats));
2364 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2365 bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats));
2366 }
2367
2368 bsg_reply->reply_payload_rcv_len = sizeof(*stats);
2369 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2370 rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
2371
2372 bsg_job->reply_len = sizeof(*bsg_reply);
2373 bsg_reply->result = DID_OK << 16;
2374 bsg_job_done(bsg_job, bsg_reply->result,
2375 bsg_reply->reply_payload_rcv_len);
2376
2377 dma_free_coherent(&ha->pdev->dev, sizeof(*stats),
2378 stats, stats_dma);
2379
2380 return 0;
2381 }
2382
2383 static int
2384 qla2x00_do_dport_diagnostics(struct bsg_job *bsg_job)
2385 {
2386 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2387 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2388 scsi_qla_host_t *vha = shost_priv(host);
2389 int rval;
2390 struct qla_dport_diag *dd;
2391
2392 if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) &&
2393 !IS_QLA28XX(vha->hw))
2394 return -EPERM;
2395
2396 dd = kmalloc(sizeof(*dd), GFP_KERNEL);
2397 if (!dd) {
2398 ql_log(ql_log_warn, vha, 0x70db,
2399 "Failed to allocate memory for dport.\n");
2400 return -ENOMEM;
2401 }
2402
2403 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2404 bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
2405
2406 rval = qla26xx_dport_diagnostics(
2407 vha, dd->buf, sizeof(dd->buf), dd->options);
2408 if (rval == QLA_SUCCESS) {
2409 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2410 bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
2411 }
2412
2413 bsg_reply->reply_payload_rcv_len = sizeof(*dd);
2414 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2415 rval ? EXT_STATUS_MAILBOX : EXT_STATUS_OK;
2416
2417 bsg_job->reply_len = sizeof(*bsg_reply);
2418 bsg_reply->result = DID_OK << 16;
2419 bsg_job_done(bsg_job, bsg_reply->result,
2420 bsg_reply->reply_payload_rcv_len);
2421
2422 kfree(dd);
2423
2424 return 0;
2425 }
2426
2427 static int
2428 qla2x00_do_dport_diagnostics_v2(struct bsg_job *bsg_job)
2429 {
2430 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2431 struct Scsi_Host *host = fc_bsg_to_shost(bsg_job);
2432 scsi_qla_host_t *vha = shost_priv(host);
2433 int rval;
2434 struct qla_dport_diag_v2 *dd;
2435 mbx_cmd_t mc;
2436 mbx_cmd_t *mcp = &mc;
2437 uint16_t options;
2438
2439 if (!IS_DPORT_CAPABLE(vha->hw))
2440 return -EPERM;
2441
2442 dd = kzalloc(sizeof(*dd), GFP_KERNEL);
2443 if (!dd)
2444 return -ENOMEM;
2445
2446 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2447 bsg_job->request_payload.sg_cnt, dd, sizeof(*dd));
2448
2449 options = dd->options;
2450
2451
2452 if (options == QLA_GET_DPORT_RESULT_V2 &&
2453 vha->dport_status & DPORT_DIAG_IN_PROGRESS) {
2454 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2455 EXT_STATUS_DPORT_DIAG_IN_PROCESS;
2456 goto dportcomplete;
2457 }
2458
2459
2460 if (vha->dport_status & DPORT_DIAG_CHIP_RESET_IN_PROGRESS &&
2461 (options == QLA_START_DPORT_TEST_V2 ||
2462 options == QLA_RESTART_DPORT_TEST_V2)) {
2463 vha->dport_status &= ~DPORT_DIAG_CHIP_RESET_IN_PROGRESS;
2464 }
2465
2466
2467 if (vha->dport_status & DPORT_DIAG_CHIP_RESET_IN_PROGRESS &&
2468 options == QLA_GET_DPORT_RESULT_V2) {
2469 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2470 EXT_STATUS_DPORT_DIAG_NOT_RUNNING;
2471 goto dportcomplete;
2472 }
2473
2474 rval = qla26xx_dport_diagnostics_v2(vha, dd, mcp);
2475
2476 if (rval == QLA_SUCCESS) {
2477 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2478 EXT_STATUS_OK;
2479 if (options == QLA_START_DPORT_TEST_V2 ||
2480 options == QLA_RESTART_DPORT_TEST_V2) {
2481 dd->mbx1 = mcp->mb[0];
2482 dd->mbx2 = mcp->mb[1];
2483 vha->dport_status |= DPORT_DIAG_IN_PROGRESS;
2484 } else if (options == QLA_GET_DPORT_RESULT_V2) {
2485 dd->mbx1 = le16_to_cpu(vha->dport_data[1]);
2486 dd->mbx2 = le16_to_cpu(vha->dport_data[2]);
2487 }
2488 } else {
2489 dd->mbx1 = mcp->mb[0];
2490 dd->mbx2 = mcp->mb[1];
2491 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
2492 EXT_STATUS_DPORT_DIAG_ERR;
2493 }
2494
2495 dportcomplete:
2496 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2497 bsg_job->reply_payload.sg_cnt, dd, sizeof(*dd));
2498
2499 bsg_reply->reply_payload_rcv_len = sizeof(*dd);
2500 bsg_job->reply_len = sizeof(*bsg_reply);
2501 bsg_reply->result = DID_OK << 16;
2502 bsg_job_done(bsg_job, bsg_reply->result,
2503 bsg_reply->reply_payload_rcv_len);
2504
2505 kfree(dd);
2506
2507 return 0;
2508 }
2509
2510 static int
2511 qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
2512 {
2513 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2514 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2515 struct qla_hw_data *ha = vha->hw;
2516 struct qla_active_regions regions = { };
2517 struct active_regions active_regions = { };
2518
2519 qla27xx_get_active_image(vha, &active_regions);
2520 regions.global_image = active_regions.global;
2521
2522 if (IS_QLA28XX(ha)) {
2523 qla28xx_get_aux_images(vha, &active_regions);
2524 regions.board_config = active_regions.aux.board_config;
2525 regions.vpd_nvram = active_regions.aux.vpd_nvram;
2526 regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1;
2527 regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3;
2528 }
2529
2530 ql_dbg(ql_dbg_user, vha, 0x70e1,
2531 "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n",
2532 __func__, vha->host_no, regions.global_image,
2533 regions.board_config, regions.vpd_nvram,
2534 regions.npiv_config_0_1, regions.npiv_config_2_3);
2535
2536 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2537 bsg_job->reply_payload.sg_cnt, ®ions, sizeof(regions));
2538
2539 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2540 bsg_reply->reply_payload_rcv_len = sizeof(regions);
2541 bsg_reply->result = DID_OK << 16;
2542 bsg_job->reply_len = sizeof(struct fc_bsg_reply);
2543 bsg_job_done(bsg_job, bsg_reply->result,
2544 bsg_reply->reply_payload_rcv_len);
2545
2546 return 0;
2547 }
2548
2549 static int
2550 qla2x00_manage_host_stats(struct bsg_job *bsg_job)
2551 {
2552 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2553 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2554 struct ql_vnd_mng_host_stats_param *req_data;
2555 struct ql_vnd_mng_host_stats_resp rsp_data;
2556 u32 req_data_len;
2557 int ret = 0;
2558
2559 if (!vha->flags.online) {
2560 ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
2561 return -EIO;
2562 }
2563
2564 req_data_len = bsg_job->request_payload.payload_len;
2565
2566 if (req_data_len != sizeof(struct ql_vnd_mng_host_stats_param)) {
2567 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2568 return -EIO;
2569 }
2570
2571 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2572 if (!req_data) {
2573 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2574 return -ENOMEM;
2575 }
2576
2577
2578 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2579 bsg_job->request_payload.sg_cnt, req_data,
2580 req_data_len);
2581
2582 switch (req_data->action) {
2583 case QLA_STOP:
2584 ret = qla2xxx_stop_stats(vha->host, req_data->stat_type);
2585 break;
2586 case QLA_START:
2587 ret = qla2xxx_start_stats(vha->host, req_data->stat_type);
2588 break;
2589 case QLA_CLEAR:
2590 ret = qla2xxx_reset_stats(vha->host, req_data->stat_type);
2591 break;
2592 default:
2593 ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
2594 ret = -EIO;
2595 break;
2596 }
2597
2598 kfree(req_data);
2599
2600
2601 rsp_data.status = ret;
2602 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2603
2604 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2605 bsg_reply->reply_payload_rcv_len =
2606 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2607 bsg_job->reply_payload.sg_cnt,
2608 &rsp_data,
2609 sizeof(struct ql_vnd_mng_host_stats_resp));
2610
2611 bsg_reply->result = DID_OK;
2612 bsg_job_done(bsg_job, bsg_reply->result,
2613 bsg_reply->reply_payload_rcv_len);
2614
2615 return ret;
2616 }
2617
2618 static int
2619 qla2x00_get_host_stats(struct bsg_job *bsg_job)
2620 {
2621 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2622 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2623 struct ql_vnd_stats_param *req_data;
2624 struct ql_vnd_host_stats_resp rsp_data;
2625 u32 req_data_len;
2626 int ret = 0;
2627 u64 ini_entry_count = 0;
2628 u64 entry_count = 0;
2629 u64 tgt_num = 0;
2630 u64 tmp_stat_type = 0;
2631 u64 response_len = 0;
2632 void *data;
2633
2634 req_data_len = bsg_job->request_payload.payload_len;
2635
2636 if (req_data_len != sizeof(struct ql_vnd_stats_param)) {
2637 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2638 return -EIO;
2639 }
2640
2641 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2642 if (!req_data) {
2643 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2644 return -ENOMEM;
2645 }
2646
2647
2648 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2649 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
2650
2651
2652 tmp_stat_type = req_data->stat_type;
2653
2654 if (tmp_stat_type & QLA2XX_TGT_SHT_LNK_DOWN) {
2655
2656 tgt_num = qla2x00_get_num_tgts(vha);
2657
2658 tmp_stat_type &= ~(1 << 17);
2659 }
2660
2661
2662 ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
2663
2664
2665 entry_count = ini_entry_count + tgt_num;
2666
2667 response_len = sizeof(struct ql_vnd_host_stats_resp) +
2668 (sizeof(struct ql_vnd_stat_entry) * entry_count);
2669
2670 if (response_len > bsg_job->reply_payload.payload_len) {
2671 rsp_data.status = EXT_STATUS_BUFFER_TOO_SMALL;
2672 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
2673 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2674
2675 bsg_reply->reply_payload_rcv_len =
2676 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2677 bsg_job->reply_payload.sg_cnt, &rsp_data,
2678 sizeof(struct ql_vnd_mng_host_stats_resp));
2679
2680 bsg_reply->result = DID_OK;
2681 bsg_job_done(bsg_job, bsg_reply->result,
2682 bsg_reply->reply_payload_rcv_len);
2683 goto host_stat_out;
2684 }
2685
2686 data = kzalloc(response_len, GFP_KERNEL);
2687 if (!data) {
2688 ret = -ENOMEM;
2689 goto host_stat_out;
2690 }
2691
2692 ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
2693 data, response_len);
2694
2695 rsp_data.status = EXT_STATUS_OK;
2696 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2697
2698 bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2699 bsg_job->reply_payload.sg_cnt,
2700 data, response_len);
2701 bsg_reply->result = DID_OK;
2702 bsg_job_done(bsg_job, bsg_reply->result,
2703 bsg_reply->reply_payload_rcv_len);
2704
2705 kfree(data);
2706 host_stat_out:
2707 kfree(req_data);
2708 return ret;
2709 }
2710
2711 static struct fc_rport *
2712 qla2xxx_find_rport(scsi_qla_host_t *vha, uint32_t tgt_num)
2713 {
2714 fc_port_t *fcport = NULL;
2715
2716 list_for_each_entry(fcport, &vha->vp_fcports, list) {
2717 if (fcport->rport->number == tgt_num)
2718 return fcport->rport;
2719 }
2720 return NULL;
2721 }
2722
2723 static int
2724 qla2x00_get_tgt_stats(struct bsg_job *bsg_job)
2725 {
2726 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2727 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2728 struct ql_vnd_tgt_stats_param *req_data;
2729 u32 req_data_len;
2730 int ret = 0;
2731 u64 response_len = 0;
2732 struct ql_vnd_tgt_stats_resp *data = NULL;
2733 struct fc_rport *rport = NULL;
2734
2735 if (!vha->flags.online) {
2736 ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
2737 return -EIO;
2738 }
2739
2740 req_data_len = bsg_job->request_payload.payload_len;
2741
2742 if (req_data_len != sizeof(struct ql_vnd_stat_entry)) {
2743 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2744 return -EIO;
2745 }
2746
2747 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2748 if (!req_data) {
2749 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2750 return -ENOMEM;
2751 }
2752
2753
2754 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2755 bsg_job->request_payload.sg_cnt,
2756 req_data, req_data_len);
2757
2758 response_len = sizeof(struct ql_vnd_tgt_stats_resp) +
2759 sizeof(struct ql_vnd_stat_entry);
2760
2761
2762 data = kzalloc(response_len, GFP_KERNEL);
2763 if (!data) {
2764 kfree(req_data);
2765 return -ENOMEM;
2766 }
2767
2768 if (response_len > bsg_job->reply_payload.payload_len) {
2769 data->status = EXT_STATUS_BUFFER_TOO_SMALL;
2770 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
2771 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
2772
2773 bsg_reply->reply_payload_rcv_len =
2774 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2775 bsg_job->reply_payload.sg_cnt, data,
2776 sizeof(struct ql_vnd_tgt_stats_resp));
2777
2778 bsg_reply->result = DID_OK;
2779 bsg_job_done(bsg_job, bsg_reply->result,
2780 bsg_reply->reply_payload_rcv_len);
2781 goto tgt_stat_out;
2782 }
2783
2784 rport = qla2xxx_find_rport(vha, req_data->tgt_id);
2785 if (!rport) {
2786 ql_log(ql_log_warn, vha, 0x0000, "target %d not found.\n", req_data->tgt_id);
2787 ret = EXT_STATUS_INVALID_PARAM;
2788 data->status = EXT_STATUS_INVALID_PARAM;
2789 goto reply;
2790 }
2791
2792 ret = qla2xxx_get_tgt_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
2793 rport, (void *)data, response_len);
2794
2795 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2796 reply:
2797 bsg_reply->reply_payload_rcv_len =
2798 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2799 bsg_job->reply_payload.sg_cnt, data,
2800 response_len);
2801 bsg_reply->result = DID_OK;
2802 bsg_job_done(bsg_job, bsg_reply->result,
2803 bsg_reply->reply_payload_rcv_len);
2804
2805 tgt_stat_out:
2806 kfree(data);
2807 kfree(req_data);
2808
2809 return ret;
2810 }
2811
2812 static int
2813 qla2x00_manage_host_port(struct bsg_job *bsg_job)
2814 {
2815 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
2816 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2817 struct ql_vnd_mng_host_port_param *req_data;
2818 struct ql_vnd_mng_host_port_resp rsp_data;
2819 u32 req_data_len;
2820 int ret = 0;
2821
2822 req_data_len = bsg_job->request_payload.payload_len;
2823
2824 if (req_data_len != sizeof(struct ql_vnd_mng_host_port_param)) {
2825 ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
2826 return -EIO;
2827 }
2828
2829 req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
2830 if (!req_data) {
2831 ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
2832 return -ENOMEM;
2833 }
2834
2835
2836 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
2837 bsg_job->request_payload.sg_cnt, req_data, req_data_len);
2838
2839 switch (req_data->action) {
2840 case QLA_ENABLE:
2841 ret = qla2xxx_enable_port(vha->host);
2842 break;
2843 case QLA_DISABLE:
2844 ret = qla2xxx_disable_port(vha->host);
2845 break;
2846 default:
2847 ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
2848 ret = -EIO;
2849 break;
2850 }
2851
2852 kfree(req_data);
2853
2854
2855 rsp_data.status = ret;
2856 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
2857 bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_port_resp);
2858
2859 bsg_reply->reply_payload_rcv_len =
2860 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
2861 bsg_job->reply_payload.sg_cnt, &rsp_data,
2862 sizeof(struct ql_vnd_mng_host_port_resp));
2863 bsg_reply->result = DID_OK;
2864 bsg_job_done(bsg_job, bsg_reply->result,
2865 bsg_reply->reply_payload_rcv_len);
2866
2867 return ret;
2868 }
2869
2870 static int
2871 qla2x00_process_vendor_specific(struct scsi_qla_host *vha, struct bsg_job *bsg_job)
2872 {
2873 struct fc_bsg_request *bsg_request = bsg_job->request;
2874
2875 ql_dbg(ql_dbg_edif, vha, 0x911b, "%s FC_BSG_HST_VENDOR cmd[0]=0x%x\n",
2876 __func__, bsg_request->rqst_data.h_vendor.vendor_cmd[0]);
2877
2878 switch (bsg_request->rqst_data.h_vendor.vendor_cmd[0]) {
2879 case QL_VND_LOOPBACK:
2880 return qla2x00_process_loopback(bsg_job);
2881
2882 case QL_VND_A84_RESET:
2883 return qla84xx_reset(bsg_job);
2884
2885 case QL_VND_A84_UPDATE_FW:
2886 return qla84xx_updatefw(bsg_job);
2887
2888 case QL_VND_A84_MGMT_CMD:
2889 return qla84xx_mgmt_cmd(bsg_job);
2890
2891 case QL_VND_IIDMA:
2892 return qla24xx_iidma(bsg_job);
2893
2894 case QL_VND_FCP_PRIO_CFG_CMD:
2895 return qla24xx_proc_fcp_prio_cfg_cmd(bsg_job);
2896
2897 case QL_VND_READ_FLASH:
2898 return qla2x00_read_optrom(bsg_job);
2899
2900 case QL_VND_UPDATE_FLASH:
2901 return qla2x00_update_optrom(bsg_job);
2902
2903 case QL_VND_SET_FRU_VERSION:
2904 return qla2x00_update_fru_versions(bsg_job);
2905
2906 case QL_VND_READ_FRU_STATUS:
2907 return qla2x00_read_fru_status(bsg_job);
2908
2909 case QL_VND_WRITE_FRU_STATUS:
2910 return qla2x00_write_fru_status(bsg_job);
2911
2912 case QL_VND_WRITE_I2C:
2913 return qla2x00_write_i2c(bsg_job);
2914
2915 case QL_VND_READ_I2C:
2916 return qla2x00_read_i2c(bsg_job);
2917
2918 case QL_VND_DIAG_IO_CMD:
2919 return qla24xx_process_bidir_cmd(bsg_job);
2920
2921 case QL_VND_FX00_MGMT_CMD:
2922 return qlafx00_mgmt_cmd(bsg_job);
2923
2924 case QL_VND_SERDES_OP:
2925 return qla26xx_serdes_op(bsg_job);
2926
2927 case QL_VND_SERDES_OP_EX:
2928 return qla8044_serdes_op(bsg_job);
2929
2930 case QL_VND_GET_FLASH_UPDATE_CAPS:
2931 return qla27xx_get_flash_upd_cap(bsg_job);
2932
2933 case QL_VND_SET_FLASH_UPDATE_CAPS:
2934 return qla27xx_set_flash_upd_cap(bsg_job);
2935
2936 case QL_VND_GET_BBCR_DATA:
2937 return qla27xx_get_bbcr_data(bsg_job);
2938
2939 case QL_VND_GET_PRIV_STATS:
2940 case QL_VND_GET_PRIV_STATS_EX:
2941 return qla2x00_get_priv_stats(bsg_job);
2942
2943 case QL_VND_DPORT_DIAGNOSTICS:
2944 return qla2x00_do_dport_diagnostics(bsg_job);
2945
2946 case QL_VND_DPORT_DIAGNOSTICS_V2:
2947 return qla2x00_do_dport_diagnostics_v2(bsg_job);
2948
2949 case QL_VND_EDIF_MGMT:
2950 return qla_edif_app_mgmt(bsg_job);
2951
2952 case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
2953 return qla2x00_get_flash_image_status(bsg_job);
2954
2955 case QL_VND_MANAGE_HOST_STATS:
2956 return qla2x00_manage_host_stats(bsg_job);
2957
2958 case QL_VND_GET_HOST_STATS:
2959 return qla2x00_get_host_stats(bsg_job);
2960
2961 case QL_VND_GET_TGT_STATS:
2962 return qla2x00_get_tgt_stats(bsg_job);
2963
2964 case QL_VND_MANAGE_HOST_PORT:
2965 return qla2x00_manage_host_port(bsg_job);
2966
2967 case QL_VND_MBX_PASSTHRU:
2968 return qla2x00_mailbox_passthru(bsg_job);
2969
2970 default:
2971 return -ENOSYS;
2972 }
2973 }
2974
2975 int
2976 qla24xx_bsg_request(struct bsg_job *bsg_job)
2977 {
2978 struct fc_bsg_request *bsg_request = bsg_job->request;
2979 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2980 int ret = -EINVAL;
2981 struct fc_rport *rport;
2982 struct Scsi_Host *host;
2983 scsi_qla_host_t *vha;
2984
2985
2986 bsg_reply->reply_payload_rcv_len = 0;
2987
2988 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
2989 rport = fc_bsg_to_rport(bsg_job);
2990 host = rport_to_shost(rport);
2991 vha = shost_priv(host);
2992 } else {
2993 host = fc_bsg_to_shost(bsg_job);
2994 vha = shost_priv(host);
2995 }
2996
2997
2998 if (bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_MANAGE_HOST_PORT ||
2999 bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_GET_HOST_STATS)
3000 goto skip_chip_chk;
3001
3002 if (vha->hw->flags.port_isolated) {
3003 bsg_reply->result = DID_ERROR;
3004
3005 return -EPERM;
3006 }
3007
3008 if (qla2x00_chip_is_down(vha)) {
3009 ql_dbg(ql_dbg_user, vha, 0x709f,
3010 "BSG: ISP abort active/needed -- cmd=%d.\n",
3011 bsg_request->msgcode);
3012 SET_DID_STATUS(bsg_reply->result, DID_ERROR);
3013 return -EBUSY;
3014 }
3015
3016 if (test_bit(PFLG_DRIVER_REMOVING, &vha->pci_flags)) {
3017 SET_DID_STATUS(bsg_reply->result, DID_ERROR);
3018 return -EIO;
3019 }
3020
3021 skip_chip_chk:
3022 ql_dbg(ql_dbg_user + ql_dbg_verbose, vha, 0x7000,
3023 "Entered %s msgcode=0x%x. bsg ptr %px\n",
3024 __func__, bsg_request->msgcode, bsg_job);
3025
3026 switch (bsg_request->msgcode) {
3027 case FC_BSG_RPT_ELS:
3028 case FC_BSG_HST_ELS_NOLOGIN:
3029 ret = qla2x00_process_els(bsg_job);
3030 break;
3031 case FC_BSG_HST_CT:
3032 ret = qla2x00_process_ct(bsg_job);
3033 break;
3034 case FC_BSG_HST_VENDOR:
3035 ret = qla2x00_process_vendor_specific(vha, bsg_job);
3036 break;
3037 case FC_BSG_HST_ADD_RPORT:
3038 case FC_BSG_HST_DEL_RPORT:
3039 case FC_BSG_RPT_CT:
3040 default:
3041 ql_log(ql_log_warn, vha, 0x705a, "Unsupported BSG request.\n");
3042 break;
3043 }
3044
3045 ql_dbg(ql_dbg_user + ql_dbg_verbose, vha, 0x7000,
3046 "%s done with return %x\n", __func__, ret);
3047
3048 return ret;
3049 }
3050
3051 int
3052 qla24xx_bsg_timeout(struct bsg_job *bsg_job)
3053 {
3054 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
3055 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
3056 struct qla_hw_data *ha = vha->hw;
3057 srb_t *sp;
3058 int cnt, que;
3059 unsigned long flags;
3060 struct req_que *req;
3061
3062 ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
3063 __func__, bsg_job);
3064
3065 if (qla2x00_isp_reg_stat(ha)) {
3066 ql_log(ql_log_info, vha, 0x9007,
3067 "PCI/Register disconnect.\n");
3068 qla_pci_set_eeh_busy(vha);
3069 }
3070
3071
3072 spin_lock_irqsave(&ha->hardware_lock, flags);
3073 for (que = 0; que < ha->max_req_queues; que++) {
3074 req = ha->req_q_map[que];
3075 if (!req)
3076 continue;
3077
3078 for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
3079 sp = req->outstanding_cmds[cnt];
3080 if (sp &&
3081 (sp->type == SRB_CT_CMD ||
3082 sp->type == SRB_ELS_CMD_HST ||
3083 sp->type == SRB_ELS_CMD_HST_NOLOGIN ||
3084 sp->type == SRB_FXIOCB_BCMD) &&
3085 sp->u.bsg_job == bsg_job) {
3086 req->outstanding_cmds[cnt] = NULL;
3087 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3088
3089 if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) {
3090 ql_log(ql_log_warn, vha, 0x7089,
3091 "mbx abort_command failed.\n");
3092 bsg_reply->result = -EIO;
3093 } else {
3094 ql_dbg(ql_dbg_user, vha, 0x708a,
3095 "mbx abort_command success.\n");
3096 bsg_reply->result = 0;
3097 }
3098 spin_lock_irqsave(&ha->hardware_lock, flags);
3099 goto done;
3100
3101 }
3102 }
3103 }
3104 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3105 ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
3106 bsg_reply->result = -ENXIO;
3107 return 0;
3108
3109 done:
3110 spin_unlock_irqrestore(&ha->hardware_lock, flags);
3111
3112 kref_put(&sp->cmd_kref, qla2x00_sp_release);
3113 return 0;
3114 }
3115
3116 int qla2x00_mailbox_passthru(struct bsg_job *bsg_job)
3117 {
3118 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
3119 scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
3120 int ret = -EINVAL;
3121 int ptsize = sizeof(struct qla_mbx_passthru);
3122 struct qla_mbx_passthru *req_data = NULL;
3123 uint32_t req_data_len;
3124
3125 req_data_len = bsg_job->request_payload.payload_len;
3126 if (req_data_len != ptsize) {
3127 ql_log(ql_log_warn, vha, 0xf0a3, "req_data_len invalid.\n");
3128 return -EIO;
3129 }
3130 req_data = kzalloc(ptsize, GFP_KERNEL);
3131 if (!req_data) {
3132 ql_log(ql_log_warn, vha, 0xf0a4,
3133 "req_data memory allocation failure.\n");
3134 return -ENOMEM;
3135 }
3136
3137
3138 sg_copy_to_buffer(bsg_job->request_payload.sg_list,
3139 bsg_job->request_payload.sg_cnt, req_data, ptsize);
3140 ret = qla_mailbox_passthru(vha, req_data->mbx_in, req_data->mbx_out);
3141
3142
3143 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
3144 bsg_job->reply_payload.sg_cnt, req_data, ptsize);
3145
3146 bsg_reply->reply_payload_rcv_len = ptsize;
3147 if (ret == QLA_SUCCESS)
3148 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
3149 else
3150 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_ERR;
3151
3152 bsg_job->reply_len = sizeof(*bsg_job->reply);
3153 bsg_reply->result = DID_OK << 16;
3154 bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
3155
3156 kfree(req_data);
3157
3158 return ret;
3159 }