aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers/scsi/cxlflash/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/cxlflash/common.h')
-rw-r--r--drivers/scsi/cxlflash/common.h137
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 */