xref: /linux/drivers/crypto/intel/qat/qat_6xxx/adf_drv.c (revision ab93e0dd72c37d378dd936f031ffb83ff2bd87ce)
117fd7514SLaurent M Coquerel // SPDX-License-Identifier: GPL-2.0-only
217fd7514SLaurent M Coquerel /* Copyright(c) 2025 Intel Corporation */
317fd7514SLaurent M Coquerel #include <linux/array_size.h>
417fd7514SLaurent M Coquerel #include <linux/device.h>
517fd7514SLaurent M Coquerel #include <linux/dma-mapping.h>
617fd7514SLaurent M Coquerel #include <linux/errno.h>
717fd7514SLaurent M Coquerel #include <linux/list.h>
817fd7514SLaurent M Coquerel #include <linux/module.h>
917fd7514SLaurent M Coquerel #include <linux/pci.h>
1017fd7514SLaurent M Coquerel #include <linux/types.h>
1117fd7514SLaurent M Coquerel 
1217fd7514SLaurent M Coquerel #include <adf_accel_devices.h>
1317fd7514SLaurent M Coquerel #include <adf_cfg.h>
1417fd7514SLaurent M Coquerel #include <adf_common_drv.h>
1517fd7514SLaurent M Coquerel #include <adf_dbgfs.h>
1617fd7514SLaurent M Coquerel 
1717fd7514SLaurent M Coquerel #include "adf_gen6_shared.h"
1817fd7514SLaurent M Coquerel #include "adf_6xxx_hw_data.h"
1917fd7514SLaurent M Coquerel 
2017fd7514SLaurent M Coquerel static int bar_map[] = {
2117fd7514SLaurent M Coquerel 	0,	/* SRAM */
2217fd7514SLaurent M Coquerel 	2,	/* PMISC */
2317fd7514SLaurent M Coquerel 	4,	/* ETR */
2417fd7514SLaurent M Coquerel };
2517fd7514SLaurent M Coquerel 
adf_device_down(void * accel_dev)2617fd7514SLaurent M Coquerel static void adf_device_down(void *accel_dev)
2717fd7514SLaurent M Coquerel {
2817fd7514SLaurent M Coquerel 	adf_dev_down(accel_dev);
2917fd7514SLaurent M Coquerel }
3017fd7514SLaurent M Coquerel 
adf_dbgfs_cleanup(void * accel_dev)3117fd7514SLaurent M Coquerel static void adf_dbgfs_cleanup(void *accel_dev)
3217fd7514SLaurent M Coquerel {
3317fd7514SLaurent M Coquerel 	adf_dbgfs_exit(accel_dev);
3417fd7514SLaurent M Coquerel }
3517fd7514SLaurent M Coquerel 
adf_cfg_device_remove(void * accel_dev)3617fd7514SLaurent M Coquerel static void adf_cfg_device_remove(void *accel_dev)
3717fd7514SLaurent M Coquerel {
3817fd7514SLaurent M Coquerel 	adf_cfg_dev_remove(accel_dev);
3917fd7514SLaurent M Coquerel }
4017fd7514SLaurent M Coquerel 
adf_cleanup_hw_data(void * accel_dev)4117fd7514SLaurent M Coquerel static void adf_cleanup_hw_data(void *accel_dev)
4217fd7514SLaurent M Coquerel {
4317fd7514SLaurent M Coquerel 	struct adf_accel_dev *accel_device = accel_dev;
4417fd7514SLaurent M Coquerel 
4517fd7514SLaurent M Coquerel 	if (accel_device->hw_device) {
4617fd7514SLaurent M Coquerel 		adf_clean_hw_data_6xxx(accel_device->hw_device);
4717fd7514SLaurent M Coquerel 		accel_device->hw_device = NULL;
4817fd7514SLaurent M Coquerel 	}
4917fd7514SLaurent M Coquerel }
5017fd7514SLaurent M Coquerel 
adf_devmgr_remove(void * accel_dev)5117fd7514SLaurent M Coquerel static void adf_devmgr_remove(void *accel_dev)
5217fd7514SLaurent M Coquerel {
5317fd7514SLaurent M Coquerel 	adf_devmgr_rm_dev(accel_dev, NULL);
5417fd7514SLaurent M Coquerel }
5517fd7514SLaurent M Coquerel 
adf_probe(struct pci_dev * pdev,const struct pci_device_id * ent)5617fd7514SLaurent M Coquerel static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
5717fd7514SLaurent M Coquerel {
5817fd7514SLaurent M Coquerel 	struct adf_accel_pci *accel_pci_dev;
5917fd7514SLaurent M Coquerel 	struct adf_hw_device_data *hw_data;
6017fd7514SLaurent M Coquerel 	struct device *dev = &pdev->dev;
6117fd7514SLaurent M Coquerel 	struct adf_accel_dev *accel_dev;
6217fd7514SLaurent M Coquerel 	struct adf_bar *bar;
6317fd7514SLaurent M Coquerel 	unsigned int i;
6417fd7514SLaurent M Coquerel 	int ret;
6517fd7514SLaurent M Coquerel 
6617fd7514SLaurent M Coquerel 	if (num_possible_nodes() > 1 && dev_to_node(dev) < 0) {
6717fd7514SLaurent M Coquerel 		/*
6817fd7514SLaurent M Coquerel 		 * If the accelerator is connected to a node with no memory
6917fd7514SLaurent M Coquerel 		 * there is no point in using the accelerator since the remote
7017fd7514SLaurent M Coquerel 		 * memory transaction will be very slow.
7117fd7514SLaurent M Coquerel 		 */
7217fd7514SLaurent M Coquerel 		return dev_err_probe(dev, -EINVAL, "Invalid NUMA configuration.\n");
7317fd7514SLaurent M Coquerel 	}
7417fd7514SLaurent M Coquerel 
7517fd7514SLaurent M Coquerel 	accel_dev = devm_kzalloc(dev, sizeof(*accel_dev), GFP_KERNEL);
7617fd7514SLaurent M Coquerel 	if (!accel_dev)
7717fd7514SLaurent M Coquerel 		return -ENOMEM;
7817fd7514SLaurent M Coquerel 
7917fd7514SLaurent M Coquerel 	INIT_LIST_HEAD(&accel_dev->crypto_list);
8017fd7514SLaurent M Coquerel 	INIT_LIST_HEAD(&accel_dev->list);
8117fd7514SLaurent M Coquerel 	accel_pci_dev = &accel_dev->accel_pci_dev;
8217fd7514SLaurent M Coquerel 	accel_pci_dev->pci_dev = pdev;
8317fd7514SLaurent M Coquerel 	accel_dev->owner = THIS_MODULE;
8417fd7514SLaurent M Coquerel 
8517fd7514SLaurent M Coquerel 	hw_data = devm_kzalloc(dev, sizeof(*hw_data), GFP_KERNEL);
8617fd7514SLaurent M Coquerel 	if (!hw_data)
8717fd7514SLaurent M Coquerel 		return -ENOMEM;
8817fd7514SLaurent M Coquerel 
8917fd7514SLaurent M Coquerel 	pci_read_config_byte(pdev, PCI_REVISION_ID, &accel_pci_dev->revid);
9017fd7514SLaurent M Coquerel 	pci_read_config_dword(pdev, ADF_GEN6_FUSECTL4_OFFSET, &hw_data->fuses[ADF_FUSECTL4]);
9117fd7514SLaurent M Coquerel 	pci_read_config_dword(pdev, ADF_GEN6_FUSECTL0_OFFSET, &hw_data->fuses[ADF_FUSECTL0]);
9217fd7514SLaurent M Coquerel 	pci_read_config_dword(pdev, ADF_GEN6_FUSECTL1_OFFSET, &hw_data->fuses[ADF_FUSECTL1]);
9317fd7514SLaurent M Coquerel 
9417fd7514SLaurent M Coquerel 	if (!(hw_data->fuses[ADF_FUSECTL1] & ICP_ACCEL_GEN6_MASK_WCP_WAT_SLICE))
9517fd7514SLaurent M Coquerel 		return dev_err_probe(dev, -EFAULT, "Wireless mode is not supported.\n");
9617fd7514SLaurent M Coquerel 
9717fd7514SLaurent M Coquerel 	/* Enable PCI device */
9817fd7514SLaurent M Coquerel 	ret = pcim_enable_device(pdev);
9917fd7514SLaurent M Coquerel 	if (ret)
10017fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "Cannot enable PCI device.\n");
10117fd7514SLaurent M Coquerel 
10217fd7514SLaurent M Coquerel 	ret = adf_devmgr_add_dev(accel_dev, NULL);
10317fd7514SLaurent M Coquerel 	if (ret)
10417fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "Failed to add new accelerator device.\n");
10517fd7514SLaurent M Coquerel 
10617fd7514SLaurent M Coquerel 	ret = devm_add_action_or_reset(dev, adf_devmgr_remove, accel_dev);
10717fd7514SLaurent M Coquerel 	if (ret)
10817fd7514SLaurent M Coquerel 		return ret;
10917fd7514SLaurent M Coquerel 
11017fd7514SLaurent M Coquerel 	accel_dev->hw_device = hw_data;
11117fd7514SLaurent M Coquerel 	adf_init_hw_data_6xxx(accel_dev->hw_device);
11217fd7514SLaurent M Coquerel 
11317fd7514SLaurent M Coquerel 	ret = devm_add_action_or_reset(dev, adf_cleanup_hw_data, accel_dev);
11417fd7514SLaurent M Coquerel 	if (ret)
11517fd7514SLaurent M Coquerel 		return ret;
11617fd7514SLaurent M Coquerel 
11717fd7514SLaurent M Coquerel 	/* Get Accelerators and Accelerator Engine masks */
11817fd7514SLaurent M Coquerel 	hw_data->accel_mask = hw_data->get_accel_mask(hw_data);
11917fd7514SLaurent M Coquerel 	hw_data->ae_mask = hw_data->get_ae_mask(hw_data);
12017fd7514SLaurent M Coquerel 	accel_pci_dev->sku = hw_data->get_sku(hw_data);
12117fd7514SLaurent M Coquerel 
12217fd7514SLaurent M Coquerel 	/* If the device has no acceleration engines then ignore it */
12317fd7514SLaurent M Coquerel 	if (!hw_data->accel_mask || !hw_data->ae_mask ||
12417fd7514SLaurent M Coquerel 	    (~hw_data->ae_mask & ADF_GEN6_ACCELERATORS_MASK)) {
12517fd7514SLaurent M Coquerel 		ret = -EFAULT;
12617fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "No acceleration units were found.\n");
12717fd7514SLaurent M Coquerel 	}
12817fd7514SLaurent M Coquerel 
12917fd7514SLaurent M Coquerel 	/* Create device configuration table */
13017fd7514SLaurent M Coquerel 	ret = adf_cfg_dev_add(accel_dev);
13117fd7514SLaurent M Coquerel 	if (ret)
13217fd7514SLaurent M Coquerel 		return ret;
13317fd7514SLaurent M Coquerel 
13417fd7514SLaurent M Coquerel 	ret = devm_add_action_or_reset(dev, adf_cfg_device_remove, accel_dev);
13517fd7514SLaurent M Coquerel 	if (ret)
13617fd7514SLaurent M Coquerel 		return ret;
13717fd7514SLaurent M Coquerel 
13817fd7514SLaurent M Coquerel 	/* Set DMA identifier */
13917fd7514SLaurent M Coquerel 	ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
14017fd7514SLaurent M Coquerel 	if (ret)
14117fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "No usable DMA configuration.\n");
14217fd7514SLaurent M Coquerel 
14317fd7514SLaurent M Coquerel 	ret = adf_gen6_cfg_dev_init(accel_dev);
14417fd7514SLaurent M Coquerel 	if (ret)
14517fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "Failed to initialize configuration.\n");
14617fd7514SLaurent M Coquerel 
14717fd7514SLaurent M Coquerel 	/* Get accelerator capability mask */
14817fd7514SLaurent M Coquerel 	hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev);
14917fd7514SLaurent M Coquerel 	if (!hw_data->accel_capabilities_mask) {
15017fd7514SLaurent M Coquerel 		ret = -EINVAL;
15117fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "Failed to get capabilities mask.\n");
15217fd7514SLaurent M Coquerel 	}
15317fd7514SLaurent M Coquerel 
15417fd7514SLaurent M Coquerel 	for (i = 0; i < ARRAY_SIZE(bar_map); i++) {
15517fd7514SLaurent M Coquerel 		bar = &accel_pci_dev->pci_bars[i];
15617fd7514SLaurent M Coquerel 
15717fd7514SLaurent M Coquerel 		/* Map 64-bit PCIe BAR */
15817fd7514SLaurent M Coquerel 		bar->virt_addr = pcim_iomap_region(pdev, bar_map[i], pci_name(pdev));
15933cd9343SDan Carpenter 		if (IS_ERR(bar->virt_addr)) {
16033cd9343SDan Carpenter 			ret = PTR_ERR(bar->virt_addr);
16117fd7514SLaurent M Coquerel 			return dev_err_probe(dev, ret, "Failed to ioremap PCI region.\n");
16217fd7514SLaurent M Coquerel 		}
16317fd7514SLaurent M Coquerel 	}
16417fd7514SLaurent M Coquerel 
16517fd7514SLaurent M Coquerel 	pci_set_master(pdev);
16617fd7514SLaurent M Coquerel 
16717fd7514SLaurent M Coquerel 	/*
16817fd7514SLaurent M Coquerel 	 * The PCI config space is saved at this point and will be restored
16917fd7514SLaurent M Coquerel 	 * after a Function Level Reset (FLR) as the FLR does not completely
17017fd7514SLaurent M Coquerel 	 * restore it.
17117fd7514SLaurent M Coquerel 	 */
17217fd7514SLaurent M Coquerel 	ret = pci_save_state(pdev);
17317fd7514SLaurent M Coquerel 	if (ret)
17417fd7514SLaurent M Coquerel 		return dev_err_probe(dev, ret, "Failed to save pci state.\n");
17517fd7514SLaurent M Coquerel 
176*662c62bbSSuman Kumar Chakraborty 	accel_dev->ras_errors.enabled = true;
177*662c62bbSSuman Kumar Chakraborty 
17817fd7514SLaurent M Coquerel 	adf_dbgfs_init(accel_dev);
17917fd7514SLaurent M Coquerel 
18017fd7514SLaurent M Coquerel 	ret = devm_add_action_or_reset(dev, adf_dbgfs_cleanup, accel_dev);
18117fd7514SLaurent M Coquerel 	if (ret)
18217fd7514SLaurent M Coquerel 		return ret;
18317fd7514SLaurent M Coquerel 
18417fd7514SLaurent M Coquerel 	ret = adf_dev_up(accel_dev, true);
18517fd7514SLaurent M Coquerel 	if (ret)
18617fd7514SLaurent M Coquerel 		return ret;
18717fd7514SLaurent M Coquerel 
18817fd7514SLaurent M Coquerel 	ret = devm_add_action_or_reset(dev, adf_device_down, accel_dev);
18917fd7514SLaurent M Coquerel 	if (ret)
19017fd7514SLaurent M Coquerel 		return ret;
19117fd7514SLaurent M Coquerel 
19217fd7514SLaurent M Coquerel 	ret = adf_sysfs_init(accel_dev);
19317fd7514SLaurent M Coquerel 
19417fd7514SLaurent M Coquerel 	return ret;
19517fd7514SLaurent M Coquerel }
19617fd7514SLaurent M Coquerel 
adf_shutdown(struct pci_dev * pdev)19717fd7514SLaurent M Coquerel static void adf_shutdown(struct pci_dev *pdev)
19817fd7514SLaurent M Coquerel {
19917fd7514SLaurent M Coquerel 	struct adf_accel_dev *accel_dev = adf_devmgr_pci_to_accel_dev(pdev);
20017fd7514SLaurent M Coquerel 
20117fd7514SLaurent M Coquerel 	adf_dev_down(accel_dev);
20217fd7514SLaurent M Coquerel }
20317fd7514SLaurent M Coquerel 
20417fd7514SLaurent M Coquerel static const struct pci_device_id adf_pci_tbl[] = {
20517fd7514SLaurent M Coquerel 	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_QAT_6XXX) },
20617fd7514SLaurent M Coquerel 	{ }
20717fd7514SLaurent M Coquerel };
20817fd7514SLaurent M Coquerel MODULE_DEVICE_TABLE(pci, adf_pci_tbl);
20917fd7514SLaurent M Coquerel 
21017fd7514SLaurent M Coquerel static struct pci_driver adf_driver = {
21117fd7514SLaurent M Coquerel 	.id_table = adf_pci_tbl,
21217fd7514SLaurent M Coquerel 	.name = ADF_6XXX_DEVICE_NAME,
21317fd7514SLaurent M Coquerel 	.probe = adf_probe,
21417fd7514SLaurent M Coquerel 	.shutdown = adf_shutdown,
21517fd7514SLaurent M Coquerel 	.sriov_configure = adf_sriov_configure,
21617fd7514SLaurent M Coquerel 	.err_handler = &adf_err_handler,
21717fd7514SLaurent M Coquerel };
21817fd7514SLaurent M Coquerel module_pci_driver(adf_driver);
21917fd7514SLaurent M Coquerel 
22017fd7514SLaurent M Coquerel MODULE_LICENSE("GPL");
22117fd7514SLaurent M Coquerel MODULE_AUTHOR("Intel");
22217fd7514SLaurent M Coquerel MODULE_FIRMWARE(ADF_6XXX_FW);
22317fd7514SLaurent M Coquerel MODULE_FIRMWARE(ADF_6XXX_MMP);
22417fd7514SLaurent M Coquerel MODULE_DESCRIPTION("Intel(R) QuickAssist Technology for GEN6 Devices");
22517fd7514SLaurent M Coquerel MODULE_SOFTDEP("pre: crypto-intel_qat");
22617fd7514SLaurent M Coquerel MODULE_IMPORT_NS("CRYPTO_QAT");
227