aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorChuck Tuffli <chuck@FreeBSD.org>2021-01-08 17:19:37 +0000
committerChuck Tuffli <chuck@FreeBSD.org>2021-01-08 17:27:56 +0000
commit6733401935f83754b4b2744bc3d33ef84b1271e0 (patch)
tree297a3ca51527c2ac0fc101aef0cc2ad9a3426c44 /sys/dev
parent7edc1bd9dc174526c69246ba45bf2c8c230d38f4 (diff)
downloadsrc-6733401935f83754b4b2744bc3d33ef84b1271e0.tar.gz
src-6733401935f83754b4b2744bc3d33ef84b1271e0.zip
nvmecontrol: add device self-test op and log page
Add decoding of the Device Self-test log page and the ability to start or abort a test. Reviewed by: imp, mav Tested by: Muhammad Ahmad <muhammad.ahmad@seagate.com> MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D27517
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/nvme/nvme.h39
1 files changed, 39 insertions, 0 deletions
diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h
index 3c159b1fd0fc..67d02ba73fd8 100644
--- a/sys/dev/nvme/nvme.h
+++ b/sys/dev/nvme/nvme.h
@@ -1396,6 +1396,28 @@ struct nvme_command_effects_page {
_Static_assert(sizeof(struct nvme_command_effects_page) == 4096,
"bad size for nvme_command_effects_page");
+struct nvme_device_self_test_page {
+ uint8_t curr_operation;
+ uint8_t curr_compl;
+ uint8_t rsvd2[2];
+ struct {
+ uint8_t status;
+ uint8_t segment_num;
+ uint8_t valid_diag_info;
+ uint8_t rsvd3;
+ uint64_t poh;
+ uint32_t nsid;
+ /* Define as an array to simplify alignment issues */
+ uint8_t failing_lba[8];
+ uint8_t status_code_type;
+ uint8_t status_code;
+ uint8_t vendor_specific[2];
+ } __packed result[20];
+} __packed __aligned(4);
+
+_Static_assert(sizeof(struct nvme_device_self_test_page) == 564,
+ "bad size for nvme_device_self_test_page");
+
struct nvme_res_notification_page {
uint64_t log_page_count;
uint8_t log_page_type;
@@ -2016,4 +2038,21 @@ void nvme_resv_status_ext_swapbytes(struct nvme_resv_status_ext *s __unused,
#endif
}
+static inline void
+nvme_device_self_test_swapbytes(struct nvme_device_self_test_page *s __unused)
+{
+#if _BYTE_ORDER != _LITTLE_ENDIAN
+ uint64_t failing_lba;
+ uint32_t r;
+
+ for (r = 0; r < 20; r++) {
+ s->result[r].poh = le64toh(s->result[r].poh);
+ s->result[r].nsid = le32toh(s->result[r].nsid);
+ /* Unaligned 64-bit loads fail on some architectures */
+ memcpy(&failing_lba, s->result[r].failing_lba, sizeof(failing_lba));
+ failing_lba = le64toh(failing_lba);
+ memcpy(s->result[r].failing_lba, &failing_lba, sizeof(failing_lba));
+ }
+#endif
+}
#endif /* __NVME_H__ */