hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/scsi/qla2xxx/qla_bsg.c
....@@ -1,8 +1,7 @@
1
- /*
1
+// SPDX-License-Identifier: GPL-2.0-only
2
+/*
23 * QLogic Fibre Channel HBA Driver
34 * Copyright (c) 2003-2014 QLogic Corporation
4
- *
5
- * See LICENSE.qla2xxx for copyright and licensing details.
65 */
76 #include "qla_def.h"
87
....@@ -11,11 +10,17 @@
1110 #include <linux/delay.h>
1211 #include <linux/bsg-lib.h>
1312
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)
1714 {
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
+{
1924 struct bsg_job *bsg_job = sp->u.bsg_job;
2025 struct fc_bsg_reply *bsg_reply = bsg_job->reply;
2126
....@@ -26,10 +31,8 @@
2631 bsg_reply->reply_payload_rcv_len);
2732 }
2833
29
-void
30
-qla2x00_bsg_sp_free(void *ptr)
34
+void qla2x00_bsg_sp_free(srb_t *sp)
3135 {
32
- srb_t *sp = ptr;
3336 struct qla_hw_data *ha = sp->vha->hw;
3437 struct bsg_job *bsg_job = sp->u.bsg_job;
3538 struct fc_bsg_request *bsg_request = bsg_job->request;
....@@ -58,8 +61,11 @@
5861
5962 if (sp->type == SRB_CT_CMD ||
6063 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
+
6369 qla2x00_rel_sp(sp);
6470 }
6571
....@@ -85,8 +91,7 @@
8591 return 0;
8692 }
8793
88
- if (bcode[0] != 'H' || bcode[1] != 'Q' || bcode[2] != 'O' ||
89
- bcode[3] != 'S') {
94
+ if (memcmp(bcode, "HQOS", 4)) {
9095 /* Invalid FCP priority data header*/
9196 ql_dbg(ql_dbg_user, vha, 0x7052,
9297 "Invalid FCP Priority data header. bcode=0x%x.\n",
....@@ -218,8 +223,7 @@
218223
219224 /* validate fcp priority data */
220225
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)) {
223227 bsg_reply->result = (DID_ERROR << 16);
224228 ret = -EINVAL;
225229 /* If buffer was invalidatic int
....@@ -264,6 +268,10 @@
264268
265269 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
266270 rport = fc_bsg_to_rport(bsg_job);
271
+ if (!rport) {
272
+ rval = -ENOMEM;
273
+ goto done;
274
+ }
267275 fcport = *(fc_port_t **) rport->dd_data;
268276 host = rport_to_shost(rport);
269277 vha = shost_priv(host);
....@@ -410,8 +418,8 @@
410418 goto done_free_fcport;
411419
412420 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);
415423 done:
416424 return rval;
417425 }
....@@ -485,7 +493,7 @@
485493 >> 24;
486494 switch (loop_id) {
487495 case 0xFC:
488
- loop_id = cpu_to_le16(NPH_SNS);
496
+ loop_id = NPH_SNS;
489497 break;
490498 case 0xFA:
491499 loop_id = vha->mgmt_svr_loop_id;
....@@ -551,7 +559,7 @@
551559 return rval;
552560
553561 done_free_fcport:
554
- kfree(fcport);
562
+ qla2x00_free_fcport(fcport);
555563 done_unmap_sg:
556564 dma_unmap_sg(&ha->pdev->dev, bsg_job->request_payload.sg_list,
557565 bsg_job->request_payload.sg_cnt, DMA_TO_DEVICE);
....@@ -686,7 +694,7 @@
686694 * dump and reset the chip.
687695 */
688696 if (ret) {
689
- ha->isp_ops->fw_dump(vha, 0);
697
+ qla2xxx_dump_fw(vha);
690698 set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
691699 }
692700 rval = -EINVAL;
....@@ -723,7 +731,7 @@
723731 uint16_t response[MAILBOX_REGISTER_COUNT];
724732 uint16_t config[4], new_config[4];
725733 uint8_t *fw_sts_ptr;
726
- uint8_t *req_data = NULL;
734
+ void *req_data = NULL;
727735 dma_addr_t req_data_dma;
728736 uint32_t req_data_len;
729737 uint8_t *rsp_data = NULL;
....@@ -801,10 +809,11 @@
801809 bsg_request->rqst_data.h_vendor.vendor_cmd[2];
802810
803811 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))) {
808817 type = "FC_BSG_HST_VENDOR_ECHO_DIAG";
809818 ql_dbg(ql_dbg_user, vha, 0x701e,
810819 "BSG request type: %s.\n", type);
....@@ -890,7 +899,7 @@
890899 * doesn't work take FCoE dump and then
891900 * reset the chip.
892901 */
893
- ha->isp_ops->fw_dump(vha, 0);
902
+ qla2xxx_dump_fw(vha);
894903 set_bit(ISP_ABORT_NEEDED,
895904 &vha->dpc_flags);
896905 }
....@@ -1049,7 +1058,7 @@
10491058 }
10501059
10511060 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);
10531062
10541063 mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
10551064 mn->entry_count = 1;
....@@ -1062,9 +1071,8 @@
10621071 mn->fw_ver = cpu_to_le32(fw_ver);
10631072 mn->fw_size = cpu_to_le32(data_len);
10641073 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);
10681076 mn->data_seg_cnt = cpu_to_le16(1);
10691077
10701078 rval = qla2x00_issue_iocb_timeout(vha, mn, mn_dma, 0, 120);
....@@ -1243,9 +1251,8 @@
12431251 if (ql84_mgmt->mgmt.cmd != QLA84_MGMT_CHNG_CONFIG) {
12441252 mn->total_byte_cnt = cpu_to_le32(ql84_mgmt->mgmt.len);
12451253 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);
12491256 }
12501257
12511258 rval = qla2x00_issue_iocb(vha, mn, mn_dma, 0);
....@@ -1359,7 +1366,7 @@
13591366
13601367 if (rval) {
13611368 ql_log(ql_log_warn, vha, 0x704c,
1362
- "iIDMA cmd failed for %8phN -- "
1369
+ "iiDMA cmd failed for %8phN -- "
13631370 "%04x %x %04x %04x.\n", fcport->port_name,
13641371 rval, fcport->fp_speed, mb[0], mb[1]);
13651372 rval = (DID_ERROR << 16);
....@@ -1417,7 +1424,8 @@
14171424 start == (ha->flt_region_fw * 4))
14181425 valid = 1;
14191426 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))
14211429 valid = 1;
14221430 if (!valid) {
14231431 ql_log(ql_log_warn, vha, 0x7058,
....@@ -1512,10 +1520,15 @@
15121520 bsg_job->request_payload.sg_cnt, ha->optrom_buffer,
15131521 ha->optrom_region_size);
15141522
1515
- ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
1523
+ rval = ha->isp_ops->write_optrom(vha, ha->optrom_buffer,
15161524 ha->optrom_region_start, ha->optrom_region_size);
15171525
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
+ }
15191532 vfree(ha->optrom_buffer);
15201533 ha->optrom_buffer = NULL;
15211534 ha->optrom_state = QLA_SWAITING;
....@@ -1539,6 +1552,7 @@
15391552 uint32_t count;
15401553 dma_addr_t sfp_dma;
15411554 void *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1555
+
15421556 if (!sfp) {
15431557 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
15441558 EXT_STATUS_NO_MEMORY;
....@@ -1589,6 +1603,7 @@
15891603 struct qla_status_reg *sr = (void *)bsg;
15901604 dma_addr_t sfp_dma;
15911605 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1606
+
15921607 if (!sfp) {
15931608 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
15941609 EXT_STATUS_NO_MEMORY;
....@@ -1639,6 +1654,7 @@
16391654 struct qla_status_reg *sr = (void *)bsg;
16401655 dma_addr_t sfp_dma;
16411656 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1657
+
16421658 if (!sfp) {
16431659 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
16441660 EXT_STATUS_NO_MEMORY;
....@@ -1685,6 +1701,7 @@
16851701 struct qla_i2c_access *i2c = (void *)bsg;
16861702 dma_addr_t sfp_dma;
16871703 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1704
+
16881705 if (!sfp) {
16891706 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
16901707 EXT_STATUS_NO_MEMORY;
....@@ -1730,6 +1747,7 @@
17301747 struct qla_i2c_access *i2c = (void *)bsg;
17311748 dma_addr_t sfp_dma;
17321749 uint8_t *sfp = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, &sfp_dma);
1750
+
17331751 if (!sfp) {
17341752 bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
17351753 EXT_STATUS_NO_MEMORY;
....@@ -1965,7 +1983,7 @@
19651983
19661984 /* Dump the vendor information */
19671985 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));
19691987
19701988 if (!vha->flags.online) {
19711989 ql_log(ql_log_warn, vha, 0x70d0,
....@@ -2027,7 +2045,7 @@
20272045
20282046 /* Initialize all required fields of fcport */
20292047 fcport->vha = vha;
2030
- fcport->loop_id = piocb_rqst->dataword;
2048
+ fcport->loop_id = le32_to_cpu(piocb_rqst->dataword);
20312049
20322050 sp->type = SRB_FXIOCB_BCMD;
20332051 sp->name = "bsg_fx_mgmt";
....@@ -2051,7 +2069,7 @@
20512069 return rval;
20522070
20532071 done_free_fcport:
2054
- kfree(fcport);
2072
+ qla2x00_free_fcport(fcport);
20552073
20562074 done_unmap_rsp_sg:
20572075 if (piocb_rqst->flags & SRB_FXDISC_RESP_DMA_VALID)
....@@ -2161,7 +2179,7 @@
21612179 struct qla_hw_data *ha = vha->hw;
21622180 struct qla_flash_update_caps cap;
21632181
2164
- if (!(IS_QLA27XX(ha)))
2182
+ if (!(IS_QLA27XX(ha)) && !IS_QLA28XX(ha))
21652183 return -EPERM;
21662184
21672185 memset(&cap, 0, sizeof(cap));
....@@ -2194,7 +2212,7 @@
21942212 uint64_t online_fw_attr = 0;
21952213 struct qla_flash_update_caps cap;
21962214
2197
- if (!(IS_QLA27XX(ha)))
2215
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
21982216 return -EPERM;
21992217
22002218 memset(&cap, 0, sizeof(cap));
....@@ -2242,7 +2260,7 @@
22422260 uint8_t domain, area, al_pa, state;
22432261 int rval;
22442262
2245
- if (!(IS_QLA27XX(ha)))
2263
+ if (!IS_QLA27XX(ha) && !IS_QLA28XX(ha))
22462264 return -EPERM;
22472265
22482266 memset(&bbcr, 0, sizeof(bbcr));
....@@ -2316,8 +2334,8 @@
23162334 if (!IS_FWI2_CAPABLE(ha))
23172335 return -EPERM;
23182336
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);
23212339 if (!stats) {
23222340 ql_log(ql_log_warn, vha, 0x70e2,
23232341 "Failed to allocate memory for stats.\n");
....@@ -2327,8 +2345,8 @@
23272345 rval = qla24xx_get_isp_stats(base_vha, stats, stats_dma, options);
23282346
23292347 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));
23322350 sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
23332351 bsg_job->reply_payload.sg_cnt, stats, sizeof(*stats));
23342352 }
....@@ -2357,7 +2375,8 @@
23572375 int rval;
23582376 struct qla_dport_diag *dd;
23592377
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))
23612380 return -EPERM;
23622381
23632382 dd = kmalloc(sizeof(*dd), GFP_KERNEL);
....@@ -2387,6 +2406,45 @@
23872406 bsg_reply->reply_payload_rcv_len);
23882407
23892408 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, &regions, 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);
23902448
23912449 return 0;
23922450 }
....@@ -2464,6 +2522,9 @@
24642522 case QL_VND_DPORT_DIAGNOSTICS:
24652523 return qla2x00_do_dport_diagnostics(bsg_job);
24662524
2525
+ case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
2526
+ return qla2x00_get_flash_image_status(bsg_job);
2527
+
24672528 default:
24682529 return -ENOSYS;
24692530 }
....@@ -2484,6 +2545,8 @@
24842545
24852546 if (bsg_request->msgcode == FC_BSG_RPT_ELS) {
24862547 rport = fc_bsg_to_rport(bsg_job);
2548
+ if (!rport)
2549
+ return ret;
24872550 host = rport_to_shost(rport);
24882551 vha = shost_priv(host);
24892552 } else {