| .. | .. |
|---|
| 1 | | - /* |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 2 | +/* |
|---|
| 2 | 3 | * QLogic Fibre Channel HBA Driver |
|---|
| 3 | 4 | * Copyright (c) 2003-2014 QLogic Corporation |
|---|
| 4 | | - * |
|---|
| 5 | | - * See LICENSE.qla2xxx for copyright and licensing details. |
|---|
| 6 | 5 | */ |
|---|
| 7 | 6 | #include "qla_def.h" |
|---|
| 8 | 7 | |
|---|
| .. | .. |
|---|
| 11 | 10 | #include <linux/delay.h> |
|---|
| 12 | 11 | #include <linux/bsg-lib.h> |
|---|
| 13 | 12 | |
|---|
| 14 | | -/* BSG support for ELS/CT pass through */ |
|---|
| 15 | | -void |
|---|
| 16 | | -qla2x00_bsg_job_done(void *ptr, int res) |
|---|
| 13 | +static void qla2xxx_free_fcport_work(struct work_struct *work) |
|---|
| 17 | 14 | { |
|---|
| 18 | | - srb_t *sp = ptr; |
|---|
| 15 | + struct fc_port *fcport = container_of(work, typeof(*fcport), |
|---|
| 16 | + free_work); |
|---|
| 17 | + |
|---|
| 18 | + qla2x00_free_fcport(fcport); |
|---|
| 19 | +} |
|---|
| 20 | + |
|---|
| 21 | +/* BSG support for ELS/CT pass through */ |
|---|
| 22 | +void qla2x00_bsg_job_done(srb_t *sp, int res) |
|---|
| 23 | +{ |
|---|
| 19 | 24 | struct bsg_job *bsg_job = sp->u.bsg_job; |
|---|
| 20 | 25 | struct fc_bsg_reply *bsg_reply = bsg_job->reply; |
|---|
| 21 | 26 | |
|---|
| .. | .. |
|---|
| 26 | 31 | bsg_reply->reply_payload_rcv_len); |
|---|
| 27 | 32 | } |
|---|
| 28 | 33 | |
|---|
| 29 | | -void |
|---|
| 30 | | -qla2x00_bsg_sp_free(void *ptr) |
|---|
| 34 | +void qla2x00_bsg_sp_free(srb_t *sp) |
|---|
| 31 | 35 | { |
|---|
| 32 | | - srb_t *sp = ptr; |
|---|
| 33 | 36 | struct qla_hw_data *ha = sp->vha->hw; |
|---|
| 34 | 37 | struct bsg_job *bsg_job = sp->u.bsg_job; |
|---|
| 35 | 38 | struct fc_bsg_request *bsg_request = bsg_job->request; |
|---|
| .. | .. |
|---|
| 58 | 61 | |
|---|
| 59 | 62 | if (sp->type == SRB_CT_CMD || |
|---|
| 60 | 63 | sp->type == SRB_FXIOCB_BCMD || |
|---|
| 61 | | - sp->type == SRB_ELS_CMD_HST) |
|---|
| 62 | | - kfree(sp->fcport); |
|---|
| 64 | + sp->type == SRB_ELS_CMD_HST) { |
|---|
| 65 | + INIT_WORK(&sp->fcport->free_work, qla2xxx_free_fcport_work); |
|---|
| 66 | + queue_work(ha->wq, &sp->fcport->free_work); |
|---|
| 67 | + } |
|---|
| 68 | + |
|---|
| 63 | 69 | qla2x00_rel_sp(sp); |
|---|
| 64 | 70 | } |
|---|
| 65 | 71 | |
|---|
| .. | .. |
|---|
| 85 | 91 | return 0; |
|---|
| 86 | 92 | } |
|---|
| 87 | 93 | |
|---|
| 88 | | - if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' || |
|---|
| 89 | | - bcode[3] != 'S') { |
|---|
| 94 | + if (memcmp(bcode, "HQOS", 4)) { |
|---|
| 90 | 95 | /* Invalid FCP priority data header*/ |
|---|
| 91 | 96 | ql_dbg(ql_dbg_user, vha, 0x7052, |
|---|
| 92 | 97 | "Invalid FCP Priority data header. bcode=0x%x.\n", |
|---|
| .. | .. |
|---|
| 218 | 223 | |
|---|
| 219 | 224 | /* validate fcp priority data */ |
|---|
| 220 | 225 | |
|---|
| 221 | | - if (!qla24xx_fcp_prio_cfg_valid(vha, |
|---|
| 222 | | - (struct qla_fcp_prio_cfg *) ha->fcp_prio_cfg, 1)) { |
|---|
| 226 | + if (!qla24xx_fcp_prio_cfg_valid(vha, ha->fcp_prio_cfg, 1)) { |
|---|
| 223 | 227 | bsg_reply->result = (DID_ERROR << 16); |
|---|
| 224 | 228 | ret = -EINVAL; |
|---|
| 225 | 229 | /* If buffer was invalidatic int |
|---|
| .. | .. |
|---|
| 264 | 268 | |
|---|
| 265 | 269 | if (bsg_request->msgcode == FC_BSG_RPT_ELS) { |
|---|
| 266 | 270 | rport = fc_bsg_to_rport(bsg_job); |
|---|
| 271 | + if (!rport) { |
|---|
| 272 | + rval = -ENOMEM; |
|---|
| 273 | + goto done; |
|---|
| 274 | + } |
|---|
| 267 | 275 | fcport = *(fc_port_t **) rport->dd_data; |
|---|
| 268 | 276 | host = rport_to_shost(rport); |
|---|
| 269 | 277 | vha = shost_priv(host); |
|---|
| .. | .. |
|---|
| 410 | 418 | goto done_free_fcport; |
|---|
| 411 | 419 | |
|---|
| 412 | 420 | done_free_fcport: |
|---|
| 413 | | - if (bsg_request->msgcode == FC_BSG_RPT_ELS) |
|---|
| 414 | | - kfree(fcport); |
|---|
| 421 | + if (bsg_request->msgcode != FC_BSG_RPT_ELS) |
|---|
| 422 | + qla2x00_free_fcport(fcport); |
|---|
| 415 | 423 | done: |
|---|
| 416 | 424 | return rval; |
|---|
| 417 | 425 | } |
|---|
| .. | .. |
|---|
| 485 | 493 | >> 24; |
|---|
| 486 | 494 | switch (loop_id) { |
|---|
| 487 | 495 | case 0xFC: |
|---|
| 488 | | - loop_id = cpu_to_le16(NPH_SNS); |
|---|
| 496 | + loop_id = NPH_SNS; |
|---|
| 489 | 497 | break; |
|---|
| 490 | 498 | case 0xFA: |
|---|
| 491 | 499 | loop_id = vha->mgmt_svr_loop_id; |
|---|
| .. | .. |
|---|
| 551 | 559 | return rval; |
|---|
| 552 | 560 | |
|---|
| 553 | 561 | done_free_fcport: |
|---|
| 554 | | - kfree(fcport); |
|---|
| 562 | + qla2x00_free_fcport(fcport); |
|---|
| 555 | 563 | done_unmap_sg: |
|---|
| 556 | 564 | dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list, |
|---|
| 557 | 565 | bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE); |
|---|
| .. | .. |
|---|
| 686 | 694 | * dump and reset the chip. |
|---|
| 687 | 695 | */ |
|---|
| 688 | 696 | if (ret) { |
|---|
| 689 | | - ha->isp_ops->fw_dump(vha, 0); |
|---|
| 697 | + qla2xxx_dump_fw(vha); |
|---|
| 690 | 698 | set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); |
|---|
| 691 | 699 | } |
|---|
| 692 | 700 | rval = -EINVAL; |
|---|
| .. | .. |
|---|
| 723 | 731 | uint16_t response[MAILBOX_REGISTER_COUNT]; |
|---|
| 724 | 732 | uint16_t config[4], new_config[4]; |
|---|
| 725 | 733 | uint8_t *fw_sts_ptr; |
|---|
| 726 | | - uint8_t *req_data = NULL; |
|---|
| 734 | + void *req_data = NULL; |
|---|
| 727 | 735 | dma_addr_t req_data_dma; |
|---|
| 728 | 736 | uint32_t req_data_len; |
|---|
| 729 | 737 | uint8_t *rsp_data = NULL; |
|---|
| .. | .. |
|---|
| 801 | 809 | bsg_request->rqst_data.h_vendor.vendor_cmd[2]; |
|---|
| 802 | 810 | |
|---|
| 803 | 811 | if (atomic_read(&vha->loop_state) == LOOP_READY && |
|---|
| 804 | | - (ha->current_topology == ISP_CFG_F || |
|---|
| 805 | | - (le32_to_cpu(*(uint32_t *)req_data) == ELS_OPCODE_BYTE && |
|---|
| 806 | | - req_data_len == MAX_ELS_FRAME_PAYLOAD)) && |
|---|
| 807 | | - elreq.options == EXTERNAL_LOOPBACK) { |
|---|
| 812 | + ((ha->current_topology == ISP_CFG_F && (elreq.options & 7) >= 2) || |
|---|
| 813 | + ((IS_QLA81XX(ha) || IS_QLA8031(ha) || IS_QLA8044(ha)) && |
|---|
| 814 | + get_unaligned_le32(req_data) == ELS_OPCODE_BYTE && |
|---|
| 815 | + req_data_len == MAX_ELS_FRAME_PAYLOAD && |
|---|
| 816 | + elreq.options == EXTERNAL_LOOPBACK))) { |
|---|
| 808 | 817 | type = "FC_BSG_HST_VENDOR_ECHO_DIAG"; |
|---|
| 809 | 818 | ql_dbg(ql_dbg_user, vha, 0x701e, |
|---|
| 810 | 819 | "BSG request type: %s.\n", type); |
|---|
| .. | .. |
|---|
| 890 | 899 | * doesn't work take FCoE dump and then |
|---|
| 891 | 900 | * reset the chip. |
|---|
| 892 | 901 | */ |
|---|
| 893 | | - ha->isp_ops->fw_dump(vha, 0); |
|---|
| 902 | + qla2xxx_dump_fw(vha); |
|---|
| 894 | 903 | set_bit(ISP_ABORT_NEEDED, |
|---|
| 895 | 904 | &vha->dpc_flags); |
|---|
| 896 | 905 | } |
|---|
| .. | .. |
|---|
| 1049 | 1058 | } |
|---|
| 1050 | 1059 | |
|---|
| 1051 | 1060 | flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1]; |
|---|
| 1052 | | - fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2))); |
|---|
| 1061 | + fw_ver = get_unaligned_le32((uint32_t *)fw_buf + 2); |
|---|
| 1053 | 1062 | |
|---|
| 1054 | 1063 | mn->entry_type = VERIFY_CHIP_IOCB_TYPE; |
|---|
| 1055 | 1064 | mn->entry_count = 1; |
|---|
| .. | .. |
|---|
| 1062 | 1071 | mn->fw_ver = cpu_to_le32(fw_ver); |
|---|
| 1063 | 1072 | mn->fw_size = cpu_to_le32(data_len); |
|---|
| 1064 | 1073 | mn->fw_seq_size = cpu_to_le32(data_len); |
|---|
| 1065 | | - mn->dseg_address[0] = cpu_to_le32(LSD(fw_dma)); |
|---|
| 1066 | | - mn->dseg_address[1] = cpu_to_le32(MSD(fw_dma)); |
|---|
| 1067 | | - mn->dseg_length = cpu_to_le32(data_len); |
|---|
| 1074 | + put_unaligned_le64(fw_dma, &mn->dsd.address); |
|---|
| 1075 | + mn->dsd.length = cpu_to_le32(data_len); |
|---|
| 1068 | 1076 | mn->data_seg_cnt = cpu_to_le16(1); |
|---|
| 1069 | 1077 | |
|---|
| 1070 | 1078 | rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120); |
|---|
| .. | .. |
|---|
| 1243 | 1251 | if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) { |
|---|
| 1244 | 1252 | mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len); |
|---|
| 1245 | 1253 | mn->dseg_count = cpu_to_le16(1); |
|---|
| 1246 | | - mn->dseg_address[0] = cpu_to_le32(LSD(mgmt_dma)); |
|---|
| 1247 | | - mn->dseg_address[1] = cpu_to_le32(MSD(mgmt_dma)); |
|---|
| 1248 | | - mn->dseg_length = cpu_to_le32(ql84_mgmt->mgmt.len); |
|---|
| 1254 | + put_unaligned_le64(mgmt_dma, &mn->dsd.address); |
|---|
| 1255 | + mn->dsd.length = cpu_to_le32(ql84_mgmt->mgmt.len); |
|---|
| 1249 | 1256 | } |
|---|
| 1250 | 1257 | |
|---|
| 1251 | 1258 | rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0); |
|---|
| .. | .. |
|---|
| 1359 | 1366 | |
|---|
| 1360 | 1367 | if (rval) { |
|---|
| 1361 | 1368 | ql_log(ql_log_warn, vha, 0x704c, |
|---|
| 1362 | | - "iIDMA cmd failed for %8phN -- " |
|---|
| 1369 | + "iiDMA cmd failed for %8phN -- " |
|---|
| 1363 | 1370 | "%04x %x %04x %04x.\n", fcport->port_name, |
|---|
| 1364 | 1371 | rval, fcport->fp_speed, mb[0], mb[1]); |
|---|
| 1365 | 1372 | rval = (DID_ERROR << 16); |
|---|
| .. | .. |
|---|
| 1417 | 1424 | start == (ha->flt_region_fw * 4)) |
|---|
| 1418 | 1425 | valid = 1; |
|---|
| 1419 | 1426 | else if (IS_QLA24XX_TYPE(ha) || IS_QLA25XX(ha) || |
|---|
| 1420 | | - IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha)) |
|---|
| 1427 | + IS_CNA_CAPABLE(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || |
|---|
| 1428 | + IS_QLA28XX(ha)) |
|---|
| 1421 | 1429 | valid = 1; |
|---|
| 1422 | 1430 | if (!valid) { |
|---|
| 1423 | 1431 | ql_log(ql_log_warn, vha, 0x7058, |
|---|
| .. | .. |
|---|
| 1512 | 1520 | bsg_job->request_payload.sg_cnt, ha->optrom_buffer, |
|---|
| 1513 | 1521 | ha->optrom_region_size); |
|---|
| 1514 | 1522 | |
|---|
| 1515 | | - ha->isp_ops->write_optrom(vha, ha->optrom_buffer, |
|---|
| 1523 | + rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer, |
|---|
| 1516 | 1524 | ha->optrom_region_start, ha->optrom_region_size); |
|---|
| 1517 | 1525 | |
|---|
| 1518 | | - bsg_reply->result = DID_OK; |
|---|
| 1526 | + if (rval) { |
|---|
| 1527 | + bsg_reply->result = -EINVAL; |
|---|
| 1528 | + rval = -EINVAL; |
|---|
| 1529 | + } else { |
|---|
| 1530 | + bsg_reply->result = DID_OK; |
|---|
| 1531 | + } |
|---|
| 1519 | 1532 | vfree(ha->optrom_buffer); |
|---|
| 1520 | 1533 | ha->optrom_buffer = NULL; |
|---|
| 1521 | 1534 | ha->optrom_state = QLA_SWAITING; |
|---|
| .. | .. |
|---|
| 1539 | 1552 | uint32_t count; |
|---|
| 1540 | 1553 | dma_addr_t sfp_dma; |
|---|
| 1541 | 1554 | void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); |
|---|
| 1555 | + |
|---|
| 1542 | 1556 | if (!sfp) { |
|---|
| 1543 | 1557 | bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = |
|---|
| 1544 | 1558 | EXT_STATUS_NO_MEMORY; |
|---|
| .. | .. |
|---|
| 1589 | 1603 | struct qla_status_reg *sr = (void *)bsg; |
|---|
| 1590 | 1604 | dma_addr_t sfp_dma; |
|---|
| 1591 | 1605 | uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); |
|---|
| 1606 | + |
|---|
| 1592 | 1607 | if (!sfp) { |
|---|
| 1593 | 1608 | bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = |
|---|
| 1594 | 1609 | EXT_STATUS_NO_MEMORY; |
|---|
| .. | .. |
|---|
| 1639 | 1654 | struct qla_status_reg *sr = (void *)bsg; |
|---|
| 1640 | 1655 | dma_addr_t sfp_dma; |
|---|
| 1641 | 1656 | uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); |
|---|
| 1657 | + |
|---|
| 1642 | 1658 | if (!sfp) { |
|---|
| 1643 | 1659 | bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = |
|---|
| 1644 | 1660 | EXT_STATUS_NO_MEMORY; |
|---|
| .. | .. |
|---|
| 1685 | 1701 | struct qla_i2c_access *i2c = (void *)bsg; |
|---|
| 1686 | 1702 | dma_addr_t sfp_dma; |
|---|
| 1687 | 1703 | uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); |
|---|
| 1704 | + |
|---|
| 1688 | 1705 | if (!sfp) { |
|---|
| 1689 | 1706 | bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = |
|---|
| 1690 | 1707 | EXT_STATUS_NO_MEMORY; |
|---|
| .. | .. |
|---|
| 1730 | 1747 | struct qla_i2c_access *i2c = (void *)bsg; |
|---|
| 1731 | 1748 | dma_addr_t sfp_dma; |
|---|
| 1732 | 1749 | uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma); |
|---|
| 1750 | + |
|---|
| 1733 | 1751 | if (!sfp) { |
|---|
| 1734 | 1752 | bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = |
|---|
| 1735 | 1753 | EXT_STATUS_NO_MEMORY; |
|---|
| .. | .. |
|---|
| 1965 | 1983 | |
|---|
| 1966 | 1984 | /* Dump the vendor information */ |
|---|
| 1967 | 1985 | ql_dump_buffer(ql_dbg_user + ql_dbg_verbose , vha, 0x70cf, |
|---|
| 1968 | | - (uint8_t *)piocb_rqst, sizeof(struct qla_mt_iocb_rqst_fx00)); |
|---|
| 1986 | + piocb_rqst, sizeof(*piocb_rqst)); |
|---|
| 1969 | 1987 | |
|---|
| 1970 | 1988 | if (!vha->flags.online) { |
|---|
| 1971 | 1989 | ql_log(ql_log_warn, vha, 0x70d0, |
|---|
| .. | .. |
|---|
| 2027 | 2045 | |
|---|
| 2028 | 2046 | /* Initialize all required fields of fcport */ |
|---|
| 2029 | 2047 | fcport->vha = vha; |
|---|
| 2030 | | - fcport->loop_id = piocb_rqst->dataword; |
|---|
| 2048 | + fcport->loop_id = le32_to_cpu(piocb_rqst->dataword); |
|---|
| 2031 | 2049 | |
|---|
| 2032 | 2050 | sp->type = SRB_FXIOCB_BCMD; |
|---|
| 2033 | 2051 | sp->name = "bsg_fx_mgmt"; |
|---|
| .. | .. |
|---|
| 2051 | 2069 | return rval; |
|---|
| 2052 | 2070 | |
|---|
| 2053 | 2071 | done_free_fcport: |
|---|
| 2054 | | - kfree(fcport); |
|---|
| 2072 | + qla2x00_free_fcport(fcport); |
|---|
| 2055 | 2073 | |
|---|
| 2056 | 2074 | done_unmap_rsp_sg: |
|---|
| 2057 | 2075 | if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID) |
|---|
| .. | .. |
|---|
| 2161 | 2179 | struct qla_hw_data *ha = vha->hw; |
|---|
| 2162 | 2180 | struct qla_flash_update_caps cap; |
|---|
| 2163 | 2181 | |
|---|
| 2164 | | - if (!(IS_QLA27XX(ha))) |
|---|
| 2182 | + if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha)) |
|---|
| 2165 | 2183 | return -EPERM; |
|---|
| 2166 | 2184 | |
|---|
| 2167 | 2185 | memset(&cap, 0, sizeof(cap)); |
|---|
| .. | .. |
|---|
| 2194 | 2212 | uint64_t online_fw_attr = 0; |
|---|
| 2195 | 2213 | struct qla_flash_update_caps cap; |
|---|
| 2196 | 2214 | |
|---|
| 2197 | | - if (!(IS_QLA27XX(ha))) |
|---|
| 2215 | + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) |
|---|
| 2198 | 2216 | return -EPERM; |
|---|
| 2199 | 2217 | |
|---|
| 2200 | 2218 | memset(&cap, 0, sizeof(cap)); |
|---|
| .. | .. |
|---|
| 2242 | 2260 | uint8_t domain, area, al_pa, state; |
|---|
| 2243 | 2261 | int rval; |
|---|
| 2244 | 2262 | |
|---|
| 2245 | | - if (!(IS_QLA27XX(ha))) |
|---|
| 2263 | + if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha)) |
|---|
| 2246 | 2264 | return -EPERM; |
|---|
| 2247 | 2265 | |
|---|
| 2248 | 2266 | memset(&bbcr, 0, sizeof(bbcr)); |
|---|
| .. | .. |
|---|
| 2316 | 2334 | if (!IS_FWI2_CAPABLE(ha)) |
|---|
| 2317 | 2335 | return -EPERM; |
|---|
| 2318 | 2336 | |
|---|
| 2319 | | - stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats), |
|---|
| 2320 | | - &stats_dma, GFP_KERNEL); |
|---|
| 2337 | + stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma, |
|---|
| 2338 | + GFP_KERNEL); |
|---|
| 2321 | 2339 | if (!stats) { |
|---|
| 2322 | 2340 | ql_log(ql_log_warn, vha, 0x70e2, |
|---|
| 2323 | 2341 | "Failed to allocate memory for stats.\n"); |
|---|
| .. | .. |
|---|
| 2327 | 2345 | rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options); |
|---|
| 2328 | 2346 | |
|---|
| 2329 | 2347 | if (rval == QLA_SUCCESS) { |
|---|
| 2330 | | - ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e3, |
|---|
| 2331 | | - (uint8_t *)stats, sizeof(*stats)); |
|---|
| 2348 | + ql_dump_buffer(ql_dbg_user + ql_dbg_verbose, vha, 0x70e5, |
|---|
| 2349 | + stats, sizeof(*stats)); |
|---|
| 2332 | 2350 | sg_copy_from_buffer(bsg_job->reply_payload.sg_list, |
|---|
| 2333 | 2351 | bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats)); |
|---|
| 2334 | 2352 | } |
|---|
| .. | .. |
|---|
| 2357 | 2375 | int rval; |
|---|
| 2358 | 2376 | struct qla_dport_diag *dd; |
|---|
| 2359 | 2377 | |
|---|
| 2360 | | - if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw)) |
|---|
| 2378 | + if (!IS_QLA83XX(vha->hw) && !IS_QLA27XX(vha->hw) && |
|---|
| 2379 | + !IS_QLA28XX(vha->hw)) |
|---|
| 2361 | 2380 | return -EPERM; |
|---|
| 2362 | 2381 | |
|---|
| 2363 | 2382 | dd = kmalloc(sizeof(*dd), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 2387 | 2406 | bsg_reply->reply_payload_rcv_len); |
|---|
| 2388 | 2407 | |
|---|
| 2389 | 2408 | kfree(dd); |
|---|
| 2409 | + |
|---|
| 2410 | + return 0; |
|---|
| 2411 | +} |
|---|
| 2412 | + |
|---|
| 2413 | +static int |
|---|
| 2414 | +qla2x00_get_flash_image_status(struct bsg_job *bsg_job) |
|---|
| 2415 | +{ |
|---|
| 2416 | + scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job)); |
|---|
| 2417 | + struct fc_bsg_reply *bsg_reply = bsg_job->reply; |
|---|
| 2418 | + struct qla_hw_data *ha = vha->hw; |
|---|
| 2419 | + struct qla_active_regions regions = { }; |
|---|
| 2420 | + struct active_regions active_regions = { }; |
|---|
| 2421 | + |
|---|
| 2422 | + qla27xx_get_active_image(vha, &active_regions); |
|---|
| 2423 | + regions.global_image = active_regions.global; |
|---|
| 2424 | + |
|---|
| 2425 | + if (IS_QLA28XX(ha)) { |
|---|
| 2426 | + qla28xx_get_aux_images(vha, &active_regions); |
|---|
| 2427 | + regions.board_config = active_regions.aux.board_config; |
|---|
| 2428 | + regions.vpd_nvram = active_regions.aux.vpd_nvram; |
|---|
| 2429 | + regions.npiv_config_0_1 = active_regions.aux.npiv_config_0_1; |
|---|
| 2430 | + regions.npiv_config_2_3 = active_regions.aux.npiv_config_2_3; |
|---|
| 2431 | + } |
|---|
| 2432 | + |
|---|
| 2433 | + ql_dbg(ql_dbg_user, vha, 0x70e1, |
|---|
| 2434 | + "%s(%lu): FW=%u BCFG=%u VPDNVR=%u NPIV01=%u NPIV02=%u\n", |
|---|
| 2435 | + __func__, vha->host_no, regions.global_image, |
|---|
| 2436 | + regions.board_config, regions.vpd_nvram, |
|---|
| 2437 | + regions.npiv_config_0_1, regions.npiv_config_2_3); |
|---|
| 2438 | + |
|---|
| 2439 | + sg_copy_from_buffer(bsg_job->reply_payload.sg_list, |
|---|
| 2440 | + bsg_job->reply_payload.sg_cnt, ®ions, sizeof(regions)); |
|---|
| 2441 | + |
|---|
| 2442 | + bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK; |
|---|
| 2443 | + bsg_reply->reply_payload_rcv_len = sizeof(regions); |
|---|
| 2444 | + bsg_reply->result = DID_OK << 16; |
|---|
| 2445 | + bsg_job->reply_len = sizeof(struct fc_bsg_reply); |
|---|
| 2446 | + bsg_job_done(bsg_job, bsg_reply->result, |
|---|
| 2447 | + bsg_reply->reply_payload_rcv_len); |
|---|
| 2390 | 2448 | |
|---|
| 2391 | 2449 | return 0; |
|---|
| 2392 | 2450 | } |
|---|
| .. | .. |
|---|
| 2464 | 2522 | case QL_VND_DPORT_DIAGNOSTICS: |
|---|
| 2465 | 2523 | return qla2x00_do_dport_diagnostics(bsg_job); |
|---|
| 2466 | 2524 | |
|---|
| 2525 | + case QL_VND_SS_GET_FLASH_IMAGE_STATUS: |
|---|
| 2526 | + return qla2x00_get_flash_image_status(bsg_job); |
|---|
| 2527 | + |
|---|
| 2467 | 2528 | default: |
|---|
| 2468 | 2529 | return -ENOSYS; |
|---|
| 2469 | 2530 | } |
|---|
| .. | .. |
|---|
| 2484 | 2545 | |
|---|
| 2485 | 2546 | if (bsg_request->msgcode == FC_BSG_RPT_ELS) { |
|---|
| 2486 | 2547 | rport = fc_bsg_to_rport(bsg_job); |
|---|
| 2548 | + if (!rport) |
|---|
| 2549 | + return ret; |
|---|
| 2487 | 2550 | host = rport_to_shost(rport); |
|---|
| 2488 | 2551 | vha = shost_priv(host); |
|---|
| 2489 | 2552 | } else { |
|---|