Commit 75a10a7a authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: elx: efct: Data structures and defines for hw operations

Start the population of the efct target mode driver.  The driver is
contained in the drivers/scsi/elx/efct subdirectory.

Create the efct directory and start population of the driver by adding
SLI-4 configuration parameters, data structures for configuring SLI-4
queues, converting from OS to SLI-4 IO requests, and handling async events.

Link: https://lore.kernel.org/r/20210601235512.20104-18-jsmart2021@gmail.comReviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarDaniel Wagner <dwagner@suse.de>
Co-developed-by: default avatarRam Vegesna <ram.vegesna@broadcom.com>
Signed-off-by: default avatarRam Vegesna <ram.vegesna@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent cdaf39ba
/* 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_HW_H
#define _EFCT_HW_H
#include "../libefc_sli/sli4.h"
/*
* EFCT PCI IDs
*/
#define EFCT_VENDOR_ID 0x10df
/* LightPulse 16Gb x 4 FC (lancer-g6) */
#define EFCT_DEVICE_LANCER_G6 0xe307
/* LightPulse 32Gb x 4 FC (lancer-g7) */
#define EFCT_DEVICE_LANCER_G7 0xf407
/*Default RQ entries len used by driver*/
#define EFCT_HW_RQ_ENTRIES_MIN 512
#define EFCT_HW_RQ_ENTRIES_DEF 1024
#define EFCT_HW_RQ_ENTRIES_MAX 4096
/*Defines the size of the RQ buffers used for each RQ*/
#define EFCT_HW_RQ_SIZE_HDR 128
#define EFCT_HW_RQ_SIZE_PAYLOAD 1024
/*Define the maximum number of multi-receive queues*/
#define EFCT_HW_MAX_MRQS 8
/*
* Define count of when to set the WQEC bit in a submitted
* WQE, causing a consummed/released completion to be posted.
*/
#define EFCT_HW_WQEC_SET_COUNT 32
/*Send frame timeout in seconds*/
#define EFCT_HW_SEND_FRAME_TIMEOUT 10
/*
* FDT Transfer Hint value, reads greater than this value
* will be segmented to implement fairness. A value of zero disables
* the feature.
*/
#define EFCT_HW_FDT_XFER_HINT 8192
#define EFCT_HW_TIMECHECK_ITERATIONS 100
#define EFCT_HW_MAX_NUM_MQ 1
#define EFCT_HW_MAX_NUM_RQ 32
#define EFCT_HW_MAX_NUM_EQ 16
#define EFCT_HW_MAX_NUM_WQ 32
#define EFCT_HW_DEF_NUM_EQ 1
#define OCE_HW_MAX_NUM_MRQ_PAIRS 16
#define EFCT_HW_MQ_DEPTH 128
#define EFCT_HW_EQ_DEPTH 1024
/*
* A CQ will be assinged to each WQ
* (CQ must have 2X entries of the WQ for abort
* processing), plus a separate one for each RQ PAIR and one for MQ
*/
#define EFCT_HW_MAX_NUM_CQ \
((EFCT_HW_MAX_NUM_WQ * 2) + 1 + (OCE_HW_MAX_NUM_MRQ_PAIRS * 2))
#define EFCT_HW_Q_HASH_SIZE 128
#define EFCT_HW_RQ_HEADER_SIZE 128
#define EFCT_HW_RQ_HEADER_INDEX 0
#define EFCT_HW_REQUE_XRI_REGTAG 65534
/* Options for efct_hw_command() */
enum efct_cmd_opts {
/* command executes synchronously and busy-waits for completion */
EFCT_CMD_POLL,
/* command executes asynchronously. Uses callback */
EFCT_CMD_NOWAIT,
};
enum efct_hw_reset {
EFCT_HW_RESET_FUNCTION,
EFCT_HW_RESET_FIRMWARE,
EFCT_HW_RESET_MAX
};
enum efct_hw_topo {
EFCT_HW_TOPOLOGY_AUTO,
EFCT_HW_TOPOLOGY_NPORT,
EFCT_HW_TOPOLOGY_LOOP,
EFCT_HW_TOPOLOGY_NONE,
EFCT_HW_TOPOLOGY_MAX
};
/* pack fw revision values into a single uint64_t */
#define HW_FWREV(a, b, c, d) (((uint64_t)(a) << 48) | ((uint64_t)(b) << 32) \
| ((uint64_t)(c) << 16) | ((uint64_t)(d)))
#define EFCT_FW_VER_STR(a, b, c, d) (#a "." #b "." #c "." #d)
enum efct_hw_io_type {
EFCT_HW_ELS_REQ,
EFCT_HW_ELS_RSP,
EFCT_HW_FC_CT,
EFCT_HW_FC_CT_RSP,
EFCT_HW_BLS_ACC,
EFCT_HW_BLS_RJT,
EFCT_HW_IO_TARGET_READ,
EFCT_HW_IO_TARGET_WRITE,
EFCT_HW_IO_TARGET_RSP,
EFCT_HW_IO_DNRX_REQUEUE,
EFCT_HW_IO_MAX,
};
enum efct_hw_io_state {
EFCT_HW_IO_STATE_FREE,
EFCT_HW_IO_STATE_INUSE,
EFCT_HW_IO_STATE_WAIT_FREE,
EFCT_HW_IO_STATE_WAIT_SEC_HIO,
};
#define EFCT_TARGET_WRITE_SKIPS 1
#define EFCT_TARGET_READ_SKIPS 2
struct efct_hw;
struct efct_io;
#define EFCT_CMD_CTX_POOL_SZ 32
/**
* HW command context.
* Stores the state for the asynchronous commands sent to the hardware.
*/
struct efct_command_ctx {
struct list_head list_entry;
int (*cb)(struct efct_hw *hw, int status, u8 *mqe, void *arg);
void *arg; /* Argument for callback */
/* buffer holding command / results */
u8 buf[SLI4_BMBX_SIZE];
void *ctx; /* upper layer context */
};
struct efct_hw_sgl {
uintptr_t addr;
size_t len;
};
union efct_hw_io_param_u {
struct sli_bls_params bls;
struct sli_els_params els;
struct sli_ct_params fc_ct;
struct sli_fcp_tgt_params fcp_tgt;
};
/* WQ steering mode */
enum efct_hw_wq_steering {
EFCT_HW_WQ_STEERING_CLASS,
EFCT_HW_WQ_STEERING_REQUEST,
EFCT_HW_WQ_STEERING_CPU,
};
/* HW wqe object */
struct efct_hw_wqe {
struct list_head list_entry;
bool abort_wqe_submit_needed;
bool send_abts;
u32 id;
u32 abort_reqtag;
u8 *wqebuf;
};
struct efct_hw_io;
/* Typedef for HW "done" callback */
typedef int (*efct_hw_done_t)(struct efct_hw_io *, u32 len, int status,
u32 ext, void *ul_arg);
/**
* HW IO object.
*
* Stores the per-IO information necessary
* for both SLI and efct.
* @ref: reference counter for hw io object
* @state: state of IO: free, busy, wait_free
* @list_entry used for busy, wait_free, free lists
* @wqe Work queue object, with link for pending
* @hw pointer back to hardware context
* @xfer_rdy transfer ready data
* @type IO type
* @xbusy Exchange is active in FW
* @abort_in_progress if TRUE, abort is in progress
* @status_saved if TRUE, latched status should be returned
* @wq_class WQ class if steering mode is Class
* @reqtag request tag for this HW IO
* @wq WQ assigned to the exchange
* @done Function called on IO completion
* @arg argument passed to IO done callback
* @abort_done Function called on abort completion
* @abort_arg argument passed to abort done callback
* @wq_steering WQ steering mode request
* @saved_status Saved status
* @saved_len Status length
* @saved_ext Saved extended status
* @eq EQ on which this HIO came up
* @sge_offset SGE data offset
* @def_sgl_count Count of SGEs in default SGL
* @abort_reqtag request tag for an abort of this HW IO
* @indicator Exchange indicator
* @def_sgl default SGL
* @sgl pointer to current active SGL
* @sgl_count count of SGEs in io->sgl
* @first_data_sge index of first data SGE
* @n_sge number of active SGEs
*/
struct efct_hw_io {
struct kref ref;
enum efct_hw_io_state state;
void (*release)(struct kref *arg);
struct list_head list_entry;
struct efct_hw_wqe wqe;
struct efct_hw *hw;
struct efc_dma xfer_rdy;
u16 type;
bool xbusy;
bool abort_in_progress;
bool status_saved;
u8 wq_class;
u16 reqtag;
struct hw_wq *wq;
efct_hw_done_t done;
void *arg;
efct_hw_done_t abort_done;
void *abort_arg;
enum efct_hw_wq_steering wq_steering;
u32 saved_status;
u32 saved_len;
u32 saved_ext;
struct hw_eq *eq;
u32 sge_offset;
u32 def_sgl_count;
u32 abort_reqtag;
u32 indicator;
struct efc_dma def_sgl;
struct efc_dma *sgl;
u32 sgl_count;
u32 first_data_sge;
u32 n_sge;
};
enum efct_hw_port {
EFCT_HW_PORT_INIT,
EFCT_HW_PORT_SHUTDOWN,
};
/* Node group rpi reference */
struct efct_hw_rpi_ref {
atomic_t rpi_count;
atomic_t rpi_attached;
};
enum efct_hw_link_stat {
EFCT_HW_LINK_STAT_LINK_FAILURE_COUNT,
EFCT_HW_LINK_STAT_LOSS_OF_SYNC_COUNT,
EFCT_HW_LINK_STAT_LOSS_OF_SIGNAL_COUNT,
EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_COUNT,
EFCT_HW_LINK_STAT_INVALID_XMIT_WORD_COUNT,
EFCT_HW_LINK_STAT_CRC_COUNT,
EFCT_HW_LINK_STAT_PRIMITIVE_SEQ_TIMEOUT_COUNT,
EFCT_HW_LINK_STAT_ELASTIC_BUFFER_OVERRUN_COUNT,
EFCT_HW_LINK_STAT_ARB_TIMEOUT_COUNT,
EFCT_HW_LINK_STAT_ADVERTISED_RCV_B2B_CREDIT,
EFCT_HW_LINK_STAT_CURR_RCV_B2B_CREDIT,
EFCT_HW_LINK_STAT_ADVERTISED_XMIT_B2B_CREDIT,
EFCT_HW_LINK_STAT_CURR_XMIT_B2B_CREDIT,
EFCT_HW_LINK_STAT_RCV_EOFA_COUNT,
EFCT_HW_LINK_STAT_RCV_EOFDTI_COUNT,
EFCT_HW_LINK_STAT_RCV_EOFNI_COUNT,
EFCT_HW_LINK_STAT_RCV_SOFF_COUNT,
EFCT_HW_LINK_STAT_RCV_DROPPED_NO_AER_COUNT,
EFCT_HW_LINK_STAT_RCV_DROPPED_NO_RPI_COUNT,
EFCT_HW_LINK_STAT_RCV_DROPPED_NO_XRI_COUNT,
EFCT_HW_LINK_STAT_MAX,
};
enum efct_hw_host_stat {
EFCT_HW_HOST_STAT_TX_KBYTE_COUNT,
EFCT_HW_HOST_STAT_RX_KBYTE_COUNT,
EFCT_HW_HOST_STAT_TX_FRAME_COUNT,
EFCT_HW_HOST_STAT_RX_FRAME_COUNT,
EFCT_HW_HOST_STAT_TX_SEQ_COUNT,
EFCT_HW_HOST_STAT_RX_SEQ_COUNT,
EFCT_HW_HOST_STAT_TOTAL_EXCH_ORIG,
EFCT_HW_HOST_STAT_TOTAL_EXCH_RESP,
EFCT_HW_HOSY_STAT_RX_P_BSY_COUNT,
EFCT_HW_HOST_STAT_RX_F_BSY_COUNT,
EFCT_HW_HOST_STAT_DROP_FRM_DUE_TO_NO_RQ_BUF_COUNT,
EFCT_HW_HOST_STAT_EMPTY_RQ_TIMEOUT_COUNT,
EFCT_HW_HOST_STAT_DROP_FRM_DUE_TO_NO_XRI_COUNT,
EFCT_HW_HOST_STAT_EMPTY_XRI_POOL_COUNT,
EFCT_HW_HOST_STAT_MAX,
};
enum efct_hw_state {
EFCT_HW_STATE_UNINITIALIZED,
EFCT_HW_STATE_QUEUES_ALLOCATED,
EFCT_HW_STATE_ACTIVE,
EFCT_HW_STATE_RESET_IN_PROGRESS,
EFCT_HW_STATE_TEARDOWN_IN_PROGRESS,
};
struct efct_hw_link_stat_counts {
u8 overflow;
u32 counter;
};
struct efct_hw_host_stat_counts {
u32 counter;
};
/* Structure used for the hash lookup of queue IDs */
struct efct_queue_hash {
bool in_use;
u16 id;
u16 index;
};
/* WQ callback object */
struct hw_wq_callback {
u16 instance_index; /* use for request tag */
void (*callback)(void *arg, u8 *cqe, int status);
void *arg;
struct list_head list_entry;
};
struct reqtag_pool {
spinlock_t lock; /* pool lock */
struct hw_wq_callback *tags[U16_MAX];
struct list_head freelist;
};
struct efct_hw_config {
u32 n_eq;
u32 n_cq;
u32 n_mq;
u32 n_rq;
u32 n_wq;
u32 n_io;
u32 n_sgl;
u32 speed;
u32 topology;
/* size of the buffers for first burst */
u32 rq_default_buffer_size;
u8 esoc;
/* MRQ RQ selection policy */
u8 rq_selection_policy;
/* RQ quanta if rq_selection_policy == 2 */
u8 rr_quanta;
u32 filter_def[SLI4_CMD_REG_FCFI_NUM_RQ_CFG];
};
struct efct_hw {
struct efct *os;
struct sli4 sli;
u16 ulp_start;
u16 ulp_max;
u32 dump_size;
enum efct_hw_state state;
bool hw_setup_called;
u8 sliport_healthcheck;
u16 fcf_indicator;
/* HW configuration */
struct efct_hw_config config;
/* calculated queue sizes for each type */
u32 num_qentries[SLI4_QTYPE_MAX];
/* Storage for SLI queue objects */
struct sli4_queue wq[EFCT_HW_MAX_NUM_WQ];
struct sli4_queue rq[EFCT_HW_MAX_NUM_RQ];
u16 hw_rq_lookup[EFCT_HW_MAX_NUM_RQ];
struct sli4_queue mq[EFCT_HW_MAX_NUM_MQ];
struct sli4_queue cq[EFCT_HW_MAX_NUM_CQ];
struct sli4_queue eq[EFCT_HW_MAX_NUM_EQ];
/* HW queue */
u32 eq_count;
u32 cq_count;
u32 mq_count;
u32 wq_count;
u32 rq_count;
u32 cmd_head_count;
struct list_head eq_list;
struct efct_queue_hash cq_hash[EFCT_HW_Q_HASH_SIZE];
struct efct_queue_hash rq_hash[EFCT_HW_Q_HASH_SIZE];
struct efct_queue_hash wq_hash[EFCT_HW_Q_HASH_SIZE];
/* Storage for HW queue objects */
struct hw_wq *hw_wq[EFCT_HW_MAX_NUM_WQ];
struct hw_rq *hw_rq[EFCT_HW_MAX_NUM_RQ];
struct hw_mq *hw_mq[EFCT_HW_MAX_NUM_MQ];
struct hw_cq *hw_cq[EFCT_HW_MAX_NUM_CQ];
struct hw_eq *hw_eq[EFCT_HW_MAX_NUM_EQ];
/* count of hw_rq[] entries */
u32 hw_rq_count;
/* count of multirq RQs */
u32 hw_mrq_count;
struct hw_wq **wq_cpu_array;
/* Sequence objects used in incoming frame processing */
struct efc_hw_sequence *seq_pool;
/* Maintain an ordered, linked list of outstanding HW commands. */
struct mutex bmbx_lock;
spinlock_t cmd_lock;
struct list_head cmd_head;
struct list_head cmd_pending;
mempool_t *cmd_ctx_pool;
mempool_t *mbox_rqst_pool;
struct sli4_link_event link;
/* pointer array of IO objects */
struct efct_hw_io **io;
/* array of WQE buffs mapped to IO objects */
u8 *wqe_buffs;
/* IO lock to synchronize list access */
spinlock_t io_lock;
/* List of IO objects in use */
struct list_head io_inuse;
/* List of IO objects waiting to be freed */
struct list_head io_wait_free;
/* List of IO objects available for allocation */
struct list_head io_free;
struct efc_dma loop_map;
struct efc_dma xfer_rdy;
struct efc_dma rnode_mem;
atomic_t io_alloc_failed_count;
/* stat: wq sumbit count */
u32 tcmd_wq_submit[EFCT_HW_MAX_NUM_WQ];
/* stat: wq complete count */
u32 tcmd_wq_complete[EFCT_HW_MAX_NUM_WQ];
atomic_t send_frame_seq_id;
struct reqtag_pool *wq_reqtag_pool;
};
enum efct_hw_io_count_type {
EFCT_HW_IO_INUSE_COUNT,
EFCT_HW_IO_FREE_COUNT,
EFCT_HW_IO_WAIT_FREE_COUNT,
EFCT_HW_IO_N_TOTAL_IO_COUNT,
};
/* HW queue data structures */
struct hw_eq {
struct list_head list_entry;
enum sli4_qtype type;
u32 instance;
u32 entry_count;
u32 entry_size;
struct efct_hw *hw;
struct sli4_queue *queue;
struct list_head cq_list;
u32 use_count;
};
struct hw_cq {
struct list_head list_entry;
enum sli4_qtype type;
u32 instance;
u32 entry_count;
u32 entry_size;
struct hw_eq *eq;
struct sli4_queue *queue;
struct list_head q_list;
u32 use_count;
};
struct hw_q {
struct list_head list_entry;
enum sli4_qtype type;
};
struct hw_mq {
struct list_head list_entry;
enum sli4_qtype type;
u32 instance;
u32 entry_count;
u32 entry_size;
struct hw_cq *cq;
struct sli4_queue *queue;
u32 use_count;
};
struct hw_wq {
struct list_head list_entry;
enum sli4_qtype type;
u32 instance;
struct efct_hw *hw;
u32 entry_count;
u32 entry_size;
struct hw_cq *cq;
struct sli4_queue *queue;
u32 class;
/* WQ consumed */
u32 wqec_set_count;
u32 wqec_count;
u32 free_count;
u32 total_submit_count;
struct list_head pending_list;
/* HW IO allocated for use with Send Frame */
struct efct_hw_io *send_frame_io;
/* Stats */
u32 use_count;
u32 wq_pending_count;
};
struct hw_rq {
struct list_head list_entry;
enum sli4_qtype type;
u32 instance;
u32 entry_count;
u32 use_count;
u32 hdr_entry_size;
u32 first_burst_entry_size;
u32 data_entry_size;
bool is_mrq;
u32 base_mrq_id;
struct hw_cq *cq;
u8 filter_mask;
struct sli4_queue *hdr;
struct sli4_queue *first_burst;
struct sli4_queue *data;
struct efc_hw_rq_buffer *hdr_buf;
struct efc_hw_rq_buffer *fb_buf;
struct efc_hw_rq_buffer *payload_buf;
/* RQ tracker for this RQ */
struct efc_hw_sequence **rq_tracker;
};
struct efct_hw_send_frame_context {
struct efct_hw *hw;
struct hw_wq_callback *wqcb;
struct efct_hw_wqe wqe;
void (*callback)(int status, void *arg);
void *arg;
/* General purpose elements */
struct efc_hw_sequence *seq;
struct efc_dma payload;
};
struct efct_hw_grp_hdr {
u32 size;
__be32 magic_number;
u32 word2;
u8 rev_name[128];
u8 date[12];
u8 revision[32];
};
#endif /* __EFCT_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment