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