17
17
#include <linux/init.h>
18
18
#include <linux/iommu.h>
19
19
#include <linux/kernel.h>
20
+ #include <linux/pci.h>
20
21
21
22
#include "iommu-bits.h"
22
23
#include "iommu.h"
@@ -36,6 +37,60 @@ static void riscv_iommu_disable(struct riscv_iommu_device *iommu)
36
37
riscv_iommu_writel (iommu , RISCV_IOMMU_REG_PQCSR , 0 );
37
38
}
38
39
40
+ static int riscv_iommu_attach_identity_domain (struct iommu_domain * iommu_domain ,
41
+ struct device * dev )
42
+ {
43
+ /* Global pass-through already enabled, do nothing for now. */
44
+ return 0 ;
45
+ }
46
+
47
+ static struct iommu_domain riscv_iommu_identity_domain = {
48
+ .type = IOMMU_DOMAIN_IDENTITY ,
49
+ .ops = & (const struct iommu_domain_ops ) {
50
+ .attach_dev = riscv_iommu_attach_identity_domain ,
51
+ }
52
+ };
53
+
54
+ static int riscv_iommu_device_domain_type (struct device * dev )
55
+ {
56
+ return IOMMU_DOMAIN_IDENTITY ;
57
+ }
58
+
59
+ static struct iommu_group * riscv_iommu_device_group (struct device * dev )
60
+ {
61
+ if (dev_is_pci (dev ))
62
+ return pci_device_group (dev );
63
+ return generic_device_group (dev );
64
+ }
65
+
66
+ static int riscv_iommu_of_xlate (struct device * dev , const struct of_phandle_args * args )
67
+ {
68
+ return iommu_fwspec_add_ids (dev , args -> args , 1 );
69
+ }
70
+
71
+ static struct iommu_device * riscv_iommu_probe_device (struct device * dev )
72
+ {
73
+ struct iommu_fwspec * fwspec = dev_iommu_fwspec_get (dev );
74
+ struct riscv_iommu_device * iommu ;
75
+
76
+ if (!fwspec || !fwspec -> iommu_fwnode -> dev || !fwspec -> num_ids )
77
+ return ERR_PTR (- ENODEV );
78
+
79
+ iommu = dev_get_drvdata (fwspec -> iommu_fwnode -> dev );
80
+ if (!iommu )
81
+ return ERR_PTR (- ENODEV );
82
+
83
+ return & iommu -> iommu ;
84
+ }
85
+
86
+ static const struct iommu_ops riscv_iommu_ops = {
87
+ .of_xlate = riscv_iommu_of_xlate ,
88
+ .identity_domain = & riscv_iommu_identity_domain ,
89
+ .def_domain_type = riscv_iommu_device_domain_type ,
90
+ .device_group = riscv_iommu_device_group ,
91
+ .probe_device = riscv_iommu_probe_device ,
92
+ };
93
+
39
94
static int riscv_iommu_init_check (struct riscv_iommu_device * iommu )
40
95
{
41
96
u64 ddtp ;
@@ -74,6 +129,7 @@ static int riscv_iommu_init_check(struct riscv_iommu_device *iommu)
74
129
75
130
void riscv_iommu_remove (struct riscv_iommu_device * iommu )
76
131
{
132
+ iommu_device_unregister (& iommu -> iommu );
77
133
iommu_device_sysfs_remove (& iommu -> iommu );
78
134
}
79
135
@@ -99,5 +155,15 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
99
155
return dev_err_probe (iommu -> dev , rc ,
100
156
"cannot register sysfs interface\n" );
101
157
158
+ rc = iommu_device_register (& iommu -> iommu , & riscv_iommu_ops , iommu -> dev );
159
+ if (rc ) {
160
+ dev_err_probe (iommu -> dev , rc , "cannot register iommu interface\n" );
161
+ goto err_remove_sysfs ;
162
+ }
163
+
102
164
return 0 ;
165
+
166
+ err_remove_sysfs :
167
+ iommu_device_sysfs_remove (& iommu -> iommu );
168
+ return rc ;
103
169
}
0 commit comments