hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/iommu/of_iommu.c
....@@ -1,29 +1,21 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * OF helpers for IOMMU
34 *
45 * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms and conditions of the GNU General Public License,
8
- * version 2, as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope it will be useful, but WITHOUT
11
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
- * more details.
14
- *
15
- * You should have received a copy of the GNU General Public License along with
16
- * this program; if not, write to the Free Software Foundation, Inc.,
17
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
186 */
197
208 #include <linux/export.h>
219 #include <linux/iommu.h>
2210 #include <linux/limits.h>
11
+#include <linux/module.h>
12
+#include <linux/msi.h>
2313 #include <linux/of.h>
2414 #include <linux/of_iommu.h>
2515 #include <linux/of_pci.h>
16
+#include <linux/pci.h>
2617 #include <linux/slab.h>
18
+#include <linux/fsl/mc.h>
2719
2820 #define NO_IOMMU 1
2921
....@@ -100,16 +92,16 @@
10092 {
10193 const struct iommu_ops *ops;
10294 struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
103
- int err;
95
+ int ret;
10496
10597 ops = iommu_ops_from_fwnode(fwnode);
10698 if ((ops && !ops->of_xlate) ||
10799 !of_device_is_available(iommu_spec->np))
108100 return NO_IOMMU;
109101
110
- err = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops);
111
- if (err)
112
- return err;
102
+ ret = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops);
103
+ if (ret)
104
+ return ret;
113105 /*
114106 * The otherwise-empty fwspec handily serves to indicate the specific
115107 * IOMMU device we're waiting for, which will be useful if we ever get
....@@ -118,7 +110,49 @@
118110 if (!ops)
119111 return driver_deferred_probe_check_state(dev);
120112
121
- return ops->of_xlate(dev, iommu_spec);
113
+ if (!try_module_get(ops->owner))
114
+ return -ENODEV;
115
+
116
+ ret = ops->of_xlate(dev, iommu_spec);
117
+ module_put(ops->owner);
118
+ return ret;
119
+}
120
+
121
+static int of_iommu_configure_dev_id(struct device_node *master_np,
122
+ struct device *dev,
123
+ const u32 *id)
124
+{
125
+ struct of_phandle_args iommu_spec = { .args_count = 1 };
126
+ int err;
127
+
128
+ err = of_map_id(master_np, *id, "iommu-map",
129
+ "iommu-map-mask", &iommu_spec.np,
130
+ iommu_spec.args);
131
+ if (err)
132
+ return err == -ENODEV ? NO_IOMMU : err;
133
+
134
+ err = of_iommu_xlate(dev, &iommu_spec);
135
+ of_node_put(iommu_spec.np);
136
+ return err;
137
+}
138
+
139
+static int of_iommu_configure_dev(struct device_node *master_np,
140
+ struct device *dev)
141
+{
142
+ struct of_phandle_args iommu_spec;
143
+ int err = NO_IOMMU, idx = 0;
144
+
145
+ while (!of_parse_phandle_with_args(master_np, "iommus",
146
+ "#iommu-cells",
147
+ idx, &iommu_spec)) {
148
+ err = of_iommu_xlate(dev, &iommu_spec);
149
+ of_node_put(iommu_spec.np);
150
+ idx++;
151
+ if (err)
152
+ break;
153
+ }
154
+
155
+ return err;
122156 }
123157
124158 struct of_pci_iommu_alias_info {
....@@ -129,25 +163,24 @@
129163 static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
130164 {
131165 struct of_pci_iommu_alias_info *info = data;
132
- struct of_phandle_args iommu_spec = { .args_count = 1 };
133
- int err;
166
+ u32 input_id = alias;
134167
135
- err = of_pci_map_rid(info->np, alias, "iommu-map",
136
- "iommu-map-mask", &iommu_spec.np,
137
- iommu_spec.args);
138
- if (err)
139
- return err == -ENODEV ? NO_IOMMU : err;
168
+ return of_iommu_configure_dev_id(info->np, info->dev, &input_id);
169
+}
140170
141
- err = of_iommu_xlate(info->dev, &iommu_spec);
142
- of_node_put(iommu_spec.np);
143
- return err;
171
+static int of_iommu_configure_device(struct device_node *master_np,
172
+ struct device *dev, const u32 *id)
173
+{
174
+ return (id) ? of_iommu_configure_dev_id(master_np, dev, id) :
175
+ of_iommu_configure_dev(master_np, dev);
144176 }
145177
146178 const struct iommu_ops *of_iommu_configure(struct device *dev,
147
- struct device_node *master_np)
179
+ struct device_node *master_np,
180
+ const u32 *id)
148181 {
149182 const struct iommu_ops *ops = NULL;
150
- struct iommu_fwspec *fwspec = dev->iommu_fwspec;
183
+ struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
151184 int err = NO_IOMMU;
152185
153186 if (!master_np)
....@@ -172,21 +205,16 @@
172205 .np = master_np,
173206 };
174207
208
+ pci_request_acs();
175209 err = pci_for_each_dma_alias(to_pci_dev(dev),
176210 of_pci_iommu_init, &info);
177211 } else {
178
- struct of_phandle_args iommu_spec;
179
- int idx = 0;
212
+ err = of_iommu_configure_device(master_np, dev, id);
180213
181
- while (!of_parse_phandle_with_args(master_np, "iommus",
182
- "#iommu-cells",
183
- idx, &iommu_spec)) {
184
- err = of_iommu_xlate(dev, &iommu_spec);
185
- of_node_put(iommu_spec.np);
186
- idx++;
187
- if (err)
188
- break;
189
- }
214
+ fwspec = dev_iommu_fwspec_get(dev);
215
+ if (!err && fwspec)
216
+ of_property_read_u32(master_np, "pasid-num-bits",
217
+ &fwspec->num_pasid_bits);
190218 }
191219
192220 /*
....@@ -195,14 +223,17 @@
195223 * 0 : we found an IOMMU, and dev->fwspec is initialised appropriately
196224 * <0 : any actual error
197225 */
198
- if (!err)
199
- ops = dev->iommu_fwspec->ops;
226
+ if (!err) {
227
+ /* The fwspec pointer changed, read it again */
228
+ fwspec = dev_iommu_fwspec_get(dev);
229
+ ops = fwspec->ops;
230
+ }
200231 /*
201232 * If we have reason to believe the IOMMU driver missed the initial
202
- * add_device callback for dev, replay it to get things in order.
233
+ * probe for dev, replay it to get things in order.
203234 */
204
- if (ops && ops->add_device && dev->bus && !dev->iommu_group)
205
- err = ops->add_device(dev);
235
+ if (!err && dev->bus && !device_iommu_mapped(dev))
236
+ err = iommu_probe_device(dev);
206237
207238 /* Ignore all other errors apart from EPROBE_DEFER */
208239 if (err == -EPROBE_DEFER) {