#ifndef _SYS_IB_ADAPTERS_HERMON_FM_H
#define _SYS_IB_ADAPTERS_HERMON_FM_H
#include <sys/ddifm.h>
#include <sys/fm/protocol.h>
#include <sys/fm/util.h>
#include <sys/fm/io/ddi.h>
#ifdef __cplusplus
extern "C" {
#endif
struct i_hca_fm {
uint32_t ref_cnt;
kmutex_t lock;
struct i_hca_acc_handle *hdl;
struct kmem_cache *fm_acc_cache;
};
struct i_hca_acc_handle {
struct i_hca_acc_handle *next;
ddi_acc_handle_t save_hdl;
kmutex_t lock;
uint32_t thread_cnt;
};
_NOTE(SCHEME_PROTECTS_DATA("safe sharing", i_hca_acc_handle::save_hdl))
#define fm_acc_hdl(hdl) (((struct i_hca_acc_handle *)(hdl))->save_hdl)
#define FM_POLL_INTERVAL (10000000)
struct i_hca_fm_test {
int num;
int type;
#define HCA_TEST_PIO 0x1
#define HCA_TEST_IBA 0x2
int trigger;
#define HCA_TEST_TRANSIENT 0x0001
#define HCA_TEST_PERSISTENT 0x0002
#define HCA_TEST_ATTACH 0x0010
#define HCA_TEST_START 0x0100
#define HCA_TEST_END 0x0200
void (*pio_injection)(struct i_hca_fm_test *, ddi_fm_error_t *);
int errcnt;
int line_num;
char *file_name;
char *hash_key;
void *private;
};
typedef struct i_hca_fm hermon_hca_fm_t;
typedef struct i_hca_acc_handle hermon_acc_handle_t;
typedef struct i_hca_fm_test hermon_test_t;
#define HERMON_FMANOTE(state, string) \
cmn_err(CE_WARN, "hermon%d: Device Error: %s", \
(state)->hs_instance, string)
#define HERMON_FMA_LOCLEN "CQE local length error"
#define HERMON_FMA_LOCQPOP "CQE local qp operation error"
#define HERMON_FMA_LOCPROT "CQE local protection error"
#define HERMON_FMA_WQFLUSH "CQE wqe flushed in error"
#define HERMON_FMA_MWBIND "CQE memory window bind error"
#define HERMON_FMA_RESP "CQE bad response"
#define HERMON_FMA_LOCACC "CQE local access error"
#define HERMON_FMA_REMREQ "CQE remote invalid request error"
#define HERMON_FMA_REMACC "CQE remote access error"
#define HERMON_FMA_REMOP "CQE remote operation error"
#define HERMON_FMA_XPORTCNT "CQE transport retry counter exceeded"
#define HERMON_FMA_RNRCNT "CQE RNR retry counter exceeded"
#define HERMON_FMA_REMABRT "CQE remote aborted error"
#define HERMON_FMA_UNKN "CQE unknown/reserved error returned"
#define HERMON_FMA_OVERRUN "EQE cq overrun or protection error"
#define HERMON_FMA_LOCCAT "EQE local work queue catastrophic error"
#define HERMON_FMA_QPCAT "EQE local queue pair catastrophic error"
#define HERMON_FMA_PATHMIG "EQE path migration failed"
#define HERMON_FMA_LOCINV "EQE invalid request - local work queue"
#define HERMON_FMA_LOCACEQ "EQE local access violation"
#define HERMON_FMA_SRQCAT "EQE shared received queue catastrophic"
#define HERMON_FMA_INTERNAL "EQE hca internal error"
#define HERMON_FMA_HCRINT "HCR internal error processing command"
#define HERMON_FMA_NVMEM "HCR NVRAM checksum/CRC failure"
#define HERMON_FMA_TOTOG "HCR Timeout waiting for command toggle"
#define HERMON_FMA_GOBIT "HCR Timeout waiting for command go bit"
#define HERMON_FMA_RSRC "HCR Command insufficient resources"
#define HERMON_FMA_CMDINV "HCR Command invalid status returned"
#define HERMON_FMA_FWVER "HCA firmware not at minimum version"
#define HERMON_FMA_PCIID "HCA PCIe devid not supported"
#define HERMON_FMA_MAINT "HCA device set to memory controller mode"
#define HERMON_FMA_BADNVMEM "HCR bad NVMEM error"
#define HCA_NO_FM 0x0000
#define HCA_PIO_FM 0x0001
#define HCA_DMA_FM 0x0002
#define HCA_EREPORT_FM 0x0004
#define HCA_ERRCB_FM 0x0010
#define HCA_ATTCH_FM 0x0100
#define HCA_RUNTM_FM 0x0200
#define HCA_SYS_ERR 0x001
#define HCA_IBA_ERR 0x002
#define HCA_ERR_TRANSIENT 0x010
#define HCA_ERR_NON_FATAL 0x020
#define HCA_ERR_SRV_LOST 0x040
#define HCA_ERR_DEGRADED 0x080
#define HCA_ERR_FATAL 0x100
#define HCA_ERR_IOCTL 0x200
#define HCA_SKIP_HW_CHK (-1)
#define HCA_PIO_OK (0)
#define HCA_PIO_TRANSIENT (1)
#define HCA_PIO_PERSISTENT (2)
#define HCA_PIO_RETRY_CNT (3)
#define HCA_FW_MISC 0x1
#define HCA_FW_CORRUPT 0x2
#define HCA_FW_MISMATCH 0x3
#ifdef FMA_TEST
#define TEST_DECLARE(tst) hermon_test_t *tst;
#define REGISTER_PIO_TEST(st, tst) \
tst = hermon_test_register(st, __FILE__, __LINE__, HCA_TEST_PIO)
#define PIO_START(st, hdl, tst) hermon_PIO_start(st, hdl, tst)
#define PIO_END(st, hdl, cnt, tst) hermon_PIO_end(st, hdl, &cnt, tst)
#else
#define TEST_DECLARE(tst)
#define REGISTER_PIO_TEST(st, tst)
#define PIO_START(st, hdl, tst) hermon_PIO_start(st, hdl, NULL)
#define PIO_END(st, hdl, cnt, tst) hermon_PIO_end(st, hdl, &cnt, NULL)
#endif
#define hermon_pio_init(cnt, status, tst) \
TEST_DECLARE(tst) \
int status = HCA_PIO_OK; \
int cnt = HCA_PIO_RETRY_CNT
#define hermon_pio_start(st, hdl, label, cnt, status, tst) \
if (st->hs_fm_state & HCA_PIO_FM) { \
if (st->hs_fm_async_fatal) { \
hermon_fm_ereport(st, HCA_SYS_ERR, \
HCA_ERR_NON_FATAL); \
goto label; \
} else { \
REGISTER_PIO_TEST(st, tst); \
cnt = HCA_PIO_RETRY_CNT; \
if (PIO_START(st, hdl, tst) == \
HCA_PIO_PERSISTENT) { \
goto label; \
} \
} \
} else { \
status = HCA_SKIP_HW_CHK; \
} \
do {
#define hermon_pio_end(st, hdl, label, cnt, status, tst) \
if (status != HCA_SKIP_HW_CHK) { \
if (st->hs_fm_async_fatal) { \
hermon_fm_ereport(st, HCA_SYS_ERR, \
HCA_ERR_NON_FATAL); \
goto label; \
} \
if ((status = PIO_END(st, hdl, cnt, tst)) == \
HCA_PIO_PERSISTENT) { \
goto label; \
} else if (status == HCA_PIO_TRANSIENT) { \
hermon_fm_ereport(st, HCA_SYS_ERR, \
HCA_ERR_TRANSIENT); \
} \
} \
} while (status == HCA_PIO_TRANSIENT)
extern void hermon_fm_init(hermon_state_t *);
extern void hermon_fm_fini(hermon_state_t *);
extern int hermon_fm_ereport_init(hermon_state_t *);
extern void hermon_fm_ereport_fini(hermon_state_t *);
extern int hermon_get_state(hermon_state_t *);
extern boolean_t hermon_init_failure(hermon_state_t *);
extern boolean_t hermon_cmd_retry_ok(hermon_cmd_post_t *, int);
extern void hermon_fm_ereport(hermon_state_t *, int, int);
extern int hermon_regs_map_setup(hermon_state_t *, uint_t, caddr_t *, offset_t,
offset_t, ddi_device_acc_attr_t *, ddi_acc_handle_t *);
extern void hermon_regs_map_free(hermon_state_t *, ddi_acc_handle_t *);
extern int hermon_pci_config_setup(hermon_state_t *, ddi_acc_handle_t *);
extern void hermon_pci_config_teardown(hermon_state_t *, ddi_acc_handle_t *);
extern ushort_t hermon_devacc_attr_version(hermon_state_t *);
extern uchar_t hermon_devacc_attr_access(hermon_state_t *);
extern int hermon_PIO_start(hermon_state_t *, ddi_acc_handle_t,
hermon_test_t *);
extern int hermon_PIO_end(hermon_state_t *, ddi_acc_handle_t, int *,
hermon_test_t *);
extern ddi_acc_handle_t hermon_rsrc_alloc_uarhdl(hermon_state_t *);
extern ddi_acc_handle_t hermon_get_uarhdl(hermon_state_t *);
extern ddi_acc_handle_t hermon_get_cmdhdl(hermon_state_t *);
extern ddi_acc_handle_t hermon_get_msix_tblhdl(hermon_state_t *);
extern ddi_acc_handle_t hermon_get_msix_pbahdl(hermon_state_t *);
extern ddi_acc_handle_t hermon_get_pcihdl(hermon_state_t *);
extern void hermon_clr_state_nolock(hermon_state_t *, int);
extern void hermon_inter_err_chk(void *);
#ifdef FMA_TEST
extern hermon_test_t *hermon_test_register(hermon_state_t *, char *, int, int);
extern void hermon_test_deregister(void);
extern int hermon_test_num;
#endif
#ifdef __cplusplus
}
#endif
#endif