xref: /freebsd/sys/dev/qat/qat_common/adf_hw_arbiter.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include "qat_freebsd.h"
5 #include "adf_cfg.h"
6 #include "adf_common_drv.h"
7 #include "adf_accel_devices.h"
8 #include "icp_qat_uclo.h"
9 #include "icp_qat_fw.h"
10 #include "icp_qat_fw_init_admin.h"
11 #include "adf_cfg_strings.h"
12 #include "adf_transport_access_macros.h"
13 #include "adf_transport_internal.h"
14 #include "adf_accel_devices.h"
15 #include "adf_common_drv.h"
16 #include "adf_transport_internal.h"
17 
18 #define ADF_ARB_NUM 4
19 #define ADF_ARB_REG_SIZE 0x4
20 #define ADF_ARB_WTR_SIZE 0x20
21 #define ADF_ARB_OFFSET 0x30000
22 #define ADF_ARB_REG_SLOT 0x1000
23 #define ADF_ARB_WTR_OFFSET 0x010
24 #define ADF_ARB_RO_EN_OFFSET 0x090
25 #define ADF_ARB_WQCFG_OFFSET 0x100
26 #define ADF_ARB_WRK_2_SER_MAP_OFFSET 0x180
27 #define ADF_ARB_RINGSRVARBEN_OFFSET 0x19C
28 
29 #define WRITE_CSR_ARB_RINGSRVARBEN(csr_addr, index, value)                     \
30 	ADF_CSR_WR(csr_addr,                                                   \
31 		   ADF_ARB_RINGSRVARBEN_OFFSET + (ADF_ARB_REG_SLOT * (index)), \
32 		   value)
33 
34 #define WRITE_CSR_ARB_SARCONFIG(csr_addr, csr_offset, index, value)            \
35 	ADF_CSR_WR(csr_addr, (csr_offset) + (ADF_ARB_REG_SIZE * (index)), value)
36 #define READ_CSR_ARB_RINGSRVARBEN(csr_addr, index)                             \
37 	ADF_CSR_RD(csr_addr,                                                   \
38 		   ADF_ARB_RINGSRVARBEN_OFFSET + (ADF_ARB_REG_SLOT * (index)))
39 
40 static DEFINE_MUTEX(csr_arb_lock);
41 
42 #define WRITE_CSR_ARB_WRK_2_SER_MAP(                                           \
43     csr_addr, csr_offset, wrk_to_ser_map_offset, index, value)                 \
44 	ADF_CSR_WR(csr_addr,                                                   \
45 		   ((csr_offset) + (wrk_to_ser_map_offset)) +                  \
46 		       (ADF_ARB_REG_SIZE * (index)),                           \
47 		   value)
48 
49 int
50 adf_init_arb(struct adf_accel_dev *accel_dev)
51 {
52 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
53 	struct arb_info info;
54 	struct resource *csr = accel_dev->transport->banks[0].csr_addr;
55 	u32 arb_cfg = 0x1 << 31 | 0x4 << 4 | 0x1;
56 	u32 arb;
57 
58 	hw_data->get_arb_info(&info);
59 
60 	/* Service arb configured for 32 bytes responses and
61 	 * ring flow control check enabled.
62 	 */
63 	for (arb = 0; arb < ADF_ARB_NUM; arb++)
64 		WRITE_CSR_ARB_SARCONFIG(csr, info.arbiter_offset, arb, arb_cfg);
65 
66 	return 0;
67 }
68 
69 int
70 adf_init_gen2_arb(struct adf_accel_dev *accel_dev)
71 {
72 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
73 	struct arb_info info;
74 	struct resource *csr = accel_dev->transport->banks[0].csr_addr;
75 	u32 i;
76 	const u32 *thd_2_arb_cfg;
77 
78 	/* invoke common adf_init_arb */
79 	adf_init_arb(accel_dev);
80 
81 	hw_data->get_arb_info(&info);
82 
83 	/* Map worker threads to service arbiters */
84 	hw_data->get_arb_mapping(accel_dev, &thd_2_arb_cfg);
85 	if (!thd_2_arb_cfg)
86 		return EFAULT;
87 
88 	for (i = 0; i < hw_data->num_engines; i++)
89 		WRITE_CSR_ARB_WRK_2_SER_MAP(csr,
90 					    info.arbiter_offset,
91 					    info.wrk_thd_2_srv_arb_map,
92 					    i,
93 					    *(thd_2_arb_cfg + i));
94 	return 0;
95 }
96 
97 void
98 adf_update_ring_arb(struct adf_etr_ring_data *ring)
99 {
100 	int shift;
101 	u32 arben, arben_tx, arben_rx, arb_mask;
102 	struct adf_accel_dev *accel_dev = ring->bank->accel_dev;
103 	struct adf_hw_csr_info *csr_info = &accel_dev->hw_device->csr_info;
104 	struct adf_hw_csr_ops *csr_ops = &csr_info->csr_ops;
105 
106 	arb_mask = csr_info->arb_enable_mask;
107 	shift = hweight32(arb_mask);
108 
109 	arben_tx = ring->bank->ring_mask & arb_mask;
110 	arben_rx = (ring->bank->ring_mask >> shift) & arb_mask;
111 	arben = arben_tx & arben_rx;
112 	csr_ops->write_csr_ring_srv_arb_en(ring->bank->csr_addr,
113 					   ring->bank->bank_number,
114 					   arben);
115 }
116 
117 void
118 adf_enable_ring_arb(struct adf_accel_dev *accel_dev,
119 		    void *csr_addr,
120 		    unsigned int bank_nr,
121 		    unsigned int mask)
122 {
123 	struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
124 	struct resource *csr = csr_addr;
125 	u32 arbenable;
126 
127 	if (!csr)
128 		return;
129 
130 	mutex_lock(&csr_arb_lock);
131 	arbenable = csr_ops->read_csr_ring_srv_arb_en(csr, bank_nr);
132 	arbenable |= mask & 0xFF;
133 	csr_ops->write_csr_ring_srv_arb_en(csr, bank_nr, arbenable);
134 
135 	mutex_unlock(&csr_arb_lock);
136 }
137 
138 void
139 adf_disable_ring_arb(struct adf_accel_dev *accel_dev,
140 		     void *csr_addr,
141 		     unsigned int bank_nr,
142 		     unsigned int mask)
143 {
144 	struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
145 	struct resource *csr = csr_addr;
146 	u32 arbenable;
147 
148 	if (!csr_addr)
149 		return;
150 
151 	mutex_lock(&csr_arb_lock);
152 	arbenable = csr_ops->read_csr_ring_srv_arb_en(csr, bank_nr);
153 	arbenable &= ~mask & 0xFF;
154 	csr_ops->write_csr_ring_srv_arb_en(csr, bank_nr, arbenable);
155 	mutex_unlock(&csr_arb_lock);
156 }
157 
158 void
159 adf_exit_arb(struct adf_accel_dev *accel_dev)
160 {
161 	struct adf_hw_csr_ops *csr_ops = GET_CSR_OPS(accel_dev);
162 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
163 	struct arb_info info;
164 	struct resource *csr;
165 	unsigned int i;
166 
167 	if (!accel_dev->transport)
168 		return;
169 
170 	csr = accel_dev->transport->banks[0].csr_addr;
171 
172 	hw_data->get_arb_info(&info);
173 
174 	/* Reset arbiter configuration */
175 	for (i = 0; i < ADF_ARB_NUM; i++)
176 		WRITE_CSR_ARB_SARCONFIG(csr, info.arbiter_offset, i, 0);
177 
178 	/* Unmap worker threads to service arbiters */
179 	if (hw_data->get_arb_mapping) {
180 		for (i = 0; i < hw_data->num_engines; i++)
181 			WRITE_CSR_ARB_WRK_2_SER_MAP(csr,
182 						    info.arbiter_offset,
183 						    info.wrk_thd_2_srv_arb_map,
184 						    i,
185 						    0);
186 	}
187 
188 	/* Disable arbitration on all rings */
189 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++)
190 		csr_ops->write_csr_ring_srv_arb_en(csr, i, 0);
191 }
192 
193 void
194 adf_disable_arb(struct adf_accel_dev *accel_dev)
195 {
196 	struct adf_hw_csr_ops *csr_ops;
197 	struct resource *csr;
198 	unsigned int i;
199 
200 	if (!accel_dev || !accel_dev->transport)
201 		return;
202 
203 	csr = accel_dev->transport->banks[0].csr_addr;
204 	csr_ops = GET_CSR_OPS(accel_dev);
205 
206 	/* Disable arbitration on all rings */
207 	for (i = 0; i < GET_MAX_BANKS(accel_dev); i++)
208 		csr_ops->write_csr_ring_srv_arb_en(csr, i, 0);
209 }
210