blob: 7b2db3a3380e34802ad4b59dc053bc3e7a8fc826 [file] [log] [blame]
Jason Gleneskf934fae2021-07-20 02:19:58 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpi_ivrs.h>
4#include <amdblocks/acpi.h>
5#include <amdblocks/cpu.h>
6#include <amdblocks/data_fabric.h>
7#include <amdblocks/ioapic.h>
8#include <arch/mmio.h>
9#include <console/console.h>
10#include <cpu/amd/cpuid.h>
11#include <cpu/amd/msr.h>
12#include <device/device.h>
13#include <device/pci_def.h>
14#include <device/pci_ops.h>
15#include <soc/acpi.h>
16#include <soc/data_fabric.h>
17#include <soc/pci_devs.h>
18#include <stdlib.h>
19
20#define MAX_DEV_ID 0xFFFF
21
22unsigned long acpi_fill_ivrs_ioapic(acpi_ivrs_t *ivrs, unsigned long current)
23{
24 ivrs_ivhd_special_t *ivhd_ioapic = (ivrs_ivhd_special_t *)current;
25 memset(ivhd_ioapic, 0, sizeof(*ivhd_ioapic));
26
27 ivhd_ioapic->type = IVHD_DEV_8_BYTE_EXT_SPECIAL_DEV;
28 ivhd_ioapic->dte_setting = IVHD_DTE_LINT_1_PASS | IVHD_DTE_LINT_0_PASS |
29 IVHD_DTE_SYS_MGT_NO_TRANS | IVHD_DTE_NMI_PASS |
30 IVHD_DTE_EXT_INT_PASS | IVHD_DTE_INIT_PASS;
31 ivhd_ioapic->handle = FCH_IOAPIC_ID;
32 ivhd_ioapic->source_dev_id = PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC);
33 ivhd_ioapic->variety = IVHD_SPECIAL_DEV_IOAPIC;
34 current += sizeof(ivrs_ivhd_special_t);
35
36 ivhd_ioapic = (ivrs_ivhd_special_t *)current;
37 memset(ivhd_ioapic, 0, sizeof(*ivhd_ioapic));
38
39 ivhd_ioapic->type = IVHD_DEV_8_BYTE_EXT_SPECIAL_DEV;
40 ivhd_ioapic->handle = GNB_IOAPIC_ID;
41 ivhd_ioapic->source_dev_id = PCI_DEVFN(0, 1);
42 ivhd_ioapic->variety = IVHD_SPECIAL_DEV_IOAPIC;
43 current += sizeof(ivrs_ivhd_special_t);
44
45 return current;
46}
47
48static unsigned long ivhd_describe_hpet(unsigned long current)
49{
50 ivrs_ivhd_special_t *ivhd_hpet = (ivrs_ivhd_special_t *)current;
51
52 ivhd_hpet->type = IVHD_DEV_8_BYTE_EXT_SPECIAL_DEV;
53 ivhd_hpet->reserved = 0x0000;
54 ivhd_hpet->dte_setting = 0x00;
55 ivhd_hpet->handle = 0x00;
56 ivhd_hpet->source_dev_id = PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC);
57 ivhd_hpet->variety = IVHD_SPECIAL_DEV_HPET;
58 current += sizeof(ivrs_ivhd_special_t);
59
60 return current;
61}
62
63static unsigned long ivhd_describe_f0_device(unsigned long current,
64 uint16_t dev_id, uint8_t datasetting)
65{
66 ivrs_ivhd_f0_entry_t *ivhd_f0 = (ivrs_ivhd_f0_entry_t *) current;
67
68 ivhd_f0->type = IVHD_DEV_VARIABLE;
69 ivhd_f0->dev_id = dev_id;
70 ivhd_f0->dte_setting = datasetting;
71 ivhd_f0->hardware_id[0] = 'A';
72 ivhd_f0->hardware_id[1] = 'M';
73 ivhd_f0->hardware_id[2] = 'D';
74 ivhd_f0->hardware_id[3] = 'I';
75 ivhd_f0->hardware_id[4] = '0';
76 ivhd_f0->hardware_id[5] = '0';
77 ivhd_f0->hardware_id[6] = '4';
78 ivhd_f0->hardware_id[7] = '0';
79
80 memset(ivhd_f0->compatible_id, 0, sizeof(ivhd_f0->compatible_id));
81
82 ivhd_f0->uuid_format = 0;
83 ivhd_f0->uuid_length = 0;
84
85 current += sizeof(ivrs_ivhd_f0_entry_t);
86 return current;
87}
88
89static unsigned long ivhd_dev_range(unsigned long current, uint16_t start_devid,
90 uint16_t end_devid, uint8_t setting)
91{
92 /* 4-byte IVHD structures must be aligned to the 4-byte boundary. */
93 current = ALIGN_UP(current, 4);
94 ivrs_ivhd_generic_t *ivhd_range = (ivrs_ivhd_generic_t *)current;
95
96 /* Create the start range IVHD entry */
97 ivhd_range->type = IVHD_DEV_4_BYTE_START_RANGE;
98 ivhd_range->dev_id = start_devid;
99 ivhd_range->dte_setting = setting;
100 current += sizeof(ivrs_ivhd_generic_t);
101
102 /* Create the end range IVHD entry */
103 ivhd_range = (ivrs_ivhd_generic_t *)current;
104 ivhd_range->type = IVHD_DEV_4_BYTE_END_RANGE;
105 ivhd_range->dev_id = end_devid;
106 ivhd_range->dte_setting = setting;
107 current += sizeof(ivrs_ivhd_generic_t);
108
109 return current;
110}
111
112static unsigned long add_ivhd_dev_entry(struct device *parent, struct device *dev,
113 unsigned long *current, uint8_t type, uint8_t data)
114{
115 if (type == IVHD_DEV_4_BYTE_SELECT) {
116 /* 4-byte IVHD structures must be aligned to the 4-byte boundary. */
117 *current = ALIGN_UP(*current, 4);
118 ivrs_ivhd_generic_t *ivhd_entry = (ivrs_ivhd_generic_t *)*current;
119
120 ivhd_entry->type = type;
121 ivhd_entry->dev_id = dev->path.pci.devfn | (dev->bus->secondary << 8);
122 ivhd_entry->dte_setting = data;
123 *current += sizeof(ivrs_ivhd_generic_t);
124 } else if (type == IVHD_DEV_8_BYTE_ALIAS_SELECT) {
125 ivrs_ivhd_alias_t *ivhd_entry = (ivrs_ivhd_alias_t *)*current;
126
127 ivhd_entry->type = type;
128 ivhd_entry->dev_id = dev->path.pci.devfn | (dev->bus->secondary << 8);
129 ivhd_entry->dte_setting = data;
130 ivhd_entry->reserved1 = 0;
131 ivhd_entry->reserved2 = 0;
132 ivhd_entry->source_dev_id = parent->path.pci.devfn |
133 (parent->bus->secondary << 8);
134 *current += sizeof(ivrs_ivhd_alias_t);
135 }
136
137 return *current;
138}
139
140static void ivrs_add_device_or_bridge(struct device *parent, struct device *dev,
141 unsigned long *current, uint16_t *ivhd_length)
142{
143 unsigned int header_type, is_pcie;
144 unsigned long current_backup;
145
146 header_type = dev->hdr_type & 0x7f;
147 is_pcie = pci_find_capability(dev, PCI_CAP_ID_PCIE);
148
149 if (((header_type == PCI_HEADER_TYPE_NORMAL) ||
150 (header_type == PCI_HEADER_TYPE_BRIDGE)) && is_pcie) {
151 /* Device or Bridge is PCIe */
152 current_backup = *current;
153 add_ivhd_dev_entry(parent, dev, current, IVHD_DEV_4_BYTE_SELECT, 0x0);
154 *ivhd_length += (*current - current_backup);
155 } else if ((header_type == PCI_HEADER_TYPE_NORMAL) && !is_pcie) {
156 /* Device is legacy PCI or PCI-X */
157 current_backup = *current;
158 add_ivhd_dev_entry(parent, dev, current, IVHD_DEV_8_BYTE_ALIAS_SELECT, 0x0);
159 *ivhd_length += (*current - current_backup);
160 }
161}
162
163static void add_ivhd_device_entries(struct device *parent, struct device *dev,
164 unsigned int depth, int linknum, int8_t *root_level,
165 unsigned long *current, uint16_t *ivhd_length)
166{
167 struct device *sibling;
168 struct bus *link;
169
170 if (!root_level)
171 return;
172
173 if (dev->path.type == DEVICE_PATH_PCI) {
174 if ((dev->bus->secondary == 0x0) &&
175 (dev->path.pci.devfn == 0x0))
176 *root_level = depth;
177
178 if ((*root_level != -1) && (dev->enabled)) {
179 if (depth != *root_level)
180 ivrs_add_device_or_bridge(parent, dev, current, ivhd_length);
181 }
182 }
183
184 for (link = dev->link_list; link; link = link->next)
185 for (sibling = link->children; sibling; sibling =
186 sibling->sibling)
187 add_ivhd_device_entries(dev, sibling, depth + 1, depth, root_level,
188 current, ivhd_length);
189}
190
191static unsigned long acpi_fill_ivrs40(unsigned long current, acpi_ivrs_t *ivrs)
192{
193 acpi_ivrs_ivhd40_t *ivhd_40;
194 unsigned long current_backup;
195 int8_t root_level;
196
197 /*
198 * These devices should be already found by previous function.
199 * Do not perform NULL checks.
200 */
201 struct device *nb_dev = pcidev_on_root(0, 0);
202 struct device *iommu_dev = pcidev_on_root(0, 2);
203
204 memset((void *)current, 0, sizeof(acpi_ivrs_ivhd40_t));
205 ivhd_40 = (acpi_ivrs_ivhd40_t *)current;
206
207 /* Enable EFR */
208 ivhd_40->type = IVHD_BLOCK_TYPE_FULL__ACPI_HID;
209 /* For type 40h bits 6 and 7 are reserved */
210 ivhd_40->flags = ivrs->ivhd.flags & 0x3f;
211 ivhd_40->length = sizeof(struct acpi_ivrs_ivhd_40);
212 /* BDF <bus>:00.2 */
213 ivhd_40->device_id = 0x02 | (nb_dev->bus->secondary << 8);
214 ivhd_40->capability_offset = pci_find_capability(iommu_dev, IOMMU_CAP_ID);
215 ivhd_40->iommu_base_low = ivrs->ivhd.iommu_base_low;
216 ivhd_40->iommu_base_high = ivrs->ivhd.iommu_base_high;
217 ivhd_40->pci_segment_group = 0x0000;
218 ivhd_40->iommu_info = ivrs->ivhd.iommu_info;
219 /* For type 40h bits 31:28 and 12:0 are reserved */
220 ivhd_40->iommu_attributes = ivrs->ivhd.iommu_feature_info & 0xfffe000;
221
222 if (pci_read_config32(iommu_dev, ivhd_40->capability_offset) & EFR_FEATURE_SUP) {
223 ivhd_40->efr_reg_image_low = read32((void *)ivhd_40->iommu_base_low + 0x30);
224 ivhd_40->efr_reg_image_high = read32((void *)ivhd_40->iommu_base_low + 0x34);
225 }
226
227 current += sizeof(acpi_ivrs_ivhd40_t);
228
229 /* Now repeat all the device entries from type 10h */
230 current_backup = current;
231 current = ivhd_dev_range(current, PCI_DEVFN(1, 0), MAX_DEV_ID, 0);
232 ivhd_40->length += (current - current_backup);
233 root_level = -1;
234 add_ivhd_device_entries(NULL, all_devices, 0, -1, &root_level,
235 &current, &ivhd_40->length);
236
237 /* Describe HPET */
238 current_backup = current;
239 current = ivhd_describe_hpet(current);
240 ivhd_40->length += (current - current_backup);
241
242 /* Describe IOAPICs */
243 current_backup = current;
244 current = acpi_fill_ivrs_ioapic(ivrs, current);
245 ivhd_40->length += (current - current_backup);
246
247 /* Describe EMMC */
248 current_backup = current;
249 current = ivhd_describe_f0_device(current, PCI_DEVFN(0x13, 1),
250 IVHD_DTE_LINT_1_PASS | IVHD_DTE_LINT_0_PASS |
251 IVHD_DTE_SYS_MGT_TRANS | IVHD_DTE_NMI_PASS |
252 IVHD_DTE_EXT_INT_PASS | IVHD_DTE_INIT_PASS);
253 ivhd_40->length += (current - current_backup);
254
255 return current;
256}
257
258static unsigned long acpi_fill_ivrs11(unsigned long current, acpi_ivrs_t *ivrs)
259{
260 acpi_ivrs_ivhd11_t *ivhd_11;
261 ivhd11_iommu_attr_t *ivhd11_attr_ptr;
262 unsigned long current_backup;
263 int8_t root_level;
264
265 /*
266 * These devices should be already found by previous function.
267 * Do not perform NULL checks.
268 */
269 struct device *nb_dev = pcidev_on_root(0, 0);
270 struct device *iommu_dev = pcidev_on_root(0, 2);
271
272 /*
273 * In order to utilize all features, firmware should expose type 11h
274 * IVHD which supersedes the type 10h.
275 */
276 memset((void *)current, 0, sizeof(acpi_ivrs_ivhd11_t));
277 ivhd_11 = (acpi_ivrs_ivhd11_t *)current;
278
279 /* Enable EFR */
280 ivhd_11->type = IVHD_BLOCK_TYPE_FULL__FIXED;
281 /* For type 11h bits 6 and 7 are reserved */
282 ivhd_11->flags = ivrs->ivhd.flags & 0x3f;
283 ivhd_11->length = sizeof(struct acpi_ivrs_ivhd_11);
284 /* BDF <bus>:00.2 */
285 ivhd_11->device_id = 0x02 | (nb_dev->bus->secondary << 8);
286 ivhd_11->capability_offset = pci_find_capability(iommu_dev, IOMMU_CAP_ID);
287 ivhd_11->iommu_base_low = ivrs->ivhd.iommu_base_low;
288 ivhd_11->iommu_base_high = ivrs->ivhd.iommu_base_high;
289 ivhd_11->pci_segment_group = 0x0000;
290 ivhd_11->iommu_info = ivrs->ivhd.iommu_info;
291 ivhd11_attr_ptr = (ivhd11_iommu_attr_t *) &ivrs->ivhd.iommu_feature_info;
292 ivhd_11->iommu_attributes.perf_counters = ivhd11_attr_ptr->perf_counters;
293 ivhd_11->iommu_attributes.perf_counter_banks = ivhd11_attr_ptr->perf_counter_banks;
294 ivhd_11->iommu_attributes.msi_num_ppr = ivhd11_attr_ptr->msi_num_ppr;
295
296 if (pci_read_config32(iommu_dev, ivhd_11->capability_offset) & EFR_FEATURE_SUP) {
297 ivhd_11->efr_reg_image_low = read32((void *)ivhd_11->iommu_base_low + 0x30);
298 ivhd_11->efr_reg_image_high = read32((void *)ivhd_11->iommu_base_low + 0x34);
299 }
300
301 current += sizeof(acpi_ivrs_ivhd11_t);
302
303 /* Now repeat all the device entries from type 10h */
304 current_backup = current;
305 current = ivhd_dev_range(current, PCI_DEVFN(1, 0), MAX_DEV_ID, 0);
306 ivhd_11->length += (current - current_backup);
307 root_level = -1;
308 add_ivhd_device_entries(NULL, all_devices, 0, -1, &root_level,
309 &current, &ivhd_11->length);
310
311 /* Describe HPET */
312 current_backup = current;
313 current = ivhd_describe_hpet(current);
314 ivhd_11->length += (current - current_backup);
315
316 /* Describe IOAPICs */
317 current_backup = current;
318 current = acpi_fill_ivrs_ioapic(ivrs, current);
319 ivhd_11->length += (current - current_backup);
320
321 return acpi_fill_ivrs40(current, ivrs);
322}
323
324unsigned long acpi_fill_ivrs(acpi_ivrs_t *ivrs, unsigned long current)
325{
326 unsigned long current_backup;
327 uint64_t mmio_x30_value;
328 uint64_t mmio_x18_value;
329 uint64_t mmio_x4000_value;
330 uint32_t cap_offset_0;
331 uint32_t cap_offset_10;
332 int8_t root_level;
333
334 struct device *iommu_dev;
335 struct device *nb_dev;
336
337 nb_dev = pcidev_on_root(0, 0);
338 if (!nb_dev) {
339 printk(BIOS_WARNING, "%s: Northbridge device not present!\n", __func__);
340 printk(BIOS_WARNING, "%s: IVRS table not generated...\n", __func__);
341
342 return (unsigned long)ivrs;
343 }
344
345 iommu_dev = pcidev_on_root(0, 2);
346 if (!iommu_dev) {
347 printk(BIOS_WARNING, "%s: IOMMU device not found\n", __func__);
348
349 return (unsigned long)ivrs;
350 }
351
352 if (ivrs != NULL) {
353 ivrs->ivhd.type = IVHD_BLOCK_TYPE_LEGACY__FIXED;
354 ivrs->ivhd.length = sizeof(struct acpi_ivrs_ivhd);
355
356 /* BDF <bus>:00.2 */
357 ivrs->ivhd.device_id = 0x02 | (nb_dev->bus->secondary << 8);
358 ivrs->ivhd.capability_offset = pci_find_capability(iommu_dev, IOMMU_CAP_ID);
359 ivrs->ivhd.iommu_base_low = pci_read_config32(iommu_dev, 0x44) & 0xffffc000;
360 ivrs->ivhd.iommu_base_high = pci_read_config32(iommu_dev, 0x48);
361
362 cap_offset_0 = pci_read_config32(iommu_dev, ivrs->ivhd.capability_offset);
363 cap_offset_10 = pci_read_config32(iommu_dev,
364 ivrs->ivhd.capability_offset + 0x10);
365 mmio_x18_value = read64((void *)ivrs->ivhd.iommu_base_low + 0x18);
366 mmio_x30_value = read64((void *)ivrs->ivhd.iommu_base_low + 0x30);
367 mmio_x4000_value = read64((void *)ivrs->ivhd.iommu_base_low + 0x4000);
368
369 ivrs->ivhd.flags |= ((mmio_x30_value & MMIO_EXT_FEATURE_PPR_SUP) ?
370 IVHD_FLAG_PPE_SUP : 0);
371 ivrs->ivhd.flags |= ((mmio_x30_value & MMIO_EXT_FEATURE_PRE_F_SUP) ?
372 IVHD_FLAG_PREF_SUP : 0);
373 ivrs->ivhd.flags |= ((mmio_x18_value & MMIO_CTRL_COHERENT) ?
374 IVHD_FLAG_COHERENT : 0);
375 ivrs->ivhd.flags |= ((cap_offset_0 & CAP_OFFSET_0_IOTLB_SP) ?
376 IVHD_FLAG_IOTLB_SUP : 0);
377 ivrs->ivhd.flags |= ((mmio_x18_value & MMIO_CTRL_ISOC) ?
378 IVHD_FLAG_ISOC : 0);
379 ivrs->ivhd.flags |= ((mmio_x18_value & MMIO_CTRL_RES_PASS_PW) ?
380 IVHD_FLAG_RES_PASS_PW : 0);
381 ivrs->ivhd.flags |= ((mmio_x18_value & MMIO_CTRL_PASS_PW) ?
382 IVHD_FLAG_PASS_PW : 0);
383 ivrs->ivhd.flags |= ((mmio_x18_value & MMIO_CTRL_HT_TUN_EN) ?
384 IVHD_FLAG_HT_TUN_EN : 0);
385
386 ivrs->ivhd.pci_segment_group = 0x0000;
387
388 ivrs->ivhd.iommu_info = pci_read_config16(iommu_dev,
389 ivrs->ivhd.capability_offset + 0x10) & 0x1F;
390 ivrs->ivhd.iommu_info |= (pci_read_config16(iommu_dev,
391 ivrs->ivhd.capability_offset + 0xC) & 0x1F) << IOMMU_INFO_UNIT_ID_SHIFT;
392
393 ivrs->ivhd.iommu_feature_info = 0;
394 ivrs->ivhd.iommu_feature_info |= (mmio_x30_value & MMIO_EXT_FEATURE_HATS_MASK)
395 << (IOMMU_FEATURE_HATS_SHIFT - MMIO_EXT_FEATURE_HATS_SHIFT);
396
397 ivrs->ivhd.iommu_feature_info |= (mmio_x30_value & MMIO_EXT_FEATURE_GATS_MASK)
398 << (IOMMU_FEATURE_GATS_SHIFT - MMIO_EXT_FEATURE_GATS_SHIFT);
399
400 ivrs->ivhd.iommu_feature_info |= (cap_offset_10 & CAP_OFFSET_10_MSI_NUM_PPR)
401 >> (CAP_OFFSET_10_MSI_NUM_PPR_SHIFT
402 - IOMMU_FEATURE_MSI_NUM_PPR_SHIFT);
403
404 ivrs->ivhd.iommu_feature_info |= (mmio_x4000_value &
405 MMIO_CNT_CFG_N_COUNTER_BANKS)
406 << (IOMMU_FEATURE_PN_BANKS_SHIFT - MMIO_CNT_CFG_N_CNT_BANKS_SHIFT);
407
408 ivrs->ivhd.iommu_feature_info |= (mmio_x4000_value & MMIO_CNT_CFG_N_COUNTER)
409 << (IOMMU_FEATURE_PN_COUNTERS_SHIFT - MMIO_CNT_CFG_N_COUNTER_SHIFT);
410 ivrs->ivhd.iommu_feature_info |= (mmio_x30_value &
411 MMIO_EXT_FEATURE_PAS_MAX_MASK)
412 >> (MMIO_EXT_FEATURE_PAS_MAX_SHIFT - IOMMU_FEATURE_PA_SMAX_SHIFT);
413 ivrs->ivhd.iommu_feature_info |= ((mmio_x30_value & MMIO_EXT_FEATURE_HE_SUP)
414 ? IOMMU_FEATURE_HE_SUP : 0);
415 ivrs->ivhd.iommu_feature_info |= ((mmio_x30_value & MMIO_EXT_FEATURE_GA_SUP)
416 ? IOMMU_FEATURE_GA_SUP : 0);
417 ivrs->ivhd.iommu_feature_info |= ((mmio_x30_value & MMIO_EXT_FEATURE_IA_SUP)
418 ? IOMMU_FEATURE_IA_SUP : 0);
419 ivrs->ivhd.iommu_feature_info |= (mmio_x30_value &
420 MMIO_EXT_FEATURE_GLX_SUP_MASK)
421 >> (MMIO_EXT_FEATURE_GLX_SHIFT - IOMMU_FEATURE_GLX_SHIFT);
422 ivrs->ivhd.iommu_feature_info |= ((mmio_x30_value & MMIO_EXT_FEATURE_GT_SUP)
423 ? IOMMU_FEATURE_GT_SUP : 0);
424 ivrs->ivhd.iommu_feature_info |= ((mmio_x30_value & MMIO_EXT_FEATURE_NX_SUP)
425 ? IOMMU_FEATURE_NX_SUP : 0);
426 ivrs->ivhd.iommu_feature_info |= ((mmio_x30_value & MMIO_EXT_FEATURE_XT_SUP)
427 ? IOMMU_FEATURE_XT_SUP : 0);
428
429 /* Enable EFR if supported */
430 ivrs->iv_info = pci_read_config32(iommu_dev,
431 ivrs->ivhd.capability_offset + 0x10) & 0x007fffe0;
432 if (pci_read_config32(iommu_dev,
433 ivrs->ivhd.capability_offset) & EFR_FEATURE_SUP)
434 ivrs->iv_info |= IVINFO_EFR_SUPPORTED;
435
436 } else {
437 printk(BIOS_WARNING, "%s: AGESA returned NULL IVRS\n", __func__);
438
439 return (unsigned long)ivrs;
440 }
441
442 /*
443 * Add all possible PCI devices that can generate transactions
444 * processed by IOMMU. Start with device 00:01.0
445 */
446 current_backup = current;
447 current = ivhd_dev_range(current, PCI_DEVFN(1, 0), MAX_DEV_ID, 0);
448 ivrs->ivhd.length += (current - current_backup);
449 root_level = -1;
450 add_ivhd_device_entries(NULL, all_devices, 0, -1, &root_level,
451 &current, &ivrs->ivhd.length);
452
453 /* Describe HPET */
454 current_backup = current;
455 current = ivhd_describe_hpet(current);
456 ivrs->ivhd.length += (current - current_backup);
457
458 /* Describe IOAPICs */
459 current_backup = current;
460 current = acpi_fill_ivrs_ioapic(ivrs, current);
461 ivrs->ivhd.length += (current - current_backup);
462
463 /* If EFR is not supported, IVHD type 11h is reserved */
464 if (!(ivrs->iv_info & IVINFO_EFR_SUPPORTED))
465 return current;
466
467 return acpi_fill_ivrs11(current, ivrs);
468}