There are scenarios when a dimm-provider need to allocate some per-dimm data that can be quickly retrieved. This data can be used to cache data that spans multiple 'struct ndctl_cmd' submissions.
Unfortunately currently in libnvdimm there is no easiy way to implement this. Even if this data is some how store in an overloaded field of 'struct ndctl_dimm', managing its lifetime is a challenge. To solve this problem this patch proposes a new member 'struct ndctl_dimm.dimm_user_data' to store per-dimm data thats specific to a dimm-provider. Also two new dimm-ops namely dimm_init() & dimm_uninit() are introduced that can be used to manage the lifetime of this per-dimm data. Semantics ========= int (*dimm_init)(struct ndctl_dimm *): This callback will be called just after dimm-probe inside add_dimm() is completed. Dimm-providers should use this callback to allocate per-dimm data and assign it to 'struct ndctl_dimm.dimm_user_data' member. In case this function returns an error, dimm initialization is halted and errors out. void (*dimm_uninit)(struct ndctl_dimm *): This callback will be called during free_dimm() and is only called if previous call to 'dimm_ops->dimm_init()' had reported no error. Dimm-providers should use this callback to unallocate and cleanup 'dimm_user_data'. Signed-off-by: Vaibhav Jain <vaib...@linux.ibm.com> --- ndctl/lib/libndctl.c | 13 ++++++++++++- ndctl/lib/private.h | 5 +++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c index 38ddfea6dbc0..a5f5fdac9f48 100644 --- a/ndctl/lib/libndctl.c +++ b/ndctl/lib/libndctl.c @@ -596,6 +596,10 @@ static void free_dimm(struct ndctl_dimm *dimm) { if (!dimm) return; + /* If needed call the dimm uninitialization function */ + if (dimm->ops && dimm->ops->dimm_uninit) + dimm->ops->dimm_uninit(dimm); + free(dimm->unique_id); free(dimm->dimm_buf); free(dimm->dimm_path); @@ -1596,8 +1600,15 @@ static void *add_dimm(void *parent, int id, const char *dimm_base) dimm->ops = msft_dimm_ops; if (dimm->cmd_family == NVDIMM_FAMILY_HYPERV) dimm->ops = hyperv_dimm_ops; - out: + + /* Call the dimm initialization function if needed */ + if (!rc && dimm->ops && dimm->ops->dimm_init) + rc = dimm->ops->dimm_init(dimm); + +out: if (rc) { + /* Ensure dimm_uninit() is not called during free_dimm() */ + dimm->ops = NULL; err(ctx, "Unable to probe dimm:%d. Err:%d\n", id, rc); goto err_read; } diff --git a/ndctl/lib/private.h b/ndctl/lib/private.h index 1f6a01c55377..fb7fa47f1f37 100644 --- a/ndctl/lib/private.h +++ b/ndctl/lib/private.h @@ -98,6 +98,7 @@ struct ndctl_dimm { } flags; int locked; int aliased; + void *dimm_user_data; struct list_node list; int formats; int format[0]; @@ -340,6 +341,10 @@ struct ndctl_dimm_ops { struct ndctl_cmd *(*new_ack_shutdown_count)(struct ndctl_dimm *); int (*fw_update_supported)(struct ndctl_dimm *); int (*xlat_firmware_status)(struct ndctl_cmd *); + /* Called just after dimm is initialized and probed */ + int (*dimm_init)(struct ndctl_dimm *); + /* Called just before struct ndctl_dimm is de-allocated */ + void (*dimm_uninit)(struct ndctl_dimm *); }; struct ndctl_dimm_ops * const intel_dimm_ops; -- 2.24.1 _______________________________________________ Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org To unsubscribe send an email to linux-nvdimm-le...@lists.01.org