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
nexedi
linux
Commits
1f716d05
Commit
1f716d05
authored
8 years ago
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
)
...
...
This diff is collapsed.
Click to expand it.
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
);
};
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
,
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
);
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
;
...
...
This diff is collapsed.
Click to expand it.
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
,
...
...
This diff is collapsed.
Click to expand it.
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__ */
This diff is collapsed.
Click to expand it.
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
,
...
...
This diff is collapsed.
Click to expand it.
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