#ifndef _EFCT_HW_H
#define _EFCT_HW_H
#include "../libefc_sli/sli4.h"
#define EFCT_VENDOR_ID 0x10df
#define EFCT_DEVICE_LANCER_G6 0xe307
#define EFCT_DEVICE_LANCER_G7 0xf407
#define EFCT_HW_RQ_ENTRIES_MIN 512
#define EFCT_HW_RQ_ENTRIES_DEF 1024
#define EFCT_HW_RQ_ENTRIES_MAX 4096
#define EFCT_HW_RQ_SIZE_HDR 128
#define EFCT_HW_RQ_SIZE_PAYLOAD 1024
#define EFCT_HW_MAX_MRQS 8
#define EFCT_HW_WQEC_SET_COUNT 32
#define EFCT_HW_SEND_FRAME_TIMEOUT 10
#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
#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
enum efct_cmd_opts {
EFCT_CMD_POLL,
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
};
#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
struct efct_command_ctx {
struct list_head list_entry;
int (*cb)(struct efct_hw *hw, int status, u8 *mqe, void *arg);
void *arg;
u8 buf[SLI4_BMBX_SIZE];
void *ctx;
};
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;
};
enum efct_hw_wq_steering {
EFCT_HW_WQ_STEERING_CLASS,
EFCT_HW_WQ_STEERING_REQUEST,
EFCT_HW_WQ_STEERING_CPU,
};
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 int (*efct_hw_done_t)(struct efct_hw_io *, u32 len, int status,
u32 ext, void *ul_arg);
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;
int 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,
};
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;
};
struct efct_queue_hash {
bool in_use;
u16 id;
u16 index;
};
struct hw_wq_callback {
u16 instance_index;
void (*callback)(void *arg, u8 *cqe, int status);
void *arg;
struct list_head list_entry;
};
struct reqtag_pool {
spinlock_t 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;
u32 rq_default_buffer_size;
u8 esoc;
u8 rq_selection_policy;
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;
struct efct_hw_config config;
u32 num_qentries[SLI4_QTYPE_MAX];
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];
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];
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];
u32 hw_rq_count;
u32 hw_mrq_count;
struct hw_wq **wq_cpu_array;
struct efc_hw_sequence *seq_pool;
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;
struct efct_hw_io **io;
u8 *wqe_buffs;
spinlock_t io_lock;
struct list_head io_inuse;
struct list_head io_wait_free;
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;
u32 tcmd_wq_submit[EFCT_HW_MAX_NUM_WQ];
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,
};
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;
u32 wqec_set_count;
u32 wqec_count;
u32 free_count;
u32 total_submit_count;
struct list_head pending_list;
struct efct_hw_io *send_frame_io;
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;
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;
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];
};
static inline int
efct_hw_get_link_speed(struct efct_hw *hw) {
return hw->link.speed;
}
int
efct_hw_setup(struct efct_hw *hw, void *os, struct pci_dev *pdev);
int efct_hw_init(struct efct_hw *hw);
int
efct_hw_parse_filter(struct efct_hw *hw, void *value);
int
efct_hw_init_queues(struct efct_hw *hw);
int
efct_hw_map_wq_cpu(struct efct_hw *hw);
uint64_t
efct_get_wwnn(struct efct_hw *hw);
uint64_t
efct_get_wwpn(struct efct_hw *hw);
int efct_hw_rx_allocate(struct efct_hw *hw);
int efct_hw_rx_post(struct efct_hw *hw);
void efct_hw_rx_free(struct efct_hw *hw);
int
efct_hw_command(struct efct_hw *hw, u8 *cmd, u32 opts, void *cb,
void *arg);
int
efct_issue_mbox_rqst(void *base, void *cmd, void *cb, void *arg);
struct efct_hw_io *efct_hw_io_alloc(struct efct_hw *hw);
int efct_hw_io_free(struct efct_hw *hw, struct efct_hw_io *io);
u8 efct_hw_io_inuse(struct efct_hw *hw, struct efct_hw_io *io);
int
efct_hw_io_send(struct efct_hw *hw, enum efct_hw_io_type type,
struct efct_hw_io *io, union efct_hw_io_param_u *iparam,
void *cb, void *arg);
int
efct_hw_io_register_sgl(struct efct_hw *hw, struct efct_hw_io *io,
struct efc_dma *sgl,
u32 sgl_count);
int
efct_hw_io_init_sges(struct efct_hw *hw,
struct efct_hw_io *io, enum efct_hw_io_type type);
int
efct_hw_io_add_sge(struct efct_hw *hw, struct efct_hw_io *io,
uintptr_t addr, u32 length);
int
efct_hw_io_abort(struct efct_hw *hw, struct efct_hw_io *io_to_abort,
bool send_abts, void *cb, void *arg);
u32
efct_hw_io_get_count(struct efct_hw *hw,
enum efct_hw_io_count_type io_count_type);
struct efct_hw_io
*efct_hw_io_lookup(struct efct_hw *hw, u32 indicator);
void efct_hw_io_abort_all(struct efct_hw *hw);
void efct_hw_io_free_internal(struct kref *arg);
struct reqtag_pool *efct_hw_reqtag_pool_alloc(struct efct_hw *hw);
void efct_hw_reqtag_pool_free(struct efct_hw *hw);
struct hw_wq_callback
*efct_hw_reqtag_alloc(struct efct_hw *hw,
void (*callback)(void *arg, u8 *cqe,
int status), void *arg);
void
efct_hw_reqtag_free(struct efct_hw *hw, struct hw_wq_callback *wqcb);
struct hw_wq_callback
*efct_hw_reqtag_get_instance(struct efct_hw *hw, u32 instance_index);
int
efct_hw_rqpair_process_rq(struct efct_hw *hw,
struct hw_cq *cq, u8 *cqe);
int
efct_hw_rqpair_sequence_free(struct efct_hw *hw, struct efc_hw_sequence *seq);
static inline void
efct_hw_sequence_copy(struct efc_hw_sequence *dst,
struct efc_hw_sequence *src)
{
*dst = *src;
}
int
efct_efc_hw_sequence_free(struct efc *efc, struct efc_hw_sequence *seq);
static inline int
efct_hw_sequence_free(struct efct_hw *hw, struct efc_hw_sequence *seq)
{
return efct_hw_rqpair_sequence_free(hw, seq);
}
int
efct_hw_eq_process(struct efct_hw *hw, struct hw_eq *eq,
u32 max_isr_time_msec);
void efct_hw_cq_process(struct efct_hw *hw, struct hw_cq *cq);
void
efct_hw_wq_process(struct efct_hw *hw, struct hw_cq *cq,
u8 *cqe, int status, u16 rid);
void
efct_hw_xabt_process(struct efct_hw *hw, struct hw_cq *cq,
u8 *cqe, u16 rid);
int
efct_hw_process(struct efct_hw *hw, u32 vector, u32 max_isr_time_msec);
int
efct_hw_queue_hash_find(struct efct_queue_hash *hash, u16 id);
int efct_hw_wq_write(struct hw_wq *wq, struct efct_hw_wqe *wqe);
int
efct_hw_send_frame(struct efct_hw *hw, struct fc_frame_header *hdr,
u8 sof, u8 eof, struct efc_dma *payload,
struct efct_hw_send_frame_context *ctx,
void (*callback)(void *arg, u8 *cqe, int status),
void *arg);
int
efct_els_hw_srrs_send(struct efc *efc, struct efc_disc_io *io);
int
efct_efc_bls_send(struct efc *efc, u32 type, struct sli_bls_params *bls);
int
efct_hw_bls_send(struct efct *efct, u32 type, struct sli_bls_params *bls_params,
void *cb, void *arg);
int
efct_hw_get_link_stats(struct efct_hw *hw,
u8 req_ext_counters,
u8 clear_overflow_flags,
u8 clear_all_counters,
void (*efct_hw_link_stat_cb_t)(int status,
u32 num_counters,
struct efct_hw_link_stat_counts *counters, void *arg),
void *arg);
int
efct_hw_get_host_stats(struct efct_hw *hw,
u8 cc,
void (*efct_hw_host_stat_cb_t)(int status,
u32 num_counters,
struct efct_hw_host_stat_counts *counters, void *arg),
void *arg);
int
efct_hw_firmware_write(struct efct_hw *hw, struct efc_dma *dma,
u32 size, u32 offset, int last,
void (*cb)(int status, u32 bytes_written,
u32 change_status, void *arg),
void *arg);
typedef void (*efct_hw_async_cb_t)(struct efct_hw *hw, int status,
u8 *mqe, void *arg);
int
efct_hw_async_call(struct efct_hw *hw, efct_hw_async_cb_t callback, void *arg);
struct hw_eq *efct_hw_new_eq(struct efct_hw *hw, u32 entry_count);
struct hw_cq *efct_hw_new_cq(struct hw_eq *eq, u32 entry_count);
u32
efct_hw_new_cq_set(struct hw_eq *eqs[], struct hw_cq *cqs[],
u32 num_cqs, u32 entry_count);
struct hw_mq *efct_hw_new_mq(struct hw_cq *cq, u32 entry_count);
struct hw_wq
*efct_hw_new_wq(struct hw_cq *cq, u32 entry_count);
u32
efct_hw_new_rq_set(struct hw_cq *cqs[], struct hw_rq *rqs[],
u32 num_rq_pairs, u32 entry_count);
void efct_hw_del_eq(struct hw_eq *eq);
void efct_hw_del_cq(struct hw_cq *cq);
void efct_hw_del_mq(struct hw_mq *mq);
void efct_hw_del_wq(struct hw_wq *wq);
void efct_hw_del_rq(struct hw_rq *rq);
void efct_hw_queue_teardown(struct efct_hw *hw);
void efct_hw_teardown(struct efct_hw *hw);
int
efct_hw_reset(struct efct_hw *hw, enum efct_hw_reset reset);
int
efct_hw_port_control(struct efct_hw *hw, enum efct_hw_port ctrl,
uintptr_t value,
void (*cb)(int status, uintptr_t value, void *arg),
void *arg);
#endif /* __EFCT_H__ */