aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth D. Merry <ken@FreeBSD.org>2026-11-07 01:05:54 +0000
committerKenneth D. Merry <ken@FreeBSD.org>2026-11-07 01:05:54 +0000
commit9814633f631b41b8026a826b7731ec04c3d7d678 (patch)
treeda6a3f0bf1259dc1a9dd2ee6614fe6ddb7ba059d
parent7a9e4375316b82ca3426820e24ee69101562611a (diff)
cam: Add NVMe reservation, format and features CCB building functions
Add NVMe CCB (union ccb / struct ccb_nvmeio) building functions for the four NVMe reservation opcodes, Format NVM, and Get Features / Set Features. These use the nvme_command building blocks added to sys/dev/nvme/nvme.h, and are used by the new camcontrol(8) nvres, nvformat and nvfeature subcommands that will be added separately. sys/cam/nvme/nvme_all.c: Add NVMe CCB building functions for the four NVMe reservation opcodes: nvme_resv_report(), nvme_resv_register(), nvme_resv_acquire() and nvme_resv_release(). Data direction is set internally (CAM_DIR_IN or CAM_DIR_OUT as appropriate), so no flags parameter is needed. Add a new nvme_format() CCB building function. Add nvme_get_feature() and nvme_set_feature() CCB building functions, along with nvme_get_feature_hostid() and nvme_set_feature_hostid() convenience wrappers for the hostid feature. nvme_set_feature_hostid() takes an sv argument so the caller can request that the hostid persist across reset. sys/cam/nvme/nvme_all.h: Add prototypes for the above. Wrap the declarations in __BEGIN_DECLS / __END_DECLS so C++ compilers don't mangle the names of the C symbols. Co-authored-by: Reid Linnemann <reidl@spectralogic.com> Co-authored-by: Dave Baukus <daveb@spectralogic.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Reviewed by: imp MFC after: 1 week Sponsored by: Spectra Logic Differential Revision: https://reviews.freebsd.org/D59532
-rw-r--r--sys/cam/nvme/nvme_all.c201
-rw-r--r--sys/cam/nvme/nvme_all.h41
2 files changed, 242 insertions, 0 deletions
diff --git a/sys/cam/nvme/nvme_all.c b/sys/cam/nvme/nvme_all.c
index 2ab8ae5340c6..a239498901d1 100644
--- a/sys/cam/nvme/nvme_all.c
+++ b/sys/cam/nvme/nvme_all.c
@@ -50,6 +50,7 @@
#include <cam/cam_queue.h>
#include <cam/cam_xpt.h>
#include <cam/nvme/nvme_all.h>
+#include <dev/nvme/nvme.h>
#include <sys/sbuf.h>
#include <sys/endian.h>
@@ -160,6 +161,206 @@ nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb)
return(0);
}
+void
+nvme_resv_report(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, uint32_t report_type, uint8_t *data_ptr,
+ uint32_t dxfer_len, uint32_t timeout)
+{
+ cam_fill_nvmeio(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_IN,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ nvme_ns_resv_report_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*length*/ dxfer_len,
+ /*report_type*/ report_type);
+}
+
+void
+nvme_resv_register(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int cptpl, int iekey, int rrega,
+ uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
+{
+ cam_fill_nvmeio(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_OUT,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ nvme_ns_resv_register_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*cptpl*/ cptpl,
+ /*iekey*/ iekey,
+ /*rrega*/ rrega);
+}
+
+void
+nvme_resv_acquire(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int rtype, int iekey, int racqa,
+ uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
+{
+ cam_fill_nvmeio(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_OUT,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ nvme_ns_resv_acquire_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*rtype*/ rtype,
+ /*iekey*/ iekey,
+ /*racqa*/ racqa);
+}
+
+void
+nvme_resv_release(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int rtype, int iekey, int rrela,
+ uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
+{
+ cam_fill_nvmeio(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_OUT,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ nvme_ns_resv_release_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*rtype*/ rtype,
+ /*iekey*/ iekey,
+ /*rrela*/ rrela);
+}
+
+void
+nvme_format(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int ses, int pil, int pi, int mset, int lbaf,
+ uint32_t timeout)
+{
+ cam_fill_nvmeadmin(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_NONE,
+ /*data_ptr*/ NULL,
+ /*dxfer_len*/ 0,
+ /*timeout*/ timeout);
+
+ nvme_admin_format_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*ses*/ ses,
+ /*pil*/ pil,
+ /*pi*/ pi,
+ /*mset*/ mset,
+ /*lbaf*/ lbaf);
+}
+
+void
+nvme_get_feature(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int sel, uint8_t feature, uint32_t cdw11,
+ int uuid_idx, uint8_t *data_ptr, uint32_t dxfer_len,
+ uint32_t timeout)
+{
+ cam_fill_nvmeadmin(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_IN,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ nvme_admin_get_feature_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*sel*/ sel,
+ /*feature*/ feature,
+ /*cdw11*/ cdw11,
+ /*uuid_idx*/ uuid_idx);
+}
+
+void
+nvme_set_feature(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int sv, uint8_t feature, uint32_t cdw11,
+ uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, uint32_t cdw15,
+ uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout)
+{
+ cam_fill_nvmeadmin(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*flags*/ CAM_DIR_OUT,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+
+ nvme_admin_set_feature_cmd(/*cmd*/ &nvmeio->cmd,
+ /*nsid*/ nsid,
+ /*sv*/ sv,
+ /*feature*/ feature,
+ /*cdw11*/ cdw11,
+ /*cdw12*/ cdw12,
+ /*cdw13*/ cdw13,
+ /*cdw14*/ cdw14,
+ /*cdw15*/ cdw15);
+}
+
+void
+nvme_get_feature_hostid(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ int sel, int uuid_idx, uint8_t *data_ptr,
+ uint32_t dxfer_len, uint32_t timeout)
+{
+ nvme_get_feature(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*nsid*/ 0,
+ /*sel*/ sel,
+ /*feature*/ NVME_FEAT_HOST_IDENTIFIER,
+ /*cdw11*/ 0,
+ /*uuid_idx*/ uuid_idx,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+}
+
+void
+nvme_set_feature_hostid(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ int sv, int exhid, uint8_t *data_ptr,
+ uint32_t dxfer_len, uint32_t timeout)
+{
+ uint32_t cdw11 = 0;
+ if (exhid)
+ cdw11 = 0x01;
+
+ nvme_set_feature(/*nvmeio*/ nvmeio,
+ /*retries*/ retries,
+ /*cbfcnp*/ cbfcnp,
+ /*nsid*/ 0,
+ /*sv*/ sv,
+ /*feature*/ NVME_FEAT_HOST_IDENTIFIER,
+ /*cdw11*/ cdw11,
+ /*cdw12*/ 0,
+ /*cdw13*/ 0,
+ /*cdw14*/ 0,
+ /*cdw15*/ 0,
+ /*data_ptr*/ data_ptr,
+ /*dxfer_len*/ dxfer_len,
+ /*timeout*/ timeout);
+}
+
/*
* nvme_status_sbuf() returns 0 for success and -1 for failure.
*/
diff --git a/sys/cam/nvme/nvme_all.h b/sys/cam/nvme/nvme_all.h
index 2bc1953e79be..fede596d4b74 100644
--- a/sys/cam/nvme/nvme_all.h
+++ b/sys/cam/nvme/nvme_all.h
@@ -32,6 +32,7 @@
struct ccb_nvmeio;
+__BEGIN_DECLS
void nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, uint32_t nsid,
uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, uint32_t cdw13,
uint32_t cdw14, uint32_t cdw15);
@@ -44,9 +45,49 @@ void nvme_print_ident_short(const struct nvme_controller_data *,
const struct nvme_namespace_data *, struct sbuf *);
void nvme_cmd_sbuf(const struct nvme_command *, struct sbuf *sb);
int nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb);
+void nvme_resv_report(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, uint32_t report_type, uint8_t *data_ptr,
+ uint32_t dxfer_len, uint32_t timeout);
+void nvme_resv_register(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int cptpl, int iekey, int rrega,
+ uint8_t *data_ptr, uint32_t dxfer_len,uint32_t timeout);
+void nvme_resv_acquire(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int rtype, int iekey, int racqa,
+ uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout);
+void nvme_resv_release(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int rtype, int iekey, int rrela,
+ uint8_t *data_ptr, uint32_t dxfer_len, uint32_t timeout);
+void nvme_format(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int ses, int pil, int pi, int mset, int lbaf,
+ uint32_t timeout);
+void nvme_get_feature(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int sel, uint8_t feature, uint32_t cdw11,
+ int uuid_idx, uint8_t *data_ptr, uint32_t dxfer_len,
+ uint32_t timeout);
+void nvme_set_feature(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ uint32_t nsid, int sv, uint8_t feature, uint32_t cdw11,
+ uint32_t cdw12, uint32_t cdw13, uint32_t cdw14,
+ uint32_t cdw15, uint8_t *data_ptr, uint32_t dxfer_len,
+ uint32_t timeout);
+void nvme_get_feature_hostid(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ int sel, int uuid_idx, uint8_t *data_ptr,
+ uint32_t dxfer_len, uint32_t timeout);
+void nvme_set_feature_hostid(struct ccb_nvmeio *nvmeio, uint32_t retries,
+ void (*cbfcnp)(struct cam_periph *, union ccb *),
+ int sv, int exhid, uint8_t *data_ptr,
+ uint32_t dxfer_len, uint32_t timeout);
const char *nvme_command_string(struct ccb_nvmeio *nvmeio, char *, size_t);
int nvme_status_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb);
const void *nvme_get_identify_cntrl(struct cam_periph *);
const void *nvme_get_identify_ns(struct cam_periph *);
+__END_DECLS
#endif /* CAM_NVME_NVME_ALL_H */