NVMe: Add public API to get log pages.
1 Add supported log pages data structure. 2 Bulid up supported log pages when NVME start. 3 Provide unified API for getting log pages. 3 Unit test suit optimization base on above modification. Change-Id: I03cdb93f5c94e6897510d7f19bc7d9f4e70f9222 Signed-off-by: Cunyin Chang <cunyin.chang@intel.com>
This commit is contained in:
parent
b61b099030
commit
9945c00cf2
@ -107,6 +107,13 @@ const struct nvme_controller_data *nvme_ctrlr_get_data(struct nvme_controller *c
|
|||||||
*/
|
*/
|
||||||
uint32_t nvme_ctrlr_get_num_ns(struct nvme_controller *ctrlr);
|
uint32_t nvme_ctrlr_get_num_ns(struct nvme_controller *ctrlr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Figure out if it is supported for the given NVMe controller and page identifier.
|
||||||
|
*
|
||||||
|
* This function is thread safe and can be called at any point after nvme_attach().
|
||||||
|
*/
|
||||||
|
bool nvme_ctrlr_is_log_page_supported(struct nvme_controller *ctrlr, int log_page);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signature for callback function invoked when a command is completed.
|
* Signature for callback function invoked when a command is completed.
|
||||||
*
|
*
|
||||||
@ -219,6 +226,25 @@ struct nvme_namespace;
|
|||||||
*/
|
*/
|
||||||
struct nvme_namespace *nvme_ctrlr_get_ns(struct nvme_controller *ctrlr, uint32_t ns_id);
|
struct nvme_namespace *nvme_ctrlr_get_ns(struct nvme_controller *ctrlr, uint32_t ns_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get a specific log page from the NVMe controllerr.
|
||||||
|
*
|
||||||
|
* This function can be called at any point after nvme_attach().
|
||||||
|
* \param log_page - the log page identifier.
|
||||||
|
* \param nsid - this is one of the cases where NVME_GLOBAL_NAMESPACE_TAG can
|
||||||
|
* be used for certain log pages.
|
||||||
|
* \param payload - the pointer to the payload buffer.
|
||||||
|
* \param payload_size - the size of payload buffer.
|
||||||
|
* \param cb_fn - call back funciton pointer which will be called after get log page.
|
||||||
|
* \param cb_arg - input parameter for the cb_fn.
|
||||||
|
* Call \ref nvme_ctrlr_process_admin_completions() to poll for completion
|
||||||
|
* of commands submitted through this function.
|
||||||
|
*/
|
||||||
|
void nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr,
|
||||||
|
uint8_t log_page, uint32_t nsid,
|
||||||
|
void *payload, uint32_t payload_size,
|
||||||
|
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the identify namespace data as defined by the NVMe specification.
|
* \brief Get the identify namespace data as defined by the NVMe specification.
|
||||||
*
|
*
|
||||||
|
@ -81,6 +81,20 @@ enum nvme_intel_smart_attribute_code {
|
|||||||
NVME_INTEL_SMART_HOST_BYTES_WRITTEN = 0xF5,
|
NVME_INTEL_SMART_HOST_BYTES_WRITTEN = 0xF5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nvme_intel_log_page_directory {
|
||||||
|
uint8_t version[2];
|
||||||
|
uint8_t reserved[384];
|
||||||
|
uint8_t read_latency_log_len;
|
||||||
|
uint8_t reserved2;
|
||||||
|
uint8_t write_latency_log_len;
|
||||||
|
uint8_t reserved3[5];
|
||||||
|
uint8_t temperature_statistics_log_len;
|
||||||
|
uint8_t reserved4[9];
|
||||||
|
uint8_t smart_log_len;
|
||||||
|
uint8_t reserved5[107];
|
||||||
|
};
|
||||||
|
SPDK_STATIC_ASSERT(sizeof(struct nvme_intel_log_page_directory) == 512, "Incorrect size");
|
||||||
|
|
||||||
struct nvme_intel_rw_latency_page {
|
struct nvme_intel_rw_latency_page {
|
||||||
uint16_t major_revison;
|
uint16_t major_revison;
|
||||||
uint16_t minor_revison;
|
uint16_t minor_revison;
|
||||||
|
@ -573,8 +573,9 @@ struct __attribute__((packed)) nvme_controller_data {
|
|||||||
struct {
|
struct {
|
||||||
/* per namespace smart/health log page */
|
/* per namespace smart/health log page */
|
||||||
uint8_t ns_smart : 1;
|
uint8_t ns_smart : 1;
|
||||||
|
/* command effects log page */
|
||||||
uint8_t lpa_rsvd : 7;
|
uint8_t celp : 1;
|
||||||
|
uint8_t lpa_rsvd : 6;
|
||||||
} lpa;
|
} lpa;
|
||||||
|
|
||||||
/** error log page entries */
|
/** error log page entries */
|
||||||
@ -876,8 +877,11 @@ enum nvme_log_page {
|
|||||||
NVME_LOG_ERROR = 0x01,
|
NVME_LOG_ERROR = 0x01,
|
||||||
NVME_LOG_HEALTH_INFORMATION = 0x02,
|
NVME_LOG_HEALTH_INFORMATION = 0x02,
|
||||||
NVME_LOG_FIRMWARE_SLOT = 0x03,
|
NVME_LOG_FIRMWARE_SLOT = 0x03,
|
||||||
/* 0x04-0x7F - reserved */
|
NVME_LOG_CHANGED_NS_LIST = 0x04,
|
||||||
/* 0x80-0xBF - I/O command set specific */
|
NVME_LOG_COMMAND_EFFECTS_LOG = 0x05,
|
||||||
|
/* 0x06-0x7F - reserved */
|
||||||
|
NVME_LOG_RESERVATION_NOTIFICATION = 0x80,
|
||||||
|
/* 0x81-0xBF - I/O command set specific */
|
||||||
/* 0xC0-0xFF - vendor specific */
|
/* 0xC0-0xFF - vendor specific */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
39
include/spdk/pci_ids.h
Normal file
39
include/spdk/pci_ids.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of Intel Corporation nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __PCI_IDS_H__
|
||||||
|
#define __PCI_IDS_H__
|
||||||
|
|
||||||
|
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||||
|
|
||||||
|
#endif /* __PCI_IDS_H__ */
|
@ -34,6 +34,8 @@
|
|||||||
#ifndef __IOAT_PCI_H__
|
#ifndef __IOAT_PCI_H__
|
||||||
#define __IOAT_PCI_H__
|
#define __IOAT_PCI_H__
|
||||||
|
|
||||||
|
#include "spdk/pci_ids.h"
|
||||||
|
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20
|
#define PCI_DEVICE_ID_INTEL_IOAT_SNB0 0x3c20
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21
|
#define PCI_DEVICE_ID_INTEL_IOAT_SNB1 0x3c21
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22
|
#define PCI_DEVICE_ID_INTEL_IOAT_SNB2 0x3c22
|
||||||
@ -88,7 +90,5 @@
|
|||||||
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
|
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
|
||||||
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
|
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
|
||||||
|
|
||||||
#endif /* __IOAT_PCI_H__ */
|
#endif /* __IOAT_PCI_H__ */
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "nvme_internal.h"
|
#include "nvme_internal.h"
|
||||||
|
#include "spdk/nvme_intel.h"
|
||||||
/**
|
/**
|
||||||
* \file
|
* \file
|
||||||
*
|
*
|
||||||
@ -41,6 +41,84 @@
|
|||||||
static int nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
|
static int nvme_ctrlr_construct_and_submit_aer(struct nvme_controller *ctrlr,
|
||||||
struct nvme_async_event_request *aer);
|
struct nvme_async_event_request *aer);
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_ctrlr_construct_intel_support_log_page_list(struct nvme_controller *ctrlr,
|
||||||
|
struct nvme_intel_log_page_directory *log_page_directory)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
if (ctrlr->cdata.vid != PCI_VENDOR_ID_INTEL || log_page_directory == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ctrlr->supported_log_pages.vendor_specific_page_id[i] = NVME_INTEL_LOG_PAGE_DIRECTORY;
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (log_page_directory->read_latency_log_len) {
|
||||||
|
ctrlr->supported_log_pages.vendor_specific_page_id[i] = NVME_INTEL_LOG_READ_CMD_LATENCY;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (log_page_directory->write_latency_log_len) {
|
||||||
|
ctrlr->supported_log_pages.vendor_specific_page_id[i] = NVME_INTEL_LOG_WRITE_CMD_LATENCY;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (log_page_directory->temperature_statistics_log_len) {
|
||||||
|
ctrlr->supported_log_pages.vendor_specific_page_id[i] = NVME_INTEL_LOG_TEMPERATURE;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (log_page_directory->smart_log_len) {
|
||||||
|
ctrlr->supported_log_pages.vendor_specific_page_id[i] = NVME_INTEL_LOG_SMART;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nvme_ctrlr_set_intel_support_log_pages(struct nvme_controller *ctrlr)
|
||||||
|
{
|
||||||
|
uint64_t phys_addr = 0;
|
||||||
|
struct nvme_completion_poll_status status;
|
||||||
|
struct nvme_intel_log_page_directory *log_page_directory;
|
||||||
|
|
||||||
|
log_page_directory = nvme_malloc("nvme_log_page_directory",
|
||||||
|
sizeof(struct nvme_intel_log_page_directory),
|
||||||
|
64, &phys_addr);
|
||||||
|
if (log_page_directory == NULL) {
|
||||||
|
nvme_printf(NULL, "could not allocate log_page_directory\n");
|
||||||
|
return ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
status.done = false;
|
||||||
|
nvme_ctrlr_cmd_get_log_page(ctrlr, NVME_INTEL_LOG_PAGE_DIRECTORY, NVME_GLOBAL_NAMESPACE_TAG,
|
||||||
|
log_page_directory, sizeof(struct nvme_intel_log_page_directory),
|
||||||
|
nvme_completion_poll_cb,
|
||||||
|
&status);
|
||||||
|
while (status.done == false) {
|
||||||
|
nvme_qpair_process_completions(&ctrlr->adminq, 0);
|
||||||
|
}
|
||||||
|
if (nvme_completion_is_error(&status.cpl)) {
|
||||||
|
nvme_free(log_page_directory);
|
||||||
|
nvme_printf(ctrlr, "nvme_ctrlr_cmd_get_log_page failed!\n");
|
||||||
|
return ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
nvme_ctrlr_construct_intel_support_log_page_list(ctrlr, log_page_directory);
|
||||||
|
nvme_free(log_page_directory);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_ctrlr_set_supported_log_pages(struct nvme_controller *ctrlr)
|
||||||
|
{
|
||||||
|
memset(&ctrlr->supported_log_pages, 0, sizeof(struct nvme_supported_log_pages));
|
||||||
|
ctrlr->supported_log_pages.vendor_id = ctrlr->cdata.vid;
|
||||||
|
ctrlr->supported_log_pages.generic_page_id[0] = NVME_LOG_ERROR;
|
||||||
|
ctrlr->supported_log_pages.generic_page_id[1] = NVME_LOG_HEALTH_INFORMATION;
|
||||||
|
ctrlr->supported_log_pages.generic_page_id[2] = NVME_LOG_FIRMWARE_SLOT;
|
||||||
|
if (ctrlr->cdata.lpa.celp) {
|
||||||
|
ctrlr->supported_log_pages.generic_page_id[3] = NVME_LOG_COMMAND_EFFECTS_LOG;
|
||||||
|
}
|
||||||
|
if (ctrlr->supported_log_pages.vendor_id == PCI_VENDOR_ID_INTEL) {
|
||||||
|
nvme_ctrlr_set_intel_support_log_pages(ctrlr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nvme_ctrlr_construct_admin_qpair(struct nvme_controller *ctrlr)
|
nvme_ctrlr_construct_admin_qpair(struct nvme_controller *ctrlr)
|
||||||
{
|
{
|
||||||
@ -620,6 +698,7 @@ nvme_ctrlr_start(struct nvme_controller *ctrlr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nvme_ctrlr_set_supported_log_pages(ctrlr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -782,3 +861,34 @@ nvme_ctrlr_register_aer_callback(struct nvme_controller *ctrlr,
|
|||||||
ctrlr->aer_cb_fn = aer_cb_fn;
|
ctrlr->aer_cb_fn = aer_cb_fn;
|
||||||
ctrlr->aer_cb_arg = aer_cb_arg;
|
ctrlr->aer_cb_arg = aer_cb_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nvme_ctrlr_is_log_page_supported(struct nvme_controller *ctrlr, int log_page)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
while (i < sizeof(ctrlr->supported_log_pages.generic_page_id)) {
|
||||||
|
if (log_page == ctrlr->supported_log_pages.generic_page_id[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < sizeof(ctrlr->supported_log_pages.command_set_page_id)) {
|
||||||
|
if (log_page == ctrlr->supported_log_pages.command_set_page_id[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < sizeof(ctrlr->supported_log_pages.vendor_specific_page_id)) {
|
||||||
|
if (log_page == ctrlr->supported_log_pages.vendor_specific_page_id[i]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -241,6 +241,7 @@ nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr, uint8_t log_page,
|
|||||||
struct nvme_request *req;
|
struct nvme_request *req;
|
||||||
struct nvme_command *cmd;
|
struct nvme_command *cmd;
|
||||||
|
|
||||||
|
nvme_mutex_lock(&ctrlr->ctrlr_lock);
|
||||||
req = nvme_allocate_request(payload, payload_size, cb_fn, cb_arg);
|
req = nvme_allocate_request(payload, payload_size, cb_fn, cb_arg);
|
||||||
|
|
||||||
cmd = &req->cmd;
|
cmd = &req->cmd;
|
||||||
@ -250,47 +251,7 @@ nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr, uint8_t log_page,
|
|||||||
cmd->cdw10 |= log_page;
|
cmd->cdw10 |= log_page;
|
||||||
|
|
||||||
nvme_ctrlr_submit_admin_request(ctrlr, req);
|
nvme_ctrlr_submit_admin_request(ctrlr, req);
|
||||||
}
|
nvme_mutex_unlock(&ctrlr->ctrlr_lock);
|
||||||
|
|
||||||
void
|
|
||||||
nvme_ctrlr_cmd_get_error_page(struct nvme_controller *ctrlr,
|
|
||||||
struct nvme_error_information_entry *payload, uint32_t num_entries,
|
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
nvme_assert(num_entries > 0, ("%s called with num_entries==0\n", __func__));
|
|
||||||
|
|
||||||
/* Controller's error log page entries is 0-based. */
|
|
||||||
nvme_assert(num_entries <= (ctrlr->cdata.elpe + 1u),
|
|
||||||
("%s called with num_entries=%d but (elpe+1)=%d\n", __func__,
|
|
||||||
num_entries, ctrlr->cdata.elpe + 1));
|
|
||||||
|
|
||||||
if (num_entries > (ctrlr->cdata.elpe + 1u))
|
|
||||||
num_entries = ctrlr->cdata.elpe + 1u;
|
|
||||||
|
|
||||||
nvme_ctrlr_cmd_get_log_page(ctrlr, NVME_LOG_ERROR,
|
|
||||||
NVME_GLOBAL_NAMESPACE_TAG, payload, sizeof(*payload) * num_entries,
|
|
||||||
cb_fn, cb_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nvme_ctrlr_cmd_get_health_information_page(struct nvme_controller *ctrlr,
|
|
||||||
uint32_t nsid, struct nvme_health_information_page *payload,
|
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
nvme_ctrlr_cmd_get_log_page(ctrlr, NVME_LOG_HEALTH_INFORMATION,
|
|
||||||
nsid, payload, sizeof(*payload), cb_fn, cb_arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
nvme_ctrlr_cmd_get_firmware_page(struct nvme_controller *ctrlr,
|
|
||||||
struct nvme_firmware_page *payload, nvme_cb_fn_t cb_fn, void *cb_arg)
|
|
||||||
{
|
|
||||||
|
|
||||||
nvme_ctrlr_cmd_get_log_page(ctrlr, NVME_LOG_FIRMWARE_SLOT,
|
|
||||||
NVME_GLOBAL_NAMESPACE_TAG, payload, sizeof(*payload), cb_fn,
|
|
||||||
cb_arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -52,6 +52,8 @@
|
|||||||
#include "spdk/queue.h"
|
#include "spdk/queue.h"
|
||||||
#include "spdk/barrier.h"
|
#include "spdk/barrier.h"
|
||||||
#include "spdk/mmio.h"
|
#include "spdk/mmio.h"
|
||||||
|
#include "spdk/pci_ids.h"
|
||||||
|
#include "spdk/nvme_intel.h"
|
||||||
|
|
||||||
#define NVME_MAX_PRP_LIST_ENTRIES (32)
|
#define NVME_MAX_PRP_LIST_ENTRIES (32)
|
||||||
|
|
||||||
@ -230,6 +232,23 @@ struct nvme_namespace {
|
|||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \brief supported log pages. */
|
||||||
|
struct nvme_supported_log_pages {
|
||||||
|
uint32_t vendor_id;
|
||||||
|
/**
|
||||||
|
* List of supported generic log page IDs, terminated with 0.
|
||||||
|
*/
|
||||||
|
uint8_t generic_page_id[128];
|
||||||
|
/**
|
||||||
|
* List of supported command set page IDs, terminated with 0.
|
||||||
|
*/
|
||||||
|
uint8_t command_set_page_id[64];
|
||||||
|
/**
|
||||||
|
* List of supported vendor specific page IDs, terminated with 0.
|
||||||
|
*/
|
||||||
|
uint8_t vendor_specific_page_id[64];
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One of these per allocated PCI device.
|
* One of these per allocated PCI device.
|
||||||
*/
|
*/
|
||||||
@ -253,6 +272,9 @@ struct nvme_controller {
|
|||||||
|
|
||||||
/* Cold data (not accessed in normal I/O path) is after this point. */
|
/* Cold data (not accessed in normal I/O path) is after this point. */
|
||||||
|
|
||||||
|
/** All the log pages supported */
|
||||||
|
struct nvme_supported_log_pages supported_log_pages;
|
||||||
|
|
||||||
/* Opaque handle to associated PCI device. */
|
/* Opaque handle to associated PCI device. */
|
||||||
void *devhandle;
|
void *devhandle;
|
||||||
|
|
||||||
@ -342,31 +364,12 @@ void nvme_ctrlr_cmd_get_feature(struct nvme_controller *ctrlr,
|
|||||||
uint8_t feature, uint32_t cdw11,
|
uint8_t feature, uint32_t cdw11,
|
||||||
void *payload, uint32_t payload_size,
|
void *payload, uint32_t payload_size,
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||||
void nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr,
|
|
||||||
uint8_t log_page, uint32_t nsid,
|
|
||||||
void *payload, uint32_t payload_size,
|
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
|
||||||
|
|
||||||
void nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr,
|
void nvme_ctrlr_cmd_identify_controller(struct nvme_controller *ctrlr,
|
||||||
void *payload,
|
void *payload,
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||||
void nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr,
|
void nvme_ctrlr_cmd_identify_namespace(struct nvme_controller *ctrlr,
|
||||||
uint16_t nsid, void *payload,
|
uint16_t nsid, void *payload,
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||||
void nvme_ctrlr_cmd_get_error_page(struct nvme_controller *ctrlr,
|
|
||||||
struct nvme_error_information_entry *payload,
|
|
||||||
uint32_t num_entries, /* 0 = max */
|
|
||||||
nvme_cb_fn_t cb_fn,
|
|
||||||
void *cb_arg);
|
|
||||||
void nvme_ctrlr_cmd_get_health_information_page(struct nvme_controller *ctrlr,
|
|
||||||
uint32_t nsid,
|
|
||||||
struct nvme_health_information_page *payload,
|
|
||||||
nvme_cb_fn_t cb_fn,
|
|
||||||
void *cb_arg);
|
|
||||||
void nvme_ctrlr_cmd_get_firmware_page(struct nvme_controller *ctrlr,
|
|
||||||
struct nvme_firmware_page *payload,
|
|
||||||
nvme_cb_fn_t cb_fn,
|
|
||||||
void *cb_arg);
|
|
||||||
void nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
|
void nvme_ctrlr_cmd_create_io_cq(struct nvme_controller *ctrlr,
|
||||||
struct nvme_qpair *io_que,
|
struct nvme_qpair *io_que,
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg);
|
nvme_cb_fn_t cb_fn, void *cb_arg);
|
||||||
|
@ -50,6 +50,12 @@ int nvme_qpair_construct(struct nvme_qpair *qpair, uint16_t id,
|
|||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
void
|
||||||
|
nvme_ctrlr_cmd_get_log_page(struct nvme_controller *ctrlr, uint8_t log_page,
|
||||||
|
uint32_t nsid, void *payload, uint32_t payload_size, nvme_cb_fn_t cb_fn,
|
||||||
|
void *cb_arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nvme_qpair_fail(struct nvme_qpair *qpair)
|
nvme_qpair_fail(struct nvme_qpair *qpair)
|
||||||
@ -175,6 +181,34 @@ test_nvme_ctrlr_fail(void)
|
|||||||
CU_ASSERT(ctrlr.is_failed == true);
|
CU_ASSERT(ctrlr.is_failed == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nvme_ctrlr_construct_intel_support_log_page_list(void)
|
||||||
|
{
|
||||||
|
bool res;
|
||||||
|
struct nvme_controller ctrlr = {};
|
||||||
|
struct nvme_intel_log_page_directory payload = {};
|
||||||
|
|
||||||
|
/* set a invalid vendor id */
|
||||||
|
ctrlr.cdata.vid = 0xFFFF;
|
||||||
|
memset(&payload, 0, sizeof(struct nvme_intel_log_page_directory));
|
||||||
|
|
||||||
|
nvme_ctrlr_construct_intel_support_log_page_list(&ctrlr, &payload);
|
||||||
|
res = nvme_ctrlr_is_log_page_supported(&ctrlr, NVME_INTEL_LOG_TEMPERATURE);
|
||||||
|
CU_ASSERT(res == false);
|
||||||
|
|
||||||
|
ctrlr.cdata.vid = PCI_VENDOR_ID_INTEL;
|
||||||
|
payload.temperature_statistics_log_len = 1;
|
||||||
|
nvme_ctrlr_construct_intel_support_log_page_list(&ctrlr, &payload);
|
||||||
|
res = nvme_ctrlr_is_log_page_supported(&ctrlr, NVME_INTEL_LOG_PAGE_DIRECTORY);
|
||||||
|
CU_ASSERT(res == true);
|
||||||
|
res = nvme_ctrlr_is_log_page_supported(&ctrlr, NVME_INTEL_LOG_TEMPERATURE);
|
||||||
|
CU_ASSERT(res == true);
|
||||||
|
res = nvme_ctrlr_is_log_page_supported(&ctrlr, NVME_INTEL_LOG_READ_CMD_LATENCY);
|
||||||
|
CU_ASSERT(res == false);
|
||||||
|
res = nvme_ctrlr_is_log_page_supported(&ctrlr, NVME_INTEL_LOG_SMART);
|
||||||
|
CU_ASSERT(res == false);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
CU_pSuite suite = NULL;
|
CU_pSuite suite = NULL;
|
||||||
@ -192,6 +226,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
CU_add_test(suite, "test nvme_ctrlr function nvme_ctrlr_fail", test_nvme_ctrlr_fail) == NULL
|
CU_add_test(suite, "test nvme_ctrlr function nvme_ctrlr_fail", test_nvme_ctrlr_fail) == NULL
|
||||||
|
|| CU_add_test(suite, "test nvme ctrlr function nvme_ctrlr_construct_intel_support_log_page_list",
|
||||||
|
test_nvme_ctrlr_construct_intel_support_log_page_list) == NULL
|
||||||
) {
|
) {
|
||||||
CU_cleanup_registry();
|
CU_cleanup_registry();
|
||||||
return CU_get_error();
|
return CU_get_error();
|
||||||
|
@ -118,6 +118,62 @@ static void verify_io_raw_cmd(struct nvme_request *req)
|
|||||||
CU_ASSERT(memcmp(&req->cmd, &command, sizeof(req->cmd)) == 0);
|
CU_ASSERT(memcmp(&req->cmd, &command, sizeof(req->cmd)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void verify_intel_smart_log_page(struct nvme_request *req)
|
||||||
|
{
|
||||||
|
uint32_t temp_cdw10;
|
||||||
|
|
||||||
|
CU_ASSERT(req->cmd.opc == NVME_OPC_GET_LOG_PAGE);
|
||||||
|
CU_ASSERT(req->cmd.nsid == health_log_nsid);
|
||||||
|
|
||||||
|
temp_cdw10 = ((sizeof(struct nvme_intel_smart_information_page) / sizeof(uint32_t) - 1) << 16) |
|
||||||
|
NVME_INTEL_LOG_SMART;
|
||||||
|
CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify_intel_temperature_log_page(struct nvme_request *req)
|
||||||
|
{
|
||||||
|
uint32_t temp_cdw10;
|
||||||
|
|
||||||
|
CU_ASSERT(req->cmd.opc == NVME_OPC_GET_LOG_PAGE);
|
||||||
|
|
||||||
|
temp_cdw10 = ((sizeof(struct nvme_intel_temperature_page) / sizeof(uint32_t) - 1) << 16) |
|
||||||
|
NVME_INTEL_LOG_TEMPERATURE;
|
||||||
|
CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify_intel_read_latency_log_page(struct nvme_request *req)
|
||||||
|
{
|
||||||
|
uint32_t temp_cdw10;
|
||||||
|
|
||||||
|
CU_ASSERT(req->cmd.opc == NVME_OPC_GET_LOG_PAGE);
|
||||||
|
|
||||||
|
temp_cdw10 = ((sizeof(struct nvme_intel_rw_latency_page) / sizeof(uint32_t) - 1) << 16) |
|
||||||
|
NVME_INTEL_LOG_READ_CMD_LATENCY;
|
||||||
|
CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify_intel_write_latency_log_page(struct nvme_request *req)
|
||||||
|
{
|
||||||
|
uint32_t temp_cdw10;
|
||||||
|
|
||||||
|
CU_ASSERT(req->cmd.opc == NVME_OPC_GET_LOG_PAGE);
|
||||||
|
|
||||||
|
temp_cdw10 = ((sizeof(struct nvme_intel_rw_latency_page) / sizeof(uint32_t) - 1) << 16) |
|
||||||
|
NVME_INTEL_LOG_WRITE_CMD_LATENCY;
|
||||||
|
CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verify_intel_get_log_page_directory(struct nvme_request *req)
|
||||||
|
{
|
||||||
|
uint32_t temp_cdw10;
|
||||||
|
|
||||||
|
CU_ASSERT(req->cmd.opc == NVME_OPC_GET_LOG_PAGE);
|
||||||
|
|
||||||
|
temp_cdw10 = ((sizeof(struct nvme_intel_log_page_directory) / sizeof(uint32_t) - 1) << 16) |
|
||||||
|
NVME_INTEL_LOG_PAGE_DIRECTORY;
|
||||||
|
CU_ASSERT(req->cmd.cdw10 == temp_cdw10);
|
||||||
|
}
|
||||||
|
|
||||||
struct nvme_request *
|
struct nvme_request *
|
||||||
nvme_allocate_request(void *payload, uint32_t payload_size,
|
nvme_allocate_request(void *payload, uint32_t payload_size,
|
||||||
nvme_cb_fn_t cb_fn, void *cb_arg)
|
nvme_cb_fn_t cb_fn, void *cb_arg)
|
||||||
@ -158,7 +214,6 @@ nvme_ctrlr_submit_admin_request(struct nvme_controller *ctrlr, struct nvme_reque
|
|||||||
memset(req, 0, sizeof(*req));
|
memset(req, 0, sizeof(*req));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_firmware_get_log_page(void)
|
test_firmware_get_log_page(void)
|
||||||
{
|
{
|
||||||
@ -167,7 +222,9 @@ test_firmware_get_log_page(void)
|
|||||||
|
|
||||||
verify_fn = verify_firmware_log_page;
|
verify_fn = verify_firmware_log_page;
|
||||||
|
|
||||||
nvme_ctrlr_cmd_get_firmware_page(&ctrlr, &payload, NULL, NULL);
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_LOG_FIRMWARE_SLOT, NVME_GLOBAL_NAMESPACE_TAG,
|
||||||
|
&payload,
|
||||||
|
sizeof(payload), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -178,7 +235,8 @@ test_health_get_log_page(void)
|
|||||||
|
|
||||||
verify_fn = verify_health_log_page;
|
verify_fn = verify_health_log_page;
|
||||||
|
|
||||||
nvme_ctrlr_cmd_get_health_information_page(&ctrlr, health_log_nsid, &payload, NULL, NULL);
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_LOG_HEALTH_INFORMATION, health_log_nsid, &payload,
|
||||||
|
sizeof(payload), NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -193,7 +251,82 @@ test_error_get_log_page(void)
|
|||||||
|
|
||||||
/* valid page */
|
/* valid page */
|
||||||
error_num_entries = 1;
|
error_num_entries = 1;
|
||||||
nvme_ctrlr_cmd_get_error_page(&ctrlr, &payload, error_num_entries, NULL, NULL);
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_LOG_ERROR, NVME_GLOBAL_NAMESPACE_TAG, &payload,
|
||||||
|
sizeof(payload), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intel_smart_get_log_page(void)
|
||||||
|
{
|
||||||
|
struct nvme_controller ctrlr = {};
|
||||||
|
struct nvme_intel_smart_information_page payload = {};
|
||||||
|
|
||||||
|
verify_fn = verify_intel_smart_log_page;
|
||||||
|
|
||||||
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_INTEL_LOG_SMART, health_log_nsid, &payload,
|
||||||
|
sizeof(payload), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intel_temperature_get_log_page(void)
|
||||||
|
{
|
||||||
|
struct nvme_controller ctrlr = {};
|
||||||
|
struct nvme_intel_temperature_page payload = {};
|
||||||
|
|
||||||
|
verify_fn = verify_intel_temperature_log_page;
|
||||||
|
|
||||||
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_INTEL_LOG_TEMPERATURE, NVME_GLOBAL_NAMESPACE_TAG,
|
||||||
|
&payload,
|
||||||
|
sizeof(payload), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intel_read_latency_get_log_page(void)
|
||||||
|
{
|
||||||
|
struct nvme_controller ctrlr = {};
|
||||||
|
struct nvme_intel_rw_latency_page payload = {};
|
||||||
|
|
||||||
|
verify_fn = verify_intel_read_latency_log_page;
|
||||||
|
|
||||||
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_INTEL_LOG_READ_CMD_LATENCY,
|
||||||
|
NVME_GLOBAL_NAMESPACE_TAG,
|
||||||
|
&payload, sizeof(payload), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intel_write_latency_get_log_page(void)
|
||||||
|
{
|
||||||
|
struct nvme_controller ctrlr = {};
|
||||||
|
struct nvme_intel_rw_latency_page payload = {};
|
||||||
|
|
||||||
|
verify_fn = verify_intel_write_latency_log_page;
|
||||||
|
|
||||||
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_INTEL_LOG_WRITE_CMD_LATENCY,
|
||||||
|
NVME_GLOBAL_NAMESPACE_TAG,
|
||||||
|
&payload, sizeof(payload), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intel_get_log_page_directory(void)
|
||||||
|
{
|
||||||
|
struct nvme_controller ctrlr = {};
|
||||||
|
struct nvme_intel_log_page_directory payload = {};
|
||||||
|
|
||||||
|
verify_fn = verify_intel_get_log_page_directory;
|
||||||
|
|
||||||
|
nvme_ctrlr_cmd_get_log_page(&ctrlr, NVME_INTEL_LOG_PAGE_DIRECTORY, NVME_GLOBAL_NAMESPACE_TAG,
|
||||||
|
&payload, sizeof(payload), NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_generic_get_log_pages(void)
|
||||||
|
{
|
||||||
|
test_error_get_log_page();
|
||||||
|
test_health_get_log_page();
|
||||||
|
test_firmware_get_log_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_intel_get_log_pages(void)
|
||||||
|
{
|
||||||
|
test_intel_get_log_page_directory();
|
||||||
|
test_intel_smart_get_log_page();
|
||||||
|
test_intel_temperature_get_log_page();
|
||||||
|
test_intel_read_latency_get_log_page();
|
||||||
|
test_intel_write_latency_get_log_page();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -238,6 +371,12 @@ test_io_raw_cmd(void)
|
|||||||
nvme_ctrlr_cmd_io_raw(&ctrlr, &cmd, NULL, 1, NULL, NULL);
|
nvme_ctrlr_cmd_io_raw(&ctrlr, &cmd, NULL, 1, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_get_log_pages(void)
|
||||||
|
{
|
||||||
|
test_generic_get_log_pages();
|
||||||
|
test_intel_get_log_pages();
|
||||||
|
}
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
CU_pSuite suite = NULL;
|
CU_pSuite suite = NULL;
|
||||||
@ -254,9 +393,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
CU_add_test(suite, "test ctrlr cmd get_firmware_page", test_firmware_get_log_page) == NULL
|
CU_add_test(suite, "test ctrlr cmd get_log_pages", test_get_log_pages) == NULL
|
||||||
|| CU_add_test(suite, "test ctrlr cmd get_health_page", test_health_get_log_page) == NULL
|
|
||||||
|| CU_add_test(suite, "test ctrlr cmd get_error_page", test_error_get_log_page) == NULL
|
|
||||||
|| CU_add_test(suite, "test ctrlr cmd set_feature", test_set_feature_cmd) == NULL
|
|| CU_add_test(suite, "test ctrlr cmd set_feature", test_set_feature_cmd) == NULL
|
||||||
|| CU_add_test(suite, "test ctrlr cmd get_feature", test_get_feature_cmd) == NULL
|
|| CU_add_test(suite, "test ctrlr cmd get_feature", test_get_feature_cmd) == NULL
|
||||||
|| CU_add_test(suite, "test ctrlr cmd abort_cmd", test_abort_cmd) == NULL
|
|| CU_add_test(suite, "test ctrlr cmd abort_cmd", test_abort_cmd) == NULL
|
||||||
|
Loading…
Reference in New Issue
Block a user