--- zzzz-none-000/linux-4.4.271/drivers/crypto/qce/core.c 2021-06-03 06:22:09.000000000 +0000 +++ dakota-7530ac-750/linux-4.4.271/drivers/crypto/qce/core.c 2023-01-11 09:25:41.000000000 +0000 @@ -14,13 +14,16 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include "core.h" #include "cipher.h" #include "sha.h" @@ -28,6 +31,11 @@ #define QCE_MAJOR_VERSION5 0x05 #define QCE_QUEUE_LENGTH 1 +bool use_fixed_key = false; + +#define to_qce_obj(x) container_of(x, struct qce_device, kobj) +#define to_qce_attr(x) container_of(x, struct qce_attribute, attr) + static const struct qce_algo_ops *qce_ops[] = { &ablkcipher_ops, &ahash_ops, @@ -139,12 +147,63 @@ static int qce_async_request_enqueue(struct qce_device *qce, struct crypto_async_request *req) { + struct qce_stat *pstat; + const char *cra_drv_name; + int ablk_flags = 0; + struct qce_cipher_reqctx *rctx; + + pstat = &qce->qce_stat; + if (req) { + cra_drv_name = crypto_tfm_alg_driver_name(req->tfm); + rctx = ablkcipher_request_ctx((void *)req); + if (rctx) + ablk_flags = rctx->flags; + + if (!strcmp(cra_drv_name, "sha1-qce")) + pstat->sha1_digest++; + else if (!strcmp(cra_drv_name, "sha256-qce")) + pstat->sha256_digest++; + else if (!strcmp(cra_drv_name, "hmac-sha256-qce")) + pstat->sha256_hmac_digest++; + else if (!strcmp(cra_drv_name, "hmac-sha1-qce")) + pstat->sha1_hmac_digest++; + else if (IS_AES(ablk_flags) && (ablk_flags & QCE_ENCRYPT)) + pstat->ablk_cipher_aes_enc++; + else if (IS_AES(ablk_flags) && (ablk_flags & QCE_DECRYPT)) + pstat->ablk_cipher_aes_dec++; + else if (IS_DES(ablk_flags) && (ablk_flags & QCE_ENCRYPT)) + pstat->ablk_cipher_des_enc++; + else if (IS_DES(ablk_flags) && (ablk_flags & QCE_DECRYPT)) + pstat->ablk_cipher_des_dec++; + else if (IS_3DES(ablk_flags) && (ablk_flags & QCE_ENCRYPT)) + pstat->ablk_cipher_3des_enc++; + else if (IS_3DES(ablk_flags) && (ablk_flags & QCE_DECRYPT)) + pstat->ablk_cipher_3des_dec++; + } + return qce_handle_queue(qce, req); } static void qce_async_request_done(struct qce_device *qce, int ret) { + u32 type; + struct qce_stat *pstat; + qce->result = ret; + pstat = &qce->qce_stat; + if (qce->req) { + type = crypto_tfm_alg_type(qce->req->tfm); + + if (ret && (type == CRYPTO_ALG_TYPE_AHASH)) + pstat->ahash_op_fail++; + if (!ret && (type == CRYPTO_ALG_TYPE_AHASH)) + pstat->ahash_op_success++; + + if (ret && (type == CRYPTO_ALG_TYPE_ABLKCIPHER)) + pstat->ablk_cipher_op_fail++; + if (!ret && (type == CRYPTO_ALG_TYPE_ABLKCIPHER)) + pstat->ablk_cipher_op_success++; + } tasklet_schedule(&qce->done_tasklet); } @@ -170,6 +229,347 @@ return 0; } +static int qce_disp_stats(struct qce_device *qce) +{ + struct qce_stat *pstat; + char *read_buf; + int len; + + pstat = &qce->qce_stat; + read_buf = qce->qce_debug_read_buf; + len = scnprintf(read_buf, DEBUG_MAX_RW_BUF - 1, + "\nQualcomm crypto accelerator Statistics\n"); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER AES encryption : %llu\n", + pstat->ablk_cipher_aes_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER AES decryption : %llu\n", + pstat->ablk_cipher_aes_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER DES encryption : %llu\n", + pstat->ablk_cipher_des_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER DES decryption : %llu\n", + pstat->ablk_cipher_des_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER 3DES encryption : %llu\n", + pstat->ablk_cipher_3des_enc); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER 3DES decryption : %llu\n", + pstat->ablk_cipher_3des_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER operation success : %llu\n", + pstat->ablk_cipher_op_success); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " ABLK CIPHER operation fail : %llu\n", + pstat->ablk_cipher_op_fail); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + "\n"); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA1-AES encryption : %llu\n", + pstat->aead_sha1_aes_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA1-AES decryption : %llu\n", + pstat->aead_sha1_aes_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA1-DES encryption : %llu\n", + pstat->aead_sha1_des_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA1-DES decryption : %llu\n", + pstat->aead_sha1_des_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA1-3DES encryption : %llu\n", + pstat->aead_sha1_3des_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA1-3DES decryption : %llu\n", + pstat->aead_sha1_3des_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA256-AES encryption : %llu\n", + pstat->aead_sha256_aes_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA256-AES decryption : %llu\n", + pstat->aead_sha256_aes_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA256-DES encryption : %llu\n", + pstat->aead_sha256_des_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA256-DES decryption : %llu\n", + pstat->aead_sha256_des_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA256-3DES encryption : %llu\n", + pstat->aead_sha256_3des_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD SHA256-3DES decryption : %llu\n", + pstat->aead_sha256_3des_dec); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD CCM-AES encryption : %llu\n", + pstat->aead_ccm_aes_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD CCM-AES decryption : %llu\n", + pstat->aead_ccm_aes_dec); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD RFC4309-CCM-AES encryption : %llu\n", + pstat->aead_rfc4309_ccm_aes_enc); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD RFC4309-CCM-AES decryption : %llu\n", + pstat->aead_rfc4309_ccm_aes_dec); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD operation success : %llu\n", + pstat->aead_op_success); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD operation fail : %llu\n", + pstat->aead_op_fail); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AEAD bad message : %llu\n", + pstat->aead_bad_msg); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + "\n"); + + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AHASH SHA1 digest : %llu\n", + pstat->sha1_digest); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AHASH SHA256 digest : %llu\n", + pstat->sha256_digest); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AHASH SHA1 HMAC digest : %llu\n", + pstat->sha1_hmac_digest); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AHASH SHA256 HMAC digest : %llu\n", + pstat->sha256_hmac_digest); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AHASH operation success : %llu\n", + pstat->ahash_op_success); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + " AHASH operation fail : %llu\n", + pstat->ahash_op_fail); + len += scnprintf(read_buf + len, DEBUG_MAX_RW_BUF - len - 1, + "\n"); + + return len; +} + +static int qce_debug_stats_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t qce_debug_stats_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct qce_device *qce = (struct qce_device *)file->private_data; + int len; + + if (!qce) + return 0; + len = qce_disp_stats(qce); + + return simple_read_from_buffer((void __user *)buf, count, + ppos, (void *)qce->qce_debug_read_buf, len); +} + +static ssize_t qce_debug_stats_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct qce_device *qce = (struct qce_device *)file->private_data; + + if (!qce) + return 0; + memset((char *)&qce->qce_stat, 0, sizeof(struct qce_stat)); + return count; +} + +static const struct file_operations qce_debug_stats_ops = { + .open = qce_debug_stats_open, + .read = qce_debug_stats_read, + .write = qce_debug_stats_write, +}; + +static int qce_debug_init(struct qce_device *qce) +{ + int rc; + char name[DEBUG_MAX_FNAME]; + struct dentry *qce_dent; + struct dentry *stats_dent; + + qce_dent = qce->qce_debug_dent; + qce_dent = debugfs_create_dir("qce", NULL); + if (IS_ERR(qce_dent)) { + pr_err("qce debugfs_create_dir fail, error %ld\n", + PTR_ERR(qce_dent)); + return PTR_ERR(qce_dent); + } + + snprintf(name, DEBUG_MAX_FNAME - 1, "stats"); + stats_dent = debugfs_create_file(name, 0644, qce_dent, + qce, &qce_debug_stats_ops); + if (stats_dent == NULL) { + pr_err("qce debugfs_create_file fail, error %ld\n", + PTR_ERR(stats_dent)); + rc = PTR_ERR(stats_dent); + goto err; + } + qce->qce_debug_dent = qce_dent; + return 0; +err: + debugfs_remove_recursive(qce_dent); + return rc; +} + +/* a custom attribute that works just for a struct qce_sysfs*/ +struct qce_attribute { + struct attribute attr; + ssize_t (*show)(struct qce_device *qce, struct qce_attribute *attr, + char *buf); + ssize_t (*store)(struct qce_device *qce, struct qce_attribute *attr, + const char *buf, size_t count); +}; + +/* + * The default show function that must be passed to sysfs. This will be + * called by sysfs for whenever a show function is called by the user on a + * sysfs file associated with the kobjects we have registered. We need to + * transpose back from a "default" kobject to our custom struct qce_sysfs and + * then call the show function for that specific object. + */ +static ssize_t qce_attr_show(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + struct qce_attribute *attribute; + struct qce_device *qce; + attribute = to_qce_attr(attr); + qce = to_qce_obj(kobj); + if (!attribute->show) + return -EIO; + return attribute->show(qce, attribute, buf); +} + +/* + * Just like the default show function above, but this one is for when the + * sysfs "store" is requested (when a value is written to a file. + */ +static ssize_t qce_attr_store(struct kobject *kobj,struct attribute *attr, + const char *buf, size_t len) +{ + struct qce_attribute *attribute; + struct qce_device *qce; + attribute = to_qce_attr(attr); + qce = to_qce_obj(kobj); + if (!attribute->store) + return -EIO; + return attribute->store(qce, attribute, buf, len); +} + +/*Our custom sysfs_ops that we will associate with our ktype later on*/ +static struct sysfs_ops qce_sysfs_ops = { + .show = qce_attr_show, + .store = qce_attr_store, +}; + +/* The "fixed_sec_key" file where the .fixed_key variable is read from + * and written to + */ +static ssize_t qce_show(struct qce_device *qce, struct qce_attribute *attr, + char *buf) +{ + return snprintf(buf, sizeof(int), "%d\n", qce->fixed_key); +} + +static ssize_t qce_store(struct qce_device *qce, struct qce_attribute *attr, + const char *buf, size_t count) +{ + sscanf(buf, "%du", &qce->fixed_key); + if (qce->fixed_key == 1) + use_fixed_key = true; + else if (qce->fixed_key == 0) { + if (qce_sec_release_xpu_prot()) + pr_err("qce XPU proctection release fail\n"); + use_fixed_key = false; + } + + return count; +} + +static struct qce_attribute qce_attribute = __ATTR(fixed_sec_key, 0644, qce_show, + qce_store); + +/* + * Create a group of attributes so that we can create and destory them all + * at once. + */ +static struct attribute *qce_default_attrs[] = { + &qce_attribute.attr, + NULL, +}; + +/* + * Our own ktype for our kobjects. Here we specify our sysfs ops, the + * release function, and the set of default attributes we want created + * whenever a kobject of this type is registered with the kernel. + */ + +static struct kobj_type qce_ktype = { + .sysfs_ops = &qce_sysfs_ops, + .default_attrs = qce_default_attrs, +}; + +static int create_qce_obj(struct qce_device *qce, char *name) +{ + int ret; + + qce->fixed_key = 0; + + /* As we have a kset for this kobject, we need to set + * it before calling the kobject core. + */ + qce->kobj.kset = qce->parent_kset; + + /* + * Initialize and add the kobject to the kernel. All the default files + * will be created here. As we have already specified a kset for this + * kobject, we don't have to set a parent for the kobject, the kobject + * will be placed beneath that kset automatically. + */ + ret = kobject_init_and_add(&qce->kobj, &qce_ktype, NULL, "%s", name); + if (ret) + return -EINVAL; + + return 0; +} + +static int qce_sysfs_init(struct qce_device *qce) +{ + int ret; + /* + * Create a simple kset with the name of "crypto", + * located under /sys/kernel/ + */ + qce->parent_kset = kset_create_and_add("crypto", NULL, kernel_kobj); + if (!qce->parent_kset) { + pr_err("Error in creating sys entry crypto\n"); + return -ENOMEM; + } + /* Create an object and register it with our kset*/ + ret = create_qce_obj(qce, "qce"); + if(ret) + return -EINVAL; + + return 0; +} + static int qce_crypto_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -185,6 +585,9 @@ platform_set_drvdata(pdev, qce); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENOMEM; + qce->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(qce->base)) return PTR_ERR(qce->base); @@ -193,6 +596,14 @@ if (ret < 0) return ret; + if (device_property_read_bool(dev, "qce,use_fixed_hw_key")) + use_fixed_key = true; + + if (device_property_read_bool(dev, "qce,cmd_desc_support")) { + qce->qce_cmd_desc_enable = true; + qce->base_dma = phys_to_dma(dev, (phys_addr_t)res->start); + } + qce->core = devm_clk_get(qce->dev, "core"); if (IS_ERR(qce->core)) return PTR_ERR(qce->core); @@ -237,6 +648,13 @@ if (ret) goto err_dma; + ret = qce_debug_init(qce); + if (ret) + goto err_dma; + + ret = qce_sysfs_init(qce); + if (ret) + goto err_dma; return 0; err_dma: @@ -260,6 +678,9 @@ clk_disable_unprepare(qce->bus); clk_disable_unprepare(qce->iface); clk_disable_unprepare(qce->core); + debugfs_remove_recursive(qce->qce_debug_dent); + kobject_put(&qce->kobj); + kset_unregister(qce->parent_kset); return 0; }