2 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #include <linux/platform_device.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/libnvdimm.h>
17 #include <linux/vmalloc.h>
18 #include <linux/device.h>
19 #include <linux/module.h>
20 #include <linux/mutex.h>
21 #include <linux/ndctl.h>
22 #include <linux/sizes.h>
23 #include <linux/list.h>
24 #include <linux/slab.h>
27 #include "nfit_test.h"
30 * Generate an NFIT table to describe the following topology:
32 * BUS0: Interleaved PMEM regions, and aliasing with BLK regions
34 * (a) (b) DIMM BLK-REGION
35 * +----------+--------------+----------+---------+
36 * +------+ | blk2.0 | pm0.0 | blk2.1 | pm1.0 | 0 region2
37 * | imc0 +--+- - - - - region0 - - - -+----------+ +
38 * +--+---+ | blk3.0 | pm0.0 | blk3.1 | pm1.0 | 1 region3
39 * | +----------+--------------v----------v v
43 * | +-------------------------^----------^ ^
44 * +--+---+ | blk4.0 | pm1.0 | 2 region4
45 * | imc1 +--+-------------------------+----------+ +
46 * +------+ | blk5.0 | pm1.0 | 3 region5
47 * +-------------------------+----------+-+-------+
51 * +--+---+ (Hotplug DIMM)
52 * | +----------------------------------------------+
53 * +--+---+ | blk6.0/pm7.0 | 4 region6/7
54 * | imc0 +--+----------------------------------------------+
58 * *) In this layout we have four dimms and two memory controllers in one
59 * socket. Each unique interface (BLK or PMEM) to DPA space
60 * is identified by a region device with a dynamically assigned id.
62 * *) The first portion of dimm0 and dimm1 are interleaved as REGION0.
63 * A single PMEM namespace "pm0.0" is created using half of the
64 * REGION0 SPA-range. REGION0 spans dimm0 and dimm1. PMEM namespace
65 * allocate from from the bottom of a region. The unallocated
66 * portion of REGION0 aliases with REGION2 and REGION3. That
67 * unallacted capacity is reclaimed as BLK namespaces ("blk2.0" and
68 * "blk3.0") starting at the base of each DIMM to offset (a) in those
69 * DIMMs. "pm0.0", "blk2.0" and "blk3.0" are free-form readable
70 * names that can be assigned to a namespace.
72 * *) In the last portion of dimm0 and dimm1 we have an interleaved
73 * SPA range, REGION1, that spans those two dimms as well as dimm2
74 * and dimm3. Some of REGION1 allocated to a PMEM namespace named
75 * "pm1.0" the rest is reclaimed in 4 BLK namespaces (for each
76 * dimm in the interleave set), "blk2.1", "blk3.1", "blk4.0", and
79 * *) The portion of dimm2 and dimm3 that do not participate in the
80 * REGION1 interleaved SPA range (i.e. the DPA address below offset
81 * (b) are also included in the "blk4.0" and "blk5.0" namespaces.
82 * Note, that BLK namespaces need not be contiguous in DPA-space, and
83 * can consume aliased capacity from multiple interleave sets.
85 * BUS1: Legacy NVDIMM (single contiguous range)
88 * +---------------------+
89 * |---------------------|
91 * |---------------------|
92 * +---------------------+
94 * *) A NFIT-table may describe a simple system-physical-address range
95 * with no BLK aliasing. This type of region may optionally
96 * reference an NVDIMM.
102 NUM_SPA
= NUM_PM
+ NUM_DCR
+ NUM_BDW
,
103 NUM_MEM
= NUM_DCR
+ NUM_BDW
+ 2 /* spa0 iset */ + 4 /* spa1 iset */,
105 LABEL_SIZE
= SZ_128K
,
106 SPA0_SIZE
= DIMM_SIZE
,
107 SPA1_SIZE
= DIMM_SIZE
*2,
108 SPA2_SIZE
= DIMM_SIZE
,
111 NUM_NFITS
= 2, /* permit testing multiple NFITs per system */
114 struct nfit_test_dcr
{
117 __u8 aperature
[BDW_SIZE
];
120 #define NFIT_DIMM_HANDLE(node, socket, imc, chan, dimm) \
121 (((node & 0xfff) << 16) | ((socket & 0xf) << 12) \
122 | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf))
124 static u32 handle
[NUM_DCR
] = {
125 [0] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0),
126 [1] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1),
127 [2] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0),
128 [3] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1),
129 [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0),
133 struct acpi_nfit_desc acpi_desc
;
134 struct platform_device pdev
;
135 struct list_head resources
;
142 dma_addr_t
*dimm_dma
;
144 dma_addr_t
*flush_dma
;
146 dma_addr_t
*label_dma
;
148 dma_addr_t
*spa_set_dma
;
149 struct nfit_test_dcr
**dcr
;
151 int (*alloc
)(struct nfit_test
*t
);
152 void (*setup
)(struct nfit_test
*t
);
155 struct nd_cmd_ars_status
*ars_status
;
156 unsigned long deadline
;
161 static struct nfit_test
*to_nfit_test(struct device
*dev
)
163 struct platform_device
*pdev
= to_platform_device(dev
);
165 return container_of(pdev
, struct nfit_test
, pdev
);
168 static int nfit_test_cmd_get_config_size(struct nd_cmd_get_config_size
*nd_cmd
,
169 unsigned int buf_len
)
171 if (buf_len
< sizeof(*nd_cmd
))
175 nd_cmd
->config_size
= LABEL_SIZE
;
176 nd_cmd
->max_xfer
= SZ_4K
;
181 static int nfit_test_cmd_get_config_data(struct nd_cmd_get_config_data_hdr
182 *nd_cmd
, unsigned int buf_len
, void *label
)
184 unsigned int len
, offset
= nd_cmd
->in_offset
;
187 if (buf_len
< sizeof(*nd_cmd
))
189 if (offset
>= LABEL_SIZE
)
191 if (nd_cmd
->in_length
+ sizeof(*nd_cmd
) > buf_len
)
195 len
= min(nd_cmd
->in_length
, LABEL_SIZE
- offset
);
196 memcpy(nd_cmd
->out_buf
, label
+ offset
, len
);
197 rc
= buf_len
- sizeof(*nd_cmd
) - len
;
202 static int nfit_test_cmd_set_config_data(struct nd_cmd_set_config_hdr
*nd_cmd
,
203 unsigned int buf_len
, void *label
)
205 unsigned int len
, offset
= nd_cmd
->in_offset
;
209 if (buf_len
< sizeof(*nd_cmd
))
211 if (offset
>= LABEL_SIZE
)
213 if (nd_cmd
->in_length
+ sizeof(*nd_cmd
) + 4 > buf_len
)
216 status
= (void *)nd_cmd
+ nd_cmd
->in_length
+ sizeof(*nd_cmd
);
218 len
= min(nd_cmd
->in_length
, LABEL_SIZE
- offset
);
219 memcpy(label
+ offset
, nd_cmd
->in_buf
, len
);
220 rc
= buf_len
- sizeof(*nd_cmd
) - (len
+ 4);
225 #define NFIT_TEST_ARS_RECORDS 4
226 #define NFIT_TEST_CLEAR_ERR_UNIT 256
228 static int nfit_test_cmd_ars_cap(struct nd_cmd_ars_cap
*nd_cmd
,
229 unsigned int buf_len
)
231 if (buf_len
< sizeof(*nd_cmd
))
234 nd_cmd
->max_ars_out
= sizeof(struct nd_cmd_ars_status
)
235 + NFIT_TEST_ARS_RECORDS
* sizeof(struct nd_ars_record
);
236 nd_cmd
->status
= (ND_ARS_PERSISTENT
| ND_ARS_VOLATILE
) << 16;
237 nd_cmd
->clear_err_unit
= NFIT_TEST_CLEAR_ERR_UNIT
;
243 * Initialize the ars_state to return an ars_result 1 second in the future with
244 * a 4K error range in the middle of the requested address range.
246 static void post_ars_status(struct ars_state
*ars_state
, u64 addr
, u64 len
)
248 struct nd_cmd_ars_status
*ars_status
;
249 struct nd_ars_record
*ars_record
;
251 ars_state
->deadline
= jiffies
+ 1*HZ
;
252 ars_status
= ars_state
->ars_status
;
253 ars_status
->status
= 0;
254 ars_status
->out_length
= sizeof(struct nd_cmd_ars_status
)
255 + sizeof(struct nd_ars_record
);
256 ars_status
->address
= addr
;
257 ars_status
->length
= len
;
258 ars_status
->type
= ND_ARS_PERSISTENT
;
259 ars_status
->num_records
= 1;
260 ars_record
= &ars_status
->records
[0];
261 ars_record
->handle
= 0;
262 ars_record
->err_address
= addr
+ len
/ 2;
263 ars_record
->length
= SZ_4K
;
266 static int nfit_test_cmd_ars_start(struct ars_state
*ars_state
,
267 struct nd_cmd_ars_start
*ars_start
, unsigned int buf_len
,
270 if (buf_len
< sizeof(*ars_start
))
273 spin_lock(&ars_state
->lock
);
274 if (time_before(jiffies
, ars_state
->deadline
)) {
275 ars_start
->status
= NFIT_ARS_START_BUSY
;
278 ars_start
->status
= 0;
279 ars_start
->scrub_time
= 1;
280 post_ars_status(ars_state
, ars_start
->address
,
284 spin_unlock(&ars_state
->lock
);
289 static int nfit_test_cmd_ars_status(struct ars_state
*ars_state
,
290 struct nd_cmd_ars_status
*ars_status
, unsigned int buf_len
,
293 if (buf_len
< ars_state
->ars_status
->out_length
)
296 spin_lock(&ars_state
->lock
);
297 if (time_before(jiffies
, ars_state
->deadline
)) {
298 memset(ars_status
, 0, buf_len
);
299 ars_status
->status
= NFIT_ARS_STATUS_BUSY
;
300 ars_status
->out_length
= sizeof(*ars_status
);
303 memcpy(ars_status
, ars_state
->ars_status
,
304 ars_state
->ars_status
->out_length
);
307 spin_unlock(&ars_state
->lock
);
311 static int nfit_test_cmd_clear_error(struct nd_cmd_clear_error
*clear_err
,
312 unsigned int buf_len
, int *cmd_rc
)
314 const u64 mask
= NFIT_TEST_CLEAR_ERR_UNIT
- 1;
315 if (buf_len
< sizeof(*clear_err
))
318 if ((clear_err
->address
& mask
) || (clear_err
->length
& mask
))
322 * Report 'all clear' success for all commands even though a new
323 * scrub will find errors again. This is enough to have the
324 * error removed from the 'badblocks' tracking in the pmem
327 clear_err
->status
= 0;
328 clear_err
->cleared
= clear_err
->length
;
333 static int nfit_test_cmd_smart(struct nd_cmd_smart
*smart
, unsigned int buf_len
)
335 static const struct nd_smart_payload smart_data
= {
336 .flags
= ND_SMART_HEALTH_VALID
| ND_SMART_TEMP_VALID
337 | ND_SMART_SPARES_VALID
| ND_SMART_ALARM_VALID
338 | ND_SMART_USED_VALID
| ND_SMART_SHUTDOWN_VALID
,
339 .health
= ND_SMART_NON_CRITICAL_HEALTH
,
340 .temperature
= 23 * 16,
342 .alarm_flags
= ND_SMART_SPARE_TRIP
| ND_SMART_TEMP_TRIP
,
348 if (buf_len
< sizeof(*smart
))
350 memcpy(smart
->data
, &smart_data
, sizeof(smart_data
));
354 static int nfit_test_cmd_smart_threshold(struct nd_cmd_smart_threshold
*smart_t
,
355 unsigned int buf_len
)
357 static const struct nd_smart_threshold_payload smart_t_data
= {
358 .alarm_control
= ND_SMART_SPARE_TRIP
| ND_SMART_TEMP_TRIP
,
359 .temperature
= 40 * 16,
363 if (buf_len
< sizeof(*smart_t
))
365 memcpy(smart_t
->data
, &smart_t_data
, sizeof(smart_t_data
));
369 static int nfit_test_ctl(struct nvdimm_bus_descriptor
*nd_desc
,
370 struct nvdimm
*nvdimm
, unsigned int cmd
, void *buf
,
371 unsigned int buf_len
, int *cmd_rc
)
373 struct acpi_nfit_desc
*acpi_desc
= to_acpi_desc(nd_desc
);
374 struct nfit_test
*t
= container_of(acpi_desc
, typeof(*t
), acpi_desc
);
375 int i
, rc
= 0, __cmd_rc
;
382 struct nfit_mem
*nfit_mem
= nvdimm_provider_data(nvdimm
);
384 if (!nfit_mem
|| !test_bit(cmd
, &nfit_mem
->dsm_mask
))
387 /* lookup label space for the given dimm */
388 for (i
= 0; i
< ARRAY_SIZE(handle
); i
++)
389 if (__to_nfit_memdev(nfit_mem
)->device_handle
==
392 if (i
>= ARRAY_SIZE(handle
))
396 case ND_CMD_GET_CONFIG_SIZE
:
397 rc
= nfit_test_cmd_get_config_size(buf
, buf_len
);
399 case ND_CMD_GET_CONFIG_DATA
:
400 rc
= nfit_test_cmd_get_config_data(buf
, buf_len
,
403 case ND_CMD_SET_CONFIG_DATA
:
404 rc
= nfit_test_cmd_set_config_data(buf
, buf_len
,
408 rc
= nfit_test_cmd_smart(buf
, buf_len
);
410 case ND_CMD_SMART_THRESHOLD
:
411 rc
= nfit_test_cmd_smart_threshold(buf
, buf_len
);
417 struct ars_state
*ars_state
= &t
->ars_state
;
419 if (!nd_desc
|| !test_bit(cmd
, &nd_desc
->dsm_mask
))
424 rc
= nfit_test_cmd_ars_cap(buf
, buf_len
);
426 case ND_CMD_ARS_START
:
427 rc
= nfit_test_cmd_ars_start(ars_state
, buf
, buf_len
,
430 case ND_CMD_ARS_STATUS
:
431 rc
= nfit_test_cmd_ars_status(ars_state
, buf
, buf_len
,
434 case ND_CMD_CLEAR_ERROR
:
435 rc
= nfit_test_cmd_clear_error(buf
, buf_len
, cmd_rc
);
445 static DEFINE_SPINLOCK(nfit_test_lock
);
446 static struct nfit_test
*instances
[NUM_NFITS
];
448 static void release_nfit_res(void *data
)
450 struct nfit_test_resource
*nfit_res
= data
;
451 struct resource
*res
= nfit_res
->res
;
453 spin_lock(&nfit_test_lock
);
454 list_del(&nfit_res
->list
);
455 spin_unlock(&nfit_test_lock
);
457 if (is_vmalloc_addr(nfit_res
->buf
))
458 vfree(nfit_res
->buf
);
460 dma_free_coherent(nfit_res
->dev
, resource_size(res
),
461 nfit_res
->buf
, res
->start
);
466 static void *__test_alloc(struct nfit_test
*t
, size_t size
, dma_addr_t
*dma
,
469 struct device
*dev
= &t
->pdev
.dev
;
470 struct resource
*res
= kzalloc(sizeof(*res
) * 2, GFP_KERNEL
);
471 struct nfit_test_resource
*nfit_res
= kzalloc(sizeof(*nfit_res
),
475 if (!res
|| !buf
|| !nfit_res
)
477 rc
= devm_add_action(dev
, release_nfit_res
, nfit_res
);
480 INIT_LIST_HEAD(&nfit_res
->list
);
481 memset(buf
, 0, size
);
486 res
->end
= *dma
+ size
- 1;
488 spin_lock(&nfit_test_lock
);
489 list_add(&nfit_res
->list
, &t
->resources
);
490 spin_unlock(&nfit_test_lock
);
492 return nfit_res
->buf
;
494 if (buf
&& !is_vmalloc_addr(buf
))
495 dma_free_coherent(dev
, size
, buf
, *dma
);
503 static void *test_alloc(struct nfit_test
*t
, size_t size
, dma_addr_t
*dma
)
505 void *buf
= vmalloc(size
);
507 *dma
= (unsigned long) buf
;
508 return __test_alloc(t
, size
, dma
, buf
);
511 static void *test_alloc_coherent(struct nfit_test
*t
, size_t size
,
514 struct device
*dev
= &t
->pdev
.dev
;
515 void *buf
= dma_alloc_coherent(dev
, size
, dma
, GFP_KERNEL
);
517 return __test_alloc(t
, size
, dma
, buf
);
520 static struct nfit_test_resource
*nfit_test_lookup(resource_size_t addr
)
524 for (i
= 0; i
< ARRAY_SIZE(instances
); i
++) {
525 struct nfit_test_resource
*n
, *nfit_res
= NULL
;
526 struct nfit_test
*t
= instances
[i
];
530 spin_lock(&nfit_test_lock
);
531 list_for_each_entry(n
, &t
->resources
, list
) {
532 if (addr
>= n
->res
->start
&& (addr
< n
->res
->start
533 + resource_size(n
->res
))) {
536 } else if (addr
>= (unsigned long) n
->buf
537 && (addr
< (unsigned long) n
->buf
538 + resource_size(n
->res
))) {
543 spin_unlock(&nfit_test_lock
);
551 static int ars_state_init(struct device
*dev
, struct ars_state
*ars_state
)
553 ars_state
->ars_status
= devm_kzalloc(dev
,
554 sizeof(struct nd_cmd_ars_status
)
555 + sizeof(struct nd_ars_record
) * NFIT_TEST_ARS_RECORDS
,
557 if (!ars_state
->ars_status
)
559 spin_lock_init(&ars_state
->lock
);
563 static int nfit_test0_alloc(struct nfit_test
*t
)
565 size_t nfit_size
= sizeof(struct acpi_nfit_system_address
) * NUM_SPA
566 + sizeof(struct acpi_nfit_memory_map
) * NUM_MEM
567 + sizeof(struct acpi_nfit_control_region
) * NUM_DCR
568 + offsetof(struct acpi_nfit_control_region
,
569 window_size
) * NUM_DCR
570 + sizeof(struct acpi_nfit_data_region
) * NUM_BDW
571 + sizeof(struct acpi_nfit_flush_address
) * NUM_DCR
;
574 t
->nfit_buf
= test_alloc(t
, nfit_size
, &t
->nfit_dma
);
577 t
->nfit_size
= nfit_size
;
579 t
->spa_set
[0] = test_alloc_coherent(t
, SPA0_SIZE
, &t
->spa_set_dma
[0]);
583 t
->spa_set
[1] = test_alloc_coherent(t
, SPA1_SIZE
, &t
->spa_set_dma
[1]);
587 t
->spa_set
[2] = test_alloc_coherent(t
, SPA0_SIZE
, &t
->spa_set_dma
[2]);
591 for (i
= 0; i
< NUM_DCR
; i
++) {
592 t
->dimm
[i
] = test_alloc(t
, DIMM_SIZE
, &t
->dimm_dma
[i
]);
596 t
->label
[i
] = test_alloc(t
, LABEL_SIZE
, &t
->label_dma
[i
]);
599 sprintf(t
->label
[i
], "label%d", i
);
601 t
->flush
[i
] = test_alloc(t
, 8, &t
->flush_dma
[i
]);
606 for (i
= 0; i
< NUM_DCR
; i
++) {
607 t
->dcr
[i
] = test_alloc(t
, LABEL_SIZE
, &t
->dcr_dma
[i
]);
612 return ars_state_init(&t
->pdev
.dev
, &t
->ars_state
);
615 static int nfit_test1_alloc(struct nfit_test
*t
)
617 size_t nfit_size
= sizeof(struct acpi_nfit_system_address
)
618 + sizeof(struct acpi_nfit_memory_map
)
619 + offsetof(struct acpi_nfit_control_region
, window_size
);
621 t
->nfit_buf
= test_alloc(t
, nfit_size
, &t
->nfit_dma
);
624 t
->nfit_size
= nfit_size
;
626 t
->spa_set
[0] = test_alloc_coherent(t
, SPA2_SIZE
, &t
->spa_set_dma
[0]);
630 return ars_state_init(&t
->pdev
.dev
, &t
->ars_state
);
633 static void nfit_test0_setup(struct nfit_test
*t
)
635 struct acpi_nfit_desc
*acpi_desc
;
636 struct acpi_nfit_memory_map
*memdev
;
637 void *nfit_buf
= t
->nfit_buf
;
638 struct acpi_nfit_system_address
*spa
;
639 struct acpi_nfit_control_region
*dcr
;
640 struct acpi_nfit_data_region
*bdw
;
641 struct acpi_nfit_flush_address
*flush
;
645 * spa0 (interleave first half of dimm0 and dimm1, note storage
646 * does not actually alias the related block-data-window
650 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
651 spa
->header
.length
= sizeof(*spa
);
652 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_PM
), 16);
653 spa
->range_index
= 0+1;
654 spa
->address
= t
->spa_set_dma
[0];
655 spa
->length
= SPA0_SIZE
;
658 * spa1 (interleave last half of the 4 DIMMS, note storage
659 * does not actually alias the related block-data-window
662 spa
= nfit_buf
+ sizeof(*spa
);
663 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
664 spa
->header
.length
= sizeof(*spa
);
665 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_PM
), 16);
666 spa
->range_index
= 1+1;
667 spa
->address
= t
->spa_set_dma
[1];
668 spa
->length
= SPA1_SIZE
;
670 /* spa2 (dcr0) dimm0 */
671 spa
= nfit_buf
+ sizeof(*spa
) * 2;
672 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
673 spa
->header
.length
= sizeof(*spa
);
674 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_DCR
), 16);
675 spa
->range_index
= 2+1;
676 spa
->address
= t
->dcr_dma
[0];
677 spa
->length
= DCR_SIZE
;
679 /* spa3 (dcr1) dimm1 */
680 spa
= nfit_buf
+ sizeof(*spa
) * 3;
681 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
682 spa
->header
.length
= sizeof(*spa
);
683 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_DCR
), 16);
684 spa
->range_index
= 3+1;
685 spa
->address
= t
->dcr_dma
[1];
686 spa
->length
= DCR_SIZE
;
688 /* spa4 (dcr2) dimm2 */
689 spa
= nfit_buf
+ sizeof(*spa
) * 4;
690 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
691 spa
->header
.length
= sizeof(*spa
);
692 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_DCR
), 16);
693 spa
->range_index
= 4+1;
694 spa
->address
= t
->dcr_dma
[2];
695 spa
->length
= DCR_SIZE
;
697 /* spa5 (dcr3) dimm3 */
698 spa
= nfit_buf
+ sizeof(*spa
) * 5;
699 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
700 spa
->header
.length
= sizeof(*spa
);
701 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_DCR
), 16);
702 spa
->range_index
= 5+1;
703 spa
->address
= t
->dcr_dma
[3];
704 spa
->length
= DCR_SIZE
;
706 /* spa6 (bdw for dcr0) dimm0 */
707 spa
= nfit_buf
+ sizeof(*spa
) * 6;
708 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
709 spa
->header
.length
= sizeof(*spa
);
710 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_BDW
), 16);
711 spa
->range_index
= 6+1;
712 spa
->address
= t
->dimm_dma
[0];
713 spa
->length
= DIMM_SIZE
;
715 /* spa7 (bdw for dcr1) dimm1 */
716 spa
= nfit_buf
+ sizeof(*spa
) * 7;
717 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
718 spa
->header
.length
= sizeof(*spa
);
719 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_BDW
), 16);
720 spa
->range_index
= 7+1;
721 spa
->address
= t
->dimm_dma
[1];
722 spa
->length
= DIMM_SIZE
;
724 /* spa8 (bdw for dcr2) dimm2 */
725 spa
= nfit_buf
+ sizeof(*spa
) * 8;
726 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
727 spa
->header
.length
= sizeof(*spa
);
728 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_BDW
), 16);
729 spa
->range_index
= 8+1;
730 spa
->address
= t
->dimm_dma
[2];
731 spa
->length
= DIMM_SIZE
;
733 /* spa9 (bdw for dcr3) dimm3 */
734 spa
= nfit_buf
+ sizeof(*spa
) * 9;
735 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
736 spa
->header
.length
= sizeof(*spa
);
737 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_BDW
), 16);
738 spa
->range_index
= 9+1;
739 spa
->address
= t
->dimm_dma
[3];
740 spa
->length
= DIMM_SIZE
;
742 offset
= sizeof(*spa
) * 10;
743 /* mem-region0 (spa0, dimm0) */
744 memdev
= nfit_buf
+ offset
;
745 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
746 memdev
->header
.length
= sizeof(*memdev
);
747 memdev
->device_handle
= handle
[0];
748 memdev
->physical_id
= 0;
749 memdev
->region_id
= 0;
750 memdev
->range_index
= 0+1;
751 memdev
->region_index
= 4+1;
752 memdev
->region_size
= SPA0_SIZE
/2;
753 memdev
->region_offset
= t
->spa_set_dma
[0];
755 memdev
->interleave_index
= 0;
756 memdev
->interleave_ways
= 2;
758 /* mem-region1 (spa0, dimm1) */
759 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
);
760 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
761 memdev
->header
.length
= sizeof(*memdev
);
762 memdev
->device_handle
= handle
[1];
763 memdev
->physical_id
= 1;
764 memdev
->region_id
= 0;
765 memdev
->range_index
= 0+1;
766 memdev
->region_index
= 5+1;
767 memdev
->region_size
= SPA0_SIZE
/2;
768 memdev
->region_offset
= t
->spa_set_dma
[0] + SPA0_SIZE
/2;
770 memdev
->interleave_index
= 0;
771 memdev
->interleave_ways
= 2;
773 /* mem-region2 (spa1, dimm0) */
774 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 2;
775 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
776 memdev
->header
.length
= sizeof(*memdev
);
777 memdev
->device_handle
= handle
[0];
778 memdev
->physical_id
= 0;
779 memdev
->region_id
= 1;
780 memdev
->range_index
= 1+1;
781 memdev
->region_index
= 4+1;
782 memdev
->region_size
= SPA1_SIZE
/4;
783 memdev
->region_offset
= t
->spa_set_dma
[1];
784 memdev
->address
= SPA0_SIZE
/2;
785 memdev
->interleave_index
= 0;
786 memdev
->interleave_ways
= 4;
788 /* mem-region3 (spa1, dimm1) */
789 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 3;
790 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
791 memdev
->header
.length
= sizeof(*memdev
);
792 memdev
->device_handle
= handle
[1];
793 memdev
->physical_id
= 1;
794 memdev
->region_id
= 1;
795 memdev
->range_index
= 1+1;
796 memdev
->region_index
= 5+1;
797 memdev
->region_size
= SPA1_SIZE
/4;
798 memdev
->region_offset
= t
->spa_set_dma
[1] + SPA1_SIZE
/4;
799 memdev
->address
= SPA0_SIZE
/2;
800 memdev
->interleave_index
= 0;
801 memdev
->interleave_ways
= 4;
803 /* mem-region4 (spa1, dimm2) */
804 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 4;
805 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
806 memdev
->header
.length
= sizeof(*memdev
);
807 memdev
->device_handle
= handle
[2];
808 memdev
->physical_id
= 2;
809 memdev
->region_id
= 0;
810 memdev
->range_index
= 1+1;
811 memdev
->region_index
= 6+1;
812 memdev
->region_size
= SPA1_SIZE
/4;
813 memdev
->region_offset
= t
->spa_set_dma
[1] + 2*SPA1_SIZE
/4;
814 memdev
->address
= SPA0_SIZE
/2;
815 memdev
->interleave_index
= 0;
816 memdev
->interleave_ways
= 4;
818 /* mem-region5 (spa1, dimm3) */
819 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 5;
820 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
821 memdev
->header
.length
= sizeof(*memdev
);
822 memdev
->device_handle
= handle
[3];
823 memdev
->physical_id
= 3;
824 memdev
->region_id
= 0;
825 memdev
->range_index
= 1+1;
826 memdev
->region_index
= 7+1;
827 memdev
->region_size
= SPA1_SIZE
/4;
828 memdev
->region_offset
= t
->spa_set_dma
[1] + 3*SPA1_SIZE
/4;
829 memdev
->address
= SPA0_SIZE
/2;
830 memdev
->interleave_index
= 0;
831 memdev
->interleave_ways
= 4;
833 /* mem-region6 (spa/dcr0, dimm0) */
834 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 6;
835 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
836 memdev
->header
.length
= sizeof(*memdev
);
837 memdev
->device_handle
= handle
[0];
838 memdev
->physical_id
= 0;
839 memdev
->region_id
= 0;
840 memdev
->range_index
= 2+1;
841 memdev
->region_index
= 0+1;
842 memdev
->region_size
= 0;
843 memdev
->region_offset
= 0;
845 memdev
->interleave_index
= 0;
846 memdev
->interleave_ways
= 1;
848 /* mem-region7 (spa/dcr1, dimm1) */
849 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 7;
850 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
851 memdev
->header
.length
= sizeof(*memdev
);
852 memdev
->device_handle
= handle
[1];
853 memdev
->physical_id
= 1;
854 memdev
->region_id
= 0;
855 memdev
->range_index
= 3+1;
856 memdev
->region_index
= 1+1;
857 memdev
->region_size
= 0;
858 memdev
->region_offset
= 0;
860 memdev
->interleave_index
= 0;
861 memdev
->interleave_ways
= 1;
863 /* mem-region8 (spa/dcr2, dimm2) */
864 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 8;
865 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
866 memdev
->header
.length
= sizeof(*memdev
);
867 memdev
->device_handle
= handle
[2];
868 memdev
->physical_id
= 2;
869 memdev
->region_id
= 0;
870 memdev
->range_index
= 4+1;
871 memdev
->region_index
= 2+1;
872 memdev
->region_size
= 0;
873 memdev
->region_offset
= 0;
875 memdev
->interleave_index
= 0;
876 memdev
->interleave_ways
= 1;
878 /* mem-region9 (spa/dcr3, dimm3) */
879 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 9;
880 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
881 memdev
->header
.length
= sizeof(*memdev
);
882 memdev
->device_handle
= handle
[3];
883 memdev
->physical_id
= 3;
884 memdev
->region_id
= 0;
885 memdev
->range_index
= 5+1;
886 memdev
->region_index
= 3+1;
887 memdev
->region_size
= 0;
888 memdev
->region_offset
= 0;
890 memdev
->interleave_index
= 0;
891 memdev
->interleave_ways
= 1;
893 /* mem-region10 (spa/bdw0, dimm0) */
894 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 10;
895 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
896 memdev
->header
.length
= sizeof(*memdev
);
897 memdev
->device_handle
= handle
[0];
898 memdev
->physical_id
= 0;
899 memdev
->region_id
= 0;
900 memdev
->range_index
= 6+1;
901 memdev
->region_index
= 0+1;
902 memdev
->region_size
= 0;
903 memdev
->region_offset
= 0;
905 memdev
->interleave_index
= 0;
906 memdev
->interleave_ways
= 1;
908 /* mem-region11 (spa/bdw1, dimm1) */
909 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 11;
910 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
911 memdev
->header
.length
= sizeof(*memdev
);
912 memdev
->device_handle
= handle
[1];
913 memdev
->physical_id
= 1;
914 memdev
->region_id
= 0;
915 memdev
->range_index
= 7+1;
916 memdev
->region_index
= 1+1;
917 memdev
->region_size
= 0;
918 memdev
->region_offset
= 0;
920 memdev
->interleave_index
= 0;
921 memdev
->interleave_ways
= 1;
923 /* mem-region12 (spa/bdw2, dimm2) */
924 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 12;
925 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
926 memdev
->header
.length
= sizeof(*memdev
);
927 memdev
->device_handle
= handle
[2];
928 memdev
->physical_id
= 2;
929 memdev
->region_id
= 0;
930 memdev
->range_index
= 8+1;
931 memdev
->region_index
= 2+1;
932 memdev
->region_size
= 0;
933 memdev
->region_offset
= 0;
935 memdev
->interleave_index
= 0;
936 memdev
->interleave_ways
= 1;
938 /* mem-region13 (spa/dcr3, dimm3) */
939 memdev
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_memory_map
) * 13;
940 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
941 memdev
->header
.length
= sizeof(*memdev
);
942 memdev
->device_handle
= handle
[3];
943 memdev
->physical_id
= 3;
944 memdev
->region_id
= 0;
945 memdev
->range_index
= 9+1;
946 memdev
->region_index
= 3+1;
947 memdev
->region_size
= 0;
948 memdev
->region_offset
= 0;
950 memdev
->interleave_index
= 0;
951 memdev
->interleave_ways
= 1;
953 offset
= offset
+ sizeof(struct acpi_nfit_memory_map
) * 14;
954 /* dcr-descriptor0: blk */
955 dcr
= nfit_buf
+ offset
;
956 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
957 dcr
->header
.length
= sizeof(struct acpi_nfit_control_region
);
958 dcr
->region_index
= 0+1;
959 dcr
->vendor_id
= 0xabcd;
961 dcr
->revision_id
= 1;
962 dcr
->serial_number
= ~handle
[0];
963 dcr
->code
= NFIT_FIC_BLK
;
965 dcr
->window_size
= DCR_SIZE
;
966 dcr
->command_offset
= 0;
967 dcr
->command_size
= 8;
968 dcr
->status_offset
= 8;
969 dcr
->status_size
= 4;
971 /* dcr-descriptor1: blk */
972 dcr
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_control_region
);
973 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
974 dcr
->header
.length
= sizeof(struct acpi_nfit_control_region
);
975 dcr
->region_index
= 1+1;
976 dcr
->vendor_id
= 0xabcd;
978 dcr
->revision_id
= 1;
979 dcr
->serial_number
= ~handle
[1];
980 dcr
->code
= NFIT_FIC_BLK
;
982 dcr
->window_size
= DCR_SIZE
;
983 dcr
->command_offset
= 0;
984 dcr
->command_size
= 8;
985 dcr
->status_offset
= 8;
986 dcr
->status_size
= 4;
988 /* dcr-descriptor2: blk */
989 dcr
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_control_region
) * 2;
990 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
991 dcr
->header
.length
= sizeof(struct acpi_nfit_control_region
);
992 dcr
->region_index
= 2+1;
993 dcr
->vendor_id
= 0xabcd;
995 dcr
->revision_id
= 1;
996 dcr
->serial_number
= ~handle
[2];
997 dcr
->code
= NFIT_FIC_BLK
;
999 dcr
->window_size
= DCR_SIZE
;
1000 dcr
->command_offset
= 0;
1001 dcr
->command_size
= 8;
1002 dcr
->status_offset
= 8;
1003 dcr
->status_size
= 4;
1005 /* dcr-descriptor3: blk */
1006 dcr
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_control_region
) * 3;
1007 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1008 dcr
->header
.length
= sizeof(struct acpi_nfit_control_region
);
1009 dcr
->region_index
= 3+1;
1010 dcr
->vendor_id
= 0xabcd;
1012 dcr
->revision_id
= 1;
1013 dcr
->serial_number
= ~handle
[3];
1014 dcr
->code
= NFIT_FIC_BLK
;
1016 dcr
->window_size
= DCR_SIZE
;
1017 dcr
->command_offset
= 0;
1018 dcr
->command_size
= 8;
1019 dcr
->status_offset
= 8;
1020 dcr
->status_size
= 4;
1022 offset
= offset
+ sizeof(struct acpi_nfit_control_region
) * 4;
1023 /* dcr-descriptor0: pmem */
1024 dcr
= nfit_buf
+ offset
;
1025 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1026 dcr
->header
.length
= offsetof(struct acpi_nfit_control_region
,
1028 dcr
->region_index
= 4+1;
1029 dcr
->vendor_id
= 0xabcd;
1031 dcr
->revision_id
= 1;
1032 dcr
->serial_number
= ~handle
[0];
1033 dcr
->code
= NFIT_FIC_BYTEN
;
1036 /* dcr-descriptor1: pmem */
1037 dcr
= nfit_buf
+ offset
+ offsetof(struct acpi_nfit_control_region
,
1039 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1040 dcr
->header
.length
= offsetof(struct acpi_nfit_control_region
,
1042 dcr
->region_index
= 5+1;
1043 dcr
->vendor_id
= 0xabcd;
1045 dcr
->revision_id
= 1;
1046 dcr
->serial_number
= ~handle
[1];
1047 dcr
->code
= NFIT_FIC_BYTEN
;
1050 /* dcr-descriptor2: pmem */
1051 dcr
= nfit_buf
+ offset
+ offsetof(struct acpi_nfit_control_region
,
1053 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1054 dcr
->header
.length
= offsetof(struct acpi_nfit_control_region
,
1056 dcr
->region_index
= 6+1;
1057 dcr
->vendor_id
= 0xabcd;
1059 dcr
->revision_id
= 1;
1060 dcr
->serial_number
= ~handle
[2];
1061 dcr
->code
= NFIT_FIC_BYTEN
;
1064 /* dcr-descriptor3: pmem */
1065 dcr
= nfit_buf
+ offset
+ offsetof(struct acpi_nfit_control_region
,
1067 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1068 dcr
->header
.length
= offsetof(struct acpi_nfit_control_region
,
1070 dcr
->region_index
= 7+1;
1071 dcr
->vendor_id
= 0xabcd;
1073 dcr
->revision_id
= 1;
1074 dcr
->serial_number
= ~handle
[3];
1075 dcr
->code
= NFIT_FIC_BYTEN
;
1078 offset
= offset
+ offsetof(struct acpi_nfit_control_region
,
1080 /* bdw0 (spa/dcr0, dimm0) */
1081 bdw
= nfit_buf
+ offset
;
1082 bdw
->header
.type
= ACPI_NFIT_TYPE_DATA_REGION
;
1083 bdw
->header
.length
= sizeof(struct acpi_nfit_data_region
);
1084 bdw
->region_index
= 0+1;
1087 bdw
->size
= BDW_SIZE
;
1088 bdw
->capacity
= DIMM_SIZE
;
1089 bdw
->start_address
= 0;
1091 /* bdw1 (spa/dcr1, dimm1) */
1092 bdw
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_data_region
);
1093 bdw
->header
.type
= ACPI_NFIT_TYPE_DATA_REGION
;
1094 bdw
->header
.length
= sizeof(struct acpi_nfit_data_region
);
1095 bdw
->region_index
= 1+1;
1098 bdw
->size
= BDW_SIZE
;
1099 bdw
->capacity
= DIMM_SIZE
;
1100 bdw
->start_address
= 0;
1102 /* bdw2 (spa/dcr2, dimm2) */
1103 bdw
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_data_region
) * 2;
1104 bdw
->header
.type
= ACPI_NFIT_TYPE_DATA_REGION
;
1105 bdw
->header
.length
= sizeof(struct acpi_nfit_data_region
);
1106 bdw
->region_index
= 2+1;
1109 bdw
->size
= BDW_SIZE
;
1110 bdw
->capacity
= DIMM_SIZE
;
1111 bdw
->start_address
= 0;
1113 /* bdw3 (spa/dcr3, dimm3) */
1114 bdw
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_data_region
) * 3;
1115 bdw
->header
.type
= ACPI_NFIT_TYPE_DATA_REGION
;
1116 bdw
->header
.length
= sizeof(struct acpi_nfit_data_region
);
1117 bdw
->region_index
= 3+1;
1120 bdw
->size
= BDW_SIZE
;
1121 bdw
->capacity
= DIMM_SIZE
;
1122 bdw
->start_address
= 0;
1124 offset
= offset
+ sizeof(struct acpi_nfit_data_region
) * 4;
1125 /* flush0 (dimm0) */
1126 flush
= nfit_buf
+ offset
;
1127 flush
->header
.type
= ACPI_NFIT_TYPE_FLUSH_ADDRESS
;
1128 flush
->header
.length
= sizeof(struct acpi_nfit_flush_address
);
1129 flush
->device_handle
= handle
[0];
1130 flush
->hint_count
= 1;
1131 flush
->hint_address
[0] = t
->flush_dma
[0];
1133 /* flush1 (dimm1) */
1134 flush
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_flush_address
) * 1;
1135 flush
->header
.type
= ACPI_NFIT_TYPE_FLUSH_ADDRESS
;
1136 flush
->header
.length
= sizeof(struct acpi_nfit_flush_address
);
1137 flush
->device_handle
= handle
[1];
1138 flush
->hint_count
= 1;
1139 flush
->hint_address
[0] = t
->flush_dma
[1];
1141 /* flush2 (dimm2) */
1142 flush
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_flush_address
) * 2;
1143 flush
->header
.type
= ACPI_NFIT_TYPE_FLUSH_ADDRESS
;
1144 flush
->header
.length
= sizeof(struct acpi_nfit_flush_address
);
1145 flush
->device_handle
= handle
[2];
1146 flush
->hint_count
= 1;
1147 flush
->hint_address
[0] = t
->flush_dma
[2];
1149 /* flush3 (dimm3) */
1150 flush
= nfit_buf
+ offset
+ sizeof(struct acpi_nfit_flush_address
) * 3;
1151 flush
->header
.type
= ACPI_NFIT_TYPE_FLUSH_ADDRESS
;
1152 flush
->header
.length
= sizeof(struct acpi_nfit_flush_address
);
1153 flush
->device_handle
= handle
[3];
1154 flush
->hint_count
= 1;
1155 flush
->hint_address
[0] = t
->flush_dma
[3];
1157 if (t
->setup_hotplug
) {
1158 offset
= offset
+ sizeof(struct acpi_nfit_flush_address
) * 4;
1159 /* dcr-descriptor4: blk */
1160 dcr
= nfit_buf
+ offset
;
1161 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1162 dcr
->header
.length
= sizeof(struct acpi_nfit_control_region
);
1163 dcr
->region_index
= 8+1;
1164 dcr
->vendor_id
= 0xabcd;
1166 dcr
->revision_id
= 1;
1167 dcr
->serial_number
= ~handle
[4];
1168 dcr
->code
= NFIT_FIC_BLK
;
1170 dcr
->window_size
= DCR_SIZE
;
1171 dcr
->command_offset
= 0;
1172 dcr
->command_size
= 8;
1173 dcr
->status_offset
= 8;
1174 dcr
->status_size
= 4;
1176 offset
= offset
+ sizeof(struct acpi_nfit_control_region
);
1177 /* dcr-descriptor4: pmem */
1178 dcr
= nfit_buf
+ offset
;
1179 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1180 dcr
->header
.length
= offsetof(struct acpi_nfit_control_region
,
1182 dcr
->region_index
= 9+1;
1183 dcr
->vendor_id
= 0xabcd;
1185 dcr
->revision_id
= 1;
1186 dcr
->serial_number
= ~handle
[4];
1187 dcr
->code
= NFIT_FIC_BYTEN
;
1190 offset
= offset
+ offsetof(struct acpi_nfit_control_region
,
1192 /* bdw4 (spa/dcr4, dimm4) */
1193 bdw
= nfit_buf
+ offset
;
1194 bdw
->header
.type
= ACPI_NFIT_TYPE_DATA_REGION
;
1195 bdw
->header
.length
= sizeof(struct acpi_nfit_data_region
);
1196 bdw
->region_index
= 8+1;
1199 bdw
->size
= BDW_SIZE
;
1200 bdw
->capacity
= DIMM_SIZE
;
1201 bdw
->start_address
= 0;
1203 offset
= offset
+ sizeof(struct acpi_nfit_data_region
);
1204 /* spa10 (dcr4) dimm4 */
1205 spa
= nfit_buf
+ offset
;
1206 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
1207 spa
->header
.length
= sizeof(*spa
);
1208 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_DCR
), 16);
1209 spa
->range_index
= 10+1;
1210 spa
->address
= t
->dcr_dma
[4];
1211 spa
->length
= DCR_SIZE
;
1214 * spa11 (single-dimm interleave for hotplug, note storage
1215 * does not actually alias the related block-data-window
1218 spa
= nfit_buf
+ offset
+ sizeof(*spa
);
1219 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
1220 spa
->header
.length
= sizeof(*spa
);
1221 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_PM
), 16);
1222 spa
->range_index
= 11+1;
1223 spa
->address
= t
->spa_set_dma
[2];
1224 spa
->length
= SPA0_SIZE
;
1226 /* spa12 (bdw for dcr4) dimm4 */
1227 spa
= nfit_buf
+ offset
+ sizeof(*spa
) * 2;
1228 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
1229 spa
->header
.length
= sizeof(*spa
);
1230 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_BDW
), 16);
1231 spa
->range_index
= 12+1;
1232 spa
->address
= t
->dimm_dma
[4];
1233 spa
->length
= DIMM_SIZE
;
1235 offset
= offset
+ sizeof(*spa
) * 3;
1236 /* mem-region14 (spa/dcr4, dimm4) */
1237 memdev
= nfit_buf
+ offset
;
1238 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
1239 memdev
->header
.length
= sizeof(*memdev
);
1240 memdev
->device_handle
= handle
[4];
1241 memdev
->physical_id
= 4;
1242 memdev
->region_id
= 0;
1243 memdev
->range_index
= 10+1;
1244 memdev
->region_index
= 8+1;
1245 memdev
->region_size
= 0;
1246 memdev
->region_offset
= 0;
1247 memdev
->address
= 0;
1248 memdev
->interleave_index
= 0;
1249 memdev
->interleave_ways
= 1;
1251 /* mem-region15 (spa0, dimm4) */
1252 memdev
= nfit_buf
+ offset
+
1253 sizeof(struct acpi_nfit_memory_map
);
1254 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
1255 memdev
->header
.length
= sizeof(*memdev
);
1256 memdev
->device_handle
= handle
[4];
1257 memdev
->physical_id
= 4;
1258 memdev
->region_id
= 0;
1259 memdev
->range_index
= 11+1;
1260 memdev
->region_index
= 9+1;
1261 memdev
->region_size
= SPA0_SIZE
;
1262 memdev
->region_offset
= t
->spa_set_dma
[2];
1263 memdev
->address
= 0;
1264 memdev
->interleave_index
= 0;
1265 memdev
->interleave_ways
= 1;
1267 /* mem-region16 (spa/bdw4, dimm4) */
1268 memdev
= nfit_buf
+ offset
+
1269 sizeof(struct acpi_nfit_memory_map
) * 2;
1270 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
1271 memdev
->header
.length
= sizeof(*memdev
);
1272 memdev
->device_handle
= handle
[4];
1273 memdev
->physical_id
= 4;
1274 memdev
->region_id
= 0;
1275 memdev
->range_index
= 12+1;
1276 memdev
->region_index
= 8+1;
1277 memdev
->region_size
= 0;
1278 memdev
->region_offset
= 0;
1279 memdev
->address
= 0;
1280 memdev
->interleave_index
= 0;
1281 memdev
->interleave_ways
= 1;
1283 offset
= offset
+ sizeof(struct acpi_nfit_memory_map
) * 3;
1284 /* flush3 (dimm4) */
1285 flush
= nfit_buf
+ offset
;
1286 flush
->header
.type
= ACPI_NFIT_TYPE_FLUSH_ADDRESS
;
1287 flush
->header
.length
= sizeof(struct acpi_nfit_flush_address
);
1288 flush
->device_handle
= handle
[4];
1289 flush
->hint_count
= 1;
1290 flush
->hint_address
[0] = t
->flush_dma
[4];
1293 post_ars_status(&t
->ars_state
, t
->spa_set_dma
[0], SPA0_SIZE
);
1295 acpi_desc
= &t
->acpi_desc
;
1296 set_bit(ND_CMD_GET_CONFIG_SIZE
, &acpi_desc
->dimm_dsm_force_en
);
1297 set_bit(ND_CMD_GET_CONFIG_DATA
, &acpi_desc
->dimm_dsm_force_en
);
1298 set_bit(ND_CMD_SET_CONFIG_DATA
, &acpi_desc
->dimm_dsm_force_en
);
1299 set_bit(ND_CMD_SMART
, &acpi_desc
->dimm_dsm_force_en
);
1300 set_bit(ND_CMD_ARS_CAP
, &acpi_desc
->bus_dsm_force_en
);
1301 set_bit(ND_CMD_ARS_START
, &acpi_desc
->bus_dsm_force_en
);
1302 set_bit(ND_CMD_ARS_STATUS
, &acpi_desc
->bus_dsm_force_en
);
1303 set_bit(ND_CMD_CLEAR_ERROR
, &acpi_desc
->bus_dsm_force_en
);
1304 set_bit(ND_CMD_SMART_THRESHOLD
, &acpi_desc
->dimm_dsm_force_en
);
1307 static void nfit_test1_setup(struct nfit_test
*t
)
1310 void *nfit_buf
= t
->nfit_buf
;
1311 struct acpi_nfit_memory_map
*memdev
;
1312 struct acpi_nfit_control_region
*dcr
;
1313 struct acpi_nfit_system_address
*spa
;
1314 struct acpi_nfit_desc
*acpi_desc
;
1317 /* spa0 (flat range with no bdw aliasing) */
1318 spa
= nfit_buf
+ offset
;
1319 spa
->header
.type
= ACPI_NFIT_TYPE_SYSTEM_ADDRESS
;
1320 spa
->header
.length
= sizeof(*spa
);
1321 memcpy(spa
->range_guid
, to_nfit_uuid(NFIT_SPA_PM
), 16);
1322 spa
->range_index
= 0+1;
1323 spa
->address
= t
->spa_set_dma
[0];
1324 spa
->length
= SPA2_SIZE
;
1326 offset
+= sizeof(*spa
);
1327 /* mem-region0 (spa0, dimm0) */
1328 memdev
= nfit_buf
+ offset
;
1329 memdev
->header
.type
= ACPI_NFIT_TYPE_MEMORY_MAP
;
1330 memdev
->header
.length
= sizeof(*memdev
);
1331 memdev
->device_handle
= 0;
1332 memdev
->physical_id
= 0;
1333 memdev
->region_id
= 0;
1334 memdev
->range_index
= 0+1;
1335 memdev
->region_index
= 0+1;
1336 memdev
->region_size
= SPA2_SIZE
;
1337 memdev
->region_offset
= 0;
1338 memdev
->address
= 0;
1339 memdev
->interleave_index
= 0;
1340 memdev
->interleave_ways
= 1;
1341 memdev
->flags
= ACPI_NFIT_MEM_SAVE_FAILED
| ACPI_NFIT_MEM_RESTORE_FAILED
1342 | ACPI_NFIT_MEM_FLUSH_FAILED
| ACPI_NFIT_MEM_HEALTH_OBSERVED
1343 | ACPI_NFIT_MEM_NOT_ARMED
;
1345 offset
+= sizeof(*memdev
);
1346 /* dcr-descriptor0 */
1347 dcr
= nfit_buf
+ offset
;
1348 dcr
->header
.type
= ACPI_NFIT_TYPE_CONTROL_REGION
;
1349 dcr
->header
.length
= offsetof(struct acpi_nfit_control_region
,
1351 dcr
->region_index
= 0+1;
1352 dcr
->vendor_id
= 0xabcd;
1354 dcr
->revision_id
= 1;
1355 dcr
->serial_number
= ~0;
1356 dcr
->code
= NFIT_FIC_BYTE
;
1359 post_ars_status(&t
->ars_state
, t
->spa_set_dma
[0], SPA2_SIZE
);
1361 acpi_desc
= &t
->acpi_desc
;
1362 set_bit(ND_CMD_ARS_CAP
, &acpi_desc
->bus_dsm_force_en
);
1363 set_bit(ND_CMD_ARS_START
, &acpi_desc
->bus_dsm_force_en
);
1364 set_bit(ND_CMD_ARS_STATUS
, &acpi_desc
->bus_dsm_force_en
);
1365 set_bit(ND_CMD_CLEAR_ERROR
, &acpi_desc
->bus_dsm_force_en
);
1368 static int nfit_test_blk_do_io(struct nd_blk_region
*ndbr
, resource_size_t dpa
,
1369 void *iobuf
, u64 len
, int rw
)
1371 struct nfit_blk
*nfit_blk
= ndbr
->blk_provider_data
;
1372 struct nfit_blk_mmio
*mmio
= &nfit_blk
->mmio
[BDW
];
1373 struct nd_region
*nd_region
= &ndbr
->nd_region
;
1376 lane
= nd_region_acquire_lane(nd_region
);
1378 memcpy(mmio
->addr
.base
+ dpa
, iobuf
, len
);
1380 memcpy(iobuf
, mmio
->addr
.base
+ dpa
, len
);
1382 /* give us some some coverage of the mmio_flush_range() API */
1383 mmio_flush_range(mmio
->addr
.base
+ dpa
, len
);
1385 nd_region_release_lane(nd_region
, lane
);
1390 static int nfit_test_probe(struct platform_device
*pdev
)
1392 struct nvdimm_bus_descriptor
*nd_desc
;
1393 struct acpi_nfit_desc
*acpi_desc
;
1394 struct device
*dev
= &pdev
->dev
;
1395 struct nfit_test
*nfit_test
;
1398 nfit_test
= to_nfit_test(&pdev
->dev
);
1401 if (nfit_test
->num_dcr
) {
1402 int num
= nfit_test
->num_dcr
;
1404 nfit_test
->dimm
= devm_kcalloc(dev
, num
, sizeof(void *),
1406 nfit_test
->dimm_dma
= devm_kcalloc(dev
, num
, sizeof(dma_addr_t
),
1408 nfit_test
->flush
= devm_kcalloc(dev
, num
, sizeof(void *),
1410 nfit_test
->flush_dma
= devm_kcalloc(dev
, num
, sizeof(dma_addr_t
),
1412 nfit_test
->label
= devm_kcalloc(dev
, num
, sizeof(void *),
1414 nfit_test
->label_dma
= devm_kcalloc(dev
, num
,
1415 sizeof(dma_addr_t
), GFP_KERNEL
);
1416 nfit_test
->dcr
= devm_kcalloc(dev
, num
,
1417 sizeof(struct nfit_test_dcr
*), GFP_KERNEL
);
1418 nfit_test
->dcr_dma
= devm_kcalloc(dev
, num
,
1419 sizeof(dma_addr_t
), GFP_KERNEL
);
1420 if (nfit_test
->dimm
&& nfit_test
->dimm_dma
&& nfit_test
->label
1421 && nfit_test
->label_dma
&& nfit_test
->dcr
1422 && nfit_test
->dcr_dma
&& nfit_test
->flush
1423 && nfit_test
->flush_dma
)
1429 if (nfit_test
->num_pm
) {
1430 int num
= nfit_test
->num_pm
;
1432 nfit_test
->spa_set
= devm_kcalloc(dev
, num
, sizeof(void *),
1434 nfit_test
->spa_set_dma
= devm_kcalloc(dev
, num
,
1435 sizeof(dma_addr_t
), GFP_KERNEL
);
1436 if (nfit_test
->spa_set
&& nfit_test
->spa_set_dma
)
1442 /* per-nfit specific alloc */
1443 if (nfit_test
->alloc(nfit_test
))
1446 nfit_test
->setup(nfit_test
);
1447 acpi_desc
= &nfit_test
->acpi_desc
;
1448 acpi_nfit_desc_init(acpi_desc
, &pdev
->dev
);
1449 acpi_desc
->nfit
= nfit_test
->nfit_buf
;
1450 acpi_desc
->blk_do_io
= nfit_test_blk_do_io
;
1451 nd_desc
= &acpi_desc
->nd_desc
;
1452 nd_desc
->provider_name
= NULL
;
1453 nd_desc
->ndctl
= nfit_test_ctl
;
1454 acpi_desc
->nvdimm_bus
= nvdimm_bus_register(&pdev
->dev
, nd_desc
);
1455 if (!acpi_desc
->nvdimm_bus
)
1458 rc
= acpi_nfit_init(acpi_desc
, nfit_test
->nfit_size
);
1460 nvdimm_bus_unregister(acpi_desc
->nvdimm_bus
);
1464 if (nfit_test
->setup
!= nfit_test0_setup
)
1467 nfit_test
->setup_hotplug
= 1;
1468 nfit_test
->setup(nfit_test
);
1470 rc
= acpi_nfit_init(acpi_desc
, nfit_test
->nfit_size
);
1472 nvdimm_bus_unregister(acpi_desc
->nvdimm_bus
);
1479 static int nfit_test_remove(struct platform_device
*pdev
)
1481 struct nfit_test
*nfit_test
= to_nfit_test(&pdev
->dev
);
1482 struct acpi_nfit_desc
*acpi_desc
= &nfit_test
->acpi_desc
;
1484 nvdimm_bus_unregister(acpi_desc
->nvdimm_bus
);
1489 static void nfit_test_release(struct device
*dev
)
1491 struct nfit_test
*nfit_test
= to_nfit_test(dev
);
1496 static const struct platform_device_id nfit_test_id
[] = {
1501 static struct platform_driver nfit_test_driver
= {
1502 .probe
= nfit_test_probe
,
1503 .remove
= nfit_test_remove
,
1505 .name
= KBUILD_MODNAME
,
1507 .id_table
= nfit_test_id
,
1510 #ifdef CONFIG_CMA_SIZE_MBYTES
1511 #define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
1513 #define CMA_SIZE_MBYTES 0
1516 static __init
int nfit_test_init(void)
1520 nfit_test_setup(nfit_test_lookup
);
1522 for (i
= 0; i
< NUM_NFITS
; i
++) {
1523 struct nfit_test
*nfit_test
;
1524 struct platform_device
*pdev
;
1527 nfit_test
= kzalloc(sizeof(*nfit_test
), GFP_KERNEL
);
1532 INIT_LIST_HEAD(&nfit_test
->resources
);
1535 nfit_test
->num_pm
= NUM_PM
;
1536 nfit_test
->num_dcr
= NUM_DCR
;
1537 nfit_test
->alloc
= nfit_test0_alloc
;
1538 nfit_test
->setup
= nfit_test0_setup
;
1541 nfit_test
->num_pm
= 1;
1542 nfit_test
->alloc
= nfit_test1_alloc
;
1543 nfit_test
->setup
= nfit_test1_setup
;
1549 pdev
= &nfit_test
->pdev
;
1550 pdev
->name
= KBUILD_MODNAME
;
1552 pdev
->dev
.release
= nfit_test_release
;
1553 rc
= platform_device_register(pdev
);
1555 put_device(&pdev
->dev
);
1559 rc
= dma_coerce_mask_and_coherent(&pdev
->dev
, DMA_BIT_MASK(64));
1563 instances
[i
] = nfit_test
;
1569 buf
= dma_alloc_coherent(&pdev
->dev
, SZ_128M
, &dma
,
1573 dev_warn(&pdev
->dev
, "need 128M of free cma\n");
1576 dma_free_coherent(&pdev
->dev
, SZ_128M
, buf
, dma
);
1580 rc
= platform_driver_register(&nfit_test_driver
);
1586 for (i
= 0; i
< NUM_NFITS
; i
++)
1588 platform_device_unregister(&instances
[i
]->pdev
);
1589 nfit_test_teardown();
1593 static __exit
void nfit_test_exit(void)
1597 platform_driver_unregister(&nfit_test_driver
);
1598 for (i
= 0; i
< NUM_NFITS
; i
++)
1599 platform_device_unregister(&instances
[i
]->pdev
);
1600 nfit_test_teardown();
1603 module_init(nfit_test_init
);
1604 module_exit(nfit_test_exit
);
1605 MODULE_LICENSE("GPL v2");
1606 MODULE_AUTHOR("Intel Corporation");