linux/drivers/scsi/lpfc/lpfc_nvmet.c

/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Fibre Channel Host Bus Adapters.                                *
 * Copyright (C) 2017-2024 Broadcom. All Rights Reserved. The term *
 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.     *
 * Copyright (C) 2004-2016 Emulex.  All rights reserved.           *
 * EMULEX and SLI are trademarks of Emulex.                        *
 * www.broadcom.com                                                *
 * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
 *                                                                 *
 * This program is free software; you can redistribute it and/or   *
 * modify it under the terms of version 2 of the GNU General       *
 * Public License as published by the Free Software Foundation.    *
 * This program is distributed in the hope that it will be useful. *
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND          *
 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,  *
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE      *
 * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
 * TO BE LEGALLY INVALID.  See the GNU General Public License for  *
 * more details, a copy of which can be found in the file COPYING  *
 * included with this package.                                     *
 ********************************************************************/
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/unaligned.h>
#include <linux/crc-t10dif.h>
#include <net/checksum.h>

#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport_fc.h>
#include <scsi/fc/fc_fs.h>

#include "lpfc_version.h"
#include "lpfc_hw4.h"
#include "lpfc_hw.h"
#include "lpfc_sli.h"
#include "lpfc_sli4.h"
#include "lpfc_nl.h"
#include "lpfc_disc.h"
#include "lpfc.h"
#include "lpfc_scsi.h"
#include "lpfc_nvme.h"
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_vport.h"
#include "lpfc_debugfs.h"

static struct lpfc_iocbq *lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *,
						 struct lpfc_async_xchg_ctx *,
						 dma_addr_t rspbuf,
						 uint16_t rspsize);
static struct lpfc_iocbq *lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *,
						  struct lpfc_async_xchg_ctx *);
static int lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *,
					  struct lpfc_async_xchg_ctx *,
					  uint32_t, uint16_t);
static int lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *,
					    struct lpfc_async_xchg_ctx *,
					    uint32_t, uint16_t);
static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *,
				    struct lpfc_async_xchg_ctx *);
static void lpfc_nvmet_fcp_rqst_defer_work(struct work_struct *);

static void lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf);

static union lpfc_wqe128 lpfc_tsend_cmd_template;
static union lpfc_wqe128 lpfc_treceive_cmd_template;
static union lpfc_wqe128 lpfc_trsp_cmd_template;

/* Setup WQE templates for NVME IOs */
void
lpfc_nvmet_cmd_template(void)
{}

#if (IS_ENABLED(CONFIG_NVME_TARGET_FC))
static struct lpfc_async_xchg_ctx *
lpfc_nvmet_get_ctx_for_xri(struct lpfc_hba *phba, u16 xri)
{}

static struct lpfc_async_xchg_ctx *
lpfc_nvmet_get_ctx_for_oxid(struct lpfc_hba *phba, u16 oxid, u32 sid)
{}
#endif

static void
lpfc_nvmet_defer_release(struct lpfc_hba *phba,
			struct lpfc_async_xchg_ctx *ctxp)
{}

/**
 * __lpfc_nvme_xmt_ls_rsp_cmp - Generic completion handler for the
 *         transmission of an NVME LS response.
 * @phba: Pointer to HBA context object.
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * The function is called from SLI ring event handler with no
 * lock held. The function frees memory resources used for the command
 * used to send the NVME LS RSP.
 **/
void
__lpfc_nvme_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
			   struct lpfc_iocbq *rspwqe)
{}

/**
 * lpfc_nvmet_xmt_ls_rsp_cmp - Completion handler for LS Response
 * @phba: Pointer to HBA context object.
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * The function is called from SLI ring event handler with no
 * lock held. This function is the completion handler for NVME LS commands
 * The function updates any states and statistics, then calls the
 * generic completion handler to free resources.
 **/
static void
lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
			  struct lpfc_iocbq *rspwqe)
{}

/**
 * lpfc_nvmet_ctxbuf_post - Repost a NVMET RQ DMA buffer and clean up context
 * @phba: HBA buffer is associated with
 * @ctx_buf: ctx buffer context
 *
 * Description: Frees the given DMA buffer in the appropriate way given by
 * reposting it to its associated RQ so it can be reused.
 *
 * Notes: Takes phba->hbalock.  Can be called with or without other locks held.
 *
 * Returns: None
 **/
void
lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct lpfc_nvmet_ctxbuf *ctx_buf)
{}

#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
static void
lpfc_nvmet_ktime(struct lpfc_hba *phba,
		 struct lpfc_async_xchg_ctx *ctxp)
{}
#endif

/**
 * lpfc_nvmet_xmt_fcp_op_cmp - Completion handler for FCP Response
 * @phba: Pointer to HBA context object.
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * The function is called from SLI ring event handler with no
 * lock held. This function is the completion handler for NVME FCP commands
 * The function frees memory resources used for the NVME commands.
 **/
static void
lpfc_nvmet_xmt_fcp_op_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
			  struct lpfc_iocbq *rspwqe)
{}

/**
 * __lpfc_nvme_xmt_ls_rsp - Generic service routine to issue transmit
 *         an NVME LS rsp for a prior NVME LS request that was received.
 * @axchg: pointer to exchange context for the NVME LS request the response
 *         is for.
 * @ls_rsp: pointer to the transport LS RSP that is to be sent
 * @xmt_ls_rsp_cmp: completion routine to call upon RSP transmit done
 *
 * This routine is used to format and send a WQE to transmit a NVME LS
 * Response.  The response is for a prior NVME LS request that was
 * received and posted to the transport.
 *
 * Returns:
 *  0 : if response successfully transmit
 *  non-zero : if response failed to transmit, of the form -Exxx.
 **/
int
__lpfc_nvme_xmt_ls_rsp(struct lpfc_async_xchg_ctx *axchg,
			struct nvmefc_ls_rsp *ls_rsp,
			void (*xmt_ls_rsp_cmp)(struct lpfc_hba *phba,
				struct lpfc_iocbq *cmdwqe,
				struct lpfc_iocbq *rspwqe))
{}

/**
 * lpfc_nvmet_xmt_ls_rsp - Transmit NVME LS response
 * @tgtport: pointer to target port that NVME LS is to be transmit from.
 * @ls_rsp: pointer to the transport LS RSP that is to be sent
 *
 * Driver registers this routine to transmit responses for received NVME
 * LS requests.
 *
 * This routine is used to format and send a WQE to transmit a NVME LS
 * Response. The ls_rsp is used to reverse-map the LS to the original
 * NVME LS request sequence, which provides addressing information for
 * the remote port the LS to be sent to, as well as the exchange id
 * that is the LS is bound to.
 *
 * Returns:
 *  0 : if response successfully transmit
 *  non-zero : if response failed to transmit, of the form -Exxx.
 **/
static int
lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
		      struct nvmefc_ls_rsp *ls_rsp)
{}

static int
lpfc_nvmet_xmt_fcp_op(struct nvmet_fc_target_port *tgtport,
		      struct nvmefc_tgt_fcp_req *rsp)
{}

static void
lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
{}

static void
lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port *tgtport,
			 struct nvmefc_tgt_fcp_req *req)
{}

static void
lpfc_nvmet_xmt_fcp_release(struct nvmet_fc_target_port *tgtport,
			   struct nvmefc_tgt_fcp_req *rsp)
{}

static void
lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
		     struct nvmefc_tgt_fcp_req *rsp)
{}

/**
 * lpfc_nvmet_ls_req_cmp - completion handler for a nvme ls request
 * @phba: Pointer to HBA context object
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * This function is the completion handler for NVME LS requests.
 * The function updates any states and statistics, then calls the
 * generic completion handler to finish completion of the request.
 **/
static void
lpfc_nvmet_ls_req_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
		      struct lpfc_iocbq *rspwqe)
{}

/**
 * lpfc_nvmet_ls_req - Issue an Link Service request
 * @targetport: pointer to target instance registered with nvmet transport.
 * @hosthandle: hosthandle set by the driver in a prior ls_rqst_rcv.
 *               Driver sets this value to the ndlp pointer.
 * @pnvme_lsreq: the transport nvme_ls_req structure for the LS
 *
 * Driver registers this routine to handle any link service request
 * from the nvme_fc transport to a remote nvme-aware port.
 *
 * Return value :
 *   0 - Success
 *   non-zero: various error codes, in form of -Exxx
 **/
static int
lpfc_nvmet_ls_req(struct nvmet_fc_target_port *targetport,
		  void *hosthandle,
		  struct nvmefc_ls_req *pnvme_lsreq)
{}

/**
 * lpfc_nvmet_ls_abort - Abort a prior NVME LS request
 * @targetport: Transport targetport, that LS was issued from.
 * @hosthandle: hosthandle set by the driver in a prior ls_rqst_rcv.
 *               Driver sets this value to the ndlp pointer.
 * @pnvme_lsreq: the transport nvme_ls_req structure for LS to be aborted
 *
 * Driver registers this routine to abort an NVME LS request that is
 * in progress (from the transports perspective).
 **/
static void
lpfc_nvmet_ls_abort(struct nvmet_fc_target_port *targetport,
		    void *hosthandle,
		    struct nvmefc_ls_req *pnvme_lsreq)
{}

static int
lpfc_nvmet_host_traddr(void *hosthandle, u64 *wwnn, u64 *wwpn)
{}

static void
lpfc_nvmet_host_release(void *hosthandle)
{}

static void
lpfc_nvmet_discovery_event(struct nvmet_fc_target_port *tgtport)
{}

static struct nvmet_fc_target_template lpfc_tgttemplate =;

static void
__lpfc_nvmet_clean_io_for_cpu(struct lpfc_hba *phba,
		struct lpfc_nvmet_ctx_info *infop)
{}

static void
lpfc_nvmet_cleanup_io_context(struct lpfc_hba *phba)
{}

static int
lpfc_nvmet_setup_io_context(struct lpfc_hba *phba)
{}

int
lpfc_nvmet_create_targetport(struct lpfc_hba *phba)
{}

int
lpfc_nvmet_update_targetport(struct lpfc_hba *phba)
{}

/**
 * lpfc_sli4_nvmet_xri_aborted - Fast-path process of nvmet xri abort
 * @phba: pointer to lpfc hba data structure.
 * @axri: pointer to the nvmet xri abort wcqe structure.
 *
 * This routine is invoked by the worker thread to process a SLI4 fast-path
 * NVMET aborted xri.
 **/
void
lpfc_sli4_nvmet_xri_aborted(struct lpfc_hba *phba,
			    struct sli4_wcqe_xri_aborted *axri)
{}

int
lpfc_nvmet_rcv_unsol_abort(struct lpfc_vport *vport,
			   struct fc_frame_header *fc_hdr)
{}

static void
lpfc_nvmet_wqfull_flush(struct lpfc_hba *phba, struct lpfc_queue *wq,
			struct lpfc_async_xchg_ctx *ctxp)
{}

void
lpfc_nvmet_wqfull_process(struct lpfc_hba *phba,
			  struct lpfc_queue *wq)
{}

void
lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
{}

/**
 * lpfc_nvmet_handle_lsreq - Process an NVME LS request
 * @phba: pointer to lpfc hba data structure.
 * @axchg: pointer to exchange context for the NVME LS request
 *
 * This routine is used for processing an asychronously received NVME LS
 * request. Any remaining validation is done and the LS is then forwarded
 * to the nvmet-fc transport via nvmet_fc_rcv_ls_req().
 *
 * The calling sequence should be: nvmet_fc_rcv_ls_req() -> (processing)
 * -> lpfc_nvmet_xmt_ls_rsp/cmp -> req->done.
 * lpfc_nvme_xmt_ls_rsp_cmp should free the allocated axchg.
 *
 * Returns 0 if LS was handled and delivered to the transport
 * Returns 1 if LS failed to be handled and should be dropped
 */
int
lpfc_nvmet_handle_lsreq(struct lpfc_hba *phba,
			struct lpfc_async_xchg_ctx *axchg)
{}

static void
lpfc_nvmet_process_rcv_fcp_req(struct lpfc_nvmet_ctxbuf *ctx_buf)
{}

static void
lpfc_nvmet_fcp_rqst_defer_work(struct work_struct *work)
{}

static struct lpfc_nvmet_ctxbuf *
lpfc_nvmet_replenish_context(struct lpfc_hba *phba,
			     struct lpfc_nvmet_ctx_info *current_infop)
{}

/**
 * lpfc_nvmet_unsol_fcp_buffer - Process an unsolicited event data buffer
 * @phba: pointer to lpfc hba data structure.
 * @idx: relative index of MRQ vector
 * @nvmebuf: pointer to lpfc nvme command HBQ data structure.
 * @isr_timestamp: in jiffies.
 * @cqflag: cq processing information regarding workload.
 *
 * This routine is used for processing the WQE associated with a unsolicited
 * event. It first determines whether there is an existing ndlp that matches
 * the DID from the unsolicited WQE. If not, it will create a new one with
 * the DID from the unsolicited WQE. The ELS command from the unsolicited
 * WQE is then used to invoke the proper routine and to set up proper state
 * of the discovery state machine.
 **/
static void
lpfc_nvmet_unsol_fcp_buffer(struct lpfc_hba *phba,
			    uint32_t idx,
			    struct rqb_dmabuf *nvmebuf,
			    uint64_t isr_timestamp,
			    uint8_t cqflag)
{}

/**
 * lpfc_nvmet_unsol_fcp_event - Process an unsolicited event from an nvme nport
 * @phba: pointer to lpfc hba data structure.
 * @idx: relative index of MRQ vector
 * @nvmebuf: pointer to received nvme data structure.
 * @isr_timestamp: in jiffies.
 * @cqflag: cq processing information regarding workload.
 *
 * This routine is used to process an unsolicited event received from a SLI
 * (Service Level Interface) ring. The actual processing of the data buffer
 * associated with the unsolicited event is done by invoking the routine
 * lpfc_nvmet_unsol_fcp_buffer() after properly set up the buffer from the
 * SLI RQ on which the unsolicited event was received.
 **/
void
lpfc_nvmet_unsol_fcp_event(struct lpfc_hba *phba,
			   uint32_t idx,
			   struct rqb_dmabuf *nvmebuf,
			   uint64_t isr_timestamp,
			   uint8_t cqflag)
{}

/**
 * lpfc_nvmet_prep_ls_wqe - Allocate and prepare a lpfc wqe data structure
 * @phba: pointer to a host N_Port data structure.
 * @ctxp: Context info for NVME LS Request
 * @rspbuf: DMA buffer of NVME command.
 * @rspsize: size of the NVME command.
 *
 * This routine is used for allocating a lpfc-WQE data structure from
 * the driver lpfc-WQE free-list and prepare the WQE with the parameters
 * passed into the routine for discovery state machine to issue an Extended
 * Link Service (NVME) commands. It is a generic lpfc-WQE allocation
 * and preparation routine that is used by all the discovery state machine
 * routines and the NVME command-specific fields will be later set up by
 * the individual discovery machine routines after calling this routine
 * allocating and preparing a generic WQE data structure. It fills in the
 * Buffer Descriptor Entries (BDEs), allocates buffers for both command
 * payload and response payload (if expected). The reference count on the
 * ndlp is incremented by 1 and the reference to the ndlp is put into
 * context1 of the WQE data structure for this WQE to hold the ndlp
 * reference for the command's callback function to access later.
 *
 * Return code
 *   Pointer to the newly allocated/prepared nvme wqe data structure
 *   NULL - when nvme wqe data structure allocation/preparation failed
 **/
static struct lpfc_iocbq *
lpfc_nvmet_prep_ls_wqe(struct lpfc_hba *phba,
		       struct lpfc_async_xchg_ctx *ctxp,
		       dma_addr_t rspbuf, uint16_t rspsize)
{}


static struct lpfc_iocbq *
lpfc_nvmet_prep_fcp_wqe(struct lpfc_hba *phba,
			struct lpfc_async_xchg_ctx *ctxp)
{}

/**
 * lpfc_nvmet_sol_fcp_abort_cmp - Completion handler for ABTS
 * @phba: Pointer to HBA context object.
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * The function is called from SLI ring event handler with no
 * lock held. This function is the completion handler for NVME ABTS for FCP cmds
 * The function frees memory resources used for the NVME commands.
 **/
static void
lpfc_nvmet_sol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
			     struct lpfc_iocbq *rspwqe)
{}

/**
 * lpfc_nvmet_unsol_fcp_abort_cmp - Completion handler for ABTS
 * @phba: Pointer to HBA context object.
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * The function is called from SLI ring event handler with no
 * lock held. This function is the completion handler for NVME ABTS for FCP cmds
 * The function frees memory resources used for the NVME commands.
 **/
static void
lpfc_nvmet_unsol_fcp_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
			       struct lpfc_iocbq *rspwqe)
{}

/**
 * lpfc_nvmet_xmt_ls_abort_cmp - Completion handler for ABTS
 * @phba: Pointer to HBA context object.
 * @cmdwqe: Pointer to driver command WQE object.
 * @rspwqe: Pointer to driver response WQE object.
 *
 * The function is called from SLI ring event handler with no
 * lock held. This function is the completion handler for NVME ABTS for LS cmds
 * The function frees memory resources used for the NVME commands.
 **/
static void
lpfc_nvmet_xmt_ls_abort_cmp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
			    struct lpfc_iocbq *rspwqe)
{}

static int
lpfc_nvmet_unsol_issue_abort(struct lpfc_hba *phba,
			     struct lpfc_async_xchg_ctx *ctxp,
			     uint32_t sid, uint16_t xri)
{}

static int
lpfc_nvmet_sol_fcp_issue_abort(struct lpfc_hba *phba,
			       struct lpfc_async_xchg_ctx *ctxp,
			       uint32_t sid, uint16_t xri)
{}

static int
lpfc_nvmet_unsol_fcp_issue_abort(struct lpfc_hba *phba,
				 struct lpfc_async_xchg_ctx *ctxp,
				 uint32_t sid, uint16_t xri)
{}

/**
 * lpfc_nvme_unsol_ls_issue_abort - issue ABTS on an exchange received
 *        via async frame receive where the frame is not handled.
 * @phba: pointer to adapter structure
 * @ctxp: pointer to the asynchronously received received sequence
 * @sid: address of the remote port to send the ABTS to
 * @xri: oxid value to for the ABTS (other side's exchange id).
 **/
int
lpfc_nvme_unsol_ls_issue_abort(struct lpfc_hba *phba,
				struct lpfc_async_xchg_ctx *ctxp,
				uint32_t sid, uint16_t xri)
{}

/**
 * lpfc_nvmet_invalidate_host
 *
 * @phba: pointer to the driver instance bound to an adapter port.
 * @ndlp: pointer to an lpfc_nodelist type
 *
 * This routine upcalls the nvmet transport to invalidate an NVME
 * host to which this target instance had active connections.
 */
void
lpfc_nvmet_invalidate_host(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
{}