aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/ats.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/ats.c')
-rw-r--r--drivers/pci/ats.c87
1 files changed, 71 insertions, 16 deletions
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index eeb9fb2b47aa..ad8ddbbbf245 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -153,23 +153,27 @@ int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
153 u32 max_requests; 153 u32 max_requests;
154 int pos; 154 int pos;
155 155
156 if (WARN_ON(pdev->pri_enabled))
157 return -EBUSY;
158
156 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); 159 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
157 if (!pos) 160 if (!pos)
158 return -EINVAL; 161 return -EINVAL;
159 162
160 pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
161 pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); 163 pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status);
162 if ((control & PCI_PRI_CTRL_ENABLE) || 164 if (!(status & PCI_PRI_STATUS_STOPPED))
163 !(status & PCI_PRI_STATUS_STOPPED))
164 return -EBUSY; 165 return -EBUSY;
165 166
166 pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests); 167 pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ, &max_requests);
167 reqs = min(max_requests, reqs); 168 reqs = min(max_requests, reqs);
169 pdev->pri_reqs_alloc = reqs;
168 pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs); 170 pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs);
169 171
170 control |= PCI_PRI_CTRL_ENABLE; 172 control = PCI_PRI_CTRL_ENABLE;
171 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); 173 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
172 174
175 pdev->pri_enabled = 1;
176
173 return 0; 177 return 0;
174} 178}
175EXPORT_SYMBOL_GPL(pci_enable_pri); 179EXPORT_SYMBOL_GPL(pci_enable_pri);
@@ -185,6 +189,9 @@ void pci_disable_pri(struct pci_dev *pdev)
185 u16 control; 189 u16 control;
186 int pos; 190 int pos;
187 191
192 if (WARN_ON(!pdev->pri_enabled))
193 return;
194
188 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); 195 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
189 if (!pos) 196 if (!pos)
190 return; 197 return;
@@ -192,10 +199,34 @@ void pci_disable_pri(struct pci_dev *pdev)
192 pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); 199 pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control);
193 control &= ~PCI_PRI_CTRL_ENABLE; 200 control &= ~PCI_PRI_CTRL_ENABLE;
194 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); 201 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
202
203 pdev->pri_enabled = 0;
195} 204}
196EXPORT_SYMBOL_GPL(pci_disable_pri); 205EXPORT_SYMBOL_GPL(pci_disable_pri);
197 206
198/** 207/**
208 * pci_restore_pri_state - Restore PRI
209 * @pdev: PCI device structure
210 */
211void pci_restore_pri_state(struct pci_dev *pdev)
212{
213 u16 control = PCI_PRI_CTRL_ENABLE;
214 u32 reqs = pdev->pri_reqs_alloc;
215 int pos;
216
217 if (!pdev->pri_enabled)
218 return;
219
220 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
221 if (!pos)
222 return;
223
224 pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ, reqs);
225 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
226}
227EXPORT_SYMBOL_GPL(pci_restore_pri_state);
228
229/**
199 * pci_reset_pri - Resets device's PRI state 230 * pci_reset_pri - Resets device's PRI state
200 * @pdev: PCI device structure 231 * @pdev: PCI device structure
201 * 232 *
@@ -207,16 +238,14 @@ int pci_reset_pri(struct pci_dev *pdev)
207 u16 control; 238 u16 control;
208 int pos; 239 int pos;
209 240
241 if (WARN_ON(pdev->pri_enabled))
242 return -EBUSY;
243
210 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); 244 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI);
211 if (!pos) 245 if (!pos)
212 return -EINVAL; 246 return -EINVAL;
213 247
214 pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); 248 control = PCI_PRI_CTRL_RESET;
215 if (control & PCI_PRI_CTRL_ENABLE)
216 return -EBUSY;
217
218 control |= PCI_PRI_CTRL_RESET;
219
220 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control); 249 pci_write_config_word(pdev, pos + PCI_PRI_CTRL, control);
221 250
222 return 0; 251 return 0;
@@ -239,16 +268,14 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
239 u16 control, supported; 268 u16 control, supported;
240 int pos; 269 int pos;
241 270
271 if (WARN_ON(pdev->pasid_enabled))
272 return -EBUSY;
273
242 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); 274 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
243 if (!pos) 275 if (!pos)
244 return -EINVAL; 276 return -EINVAL;
245 277
246 pci_read_config_word(pdev, pos + PCI_PASID_CTRL, &control);
247 pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported); 278 pci_read_config_word(pdev, pos + PCI_PASID_CAP, &supported);
248
249 if (control & PCI_PASID_CTRL_ENABLE)
250 return -EINVAL;
251
252 supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV; 279 supported &= PCI_PASID_CAP_EXEC | PCI_PASID_CAP_PRIV;
253 280
254 /* User wants to enable anything unsupported? */ 281 /* User wants to enable anything unsupported? */
@@ -256,9 +283,12 @@ int pci_enable_pasid(struct pci_dev *pdev, int features)
256 return -EINVAL; 283 return -EINVAL;
257 284
258 control = PCI_PASID_CTRL_ENABLE | features; 285 control = PCI_PASID_CTRL_ENABLE | features;
286 pdev->pasid_features = features;
259 287
260 pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); 288 pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
261 289
290 pdev->pasid_enabled = 1;
291
262 return 0; 292 return 0;
263} 293}
264EXPORT_SYMBOL_GPL(pci_enable_pasid); 294EXPORT_SYMBOL_GPL(pci_enable_pasid);
@@ -266,22 +296,47 @@ EXPORT_SYMBOL_GPL(pci_enable_pasid);
266/** 296/**
267 * pci_disable_pasid - Disable the PASID capability 297 * pci_disable_pasid - Disable the PASID capability
268 * @pdev: PCI device structure 298 * @pdev: PCI device structure
269 *
270 */ 299 */
271void pci_disable_pasid(struct pci_dev *pdev) 300void pci_disable_pasid(struct pci_dev *pdev)
272{ 301{
273 u16 control = 0; 302 u16 control = 0;
274 int pos; 303 int pos;
275 304
305 if (WARN_ON(!pdev->pasid_enabled))
306 return;
307
276 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID); 308 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
277 if (!pos) 309 if (!pos)
278 return; 310 return;
279 311
280 pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control); 312 pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
313
314 pdev->pasid_enabled = 0;
281} 315}
282EXPORT_SYMBOL_GPL(pci_disable_pasid); 316EXPORT_SYMBOL_GPL(pci_disable_pasid);
283 317
284/** 318/**
319 * pci_restore_pasid_state - Restore PASID capabilities
320 * @pdev: PCI device structure
321 */
322void pci_restore_pasid_state(struct pci_dev *pdev)
323{
324 u16 control;
325 int pos;
326
327 if (!pdev->pasid_enabled)
328 return;
329
330 pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PASID);
331 if (!pos)
332 return;
333
334 control = PCI_PASID_CTRL_ENABLE | pdev->pasid_features;
335 pci_write_config_word(pdev, pos + PCI_PASID_CTRL, control);
336}
337EXPORT_SYMBOL_GPL(pci_restore_pasid_state);
338
339/**
285 * pci_pasid_features - Check which PASID features are supported 340 * pci_pasid_features - Check which PASID features are supported
286 * @pdev: PCI device structure 341 * @pdev: PCI device structure
287 * 342 *