| /* |
| * Filename: rsxx_priv.h |
| * |
| * |
| * Authors: Joshua Morris <josh.h.morris@us.ibm.com> |
| * Philip Kelleher <pjk1939@linux.vnet.ibm.com> |
| * |
| * (C) Copyright 2013 IBM Corporation |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation; either version 2 of the |
| * License, or (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software Foundation, |
| * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #ifndef __RSXX_PRIV_H__ |
| #define __RSXX_PRIV_H__ |
| |
| #include <linux/version.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__ */ |