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> 1147c16ac2SDave Jiang #include <linux/idr.h> 1281dd4d4dSTom Zanussi #include <linux/pci.h> 138b67426eSDave Jiang #include <linux/ioasid.h> 1481dd4d4dSTom Zanussi #include <linux/perf_event.h> 15a9c17152SDave Jiang #include <uapi/linux/idxd.h> 16bfe1d560SDave Jiang #include "registers.h" 17bfe1d560SDave Jiang 18bfe1d560SDave Jiang #define IDXD_DRIVER_VERSION "1.00" 19bfe1d560SDave Jiang 20bfe1d560SDave Jiang extern struct kmem_cache *idxd_desc_pool; 21ade8a86bSDave Jiang extern bool tc_override; 22bfe1d560SDave Jiang 2339786285SDave Jiang struct idxd_wq; 24700af3a0SDave Jiang struct idxd_dev; 25700af3a0SDave Jiang 26700af3a0SDave Jiang enum idxd_dev_type { 27700af3a0SDave Jiang IDXD_DEV_NONE = -1, 28700af3a0SDave Jiang IDXD_DEV_DSA = 0, 29700af3a0SDave Jiang IDXD_DEV_IAX, 30700af3a0SDave Jiang IDXD_DEV_WQ, 31700af3a0SDave Jiang IDXD_DEV_GROUP, 32700af3a0SDave Jiang IDXD_DEV_ENGINE, 33700af3a0SDave Jiang IDXD_DEV_CDEV, 34700af3a0SDave Jiang IDXD_DEV_MAX_TYPE, 35700af3a0SDave Jiang }; 36700af3a0SDave Jiang 37700af3a0SDave Jiang struct idxd_dev { 38700af3a0SDave Jiang struct device conf_dev; 39700af3a0SDave Jiang enum idxd_dev_type type; 40700af3a0SDave Jiang }; 4139786285SDave Jiang 42bfe1d560SDave Jiang #define IDXD_REG_TIMEOUT 50 43bfe1d560SDave Jiang #define IDXD_DRAIN_TIMEOUT 5000 44bfe1d560SDave Jiang 45bfe1d560SDave Jiang enum idxd_type { 46bfe1d560SDave Jiang IDXD_TYPE_UNKNOWN = -1, 47bfe1d560SDave Jiang IDXD_TYPE_DSA = 0, 48f25b4638SDave Jiang IDXD_TYPE_IAX, 49f25b4638SDave Jiang IDXD_TYPE_MAX, 50bfe1d560SDave Jiang }; 51bfe1d560SDave Jiang 52bfe1d560SDave Jiang #define IDXD_NAME_SIZE 128 5381dd4d4dSTom Zanussi #define IDXD_PMU_EVENT_MAX 64 54bfe1d560SDave Jiang 55bfe1d560SDave Jiang struct idxd_device_driver { 56da5a11d7SDave Jiang const char *name; 575fee6567SDave Jiang enum idxd_dev_type *type; 58fcc2281bSDave Jiang int (*probe)(struct idxd_dev *idxd_dev); 59fcc2281bSDave Jiang void (*remove)(struct idxd_dev *idxd_dev); 60bfe1d560SDave Jiang struct device_driver drv; 61bfe1d560SDave Jiang }; 62bfe1d560SDave Jiang 63c05257b5SDave Jiang extern struct idxd_device_driver dsa_drv; 64034b3290SDave Jiang extern struct idxd_device_driver idxd_drv; 650cda4f69SDave Jiang extern struct idxd_device_driver idxd_dmaengine_drv; 66448c3de8SDave Jiang extern struct idxd_device_driver idxd_user_drv; 67c05257b5SDave Jiang 688b67426eSDave Jiang #define INVALID_INT_HANDLE -1 69bfe1d560SDave Jiang struct idxd_irq_entry { 70bfe1d560SDave Jiang struct idxd_device *idxd; 71bfe1d560SDave Jiang int id; 725fc8e85fSDave Jiang int vector; 73bfe1d560SDave Jiang struct llist_head pending_llist; 74bfe1d560SDave Jiang struct list_head work_list; 75e4f4d8cdSDave Jiang /* 76e4f4d8cdSDave Jiang * Lock to protect access between irq thread process descriptor 77e4f4d8cdSDave Jiang * and irq thread processing error descriptor. 78e4f4d8cdSDave Jiang */ 79e4f4d8cdSDave Jiang spinlock_t list_lock; 808b67426eSDave Jiang int int_handle; 818b67426eSDave Jiang struct idxd_wq *wq; 828b67426eSDave Jiang ioasid_t pasid; 83bfe1d560SDave Jiang }; 84bfe1d560SDave Jiang 85bfe1d560SDave Jiang struct idxd_group { 86700af3a0SDave Jiang struct idxd_dev idxd_dev; 87bfe1d560SDave Jiang struct idxd_device *idxd; 88bfe1d560SDave Jiang struct grpcfg grpcfg; 89bfe1d560SDave Jiang int id; 90bfe1d560SDave Jiang int num_engines; 91bfe1d560SDave Jiang int num_wqs; 92bfe1d560SDave Jiang bool use_token_limit; 93bfe1d560SDave Jiang u8 tokens_allowed; 94bfe1d560SDave Jiang u8 tokens_reserved; 95bfe1d560SDave Jiang int tc_a; 96bfe1d560SDave Jiang int tc_b; 97bfe1d560SDave Jiang }; 98bfe1d560SDave Jiang 9981dd4d4dSTom Zanussi struct idxd_pmu { 10081dd4d4dSTom Zanussi struct idxd_device *idxd; 10181dd4d4dSTom Zanussi 10281dd4d4dSTom Zanussi struct perf_event *event_list[IDXD_PMU_EVENT_MAX]; 10381dd4d4dSTom Zanussi int n_events; 10481dd4d4dSTom Zanussi 10581dd4d4dSTom Zanussi DECLARE_BITMAP(used_mask, IDXD_PMU_EVENT_MAX); 10681dd4d4dSTom Zanussi 10781dd4d4dSTom Zanussi struct pmu pmu; 10881dd4d4dSTom Zanussi char name[IDXD_NAME_SIZE]; 10981dd4d4dSTom Zanussi int cpu; 11081dd4d4dSTom Zanussi 11181dd4d4dSTom Zanussi int n_counters; 11281dd4d4dSTom Zanussi int counter_width; 11381dd4d4dSTom Zanussi int n_event_categories; 11481dd4d4dSTom Zanussi 11581dd4d4dSTom Zanussi bool per_counter_caps_supported; 11681dd4d4dSTom Zanussi unsigned long supported_event_categories; 11781dd4d4dSTom Zanussi 11881dd4d4dSTom Zanussi unsigned long supported_filters; 11981dd4d4dSTom Zanussi int n_filters; 12081dd4d4dSTom Zanussi 12181dd4d4dSTom Zanussi struct hlist_node cpuhp_node; 12281dd4d4dSTom Zanussi }; 12381dd4d4dSTom Zanussi 124bfe1d560SDave Jiang #define IDXD_MAX_PRIORITY 0xf 125bfe1d560SDave Jiang 126bfe1d560SDave Jiang enum idxd_wq_state { 127bfe1d560SDave Jiang IDXD_WQ_DISABLED = 0, 128bfe1d560SDave Jiang IDXD_WQ_ENABLED, 129bfe1d560SDave Jiang }; 130bfe1d560SDave Jiang 131bfe1d560SDave Jiang enum idxd_wq_flag { 132bfe1d560SDave Jiang WQ_FLAG_DEDICATED = 0, 1338e50d392SDave Jiang WQ_FLAG_BLOCK_ON_FAULT, 134bfe1d560SDave Jiang }; 135bfe1d560SDave Jiang 136bfe1d560SDave Jiang enum idxd_wq_type { 137bfe1d560SDave Jiang IDXD_WQT_NONE = 0, 138bfe1d560SDave Jiang IDXD_WQT_KERNEL, 13942d279f9SDave Jiang IDXD_WQT_USER, 14042d279f9SDave Jiang }; 14142d279f9SDave Jiang 14242d279f9SDave Jiang struct idxd_cdev { 14304922b74SDave Jiang struct idxd_wq *wq; 14442d279f9SDave Jiang struct cdev cdev; 145700af3a0SDave Jiang struct idxd_dev idxd_dev; 14642d279f9SDave Jiang int minor; 147bfe1d560SDave Jiang }; 148bfe1d560SDave Jiang 149bfe1d560SDave Jiang #define IDXD_ALLOCATED_BATCH_SIZE 128U 150bfe1d560SDave Jiang #define WQ_NAME_SIZE 1024 151bfe1d560SDave Jiang #define WQ_TYPE_SIZE 10 152bfe1d560SDave Jiang 153d1dfe5b8SDave Jiang enum idxd_op_type { 154d1dfe5b8SDave Jiang IDXD_OP_BLOCK = 0, 155d1dfe5b8SDave Jiang IDXD_OP_NONBLOCK = 1, 156d1dfe5b8SDave Jiang }; 157d1dfe5b8SDave Jiang 1588f47d1a5SDave Jiang enum idxd_complete_type { 1598f47d1a5SDave Jiang IDXD_COMPLETE_NORMAL = 0, 1608f47d1a5SDave Jiang IDXD_COMPLETE_ABORT, 1618e50d392SDave Jiang IDXD_COMPLETE_DEV_FAIL, 1628f47d1a5SDave Jiang }; 1638f47d1a5SDave Jiang 16439786285SDave Jiang struct idxd_dma_chan { 16539786285SDave Jiang struct dma_chan chan; 16639786285SDave Jiang struct idxd_wq *wq; 16739786285SDave Jiang }; 16839786285SDave Jiang 169bfe1d560SDave Jiang struct idxd_wq { 1708e50d392SDave Jiang void __iomem *portal; 171a9c17152SDave Jiang u32 portal_offset; 17293a40a6dSDave Jiang struct percpu_ref wq_active; 17393a40a6dSDave Jiang struct completion wq_dead; 174700af3a0SDave Jiang struct idxd_dev idxd_dev; 17504922b74SDave Jiang struct idxd_cdev *idxd_cdev; 17604922b74SDave Jiang struct wait_queue_head err_queue; 177bfe1d560SDave Jiang struct idxd_device *idxd; 178bfe1d560SDave Jiang int id; 1798b67426eSDave Jiang struct idxd_irq_entry *ie; 180bfe1d560SDave Jiang enum idxd_wq_type type; 181bfe1d560SDave Jiang struct idxd_group *group; 182bfe1d560SDave Jiang int client_count; 183bfe1d560SDave Jiang struct mutex wq_lock; /* mutex for workqueue */ 184bfe1d560SDave Jiang u32 size; 185bfe1d560SDave Jiang u32 threshold; 186bfe1d560SDave Jiang u32 priority; 187bfe1d560SDave Jiang enum idxd_wq_state state; 188bfe1d560SDave Jiang unsigned long flags; 189d98793b5SDave Jiang union wqcfg *wqcfg; 190bfe1d560SDave Jiang struct dsa_hw_desc **hw_descs; 191bfe1d560SDave Jiang int num_descs; 192f25b4638SDave Jiang union { 193bfe1d560SDave Jiang struct dsa_completion_record *compls; 194f25b4638SDave Jiang struct iax_completion_record *iax_compls; 195f25b4638SDave Jiang }; 196bfe1d560SDave Jiang dma_addr_t compls_addr; 197bfe1d560SDave Jiang int compls_size; 198bfe1d560SDave Jiang struct idxd_desc **descs; 1990705107fSDave Jiang struct sbitmap_queue sbq; 20039786285SDave Jiang struct idxd_dma_chan *idxd_chan; 201bfe1d560SDave Jiang char name[WQ_NAME_SIZE + 1]; 202d7aad555SDave Jiang u64 max_xfer_bytes; 203e7184b15SDave Jiang u32 max_batch_size; 20492de5fa2SDave Jiang bool ats_dis; 205bfe1d560SDave Jiang }; 206bfe1d560SDave Jiang 207bfe1d560SDave Jiang struct idxd_engine { 208700af3a0SDave Jiang struct idxd_dev idxd_dev; 209bfe1d560SDave Jiang int id; 210bfe1d560SDave Jiang struct idxd_group *group; 211bfe1d560SDave Jiang struct idxd_device *idxd; 212bfe1d560SDave Jiang }; 213bfe1d560SDave Jiang 214bfe1d560SDave Jiang /* shadow registers */ 215bfe1d560SDave Jiang struct idxd_hw { 216bfe1d560SDave Jiang u32 version; 217bfe1d560SDave Jiang union gen_cap_reg gen_cap; 218bfe1d560SDave Jiang union wq_cap_reg wq_cap; 219bfe1d560SDave Jiang union group_cap_reg group_cap; 220bfe1d560SDave Jiang union engine_cap_reg engine_cap; 221bfe1d560SDave Jiang struct opcap opcap; 222eb15e715SDave Jiang u32 cmd_cap; 223bfe1d560SDave Jiang }; 224bfe1d560SDave Jiang 225bfe1d560SDave Jiang enum idxd_device_state { 226bfe1d560SDave Jiang IDXD_DEV_HALTED = -1, 227bfe1d560SDave Jiang IDXD_DEV_DISABLED = 0, 228bfe1d560SDave Jiang IDXD_DEV_ENABLED, 229bfe1d560SDave Jiang }; 230bfe1d560SDave Jiang 231bfe1d560SDave Jiang enum idxd_device_flag { 232bfe1d560SDave Jiang IDXD_FLAG_CONFIGURABLE = 0, 2330d5c10b4SDave Jiang IDXD_FLAG_CMD_RUNNING, 2348e50d392SDave Jiang IDXD_FLAG_PASID_ENABLED, 235bfe1d560SDave Jiang }; 236bfe1d560SDave Jiang 23739786285SDave Jiang struct idxd_dma_dev { 23839786285SDave Jiang struct idxd_device *idxd; 23939786285SDave Jiang struct dma_device dma; 24039786285SDave Jiang }; 24139786285SDave Jiang 242435b512dSDave Jiang struct idxd_driver_data { 243435b512dSDave Jiang const char *name_prefix; 244bfe1d560SDave Jiang enum idxd_type type; 245435b512dSDave Jiang struct device_type *dev_type; 246435b512dSDave Jiang int compl_size; 247435b512dSDave Jiang int align; 248435b512dSDave Jiang }; 249435b512dSDave Jiang 250435b512dSDave Jiang struct idxd_device { 251700af3a0SDave Jiang struct idxd_dev idxd_dev; 252435b512dSDave Jiang struct idxd_driver_data *data; 253bfe1d560SDave Jiang struct list_head list; 254bfe1d560SDave Jiang struct idxd_hw hw; 255bfe1d560SDave Jiang enum idxd_device_state state; 256bfe1d560SDave Jiang unsigned long flags; 257bfe1d560SDave Jiang int id; 25842d279f9SDave Jiang int major; 259125d1037SDave Jiang u32 cmd_status; 260bfe1d560SDave Jiang 261bfe1d560SDave Jiang struct pci_dev *pdev; 262bfe1d560SDave Jiang void __iomem *reg_base; 263bfe1d560SDave Jiang 264bfe1d560SDave Jiang spinlock_t dev_lock; /* spinlock for device */ 26553b2ee7fSDave Jiang spinlock_t cmd_lock; /* spinlock for device commands */ 2660d5c10b4SDave Jiang struct completion *cmd_done; 267defe49f9SDave Jiang struct idxd_group **groups; 2687c5dd23eSDave Jiang struct idxd_wq **wqs; 26975b91130SDave Jiang struct idxd_engine **engines; 270bfe1d560SDave Jiang 2718e50d392SDave Jiang struct iommu_sva *sva; 2728e50d392SDave Jiang unsigned int pasid; 2738e50d392SDave Jiang 274bfe1d560SDave Jiang int num_groups; 2758b67426eSDave Jiang int irq_cnt; 2768b67426eSDave Jiang bool request_int_handles; 277bfe1d560SDave Jiang 278bfe1d560SDave Jiang u32 msix_perm_offset; 279bfe1d560SDave Jiang u32 wqcfg_offset; 280bfe1d560SDave Jiang u32 grpcfg_offset; 281bfe1d560SDave Jiang u32 perfmon_offset; 282bfe1d560SDave Jiang 283bfe1d560SDave Jiang u64 max_xfer_bytes; 284bfe1d560SDave Jiang u32 max_batch_size; 285bfe1d560SDave Jiang int max_groups; 286bfe1d560SDave Jiang int max_engines; 287bfe1d560SDave Jiang int max_tokens; 288bfe1d560SDave Jiang int max_wqs; 289bfe1d560SDave Jiang int max_wq_size; 290bfe1d560SDave Jiang int token_limit; 291c52ca478SDave Jiang int nr_tokens; /* non-reserved tokens */ 292d98793b5SDave Jiang unsigned int wqcfg_size; 293bfe1d560SDave Jiang 294bfe1d560SDave Jiang union sw_err_reg sw_err; 2950d5c10b4SDave Jiang wait_queue_head_t cmd_waitq; 296bfe1d560SDave Jiang int num_wq_irqs; 297bfe1d560SDave Jiang struct idxd_irq_entry *irq_entries; 2988f47d1a5SDave Jiang 29939786285SDave Jiang struct idxd_dma_dev *idxd_dma; 3000d5c10b4SDave Jiang struct workqueue_struct *wq; 3010d5c10b4SDave Jiang struct work_struct work; 302eb15e715SDave Jiang 30381dd4d4dSTom Zanussi struct idxd_pmu *idxd_pmu; 304bfe1d560SDave Jiang }; 305bfe1d560SDave Jiang 306bfe1d560SDave Jiang /* IDXD software descriptor */ 307bfe1d560SDave Jiang struct idxd_desc { 308f25b4638SDave Jiang union { 309bfe1d560SDave Jiang struct dsa_hw_desc *hw; 310f25b4638SDave Jiang struct iax_hw_desc *iax_hw; 311f25b4638SDave Jiang }; 312bfe1d560SDave Jiang dma_addr_t desc_dma; 313f25b4638SDave Jiang union { 314bfe1d560SDave Jiang struct dsa_completion_record *completion; 315f25b4638SDave Jiang struct iax_completion_record *iax_completion; 316f25b4638SDave Jiang }; 317bfe1d560SDave Jiang dma_addr_t compl_dma; 3188f47d1a5SDave Jiang struct dma_async_tx_descriptor txd; 319bfe1d560SDave Jiang struct llist_node llnode; 320bfe1d560SDave Jiang struct list_head list; 321bfe1d560SDave Jiang int id; 3220705107fSDave Jiang int cpu; 323bfe1d560SDave Jiang struct idxd_wq *wq; 324bfe1d560SDave Jiang }; 325bfe1d560SDave Jiang 3266b4b87f2SDave Jiang /* 3276b4b87f2SDave Jiang * This is software defined error for the completion status. We overload the error code 3286b4b87f2SDave Jiang * that will never appear in completion status and only SWERR register. 3296b4b87f2SDave Jiang */ 3306b4b87f2SDave Jiang enum idxd_completion_status { 3316b4b87f2SDave Jiang IDXD_COMP_DESC_ABORT = 0xff, 3326b4b87f2SDave Jiang }; 3336b4b87f2SDave Jiang 334700af3a0SDave Jiang #define idxd_confdev(idxd) &idxd->idxd_dev.conf_dev 335700af3a0SDave Jiang #define wq_confdev(wq) &wq->idxd_dev.conf_dev 336700af3a0SDave Jiang #define engine_confdev(engine) &engine->idxd_dev.conf_dev 337700af3a0SDave Jiang #define group_confdev(group) &group->idxd_dev.conf_dev 338700af3a0SDave Jiang #define cdev_dev(cdev) &cdev->idxd_dev.conf_dev 339700af3a0SDave Jiang 340700af3a0SDave Jiang #define confdev_to_idxd_dev(dev) container_of(dev, struct idxd_dev, conf_dev) 341fcc2281bSDave Jiang #define idxd_dev_to_idxd(idxd_dev) container_of(idxd_dev, struct idxd_device, idxd_dev) 342fcc2281bSDave Jiang #define idxd_dev_to_wq(idxd_dev) container_of(idxd_dev, struct idxd_wq, idxd_dev) 343700af3a0SDave Jiang 344700af3a0SDave Jiang static inline struct idxd_device *confdev_to_idxd(struct device *dev) 345700af3a0SDave Jiang { 346700af3a0SDave Jiang struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev); 347700af3a0SDave Jiang 348fcc2281bSDave Jiang return idxd_dev_to_idxd(idxd_dev); 349700af3a0SDave Jiang } 350700af3a0SDave Jiang 351700af3a0SDave Jiang static inline struct idxd_wq *confdev_to_wq(struct device *dev) 352700af3a0SDave Jiang { 353700af3a0SDave Jiang struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev); 354700af3a0SDave Jiang 355fcc2281bSDave Jiang return idxd_dev_to_wq(idxd_dev); 356700af3a0SDave Jiang } 357700af3a0SDave Jiang 358700af3a0SDave Jiang static inline struct idxd_engine *confdev_to_engine(struct device *dev) 359700af3a0SDave Jiang { 360700af3a0SDave Jiang struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev); 361700af3a0SDave Jiang 362700af3a0SDave Jiang return container_of(idxd_dev, struct idxd_engine, idxd_dev); 363700af3a0SDave Jiang } 364700af3a0SDave Jiang 365700af3a0SDave Jiang static inline struct idxd_group *confdev_to_group(struct device *dev) 366700af3a0SDave Jiang { 367700af3a0SDave Jiang struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev); 368700af3a0SDave Jiang 369700af3a0SDave Jiang return container_of(idxd_dev, struct idxd_group, idxd_dev); 370700af3a0SDave Jiang } 371700af3a0SDave Jiang 372700af3a0SDave Jiang static inline struct idxd_cdev *dev_to_cdev(struct device *dev) 373700af3a0SDave Jiang { 374700af3a0SDave Jiang struct idxd_dev *idxd_dev = confdev_to_idxd_dev(dev); 375700af3a0SDave Jiang 376700af3a0SDave Jiang return container_of(idxd_dev, struct idxd_cdev, idxd_dev); 377700af3a0SDave Jiang } 378700af3a0SDave Jiang 379700af3a0SDave Jiang static inline void idxd_dev_set_type(struct idxd_dev *idev, int type) 380700af3a0SDave Jiang { 381700af3a0SDave Jiang if (type >= IDXD_DEV_MAX_TYPE) { 382700af3a0SDave Jiang idev->type = IDXD_DEV_NONE; 383700af3a0SDave Jiang return; 384700af3a0SDave Jiang } 385700af3a0SDave Jiang 386700af3a0SDave Jiang idev->type = type; 387700af3a0SDave Jiang } 388bfe1d560SDave Jiang 38942d279f9SDave Jiang extern struct bus_type dsa_bus_type; 39042d279f9SDave Jiang 3918e50d392SDave Jiang extern bool support_enqcmd; 3924b73e4ebSDave Jiang extern struct ida idxd_ida; 39347c16ac2SDave Jiang extern struct device_type dsa_device_type; 39447c16ac2SDave Jiang extern struct device_type iax_device_type; 3957c5dd23eSDave Jiang extern struct device_type idxd_wq_device_type; 39675b91130SDave Jiang extern struct device_type idxd_engine_device_type; 397defe49f9SDave Jiang extern struct device_type idxd_group_device_type; 39847c16ac2SDave Jiang 399fcc2281bSDave Jiang static inline bool is_dsa_dev(struct idxd_dev *idxd_dev) 40047c16ac2SDave Jiang { 401fcc2281bSDave Jiang return idxd_dev->type == IDXD_DEV_DSA; 40247c16ac2SDave Jiang } 40347c16ac2SDave Jiang 404fcc2281bSDave Jiang static inline bool is_iax_dev(struct idxd_dev *idxd_dev) 40547c16ac2SDave Jiang { 406fcc2281bSDave Jiang return idxd_dev->type == IDXD_DEV_IAX; 40747c16ac2SDave Jiang } 40847c16ac2SDave Jiang 409fcc2281bSDave Jiang static inline bool is_idxd_dev(struct idxd_dev *idxd_dev) 41047c16ac2SDave Jiang { 411fcc2281bSDave Jiang return is_dsa_dev(idxd_dev) || is_iax_dev(idxd_dev); 41247c16ac2SDave Jiang } 4138e50d392SDave Jiang 414fcc2281bSDave Jiang static inline bool is_idxd_wq_dev(struct idxd_dev *idxd_dev) 4157c5dd23eSDave Jiang { 416fcc2281bSDave Jiang return idxd_dev->type == IDXD_DEV_WQ; 4177c5dd23eSDave Jiang } 4187c5dd23eSDave Jiang 4197c5dd23eSDave Jiang static inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq) 4207c5dd23eSDave Jiang { 4217c5dd23eSDave Jiang if (wq->type == IDXD_WQT_KERNEL && strcmp(wq->name, "dmaengine") == 0) 4227c5dd23eSDave Jiang return true; 4237c5dd23eSDave Jiang return false; 4247c5dd23eSDave Jiang } 4257c5dd23eSDave Jiang 4266e7f3ee9SDave Jiang static inline bool is_idxd_wq_user(struct idxd_wq *wq) 4277c5dd23eSDave Jiang { 4287c5dd23eSDave Jiang return wq->type == IDXD_WQT_USER; 4297c5dd23eSDave Jiang } 4307c5dd23eSDave Jiang 4316e7f3ee9SDave Jiang static inline bool is_idxd_wq_kernel(struct idxd_wq *wq) 4326e7f3ee9SDave Jiang { 4336e7f3ee9SDave Jiang return wq->type == IDXD_WQT_KERNEL; 4346e7f3ee9SDave Jiang } 4356e7f3ee9SDave Jiang 436bfe1d560SDave Jiang static inline bool wq_dedicated(struct idxd_wq *wq) 437bfe1d560SDave Jiang { 438bfe1d560SDave Jiang return test_bit(WQ_FLAG_DEDICATED, &wq->flags); 439bfe1d560SDave Jiang } 440bfe1d560SDave Jiang 4418e50d392SDave Jiang static inline bool wq_shared(struct idxd_wq *wq) 4428e50d392SDave Jiang { 4438e50d392SDave Jiang return !test_bit(WQ_FLAG_DEDICATED, &wq->flags); 4448e50d392SDave Jiang } 4458e50d392SDave Jiang 4468e50d392SDave Jiang static inline bool device_pasid_enabled(struct idxd_device *idxd) 4478e50d392SDave Jiang { 4488e50d392SDave Jiang return test_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); 4498e50d392SDave Jiang } 4508e50d392SDave Jiang 4518e50d392SDave Jiang static inline bool device_swq_supported(struct idxd_device *idxd) 4528e50d392SDave Jiang { 4538e50d392SDave Jiang return (support_enqcmd && device_pasid_enabled(idxd)); 4548e50d392SDave Jiang } 4558e50d392SDave Jiang 45642d279f9SDave Jiang enum idxd_portal_prot { 45742d279f9SDave Jiang IDXD_PORTAL_UNLIMITED = 0, 45842d279f9SDave Jiang IDXD_PORTAL_LIMITED, 45942d279f9SDave Jiang }; 46042d279f9SDave Jiang 461eb15e715SDave Jiang enum idxd_interrupt_type { 462eb15e715SDave Jiang IDXD_IRQ_MSIX = 0, 463eb15e715SDave Jiang IDXD_IRQ_IMS, 464eb15e715SDave Jiang }; 465eb15e715SDave Jiang 46642d279f9SDave Jiang static inline int idxd_get_wq_portal_offset(enum idxd_portal_prot prot) 46742d279f9SDave Jiang { 46842d279f9SDave Jiang return prot * 0x1000; 46942d279f9SDave Jiang } 47042d279f9SDave Jiang 47142d279f9SDave Jiang static inline int idxd_get_wq_portal_full_offset(int wq_id, 47242d279f9SDave Jiang enum idxd_portal_prot prot) 47342d279f9SDave Jiang { 47442d279f9SDave Jiang return ((wq_id * 4) << PAGE_SHIFT) + idxd_get_wq_portal_offset(prot); 47542d279f9SDave Jiang } 47642d279f9SDave Jiang 477a9c17152SDave Jiang #define IDXD_PORTAL_MASK (PAGE_SIZE - 1) 478a9c17152SDave Jiang 479a9c17152SDave Jiang /* 480a9c17152SDave Jiang * Even though this function can be accessed by multiple threads, it is safe to use. 481a9c17152SDave Jiang * At worst the address gets used more than once before it gets incremented. We don't 482a9c17152SDave Jiang * hit a threshold until iops becomes many million times a second. So the occasional 483a9c17152SDave Jiang * reuse of the same address is tolerable compare to using an atomic variable. This is 484a9c17152SDave Jiang * safe on a system that has atomic load/store for 32bit integers. Given that this is an 485a9c17152SDave Jiang * Intel iEP device, that should not be a problem. 486a9c17152SDave Jiang */ 487a9c17152SDave Jiang static inline void __iomem *idxd_wq_portal_addr(struct idxd_wq *wq) 488a9c17152SDave Jiang { 489a9c17152SDave Jiang int ofs = wq->portal_offset; 490a9c17152SDave Jiang 491a9c17152SDave Jiang wq->portal_offset = (ofs + sizeof(struct dsa_raw_desc)) & IDXD_PORTAL_MASK; 492a9c17152SDave Jiang return wq->portal + ofs; 493a9c17152SDave Jiang } 494a9c17152SDave Jiang 495c52ca478SDave Jiang static inline void idxd_wq_get(struct idxd_wq *wq) 496c52ca478SDave Jiang { 497c52ca478SDave Jiang wq->client_count++; 498c52ca478SDave Jiang } 499c52ca478SDave Jiang 500c52ca478SDave Jiang static inline void idxd_wq_put(struct idxd_wq *wq) 501c52ca478SDave Jiang { 502c52ca478SDave Jiang wq->client_count--; 503c52ca478SDave Jiang } 504c52ca478SDave Jiang 505c52ca478SDave Jiang static inline int idxd_wq_refcount(struct idxd_wq *wq) 506c52ca478SDave Jiang { 507c52ca478SDave Jiang return wq->client_count; 508c52ca478SDave Jiang }; 509c52ca478SDave Jiang 5103ecfc913SDave Jiang int __must_check __idxd_driver_register(struct idxd_device_driver *idxd_drv, 5113ecfc913SDave Jiang struct module *module, const char *mod_name); 5123ecfc913SDave Jiang #define idxd_driver_register(driver) \ 5133ecfc913SDave Jiang __idxd_driver_register(driver, THIS_MODULE, KBUILD_MODNAME) 5143ecfc913SDave Jiang 5153ecfc913SDave Jiang void idxd_driver_unregister(struct idxd_device_driver *idxd_drv); 5163ecfc913SDave Jiang 5176e7f3ee9SDave Jiang #define module_idxd_driver(__idxd_driver) \ 5186e7f3ee9SDave Jiang module_driver(__idxd_driver, idxd_driver_register, idxd_driver_unregister) 5196e7f3ee9SDave Jiang 520c52ca478SDave Jiang int idxd_register_bus_type(void); 521c52ca478SDave Jiang void idxd_unregister_bus_type(void); 52247c16ac2SDave Jiang int idxd_register_devices(struct idxd_device *idxd); 52347c16ac2SDave Jiang void idxd_unregister_devices(struct idxd_device *idxd); 524c52ca478SDave Jiang int idxd_register_driver(void); 525c52ca478SDave Jiang void idxd_unregister_driver(void); 5265b0c68c4SDave Jiang void idxd_wqs_quiesce(struct idxd_device *idxd); 527*f6d442f7SDave Jiang bool idxd_queue_int_handle_resubmit(struct idxd_desc *desc); 528bfe1d560SDave Jiang 529bfe1d560SDave Jiang /* device interrupt control */ 5306df0e6c5SDave Jiang void idxd_msix_perm_setup(struct idxd_device *idxd); 5316df0e6c5SDave Jiang void idxd_msix_perm_clear(struct idxd_device *idxd); 532bfe1d560SDave Jiang irqreturn_t idxd_misc_thread(int vec, void *data); 533bfe1d560SDave Jiang irqreturn_t idxd_wq_thread(int irq, void *data); 534bfe1d560SDave Jiang void idxd_mask_error_interrupts(struct idxd_device *idxd); 535bfe1d560SDave Jiang void idxd_unmask_error_interrupts(struct idxd_device *idxd); 536bfe1d560SDave Jiang void idxd_mask_msix_vectors(struct idxd_device *idxd); 5374548a6adSDave Jiang void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id); 5384548a6adSDave Jiang void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id); 539bfe1d560SDave Jiang 540bfe1d560SDave Jiang /* device control */ 541034b3290SDave Jiang int idxd_register_idxd_drv(void); 542034b3290SDave Jiang void idxd_unregister_idxd_drv(void); 543bd42805bSDave Jiang int idxd_device_drv_probe(struct idxd_dev *idxd_dev); 544745e92a6SDave Jiang void idxd_device_drv_remove(struct idxd_dev *idxd_dev); 5451f2bb403SDave Jiang int drv_enable_wq(struct idxd_wq *wq); 5460cda4f69SDave Jiang int __drv_enable_wq(struct idxd_wq *wq); 54769e4f8beSDave Jiang void drv_disable_wq(struct idxd_wq *wq); 5480cda4f69SDave Jiang void __drv_disable_wq(struct idxd_wq *wq); 54989e3becdSDave Jiang int idxd_device_init_reset(struct idxd_device *idxd); 550bfe1d560SDave Jiang int idxd_device_enable(struct idxd_device *idxd); 551bfe1d560SDave Jiang int idxd_device_disable(struct idxd_device *idxd); 5520d5c10b4SDave Jiang void idxd_device_reset(struct idxd_device *idxd); 5530dcfe41eSDave Jiang void idxd_device_clear_state(struct idxd_device *idxd); 554bfe1d560SDave Jiang int idxd_device_config(struct idxd_device *idxd); 5558e50d392SDave Jiang void idxd_device_drain_pasid(struct idxd_device *idxd, int pasid); 5568c66bbdcSDave Jiang int idxd_device_load_config(struct idxd_device *idxd); 557eb15e715SDave Jiang int idxd_device_request_int_handle(struct idxd_device *idxd, int idx, int *handle, 558eb15e715SDave Jiang enum idxd_interrupt_type irq_type); 559eb15e715SDave Jiang int idxd_device_release_int_handle(struct idxd_device *idxd, int handle, 560eb15e715SDave Jiang enum idxd_interrupt_type irq_type); 561bfe1d560SDave Jiang 562bfe1d560SDave Jiang /* work queue control */ 5635b0c68c4SDave Jiang void idxd_wqs_unmap_portal(struct idxd_device *idxd); 564bfe1d560SDave Jiang int idxd_wq_alloc_resources(struct idxd_wq *wq); 565bfe1d560SDave Jiang void idxd_wq_free_resources(struct idxd_wq *wq); 566bfe1d560SDave Jiang int idxd_wq_enable(struct idxd_wq *wq); 5670dcfe41eSDave Jiang int idxd_wq_disable(struct idxd_wq *wq, bool reset_config); 5680d5c10b4SDave Jiang void idxd_wq_drain(struct idxd_wq *wq); 569ea9aadc0SDave Jiang void idxd_wq_reset(struct idxd_wq *wq); 570c52ca478SDave Jiang int idxd_wq_map_portal(struct idxd_wq *wq); 571c52ca478SDave Jiang void idxd_wq_unmap_portal(struct idxd_wq *wq); 5728e50d392SDave Jiang int idxd_wq_set_pasid(struct idxd_wq *wq, int pasid); 5738e50d392SDave Jiang int idxd_wq_disable_pasid(struct idxd_wq *wq); 574bd5970a0SDave Jiang void __idxd_wq_quiesce(struct idxd_wq *wq); 57593a40a6dSDave Jiang void idxd_wq_quiesce(struct idxd_wq *wq); 57693a40a6dSDave Jiang int idxd_wq_init_percpu_ref(struct idxd_wq *wq); 577bfe1d560SDave Jiang 578d1dfe5b8SDave Jiang /* submission */ 579d1dfe5b8SDave Jiang int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc); 580d1dfe5b8SDave Jiang struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype); 581d1dfe5b8SDave Jiang void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc); 582d1dfe5b8SDave Jiang 5838f47d1a5SDave Jiang /* dmaengine */ 5848f47d1a5SDave Jiang int idxd_register_dma_device(struct idxd_device *idxd); 5858f47d1a5SDave Jiang void idxd_unregister_dma_device(struct idxd_device *idxd); 5868f47d1a5SDave Jiang int idxd_register_dma_channel(struct idxd_wq *wq); 5878f47d1a5SDave Jiang void idxd_unregister_dma_channel(struct idxd_wq *wq); 5888f47d1a5SDave Jiang void idxd_parse_completion_status(u8 status, enum dmaengine_tx_result *res); 5898f47d1a5SDave Jiang void idxd_dma_complete_txd(struct idxd_desc *desc, 5905d78abb6SDave Jiang enum idxd_complete_type comp_type, bool free_desc); 5918f47d1a5SDave Jiang 59242d279f9SDave Jiang /* cdev */ 59342d279f9SDave Jiang int idxd_cdev_register(void); 59442d279f9SDave Jiang void idxd_cdev_remove(void); 59542d279f9SDave Jiang int idxd_cdev_get_major(struct idxd_device *idxd); 59642d279f9SDave Jiang int idxd_wq_add_cdev(struct idxd_wq *wq); 59742d279f9SDave Jiang void idxd_wq_del_cdev(struct idxd_wq *wq); 59842d279f9SDave Jiang 59981dd4d4dSTom Zanussi /* perfmon */ 60081dd4d4dSTom Zanussi #if IS_ENABLED(CONFIG_INTEL_IDXD_PERFMON) 60181dd4d4dSTom Zanussi int perfmon_pmu_init(struct idxd_device *idxd); 60281dd4d4dSTom Zanussi void perfmon_pmu_remove(struct idxd_device *idxd); 60381dd4d4dSTom Zanussi void perfmon_counter_overflow(struct idxd_device *idxd); 60481dd4d4dSTom Zanussi void perfmon_init(void); 60581dd4d4dSTom Zanussi void perfmon_exit(void); 60681dd4d4dSTom Zanussi #else 60781dd4d4dSTom Zanussi static inline int perfmon_pmu_init(struct idxd_device *idxd) { return 0; } 60881dd4d4dSTom Zanussi static inline void perfmon_pmu_remove(struct idxd_device *idxd) {} 60981dd4d4dSTom Zanussi static inline void perfmon_counter_overflow(struct idxd_device *idxd) {} 61081dd4d4dSTom Zanussi static inline void perfmon_init(void) {} 61181dd4d4dSTom Zanussi static inline void perfmon_exit(void) {} 61281dd4d4dSTom Zanussi #endif 61381dd4d4dSTom Zanussi 614bfe1d560SDave Jiang #endif 615