18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2019 Intel Corporation. All rights rsvd. */ 38c2ecf20Sopenharmony_ci#include <linux/init.h> 48c2ecf20Sopenharmony_ci#include <linux/kernel.h> 58c2ecf20Sopenharmony_ci#include <linux/module.h> 68c2ecf20Sopenharmony_ci#include <linux/pci.h> 78c2ecf20Sopenharmony_ci#include <linux/device.h> 88c2ecf20Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h> 98c2ecf20Sopenharmony_ci#include <uapi/linux/idxd.h> 108c2ecf20Sopenharmony_ci#include "registers.h" 118c2ecf20Sopenharmony_ci#include "idxd.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_cistatic char *idxd_wq_type_names[] = { 148c2ecf20Sopenharmony_ci [IDXD_WQT_NONE] = "none", 158c2ecf20Sopenharmony_ci [IDXD_WQT_KERNEL] = "kernel", 168c2ecf20Sopenharmony_ci [IDXD_WQT_USER] = "user", 178c2ecf20Sopenharmony_ci}; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic void idxd_conf_device_release(struct device *dev) 208c2ecf20Sopenharmony_ci{ 218c2ecf20Sopenharmony_ci dev_dbg(dev, "%s for %s\n", __func__, dev_name(dev)); 228c2ecf20Sopenharmony_ci} 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistatic struct device_type idxd_group_device_type = { 258c2ecf20Sopenharmony_ci .name = "group", 268c2ecf20Sopenharmony_ci .release = idxd_conf_device_release, 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic struct device_type idxd_wq_device_type = { 308c2ecf20Sopenharmony_ci .name = "wq", 318c2ecf20Sopenharmony_ci .release = idxd_conf_device_release, 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic struct device_type idxd_engine_device_type = { 358c2ecf20Sopenharmony_ci .name = "engine", 368c2ecf20Sopenharmony_ci .release = idxd_conf_device_release, 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic struct device_type dsa_device_type = { 408c2ecf20Sopenharmony_ci .name = "dsa", 418c2ecf20Sopenharmony_ci .release = idxd_conf_device_release, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic inline bool is_dsa_dev(struct device *dev) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci return dev ? dev->type == &dsa_device_type : false; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic inline bool is_idxd_dev(struct device *dev) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci return is_dsa_dev(dev); 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic inline bool is_idxd_wq_dev(struct device *dev) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci return dev ? dev->type == &idxd_wq_device_type : false; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic inline bool is_idxd_wq_dmaengine(struct idxd_wq *wq) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci if (wq->type == IDXD_WQT_KERNEL && 628c2ecf20Sopenharmony_ci strcmp(wq->name, "dmaengine") == 0) 638c2ecf20Sopenharmony_ci return true; 648c2ecf20Sopenharmony_ci return false; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic inline bool is_idxd_wq_cdev(struct idxd_wq *wq) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci return wq->type == IDXD_WQT_USER; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic int idxd_config_bus_match(struct device *dev, 738c2ecf20Sopenharmony_ci struct device_driver *drv) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci int matched = 0; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (is_idxd_dev(dev)) { 788c2ecf20Sopenharmony_ci struct idxd_device *idxd = confdev_to_idxd(dev); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (idxd->state != IDXD_DEV_CONF_READY) 818c2ecf20Sopenharmony_ci return 0; 828c2ecf20Sopenharmony_ci matched = 1; 838c2ecf20Sopenharmony_ci } else if (is_idxd_wq_dev(dev)) { 848c2ecf20Sopenharmony_ci struct idxd_wq *wq = confdev_to_wq(dev); 858c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (idxd->state < IDXD_DEV_CONF_READY) 888c2ecf20Sopenharmony_ci return 0; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) { 918c2ecf20Sopenharmony_ci dev_dbg(dev, "%s not disabled\n", dev_name(dev)); 928c2ecf20Sopenharmony_ci return 0; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci matched = 1; 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (matched) 988c2ecf20Sopenharmony_ci dev_dbg(dev, "%s matched\n", dev_name(dev)); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci return matched; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic int idxd_config_bus_probe(struct device *dev) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci int rc; 1068c2ecf20Sopenharmony_ci unsigned long flags; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci dev_dbg(dev, "%s called\n", __func__); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (is_idxd_dev(dev)) { 1118c2ecf20Sopenharmony_ci struct idxd_device *idxd = confdev_to_idxd(dev); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci if (idxd->state != IDXD_DEV_CONF_READY) { 1148c2ecf20Sopenharmony_ci dev_warn(dev, "Device not ready for config\n"); 1158c2ecf20Sopenharmony_ci return -EBUSY; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (!try_module_get(THIS_MODULE)) 1198c2ecf20Sopenharmony_ci return -ENXIO; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* Perform IDXD configuration and enabling */ 1228c2ecf20Sopenharmony_ci spin_lock_irqsave(&idxd->dev_lock, flags); 1238c2ecf20Sopenharmony_ci rc = idxd_device_config(idxd); 1248c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&idxd->dev_lock, flags); 1258c2ecf20Sopenharmony_ci if (rc < 0) { 1268c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 1278c2ecf20Sopenharmony_ci dev_warn(dev, "Device config failed: %d\n", rc); 1288c2ecf20Sopenharmony_ci return rc; 1298c2ecf20Sopenharmony_ci } 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* start device */ 1328c2ecf20Sopenharmony_ci rc = idxd_device_enable(idxd); 1338c2ecf20Sopenharmony_ci if (rc < 0) { 1348c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 1358c2ecf20Sopenharmony_ci dev_warn(dev, "Device enable failed: %d\n", rc); 1368c2ecf20Sopenharmony_ci return rc; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci dev_info(dev, "Device %s enabled\n", dev_name(dev)); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci rc = idxd_register_dma_device(idxd); 1428c2ecf20Sopenharmony_ci if (rc < 0) { 1438c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 1448c2ecf20Sopenharmony_ci dev_dbg(dev, "Failed to register dmaengine device\n"); 1458c2ecf20Sopenharmony_ci return rc; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci return 0; 1488c2ecf20Sopenharmony_ci } else if (is_idxd_wq_dev(dev)) { 1498c2ecf20Sopenharmony_ci struct idxd_wq *wq = confdev_to_wq(dev); 1508c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci mutex_lock(&wq->wq_lock); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (idxd->state != IDXD_DEV_ENABLED) { 1558c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1568c2ecf20Sopenharmony_ci dev_warn(dev, "Enabling while device not enabled.\n"); 1578c2ecf20Sopenharmony_ci return -EPERM; 1588c2ecf20Sopenharmony_ci } 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) { 1618c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1628c2ecf20Sopenharmony_ci dev_warn(dev, "WQ %d already enabled.\n", wq->id); 1638c2ecf20Sopenharmony_ci return -EBUSY; 1648c2ecf20Sopenharmony_ci } 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci if (!wq->group) { 1678c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1688c2ecf20Sopenharmony_ci dev_warn(dev, "WQ not attached to group.\n"); 1698c2ecf20Sopenharmony_ci return -EINVAL; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci if (strlen(wq->name) == 0) { 1738c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1748c2ecf20Sopenharmony_ci dev_warn(dev, "WQ name not set.\n"); 1758c2ecf20Sopenharmony_ci return -EINVAL; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci rc = idxd_wq_alloc_resources(wq); 1798c2ecf20Sopenharmony_ci if (rc < 0) { 1808c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1818c2ecf20Sopenharmony_ci dev_warn(dev, "WQ resource alloc failed\n"); 1828c2ecf20Sopenharmony_ci return rc; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci spin_lock_irqsave(&idxd->dev_lock, flags); 1868c2ecf20Sopenharmony_ci rc = idxd_device_config(idxd); 1878c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&idxd->dev_lock, flags); 1888c2ecf20Sopenharmony_ci if (rc < 0) { 1898c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1908c2ecf20Sopenharmony_ci dev_warn(dev, "Writing WQ %d config failed: %d\n", 1918c2ecf20Sopenharmony_ci wq->id, rc); 1928c2ecf20Sopenharmony_ci return rc; 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci rc = idxd_wq_enable(wq); 1968c2ecf20Sopenharmony_ci if (rc < 0) { 1978c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 1988c2ecf20Sopenharmony_ci dev_warn(dev, "WQ %d enabling failed: %d\n", 1998c2ecf20Sopenharmony_ci wq->id, rc); 2008c2ecf20Sopenharmony_ci return rc; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci rc = idxd_wq_map_portal(wq); 2048c2ecf20Sopenharmony_ci if (rc < 0) { 2058c2ecf20Sopenharmony_ci dev_warn(dev, "wq portal mapping failed: %d\n", rc); 2068c2ecf20Sopenharmony_ci rc = idxd_wq_disable(wq); 2078c2ecf20Sopenharmony_ci if (rc < 0) 2088c2ecf20Sopenharmony_ci dev_warn(dev, "IDXD wq disable failed\n"); 2098c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 2108c2ecf20Sopenharmony_ci return rc; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci wq->client_count = 0; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci dev_info(dev, "wq %s enabled\n", dev_name(&wq->conf_dev)); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (is_idxd_wq_dmaengine(wq)) { 2188c2ecf20Sopenharmony_ci rc = idxd_register_dma_channel(wq); 2198c2ecf20Sopenharmony_ci if (rc < 0) { 2208c2ecf20Sopenharmony_ci dev_dbg(dev, "DMA channel register failed\n"); 2218c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 2228c2ecf20Sopenharmony_ci return rc; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci } else if (is_idxd_wq_cdev(wq)) { 2258c2ecf20Sopenharmony_ci rc = idxd_wq_add_cdev(wq); 2268c2ecf20Sopenharmony_ci if (rc < 0) { 2278c2ecf20Sopenharmony_ci dev_dbg(dev, "Cdev creation failed\n"); 2288c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 2298c2ecf20Sopenharmony_ci return rc; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 2348c2ecf20Sopenharmony_ci return 0; 2358c2ecf20Sopenharmony_ci } 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci return -ENODEV; 2388c2ecf20Sopenharmony_ci} 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_cistatic void disable_wq(struct idxd_wq *wq) 2418c2ecf20Sopenharmony_ci{ 2428c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 2438c2ecf20Sopenharmony_ci struct device *dev = &idxd->pdev->dev; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci mutex_lock(&wq->wq_lock); 2468c2ecf20Sopenharmony_ci dev_dbg(dev, "%s removing WQ %s\n", __func__, dev_name(&wq->conf_dev)); 2478c2ecf20Sopenharmony_ci if (wq->state == IDXD_WQ_DISABLED) { 2488c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 2498c2ecf20Sopenharmony_ci return; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (is_idxd_wq_dmaengine(wq)) 2538c2ecf20Sopenharmony_ci idxd_unregister_dma_channel(wq); 2548c2ecf20Sopenharmony_ci else if (is_idxd_wq_cdev(wq)) 2558c2ecf20Sopenharmony_ci idxd_wq_del_cdev(wq); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (idxd_wq_refcount(wq)) 2588c2ecf20Sopenharmony_ci dev_warn(dev, "Clients has claim on wq %d: %d\n", 2598c2ecf20Sopenharmony_ci wq->id, idxd_wq_refcount(wq)); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci idxd_wq_unmap_portal(wq); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci idxd_wq_drain(wq); 2648c2ecf20Sopenharmony_ci idxd_wq_reset(wq); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci idxd_wq_free_resources(wq); 2678c2ecf20Sopenharmony_ci wq->client_count = 0; 2688c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci dev_info(dev, "wq %s disabled\n", dev_name(&wq->conf_dev)); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic int idxd_config_bus_remove(struct device *dev) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci int rc; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci dev_dbg(dev, "%s called for %s\n", __func__, dev_name(dev)); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci /* disable workqueue here */ 2808c2ecf20Sopenharmony_ci if (is_idxd_wq_dev(dev)) { 2818c2ecf20Sopenharmony_ci struct idxd_wq *wq = confdev_to_wq(dev); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci disable_wq(wq); 2848c2ecf20Sopenharmony_ci } else if (is_idxd_dev(dev)) { 2858c2ecf20Sopenharmony_ci struct idxd_device *idxd = confdev_to_idxd(dev); 2868c2ecf20Sopenharmony_ci int i; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci dev_dbg(dev, "%s removing dev %s\n", __func__, 2898c2ecf20Sopenharmony_ci dev_name(&idxd->conf_dev)); 2908c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 2918c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci if (wq->state == IDXD_WQ_DISABLED) 2948c2ecf20Sopenharmony_ci continue; 2958c2ecf20Sopenharmony_ci dev_warn(dev, "Active wq %d on disable %s.\n", i, 2968c2ecf20Sopenharmony_ci dev_name(&idxd->conf_dev)); 2978c2ecf20Sopenharmony_ci device_release_driver(&wq->conf_dev); 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci idxd_unregister_dma_device(idxd); 3018c2ecf20Sopenharmony_ci rc = idxd_device_disable(idxd); 3028c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 3038c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci mutex_lock(&wq->wq_lock); 3068c2ecf20Sopenharmony_ci idxd_wq_disable_cleanup(wq); 3078c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 3108c2ecf20Sopenharmony_ci if (rc < 0) 3118c2ecf20Sopenharmony_ci dev_warn(dev, "Device disable failed\n"); 3128c2ecf20Sopenharmony_ci else 3138c2ecf20Sopenharmony_ci dev_info(dev, "Device %s disabled\n", dev_name(dev)); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci return 0; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic void idxd_config_bus_shutdown(struct device *dev) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci dev_dbg(dev, "%s called\n", __func__); 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistruct bus_type dsa_bus_type = { 3268c2ecf20Sopenharmony_ci .name = "dsa", 3278c2ecf20Sopenharmony_ci .match = idxd_config_bus_match, 3288c2ecf20Sopenharmony_ci .probe = idxd_config_bus_probe, 3298c2ecf20Sopenharmony_ci .remove = idxd_config_bus_remove, 3308c2ecf20Sopenharmony_ci .shutdown = idxd_config_bus_shutdown, 3318c2ecf20Sopenharmony_ci}; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic struct bus_type *idxd_bus_types[] = { 3348c2ecf20Sopenharmony_ci &dsa_bus_type 3358c2ecf20Sopenharmony_ci}; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic struct idxd_device_driver dsa_drv = { 3388c2ecf20Sopenharmony_ci .drv = { 3398c2ecf20Sopenharmony_ci .name = "dsa", 3408c2ecf20Sopenharmony_ci .bus = &dsa_bus_type, 3418c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3428c2ecf20Sopenharmony_ci .mod_name = KBUILD_MODNAME, 3438c2ecf20Sopenharmony_ci }, 3448c2ecf20Sopenharmony_ci}; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic struct idxd_device_driver *idxd_drvs[] = { 3478c2ecf20Sopenharmony_ci &dsa_drv 3488c2ecf20Sopenharmony_ci}; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistruct bus_type *idxd_get_bus_type(struct idxd_device *idxd) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci return idxd_bus_types[idxd->type]; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic struct device_type *idxd_get_device_type(struct idxd_device *idxd) 3568c2ecf20Sopenharmony_ci{ 3578c2ecf20Sopenharmony_ci if (idxd->type == IDXD_TYPE_DSA) 3588c2ecf20Sopenharmony_ci return &dsa_device_type; 3598c2ecf20Sopenharmony_ci else 3608c2ecf20Sopenharmony_ci return NULL; 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci/* IDXD generic driver setup */ 3648c2ecf20Sopenharmony_ciint idxd_register_driver(void) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci int i, rc; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci for (i = 0; i < IDXD_TYPE_MAX; i++) { 3698c2ecf20Sopenharmony_ci rc = driver_register(&idxd_drvs[i]->drv); 3708c2ecf20Sopenharmony_ci if (rc < 0) 3718c2ecf20Sopenharmony_ci goto drv_fail; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci return 0; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cidrv_fail: 3778c2ecf20Sopenharmony_ci while (--i >= 0) 3788c2ecf20Sopenharmony_ci driver_unregister(&idxd_drvs[i]->drv); 3798c2ecf20Sopenharmony_ci return rc; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_civoid idxd_unregister_driver(void) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci int i; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci for (i = 0; i < IDXD_TYPE_MAX; i++) 3878c2ecf20Sopenharmony_ci driver_unregister(&idxd_drvs[i]->drv); 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci/* IDXD engine attributes */ 3918c2ecf20Sopenharmony_cistatic ssize_t engine_group_id_show(struct device *dev, 3928c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci struct idxd_engine *engine = 3958c2ecf20Sopenharmony_ci container_of(dev, struct idxd_engine, conf_dev); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci if (engine->group) 3988c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", engine->group->id); 3998c2ecf20Sopenharmony_ci else 4008c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", -1); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic ssize_t engine_group_id_store(struct device *dev, 4048c2ecf20Sopenharmony_ci struct device_attribute *attr, 4058c2ecf20Sopenharmony_ci const char *buf, size_t count) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci struct idxd_engine *engine = 4088c2ecf20Sopenharmony_ci container_of(dev, struct idxd_engine, conf_dev); 4098c2ecf20Sopenharmony_ci struct idxd_device *idxd = engine->idxd; 4108c2ecf20Sopenharmony_ci long id; 4118c2ecf20Sopenharmony_ci int rc; 4128c2ecf20Sopenharmony_ci struct idxd_group *prevg; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci rc = kstrtol(buf, 10, &id); 4158c2ecf20Sopenharmony_ci if (rc < 0) 4168c2ecf20Sopenharmony_ci return -EINVAL; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 4198c2ecf20Sopenharmony_ci return -EPERM; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (id > idxd->max_groups - 1 || id < -1) 4228c2ecf20Sopenharmony_ci return -EINVAL; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci if (id == -1) { 4258c2ecf20Sopenharmony_ci if (engine->group) { 4268c2ecf20Sopenharmony_ci engine->group->num_engines--; 4278c2ecf20Sopenharmony_ci engine->group = NULL; 4288c2ecf20Sopenharmony_ci } 4298c2ecf20Sopenharmony_ci return count; 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci prevg = engine->group; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci if (prevg) 4358c2ecf20Sopenharmony_ci prevg->num_engines--; 4368c2ecf20Sopenharmony_ci engine->group = &idxd->groups[id]; 4378c2ecf20Sopenharmony_ci engine->group->num_engines++; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci return count; 4408c2ecf20Sopenharmony_ci} 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_engine_group = 4438c2ecf20Sopenharmony_ci __ATTR(group_id, 0644, engine_group_id_show, 4448c2ecf20Sopenharmony_ci engine_group_id_store); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic struct attribute *idxd_engine_attributes[] = { 4478c2ecf20Sopenharmony_ci &dev_attr_engine_group.attr, 4488c2ecf20Sopenharmony_ci NULL, 4498c2ecf20Sopenharmony_ci}; 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic const struct attribute_group idxd_engine_attribute_group = { 4528c2ecf20Sopenharmony_ci .attrs = idxd_engine_attributes, 4538c2ecf20Sopenharmony_ci}; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic const struct attribute_group *idxd_engine_attribute_groups[] = { 4568c2ecf20Sopenharmony_ci &idxd_engine_attribute_group, 4578c2ecf20Sopenharmony_ci NULL, 4588c2ecf20Sopenharmony_ci}; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci/* Group attributes */ 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic void idxd_set_free_tokens(struct idxd_device *idxd) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci int i, tokens; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci for (i = 0, tokens = 0; i < idxd->max_groups; i++) { 4678c2ecf20Sopenharmony_ci struct idxd_group *g = &idxd->groups[i]; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci tokens += g->tokens_reserved; 4708c2ecf20Sopenharmony_ci } 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci idxd->nr_tokens = idxd->max_tokens - tokens; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic ssize_t group_tokens_reserved_show(struct device *dev, 4768c2ecf20Sopenharmony_ci struct device_attribute *attr, 4778c2ecf20Sopenharmony_ci char *buf) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci struct idxd_group *group = 4808c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", group->tokens_reserved); 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistatic ssize_t group_tokens_reserved_store(struct device *dev, 4868c2ecf20Sopenharmony_ci struct device_attribute *attr, 4878c2ecf20Sopenharmony_ci const char *buf, size_t count) 4888c2ecf20Sopenharmony_ci{ 4898c2ecf20Sopenharmony_ci struct idxd_group *group = 4908c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 4918c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 4928c2ecf20Sopenharmony_ci unsigned long val; 4938c2ecf20Sopenharmony_ci int rc; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci rc = kstrtoul(buf, 10, &val); 4968c2ecf20Sopenharmony_ci if (rc < 0) 4978c2ecf20Sopenharmony_ci return -EINVAL; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 5008c2ecf20Sopenharmony_ci return -EPERM; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 5038c2ecf20Sopenharmony_ci return -EPERM; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (val > idxd->max_tokens) 5068c2ecf20Sopenharmony_ci return -EINVAL; 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (val > idxd->nr_tokens + group->tokens_reserved) 5098c2ecf20Sopenharmony_ci return -EINVAL; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci group->tokens_reserved = val; 5128c2ecf20Sopenharmony_ci idxd_set_free_tokens(idxd); 5138c2ecf20Sopenharmony_ci return count; 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_tokens_reserved = 5178c2ecf20Sopenharmony_ci __ATTR(tokens_reserved, 0644, group_tokens_reserved_show, 5188c2ecf20Sopenharmony_ci group_tokens_reserved_store); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic ssize_t group_tokens_allowed_show(struct device *dev, 5218c2ecf20Sopenharmony_ci struct device_attribute *attr, 5228c2ecf20Sopenharmony_ci char *buf) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci struct idxd_group *group = 5258c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", group->tokens_allowed); 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic ssize_t group_tokens_allowed_store(struct device *dev, 5318c2ecf20Sopenharmony_ci struct device_attribute *attr, 5328c2ecf20Sopenharmony_ci const char *buf, size_t count) 5338c2ecf20Sopenharmony_ci{ 5348c2ecf20Sopenharmony_ci struct idxd_group *group = 5358c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 5368c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 5378c2ecf20Sopenharmony_ci unsigned long val; 5388c2ecf20Sopenharmony_ci int rc; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci rc = kstrtoul(buf, 10, &val); 5418c2ecf20Sopenharmony_ci if (rc < 0) 5428c2ecf20Sopenharmony_ci return -EINVAL; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 5458c2ecf20Sopenharmony_ci return -EPERM; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 5488c2ecf20Sopenharmony_ci return -EPERM; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (val < 4 * group->num_engines || 5518c2ecf20Sopenharmony_ci val > group->tokens_reserved + idxd->nr_tokens) 5528c2ecf20Sopenharmony_ci return -EINVAL; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci group->tokens_allowed = val; 5558c2ecf20Sopenharmony_ci return count; 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_tokens_allowed = 5598c2ecf20Sopenharmony_ci __ATTR(tokens_allowed, 0644, group_tokens_allowed_show, 5608c2ecf20Sopenharmony_ci group_tokens_allowed_store); 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_cistatic ssize_t group_use_token_limit_show(struct device *dev, 5638c2ecf20Sopenharmony_ci struct device_attribute *attr, 5648c2ecf20Sopenharmony_ci char *buf) 5658c2ecf20Sopenharmony_ci{ 5668c2ecf20Sopenharmony_ci struct idxd_group *group = 5678c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", group->use_token_limit); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic ssize_t group_use_token_limit_store(struct device *dev, 5738c2ecf20Sopenharmony_ci struct device_attribute *attr, 5748c2ecf20Sopenharmony_ci const char *buf, size_t count) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci struct idxd_group *group = 5778c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 5788c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 5798c2ecf20Sopenharmony_ci unsigned long val; 5808c2ecf20Sopenharmony_ci int rc; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci rc = kstrtoul(buf, 10, &val); 5838c2ecf20Sopenharmony_ci if (rc < 0) 5848c2ecf20Sopenharmony_ci return -EINVAL; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 5878c2ecf20Sopenharmony_ci return -EPERM; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 5908c2ecf20Sopenharmony_ci return -EPERM; 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci if (idxd->token_limit == 0) 5938c2ecf20Sopenharmony_ci return -EPERM; 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci group->use_token_limit = !!val; 5968c2ecf20Sopenharmony_ci return count; 5978c2ecf20Sopenharmony_ci} 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_use_token_limit = 6008c2ecf20Sopenharmony_ci __ATTR(use_token_limit, 0644, group_use_token_limit_show, 6018c2ecf20Sopenharmony_ci group_use_token_limit_store); 6028c2ecf20Sopenharmony_ci 6038c2ecf20Sopenharmony_cistatic ssize_t group_engines_show(struct device *dev, 6048c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6058c2ecf20Sopenharmony_ci{ 6068c2ecf20Sopenharmony_ci struct idxd_group *group = 6078c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 6088c2ecf20Sopenharmony_ci int i, rc = 0; 6098c2ecf20Sopenharmony_ci char *tmp = buf; 6108c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_engines; i++) { 6138c2ecf20Sopenharmony_ci struct idxd_engine *engine = &idxd->engines[i]; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci if (!engine->group) 6168c2ecf20Sopenharmony_ci continue; 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci if (engine->group->id == group->id) 6198c2ecf20Sopenharmony_ci rc += sprintf(tmp + rc, "engine%d.%d ", 6208c2ecf20Sopenharmony_ci idxd->id, engine->id); 6218c2ecf20Sopenharmony_ci } 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci rc--; 6248c2ecf20Sopenharmony_ci rc += sprintf(tmp + rc, "\n"); 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci return rc; 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_engines = 6308c2ecf20Sopenharmony_ci __ATTR(engines, 0444, group_engines_show, NULL); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_cistatic ssize_t group_work_queues_show(struct device *dev, 6338c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci struct idxd_group *group = 6368c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 6378c2ecf20Sopenharmony_ci int i, rc = 0; 6388c2ecf20Sopenharmony_ci char *tmp = buf; 6398c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 6428c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci if (!wq->group) 6458c2ecf20Sopenharmony_ci continue; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci if (wq->group->id == group->id) 6488c2ecf20Sopenharmony_ci rc += sprintf(tmp + rc, "wq%d.%d ", 6498c2ecf20Sopenharmony_ci idxd->id, wq->id); 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci rc--; 6538c2ecf20Sopenharmony_ci rc += sprintf(tmp + rc, "\n"); 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci return rc; 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_work_queues = 6598c2ecf20Sopenharmony_ci __ATTR(work_queues, 0444, group_work_queues_show, NULL); 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_cistatic ssize_t group_traffic_class_a_show(struct device *dev, 6628c2ecf20Sopenharmony_ci struct device_attribute *attr, 6638c2ecf20Sopenharmony_ci char *buf) 6648c2ecf20Sopenharmony_ci{ 6658c2ecf20Sopenharmony_ci struct idxd_group *group = 6668c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", group->tc_a); 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_cistatic ssize_t group_traffic_class_a_store(struct device *dev, 6728c2ecf20Sopenharmony_ci struct device_attribute *attr, 6738c2ecf20Sopenharmony_ci const char *buf, size_t count) 6748c2ecf20Sopenharmony_ci{ 6758c2ecf20Sopenharmony_ci struct idxd_group *group = 6768c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 6778c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 6788c2ecf20Sopenharmony_ci long val; 6798c2ecf20Sopenharmony_ci int rc; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci rc = kstrtol(buf, 10, &val); 6828c2ecf20Sopenharmony_ci if (rc < 0) 6838c2ecf20Sopenharmony_ci return -EINVAL; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 6868c2ecf20Sopenharmony_ci return -EPERM; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 6898c2ecf20Sopenharmony_ci return -EPERM; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci if (val < 0 || val > 7) 6928c2ecf20Sopenharmony_ci return -EINVAL; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci group->tc_a = val; 6958c2ecf20Sopenharmony_ci return count; 6968c2ecf20Sopenharmony_ci} 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_traffic_class_a = 6998c2ecf20Sopenharmony_ci __ATTR(traffic_class_a, 0644, group_traffic_class_a_show, 7008c2ecf20Sopenharmony_ci group_traffic_class_a_store); 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_cistatic ssize_t group_traffic_class_b_show(struct device *dev, 7038c2ecf20Sopenharmony_ci struct device_attribute *attr, 7048c2ecf20Sopenharmony_ci char *buf) 7058c2ecf20Sopenharmony_ci{ 7068c2ecf20Sopenharmony_ci struct idxd_group *group = 7078c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", group->tc_b); 7108c2ecf20Sopenharmony_ci} 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic ssize_t group_traffic_class_b_store(struct device *dev, 7138c2ecf20Sopenharmony_ci struct device_attribute *attr, 7148c2ecf20Sopenharmony_ci const char *buf, size_t count) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci struct idxd_group *group = 7178c2ecf20Sopenharmony_ci container_of(dev, struct idxd_group, conf_dev); 7188c2ecf20Sopenharmony_ci struct idxd_device *idxd = group->idxd; 7198c2ecf20Sopenharmony_ci long val; 7208c2ecf20Sopenharmony_ci int rc; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci rc = kstrtol(buf, 10, &val); 7238c2ecf20Sopenharmony_ci if (rc < 0) 7248c2ecf20Sopenharmony_ci return -EINVAL; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 7278c2ecf20Sopenharmony_ci return -EPERM; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 7308c2ecf20Sopenharmony_ci return -EPERM; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci if (val < 0 || val > 7) 7338c2ecf20Sopenharmony_ci return -EINVAL; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci group->tc_b = val; 7368c2ecf20Sopenharmony_ci return count; 7378c2ecf20Sopenharmony_ci} 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_group_traffic_class_b = 7408c2ecf20Sopenharmony_ci __ATTR(traffic_class_b, 0644, group_traffic_class_b_show, 7418c2ecf20Sopenharmony_ci group_traffic_class_b_store); 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic struct attribute *idxd_group_attributes[] = { 7448c2ecf20Sopenharmony_ci &dev_attr_group_work_queues.attr, 7458c2ecf20Sopenharmony_ci &dev_attr_group_engines.attr, 7468c2ecf20Sopenharmony_ci &dev_attr_group_use_token_limit.attr, 7478c2ecf20Sopenharmony_ci &dev_attr_group_tokens_allowed.attr, 7488c2ecf20Sopenharmony_ci &dev_attr_group_tokens_reserved.attr, 7498c2ecf20Sopenharmony_ci &dev_attr_group_traffic_class_a.attr, 7508c2ecf20Sopenharmony_ci &dev_attr_group_traffic_class_b.attr, 7518c2ecf20Sopenharmony_ci NULL, 7528c2ecf20Sopenharmony_ci}; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_cistatic const struct attribute_group idxd_group_attribute_group = { 7558c2ecf20Sopenharmony_ci .attrs = idxd_group_attributes, 7568c2ecf20Sopenharmony_ci}; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_cistatic const struct attribute_group *idxd_group_attribute_groups[] = { 7598c2ecf20Sopenharmony_ci &idxd_group_attribute_group, 7608c2ecf20Sopenharmony_ci NULL, 7618c2ecf20Sopenharmony_ci}; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci/* IDXD work queue attribs */ 7648c2ecf20Sopenharmony_cistatic ssize_t wq_clients_show(struct device *dev, 7658c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", wq->client_count); 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_clients = 7738c2ecf20Sopenharmony_ci __ATTR(clients, 0444, wq_clients_show, NULL); 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_cistatic ssize_t wq_state_show(struct device *dev, 7768c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 7778c2ecf20Sopenharmony_ci{ 7788c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci switch (wq->state) { 7818c2ecf20Sopenharmony_ci case IDXD_WQ_DISABLED: 7828c2ecf20Sopenharmony_ci return sprintf(buf, "disabled\n"); 7838c2ecf20Sopenharmony_ci case IDXD_WQ_ENABLED: 7848c2ecf20Sopenharmony_ci return sprintf(buf, "enabled\n"); 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci return sprintf(buf, "unknown\n"); 7888c2ecf20Sopenharmony_ci} 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_state = 7918c2ecf20Sopenharmony_ci __ATTR(state, 0444, wq_state_show, NULL); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_cistatic ssize_t wq_group_id_show(struct device *dev, 7948c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci if (wq->group) 7998c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", wq->group->id); 8008c2ecf20Sopenharmony_ci else 8018c2ecf20Sopenharmony_ci return sprintf(buf, "-1\n"); 8028c2ecf20Sopenharmony_ci} 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_cistatic ssize_t wq_group_id_store(struct device *dev, 8058c2ecf20Sopenharmony_ci struct device_attribute *attr, 8068c2ecf20Sopenharmony_ci const char *buf, size_t count) 8078c2ecf20Sopenharmony_ci{ 8088c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 8098c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 8108c2ecf20Sopenharmony_ci long id; 8118c2ecf20Sopenharmony_ci int rc; 8128c2ecf20Sopenharmony_ci struct idxd_group *prevg, *group; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci rc = kstrtol(buf, 10, &id); 8158c2ecf20Sopenharmony_ci if (rc < 0) 8168c2ecf20Sopenharmony_ci return -EINVAL; 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 8198c2ecf20Sopenharmony_ci return -EPERM; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 8228c2ecf20Sopenharmony_ci return -EPERM; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci if (id > idxd->max_groups - 1 || id < -1) 8258c2ecf20Sopenharmony_ci return -EINVAL; 8268c2ecf20Sopenharmony_ci 8278c2ecf20Sopenharmony_ci if (id == -1) { 8288c2ecf20Sopenharmony_ci if (wq->group) { 8298c2ecf20Sopenharmony_ci wq->group->num_wqs--; 8308c2ecf20Sopenharmony_ci wq->group = NULL; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci return count; 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci group = &idxd->groups[id]; 8368c2ecf20Sopenharmony_ci prevg = wq->group; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci if (prevg) 8398c2ecf20Sopenharmony_ci prevg->num_wqs--; 8408c2ecf20Sopenharmony_ci wq->group = group; 8418c2ecf20Sopenharmony_ci group->num_wqs++; 8428c2ecf20Sopenharmony_ci return count; 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_group_id = 8468c2ecf20Sopenharmony_ci __ATTR(group_id, 0644, wq_group_id_show, wq_group_id_store); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_cistatic ssize_t wq_mode_show(struct device *dev, struct device_attribute *attr, 8498c2ecf20Sopenharmony_ci char *buf) 8508c2ecf20Sopenharmony_ci{ 8518c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", 8548c2ecf20Sopenharmony_ci wq_dedicated(wq) ? "dedicated" : "shared"); 8558c2ecf20Sopenharmony_ci} 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_cistatic ssize_t wq_mode_store(struct device *dev, 8588c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 8598c2ecf20Sopenharmony_ci size_t count) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 8628c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 8658c2ecf20Sopenharmony_ci return -EPERM; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 8688c2ecf20Sopenharmony_ci return -EPERM; 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci if (sysfs_streq(buf, "dedicated")) { 8718c2ecf20Sopenharmony_ci set_bit(WQ_FLAG_DEDICATED, &wq->flags); 8728c2ecf20Sopenharmony_ci wq->threshold = 0; 8738c2ecf20Sopenharmony_ci } else { 8748c2ecf20Sopenharmony_ci return -EINVAL; 8758c2ecf20Sopenharmony_ci } 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci return count; 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_mode = 8818c2ecf20Sopenharmony_ci __ATTR(mode, 0644, wq_mode_show, wq_mode_store); 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_cistatic ssize_t wq_size_show(struct device *dev, struct device_attribute *attr, 8848c2ecf20Sopenharmony_ci char *buf) 8858c2ecf20Sopenharmony_ci{ 8868c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", wq->size); 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_cistatic int total_claimed_wq_size(struct idxd_device *idxd) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci int i; 8948c2ecf20Sopenharmony_ci int wq_size = 0; 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 8978c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci wq_size += wq->size; 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci return wq_size; 9038c2ecf20Sopenharmony_ci} 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_cistatic ssize_t wq_size_store(struct device *dev, 9068c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 9078c2ecf20Sopenharmony_ci size_t count) 9088c2ecf20Sopenharmony_ci{ 9098c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 9108c2ecf20Sopenharmony_ci unsigned long size; 9118c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 9128c2ecf20Sopenharmony_ci int rc; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci rc = kstrtoul(buf, 10, &size); 9158c2ecf20Sopenharmony_ci if (rc < 0) 9168c2ecf20Sopenharmony_ci return -EINVAL; 9178c2ecf20Sopenharmony_ci 9188c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 9198c2ecf20Sopenharmony_ci return -EPERM; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 9228c2ecf20Sopenharmony_ci return -EPERM; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci if (size + total_claimed_wq_size(idxd) - wq->size > idxd->max_wq_size) 9258c2ecf20Sopenharmony_ci return -EINVAL; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci wq->size = size; 9288c2ecf20Sopenharmony_ci return count; 9298c2ecf20Sopenharmony_ci} 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_size = 9328c2ecf20Sopenharmony_ci __ATTR(size, 0644, wq_size_show, wq_size_store); 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic ssize_t wq_priority_show(struct device *dev, 9358c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 9368c2ecf20Sopenharmony_ci{ 9378c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", wq->priority); 9408c2ecf20Sopenharmony_ci} 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_cistatic ssize_t wq_priority_store(struct device *dev, 9438c2ecf20Sopenharmony_ci struct device_attribute *attr, 9448c2ecf20Sopenharmony_ci const char *buf, size_t count) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 9478c2ecf20Sopenharmony_ci unsigned long prio; 9488c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 9498c2ecf20Sopenharmony_ci int rc; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci rc = kstrtoul(buf, 10, &prio); 9528c2ecf20Sopenharmony_ci if (rc < 0) 9538c2ecf20Sopenharmony_ci return -EINVAL; 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 9568c2ecf20Sopenharmony_ci return -EPERM; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 9598c2ecf20Sopenharmony_ci return -EPERM; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci if (prio > IDXD_MAX_PRIORITY) 9628c2ecf20Sopenharmony_ci return -EINVAL; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci wq->priority = prio; 9658c2ecf20Sopenharmony_ci return count; 9668c2ecf20Sopenharmony_ci} 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_priority = 9698c2ecf20Sopenharmony_ci __ATTR(priority, 0644, wq_priority_show, wq_priority_store); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic ssize_t wq_type_show(struct device *dev, 9728c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 9738c2ecf20Sopenharmony_ci{ 9748c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci switch (wq->type) { 9778c2ecf20Sopenharmony_ci case IDXD_WQT_KERNEL: 9788c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", 9798c2ecf20Sopenharmony_ci idxd_wq_type_names[IDXD_WQT_KERNEL]); 9808c2ecf20Sopenharmony_ci case IDXD_WQT_USER: 9818c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", 9828c2ecf20Sopenharmony_ci idxd_wq_type_names[IDXD_WQT_USER]); 9838c2ecf20Sopenharmony_ci case IDXD_WQT_NONE: 9848c2ecf20Sopenharmony_ci default: 9858c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", 9868c2ecf20Sopenharmony_ci idxd_wq_type_names[IDXD_WQT_NONE]); 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci return -EINVAL; 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic ssize_t wq_type_store(struct device *dev, 9938c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 9948c2ecf20Sopenharmony_ci size_t count) 9958c2ecf20Sopenharmony_ci{ 9968c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 9978c2ecf20Sopenharmony_ci enum idxd_wq_type old_type; 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 10008c2ecf20Sopenharmony_ci return -EPERM; 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci old_type = wq->type; 10038c2ecf20Sopenharmony_ci if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_NONE])) 10048c2ecf20Sopenharmony_ci wq->type = IDXD_WQT_NONE; 10058c2ecf20Sopenharmony_ci else if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_KERNEL])) 10068c2ecf20Sopenharmony_ci wq->type = IDXD_WQT_KERNEL; 10078c2ecf20Sopenharmony_ci else if (sysfs_streq(buf, idxd_wq_type_names[IDXD_WQT_USER])) 10088c2ecf20Sopenharmony_ci wq->type = IDXD_WQT_USER; 10098c2ecf20Sopenharmony_ci else 10108c2ecf20Sopenharmony_ci return -EINVAL; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci /* If we are changing queue type, clear the name */ 10138c2ecf20Sopenharmony_ci if (wq->type != old_type) 10148c2ecf20Sopenharmony_ci memset(wq->name, 0, WQ_NAME_SIZE + 1); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci return count; 10178c2ecf20Sopenharmony_ci} 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_type = 10208c2ecf20Sopenharmony_ci __ATTR(type, 0644, wq_type_show, wq_type_store); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_cistatic ssize_t wq_name_show(struct device *dev, 10238c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 10248c2ecf20Sopenharmony_ci{ 10258c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci return sprintf(buf, "%s\n", wq->name); 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_cistatic ssize_t wq_name_store(struct device *dev, 10318c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 10328c2ecf20Sopenharmony_ci size_t count) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 10378c2ecf20Sopenharmony_ci return -EPERM; 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci if (strlen(buf) > WQ_NAME_SIZE || strlen(buf) == 0) 10408c2ecf20Sopenharmony_ci return -EINVAL; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci memset(wq->name, 0, WQ_NAME_SIZE + 1); 10438c2ecf20Sopenharmony_ci strncpy(wq->name, buf, WQ_NAME_SIZE); 10448c2ecf20Sopenharmony_ci strreplace(wq->name, '\n', '\0'); 10458c2ecf20Sopenharmony_ci return count; 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_name = 10498c2ecf20Sopenharmony_ci __ATTR(name, 0644, wq_name_show, wq_name_store); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_cistatic ssize_t wq_cdev_minor_show(struct device *dev, 10528c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 10538c2ecf20Sopenharmony_ci{ 10548c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 10558c2ecf20Sopenharmony_ci int minor = -1; 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci mutex_lock(&wq->wq_lock); 10588c2ecf20Sopenharmony_ci if (wq->idxd_cdev) 10598c2ecf20Sopenharmony_ci minor = wq->idxd_cdev->minor; 10608c2ecf20Sopenharmony_ci mutex_unlock(&wq->wq_lock); 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci if (minor == -1) 10638c2ecf20Sopenharmony_ci return -ENXIO; 10648c2ecf20Sopenharmony_ci return sysfs_emit(buf, "%d\n", minor); 10658c2ecf20Sopenharmony_ci} 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_cdev_minor = 10688c2ecf20Sopenharmony_ci __ATTR(cdev_minor, 0444, wq_cdev_minor_show, NULL); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic int __get_sysfs_u64(const char *buf, u64 *val) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci int rc; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci rc = kstrtou64(buf, 0, val); 10758c2ecf20Sopenharmony_ci if (rc < 0) 10768c2ecf20Sopenharmony_ci return -EINVAL; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (*val == 0) 10798c2ecf20Sopenharmony_ci return -EINVAL; 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci *val = roundup_pow_of_two(*val); 10828c2ecf20Sopenharmony_ci return 0; 10838c2ecf20Sopenharmony_ci} 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_cistatic ssize_t wq_max_transfer_size_show(struct device *dev, struct device_attribute *attr, 10868c2ecf20Sopenharmony_ci char *buf) 10878c2ecf20Sopenharmony_ci{ 10888c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", wq->max_xfer_bytes); 10918c2ecf20Sopenharmony_ci} 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_cistatic ssize_t wq_max_transfer_size_store(struct device *dev, struct device_attribute *attr, 10948c2ecf20Sopenharmony_ci const char *buf, size_t count) 10958c2ecf20Sopenharmony_ci{ 10968c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 10978c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 10988c2ecf20Sopenharmony_ci u64 xfer_size; 10998c2ecf20Sopenharmony_ci int rc; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 11028c2ecf20Sopenharmony_ci return -EPERM; 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 11058c2ecf20Sopenharmony_ci return -EPERM; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci rc = __get_sysfs_u64(buf, &xfer_size); 11088c2ecf20Sopenharmony_ci if (rc < 0) 11098c2ecf20Sopenharmony_ci return rc; 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci if (xfer_size > idxd->max_xfer_bytes) 11128c2ecf20Sopenharmony_ci return -EINVAL; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci wq->max_xfer_bytes = xfer_size; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci return count; 11178c2ecf20Sopenharmony_ci} 11188c2ecf20Sopenharmony_ci 11198c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_max_transfer_size = 11208c2ecf20Sopenharmony_ci __ATTR(max_transfer_size, 0644, 11218c2ecf20Sopenharmony_ci wq_max_transfer_size_show, wq_max_transfer_size_store); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cistatic ssize_t wq_max_batch_size_show(struct device *dev, struct device_attribute *attr, char *buf) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", wq->max_batch_size); 11288c2ecf20Sopenharmony_ci} 11298c2ecf20Sopenharmony_ci 11308c2ecf20Sopenharmony_cistatic ssize_t wq_max_batch_size_store(struct device *dev, struct device_attribute *attr, 11318c2ecf20Sopenharmony_ci const char *buf, size_t count) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 11348c2ecf20Sopenharmony_ci struct idxd_device *idxd = wq->idxd; 11358c2ecf20Sopenharmony_ci u64 batch_size; 11368c2ecf20Sopenharmony_ci int rc; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 11398c2ecf20Sopenharmony_ci return -EPERM; 11408c2ecf20Sopenharmony_ci 11418c2ecf20Sopenharmony_ci if (wq->state != IDXD_WQ_DISABLED) 11428c2ecf20Sopenharmony_ci return -EPERM; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci rc = __get_sysfs_u64(buf, &batch_size); 11458c2ecf20Sopenharmony_ci if (rc < 0) 11468c2ecf20Sopenharmony_ci return rc; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci if (batch_size > idxd->max_batch_size) 11498c2ecf20Sopenharmony_ci return -EINVAL; 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci wq->max_batch_size = (u32)batch_size; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci return count; 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_cistatic struct device_attribute dev_attr_wq_max_batch_size = 11578c2ecf20Sopenharmony_ci __ATTR(max_batch_size, 0644, wq_max_batch_size_show, wq_max_batch_size_store); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_cistatic struct attribute *idxd_wq_attributes[] = { 11608c2ecf20Sopenharmony_ci &dev_attr_wq_clients.attr, 11618c2ecf20Sopenharmony_ci &dev_attr_wq_state.attr, 11628c2ecf20Sopenharmony_ci &dev_attr_wq_group_id.attr, 11638c2ecf20Sopenharmony_ci &dev_attr_wq_mode.attr, 11648c2ecf20Sopenharmony_ci &dev_attr_wq_size.attr, 11658c2ecf20Sopenharmony_ci &dev_attr_wq_priority.attr, 11668c2ecf20Sopenharmony_ci &dev_attr_wq_type.attr, 11678c2ecf20Sopenharmony_ci &dev_attr_wq_name.attr, 11688c2ecf20Sopenharmony_ci &dev_attr_wq_cdev_minor.attr, 11698c2ecf20Sopenharmony_ci &dev_attr_wq_max_transfer_size.attr, 11708c2ecf20Sopenharmony_ci &dev_attr_wq_max_batch_size.attr, 11718c2ecf20Sopenharmony_ci NULL, 11728c2ecf20Sopenharmony_ci}; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_cistatic const struct attribute_group idxd_wq_attribute_group = { 11758c2ecf20Sopenharmony_ci .attrs = idxd_wq_attributes, 11768c2ecf20Sopenharmony_ci}; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_cistatic const struct attribute_group *idxd_wq_attribute_groups[] = { 11798c2ecf20Sopenharmony_ci &idxd_wq_attribute_group, 11808c2ecf20Sopenharmony_ci NULL, 11818c2ecf20Sopenharmony_ci}; 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci/* IDXD device attribs */ 11848c2ecf20Sopenharmony_cistatic ssize_t version_show(struct device *dev, struct device_attribute *attr, 11858c2ecf20Sopenharmony_ci char *buf) 11868c2ecf20Sopenharmony_ci{ 11878c2ecf20Sopenharmony_ci struct idxd_device *idxd = 11888c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci return sprintf(buf, "%#x\n", idxd->hw.version); 11918c2ecf20Sopenharmony_ci} 11928c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(version); 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_cistatic ssize_t max_work_queues_size_show(struct device *dev, 11958c2ecf20Sopenharmony_ci struct device_attribute *attr, 11968c2ecf20Sopenharmony_ci char *buf) 11978c2ecf20Sopenharmony_ci{ 11988c2ecf20Sopenharmony_ci struct idxd_device *idxd = 11998c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->max_wq_size); 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_work_queues_size); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_cistatic ssize_t max_groups_show(struct device *dev, 12068c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12078c2ecf20Sopenharmony_ci{ 12088c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12098c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->max_groups); 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_groups); 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_cistatic ssize_t max_work_queues_show(struct device *dev, 12168c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12198c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->max_wqs); 12228c2ecf20Sopenharmony_ci} 12238c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_work_queues); 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic ssize_t max_engines_show(struct device *dev, 12268c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12298c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->max_engines); 12328c2ecf20Sopenharmony_ci} 12338c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_engines); 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_cistatic ssize_t numa_node_show(struct device *dev, 12368c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12378c2ecf20Sopenharmony_ci{ 12388c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12398c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", dev_to_node(&idxd->pdev->dev)); 12428c2ecf20Sopenharmony_ci} 12438c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(numa_node); 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_cistatic ssize_t max_batch_size_show(struct device *dev, 12468c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12478c2ecf20Sopenharmony_ci{ 12488c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12498c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->max_batch_size); 12528c2ecf20Sopenharmony_ci} 12538c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_batch_size); 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic ssize_t max_transfer_size_show(struct device *dev, 12568c2ecf20Sopenharmony_ci struct device_attribute *attr, 12578c2ecf20Sopenharmony_ci char *buf) 12588c2ecf20Sopenharmony_ci{ 12598c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12608c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", idxd->max_xfer_bytes); 12638c2ecf20Sopenharmony_ci} 12648c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_transfer_size); 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_cistatic ssize_t op_cap_show(struct device *dev, 12678c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12688c2ecf20Sopenharmony_ci{ 12698c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12708c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12718c2ecf20Sopenharmony_ci int i, rc = 0; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 12748c2ecf20Sopenharmony_ci rc += sysfs_emit_at(buf, rc, "%#llx ", idxd->hw.opcap.bits[i]); 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci rc--; 12778c2ecf20Sopenharmony_ci rc += sysfs_emit_at(buf, rc, "\n"); 12788c2ecf20Sopenharmony_ci return rc; 12798c2ecf20Sopenharmony_ci} 12808c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(op_cap); 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_cistatic ssize_t gen_cap_show(struct device *dev, 12838c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12848c2ecf20Sopenharmony_ci{ 12858c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12868c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci return sprintf(buf, "%#llx\n", idxd->hw.gen_cap.bits); 12898c2ecf20Sopenharmony_ci} 12908c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(gen_cap); 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_cistatic ssize_t configurable_show(struct device *dev, 12938c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 12948c2ecf20Sopenharmony_ci{ 12958c2ecf20Sopenharmony_ci struct idxd_device *idxd = 12968c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", 12998c2ecf20Sopenharmony_ci test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)); 13008c2ecf20Sopenharmony_ci} 13018c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(configurable); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_cistatic ssize_t clients_show(struct device *dev, 13048c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 13058c2ecf20Sopenharmony_ci{ 13068c2ecf20Sopenharmony_ci struct idxd_device *idxd = 13078c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 13088c2ecf20Sopenharmony_ci unsigned long flags; 13098c2ecf20Sopenharmony_ci int count = 0, i; 13108c2ecf20Sopenharmony_ci 13118c2ecf20Sopenharmony_ci spin_lock_irqsave(&idxd->dev_lock, flags); 13128c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 13138c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci count += wq->client_count; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&idxd->dev_lock, flags); 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci return sprintf(buf, "%d\n", count); 13208c2ecf20Sopenharmony_ci} 13218c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(clients); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_cistatic ssize_t state_show(struct device *dev, 13248c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 13258c2ecf20Sopenharmony_ci{ 13268c2ecf20Sopenharmony_ci struct idxd_device *idxd = 13278c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 13288c2ecf20Sopenharmony_ci 13298c2ecf20Sopenharmony_ci switch (idxd->state) { 13308c2ecf20Sopenharmony_ci case IDXD_DEV_DISABLED: 13318c2ecf20Sopenharmony_ci case IDXD_DEV_CONF_READY: 13328c2ecf20Sopenharmony_ci return sprintf(buf, "disabled\n"); 13338c2ecf20Sopenharmony_ci case IDXD_DEV_ENABLED: 13348c2ecf20Sopenharmony_ci return sprintf(buf, "enabled\n"); 13358c2ecf20Sopenharmony_ci case IDXD_DEV_HALTED: 13368c2ecf20Sopenharmony_ci return sprintf(buf, "halted\n"); 13378c2ecf20Sopenharmony_ci } 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci return sprintf(buf, "unknown\n"); 13408c2ecf20Sopenharmony_ci} 13418c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(state); 13428c2ecf20Sopenharmony_ci 13438c2ecf20Sopenharmony_cistatic ssize_t errors_show(struct device *dev, 13448c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 13458c2ecf20Sopenharmony_ci{ 13468c2ecf20Sopenharmony_ci struct idxd_device *idxd = 13478c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 13488c2ecf20Sopenharmony_ci int i, out = 0; 13498c2ecf20Sopenharmony_ci unsigned long flags; 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci spin_lock_irqsave(&idxd->dev_lock, flags); 13528c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) 13538c2ecf20Sopenharmony_ci out += sprintf(buf + out, "%#018llx ", idxd->sw_err.bits[i]); 13548c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&idxd->dev_lock, flags); 13558c2ecf20Sopenharmony_ci out--; 13568c2ecf20Sopenharmony_ci out += sprintf(buf + out, "\n"); 13578c2ecf20Sopenharmony_ci return out; 13588c2ecf20Sopenharmony_ci} 13598c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(errors); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_cistatic ssize_t max_tokens_show(struct device *dev, 13628c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 13638c2ecf20Sopenharmony_ci{ 13648c2ecf20Sopenharmony_ci struct idxd_device *idxd = 13658c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->max_tokens); 13688c2ecf20Sopenharmony_ci} 13698c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(max_tokens); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_cistatic ssize_t token_limit_show(struct device *dev, 13728c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 13738c2ecf20Sopenharmony_ci{ 13748c2ecf20Sopenharmony_ci struct idxd_device *idxd = 13758c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->token_limit); 13788c2ecf20Sopenharmony_ci} 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_cistatic ssize_t token_limit_store(struct device *dev, 13818c2ecf20Sopenharmony_ci struct device_attribute *attr, 13828c2ecf20Sopenharmony_ci const char *buf, size_t count) 13838c2ecf20Sopenharmony_ci{ 13848c2ecf20Sopenharmony_ci struct idxd_device *idxd = 13858c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 13868c2ecf20Sopenharmony_ci unsigned long val; 13878c2ecf20Sopenharmony_ci int rc; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci rc = kstrtoul(buf, 10, &val); 13908c2ecf20Sopenharmony_ci if (rc < 0) 13918c2ecf20Sopenharmony_ci return -EINVAL; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci if (idxd->state == IDXD_DEV_ENABLED) 13948c2ecf20Sopenharmony_ci return -EPERM; 13958c2ecf20Sopenharmony_ci 13968c2ecf20Sopenharmony_ci if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) 13978c2ecf20Sopenharmony_ci return -EPERM; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci if (!idxd->hw.group_cap.token_limit) 14008c2ecf20Sopenharmony_ci return -EPERM; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci if (val > idxd->hw.group_cap.total_tokens) 14038c2ecf20Sopenharmony_ci return -EINVAL; 14048c2ecf20Sopenharmony_ci 14058c2ecf20Sopenharmony_ci idxd->token_limit = val; 14068c2ecf20Sopenharmony_ci return count; 14078c2ecf20Sopenharmony_ci} 14088c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RW(token_limit); 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_cistatic ssize_t cdev_major_show(struct device *dev, 14118c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14128c2ecf20Sopenharmony_ci{ 14138c2ecf20Sopenharmony_ci struct idxd_device *idxd = 14148c2ecf20Sopenharmony_ci container_of(dev, struct idxd_device, conf_dev); 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", idxd->major); 14178c2ecf20Sopenharmony_ci} 14188c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(cdev_major); 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_cistatic ssize_t cmd_status_show(struct device *dev, 14218c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 14228c2ecf20Sopenharmony_ci{ 14238c2ecf20Sopenharmony_ci struct idxd_device *idxd = container_of(dev, struct idxd_device, conf_dev); 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci return sprintf(buf, "%#x\n", idxd->cmd_status); 14268c2ecf20Sopenharmony_ci} 14278c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(cmd_status); 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_cistatic struct attribute *idxd_device_attributes[] = { 14308c2ecf20Sopenharmony_ci &dev_attr_version.attr, 14318c2ecf20Sopenharmony_ci &dev_attr_max_groups.attr, 14328c2ecf20Sopenharmony_ci &dev_attr_max_work_queues.attr, 14338c2ecf20Sopenharmony_ci &dev_attr_max_work_queues_size.attr, 14348c2ecf20Sopenharmony_ci &dev_attr_max_engines.attr, 14358c2ecf20Sopenharmony_ci &dev_attr_numa_node.attr, 14368c2ecf20Sopenharmony_ci &dev_attr_max_batch_size.attr, 14378c2ecf20Sopenharmony_ci &dev_attr_max_transfer_size.attr, 14388c2ecf20Sopenharmony_ci &dev_attr_op_cap.attr, 14398c2ecf20Sopenharmony_ci &dev_attr_gen_cap.attr, 14408c2ecf20Sopenharmony_ci &dev_attr_configurable.attr, 14418c2ecf20Sopenharmony_ci &dev_attr_clients.attr, 14428c2ecf20Sopenharmony_ci &dev_attr_state.attr, 14438c2ecf20Sopenharmony_ci &dev_attr_errors.attr, 14448c2ecf20Sopenharmony_ci &dev_attr_max_tokens.attr, 14458c2ecf20Sopenharmony_ci &dev_attr_token_limit.attr, 14468c2ecf20Sopenharmony_ci &dev_attr_cdev_major.attr, 14478c2ecf20Sopenharmony_ci &dev_attr_cmd_status.attr, 14488c2ecf20Sopenharmony_ci NULL, 14498c2ecf20Sopenharmony_ci}; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_cistatic const struct attribute_group idxd_device_attribute_group = { 14528c2ecf20Sopenharmony_ci .attrs = idxd_device_attributes, 14538c2ecf20Sopenharmony_ci}; 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_cistatic const struct attribute_group *idxd_attribute_groups[] = { 14568c2ecf20Sopenharmony_ci &idxd_device_attribute_group, 14578c2ecf20Sopenharmony_ci NULL, 14588c2ecf20Sopenharmony_ci}; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_cistatic int idxd_setup_engine_sysfs(struct idxd_device *idxd) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci struct device *dev = &idxd->pdev->dev; 14638c2ecf20Sopenharmony_ci int i, rc; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_engines; i++) { 14668c2ecf20Sopenharmony_ci struct idxd_engine *engine = &idxd->engines[i]; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_ci engine->conf_dev.parent = &idxd->conf_dev; 14698c2ecf20Sopenharmony_ci dev_set_name(&engine->conf_dev, "engine%d.%d", 14708c2ecf20Sopenharmony_ci idxd->id, engine->id); 14718c2ecf20Sopenharmony_ci engine->conf_dev.bus = idxd_get_bus_type(idxd); 14728c2ecf20Sopenharmony_ci engine->conf_dev.groups = idxd_engine_attribute_groups; 14738c2ecf20Sopenharmony_ci engine->conf_dev.type = &idxd_engine_device_type; 14748c2ecf20Sopenharmony_ci dev_dbg(dev, "Engine device register: %s\n", 14758c2ecf20Sopenharmony_ci dev_name(&engine->conf_dev)); 14768c2ecf20Sopenharmony_ci rc = device_register(&engine->conf_dev); 14778c2ecf20Sopenharmony_ci if (rc < 0) { 14788c2ecf20Sopenharmony_ci put_device(&engine->conf_dev); 14798c2ecf20Sopenharmony_ci goto cleanup; 14808c2ecf20Sopenharmony_ci } 14818c2ecf20Sopenharmony_ci } 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci return 0; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_cicleanup: 14868c2ecf20Sopenharmony_ci while (i--) { 14878c2ecf20Sopenharmony_ci struct idxd_engine *engine = &idxd->engines[i]; 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci device_unregister(&engine->conf_dev); 14908c2ecf20Sopenharmony_ci } 14918c2ecf20Sopenharmony_ci return rc; 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cistatic int idxd_setup_group_sysfs(struct idxd_device *idxd) 14958c2ecf20Sopenharmony_ci{ 14968c2ecf20Sopenharmony_ci struct device *dev = &idxd->pdev->dev; 14978c2ecf20Sopenharmony_ci int i, rc; 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_groups; i++) { 15008c2ecf20Sopenharmony_ci struct idxd_group *group = &idxd->groups[i]; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci group->conf_dev.parent = &idxd->conf_dev; 15038c2ecf20Sopenharmony_ci dev_set_name(&group->conf_dev, "group%d.%d", 15048c2ecf20Sopenharmony_ci idxd->id, group->id); 15058c2ecf20Sopenharmony_ci group->conf_dev.bus = idxd_get_bus_type(idxd); 15068c2ecf20Sopenharmony_ci group->conf_dev.groups = idxd_group_attribute_groups; 15078c2ecf20Sopenharmony_ci group->conf_dev.type = &idxd_group_device_type; 15088c2ecf20Sopenharmony_ci dev_dbg(dev, "Group device register: %s\n", 15098c2ecf20Sopenharmony_ci dev_name(&group->conf_dev)); 15108c2ecf20Sopenharmony_ci rc = device_register(&group->conf_dev); 15118c2ecf20Sopenharmony_ci if (rc < 0) { 15128c2ecf20Sopenharmony_ci put_device(&group->conf_dev); 15138c2ecf20Sopenharmony_ci goto cleanup; 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci return 0; 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cicleanup: 15208c2ecf20Sopenharmony_ci while (i--) { 15218c2ecf20Sopenharmony_ci struct idxd_group *group = &idxd->groups[i]; 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci device_unregister(&group->conf_dev); 15248c2ecf20Sopenharmony_ci } 15258c2ecf20Sopenharmony_ci return rc; 15268c2ecf20Sopenharmony_ci} 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_cistatic int idxd_setup_wq_sysfs(struct idxd_device *idxd) 15298c2ecf20Sopenharmony_ci{ 15308c2ecf20Sopenharmony_ci struct device *dev = &idxd->pdev->dev; 15318c2ecf20Sopenharmony_ci int i, rc; 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 15348c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci wq->conf_dev.parent = &idxd->conf_dev; 15378c2ecf20Sopenharmony_ci dev_set_name(&wq->conf_dev, "wq%d.%d", idxd->id, wq->id); 15388c2ecf20Sopenharmony_ci wq->conf_dev.bus = idxd_get_bus_type(idxd); 15398c2ecf20Sopenharmony_ci wq->conf_dev.groups = idxd_wq_attribute_groups; 15408c2ecf20Sopenharmony_ci wq->conf_dev.type = &idxd_wq_device_type; 15418c2ecf20Sopenharmony_ci dev_dbg(dev, "WQ device register: %s\n", 15428c2ecf20Sopenharmony_ci dev_name(&wq->conf_dev)); 15438c2ecf20Sopenharmony_ci rc = device_register(&wq->conf_dev); 15448c2ecf20Sopenharmony_ci if (rc < 0) { 15458c2ecf20Sopenharmony_ci put_device(&wq->conf_dev); 15468c2ecf20Sopenharmony_ci goto cleanup; 15478c2ecf20Sopenharmony_ci } 15488c2ecf20Sopenharmony_ci } 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci return 0; 15518c2ecf20Sopenharmony_ci 15528c2ecf20Sopenharmony_cicleanup: 15538c2ecf20Sopenharmony_ci while (i--) { 15548c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci device_unregister(&wq->conf_dev); 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci return rc; 15598c2ecf20Sopenharmony_ci} 15608c2ecf20Sopenharmony_ci 15618c2ecf20Sopenharmony_cistatic int idxd_setup_device_sysfs(struct idxd_device *idxd) 15628c2ecf20Sopenharmony_ci{ 15638c2ecf20Sopenharmony_ci struct device *dev = &idxd->pdev->dev; 15648c2ecf20Sopenharmony_ci int rc; 15658c2ecf20Sopenharmony_ci char devname[IDXD_NAME_SIZE]; 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci sprintf(devname, "%s%d", idxd_get_dev_name(idxd), idxd->id); 15688c2ecf20Sopenharmony_ci idxd->conf_dev.parent = dev; 15698c2ecf20Sopenharmony_ci dev_set_name(&idxd->conf_dev, "%s", devname); 15708c2ecf20Sopenharmony_ci idxd->conf_dev.bus = idxd_get_bus_type(idxd); 15718c2ecf20Sopenharmony_ci idxd->conf_dev.groups = idxd_attribute_groups; 15728c2ecf20Sopenharmony_ci idxd->conf_dev.type = idxd_get_device_type(idxd); 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci dev_dbg(dev, "IDXD device register: %s\n", dev_name(&idxd->conf_dev)); 15758c2ecf20Sopenharmony_ci rc = device_register(&idxd->conf_dev); 15768c2ecf20Sopenharmony_ci if (rc < 0) { 15778c2ecf20Sopenharmony_ci put_device(&idxd->conf_dev); 15788c2ecf20Sopenharmony_ci return rc; 15798c2ecf20Sopenharmony_ci } 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci return 0; 15828c2ecf20Sopenharmony_ci} 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ciint idxd_setup_sysfs(struct idxd_device *idxd) 15858c2ecf20Sopenharmony_ci{ 15868c2ecf20Sopenharmony_ci struct device *dev = &idxd->pdev->dev; 15878c2ecf20Sopenharmony_ci int rc; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_ci rc = idxd_setup_device_sysfs(idxd); 15908c2ecf20Sopenharmony_ci if (rc < 0) { 15918c2ecf20Sopenharmony_ci dev_dbg(dev, "Device sysfs registering failed: %d\n", rc); 15928c2ecf20Sopenharmony_ci return rc; 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci rc = idxd_setup_wq_sysfs(idxd); 15968c2ecf20Sopenharmony_ci if (rc < 0) { 15978c2ecf20Sopenharmony_ci /* unregister conf dev */ 15988c2ecf20Sopenharmony_ci dev_dbg(dev, "Work Queue sysfs registering failed: %d\n", rc); 15998c2ecf20Sopenharmony_ci return rc; 16008c2ecf20Sopenharmony_ci } 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci rc = idxd_setup_group_sysfs(idxd); 16038c2ecf20Sopenharmony_ci if (rc < 0) { 16048c2ecf20Sopenharmony_ci /* unregister conf dev */ 16058c2ecf20Sopenharmony_ci dev_dbg(dev, "Group sysfs registering failed: %d\n", rc); 16068c2ecf20Sopenharmony_ci return rc; 16078c2ecf20Sopenharmony_ci } 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_ci rc = idxd_setup_engine_sysfs(idxd); 16108c2ecf20Sopenharmony_ci if (rc < 0) { 16118c2ecf20Sopenharmony_ci /* unregister conf dev */ 16128c2ecf20Sopenharmony_ci dev_dbg(dev, "Engine sysfs registering failed: %d\n", rc); 16138c2ecf20Sopenharmony_ci return rc; 16148c2ecf20Sopenharmony_ci } 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci return 0; 16178c2ecf20Sopenharmony_ci} 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_civoid idxd_cleanup_sysfs(struct idxd_device *idxd) 16208c2ecf20Sopenharmony_ci{ 16218c2ecf20Sopenharmony_ci int i; 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_wqs; i++) { 16248c2ecf20Sopenharmony_ci struct idxd_wq *wq = &idxd->wqs[i]; 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci device_unregister(&wq->conf_dev); 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_engines; i++) { 16308c2ecf20Sopenharmony_ci struct idxd_engine *engine = &idxd->engines[i]; 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci device_unregister(&engine->conf_dev); 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_ci for (i = 0; i < idxd->max_groups; i++) { 16368c2ecf20Sopenharmony_ci struct idxd_group *group = &idxd->groups[i]; 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci device_unregister(&group->conf_dev); 16398c2ecf20Sopenharmony_ci } 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci device_unregister(&idxd->conf_dev); 16428c2ecf20Sopenharmony_ci} 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ciint idxd_register_bus_type(void) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci int i, rc; 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci for (i = 0; i < IDXD_TYPE_MAX; i++) { 16498c2ecf20Sopenharmony_ci rc = bus_register(idxd_bus_types[i]); 16508c2ecf20Sopenharmony_ci if (rc < 0) 16518c2ecf20Sopenharmony_ci goto bus_err; 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci return 0; 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_cibus_err: 16578c2ecf20Sopenharmony_ci while (--i >= 0) 16588c2ecf20Sopenharmony_ci bus_unregister(idxd_bus_types[i]); 16598c2ecf20Sopenharmony_ci return rc; 16608c2ecf20Sopenharmony_ci} 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_civoid idxd_unregister_bus_type(void) 16638c2ecf20Sopenharmony_ci{ 16648c2ecf20Sopenharmony_ci int i; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci for (i = 0; i < IDXD_TYPE_MAX; i++) 16678c2ecf20Sopenharmony_ci bus_unregister(idxd_bus_types[i]); 16688c2ecf20Sopenharmony_ci} 1669