blob: bf892a025d4f9065c54068daf12071b4a3218224 [file] [log] [blame]
Joerg Roedeldb3c33c2011-09-27 15:57:13 +02001/*
2 * drivers/pci/ats.c
3 *
4 * Copyright (C) 2009 Intel Corporation, Yu Zhao <yu.zhao@intel.com>
Joerg Roedelc320b972011-09-27 15:57:15 +02005 * Copyright (C) 2011 Advanced Micro Devices,
Joerg Roedeldb3c33c2011-09-27 15:57:13 +02006 *
7 * PCI Express I/O Virtualization (IOV) support.
8 * Address Translation Service 1.0
Joerg Roedelc320b972011-09-27 15:57:15 +02009 * Page Request Interface added by Joerg Roedel <joerg.roedel@amd.com>
Joerg Roedeldb3c33c2011-09-27 15:57:13 +020010 */
11
12#include <linux/pci-ats.h>
13#include <linux/pci.h>
14
15#include "pci.h"
16
17static int ats_alloc_one(struct pci_dev *dev, int ps)
18{
19 int pos;
20 u16 cap;
21 struct pci_ats *ats;
22
23 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
24 if (!pos)
25 return -ENODEV;
26
27 ats = kzalloc(sizeof(*ats), GFP_KERNEL);
28 if (!ats)
29 return -ENOMEM;
30
31 ats->pos = pos;
32 ats->stu = ps;
33 pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
34 ats->qdep = PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
35 PCI_ATS_MAX_QDEP;
36 dev->ats = ats;
37
38 return 0;
39}
40
41static void ats_free_one(struct pci_dev *dev)
42{
43 kfree(dev->ats);
44 dev->ats = NULL;
45}
46
47/**
48 * pci_enable_ats - enable the ATS capability
49 * @dev: the PCI device
50 * @ps: the IOMMU page shift
51 *
52 * Returns 0 on success, or negative on failure.
53 */
54int pci_enable_ats(struct pci_dev *dev, int ps)
55{
56 int rc;
57 u16 ctrl;
58
59 BUG_ON(dev->ats && dev->ats->is_enabled);
60
61 if (ps < PCI_ATS_MIN_STU)
62 return -EINVAL;
63
64 if (dev->is_physfn || dev->is_virtfn) {
65 struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
66
67 mutex_lock(&pdev->sriov->lock);
68 if (pdev->ats)
69 rc = pdev->ats->stu == ps ? 0 : -EINVAL;
70 else
71 rc = ats_alloc_one(pdev, ps);
72
73 if (!rc)
74 pdev->ats->ref_cnt++;
75 mutex_unlock(&pdev->sriov->lock);
76 if (rc)
77 return rc;
78 }
79
80 if (!dev->is_physfn) {
81 rc = ats_alloc_one(dev, ps);
82 if (rc)
83 return rc;
84 }
85
86 ctrl = PCI_ATS_CTRL_ENABLE;
87 if (!dev->is_virtfn)
88 ctrl |= PCI_ATS_CTRL_STU(ps - PCI_ATS_MIN_STU);
89 pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
90
91 dev->ats->is_enabled = 1;
92
93 return 0;
94}
Joerg Roedeld4c06362011-09-27 15:57:14 +020095EXPORT_SYMBOL_GPL(pci_enable_ats);
Joerg Roedeldb3c33c2011-09-27 15:57:13 +020096
97/**
98 * pci_disable_ats - disable the ATS capability
99 * @dev: the PCI device
100 */
101void pci_disable_ats(struct pci_dev *dev)
102{
103 u16 ctrl;
104
105 BUG_ON(!dev->ats || !dev->ats->is_enabled);
106
107 pci_read_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, &ctrl);
108 ctrl &= ~PCI_ATS_CTRL_ENABLE;
109 pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
110
111 dev->ats->is_enabled = 0;
112
113 if (dev->is_physfn || dev->is_virtfn) {
114 struct pci_dev *pdev = dev->is_physfn ? dev : dev->physfn;
115
116 mutex_lock(&pdev->sriov->lock);
117 pdev->ats->ref_cnt--;
118 if (!pdev->ats->ref_cnt)
119 ats_free_one(pdev);
120 mutex_unlock(&pdev->sriov->lock);
121 }
122
123 if (!dev->is_physfn)
124 ats_free_one(dev);
125}
Joerg Roedeld4c06362011-09-27 15:57:14 +0200126EXPORT_SYMBOL_GPL(pci_disable_ats);
Joerg Roedeldb3c33c2011-09-27 15:57:13 +0200127
128/**
129 * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
130 * @dev: the PCI device
131 *
132 * Returns the queue depth on success, or negative on failure.
133 *
134 * The ATS spec uses 0 in the Invalidate Queue Depth field to
135 * indicate that the function can accept 32 Invalidate Request.
136 * But here we use the `real' values (i.e. 1~32) for the Queue
137 * Depth; and 0 indicates the function shares the Queue with
138 * other functions (doesn't exclusively own a Queue).
139 */
140int pci_ats_queue_depth(struct pci_dev *dev)
141{
142 int pos;
143 u16 cap;
144
145 if (dev->is_virtfn)
146 return 0;
147
148 if (dev->ats)
149 return dev->ats->qdep;
150
151 pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS);
152 if (!pos)
153 return -ENODEV;
154
155 pci_read_config_word(dev, pos + PCI_ATS_CAP, &cap);
156
157 return PCI_ATS_CAP_QDEP(cap) ? PCI_ATS_CAP_QDEP(cap) :
158 PCI_ATS_MAX_QDEP;
159}
Joerg Roedeld4c06362011-09-27 15:57:14 +0200160EXPORT_SYMBOL_GPL(pci_ats_queue_depth);
Joerg Roedelc320b972011-09-27 15:57:15 +0200161
162#ifdef CONFIG_PCI_PRI
163/**
164 * pci_enable_pri - Enable PRI capability
165 * @ pdev: PCI device structure
166 *
167 * Returns 0 on success, negative value on error
168 */
169int pci_enable_pri(struct pci_dev *pdev, u32 reqs)
170{
171 u16 control, status;
172 u32 max_requests;
173 int pos;
174
175 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
176 if (!pos)
177 return -EINVAL;
178
179 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
180 pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
181 if ((control & PCI_PRI_ENABLE) || !(status & PCI_PRI_STATUS_STOPPED))
182 return -EBUSY;
183
184 pci_read_config_dword(pdev, pos + PCI_PRI_MAX_REQ_OFF, &max_requests);
185 reqs = min(max_requests, reqs);
186 pci_write_config_dword(pdev, pos + PCI_PRI_ALLOC_REQ_OFF, reqs);
187
188 control |= PCI_PRI_ENABLE;
189 pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
190
191 return 0;
192}
193EXPORT_SYMBOL_GPL(pci_enable_pri);
194
195/**
196 * pci_disable_pri - Disable PRI capability
197 * @pdev: PCI device structure
198 *
199 * Only clears the enabled-bit, regardless of its former value
200 */
201void pci_disable_pri(struct pci_dev *pdev)
202{
203 u16 control;
204 int pos;
205
206 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
207 if (!pos)
208 return;
209
210 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
211 control &= ~PCI_PRI_ENABLE;
212 pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
213}
214EXPORT_SYMBOL_GPL(pci_disable_pri);
215
216/**
217 * pci_pri_enabled - Checks if PRI capability is enabled
218 * @pdev: PCI device structure
219 *
220 * Returns true if PRI is enabled on the device, false otherwise
221 */
222bool pci_pri_enabled(struct pci_dev *pdev)
223{
224 u16 control;
225 int pos;
226
227 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
228 if (!pos)
229 return false;
230
231 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
232
233 return (control & PCI_PRI_ENABLE) ? true : false;
234}
235EXPORT_SYMBOL_GPL(pci_pri_enabled);
236
237/**
238 * pci_reset_pri - Resets device's PRI state
239 * @pdev: PCI device structure
240 *
241 * The PRI capability must be disabled before this function is called.
242 * Returns 0 on success, negative value on error.
243 */
244int pci_reset_pri(struct pci_dev *pdev)
245{
246 u16 control;
247 int pos;
248
249 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
250 if (!pos)
251 return -EINVAL;
252
253 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
254 if (control & PCI_PRI_ENABLE)
255 return -EBUSY;
256
257 control |= PCI_PRI_RESET;
258
259 pci_write_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, control);
260
261 return 0;
262}
263EXPORT_SYMBOL_GPL(pci_reset_pri);
264
265/**
266 * pci_pri_stopped - Checks whether the PRI capability is stopped
267 * @pdev: PCI device structure
268 *
269 * Returns true if the PRI capability on the device is disabled and the
270 * device has no outstanding PRI requests, false otherwise. The device
271 * indicates this via the STOPPED bit in the status register of the
272 * capability.
273 * The device internal state can be cleared by resetting the PRI state
274 * with pci_reset_pri(). This can force the capability into the STOPPED
275 * state.
276 */
277bool pci_pri_stopped(struct pci_dev *pdev)
278{
279 u16 control, status;
280 int pos;
281
282 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
283 if (!pos)
284 return true;
285
286 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
287 pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
288
289 if (control & PCI_PRI_ENABLE)
290 return false;
291
292 return (status & PCI_PRI_STATUS_STOPPED) ? true : false;
293}
294EXPORT_SYMBOL_GPL(pci_pri_stopped);
295
296/**
297 * pci_pri_status - Request PRI status of a device
298 * @pdev: PCI device structure
299 *
300 * Returns negative value on failure, status on success. The status can
301 * be checked against status-bits. Supported bits are currently:
302 * PCI_PRI_STATUS_RF: Response failure
303 * PCI_PRI_STATUS_UPRGI: Unexpected Page Request Group Index
304 * PCI_PRI_STATUS_STOPPED: PRI has stopped
305 */
306int pci_pri_status(struct pci_dev *pdev)
307{
308 u16 status, control;
309 int pos;
310
311 pos = pci_find_ext_capability(pdev, PCI_PRI_CAP);
312 if (!pos)
313 return -EINVAL;
314
315 pci_read_config_word(pdev, pos + PCI_PRI_CONTROL_OFF, &control);
316 pci_read_config_word(pdev, pos + PCI_PRI_STATUS_OFF, &status);
317
318 /* Stopped bit is undefined when enable == 1, so clear it */
319 if (control & PCI_PRI_ENABLE)
320 status &= ~PCI_PRI_STATUS_STOPPED;
321
322 return status;
323}
324EXPORT_SYMBOL_GPL(pci_pri_status);
325#endif /* CONFIG_PCI_PRI */