crypto/nx: Get NX capabilities for GZIP coprocessor type
authorHaren Myneni <haren@linux.ibm.com>
Thu, 17 Jun 2021 20:38:36 +0000 (13:38 -0700)
committerMichael Ellerman <mpe@ellerman.id.au>
Sun, 20 Jun 2021 11:58:58 +0000 (21:58 +1000)
The hypervisor provides different NX capabilities that it
supports. These capabilities such as recommended minimum
compression / decompression lengths and the maximum request
buffer size in bytes are used to define the user space NX
request.

NX will reject the request if the buffer size is more than
the maximum buffer size. Whereas compression / decompression
lengths are recommended values for better performance.

Changes to get NX overall capabilities which points to the
specific features that the hypervisor supports. Then retrieve
the capabilities for the specific feature (available only
for NXGZIP).

Signed-off-by: Haren Myneni <haren@linux.ibm.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Acked-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/f2b6a1fb8b6112595a73d81c67a35af4e7f5d0a3.camel@linux.ibm.com
drivers/crypto/nx/nx-common-pseries.c

index cc8dd30..9fc2abb 100644 (file)
@@ -9,6 +9,8 @@
  */
 
 #include <asm/vio.h>
+#include <asm/hvcall.h>
+#include <asm/vas.h>
 
 #include "nx-842.h"
 #include "nx_csbcpb.h" /* struct nx_csbcpb */
@@ -19,6 +21,29 @@ MODULE_DESCRIPTION("842 H/W Compression driver for IBM Power processors");
 MODULE_ALIAS_CRYPTO("842");
 MODULE_ALIAS_CRYPTO("842-nx");
 
+/*
+ * Coprocessor type specific capabilities from the hypervisor.
+ */
+struct hv_nx_cop_caps {
+       __be64  descriptor;
+       __be64  req_max_processed_len;  /* Max bytes in one GZIP request */
+       __be64  min_compress_len;       /* Min compression size in bytes */
+       __be64  min_decompress_len;     /* Min decompression size in bytes */
+} __packed __aligned(0x1000);
+
+/*
+ * Coprocessor type specific capabilities.
+ */
+struct nx_cop_caps {
+       u64     descriptor;
+       u64     req_max_processed_len;  /* Max bytes in one GZIP request */
+       u64     min_compress_len;       /* Min compression in bytes */
+       u64     min_decompress_len;     /* Min decompression in bytes */
+};
+
+static u64 caps_feat;
+static struct nx_cop_caps nx_cop_caps;
+
 static struct nx842_constraints nx842_pseries_constraints = {
        .alignment =    DDE_BUFFER_ALIGN,
        .multiple =     DDE_BUFFER_LAST_MULT,
@@ -1065,6 +1090,64 @@ static void nx842_remove(struct vio_dev *viodev)
        kfree(old_devdata);
 }
 
+/*
+ * Get NX capabilities from the hypervisor.
+ * Only NXGZIP capabilities are provided by the hypersvisor right
+ * now and these values are available to user space with sysfs.
+ */
+static void __init nxcop_get_capabilities(void)
+{
+       struct hv_vas_all_caps *hv_caps;
+       struct hv_nx_cop_caps *hv_nxc;
+       int rc;
+
+       hv_caps = kmalloc(sizeof(*hv_caps), GFP_KERNEL);
+       if (!hv_caps)
+               return;
+       /*
+        * Get NX overall capabilities with feature type=0
+        */
+       rc = h_query_vas_capabilities(H_QUERY_NX_CAPABILITIES, 0,
+                                         (u64)virt_to_phys(hv_caps));
+       if (rc)
+               goto out;
+
+       caps_feat = be64_to_cpu(hv_caps->feat_type);
+       /*
+        * NX-GZIP feature available
+        */
+       if (caps_feat & VAS_NX_GZIP_FEAT_BIT) {
+               hv_nxc = kmalloc(sizeof(*hv_nxc), GFP_KERNEL);
+               if (!hv_nxc)
+                       goto out;
+               /*
+                * Get capabilities for NX-GZIP feature
+                */
+               rc = h_query_vas_capabilities(H_QUERY_NX_CAPABILITIES,
+                                                 VAS_NX_GZIP_FEAT,
+                                                 (u64)virt_to_phys(hv_nxc));
+       } else {
+               pr_err("NX-GZIP feature is not available\n");
+               rc = -EINVAL;
+       }
+
+       if (!rc) {
+               nx_cop_caps.descriptor = be64_to_cpu(hv_nxc->descriptor);
+               nx_cop_caps.req_max_processed_len =
+                               be64_to_cpu(hv_nxc->req_max_processed_len);
+               nx_cop_caps.min_compress_len =
+                               be64_to_cpu(hv_nxc->min_compress_len);
+               nx_cop_caps.min_decompress_len =
+                               be64_to_cpu(hv_nxc->min_decompress_len);
+       } else {
+               caps_feat = 0;
+       }
+
+       kfree(hv_nxc);
+out:
+       kfree(hv_caps);
+}
+
 static const struct vio_device_id nx842_vio_driver_ids[] = {
        {"ibm,compression-v1", "ibm,compression"},
        {"", ""},
@@ -1092,6 +1175,10 @@ static int __init nx842_pseries_init(void)
                return -ENOMEM;
 
        RCU_INIT_POINTER(devdata, new_devdata);
+       /*
+        * Get NX capabilities from the hypervisor.
+        */
+       nxcop_get_capabilities();
 
        ret = vio_register_driver(&nx842_vio_driver);
        if (ret) {