// SPDX-License-Identifier: GPL-2.0-only
/*
* QLogic Fibre Channel HBA Driver
* Copyright (c) 2003-2017 QLogic Corporation
*/
#include "qla_nvme.h"
#include <linux/scatterlist.h>
#include <linux/delay.h>
#include <linux/nvme.h>
#include <linux/nvme-fc.h>
#include <linux/blk-mq.h>
static struct nvme_fc_port_template qla_nvme_fc_transport;
static int qla_nvme_ls_reject_iocb(struct scsi_qla_host *vha,
struct qla_qpair *qp,
struct qla_nvme_lsrjt_pt_arg *a,
bool is_xchg_terminate);
struct qla_nvme_unsol_ctx {
struct list_head elem;
struct scsi_qla_host *vha;
struct fc_port *fcport;
struct srb *sp;
struct nvmefc_ls_rsp lsrsp;
struct nvmefc_ls_rsp *fd_rsp;
struct work_struct lsrsp_work;
struct work_struct abort_work;
__le32 exchange_address;
__le16 nport_handle;
__le16 ox_id;
int comp_status;
spinlock_t cmd_lock;
};
int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
{
struct qla_nvme_rport *rport;
struct nvme_fc_port_info req;
int ret;
if (!IS_ENABLED(CONFIG_NVME_FC))
return 0;
if (!vha->flags.nvme_enabled) {
ql_log(ql_log_info, vha, 0x2100,
"%s: Not registering target since Host NVME is not enabled\n",
__func__);
return 0;
}
if (qla_nvme_register_hba(vha))
return 0;
if (!vha->nvme_local_port)
return 0;
if (!(fcport->nvme_prli_service_param &
(NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY)) ||
(fcport->nvme_flag & NVME_FLAG_REGISTERED))
return 0;
fcport->nvme_flag &= ~NVME_FLAG_RESETTING;
memset(&req, 0, sizeof(struct nvme_fc_port_info));
req.port_name = wwn_to_u64(fcport->port_name);
req.node_name = wwn_to_u64(fcport