1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include "adf_accel_devices.h"
5 #include "adf_common_drv.h"
6 #include "adf_cfg_common.h"
7 #include "adf_transport_internal.h"
8 #include "icp_qat_hw.h"
9 #include "adf_c4xxx_hw_data.h"
10 
11 #define ADF_C4XXX_PARTTITION_SHIFT 8
12 #define ADF_C4XXX_PARTITION(svc, ring)                                         \
13 	((svc) << ((ring)*ADF_C4XXX_PARTTITION_SHIFT))
14 
15 static void
16 adf_get_partitions_mask(struct adf_accel_dev *accel_dev, u32 *partitions_mask)
17 {
18 	device_t dev = accel_to_pci_dev(accel_dev);
19 	u32 enabled_partitions_msk = 0;
20 	u8 ring_pair = 0;
21 	enum adf_cfg_service_type serv_type = 0;
22 	u16 ring_to_svc_map = accel_dev->hw_device->ring_to_svc_map;
23 
24 	for (ring_pair = 0; ring_pair < ADF_CFG_NUM_SERVICES; ring_pair++) {
25 		serv_type = GET_SRV_TYPE(ring_to_svc_map, ring_pair);
26 		switch (serv_type) {
27 		case CRYPTO: {
28 			enabled_partitions_msk |=
29 			    ADF_C4XXX_PARTITION(ADF_C4XXX_PART_ASYM,
30 						ring_pair++);
31 			if (ring_pair < ADF_CFG_NUM_SERVICES)
32 				enabled_partitions_msk |=
33 				    ADF_C4XXX_PARTITION(ADF_C4XXX_PART_SYM,
34 							ring_pair);
35 			else
36 				device_printf(
37 				    dev, "Failed to enable SYM partition.\n");
38 			break;
39 		}
40 		case COMP:
41 			enabled_partitions_msk |=
42 			    ADF_C4XXX_PARTITION(ADF_C4XXX_PART_DC, ring_pair);
43 			break;
44 		case SYM:
45 			enabled_partitions_msk |=
46 			    ADF_C4XXX_PARTITION(ADF_C4XXX_PART_SYM, ring_pair);
47 			break;
48 		case ASYM:
49 			enabled_partitions_msk |=
50 			    ADF_C4XXX_PARTITION(ADF_C4XXX_PART_ASYM, ring_pair);
51 			break;
52 		default:
53 			enabled_partitions_msk |=
54 			    ADF_C4XXX_PARTITION(ADF_C4XXX_PART_UNUSED,
55 						ring_pair);
56 			break;
57 		}
58 	}
59 	*partitions_mask = enabled_partitions_msk;
60 }
61 
62 static void
63 adf_enable_sym_threads(struct adf_accel_dev *accel_dev, u32 ae, u32 partition)
64 {
65 	struct resource *csr = accel_dev->transport->banks[0].csr_addr;
66 	const struct adf_ae_info *ae_info = accel_dev->au_info->ae_info;
67 	u32 num_sym_thds = ae_info[ae].num_sym_thd;
68 	u32 i;
69 	u32 part_group = partition / ADF_C4XXX_PARTS_PER_GRP;
70 	u32 wkrthd2_partmap = part_group << ADF_C4XXX_PARTS_PER_GRP |
71 	    (BIT(partition % ADF_C4XXX_PARTS_PER_GRP));
72 
73 	for (i = 0; i < num_sym_thds; i++)
74 		WRITE_CSR_WQM(csr,
75 			      ADF_C4XXX_WRKTHD2PARTMAP,
76 			      (ae * ADF_NUM_THREADS_PER_AE + i),
77 			      wkrthd2_partmap);
78 }
79 
80 static void
81 adf_enable_asym_threads(struct adf_accel_dev *accel_dev, u32 ae, u32 partition)
82 {
83 	struct resource *csr = accel_dev->transport->banks[0].csr_addr;
84 	const struct adf_ae_info *ae_info = accel_dev->au_info->ae_info;
85 	u32 num_asym_thds = ae_info[ae].num_asym_thd;
86 	u32 i;
87 	u32 part_group = partition / ADF_C4XXX_PARTS_PER_GRP;
88 	u32 wkrthd2_partmap = part_group << ADF_C4XXX_PARTS_PER_GRP |
89 	    (BIT(partition % ADF_C4XXX_PARTS_PER_GRP));
90 	/* For asymmetric cryptography SKU we have one thread less */
91 	u32 num_all_thds = ADF_NUM_THREADS_PER_AE - 2;
92 
93 	for (i = num_all_thds; i > (num_all_thds - num_asym_thds); i--)
94 		WRITE_CSR_WQM(csr,
95 			      ADF_C4XXX_WRKTHD2PARTMAP,
96 			      (ae * ADF_NUM_THREADS_PER_AE + i),
97 			      wkrthd2_partmap);
98 }
99 
100 static void
101 adf_enable_dc_threads(struct adf_accel_dev *accel_dev, u32 ae, u32 partition)
102 {
103 	struct resource *csr = accel_dev->transport->banks[0].csr_addr;
104 	const struct adf_ae_info *ae_info = accel_dev->au_info->ae_info;
105 	u32 num_dc_thds = ae_info[ae].num_dc_thd;
106 	u32 i;
107 	u32 part_group = partition / ADF_C4XXX_PARTS_PER_GRP;
108 	u32 wkrthd2_partmap = part_group << ADF_C4XXX_PARTS_PER_GRP |
109 	    (BIT(partition % ADF_C4XXX_PARTS_PER_GRP));
110 
111 	for (i = 0; i < num_dc_thds; i++)
112 		WRITE_CSR_WQM(csr,
113 			      ADF_C4XXX_WRKTHD2PARTMAP,
114 			      (ae * ADF_NUM_THREADS_PER_AE + i),
115 			      wkrthd2_partmap);
116 }
117 
118 /* Initialise Resource partitioning.
119  * Initialise a default set of 4 partitions to arbitrate
120  * request rings per bundle.
121  */
122 int
123 adf_init_arb_c4xxx(struct adf_accel_dev *accel_dev)
124 {
125 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
126 	struct resource *csr = accel_dev->transport->banks[0].csr_addr;
127 	struct adf_accel_unit_info *au_info = accel_dev->au_info;
128 	u32 i;
129 	unsigned long ae_mask;
130 	u32 partitions_mask = 0;
131 
132 	/* invoke common adf_init_arb */
133 	adf_init_arb(accel_dev);
134 
135 	adf_get_partitions_mask(accel_dev, &partitions_mask);
136 	for (i = 0; i < hw_data->num_banks; i++)
137 		WRITE_CSR_WQM(csr,
138 			      ADF_C4XXX_PARTITION_LUT_OFFSET,
139 			      i,
140 			      partitions_mask);
141 
142 	ae_mask = hw_data->ae_mask;
143 
144 	/* Assigning default partitions to accel engine
145 	 * worker threads
146 	 */
147 	for_each_set_bit(i, &ae_mask, ADF_C4XXX_MAX_ACCELENGINES)
148 	{
149 		if (BIT(i) & au_info->sym_ae_msk)
150 			adf_enable_sym_threads(accel_dev,
151 					       i,
152 					       ADF_C4XXX_PART_SYM);
153 		if (BIT(i) & au_info->asym_ae_msk)
154 			adf_enable_asym_threads(accel_dev,
155 						i,
156 						ADF_C4XXX_PART_ASYM);
157 		if (BIT(i) & au_info->dc_ae_msk)
158 			adf_enable_dc_threads(accel_dev, i, ADF_C4XXX_PART_DC);
159 	}
160 
161 	return 0;
162 }
163 
164 /* Disable the resource partitioning feature
165  * and restore the default partitioning scheme
166  */
167 void
168 adf_exit_arb_c4xxx(struct adf_accel_dev *accel_dev)
169 {
170 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
171 	struct resource *csr;
172 	u32 i;
173 	unsigned long ae_mask;
174 
175 	if (!accel_dev->transport)
176 		return;
177 	csr = accel_dev->transport->banks[0].csr_addr;
178 
179 	/* Restore the default partitionLUT registers */
180 	for (i = 0; i < hw_data->num_banks; i++)
181 		WRITE_CSR_WQM(csr,
182 			      ADF_C4XXX_PARTITION_LUT_OFFSET,
183 			      i,
184 			      ADF_C4XXX_DEFAULT_PARTITIONS);
185 
186 	ae_mask = hw_data->ae_mask;
187 
188 	/* Reset worker thread to partition mapping */
189 	for (i = 0; i < hw_data->num_engines * ADF_NUM_THREADS_PER_AE; i++) {
190 		if (!test_bit((u32)(i / ADF_NUM_THREADS_PER_AE), &ae_mask))
191 			continue;
192 
193 		WRITE_CSR_WQM(csr, ADF_C4XXX_WRKTHD2PARTMAP, i, 0);
194 	}
195 }
196