Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
1f716d05
Commit
1f716d05
authored
May 18, 2016
by
Dan Williams
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'for-4.7/dsm' into libnvdimm-for-next
parents
2159669f
a94e3fbe
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
283 additions
and
58 deletions
+283
-58
drivers/acpi/nfit.c
drivers/acpi/nfit.c
+127
-18
drivers/acpi/nfit.h
drivers/acpi/nfit.h
+15
-3
drivers/acpi/utils.c
drivers/acpi/utils.c
+2
-2
drivers/nvdimm/bus.c
drivers/nvdimm/bus.c
+43
-4
drivers/nvdimm/core.c
drivers/nvdimm/core.c
+1
-1
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/dimm_devs.c
+12
-6
drivers/nvdimm/nd-core.h
drivers/nvdimm/nd-core.h
+1
-1
include/acpi/acpi_bus.h
include/acpi/acpi_bus.h
+3
-3
include/linux/libnvdimm.h
include/linux/libnvdimm.h
+4
-3
include/uapi/linux/ndctl.h
include/uapi/linux/ndctl.h
+42
-0
tools/testing/nvdimm/test/nfit.c
tools/testing/nvdimm/test/nfit.c
+33
-17
No files found.
drivers/acpi/nfit.c
View file @
1f716d05
...
...
@@ -45,6 +45,11 @@ module_param(scrub_overflow_abort, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC
(
scrub_overflow_abort
,
"Number of times we overflow ARS results before abort"
);
static
bool
disable_vendor_specific
;
module_param
(
disable_vendor_specific
,
bool
,
S_IRUGO
);
MODULE_PARM_DESC
(
disable_vendor_specific
,
"Limit commands to the publicly specified set
\n
"
);
static
struct
workqueue_struct
*
nfit_wq
;
struct
nfit_table_prev
{
...
...
@@ -171,33 +176,46 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
unsigned
int
buf_len
,
int
*
cmd_rc
)
{
struct
acpi_nfit_desc
*
acpi_desc
=
to_acpi_nfit_desc
(
nd_desc
);
const
struct
nd_cmd_desc
*
desc
=
NULL
;
union
acpi_object
in_obj
,
in_buf
,
*
out_obj
;
const
struct
nd_cmd_desc
*
desc
=
NULL
;
struct
device
*
dev
=
acpi_desc
->
dev
;
struct
nd_cmd_pkg
*
call_pkg
=
NULL
;
const
char
*
cmd_name
,
*
dimm_name
;
unsigned
long
dsm_mask
;
unsigned
long
cmd_mask
,
dsm_mask
;
acpi_handle
handle
;
unsigned
int
func
;
const
u8
*
uuid
;
u32
offset
;
int
rc
,
i
;
func
=
cmd
;
if
(
cmd
==
ND_CMD_CALL
)
{
call_pkg
=
buf
;
func
=
call_pkg
->
nd_command
;
}
if
(
nvdimm
)
{
struct
nfit_mem
*
nfit_mem
=
nvdimm_provider_data
(
nvdimm
);
struct
acpi_device
*
adev
=
nfit_mem
->
adev
;
if
(
!
adev
)
return
-
ENOTTY
;
if
(
call_pkg
&&
nfit_mem
->
family
!=
call_pkg
->
nd_family
)
return
-
ENOTTY
;
dimm_name
=
nvdimm_name
(
nvdimm
);
cmd_name
=
nvdimm_cmd_name
(
cmd
);
cmd_mask
=
nvdimm_cmd_mask
(
nvdimm
);
dsm_mask
=
nfit_mem
->
dsm_mask
;
desc
=
nd_cmd_dimm_desc
(
cmd
);
uuid
=
to_nfit_uuid
(
NFIT_DEV_DIMM
);
uuid
=
to_nfit_uuid
(
nfit_mem
->
family
);
handle
=
adev
->
handle
;
}
else
{
struct
acpi_device
*
adev
=
to_acpi_dev
(
acpi_desc
);
cmd_name
=
nvdimm_bus_cmd_name
(
cmd
);
dsm_mask
=
nd_desc
->
dsm_mask
;
cmd_mask
=
nd_desc
->
cmd_mask
;
dsm_mask
=
cmd_mask
;
desc
=
nd_cmd_bus_desc
(
cmd
);
uuid
=
to_nfit_uuid
(
NFIT_DEV_BUS
);
handle
=
adev
->
handle
;
...
...
@@ -207,7 +225,7 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
if
(
!
desc
||
(
cmd
&&
(
desc
->
out_num
+
desc
->
in_num
==
0
)))
return
-
ENOTTY
;
if
(
!
test_bit
(
cmd
,
&
dsm_mask
))
if
(
!
test_bit
(
cmd
,
&
cmd_mask
)
||
!
test_bit
(
func
,
&
dsm_mask
))
return
-
ENOTTY
;
in_obj
.
type
=
ACPI_TYPE_PACKAGE
;
...
...
@@ -222,21 +240,44 @@ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
in_buf
.
buffer
.
length
+=
nd_cmd_in_size
(
nvdimm
,
cmd
,
desc
,
i
,
buf
);
if
(
call_pkg
)
{
/* skip over package wrapper */
in_buf
.
buffer
.
pointer
=
(
void
*
)
&
call_pkg
->
nd_payload
;
in_buf
.
buffer
.
length
=
call_pkg
->
nd_size_in
;
}
if
(
IS_ENABLED
(
CONFIG_ACPI_NFIT_DEBUG
))
{
dev_dbg
(
dev
,
"%s:%s cmd: %s input length: %d
\n
"
,
__func__
,
dimm_name
,
cmd_name
,
in_buf
.
buffer
.
length
);
print_hex_dump_debug
(
cmd_name
,
DUMP_PREFIX_OFFSET
,
4
,
4
,
in_buf
.
buffer
.
pointer
,
min_t
(
u32
,
128
,
in_buf
.
buffer
.
length
),
true
);
dev_dbg
(
dev
,
"%s:%s cmd: %d: func: %d input length: %d
\n
"
,
__func__
,
dimm_name
,
cmd
,
func
,
in_buf
.
buffer
.
length
);
print_hex_dump_debug
(
"nvdimm in "
,
DUMP_PREFIX_OFFSET
,
4
,
4
,
in_buf
.
buffer
.
pointer
,
min_t
(
u32
,
256
,
in_buf
.
buffer
.
length
),
true
);
}
out_obj
=
acpi_evaluate_dsm
(
handle
,
uuid
,
1
,
cmd
,
&
in_obj
);
out_obj
=
acpi_evaluate_dsm
(
handle
,
uuid
,
1
,
func
,
&
in_obj
);
if
(
!
out_obj
)
{
dev_dbg
(
dev
,
"%s:%s _DSM failed cmd: %s
\n
"
,
__func__
,
dimm_name
,
cmd_name
);
return
-
EINVAL
;
}
if
(
call_pkg
)
{
call_pkg
->
nd_fw_size
=
out_obj
->
buffer
.
length
;
memcpy
(
call_pkg
->
nd_payload
+
call_pkg
->
nd_size_in
,
out_obj
->
buffer
.
pointer
,
min
(
call_pkg
->
nd_fw_size
,
call_pkg
->
nd_size_out
));
ACPI_FREE
(
out_obj
);
/*
* Need to support FW function w/o known size in advance.
* Caller can determine required size based upon nd_fw_size.
* If we return an error (like elsewhere) then caller wouldn't
* be able to rely upon data returned to make calculation.
*/
return
0
;
}
if
(
out_obj
->
package
.
type
!=
ACPI_TYPE_BUFFER
)
{
dev_dbg
(
dev
,
"%s:%s unexpected output object type cmd: %s type: %d
\n
"
,
__func__
,
dimm_name
,
cmd_name
,
out_obj
->
type
);
...
...
@@ -921,6 +962,30 @@ static ssize_t serial_show(struct device *dev,
}
static
DEVICE_ATTR_RO
(
serial
);
static
ssize_t
family_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nvdimm
*
nvdimm
=
to_nvdimm
(
dev
);
struct
nfit_mem
*
nfit_mem
=
nvdimm_provider_data
(
nvdimm
);
if
(
nfit_mem
->
family
<
0
)
return
-
ENXIO
;
return
sprintf
(
buf
,
"%d
\n
"
,
nfit_mem
->
family
);
}
static
DEVICE_ATTR_RO
(
family
);
static
ssize_t
dsm_mask_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
struct
nvdimm
*
nvdimm
=
to_nvdimm
(
dev
);
struct
nfit_mem
*
nfit_mem
=
nvdimm_provider_data
(
nvdimm
);
if
(
nfit_mem
->
family
<
0
)
return
-
ENXIO
;
return
sprintf
(
buf
,
"%#lx
\n
"
,
nfit_mem
->
dsm_mask
);
}
static
DEVICE_ATTR_RO
(
dsm_mask
);
static
ssize_t
flags_show
(
struct
device
*
dev
,
struct
device_attribute
*
attr
,
char
*
buf
)
{
...
...
@@ -946,6 +1011,8 @@ static struct attribute *acpi_nfit_dimm_attributes[] = {
&
dev_attr_serial
.
attr
,
&
dev_attr_rev_id
.
attr
,
&
dev_attr_flags
.
attr
,
&
dev_attr_family
.
attr
,
&
dev_attr_dsm_mask
.
attr
,
NULL
,
};
...
...
@@ -992,10 +1059,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
{
struct
acpi_device
*
adev
,
*
adev_dimm
;
struct
device
*
dev
=
acpi_desc
->
dev
;
const
u8
*
uuid
=
to_nfit_uuid
(
NFIT_DEV_DIMM
);
unsigned
long
dsm_mask
;
const
u8
*
uuid
;
int
i
;
nfit_mem
->
dsm_mask
=
acpi_desc
->
dimm_dsm_force_en
;
/* nfit test assumes 1:1 relationship between commands and dsms */
nfit_mem
->
dsm_mask
=
acpi_desc
->
dimm_cmd_force_en
;
nfit_mem
->
family
=
NVDIMM_FAMILY_INTEL
;
adev
=
to_acpi_dev
(
acpi_desc
);
if
(
!
adev
)
return
0
;
...
...
@@ -1008,7 +1078,35 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
return
force_enable_dimms
?
0
:
-
ENODEV
;
}
for
(
i
=
ND_CMD_SMART
;
i
<=
ND_CMD_VENDOR
;
i
++
)
/*
* Until standardization materializes we need to consider up to 3
* different command sets. Note, that checking for function0 (bit0)
* tells us if any commands are reachable through this uuid.
*/
for
(
i
=
NVDIMM_FAMILY_INTEL
;
i
<=
NVDIMM_FAMILY_HPE2
;
i
++
)
if
(
acpi_check_dsm
(
adev_dimm
->
handle
,
to_nfit_uuid
(
i
),
1
,
1
))
break
;
/* limit the supported commands to those that are publicly documented */
nfit_mem
->
family
=
i
;
if
(
nfit_mem
->
family
==
NVDIMM_FAMILY_INTEL
)
{
dsm_mask
=
0x3fe
;
if
(
disable_vendor_specific
)
dsm_mask
&=
~
(
1
<<
ND_CMD_VENDOR
);
}
else
if
(
nfit_mem
->
family
==
NVDIMM_FAMILY_HPE1
)
dsm_mask
=
0x1c3c76
;
else
if
(
nfit_mem
->
family
==
NVDIMM_FAMILY_HPE2
)
{
dsm_mask
=
0x1fe
;
if
(
disable_vendor_specific
)
dsm_mask
&=
~
(
1
<<
8
);
}
else
{
dev_err
(
dev
,
"unknown dimm command family
\n
"
);
nfit_mem
->
family
=
-
1
;
return
force_enable_dimms
?
0
:
-
ENODEV
;
}
uuid
=
to_nfit_uuid
(
nfit_mem
->
family
);
for_each_set_bit
(
i
,
&
dsm_mask
,
BITS_PER_LONG
)
if
(
acpi_check_dsm
(
adev_dimm
->
handle
,
uuid
,
1
,
1ULL
<<
i
))
set_bit
(
i
,
&
nfit_mem
->
dsm_mask
);
...
...
@@ -1021,8 +1119,8 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
int
dimm_count
=
0
;
list_for_each_entry
(
nfit_mem
,
&
acpi_desc
->
dimms
,
list
)
{
unsigned
long
flags
=
0
,
cmd_mask
;
struct
nvdimm
*
nvdimm
;
unsigned
long
flags
=
0
;
u32
device_handle
;
u16
mem_flags
;
int
rc
;
...
...
@@ -1045,9 +1143,18 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
if
(
rc
)
continue
;
/*
* TODO: provide translation for non-NVDIMM_FAMILY_INTEL
* devices (i.e. from nd_cmd to acpi_dsm) to standardize the
* userspace interface.
*/
cmd_mask
=
1UL
<<
ND_CMD_CALL
;
if
(
nfit_mem
->
family
==
NVDIMM_FAMILY_INTEL
)
cmd_mask
|=
nfit_mem
->
dsm_mask
;
nvdimm
=
nvdimm_create
(
acpi_desc
->
nvdimm_bus
,
nfit_mem
,
acpi_nfit_dimm_attribute_groups
,
flags
,
&
nfit_mem
->
dsm
_mask
);
flags
,
cmd
_mask
);
if
(
!
nvdimm
)
return
-
ENOMEM
;
...
...
@@ -1076,14 +1183,14 @@ static void acpi_nfit_init_dsms(struct acpi_nfit_desc *acpi_desc)
struct
acpi_device
*
adev
;
int
i
;
nd_desc
->
dsm_mask
=
acpi_desc
->
bus_dsm
_force_en
;
nd_desc
->
cmd_mask
=
acpi_desc
->
bus_cmd
_force_en
;
adev
=
to_acpi_dev
(
acpi_desc
);
if
(
!
adev
)
return
;
for
(
i
=
ND_CMD_ARS_CAP
;
i
<=
ND_CMD_CLEAR_ERROR
;
i
++
)
if
(
acpi_check_dsm
(
adev
->
handle
,
uuid
,
1
,
1ULL
<<
i
))
set_bit
(
i
,
&
nd_desc
->
dsm
_mask
);
set_bit
(
i
,
&
nd_desc
->
cmd
_mask
);
}
static
ssize_t
range_index_show
(
struct
device
*
dev
,
...
...
@@ -2532,6 +2639,8 @@ static __init int nfit_init(void)
acpi_str_to_uuid
(
UUID_PERSISTENT_VIRTUAL_CD
,
nfit_uuid
[
NFIT_SPA_PCD
]);
acpi_str_to_uuid
(
UUID_NFIT_BUS
,
nfit_uuid
[
NFIT_DEV_BUS
]);
acpi_str_to_uuid
(
UUID_NFIT_DIMM
,
nfit_uuid
[
NFIT_DEV_DIMM
]);
acpi_str_to_uuid
(
UUID_NFIT_DIMM_N_HPE1
,
nfit_uuid
[
NFIT_DEV_DIMM_N_HPE1
]);
acpi_str_to_uuid
(
UUID_NFIT_DIMM_N_HPE2
,
nfit_uuid
[
NFIT_DEV_DIMM_N_HPE2
]);
nfit_wq
=
create_singlethread_workqueue
(
"nfit"
);
if
(
!
nfit_wq
)
...
...
drivers/acpi/nfit.h
View file @
1f716d05
...
...
@@ -21,13 +21,25 @@
#include <linux/acpi.h>
#include <acpi/acuuid.h>
/* ACPI 6.1 */
#define UUID_NFIT_BUS "2f10e7a4-9e91-11e4-89d3-123b93f75cba"
/* http://pmem.io/documents/NVDIMM_DSM_Interface_Example.pdf */
#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66"
/* https://github.com/HewlettPackard/hpe-nvm/blob/master/Documentation/ */
#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6"
#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e"
#define ACPI_NFIT_MEM_FAILED_MASK (ACPI_NFIT_MEM_SAVE_FAILED \
| ACPI_NFIT_MEM_RESTORE_FAILED | ACPI_NFIT_MEM_FLUSH_FAILED \
| ACPI_NFIT_MEM_NOT_ARMED)
enum
nfit_uuids
{
/* for simplicity alias the uuid index with the family id */
NFIT_DEV_DIMM
=
NVDIMM_FAMILY_INTEL
,
NFIT_DEV_DIMM_N_HPE1
=
NVDIMM_FAMILY_HPE1
,
NFIT_DEV_DIMM_N_HPE2
=
NVDIMM_FAMILY_HPE2
,
NFIT_SPA_VOLATILE
,
NFIT_SPA_PM
,
NFIT_SPA_DCR
,
...
...
@@ -37,7 +49,6 @@ enum nfit_uuids {
NFIT_SPA_PDISK
,
NFIT_SPA_PCD
,
NFIT_DEV_BUS
,
NFIT_DEV_DIMM
,
NFIT_UUID_MAX
,
};
...
...
@@ -111,6 +122,7 @@ struct nfit_mem {
struct
acpi_device
*
adev
;
struct
acpi_nfit_desc
*
acpi_desc
;
unsigned
long
dsm_mask
;
int
family
;
};
struct
acpi_nfit_desc
{
...
...
@@ -133,8 +145,8 @@ struct acpi_nfit_desc {
size_t
ars_status_size
;
struct
work_struct
work
;
unsigned
int
cancel
:
1
;
unsigned
long
dimm_
dsm
_force_en
;
unsigned
long
bus_
dsm
_force_en
;
unsigned
long
dimm_
cmd
_force_en
;
unsigned
long
bus_
cmd
_force_en
;
int
(
*
blk_do_io
)(
struct
nd_blk_region
*
ndbr
,
resource_size_t
dpa
,
void
*
iobuf
,
u64
len
,
int
rw
);
};
...
...
drivers/acpi/utils.c
View file @
1f716d05
...
...
@@ -625,7 +625,7 @@ acpi_status acpi_evaluate_lck(acpi_handle handle, int lock)
* some old BIOSes do expect a buffer or an integer etc.
*/
union
acpi_object
*
acpi_evaluate_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
int
rev
,
int
func
,
acpi_evaluate_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
u64
rev
,
u64
func
,
union
acpi_object
*
argv4
)
{
acpi_status
ret
;
...
...
@@ -674,7 +674,7 @@ EXPORT_SYMBOL(acpi_evaluate_dsm);
* functions. Currently only support 64 functions at maximum, should be
* enough for now.
*/
bool
acpi_check_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
int
rev
,
u64
funcs
)
bool
acpi_check_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
u64
rev
,
u64
funcs
)
{
int
i
;
u64
mask
=
0
;
...
...
drivers/nvdimm/bus.c
View file @
1f716d05
...
...
@@ -443,6 +443,12 @@ static const struct nd_cmd_desc __nd_cmd_dimm_descs[] = {
.
out_num
=
3
,
.
out_sizes
=
{
4
,
4
,
UINT_MAX
,
},
},
[
ND_CMD_CALL
]
=
{
.
in_num
=
2
,
.
in_sizes
=
{
sizeof
(
struct
nd_cmd_pkg
),
UINT_MAX
,
},
.
out_num
=
1
,
.
out_sizes
=
{
UINT_MAX
,
},
},
};
const
struct
nd_cmd_desc
*
nd_cmd_dimm_desc
(
int
cmd
)
...
...
@@ -477,6 +483,12 @@ static const struct nd_cmd_desc __nd_cmd_bus_descs[] = {
.
out_num
=
3
,
.
out_sizes
=
{
4
,
4
,
8
,
},
},
[
ND_CMD_CALL
]
=
{
.
in_num
=
2
,
.
in_sizes
=
{
sizeof
(
struct
nd_cmd_pkg
),
UINT_MAX
,
},
.
out_num
=
1
,
.
out_sizes
=
{
UINT_MAX
,
},
},
};
const
struct
nd_cmd_desc
*
nd_cmd_bus_desc
(
int
cmd
)
...
...
@@ -504,6 +516,10 @@ u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
struct
nd_cmd_vendor_hdr
*
hdr
=
buf
;
return
hdr
->
in_length
;
}
else
if
(
cmd
==
ND_CMD_CALL
)
{
struct
nd_cmd_pkg
*
pkg
=
buf
;
return
pkg
->
nd_size_in
;
}
return
UINT_MAX
;
...
...
@@ -526,6 +542,12 @@ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
return
out_field
[
1
];
else
if
(
!
nvdimm
&&
cmd
==
ND_CMD_ARS_STATUS
&&
idx
==
2
)
return
out_field
[
1
]
-
8
;
else
if
(
cmd
==
ND_CMD_CALL
)
{
struct
nd_cmd_pkg
*
pkg
=
(
struct
nd_cmd_pkg
*
)
in_field
;
return
pkg
->
nd_size_out
;
}
return
UINT_MAX
;
}
...
...
@@ -592,25 +614,31 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
unsigned
int
cmd
=
_IOC_NR
(
ioctl_cmd
);
void
__user
*
p
=
(
void
__user
*
)
arg
;
struct
device
*
dev
=
&
nvdimm_bus
->
dev
;
struct
nd_cmd_pkg
pkg
;
const
char
*
cmd_name
,
*
dimm_name
;
unsigned
long
dsm
_mask
;
unsigned
long
cmd
_mask
;
void
*
buf
;
int
rc
,
i
;
if
(
nvdimm
)
{
desc
=
nd_cmd_dimm_desc
(
cmd
);
cmd_name
=
nvdimm_cmd_name
(
cmd
);
dsm_mask
=
nvdimm
->
dsm_mask
?
*
(
nvdimm
->
dsm_mask
)
:
0
;
cmd_mask
=
nvdimm
->
cmd_mask
;
dimm_name
=
dev_name
(
&
nvdimm
->
dev
);
}
else
{
desc
=
nd_cmd_bus_desc
(
cmd
);
cmd_name
=
nvdimm_bus_cmd_name
(
cmd
);
dsm_mask
=
nd_desc
->
dsm
_mask
;
cmd_mask
=
nd_desc
->
cmd
_mask
;
dimm_name
=
"bus"
;
}
if
(
cmd
==
ND_CMD_CALL
)
{
if
(
copy_from_user
(
&
pkg
,
p
,
sizeof
(
pkg
)))
return
-
EFAULT
;
}
if
(
!
desc
||
(
desc
->
out_num
+
desc
->
in_num
==
0
)
||
!
test_bit
(
cmd
,
&
dsm
_mask
))
!
test_bit
(
cmd
,
&
cmd
_mask
))
return
-
ENOTTY
;
/* fail write commands (when read-only) */
...
...
@@ -620,6 +648,7 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
case
ND_CMD_SET_CONFIG_DATA
:
case
ND_CMD_ARS_START
:
case
ND_CMD_CLEAR_ERROR
:
case
ND_CMD_CALL
:
dev_dbg
(
&
nvdimm_bus
->
dev
,
"'%s' command while read-only.
\n
"
,
nvdimm
?
nvdimm_cmd_name
(
cmd
)
:
nvdimm_bus_cmd_name
(
cmd
));
...
...
@@ -647,6 +676,16 @@ static int __nd_ioctl(struct nvdimm_bus *nvdimm_bus, struct nvdimm *nvdimm,
in_len
+=
in_size
;
}
if
(
cmd
==
ND_CMD_CALL
)
{
dev_dbg
(
dev
,
"%s:%s, idx: %llu, in: %zu, out: %zu, len %zu
\n
"
,
__func__
,
dimm_name
,
pkg
.
nd_command
,
in_len
,
out_len
,
buf_len
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
pkg
.
nd_reserved2
);
i
++
)
if
(
pkg
.
nd_reserved2
[
i
])
return
-
EINVAL
;
}
/* process an output envelope */
for
(
i
=
0
;
i
<
desc
->
out_num
;
i
++
)
{
u32
out_size
=
nd_cmd_out_size
(
nvdimm
,
cmd
,
desc
,
i
,
...
...
drivers/nvdimm/core.c
View file @
1f716d05
...
...
@@ -251,7 +251,7 @@ static ssize_t commands_show(struct device *dev,
struct
nvdimm_bus
*
nvdimm_bus
=
to_nvdimm_bus
(
dev
);
struct
nvdimm_bus_descriptor
*
nd_desc
=
nvdimm_bus
->
nd_desc
;
for_each_set_bit
(
cmd
,
&
nd_desc
->
dsm
_mask
,
BITS_PER_LONG
)
for_each_set_bit
(
cmd
,
&
nd_desc
->
cmd
_mask
,
BITS_PER_LONG
)
len
+=
sprintf
(
buf
+
len
,
"%s "
,
nvdimm_bus_cmd_name
(
cmd
));
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
return
len
;
...
...
drivers/nvdimm/dimm_devs.c
View file @
1f716d05
...
...
@@ -37,9 +37,9 @@ static int __validate_dimm(struct nvdimm_drvdata *ndd)
nvdimm
=
to_nvdimm
(
ndd
->
dev
);
if
(
!
nvdimm
->
dsm
_mask
)
if
(
!
nvdimm
->
cmd
_mask
)
return
-
ENXIO
;
if
(
!
test_bit
(
ND_CMD_GET_CONFIG_DATA
,
nvdimm
->
dsm
_mask
))
if
(
!
test_bit
(
ND_CMD_GET_CONFIG_DATA
,
&
nvdimm
->
cmd
_mask
))
return
-
ENXIO
;
return
0
;
...
...
@@ -263,6 +263,12 @@ const char *nvdimm_name(struct nvdimm *nvdimm)
}
EXPORT_SYMBOL_GPL
(
nvdimm_name
);
unsigned
long
nvdimm_cmd_mask
(
struct
nvdimm
*
nvdimm
)
{
return
nvdimm
->
cmd_mask
;
}
EXPORT_SYMBOL_GPL
(
nvdimm_cmd_mask
);
void
*
nvdimm_provider_data
(
struct
nvdimm
*
nvdimm
)
{
if
(
nvdimm
)
...
...
@@ -277,10 +283,10 @@ static ssize_t commands_show(struct device *dev,
struct
nvdimm
*
nvdimm
=
to_nvdimm
(
dev
);
int
cmd
,
len
=
0
;
if
(
!
nvdimm
->
dsm
_mask
)
if
(
!
nvdimm
->
cmd
_mask
)
return
sprintf
(
buf
,
"
\n
"
);
for_each_set_bit
(
cmd
,
nvdimm
->
dsm
_mask
,
BITS_PER_LONG
)
for_each_set_bit
(
cmd
,
&
nvdimm
->
cmd
_mask
,
BITS_PER_LONG
)
len
+=
sprintf
(
buf
+
len
,
"%s "
,
nvdimm_cmd_name
(
cmd
));
len
+=
sprintf
(
buf
+
len
,
"
\n
"
);
return
len
;
...
...
@@ -340,7 +346,7 @@ EXPORT_SYMBOL_GPL(nvdimm_attribute_group);
struct
nvdimm
*
nvdimm_create
(
struct
nvdimm_bus
*
nvdimm_bus
,
void
*
provider_data
,
const
struct
attribute_group
**
groups
,
unsigned
long
flags
,
unsigned
long
*
dsm
_mask
)
unsigned
long
cmd
_mask
)
{
struct
nvdimm
*
nvdimm
=
kzalloc
(
sizeof
(
*
nvdimm
),
GFP_KERNEL
);
struct
device
*
dev
;
...
...
@@ -355,7 +361,7 @@ struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
}
nvdimm
->
provider_data
=
provider_data
;
nvdimm
->
flags
=
flags
;
nvdimm
->
dsm_mask
=
dsm
_mask
;
nvdimm
->
cmd_mask
=
cmd
_mask
;
atomic_set
(
&
nvdimm
->
busy
,
0
);
dev
=
&
nvdimm
->
dev
;
dev_set_name
(
dev
,
"nmem%d"
,
nvdimm
->
id
);
...
...
drivers/nvdimm/nd-core.h
View file @
1f716d05
...
...
@@ -37,7 +37,7 @@ struct nvdimm_bus {
struct
nvdimm
{
unsigned
long
flags
;
void
*
provider_data
;
unsigned
long
*
dsm
_mask
;
unsigned
long
cmd
_mask
;
struct
device
dev
;
atomic_t
busy
;
int
id
;
...
...
include/acpi/acpi_bus.h
View file @
1f716d05
...
...
@@ -61,12 +61,12 @@ bool acpi_ata_match(acpi_handle handle);
bool
acpi_bay_match
(
acpi_handle
handle
);
bool
acpi_dock_match
(
acpi_handle
handle
);
bool
acpi_check_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
int
rev
,
u64
funcs
);
bool
acpi_check_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
u64
rev
,
u64
funcs
);
union
acpi_object
*
acpi_evaluate_dsm
(
acpi_handle
handle
,
const
u8
*
uuid
,
int
rev
,
int
func
,
union
acpi_object
*
argv4
);
u64
rev
,
u64
func
,
union
acpi_object
*
argv4
);
static
inline
union
acpi_object
*
acpi_evaluate_dsm_typed
(
acpi_handle
handle
,
const
u8
*
uuid
,
int
rev
,
int
func
,
acpi_evaluate_dsm_typed
(
acpi_handle
handle
,
const
u8
*
uuid
,
u64
rev
,
u64
func
,
union
acpi_object
*
argv4
,
acpi_object_type
type
)
{
union
acpi_object
*
obj
;
...
...
include/linux/libnvdimm.h
View file @
1f716d05
...
...
@@ -27,7 +27,7 @@ enum {
/* need to set a limit somewhere, but yes, this is likely overkill */
ND_IOCTL_MAX_BUFLEN
=
SZ_4M
,
ND_CMD_MAX_ELEM
=
5
,
ND_CMD_MAX_ENVELOPE
=
1
6
,
ND_CMD_MAX_ENVELOPE
=
25
6
,
ND_MAX_MAPPINGS
=
32
,
/* region flag indicating to direct-map persistent memory by default */
...
...
@@ -68,7 +68,7 @@ struct nd_mapping {
struct
nvdimm_bus_descriptor
{
const
struct
attribute_group
**
attr_groups
;
unsigned
long
dsm
_mask
;
unsigned
long
cmd
_mask
;
char
*
provider_name
;
ndctl_fn
ndctl
;
int
(
*
flush_probe
)(
struct
nvdimm_bus_descriptor
*
nd_desc
);
...
...
@@ -130,10 +130,11 @@ struct nd_region *to_nd_region(struct device *dev);
struct
nd_blk_region
*
to_nd_blk_region
(
struct
device
*
dev
);
struct
nvdimm_bus_descriptor
*
to_nd_desc
(
struct
nvdimm_bus
*
nvdimm_bus
);
const
char
*
nvdimm_name
(
struct
nvdimm
*
nvdimm
);
unsigned
long
nvdimm_cmd_mask
(
struct
nvdimm
*
nvdimm
);
void
*
nvdimm_provider_data
(
struct
nvdimm
*
nvdimm
);
struct
nvdimm
*
nvdimm_create
(
struct
nvdimm_bus
*
nvdimm_bus
,
void
*
provider_data
,
const
struct
attribute_group
**
groups
,
unsigned
long
flags
,
unsigned
long
*
dsm
_mask
);
unsigned
long
cmd
_mask
);
const
struct
nd_cmd_desc
*
nd_cmd_dimm_desc
(
int
cmd
);
const
struct
nd_cmd_desc
*
nd_cmd_bus_desc
(
int
cmd
);
u32
nd_cmd_in_size
(
struct
nvdimm
*
nvdimm
,
int
cmd
,
...
...
include/uapi/linux/ndctl.h
View file @
1f716d05
...
...
@@ -159,6 +159,7 @@ enum {
ND_CMD_VENDOR_EFFECT_LOG_SIZE
=
7
,
ND_CMD_VENDOR_EFFECT_LOG
=
8
,
ND_CMD_VENDOR
=
9
,
ND_CMD_CALL
=
10
,
};
enum
{
...
...
@@ -192,6 +193,7 @@ static inline const char *nvdimm_cmd_name(unsigned cmd)
[
ND_CMD_VENDOR_EFFECT_LOG_SIZE
]
=
"effect_size"
,
[
ND_CMD_VENDOR_EFFECT_LOG
]
=
"effect_log"
,
[
ND_CMD_VENDOR
]
=
"vendor"
,
[
ND_CMD_CALL
]
=
"cmd_call"
,
};
if
(
cmd
<
ARRAY_SIZE
(
names
)
&&
names
[
cmd
])
...
...
@@ -260,4 +262,44 @@ enum ars_masks {
ARS_STATUS_MASK
=
0x0000FFFF
,
ARS_EXT_STATUS_SHIFT
=
16
,
};
/*
* struct nd_cmd_pkg
*
* is a wrapper to a quasi pass thru interface for invoking firmware
* associated with nvdimms.
*
* INPUT PARAMETERS
*
* nd_family corresponds to the firmware (e.g. DSM) interface.
*
* nd_command are the function index advertised by the firmware.
*
* nd_size_in is the size of the input parameters being passed to firmware
*
* OUTPUT PARAMETERS
*
* nd_fw_size is the size of the data firmware wants to return for
* the call. If nd_fw_size is greater than size of nd_size_out, only
* the first nd_size_out bytes are returned.
*/
struct
nd_cmd_pkg
{
__u64
nd_family
;
/* family of commands */
__u64
nd_command
;
__u32
nd_size_in
;
/* INPUT: size of input args */
__u32
nd_size_out
;
/* INPUT: size of payload */
__u32
nd_reserved2
[
9
];
/* reserved must be zero */
__u32
nd_fw_size
;
/* OUTPUT: size fw wants to return */
unsigned
char
nd_payload
[];
/* Contents of call */
};
/* These NVDIMM families represent pre-standardization command sets */
#define NVDIMM_FAMILY_INTEL 0
#define NVDIMM_FAMILY_HPE1 1
#define NVDIMM_FAMILY_HPE2 2
#define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\
struct nd_cmd_pkg)
#endif
/* __NDCTL_H__ */
tools/testing/nvdimm/test/nfit.c
View file @
1f716d05
...
...
@@ -372,6 +372,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
{
struct
acpi_nfit_desc
*
acpi_desc
=
to_acpi_desc
(
nd_desc
);
struct
nfit_test
*
t
=
container_of
(
acpi_desc
,
typeof
(
*
t
),
acpi_desc
);
unsigned
int
func
=
cmd
;
int
i
,
rc
=
0
,
__cmd_rc
;
if
(
!
cmd_rc
)
...
...
@@ -380,8 +381,23 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
if
(
nvdimm
)
{
struct
nfit_mem
*
nfit_mem
=
nvdimm_provider_data
(
nvdimm
);
unsigned
long
cmd_mask
=
nvdimm_cmd_mask
(
nvdimm
);
if
(
!
nfit_mem
||
!
test_bit
(
cmd
,
&
nfit_mem
->
dsm_mask
))
if
(
!
nfit_mem
)
return
-
ENOTTY
;
if
(
cmd
==
ND_CMD_CALL
)
{
struct
nd_cmd_pkg
*
call_pkg
=
buf
;
buf_len
=
call_pkg
->
nd_size_in
+
call_pkg
->
nd_size_out
;
buf
=
(
void
*
)
call_pkg
->
nd_payload
;
func
=
call_pkg
->
nd_command
;
if
(
call_pkg
->
nd_family
!=
nfit_mem
->
family
)
return
-
ENOTTY
;
}
if
(
!
test_bit
(
cmd
,
&
cmd_mask
)
||
!
test_bit
(
func
,
&
nfit_mem
->
dsm_mask
))
return
-
ENOTTY
;
/* lookup label space for the given dimm */
...
...
@@ -392,7 +408,7 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
if
(
i
>=
ARRAY_SIZE
(
handle
))
return
-
ENXIO
;
switch
(
cmd
)
{
switch
(
func
)
{
case
ND_CMD_GET_CONFIG_SIZE
:
rc
=
nfit_test_cmd_get_config_size
(
buf
,
buf_len
);
break
;
...
...
@@ -416,10 +432,10 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
}
else
{
struct
ars_state
*
ars_state
=
&
t
->
ars_state
;
if
(
!
nd_desc
||
!
test_bit
(
cmd
,
&
nd_desc
->
dsm
_mask
))
if
(
!
nd_desc
||
!
test_bit
(
cmd
,
&
nd_desc
->
cmd
_mask
))
return
-
ENOTTY
;
switch
(
cmd
)
{
switch
(
func
)
{
case
ND_CMD_ARS_CAP
:
rc
=
nfit_test_cmd_ars_cap
(
buf
,
buf_len
);
break
;
...
...
@@ -1293,15 +1309,15 @@ static void nfit_test0_setup(struct nfit_test *t)
post_ars_status
(
&
t
->
ars_state
,
t
->
spa_set_dma
[
0
],
SPA0_SIZE
);
acpi_desc
=
&
t
->
acpi_desc
;
set_bit
(
ND_CMD_GET_CONFIG_SIZE
,
&
acpi_desc
->
dimm_
dsm
_force_en
);
set_bit
(
ND_CMD_GET_CONFIG_DATA
,
&
acpi_desc
->
dimm_
dsm
_force_en
);
set_bit
(
ND_CMD_SET_CONFIG_DATA
,
&
acpi_desc
->
dimm_
dsm
_force_en
);
set_bit
(
ND_CMD_SMART
,
&
acpi_desc
->
dimm_
dsm
_force_en
);
set_bit
(
ND_CMD_ARS_CAP
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_ARS_START
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_ARS_STATUS
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_CLEAR_ERROR
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_SMART_THRESHOLD
,
&
acpi_desc
->
dimm_
dsm
_force_en
);
set_bit
(
ND_CMD_GET_CONFIG_SIZE
,
&
acpi_desc
->
dimm_
cmd
_force_en
);
set_bit
(
ND_CMD_GET_CONFIG_DATA
,
&
acpi_desc
->
dimm_
cmd
_force_en
);
set_bit
(
ND_CMD_SET_CONFIG_DATA
,
&
acpi_desc
->
dimm_
cmd
_force_en
);
set_bit
(
ND_CMD_SMART
,
&
acpi_desc
->
dimm_
cmd
_force_en
);
set_bit
(
ND_CMD_ARS_CAP
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_ARS_START
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_ARS_STATUS
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_CLEAR_ERROR
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_SMART_THRESHOLD
,
&
acpi_desc
->
dimm_
cmd
_force_en
);
}
static
void
nfit_test1_setup
(
struct
nfit_test
*
t
)
...
...
@@ -1359,10 +1375,10 @@ static void nfit_test1_setup(struct nfit_test *t)
post_ars_status
(
&
t
->
ars_state
,
t
->
spa_set_dma
[
0
],
SPA2_SIZE
);
acpi_desc
=
&
t
->
acpi_desc
;
set_bit
(
ND_CMD_ARS_CAP
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_ARS_START
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_ARS_STATUS
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_CLEAR_ERROR
,
&
acpi_desc
->
bus_
dsm
_force_en
);
set_bit
(
ND_CMD_ARS_CAP
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_ARS_START
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_ARS_STATUS
,
&
acpi_desc
->
bus_
cmd
_force_en
);
set_bit
(
ND_CMD_CLEAR_ERROR
,
&
acpi_desc
->
bus_
cmd
_force_en
);
}
static
int
nfit_test_blk_do_io
(
struct
nd_blk_region
*
ndbr
,
resource_size_t
dpa
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment