diff mbox

[v8,09/10] nvdimm: sysfs shows which dsm support full command ioctl.

Message ID a016b07e1705c6b37ae9aa4d0a1896e6b7eb6f75.1458583367.git.jerry.hoemann@hpe.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jerry Hoemann March 21, 2016, 7:37 p.m. UTC
NVDIMM DSMs whose functions map to the Intel Example DSM, can
be called with the ND_IOCTL_.* ioctl interface.  Those that
don't map, can only be called with the pass thru command.

Save this indication in struct nvdimm to be passed to
the sysfs interface.

Signed-off-by: Jerry Hoemann <jerry.hoemann@hpe.com>
---
 drivers/acpi/nfit.c        | 25 +++++++++++++++----------
 drivers/nvdimm/core.c      |  1 +
 drivers/nvdimm/dimm_devs.c | 12 ++++++++----
 include/linux/libnvdimm.h  |  2 +-
 4 files changed, 25 insertions(+), 15 deletions(-)

Comments

Dan Williams April 11, 2016, 9:43 p.m. UTC | #1
On Mon, Mar 21, 2016 at 12:37 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> NVDIMM DSMs whose functions map to the Intel Example DSM, can
> be called with the ND_IOCTL_.* ioctl interface.  Those that
> don't map, can only be called with the pass thru command.
>
> Save this indication in struct nvdimm to be passed to
> the sysfs interface.
>

I'm having trouble understanding the intent of cmd_ioctl.  I don't
want a flag for "supports Intel Example DSM", I want a mask of ND
commands the bus provider knows how to handle in its ->ndctl() entry
point for the given dimm.  The bus provider is free to provide a
translation of ND command to the bus specific command.  It's just an
arbitrary coincidence that the current list of ND commands matches the
Intel ACPI _DSM command format.
Jerry Hoemann April 11, 2016, 11:58 p.m. UTC | #2
On Mon, Apr 11, 2016 at 02:43:39PM -0700, Dan Williams wrote:
> On Mon, Mar 21, 2016 at 12:37 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> > NVDIMM DSMs whose functions map to the Intel Example DSM, can
> > be called with the ND_IOCTL_.* ioctl interface.  Those that
> > don't map, can only be called with the pass thru command.
> >
> > Save this indication in struct nvdimm to be passed to
> > the sysfs interface.
> >
> 
> I'm having trouble understanding the intent of cmd_ioctl.  I don't
> want a flag for "supports Intel Example DSM", I want a mask of ND
> commands the bus provider knows how to handle in its ->ndctl() entry
> point for the given dimm.  The bus provider is free to provide a
> translation of ND command to the bus specific command.  It's just an
> arbitrary coincidence that the current list of ND commands matches the
> Intel ACPI _DSM command format.

This is my extension of your earlier RFC patch, so I may
have misunderstood your original intent.

The commands_show functions prints the listing of commands for that device.
There is one version for root, and one version for non-root.

For root commands, both dsm spec match on names and semantics, so no
code works for both nvdimms types.

But for non-root commands the names/semantics don't match. So, this
is an attempt to show that on an NVDIMM-N,  only the pass thru command
is supported.
Dan Williams April 12, 2016, 12:30 a.m. UTC | #3
On Mon, Apr 11, 2016 at 4:58 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> On Mon, Apr 11, 2016 at 02:43:39PM -0700, Dan Williams wrote:
>> On Mon, Mar 21, 2016 at 12:37 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
>> > NVDIMM DSMs whose functions map to the Intel Example DSM, can
>> > be called with the ND_IOCTL_.* ioctl interface.  Those that
>> > don't map, can only be called with the pass thru command.
>> >
>> > Save this indication in struct nvdimm to be passed to
>> > the sysfs interface.
>> >
>>
>> I'm having trouble understanding the intent of cmd_ioctl.  I don't
>> want a flag for "supports Intel Example DSM", I want a mask of ND
>> commands the bus provider knows how to handle in its ->ndctl() entry
>> point for the given dimm.  The bus provider is free to provide a
>> translation of ND command to the bus specific command.  It's just an
>> arbitrary coincidence that the current list of ND commands matches the
>> Intel ACPI _DSM command format.
>
> This is my extension of your earlier RFC patch, so I may
> have misunderstood your original intent.
>
> The commands_show functions prints the listing of commands for that device.
> There is one version for root, and one version for non-root.
>
> For root commands, both dsm spec match on names and semantics, so no
> code works for both nvdimms types.
>
> But for non-root commands the names/semantics don't match. So, this
> is an attempt to show that on an NVDIMM-N,  only the pass thru command
> is supported.

Ah, ok.  Rather than telling the core about a dsm_mask and a cmd_ioctl
at nvdimm_create() time, it should just be passing the mask of generic
ND commands that the dimm supports.  For NVDIMM-N that mask will just
be (1 << 10) it's up to the nfit driver to manage any ND command to
ACPI _DSM command number translation.
Jerry Hoemann April 12, 2016, 9:41 p.m. UTC | #4
On Mon, Apr 11, 2016 at 05:30:25PM -0700, Dan Williams wrote:
> On Mon, Apr 11, 2016 at 4:58 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> > On Mon, Apr 11, 2016 at 02:43:39PM -0700, Dan Williams wrote:
> >> On Mon, Mar 21, 2016 at 12:37 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> >> > NVDIMM DSMs whose functions map to the Intel Example DSM, can
> >> > be called with the ND_IOCTL_.* ioctl interface.  Those that
> >> > don't map, can only be called with the pass thru command.
> >> >
> >> > Save this indication in struct nvdimm to be passed to
> >> > the sysfs interface.
> >> >
> >>
> >> I'm having trouble understanding the intent of cmd_ioctl.  I don't
> >> want a flag for "supports Intel Example DSM", I want a mask of ND
> >> commands the bus provider knows how to handle in its ->ndctl() entry
> >> point for the given dimm.  The bus provider is free to provide a
> >> translation of ND command to the bus specific command.  It's just an
> >> arbitrary coincidence that the current list of ND commands matches the
> >> Intel ACPI _DSM command format.
> >
> > This is my extension of your earlier RFC patch, so I may
> > have misunderstood your original intent.
> >
> > The commands_show functions prints the listing of commands for that device.
> > There is one version for root, and one version for non-root.
> >
> > For root commands, both dsm spec match on names and semantics, so no
> > code works for both nvdimms types.
> >
> > But for non-root commands the names/semantics don't match. So, this
> > is an attempt to show that on an NVDIMM-N,  only the pass thru command
> > is supported.
> 
> Ah, ok.  Rather than telling the core about a dsm_mask and a cmd_ioctl
> at nvdimm_create() time, it should just be passing the mask of generic
> ND commands that the dimm supports.  For NVDIMM-N that mask will just
> be (1 << 10) it's up to the nfit driver to manage any ND command to
> ACPI _DSM command number translation.

dsm_mask is used in both acpi_nfit_ctl and __nd_ioctl to filter calls
the functions might make.  I think dsm_mask and cmd_ioctl need to be
kept separate, or drop use of filtering by dsm_mask in these two
functions.

Or another way of controlling what commands_show produces?
Dan Williams April 12, 2016, 10:05 p.m. UTC | #5
On Tue, Apr 12, 2016 at 2:41 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> On Mon, Apr 11, 2016 at 05:30:25PM -0700, Dan Williams wrote:
>> On Mon, Apr 11, 2016 at 4:58 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
>> > On Mon, Apr 11, 2016 at 02:43:39PM -0700, Dan Williams wrote:
>> >> On Mon, Mar 21, 2016 at 12:37 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
>> >> > NVDIMM DSMs whose functions map to the Intel Example DSM, can
>> >> > be called with the ND_IOCTL_.* ioctl interface.  Those that
>> >> > don't map, can only be called with the pass thru command.
>> >> >
>> >> > Save this indication in struct nvdimm to be passed to
>> >> > the sysfs interface.
>> >> >
>> >>
>> >> I'm having trouble understanding the intent of cmd_ioctl.  I don't
>> >> want a flag for "supports Intel Example DSM", I want a mask of ND
>> >> commands the bus provider knows how to handle in its ->ndctl() entry
>> >> point for the given dimm.  The bus provider is free to provide a
>> >> translation of ND command to the bus specific command.  It's just an
>> >> arbitrary coincidence that the current list of ND commands matches the
>> >> Intel ACPI _DSM command format.
>> >
>> > This is my extension of your earlier RFC patch, so I may
>> > have misunderstood your original intent.
>> >
>> > The commands_show functions prints the listing of commands for that device.
>> > There is one version for root, and one version for non-root.
>> >
>> > For root commands, both dsm spec match on names and semantics, so no
>> > code works for both nvdimms types.
>> >
>> > But for non-root commands the names/semantics don't match. So, this
>> > is an attempt to show that on an NVDIMM-N,  only the pass thru command
>> > is supported.
>>
>> Ah, ok.  Rather than telling the core about a dsm_mask and a cmd_ioctl
>> at nvdimm_create() time, it should just be passing the mask of generic
>> ND commands that the dimm supports.  For NVDIMM-N that mask will just
>> be (1 << 10) it's up to the nfit driver to manage any ND command to
>> ACPI _DSM command number translation.
>
> dsm_mask is used in both acpi_nfit_ctl and __nd_ioctl to filter calls
> the functions might make.  I think dsm_mask and cmd_ioctl need to be
> kept separate, or drop use of filtering by dsm_mask in these two
> functions.
>
> Or another way of controlling what commands_show produces?

I was thinking that the dsm_mask cease being a pointer in struct
nvdimm and instead be a cmd_mask (of ND function numbers).  struct
nfit_mem would maintain the dsm_mask.  acpi_nfit_ctl is charged with
translating from the nd command to the acpi dsm.  This "just works"
for the existing sysfs interface, and we can export the dsm_mask in
the nfit-specific attributes of the nme device.
Jerry Hoemann April 14, 2016, 10:58 p.m. UTC | #6
On Tue, Apr 12, 2016 at 03:05:47PM -0700, Dan Williams wrote:
> On Tue, Apr 12, 2016 at 2:41 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> > On Mon, Apr 11, 2016 at 05:30:25PM -0700, Dan Williams wrote:
> >> On Mon, Apr 11, 2016 at 4:58 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> >> > On Mon, Apr 11, 2016 at 02:43:39PM -0700, Dan Williams wrote:
> >> >> On Mon, Mar 21, 2016 at 12:37 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> >> >> > NVDIMM DSMs whose functions map to the Intel Example DSM, can
> >> >> > be called with the ND_IOCTL_.* ioctl interface.  Those that
> >> >> > don't map, can only be called with the pass thru command.
> >> >> >
> >> >> > Save this indication in struct nvdimm to be passed to
> >> >> > the sysfs interface.
> >> >> >
> >> >>
> >> >> I'm having trouble understanding the intent of cmd_ioctl.  I don't
> >> >> want a flag for "supports Intel Example DSM", I want a mask of ND
> >> >> commands the bus provider knows how to handle in its ->ndctl() entry
> >> >> point for the given dimm.  The bus provider is free to provide a
> >> >> translation of ND command to the bus specific command.  It's just an
> >> >> arbitrary coincidence that the current list of ND commands matches the
> >> >> Intel ACPI _DSM command format.
> >> >
> >> > This is my extension of your earlier RFC patch, so I may
> >> > have misunderstood your original intent.
> >> >
> >> > The commands_show functions prints the listing of commands for that device.
> >> > There is one version for root, and one version for non-root.
> >> >
> >> > For root commands, both dsm spec match on names and semantics, so no
> >> > code works for both nvdimms types.
> >> >
> >> > But for non-root commands the names/semantics don't match. So, this
> >> > is an attempt to show that on an NVDIMM-N,  only the pass thru command
> >> > is supported.
> >>
> >> Ah, ok.  Rather than telling the core about a dsm_mask and a cmd_ioctl
> >> at nvdimm_create() time, it should just be passing the mask of generic
> >> ND commands that the dimm supports.  For NVDIMM-N that mask will just
> >> be (1 << 10) it's up to the nfit driver to manage any ND command to
> >> ACPI _DSM command number translation.
> >
> > dsm_mask is used in both acpi_nfit_ctl and __nd_ioctl to filter calls
> > the functions might make.  I think dsm_mask and cmd_ioctl need to be
> > kept separate, or drop use of filtering by dsm_mask in these two
> > functions.
> >
> > Or another way of controlling what commands_show produces?
> 
> I was thinking that the dsm_mask cease being a pointer in struct
> nvdimm and instead be a cmd_mask (of ND function numbers).  struct
> nfit_mem would maintain the dsm_mask.  acpi_nfit_ctl is charged with
> translating from the nd command to the acpi dsm.  This "just works"
> for the existing sysfs interface, and we can export the dsm_mask in
> the nfit-specific attributes of the nme device.

Not sure I understand.

Are you suggesting that struct nfit_mem have both a dsm_mask and a cmd_mask
and when nvdimm_create is called we pass just cmd_mask and assign it to
new field u64 cmd_mask (deleting the old pointer to dsm_mask?)

For NVDIMM-N,  the cmd_mask would just be (1<<ND_CMD_CALL) and for the
pre-existent nvdimm it would be (1<<ND_CMD_CALL)|dsm_mask  

This would have acpi_nfit_ctl testing against cmd_mask and __nd_ioctl
testing against dsm_mask.

I don't know how nvdimm_create would get the nd_cmd_mask if its
not determined in acpi_nfit_add_dimm when we determine uuid......
Dan Williams April 15, 2016, 2:49 a.m. UTC | #7
On Thu, Apr 14, 2016 at 3:58 PM, Jerry Hoemann <jerry.hoemann@hpe.com> wrote:
> On Tue, Apr 12, 2016 at 03:05:47PM -0700, Dan Williams wrote:
[..]
>> I was thinking that the dsm_mask cease being a pointer in struct
>> nvdimm and instead be a cmd_mask (of ND function numbers).  struct
>> nfit_mem would maintain the dsm_mask.  acpi_nfit_ctl is charged with
>> translating from the nd command to the acpi dsm.  This "just works"
>> for the existing sysfs interface, and we can export the dsm_mask in
>> the nfit-specific attributes of the nme device.
>
> Not sure I understand.
>
> Are you suggesting that struct nfit_mem have both a dsm_mask and a cmd_mask
> and when nvdimm_create is called we pass just cmd_mask and assign it to
> new field u64 cmd_mask (deleting the old pointer to dsm_mask?)

Yes.

> For NVDIMM-N,  the cmd_mask would just be (1<<ND_CMD_CALL) and for the
> pre-existent nvdimm it would be (1<<ND_CMD_CALL)|dsm_mask
>

Yes.

> This would have acpi_nfit_ctl testing against cmd_mask and __nd_ioctl
> testing against dsm_mask.

__nd_ioctl would only test against cmd_mask.

acpi_nfit_ctl would check if it can translate the cmd to a DSM.  In
the case of ND_CMD_SMART..ND_CMD_VENDOR it translate to the
corresponding DSM (currently a nop for Intel DIMMs and not applicable
to HP DIMMs).  In the case of ND_CMD_CALL it will check the nfit_mem's
dsm_mask to see if the DSM is supported and passes it through.

> I don't know how nvdimm_create would get the nd_cmd_mask if its
> not determined in acpi_nfit_add_dimm when we determine uuid......

nfit_mem will have a cmd_mask and dsm_mask both initialized at
acpi_nfit_add_dimm() time.  At nvdimm_create we just pass
nfit_mem->cmd_mask.
diff mbox

Patch

diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 8d933b3..a35b939 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -61,14 +61,15 @@  struct cmd_family_tbl {
 	int		key_type;	/* Exported handle		*/
 	int		rev;		/* _DSM rev			*/
 	u64		mask;		/* 0 bit excludes underlying func.*/
+	int		cmd_ioctl;	/* supports full cmd ioctl interface */
 };
 
 struct cmd_family_tbl nfit_cmd_family_tbl[] = {
-	{ NFIT_DEV_BUS,		ND_TYPE_BUS,		1, ~0UL},
-	{ NFIT_DEV_DIMM,	ND_TYPE_DIMM_INTEL1,	1, ~0UL},
-	{ NFIT_DEV_DIMM_N_HPE1, ND_TYPE_DIMM_N_HPE1,	1, ~0UL},
-	{ NFIT_DEV_DIMM_N_HPE2, ND_TYPE_DIMM_N_HPE2,	1, ~0UL},
-	{ -1, -1, -1, 0},
+	{ NFIT_DEV_BUS,		ND_TYPE_BUS,		1, ~0UL, 1},
+	{ NFIT_DEV_DIMM,	ND_TYPE_DIMM_INTEL1,	1, ~0UL, 1},
+	{ NFIT_DEV_DIMM_N_HPE1, ND_TYPE_DIMM_N_HPE1,	1, ~0UL, 0},
+	{ NFIT_DEV_DIMM_N_HPE2, ND_TYPE_DIMM_N_HPE2,	1, ~0UL, 0},
+	{ -1, -1, -1, -1, 0},
 };
 
 static u8 nfit_uuid[NFIT_UUID_MAX][16];
@@ -264,8 +265,8 @@  static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
 		in_buf.buffer.length = call_dsm->nd_size_in;
 		uuid = family_to_uuid(call_dsm->nd_family);
 		if (!uuid) {
-			dev_dbg(dev, "%s:%s unsupported uuid\n", dimm_name,
-					cmd_name);
+			dev_dbg(dev, "%s unsupported cmd family: %lld\n",
+					dimm_name, call_dsm->nd_family);
 			return -EINVAL;
 		}
 	}
@@ -1009,7 +1010,8 @@  static int acpi_nfit_sup_func(acpi_handle handle, const u8 *uuid,
 
 static inline void
 to_nfit_uuid_msk(acpi_handle handle, struct cmd_family_tbl *tbl,
-		u8 const **cmd_uuid, unsigned long *cmd_mask)
+		u8 const **cmd_uuid, unsigned long *cmd_mask,
+		int *cmd_ioctl)
 {
 	unsigned long mask = 0;
 	int i;
@@ -1021,6 +1023,7 @@  to_nfit_uuid_msk(acpi_handle handle, struct cmd_family_tbl *tbl,
 		if (acpi_nfit_sup_func(handle, uuid, rev, &mask)) {
 			*cmd_mask = mask & tbl[i].mask;
 			*cmd_uuid = uuid;
+			*cmd_ioctl = tbl[i].cmd_ioctl;
 			break;
 		}
 	}
@@ -1046,7 +1049,8 @@  static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
 	}
 
 	to_nfit_uuid_msk(adev_dimm->handle, nfit_cmd_family_tbl,
-			&nfit_mem->dsm_uuid, &nfit_mem->dsm_mask);
+			&nfit_mem->dsm_uuid, &nfit_mem->dsm_mask,
+			&nfit_mem->cmd_ioctl);
 
 	return 0;
 }
@@ -1083,7 +1087,8 @@  static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
 
 		nvdimm = nvdimm_create(acpi_desc->nvdimm_bus, nfit_mem,
 				acpi_nfit_dimm_attribute_groups,
-				flags, &nfit_mem->dsm_mask);
+				flags, &nfit_mem->dsm_mask,
+				nfit_mem->cmd_ioctl);
 		if (!nvdimm)
 			return -ENOMEM;
 
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index ce80767..24da865 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -253,6 +253,7 @@  static ssize_t commands_show(struct device *dev,
 
 	for_each_set_bit(cmd, &nd_desc->cmd_mask, BITS_PER_LONG)
 		len += sprintf(buf + len, "%s ", nvdimm_bus_cmd_name(cmd));
+	len += sprintf(buf + len, "%s ", nvdimm_cmd_name(ND_CMD_CALL));
 	len += sprintf(buf + len, "\n");
 	return len;
 }
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index c56f882..65614b2 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -274,14 +274,17 @@  EXPORT_SYMBOL_GPL(nvdimm_provider_data);
 static ssize_t commands_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
+	struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev);
 	struct nvdimm *nvdimm = to_nvdimm(dev);
 	int cmd, len = 0;
 
-	if (!nvdimm->dsm_mask)
+	if (!nvdimm->dsm_mask || !nvdimm_bus)
 		return sprintf(buf, "\n");
 
-	for_each_set_bit(cmd, nvdimm->dsm_mask, BITS_PER_LONG)
-		len += sprintf(buf + len, "%s ", nvdimm_cmd_name(cmd));
+	if (nvdimm->cmd_ioctl)
+		for_each_set_bit(cmd, nvdimm->dsm_mask, BITS_PER_LONG)
+			len += sprintf(buf + len, "%s ", nvdimm_cmd_name(cmd));
+	len += sprintf(buf + len, "%s ", nvdimm_cmd_name(ND_CMD_CALL));
 	len += sprintf(buf + len, "\n");
 	return len;
 }
@@ -340,7 +343,7 @@  EXPORT_SYMBOL_GPL(nvdimm_attribute_group);
 
 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
 		const struct attribute_group **groups, unsigned long flags,
-		unsigned long *dsm_mask)
+		unsigned long *dsm_mask, int cmd_ioctl)
 {
 	struct nvdimm *nvdimm = kzalloc(sizeof(*nvdimm), GFP_KERNEL);
 	struct device *dev;
@@ -356,6 +359,7 @@  struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
 	nvdimm->provider_data = provider_data;
 	nvdimm->flags = flags;
 	nvdimm->dsm_mask = dsm_mask;
+	nvdimm->cmd_ioctl = cmd_ioctl;
 	atomic_set(&nvdimm->busy, 0);
 	dev = &nvdimm->dev;
 	dev_set_name(dev, "nmem%d", nvdimm->id);
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 67a1ba0..154986a 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -133,7 +133,7 @@  const char *nvdimm_name(struct nvdimm *nvdimm);
 void *nvdimm_provider_data(struct nvdimm *nvdimm);
 struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
 		const struct attribute_group **groups, unsigned long flags,
-		unsigned long *dsm_mask);
+		unsigned long *dsm_mask, int cmd_ioctl);
 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
 u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,