root/drivers/scsi/elx/efct/efct_lio.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.
 */

#ifndef __EFCT_LIO_H__
#define __EFCT_LIO_H__

#include "efct_scsi.h"
#include <target/target_core_base.h>

#define efct_lio_io_printf(io, fmt, ...)                        \
        efc_log_debug(io->efct,                                 \
                "[%s] [%04x][i:%04x t:%04x h:%04x]" fmt,\
                io->node->display_name, io->instance_index,     \
                io->init_task_tag, io->tgt_task_tag, io->hw_tag,\
                ##__VA_ARGS__)

#define efct_lio_tmfio_printf(io, fmt, ...)                     \
        efc_log_debug(io->efct,                                 \
                "[%s] [%04x][i:%04x t:%04x h:%04x][f:%02x]" fmt,\
                io->node->display_name, io->instance_index,     \
                io->init_task_tag, io->tgt_task_tag, io->hw_tag,\
                io->tgt_io.tmf,  ##__VA_ARGS__)

#define efct_set_lio_io_state(io, value) (io->tgt_io.state |= value)

struct efct_lio_wq_data {
        struct efct             *efct;
        void                    *ptr;
        struct work_struct      work;
};

/* Target private efct structure */
struct efct_scsi_tgt {
        u32                     max_sge;
        u32                     max_sgl;

        /*
         * Variables used to send task set full. We are using a high watermark
         * method to send task set full. We will reserve a fixed number of IOs
         * per initiator plus a fudge factor. Once we reach this number,
         * then the target will start sending task set full/busy responses.
         */
        atomic_t                initiator_count;
        atomic_t                ios_in_use;
        atomic_t                io_high_watermark;

        atomic_t                watermark_hit;
        int                     watermark_min;
        int                     watermark_max;

        struct efct_lio_nport   *lio_nport;
        struct efct_lio_tpg     *tpg;

        struct list_head        vport_list;
        /* Protects vport list*/
        spinlock_t              efct_lio_lock;

        u64                     wwnn;
};

struct efct_scsi_tgt_nport {
        struct efct_lio_nport   *lio_nport;
};

struct efct_node {
        struct list_head        list_entry;
        struct kref             ref;
        void                    (*release)(struct kref *arg);
        struct efct             *efct;
        struct efc_node         *node;
        struct se_session       *session;
        spinlock_t              active_ios_lock;
        struct list_head        active_ios;
        char                    display_name[EFC_NAME_LENGTH];
        u32                     port_fc_id;
        u32                     node_fc_id;
        u32                     vpi;
        u32                     rpi;
        u32                     abort_cnt;
};

#define EFCT_LIO_STATE_SCSI_RECV_CMD            (1 << 0)
#define EFCT_LIO_STATE_TGT_SUBMIT_CMD           (1 << 1)
#define EFCT_LIO_STATE_TFO_QUEUE_DATA_IN        (1 << 2)
#define EFCT_LIO_STATE_TFO_WRITE_PENDING        (1 << 3)
#define EFCT_LIO_STATE_TGT_EXECUTE_CMD          (1 << 4)
#define EFCT_LIO_STATE_SCSI_SEND_RD_DATA        (1 << 5)
#define EFCT_LIO_STATE_TFO_CHK_STOP_FREE        (1 << 6)
#define EFCT_LIO_STATE_SCSI_DATA_DONE           (1 << 7)
#define EFCT_LIO_STATE_TFO_QUEUE_STATUS         (1 << 8)
#define EFCT_LIO_STATE_SCSI_SEND_RSP            (1 << 9)
#define EFCT_LIO_STATE_SCSI_RSP_DONE            (1 << 10)
#define EFCT_LIO_STATE_TGT_GENERIC_FREE         (1 << 11)
#define EFCT_LIO_STATE_SCSI_RECV_TMF            (1 << 12)
#define EFCT_LIO_STATE_TGT_SUBMIT_TMR           (1 << 13)
#define EFCT_LIO_STATE_TFO_WRITE_PEND_STATUS    (1 << 14)
#define EFCT_LIO_STATE_TGT_GENERIC_REQ_FAILURE  (1 << 15)

#define EFCT_LIO_STATE_TFO_ABORTED_TASK         (1 << 29)
#define EFCT_LIO_STATE_TFO_RELEASE_CMD          (1 << 30)
#define EFCT_LIO_STATE_SCSI_CMPL_CMD            (1u << 31)

struct efct_scsi_tgt_io {
        struct se_cmd           cmd;
        unsigned char           sense_buffer[TRANSPORT_SENSE_BUFFER];
        enum dma_data_direction ddir;
        int                     task_attr;
        u64                     lun;

        u32                     state;
        u8                      tmf;
        struct efct_io          *io_to_abort;
        u32                     seg_map_cnt;
        u32                     seg_cnt;
        u32                     cur_seg;
        enum efct_scsi_io_status err;
        bool                    aborting;
        bool                    rsp_sent;
        u32                     transferred_len;
};

/* Handler return codes */
enum {
        SCSI_HANDLER_DATAPHASE_STARTED = 1,
        SCSI_HANDLER_RESP_STARTED,
        SCSI_HANDLER_VALIDATED_DATAPHASE_STARTED,
        SCSI_CMD_NOT_SUPPORTED,
};

#define WWN_NAME_LEN            32
struct efct_lio_vport {
        u64                     wwpn;
        u64                     npiv_wwpn;
        u64                     npiv_wwnn;
        unsigned char           wwpn_str[WWN_NAME_LEN];
        struct se_wwn           vport_wwn;
        struct efct_lio_tpg     *tpg;
        struct efct             *efct;
        struct Scsi_Host        *shost;
        struct fc_vport         *fc_vport;
        atomic_t                enable;
};

struct efct_lio_nport {
        u64                     wwpn;
        unsigned char           wwpn_str[WWN_NAME_LEN];
        struct se_wwn           nport_wwn;
        struct efct_lio_tpg     *tpg;
        struct efct             *efct;
        atomic_t                enable;
};

struct efct_lio_tpg_attrib {
        u32                     generate_node_acls;
        u32                     cache_dynamic_acls;
        u32                     demo_mode_write_protect;
        u32                     prod_mode_write_protect;
        u32                     demo_mode_login_only;
        bool                    session_deletion_wait;
};

struct efct_lio_tpg {
        struct se_portal_group  tpg;
        struct efct_lio_nport   *nport;
        struct efct_lio_vport   *vport;
        struct efct_lio_tpg_attrib tpg_attrib;
        unsigned short          tpgt;
        bool                    enabled;
};

struct efct_lio_nacl {
        u64                     nport_wwnn;
        char                    nport_name[WWN_NAME_LEN];
        struct se_session       *session;
        struct se_node_acl      se_node_acl;
};

struct efct_lio_vport_list_t {
        struct list_head        list_entry;
        struct efct_lio_vport   *lio_vport;
};

int efct_scsi_tgt_driver_init(void);
int efct_scsi_tgt_driver_exit(void);

#endif /*__EFCT_LIO_H__ */