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 easy way to implement
this. Even if this data is some how stored in some field of 'struct
ndctl_dimm', managing its lifetime is a challenge.

To solve this problem, the patch proposes a new member 'struct
ndctl_dimm.dimm_user_data' to store per-dimm data interpretation of
which is 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 <[email protected]>
---
Changelog:

v1..v2:
* Changed the patch order
---
 ndctl/lib/libndctl.c | 11 +++++++++++
 ndctl/lib/private.h  |  5 +++++
 2 files changed, 16 insertions(+)

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 60dad8e56f5a..cda17ff32410 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -598,6 +598,11 @@ 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);
@@ -1714,8 +1719,14 @@ static void *add_dimm(void *parent, int id, const char 
*dimm_base)
        if (dimm->cmd_family == NVDIMM_FAMILY_PAPR_SCM)
                dimm->ops = papr_scm_dimm_ops;
 
+       /* 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 05c703ed71b4..679e359a1070 100644
--- a/ndctl/lib/private.h
+++ b/ndctl/lib/private.h
@@ -99,6 +99,7 @@ struct ndctl_dimm {
        } flags;
        int locked;
        int aliased;
+       void *dimm_user_data;
        struct list_node list;
        int formats;
        int format[0];
@@ -347,6 +348,10 @@ struct ndctl_dimm_ops {
        int (*fw_update_supported)(struct ndctl_dimm *);
        int (*xlat_firmware_status)(struct ndctl_cmd *);
        u32 (*get_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 *);
 };
 
 extern struct ndctl_dimm_ops * const intel_dimm_ops;
-- 
2.25.3
_______________________________________________
Linux-nvdimm mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to