diff options
Diffstat (limited to 'drivers/scsi/cxlflash/common.h')
-rw-r--r-- | drivers/scsi/cxlflash/common.h | 137 |
1 files changed, 103 insertions, 34 deletions
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h index d11dcc59ff46..256af819377d 100644 --- a/drivers/scsi/cxlflash/common.h +++ b/drivers/scsi/cxlflash/common.h @@ -15,6 +15,7 @@ #ifndef _CXLFLASH_COMMON_H #define _CXLFLASH_COMMON_H +#include <linux/irq_poll.h> #include <linux/list.h> #include <linux/rwsem.h> #include <linux/types.h> @@ -24,30 +25,32 @@ extern const struct file_operations cxlflash_cxl_fops; -#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */ +#define MAX_CONTEXT CXLFLASH_MAX_CONTEXT /* num contexts per afu */ +#define MAX_FC_PORTS CXLFLASH_MAX_FC_PORTS /* max ports per AFU */ +#define LEGACY_FC_PORTS 2 /* legacy ports per AFU */ -#define CXLFLASH_BLOCK_SIZE 4096 /* 4K blocks */ +#define CHAN2PORTBANK(_x) ((_x) >> ilog2(CXLFLASH_NUM_FC_PORTS_PER_BANK)) +#define CHAN2BANKPORT(_x) ((_x) & (CXLFLASH_NUM_FC_PORTS_PER_BANK - 1)) + +#define CHAN2PORTMASK(_x) (1 << (_x)) /* channel to port mask */ +#define PORTMASK2CHAN(_x) (ilog2((_x))) /* port mask to channel */ +#define PORTNUM2CHAN(_x) ((_x) - 1) /* port number to channel */ + +#define CXLFLASH_BLOCK_SIZE 4096 /* 4K blocks */ #define CXLFLASH_MAX_XFER_SIZE 16777216 /* 16MB transfer */ #define CXLFLASH_MAX_SECTORS (CXLFLASH_MAX_XFER_SIZE/512) /* SCSI wants - max_sectors - in units of - 512 byte - sectors - */ + * max_sectors + * in units of + * 512 byte + * sectors + */ #define MAX_RHT_PER_CONTEXT (PAGE_SIZE / sizeof(struct sisl_rht_entry)) /* AFU command retry limit */ -#define MC_RETRY_CNT 5 /* sufficient for SCSI check and - certain AFU errors */ +#define MC_RETRY_CNT 5 /* Sufficient for SCSI and certain AFU errors */ /* Command management definitions */ -#define CXLFLASH_NUM_CMDS (2 * CXLFLASH_MAX_CMDS) /* Must be a pow2 for - alignment and more - efficient array - index derivation - */ - #define CXLFLASH_MAX_CMDS 256 #define CXLFLASH_MAX_CMDS_PER_LUN CXLFLASH_MAX_CMDS @@ -57,10 +60,16 @@ extern const struct file_operations cxlflash_cxl_fops; /* SQ for master issued cmds */ #define NUM_SQ_ENTRY CXLFLASH_MAX_CMDS +/* Hardware queue definitions */ +#define CXLFLASH_DEF_HWQS 1 +#define CXLFLASH_MAX_HWQS 8 +#define PRIMARY_HWQ 0 + static inline void check_sizes(void) { - BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_NUM_CMDS); + BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_NUM_FC_PORTS_PER_BANK); + BUILD_BUG_ON_NOT_POWER_OF_2(CXLFLASH_MAX_CMDS); } /* AFU defines a fixed size of 4K for command buffers (borrow 4K page define) */ @@ -80,11 +89,20 @@ enum cxlflash_init_state { }; enum cxlflash_state { + STATE_PROBING, /* Initial state during probe */ + STATE_PROBED, /* Temporary state, probe completed but EEH occurred */ STATE_NORMAL, /* Normal running state, everything good */ STATE_RESET, /* Reset state, trying to reset/recover */ STATE_FAILTERM /* Failed/terminating state, error out users/threads */ }; +enum cxlflash_hwq_mode { + HWQ_MODE_RR, /* Roundrobin (default) */ + HWQ_MODE_TAG, /* Distribute based on block MQ tag */ + HWQ_MODE_CPU, /* CPU affinity */ + MAX_HWQ_MODE +}; + /* * Each context has its own set of resource handles that is visible * only from that context. @@ -92,11 +110,11 @@ enum cxlflash_state { struct cxlflash_cfg { struct afu *afu; - struct cxl_context *mcctx; struct pci_dev *dev; struct pci_device_id *dev_id; struct Scsi_Host *host; + int num_fc_ports; ulong cxlflash_regs_pci; @@ -117,7 +135,7 @@ struct cxlflash_cfg { struct file_operations cxl_fops; /* Parameters that are LUN table related */ - int last_lun_index[CXLFLASH_NUM_FC_PORTS]; + int last_lun_index[MAX_FC_PORTS]; int promote_lun_index; struct list_head lluns; /* list of llun_info structs */ @@ -134,6 +152,8 @@ struct afu_cmd { struct afu *parent; struct scsi_cmnd *scp; struct completion cevent; + struct list_head queue; + u32 hwq_index; u8 cmd_tmf:1; @@ -156,7 +176,7 @@ static inline struct afu_cmd *sc_to_afucz(struct scsi_cmnd *sc) return afuc; } -struct afu { +struct hwq { /* Stuff requiring alignment go first. */ struct sisl_ioarcb sq[NUM_SQ_ENTRY]; /* 16K SQ */ u64 rrq_entry[NUM_RRQ_ENTRY]; /* 2K RRQ */ @@ -164,40 +184,67 @@ struct afu { /* Beware of alignment till here. Preferably introduce new * fields after this point */ - - int (*send_cmd)(struct afu *, struct afu_cmd *); - void (*context_reset)(struct afu_cmd *); - - /* AFU HW */ + struct afu *afu; + struct cxl_context *ctx; struct cxl_ioctl_start_work work; - struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */ struct sisl_host_map __iomem *host_map; /* MC host map */ struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */ - ctx_hndl_t ctx_hndl; /* master's context handle */ + u32 index; /* Index of this hwq */ atomic_t hsq_credits; spinlock_t hsq_slock; struct sisl_ioarcb *hsq_start; struct sisl_ioarcb *hsq_end; struct sisl_ioarcb *hsq_curr; + spinlock_t hrrq_slock; u64 *hrrq_start; u64 *hrrq_end; u64 *hrrq_curr; bool toggle; - atomic_t cmds_active; /* Number of currently active AFU commands */ + s64 room; spinlock_t rrin_slock; /* Lock to rrin queuing and cmd_room updates */ + + struct irq_poll irqpoll; +} __aligned(cache_line_size()); + +struct afu { + struct hwq hwqs[CXLFLASH_MAX_HWQS]; + int (*send_cmd)(struct afu *, struct afu_cmd *); + void (*context_reset)(struct afu_cmd *); + + /* AFU HW */ + struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */ + + atomic_t cmds_active; /* Number of currently active AFU commands */ u64 hb; u32 internal_lun; /* User-desired LUN mode for this AFU */ + u32 num_hwqs; /* Number of hardware queues */ + u32 desired_hwqs; /* Desired h/w queues, effective on AFU reset */ + enum cxlflash_hwq_mode hwq_mode; /* Steering mode for h/w queues */ + u32 hwq_rr_count; /* Count to distribute traffic for roundrobin */ + char version[16]; u64 interface_version; + u32 irqpoll_weight; struct cxlflash_cfg *parent; /* Pointer back to parent cxlflash_cfg */ - }; +static inline struct hwq *get_hwq(struct afu *afu, u32 index) +{ + WARN_ON(index >= CXLFLASH_MAX_HWQS); + + return &afu->hwqs[index]; +} + +static inline bool afu_is_irqpoll_enabled(struct afu *afu) +{ + return !!afu->irqpoll_weight; +} + static inline bool afu_is_cmd_mode(struct afu *afu, u64 cmd_mode) { u64 afu_cap = afu->interface_version >> SISL_INTVER_CAP_SHIFT; @@ -223,14 +270,36 @@ static inline u64 lun_to_lunid(u64 lun) return be64_to_cpu(lun_id); } -int cxlflash_afu_sync(struct afu *, ctx_hndl_t, res_hndl_t, u8); +static inline struct fc_port_bank __iomem *get_fc_port_bank( + struct cxlflash_cfg *cfg, int i) +{ + struct afu *afu = cfg->afu; + + return &afu->afu_map->global.bank[CHAN2PORTBANK(i)]; +} + +static inline __be64 __iomem *get_fc_port_regs(struct cxlflash_cfg *cfg, int i) +{ + struct fc_port_bank __iomem *fcpb = get_fc_port_bank(cfg, i); + + return &fcpb->fc_port_regs[CHAN2BANKPORT(i)][0]; +} + +static inline __be64 __iomem *get_fc_port_luns(struct cxlflash_cfg *cfg, int i) +{ + struct fc_port_bank __iomem *fcpb = get_fc_port_bank(cfg, i); + + return &fcpb->fc_port_luns[CHAN2BANKPORT(i)][0]; +} + +int cxlflash_afu_sync(struct afu *afu, ctx_hndl_t c, res_hndl_t r, u8 mode); void cxlflash_list_init(void); void cxlflash_term_global_luns(void); void cxlflash_free_errpage(void); -int cxlflash_ioctl(struct scsi_device *, int, void __user *); -void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *); -int cxlflash_mark_contexts_error(struct cxlflash_cfg *); -void cxlflash_term_local_luns(struct cxlflash_cfg *); -void cxlflash_restore_luntable(struct cxlflash_cfg *); +int cxlflash_ioctl(struct scsi_device *sdev, int cmd, void __user *arg); +void cxlflash_stop_term_user_contexts(struct cxlflash_cfg *cfg); +int cxlflash_mark_contexts_error(struct cxlflash_cfg *cfg); +void cxlflash_term_local_luns(struct cxlflash_cfg *cfg); +void cxlflash_restore_luntable(struct cxlflash_cfg *cfg); #endif /* ifndef _CXLFLASH_COMMON_H */ |