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_200xx_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_200XX, "qat_200xx", "qat_200xx");
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_200XX_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_200XX_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_200XX_PCI_DEVICE_ID:
6878ee8d1cSJulian Grajkowski adf_clean_hw_data_200xx(accel_dev->hw_device);
6978ee8d1cSJulian Grajkowski break;
7078ee8d1cSJulian Grajkowski default:
7178ee8d1cSJulian Grajkowski break;
7278ee8d1cSJulian Grajkowski }
7378ee8d1cSJulian Grajkowski free(accel_dev->hw_device, M_QAT_200XX);
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 = 0, bar_nr = 0, reg_val = 0;
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_200XX, M_WAITOK | M_ZERO);
11878ee8d1cSJulian Grajkowski
11978ee8d1cSJulian Grajkowski accel_dev->hw_device = hw_data;
12078ee8d1cSJulian Grajkowski adf_init_hw_data_200xx(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 if (accel_pci_dev->revid == 0x00) {
12478ee8d1cSJulian Grajkowski device_printf(dev, "A0 stepping is not supported.\n");
12578ee8d1cSJulian Grajkowski ret = ENODEV;
12678ee8d1cSJulian Grajkowski goto out_err;
12778ee8d1cSJulian Grajkowski }
12878ee8d1cSJulian Grajkowski
12978ee8d1cSJulian Grajkowski /* Get PPAERUCM values and store */
13078ee8d1cSJulian Grajkowski ret = adf_aer_store_ppaerucm_reg(dev, hw_data);
13178ee8d1cSJulian Grajkowski if (ret)
13278ee8d1cSJulian Grajkowski goto out_err;
13378ee8d1cSJulian Grajkowski
13478ee8d1cSJulian Grajkowski /* Clear PFIEERRUNCSTSR register bits if they are set */
13578ee8d1cSJulian Grajkowski reg_val = pci_read_config(dev, ADF_200XX_PFIEERRUNCSTSR, 4);
13678ee8d1cSJulian Grajkowski if (reg_val) {
13778ee8d1cSJulian Grajkowski device_printf(
13878ee8d1cSJulian Grajkowski dev,
13978ee8d1cSJulian Grajkowski "Clearing PFIEERRUNCSTSR, previous status : %0x\n",
14078ee8d1cSJulian Grajkowski reg_val);
14178ee8d1cSJulian Grajkowski pci_write_config(dev, ADF_200XX_PFIEERRUNCSTSR, reg_val, 4);
14278ee8d1cSJulian Grajkowski }
14378ee8d1cSJulian Grajkowski
14478ee8d1cSJulian Grajkowski /* Get Accelerators and Accelerators Engines masks */
14578ee8d1cSJulian Grajkowski hw_data->accel_mask = hw_data->get_accel_mask(accel_dev);
14678ee8d1cSJulian Grajkowski hw_data->ae_mask = hw_data->get_ae_mask(accel_dev);
147*a977168cSMichal Gulbicki hw_data->admin_ae_mask = hw_data->ae_mask;
14878ee8d1cSJulian Grajkowski
14978ee8d1cSJulian Grajkowski accel_pci_dev->sku = hw_data->get_sku(hw_data);
15078ee8d1cSJulian Grajkowski /* If the device has no acceleration engines then ignore it. */
15178ee8d1cSJulian Grajkowski if (!hw_data->accel_mask || !hw_data->ae_mask ||
15278ee8d1cSJulian Grajkowski (~hw_data->ae_mask & 0x01)) {
15378ee8d1cSJulian Grajkowski device_printf(dev, "No acceleration units found\n");
15478ee8d1cSJulian Grajkowski ret = ENXIO;
15578ee8d1cSJulian Grajkowski goto out_err;
15678ee8d1cSJulian Grajkowski }
15778ee8d1cSJulian Grajkowski
15878ee8d1cSJulian Grajkowski /* Create device configuration table */
15978ee8d1cSJulian Grajkowski ret = adf_cfg_dev_add(accel_dev);
16078ee8d1cSJulian Grajkowski if (ret)
16178ee8d1cSJulian Grajkowski goto out_err;
16278ee8d1cSJulian Grajkowski ret = adf_clock_debugfs_add(accel_dev);
16378ee8d1cSJulian Grajkowski if (ret)
16478ee8d1cSJulian Grajkowski goto out_err;
16578ee8d1cSJulian Grajkowski
16678ee8d1cSJulian Grajkowski pci_set_max_read_req(dev, 1024);
16778ee8d1cSJulian Grajkowski
16878ee8d1cSJulian Grajkowski ret = bus_dma_tag_create(bus_get_dma_tag(dev),
16978ee8d1cSJulian Grajkowski 1,
17078ee8d1cSJulian Grajkowski 0,
17178ee8d1cSJulian Grajkowski BUS_SPACE_MAXADDR,
17278ee8d1cSJulian Grajkowski BUS_SPACE_MAXADDR,
17378ee8d1cSJulian Grajkowski NULL,
17478ee8d1cSJulian Grajkowski NULL,
17578ee8d1cSJulian Grajkowski BUS_SPACE_MAXSIZE,
17678ee8d1cSJulian Grajkowski /* BUS_SPACE_UNRESTRICTED */ 1,
17778ee8d1cSJulian Grajkowski BUS_SPACE_MAXSIZE,
17878ee8d1cSJulian Grajkowski 0,
17978ee8d1cSJulian Grajkowski NULL,
18078ee8d1cSJulian Grajkowski NULL,
18178ee8d1cSJulian Grajkowski &accel_dev->dma_tag);
18278ee8d1cSJulian Grajkowski if (ret)
18378ee8d1cSJulian Grajkowski goto out_err;
18478ee8d1cSJulian Grajkowski
18578ee8d1cSJulian Grajkowski if (hw_data->get_accel_cap) {
18678ee8d1cSJulian Grajkowski hw_data->accel_capabilities_mask =
18778ee8d1cSJulian Grajkowski hw_data->get_accel_cap(accel_dev);
18878ee8d1cSJulian Grajkowski }
18978ee8d1cSJulian Grajkowski
19078ee8d1cSJulian Grajkowski /* Find and map all the device's BARS */
19178ee8d1cSJulian Grajkowski for (bar_nr = 0; i < ADF_PCI_MAX_BARS && bar_nr < PCIR_MAX_BAR_0;
19278ee8d1cSJulian Grajkowski bar_nr++) {
19378ee8d1cSJulian Grajkowski struct adf_bar *bar;
19478ee8d1cSJulian Grajkowski
19578ee8d1cSJulian Grajkowski /*
19678ee8d1cSJulian Grajkowski * XXX: This isn't quite right as it will ignore a BAR
19778ee8d1cSJulian Grajkowski * that wasn't assigned a valid resource range by the
19878ee8d1cSJulian Grajkowski * firmware.
19978ee8d1cSJulian Grajkowski */
20078ee8d1cSJulian Grajkowski rid = PCIR_BAR(bar_nr);
20178ee8d1cSJulian Grajkowski if (bus_get_resource(dev, SYS_RES_MEMORY, rid, NULL, NULL) != 0)
20278ee8d1cSJulian Grajkowski continue;
20378ee8d1cSJulian Grajkowski bar = &accel_pci_dev->pci_bars[i++];
20478ee8d1cSJulian Grajkowski bar->virt_addr = bus_alloc_resource_any(dev,
20578ee8d1cSJulian Grajkowski SYS_RES_MEMORY,
20678ee8d1cSJulian Grajkowski &rid,
20778ee8d1cSJulian Grajkowski RF_ACTIVE);
20878ee8d1cSJulian Grajkowski if (!bar->virt_addr) {
20978ee8d1cSJulian Grajkowski device_printf(dev, "Failed to map BAR %d\n", bar_nr);
21078ee8d1cSJulian Grajkowski ret = ENXIO;
21178ee8d1cSJulian Grajkowski goto out_err;
21278ee8d1cSJulian Grajkowski }
21378ee8d1cSJulian Grajkowski bar->base_addr = rman_get_start(bar->virt_addr);
21478ee8d1cSJulian Grajkowski bar->size = rman_get_size(bar->virt_addr);
21578ee8d1cSJulian Grajkowski }
21678ee8d1cSJulian Grajkowski pci_enable_busmaster(dev);
21778ee8d1cSJulian Grajkowski
21878ee8d1cSJulian Grajkowski if (!accel_dev->hw_device->config_device) {
21978ee8d1cSJulian Grajkowski ret = EFAULT;
22078ee8d1cSJulian Grajkowski goto out_err;
22178ee8d1cSJulian Grajkowski }
22278ee8d1cSJulian Grajkowski
22378ee8d1cSJulian Grajkowski ret = accel_dev->hw_device->config_device(accel_dev);
22478ee8d1cSJulian Grajkowski if (ret)
22578ee8d1cSJulian Grajkowski goto out_err;
22678ee8d1cSJulian Grajkowski
22778ee8d1cSJulian Grajkowski ret = adf_dev_init(accel_dev);
22878ee8d1cSJulian Grajkowski if (ret)
22978ee8d1cSJulian Grajkowski goto out_dev_shutdown;
23078ee8d1cSJulian Grajkowski
23178ee8d1cSJulian Grajkowski ret = adf_dev_start(accel_dev);
23278ee8d1cSJulian Grajkowski if (ret)
23378ee8d1cSJulian Grajkowski goto out_dev_stop;
23478ee8d1cSJulian Grajkowski
23578ee8d1cSJulian Grajkowski cfg_dev = accel_dev->cfg->dev;
23678ee8d1cSJulian Grajkowski adf_cfg_device_clear(cfg_dev, accel_dev);
23778ee8d1cSJulian Grajkowski free(cfg_dev, M_QAT);
23878ee8d1cSJulian Grajkowski accel_dev->cfg->dev = NULL;
23978ee8d1cSJulian Grajkowski return ret;
24078ee8d1cSJulian Grajkowski out_dev_stop:
24178ee8d1cSJulian Grajkowski adf_dev_stop(accel_dev);
24278ee8d1cSJulian Grajkowski out_dev_shutdown:
24378ee8d1cSJulian Grajkowski adf_dev_shutdown(accel_dev);
24478ee8d1cSJulian Grajkowski out_err:
24578ee8d1cSJulian Grajkowski adf_cleanup_accel(accel_dev);
24678ee8d1cSJulian Grajkowski return ret;
24778ee8d1cSJulian Grajkowski }
24878ee8d1cSJulian Grajkowski
24978ee8d1cSJulian Grajkowski static int
adf_detach(device_t dev)25078ee8d1cSJulian Grajkowski adf_detach(device_t dev)
25178ee8d1cSJulian Grajkowski {
25278ee8d1cSJulian Grajkowski struct adf_accel_dev *accel_dev = device_get_softc(dev);
25378ee8d1cSJulian Grajkowski
25478ee8d1cSJulian Grajkowski if (adf_dev_stop(accel_dev)) {
25578ee8d1cSJulian Grajkowski device_printf(dev, "Failed to stop QAT accel dev\n");
25678ee8d1cSJulian Grajkowski return EBUSY;
25778ee8d1cSJulian Grajkowski }
25878ee8d1cSJulian Grajkowski
25978ee8d1cSJulian Grajkowski adf_dev_shutdown(accel_dev);
26078ee8d1cSJulian Grajkowski
26178ee8d1cSJulian Grajkowski adf_cleanup_accel(accel_dev);
26278ee8d1cSJulian Grajkowski
26378ee8d1cSJulian Grajkowski return 0;
26478ee8d1cSJulian Grajkowski }
26578ee8d1cSJulian Grajkowski
26678ee8d1cSJulian Grajkowski static device_method_t adf_methods[] = { DEVMETHOD(device_probe, adf_probe),
26778ee8d1cSJulian Grajkowski DEVMETHOD(device_attach, adf_attach),
26878ee8d1cSJulian Grajkowski DEVMETHOD(device_detach, adf_detach),
26978ee8d1cSJulian Grajkowski
27078ee8d1cSJulian Grajkowski DEVMETHOD_END };
27178ee8d1cSJulian Grajkowski
27278ee8d1cSJulian Grajkowski static driver_t adf_driver = { "qat",
27378ee8d1cSJulian Grajkowski adf_methods,
27478ee8d1cSJulian Grajkowski sizeof(struct adf_accel_dev) };
27578ee8d1cSJulian Grajkowski
27678ee8d1cSJulian Grajkowski DRIVER_MODULE_ORDERED(qat_200xx, pci, adf_driver, NULL, NULL, SI_ORDER_THIRD);
27778ee8d1cSJulian Grajkowski MODULE_VERSION(qat_200xx, 1);
27878ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_200xx, qat_common, 1, 1, 1);
27978ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_200xx, qat_api, 1, 1, 1);
28078ee8d1cSJulian Grajkowski MODULE_DEPEND(qat_200xx, linuxkpi, 1, 1, 1);
281