xref: /freebsd/sys/dev/qat_c2xxx/qat.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1*b61a5730SWarner Losh /* SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause */
2f4f56ff4SMark Johnston /*	$NetBSD: qat.c,v 1.6 2020/06/14 23:23:12 riastradh Exp $	*/
3f4f56ff4SMark Johnston 
4f4f56ff4SMark Johnston /*
5f4f56ff4SMark Johnston  * Copyright (c) 2019 Internet Initiative Japan, Inc.
6f4f56ff4SMark Johnston  * All rights reserved.
7f4f56ff4SMark Johnston  *
8f4f56ff4SMark Johnston  * Redistribution and use in source and binary forms, with or without
9f4f56ff4SMark Johnston  * modification, are permitted provided that the following conditions
10f4f56ff4SMark Johnston  * are met:
11f4f56ff4SMark Johnston  * 1. Redistributions of source code must retain the above copyright
12f4f56ff4SMark Johnston  *    notice, this list of conditions and the following disclaimer.
13f4f56ff4SMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
14f4f56ff4SMark Johnston  *    notice, this list of conditions and the following disclaimer in the
15f4f56ff4SMark Johnston  *    documentation and/or other materials provided with the distribution.
16f4f56ff4SMark Johnston  *
17f4f56ff4SMark Johnston  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18f4f56ff4SMark Johnston  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19f4f56ff4SMark Johnston  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20f4f56ff4SMark Johnston  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21f4f56ff4SMark Johnston  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22f4f56ff4SMark Johnston  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23f4f56ff4SMark Johnston  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24f4f56ff4SMark Johnston  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25f4f56ff4SMark Johnston  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26f4f56ff4SMark Johnston  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27f4f56ff4SMark Johnston  * POSSIBILITY OF SUCH DAMAGE.
28f4f56ff4SMark Johnston  */
29f4f56ff4SMark Johnston 
30f4f56ff4SMark Johnston /*
31f4f56ff4SMark Johnston  *   Copyright(c) 2007-2019 Intel Corporation. All rights reserved.
32f4f56ff4SMark Johnston  *
33f4f56ff4SMark Johnston  *   Redistribution and use in source and binary forms, with or without
34f4f56ff4SMark Johnston  *   modification, are permitted provided that the following conditions
35f4f56ff4SMark Johnston  *   are met:
36f4f56ff4SMark Johnston  *
37f4f56ff4SMark Johnston  *     * Redistributions of source code must retain the above copyright
38f4f56ff4SMark Johnston  *       notice, this list of conditions and the following disclaimer.
39f4f56ff4SMark Johnston  *     * Redistributions in binary form must reproduce the above copyright
40f4f56ff4SMark Johnston  *       notice, this list of conditions and the following disclaimer in
41f4f56ff4SMark Johnston  *       the documentation and/or other materials provided with the
42f4f56ff4SMark Johnston  *       distribution.
43f4f56ff4SMark Johnston  *     * Neither the name of Intel Corporation nor the names of its
44f4f56ff4SMark Johnston  *       contributors may be used to endorse or promote products derived
45f4f56ff4SMark Johnston  *       from this software without specific prior written permission.
46f4f56ff4SMark Johnston  *
47f4f56ff4SMark Johnston  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48f4f56ff4SMark Johnston  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49f4f56ff4SMark Johnston  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50f4f56ff4SMark Johnston  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51f4f56ff4SMark Johnston  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52f4f56ff4SMark Johnston  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53f4f56ff4SMark Johnston  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54f4f56ff4SMark Johnston  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55f4f56ff4SMark Johnston  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56f4f56ff4SMark Johnston  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57f4f56ff4SMark Johnston  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58f4f56ff4SMark Johnston  */
59f4f56ff4SMark Johnston 
60f4f56ff4SMark Johnston #include <sys/cdefs.h>
61f4f56ff4SMark Johnston #if 0
62f4f56ff4SMark Johnston __KERNEL_RCSID(0, "$NetBSD: qat.c,v 1.6 2020/06/14 23:23:12 riastradh Exp $");
63f4f56ff4SMark Johnston #endif
64f4f56ff4SMark Johnston 
65f4f56ff4SMark Johnston #include <sys/param.h>
66f4f56ff4SMark Johnston #include <sys/systm.h>
67f4f56ff4SMark Johnston #include <sys/bus.h>
68f4f56ff4SMark Johnston #include <sys/cpu.h>
69f4f56ff4SMark Johnston #include <sys/firmware.h>
70f4f56ff4SMark Johnston #include <sys/kernel.h>
71f4f56ff4SMark Johnston #include <sys/mbuf.h>
72f4f56ff4SMark Johnston #include <sys/md5.h>
73f4f56ff4SMark Johnston #include <sys/module.h>
74f4f56ff4SMark Johnston #include <sys/mutex.h>
75f4f56ff4SMark Johnston #include <sys/smp.h>
76f4f56ff4SMark Johnston #include <sys/sysctl.h>
77f4f56ff4SMark Johnston #include <sys/rman.h>
78f4f56ff4SMark Johnston 
79f4f56ff4SMark Johnston #include <machine/bus.h>
80f4f56ff4SMark Johnston 
81f4f56ff4SMark Johnston #include <opencrypto/cryptodev.h>
82f4f56ff4SMark Johnston #include <opencrypto/xform.h>
83f4f56ff4SMark Johnston 
84f4f56ff4SMark Johnston #include "cryptodev_if.h"
85f4f56ff4SMark Johnston 
86f4f56ff4SMark Johnston #include <dev/pci/pcireg.h>
87f4f56ff4SMark Johnston #include <dev/pci/pcivar.h>
88f4f56ff4SMark Johnston 
89f4f56ff4SMark Johnston #include "qatreg.h"
90f4f56ff4SMark Johnston #include "qatvar.h"
91f4f56ff4SMark Johnston #include "qat_aevar.h"
92f4f56ff4SMark Johnston 
93f4f56ff4SMark Johnston extern struct qat_hw qat_hw_c2xxx;
94f4f56ff4SMark Johnston 
95f4f56ff4SMark Johnston #define PCI_VENDOR_INTEL			0x8086
96f4f56ff4SMark Johnston #define PCI_PRODUCT_INTEL_C2000_IQIA_PHYS	0x1f18
97f4f56ff4SMark Johnston 
98f4f56ff4SMark Johnston static const struct qat_product {
99f4f56ff4SMark Johnston 	uint16_t qatp_vendor;
100f4f56ff4SMark Johnston 	uint16_t qatp_product;
101f4f56ff4SMark Johnston 	const char *qatp_name;
102f4f56ff4SMark Johnston 	enum qat_chip_type qatp_chip;
103f4f56ff4SMark Johnston 	const struct qat_hw *qatp_hw;
104f4f56ff4SMark Johnston } qat_products[] = {
105f4f56ff4SMark Johnston 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_C2000_IQIA_PHYS,
106f4f56ff4SMark Johnston 	  "Intel C2000 QuickAssist PF",
107f4f56ff4SMark Johnston 	  QAT_CHIP_C2XXX, &qat_hw_c2xxx },
108f4f56ff4SMark Johnston 	{ 0, 0, NULL, 0, NULL },
109f4f56ff4SMark Johnston };
110f4f56ff4SMark Johnston 
111f4f56ff4SMark Johnston /* Hash Algorithm specific structure */
112f4f56ff4SMark Johnston 
113f4f56ff4SMark Johnston /* SHA1 - 20 bytes - Initialiser state can be found in FIPS stds 180-2 */
114f4f56ff4SMark Johnston static const uint8_t sha1_initial_state[QAT_HASH_SHA1_STATE_SIZE] = {
115f4f56ff4SMark Johnston 	0x67, 0x45, 0x23, 0x01,
116f4f56ff4SMark Johnston 	0xef, 0xcd, 0xab, 0x89,
117f4f56ff4SMark Johnston 	0x98, 0xba, 0xdc, 0xfe,
118f4f56ff4SMark Johnston 	0x10, 0x32, 0x54, 0x76,
119f4f56ff4SMark Johnston 	0xc3, 0xd2, 0xe1, 0xf0
120f4f56ff4SMark Johnston };
121f4f56ff4SMark Johnston 
122f4f56ff4SMark Johnston /* SHA 256 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */
123f4f56ff4SMark Johnston static const uint8_t sha256_initial_state[QAT_HASH_SHA256_STATE_SIZE] = {
124f4f56ff4SMark Johnston 	0x6a, 0x09, 0xe6, 0x67,
125f4f56ff4SMark Johnston 	0xbb, 0x67, 0xae, 0x85,
126f4f56ff4SMark Johnston 	0x3c, 0x6e, 0xf3, 0x72,
127f4f56ff4SMark Johnston 	0xa5, 0x4f, 0xf5, 0x3a,
128f4f56ff4SMark Johnston 	0x51, 0x0e, 0x52, 0x7f,
129f4f56ff4SMark Johnston 	0x9b, 0x05, 0x68, 0x8c,
130f4f56ff4SMark Johnston 	0x1f, 0x83, 0xd9, 0xab,
131f4f56ff4SMark Johnston 	0x5b, 0xe0, 0xcd, 0x19
132f4f56ff4SMark Johnston };
133f4f56ff4SMark Johnston 
134f4f56ff4SMark Johnston /* SHA 384 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */
135f4f56ff4SMark Johnston static const uint8_t sha384_initial_state[QAT_HASH_SHA384_STATE_SIZE] = {
136f4f56ff4SMark Johnston 	0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8,
137f4f56ff4SMark Johnston 	0x62, 0x9a, 0x29, 0x2a, 0x36, 0x7c, 0xd5, 0x07,
138f4f56ff4SMark Johnston 	0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, 0xdd, 0x17,
139f4f56ff4SMark Johnston 	0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39,
140f4f56ff4SMark Johnston 	0x67, 0x33, 0x26, 0x67, 0xff, 0xc0, 0x0b, 0x31,
141f4f56ff4SMark Johnston 	0x8e, 0xb4, 0x4a, 0x87, 0x68, 0x58, 0x15, 0x11,
142f4f56ff4SMark Johnston 	0xdb, 0x0c, 0x2e, 0x0d, 0x64, 0xf9, 0x8f, 0xa7,
143f4f56ff4SMark Johnston 	0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, 0xa4
144f4f56ff4SMark Johnston };
145f4f56ff4SMark Johnston 
146f4f56ff4SMark Johnston /* SHA 512 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */
147f4f56ff4SMark Johnston static const uint8_t sha512_initial_state[QAT_HASH_SHA512_STATE_SIZE] = {
148f4f56ff4SMark Johnston 	0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08,
149f4f56ff4SMark Johnston 	0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b,
150f4f56ff4SMark Johnston 	0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b,
151f4f56ff4SMark Johnston 	0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1,
152f4f56ff4SMark Johnston 	0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1,
153f4f56ff4SMark Johnston 	0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f,
154f4f56ff4SMark Johnston 	0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b,
155f4f56ff4SMark Johnston 	0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79
156f4f56ff4SMark Johnston };
157f4f56ff4SMark Johnston 
158f4f56ff4SMark Johnston static const struct qat_sym_hash_alg_info sha1_info = {
159f4f56ff4SMark Johnston 	.qshai_digest_len = QAT_HASH_SHA1_DIGEST_SIZE,
160f4f56ff4SMark Johnston 	.qshai_block_len = QAT_HASH_SHA1_BLOCK_SIZE,
161f4f56ff4SMark Johnston 	.qshai_state_size = QAT_HASH_SHA1_STATE_SIZE,
162f4f56ff4SMark Johnston 	.qshai_init_state = sha1_initial_state,
163f4f56ff4SMark Johnston 	.qshai_sah = &auth_hash_hmac_sha1,
164f4f56ff4SMark Johnston 	.qshai_state_offset = 0,
165f4f56ff4SMark Johnston 	.qshai_state_word = 4,
166f4f56ff4SMark Johnston };
167f4f56ff4SMark Johnston 
168f4f56ff4SMark Johnston static const struct qat_sym_hash_alg_info sha256_info = {
169f4f56ff4SMark Johnston 	.qshai_digest_len = QAT_HASH_SHA256_DIGEST_SIZE,
170f4f56ff4SMark Johnston 	.qshai_block_len = QAT_HASH_SHA256_BLOCK_SIZE,
171f4f56ff4SMark Johnston 	.qshai_state_size = QAT_HASH_SHA256_STATE_SIZE,
172f4f56ff4SMark Johnston 	.qshai_init_state = sha256_initial_state,
173f4f56ff4SMark Johnston 	.qshai_sah = &auth_hash_hmac_sha2_256,
174f4f56ff4SMark Johnston 	.qshai_state_offset = offsetof(SHA256_CTX, state),
175f4f56ff4SMark Johnston 	.qshai_state_word = 4,
176f4f56ff4SMark Johnston };
177f4f56ff4SMark Johnston 
178f4f56ff4SMark Johnston static const struct qat_sym_hash_alg_info sha384_info = {
179f4f56ff4SMark Johnston 	.qshai_digest_len = QAT_HASH_SHA384_DIGEST_SIZE,
180f4f56ff4SMark Johnston 	.qshai_block_len = QAT_HASH_SHA384_BLOCK_SIZE,
181f4f56ff4SMark Johnston 	.qshai_state_size = QAT_HASH_SHA384_STATE_SIZE,
182f4f56ff4SMark Johnston 	.qshai_init_state = sha384_initial_state,
183f4f56ff4SMark Johnston 	.qshai_sah = &auth_hash_hmac_sha2_384,
184f4f56ff4SMark Johnston 	.qshai_state_offset = offsetof(SHA384_CTX, state),
185f4f56ff4SMark Johnston 	.qshai_state_word = 8,
186f4f56ff4SMark Johnston };
187f4f56ff4SMark Johnston 
188f4f56ff4SMark Johnston static const struct qat_sym_hash_alg_info sha512_info = {
189f4f56ff4SMark Johnston 	.qshai_digest_len = QAT_HASH_SHA512_DIGEST_SIZE,
190f4f56ff4SMark Johnston 	.qshai_block_len = QAT_HASH_SHA512_BLOCK_SIZE,
191f4f56ff4SMark Johnston 	.qshai_state_size = QAT_HASH_SHA512_STATE_SIZE,
192f4f56ff4SMark Johnston 	.qshai_init_state = sha512_initial_state,
193f4f56ff4SMark Johnston 	.qshai_sah = &auth_hash_hmac_sha2_512,
194f4f56ff4SMark Johnston 	.qshai_state_offset = offsetof(SHA512_CTX, state),
195f4f56ff4SMark Johnston 	.qshai_state_word = 8,
196f4f56ff4SMark Johnston };
197f4f56ff4SMark Johnston 
198f4f56ff4SMark Johnston static const struct qat_sym_hash_alg_info aes_gcm_info = {
199f4f56ff4SMark Johnston 	.qshai_digest_len = QAT_HASH_AES_GCM_DIGEST_SIZE,
200f4f56ff4SMark Johnston 	.qshai_block_len = QAT_HASH_AES_GCM_BLOCK_SIZE,
201f4f56ff4SMark Johnston 	.qshai_state_size = QAT_HASH_AES_GCM_STATE_SIZE,
202f4f56ff4SMark Johnston 	.qshai_sah = &auth_hash_nist_gmac_aes_128,
203f4f56ff4SMark Johnston };
204f4f56ff4SMark Johnston 
205f4f56ff4SMark Johnston /* Hash QAT specific structures */
206f4f56ff4SMark Johnston 
207f4f56ff4SMark Johnston static const struct qat_sym_hash_qat_info sha1_config = {
208f4f56ff4SMark Johnston 	.qshqi_algo_enc = HW_AUTH_ALGO_SHA1,
209f4f56ff4SMark Johnston 	.qshqi_auth_counter = QAT_HASH_SHA1_BLOCK_SIZE,
210f4f56ff4SMark Johnston 	.qshqi_state1_len = HW_SHA1_STATE1_SZ,
211f4f56ff4SMark Johnston 	.qshqi_state2_len = HW_SHA1_STATE2_SZ,
212f4f56ff4SMark Johnston };
213f4f56ff4SMark Johnston 
214f4f56ff4SMark Johnston static const struct qat_sym_hash_qat_info sha256_config = {
215f4f56ff4SMark Johnston 	.qshqi_algo_enc = HW_AUTH_ALGO_SHA256,
216f4f56ff4SMark Johnston 	.qshqi_auth_counter = QAT_HASH_SHA256_BLOCK_SIZE,
217f4f56ff4SMark Johnston 	.qshqi_state1_len = HW_SHA256_STATE1_SZ,
218f4f56ff4SMark Johnston 	.qshqi_state2_len = HW_SHA256_STATE2_SZ
219f4f56ff4SMark Johnston };
220f4f56ff4SMark Johnston 
221f4f56ff4SMark Johnston static const struct qat_sym_hash_qat_info sha384_config = {
222f4f56ff4SMark Johnston 	.qshqi_algo_enc = HW_AUTH_ALGO_SHA384,
223f4f56ff4SMark Johnston 	.qshqi_auth_counter = QAT_HASH_SHA384_BLOCK_SIZE,
224f4f56ff4SMark Johnston 	.qshqi_state1_len = HW_SHA384_STATE1_SZ,
225f4f56ff4SMark Johnston 	.qshqi_state2_len = HW_SHA384_STATE2_SZ
226f4f56ff4SMark Johnston };
227f4f56ff4SMark Johnston 
228f4f56ff4SMark Johnston static const struct qat_sym_hash_qat_info sha512_config = {
229f4f56ff4SMark Johnston 	.qshqi_algo_enc = HW_AUTH_ALGO_SHA512,
230f4f56ff4SMark Johnston 	.qshqi_auth_counter = QAT_HASH_SHA512_BLOCK_SIZE,
231f4f56ff4SMark Johnston 	.qshqi_state1_len = HW_SHA512_STATE1_SZ,
232f4f56ff4SMark Johnston 	.qshqi_state2_len = HW_SHA512_STATE2_SZ
233f4f56ff4SMark Johnston };
234f4f56ff4SMark Johnston 
235f4f56ff4SMark Johnston static const struct qat_sym_hash_qat_info aes_gcm_config = {
236f4f56ff4SMark Johnston 	.qshqi_algo_enc = HW_AUTH_ALGO_GALOIS_128,
237f4f56ff4SMark Johnston 	.qshqi_auth_counter = QAT_HASH_AES_GCM_BLOCK_SIZE,
238f4f56ff4SMark Johnston 	.qshqi_state1_len = HW_GALOIS_128_STATE1_SZ,
239f4f56ff4SMark Johnston 	.qshqi_state2_len =
240f4f56ff4SMark Johnston 	    HW_GALOIS_H_SZ + HW_GALOIS_LEN_A_SZ + HW_GALOIS_E_CTR0_SZ,
241f4f56ff4SMark Johnston };
242f4f56ff4SMark Johnston 
243f4f56ff4SMark Johnston static const struct qat_sym_hash_def qat_sym_hash_defs[] = {
244f4f56ff4SMark Johnston 	[QAT_SYM_HASH_SHA1] = { &sha1_info, &sha1_config },
245f4f56ff4SMark Johnston 	[QAT_SYM_HASH_SHA256] = { &sha256_info, &sha256_config },
246f4f56ff4SMark Johnston 	[QAT_SYM_HASH_SHA384] = { &sha384_info, &sha384_config },
247f4f56ff4SMark Johnston 	[QAT_SYM_HASH_SHA512] = { &sha512_info, &sha512_config },
248f4f56ff4SMark Johnston 	[QAT_SYM_HASH_AES_GCM] = { &aes_gcm_info, &aes_gcm_config },
249f4f56ff4SMark Johnston };
250f4f56ff4SMark Johnston 
251f4f56ff4SMark Johnston static const struct qat_product *qat_lookup(device_t);
252f4f56ff4SMark Johnston static int	qat_probe(device_t);
253f4f56ff4SMark Johnston static int	qat_attach(device_t);
254f4f56ff4SMark Johnston static int	qat_init(device_t);
255f4f56ff4SMark Johnston static int	qat_start(device_t);
256f4f56ff4SMark Johnston static int	qat_detach(device_t);
257f4f56ff4SMark Johnston 
258f4f56ff4SMark Johnston static int	qat_newsession(device_t dev, crypto_session_t cses,
259f4f56ff4SMark Johnston 		    const struct crypto_session_params *csp);
260f4f56ff4SMark Johnston static void	qat_freesession(device_t dev, crypto_session_t cses);
261f4f56ff4SMark Johnston 
262f4f56ff4SMark Johnston static int	qat_setup_msix_intr(struct qat_softc *);
263f4f56ff4SMark Johnston 
264f4f56ff4SMark Johnston static void	qat_etr_init(struct qat_softc *);
265f4f56ff4SMark Johnston static void	qat_etr_deinit(struct qat_softc *);
266f4f56ff4SMark Johnston static void	qat_etr_bank_init(struct qat_softc *, int);
267f4f56ff4SMark Johnston static void	qat_etr_bank_deinit(struct qat_softc *sc, int);
268f4f56ff4SMark Johnston 
269f4f56ff4SMark Johnston static void	qat_etr_ap_bank_init(struct qat_softc *);
270f4f56ff4SMark Johnston static void	qat_etr_ap_bank_set_ring_mask(uint32_t *, uint32_t, int);
271f4f56ff4SMark Johnston static void	qat_etr_ap_bank_set_ring_dest(struct qat_softc *, uint32_t *,
272f4f56ff4SMark Johnston 		    uint32_t, int);
273f4f56ff4SMark Johnston static void	qat_etr_ap_bank_setup_ring(struct qat_softc *,
274f4f56ff4SMark Johnston 		    struct qat_ring *);
275f4f56ff4SMark Johnston static int	qat_etr_verify_ring_size(uint32_t, uint32_t);
276f4f56ff4SMark Johnston 
277f4f56ff4SMark Johnston static int	qat_etr_ring_intr(struct qat_softc *, struct qat_bank *,
278f4f56ff4SMark Johnston 		    struct qat_ring *);
279f4f56ff4SMark Johnston static void	qat_etr_bank_intr(void *);
280f4f56ff4SMark Johnston 
281f4f56ff4SMark Johnston static void	qat_arb_update(struct qat_softc *, struct qat_bank *);
282f4f56ff4SMark Johnston 
283f4f56ff4SMark Johnston static struct qat_sym_cookie *qat_crypto_alloc_sym_cookie(
284f4f56ff4SMark Johnston 		    struct qat_crypto_bank *);
285f4f56ff4SMark Johnston static void	qat_crypto_free_sym_cookie(struct qat_crypto_bank *,
286f4f56ff4SMark Johnston 		    struct qat_sym_cookie *);
287f4f56ff4SMark Johnston static int	qat_crypto_setup_ring(struct qat_softc *,
288f4f56ff4SMark Johnston 		    struct qat_crypto_bank *);
289f4f56ff4SMark Johnston static int	qat_crypto_bank_init(struct qat_softc *,
290f4f56ff4SMark Johnston 		    struct qat_crypto_bank *);
291f4f56ff4SMark Johnston static int	qat_crypto_init(struct qat_softc *);
292f4f56ff4SMark Johnston static void	qat_crypto_deinit(struct qat_softc *);
293f4f56ff4SMark Johnston static int	qat_crypto_start(struct qat_softc *);
294f4f56ff4SMark Johnston static void	qat_crypto_stop(struct qat_softc *);
295f4f56ff4SMark Johnston static int	qat_crypto_sym_rxintr(struct qat_softc *, void *, void *);
296f4f56ff4SMark Johnston 
297f4f56ff4SMark Johnston static MALLOC_DEFINE(M_QAT, "qat", "Intel QAT driver");
298f4f56ff4SMark Johnston 
299f4f56ff4SMark Johnston static const struct qat_product *
qat_lookup(device_t dev)300f4f56ff4SMark Johnston qat_lookup(device_t dev)
301f4f56ff4SMark Johnston {
302f4f56ff4SMark Johnston 	const struct qat_product *qatp;
303f4f56ff4SMark Johnston 
304f4f56ff4SMark Johnston 	for (qatp = qat_products; qatp->qatp_name != NULL; qatp++) {
305f4f56ff4SMark Johnston 		if (pci_get_vendor(dev) == qatp->qatp_vendor &&
306f4f56ff4SMark Johnston 		    pci_get_device(dev) == qatp->qatp_product)
307f4f56ff4SMark Johnston 			return qatp;
308f4f56ff4SMark Johnston 	}
309f4f56ff4SMark Johnston 	return NULL;
310f4f56ff4SMark Johnston }
311f4f56ff4SMark Johnston 
312f4f56ff4SMark Johnston static int
qat_probe(device_t dev)313f4f56ff4SMark Johnston qat_probe(device_t dev)
314f4f56ff4SMark Johnston {
315f4f56ff4SMark Johnston 	const struct qat_product *prod;
316f4f56ff4SMark Johnston 
317f4f56ff4SMark Johnston 	prod = qat_lookup(dev);
318f4f56ff4SMark Johnston 	if (prod != NULL) {
319f4f56ff4SMark Johnston 		device_set_desc(dev, prod->qatp_name);
320f4f56ff4SMark Johnston 		return BUS_PROBE_DEFAULT;
321f4f56ff4SMark Johnston 	}
322f4f56ff4SMark Johnston 	return ENXIO;
323f4f56ff4SMark Johnston }
324f4f56ff4SMark Johnston 
325f4f56ff4SMark Johnston static int
qat_attach(device_t dev)326f4f56ff4SMark Johnston qat_attach(device_t dev)
327f4f56ff4SMark Johnston {
328f4f56ff4SMark Johnston 	struct qat_softc *sc = device_get_softc(dev);
329f4f56ff4SMark Johnston 	const struct qat_product *qatp;
330f4f56ff4SMark Johnston 	int bar, count, error, i;
331f4f56ff4SMark Johnston 
332f4f56ff4SMark Johnston 	sc->sc_dev = dev;
333f4f56ff4SMark Johnston 	sc->sc_rev = pci_get_revid(dev);
334f4f56ff4SMark Johnston 	sc->sc_crypto.qcy_cid = -1;
335f4f56ff4SMark Johnston 
336f4f56ff4SMark Johnston 	qatp = qat_lookup(dev);
337f4f56ff4SMark Johnston 	memcpy(&sc->sc_hw, qatp->qatp_hw, sizeof(struct qat_hw));
338f4f56ff4SMark Johnston 
339f4f56ff4SMark Johnston 	/* Determine active accelerators and engines */
340f4f56ff4SMark Johnston 	sc->sc_accel_mask = sc->sc_hw.qhw_get_accel_mask(sc);
341f4f56ff4SMark Johnston 	sc->sc_ae_mask = sc->sc_hw.qhw_get_ae_mask(sc);
342f4f56ff4SMark Johnston 
343f4f56ff4SMark Johnston 	sc->sc_accel_num = 0;
344f4f56ff4SMark Johnston 	for (i = 0; i < sc->sc_hw.qhw_num_accel; i++) {
345f4f56ff4SMark Johnston 		if (sc->sc_accel_mask & (1 << i))
346f4f56ff4SMark Johnston 			sc->sc_accel_num++;
347f4f56ff4SMark Johnston 	}
348f4f56ff4SMark Johnston 	sc->sc_ae_num = 0;
349f4f56ff4SMark Johnston 	for (i = 0; i < sc->sc_hw.qhw_num_engines; i++) {
350f4f56ff4SMark Johnston 		if (sc->sc_ae_mask & (1 << i))
351f4f56ff4SMark Johnston 			sc->sc_ae_num++;
352f4f56ff4SMark Johnston 	}
353f4f56ff4SMark Johnston 
354f4f56ff4SMark Johnston 	if (!sc->sc_accel_mask || (sc->sc_ae_mask & 0x01) == 0) {
355f4f56ff4SMark Johnston 		device_printf(sc->sc_dev, "couldn't find acceleration");
356f4f56ff4SMark Johnston 		goto fail;
357f4f56ff4SMark Johnston 	}
358f4f56ff4SMark Johnston 
359f4f56ff4SMark Johnston 	MPASS(sc->sc_accel_num <= MAX_NUM_ACCEL);
360f4f56ff4SMark Johnston 	MPASS(sc->sc_ae_num <= MAX_NUM_AE);
361f4f56ff4SMark Johnston 
362f4f56ff4SMark Johnston 	/* Determine SKU and capabilities */
363f4f56ff4SMark Johnston 	sc->sc_sku = sc->sc_hw.qhw_get_sku(sc);
364f4f56ff4SMark Johnston 	sc->sc_accel_cap = sc->sc_hw.qhw_get_accel_cap(sc);
365f4f56ff4SMark Johnston 	sc->sc_fw_uof_name = sc->sc_hw.qhw_get_fw_uof_name(sc);
366f4f56ff4SMark Johnston 
367f4f56ff4SMark Johnston 	i = 0;
368f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_sram_bar_id != NO_PCI_REG) {
369f4f56ff4SMark Johnston 		MPASS(sc->sc_hw.qhw_sram_bar_id == 0);
370f4f56ff4SMark Johnston 		uint32_t fusectl = pci_read_config(dev, FUSECTL_REG, 4);
371f4f56ff4SMark Johnston 		/* Skip SRAM BAR */
372f4f56ff4SMark Johnston 		i = (fusectl & FUSECTL_MASK) ? 1 : 0;
373f4f56ff4SMark Johnston 	}
374f4f56ff4SMark Johnston 	for (bar = 0; bar < PCIR_MAX_BAR_0; bar++) {
375f4f56ff4SMark Johnston 		uint32_t val = pci_read_config(dev, PCIR_BAR(bar), 4);
376f4f56ff4SMark Johnston 		if (val == 0 || !PCI_BAR_MEM(val))
377f4f56ff4SMark Johnston 			continue;
378f4f56ff4SMark Johnston 
379f4f56ff4SMark Johnston 		sc->sc_rid[i] = PCIR_BAR(bar);
380f4f56ff4SMark Johnston 		sc->sc_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
381f4f56ff4SMark Johnston 		    &sc->sc_rid[i], RF_ACTIVE);
382f4f56ff4SMark Johnston 		if (sc->sc_res[i] == NULL) {
383f4f56ff4SMark Johnston 			device_printf(dev, "couldn't map BAR %d\n", bar);
384f4f56ff4SMark Johnston 			goto fail;
385f4f56ff4SMark Johnston 		}
386f4f56ff4SMark Johnston 
387f4f56ff4SMark Johnston 		sc->sc_csrt[i] = rman_get_bustag(sc->sc_res[i]);
388f4f56ff4SMark Johnston 		sc->sc_csrh[i] = rman_get_bushandle(sc->sc_res[i]);
389f4f56ff4SMark Johnston 
390f4f56ff4SMark Johnston 		i++;
391f4f56ff4SMark Johnston 		if ((val & PCIM_BAR_MEM_TYPE) == PCIM_BAR_MEM_64)
392f4f56ff4SMark Johnston 			bar++;
393f4f56ff4SMark Johnston 	}
394f4f56ff4SMark Johnston 
395f4f56ff4SMark Johnston 	pci_enable_busmaster(dev);
396f4f56ff4SMark Johnston 
397f4f56ff4SMark Johnston 	count = sc->sc_hw.qhw_num_banks + 1;
398f4f56ff4SMark Johnston 	if (pci_msix_count(dev) < count) {
399f4f56ff4SMark Johnston 		device_printf(dev, "insufficient MSI-X vectors (%d vs. %d)\n",
400f4f56ff4SMark Johnston 		    pci_msix_count(dev), count);
401f4f56ff4SMark Johnston 		goto fail;
402f4f56ff4SMark Johnston 	}
403f4f56ff4SMark Johnston 	error = pci_alloc_msix(dev, &count);
404f4f56ff4SMark Johnston 	if (error != 0) {
405f4f56ff4SMark Johnston 		device_printf(dev, "failed to allocate MSI-X vectors\n");
406f4f56ff4SMark Johnston 		goto fail;
407f4f56ff4SMark Johnston 	}
408f4f56ff4SMark Johnston 
409f4f56ff4SMark Johnston 	error = qat_init(dev);
410f4f56ff4SMark Johnston 	if (error == 0)
411f4f56ff4SMark Johnston 		return 0;
412f4f56ff4SMark Johnston 
413f4f56ff4SMark Johnston fail:
414f4f56ff4SMark Johnston 	qat_detach(dev);
415f4f56ff4SMark Johnston 	return ENXIO;
416f4f56ff4SMark Johnston }
417f4f56ff4SMark Johnston 
418f4f56ff4SMark Johnston static int
qat_init(device_t dev)419f4f56ff4SMark Johnston qat_init(device_t dev)
420f4f56ff4SMark Johnston {
421f4f56ff4SMark Johnston 	struct qat_softc *sc = device_get_softc(dev);
422f4f56ff4SMark Johnston 	int error;
423f4f56ff4SMark Johnston 
424f4f56ff4SMark Johnston 	qat_etr_init(sc);
425f4f56ff4SMark Johnston 
426f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_init_admin_comms != NULL &&
427f4f56ff4SMark Johnston 	    (error = sc->sc_hw.qhw_init_admin_comms(sc)) != 0) {
428f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
429f4f56ff4SMark Johnston 		    "Could not initialize admin comms: %d\n", error);
430f4f56ff4SMark Johnston 		return error;
431f4f56ff4SMark Johnston 	}
432f4f56ff4SMark Johnston 
433f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_init_arb != NULL &&
434f4f56ff4SMark Johnston 	    (error = sc->sc_hw.qhw_init_arb(sc)) != 0) {
435f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
436f4f56ff4SMark Johnston 		    "Could not initialize hw arbiter: %d\n", error);
437f4f56ff4SMark Johnston 		return error;
438f4f56ff4SMark Johnston 	}
439f4f56ff4SMark Johnston 
440f4f56ff4SMark Johnston 	error = qat_ae_init(sc);
441f4f56ff4SMark Johnston 	if (error) {
442f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
443f4f56ff4SMark Johnston 		    "Could not initialize Acceleration Engine: %d\n", error);
444f4f56ff4SMark Johnston 		return error;
445f4f56ff4SMark Johnston 	}
446f4f56ff4SMark Johnston 
447f4f56ff4SMark Johnston 	error = qat_aefw_load(sc);
448f4f56ff4SMark Johnston 	if (error) {
449f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
450f4f56ff4SMark Johnston 		    "Could not load firmware: %d\n", error);
451f4f56ff4SMark Johnston 		return error;
452f4f56ff4SMark Johnston 	}
453f4f56ff4SMark Johnston 
454f4f56ff4SMark Johnston 	error = qat_setup_msix_intr(sc);
455f4f56ff4SMark Johnston 	if (error) {
456f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
457f4f56ff4SMark Johnston 		    "Could not setup interrupts: %d\n", error);
458f4f56ff4SMark Johnston 		return error;
459f4f56ff4SMark Johnston 	}
460f4f56ff4SMark Johnston 
461f4f56ff4SMark Johnston 	sc->sc_hw.qhw_enable_intr(sc);
462f4f56ff4SMark Johnston 
463f4f56ff4SMark Johnston 	error = qat_crypto_init(sc);
464f4f56ff4SMark Johnston 	if (error) {
465f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
466f4f56ff4SMark Johnston 		    "Could not initialize service: %d\n", error);
467f4f56ff4SMark Johnston 		return error;
468f4f56ff4SMark Johnston 	}
469f4f56ff4SMark Johnston 
470f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_enable_error_correction != NULL)
471f4f56ff4SMark Johnston 		sc->sc_hw.qhw_enable_error_correction(sc);
472f4f56ff4SMark Johnston 
473f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_set_ssm_wdtimer != NULL &&
474f4f56ff4SMark Johnston 	    (error = sc->sc_hw.qhw_set_ssm_wdtimer(sc)) != 0) {
475f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
476f4f56ff4SMark Johnston 		    "Could not initialize watchdog timer: %d\n", error);
477f4f56ff4SMark Johnston 		return error;
478f4f56ff4SMark Johnston 	}
479f4f56ff4SMark Johnston 
480f4f56ff4SMark Johnston 	error = qat_start(dev);
481f4f56ff4SMark Johnston 	if (error) {
482f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
483f4f56ff4SMark Johnston 		    "Could not start: %d\n", error);
484f4f56ff4SMark Johnston 		return error;
485f4f56ff4SMark Johnston 	}
486f4f56ff4SMark Johnston 
487f4f56ff4SMark Johnston 	return 0;
488f4f56ff4SMark Johnston }
489f4f56ff4SMark Johnston 
490f4f56ff4SMark Johnston static int
qat_start(device_t dev)491f4f56ff4SMark Johnston qat_start(device_t dev)
492f4f56ff4SMark Johnston {
493f4f56ff4SMark Johnston 	struct qat_softc *sc = device_get_softc(dev);
494f4f56ff4SMark Johnston 	int error;
495f4f56ff4SMark Johnston 
496f4f56ff4SMark Johnston 	error = qat_ae_start(sc);
497f4f56ff4SMark Johnston 	if (error)
498f4f56ff4SMark Johnston 		return error;
499f4f56ff4SMark Johnston 
500f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_send_admin_init != NULL &&
501f4f56ff4SMark Johnston 	    (error = sc->sc_hw.qhw_send_admin_init(sc)) != 0) {
502f4f56ff4SMark Johnston 		return error;
503f4f56ff4SMark Johnston 	}
504f4f56ff4SMark Johnston 
505f4f56ff4SMark Johnston 	error = qat_crypto_start(sc);
506f4f56ff4SMark Johnston 	if (error)
507f4f56ff4SMark Johnston 		return error;
508f4f56ff4SMark Johnston 
509f4f56ff4SMark Johnston 	return 0;
510f4f56ff4SMark Johnston }
511f4f56ff4SMark Johnston 
512f4f56ff4SMark Johnston static int
qat_detach(device_t dev)513f4f56ff4SMark Johnston qat_detach(device_t dev)
514f4f56ff4SMark Johnston {
515f4f56ff4SMark Johnston 	struct qat_softc *sc;
516f4f56ff4SMark Johnston 	int bar, i;
517f4f56ff4SMark Johnston 
518f4f56ff4SMark Johnston 	sc = device_get_softc(dev);
519f4f56ff4SMark Johnston 
520f4f56ff4SMark Johnston 	qat_crypto_stop(sc);
521f4f56ff4SMark Johnston 	qat_crypto_deinit(sc);
522f4f56ff4SMark Johnston 	qat_aefw_unload(sc);
523f4f56ff4SMark Johnston 
524f4f56ff4SMark Johnston 	if (sc->sc_etr_banks != NULL) {
525f4f56ff4SMark Johnston 		for (i = 0; i < sc->sc_hw.qhw_num_banks; i++) {
526f4f56ff4SMark Johnston 			struct qat_bank *qb = &sc->sc_etr_banks[i];
527f4f56ff4SMark Johnston 
528f4f56ff4SMark Johnston 			if (qb->qb_ih_cookie != NULL)
529f4f56ff4SMark Johnston 				(void)bus_teardown_intr(dev, qb->qb_ih,
530f4f56ff4SMark Johnston 				    qb->qb_ih_cookie);
531f4f56ff4SMark Johnston 			if (qb->qb_ih != NULL)
532f4f56ff4SMark Johnston 				(void)bus_release_resource(dev, SYS_RES_IRQ,
533f4f56ff4SMark Johnston 				    i + 1, qb->qb_ih);
534f4f56ff4SMark Johnston 		}
535f4f56ff4SMark Johnston 	}
536f4f56ff4SMark Johnston 	if (sc->sc_ih_cookie != NULL) {
537f4f56ff4SMark Johnston 		(void)bus_teardown_intr(dev, sc->sc_ih, sc->sc_ih_cookie);
538f4f56ff4SMark Johnston 		sc->sc_ih_cookie = NULL;
539f4f56ff4SMark Johnston 	}
540f4f56ff4SMark Johnston 	if (sc->sc_ih != NULL) {
541f4f56ff4SMark Johnston 		(void)bus_release_resource(dev, SYS_RES_IRQ,
542f4f56ff4SMark Johnston 		    sc->sc_hw.qhw_num_banks + 1, sc->sc_ih);
543f4f56ff4SMark Johnston 		sc->sc_ih = NULL;
544f4f56ff4SMark Johnston 	}
545f4f56ff4SMark Johnston 	pci_release_msi(dev);
546f4f56ff4SMark Johnston 
547f4f56ff4SMark Johnston 	qat_etr_deinit(sc);
548f4f56ff4SMark Johnston 
549f4f56ff4SMark Johnston 	for (bar = 0; bar < MAX_BARS; bar++) {
550f4f56ff4SMark Johnston 		if (sc->sc_res[bar] != NULL) {
551f4f56ff4SMark Johnston 			(void)bus_release_resource(dev, SYS_RES_MEMORY,
552f4f56ff4SMark Johnston 			    sc->sc_rid[bar], sc->sc_res[bar]);
553f4f56ff4SMark Johnston 			sc->sc_res[bar] = NULL;
554f4f56ff4SMark Johnston 		}
555f4f56ff4SMark Johnston 	}
556f4f56ff4SMark Johnston 
557f4f56ff4SMark Johnston 	return 0;
558f4f56ff4SMark Johnston }
559f4f56ff4SMark Johnston 
560f4f56ff4SMark Johnston void *
qat_alloc_mem(size_t size)561f4f56ff4SMark Johnston qat_alloc_mem(size_t size)
562f4f56ff4SMark Johnston {
563f4f56ff4SMark Johnston 	return (malloc(size, M_QAT, M_WAITOK | M_ZERO));
564f4f56ff4SMark Johnston }
565f4f56ff4SMark Johnston 
566f4f56ff4SMark Johnston void
qat_free_mem(void * ptr)567f4f56ff4SMark Johnston qat_free_mem(void *ptr)
568f4f56ff4SMark Johnston {
569f4f56ff4SMark Johnston 	free(ptr, M_QAT);
570f4f56ff4SMark Johnston }
571f4f56ff4SMark Johnston 
572f4f56ff4SMark Johnston static void
qat_alloc_dmamem_cb(void * arg,bus_dma_segment_t * segs,int nseg,int error)573f4f56ff4SMark Johnston qat_alloc_dmamem_cb(void *arg, bus_dma_segment_t *segs, int nseg,
574f4f56ff4SMark Johnston     int error)
575f4f56ff4SMark Johnston {
576f4f56ff4SMark Johnston 	struct qat_dmamem *qdm;
577f4f56ff4SMark Johnston 
578f4f56ff4SMark Johnston 	if (error != 0)
579f4f56ff4SMark Johnston 		return;
580f4f56ff4SMark Johnston 
581f4f56ff4SMark Johnston 	KASSERT(nseg == 1, ("%s: nsegs is %d", __func__, nseg));
582f4f56ff4SMark Johnston 	qdm = arg;
583f4f56ff4SMark Johnston 	qdm->qdm_dma_seg = segs[0];
584f4f56ff4SMark Johnston }
585f4f56ff4SMark Johnston 
586f4f56ff4SMark Johnston int
qat_alloc_dmamem(struct qat_softc * sc,struct qat_dmamem * qdm,int nseg,bus_size_t size,bus_size_t alignment)587f4f56ff4SMark Johnston qat_alloc_dmamem(struct qat_softc *sc, struct qat_dmamem *qdm,
588f4f56ff4SMark Johnston     int nseg, bus_size_t size, bus_size_t alignment)
589f4f56ff4SMark Johnston {
590f4f56ff4SMark Johnston 	int error;
591f4f56ff4SMark Johnston 
592f4f56ff4SMark Johnston 	KASSERT(qdm->qdm_dma_vaddr == NULL,
593f4f56ff4SMark Johnston 	    ("%s: DMA memory descriptor in use", __func__));
594f4f56ff4SMark Johnston 
595f4f56ff4SMark Johnston 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),
596f4f56ff4SMark Johnston 	    alignment, 0, 		/* alignment, boundary */
597f4f56ff4SMark Johnston 	    BUS_SPACE_MAXADDR,		/* lowaddr */
598f4f56ff4SMark Johnston 	    BUS_SPACE_MAXADDR, 		/* highaddr */
599f4f56ff4SMark Johnston 	    NULL, NULL, 		/* filter, filterarg */
600f4f56ff4SMark Johnston 	    size,			/* maxsize */
601f4f56ff4SMark Johnston 	    nseg,			/* nsegments */
602f4f56ff4SMark Johnston 	    size,			/* maxsegsize */
603f4f56ff4SMark Johnston 	    BUS_DMA_COHERENT,		/* flags */
604f4f56ff4SMark Johnston 	    NULL, NULL,			/* lockfunc, lockarg */
605f4f56ff4SMark Johnston 	    &qdm->qdm_dma_tag);
606f4f56ff4SMark Johnston 	if (error != 0)
607f4f56ff4SMark Johnston 		return error;
608f4f56ff4SMark Johnston 
609f4f56ff4SMark Johnston 	error = bus_dmamem_alloc(qdm->qdm_dma_tag, &qdm->qdm_dma_vaddr,
610f4f56ff4SMark Johnston 	    BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT,
611f4f56ff4SMark Johnston 	    &qdm->qdm_dma_map);
612f4f56ff4SMark Johnston 	if (error != 0) {
613f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
614f4f56ff4SMark Johnston 		    "couldn't allocate dmamem, error = %d\n", error);
615f4f56ff4SMark Johnston 		goto fail_0;
616f4f56ff4SMark Johnston 	}
617f4f56ff4SMark Johnston 
618f4f56ff4SMark Johnston 	error = bus_dmamap_load(qdm->qdm_dma_tag, qdm->qdm_dma_map,
619f4f56ff4SMark Johnston 	    qdm->qdm_dma_vaddr, size, qat_alloc_dmamem_cb, qdm,
620f4f56ff4SMark Johnston 	    BUS_DMA_NOWAIT);
621f4f56ff4SMark Johnston 	if (error) {
622f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
623f4f56ff4SMark Johnston 		    "couldn't load dmamem map, error = %d\n", error);
624f4f56ff4SMark Johnston 		goto fail_1;
625f4f56ff4SMark Johnston 	}
626f4f56ff4SMark Johnston 
627f4f56ff4SMark Johnston 	return 0;
628f4f56ff4SMark Johnston fail_1:
629f4f56ff4SMark Johnston 	bus_dmamem_free(qdm->qdm_dma_tag, qdm->qdm_dma_vaddr, qdm->qdm_dma_map);
630f4f56ff4SMark Johnston fail_0:
631f4f56ff4SMark Johnston 	bus_dma_tag_destroy(qdm->qdm_dma_tag);
632f4f56ff4SMark Johnston 	return error;
633f4f56ff4SMark Johnston }
634f4f56ff4SMark Johnston 
635f4f56ff4SMark Johnston void
qat_free_dmamem(struct qat_softc * sc,struct qat_dmamem * qdm)636f4f56ff4SMark Johnston qat_free_dmamem(struct qat_softc *sc, struct qat_dmamem *qdm)
637f4f56ff4SMark Johnston {
638f4f56ff4SMark Johnston 	if (qdm->qdm_dma_tag != NULL) {
639f4f56ff4SMark Johnston 		bus_dmamap_unload(qdm->qdm_dma_tag, qdm->qdm_dma_map);
640f4f56ff4SMark Johnston 		bus_dmamem_free(qdm->qdm_dma_tag, qdm->qdm_dma_vaddr,
641f4f56ff4SMark Johnston 		    qdm->qdm_dma_map);
642f4f56ff4SMark Johnston 		bus_dma_tag_destroy(qdm->qdm_dma_tag);
643f4f56ff4SMark Johnston 		explicit_bzero(qdm, sizeof(*qdm));
644f4f56ff4SMark Johnston 	}
645f4f56ff4SMark Johnston }
646f4f56ff4SMark Johnston 
647f4f56ff4SMark Johnston static int
qat_setup_msix_intr(struct qat_softc * sc)648f4f56ff4SMark Johnston qat_setup_msix_intr(struct qat_softc *sc)
649f4f56ff4SMark Johnston {
650f4f56ff4SMark Johnston 	device_t dev;
651f4f56ff4SMark Johnston 	int error, i, rid;
652f4f56ff4SMark Johnston 
653f4f56ff4SMark Johnston 	dev = sc->sc_dev;
654f4f56ff4SMark Johnston 
655f4f56ff4SMark Johnston 	for (i = 1; i <= sc->sc_hw.qhw_num_banks; i++) {
656f4f56ff4SMark Johnston 		struct qat_bank *qb = &sc->sc_etr_banks[i - 1];
657f4f56ff4SMark Johnston 
658f4f56ff4SMark Johnston 		rid = i;
659f4f56ff4SMark Johnston 		qb->qb_ih = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
660f4f56ff4SMark Johnston 		    RF_ACTIVE);
661f4f56ff4SMark Johnston 		if (qb->qb_ih == NULL) {
662f4f56ff4SMark Johnston 			device_printf(dev,
663f4f56ff4SMark Johnston 			    "failed to allocate bank intr resource\n");
664f4f56ff4SMark Johnston 			return ENXIO;
665f4f56ff4SMark Johnston 		}
666f4f56ff4SMark Johnston 		error = bus_setup_intr(dev, qb->qb_ih,
667f4f56ff4SMark Johnston 		    INTR_TYPE_NET | INTR_MPSAFE, NULL, qat_etr_bank_intr, qb,
668f4f56ff4SMark Johnston 		    &qb->qb_ih_cookie);
669f4f56ff4SMark Johnston 		if (error != 0) {
670f4f56ff4SMark Johnston 			device_printf(dev, "failed to set up bank intr\n");
671f4f56ff4SMark Johnston 			return error;
672f4f56ff4SMark Johnston 		}
673f4f56ff4SMark Johnston 		error = bus_bind_intr(dev, qb->qb_ih, (i - 1) % mp_ncpus);
674f4f56ff4SMark Johnston 		if (error != 0)
675f4f56ff4SMark Johnston 			device_printf(dev, "failed to bind intr %d\n", i);
676f4f56ff4SMark Johnston 	}
677f4f56ff4SMark Johnston 
678f4f56ff4SMark Johnston 	rid = i;
679f4f56ff4SMark Johnston 	sc->sc_ih = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
680f4f56ff4SMark Johnston 	    RF_ACTIVE);
681f4f56ff4SMark Johnston 	if (sc->sc_ih == NULL)
682f4f56ff4SMark Johnston 		return ENXIO;
683f4f56ff4SMark Johnston 	error = bus_setup_intr(dev, sc->sc_ih, INTR_TYPE_NET | INTR_MPSAFE,
684f4f56ff4SMark Johnston 	    NULL, qat_ae_cluster_intr, sc, &sc->sc_ih_cookie);
685f4f56ff4SMark Johnston 
686f4f56ff4SMark Johnston 	return error;
687f4f56ff4SMark Johnston }
688f4f56ff4SMark Johnston 
689f4f56ff4SMark Johnston static void
qat_etr_init(struct qat_softc * sc)690f4f56ff4SMark Johnston qat_etr_init(struct qat_softc *sc)
691f4f56ff4SMark Johnston {
692f4f56ff4SMark Johnston 	int i;
693f4f56ff4SMark Johnston 
694f4f56ff4SMark Johnston 	sc->sc_etr_banks = qat_alloc_mem(
695f4f56ff4SMark Johnston 	    sizeof(struct qat_bank) * sc->sc_hw.qhw_num_banks);
696f4f56ff4SMark Johnston 
697f4f56ff4SMark Johnston 	for (i = 0; i < sc->sc_hw.qhw_num_banks; i++)
698f4f56ff4SMark Johnston 		qat_etr_bank_init(sc, i);
699f4f56ff4SMark Johnston 
700f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_num_ap_banks) {
701f4f56ff4SMark Johnston 		sc->sc_etr_ap_banks = qat_alloc_mem(
702f4f56ff4SMark Johnston 		    sizeof(struct qat_ap_bank) * sc->sc_hw.qhw_num_ap_banks);
703f4f56ff4SMark Johnston 		qat_etr_ap_bank_init(sc);
704f4f56ff4SMark Johnston 	}
705f4f56ff4SMark Johnston }
706f4f56ff4SMark Johnston 
707f4f56ff4SMark Johnston static void
qat_etr_deinit(struct qat_softc * sc)708f4f56ff4SMark Johnston qat_etr_deinit(struct qat_softc *sc)
709f4f56ff4SMark Johnston {
710f4f56ff4SMark Johnston 	int i;
711f4f56ff4SMark Johnston 
712f4f56ff4SMark Johnston 	if (sc->sc_etr_banks != NULL) {
713f4f56ff4SMark Johnston 		for (i = 0; i < sc->sc_hw.qhw_num_banks; i++)
714f4f56ff4SMark Johnston 			qat_etr_bank_deinit(sc, i);
715f4f56ff4SMark Johnston 		qat_free_mem(sc->sc_etr_banks);
716f4f56ff4SMark Johnston 		sc->sc_etr_banks = NULL;
717f4f56ff4SMark Johnston 	}
718f4f56ff4SMark Johnston 	if (sc->sc_etr_ap_banks != NULL) {
719f4f56ff4SMark Johnston 		qat_free_mem(sc->sc_etr_ap_banks);
720f4f56ff4SMark Johnston 		sc->sc_etr_ap_banks = NULL;
721f4f56ff4SMark Johnston 	}
722f4f56ff4SMark Johnston }
723f4f56ff4SMark Johnston 
724f4f56ff4SMark Johnston static void
qat_etr_bank_init(struct qat_softc * sc,int bank)725f4f56ff4SMark Johnston qat_etr_bank_init(struct qat_softc *sc, int bank)
726f4f56ff4SMark Johnston {
727f4f56ff4SMark Johnston 	struct qat_bank *qb = &sc->sc_etr_banks[bank];
728f4f56ff4SMark Johnston 	int i, tx_rx_gap = sc->sc_hw.qhw_tx_rx_gap;
729f4f56ff4SMark Johnston 
730f4f56ff4SMark Johnston 	MPASS(bank < sc->sc_hw.qhw_num_banks);
731f4f56ff4SMark Johnston 
732f4f56ff4SMark Johnston 	mtx_init(&qb->qb_bank_mtx, "qb bank", NULL, MTX_DEF);
733f4f56ff4SMark Johnston 
734f4f56ff4SMark Johnston 	qb->qb_sc = sc;
735f4f56ff4SMark Johnston 	qb->qb_bank = bank;
736f4f56ff4SMark Johnston 	qb->qb_coalescing_time = COALESCING_TIME_INTERVAL_DEFAULT;
737f4f56ff4SMark Johnston 
738f4f56ff4SMark Johnston 	/* Clean CSRs for all rings within the bank */
739f4f56ff4SMark Johnston 	for (i = 0; i < sc->sc_hw.qhw_num_rings_per_bank; i++) {
740f4f56ff4SMark Johnston 		struct qat_ring *qr = &qb->qb_et_rings[i];
741f4f56ff4SMark Johnston 
742f4f56ff4SMark Johnston 		qat_etr_bank_ring_write_4(sc, bank, i,
743f4f56ff4SMark Johnston 		    ETR_RING_CONFIG, 0);
744f4f56ff4SMark Johnston 		qat_etr_bank_ring_base_write_8(sc, bank, i, 0);
745f4f56ff4SMark Johnston 
746f4f56ff4SMark Johnston 		if (sc->sc_hw.qhw_tx_rings_mask & (1 << i)) {
747f4f56ff4SMark Johnston 			qr->qr_inflight = qat_alloc_mem(sizeof(uint32_t));
748f4f56ff4SMark Johnston 		} else if (sc->sc_hw.qhw_tx_rings_mask &
749f4f56ff4SMark Johnston 		    (1 << (i - tx_rx_gap))) {
750f4f56ff4SMark Johnston 			/* Share inflight counter with rx and tx */
751f4f56ff4SMark Johnston 			qr->qr_inflight =
752f4f56ff4SMark Johnston 			    qb->qb_et_rings[i - tx_rx_gap].qr_inflight;
753f4f56ff4SMark Johnston 		}
754f4f56ff4SMark Johnston 	}
755f4f56ff4SMark Johnston 
756f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_init_etr_intr != NULL) {
757f4f56ff4SMark Johnston 		sc->sc_hw.qhw_init_etr_intr(sc, bank);
758f4f56ff4SMark Johnston 	} else {
759f4f56ff4SMark Johnston 		/* common code in qat 1.7 */
760f4f56ff4SMark Johnston 		qat_etr_bank_write_4(sc, bank, ETR_INT_REG,
761f4f56ff4SMark Johnston 		    ETR_INT_REG_CLEAR_MASK);
762f4f56ff4SMark Johnston 		for (i = 0; i < sc->sc_hw.qhw_num_rings_per_bank /
763f4f56ff4SMark Johnston 		    ETR_RINGS_PER_INT_SRCSEL; i++) {
764f4f56ff4SMark Johnston 			qat_etr_bank_write_4(sc, bank, ETR_INT_SRCSEL +
765f4f56ff4SMark Johnston 			    (i * ETR_INT_SRCSEL_NEXT_OFFSET),
766f4f56ff4SMark Johnston 			    ETR_INT_SRCSEL_MASK);
767f4f56ff4SMark Johnston 		}
768f4f56ff4SMark Johnston 	}
769f4f56ff4SMark Johnston }
770f4f56ff4SMark Johnston 
771f4f56ff4SMark Johnston static void
qat_etr_bank_deinit(struct qat_softc * sc,int bank)772f4f56ff4SMark Johnston qat_etr_bank_deinit(struct qat_softc *sc, int bank)
773f4f56ff4SMark Johnston {
774f4f56ff4SMark Johnston 	struct qat_bank *qb;
775f4f56ff4SMark Johnston 	struct qat_ring *qr;
776f4f56ff4SMark Johnston 	int i;
777f4f56ff4SMark Johnston 
778f4f56ff4SMark Johnston 	qb = &sc->sc_etr_banks[bank];
779f4f56ff4SMark Johnston 	for (i = 0; i < sc->sc_hw.qhw_num_rings_per_bank; i++) {
780f4f56ff4SMark Johnston 		if (sc->sc_hw.qhw_tx_rings_mask & (1 << i)) {
781f4f56ff4SMark Johnston 			qr = &qb->qb_et_rings[i];
782f4f56ff4SMark Johnston 			qat_free_mem(qr->qr_inflight);
783f4f56ff4SMark Johnston 		}
784f4f56ff4SMark Johnston 	}
785f4f56ff4SMark Johnston }
786f4f56ff4SMark Johnston 
787f4f56ff4SMark Johnston static void
qat_etr_ap_bank_init(struct qat_softc * sc)788f4f56ff4SMark Johnston qat_etr_ap_bank_init(struct qat_softc *sc)
789f4f56ff4SMark Johnston {
790f4f56ff4SMark Johnston 	int ap_bank;
791f4f56ff4SMark Johnston 
792f4f56ff4SMark Johnston 	for (ap_bank = 0; ap_bank < sc->sc_hw.qhw_num_ap_banks; ap_bank++) {
793f4f56ff4SMark Johnston 		struct qat_ap_bank *qab = &sc->sc_etr_ap_banks[ap_bank];
794f4f56ff4SMark Johnston 
795f4f56ff4SMark Johnston 		qat_etr_ap_bank_write_4(sc, ap_bank, ETR_AP_NF_MASK,
796f4f56ff4SMark Johnston 		    ETR_AP_NF_MASK_INIT);
797f4f56ff4SMark Johnston 		qat_etr_ap_bank_write_4(sc, ap_bank, ETR_AP_NF_DEST, 0);
798f4f56ff4SMark Johnston 		qat_etr_ap_bank_write_4(sc, ap_bank, ETR_AP_NE_MASK,
799f4f56ff4SMark Johnston 		    ETR_AP_NE_MASK_INIT);
800f4f56ff4SMark Johnston 		qat_etr_ap_bank_write_4(sc, ap_bank, ETR_AP_NE_DEST, 0);
801f4f56ff4SMark Johnston 
802f4f56ff4SMark Johnston 		memset(qab, 0, sizeof(*qab));
803f4f56ff4SMark Johnston 	}
804f4f56ff4SMark Johnston }
805f4f56ff4SMark Johnston 
806f4f56ff4SMark Johnston static void
qat_etr_ap_bank_set_ring_mask(uint32_t * ap_mask,uint32_t ring,int set_mask)807f4f56ff4SMark Johnston qat_etr_ap_bank_set_ring_mask(uint32_t *ap_mask, uint32_t ring, int set_mask)
808f4f56ff4SMark Johnston {
809f4f56ff4SMark Johnston 	if (set_mask)
810f4f56ff4SMark Johnston 		*ap_mask |= (1 << ETR_RING_NUMBER_IN_AP_BANK(ring));
811f4f56ff4SMark Johnston 	else
812f4f56ff4SMark Johnston 		*ap_mask &= ~(1 << ETR_RING_NUMBER_IN_AP_BANK(ring));
813f4f56ff4SMark Johnston }
814f4f56ff4SMark Johnston 
815f4f56ff4SMark Johnston static void
qat_etr_ap_bank_set_ring_dest(struct qat_softc * sc,uint32_t * ap_dest,uint32_t ring,int set_dest)816f4f56ff4SMark Johnston qat_etr_ap_bank_set_ring_dest(struct qat_softc *sc, uint32_t *ap_dest,
817f4f56ff4SMark Johnston     uint32_t ring, int set_dest)
818f4f56ff4SMark Johnston {
819f4f56ff4SMark Johnston 	uint32_t ae_mask;
820f4f56ff4SMark Johnston 	uint8_t mailbox, ae, nae;
821f4f56ff4SMark Johnston 	uint8_t *dest = (uint8_t *)ap_dest;
822f4f56ff4SMark Johnston 
823f4f56ff4SMark Johnston 	mailbox = ETR_RING_AP_MAILBOX_NUMBER(ring);
824f4f56ff4SMark Johnston 
825f4f56ff4SMark Johnston 	nae = 0;
826f4f56ff4SMark Johnston 	ae_mask = sc->sc_ae_mask;
827f4f56ff4SMark Johnston 	for (ae = 0; ae < sc->sc_hw.qhw_num_engines; ae++) {
828f4f56ff4SMark Johnston 		if ((ae_mask & (1 << ae)) == 0)
829f4f56ff4SMark Johnston 			continue;
830f4f56ff4SMark Johnston 
831f4f56ff4SMark Johnston 		if (set_dest) {
832f4f56ff4SMark Johnston 			dest[nae] = __SHIFTIN(ae, ETR_AP_DEST_AE) |
833f4f56ff4SMark Johnston 			    __SHIFTIN(mailbox, ETR_AP_DEST_MAILBOX) |
834f4f56ff4SMark Johnston 			    ETR_AP_DEST_ENABLE;
835f4f56ff4SMark Johnston 		} else {
836f4f56ff4SMark Johnston 			dest[nae] = 0;
837f4f56ff4SMark Johnston 		}
838f4f56ff4SMark Johnston 		nae++;
839f4f56ff4SMark Johnston 		if (nae == ETR_MAX_AE_PER_MAILBOX)
840f4f56ff4SMark Johnston 			break;
841f4f56ff4SMark Johnston 	}
842f4f56ff4SMark Johnston }
843f4f56ff4SMark Johnston 
844f4f56ff4SMark Johnston static void
qat_etr_ap_bank_setup_ring(struct qat_softc * sc,struct qat_ring * qr)845f4f56ff4SMark Johnston qat_etr_ap_bank_setup_ring(struct qat_softc *sc, struct qat_ring *qr)
846f4f56ff4SMark Johnston {
847f4f56ff4SMark Johnston 	struct qat_ap_bank *qab;
848f4f56ff4SMark Johnston 	int ap_bank;
849f4f56ff4SMark Johnston 
850f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_num_ap_banks == 0)
851f4f56ff4SMark Johnston 		return;
852f4f56ff4SMark Johnston 
853f4f56ff4SMark Johnston 	ap_bank = ETR_RING_AP_BANK_NUMBER(qr->qr_ring);
854f4f56ff4SMark Johnston 	MPASS(ap_bank < sc->sc_hw.qhw_num_ap_banks);
855f4f56ff4SMark Johnston 	qab = &sc->sc_etr_ap_banks[ap_bank];
856f4f56ff4SMark Johnston 
857f4f56ff4SMark Johnston 	if (qr->qr_cb == NULL) {
858f4f56ff4SMark Johnston 		qat_etr_ap_bank_set_ring_mask(&qab->qab_ne_mask, qr->qr_ring, 1);
859f4f56ff4SMark Johnston 		if (!qab->qab_ne_dest) {
860f4f56ff4SMark Johnston 			qat_etr_ap_bank_set_ring_dest(sc, &qab->qab_ne_dest,
861f4f56ff4SMark Johnston 			    qr->qr_ring, 1);
862f4f56ff4SMark Johnston 			qat_etr_ap_bank_write_4(sc, ap_bank, ETR_AP_NE_DEST,
863f4f56ff4SMark Johnston 			    qab->qab_ne_dest);
864f4f56ff4SMark Johnston 		}
865f4f56ff4SMark Johnston 	} else {
866f4f56ff4SMark Johnston 		qat_etr_ap_bank_set_ring_mask(&qab->qab_nf_mask, qr->qr_ring, 1);
867f4f56ff4SMark Johnston 		if (!qab->qab_nf_dest) {
868f4f56ff4SMark Johnston 			qat_etr_ap_bank_set_ring_dest(sc, &qab->qab_nf_dest,
869f4f56ff4SMark Johnston 			    qr->qr_ring, 1);
870f4f56ff4SMark Johnston 			qat_etr_ap_bank_write_4(sc, ap_bank, ETR_AP_NF_DEST,
871f4f56ff4SMark Johnston 			    qab->qab_nf_dest);
872f4f56ff4SMark Johnston 		}
873f4f56ff4SMark Johnston 	}
874f4f56ff4SMark Johnston }
875f4f56ff4SMark Johnston 
876f4f56ff4SMark Johnston static int
qat_etr_verify_ring_size(uint32_t msg_size,uint32_t num_msgs)877f4f56ff4SMark Johnston qat_etr_verify_ring_size(uint32_t msg_size, uint32_t num_msgs)
878f4f56ff4SMark Johnston {
879f4f56ff4SMark Johnston 	int i = QAT_MIN_RING_SIZE;
880f4f56ff4SMark Johnston 
881f4f56ff4SMark Johnston 	for (; i <= QAT_MAX_RING_SIZE; i++)
882f4f56ff4SMark Johnston 		if ((msg_size * num_msgs) == QAT_SIZE_TO_RING_SIZE_IN_BYTES(i))
883f4f56ff4SMark Johnston 			return i;
884f4f56ff4SMark Johnston 
885f4f56ff4SMark Johnston 	return QAT_DEFAULT_RING_SIZE;
886f4f56ff4SMark Johnston }
887f4f56ff4SMark Johnston 
888f4f56ff4SMark Johnston int
qat_etr_setup_ring(struct qat_softc * sc,int bank,uint32_t ring,uint32_t num_msgs,uint32_t msg_size,qat_cb_t cb,void * cb_arg,const char * name,struct qat_ring ** rqr)889f4f56ff4SMark Johnston qat_etr_setup_ring(struct qat_softc *sc, int bank, uint32_t ring,
890f4f56ff4SMark Johnston     uint32_t num_msgs, uint32_t msg_size, qat_cb_t cb, void *cb_arg,
891f4f56ff4SMark Johnston     const char *name, struct qat_ring **rqr)
892f4f56ff4SMark Johnston {
893f4f56ff4SMark Johnston 	struct qat_bank *qb;
894f4f56ff4SMark Johnston 	struct qat_ring *qr = NULL;
895f4f56ff4SMark Johnston 	int error;
896f4f56ff4SMark Johnston 	uint32_t ring_size_bytes, ring_config;
897f4f56ff4SMark Johnston 	uint64_t ring_base;
898f4f56ff4SMark Johnston 	uint32_t wm_nf = ETR_RING_CONFIG_NEAR_WM_512;
899f4f56ff4SMark Johnston 	uint32_t wm_ne = ETR_RING_CONFIG_NEAR_WM_0;
900f4f56ff4SMark Johnston 
901f4f56ff4SMark Johnston 	MPASS(bank < sc->sc_hw.qhw_num_banks);
902f4f56ff4SMark Johnston 
903f4f56ff4SMark Johnston 	/* Allocate a ring from specified bank */
904f4f56ff4SMark Johnston 	qb = &sc->sc_etr_banks[bank];
905f4f56ff4SMark Johnston 
906f4f56ff4SMark Johnston 	if (ring >= sc->sc_hw.qhw_num_rings_per_bank)
907f4f56ff4SMark Johnston 		return EINVAL;
908f4f56ff4SMark Johnston 	if (qb->qb_allocated_rings & (1 << ring))
909f4f56ff4SMark Johnston 		return ENOENT;
910f4f56ff4SMark Johnston 	qr = &qb->qb_et_rings[ring];
911f4f56ff4SMark Johnston 	qb->qb_allocated_rings |= 1 << ring;
912f4f56ff4SMark Johnston 
913f4f56ff4SMark Johnston 	/* Initialize allocated ring */
914f4f56ff4SMark Johnston 	qr->qr_ring = ring;
915f4f56ff4SMark Johnston 	qr->qr_bank = bank;
916f4f56ff4SMark Johnston 	qr->qr_name = name;
917f4f56ff4SMark Johnston 	qr->qr_ring_id = qr->qr_bank * sc->sc_hw.qhw_num_rings_per_bank + ring;
918f4f56ff4SMark Johnston 	qr->qr_ring_mask = (1 << ring);
919f4f56ff4SMark Johnston 	qr->qr_cb = cb;
920f4f56ff4SMark Johnston 	qr->qr_cb_arg = cb_arg;
921f4f56ff4SMark Johnston 
922f4f56ff4SMark Johnston 	/* Setup the shadow variables */
923f4f56ff4SMark Johnston 	qr->qr_head = 0;
924f4f56ff4SMark Johnston 	qr->qr_tail = 0;
925f4f56ff4SMark Johnston 	qr->qr_msg_size = QAT_BYTES_TO_MSG_SIZE(msg_size);
926f4f56ff4SMark Johnston 	qr->qr_ring_size = qat_etr_verify_ring_size(msg_size, num_msgs);
927f4f56ff4SMark Johnston 
928f4f56ff4SMark Johnston 	/*
929f4f56ff4SMark Johnston 	 * To make sure that ring is alligned to ring size allocate
930f4f56ff4SMark Johnston 	 * at least 4k and then tell the user it is smaller.
931f4f56ff4SMark Johnston 	 */
932f4f56ff4SMark Johnston 	ring_size_bytes = QAT_SIZE_TO_RING_SIZE_IN_BYTES(qr->qr_ring_size);
933f4f56ff4SMark Johnston 	ring_size_bytes = QAT_RING_SIZE_BYTES_MIN(ring_size_bytes);
934f4f56ff4SMark Johnston 	error = qat_alloc_dmamem(sc, &qr->qr_dma, 1, ring_size_bytes,
935f4f56ff4SMark Johnston 	    ring_size_bytes);
936f4f56ff4SMark Johnston 	if (error)
937f4f56ff4SMark Johnston 		return error;
938f4f56ff4SMark Johnston 
939f4f56ff4SMark Johnston 	qr->qr_ring_vaddr = qr->qr_dma.qdm_dma_vaddr;
940f4f56ff4SMark Johnston 	qr->qr_ring_paddr = qr->qr_dma.qdm_dma_seg.ds_addr;
941f4f56ff4SMark Johnston 
942f4f56ff4SMark Johnston 	memset(qr->qr_ring_vaddr, QAT_RING_PATTERN,
943f4f56ff4SMark Johnston 	    qr->qr_dma.qdm_dma_seg.ds_len);
944f4f56ff4SMark Johnston 
945f4f56ff4SMark Johnston 	bus_dmamap_sync(qr->qr_dma.qdm_dma_tag, qr->qr_dma.qdm_dma_map,
946f4f56ff4SMark Johnston 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
947f4f56ff4SMark Johnston 
948f4f56ff4SMark Johnston 	if (cb == NULL) {
949f4f56ff4SMark Johnston 		ring_config = ETR_RING_CONFIG_BUILD(qr->qr_ring_size);
950f4f56ff4SMark Johnston 	} else {
951f4f56ff4SMark Johnston 		ring_config =
952f4f56ff4SMark Johnston 		    ETR_RING_CONFIG_BUILD_RESP(qr->qr_ring_size, wm_nf, wm_ne);
953f4f56ff4SMark Johnston 	}
954f4f56ff4SMark Johnston 	qat_etr_bank_ring_write_4(sc, bank, ring, ETR_RING_CONFIG, ring_config);
955f4f56ff4SMark Johnston 
956f4f56ff4SMark Johnston 	ring_base = ETR_RING_BASE_BUILD(qr->qr_ring_paddr, qr->qr_ring_size);
957f4f56ff4SMark Johnston 	qat_etr_bank_ring_base_write_8(sc, bank, ring, ring_base);
958f4f56ff4SMark Johnston 
959f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_init_arb != NULL)
960f4f56ff4SMark Johnston 		qat_arb_update(sc, qb);
961f4f56ff4SMark Johnston 
962f4f56ff4SMark Johnston 	mtx_init(&qr->qr_ring_mtx, "qr ring", NULL, MTX_DEF);
963f4f56ff4SMark Johnston 
964f4f56ff4SMark Johnston 	qat_etr_ap_bank_setup_ring(sc, qr);
965f4f56ff4SMark Johnston 
966f4f56ff4SMark Johnston 	if (cb != NULL) {
967f4f56ff4SMark Johnston 		uint32_t intr_mask;
968f4f56ff4SMark Johnston 
969f4f56ff4SMark Johnston 		qb->qb_intr_mask |= qr->qr_ring_mask;
970f4f56ff4SMark Johnston 		intr_mask = qb->qb_intr_mask;
971f4f56ff4SMark Johnston 
972f4f56ff4SMark Johnston 		qat_etr_bank_write_4(sc, bank, ETR_INT_COL_EN, intr_mask);
973f4f56ff4SMark Johnston 		qat_etr_bank_write_4(sc, bank, ETR_INT_COL_CTL,
974f4f56ff4SMark Johnston 		    ETR_INT_COL_CTL_ENABLE | qb->qb_coalescing_time);
975f4f56ff4SMark Johnston 	}
976f4f56ff4SMark Johnston 
977f4f56ff4SMark Johnston 	*rqr = qr;
978f4f56ff4SMark Johnston 
979f4f56ff4SMark Johnston 	return 0;
980f4f56ff4SMark Johnston }
981f4f56ff4SMark Johnston 
982f4f56ff4SMark Johnston static inline u_int
qat_modulo(u_int data,u_int shift)983f4f56ff4SMark Johnston qat_modulo(u_int data, u_int shift)
984f4f56ff4SMark Johnston {
985f4f56ff4SMark Johnston 	u_int div = data >> shift;
986f4f56ff4SMark Johnston 	u_int mult = div << shift;
987f4f56ff4SMark Johnston 	return data - mult;
988f4f56ff4SMark Johnston }
989f4f56ff4SMark Johnston 
990f4f56ff4SMark Johnston int
qat_etr_put_msg(struct qat_softc * sc,struct qat_ring * qr,uint32_t * msg)991f4f56ff4SMark Johnston qat_etr_put_msg(struct qat_softc *sc, struct qat_ring *qr, uint32_t *msg)
992f4f56ff4SMark Johnston {
993f4f56ff4SMark Johnston 	uint32_t inflight;
994f4f56ff4SMark Johnston 	uint32_t *addr;
995f4f56ff4SMark Johnston 
996f4f56ff4SMark Johnston 	mtx_lock(&qr->qr_ring_mtx);
997f4f56ff4SMark Johnston 
998f4f56ff4SMark Johnston 	inflight = atomic_fetchadd_32(qr->qr_inflight, 1) + 1;
999f4f56ff4SMark Johnston 	if (inflight > QAT_MAX_INFLIGHTS(qr->qr_ring_size, qr->qr_msg_size)) {
1000f4f56ff4SMark Johnston 		atomic_subtract_32(qr->qr_inflight, 1);
1001f4f56ff4SMark Johnston 		qr->qr_need_wakeup = true;
1002f4f56ff4SMark Johnston 		mtx_unlock(&qr->qr_ring_mtx);
1003f4f56ff4SMark Johnston 		counter_u64_add(sc->sc_ring_full_restarts, 1);
1004f4f56ff4SMark Johnston 		return ERESTART;
1005f4f56ff4SMark Johnston 	}
1006f4f56ff4SMark Johnston 
1007f4f56ff4SMark Johnston 	addr = (uint32_t *)((uintptr_t)qr->qr_ring_vaddr + qr->qr_tail);
1008f4f56ff4SMark Johnston 
1009f4f56ff4SMark Johnston 	memcpy(addr, msg, QAT_MSG_SIZE_TO_BYTES(qr->qr_msg_size));
1010f4f56ff4SMark Johnston 
1011f4f56ff4SMark Johnston 	bus_dmamap_sync(qr->qr_dma.qdm_dma_tag, qr->qr_dma.qdm_dma_map,
1012f4f56ff4SMark Johnston 	    BUS_DMASYNC_PREWRITE);
1013f4f56ff4SMark Johnston 
1014f4f56ff4SMark Johnston 	qr->qr_tail = qat_modulo(qr->qr_tail +
1015f4f56ff4SMark Johnston 	    QAT_MSG_SIZE_TO_BYTES(qr->qr_msg_size),
1016f4f56ff4SMark Johnston 	    QAT_RING_SIZE_MODULO(qr->qr_ring_size));
1017f4f56ff4SMark Johnston 
1018f4f56ff4SMark Johnston 	qat_etr_bank_ring_write_4(sc, qr->qr_bank, qr->qr_ring,
1019f4f56ff4SMark Johnston 	    ETR_RING_TAIL_OFFSET, qr->qr_tail);
1020f4f56ff4SMark Johnston 
1021f4f56ff4SMark Johnston 	mtx_unlock(&qr->qr_ring_mtx);
1022f4f56ff4SMark Johnston 
1023f4f56ff4SMark Johnston 	return 0;
1024f4f56ff4SMark Johnston }
1025f4f56ff4SMark Johnston 
1026f4f56ff4SMark Johnston static int
qat_etr_ring_intr(struct qat_softc * sc,struct qat_bank * qb,struct qat_ring * qr)1027f4f56ff4SMark Johnston qat_etr_ring_intr(struct qat_softc *sc, struct qat_bank *qb,
1028f4f56ff4SMark Johnston     struct qat_ring *qr)
1029f4f56ff4SMark Johnston {
1030f4f56ff4SMark Johnston 	uint32_t *msg, nmsg = 0;
1031f4f56ff4SMark Johnston 	int handled = 0;
1032f4f56ff4SMark Johnston 	bool blocked = false;
1033f4f56ff4SMark Johnston 
1034f4f56ff4SMark Johnston 	mtx_lock(&qr->qr_ring_mtx);
1035f4f56ff4SMark Johnston 
1036f4f56ff4SMark Johnston 	msg = (uint32_t *)((uintptr_t)qr->qr_ring_vaddr + qr->qr_head);
1037f4f56ff4SMark Johnston 
1038f4f56ff4SMark Johnston 	bus_dmamap_sync(qr->qr_dma.qdm_dma_tag, qr->qr_dma.qdm_dma_map,
1039f4f56ff4SMark Johnston 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1040f4f56ff4SMark Johnston 
1041f4f56ff4SMark Johnston 	while (atomic_load_32(msg) != ETR_RING_EMPTY_ENTRY_SIG) {
1042f4f56ff4SMark Johnston 		atomic_subtract_32(qr->qr_inflight, 1);
1043f4f56ff4SMark Johnston 
1044f4f56ff4SMark Johnston 		if (qr->qr_cb != NULL) {
1045f4f56ff4SMark Johnston 			mtx_unlock(&qr->qr_ring_mtx);
1046f4f56ff4SMark Johnston 			handled |= qr->qr_cb(sc, qr->qr_cb_arg, msg);
1047f4f56ff4SMark Johnston 			mtx_lock(&qr->qr_ring_mtx);
1048f4f56ff4SMark Johnston 		}
1049f4f56ff4SMark Johnston 
1050f4f56ff4SMark Johnston 		atomic_store_32(msg, ETR_RING_EMPTY_ENTRY_SIG);
1051f4f56ff4SMark Johnston 
1052f4f56ff4SMark Johnston 		qr->qr_head = qat_modulo(qr->qr_head +
1053f4f56ff4SMark Johnston 		    QAT_MSG_SIZE_TO_BYTES(qr->qr_msg_size),
1054f4f56ff4SMark Johnston 		    QAT_RING_SIZE_MODULO(qr->qr_ring_size));
1055f4f56ff4SMark Johnston 		nmsg++;
1056f4f56ff4SMark Johnston 
1057f4f56ff4SMark Johnston 		msg = (uint32_t *)((uintptr_t)qr->qr_ring_vaddr + qr->qr_head);
1058f4f56ff4SMark Johnston 	}
1059f4f56ff4SMark Johnston 
1060f4f56ff4SMark Johnston 	bus_dmamap_sync(qr->qr_dma.qdm_dma_tag, qr->qr_dma.qdm_dma_map,
1061f4f56ff4SMark Johnston 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
1062f4f56ff4SMark Johnston 
1063f4f56ff4SMark Johnston 	if (nmsg > 0) {
1064f4f56ff4SMark Johnston 		qat_etr_bank_ring_write_4(sc, qr->qr_bank, qr->qr_ring,
1065f4f56ff4SMark Johnston 		    ETR_RING_HEAD_OFFSET, qr->qr_head);
1066f4f56ff4SMark Johnston 		if (qr->qr_need_wakeup) {
1067f4f56ff4SMark Johnston 			blocked = true;
1068f4f56ff4SMark Johnston 			qr->qr_need_wakeup = false;
1069f4f56ff4SMark Johnston 		}
1070f4f56ff4SMark Johnston 	}
1071f4f56ff4SMark Johnston 
1072f4f56ff4SMark Johnston 	mtx_unlock(&qr->qr_ring_mtx);
1073f4f56ff4SMark Johnston 
1074f4f56ff4SMark Johnston 	if (blocked)
1075f4f56ff4SMark Johnston 		crypto_unblock(sc->sc_crypto.qcy_cid, CRYPTO_SYMQ);
1076f4f56ff4SMark Johnston 
1077f4f56ff4SMark Johnston 	return handled;
1078f4f56ff4SMark Johnston }
1079f4f56ff4SMark Johnston 
1080f4f56ff4SMark Johnston static void
qat_etr_bank_intr(void * arg)1081f4f56ff4SMark Johnston qat_etr_bank_intr(void *arg)
1082f4f56ff4SMark Johnston {
1083f4f56ff4SMark Johnston 	struct qat_bank *qb = arg;
1084f4f56ff4SMark Johnston 	struct qat_softc *sc = qb->qb_sc;
1085f4f56ff4SMark Johnston 	uint32_t estat;
1086f4f56ff4SMark Johnston 	int i;
1087f4f56ff4SMark Johnston 
1088f4f56ff4SMark Johnston 	mtx_lock(&qb->qb_bank_mtx);
1089f4f56ff4SMark Johnston 
1090f4f56ff4SMark Johnston 	qat_etr_bank_write_4(sc, qb->qb_bank, ETR_INT_COL_CTL, 0);
1091f4f56ff4SMark Johnston 
1092f4f56ff4SMark Johnston 	/* Now handle all the responses */
1093f4f56ff4SMark Johnston 	estat = ~qat_etr_bank_read_4(sc, qb->qb_bank, ETR_E_STAT);
1094f4f56ff4SMark Johnston 	estat &= qb->qb_intr_mask;
1095f4f56ff4SMark Johnston 
1096f4f56ff4SMark Johnston 	qat_etr_bank_write_4(sc, qb->qb_bank, ETR_INT_COL_CTL,
1097f4f56ff4SMark Johnston 	    ETR_INT_COL_CTL_ENABLE | qb->qb_coalescing_time);
1098f4f56ff4SMark Johnston 
1099f4f56ff4SMark Johnston 	mtx_unlock(&qb->qb_bank_mtx);
1100f4f56ff4SMark Johnston 
1101f4f56ff4SMark Johnston 	while ((i = ffs(estat)) != 0) {
1102f4f56ff4SMark Johnston 		struct qat_ring *qr = &qb->qb_et_rings[--i];
1103f4f56ff4SMark Johnston 		estat &= ~(1 << i);
1104f4f56ff4SMark Johnston 		(void)qat_etr_ring_intr(sc, qb, qr);
1105f4f56ff4SMark Johnston 	}
1106f4f56ff4SMark Johnston }
1107f4f56ff4SMark Johnston 
1108f4f56ff4SMark Johnston void
qat_arb_update(struct qat_softc * sc,struct qat_bank * qb)1109f4f56ff4SMark Johnston qat_arb_update(struct qat_softc *sc, struct qat_bank *qb)
1110f4f56ff4SMark Johnston {
1111f4f56ff4SMark Johnston 
1112f4f56ff4SMark Johnston 	qat_arb_ringsrvarben_write_4(sc, qb->qb_bank,
1113f4f56ff4SMark Johnston 	    qb->qb_allocated_rings & 0xff);
1114f4f56ff4SMark Johnston }
1115f4f56ff4SMark Johnston 
1116f4f56ff4SMark Johnston static struct qat_sym_cookie *
qat_crypto_alloc_sym_cookie(struct qat_crypto_bank * qcb)1117f4f56ff4SMark Johnston qat_crypto_alloc_sym_cookie(struct qat_crypto_bank *qcb)
1118f4f56ff4SMark Johnston {
1119f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
1120f4f56ff4SMark Johnston 
1121f4f56ff4SMark Johnston 	mtx_lock(&qcb->qcb_bank_mtx);
1122f4f56ff4SMark Johnston 
1123f4f56ff4SMark Johnston 	if (qcb->qcb_symck_free_count == 0) {
1124f4f56ff4SMark Johnston 		mtx_unlock(&qcb->qcb_bank_mtx);
1125f4f56ff4SMark Johnston 		return NULL;
1126f4f56ff4SMark Johnston 	}
1127f4f56ff4SMark Johnston 
1128f4f56ff4SMark Johnston 	qsc = qcb->qcb_symck_free[--qcb->qcb_symck_free_count];
1129f4f56ff4SMark Johnston 
1130f4f56ff4SMark Johnston 	mtx_unlock(&qcb->qcb_bank_mtx);
1131f4f56ff4SMark Johnston 
1132f4f56ff4SMark Johnston 	return qsc;
1133f4f56ff4SMark Johnston }
1134f4f56ff4SMark Johnston 
1135f4f56ff4SMark Johnston static void
qat_crypto_free_sym_cookie(struct qat_crypto_bank * qcb,struct qat_sym_cookie * qsc)1136f4f56ff4SMark Johnston qat_crypto_free_sym_cookie(struct qat_crypto_bank *qcb,
1137f4f56ff4SMark Johnston     struct qat_sym_cookie *qsc)
1138f4f56ff4SMark Johnston {
1139f4f56ff4SMark Johnston 	explicit_bzero(qsc->qsc_iv_buf, EALG_MAX_BLOCK_LEN);
1140f4f56ff4SMark Johnston 	explicit_bzero(qsc->qsc_auth_res, QAT_SYM_HASH_BUFFER_LEN);
1141f4f56ff4SMark Johnston 
1142f4f56ff4SMark Johnston 	mtx_lock(&qcb->qcb_bank_mtx);
1143f4f56ff4SMark Johnston 	qcb->qcb_symck_free[qcb->qcb_symck_free_count++] = qsc;
1144f4f56ff4SMark Johnston 	mtx_unlock(&qcb->qcb_bank_mtx);
1145f4f56ff4SMark Johnston }
1146f4f56ff4SMark Johnston 
1147f4f56ff4SMark Johnston void
qat_memcpy_htobe64(void * dst,const void * src,size_t len)1148f4f56ff4SMark Johnston qat_memcpy_htobe64(void *dst, const void *src, size_t len)
1149f4f56ff4SMark Johnston {
1150f4f56ff4SMark Johnston 	uint64_t *dst0 = dst;
1151f4f56ff4SMark Johnston 	const uint64_t *src0 = src;
1152f4f56ff4SMark Johnston 	size_t i;
1153f4f56ff4SMark Johnston 
1154f4f56ff4SMark Johnston 	MPASS(len % sizeof(*dst0) == 0);
1155f4f56ff4SMark Johnston 
1156f4f56ff4SMark Johnston 	for (i = 0; i < len / sizeof(*dst0); i++)
1157f4f56ff4SMark Johnston 		*(dst0 + i) = htobe64(*(src0 + i));
1158f4f56ff4SMark Johnston }
1159f4f56ff4SMark Johnston 
1160f4f56ff4SMark Johnston void
qat_memcpy_htobe32(void * dst,const void * src,size_t len)1161f4f56ff4SMark Johnston qat_memcpy_htobe32(void *dst, const void *src, size_t len)
1162f4f56ff4SMark Johnston {
1163f4f56ff4SMark Johnston 	uint32_t *dst0 = dst;
1164f4f56ff4SMark Johnston 	const uint32_t *src0 = src;
1165f4f56ff4SMark Johnston 	size_t i;
1166f4f56ff4SMark Johnston 
1167f4f56ff4SMark Johnston 	MPASS(len % sizeof(*dst0) == 0);
1168f4f56ff4SMark Johnston 
1169f4f56ff4SMark Johnston 	for (i = 0; i < len / sizeof(*dst0); i++)
1170f4f56ff4SMark Johnston 		*(dst0 + i) = htobe32(*(src0 + i));
1171f4f56ff4SMark Johnston }
1172f4f56ff4SMark Johnston 
1173f4f56ff4SMark Johnston void
qat_memcpy_htobe(void * dst,const void * src,size_t len,uint32_t wordbyte)1174f4f56ff4SMark Johnston qat_memcpy_htobe(void *dst, const void *src, size_t len, uint32_t wordbyte)
1175f4f56ff4SMark Johnston {
1176f4f56ff4SMark Johnston 	switch (wordbyte) {
1177f4f56ff4SMark Johnston 	case 4:
1178f4f56ff4SMark Johnston 		qat_memcpy_htobe32(dst, src, len);
1179f4f56ff4SMark Johnston 		break;
1180f4f56ff4SMark Johnston 	case 8:
1181f4f56ff4SMark Johnston 		qat_memcpy_htobe64(dst, src, len);
1182f4f56ff4SMark Johnston 		break;
1183f4f56ff4SMark Johnston 	default:
1184f4f56ff4SMark Johnston 		panic("invalid word size %u", wordbyte);
1185f4f56ff4SMark Johnston 	}
1186f4f56ff4SMark Johnston }
1187f4f56ff4SMark Johnston 
1188f4f56ff4SMark Johnston void
qat_crypto_gmac_precompute(const struct qat_crypto_desc * desc,const uint8_t * key,int klen,const struct qat_sym_hash_def * hash_def,uint8_t * state)1189f4f56ff4SMark Johnston qat_crypto_gmac_precompute(const struct qat_crypto_desc *desc,
1190f4f56ff4SMark Johnston     const uint8_t *key, int klen, const struct qat_sym_hash_def *hash_def,
1191f4f56ff4SMark Johnston     uint8_t *state)
1192f4f56ff4SMark Johnston {
1193f4f56ff4SMark Johnston 	uint32_t ks[4 * (RIJNDAEL_MAXNR + 1)];
1194f4f56ff4SMark Johnston 	char zeros[AES_BLOCK_LEN];
1195f4f56ff4SMark Johnston 	int rounds;
1196f4f56ff4SMark Johnston 
1197f4f56ff4SMark Johnston 	memset(zeros, 0, sizeof(zeros));
1198f4f56ff4SMark Johnston 	rounds = rijndaelKeySetupEnc(ks, key, klen * NBBY);
1199f4f56ff4SMark Johnston 	rijndaelEncrypt(ks, rounds, zeros, state);
1200f4f56ff4SMark Johnston 	explicit_bzero(ks, sizeof(ks));
1201f4f56ff4SMark Johnston }
1202f4f56ff4SMark Johnston 
1203f4f56ff4SMark Johnston void
qat_crypto_hmac_precompute(const struct qat_crypto_desc * desc,const uint8_t * key,int klen,const struct qat_sym_hash_def * hash_def,uint8_t * state1,uint8_t * state2)1204f4f56ff4SMark Johnston qat_crypto_hmac_precompute(const struct qat_crypto_desc *desc,
1205f4f56ff4SMark Johnston     const uint8_t *key, int klen, const struct qat_sym_hash_def *hash_def,
1206f4f56ff4SMark Johnston     uint8_t *state1, uint8_t *state2)
1207f4f56ff4SMark Johnston {
1208f4f56ff4SMark Johnston 	union authctx ctx;
1209f4f56ff4SMark Johnston 	const struct auth_hash *sah = hash_def->qshd_alg->qshai_sah;
1210f4f56ff4SMark Johnston 	uint32_t state_offset = hash_def->qshd_alg->qshai_state_offset;
1211f4f56ff4SMark Johnston 	uint32_t state_size = hash_def->qshd_alg->qshai_state_size;
1212f4f56ff4SMark Johnston 	uint32_t state_word = hash_def->qshd_alg->qshai_state_word;
1213f4f56ff4SMark Johnston 
1214f4f56ff4SMark Johnston 	hmac_init_ipad(sah, key, klen, &ctx);
1215f4f56ff4SMark Johnston 	qat_memcpy_htobe(state1, (uint8_t *)&ctx + state_offset, state_size,
1216f4f56ff4SMark Johnston 	    state_word);
1217f4f56ff4SMark Johnston 	hmac_init_opad(sah, key, klen, &ctx);
1218f4f56ff4SMark Johnston 	qat_memcpy_htobe(state2, (uint8_t *)&ctx + state_offset, state_size,
1219f4f56ff4SMark Johnston 	    state_word);
1220f4f56ff4SMark Johnston 	explicit_bzero(&ctx, sizeof(ctx));
1221f4f56ff4SMark Johnston }
1222f4f56ff4SMark Johnston 
1223f4f56ff4SMark Johnston static enum hw_cipher_algo
qat_aes_cipher_algo(int klen)1224f4f56ff4SMark Johnston qat_aes_cipher_algo(int klen)
1225f4f56ff4SMark Johnston {
1226f4f56ff4SMark Johnston 	switch (klen) {
1227f4f56ff4SMark Johnston 	case HW_AES_128_KEY_SZ:
1228f4f56ff4SMark Johnston 		return HW_CIPHER_ALGO_AES128;
1229f4f56ff4SMark Johnston 	case HW_AES_192_KEY_SZ:
1230f4f56ff4SMark Johnston 		return HW_CIPHER_ALGO_AES192;
1231f4f56ff4SMark Johnston 	case HW_AES_256_KEY_SZ:
1232f4f56ff4SMark Johnston 		return HW_CIPHER_ALGO_AES256;
1233f4f56ff4SMark Johnston 	default:
1234f4f56ff4SMark Johnston 		panic("invalid key length %d", klen);
1235f4f56ff4SMark Johnston 	}
1236f4f56ff4SMark Johnston }
1237f4f56ff4SMark Johnston 
1238f4f56ff4SMark Johnston uint16_t
qat_crypto_load_cipher_session(const struct qat_crypto_desc * desc,const struct qat_session * qs)1239f4f56ff4SMark Johnston qat_crypto_load_cipher_session(const struct qat_crypto_desc *desc,
1240f4f56ff4SMark Johnston     const struct qat_session *qs)
1241f4f56ff4SMark Johnston {
1242f4f56ff4SMark Johnston 	enum hw_cipher_algo algo;
1243f4f56ff4SMark Johnston 	enum hw_cipher_dir dir;
1244f4f56ff4SMark Johnston 	enum hw_cipher_convert key_convert;
1245f4f56ff4SMark Johnston 	enum hw_cipher_mode mode;
1246f4f56ff4SMark Johnston 
1247f4f56ff4SMark Johnston 	dir = desc->qcd_cipher_dir;
1248f4f56ff4SMark Johnston 	key_convert = HW_CIPHER_NO_CONVERT;
1249f4f56ff4SMark Johnston 	mode = qs->qs_cipher_mode;
1250f4f56ff4SMark Johnston 	switch (mode) {
1251f4f56ff4SMark Johnston 	case HW_CIPHER_CBC_MODE:
1252f4f56ff4SMark Johnston 	case HW_CIPHER_XTS_MODE:
1253f4f56ff4SMark Johnston 		algo = qs->qs_cipher_algo;
1254f4f56ff4SMark Johnston 
1255f4f56ff4SMark Johnston 		/*
1256f4f56ff4SMark Johnston 		 * AES decrypt key needs to be reversed.
1257f4f56ff4SMark Johnston 		 * Instead of reversing the key at session registration,
1258f4f56ff4SMark Johnston 		 * it is instead reversed on-the-fly by setting the KEY_CONVERT
1259f4f56ff4SMark Johnston 		 * bit here.
1260f4f56ff4SMark Johnston 		 */
1261f4f56ff4SMark Johnston 		if (desc->qcd_cipher_dir == HW_CIPHER_DECRYPT)
1262f4f56ff4SMark Johnston 			key_convert = HW_CIPHER_KEY_CONVERT;
1263f4f56ff4SMark Johnston 		break;
1264f4f56ff4SMark Johnston 	case HW_CIPHER_CTR_MODE:
1265f4f56ff4SMark Johnston 		algo = qs->qs_cipher_algo;
1266f4f56ff4SMark Johnston 		dir = HW_CIPHER_ENCRYPT;
1267f4f56ff4SMark Johnston 		break;
1268f4f56ff4SMark Johnston 	default:
1269f4f56ff4SMark Johnston 		panic("unhandled cipher mode %d", mode);
1270f4f56ff4SMark Johnston 		break;
1271f4f56ff4SMark Johnston 	}
1272f4f56ff4SMark Johnston 
1273f4f56ff4SMark Johnston 	return HW_CIPHER_CONFIG_BUILD(mode, algo, key_convert, dir);
1274f4f56ff4SMark Johnston }
1275f4f56ff4SMark Johnston 
1276f4f56ff4SMark Johnston uint16_t
qat_crypto_load_auth_session(const struct qat_crypto_desc * desc,const struct qat_session * qs,const struct qat_sym_hash_def ** hash_def)1277f4f56ff4SMark Johnston qat_crypto_load_auth_session(const struct qat_crypto_desc *desc,
1278f4f56ff4SMark Johnston     const struct qat_session *qs, const struct qat_sym_hash_def **hash_def)
1279f4f56ff4SMark Johnston {
1280f4f56ff4SMark Johnston 	enum qat_sym_hash_algorithm algo;
1281f4f56ff4SMark Johnston 
1282f4f56ff4SMark Johnston 	switch (qs->qs_auth_algo) {
1283f4f56ff4SMark Johnston 	case HW_AUTH_ALGO_SHA1:
1284f4f56ff4SMark Johnston 		algo = QAT_SYM_HASH_SHA1;
1285f4f56ff4SMark Johnston 		break;
1286f4f56ff4SMark Johnston 	case HW_AUTH_ALGO_SHA256:
1287f4f56ff4SMark Johnston 		algo = QAT_SYM_HASH_SHA256;
1288f4f56ff4SMark Johnston 		break;
1289f4f56ff4SMark Johnston 	case HW_AUTH_ALGO_SHA384:
1290f4f56ff4SMark Johnston 		algo = QAT_SYM_HASH_SHA384;
1291f4f56ff4SMark Johnston 		break;
1292f4f56ff4SMark Johnston 	case HW_AUTH_ALGO_SHA512:
1293f4f56ff4SMark Johnston 		algo = QAT_SYM_HASH_SHA512;
1294f4f56ff4SMark Johnston 		break;
1295f4f56ff4SMark Johnston 	case HW_AUTH_ALGO_GALOIS_128:
1296f4f56ff4SMark Johnston 		algo = QAT_SYM_HASH_AES_GCM;
1297f4f56ff4SMark Johnston 		break;
1298f4f56ff4SMark Johnston 	default:
1299f4f56ff4SMark Johnston 		panic("unhandled auth algorithm %d", qs->qs_auth_algo);
1300f4f56ff4SMark Johnston 		break;
1301f4f56ff4SMark Johnston 	}
1302f4f56ff4SMark Johnston 	*hash_def = &qat_sym_hash_defs[algo];
1303f4f56ff4SMark Johnston 
1304f4f56ff4SMark Johnston 	return HW_AUTH_CONFIG_BUILD(qs->qs_auth_mode,
1305f4f56ff4SMark Johnston 	    (*hash_def)->qshd_qat->qshqi_algo_enc,
1306f4f56ff4SMark Johnston 	    (*hash_def)->qshd_alg->qshai_digest_len);
1307f4f56ff4SMark Johnston }
1308f4f56ff4SMark Johnston 
1309f4f56ff4SMark Johnston struct qat_crypto_load_cb_arg {
1310f4f56ff4SMark Johnston 	struct qat_session	*qs;
1311f4f56ff4SMark Johnston 	struct qat_sym_cookie	*qsc;
1312f4f56ff4SMark Johnston 	struct cryptop		*crp;
1313f4f56ff4SMark Johnston 	int			error;
1314f4f56ff4SMark Johnston };
1315f4f56ff4SMark Johnston 
1316f4f56ff4SMark Johnston static int
qat_crypto_populate_buf_list(struct buffer_list_desc * buffers,bus_dma_segment_t * segs,int niseg,int noseg,int skip)1317f4f56ff4SMark Johnston qat_crypto_populate_buf_list(struct buffer_list_desc *buffers,
1318f4f56ff4SMark Johnston     bus_dma_segment_t *segs, int niseg, int noseg, int skip)
1319f4f56ff4SMark Johnston {
1320f4f56ff4SMark Johnston 	struct flat_buffer_desc *flatbuf;
1321f4f56ff4SMark Johnston 	bus_addr_t addr;
1322f4f56ff4SMark Johnston 	bus_size_t len;
1323f4f56ff4SMark Johnston 	int iseg, oseg;
1324f4f56ff4SMark Johnston 
1325f4f56ff4SMark Johnston 	for (iseg = 0, oseg = noseg; iseg < niseg && oseg < QAT_MAXSEG;
1326f4f56ff4SMark Johnston 	    iseg++) {
1327f4f56ff4SMark Johnston 		addr = segs[iseg].ds_addr;
1328f4f56ff4SMark Johnston 		len = segs[iseg].ds_len;
1329f4f56ff4SMark Johnston 
1330f4f56ff4SMark Johnston 		if (skip > 0) {
1331f4f56ff4SMark Johnston 			if (skip < len) {
1332f4f56ff4SMark Johnston 				addr += skip;
1333f4f56ff4SMark Johnston 				len -= skip;
1334f4f56ff4SMark Johnston 				skip = 0;
1335f4f56ff4SMark Johnston 			} else {
1336f4f56ff4SMark Johnston 				skip -= len;
1337f4f56ff4SMark Johnston 				continue;
1338f4f56ff4SMark Johnston 			}
1339f4f56ff4SMark Johnston 		}
1340f4f56ff4SMark Johnston 
1341f4f56ff4SMark Johnston 		flatbuf = &buffers->flat_bufs[oseg++];
1342f4f56ff4SMark Johnston 		flatbuf->data_len_in_bytes = (uint32_t)len;
1343f4f56ff4SMark Johnston 		flatbuf->phy_buffer = (uint64_t)addr;
1344f4f56ff4SMark Johnston 	}
1345f4f56ff4SMark Johnston 	buffers->num_buffers = oseg;
1346f4f56ff4SMark Johnston 	return iseg < niseg ? E2BIG : 0;
1347f4f56ff4SMark Johnston }
1348f4f56ff4SMark Johnston 
1349f4f56ff4SMark Johnston static void
qat_crypto_load_aadbuf_cb(void * _arg,bus_dma_segment_t * segs,int nseg,int error)1350f4f56ff4SMark Johnston qat_crypto_load_aadbuf_cb(void *_arg, bus_dma_segment_t *segs, int nseg,
1351f4f56ff4SMark Johnston     int error)
1352f4f56ff4SMark Johnston {
1353f4f56ff4SMark Johnston 	struct qat_crypto_load_cb_arg *arg;
1354f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
1355f4f56ff4SMark Johnston 
1356f4f56ff4SMark Johnston 	arg = _arg;
1357f4f56ff4SMark Johnston 	if (error != 0) {
1358f4f56ff4SMark Johnston 		arg->error = error;
1359f4f56ff4SMark Johnston 		return;
1360f4f56ff4SMark Johnston 	}
1361f4f56ff4SMark Johnston 
1362f4f56ff4SMark Johnston 	qsc = arg->qsc;
1363f4f56ff4SMark Johnston 	arg->error = qat_crypto_populate_buf_list(&qsc->qsc_buf_list, segs,
1364f4f56ff4SMark Johnston 	    nseg, 0, 0);
1365f4f56ff4SMark Johnston }
1366f4f56ff4SMark Johnston 
1367f4f56ff4SMark Johnston static void
qat_crypto_load_buf_cb(void * _arg,bus_dma_segment_t * segs,int nseg,int error)1368f4f56ff4SMark Johnston qat_crypto_load_buf_cb(void *_arg, bus_dma_segment_t *segs, int nseg,
1369f4f56ff4SMark Johnston     int error)
1370f4f56ff4SMark Johnston {
1371f4f56ff4SMark Johnston 	struct cryptop *crp;
1372f4f56ff4SMark Johnston 	struct qat_crypto_load_cb_arg *arg;
1373f4f56ff4SMark Johnston 	struct qat_session *qs;
1374f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
1375f4f56ff4SMark Johnston 	int noseg, skip;
1376f4f56ff4SMark Johnston 
1377f4f56ff4SMark Johnston 	arg = _arg;
1378f4f56ff4SMark Johnston 	if (error != 0) {
1379f4f56ff4SMark Johnston 		arg->error = error;
1380f4f56ff4SMark Johnston 		return;
1381f4f56ff4SMark Johnston 	}
1382f4f56ff4SMark Johnston 
1383f4f56ff4SMark Johnston 	crp = arg->crp;
1384f4f56ff4SMark Johnston 	qs = arg->qs;
1385f4f56ff4SMark Johnston 	qsc = arg->qsc;
1386f4f56ff4SMark Johnston 
1387f4f56ff4SMark Johnston 	if (qs->qs_auth_algo == HW_AUTH_ALGO_GALOIS_128) {
1388f4f56ff4SMark Johnston 		/* AAD was handled in qat_crypto_load(). */
1389f4f56ff4SMark Johnston 		skip = crp->crp_payload_start;
1390f4f56ff4SMark Johnston 		noseg = 0;
1391f4f56ff4SMark Johnston 	} else if (crp->crp_aad == NULL && crp->crp_aad_length > 0) {
1392f4f56ff4SMark Johnston 		skip = crp->crp_aad_start;
1393f4f56ff4SMark Johnston 		noseg = 0;
1394f4f56ff4SMark Johnston 	} else {
1395f4f56ff4SMark Johnston 		skip = crp->crp_payload_start;
1396f4f56ff4SMark Johnston 		noseg = crp->crp_aad == NULL ?
1397f4f56ff4SMark Johnston 		    0 : qsc->qsc_buf_list.num_buffers;
1398f4f56ff4SMark Johnston 	}
1399f4f56ff4SMark Johnston 	arg->error = qat_crypto_populate_buf_list(&qsc->qsc_buf_list, segs,
1400f4f56ff4SMark Johnston 	    nseg, noseg, skip);
1401f4f56ff4SMark Johnston }
1402f4f56ff4SMark Johnston 
1403f4f56ff4SMark Johnston static void
qat_crypto_load_obuf_cb(void * _arg,bus_dma_segment_t * segs,int nseg,int error)1404f4f56ff4SMark Johnston qat_crypto_load_obuf_cb(void *_arg, bus_dma_segment_t *segs, int nseg,
1405f4f56ff4SMark Johnston     int error)
1406f4f56ff4SMark Johnston {
1407f4f56ff4SMark Johnston 	struct buffer_list_desc *ibufs, *obufs;
1408f4f56ff4SMark Johnston 	struct flat_buffer_desc *ibuf, *obuf;
1409f4f56ff4SMark Johnston 	struct cryptop *crp;
1410f4f56ff4SMark Johnston 	struct qat_crypto_load_cb_arg *arg;
1411f4f56ff4SMark Johnston 	struct qat_session *qs;
1412f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
1413f4f56ff4SMark Johnston 	int buflen, osegs, tocopy;
1414f4f56ff4SMark Johnston 
1415f4f56ff4SMark Johnston 	arg = _arg;
1416f4f56ff4SMark Johnston 	if (error != 0) {
1417f4f56ff4SMark Johnston 		arg->error = error;
1418f4f56ff4SMark Johnston 		return;
1419f4f56ff4SMark Johnston 	}
1420f4f56ff4SMark Johnston 
1421f4f56ff4SMark Johnston 	crp = arg->crp;
1422f4f56ff4SMark Johnston 	qs = arg->qs;
1423f4f56ff4SMark Johnston 	qsc = arg->qsc;
1424f4f56ff4SMark Johnston 
1425f4f56ff4SMark Johnston 	/*
1426f4f56ff4SMark Johnston 	 * The payload must start at the same offset in the output SG list as in
1427f4f56ff4SMark Johnston 	 * the input SG list.  Copy over SG entries from the input corresponding
1428f4f56ff4SMark Johnston 	 * to the AAD buffer.
1429f4f56ff4SMark Johnston 	 */
1430f4f56ff4SMark Johnston 	osegs = 0;
1431f4f56ff4SMark Johnston 	if (qs->qs_auth_algo != HW_AUTH_ALGO_GALOIS_128 &&
1432f4f56ff4SMark Johnston 	    crp->crp_aad_length > 0) {
1433f4f56ff4SMark Johnston 		tocopy = crp->crp_aad == NULL ?
1434f4f56ff4SMark Johnston 		    crp->crp_payload_start - crp->crp_aad_start :
1435f4f56ff4SMark Johnston 		    crp->crp_aad_length;
1436f4f56ff4SMark Johnston 
1437f4f56ff4SMark Johnston 		ibufs = &qsc->qsc_buf_list;
1438f4f56ff4SMark Johnston 		obufs = &qsc->qsc_obuf_list;
1439f4f56ff4SMark Johnston 		for (; osegs < ibufs->num_buffers && tocopy > 0; osegs++) {
1440f4f56ff4SMark Johnston 			ibuf = &ibufs->flat_bufs[osegs];
1441f4f56ff4SMark Johnston 			obuf = &obufs->flat_bufs[osegs];
1442f4f56ff4SMark Johnston 
1443f4f56ff4SMark Johnston 			obuf->phy_buffer = ibuf->phy_buffer;
1444f4f56ff4SMark Johnston 			buflen = imin(ibuf->data_len_in_bytes, tocopy);
1445f4f56ff4SMark Johnston 			obuf->data_len_in_bytes = buflen;
1446f4f56ff4SMark Johnston 			tocopy -= buflen;
1447f4f56ff4SMark Johnston 		}
1448f4f56ff4SMark Johnston 	}
1449f4f56ff4SMark Johnston 
1450f4f56ff4SMark Johnston 	arg->error = qat_crypto_populate_buf_list(&qsc->qsc_obuf_list, segs,
1451f4f56ff4SMark Johnston 	    nseg, osegs, crp->crp_payload_output_start);
1452f4f56ff4SMark Johnston }
1453f4f56ff4SMark Johnston 
1454f4f56ff4SMark Johnston static int
qat_crypto_load(struct qat_session * qs,struct qat_sym_cookie * qsc,struct qat_crypto_desc const * desc,struct cryptop * crp)1455f4f56ff4SMark Johnston qat_crypto_load(struct qat_session *qs, struct qat_sym_cookie *qsc,
1456f4f56ff4SMark Johnston     struct qat_crypto_desc const *desc, struct cryptop *crp)
1457f4f56ff4SMark Johnston {
1458f4f56ff4SMark Johnston 	struct qat_crypto_load_cb_arg arg;
1459f4f56ff4SMark Johnston 	int error;
1460f4f56ff4SMark Johnston 
1461f4f56ff4SMark Johnston 	crypto_read_iv(crp, qsc->qsc_iv_buf);
1462f4f56ff4SMark Johnston 
1463f4f56ff4SMark Johnston 	arg.crp = crp;
1464f4f56ff4SMark Johnston 	arg.qs = qs;
1465f4f56ff4SMark Johnston 	arg.qsc = qsc;
1466f4f56ff4SMark Johnston 	arg.error = 0;
1467f4f56ff4SMark Johnston 
1468f4f56ff4SMark Johnston 	error = 0;
1469f4f56ff4SMark Johnston 	if (qs->qs_auth_algo == HW_AUTH_ALGO_GALOIS_128 &&
1470f4f56ff4SMark Johnston 	    crp->crp_aad_length > 0) {
1471f4f56ff4SMark Johnston 		/*
1472f4f56ff4SMark Johnston 		 * The firmware expects AAD to be in a contiguous buffer and
1473f4f56ff4SMark Johnston 		 * padded to a multiple of 16 bytes.  To satisfy these
1474f4f56ff4SMark Johnston 		 * constraints we bounce the AAD into a per-request buffer.
1475f4f56ff4SMark Johnston 		 * There is a small limit on the AAD size so this is not too
1476f4f56ff4SMark Johnston 		 * onerous.
1477f4f56ff4SMark Johnston 		 */
1478f4f56ff4SMark Johnston 		memset(qsc->qsc_gcm_aad, 0, QAT_GCM_AAD_SIZE_MAX);
1479f4f56ff4SMark Johnston 		if (crp->crp_aad == NULL) {
1480f4f56ff4SMark Johnston 			crypto_copydata(crp, crp->crp_aad_start,
1481f4f56ff4SMark Johnston 			    crp->crp_aad_length, qsc->qsc_gcm_aad);
1482f4f56ff4SMark Johnston 		} else {
1483f4f56ff4SMark Johnston 			memcpy(qsc->qsc_gcm_aad, crp->crp_aad,
1484f4f56ff4SMark Johnston 			    crp->crp_aad_length);
1485f4f56ff4SMark Johnston 		}
1486f4f56ff4SMark Johnston 	} else if (crp->crp_aad != NULL) {
1487f4f56ff4SMark Johnston 		error = bus_dmamap_load(
1488f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_AADBUF].qsd_dma_tag,
1489f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_AADBUF].qsd_dmamap,
1490f4f56ff4SMark Johnston 		    crp->crp_aad, crp->crp_aad_length,
1491f4f56ff4SMark Johnston 		    qat_crypto_load_aadbuf_cb, &arg, BUS_DMA_NOWAIT);
1492f4f56ff4SMark Johnston 		if (error == 0)
1493f4f56ff4SMark Johnston 			error = arg.error;
1494f4f56ff4SMark Johnston 	}
1495f4f56ff4SMark Johnston 	if (error == 0) {
1496f4f56ff4SMark Johnston 		error = bus_dmamap_load_crp_buffer(
1497f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_BUF].qsd_dma_tag,
1498f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_BUF].qsd_dmamap,
1499f4f56ff4SMark Johnston 		    &crp->crp_buf, qat_crypto_load_buf_cb, &arg,
1500f4f56ff4SMark Johnston 		    BUS_DMA_NOWAIT);
1501f4f56ff4SMark Johnston 		if (error == 0)
1502f4f56ff4SMark Johnston 			error = arg.error;
1503f4f56ff4SMark Johnston 	}
1504f4f56ff4SMark Johnston 	if (error == 0 && CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
1505f4f56ff4SMark Johnston 		error = bus_dmamap_load_crp_buffer(
1506f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_OBUF].qsd_dma_tag,
1507f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_OBUF].qsd_dmamap,
1508f4f56ff4SMark Johnston 		    &crp->crp_obuf, qat_crypto_load_obuf_cb, &arg,
1509f4f56ff4SMark Johnston 		    BUS_DMA_NOWAIT);
1510f4f56ff4SMark Johnston 		if (error == 0)
1511f4f56ff4SMark Johnston 			error = arg.error;
1512f4f56ff4SMark Johnston 	}
1513f4f56ff4SMark Johnston 	return error;
1514f4f56ff4SMark Johnston }
1515f4f56ff4SMark Johnston 
1516f4f56ff4SMark Johnston static inline struct qat_crypto_bank *
qat_crypto_select_bank(struct qat_crypto * qcy)1517f4f56ff4SMark Johnston qat_crypto_select_bank(struct qat_crypto *qcy)
1518f4f56ff4SMark Johnston {
1519f4f56ff4SMark Johnston 	u_int cpuid = PCPU_GET(cpuid);
1520f4f56ff4SMark Johnston 
1521f4f56ff4SMark Johnston 	return &qcy->qcy_banks[cpuid % qcy->qcy_num_banks];
1522f4f56ff4SMark Johnston }
1523f4f56ff4SMark Johnston 
1524f4f56ff4SMark Johnston static int
qat_crypto_setup_ring(struct qat_softc * sc,struct qat_crypto_bank * qcb)1525f4f56ff4SMark Johnston qat_crypto_setup_ring(struct qat_softc *sc, struct qat_crypto_bank *qcb)
1526f4f56ff4SMark Johnston {
1527f4f56ff4SMark Johnston 	char *name;
1528f4f56ff4SMark Johnston 	int bank, curname, error, i, j;
1529f4f56ff4SMark Johnston 
1530f4f56ff4SMark Johnston 	bank = qcb->qcb_bank;
1531f4f56ff4SMark Johnston 	curname = 0;
1532f4f56ff4SMark Johnston 
1533f4f56ff4SMark Johnston 	name = qcb->qcb_ring_names[curname++];
1534f4f56ff4SMark Johnston 	snprintf(name, QAT_RING_NAME_SIZE, "bank%d sym_tx", bank);
1535f4f56ff4SMark Johnston 	error = qat_etr_setup_ring(sc, qcb->qcb_bank,
1536f4f56ff4SMark Johnston 	    sc->sc_hw.qhw_ring_sym_tx, QAT_NSYMREQ, sc->sc_hw.qhw_fw_req_size,
1537f4f56ff4SMark Johnston 	    NULL, NULL, name, &qcb->qcb_sym_tx);
1538f4f56ff4SMark Johnston 	if (error)
1539f4f56ff4SMark Johnston 		return error;
1540f4f56ff4SMark Johnston 
1541f4f56ff4SMark Johnston 	name = qcb->qcb_ring_names[curname++];
1542f4f56ff4SMark Johnston 	snprintf(name, QAT_RING_NAME_SIZE, "bank%d sym_rx", bank);
1543f4f56ff4SMark Johnston 	error = qat_etr_setup_ring(sc, qcb->qcb_bank,
1544f4f56ff4SMark Johnston 	    sc->sc_hw.qhw_ring_sym_rx, QAT_NSYMREQ, sc->sc_hw.qhw_fw_resp_size,
1545f4f56ff4SMark Johnston 	    qat_crypto_sym_rxintr, qcb, name, &qcb->qcb_sym_rx);
1546f4f56ff4SMark Johnston 	if (error)
1547f4f56ff4SMark Johnston 		return error;
1548f4f56ff4SMark Johnston 
1549f4f56ff4SMark Johnston 	for (i = 0; i < QAT_NSYMCOOKIE; i++) {
1550f4f56ff4SMark Johnston 		struct qat_dmamem *qdm = &qcb->qcb_symck_dmamems[i];
1551f4f56ff4SMark Johnston 		struct qat_sym_cookie *qsc;
1552f4f56ff4SMark Johnston 
1553f4f56ff4SMark Johnston 		error = qat_alloc_dmamem(sc, qdm, 1,
1554f4f56ff4SMark Johnston 		    sizeof(struct qat_sym_cookie), QAT_OPTIMAL_ALIGN);
1555f4f56ff4SMark Johnston 		if (error)
1556f4f56ff4SMark Johnston 			return error;
1557f4f56ff4SMark Johnston 
1558f4f56ff4SMark Johnston 		qsc = qdm->qdm_dma_vaddr;
1559f4f56ff4SMark Johnston 		qsc->qsc_self_dmamap = qdm->qdm_dma_map;
1560f4f56ff4SMark Johnston 		qsc->qsc_self_dma_tag = qdm->qdm_dma_tag;
1561f4f56ff4SMark Johnston 		qsc->qsc_bulk_req_params_buf_paddr =
1562f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1563f4f56ff4SMark Johnston 		    qsc_bulk_cookie.qsbc_req_params_buf);
1564f4f56ff4SMark Johnston 		qsc->qsc_buffer_list_desc_paddr =
1565f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1566f4f56ff4SMark Johnston 		    qsc_buf_list);
1567f4f56ff4SMark Johnston 		qsc->qsc_obuffer_list_desc_paddr =
1568f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1569f4f56ff4SMark Johnston 		    qsc_obuf_list);
1570f4f56ff4SMark Johnston 		qsc->qsc_obuffer_list_desc_paddr =
1571f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1572f4f56ff4SMark Johnston 		    qsc_obuf_list);
1573f4f56ff4SMark Johnston 		qsc->qsc_iv_buf_paddr =
1574f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1575f4f56ff4SMark Johnston 		    qsc_iv_buf);
1576f4f56ff4SMark Johnston 		qsc->qsc_auth_res_paddr =
1577f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1578f4f56ff4SMark Johnston 		    qsc_auth_res);
1579f4f56ff4SMark Johnston 		qsc->qsc_gcm_aad_paddr =
1580f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1581f4f56ff4SMark Johnston 		    qsc_gcm_aad);
1582f4f56ff4SMark Johnston 		qsc->qsc_content_desc_paddr =
1583f4f56ff4SMark Johnston 		    qdm->qdm_dma_seg.ds_addr + offsetof(struct qat_sym_cookie,
1584f4f56ff4SMark Johnston 		    qsc_content_desc);
1585f4f56ff4SMark Johnston 		qcb->qcb_symck_free[i] = qsc;
1586f4f56ff4SMark Johnston 		qcb->qcb_symck_free_count++;
1587f4f56ff4SMark Johnston 
1588f4f56ff4SMark Johnston 		for (j = 0; j < QAT_SYM_DMA_COUNT; j++) {
1589f4f56ff4SMark Johnston 			error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev),
1590f4f56ff4SMark Johnston 			    1, 0, 		/* alignment, boundary */
1591f4f56ff4SMark Johnston 			    BUS_SPACE_MAXADDR,	/* lowaddr */
1592f4f56ff4SMark Johnston 			    BUS_SPACE_MAXADDR, 	/* highaddr */
1593f4f56ff4SMark Johnston 			    NULL, NULL, 	/* filter, filterarg */
1594f4f56ff4SMark Johnston 			    QAT_MAXLEN,		/* maxsize */
1595f4f56ff4SMark Johnston 			    QAT_MAXSEG,		/* nsegments */
1596f4f56ff4SMark Johnston 			    QAT_MAXLEN,		/* maxsegsize */
1597f4f56ff4SMark Johnston 			    BUS_DMA_COHERENT,	/* flags */
1598f4f56ff4SMark Johnston 			    NULL, NULL,		/* lockfunc, lockarg */
1599f4f56ff4SMark Johnston 			    &qsc->qsc_dma[j].qsd_dma_tag);
1600f4f56ff4SMark Johnston 			if (error != 0)
1601f4f56ff4SMark Johnston 				return error;
1602f4f56ff4SMark Johnston 			error = bus_dmamap_create(qsc->qsc_dma[j].qsd_dma_tag,
1603f4f56ff4SMark Johnston 			    BUS_DMA_COHERENT, &qsc->qsc_dma[j].qsd_dmamap);
1604f4f56ff4SMark Johnston 			if (error != 0)
1605f4f56ff4SMark Johnston 				return error;
1606f4f56ff4SMark Johnston 		}
1607f4f56ff4SMark Johnston 	}
1608f4f56ff4SMark Johnston 
1609f4f56ff4SMark Johnston 	return 0;
1610f4f56ff4SMark Johnston }
1611f4f56ff4SMark Johnston 
1612f4f56ff4SMark Johnston static int
qat_crypto_bank_init(struct qat_softc * sc,struct qat_crypto_bank * qcb)1613f4f56ff4SMark Johnston qat_crypto_bank_init(struct qat_softc *sc, struct qat_crypto_bank *qcb)
1614f4f56ff4SMark Johnston {
1615f4f56ff4SMark Johnston 	mtx_init(&qcb->qcb_bank_mtx, "qcb bank", NULL, MTX_DEF);
1616f4f56ff4SMark Johnston 
1617f4f56ff4SMark Johnston 	return qat_crypto_setup_ring(sc, qcb);
1618f4f56ff4SMark Johnston }
1619f4f56ff4SMark Johnston 
1620f4f56ff4SMark Johnston static void
qat_crypto_bank_deinit(struct qat_softc * sc,struct qat_crypto_bank * qcb)1621f4f56ff4SMark Johnston qat_crypto_bank_deinit(struct qat_softc *sc, struct qat_crypto_bank *qcb)
1622f4f56ff4SMark Johnston {
1623f4f56ff4SMark Johnston 	struct qat_dmamem *qdm;
1624f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
1625f4f56ff4SMark Johnston 	int i, j;
1626f4f56ff4SMark Johnston 
1627f4f56ff4SMark Johnston 	for (i = 0; i < QAT_NSYMCOOKIE; i++) {
1628f4f56ff4SMark Johnston 		qdm = &qcb->qcb_symck_dmamems[i];
1629f4f56ff4SMark Johnston 		qsc = qcb->qcb_symck_free[i];
1630f4f56ff4SMark Johnston 		for (j = 0; j < QAT_SYM_DMA_COUNT; j++) {
1631f4f56ff4SMark Johnston 			bus_dmamap_destroy(qsc->qsc_dma[j].qsd_dma_tag,
1632f4f56ff4SMark Johnston 			    qsc->qsc_dma[j].qsd_dmamap);
1633f4f56ff4SMark Johnston 			bus_dma_tag_destroy(qsc->qsc_dma[j].qsd_dma_tag);
1634f4f56ff4SMark Johnston 		}
1635f4f56ff4SMark Johnston 		qat_free_dmamem(sc, qdm);
1636f4f56ff4SMark Johnston 	}
1637f4f56ff4SMark Johnston 	qat_free_dmamem(sc, &qcb->qcb_sym_tx->qr_dma);
1638f4f56ff4SMark Johnston 	qat_free_dmamem(sc, &qcb->qcb_sym_rx->qr_dma);
1639f4f56ff4SMark Johnston 
1640f4f56ff4SMark Johnston 	mtx_destroy(&qcb->qcb_bank_mtx);
1641f4f56ff4SMark Johnston }
1642f4f56ff4SMark Johnston 
1643f4f56ff4SMark Johnston static int
qat_crypto_init(struct qat_softc * sc)1644f4f56ff4SMark Johnston qat_crypto_init(struct qat_softc *sc)
1645f4f56ff4SMark Johnston {
1646f4f56ff4SMark Johnston 	struct qat_crypto *qcy = &sc->sc_crypto;
1647f4f56ff4SMark Johnston 	struct sysctl_ctx_list *ctx;
1648f4f56ff4SMark Johnston 	struct sysctl_oid *oid;
1649f4f56ff4SMark Johnston 	struct sysctl_oid_list *children;
1650f4f56ff4SMark Johnston 	int bank, error, num_banks;
1651f4f56ff4SMark Johnston 
1652f4f56ff4SMark Johnston 	qcy->qcy_sc = sc;
1653f4f56ff4SMark Johnston 
1654f4f56ff4SMark Johnston 	if (sc->sc_hw.qhw_init_arb != NULL)
1655f4f56ff4SMark Johnston 		num_banks = imin(mp_ncpus, sc->sc_hw.qhw_num_banks);
1656f4f56ff4SMark Johnston 	else
1657f4f56ff4SMark Johnston 		num_banks = sc->sc_ae_num;
1658f4f56ff4SMark Johnston 
1659f4f56ff4SMark Johnston 	qcy->qcy_num_banks = num_banks;
1660f4f56ff4SMark Johnston 
1661f4f56ff4SMark Johnston 	qcy->qcy_banks =
1662f4f56ff4SMark Johnston 	    qat_alloc_mem(sizeof(struct qat_crypto_bank) * num_banks);
1663f4f56ff4SMark Johnston 
1664f4f56ff4SMark Johnston 	for (bank = 0; bank < num_banks; bank++) {
1665f4f56ff4SMark Johnston 		struct qat_crypto_bank *qcb = &qcy->qcy_banks[bank];
1666f4f56ff4SMark Johnston 		qcb->qcb_bank = bank;
1667f4f56ff4SMark Johnston 		error = qat_crypto_bank_init(sc, qcb);
1668f4f56ff4SMark Johnston 		if (error)
1669f4f56ff4SMark Johnston 			return error;
1670f4f56ff4SMark Johnston 	}
1671f4f56ff4SMark Johnston 
1672f4f56ff4SMark Johnston 	mtx_init(&qcy->qcy_crypto_mtx, "qcy crypto", NULL, MTX_DEF);
1673f4f56ff4SMark Johnston 
1674f4f56ff4SMark Johnston 	ctx = device_get_sysctl_ctx(sc->sc_dev);
1675f4f56ff4SMark Johnston 	oid = device_get_sysctl_tree(sc->sc_dev);
1676f4f56ff4SMark Johnston 	children = SYSCTL_CHILDREN(oid);
1677f4f56ff4SMark Johnston 	oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats",
1678f4f56ff4SMark Johnston 	    CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "statistics");
1679f4f56ff4SMark Johnston 	children = SYSCTL_CHILDREN(oid);
1680f4f56ff4SMark Johnston 
1681f4f56ff4SMark Johnston 	sc->sc_gcm_aad_restarts = counter_u64_alloc(M_WAITOK);
1682f4f56ff4SMark Johnston 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "gcm_aad_restarts",
1683f4f56ff4SMark Johnston 	    CTLFLAG_RD, &sc->sc_gcm_aad_restarts,
1684f4f56ff4SMark Johnston 	    "GCM requests deferred due to AAD size change");
1685f4f56ff4SMark Johnston 	sc->sc_gcm_aad_updates = counter_u64_alloc(M_WAITOK);
1686f4f56ff4SMark Johnston 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "gcm_aad_updates",
1687f4f56ff4SMark Johnston 	    CTLFLAG_RD, &sc->sc_gcm_aad_updates,
1688f4f56ff4SMark Johnston 	    "GCM requests that required session state update");
1689f4f56ff4SMark Johnston 	sc->sc_ring_full_restarts = counter_u64_alloc(M_WAITOK);
1690f4f56ff4SMark Johnston 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "ring_full",
1691f4f56ff4SMark Johnston 	    CTLFLAG_RD, &sc->sc_ring_full_restarts,
1692f4f56ff4SMark Johnston 	    "Requests deferred due to in-flight max reached");
1693f4f56ff4SMark Johnston 	sc->sc_sym_alloc_failures = counter_u64_alloc(M_WAITOK);
1694f4f56ff4SMark Johnston 	SYSCTL_ADD_COUNTER_U64(ctx, children, OID_AUTO, "sym_alloc_failures",
1695f4f56ff4SMark Johnston 	    CTLFLAG_RD, &sc->sc_sym_alloc_failures,
1696f4f56ff4SMark Johnston 	    "Request allocation failures");
1697f4f56ff4SMark Johnston 
1698f4f56ff4SMark Johnston 	return 0;
1699f4f56ff4SMark Johnston }
1700f4f56ff4SMark Johnston 
1701f4f56ff4SMark Johnston static void
qat_crypto_deinit(struct qat_softc * sc)1702f4f56ff4SMark Johnston qat_crypto_deinit(struct qat_softc *sc)
1703f4f56ff4SMark Johnston {
1704f4f56ff4SMark Johnston 	struct qat_crypto *qcy = &sc->sc_crypto;
1705f4f56ff4SMark Johnston 	struct qat_crypto_bank *qcb;
1706f4f56ff4SMark Johnston 	int bank;
1707f4f56ff4SMark Johnston 
1708f4f56ff4SMark Johnston 	counter_u64_free(sc->sc_sym_alloc_failures);
1709f4f56ff4SMark Johnston 	counter_u64_free(sc->sc_ring_full_restarts);
1710f4f56ff4SMark Johnston 	counter_u64_free(sc->sc_gcm_aad_updates);
1711f4f56ff4SMark Johnston 	counter_u64_free(sc->sc_gcm_aad_restarts);
1712f4f56ff4SMark Johnston 
1713f4f56ff4SMark Johnston 	if (qcy->qcy_banks != NULL) {
1714f4f56ff4SMark Johnston 		for (bank = 0; bank < qcy->qcy_num_banks; bank++) {
1715f4f56ff4SMark Johnston 			qcb = &qcy->qcy_banks[bank];
1716f4f56ff4SMark Johnston 			qat_crypto_bank_deinit(sc, qcb);
1717f4f56ff4SMark Johnston 		}
1718f4f56ff4SMark Johnston 		qat_free_mem(qcy->qcy_banks);
1719f4f56ff4SMark Johnston 		mtx_destroy(&qcy->qcy_crypto_mtx);
1720f4f56ff4SMark Johnston 	}
1721f4f56ff4SMark Johnston }
1722f4f56ff4SMark Johnston 
1723f4f56ff4SMark Johnston static int
qat_crypto_start(struct qat_softc * sc)1724f4f56ff4SMark Johnston qat_crypto_start(struct qat_softc *sc)
1725f4f56ff4SMark Johnston {
1726f4f56ff4SMark Johnston 	struct qat_crypto *qcy;
1727f4f56ff4SMark Johnston 
1728f4f56ff4SMark Johnston 	qcy = &sc->sc_crypto;
1729f4f56ff4SMark Johnston 	qcy->qcy_cid = crypto_get_driverid(sc->sc_dev,
1730f4f56ff4SMark Johnston 	    sizeof(struct qat_session), CRYPTOCAP_F_HARDWARE);
1731f4f56ff4SMark Johnston 	if (qcy->qcy_cid < 0) {
1732f4f56ff4SMark Johnston 		device_printf(sc->sc_dev,
1733f4f56ff4SMark Johnston 		    "could not get opencrypto driver id\n");
1734f4f56ff4SMark Johnston 		return ENOENT;
1735f4f56ff4SMark Johnston 	}
1736f4f56ff4SMark Johnston 
1737f4f56ff4SMark Johnston 	return 0;
1738f4f56ff4SMark Johnston }
1739f4f56ff4SMark Johnston 
1740f4f56ff4SMark Johnston static void
qat_crypto_stop(struct qat_softc * sc)1741f4f56ff4SMark Johnston qat_crypto_stop(struct qat_softc *sc)
1742f4f56ff4SMark Johnston {
1743f4f56ff4SMark Johnston 	struct qat_crypto *qcy;
1744f4f56ff4SMark Johnston 
1745f4f56ff4SMark Johnston 	qcy = &sc->sc_crypto;
1746f4f56ff4SMark Johnston 	if (qcy->qcy_cid >= 0)
1747f4f56ff4SMark Johnston 		(void)crypto_unregister_all(qcy->qcy_cid);
1748f4f56ff4SMark Johnston }
1749f4f56ff4SMark Johnston 
1750f4f56ff4SMark Johnston static void
qat_crypto_sym_dma_unload(struct qat_sym_cookie * qsc,enum qat_sym_dma i)1751f4f56ff4SMark Johnston qat_crypto_sym_dma_unload(struct qat_sym_cookie *qsc, enum qat_sym_dma i)
1752f4f56ff4SMark Johnston {
1753f4f56ff4SMark Johnston 	bus_dmamap_sync(qsc->qsc_dma[i].qsd_dma_tag, qsc->qsc_dma[i].qsd_dmamap,
1754f4f56ff4SMark Johnston 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1755f4f56ff4SMark Johnston 	bus_dmamap_unload(qsc->qsc_dma[i].qsd_dma_tag,
1756f4f56ff4SMark Johnston 	    qsc->qsc_dma[i].qsd_dmamap);
1757f4f56ff4SMark Johnston }
1758f4f56ff4SMark Johnston 
1759f4f56ff4SMark Johnston static int
qat_crypto_sym_rxintr(struct qat_softc * sc,void * arg,void * msg)1760f4f56ff4SMark Johnston qat_crypto_sym_rxintr(struct qat_softc *sc, void *arg, void *msg)
1761f4f56ff4SMark Johnston {
1762f4f56ff4SMark Johnston 	char icv[QAT_SYM_HASH_BUFFER_LEN];
1763f4f56ff4SMark Johnston 	struct qat_crypto_bank *qcb = arg;
1764f4f56ff4SMark Johnston 	struct qat_crypto *qcy;
1765f4f56ff4SMark Johnston 	struct qat_session *qs;
1766f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
1767f4f56ff4SMark Johnston 	struct qat_sym_bulk_cookie *qsbc;
1768f4f56ff4SMark Johnston 	struct cryptop *crp;
1769f4f56ff4SMark Johnston 	int error;
1770f4f56ff4SMark Johnston 	uint16_t auth_sz;
1771f4f56ff4SMark Johnston 	bool blocked;
1772f4f56ff4SMark Johnston 
1773f4f56ff4SMark Johnston 	qsc = *(void **)((uintptr_t)msg + sc->sc_hw.qhw_crypto_opaque_offset);
1774f4f56ff4SMark Johnston 
1775f4f56ff4SMark Johnston 	qsbc = &qsc->qsc_bulk_cookie;
1776f4f56ff4SMark Johnston 	qcy = qsbc->qsbc_crypto;
1777f4f56ff4SMark Johnston 	qs = qsbc->qsbc_session;
1778f4f56ff4SMark Johnston 	crp = qsbc->qsbc_cb_tag;
1779f4f56ff4SMark Johnston 
1780f4f56ff4SMark Johnston 	bus_dmamap_sync(qsc->qsc_self_dma_tag, qsc->qsc_self_dmamap,
1781f4f56ff4SMark Johnston 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1782f4f56ff4SMark Johnston 
1783f4f56ff4SMark Johnston 	if (crp->crp_aad != NULL)
1784f4f56ff4SMark Johnston 		qat_crypto_sym_dma_unload(qsc, QAT_SYM_DMA_AADBUF);
1785f4f56ff4SMark Johnston 	qat_crypto_sym_dma_unload(qsc, QAT_SYM_DMA_BUF);
1786f4f56ff4SMark Johnston 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp))
1787f4f56ff4SMark Johnston 		qat_crypto_sym_dma_unload(qsc, QAT_SYM_DMA_OBUF);
1788f4f56ff4SMark Johnston 
1789f4f56ff4SMark Johnston 	error = 0;
1790f4f56ff4SMark Johnston 	if ((auth_sz = qs->qs_auth_mlen) != 0) {
1791f4f56ff4SMark Johnston 		if ((crp->crp_op & CRYPTO_OP_VERIFY_DIGEST) != 0) {
1792f4f56ff4SMark Johnston 			crypto_copydata(crp, crp->crp_digest_start,
1793f4f56ff4SMark Johnston 			    auth_sz, icv);
1794f4f56ff4SMark Johnston 			if (timingsafe_bcmp(icv, qsc->qsc_auth_res,
1795f4f56ff4SMark Johnston 			    auth_sz) != 0) {
1796f4f56ff4SMark Johnston 				error = EBADMSG;
1797f4f56ff4SMark Johnston 			}
1798f4f56ff4SMark Johnston 		} else {
1799f4f56ff4SMark Johnston 			crypto_copyback(crp, crp->crp_digest_start,
1800f4f56ff4SMark Johnston 			    auth_sz, qsc->qsc_auth_res);
1801f4f56ff4SMark Johnston 		}
1802f4f56ff4SMark Johnston 	}
1803f4f56ff4SMark Johnston 
1804f4f56ff4SMark Johnston 	qat_crypto_free_sym_cookie(qcb, qsc);
1805f4f56ff4SMark Johnston 
1806f4f56ff4SMark Johnston 	blocked = false;
1807f4f56ff4SMark Johnston 	mtx_lock(&qs->qs_session_mtx);
1808f4f56ff4SMark Johnston 	MPASS(qs->qs_status & QAT_SESSION_STATUS_ACTIVE);
1809f4f56ff4SMark Johnston 	qs->qs_inflight--;
1810f4f56ff4SMark Johnston 	if (__predict_false(qs->qs_need_wakeup && qs->qs_inflight == 0)) {
1811f4f56ff4SMark Johnston 		blocked = true;
1812f4f56ff4SMark Johnston 		qs->qs_need_wakeup = false;
1813f4f56ff4SMark Johnston 	}
1814f4f56ff4SMark Johnston 	mtx_unlock(&qs->qs_session_mtx);
1815f4f56ff4SMark Johnston 
1816f4f56ff4SMark Johnston 	crp->crp_etype = error;
1817f4f56ff4SMark Johnston 	crypto_done(crp);
1818f4f56ff4SMark Johnston 
1819f4f56ff4SMark Johnston 	if (blocked)
1820f4f56ff4SMark Johnston 		crypto_unblock(qcy->qcy_cid, CRYPTO_SYMQ);
1821f4f56ff4SMark Johnston 
1822f4f56ff4SMark Johnston 	return 1;
1823f4f56ff4SMark Johnston }
1824f4f56ff4SMark Johnston 
1825f4f56ff4SMark Johnston static int
qat_probesession(device_t dev,const struct crypto_session_params * csp)1826f4f56ff4SMark Johnston qat_probesession(device_t dev, const struct crypto_session_params *csp)
1827f4f56ff4SMark Johnston {
1828f4f56ff4SMark Johnston 	if ((csp->csp_flags & ~(CSP_F_SEPARATE_OUTPUT | CSP_F_SEPARATE_AAD)) !=
1829f4f56ff4SMark Johnston 	    0)
1830f4f56ff4SMark Johnston 		return EINVAL;
1831f4f56ff4SMark Johnston 
1832f4f56ff4SMark Johnston 	if (csp->csp_cipher_alg == CRYPTO_AES_XTS &&
1833f4f56ff4SMark Johnston 	    qat_lookup(dev)->qatp_chip == QAT_CHIP_C2XXX) {
1834f4f56ff4SMark Johnston 		/*
1835f4f56ff4SMark Johnston 		 * AES-XTS is not supported by the NanoQAT.
1836f4f56ff4SMark Johnston 		 */
1837f4f56ff4SMark Johnston 		return EINVAL;
1838f4f56ff4SMark Johnston 	}
1839f4f56ff4SMark Johnston 
1840f4f56ff4SMark Johnston 	switch (csp->csp_mode) {
1841f4f56ff4SMark Johnston 	case CSP_MODE_CIPHER:
1842f4f56ff4SMark Johnston 		switch (csp->csp_cipher_alg) {
1843f4f56ff4SMark Johnston 		case CRYPTO_AES_CBC:
1844f4f56ff4SMark Johnston 		case CRYPTO_AES_ICM:
1845f4f56ff4SMark Johnston 			if (csp->csp_ivlen != AES_BLOCK_LEN)
1846f4f56ff4SMark Johnston 				return EINVAL;
1847f4f56ff4SMark Johnston 			break;
1848f4f56ff4SMark Johnston 		case CRYPTO_AES_XTS:
1849f4f56ff4SMark Johnston 			if (csp->csp_ivlen != AES_XTS_IV_LEN)
1850f4f56ff4SMark Johnston 				return EINVAL;
1851f4f56ff4SMark Johnston 			break;
1852f4f56ff4SMark Johnston 		default:
1853f4f56ff4SMark Johnston 			return EINVAL;
1854f4f56ff4SMark Johnston 		}
1855f4f56ff4SMark Johnston 		break;
1856f4f56ff4SMark Johnston 	case CSP_MODE_DIGEST:
1857f4f56ff4SMark Johnston 		switch (csp->csp_auth_alg) {
1858f4f56ff4SMark Johnston 		case CRYPTO_SHA1:
1859f4f56ff4SMark Johnston 		case CRYPTO_SHA1_HMAC:
1860f4f56ff4SMark Johnston 		case CRYPTO_SHA2_256:
1861f4f56ff4SMark Johnston 		case CRYPTO_SHA2_256_HMAC:
1862f4f56ff4SMark Johnston 		case CRYPTO_SHA2_384:
1863f4f56ff4SMark Johnston 		case CRYPTO_SHA2_384_HMAC:
1864f4f56ff4SMark Johnston 		case CRYPTO_SHA2_512:
1865f4f56ff4SMark Johnston 		case CRYPTO_SHA2_512_HMAC:
1866f4f56ff4SMark Johnston 			break;
1867f4f56ff4SMark Johnston 		case CRYPTO_AES_NIST_GMAC:
1868f4f56ff4SMark Johnston 			if (csp->csp_ivlen != AES_GCM_IV_LEN)
1869f4f56ff4SMark Johnston 				return EINVAL;
1870f4f56ff4SMark Johnston 			break;
1871f4f56ff4SMark Johnston 		default:
1872f4f56ff4SMark Johnston 			return EINVAL;
1873f4f56ff4SMark Johnston 		}
1874f4f56ff4SMark Johnston 		break;
1875f4f56ff4SMark Johnston 	case CSP_MODE_AEAD:
1876f4f56ff4SMark Johnston 		switch (csp->csp_cipher_alg) {
1877f4f56ff4SMark Johnston 		case CRYPTO_AES_NIST_GCM_16:
1878f4f56ff4SMark Johnston 			break;
1879f4f56ff4SMark Johnston 		default:
1880f4f56ff4SMark Johnston 			return EINVAL;
1881f4f56ff4SMark Johnston 		}
1882f4f56ff4SMark Johnston 		break;
1883f4f56ff4SMark Johnston 	case CSP_MODE_ETA:
1884f4f56ff4SMark Johnston 		switch (csp->csp_auth_alg) {
1885f4f56ff4SMark Johnston 		case CRYPTO_SHA1_HMAC:
1886f4f56ff4SMark Johnston 		case CRYPTO_SHA2_256_HMAC:
1887f4f56ff4SMark Johnston 		case CRYPTO_SHA2_384_HMAC:
1888f4f56ff4SMark Johnston 		case CRYPTO_SHA2_512_HMAC:
1889f4f56ff4SMark Johnston 			switch (csp->csp_cipher_alg) {
1890f4f56ff4SMark Johnston 			case CRYPTO_AES_CBC:
1891f4f56ff4SMark Johnston 			case CRYPTO_AES_ICM:
1892f4f56ff4SMark Johnston 				if (csp->csp_ivlen != AES_BLOCK_LEN)
1893f4f56ff4SMark Johnston 					return EINVAL;
1894f4f56ff4SMark Johnston 				break;
1895f4f56ff4SMark Johnston 			case CRYPTO_AES_XTS:
1896f4f56ff4SMark Johnston 				if (csp->csp_ivlen != AES_XTS_IV_LEN)
1897f4f56ff4SMark Johnston 					return EINVAL;
1898f4f56ff4SMark Johnston 				break;
1899f4f56ff4SMark Johnston 			default:
1900f4f56ff4SMark Johnston 				return EINVAL;
1901f4f56ff4SMark Johnston 			}
1902f4f56ff4SMark Johnston 			break;
1903f4f56ff4SMark Johnston 		default:
1904f4f56ff4SMark Johnston 			return EINVAL;
1905f4f56ff4SMark Johnston 		}
1906f4f56ff4SMark Johnston 		break;
1907f4f56ff4SMark Johnston 	default:
1908f4f56ff4SMark Johnston 		return EINVAL;
1909f4f56ff4SMark Johnston 	}
1910f4f56ff4SMark Johnston 
1911f4f56ff4SMark Johnston 	return CRYPTODEV_PROBE_HARDWARE;
1912f4f56ff4SMark Johnston }
1913f4f56ff4SMark Johnston 
1914f4f56ff4SMark Johnston static int
qat_newsession(device_t dev,crypto_session_t cses,const struct crypto_session_params * csp)1915f4f56ff4SMark Johnston qat_newsession(device_t dev, crypto_session_t cses,
1916f4f56ff4SMark Johnston     const struct crypto_session_params *csp)
1917f4f56ff4SMark Johnston {
1918f4f56ff4SMark Johnston 	struct qat_crypto *qcy;
1919f4f56ff4SMark Johnston 	struct qat_dmamem *qdm;
1920f4f56ff4SMark Johnston 	struct qat_session *qs;
1921f4f56ff4SMark Johnston 	struct qat_softc *sc;
1922f4f56ff4SMark Johnston 	struct qat_crypto_desc *ddesc, *edesc;
1923f4f56ff4SMark Johnston 	int error, slices;
1924f4f56ff4SMark Johnston 
1925f4f56ff4SMark Johnston 	sc = device_get_softc(dev);
1926f4f56ff4SMark Johnston 	qs = crypto_get_driver_session(cses);
1927f4f56ff4SMark Johnston 	qcy = &sc->sc_crypto;
1928f4f56ff4SMark Johnston 
1929f4f56ff4SMark Johnston 	qdm = &qs->qs_desc_mem;
1930f4f56ff4SMark Johnston 	error = qat_alloc_dmamem(sc, qdm, QAT_MAXSEG,
1931f4f56ff4SMark Johnston 	    sizeof(struct qat_crypto_desc) * 2, QAT_OPTIMAL_ALIGN);
1932f4f56ff4SMark Johnston 	if (error != 0)
1933f4f56ff4SMark Johnston 		return error;
1934f4f56ff4SMark Johnston 
1935f4f56ff4SMark Johnston 	mtx_init(&qs->qs_session_mtx, "qs session", NULL, MTX_DEF);
1936f4f56ff4SMark Johnston 	qs->qs_aad_length = -1;
1937f4f56ff4SMark Johnston 
1938f4f56ff4SMark Johnston 	qs->qs_dec_desc = ddesc = qdm->qdm_dma_vaddr;
1939f4f56ff4SMark Johnston 	qs->qs_enc_desc = edesc = ddesc + 1;
1940f4f56ff4SMark Johnston 
1941f4f56ff4SMark Johnston 	ddesc->qcd_desc_paddr = qdm->qdm_dma_seg.ds_addr;
1942f4f56ff4SMark Johnston 	ddesc->qcd_hash_state_paddr = ddesc->qcd_desc_paddr +
1943f4f56ff4SMark Johnston 	    offsetof(struct qat_crypto_desc, qcd_hash_state_prefix_buf);
1944f4f56ff4SMark Johnston 	edesc->qcd_desc_paddr = qdm->qdm_dma_seg.ds_addr +
1945f4f56ff4SMark Johnston 	    sizeof(struct qat_crypto_desc);
1946f4f56ff4SMark Johnston 	edesc->qcd_hash_state_paddr = edesc->qcd_desc_paddr +
1947f4f56ff4SMark Johnston 	    offsetof(struct qat_crypto_desc, qcd_hash_state_prefix_buf);
1948f4f56ff4SMark Johnston 
1949f4f56ff4SMark Johnston 	qs->qs_status = QAT_SESSION_STATUS_ACTIVE;
1950f4f56ff4SMark Johnston 	qs->qs_inflight = 0;
1951f4f56ff4SMark Johnston 
1952f4f56ff4SMark Johnston 	qs->qs_cipher_key = csp->csp_cipher_key;
1953f4f56ff4SMark Johnston 	qs->qs_cipher_klen = csp->csp_cipher_klen;
1954f4f56ff4SMark Johnston 	qs->qs_auth_key = csp->csp_auth_key;
1955f4f56ff4SMark Johnston 	qs->qs_auth_klen = csp->csp_auth_klen;
1956f4f56ff4SMark Johnston 
1957f4f56ff4SMark Johnston 	switch (csp->csp_cipher_alg) {
1958f4f56ff4SMark Johnston 	case CRYPTO_AES_CBC:
1959f4f56ff4SMark Johnston 		qs->qs_cipher_algo = qat_aes_cipher_algo(csp->csp_cipher_klen);
1960f4f56ff4SMark Johnston 		qs->qs_cipher_mode = HW_CIPHER_CBC_MODE;
1961f4f56ff4SMark Johnston 		break;
1962f4f56ff4SMark Johnston 	case CRYPTO_AES_ICM:
1963f4f56ff4SMark Johnston 		qs->qs_cipher_algo = qat_aes_cipher_algo(csp->csp_cipher_klen);
1964f4f56ff4SMark Johnston 		qs->qs_cipher_mode = HW_CIPHER_CTR_MODE;
1965f4f56ff4SMark Johnston 		break;
1966f4f56ff4SMark Johnston 	case CRYPTO_AES_XTS:
1967f4f56ff4SMark Johnston 		qs->qs_cipher_algo =
1968f4f56ff4SMark Johnston 		    qat_aes_cipher_algo(csp->csp_cipher_klen / 2);
1969f4f56ff4SMark Johnston 		qs->qs_cipher_mode = HW_CIPHER_XTS_MODE;
1970f4f56ff4SMark Johnston 		break;
1971f4f56ff4SMark Johnston 	case CRYPTO_AES_NIST_GCM_16:
1972f4f56ff4SMark Johnston 		qs->qs_cipher_algo = qat_aes_cipher_algo(csp->csp_cipher_klen);
1973f4f56ff4SMark Johnston 		qs->qs_cipher_mode = HW_CIPHER_CTR_MODE;
1974f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_GALOIS_128;
1975f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE1;
1976f4f56ff4SMark Johnston 		break;
1977f4f56ff4SMark Johnston 	case 0:
1978f4f56ff4SMark Johnston 		break;
1979f4f56ff4SMark Johnston 	default:
1980f4f56ff4SMark Johnston 		panic("%s: unhandled cipher algorithm %d", __func__,
1981f4f56ff4SMark Johnston 		    csp->csp_cipher_alg);
1982f4f56ff4SMark Johnston 	}
1983f4f56ff4SMark Johnston 
1984f4f56ff4SMark Johnston 	switch (csp->csp_auth_alg) {
1985f4f56ff4SMark Johnston 	case CRYPTO_SHA1_HMAC:
1986f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA1;
1987f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE1;
1988f4f56ff4SMark Johnston 		break;
1989f4f56ff4SMark Johnston 	case CRYPTO_SHA1:
1990f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA1;
1991f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE0;
1992f4f56ff4SMark Johnston 		break;
1993f4f56ff4SMark Johnston 	case CRYPTO_SHA2_256_HMAC:
1994f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA256;
1995f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE1;
1996f4f56ff4SMark Johnston 		break;
1997f4f56ff4SMark Johnston 	case CRYPTO_SHA2_256:
1998f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA256;
1999f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE0;
2000f4f56ff4SMark Johnston 		break;
2001f4f56ff4SMark Johnston 	case CRYPTO_SHA2_384_HMAC:
2002f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA384;
2003f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE1;
2004f4f56ff4SMark Johnston 		break;
2005f4f56ff4SMark Johnston 	case CRYPTO_SHA2_384:
2006f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA384;
2007f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE0;
2008f4f56ff4SMark Johnston 		break;
2009f4f56ff4SMark Johnston 	case CRYPTO_SHA2_512_HMAC:
2010f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA512;
2011f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE1;
2012f4f56ff4SMark Johnston 		break;
2013f4f56ff4SMark Johnston 	case CRYPTO_SHA2_512:
2014f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_SHA512;
2015f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE0;
2016f4f56ff4SMark Johnston 		break;
2017f4f56ff4SMark Johnston 	case CRYPTO_AES_NIST_GMAC:
2018f4f56ff4SMark Johnston 		qs->qs_cipher_algo = qat_aes_cipher_algo(csp->csp_auth_klen);
2019f4f56ff4SMark Johnston 		qs->qs_cipher_mode = HW_CIPHER_CTR_MODE;
2020f4f56ff4SMark Johnston 		qs->qs_auth_algo = HW_AUTH_ALGO_GALOIS_128;
2021f4f56ff4SMark Johnston 		qs->qs_auth_mode = HW_AUTH_MODE1;
2022f4f56ff4SMark Johnston 
2023f4f56ff4SMark Johnston 		qs->qs_cipher_key = qs->qs_auth_key;
2024f4f56ff4SMark Johnston 		qs->qs_cipher_klen = qs->qs_auth_klen;
2025f4f56ff4SMark Johnston 		break;
2026f4f56ff4SMark Johnston 	case 0:
2027f4f56ff4SMark Johnston 		break;
2028f4f56ff4SMark Johnston 	default:
2029f4f56ff4SMark Johnston 		panic("%s: unhandled auth algorithm %d", __func__,
2030f4f56ff4SMark Johnston 		    csp->csp_auth_alg);
2031f4f56ff4SMark Johnston 	}
2032f4f56ff4SMark Johnston 
2033f4f56ff4SMark Johnston 	slices = 0;
2034f4f56ff4SMark Johnston 	switch (csp->csp_mode) {
2035f4f56ff4SMark Johnston 	case CSP_MODE_AEAD:
2036f4f56ff4SMark Johnston 	case CSP_MODE_ETA:
2037f4f56ff4SMark Johnston 		/* auth then decrypt */
2038f4f56ff4SMark Johnston 		ddesc->qcd_slices[0] = FW_SLICE_AUTH;
2039f4f56ff4SMark Johnston 		ddesc->qcd_slices[1] = FW_SLICE_CIPHER;
2040f4f56ff4SMark Johnston 		ddesc->qcd_cipher_dir = HW_CIPHER_DECRYPT;
2041f4f56ff4SMark Johnston 		ddesc->qcd_cmd_id = FW_LA_CMD_HASH_CIPHER;
2042f4f56ff4SMark Johnston 		/* encrypt then auth */
2043f4f56ff4SMark Johnston 		edesc->qcd_slices[0] = FW_SLICE_CIPHER;
2044f4f56ff4SMark Johnston 		edesc->qcd_slices[1] = FW_SLICE_AUTH;
2045f4f56ff4SMark Johnston 		edesc->qcd_cipher_dir = HW_CIPHER_ENCRYPT;
2046f4f56ff4SMark Johnston 		edesc->qcd_cmd_id = FW_LA_CMD_CIPHER_HASH;
2047f4f56ff4SMark Johnston 		slices = 2;
2048f4f56ff4SMark Johnston 		break;
2049f4f56ff4SMark Johnston 	case CSP_MODE_CIPHER:
2050f4f56ff4SMark Johnston 		/* decrypt */
2051f4f56ff4SMark Johnston 		ddesc->qcd_slices[0] = FW_SLICE_CIPHER;
2052f4f56ff4SMark Johnston 		ddesc->qcd_cipher_dir = HW_CIPHER_DECRYPT;
2053f4f56ff4SMark Johnston 		ddesc->qcd_cmd_id = FW_LA_CMD_CIPHER;
2054f4f56ff4SMark Johnston 		/* encrypt */
2055f4f56ff4SMark Johnston 		edesc->qcd_slices[0] = FW_SLICE_CIPHER;
2056f4f56ff4SMark Johnston 		edesc->qcd_cipher_dir = HW_CIPHER_ENCRYPT;
2057f4f56ff4SMark Johnston 		edesc->qcd_cmd_id = FW_LA_CMD_CIPHER;
2058f4f56ff4SMark Johnston 		slices = 1;
2059f4f56ff4SMark Johnston 		break;
2060f4f56ff4SMark Johnston 	case CSP_MODE_DIGEST:
2061f4f56ff4SMark Johnston 		if (qs->qs_auth_algo == HW_AUTH_ALGO_GALOIS_128) {
2062f4f56ff4SMark Johnston 			/* auth then decrypt */
2063f4f56ff4SMark Johnston 			ddesc->qcd_slices[0] = FW_SLICE_AUTH;
2064f4f56ff4SMark Johnston 			ddesc->qcd_slices[1] = FW_SLICE_CIPHER;
2065f4f56ff4SMark Johnston 			ddesc->qcd_cipher_dir = HW_CIPHER_DECRYPT;
2066f4f56ff4SMark Johnston 			ddesc->qcd_cmd_id = FW_LA_CMD_HASH_CIPHER;
2067f4f56ff4SMark Johnston 			/* encrypt then auth */
2068f4f56ff4SMark Johnston 			edesc->qcd_slices[0] = FW_SLICE_CIPHER;
2069f4f56ff4SMark Johnston 			edesc->qcd_slices[1] = FW_SLICE_AUTH;
2070f4f56ff4SMark Johnston 			edesc->qcd_cipher_dir = HW_CIPHER_ENCRYPT;
2071f4f56ff4SMark Johnston 			edesc->qcd_cmd_id = FW_LA_CMD_CIPHER_HASH;
2072f4f56ff4SMark Johnston 			slices = 2;
2073f4f56ff4SMark Johnston 		} else {
2074f4f56ff4SMark Johnston 			ddesc->qcd_slices[0] = FW_SLICE_AUTH;
2075f4f56ff4SMark Johnston 			ddesc->qcd_cmd_id = FW_LA_CMD_AUTH;
2076f4f56ff4SMark Johnston 			edesc->qcd_slices[0] = FW_SLICE_AUTH;
2077f4f56ff4SMark Johnston 			edesc->qcd_cmd_id = FW_LA_CMD_AUTH;
2078f4f56ff4SMark Johnston 			slices = 1;
2079f4f56ff4SMark Johnston 		}
2080f4f56ff4SMark Johnston 		break;
2081f4f56ff4SMark Johnston 	default:
2082f4f56ff4SMark Johnston 		panic("%s: unhandled crypto algorithm %d, %d", __func__,
2083f4f56ff4SMark Johnston 		    csp->csp_cipher_alg, csp->csp_auth_alg);
2084f4f56ff4SMark Johnston 	}
2085f4f56ff4SMark Johnston 	ddesc->qcd_slices[slices] = FW_SLICE_DRAM_WR;
2086f4f56ff4SMark Johnston 	edesc->qcd_slices[slices] = FW_SLICE_DRAM_WR;
2087f4f56ff4SMark Johnston 
2088f4f56ff4SMark Johnston 	qcy->qcy_sc->sc_hw.qhw_crypto_setup_desc(qcy, qs, ddesc);
2089f4f56ff4SMark Johnston 	qcy->qcy_sc->sc_hw.qhw_crypto_setup_desc(qcy, qs, edesc);
2090f4f56ff4SMark Johnston 
2091f4f56ff4SMark Johnston 	if (csp->csp_auth_mlen != 0)
2092f4f56ff4SMark Johnston 		qs->qs_auth_mlen = csp->csp_auth_mlen;
2093f4f56ff4SMark Johnston 	else
2094f4f56ff4SMark Johnston 		qs->qs_auth_mlen = edesc->qcd_auth_sz;
2095f4f56ff4SMark Johnston 
2096f4f56ff4SMark Johnston 	/* Compute the GMAC by specifying a null cipher payload. */
2097f4f56ff4SMark Johnston 	if (csp->csp_auth_alg == CRYPTO_AES_NIST_GMAC)
2098f4f56ff4SMark Johnston 		ddesc->qcd_cmd_id = edesc->qcd_cmd_id = FW_LA_CMD_AUTH;
2099f4f56ff4SMark Johnston 
2100f4f56ff4SMark Johnston 	return 0;
2101f4f56ff4SMark Johnston }
2102f4f56ff4SMark Johnston 
2103f4f56ff4SMark Johnston static void
qat_crypto_clear_desc(struct qat_crypto_desc * desc)2104f4f56ff4SMark Johnston qat_crypto_clear_desc(struct qat_crypto_desc *desc)
2105f4f56ff4SMark Johnston {
2106f4f56ff4SMark Johnston 	explicit_bzero(desc->qcd_content_desc, sizeof(desc->qcd_content_desc));
2107f4f56ff4SMark Johnston 	explicit_bzero(desc->qcd_hash_state_prefix_buf,
2108f4f56ff4SMark Johnston 	    sizeof(desc->qcd_hash_state_prefix_buf));
2109f4f56ff4SMark Johnston 	explicit_bzero(desc->qcd_req_cache, sizeof(desc->qcd_req_cache));
2110f4f56ff4SMark Johnston }
2111f4f56ff4SMark Johnston 
2112f4f56ff4SMark Johnston static void
qat_freesession(device_t dev,crypto_session_t cses)2113f4f56ff4SMark Johnston qat_freesession(device_t dev, crypto_session_t cses)
2114f4f56ff4SMark Johnston {
2115f4f56ff4SMark Johnston 	struct qat_session *qs;
2116f4f56ff4SMark Johnston 
2117f4f56ff4SMark Johnston 	qs = crypto_get_driver_session(cses);
2118f4f56ff4SMark Johnston 	KASSERT(qs->qs_inflight == 0,
2119f4f56ff4SMark Johnston 	    ("%s: session %p has requests in flight", __func__, qs));
2120f4f56ff4SMark Johnston 
2121f4f56ff4SMark Johnston 	qat_crypto_clear_desc(qs->qs_enc_desc);
2122f4f56ff4SMark Johnston 	qat_crypto_clear_desc(qs->qs_dec_desc);
2123f4f56ff4SMark Johnston 	qat_free_dmamem(device_get_softc(dev), &qs->qs_desc_mem);
2124f4f56ff4SMark Johnston 	mtx_destroy(&qs->qs_session_mtx);
2125f4f56ff4SMark Johnston }
2126f4f56ff4SMark Johnston 
2127f4f56ff4SMark Johnston static int
qat_process(device_t dev,struct cryptop * crp,int hint)2128f4f56ff4SMark Johnston qat_process(device_t dev, struct cryptop *crp, int hint)
2129f4f56ff4SMark Johnston {
2130f4f56ff4SMark Johnston 	struct qat_crypto *qcy;
2131f4f56ff4SMark Johnston 	struct qat_crypto_bank *qcb;
2132f4f56ff4SMark Johnston 	struct qat_crypto_desc const *desc;
2133f4f56ff4SMark Johnston 	struct qat_session *qs;
2134f4f56ff4SMark Johnston 	struct qat_softc *sc;
2135f4f56ff4SMark Johnston 	struct qat_sym_cookie *qsc;
2136f4f56ff4SMark Johnston 	struct qat_sym_bulk_cookie *qsbc;
2137f4f56ff4SMark Johnston 	int error;
2138f4f56ff4SMark Johnston 
2139f4f56ff4SMark Johnston 	sc = device_get_softc(dev);
2140f4f56ff4SMark Johnston 	qcy = &sc->sc_crypto;
2141f4f56ff4SMark Johnston 	qs = crypto_get_driver_session(crp->crp_session);
2142f4f56ff4SMark Johnston 	qsc = NULL;
2143f4f56ff4SMark Johnston 
2144f4f56ff4SMark Johnston 	if (__predict_false(crypto_buffer_len(&crp->crp_buf) > QAT_MAXLEN)) {
2145f4f56ff4SMark Johnston 		error = E2BIG;
2146f4f56ff4SMark Johnston 		goto fail1;
2147f4f56ff4SMark Johnston 	}
2148f4f56ff4SMark Johnston 
2149f4f56ff4SMark Johnston 	mtx_lock(&qs->qs_session_mtx);
2150f4f56ff4SMark Johnston 	if (qs->qs_auth_algo == HW_AUTH_ALGO_GALOIS_128) {
2151f4f56ff4SMark Johnston 		if (crp->crp_aad_length > QAT_GCM_AAD_SIZE_MAX) {
2152f4f56ff4SMark Johnston 			error = E2BIG;
2153f4f56ff4SMark Johnston 			mtx_unlock(&qs->qs_session_mtx);
2154f4f56ff4SMark Johnston 			goto fail1;
2155f4f56ff4SMark Johnston 		}
2156f4f56ff4SMark Johnston 
2157f4f56ff4SMark Johnston 		/*
2158f4f56ff4SMark Johnston 		 * The firmware interface for GCM annoyingly requires the AAD
2159f4f56ff4SMark Johnston 		 * size to be stored in the session's content descriptor, which
2160f4f56ff4SMark Johnston 		 * is not really meant to be updated after session
2161f4f56ff4SMark Johnston 		 * initialization.  For IPSec the AAD size is fixed so this is
2162f4f56ff4SMark Johnston 		 * not much of a problem in practice, but we have to catch AAD
2163f4f56ff4SMark Johnston 		 * size updates here so that the device code can safely update
2164f4f56ff4SMark Johnston 		 * the session's recorded AAD size.
2165f4f56ff4SMark Johnston 		 */
2166f4f56ff4SMark Johnston 		if (__predict_false(crp->crp_aad_length != qs->qs_aad_length)) {
2167f4f56ff4SMark Johnston 			if (qs->qs_inflight == 0) {
2168f4f56ff4SMark Johnston 				if (qs->qs_aad_length != -1) {
2169f4f56ff4SMark Johnston 					counter_u64_add(sc->sc_gcm_aad_updates,
2170f4f56ff4SMark Johnston 					    1);
2171f4f56ff4SMark Johnston 				}
2172f4f56ff4SMark Johnston 				qs->qs_aad_length = crp->crp_aad_length;
2173f4f56ff4SMark Johnston 			} else {
2174f4f56ff4SMark Johnston 				qs->qs_need_wakeup = true;
2175f4f56ff4SMark Johnston 				mtx_unlock(&qs->qs_session_mtx);
2176f4f56ff4SMark Johnston 				counter_u64_add(sc->sc_gcm_aad_restarts, 1);
2177f4f56ff4SMark Johnston 				error = ERESTART;
2178f4f56ff4SMark Johnston 				goto fail1;
2179f4f56ff4SMark Johnston 			}
2180f4f56ff4SMark Johnston 		}
2181f4f56ff4SMark Johnston 	}
2182f4f56ff4SMark Johnston 	qs->qs_inflight++;
2183f4f56ff4SMark Johnston 	mtx_unlock(&qs->qs_session_mtx);
2184f4f56ff4SMark Johnston 
2185f4f56ff4SMark Johnston 	qcb = qat_crypto_select_bank(qcy);
2186f4f56ff4SMark Johnston 
2187f4f56ff4SMark Johnston 	qsc = qat_crypto_alloc_sym_cookie(qcb);
2188f4f56ff4SMark Johnston 	if (qsc == NULL) {
2189f4f56ff4SMark Johnston 		counter_u64_add(sc->sc_sym_alloc_failures, 1);
2190f4f56ff4SMark Johnston 		error = ENOBUFS;
2191f4f56ff4SMark Johnston 		goto fail2;
2192f4f56ff4SMark Johnston 	}
2193f4f56ff4SMark Johnston 
2194f4f56ff4SMark Johnston 	if (CRYPTO_OP_IS_ENCRYPT(crp->crp_op))
2195f4f56ff4SMark Johnston 		desc = qs->qs_enc_desc;
2196f4f56ff4SMark Johnston 	else
2197f4f56ff4SMark Johnston 		desc = qs->qs_dec_desc;
2198f4f56ff4SMark Johnston 
2199f4f56ff4SMark Johnston 	error = qat_crypto_load(qs, qsc, desc, crp);
2200f4f56ff4SMark Johnston 	if (error != 0)
2201f4f56ff4SMark Johnston 		goto fail2;
2202f4f56ff4SMark Johnston 
2203f4f56ff4SMark Johnston 	qsbc = &qsc->qsc_bulk_cookie;
2204f4f56ff4SMark Johnston 	qsbc->qsbc_crypto = qcy;
2205f4f56ff4SMark Johnston 	qsbc->qsbc_session = qs;
2206f4f56ff4SMark Johnston 	qsbc->qsbc_cb_tag = crp;
2207f4f56ff4SMark Johnston 
2208f4f56ff4SMark Johnston 	sc->sc_hw.qhw_crypto_setup_req_params(qcb, qs, desc, qsc, crp);
2209f4f56ff4SMark Johnston 
2210f4f56ff4SMark Johnston 	if (crp->crp_aad != NULL) {
2211f4f56ff4SMark Johnston 		bus_dmamap_sync(qsc->qsc_dma[QAT_SYM_DMA_AADBUF].qsd_dma_tag,
2212f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_AADBUF].qsd_dmamap,
2213f4f56ff4SMark Johnston 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2214f4f56ff4SMark Johnston 	}
2215f4f56ff4SMark Johnston 	bus_dmamap_sync(qsc->qsc_dma[QAT_SYM_DMA_BUF].qsd_dma_tag,
2216f4f56ff4SMark Johnston 	    qsc->qsc_dma[QAT_SYM_DMA_BUF].qsd_dmamap,
2217f4f56ff4SMark Johnston 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2218f4f56ff4SMark Johnston 	if (CRYPTO_HAS_OUTPUT_BUFFER(crp)) {
2219f4f56ff4SMark Johnston 		bus_dmamap_sync(qsc->qsc_dma[QAT_SYM_DMA_OBUF].qsd_dma_tag,
2220f4f56ff4SMark Johnston 		    qsc->qsc_dma[QAT_SYM_DMA_OBUF].qsd_dmamap,
2221f4f56ff4SMark Johnston 		    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2222f4f56ff4SMark Johnston 	}
2223f4f56ff4SMark Johnston 	bus_dmamap_sync(qsc->qsc_self_dma_tag, qsc->qsc_self_dmamap,
2224f4f56ff4SMark Johnston 	    BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
2225f4f56ff4SMark Johnston 
2226f4f56ff4SMark Johnston 	error = qat_etr_put_msg(sc, qcb->qcb_sym_tx,
2227f4f56ff4SMark Johnston 	    (uint32_t *)qsbc->qsbc_msg);
2228f4f56ff4SMark Johnston 	if (error)
2229f4f56ff4SMark Johnston 		goto fail2;
2230f4f56ff4SMark Johnston 
2231f4f56ff4SMark Johnston 	return 0;
2232f4f56ff4SMark Johnston 
2233f4f56ff4SMark Johnston fail2:
2234f4f56ff4SMark Johnston 	if (qsc)
2235f4f56ff4SMark Johnston 		qat_crypto_free_sym_cookie(qcb, qsc);
2236f4f56ff4SMark Johnston 	mtx_lock(&qs->qs_session_mtx);
2237f4f56ff4SMark Johnston 	qs->qs_inflight--;
2238f4f56ff4SMark Johnston 	mtx_unlock(&qs->qs_session_mtx);
2239f4f56ff4SMark Johnston fail1:
2240f4f56ff4SMark Johnston 	crp->crp_etype = error;
2241f4f56ff4SMark Johnston 	crypto_done(crp);
2242f4f56ff4SMark Johnston 	return 0;
2243f4f56ff4SMark Johnston }
2244f4f56ff4SMark Johnston 
2245f4f56ff4SMark Johnston static device_method_t qat_methods[] = {
2246f4f56ff4SMark Johnston 	/* Device interface */
2247f4f56ff4SMark Johnston 	DEVMETHOD(device_probe,		qat_probe),
2248f4f56ff4SMark Johnston 	DEVMETHOD(device_attach,	qat_attach),
2249f4f56ff4SMark Johnston 	DEVMETHOD(device_detach,	qat_detach),
2250f4f56ff4SMark Johnston 
2251f4f56ff4SMark Johnston 	/* Cryptodev interface */
2252f4f56ff4SMark Johnston 	DEVMETHOD(cryptodev_probesession, qat_probesession),
2253f4f56ff4SMark Johnston 	DEVMETHOD(cryptodev_newsession,	qat_newsession),
2254f4f56ff4SMark Johnston 	DEVMETHOD(cryptodev_freesession, qat_freesession),
2255f4f56ff4SMark Johnston 	DEVMETHOD(cryptodev_process,	qat_process),
2256f4f56ff4SMark Johnston 
2257f4f56ff4SMark Johnston 	DEVMETHOD_END
2258f4f56ff4SMark Johnston };
2259f4f56ff4SMark Johnston 
2260f4f56ff4SMark Johnston static driver_t qat_driver = {
2261f4f56ff4SMark Johnston 	.name		= "qat_c2xxx",
2262f4f56ff4SMark Johnston 	.methods	= qat_methods,
2263f4f56ff4SMark Johnston 	.size		= sizeof(struct qat_softc),
2264f4f56ff4SMark Johnston };
2265f4f56ff4SMark Johnston 
2266f4f56ff4SMark Johnston DRIVER_MODULE(qat_c2xxx, pci, qat_driver, 0, 0);
2267f4f56ff4SMark Johnston MODULE_VERSION(qat_c2xxx, 1);
2268f4f56ff4SMark Johnston MODULE_DEPEND(qat_c2xxx, crypto, 1, 1, 1);
2269675e065bSMark Johnston MODULE_DEPEND(qat_c2xxx, firmware, 1, 1, 1);
2270f4f56ff4SMark Johnston MODULE_DEPEND(qat_c2xxx, pci, 1, 1, 1);
2271