cdev.c (0ea8a56de21be24cb79abb03dee79aabcd60a316) | cdev.c (8e50d392652f20616a136165dff516b86baf5e49) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2019 Intel Corporation. All rights rsvd. */ 3#include <linux/init.h> 4#include <linux/kernel.h> 5#include <linux/module.h> 6#include <linux/pci.h> 7#include <linux/device.h> 8#include <linux/sched/task.h> 9#include <linux/intel-svm.h> 10#include <linux/io-64-nonatomic-lo-hi.h> 11#include <linux/cdev.h> 12#include <linux/fs.h> 13#include <linux/poll.h> | 1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2019 Intel Corporation. All rights rsvd. */ 3#include <linux/init.h> 4#include <linux/kernel.h> 5#include <linux/module.h> 6#include <linux/pci.h> 7#include <linux/device.h> 8#include <linux/sched/task.h> 9#include <linux/intel-svm.h> 10#include <linux/io-64-nonatomic-lo-hi.h> 11#include <linux/cdev.h> 12#include <linux/fs.h> 13#include <linux/poll.h> |
14#include <linux/iommu.h> |
|
14#include <uapi/linux/idxd.h> 15#include "registers.h" 16#include "idxd.h" 17 18struct idxd_cdev_context { 19 const char *name; 20 dev_t devt; 21 struct ida minor_ida; --- 5 unchanged lines hidden (view full) --- 27 */ 28static struct idxd_cdev_context ictx[IDXD_TYPE_MAX] = { 29 { .name = "dsa" }, 30}; 31 32struct idxd_user_context { 33 struct idxd_wq *wq; 34 struct task_struct *task; | 15#include <uapi/linux/idxd.h> 16#include "registers.h" 17#include "idxd.h" 18 19struct idxd_cdev_context { 20 const char *name; 21 dev_t devt; 22 struct ida minor_ida; --- 5 unchanged lines hidden (view full) --- 28 */ 29static struct idxd_cdev_context ictx[IDXD_TYPE_MAX] = { 30 { .name = "dsa" }, 31}; 32 33struct idxd_user_context { 34 struct idxd_wq *wq; 35 struct task_struct *task; |
36 unsigned int pasid; |
|
35 unsigned int flags; | 37 unsigned int flags; |
38 struct iommu_sva *sva; |
|
36}; 37 38enum idxd_cdev_cleanup { 39 CDEV_NORMAL = 0, 40 CDEV_FAILED, 41}; 42 43static void idxd_cdev_dev_release(struct device *dev) --- 26 unchanged lines hidden (view full) --- 70 71static int idxd_cdev_open(struct inode *inode, struct file *filp) 72{ 73 struct idxd_user_context *ctx; 74 struct idxd_device *idxd; 75 struct idxd_wq *wq; 76 struct device *dev; 77 int rc = 0; | 39}; 40 41enum idxd_cdev_cleanup { 42 CDEV_NORMAL = 0, 43 CDEV_FAILED, 44}; 45 46static void idxd_cdev_dev_release(struct device *dev) --- 26 unchanged lines hidden (view full) --- 73 74static int idxd_cdev_open(struct inode *inode, struct file *filp) 75{ 76 struct idxd_user_context *ctx; 77 struct idxd_device *idxd; 78 struct idxd_wq *wq; 79 struct device *dev; 80 int rc = 0; |
81 struct iommu_sva *sva; 82 unsigned int pasid; |
|
78 79 wq = inode_wq(inode); 80 idxd = wq->idxd; 81 dev = &idxd->pdev->dev; 82 83 dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq)); 84 85 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); --- 4 unchanged lines hidden (view full) --- 90 91 if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) { 92 rc = -EBUSY; 93 goto failed; 94 } 95 96 ctx->wq = wq; 97 filp->private_data = ctx; | 83 84 wq = inode_wq(inode); 85 idxd = wq->idxd; 86 dev = &idxd->pdev->dev; 87 88 dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq)); 89 90 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); --- 4 unchanged lines hidden (view full) --- 95 96 if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) { 97 rc = -EBUSY; 98 goto failed; 99 } 100 101 ctx->wq = wq; 102 filp->private_data = ctx; |
103 104 if (device_pasid_enabled(idxd)) { 105 sva = iommu_sva_bind_device(dev, current->mm, NULL); 106 if (IS_ERR(sva)) { 107 rc = PTR_ERR(sva); 108 dev_err(dev, "pasid allocation failed: %d\n", rc); 109 goto failed; 110 } 111 112 pasid = iommu_sva_get_pasid(sva); 113 if (pasid == IOMMU_PASID_INVALID) { 114 iommu_sva_unbind_device(sva); 115 goto failed; 116 } 117 118 ctx->sva = sva; 119 ctx->pasid = pasid; 120 121 if (wq_dedicated(wq)) { 122 rc = idxd_wq_set_pasid(wq, pasid); 123 if (rc < 0) { 124 iommu_sva_unbind_device(sva); 125 dev_err(dev, "wq set pasid failed: %d\n", rc); 126 goto failed; 127 } 128 } 129 } 130 |
|
98 idxd_wq_get(wq); 99 mutex_unlock(&wq->wq_lock); 100 return 0; 101 102 failed: 103 mutex_unlock(&wq->wq_lock); 104 kfree(ctx); 105 return rc; 106} 107 108static int idxd_cdev_release(struct inode *node, struct file *filep) 109{ 110 struct idxd_user_context *ctx = filep->private_data; 111 struct idxd_wq *wq = ctx->wq; 112 struct idxd_device *idxd = wq->idxd; 113 struct device *dev = &idxd->pdev->dev; | 131 idxd_wq_get(wq); 132 mutex_unlock(&wq->wq_lock); 133 return 0; 134 135 failed: 136 mutex_unlock(&wq->wq_lock); 137 kfree(ctx); 138 return rc; 139} 140 141static int idxd_cdev_release(struct inode *node, struct file *filep) 142{ 143 struct idxd_user_context *ctx = filep->private_data; 144 struct idxd_wq *wq = ctx->wq; 145 struct idxd_device *idxd = wq->idxd; 146 struct device *dev = &idxd->pdev->dev; |
147 int rc; |
|
114 115 dev_dbg(dev, "%s called\n", __func__); 116 filep->private_data = NULL; 117 118 /* Wait for in-flight operations to complete. */ | 148 149 dev_dbg(dev, "%s called\n", __func__); 150 filep->private_data = NULL; 151 152 /* Wait for in-flight operations to complete. */ |
119 idxd_wq_drain(wq); | 153 if (wq_shared(wq)) { 154 idxd_device_drain_pasid(idxd, ctx->pasid); 155 } else { 156 if (device_pasid_enabled(idxd)) { 157 /* The wq disable in the disable pasid function will drain the wq */ 158 rc = idxd_wq_disable_pasid(wq); 159 if (rc < 0) 160 dev_err(dev, "wq disable pasid failed.\n"); 161 } else { 162 idxd_wq_drain(wq); 163 } 164 } |
120 | 165 |
166 if (ctx->sva) 167 iommu_sva_unbind_device(ctx->sva); |
|
121 kfree(ctx); 122 mutex_lock(&wq->wq_lock); 123 idxd_wq_put(wq); 124 mutex_unlock(&wq->wq_lock); 125 return 0; 126} 127 128static int check_vma(struct idxd_wq *wq, struct vm_area_struct *vma, --- 190 unchanged lines hidden --- | 168 kfree(ctx); 169 mutex_lock(&wq->wq_lock); 170 idxd_wq_put(wq); 171 mutex_unlock(&wq->wq_lock); 172 return 0; 173} 174 175static int check_vma(struct idxd_wq *wq, struct vm_area_struct *vma, --- 190 unchanged lines hidden --- |