Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: hisilicon - register zip engine to uacce

Register qm to uacce framework for user crypto driver

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhou Wang <wangzhou1@hisilicon.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Zhangfei Gao and committed by
Herbert Xu
9e00df71 18bead70

+283 -8
+233 -6
drivers/crypto/hisilicon/qm.c
··· 9 9 #include <linux/log2.h> 10 10 #include <linux/seq_file.h> 11 11 #include <linux/slab.h> 12 + #include <linux/uacce.h> 13 + #include <linux/uaccess.h> 14 + #include <uapi/misc/uacce/hisi_qm.h> 12 15 #include "qm.h" 13 16 14 17 /* eq/aeq irq enable */ ··· 469 466 470 467 static void qm_poll_qp(struct hisi_qp *qp, struct hisi_qm *qm) 471 468 { 472 - struct qm_cqe *cqe = qp->cqe + qp->qp_status.cq_head; 469 + if (qp->event_cb) { 470 + qp->event_cb(qp); 471 + return; 472 + } 473 473 474 474 if (qp->req_cb) { 475 + struct qm_cqe *cqe = qp->cqe + qp->qp_status.cq_head; 476 + 475 477 while (QM_CQE_PHASE(cqe) == qp->qp_status.cqc_phase) { 476 478 dma_rmb(); 477 479 qp->req_cb(qp, qp->sqe + qm->sqe_size * ··· 1281 1273 * @qp: The qp we want to start to run. 1282 1274 * @arg: Accelerator specific argument. 1283 1275 * 1284 - * After this function, qp can receive request from user. Return qp_id if 1276 + * After this function, qp can receive request from user. Return 0 if 1285 1277 * successful, Return -EBUSY if failed. 1286 1278 */ 1287 1279 int hisi_qm_start_qp(struct hisi_qp *qp, unsigned long arg) ··· 1326 1318 1327 1319 dev_dbg(dev, "queue %d started\n", qp_id); 1328 1320 1329 - return qp_id; 1321 + return 0; 1330 1322 } 1331 1323 EXPORT_SYMBOL_GPL(hisi_qm_start_qp); 1332 1324 ··· 1407 1399 } 1408 1400 } 1409 1401 1402 + static void qm_qp_event_notifier(struct hisi_qp *qp) 1403 + { 1404 + wake_up_interruptible(&qp->uacce_q->wait); 1405 + } 1406 + 1407 + static int hisi_qm_get_available_instances(struct uacce_device *uacce) 1408 + { 1409 + int i, ret; 1410 + struct hisi_qm *qm = uacce->priv; 1411 + 1412 + read_lock(&qm->qps_lock); 1413 + for (i = 0, ret = 0; i < qm->qp_num; i++) 1414 + if (!qm->qp_array[i]) 1415 + ret++; 1416 + read_unlock(&qm->qps_lock); 1417 + 1418 + return ret; 1419 + } 1420 + 1421 + static int hisi_qm_uacce_get_queue(struct uacce_device *uacce, 1422 + unsigned long arg, 1423 + struct uacce_queue *q) 1424 + { 1425 + struct hisi_qm *qm = uacce->priv; 1426 + struct hisi_qp *qp; 1427 + u8 alg_type = 0; 1428 + 1429 + qp = hisi_qm_create_qp(qm, alg_type); 1430 + if (IS_ERR(qp)) 1431 + return PTR_ERR(qp); 1432 + 1433 + q->priv = qp; 1434 + q->uacce = uacce; 1435 + qp->uacce_q = q; 1436 + qp->event_cb = qm_qp_event_notifier; 1437 + qp->pasid = arg; 1438 + 1439 + return 0; 1440 + } 1441 + 1442 + static void hisi_qm_uacce_put_queue(struct uacce_queue *q) 1443 + { 1444 + struct hisi_qp *qp = q->priv; 1445 + 1446 + hisi_qm_cache_wb(qp->qm); 1447 + hisi_qm_release_qp(qp); 1448 + } 1449 + 1450 + /* map sq/cq/doorbell to user space */ 1451 + static int hisi_qm_uacce_mmap(struct uacce_queue *q, 1452 + struct vm_area_struct *vma, 1453 + struct uacce_qfile_region *qfr) 1454 + { 1455 + struct hisi_qp *qp = q->priv; 1456 + struct hisi_qm *qm = qp->qm; 1457 + size_t sz = vma->vm_end - vma->vm_start; 1458 + struct pci_dev *pdev = qm->pdev; 1459 + struct device *dev = &pdev->dev; 1460 + unsigned long vm_pgoff; 1461 + int ret; 1462 + 1463 + switch (qfr->type) { 1464 + case UACCE_QFRT_MMIO: 1465 + if (qm->ver == QM_HW_V2) { 1466 + if (sz > PAGE_SIZE * (QM_DOORBELL_PAGE_NR + 1467 + QM_DOORBELL_SQ_CQ_BASE_V2 / PAGE_SIZE)) 1468 + return -EINVAL; 1469 + } else { 1470 + if (sz > PAGE_SIZE * QM_DOORBELL_PAGE_NR) 1471 + return -EINVAL; 1472 + } 1473 + 1474 + vma->vm_flags |= VM_IO; 1475 + 1476 + return remap_pfn_range(vma, vma->vm_start, 1477 + qm->phys_base >> PAGE_SHIFT, 1478 + sz, pgprot_noncached(vma->vm_page_prot)); 1479 + case UACCE_QFRT_DUS: 1480 + if (sz != qp->qdma.size) 1481 + return -EINVAL; 1482 + 1483 + /* 1484 + * dma_mmap_coherent() requires vm_pgoff as 0 1485 + * restore vm_pfoff to initial value for mmap() 1486 + */ 1487 + vm_pgoff = vma->vm_pgoff; 1488 + vma->vm_pgoff = 0; 1489 + ret = dma_mmap_coherent(dev, vma, qp->qdma.va, 1490 + qp->qdma.dma, sz); 1491 + vma->vm_pgoff = vm_pgoff; 1492 + return ret; 1493 + 1494 + default: 1495 + return -EINVAL; 1496 + } 1497 + } 1498 + 1499 + static int hisi_qm_uacce_start_queue(struct uacce_queue *q) 1500 + { 1501 + struct hisi_qp *qp = q->priv; 1502 + 1503 + return hisi_qm_start_qp(qp, qp->pasid); 1504 + } 1505 + 1506 + static void hisi_qm_uacce_stop_queue(struct uacce_queue *q) 1507 + { 1508 + hisi_qm_stop_qp(q->priv); 1509 + } 1510 + 1511 + static int qm_set_sqctype(struct uacce_queue *q, u16 type) 1512 + { 1513 + struct hisi_qm *qm = q->uacce->priv; 1514 + struct hisi_qp *qp = q->priv; 1515 + 1516 + write_lock(&qm->qps_lock); 1517 + qp->alg_type = type; 1518 + write_unlock(&qm->qps_lock); 1519 + 1520 + return 0; 1521 + } 1522 + 1523 + static long hisi_qm_uacce_ioctl(struct uacce_queue *q, unsigned int cmd, 1524 + unsigned long arg) 1525 + { 1526 + struct hisi_qp *qp = q->priv; 1527 + struct hisi_qp_ctx qp_ctx; 1528 + 1529 + if (cmd == UACCE_CMD_QM_SET_QP_CTX) { 1530 + if (copy_from_user(&qp_ctx, (void __user *)arg, 1531 + sizeof(struct hisi_qp_ctx))) 1532 + return -EFAULT; 1533 + 1534 + if (qp_ctx.qc_type != 0 && qp_ctx.qc_type != 1) 1535 + return -EINVAL; 1536 + 1537 + qm_set_sqctype(q, qp_ctx.qc_type); 1538 + qp_ctx.id = qp->qp_id; 1539 + 1540 + if (copy_to_user((void __user *)arg, &qp_ctx, 1541 + sizeof(struct hisi_qp_ctx))) 1542 + return -EFAULT; 1543 + } else { 1544 + return -EINVAL; 1545 + } 1546 + 1547 + return 0; 1548 + } 1549 + 1550 + static const struct uacce_ops uacce_qm_ops = { 1551 + .get_available_instances = hisi_qm_get_available_instances, 1552 + .get_queue = hisi_qm_uacce_get_queue, 1553 + .put_queue = hisi_qm_uacce_put_queue, 1554 + .start_queue = hisi_qm_uacce_start_queue, 1555 + .stop_queue = hisi_qm_uacce_stop_queue, 1556 + .mmap = hisi_qm_uacce_mmap, 1557 + .ioctl = hisi_qm_uacce_ioctl, 1558 + }; 1559 + 1560 + static int qm_alloc_uacce(struct hisi_qm *qm) 1561 + { 1562 + struct pci_dev *pdev = qm->pdev; 1563 + struct uacce_device *uacce; 1564 + unsigned long mmio_page_nr; 1565 + unsigned long dus_page_nr; 1566 + struct uacce_interface interface = { 1567 + .flags = UACCE_DEV_SVA, 1568 + .ops = &uacce_qm_ops, 1569 + }; 1570 + 1571 + strncpy(interface.name, pdev->driver->name, sizeof(interface.name)); 1572 + 1573 + uacce = uacce_alloc(&pdev->dev, &interface); 1574 + if (IS_ERR(uacce)) 1575 + return PTR_ERR(uacce); 1576 + 1577 + if (uacce->flags & UACCE_DEV_SVA) { 1578 + qm->use_sva = true; 1579 + } else { 1580 + /* only consider sva case */ 1581 + uacce_remove(uacce); 1582 + qm->uacce = NULL; 1583 + return -EINVAL; 1584 + } 1585 + 1586 + uacce->is_vf = pdev->is_virtfn; 1587 + uacce->priv = qm; 1588 + uacce->algs = qm->algs; 1589 + 1590 + if (qm->ver == QM_HW_V1) { 1591 + mmio_page_nr = QM_DOORBELL_PAGE_NR; 1592 + uacce->api_ver = HISI_QM_API_VER_BASE; 1593 + } else { 1594 + mmio_page_nr = QM_DOORBELL_PAGE_NR + 1595 + QM_DOORBELL_SQ_CQ_BASE_V2 / PAGE_SIZE; 1596 + uacce->api_ver = HISI_QM_API_VER2_BASE; 1597 + } 1598 + 1599 + dus_page_nr = (PAGE_SIZE - 1 + qm->sqe_size * QM_Q_DEPTH + 1600 + sizeof(struct qm_cqe) * QM_Q_DEPTH) >> PAGE_SHIFT; 1601 + 1602 + uacce->qf_pg_num[UACCE_QFRT_MMIO] = mmio_page_nr; 1603 + uacce->qf_pg_num[UACCE_QFRT_DUS] = dus_page_nr; 1604 + 1605 + qm->uacce = uacce; 1606 + 1607 + return 0; 1608 + } 1609 + 1410 1610 /** 1411 1611 * hisi_qm_get_free_qp_num() - Get free number of qp in qm. 1412 1612 * @qm: The qm which want to get free qp. ··· 1657 1441 return -EINVAL; 1658 1442 } 1659 1443 1444 + ret = qm_alloc_uacce(qm); 1445 + if (ret < 0) 1446 + dev_warn(&pdev->dev, "fail to alloc uacce (%d)\n", ret); 1447 + 1660 1448 ret = pci_enable_device_mem(pdev); 1661 1449 if (ret < 0) { 1662 1450 dev_err(&pdev->dev, "Failed to enable device mem!\n"); 1663 - return ret; 1451 + goto err_remove_uacce; 1664 1452 } 1665 1453 1666 1454 ret = pci_request_mem_regions(pdev, qm->dev_name); ··· 1673 1453 goto err_disable_pcidev; 1674 1454 } 1675 1455 1676 - qm->io_base = ioremap(pci_resource_start(pdev, PCI_BAR_2), 1677 - pci_resource_len(qm->pdev, PCI_BAR_2)); 1456 + qm->phys_base = pci_resource_start(pdev, PCI_BAR_2); 1457 + qm->phys_size = pci_resource_len(qm->pdev, PCI_BAR_2); 1458 + qm->io_base = ioremap(qm->phys_base, qm->phys_size); 1678 1459 if (!qm->io_base) { 1679 1460 ret = -EIO; 1680 1461 goto err_release_mem_regions; ··· 1718 1497 pci_release_mem_regions(pdev); 1719 1498 err_disable_pcidev: 1720 1499 pci_disable_device(pdev); 1500 + err_remove_uacce: 1501 + uacce_remove(qm->uacce); 1502 + qm->uacce = NULL; 1721 1503 1722 1504 return ret; 1723 1505 } ··· 1736 1512 { 1737 1513 struct pci_dev *pdev = qm->pdev; 1738 1514 struct device *dev = &pdev->dev; 1515 + 1516 + uacce_remove(qm->uacce); 1517 + qm->uacce = NULL; 1739 1518 1740 1519 if (qm->use_dma_api && qm->qdma.va) { 1741 1520 hisi_qm_cache_wb(qm);
+11
drivers/crypto/hisilicon/qm.h
··· 77 77 78 78 #define HISI_ACC_SGL_SGE_NR_MAX 255 79 79 80 + /* page number for queue file region */ 81 + #define QM_DOORBELL_PAGE_NR 1 82 + 80 83 enum qp_state { 81 84 QP_STOP, 82 85 }; ··· 183 180 u32 error_mask; 184 181 u32 msi_mask; 185 182 183 + const char *algs; 186 184 bool use_dma_api; 185 + bool use_sva; 186 + resource_size_t phys_base; 187 + resource_size_t phys_size; 188 + struct uacce_device *uacce; 187 189 }; 188 190 189 191 struct hisi_qp_status { ··· 218 210 struct hisi_qp_ops *hw_ops; 219 211 void *qp_ctx; 220 212 void (*req_cb)(struct hisi_qp *qp, void *data); 213 + void (*event_cb)(struct hisi_qp *qp); 221 214 struct work_struct work; 222 215 struct workqueue_struct *wq; 223 216 224 217 struct hisi_qm *qm; 218 + u16 pasid; 219 + struct uacce_queue *uacce_q; 225 220 }; 226 221 227 222 int hisi_qm_init(struct hisi_qm *qm);
+16 -2
drivers/crypto/hisilicon/zip/zip_main.c
··· 11 11 #include <linux/pci.h> 12 12 #include <linux/seq_file.h> 13 13 #include <linux/topology.h> 14 + #include <linux/uacce.h> 14 15 #include "zip.h" 15 16 16 17 #define PCI_DEVICE_ID_ZIP_PF 0xa250 ··· 355 354 writel(AXUSER_BASE, base + HZIP_BD_RUSER_32_63); 356 355 writel(AXUSER_BASE, base + HZIP_SGL_RUSER_32_63); 357 356 writel(AXUSER_BASE, base + HZIP_BD_WUSER_32_63); 358 - writel(AXUSER_BASE, base + HZIP_DATA_RUSER_32_63); 359 - writel(AXUSER_BASE, base + HZIP_DATA_WUSER_32_63); 357 + 358 + if (hisi_zip->qm.use_sva) { 359 + writel(AXUSER_BASE | AXUSER_SSV, base + HZIP_DATA_RUSER_32_63); 360 + writel(AXUSER_BASE | AXUSER_SSV, base + HZIP_DATA_WUSER_32_63); 361 + } else { 362 + writel(AXUSER_BASE, base + HZIP_DATA_RUSER_32_63); 363 + writel(AXUSER_BASE, base + HZIP_DATA_WUSER_32_63); 364 + } 360 365 361 366 /* let's open all compression/decompression cores */ 362 367 writel(DECOMP_CHECK_ENABLE | ALL_COMP_DECOMP_EN, ··· 849 842 qm->pdev = pdev; 850 843 qm->ver = rev_id; 851 844 845 + qm->algs = "zlib\ngzip"; 852 846 qm->sqe_size = HZIP_SQE_SIZE; 853 847 qm->dev_name = hisi_zip_name; 854 848 qm->fun_type = (pdev->device == PCI_DEVICE_ID_ZIP_PF) ? QM_HW_PF : ··· 892 884 dev_err(&pdev->dev, "Failed to init debugfs (%d)!\n", ret); 893 885 894 886 hisi_zip_add_to_list(hisi_zip); 887 + 888 + if (qm->uacce) { 889 + ret = uacce_register(qm->uacce); 890 + if (ret) 891 + goto err_qm_uninit; 892 + } 895 893 896 894 if (qm->fun_type == QM_HW_PF && vfs_num > 0) { 897 895 ret = hisi_zip_sriov_enable(pdev, vfs_num);
+23
include/uapi/misc/uacce/hisi_qm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ 2 + #ifndef _UAPI_HISI_QM_H 3 + #define _UAPI_HISI_QM_H 4 + 5 + #include <linux/types.h> 6 + 7 + /** 8 + * struct hisi_qp_ctx - User data for hisi qp. 9 + * @id: qp_index return to user space 10 + * @qc_type: Accelerator algorithm type 11 + */ 12 + struct hisi_qp_ctx { 13 + __u16 id; 14 + __u16 qc_type; 15 + }; 16 + 17 + #define HISI_QM_API_VER_BASE "hisi_qm_v1" 18 + #define HISI_QM_API_VER2_BASE "hisi_qm_v2" 19 + 20 + /* UACCE_CMD_QM_SET_QP_CTX: Set qp algorithm type */ 21 + #define UACCE_CMD_QM_SET_QP_CTX _IOWR('H', 10, struct hisi_qp_ctx) 22 + 23 + #endif