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

crypto: safexcel - Cleanup ring IRQ workqueues on load failure

A failure loading the safexcel driver results in the following warning
on boot, because the IRQ affinity has not been correctly cleaned up.
Ensure we clean up the affinity and workqueues on a failure to load the
driver.

crypto-safexcel: probe of f2800000.crypto failed with error -2
------------[ cut here ]------------
WARNING: CPU: 1 PID: 232 at kernel/irq/manage.c:1913 free_irq+0x300/0x340
Modules linked in: hwmon mdio_i2c crypto_safexcel(+) md5 sha256_generic libsha256 authenc libdes omap_rng rng_core nft_masq nft_nat nft_chain_nat nf_nat nft_ct nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables libcrc32c nfnetlink fuse autofs4
CPU: 1 PID: 232 Comm: systemd-udevd Tainted: G W 6.1.6-00002-g9d4898824677 #3
Hardware name: MikroTik RB5009 (DT)
pstate: 600000c5 (nZCv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : free_irq+0x300/0x340
lr : free_irq+0x2e0/0x340
sp : ffff800008fa3890
x29: ffff800008fa3890 x28: 0000000000000000 x27: 0000000000000000
x26: ffff8000008e6dc0 x25: ffff000009034cac x24: ffff000009034d50
x23: 0000000000000000 x22: 000000000000004a x21: ffff0000093e0d80
x20: ffff000009034c00 x19: ffff00000615fc00 x18: 0000000000000000
x17: 0000000000000000 x16: 0000000000000000 x15: 000075f5c1584c5e
x14: 0000000000000017 x13: 0000000000000000 x12: 0000000000000040
x11: ffff000000579b60 x10: ffff000000579b62 x9 : ffff800008bbe370
x8 : ffff000000579dd0 x7 : 0000000000000000 x6 : ffff000000579e18
x5 : ffff000000579da8 x4 : ffff800008ca0000 x3 : ffff800008ca0188
x2 : 0000000013033204 x1 : ffff000009034c00 x0 : ffff8000087eadf0
Call trace:
free_irq+0x300/0x340
devm_irq_release+0x14/0x20
devres_release_all+0xa0/0x100
device_unbind_cleanup+0x14/0x60
really_probe+0x198/0x2d4
__driver_probe_device+0x74/0xdc
driver_probe_device+0x3c/0x110
__driver_attach+0x8c/0x190
bus_for_each_dev+0x6c/0xc0
driver_attach+0x20/0x30
bus_add_driver+0x148/0x1fc
driver_register+0x74/0x120
__platform_driver_register+0x24/0x30
safexcel_init+0x48/0x1000 [crypto_safexcel]
do_one_initcall+0x4c/0x1b0
do_init_module+0x44/0x1cc
load_module+0x1724/0x1be4
__do_sys_finit_module+0xbc/0x110
__arm64_sys_finit_module+0x1c/0x24
invoke_syscall+0x44/0x110
el0_svc_common.constprop.0+0xc0/0xe0
do_el0_svc+0x20/0x80
el0_svc+0x14/0x4c
el0t_64_sync_handler+0xb0/0xb4
el0t_64_sync+0x148/0x14c
---[ end trace 0000000000000000 ]---

Fixes: 1b44c5a60c13 ("inside-secure - add SafeXcel EIP197 crypto engine driver")
Signed-off-by: Jonathan McDowell <noodles@earth.li>
Cc: stable@vger.kernel.org
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Jonathan McDowell and committed by
Herbert Xu
ca25c00c 86e8e3ce

+27 -10
+27 -10
drivers/crypto/inside-secure/safexcel.c
··· 1628 1628 &priv->ring[i].rdr); 1629 1629 if (ret) { 1630 1630 dev_err(dev, "Failed to initialize rings\n"); 1631 - return ret; 1631 + goto err_cleanup_rings; 1632 1632 } 1633 1633 1634 1634 priv->ring[i].rdr_req = devm_kcalloc(dev, 1635 1635 EIP197_DEFAULT_RING_SIZE, 1636 1636 sizeof(*priv->ring[i].rdr_req), 1637 1637 GFP_KERNEL); 1638 - if (!priv->ring[i].rdr_req) 1639 - return -ENOMEM; 1638 + if (!priv->ring[i].rdr_req) { 1639 + ret = -ENOMEM; 1640 + goto err_cleanup_rings; 1641 + } 1640 1642 1641 1643 ring_irq = devm_kzalloc(dev, sizeof(*ring_irq), GFP_KERNEL); 1642 - if (!ring_irq) 1643 - return -ENOMEM; 1644 + if (!ring_irq) { 1645 + ret = -ENOMEM; 1646 + goto err_cleanup_rings; 1647 + } 1644 1648 1645 1649 ring_irq->priv = priv; 1646 1650 ring_irq->ring = i; ··· 1658 1654 ring_irq); 1659 1655 if (irq < 0) { 1660 1656 dev_err(dev, "Failed to get IRQ ID for ring %d\n", i); 1661 - return irq; 1657 + ret = irq; 1658 + goto err_cleanup_rings; 1662 1659 } 1663 1660 1664 1661 priv->ring[i].irq = irq; ··· 1671 1666 snprintf(wq_name, 9, "wq_ring%d", i); 1672 1667 priv->ring[i].workqueue = 1673 1668 create_singlethread_workqueue(wq_name); 1674 - if (!priv->ring[i].workqueue) 1675 - return -ENOMEM; 1669 + if (!priv->ring[i].workqueue) { 1670 + ret = -ENOMEM; 1671 + goto err_cleanup_rings; 1672 + } 1676 1673 1677 1674 priv->ring[i].requests = 0; 1678 1675 priv->ring[i].busy = false; ··· 1691 1684 ret = safexcel_hw_init(priv); 1692 1685 if (ret) { 1693 1686 dev_err(dev, "HW init failed (%d)\n", ret); 1694 - return ret; 1687 + goto err_cleanup_rings; 1695 1688 } 1696 1689 1697 1690 ret = safexcel_register_algorithms(priv); 1698 1691 if (ret) { 1699 1692 dev_err(dev, "Failed to register algorithms (%d)\n", ret); 1700 - return ret; 1693 + goto err_cleanup_rings; 1701 1694 } 1702 1695 1703 1696 return 0; 1697 + 1698 + err_cleanup_rings: 1699 + for (i = 0; i < priv->config.rings; i++) { 1700 + if (priv->ring[i].irq) 1701 + irq_set_affinity_hint(priv->ring[i].irq, NULL); 1702 + if (priv->ring[i].workqueue) 1703 + destroy_workqueue(priv->ring[i].workqueue); 1704 + } 1705 + 1706 + return ret; 1704 1707 } 1705 1708 1706 1709 static void safexcel_hw_reset_rings(struct safexcel_crypto_priv *priv)