319 lines
8.9 KiB
C
319 lines
8.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright(c) 2023 Advanced Micro Devices, Inc */
|
|
|
|
#ifndef _PDSC_H_
|
|
#define _PDSC_H_
|
|
|
|
#include <linux/debugfs.h>
|
|
#include <net/devlink.h>
|
|
|
|
#include <linux/pds/pds_common.h>
|
|
#include <linux/pds/pds_core_if.h>
|
|
#include <linux/pds/pds_adminq.h>
|
|
#include <linux/pds/pds_intr.h>
|
|
|
|
#define PDSC_DRV_DESCRIPTION "AMD/Pensando Core Driver"
|
|
|
|
#define PDSC_WATCHDOG_SECS 5
|
|
#define PDSC_QUEUE_NAME_MAX_SZ 16
|
|
#define PDSC_ADMINQ_MIN_LENGTH 16 /* must be a power of two */
|
|
#define PDSC_NOTIFYQ_LENGTH 64 /* must be a power of two */
|
|
#define PDSC_TEARDOWN_RECOVERY false
|
|
#define PDSC_TEARDOWN_REMOVING true
|
|
#define PDSC_SETUP_RECOVERY false
|
|
#define PDSC_SETUP_INIT true
|
|
|
|
struct pdsc_dev_bar {
|
|
void __iomem *vaddr;
|
|
phys_addr_t bus_addr;
|
|
unsigned long len;
|
|
int res_index;
|
|
};
|
|
|
|
struct pdsc;
|
|
|
|
struct pdsc_vf {
|
|
struct pds_auxiliary_dev *padev;
|
|
struct pdsc *vf;
|
|
u16 index;
|
|
__le16 vif_types[PDS_DEV_TYPE_MAX];
|
|
};
|
|
|
|
struct pdsc_devinfo {
|
|
u8 asic_type;
|
|
u8 asic_rev;
|
|
char fw_version[PDS_CORE_DEVINFO_FWVERS_BUFLEN + 1];
|
|
char serial_num[PDS_CORE_DEVINFO_SERIAL_BUFLEN + 1];
|
|
};
|
|
|
|
struct pdsc_queue {
|
|
struct pdsc_q_info *info;
|
|
u64 dbval;
|
|
u16 head_idx;
|
|
u16 tail_idx;
|
|
u8 hw_type;
|
|
unsigned int index;
|
|
unsigned int num_descs;
|
|
u64 dbell_count;
|
|
u64 features;
|
|
unsigned int type;
|
|
unsigned int hw_index;
|
|
union {
|
|
void *base;
|
|
struct pds_core_admin_cmd *adminq;
|
|
};
|
|
dma_addr_t base_pa; /* must be page aligned */
|
|
unsigned int desc_size;
|
|
unsigned int pid;
|
|
char name[PDSC_QUEUE_NAME_MAX_SZ];
|
|
};
|
|
|
|
#define PDSC_INTR_NAME_MAX_SZ 32
|
|
|
|
struct pdsc_intr_info {
|
|
char name[PDSC_INTR_NAME_MAX_SZ];
|
|
unsigned int index;
|
|
unsigned int vector;
|
|
void *data;
|
|
};
|
|
|
|
struct pdsc_cq_info {
|
|
void *comp;
|
|
};
|
|
|
|
struct pdsc_buf_info {
|
|
struct page *page;
|
|
dma_addr_t dma_addr;
|
|
u32 page_offset;
|
|
u32 len;
|
|
};
|
|
|
|
struct pdsc_q_info {
|
|
union {
|
|
void *desc;
|
|
struct pdsc_admin_cmd *adminq_desc;
|
|
};
|
|
unsigned int bytes;
|
|
unsigned int nbufs;
|
|
struct pdsc_buf_info bufs[PDS_CORE_MAX_FRAGS];
|
|
struct pdsc_wait_context *wc;
|
|
void *dest;
|
|
};
|
|
|
|
struct pdsc_cq {
|
|
struct pdsc_cq_info *info;
|
|
struct pdsc_queue *bound_q;
|
|
struct pdsc_intr_info *bound_intr;
|
|
u16 tail_idx;
|
|
bool done_color;
|
|
unsigned int num_descs;
|
|
unsigned int desc_size;
|
|
void *base;
|
|
dma_addr_t base_pa; /* must be page aligned */
|
|
} ____cacheline_aligned_in_smp;
|
|
|
|
struct pdsc_qcq {
|
|
struct pdsc *pdsc;
|
|
void *q_base;
|
|
dma_addr_t q_base_pa; /* might not be page aligned */
|
|
void *cq_base;
|
|
dma_addr_t cq_base_pa; /* might not be page aligned */
|
|
u32 q_size;
|
|
u32 cq_size;
|
|
bool armed;
|
|
unsigned int flags;
|
|
|
|
struct work_struct work;
|
|
struct pdsc_queue q;
|
|
struct pdsc_cq cq;
|
|
int intx;
|
|
|
|
u32 accum_work;
|
|
struct dentry *dentry;
|
|
};
|
|
|
|
struct pdsc_viftype {
|
|
char *name;
|
|
bool supported;
|
|
bool enabled;
|
|
int dl_id;
|
|
int vif_id;
|
|
struct pds_auxiliary_dev *padev;
|
|
};
|
|
|
|
/* No state flags set means we are in a steady running state */
|
|
enum pdsc_state_flags {
|
|
PDSC_S_FW_DEAD, /* stopped, wait on startup or recovery */
|
|
PDSC_S_INITING_DRIVER, /* initial startup from probe */
|
|
PDSC_S_STOPPING_DRIVER, /* driver remove */
|
|
|
|
/* leave this as last */
|
|
PDSC_S_STATE_SIZE
|
|
};
|
|
|
|
struct pdsc {
|
|
struct pci_dev *pdev;
|
|
struct dentry *dentry;
|
|
struct device *dev;
|
|
struct pdsc_dev_bar bars[PDS_CORE_BARS_MAX];
|
|
struct pdsc_vf *vfs;
|
|
int num_vfs;
|
|
int vf_id;
|
|
int hw_index;
|
|
int uid;
|
|
|
|
unsigned long state;
|
|
u8 fw_status;
|
|
u8 fw_generation;
|
|
unsigned long last_fw_time;
|
|
u32 last_hb;
|
|
struct timer_list wdtimer;
|
|
unsigned int wdtimer_period;
|
|
struct work_struct health_work;
|
|
struct devlink_health_reporter *fw_reporter;
|
|
u32 fw_recoveries;
|
|
|
|
struct pdsc_devinfo dev_info;
|
|
struct pds_core_dev_identity dev_ident;
|
|
unsigned int nintrs;
|
|
struct pdsc_intr_info *intr_info; /* array of nintrs elements */
|
|
|
|
struct workqueue_struct *wq;
|
|
|
|
unsigned int devcmd_timeout;
|
|
struct mutex devcmd_lock; /* lock for dev_cmd operations */
|
|
struct mutex config_lock; /* lock for configuration operations */
|
|
spinlock_t adminq_lock; /* lock for adminq operations */
|
|
refcount_t adminq_refcnt;
|
|
struct pds_core_dev_info_regs __iomem *info_regs;
|
|
struct pds_core_dev_cmd_regs __iomem *cmd_regs;
|
|
struct pds_core_intr __iomem *intr_ctrl;
|
|
u64 __iomem *intr_status;
|
|
u64 __iomem *db_pages;
|
|
dma_addr_t phy_db_pages;
|
|
u64 __iomem *kern_dbpage;
|
|
|
|
struct pdsc_qcq adminqcq;
|
|
struct pdsc_qcq notifyqcq;
|
|
u64 last_eid;
|
|
struct pdsc_viftype *viftype_status;
|
|
struct work_struct pci_reset_work;
|
|
};
|
|
|
|
/** enum pds_core_dbell_bits - bitwise composition of dbell values.
|
|
*
|
|
* @PDS_CORE_DBELL_QID_MASK: unshifted mask of valid queue id bits.
|
|
* @PDS_CORE_DBELL_QID_SHIFT: queue id shift amount in dbell value.
|
|
* @PDS_CORE_DBELL_QID: macro to build QID component of dbell value.
|
|
*
|
|
* @PDS_CORE_DBELL_RING_MASK: unshifted mask of valid ring bits.
|
|
* @PDS_CORE_DBELL_RING_SHIFT: ring shift amount in dbell value.
|
|
* @PDS_CORE_DBELL_RING: macro to build ring component of dbell value.
|
|
*
|
|
* @PDS_CORE_DBELL_RING_0: ring zero dbell component value.
|
|
* @PDS_CORE_DBELL_RING_1: ring one dbell component value.
|
|
* @PDS_CORE_DBELL_RING_2: ring two dbell component value.
|
|
* @PDS_CORE_DBELL_RING_3: ring three dbell component value.
|
|
*
|
|
* @PDS_CORE_DBELL_INDEX_MASK: bit mask of valid index bits, no shift needed.
|
|
*/
|
|
enum pds_core_dbell_bits {
|
|
PDS_CORE_DBELL_QID_MASK = 0xffffff,
|
|
PDS_CORE_DBELL_QID_SHIFT = 24,
|
|
|
|
#define PDS_CORE_DBELL_QID(n) \
|
|
(((u64)(n) & PDS_CORE_DBELL_QID_MASK) << PDS_CORE_DBELL_QID_SHIFT)
|
|
|
|
PDS_CORE_DBELL_RING_MASK = 0x7,
|
|
PDS_CORE_DBELL_RING_SHIFT = 16,
|
|
|
|
#define PDS_CORE_DBELL_RING(n) \
|
|
(((u64)(n) & PDS_CORE_DBELL_RING_MASK) << PDS_CORE_DBELL_RING_SHIFT)
|
|
|
|
PDS_CORE_DBELL_RING_0 = 0,
|
|
PDS_CORE_DBELL_RING_1 = PDS_CORE_DBELL_RING(1),
|
|
PDS_CORE_DBELL_RING_2 = PDS_CORE_DBELL_RING(2),
|
|
PDS_CORE_DBELL_RING_3 = PDS_CORE_DBELL_RING(3),
|
|
|
|
PDS_CORE_DBELL_INDEX_MASK = 0xffff,
|
|
};
|
|
|
|
static inline void pds_core_dbell_ring(u64 __iomem *db_page,
|
|
enum pds_core_logical_qtype qtype,
|
|
u64 val)
|
|
{
|
|
writeq(val, &db_page[qtype]);
|
|
}
|
|
|
|
int pdsc_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
|
|
struct devlink_fmsg *fmsg,
|
|
struct netlink_ext_ack *extack);
|
|
int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
|
|
struct netlink_ext_ack *extack);
|
|
int pdsc_dl_flash_update(struct devlink *dl,
|
|
struct devlink_flash_update_params *params,
|
|
struct netlink_ext_ack *extack);
|
|
int pdsc_dl_enable_get(struct devlink *dl, u32 id,
|
|
struct devlink_param_gset_ctx *ctx);
|
|
int pdsc_dl_enable_set(struct devlink *dl, u32 id,
|
|
struct devlink_param_gset_ctx *ctx);
|
|
int pdsc_dl_enable_validate(struct devlink *dl, u32 id,
|
|
union devlink_param_value val,
|
|
struct netlink_ext_ack *extack);
|
|
|
|
void __iomem *pdsc_map_dbpage(struct pdsc *pdsc, int page_num);
|
|
|
|
void pdsc_debugfs_create(void);
|
|
void pdsc_debugfs_destroy(void);
|
|
void pdsc_debugfs_add_dev(struct pdsc *pdsc);
|
|
void pdsc_debugfs_del_dev(struct pdsc *pdsc);
|
|
void pdsc_debugfs_add_ident(struct pdsc *pdsc);
|
|
void pdsc_debugfs_add_viftype(struct pdsc *pdsc);
|
|
void pdsc_debugfs_add_irqs(struct pdsc *pdsc);
|
|
void pdsc_debugfs_add_qcq(struct pdsc *pdsc, struct pdsc_qcq *qcq);
|
|
void pdsc_debugfs_del_qcq(struct pdsc_qcq *qcq);
|
|
|
|
int pdsc_err_to_errno(enum pds_core_status_code code);
|
|
bool pdsc_is_fw_running(struct pdsc *pdsc);
|
|
bool pdsc_is_fw_good(struct pdsc *pdsc);
|
|
int pdsc_devcmd(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
|
|
union pds_core_dev_comp *comp, int max_seconds);
|
|
int pdsc_devcmd_locked(struct pdsc *pdsc, union pds_core_dev_cmd *cmd,
|
|
union pds_core_dev_comp *comp, int max_seconds);
|
|
int pdsc_devcmd_init(struct pdsc *pdsc);
|
|
int pdsc_devcmd_reset(struct pdsc *pdsc);
|
|
int pdsc_dev_init(struct pdsc *pdsc);
|
|
|
|
int pdsc_intr_alloc(struct pdsc *pdsc, char *name,
|
|
irq_handler_t handler, void *data);
|
|
void pdsc_intr_free(struct pdsc *pdsc, int index);
|
|
void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq);
|
|
int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
|
|
const char *name, unsigned int flags, unsigned int num_descs,
|
|
unsigned int desc_size, unsigned int cq_desc_size,
|
|
unsigned int pid, struct pdsc_qcq *qcq);
|
|
int pdsc_setup(struct pdsc *pdsc, bool init);
|
|
void pdsc_teardown(struct pdsc *pdsc, bool removing);
|
|
int pdsc_start(struct pdsc *pdsc);
|
|
void pdsc_stop(struct pdsc *pdsc);
|
|
void pdsc_health_thread(struct work_struct *work);
|
|
|
|
int pdsc_register_notify(struct notifier_block *nb);
|
|
void pdsc_unregister_notify(struct notifier_block *nb);
|
|
void pdsc_notify(unsigned long event, void *data);
|
|
int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf);
|
|
int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf);
|
|
|
|
void pdsc_process_adminq(struct pdsc_qcq *qcq);
|
|
void pdsc_work_thread(struct work_struct *work);
|
|
irqreturn_t pdsc_adminq_isr(int irq, void *data);
|
|
|
|
int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw,
|
|
struct netlink_ext_ack *extack);
|
|
|
|
void pdsc_fw_down(struct pdsc *pdsc);
|
|
void pdsc_fw_up(struct pdsc *pdsc);
|
|
void pdsc_pci_reset_thread(struct work_struct *work);
|
|
|
|
#endif /* _PDSC_H_ */
|