1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include <dev/pci/pcireg.h>
5 #include "adf_c4xxx_reset.h"
6 
7 static void
8 adf_check_uncorr_status(struct adf_accel_dev *accel_dev)
9 {
10 	u32 uncorr_err;
11 	device_t pdev = accel_dev->accel_pci_dev.pci_dev;
12 
13 	uncorr_err = pci_read_config(pdev, PCI_EXP_AERUCS, 4);
14 	if (uncorr_err & PCIE_C4XXX_VALID_ERR_MASK) {
15 		device_printf(GET_DEV(accel_dev),
16 			      "Uncorrectable error occurred during reset\n");
17 		device_printf(GET_DEV(accel_dev),
18 			      "Error code value: 0x%04x\n",
19 			      uncorr_err);
20 	}
21 }
22 
23 static void
24 adf_c4xxx_dev_reset(struct adf_accel_dev *accel_dev)
25 {
26 	device_t pdev = accel_dev->accel_pci_dev.pci_dev;
27 	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
28 	u8 count = 0;
29 	uintptr_t device_id1;
30 	uintptr_t device_id2;
31 
32 	/* Read device ID before triggering reset */
33 	device_id1 = pci_read_config(pdev, PCIR_DEVICE, 2);
34 	hw_device->reset_device(accel_dev);
35 
36 	/* Wait for reset to complete */
37 	do {
38 		/* Ensure we have the configuration space restored */
39 		device_id2 = pci_read_config(pdev, PCIR_DEVICE, 2);
40 		if (device_id1 == device_id2) {
41 			/* Check if a PCIe uncorrectable error occurred
42 			 * during the reset
43 			 */
44 			adf_check_uncorr_status(accel_dev);
45 			return;
46 		}
47 		count++;
48 		pause_ms("adfstop", 100);
49 	} while (count < ADF_PCIE_FLR_ATTEMPT);
50 	device_printf(GET_DEV(accel_dev),
51 		      "Too many attempts to read back config space.\n");
52 }
53 
54 void
55 adf_c4xxx_dev_restore(struct adf_accel_dev *accel_dev)
56 {
57 	struct adf_hw_device_data *hw_device = accel_dev->hw_device;
58 	device_t pdev = accel_dev->accel_pci_dev.pci_dev;
59 	u32 pmisclbar1;
60 	u32 pmisclbar2;
61 	u32 pmiscubar1;
62 	u32 pmiscubar2;
63 
64 	if (hw_device->reset_device) {
65 		device_printf(GET_DEV(accel_dev),
66 			      "Resetting device qat_dev%d\n",
67 			      accel_dev->accel_id);
68 
69 		/* Read pmiscubar and pmisclbar */
70 		pmisclbar1 = pci_read_config(pdev, ADF_PMISC_L_OFFSET, 4);
71 		pmiscubar1 = pci_read_config(pdev, ADF_PMISC_U_OFFSET, 4);
72 
73 		adf_c4xxx_dev_reset(accel_dev);
74 		pci_restore_state(pdev);
75 
76 		/* Read pmiscubar and pmisclbar */
77 		pmisclbar2 = pci_read_config(pdev, ADF_PMISC_L_OFFSET, 4);
78 		pmiscubar2 = pci_read_config(pdev, ADF_PMISC_U_OFFSET, 4);
79 
80 		/* Check if restore operation has completed successfully */
81 		if (pmisclbar1 != pmisclbar2 || pmiscubar1 != pmiscubar2) {
82 			device_printf(
83 			    GET_DEV(accel_dev),
84 			    "Failed to restore device configuration\n");
85 			return;
86 		}
87 		pci_save_state(pdev);
88 	}
89 
90 	if (hw_device->post_reset) {
91 		dev_dbg(GET_DEV(accel_dev), "Performing post reset restore\n");
92 		hw_device->post_reset(accel_dev);
93 	}
94 }
95