xref: /freebsd/sys/dev/qat/qat_hw/qat_c4xxx/adf_drv.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
178ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
278ee8d1cSJulian Grajkowski /* Copyright(c) 2007-2022 Intel Corporation */
378ee8d1cSJulian Grajkowski #include "qat_freebsd.h"
478ee8d1cSJulian Grajkowski #include "adf_cfg.h"
578ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
678ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
778ee8d1cSJulian Grajkowski #include "adf_c4xxx_hw_data.h"
878ee8d1cSJulian Grajkowski #include "adf_fw_counters.h"
978ee8d1cSJulian Grajkowski #include "adf_cfg_device.h"
1078ee8d1cSJulian Grajkowski #include <sys/types.h>
1178ee8d1cSJulian Grajkowski #include <sys/kernel.h>
1278ee8d1cSJulian Grajkowski #include <sys/malloc.h>
1378ee8d1cSJulian Grajkowski #include <machine/bus_dma.h>
1478ee8d1cSJulian Grajkowski #include <dev/pci/pcireg.h>
1578ee8d1cSJulian Grajkowski #include "adf_heartbeat_dbg.h"
1678ee8d1cSJulian Grajkowski #include "adf_cnvnr_freq_counters.h"
1778ee8d1cSJulian Grajkowski 
1878ee8d1cSJulian Grajkowski static MALLOC_DEFINE(M_QAT_C4XXX, "qat_c4xx", "qat_c4xx");
1978ee8d1cSJulian Grajkowski 
2078ee8d1cSJulian Grajkowski #define ADF_SYSTEM_DEVICE(device_id)                                           \
2178ee8d1cSJulian Grajkowski 	{                                                                      \
2278ee8d1cSJulian Grajkowski 		PCI_VENDOR_ID_INTEL, device_id                                 \
2378ee8d1cSJulian Grajkowski 	}
2478ee8d1cSJulian Grajkowski 
2578ee8d1cSJulian Grajkowski static const struct pci_device_id adf_pci_tbl[] =
2678ee8d1cSJulian Grajkowski     { ADF_SYSTEM_DEVICE(ADF_C4XXX_PCI_DEVICE_ID),
2778ee8d1cSJulian Grajkowski       {
2878ee8d1cSJulian Grajkowski 	  0,
2978ee8d1cSJulian Grajkowski       } };
3078ee8d1cSJulian Grajkowski 
3178ee8d1cSJulian Grajkowski static int
adf_probe(device_t dev)3278ee8d1cSJulian Grajkowski adf_probe(device_t dev)
3378ee8d1cSJulian Grajkowski {
3478ee8d1cSJulian Grajkowski 	const struct pci_device_id *id;
3578ee8d1cSJulian Grajkowski 
3678ee8d1cSJulian Grajkowski 	for (id = adf_pci_tbl; id->vendor != 0; id++) {
3778ee8d1cSJulian Grajkowski 		if (pci_get_vendor(dev) == id->vendor &&
3878ee8d1cSJulian Grajkowski 		    pci_get_device(dev) == id->device) {
3978ee8d1cSJulian Grajkowski 			device_set_desc(dev,
4078ee8d1cSJulian Grajkowski 					"Intel " ADF_C4XXX_DEVICE_NAME
4178ee8d1cSJulian Grajkowski 					" QuickAssist");
4278ee8d1cSJulian Grajkowski 			return BUS_PROBE_GENERIC;
4378ee8d1cSJulian Grajkowski 		}
4478ee8d1cSJulian Grajkowski 	}
4578ee8d1cSJulian Grajkowski 	return ENXIO;
4678ee8d1cSJulian Grajkowski }
4778ee8d1cSJulian Grajkowski 
4878ee8d1cSJulian Grajkowski static void
adf_cleanup_accel(struct adf_accel_dev * accel_dev)4978ee8d1cSJulian Grajkowski adf_cleanup_accel(struct adf_accel_dev *accel_dev)
5078ee8d1cSJulian Grajkowski {
5178ee8d1cSJulian Grajkowski 	struct adf_accel_pci *accel_pci_dev = &accel_dev->accel_pci_dev;
5278ee8d1cSJulian Grajkowski 	int i;
5378ee8d1cSJulian Grajkowski 
5478ee8d1cSJulian Grajkowski 	if (accel_dev->dma_tag)
5578ee8d1cSJulian Grajkowski 		bus_dma_tag_destroy(accel_dev->dma_tag);
5678ee8d1cSJulian Grajkowski 	for (i = 0; i < ADF_PCI_MAX_BARS; i++) {
5778ee8d1cSJulian Grajkowski 		struct adf_bar *bar = &accel_pci_dev->pci_bars[i];
5878ee8d1cSJulian Grajkowski 
5978ee8d1cSJulian Grajkowski 		if (bar->virt_addr)
6078ee8d1cSJulian Grajkowski 			bus_free_resource(accel_pci_dev->pci_dev,
6178ee8d1cSJulian Grajkowski 					  SYS_RES_MEMORY,
6278ee8d1cSJulian Grajkowski 					  bar->virt_addr);
6378ee8d1cSJulian Grajkowski 	}
6478ee8d1cSJulian Grajkowski 
6578ee8d1cSJulian Grajkowski 	if (accel_dev->hw_device) {
6678ee8d1cSJulian Grajkowski 		switch (pci_get_device(accel_pci_dev->pci_dev)) {
6778ee8d1cSJulian Grajkowski 		case ADF_C4XXX_PCI_DEVICE_ID:
6878ee8d1cSJulian Grajkowski 			adf_clean_hw_data_c4xxx(accel_dev->hw_device);
6978ee8d1cSJulian Grajkowski 			break;
7078ee8d1cSJulian Grajkowski 		default:
7178ee8d1cSJulian Grajkowski 			break;
7278ee8d1cSJulian Grajkowski 		}
7378ee8d1cSJulian Grajkowski 		free(accel_dev->hw_device, M_QAT_C4XXX);
7478ee8d1cSJulian Grajkowski 		accel_dev->hw_device = NULL;
7578ee8d1cSJulian Grajkowski 	}
7678ee8d1cSJulian Grajkowski 	adf_cfg_dev_remove(accel_dev);
7778ee8d1cSJulian Grajkowski 	adf_devmgr_rm_dev(accel_dev, NULL);
7878ee8d1cSJulian Grajkowski }
7978ee8d1cSJulian Grajkowski 
8078ee8d1cSJulian Grajkowski static int
adf_attach(device_t dev)8178ee8d1cSJulian Grajkowski adf_attach(device_t dev)
8278ee8d1cSJulian Grajkowski {
8378ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev;
8478ee8d1cSJulian Grajkowski 	struct adf_accel_pci *accel_pci_dev;
8578ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_data;
8678ee8d1cSJulian Grajkowski 	unsigned int i, bar_nr;
8778ee8d1cSJulian Grajkowski 	int ret, rid;
8878ee8d1cSJulian Grajkowski 	struct adf_cfg_device *cfg_dev = NULL;
8978ee8d1cSJulian Grajkowski 
9078ee8d1cSJulian Grajkowski 	/* Set pci MaxPayLoad to 256. Implemented to avoid the issue of
9178ee8d1cSJulian Grajkowski 	 * Pci-passthrough causing Maxpayload to be reset to 128 bytes
9278ee8d1cSJulian Grajkowski 	 * when the device is reset.
9378ee8d1cSJulian Grajkowski 	 */
9478ee8d1cSJulian Grajkowski 	if (pci_get_max_payload(dev) != 256)
9578ee8d1cSJulian Grajkowski 		pci_set_max_payload(dev, 256);
9678ee8d1cSJulian Grajkowski 
9778ee8d1cSJulian Grajkowski 	accel_dev = device_get_softc(dev);
9878ee8d1cSJulian Grajkowski 
9978ee8d1cSJulian Grajkowski 	INIT_LIST_HEAD(&accel_dev->crypto_list);
10078ee8d1cSJulian Grajkowski 	accel_pci_dev = &accel_dev->accel_pci_dev;
10178ee8d1cSJulian Grajkowski 	accel_pci_dev->pci_dev = dev;
10278ee8d1cSJulian Grajkowski 
10378ee8d1cSJulian Grajkowski 	if (bus_get_domain(dev, &accel_pci_dev->node) != 0)
10478ee8d1cSJulian Grajkowski 		accel_pci_dev->node = 0;
10578ee8d1cSJulian Grajkowski 
10678ee8d1cSJulian Grajkowski 	/* XXX: Revisit if we actually need a devmgr table at all. */
10778ee8d1cSJulian Grajkowski 
10878ee8d1cSJulian Grajkowski 	/* Add accel device to accel table.
10978ee8d1cSJulian Grajkowski 	 * This should be called before adf_cleanup_accel is called
11078ee8d1cSJulian Grajkowski 	 */
11178ee8d1cSJulian Grajkowski 	if (adf_devmgr_add_dev(accel_dev, NULL)) {
11278ee8d1cSJulian Grajkowski 		device_printf(dev, "Failed to add new accelerator device.\n");
11378ee8d1cSJulian Grajkowski 		return ENXIO;
11478ee8d1cSJulian Grajkowski 	}
11578ee8d1cSJulian Grajkowski 
11678ee8d1cSJulian Grajkowski 	/* Allocate and configure device configuration structure */
11778ee8d1cSJulian Grajkowski 	hw_data = malloc(sizeof(*hw_data), M_QAT_C4XXX, M_WAITOK | M_ZERO);
11878ee8d1cSJulian Grajkowski 
11978ee8d1cSJulian Grajkowski 	accel_dev->hw_device = hw_data;
12078ee8d1cSJulian Grajkowski 	adf_init_hw_data_c4xxx(accel_dev->hw_device);
12178ee8d1cSJulian Grajkowski 	accel_pci_dev->revid = pci_get_revid(dev);
12278ee8d1cSJulian Grajkowski 	hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4);
12378ee8d1cSJulian Grajkowski 
12478ee8d1cSJulian Grajkowski 	/* Get PPAERUCM values and store */
12578ee8d1cSJulian Grajkowski 	ret = adf_aer_store_ppaerucm_reg(dev, hw_data);
12678ee8d1cSJulian Grajkowski 	if (ret)
12778ee8d1cSJulian Grajkowski 		goto out_err;
12878ee8d1cSJulian Grajkowski 
12978ee8d1cSJulian Grajkowski 	/* Get Accelerators and Accelerators Engines masks */
13078ee8d1cSJulian Grajkowski 	hw_data->accel_mask = hw_data->get_accel_mask(accel_dev);
13178ee8d1cSJulian Grajkowski 	hw_data->ae_mask = hw_data->get_ae_mask(accel_dev);
132*a977168cSMichal Gulbicki 	hw_data->admin_ae_mask = hw_data->ae_mask;
13378ee8d1cSJulian Grajkowski 
13478ee8d1cSJulian Grajkowski 	/* If the device has no acceleration engines then ignore it. */
13578ee8d1cSJulian Grajkowski 	if (!hw_data->accel_mask || !hw_data->ae_mask ||
13678ee8d1cSJulian Grajkowski 	    (~hw_data->ae_mask & 0x01)) {
13778ee8d1cSJulian Grajkowski 		device_printf(dev, "No acceleration units found\n");
13878ee8d1cSJulian Grajkowski 		ret = ENXIO;
13978ee8d1cSJulian Grajkowski 		goto out_err;
14078ee8d1cSJulian Grajkowski 	}
14178ee8d1cSJulian Grajkowski 
14278ee8d1cSJulian Grajkowski 	/* Create device configuration table */
14378ee8d1cSJulian Grajkowski 	ret = adf_cfg_dev_add(accel_dev);
14478ee8d1cSJulian Grajkowski 	if (ret)
14578ee8d1cSJulian Grajkowski 		goto out_err;
14678ee8d1cSJulian Grajkowski 
14778ee8d1cSJulian Grajkowski 	ret = adf_clock_debugfs_add(accel_dev);
14878ee8d1cSJulian Grajkowski 	if (ret)
14978ee8d1cSJulian Grajkowski 		goto out_err;
15078ee8d1cSJulian Grajkowski 
15178ee8d1cSJulian Grajkowski 	pci_set_max_read_req(dev, 1024);
15278ee8d1cSJulian Grajkowski 
15378ee8d1cSJulian Grajkowski 	ret = bus_dma_tag_create(bus_get_dma_tag(dev),
15478ee8d1cSJulian Grajkowski 				 1,
15578ee8d1cSJulian Grajkowski 				 0,
15678ee8d1cSJulian Grajkowski 				 BUS_SPACE_MAXADDR,
15778ee8d1cSJulian Grajkowski 				 BUS_SPACE_MAXADDR,
15878ee8d1cSJulian Grajkowski 				 NULL,
15978ee8d1cSJulian Grajkowski 				 NULL,
16078ee8d1cSJulian Grajkowski 				 BUS_SPACE_MAXSIZE,
16178ee8d1cSJulian Grajkowski 				 /*BUS_SPACE_UNRESTRICTED*/ 1,
16278ee8d1cSJulian Grajkowski 				 BUS_SPACE_MAXSIZE,
16378ee8d1cSJulian Grajkowski 				 0,
16478ee8d1cSJulian Grajkowski 				 NULL,
16578ee8d1cSJulian Grajkowski 				 NULL,
16678ee8d1cSJulian Grajkowski 				 &accel_dev->dma_tag);
16778ee8d1cSJulian Grajkowski 	if (ret)
16878ee8d1cSJulian Grajkowski 		goto out_err;
16978ee8d1cSJulian Grajkowski 
17078ee8d1cSJulian Grajkowski 	if (hw_data->get_accel_cap) {
17178ee8d1cSJulian Grajkowski 		hw_data->accel_capabilities_mask =
17278ee8d1cSJulian Grajkowski 		    hw_data->get_accel_cap(accel_dev);
17378ee8d1cSJulian Grajkowski 	}
17478ee8d1cSJulian Grajkowski 
17578ee8d1cSJulian Grajkowski 	accel_pci_dev->sku = hw_data->get_sku(hw_data);
17678ee8d1cSJulian Grajkowski 
17778ee8d1cSJulian Grajkowski 	/* Find and map all the device's BARS */
17878ee8d1cSJulian Grajkowski 	i = 0;
17978ee8d1cSJulian Grajkowski 	for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0;
18078ee8d1cSJulian Grajkowski 	     bar_nr++) {
18178ee8d1cSJulian Grajkowski 		struct adf_bar *bar;
18278ee8d1cSJulian Grajkowski 
18378ee8d1cSJulian Grajkowski 		/*
18478ee8d1cSJulian Grajkowski 		 * XXX: This isn't quite right as it will ignore a BAR
18578ee8d1cSJulian Grajkowski 		 * that wasn't assigned a valid resource range by the
18678ee8d1cSJulian Grajkowski 		 * firmware.
18778ee8d1cSJulian Grajkowski 		 */
18878ee8d1cSJulian Grajkowski 		rid = PCIR_BAR(bar_nr);
18978ee8d1cSJulian Grajkowski 		if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0)
19078ee8d1cSJulian Grajkowski 			continue;
19178ee8d1cSJulian Grajkowski 		bar = &accel_pci_dev->pci_bars[i++];
19278ee8d1cSJulian Grajkowski 		bar->virt_addr = bus_alloc_resource_any(dev,
19378ee8d1cSJulian Grajkowski 							SYS_RES_MEMORY,
19478ee8d1cSJulian Grajkowski 							&rid,
19578ee8d1cSJulian Grajkowski 							RF_ACTIVE);
19678ee8d1cSJulian Grajkowski 		if (!bar->virt_addr) {
19778ee8d1cSJulian Grajkowski 			device_printf(dev, "Failed to map BAR %d\n", bar_nr);
19878ee8d1cSJulian Grajkowski 			ret = ENXIO;
19978ee8d1cSJulian Grajkowski 			goto out_err;
20078ee8d1cSJulian Grajkowski 		}
20178ee8d1cSJulian Grajkowski 		bar->base_addr = rman_get_start(bar->virt_addr);
20278ee8d1cSJulian Grajkowski 		bar->size = rman_get_start(bar->virt_addr);
20378ee8d1cSJulian Grajkowski 	}
20478ee8d1cSJulian Grajkowski 	pci_enable_busmaster(dev);
20578ee8d1cSJulian Grajkowski 
20678ee8d1cSJulian Grajkowski 	if (!accel_dev->hw_device->config_device) {
20778ee8d1cSJulian Grajkowski 		ret = EFAULT;
20878ee8d1cSJulian Grajkowski 		goto out_err;
20978ee8d1cSJulian Grajkowski 	}
21078ee8d1cSJulian Grajkowski 
21178ee8d1cSJulian Grajkowski 	ret = accel_dev->hw_device->config_device(accel_dev);
21278ee8d1cSJulian Grajkowski 	if (ret)
21378ee8d1cSJulian Grajkowski 		goto out_err;
21478ee8d1cSJulian Grajkowski 
21578ee8d1cSJulian Grajkowski 	ret = adf_dev_init(accel_dev);
21678ee8d1cSJulian Grajkowski 	if (ret)
21778ee8d1cSJulian Grajkowski 		goto out_dev_shutdown;
21878ee8d1cSJulian Grajkowski 
21978ee8d1cSJulian Grajkowski 	ret = adf_dev_start(accel_dev);
22078ee8d1cSJulian Grajkowski 	if (ret)
22178ee8d1cSJulian Grajkowski 		goto out_dev_stop;
22278ee8d1cSJulian Grajkowski 
22378ee8d1cSJulian Grajkowski 	cfg_dev = accel_dev->cfg->dev;
22478ee8d1cSJulian Grajkowski 	adf_cfg_device_clear(cfg_dev, accel_dev);
22578ee8d1cSJulian Grajkowski 	free(cfg_dev, M_QAT);
22678ee8d1cSJulian Grajkowski 	accel_dev->cfg->dev = NULL;
22778ee8d1cSJulian Grajkowski 	return ret;
22878ee8d1cSJulian Grajkowski out_dev_stop:
22978ee8d1cSJulian Grajkowski 	adf_dev_stop(accel_dev);
23078ee8d1cSJulian Grajkowski out_dev_shutdown:
23178ee8d1cSJulian Grajkowski 	adf_dev_shutdown(accel_dev);
23278ee8d1cSJulian Grajkowski out_err:
23378ee8d1cSJulian Grajkowski 	adf_cleanup_accel(accel_dev);
23478ee8d1cSJulian Grajkowski 	return ret;
23578ee8d1cSJulian Grajkowski }
23678ee8d1cSJulian Grajkowski 
23778ee8d1cSJulian Grajkowski static int
adf_detach(device_t dev)23878ee8d1cSJulian Grajkowski adf_detach(device_t dev)
23978ee8d1cSJulian Grajkowski {
24078ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = device_get_softc(dev);
24178ee8d1cSJulian Grajkowski 
24278ee8d1cSJulian Grajkowski 	if (adf_dev_stop(accel_dev)) {
24378ee8d1cSJulian Grajkowski 		device_printf(dev, "Failed to stop QAT accel dev\n");
24478ee8d1cSJulian Grajkowski 		return EBUSY;
24578ee8d1cSJulian Grajkowski 	}
24678ee8d1cSJulian Grajkowski 
24778ee8d1cSJulian Grajkowski 	adf_dev_shutdown(accel_dev);
24878ee8d1cSJulian Grajkowski 
24978ee8d1cSJulian Grajkowski 	adf_cleanup_accel(accel_dev);
25078ee8d1cSJulian Grajkowski 
25178ee8d1cSJulian Grajkowski 	return 0;
25278ee8d1cSJulian Grajkowski }
25378ee8d1cSJulian Grajkowski 
25478ee8d1cSJulian Grajkowski static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe),
25578ee8d1cSJulian Grajkowski 					 DEVMETHOD(device_attach, adf_attach),
25678ee8d1cSJulian Grajkowski 					 DEVMETHOD(device_detach, adf_detach),
25778ee8d1cSJulian Grajkowski 
25878ee8d1cSJulian Grajkowski 					 DEVMETHOD_END };
25978ee8d1cSJulian Grajkowski 
26078ee8d1cSJulian Grajkowski static driver_t adf_driver = { "qat",
26178ee8d1cSJulian Grajkowski 			       adf_methods,
26278ee8d1cSJulian Grajkowski 			       sizeof(struct adf_accel_dev) };
26378ee8d1cSJulian Grajkowski 
26478ee8d1cSJulian Grajkowski DRIVER_MODULE_ORDERED(qat_c4xxx, pci, adf_driver, NULL, NULL, SI_ORDER_THIRD);
26578ee8d1cSJulian Grajkowski MODULE_VERSION(qat_c4xxx, 1);
26678ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_c4xxx, qat_common, 1, 1, 1);
26778ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_c4xxx, qat_api, 1, 1, 1);
26878ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_c4xxx, linuxkpi, 1, 1, 1);
269