File Index
Files and directories
Sign in
FILE

dca.c

File preview with syntax highlighting.

linux-6.19.14/drivers/dma/ioat/dca.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Intel I/OAT DMA Linux driver
  4 * Copyright(c) 2007 - 2009 Intel Corporation.
  5 */
  6
  7#include <linux/kernel.h>
  8#include <linux/pci.h>
  9#include <linux/smp.h>
 10#include <linux/interrupt.h>
 11#include <linux/dca.h>
 12
 13#include <asm/cpuid/api.h>
 14
 15/* either a kernel change is needed, or we need something like this in kernel */
 16#ifndef CONFIG_SMP
 17#include <asm/smp.h>
 18#undef cpu_physical_id
 19#define cpu_physical_id(cpu) (cpuid_ebx(1) >> 24)
 20#endif
 21
 22#include "dma.h"
 23#include "registers.h"
 24
 25/*
 26 * Bit 7 of a tag map entry is the "valid" bit, if it is set then bits 0:6
 27 * contain the bit number of the APIC ID to map into the DCA tag.  If the valid
 28 * bit is not set, then the value must be 0 or 1 and defines the bit in the tag.
 29 */
 30#define DCA_TAG_MAP_VALID 0x80
 31
 32#define DCA3_TAG_MAP_BIT_TO_INV 0x80
 33#define DCA3_TAG_MAP_BIT_TO_SEL 0x40
 34#define DCA3_TAG_MAP_LITERAL_VAL 0x1
 35
 36#define DCA_TAG_MAP_MASK 0xDF
 37
 38/* expected tag map bytes for I/OAT ver.2 */
 39#define DCA2_TAG_MAP_BYTE0 0x80
 40#define DCA2_TAG_MAP_BYTE1 0x0
 41#define DCA2_TAG_MAP_BYTE2 0x81
 42#define DCA2_TAG_MAP_BYTE3 0x82
 43#define DCA2_TAG_MAP_BYTE4 0x82
 44
 45/*
 46 * "Legacy" DCA systems do not implement the DCA register set in the
 47 * I/OAT device.  Software needs direct support for their tag mappings.
 48 */
 49
 50#define APICID_BIT(x)		(DCA_TAG_MAP_VALID | (x))
 51#define IOAT_TAG_MAP_LEN	8
 52
 53/* pack PCI B/D/F into a u16 */
 54static inline u16 dcaid_from_pcidev(struct pci_dev *pci)
 55{
 56	return pci_dev_id(pci);
 57}
 58
 59static int dca_enabled_in_bios(struct pci_dev *pdev)
 60{
 61	/* CPUID level 9 returns DCA configuration */
 62	/* Bit 0 indicates DCA enabled by the BIOS */
 63	u32 eax;
 64	int res;
 65
 66	eax = cpuid_eax(CPUID_LEAF_DCA);
 67	res = eax & BIT(0);
 68	if (!res)
 69		dev_dbg(&pdev->dev, "DCA is disabled in BIOS\n");
 70
 71	return res;
 72}
 73
 74int system_has_dca_enabled(struct pci_dev *pdev)
 75{
 76	if (boot_cpu_has(X86_FEATURE_DCA))
 77		return dca_enabled_in_bios(pdev);
 78
 79	dev_dbg(&pdev->dev, "boot cpu doesn't have X86_FEATURE_DCA\n");
 80	return 0;
 81}
 82
 83struct ioat_dca_slot {
 84	struct pci_dev *pdev;	/* requester device */
 85	u16 rid;		/* requester id, as used by IOAT */
 86};
 87
 88#define IOAT_DCA_MAX_REQ 6
 89#define IOAT3_DCA_MAX_REQ 2
 90
 91struct ioat_dca_priv {
 92	void __iomem		*iobase;
 93	void __iomem		*dca_base;
 94	int			 max_requesters;
 95	int			 requester_count;
 96	u8			 tag_map[IOAT_TAG_MAP_LEN];
 97	struct ioat_dca_slot	 req_slots[];
 98};
 99
100static int ioat_dca_dev_managed(struct dca_provider *dca,
101				struct device *dev)
102{
103	struct ioat_dca_priv *ioatdca = dca_priv(dca);
104	struct pci_dev *pdev;
105	int i;
106
107	pdev = to_pci_dev(dev);
108	for (i = 0; i < ioatdca->max_requesters; i++) {
109		if (ioatdca->req_slots[i].pdev == pdev)
110			return 1;
111	}
112	return 0;
113}
114
115static int ioat_dca_add_requester(struct dca_provider *dca, struct device *dev)
116{
117	struct ioat_dca_priv *ioatdca = dca_priv(dca);
118	struct pci_dev *pdev;
119	int i;
120	u16 id;
121	u16 global_req_table;
122
123	/* This implementation only supports PCI-Express */
124	if (!dev_is_pci(dev))
125		return -ENODEV;
126	pdev = to_pci_dev(dev);
127	id = dcaid_from_pcidev(pdev);
128
129	if (ioatdca->requester_count == ioatdca->max_requesters)
130		return -ENODEV;
131
132	for (i = 0; i < ioatdca->max_requesters; i++) {
133		if (ioatdca->req_slots[i].pdev == NULL) {
134			/* found an empty slot */
135			ioatdca->requester_count++;
136			ioatdca->req_slots[i].pdev = pdev;
137			ioatdca->req_slots[i].rid = id;
138			global_req_table =
139			      readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
140			writel(id | IOAT_DCA_GREQID_VALID,
141			       ioatdca->iobase + global_req_table + (i * 4));
142			return i;
143		}
144	}
145	/* Error, ioatdma->requester_count is out of whack */
146	return -EFAULT;
147}
148
149static int ioat_dca_remove_requester(struct dca_provider *dca,
150				      struct device *dev)
151{
152	struct ioat_dca_priv *ioatdca = dca_priv(dca);
153	struct pci_dev *pdev;
154	int i;
155	u16 global_req_table;
156
157	/* This implementation only supports PCI-Express */
158	if (!dev_is_pci(dev))
159		return -ENODEV;
160	pdev = to_pci_dev(dev);
161
162	for (i = 0; i < ioatdca->max_requesters; i++) {
163		if (ioatdca->req_slots[i].pdev == pdev) {
164			global_req_table =
165			      readw(ioatdca->dca_base + IOAT3_DCA_GREQID_OFFSET);
166			writel(0, ioatdca->iobase + global_req_table + (i * 4));
167			ioatdca->req_slots[i].pdev = NULL;
168			ioatdca->req_slots[i].rid = 0;
169			ioatdca->requester_count--;
170			return i;
171		}
172	}
173	return -ENODEV;
174}
175
176static u8 ioat_dca_get_tag(struct dca_provider *dca,
177			    struct device *dev,
178			    int cpu)
179{
180	u8 tag;
181
182	struct ioat_dca_priv *ioatdca = dca_priv(dca);
183	int i, apic_id, bit, value;
184	u8 entry;
185
186	tag = 0;
187	apic_id = cpu_physical_id(cpu);
188
189	for (i = 0; i < IOAT_TAG_MAP_LEN; i++) {
190		entry = ioatdca->tag_map[i];
191		if (entry & DCA3_TAG_MAP_BIT_TO_SEL) {
192			bit = entry &
193				~(DCA3_TAG_MAP_BIT_TO_SEL | DCA3_TAG_MAP_BIT_TO_INV);
194			value = (apic_id & (1 << bit)) ? 1 : 0;
195		} else if (entry & DCA3_TAG_MAP_BIT_TO_INV) {
196			bit = entry & ~DCA3_TAG_MAP_BIT_TO_INV;
197			value = (apic_id & (1 << bit)) ? 0 : 1;
198		} else {
199			value = (entry & DCA3_TAG_MAP_LITERAL_VAL) ? 1 : 0;
200		}
201		tag |= (value << i);
202	}
203
204	return tag;
205}
206
207static const struct dca_ops ioat_dca_ops = {
208	.add_requester		= ioat_dca_add_requester,
209	.remove_requester	= ioat_dca_remove_requester,
210	.get_tag		= ioat_dca_get_tag,
211	.dev_managed		= ioat_dca_dev_managed,
212};
213
214static int ioat_dca_count_dca_slots(void *iobase, u16 dca_offset)
215{
216	int slots = 0;
217	u32 req;
218	u16 global_req_table;
219
220	global_req_table = readw(iobase + dca_offset + IOAT3_DCA_GREQID_OFFSET);
221	if (global_req_table == 0)
222		return 0;
223
224	do {
225		req = readl(iobase + global_req_table + (slots * sizeof(u32)));
226		slots++;
227	} while ((req & IOAT_DCA_GREQID_LASTID) == 0);
228
229	return slots;
230}
231
232static inline int dca3_tag_map_invalid(u8 *tag_map)
233{
234	/*
235	 * If the tag map is not programmed by the BIOS the default is:
236	 * 0x80 0x80 0x80 0x80 0x80 0x00 0x00 0x00
237	 *
238	 * This an invalid map and will result in only 2 possible tags
239	 * 0x1F and 0x00.  0x00 is an invalid DCA tag so we know that
240	 * this entire definition is invalid.
241	 */
242	return ((tag_map[0] == DCA_TAG_MAP_VALID) &&
243		(tag_map[1] == DCA_TAG_MAP_VALID) &&
244		(tag_map[2] == DCA_TAG_MAP_VALID) &&
245		(tag_map[3] == DCA_TAG_MAP_VALID) &&
246		(tag_map[4] == DCA_TAG_MAP_VALID));
247}
248
249struct dca_provider *ioat_dca_init(struct pci_dev *pdev, void __iomem *iobase)
250{
251	struct dca_provider *dca;
252	struct ioat_dca_priv *ioatdca;
253	int slots;
254	int i;
255	int err;
256	u16 dca_offset;
257	u16 csi_fsb_control;
258	u16 pcie_control;
259	u8 bit;
260
261	union {
262		u64 full;
263		struct {
264			u32 low;
265			u32 high;
266		};
267	} tag_map;
268
269	if (!system_has_dca_enabled(pdev))
270		return NULL;
271
272	dca_offset = readw(iobase + IOAT_DCAOFFSET_OFFSET);
273	if (dca_offset == 0)
274		return NULL;
275
276	slots = ioat_dca_count_dca_slots(iobase, dca_offset);
277	if (slots == 0)
278		return NULL;
279
280	dca = alloc_dca_provider(&ioat_dca_ops,
281				 struct_size(ioatdca, req_slots, slots));
282	if (!dca)
283		return NULL;
284
285	ioatdca = dca_priv(dca);
286	ioatdca->iobase = iobase;
287	ioatdca->dca_base = iobase + dca_offset;
288	ioatdca->max_requesters = slots;
289
290	/* some bios might not know to turn these on */
291	csi_fsb_control = readw(ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
292	if ((csi_fsb_control & IOAT3_CSI_CONTROL_PREFETCH) == 0) {
293		csi_fsb_control |= IOAT3_CSI_CONTROL_PREFETCH;
294		writew(csi_fsb_control,
295		       ioatdca->dca_base + IOAT3_CSI_CONTROL_OFFSET);
296	}
297	pcie_control = readw(ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
298	if ((pcie_control & IOAT3_PCI_CONTROL_MEMWR) == 0) {
299		pcie_control |= IOAT3_PCI_CONTROL_MEMWR;
300		writew(pcie_control,
301		       ioatdca->dca_base + IOAT3_PCI_CONTROL_OFFSET);
302	}
303
304
305	/* TODO version, compatibility and configuration checks */
306
307	/* copy out the APIC to DCA tag map */
308	tag_map.low =
309		readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_LOW);
310	tag_map.high =
311		readl(ioatdca->dca_base + IOAT3_APICID_TAG_MAP_OFFSET_HIGH);
312	for (i = 0; i < 8; i++) {
313		bit = tag_map.full >> (8 * i);
314		ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
315	}
316
317	if (dca3_tag_map_invalid(ioatdca->tag_map)) {
318		add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
319		pr_warn_once("%s %s: APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n",
320			     dev_driver_string(&pdev->dev),
321			     dev_name(&pdev->dev));
322		free_dca_provider(dca);
323		return NULL;
324	}
325
326	err = register_dca_provider(dca, &pdev->dev);
327	if (err) {
328		free_dca_provider(dca);
329		return NULL;
330	}
331
332	return dca;
333}
~/ Read-only file preview.