Rework logpage extensibility.
Move from using a linker set to a constructor function that's called. This simplifies the code and is slightly more obvious. We now keep a list of page decoders rather than having an array we managed before. Commands will move to something similar in the future. Reviewed by: jhb@ Differential Revision: https://reviews.freebsd.org/D19275
This commit is contained in:
parent
b9af2aaaa3
commit
90eaca25c1
@ -53,7 +53,14 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#define MAX_FW_SLOTS (7)
|
#define MAX_FW_SLOTS (7)
|
||||||
|
|
||||||
SET_CONCAT_DEF(logpage, struct logpage_function);
|
static SLIST_HEAD(,logpage_function) logpages;
|
||||||
|
|
||||||
|
void
|
||||||
|
logpage_register(struct logpage_function *p)
|
||||||
|
{
|
||||||
|
|
||||||
|
SLIST_INSERT_HEAD(&logpages, p, link);
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key)
|
kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key)
|
||||||
@ -326,15 +333,15 @@ NVME_LOGPAGE(fw,
|
|||||||
static void
|
static void
|
||||||
logpage_help(void)
|
logpage_help(void)
|
||||||
{
|
{
|
||||||
const struct logpage_function * const *f;
|
const struct logpage_function *f;
|
||||||
const char *v;
|
const char *v;
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "%-8s %-10s %s\n", "Page", "Vendor","Page Name");
|
fprintf(stderr, "%-8s %-10s %s\n", "Page", "Vendor","Page Name");
|
||||||
fprintf(stderr, "-------- ---------- ----------\n");
|
fprintf(stderr, "-------- ---------- ----------\n");
|
||||||
for (f = logpage_begin(); f < logpage_limit(); f++) {
|
SLIST_FOREACH(f, &logpages, link) {
|
||||||
v = (*f)->vendor == NULL ? "-" : (*f)->vendor;
|
v = f->vendor == NULL ? "-" : f->vendor;
|
||||||
fprintf(stderr, "0x%02x %-10s %s\n", (*f)->log_page, v, (*f)->name);
|
fprintf(stderr, "0x%02x %-10s %s\n", f->log_page, v, f->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -352,7 +359,7 @@ logpage(const struct nvme_function *nf, int argc, char *argv[])
|
|||||||
uint32_t nsid, size;
|
uint32_t nsid, size;
|
||||||
void *buf;
|
void *buf;
|
||||||
const char *vendor = NULL;
|
const char *vendor = NULL;
|
||||||
const struct logpage_function * const *f;
|
const struct logpage_function *f;
|
||||||
struct nvme_controller_data cdata;
|
struct nvme_controller_data cdata;
|
||||||
print_fn_t print_fn;
|
print_fn_t print_fn;
|
||||||
uint8_t ns_smart;
|
uint8_t ns_smart;
|
||||||
@ -438,14 +445,14 @@ logpage(const struct nvme_function *nf, int argc, char *argv[])
|
|||||||
* the page is vendor specific, don't match the print function
|
* the page is vendor specific, don't match the print function
|
||||||
* unless the vendors match.
|
* unless the vendors match.
|
||||||
*/
|
*/
|
||||||
for (f = logpage_begin(); f < logpage_limit(); f++) {
|
SLIST_FOREACH(f, &logpages, link) {
|
||||||
if ((*f)->vendor != NULL && vendor != NULL &&
|
if (f->vendor != NULL && vendor != NULL &&
|
||||||
strcmp((*f)->vendor, vendor) != 0)
|
strcmp(f->vendor, vendor) != 0)
|
||||||
continue;
|
continue;
|
||||||
if (log_page != (*f)->log_page)
|
if (log_page != f->log_page)
|
||||||
continue;
|
continue;
|
||||||
print_fn = (*f)->print_fn;
|
print_fn = f->print_fn;
|
||||||
size = (*f)->size;
|
size = f->size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,19 +312,17 @@ load_dir(const char *dir)
|
|||||||
warnx("Can't load %s: %s", path, dlerror());
|
warnx("Can't load %s: %s", path, dlerror());
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
* Add in the top (for cli commands) and logpage (for
|
* Add in the top (for cli commands)linker sets. We have
|
||||||
* logpage parsing) linker sets. We have to do this by
|
* to do this by hand because linker sets aren't
|
||||||
* hand because linker sets aren't automatically merged.
|
* automatically merged.
|
||||||
*/
|
*/
|
||||||
void *begin, *limit;
|
void *begin, *limit;
|
||||||
|
|
||||||
begin = dlsym(h, "__start_set_top");
|
begin = dlsym(h, "__start_set_top");
|
||||||
limit = dlsym(h, "__stop_set_top");
|
limit = dlsym(h, "__stop_set_top");
|
||||||
if (begin)
|
if (begin)
|
||||||
add_to_top(begin, limit);
|
add_to_top(begin, limit);
|
||||||
begin = dlsym(h, "__start_set_logpage");
|
/* log pages use constructors so are done on load */
|
||||||
limit = dlsym(h, "__stop_set_logpage");
|
|
||||||
if (begin)
|
|
||||||
add_to_logpage(begin, limit);
|
|
||||||
}
|
}
|
||||||
free(path);
|
free(path);
|
||||||
path = NULL;
|
path = NULL;
|
||||||
@ -337,7 +335,6 @@ main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
|
|
||||||
add_to_top(NVME_CMD_BEGIN(top), NVME_CMD_LIMIT(top));
|
add_to_top(NVME_CMD_BEGIN(top), NVME_CMD_LIMIT(top));
|
||||||
add_to_logpage(NVME_LOGPAGE_BEGIN, NVME_LOGPAGE_LIMIT);
|
|
||||||
|
|
||||||
load_dir("/lib/nvmecontrol");
|
load_dir("/lib/nvmecontrol");
|
||||||
load_dir("/usr/local/lib/nvmecontrol");
|
load_dir("/usr/local/lib/nvmecontrol");
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define __NVMECONTROL_H__
|
#define __NVMECONTROL_H__
|
||||||
|
|
||||||
#include <sys/linker_set.h>
|
#include <sys/linker_set.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
#include <dev/nvme/nvme.h>
|
#include <dev/nvme/nvme.h>
|
||||||
|
|
||||||
struct nvme_function;
|
struct nvme_function;
|
||||||
@ -56,6 +57,7 @@ struct nvme_function {
|
|||||||
typedef void (*print_fn_t)(const struct nvme_controller_data *cdata, void *buf, uint32_t size);
|
typedef void (*print_fn_t)(const struct nvme_controller_data *cdata, void *buf, uint32_t size);
|
||||||
|
|
||||||
struct logpage_function {
|
struct logpage_function {
|
||||||
|
SLIST_ENTRY(logpage_function) link;
|
||||||
uint8_t log_page;
|
uint8_t log_page;
|
||||||
const char *vendor;
|
const char *vendor;
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -64,7 +66,6 @@ struct logpage_function {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define NVME_LOGPAGESET(sym) DATA_SET(NVME_SETNAME(logpage), sym)
|
|
||||||
#define NVME_LOGPAGE(unique, lp, vend, nam, fn, sz) \
|
#define NVME_LOGPAGE(unique, lp, vend, nam, fn, sz) \
|
||||||
static struct logpage_function unique ## _lpf = { \
|
static struct logpage_function unique ## _lpf = { \
|
||||||
.log_page = lp, \
|
.log_page = lp, \
|
||||||
@ -73,10 +74,8 @@ struct logpage_function {
|
|||||||
.print_fn = fn, \
|
.print_fn = fn, \
|
||||||
.size = sz, \
|
.size = sz, \
|
||||||
} ; \
|
} ; \
|
||||||
NVME_LOGPAGESET(unique ## _lpf)
|
static void logpage_reg_##unique(void) __attribute__((constructor)); \
|
||||||
#define NVME_LOGPAGE_BEGIN SET_BEGIN(NVME_SETNAME(logpage))
|
static void logpage_reg_##unique(void) { logpage_register(&unique##_lpf); }
|
||||||
#define NVME_LOGPAGE_LIMIT SET_LIMIT(NVME_SETNAME(logpage))
|
|
||||||
#define NVME_LOGPAGE_DECLARE(t) SET_DECLARE(NVME_SETNAME(logpage), t)
|
|
||||||
|
|
||||||
#define DEFAULT_SIZE (4096)
|
#define DEFAULT_SIZE (4096)
|
||||||
struct kv_name {
|
struct kv_name {
|
||||||
@ -87,7 +86,7 @@ struct kv_name {
|
|||||||
const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key);
|
const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key);
|
||||||
|
|
||||||
NVME_CMD_DECLARE(top, struct nvme_function);
|
NVME_CMD_DECLARE(top, struct nvme_function);
|
||||||
NVME_LOGPAGE_DECLARE(struct logpage_function);
|
void logpage_register(struct logpage_function *p);
|
||||||
|
|
||||||
struct set_concat {
|
struct set_concat {
|
||||||
void **begin;
|
void **begin;
|
||||||
@ -105,7 +104,6 @@ void add_to_ ## set(t **b, t **e) \
|
|||||||
#define SET_CONCAT_DECL(set, t) \
|
#define SET_CONCAT_DECL(set, t) \
|
||||||
void add_to_ ## set(t **b, t **e)
|
void add_to_ ## set(t **b, t **e)
|
||||||
SET_CONCAT_DECL(top, struct nvme_function);
|
SET_CONCAT_DECL(top, struct nvme_function);
|
||||||
SET_CONCAT_DECL(logpage, struct logpage_function);
|
|
||||||
|
|
||||||
#define NVME_CTRLR_PREFIX "nvme"
|
#define NVME_CTRLR_PREFIX "nvme"
|
||||||
#define NVME_NS_PREFIX "ns"
|
#define NVME_NS_PREFIX "ns"
|
||||||
|
Loading…
Reference in New Issue
Block a user