root/drivers/scsi/elx/efct/efct_io.h
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2021 Broadcom. All Rights Reserved. The term
 * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
 */

#if !defined(__EFCT_IO_H__)
#define __EFCT_IO_H__

#include "efct_lio.h"

#define EFCT_LOG_ENABLE_IO_ERRORS(efct)         \
                (((efct) != NULL) ? (((efct)->logmask & (1U << 6)) != 0) : 0)

#define io_error_log(io, fmt, ...)  \
        do { \
                if (EFCT_LOG_ENABLE_IO_ERRORS(io->efct)) \
                        efc_log_warn(io->efct, fmt, ##__VA_ARGS__); \
        } while (0)

#define SCSI_CMD_BUF_LENGTH     48
#define SCSI_RSP_BUF_LENGTH     (FCP_RESP_WITH_EXT + SCSI_SENSE_BUFFERSIZE)
#define EFCT_NUM_SCSI_IOS       8192

enum efct_io_type {
        EFCT_IO_TYPE_IO = 0,
        EFCT_IO_TYPE_ELS,
        EFCT_IO_TYPE_CT,
        EFCT_IO_TYPE_CT_RESP,
        EFCT_IO_TYPE_BLS_RESP,
        EFCT_IO_TYPE_ABORT,

        EFCT_IO_TYPE_MAX,
};

enum efct_els_state {
        EFCT_ELS_REQUEST = 0,
        EFCT_ELS_REQUEST_DELAYED,
        EFCT_ELS_REQUEST_DELAY_ABORT,
        EFCT_ELS_REQ_ABORT,
        EFCT_ELS_REQ_ABORTED,
        EFCT_ELS_ABORT_IO_COMPL,
};

/**
 * Scsi target IO object
 * @efct:               pointer back to efct
 * @instance_index:     unique instance index value
 * @io:                 IO display name
 * @node:               pointer to node
 * @list_entry:         io list entry
 * @io_pending_link:    io pending list entry
 * @ref:                reference counter
 * @release:            release callback function
 * @init_task_tag:      initiator task tag (OX_ID) for back-end and SCSI logging
 * @tgt_task_tag:       target task tag (RX_ID) for back-end and SCSI logging
 * @hw_tag:             HW layer unique IO id
 * @tag:                unique IO identifier
 * @sgl:                SGL
 * @sgl_allocated:      Number of allocated SGEs
 * @sgl_count:          Number of SGEs in this SGL
 * @tgt_io:             backend target private IO data
 * @exp_xfer_len:       expected data transfer length, based on FC header
 * @hw_priv:            Declarations private to HW/SLI
 * @io_type:            indicates what this struct efct_io structure is used for
 * @hio:                hw io object
 * @transferred:        Number of bytes transferred
 * @auto_resp:          set if auto_trsp was set
 * @low_latency:        set if low latency request
 * @wq_steering:        selected WQ steering request
 * @wq_class:           selected WQ class if steering is class
 * @xfer_req:           transfer size for current request
 * @scsi_tgt_cb:        target callback function
 * @scsi_tgt_cb_arg:    target callback function argument
 * @abort_cb:           abort callback function
 * @abort_cb_arg:       abort callback function argument
 * @bls_cb:             BLS callback function
 * @bls_cb_arg:         BLS callback function argument
 * @tmf_cmd:            TMF command being processed
 * @abort_rx_id:        rx_id from the ABTS that initiated the command abort
 * @cmd_tgt:            True if this is a Target command
 * @send_abts:          when aborting, indicates ABTS is to be sent
 * @cmd_ini:            True if this is an Initiator command
 * @seq_init:           True if local node has sequence initiative
 * @iparam:             iparams for hw io send call
 * @hio_type:           HW IO type
 * @wire_len:           wire length
 * @hw_cb:              saved HW callback
 * @io_to_abort:        for abort handling, pointer to IO to abort
 * @rspbuf:             SCSI Response buffer
 * @timeout:            Timeout value in seconds for this IO
 * @cs_ctl:             CS_CTL priority for this IO
 * @io_free:            Is io object in freelist
 * @app_id:             application id
 */
struct efct_io {
        struct efct             *efct;
        u32                     instance_index;
        const char              *display_name;
        struct efct_node        *node;

        struct list_head        list_entry;
        struct list_head        io_pending_link;
        struct kref             ref;
        void (*release)(struct kref *arg);
        u32                     init_task_tag;
        u32                     tgt_task_tag;
        u32                     hw_tag;
        u32                     tag;
        struct efct_scsi_sgl    *sgl;
        u32                     sgl_allocated;
        u32                     sgl_count;
        struct efct_scsi_tgt_io tgt_io;
        u32                     exp_xfer_len;

        void                    *hw_priv;

        enum efct_io_type       io_type;
        struct efct_hw_io       *hio;
        size_t                  transferred;

        bool                    auto_resp;
        bool                    low_latency;
        u8                      wq_steering;
        u8                      wq_class;
        u64                     xfer_req;
        efct_scsi_io_cb_t       scsi_tgt_cb;
        void                    *scsi_tgt_cb_arg;
        efct_scsi_io_cb_t       abort_cb;
        void                    *abort_cb_arg;
        efct_scsi_io_cb_t       bls_cb;
        void                    *bls_cb_arg;
        enum efct_scsi_tmf_cmd  tmf_cmd;
        u16                     abort_rx_id;

        bool                    cmd_tgt;
        bool                    send_abts;
        bool                    cmd_ini;
        bool                    seq_init;
        union efct_hw_io_param_u iparam;
        enum efct_hw_io_type    hio_type;
        u64                     wire_len;
        void                    *hw_cb;

        struct efct_io          *io_to_abort;

        struct efc_dma          rspbuf;
        u32                     timeout;
        u8                      cs_ctl;
        u8                      io_free;
        u32                     app_id;
};

struct efct_io_cb_arg {
        int status;
        int ext_status;
        void *app;
};

struct efct_io_pool *
efct_io_pool_create(struct efct *efct, u32 num_sgl);
int
efct_io_pool_free(struct efct_io_pool *io_pool);
u32
efct_io_pool_allocated(struct efct_io_pool *io_pool);

struct efct_io *
efct_io_pool_io_alloc(struct efct_io_pool *io_pool);
void
efct_io_pool_io_free(struct efct_io_pool *io_pool, struct efct_io *io);
struct efct_io *
efct_io_find_tgt_io(struct efct *efct, struct efct_node *node,
                    u16 ox_id, u16 rx_id);
#endif /* __EFCT_IO_H__ */