forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
419 lines
11 KiB
419 lines
11 KiB
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|
/* |
|
* Filename: rsxx_priv.h |
|
* |
|
* Authors: Joshua Morris <[email protected]> |
|
* Philip Kelleher <[email protected]> |
|
* |
|
* (C) Copyright 2013 IBM Corporation |
|
*/ |
|
|
|
#ifndef __RSXX_PRIV_H__ |
|
#define __RSXX_PRIV_H__ |
|
|
|
#include <linux/semaphore.h> |
|
|
|
#include <linux/fs.h> |
|
#include <linux/interrupt.h> |
|
#include <linux/mutex.h> |
|
#include <linux/pci.h> |
|
#include <linux/spinlock.h> |
|
#include <linux/sysfs.h> |
|
#include <linux/workqueue.h> |
|
#include <linux/bio.h> |
|
#include <linux/vmalloc.h> |
|
#include <linux/timer.h> |
|
#include <linux/ioctl.h> |
|
#include <linux/delay.h> |
|
|
|
#include "rsxx.h" |
|
#include "rsxx_cfg.h" |
|
|
|
struct proc_cmd; |
|
|
|
#define PCI_DEVICE_ID_FS70_FLASH 0x04A9 |
|
#define PCI_DEVICE_ID_FS80_FLASH 0x04AA |
|
|
|
#define RS70_PCI_REV_SUPPORTED 4 |
|
|
|
#define DRIVER_NAME "rsxx" |
|
#define DRIVER_VERSION "4.0.3.2516" |
|
|
|
/* Block size is 4096 */ |
|
#define RSXX_HW_BLK_SHIFT 12 |
|
#define RSXX_HW_BLK_SIZE (1 << RSXX_HW_BLK_SHIFT) |
|
#define RSXX_HW_BLK_MASK (RSXX_HW_BLK_SIZE - 1) |
|
|
|
#define MAX_CREG_DATA8 32 |
|
#define LOG_BUF_SIZE8 128 |
|
|
|
#define RSXX_MAX_OUTSTANDING_CMDS 255 |
|
#define RSXX_CS_IDX_MASK 0xff |
|
|
|
#define STATUS_BUFFER_SIZE8 4096 |
|
#define COMMAND_BUFFER_SIZE8 4096 |
|
|
|
#define RSXX_MAX_TARGETS 8 |
|
|
|
struct dma_tracker_list; |
|
|
|
/* DMA Command/Status Buffer structure */ |
|
struct rsxx_cs_buffer { |
|
dma_addr_t dma_addr; |
|
void *buf; |
|
u32 idx; |
|
}; |
|
|
|
struct rsxx_dma_stats { |
|
u32 crc_errors; |
|
u32 hard_errors; |
|
u32 soft_errors; |
|
u32 writes_issued; |
|
u32 writes_failed; |
|
u32 reads_issued; |
|
u32 reads_failed; |
|
u32 reads_retried; |
|
u32 discards_issued; |
|
u32 discards_failed; |
|
u32 done_rescheduled; |
|
u32 issue_rescheduled; |
|
u32 dma_sw_err; |
|
u32 dma_hw_fault; |
|
u32 dma_cancelled; |
|
u32 sw_q_depth; /* Number of DMAs on the SW queue. */ |
|
atomic_t hw_q_depth; /* Number of DMAs queued to HW. */ |
|
}; |
|
|
|
struct rsxx_dma_ctrl { |
|
struct rsxx_cardinfo *card; |
|
int id; |
|
void __iomem *regmap; |
|
struct rsxx_cs_buffer status; |
|
struct rsxx_cs_buffer cmd; |
|
u16 e_cnt; |
|
spinlock_t queue_lock; |
|
struct list_head queue; |
|
struct workqueue_struct *issue_wq; |
|
struct work_struct issue_dma_work; |
|
struct workqueue_struct *done_wq; |
|
struct work_struct dma_done_work; |
|
struct timer_list activity_timer; |
|
struct dma_tracker_list *trackers; |
|
struct rsxx_dma_stats stats; |
|
struct mutex work_lock; |
|
}; |
|
|
|
struct rsxx_cardinfo { |
|
struct pci_dev *dev; |
|
unsigned int halt; |
|
unsigned int eeh_state; |
|
|
|
void __iomem *regmap; |
|
spinlock_t irq_lock; |
|
unsigned int isr_mask; |
|
unsigned int ier_mask; |
|
|
|
struct rsxx_card_cfg config; |
|
int config_valid; |
|
|
|
/* Embedded CPU Communication */ |
|
struct { |
|
spinlock_t lock; |
|
bool active; |
|
struct creg_cmd *active_cmd; |
|
struct workqueue_struct *creg_wq; |
|
struct work_struct done_work; |
|
struct list_head queue; |
|
unsigned int q_depth; |
|
/* Cache the creg status to prevent ioreads */ |
|
struct { |
|
u32 stat; |
|
u32 failed_cancel_timer; |
|
u32 creg_timeout; |
|
} creg_stats; |
|
struct timer_list cmd_timer; |
|
struct mutex reset_lock; |
|
int reset; |
|
} creg_ctrl; |
|
|
|
struct { |
|
char tmp[MAX_CREG_DATA8]; |
|
char buf[LOG_BUF_SIZE8]; /* terminated */ |
|
int buf_len; |
|
} log; |
|
|
|
struct workqueue_struct *event_wq; |
|
struct work_struct event_work; |
|
unsigned int state; |
|
u64 size8; |
|
|
|
/* Lock the device attach/detach function */ |
|
struct mutex dev_lock; |
|
|
|
/* Block Device Variables */ |
|
bool bdev_attached; |
|
int disk_id; |
|
int major; |
|
struct request_queue *queue; |
|
struct gendisk *gendisk; |
|
struct { |
|
/* Used to convert a byte address to a device address. */ |
|
u64 lower_mask; |
|
u64 upper_shift; |
|
u64 upper_mask; |
|
u64 target_mask; |
|
u64 target_shift; |
|
} _stripe; |
|
unsigned int dma_fault; |
|
|
|
int scrub_hard; |
|
|
|
int n_targets; |
|
struct rsxx_dma_ctrl *ctrl; |
|
|
|
struct dentry *debugfs_dir; |
|
}; |
|
|
|
enum rsxx_pci_regmap { |
|
HWID = 0x00, /* Hardware Identification Register */ |
|
SCRATCH = 0x04, /* Scratch/Debug Register */ |
|
RESET = 0x08, /* Reset Register */ |
|
ISR = 0x10, /* Interrupt Status Register */ |
|
IER = 0x14, /* Interrupt Enable Register */ |
|
IPR = 0x18, /* Interrupt Poll Register */ |
|
CB_ADD_LO = 0x20, /* Command Host Buffer Address [31:0] */ |
|
CB_ADD_HI = 0x24, /* Command Host Buffer Address [63:32]*/ |
|
HW_CMD_IDX = 0x28, /* Hardware Processed Command Index */ |
|
SW_CMD_IDX = 0x2C, /* Software Processed Command Index */ |
|
SB_ADD_LO = 0x30, /* Status Host Buffer Address [31:0] */ |
|
SB_ADD_HI = 0x34, /* Status Host Buffer Address [63:32] */ |
|
HW_STATUS_CNT = 0x38, /* Hardware Status Counter */ |
|
SW_STATUS_CNT = 0x3C, /* Deprecated */ |
|
CREG_CMD = 0x40, /* CPU Command Register */ |
|
CREG_ADD = 0x44, /* CPU Address Register */ |
|
CREG_CNT = 0x48, /* CPU Count Register */ |
|
CREG_STAT = 0x4C, /* CPU Status Register */ |
|
CREG_DATA0 = 0x50, /* CPU Data Registers */ |
|
CREG_DATA1 = 0x54, |
|
CREG_DATA2 = 0x58, |
|
CREG_DATA3 = 0x5C, |
|
CREG_DATA4 = 0x60, |
|
CREG_DATA5 = 0x64, |
|
CREG_DATA6 = 0x68, |
|
CREG_DATA7 = 0x6c, |
|
INTR_COAL = 0x70, /* Interrupt Coalescing Register */ |
|
HW_ERROR = 0x74, /* Card Error Register */ |
|
PCI_DEBUG0 = 0x78, /* PCI Debug Registers */ |
|
PCI_DEBUG1 = 0x7C, |
|
PCI_DEBUG2 = 0x80, |
|
PCI_DEBUG3 = 0x84, |
|
PCI_DEBUG4 = 0x88, |
|
PCI_DEBUG5 = 0x8C, |
|
PCI_DEBUG6 = 0x90, |
|
PCI_DEBUG7 = 0x94, |
|
PCI_POWER_THROTTLE = 0x98, |
|
PERF_CTRL = 0x9c, |
|
PERF_TIMER_LO = 0xa0, |
|
PERF_TIMER_HI = 0xa4, |
|
PERF_RD512_LO = 0xa8, |
|
PERF_RD512_HI = 0xac, |
|
PERF_WR512_LO = 0xb0, |
|
PERF_WR512_HI = 0xb4, |
|
PCI_RECONFIG = 0xb8, |
|
}; |
|
|
|
enum rsxx_intr { |
|
CR_INTR_DMA0 = 0x00000001, |
|
CR_INTR_CREG = 0x00000002, |
|
CR_INTR_DMA1 = 0x00000004, |
|
CR_INTR_EVENT = 0x00000008, |
|
CR_INTR_DMA2 = 0x00000010, |
|
CR_INTR_DMA3 = 0x00000020, |
|
CR_INTR_DMA4 = 0x00000040, |
|
CR_INTR_DMA5 = 0x00000080, |
|
CR_INTR_DMA6 = 0x00000100, |
|
CR_INTR_DMA7 = 0x00000200, |
|
CR_INTR_ALL_C = 0x0000003f, |
|
CR_INTR_ALL_G = 0x000003ff, |
|
CR_INTR_DMA_ALL = 0x000003f5, |
|
CR_INTR_ALL = 0xffffffff, |
|
}; |
|
|
|
static inline int CR_INTR_DMA(int N) |
|
{ |
|
static const unsigned int _CR_INTR_DMA[] = { |
|
CR_INTR_DMA0, CR_INTR_DMA1, CR_INTR_DMA2, CR_INTR_DMA3, |
|
CR_INTR_DMA4, CR_INTR_DMA5, CR_INTR_DMA6, CR_INTR_DMA7 |
|
}; |
|
return _CR_INTR_DMA[N]; |
|
} |
|
enum rsxx_pci_reset { |
|
DMA_QUEUE_RESET = 0x00000001, |
|
}; |
|
|
|
enum rsxx_hw_fifo_flush { |
|
RSXX_FLUSH_BUSY = 0x00000002, |
|
RSXX_FLUSH_TIMEOUT = 0x00000004, |
|
}; |
|
|
|
enum rsxx_pci_revision { |
|
RSXX_DISCARD_SUPPORT = 2, |
|
RSXX_EEH_SUPPORT = 3, |
|
}; |
|
|
|
enum rsxx_creg_cmd { |
|
CREG_CMD_TAG_MASK = 0x0000FF00, |
|
CREG_OP_WRITE = 0x000000C0, |
|
CREG_OP_READ = 0x000000E0, |
|
}; |
|
|
|
enum rsxx_creg_addr { |
|
CREG_ADD_CARD_CMD = 0x80001000, |
|
CREG_ADD_CARD_STATE = 0x80001004, |
|
CREG_ADD_CARD_SIZE = 0x8000100c, |
|
CREG_ADD_CAPABILITIES = 0x80001050, |
|
CREG_ADD_LOG = 0x80002000, |
|
CREG_ADD_NUM_TARGETS = 0x80003000, |
|
CREG_ADD_CRAM = 0xA0000000, |
|
CREG_ADD_CONFIG = 0xB0000000, |
|
}; |
|
|
|
enum rsxx_creg_card_cmd { |
|
CARD_CMD_STARTUP = 1, |
|
CARD_CMD_SHUTDOWN = 2, |
|
CARD_CMD_LOW_LEVEL_FORMAT = 3, |
|
CARD_CMD_FPGA_RECONFIG_BR = 4, |
|
CARD_CMD_FPGA_RECONFIG_MAIN = 5, |
|
CARD_CMD_BACKUP = 6, |
|
CARD_CMD_RESET = 7, |
|
CARD_CMD_deprecated = 8, |
|
CARD_CMD_UNINITIALIZE = 9, |
|
CARD_CMD_DSTROY_EMERGENCY = 10, |
|
CARD_CMD_DSTROY_NORMAL = 11, |
|
CARD_CMD_DSTROY_EXTENDED = 12, |
|
CARD_CMD_DSTROY_ABORT = 13, |
|
}; |
|
|
|
enum rsxx_card_state { |
|
CARD_STATE_SHUTDOWN = 0x00000001, |
|
CARD_STATE_STARTING = 0x00000002, |
|
CARD_STATE_FORMATTING = 0x00000004, |
|
CARD_STATE_UNINITIALIZED = 0x00000008, |
|
CARD_STATE_GOOD = 0x00000010, |
|
CARD_STATE_SHUTTING_DOWN = 0x00000020, |
|
CARD_STATE_FAULT = 0x00000040, |
|
CARD_STATE_RD_ONLY_FAULT = 0x00000080, |
|
CARD_STATE_DSTROYING = 0x00000100, |
|
}; |
|
|
|
enum rsxx_led { |
|
LED_DEFAULT = 0x0, |
|
LED_IDENTIFY = 0x1, |
|
LED_SOAK = 0x2, |
|
}; |
|
|
|
enum rsxx_creg_flash_lock { |
|
CREG_FLASH_LOCK = 1, |
|
CREG_FLASH_UNLOCK = 2, |
|
}; |
|
|
|
enum rsxx_card_capabilities { |
|
CARD_CAP_SUBPAGE_WRITES = 0x00000080, |
|
}; |
|
|
|
enum rsxx_creg_stat { |
|
CREG_STAT_STATUS_MASK = 0x00000003, |
|
CREG_STAT_SUCCESS = 0x1, |
|
CREG_STAT_ERROR = 0x2, |
|
CREG_STAT_CHAR_PENDING = 0x00000004, /* Character I/O pending bit */ |
|
CREG_STAT_LOG_PENDING = 0x00000008, /* HW log message pending bit */ |
|
CREG_STAT_TAG_MASK = 0x0000ff00, |
|
}; |
|
|
|
enum rsxx_dma_finish { |
|
FREE_DMA = 0x0, |
|
COMPLETE_DMA = 0x1, |
|
}; |
|
|
|
static inline unsigned int CREG_DATA(int N) |
|
{ |
|
return CREG_DATA0 + (N << 2); |
|
} |
|
|
|
/*----------------- Convenient Log Wrappers -------------------*/ |
|
#define CARD_TO_DEV(__CARD) (&(__CARD)->dev->dev) |
|
|
|
/***** config.c *****/ |
|
int rsxx_load_config(struct rsxx_cardinfo *card); |
|
|
|
/***** core.c *****/ |
|
void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr); |
|
void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr); |
|
void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card, |
|
unsigned int intr); |
|
void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card, |
|
unsigned int intr); |
|
|
|
/***** dev.c *****/ |
|
int rsxx_attach_dev(struct rsxx_cardinfo *card); |
|
void rsxx_detach_dev(struct rsxx_cardinfo *card); |
|
int rsxx_setup_dev(struct rsxx_cardinfo *card); |
|
void rsxx_destroy_dev(struct rsxx_cardinfo *card); |
|
int rsxx_dev_init(void); |
|
void rsxx_dev_cleanup(void); |
|
|
|
/***** dma.c ****/ |
|
typedef void (*rsxx_dma_cb)(struct rsxx_cardinfo *card, |
|
void *cb_data, |
|
unsigned int status); |
|
int rsxx_dma_setup(struct rsxx_cardinfo *card); |
|
void rsxx_dma_destroy(struct rsxx_cardinfo *card); |
|
int rsxx_dma_init(void); |
|
int rsxx_cleanup_dma_queue(struct rsxx_dma_ctrl *ctrl, |
|
struct list_head *q, |
|
unsigned int done); |
|
int rsxx_dma_cancel(struct rsxx_dma_ctrl *ctrl); |
|
void rsxx_dma_cleanup(void); |
|
void rsxx_dma_queue_reset(struct rsxx_cardinfo *card); |
|
int rsxx_dma_configure(struct rsxx_cardinfo *card); |
|
blk_status_t rsxx_dma_queue_bio(struct rsxx_cardinfo *card, |
|
struct bio *bio, |
|
atomic_t *n_dmas, |
|
rsxx_dma_cb cb, |
|
void *cb_data); |
|
int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl); |
|
int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card); |
|
int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card); |
|
|
|
/***** cregs.c *****/ |
|
int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr, |
|
unsigned int size8, |
|
void *data, |
|
int byte_stream); |
|
int rsxx_creg_read(struct rsxx_cardinfo *card, |
|
u32 addr, |
|
unsigned int size8, |
|
void *data, |
|
int byte_stream); |
|
int rsxx_read_hw_log(struct rsxx_cardinfo *card); |
|
int rsxx_get_card_state(struct rsxx_cardinfo *card, |
|
unsigned int *state); |
|
int rsxx_get_card_size8(struct rsxx_cardinfo *card, u64 *size8); |
|
int rsxx_get_num_targets(struct rsxx_cardinfo *card, |
|
unsigned int *n_targets); |
|
int rsxx_get_card_capabilities(struct rsxx_cardinfo *card, |
|
u32 *capabilities); |
|
int rsxx_issue_card_cmd(struct rsxx_cardinfo *card, u32 cmd); |
|
int rsxx_creg_setup(struct rsxx_cardinfo *card); |
|
void rsxx_creg_destroy(struct rsxx_cardinfo *card); |
|
int rsxx_creg_init(void); |
|
void rsxx_creg_cleanup(void); |
|
int rsxx_reg_access(struct rsxx_cardinfo *card, |
|
struct rsxx_reg_access __user *ucmd, |
|
int read); |
|
void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card); |
|
void rsxx_kick_creg_queue(struct rsxx_cardinfo *card); |
|
|
|
|
|
|
|
#endif /* __DRIVERS_BLOCK_RSXX_H__ */
|
|
|