1bfe1d560SDave Jiang /* SPDX-License-Identifier: GPL-2.0 */ 2bfe1d560SDave Jiang /* Copyright(c) 2019 Intel Corporation. All rights rsvd. */ 3bfe1d560SDave Jiang #ifndef _IDXD_H_ 4bfe1d560SDave Jiang #define _IDXD_H_ 5bfe1d560SDave Jiang 6bfe1d560SDave Jiang #include <linux/sbitmap.h> 78f47d1a5SDave Jiang #include <linux/dmaengine.h> 8bfe1d560SDave Jiang #include <linux/percpu-rwsem.h> 9bfe1d560SDave Jiang #include <linux/wait.h> 1042d279f9SDave Jiang #include <linux/cdev.h> 11bfe1d560SDave Jiang #include "registers.h" 12bfe1d560SDave Jiang 13bfe1d560SDave Jiang #define IDXD_DRIVER_VERSION "1.00" 14bfe1d560SDave Jiang 15bfe1d560SDave Jiang extern struct kmem_cache *idxd_desc_pool; 16bfe1d560SDave Jiang 17bfe1d560SDave Jiang #define IDXD_REG_TIMEOUT 50 18bfe1d560SDave Jiang #define IDXD_DRAIN_TIMEOUT 5000 19bfe1d560SDave Jiang 20bfe1d560SDave Jiang enum idxd_type { 21bfe1d560SDave Jiang IDXD_TYPE_UNKNOWN = -1, 22bfe1d560SDave Jiang IDXD_TYPE_DSA = 0, 23bfe1d560SDave Jiang IDXD_TYPE_MAX 24bfe1d560SDave Jiang }; 25bfe1d560SDave Jiang 26bfe1d560SDave Jiang #define IDXD_NAME_SIZE 128 27bfe1d560SDave Jiang 28bfe1d560SDave Jiang struct idxd_device_driver { 29bfe1d560SDave Jiang struct device_driver drv; 30bfe1d560SDave Jiang }; 31bfe1d560SDave Jiang 32bfe1d560SDave Jiang struct idxd_irq_entry { 33bfe1d560SDave Jiang struct idxd_device *idxd; 34bfe1d560SDave Jiang int id; 35bfe1d560SDave Jiang struct llist_head pending_llist; 36bfe1d560SDave Jiang struct list_head work_list; 37bfe1d560SDave Jiang }; 38bfe1d560SDave Jiang 39bfe1d560SDave Jiang struct idxd_group { 40bfe1d560SDave Jiang struct device conf_dev; 41bfe1d560SDave Jiang struct idxd_device *idxd; 42bfe1d560SDave Jiang struct grpcfg grpcfg; 43bfe1d560SDave Jiang int id; 44bfe1d560SDave Jiang int num_engines; 45bfe1d560SDave Jiang int num_wqs; 46bfe1d560SDave Jiang bool use_token_limit; 47bfe1d560SDave Jiang u8 tokens_allowed; 48bfe1d560SDave Jiang u8 tokens_reserved; 49bfe1d560SDave Jiang int tc_a; 50bfe1d560SDave Jiang int tc_b; 51bfe1d560SDave Jiang }; 52bfe1d560SDave Jiang 53bfe1d560SDave Jiang #define IDXD_MAX_PRIORITY 0xf 54bfe1d560SDave Jiang 55bfe1d560SDave Jiang enum idxd_wq_state { 56bfe1d560SDave Jiang IDXD_WQ_DISABLED = 0, 57bfe1d560SDave Jiang IDXD_WQ_ENABLED, 58bfe1d560SDave Jiang }; 59bfe1d560SDave Jiang 60bfe1d560SDave Jiang enum idxd_wq_flag { 61bfe1d560SDave Jiang WQ_FLAG_DEDICATED = 0, 62bfe1d560SDave Jiang }; 63bfe1d560SDave Jiang 64bfe1d560SDave Jiang enum idxd_wq_type { 65bfe1d560SDave Jiang IDXD_WQT_NONE = 0, 66bfe1d560SDave Jiang IDXD_WQT_KERNEL, 6742d279f9SDave Jiang IDXD_WQT_USER, 6842d279f9SDave Jiang }; 6942d279f9SDave Jiang 7042d279f9SDave Jiang struct idxd_cdev { 7142d279f9SDave Jiang struct cdev cdev; 7242d279f9SDave Jiang struct device *dev; 7342d279f9SDave Jiang int minor; 7442d279f9SDave Jiang struct wait_queue_head err_queue; 75bfe1d560SDave Jiang }; 76bfe1d560SDave Jiang 77bfe1d560SDave Jiang #define IDXD_ALLOCATED_BATCH_SIZE 128U 78bfe1d560SDave Jiang #define WQ_NAME_SIZE 1024 79bfe1d560SDave Jiang #define WQ_TYPE_SIZE 10 80bfe1d560SDave Jiang 81d1dfe5b8SDave Jiang enum idxd_op_type { 82d1dfe5b8SDave Jiang IDXD_OP_BLOCK = 0, 83d1dfe5b8SDave Jiang IDXD_OP_NONBLOCK = 1, 84d1dfe5b8SDave Jiang }; 85d1dfe5b8SDave Jiang 868f47d1a5SDave Jiang enum idxd_complete_type { 878f47d1a5SDave Jiang IDXD_COMPLETE_NORMAL = 0, 888f47d1a5SDave Jiang IDXD_COMPLETE_ABORT, 898f47d1a5SDave Jiang }; 908f47d1a5SDave Jiang 91bfe1d560SDave Jiang struct idxd_wq { 92bfe1d560SDave Jiang void __iomem *dportal; 93bfe1d560SDave Jiang struct device conf_dev; 9442d279f9SDave Jiang struct idxd_cdev idxd_cdev; 95bfe1d560SDave Jiang struct idxd_device *idxd; 96bfe1d560SDave Jiang int id; 97bfe1d560SDave Jiang enum idxd_wq_type type; 98bfe1d560SDave Jiang struct idxd_group *group; 99bfe1d560SDave Jiang int client_count; 100bfe1d560SDave Jiang struct mutex wq_lock; /* mutex for workqueue */ 101bfe1d560SDave Jiang u32 size; 102bfe1d560SDave Jiang u32 threshold; 103bfe1d560SDave Jiang u32 priority; 104bfe1d560SDave Jiang enum idxd_wq_state state; 105bfe1d560SDave Jiang unsigned long flags; 106bfe1d560SDave Jiang union wqcfg wqcfg; 107bfe1d560SDave Jiang u32 vec_ptr; /* interrupt steering */ 108bfe1d560SDave Jiang struct dsa_hw_desc **hw_descs; 109bfe1d560SDave Jiang int num_descs; 110bfe1d560SDave Jiang struct dsa_completion_record *compls; 111bfe1d560SDave Jiang dma_addr_t compls_addr; 112bfe1d560SDave Jiang int compls_size; 113bfe1d560SDave Jiang struct idxd_desc **descs; 1140705107fSDave Jiang struct sbitmap_queue sbq; 1158f47d1a5SDave Jiang struct dma_chan dma_chan; 116bfe1d560SDave Jiang char name[WQ_NAME_SIZE + 1]; 117d7aad555SDave Jiang u64 max_xfer_bytes; 118e7184b15SDave Jiang u32 max_batch_size; 119bfe1d560SDave Jiang }; 120bfe1d560SDave Jiang 121bfe1d560SDave Jiang struct idxd_engine { 122bfe1d560SDave Jiang struct device conf_dev; 123bfe1d560SDave Jiang int id; 124bfe1d560SDave Jiang struct idxd_group *group; 125bfe1d560SDave Jiang struct idxd_device *idxd; 126bfe1d560SDave Jiang }; 127bfe1d560SDave Jiang 128bfe1d560SDave Jiang /* shadow registers */ 129bfe1d560SDave Jiang struct idxd_hw { 130bfe1d560SDave Jiang u32 version; 131bfe1d560SDave Jiang union gen_cap_reg gen_cap; 132bfe1d560SDave Jiang union wq_cap_reg wq_cap; 133bfe1d560SDave Jiang union group_cap_reg group_cap; 134bfe1d560SDave Jiang union engine_cap_reg engine_cap; 135bfe1d560SDave Jiang struct opcap opcap; 136bfe1d560SDave Jiang }; 137bfe1d560SDave Jiang 138bfe1d560SDave Jiang enum idxd_device_state { 139bfe1d560SDave Jiang IDXD_DEV_HALTED = -1, 140bfe1d560SDave Jiang IDXD_DEV_DISABLED = 0, 141bfe1d560SDave Jiang IDXD_DEV_CONF_READY, 142bfe1d560SDave Jiang IDXD_DEV_ENABLED, 143bfe1d560SDave Jiang }; 144bfe1d560SDave Jiang 145bfe1d560SDave Jiang enum idxd_device_flag { 146bfe1d560SDave Jiang IDXD_FLAG_CONFIGURABLE = 0, 1470d5c10b4SDave Jiang IDXD_FLAG_CMD_RUNNING, 148bfe1d560SDave Jiang }; 149bfe1d560SDave Jiang 150bfe1d560SDave Jiang struct idxd_device { 151bfe1d560SDave Jiang enum idxd_type type; 152bfe1d560SDave Jiang struct device conf_dev; 153bfe1d560SDave Jiang struct list_head list; 154bfe1d560SDave Jiang struct idxd_hw hw; 155bfe1d560SDave Jiang enum idxd_device_state state; 156bfe1d560SDave Jiang unsigned long flags; 157bfe1d560SDave Jiang int id; 15842d279f9SDave Jiang int major; 159*ff18de55SDave Jiang u8 cmd_status; 160bfe1d560SDave Jiang 161bfe1d560SDave Jiang struct pci_dev *pdev; 162bfe1d560SDave Jiang void __iomem *reg_base; 163bfe1d560SDave Jiang 164bfe1d560SDave Jiang spinlock_t dev_lock; /* spinlock for device */ 1650d5c10b4SDave Jiang struct completion *cmd_done; 166bfe1d560SDave Jiang struct idxd_group *groups; 167bfe1d560SDave Jiang struct idxd_wq *wqs; 168bfe1d560SDave Jiang struct idxd_engine *engines; 169bfe1d560SDave Jiang 170bfe1d560SDave Jiang int num_groups; 171bfe1d560SDave Jiang 172bfe1d560SDave Jiang u32 msix_perm_offset; 173bfe1d560SDave Jiang u32 wqcfg_offset; 174bfe1d560SDave Jiang u32 grpcfg_offset; 175bfe1d560SDave Jiang u32 perfmon_offset; 176bfe1d560SDave Jiang 177bfe1d560SDave Jiang u64 max_xfer_bytes; 178bfe1d560SDave Jiang u32 max_batch_size; 179bfe1d560SDave Jiang int max_groups; 180bfe1d560SDave Jiang int max_engines; 181bfe1d560SDave Jiang int max_tokens; 182bfe1d560SDave Jiang int max_wqs; 183bfe1d560SDave Jiang int max_wq_size; 184bfe1d560SDave Jiang int token_limit; 185c52ca478SDave Jiang int nr_tokens; /* non-reserved tokens */ 186bfe1d560SDave Jiang 187bfe1d560SDave Jiang union sw_err_reg sw_err; 1880d5c10b4SDave Jiang wait_queue_head_t cmd_waitq; 189bfe1d560SDave Jiang struct msix_entry *msix_entries; 190bfe1d560SDave Jiang int num_wq_irqs; 191bfe1d560SDave Jiang struct idxd_irq_entry *irq_entries; 1928f47d1a5SDave Jiang 1938f47d1a5SDave Jiang struct dma_device dma_dev; 1940d5c10b4SDave Jiang struct workqueue_struct *wq; 1950d5c10b4SDave Jiang struct work_struct work; 196bfe1d560SDave Jiang }; 197bfe1d560SDave Jiang 198bfe1d560SDave Jiang /* IDXD software descriptor */ 199bfe1d560SDave Jiang struct idxd_desc { 200bfe1d560SDave Jiang struct dsa_hw_desc *hw; 201bfe1d560SDave Jiang dma_addr_t desc_dma; 202bfe1d560SDave Jiang struct dsa_completion_record *completion; 203bfe1d560SDave Jiang dma_addr_t compl_dma; 2048f47d1a5SDave Jiang struct dma_async_tx_descriptor txd; 205bfe1d560SDave Jiang struct llist_node llnode; 206bfe1d560SDave Jiang struct list_head list; 207bfe1d560SDave Jiang int id; 2080705107fSDave Jiang int cpu; 209bfe1d560SDave Jiang struct idxd_wq *wq; 210bfe1d560SDave Jiang }; 211bfe1d560SDave Jiang 212bfe1d560SDave Jiang #define confdev_to_idxd(dev) container_of(dev, struct idxd_device, conf_dev) 213bfe1d560SDave Jiang #define confdev_to_wq(dev) container_of(dev, struct idxd_wq, conf_dev) 214bfe1d560SDave Jiang 21542d279f9SDave Jiang extern struct bus_type dsa_bus_type; 21642d279f9SDave Jiang 217bfe1d560SDave Jiang static inline bool wq_dedicated(struct idxd_wq *wq) 218bfe1d560SDave Jiang { 219bfe1d560SDave Jiang return test_bit(WQ_FLAG_DEDICATED, &wq->flags); 220bfe1d560SDave Jiang } 221bfe1d560SDave Jiang 22242d279f9SDave Jiang enum idxd_portal_prot { 22342d279f9SDave Jiang IDXD_PORTAL_UNLIMITED = 0, 22442d279f9SDave Jiang IDXD_PORTAL_LIMITED, 22542d279f9SDave Jiang }; 22642d279f9SDave Jiang 22742d279f9SDave Jiang static inline int idxd_get_wq_portal_offset(enum idxd_portal_prot prot) 22842d279f9SDave Jiang { 22942d279f9SDave Jiang return prot * 0x1000; 23042d279f9SDave Jiang } 23142d279f9SDave Jiang 23242d279f9SDave Jiang static inline int idxd_get_wq_portal_full_offset(int wq_id, 23342d279f9SDave Jiang enum idxd_portal_prot prot) 23442d279f9SDave Jiang { 23542d279f9SDave Jiang return ((wq_id * 4) << PAGE_SHIFT) + idxd_get_wq_portal_offset(prot); 23642d279f9SDave Jiang } 23742d279f9SDave Jiang 238bfe1d560SDave Jiang static inline void idxd_set_type(struct idxd_device *idxd) 239bfe1d560SDave Jiang { 240bfe1d560SDave Jiang struct pci_dev *pdev = idxd->pdev; 241bfe1d560SDave Jiang 242bfe1d560SDave Jiang if (pdev->device == PCI_DEVICE_ID_INTEL_DSA_SPR0) 243bfe1d560SDave Jiang idxd->type = IDXD_TYPE_DSA; 244bfe1d560SDave Jiang else 245bfe1d560SDave Jiang idxd->type = IDXD_TYPE_UNKNOWN; 246bfe1d560SDave Jiang } 247bfe1d560SDave Jiang 248c52ca478SDave Jiang static inline void idxd_wq_get(struct idxd_wq *wq) 249c52ca478SDave Jiang { 250c52ca478SDave Jiang wq->client_count++; 251c52ca478SDave Jiang } 252c52ca478SDave Jiang 253c52ca478SDave Jiang static inline void idxd_wq_put(struct idxd_wq *wq) 254c52ca478SDave Jiang { 255c52ca478SDave Jiang wq->client_count--; 256c52ca478SDave Jiang } 257c52ca478SDave Jiang 258c52ca478SDave Jiang static inline int idxd_wq_refcount(struct idxd_wq *wq) 259c52ca478SDave Jiang { 260c52ca478SDave Jiang return wq->client_count; 261c52ca478SDave Jiang }; 262c52ca478SDave Jiang 263bfe1d560SDave Jiang const char *idxd_get_dev_name(struct idxd_device *idxd); 264c52ca478SDave Jiang int idxd_register_bus_type(void); 265c52ca478SDave Jiang void idxd_unregister_bus_type(void); 266c52ca478SDave Jiang int idxd_setup_sysfs(struct idxd_device *idxd); 267c52ca478SDave Jiang void idxd_cleanup_sysfs(struct idxd_device *idxd); 268c52ca478SDave Jiang int idxd_register_driver(void); 269c52ca478SDave Jiang void idxd_unregister_driver(void); 27042d279f9SDave Jiang struct bus_type *idxd_get_bus_type(struct idxd_device *idxd); 271bfe1d560SDave Jiang 272bfe1d560SDave Jiang /* device interrupt control */ 273bfe1d560SDave Jiang irqreturn_t idxd_irq_handler(int vec, void *data); 274bfe1d560SDave Jiang irqreturn_t idxd_misc_thread(int vec, void *data); 275bfe1d560SDave Jiang irqreturn_t idxd_wq_thread(int irq, void *data); 276bfe1d560SDave Jiang void idxd_mask_error_interrupts(struct idxd_device *idxd); 277bfe1d560SDave Jiang void idxd_unmask_error_interrupts(struct idxd_device *idxd); 278bfe1d560SDave Jiang void idxd_mask_msix_vectors(struct idxd_device *idxd); 2794548a6adSDave Jiang void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id); 2804548a6adSDave Jiang void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id); 281bfe1d560SDave Jiang 282bfe1d560SDave Jiang /* device control */ 2830d5c10b4SDave Jiang void idxd_device_init_reset(struct idxd_device *idxd); 284bfe1d560SDave Jiang int idxd_device_enable(struct idxd_device *idxd); 285bfe1d560SDave Jiang int idxd_device_disable(struct idxd_device *idxd); 2860d5c10b4SDave Jiang void idxd_device_reset(struct idxd_device *idxd); 287bfe1d560SDave Jiang void idxd_device_cleanup(struct idxd_device *idxd); 288bfe1d560SDave Jiang int idxd_device_config(struct idxd_device *idxd); 289bfe1d560SDave Jiang void idxd_device_wqs_clear_state(struct idxd_device *idxd); 290bfe1d560SDave Jiang 291bfe1d560SDave Jiang /* work queue control */ 292bfe1d560SDave Jiang int idxd_wq_alloc_resources(struct idxd_wq *wq); 293bfe1d560SDave Jiang void idxd_wq_free_resources(struct idxd_wq *wq); 294bfe1d560SDave Jiang int idxd_wq_enable(struct idxd_wq *wq); 295bfe1d560SDave Jiang int idxd_wq_disable(struct idxd_wq *wq); 2960d5c10b4SDave Jiang void idxd_wq_drain(struct idxd_wq *wq); 297c52ca478SDave Jiang int idxd_wq_map_portal(struct idxd_wq *wq); 298c52ca478SDave Jiang void idxd_wq_unmap_portal(struct idxd_wq *wq); 299da32b28cSDave Jiang void idxd_wq_disable_cleanup(struct idxd_wq *wq); 300bfe1d560SDave Jiang 301d1dfe5b8SDave Jiang /* submission */ 302d1dfe5b8SDave Jiang int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc); 303d1dfe5b8SDave Jiang struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype); 304d1dfe5b8SDave Jiang void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc); 305d1dfe5b8SDave Jiang 3068f47d1a5SDave Jiang /* dmaengine */ 3078f47d1a5SDave Jiang int idxd_register_dma_device(struct idxd_device *idxd); 3088f47d1a5SDave Jiang void idxd_unregister_dma_device(struct idxd_device *idxd); 3098f47d1a5SDave Jiang int idxd_register_dma_channel(struct idxd_wq *wq); 3108f47d1a5SDave Jiang void idxd_unregister_dma_channel(struct idxd_wq *wq); 3118f47d1a5SDave Jiang void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res); 3128f47d1a5SDave Jiang void idxd_dma_complete_txd(struct idxd_desc *desc, 3138f47d1a5SDave Jiang enum idxd_complete_type comp_type); 3148f47d1a5SDave Jiang dma_cookie_t idxd_dma_tx_submit(struct dma_async_tx_descriptor *tx); 3158f47d1a5SDave Jiang 31642d279f9SDave Jiang /* cdev */ 31742d279f9SDave Jiang int idxd_cdev_register(void); 31842d279f9SDave Jiang void idxd_cdev_remove(void); 31942d279f9SDave Jiang int idxd_cdev_get_major(struct idxd_device *idxd); 32042d279f9SDave Jiang int idxd_wq_add_cdev(struct idxd_wq *wq); 32142d279f9SDave Jiang void idxd_wq_del_cdev(struct idxd_wq *wq); 32242d279f9SDave Jiang 323bfe1d560SDave Jiang #endif 324