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 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 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 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 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 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 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 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