Re: [PATCH v4 14/25] nvdimm/ocxl: Add support for Admin commands

2020-04-01 Thread Dan Williams
On Sun, Mar 29, 2020 at 10:23 PM Alastair D'Silva  wrote:
>
> Admin commands for these devices are the primary means of interacting
> with the device controller to provide functionality beyond the load/store
> capabilities offered via the NPU.
>
> For example, SMART data, firmware update, and device error logs are
> implemented via admin commands.
>
> This patch requests the metadata required to issue admin commands, as well
> as some helper functions to construct and check the completion of the
> commands.
>
> Signed-off-by: Alastair D'Silva 
> ---
>  drivers/nvdimm/ocxl/main.c  |  65 ++
>  drivers/nvdimm/ocxl/ocxlpmem.h  |  50 -
>  drivers/nvdimm/ocxl/ocxlpmem_internal.c | 261 
>  3 files changed, 375 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/nvdimm/ocxl/main.c b/drivers/nvdimm/ocxl/main.c
> index be76acd33d74..8db573036423 100644
> --- a/drivers/nvdimm/ocxl/main.c
> +++ b/drivers/nvdimm/ocxl/main.c
> @@ -217,6 +217,58 @@ static int register_lpc_mem(struct ocxlpmem *ocxlpmem)
> return 0;
>  }
>
> +/**
> + * extract_command_metadata() - Extract command data from MMIO & save it for 
> further use
> + * @ocxlpmem: the device metadata
> + * @offset: The base address of the command data structures (address of 
> CREQO)
> + * @command_metadata: A pointer to the command metadata to populate
> + * Return: 0 on success, negative on failure
> + */
> +static int extract_command_metadata(struct ocxlpmem *ocxlpmem, u32 offset,
> +   struct command_metadata *command_metadata)

How about "struct ocxlpmem *ocp" throughout all these patches? The
full duplication of the type name as the local variable name makes
this look like non-idiomatic Linux code to me. It had not quite hit me
until I saw "struct command_metadata *command_metadata" that just
strikes me as too literal and the person that gets to maintain this
code later will appreciate a smaller amount of typing.

Also, is it really the case that the layout of the admin command
metadata needs to be programmatically determined at runtime? I would
expect it to be a static command definition in the spec.


> +{
> +   int rc;
> +   u64 tmp;
> +
> +   rc = ocxl_global_mmio_read64(ocxlpmem->ocxl_afu, offset,
> +OCXL_LITTLE_ENDIAN, &tmp);
> +   if (rc)
> +   return rc;
> +
> +   command_metadata->request_offset = tmp >> 32;
> +   command_metadata->response_offset = tmp & 0x;
> +
> +   rc = ocxl_global_mmio_read64(ocxlpmem->ocxl_afu, offset + 8,
> +OCXL_LITTLE_ENDIAN, &tmp);
> +   if (rc)
> +   return rc;
> +
> +   command_metadata->data_offset = tmp >> 32;
> +   command_metadata->data_size = tmp & 0x;
> +
> +   command_metadata->id = 0;
> +
> +   return 0;
> +}
> +
> +/**
> + * setup_command_metadata() - Set up the command metadata
> + * @ocxlpmem: the device metadata
> + */
> +static int setup_command_metadata(struct ocxlpmem *ocxlpmem)
> +{
> +   int rc;
> +
> +   mutex_init(&ocxlpmem->admin_command.lock);
> +
> +   rc = extract_command_metadata(ocxlpmem, GLOBAL_MMIO_ACMA_CREQO,
> + &ocxlpmem->admin_command);
> +   if (rc)
> +   return rc;
> +
> +   return 0;
> +}
> +
>  /**
>   * allocate_minor() - Allocate a minor number to use for an OpenCAPI pmem 
> device
>   * @ocxlpmem: the device metadata
> @@ -421,6 +473,14 @@ static int probe(struct pci_dev *pdev, const struct 
> pci_device_id *ent)
>
> ocxlpmem->pdev = pci_dev_get(pdev);
>
> +   ocxlpmem->timeouts[ADMIN_COMMAND_ERRLOG] = 2000; // ms
> +   ocxlpmem->timeouts[ADMIN_COMMAND_HEARTBEAT] = 100; // ms
> +   ocxlpmem->timeouts[ADMIN_COMMAND_SMART] = 100; // ms
> +   ocxlpmem->timeouts[ADMIN_COMMAND_CONTROLLER_DUMP] = 1000; // ms
> +   ocxlpmem->timeouts[ADMIN_COMMAND_CONTROLLER_STATS] = 100; // ms
> +   ocxlpmem->timeouts[ADMIN_COMMAND_SHUTDOWN] = 1000; // ms
> +   ocxlpmem->timeouts[ADMIN_COMMAND_FW_UPDATE] = 16000; // ms
> +
> pci_set_drvdata(pdev, ocxlpmem);
>
> ocxlpmem->ocxl_fn = ocxl_function_open(pdev);
> @@ -467,6 +527,11 @@ static int probe(struct pci_dev *pdev, const struct 
> pci_device_id *ent)
> goto err;
> }
>
> +   if (setup_command_metadata(ocxlpmem)) {
> +   dev_err(&pdev->dev, "Could not read command metadata\n");
> +   goto err;
> +   }
> +
> elapsed = 0;
> timeout = ocxlpmem->readiness_timeout +
>   ocxlpmem->memory_available_timeout;
> diff --git a/drivers/nvdimm/ocxl/ocxlpmem.h b/drivers/nvdimm/ocxl/ocxlpmem.h
> index 3eadbe19f6d0..b72b3f909fc3 100644
> --- a/drivers/nvdimm/ocxl/ocxlpmem.h
> +++ b/drivers/nvdimm/ocxl/ocxlpmem.h
> @@ -7,6 +7,7 @@
>  #include 
>
>  #define LABEL_AREA_SIZEBIT_ULL(PA_SECTION_SHIFT)
> +#define DEFAU

[PATCH v4 14/25] nvdimm/ocxl: Add support for Admin commands

2020-03-29 Thread Alastair D'Silva
Admin commands for these devices are the primary means of interacting
with the device controller to provide functionality beyond the load/store
capabilities offered via the NPU.

For example, SMART data, firmware update, and device error logs are
implemented via admin commands.

This patch requests the metadata required to issue admin commands, as well
as some helper functions to construct and check the completion of the
commands.

Signed-off-by: Alastair D'Silva 
---
 drivers/nvdimm/ocxl/main.c  |  65 ++
 drivers/nvdimm/ocxl/ocxlpmem.h  |  50 -
 drivers/nvdimm/ocxl/ocxlpmem_internal.c | 261 
 3 files changed, 375 insertions(+), 1 deletion(-)

diff --git a/drivers/nvdimm/ocxl/main.c b/drivers/nvdimm/ocxl/main.c
index be76acd33d74..8db573036423 100644
--- a/drivers/nvdimm/ocxl/main.c
+++ b/drivers/nvdimm/ocxl/main.c
@@ -217,6 +217,58 @@ static int register_lpc_mem(struct ocxlpmem *ocxlpmem)
return 0;
 }
 
+/**
+ * extract_command_metadata() - Extract command data from MMIO & save it for 
further use
+ * @ocxlpmem: the device metadata
+ * @offset: The base address of the command data structures (address of CREQO)
+ * @command_metadata: A pointer to the command metadata to populate
+ * Return: 0 on success, negative on failure
+ */
+static int extract_command_metadata(struct ocxlpmem *ocxlpmem, u32 offset,
+   struct command_metadata *command_metadata)
+{
+   int rc;
+   u64 tmp;
+
+   rc = ocxl_global_mmio_read64(ocxlpmem->ocxl_afu, offset,
+OCXL_LITTLE_ENDIAN, &tmp);
+   if (rc)
+   return rc;
+
+   command_metadata->request_offset = tmp >> 32;
+   command_metadata->response_offset = tmp & 0x;
+
+   rc = ocxl_global_mmio_read64(ocxlpmem->ocxl_afu, offset + 8,
+OCXL_LITTLE_ENDIAN, &tmp);
+   if (rc)
+   return rc;
+
+   command_metadata->data_offset = tmp >> 32;
+   command_metadata->data_size = tmp & 0x;
+
+   command_metadata->id = 0;
+
+   return 0;
+}
+
+/**
+ * setup_command_metadata() - Set up the command metadata
+ * @ocxlpmem: the device metadata
+ */
+static int setup_command_metadata(struct ocxlpmem *ocxlpmem)
+{
+   int rc;
+
+   mutex_init(&ocxlpmem->admin_command.lock);
+
+   rc = extract_command_metadata(ocxlpmem, GLOBAL_MMIO_ACMA_CREQO,
+ &ocxlpmem->admin_command);
+   if (rc)
+   return rc;
+
+   return 0;
+}
+
 /**
  * allocate_minor() - Allocate a minor number to use for an OpenCAPI pmem 
device
  * @ocxlpmem: the device metadata
@@ -421,6 +473,14 @@ static int probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
 
ocxlpmem->pdev = pci_dev_get(pdev);
 
+   ocxlpmem->timeouts[ADMIN_COMMAND_ERRLOG] = 2000; // ms
+   ocxlpmem->timeouts[ADMIN_COMMAND_HEARTBEAT] = 100; // ms
+   ocxlpmem->timeouts[ADMIN_COMMAND_SMART] = 100; // ms
+   ocxlpmem->timeouts[ADMIN_COMMAND_CONTROLLER_DUMP] = 1000; // ms
+   ocxlpmem->timeouts[ADMIN_COMMAND_CONTROLLER_STATS] = 100; // ms
+   ocxlpmem->timeouts[ADMIN_COMMAND_SHUTDOWN] = 1000; // ms
+   ocxlpmem->timeouts[ADMIN_COMMAND_FW_UPDATE] = 16000; // ms
+
pci_set_drvdata(pdev, ocxlpmem);
 
ocxlpmem->ocxl_fn = ocxl_function_open(pdev);
@@ -467,6 +527,11 @@ static int probe(struct pci_dev *pdev, const struct 
pci_device_id *ent)
goto err;
}
 
+   if (setup_command_metadata(ocxlpmem)) {
+   dev_err(&pdev->dev, "Could not read command metadata\n");
+   goto err;
+   }
+
elapsed = 0;
timeout = ocxlpmem->readiness_timeout +
  ocxlpmem->memory_available_timeout;
diff --git a/drivers/nvdimm/ocxl/ocxlpmem.h b/drivers/nvdimm/ocxl/ocxlpmem.h
index 3eadbe19f6d0..b72b3f909fc3 100644
--- a/drivers/nvdimm/ocxl/ocxlpmem.h
+++ b/drivers/nvdimm/ocxl/ocxlpmem.h
@@ -7,6 +7,7 @@
 #include 
 
 #define LABEL_AREA_SIZEBIT_ULL(PA_SECTION_SHIFT)
+#define DEFAULT_TIMEOUT 100
 
 #define GLOBAL_MMIO_CHI0x000
 #define GLOBAL_MMIO_CHIC   0x008
@@ -57,6 +58,7 @@
 #define GLOBAL_MMIO_HCI_CONTROLLER_DUMP_COLLECTED  BIT_ULL(5) // CDC
 #define GLOBAL_MMIO_HCI_REQ_HEALTH_PERFBIT_ULL(6) // 
CHPD
 
+// must be maintained with admin_command_names in ocxlpmem_internal.c
 #define ADMIN_COMMAND_HEARTBEAT0x00u
 #define ADMIN_COMMAND_SHUTDOWN 0x01u
 #define ADMIN_COMMAND_FW_UPDATE0x02u
@@ -68,6 +70,13 @@
 #define ADMIN_COMMAND_CMD_CAPS 0x08u
 #define ADMIN_COMMAND_MAX  0x08u
 
+#define NS_COMMAND_SECURE_ERASE0x20ull
+
+#define NS_RESPONSE_SECURE_ERASE_ACCESSIBLE_SUCCESS 0x20
+#define NS_RESPONSE_SECURE_ERASE_ACCESSIBLE_ATTEMPTED 0x28
+#define NS_RESPONSE_SECURE_ERASE_DEFECTIVE_SUCCESS 0x30
+#define NS_RESPONSE_SECURE_ERASE_DE