| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 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 | #include "qla_gbl.h" |
|---|
| .. | .. |
|---|
| 66 | 65 | uint16_t vp_id; |
|---|
| 67 | 66 | struct qla_hw_data *ha = vha->hw; |
|---|
| 68 | 67 | unsigned long flags = 0; |
|---|
| 68 | + u8 i; |
|---|
| 69 | 69 | |
|---|
| 70 | 70 | mutex_lock(&ha->vport_lock); |
|---|
| 71 | 71 | /* |
|---|
| .. | .. |
|---|
| 75 | 75 | * ensures no active vp_list traversal while the vport is removed |
|---|
| 76 | 76 | * from the queue) |
|---|
| 77 | 77 | */ |
|---|
| 78 | | - wait_event_timeout(vha->vref_waitq, !atomic_read(&vha->vref_count), |
|---|
| 79 | | - 10*HZ); |
|---|
| 78 | + for (i = 0; i < 10; i++) { |
|---|
| 79 | + if (wait_event_timeout(vha->vref_waitq, |
|---|
| 80 | + !atomic_read(&vha->vref_count), HZ) > 0) |
|---|
| 81 | + break; |
|---|
| 82 | + } |
|---|
| 80 | 83 | |
|---|
| 81 | 84 | spin_lock_irqsave(&ha->vport_slock, flags); |
|---|
| 82 | 85 | if (atomic_read(&vha->vref_count)) { |
|---|
| .. | .. |
|---|
| 143 | 146 | "Marking port dead, loop_id=0x%04x : %x.\n", |
|---|
| 144 | 147 | fcport->loop_id, fcport->vha->vp_idx); |
|---|
| 145 | 148 | |
|---|
| 146 | | - qla2x00_mark_device_lost(vha, fcport, 0, 0); |
|---|
| 149 | + qla2x00_mark_device_lost(vha, fcport, 0); |
|---|
| 147 | 150 | qla2x00_set_fcport_state(fcport, FCS_UNCONFIGURED); |
|---|
| 148 | 151 | } |
|---|
| 149 | 152 | } |
|---|
| .. | .. |
|---|
| 163 | 166 | list_for_each_entry(fcport, &vha->vp_fcports, list) |
|---|
| 164 | 167 | fcport->logout_on_delete = 0; |
|---|
| 165 | 168 | |
|---|
| 166 | | - qla2x00_mark_all_devices_lost(vha, 0); |
|---|
| 169 | + qla2x00_mark_all_devices_lost(vha); |
|---|
| 167 | 170 | |
|---|
| 168 | 171 | /* Remove port id from vp target map */ |
|---|
| 169 | 172 | spin_lock_irqsave(&vha->hw->hardware_lock, flags); |
|---|
| .. | .. |
|---|
| 262 | 265 | spin_lock_irqsave(&ha->vport_slock, flags); |
|---|
| 263 | 266 | list_for_each_entry(vha, &ha->vp_list, list) { |
|---|
| 264 | 267 | if (vha->vp_idx) { |
|---|
| 268 | + if (test_bit(VPORT_DELETE, &vha->dpc_flags)) |
|---|
| 269 | + continue; |
|---|
| 270 | + |
|---|
| 265 | 271 | atomic_inc(&vha->vref_count); |
|---|
| 266 | 272 | spin_unlock_irqrestore(&ha->vport_slock, flags); |
|---|
| 267 | 273 | |
|---|
| .. | .. |
|---|
| 300 | 306 | int |
|---|
| 301 | 307 | qla2x00_vp_abort_isp(scsi_qla_host_t *vha) |
|---|
| 302 | 308 | { |
|---|
| 309 | + fc_port_t *fcport; |
|---|
| 310 | + |
|---|
| 311 | + /* |
|---|
| 312 | + * To exclusively reset vport, we need to log it out first. |
|---|
| 313 | + * Note: This control_vp can fail if ISP reset is already |
|---|
| 314 | + * issued, this is expected, as the vp would be already |
|---|
| 315 | + * logged out due to ISP reset. |
|---|
| 316 | + */ |
|---|
| 317 | + if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) { |
|---|
| 318 | + qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); |
|---|
| 319 | + list_for_each_entry(fcport, &vha->vp_fcports, list) |
|---|
| 320 | + fcport->logout_on_delete = 0; |
|---|
| 321 | + } |
|---|
| 322 | + |
|---|
| 303 | 323 | /* |
|---|
| 304 | 324 | * Physical port will do most of the abort and recovery work. We can |
|---|
| 305 | 325 | * just treat it as a loop down |
|---|
| 306 | 326 | */ |
|---|
| 307 | 327 | if (atomic_read(&vha->loop_state) != LOOP_DOWN) { |
|---|
| 308 | 328 | atomic_set(&vha->loop_state, LOOP_DOWN); |
|---|
| 309 | | - qla2x00_mark_all_devices_lost(vha, 0); |
|---|
| 329 | + qla2x00_mark_all_devices_lost(vha); |
|---|
| 310 | 330 | } else { |
|---|
| 311 | 331 | if (!atomic_read(&vha->loop_down_timer)) |
|---|
| 312 | 332 | atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME); |
|---|
| 313 | 333 | } |
|---|
| 314 | 334 | |
|---|
| 315 | | - /* |
|---|
| 316 | | - * To exclusively reset vport, we need to log it out first. Note: this |
|---|
| 317 | | - * control_vp can fail if ISP reset is already issued, this is |
|---|
| 318 | | - * expected, as the vp would be already logged out due to ISP reset. |
|---|
| 319 | | - */ |
|---|
| 320 | | - if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) |
|---|
| 321 | | - qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); |
|---|
| 322 | | - |
|---|
| 323 | 335 | ql_dbg(ql_dbg_taskm, vha, 0x801d, |
|---|
| 324 | 336 | "Scheduling enable of Vport %d.\n", vha->vp_idx); |
|---|
| 337 | + |
|---|
| 325 | 338 | return qla24xx_enable_vp(vha); |
|---|
| 326 | 339 | } |
|---|
| 327 | 340 | |
|---|
| .. | .. |
|---|
| 344 | 357 | ql_dbg(ql_dbg_dpc, vha, 0x4015, |
|---|
| 345 | 358 | "Configure VP end.\n"); |
|---|
| 346 | 359 | return 0; |
|---|
| 360 | + } |
|---|
| 361 | + } |
|---|
| 362 | + |
|---|
| 363 | + if (test_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags)) { |
|---|
| 364 | + if (atomic_read(&vha->loop_state) == LOOP_READY) { |
|---|
| 365 | + qla24xx_process_purex_list(&vha->purex_list); |
|---|
| 366 | + clear_bit(PROCESS_PUREX_IOCB, &vha->dpc_flags); |
|---|
| 347 | 367 | } |
|---|
| 348 | 368 | } |
|---|
| 349 | 369 | |
|---|
| .. | .. |
|---|
| 495 | 515 | vha->mgmt_svr_loop_id = qla2x00_reserve_mgmt_server_loop_id(vha); |
|---|
| 496 | 516 | |
|---|
| 497 | 517 | vha->dpc_flags = 0L; |
|---|
| 518 | + ha->dpc_active = 0; |
|---|
| 519 | + set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags); |
|---|
| 520 | + set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags); |
|---|
| 498 | 521 | |
|---|
| 499 | 522 | /* |
|---|
| 500 | 523 | * To fix the issue of processing a parent's RSCN for the vport before |
|---|
| .. | .. |
|---|
| 507 | 530 | qla2x00_start_timer(vha, WATCH_INTERVAL); |
|---|
| 508 | 531 | |
|---|
| 509 | 532 | vha->req = base_vha->req; |
|---|
| 533 | + vha->flags.nvme_enabled = base_vha->flags.nvme_enabled; |
|---|
| 510 | 534 | host->can_queue = base_vha->req->length + 128; |
|---|
| 511 | 535 | host->cmd_per_lun = 3; |
|---|
| 512 | 536 | if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) |
|---|
| .. | .. |
|---|
| 745 | 769 | req->req_q_in = ®->isp25mq.req_q_in; |
|---|
| 746 | 770 | req->req_q_out = ®->isp25mq.req_q_out; |
|---|
| 747 | 771 | req->max_q_depth = ha->req_q_map[0]->max_q_depth; |
|---|
| 748 | | - req->out_ptr = (void *)(req->ring + req->length); |
|---|
| 772 | + req->out_ptr = (uint16_t *)(req->ring + req->length); |
|---|
| 749 | 773 | mutex_unlock(&ha->mq_lock); |
|---|
| 750 | 774 | ql_dbg(ql_dbg_multiq, base_vha, 0xc004, |
|---|
| 751 | 775 | "ring_ptr=%p ring_index=%d, " |
|---|
| .. | .. |
|---|
| 783 | 807 | { |
|---|
| 784 | 808 | unsigned long flags; |
|---|
| 785 | 809 | struct qla_qpair *qpair = container_of(work, struct qla_qpair, q_work); |
|---|
| 786 | | - struct scsi_qla_host *vha; |
|---|
| 787 | | - struct qla_hw_data *ha = qpair->hw; |
|---|
| 810 | + struct scsi_qla_host *vha = qpair->vha; |
|---|
| 788 | 811 | |
|---|
| 789 | 812 | spin_lock_irqsave(&qpair->qp_lock, flags); |
|---|
| 790 | | - vha = pci_get_drvdata(ha->pdev); |
|---|
| 791 | 813 | qla24xx_process_response_queue(vha, qpair->rsp); |
|---|
| 792 | 814 | spin_unlock_irqrestore(&qpair->qp_lock, flags); |
|---|
| 793 | 815 | |
|---|
| .. | .. |
|---|
| 859 | 881 | reg = ISP_QUE_REG(ha, que_id); |
|---|
| 860 | 882 | rsp->rsp_q_in = ®->isp25mq.rsp_q_in; |
|---|
| 861 | 883 | rsp->rsp_q_out = ®->isp25mq.rsp_q_out; |
|---|
| 862 | | - rsp->in_ptr = (void *)(rsp->ring + rsp->length); |
|---|
| 884 | + rsp->in_ptr = (uint16_t *)(rsp->ring + rsp->length); |
|---|
| 863 | 885 | mutex_unlock(&ha->mq_lock); |
|---|
| 864 | 886 | ql_dbg(ql_dbg_multiq, base_vha, 0xc00b, |
|---|
| 865 | 887 | "options=%x id=%d rsp_q_in=%p rsp_q_out=%p\n", |
|---|
| .. | .. |
|---|
| 871 | 893 | rsp->rsp_q_out); |
|---|
| 872 | 894 | |
|---|
| 873 | 895 | ret = qla25xx_request_irq(ha, qpair, qpair->msix, |
|---|
| 874 | | - QLA_MSIX_QPAIR_MULTIQ_RSP_Q); |
|---|
| 896 | + ha->flags.disable_msix_handshake ? |
|---|
| 897 | + QLA_MSIX_QPAIR_MULTIQ_RSP_Q : QLA_MSIX_QPAIR_MULTIQ_RSP_Q_HS); |
|---|
| 875 | 898 | if (ret) |
|---|
| 876 | 899 | goto que_failed; |
|---|
| 877 | 900 | |
|---|
| .. | .. |
|---|
| 900 | 923 | return 0; |
|---|
| 901 | 924 | } |
|---|
| 902 | 925 | |
|---|
| 903 | | -static void qla_ctrlvp_sp_done(void *s, int res) |
|---|
| 926 | +static void qla_ctrlvp_sp_done(srb_t *sp, int res) |
|---|
| 904 | 927 | { |
|---|
| 905 | | - struct srb *sp = s; |
|---|
| 906 | | - |
|---|
| 907 | | - complete(&sp->comp); |
|---|
| 928 | + if (sp->comp) |
|---|
| 929 | + complete(sp->comp); |
|---|
| 908 | 930 | /* don't free sp here. Let the caller do the free */ |
|---|
| 909 | 931 | } |
|---|
| 910 | 932 | |
|---|
| .. | .. |
|---|
| 921 | 943 | struct qla_hw_data *ha = vha->hw; |
|---|
| 922 | 944 | int vp_index = vha->vp_idx; |
|---|
| 923 | 945 | struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); |
|---|
| 946 | + DECLARE_COMPLETION_ONSTACK(comp); |
|---|
| 924 | 947 | srb_t *sp; |
|---|
| 925 | 948 | |
|---|
| 926 | 949 | ql_dbg(ql_dbg_vport, vha, 0x10c1, |
|---|
| .. | .. |
|---|
| 935 | 958 | |
|---|
| 936 | 959 | sp->type = SRB_CTRL_VP; |
|---|
| 937 | 960 | sp->name = "ctrl_vp"; |
|---|
| 961 | + sp->comp = ∁ |
|---|
| 938 | 962 | sp->done = qla_ctrlvp_sp_done; |
|---|
| 939 | 963 | sp->u.iocb_cmd.timeout = qla2x00_async_iocb_timeout; |
|---|
| 940 | 964 | qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2); |
|---|
| .. | .. |
|---|
| 952 | 976 | ql_dbg(ql_dbg_vport, vha, 0x113f, "%s hndl %x submitted\n", |
|---|
| 953 | 977 | sp->name, sp->handle); |
|---|
| 954 | 978 | |
|---|
| 955 | | - wait_for_completion(&sp->comp); |
|---|
| 979 | + wait_for_completion(&comp); |
|---|
| 980 | + sp->comp = NULL; |
|---|
| 981 | + |
|---|
| 956 | 982 | rval = sp->rc; |
|---|
| 957 | 983 | switch (rval) { |
|---|
| 958 | 984 | case QLA_FUNCTION_TIMEOUT: |
|---|