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_dh895xcc_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_DH895XCC, "qat_dh895xcc", "qat_dh895xcc");
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_DH895XCC_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_DH895XCC_DEVICE_NAME
4178ee8d1cSJulian Grajkowski " QuickAssist");
4278ee8d1cSJulian Grajkowski return BUS_PROBE_DEFAULT;
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_DH895XCC_PCI_DEVICE_ID:
6878ee8d1cSJulian Grajkowski adf_clean_hw_data_dh895xcc(accel_dev->hw_device);
6978ee8d1cSJulian Grajkowski break;
7078ee8d1cSJulian Grajkowski default:
7178ee8d1cSJulian Grajkowski break;
7278ee8d1cSJulian Grajkowski }
7378ee8d1cSJulian Grajkowski free(accel_dev->hw_device, M_QAT_DH895XCC);
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 if (pci_get_max_payload(dev) != 256)
9478ee8d1cSJulian Grajkowski pci_set_max_payload(dev, 256);
9578ee8d1cSJulian Grajkowski
9678ee8d1cSJulian Grajkowski accel_dev = device_get_softc(dev);
9778ee8d1cSJulian Grajkowski
9878ee8d1cSJulian Grajkowski INIT_LIST_HEAD(&accel_dev->crypto_list);
9978ee8d1cSJulian Grajkowski accel_pci_dev = &accel_dev->accel_pci_dev;
10078ee8d1cSJulian Grajkowski accel_pci_dev->pci_dev = dev;
10178ee8d1cSJulian Grajkowski
10278ee8d1cSJulian Grajkowski if (bus_get_domain(dev, &accel_pci_dev->node) != 0)
10378ee8d1cSJulian Grajkowski accel_pci_dev->node = 0;
10478ee8d1cSJulian Grajkowski
10578ee8d1cSJulian Grajkowski /* Add accel device to accel table.
10678ee8d1cSJulian Grajkowski * This should be called before adf_cleanup_accel is called */
10778ee8d1cSJulian Grajkowski if (adf_devmgr_add_dev(accel_dev, NULL)) {
10878ee8d1cSJulian Grajkowski device_printf(dev, "Failed to add new accelerator device.\n");
10978ee8d1cSJulian Grajkowski return ENXIO;
11078ee8d1cSJulian Grajkowski }
11178ee8d1cSJulian Grajkowski
11278ee8d1cSJulian Grajkowski /* Allocate and configure device configuration structure */
11378ee8d1cSJulian Grajkowski hw_data = malloc(sizeof(*hw_data), M_QAT_DH895XCC, M_WAITOK | M_ZERO);
11478ee8d1cSJulian Grajkowski
11578ee8d1cSJulian Grajkowski accel_dev->hw_device = hw_data;
11678ee8d1cSJulian Grajkowski adf_init_hw_data_dh895xcc(accel_dev->hw_device);
11778ee8d1cSJulian Grajkowski accel_pci_dev->revid = pci_get_revid(dev);
11878ee8d1cSJulian Grajkowski hw_data->fuses = pci_read_config(dev, ADF_DEVICE_FUSECTL_OFFSET, 4);
11978ee8d1cSJulian Grajkowski
12078ee8d1cSJulian Grajkowski /* Get PPAERUCM values and store */
12178ee8d1cSJulian Grajkowski ret = adf_aer_store_ppaerucm_reg(dev, hw_data);
12278ee8d1cSJulian Grajkowski if (ret)
12378ee8d1cSJulian Grajkowski goto out_err;
12478ee8d1cSJulian Grajkowski
12578ee8d1cSJulian Grajkowski /* Get Accelerators and Accelerators Engines masks */
12678ee8d1cSJulian Grajkowski hw_data->accel_mask = hw_data->get_accel_mask(accel_dev);
12778ee8d1cSJulian Grajkowski hw_data->ae_mask = hw_data->get_ae_mask(accel_dev);
128*a977168cSMichal Gulbicki hw_data->admin_ae_mask = hw_data->ae_mask;
12978ee8d1cSJulian Grajkowski accel_pci_dev->sku = hw_data->get_sku(hw_data);
13078ee8d1cSJulian Grajkowski /* If the device has no acceleration engines then ignore it. */
13178ee8d1cSJulian Grajkowski if (!hw_data->accel_mask || !hw_data->ae_mask ||
13278ee8d1cSJulian Grajkowski ((~hw_data->ae_mask) & 0x01)) {
13378ee8d1cSJulian Grajkowski device_printf(dev, "No acceleration units found\n");
13478ee8d1cSJulian Grajkowski ret = ENXIO;
13578ee8d1cSJulian Grajkowski goto out_err;
13678ee8d1cSJulian Grajkowski }
13778ee8d1cSJulian Grajkowski
13878ee8d1cSJulian Grajkowski /* Create device configuration table */
13978ee8d1cSJulian Grajkowski ret = adf_cfg_dev_add(accel_dev);
14078ee8d1cSJulian Grajkowski if (ret)
14178ee8d1cSJulian Grajkowski goto out_err;
14278ee8d1cSJulian Grajkowski
14378ee8d1cSJulian Grajkowski pci_set_max_read_req(dev, 1024);
14478ee8d1cSJulian Grajkowski
14578ee8d1cSJulian Grajkowski ret = bus_dma_tag_create(bus_get_dma_tag(dev),
14678ee8d1cSJulian Grajkowski 1,
14778ee8d1cSJulian Grajkowski 0,
14878ee8d1cSJulian Grajkowski BUS_SPACE_MAXADDR,
14978ee8d1cSJulian Grajkowski BUS_SPACE_MAXADDR,
15078ee8d1cSJulian Grajkowski NULL,
15178ee8d1cSJulian Grajkowski NULL,
15278ee8d1cSJulian Grajkowski BUS_SPACE_MAXSIZE,
15378ee8d1cSJulian Grajkowski /* BUS_SPACE_UNRESTRICTED */ 1,
15478ee8d1cSJulian Grajkowski BUS_SPACE_MAXSIZE,
15578ee8d1cSJulian Grajkowski 0,
15678ee8d1cSJulian Grajkowski NULL,
15778ee8d1cSJulian Grajkowski NULL,
15878ee8d1cSJulian Grajkowski &accel_dev->dma_tag);
15978ee8d1cSJulian Grajkowski if (ret)
16078ee8d1cSJulian Grajkowski goto out_err;
16178ee8d1cSJulian Grajkowski
16278ee8d1cSJulian Grajkowski if (hw_data->get_accel_cap) {
16378ee8d1cSJulian Grajkowski hw_data->accel_capabilities_mask =
16478ee8d1cSJulian Grajkowski hw_data->get_accel_cap(accel_dev);
16578ee8d1cSJulian Grajkowski }
16678ee8d1cSJulian Grajkowski
16778ee8d1cSJulian Grajkowski /* Find and map all the device's BARS */
16878ee8d1cSJulian Grajkowski i = 0;
16978ee8d1cSJulian Grajkowski for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0;
17078ee8d1cSJulian Grajkowski bar_nr++) {
17178ee8d1cSJulian Grajkowski struct adf_bar *bar;
17278ee8d1cSJulian Grajkowski
17378ee8d1cSJulian Grajkowski /*
17478ee8d1cSJulian Grajkowski * This will ignore a BAR
17578ee8d1cSJulian Grajkowski * that wasn't assigned a valid resource range by the
17678ee8d1cSJulian Grajkowski * firmware.
17778ee8d1cSJulian Grajkowski */
17878ee8d1cSJulian Grajkowski rid = PCIR_BAR(bar_nr);
17978ee8d1cSJulian Grajkowski if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0)
18078ee8d1cSJulian Grajkowski continue;
18178ee8d1cSJulian Grajkowski bar = &accel_pci_dev->pci_bars[i++];
18278ee8d1cSJulian Grajkowski bar->virt_addr = bus_alloc_resource_any(dev,
18378ee8d1cSJulian Grajkowski SYS_RES_MEMORY,
18478ee8d1cSJulian Grajkowski &rid,
18578ee8d1cSJulian Grajkowski RF_ACTIVE);
18678ee8d1cSJulian Grajkowski if (bar->virt_addr == NULL) {
18778ee8d1cSJulian Grajkowski device_printf(dev, "Failed to map BAR %d\n", bar_nr);
18878ee8d1cSJulian Grajkowski ret = ENXIO;
18978ee8d1cSJulian Grajkowski goto out_err;
19078ee8d1cSJulian Grajkowski }
19178ee8d1cSJulian Grajkowski bar->base_addr = rman_get_start(bar->virt_addr);
19278ee8d1cSJulian Grajkowski bar->size = rman_get_size(bar->virt_addr);
19378ee8d1cSJulian Grajkowski }
19478ee8d1cSJulian Grajkowski pci_enable_busmaster(dev);
19578ee8d1cSJulian Grajkowski
19678ee8d1cSJulian Grajkowski if (!accel_dev->hw_device->config_device) {
19778ee8d1cSJulian Grajkowski ret = EFAULT;
19878ee8d1cSJulian Grajkowski goto out_err;
19978ee8d1cSJulian Grajkowski }
20078ee8d1cSJulian Grajkowski
20178ee8d1cSJulian Grajkowski ret = accel_dev->hw_device->config_device(accel_dev);
20278ee8d1cSJulian Grajkowski if (ret)
20378ee8d1cSJulian Grajkowski goto out_err;
20478ee8d1cSJulian Grajkowski
20578ee8d1cSJulian Grajkowski ret = adf_dev_init(accel_dev);
20678ee8d1cSJulian Grajkowski if (ret)
20778ee8d1cSJulian Grajkowski goto out_dev_shutdown;
20878ee8d1cSJulian Grajkowski
20978ee8d1cSJulian Grajkowski ret = adf_dev_start(accel_dev);
21078ee8d1cSJulian Grajkowski if (ret)
21178ee8d1cSJulian Grajkowski goto out_dev_stop;
21278ee8d1cSJulian Grajkowski
21378ee8d1cSJulian Grajkowski cfg_dev = accel_dev->cfg->dev;
21478ee8d1cSJulian Grajkowski adf_cfg_device_clear(cfg_dev, accel_dev);
21578ee8d1cSJulian Grajkowski free(cfg_dev, M_QAT);
21678ee8d1cSJulian Grajkowski accel_dev->cfg->dev = NULL;
21778ee8d1cSJulian Grajkowski return ret;
21878ee8d1cSJulian Grajkowski out_dev_stop:
21978ee8d1cSJulian Grajkowski adf_dev_stop(accel_dev);
22078ee8d1cSJulian Grajkowski out_dev_shutdown:
22178ee8d1cSJulian Grajkowski adf_dev_shutdown(accel_dev);
22278ee8d1cSJulian Grajkowski out_err:
22378ee8d1cSJulian Grajkowski adf_cleanup_accel(accel_dev);
22478ee8d1cSJulian Grajkowski return ret;
22578ee8d1cSJulian Grajkowski }
22678ee8d1cSJulian Grajkowski
22778ee8d1cSJulian Grajkowski static int
adf_detach(device_t dev)22878ee8d1cSJulian Grajkowski adf_detach(device_t dev)
22978ee8d1cSJulian Grajkowski {
23078ee8d1cSJulian Grajkowski struct adf_accel_dev *accel_dev = device_get_softc(dev);
23178ee8d1cSJulian Grajkowski
23278ee8d1cSJulian Grajkowski if (adf_dev_stop(accel_dev)) {
23378ee8d1cSJulian Grajkowski device_printf(dev, "Failed to stop QAT accel dev\n");
23478ee8d1cSJulian Grajkowski return EBUSY;
23578ee8d1cSJulian Grajkowski }
23678ee8d1cSJulian Grajkowski
23778ee8d1cSJulian Grajkowski adf_dev_shutdown(accel_dev);
23878ee8d1cSJulian Grajkowski
23978ee8d1cSJulian Grajkowski adf_cleanup_accel(accel_dev);
24078ee8d1cSJulian Grajkowski return 0;
24178ee8d1cSJulian Grajkowski }
24278ee8d1cSJulian Grajkowski
24378ee8d1cSJulian Grajkowski static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe),
24478ee8d1cSJulian Grajkowski DEVMETHOD(device_attach, adf_attach),
24578ee8d1cSJulian Grajkowski DEVMETHOD(device_detach, adf_detach),
24678ee8d1cSJulian Grajkowski
24778ee8d1cSJulian Grajkowski DEVMETHOD_END };
24878ee8d1cSJulian Grajkowski
24978ee8d1cSJulian Grajkowski static driver_t adf_driver = { "qat",
25078ee8d1cSJulian Grajkowski adf_methods,
25178ee8d1cSJulian Grajkowski sizeof(struct adf_accel_dev) };
25278ee8d1cSJulian Grajkowski
25378ee8d1cSJulian Grajkowski DRIVER_MODULE_ORDERED(qat_dh895xcc,
25478ee8d1cSJulian Grajkowski pci,
25578ee8d1cSJulian Grajkowski adf_driver,
25678ee8d1cSJulian Grajkowski NULL,
25778ee8d1cSJulian Grajkowski NULL,
25878ee8d1cSJulian Grajkowski SI_ORDER_THIRD);
25978ee8d1cSJulian Grajkowski MODULE_VERSION(qat_dh895xcc, 1);
26078ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_dh895xcc, qat_common, 1, 1, 1);
26178ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_dh895xcc, qat_api, 1, 1, 1);
26278ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_dh895xcc, linuxkpi, 1, 1, 1);
263