summaryrefslogtreecommitdiffstats
path: root/sys/dev/cesa/cesa.h
blob: 2c953f0c92981d1289366138e77834767e7076ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/*-
 * Copyright (C) 2009-2011 Semihalf.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

#ifndef _DEV_CESA_H_
#define _DEV_CESA_H_

/* Maximum number of allocated sessions */
#define CESA_SESSIONS			64

/* Maximum number of queued requests */
#define CESA_REQUESTS			256

/*
 * CESA is able to process data only in CESA SRAM, which is quite small (2 kB).
 * We have to fit a packet there, which contains SA descriptor, keys, IV
 * and data to be processed. Every request must be converted into chain of
 * packets and each packet can hold about 1.75 kB of data.
 *
 * To process each packet we need at least 1 SA descriptor and at least 4 TDMA
 * descriptors. However there are cases when we use 2 SA and 8 TDMA descriptors
 * per packet. Number of used TDMA descriptors can increase beyond given values
 * if data in the request is fragmented in physical memory.
 *
 * The driver uses preallocated SA and TDMA descriptors pools to get best
 * performace. Size of these pools should match expected request size. Example:
 *
 * Expected average request size:			1.5 kB (Ethernet MTU)
 * Packets per average request:				(1.5 kB / 1.75 kB) = 1
 * SA decriptors per average request (worst case):	1 * 2 = 2
 * TDMA desctiptors per average request (worst case):	1 * 8 = 8
 *
 * More TDMA descriptors should be allocated, if data fragmentation is expected
 * (for example while processing mbufs larger than MCLBYTES). The driver may use
 * 2 additional TDMA descriptors per each discontinuity in the physical data
 * layout.
 */

/* Values below are optimized for requests containing about 1.5 kB of data */
#define CESA_SA_DESC_PER_REQ		2
#define CESA_TDMA_DESC_PER_REQ		8

#define CESA_SA_DESCRIPTORS		(CESA_SA_DESC_PER_REQ * CESA_REQUESTS)
#define CESA_TDMA_DESCRIPTORS		(CESA_TDMA_DESC_PER_REQ * CESA_REQUESTS)

/* Useful constants */
#define CESA_HMAC_HASH_LENGTH		12
#define CESA_MAX_FRAGMENTS		64
#define CESA_SRAM_SIZE			2048

/*
 * CESA_MAX_HASH_LEN is maximum length of hash generated by CESA.
 * As CESA suports only MD5 and SHA1 this equals to 20 bytes.
 * However we increase the value to 24 bytes to meet alignment
 * requirements in cesa_sa_data structure.
 */
#define CESA_MAX_HASH_LEN		24
#define CESA_MAX_KEY_LEN		32
#define CESA_MAX_IV_LEN			16
#define CESA_MAX_HMAC_BLOCK_LEN		64
#define CESA_MAX_MKEY_LEN		CESA_MAX_HMAC_BLOCK_LEN
#define CESA_MAX_PACKET_SIZE		(CESA_SRAM_SIZE - CESA_DATA(0))
#define CESA_MAX_REQUEST_SIZE		65535

/* Locking macros */
#define CESA_LOCK(sc, what)		mtx_lock(&(sc)->sc_ ## what ## _lock)
#define CESA_UNLOCK(sc, what)		mtx_unlock(&(sc)->sc_ ## what ## _lock)
#define CESA_LOCK_ASSERT(sc, what)	\
	mtx_assert(&(sc)->sc_ ## what ## _lock, MA_OWNED)

/* Registers read/write macros */
#define CESA_READ(sc, reg)		\
	bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
#define CESA_WRITE(sc, reg, val)	\
	bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))

/* Generic allocator for objects */
#define CESA_GENERIC_ALLOC_LOCKED(sc, obj, pool) do {		\
	CESA_LOCK(sc, pool);					\
								\
	if (STAILQ_EMPTY(&(sc)->sc_free_ ## pool))		\
		obj = NULL;					\
	else {							\
		obj = STAILQ_FIRST(&(sc)->sc_free_ ## pool);	\
		STAILQ_REMOVE_HEAD(&(sc)->sc_free_ ## pool,	\
		    obj ## _stq);				\
	}							\
								\
	CESA_UNLOCK(sc, pool);					\
} while (0)

#define CESA_GENERIC_FREE_LOCKED(sc, obj, pool) do {		\
	CESA_LOCK(sc, pool);					\
	STAILQ_INSERT_TAIL(&(sc)->sc_free_ ## pool, obj,	\
	    obj ## _stq);					\
	CESA_UNLOCK(sc, pool);					\
} while (0)

/* CESA SRAM offset calculation macros */
#define CESA_SA_DATA(member)					\
	(sizeof(struct cesa_sa_hdesc) + offsetof(struct cesa_sa_data, member))
#define CESA_DATA(offset)					\
	(sizeof(struct cesa_sa_hdesc) + sizeof(struct cesa_sa_data) + offset)

struct cesa_tdma_hdesc {
	uint16_t	cthd_byte_count;
	uint16_t	cthd_flags;
	uint32_t	cthd_src;
	uint32_t	cthd_dst;
	uint32_t	cthd_next;
};

struct cesa_sa_hdesc {
	uint32_t	cshd_config;
	uint16_t	cshd_enc_src;
	uint16_t	cshd_enc_dst;
	uint32_t	cshd_enc_dlen;
	uint32_t	cshd_enc_key;
	uint16_t	cshd_enc_iv;
	uint16_t	cshd_enc_iv_buf;
	uint16_t	cshd_mac_src;
	uint16_t	cshd_mac_total_dlen;
	uint16_t	cshd_mac_dst;
	uint16_t	cshd_mac_dlen;
	uint16_t	cshd_mac_iv_in;
	uint16_t	cshd_mac_iv_out;
};

struct cesa_sa_data {
	uint8_t		csd_key[CESA_MAX_KEY_LEN];
	uint8_t		csd_iv[CESA_MAX_IV_LEN];
	uint8_t		csd_hiv_in[CESA_MAX_HASH_LEN];
	uint8_t		csd_hiv_out[CESA_MAX_HASH_LEN];
	uint8_t		csd_hash[CESA_MAX_HASH_LEN];
};

struct cesa_dma_mem {
	void		*cdm_vaddr;
	bus_addr_t	cdm_paddr;
	bus_dma_tag_t	cdm_tag;
	bus_dmamap_t	cdm_map;
};

struct cesa_tdma_desc {
	struct cesa_tdma_hdesc		*ctd_cthd;
	bus_addr_t			ctd_cthd_paddr;

	STAILQ_ENTRY(cesa_tdma_desc)	ctd_stq;
};

struct cesa_sa_desc {
	struct cesa_sa_hdesc		*csd_cshd;
	bus_addr_t			csd_cshd_paddr;

	STAILQ_ENTRY(cesa_sa_desc)	csd_stq;
};

struct cesa_session {
	uint32_t			cs_sid;
	uint32_t			cs_config;
	unsigned int			cs_klen;
	unsigned int			cs_ivlen;
	unsigned int			cs_hlen;
	unsigned int			cs_mblen;
	uint8_t				cs_key[CESA_MAX_KEY_LEN];
	uint8_t				cs_aes_dkey[CESA_MAX_KEY_LEN];
	uint8_t				cs_hiv_in[CESA_MAX_HASH_LEN];
	uint8_t				cs_hiv_out[CESA_MAX_HASH_LEN];

	STAILQ_ENTRY(cesa_session)	cs_stq;
};

struct cesa_request {
	struct cesa_sa_data		*cr_csd;
	bus_addr_t			cr_csd_paddr;
	struct cryptop			*cr_crp;
	struct cryptodesc		*cr_enc;
	struct cryptodesc		*cr_mac;
	struct cesa_session		*cr_cs;
	bus_dmamap_t			cr_dmap;
	int				cr_dmap_loaded;

	STAILQ_HEAD(, cesa_tdma_desc)	cr_tdesc;
	STAILQ_HEAD(, cesa_sa_desc)	cr_sdesc;

	STAILQ_ENTRY(cesa_request)	cr_stq;
};

struct cesa_packet {
	STAILQ_HEAD(, cesa_tdma_desc)	cp_copyin;
	STAILQ_HEAD(, cesa_tdma_desc)	cp_copyout;
	unsigned int			cp_size;
	unsigned int			cp_offset;
};

struct cesa_softc {
	device_t			sc_dev;
	int32_t				sc_cid;
	struct resource			*sc_res[2];
	void				*sc_icookie;
	bus_dma_tag_t			sc_data_dtag;
	bus_space_tag_t			sc_bst;
	bus_space_handle_t		sc_bsh;
	int				sc_error;
	int				sc_tperr;

	struct mtx			sc_sc_lock;
	int				sc_blocked;

	/* TDMA descriptors pool */
	struct mtx			sc_tdesc_lock;
	struct cesa_tdma_desc		sc_tdesc[CESA_TDMA_DESCRIPTORS];
	struct cesa_dma_mem		sc_tdesc_cdm;
	STAILQ_HEAD(, cesa_tdma_desc)	sc_free_tdesc;

	/* SA descriptors pool */
	struct mtx			sc_sdesc_lock;
	struct cesa_sa_desc		sc_sdesc[CESA_SA_DESCRIPTORS];
	struct cesa_dma_mem		sc_sdesc_cdm;
	STAILQ_HEAD(, cesa_sa_desc)	sc_free_sdesc;

	/* Requests pool */
	struct mtx			sc_requests_lock;
	struct cesa_request		sc_requests[CESA_REQUESTS];
	struct cesa_dma_mem		sc_requests_cdm;
	STAILQ_HEAD(, cesa_request)	sc_free_requests;
	STAILQ_HEAD(, cesa_request)	sc_ready_requests;
	STAILQ_HEAD(, cesa_request)	sc_queued_requests;

	/* Sessions pool */
	struct mtx			sc_sessions_lock;
	struct cesa_session		sc_sessions[CESA_SESSIONS];
	STAILQ_HEAD(, cesa_session)	sc_free_sessions;

	/* CESA SRAM Address */
	bus_addr_t			sc_sram_base;
};

struct cesa_chain_info {
	struct cesa_softc		*cci_sc;
	struct cesa_request		*cci_cr;
	struct cryptodesc		*cci_enc;
	struct cryptodesc		*cci_mac;
	uint32_t			cci_config;
	int				cci_error;
};

/* CESA descriptors flags definitions */
#define CESA_CTHD_OWNED			(1 << 15)

#define CESA_CSHD_MAC			(0 << 0)
#define CESA_CSHD_ENC			(1 << 0)
#define CESA_CSHD_MAC_AND_ENC		(2 << 0)
#define CESA_CSHD_ENC_AND_MAC		(3 << 0)
#define CESA_CSHD_OP_MASK		(3 << 0)

#define CESA_CSHD_MD5			(4 << 4)
#define CESA_CSHD_SHA1			(5 << 4)
#define CESA_CSHD_MD5_HMAC		((6 << 4) | (1 << 7))
#define CESA_CSHD_SHA1_HMAC		((7 << 4) | (1 << 7))

#define CESA_CSHD_DES			(1 << 8)
#define CESA_CSHD_3DES			(2 << 8)
#define CESA_CSHD_AES			(3 << 8)

#define CESA_CSHD_DECRYPT		(1 << 12)
#define CESA_CSHD_CBC			(1 << 16)
#define CESA_CSHD_3DES_EDE		(1 << 20)

#define CESA_CSH_AES_KLEN_128		(0 << 24)
#define CESA_CSH_AES_KLEN_192		(1 << 24)
#define CESA_CSH_AES_KLEN_256		(2 << 24)
#define CESA_CSH_AES_KLEN_MASK		(3 << 24)

#define CESA_CSHD_FRAG_FIRST		(1 << 30)
#define CESA_CSHD_FRAG_LAST		(2 << 30)
#define CESA_CSHD_FRAG_MIDDLE		(3 << 30)

/* CESA registers definitions */
#define CESA_ICR			0xDE20
#define CESA_ICR_ACCTDMA		(1 << 7)
#define CESA_ICR_TPERR			(1 << 12)

#define CESA_ICM			0xDE24
#define CESA_ICM_ACCTDMA		CESA_ICR_ACCTDMA
#define CESA_ICM_TPERR			CESA_ICR_TPERR

/* CESA TDMA registers definitions */
#define CESA_TDMA_ND			0x0830

#define CESA_TDMA_CR			0x0840
#define CESA_TDMA_CR_DBL128		(4 << 0)
#define CESA_TDMA_CR_ORDEN		(1 << 4)
#define CESA_TDMA_CR_SBL128		(4 << 6)
#define CESA_TDMA_CR_NBS		(1 << 11)
#define CESA_TDMA_CR_ENABLE		(1 << 12)
#define CESA_TDMA_CR_FETCHND		(1 << 13)
#define CESA_TDMA_CR_ACTIVE		(1 << 14)

#define CESA_TDMA_ECR			0x08C8
#define CESA_TDMA_ECR_MISS		(1 << 0)
#define CESA_TDMA_ECR_DOUBLE_HIT	(1 << 1)
#define CESA_TDMA_ECR_BOTH_HIT		(1 << 2)
#define CESA_TDMA_ECR_DATA_ERROR	(1 << 3)

#define CESA_TDMA_EMR			0x08CC
#define CESA_TDMA_EMR_MISS		CESA_TDMA_ECR_MISS
#define CESA_TDMA_EMR_DOUBLE_HIT	CESA_TDMA_ECR_DOUBLE_HIT
#define CESA_TDMA_EMR_BOTH_HIT		CESA_TDMA_ECR_BOTH_HIT
#define CESA_TDMA_EMR_DATA_ERROR	CESA_TDMA_ECR_DATA_ERROR

/* CESA SA registers definitions */
#define CESA_SA_CMD			0xDE00
#define CESA_SA_CMD_ACTVATE		(1 << 0)

#define CESA_SA_DPR			0xDE04

#define CESA_SA_CR			0xDE08
#define CESA_SA_CR_WAIT_FOR_TDMA	(1 << 7)
#define CESA_SA_CR_ACTIVATE_TDMA	(1 << 9)
#define CESA_SA_CR_MULTI_MODE		(1 << 11)

#define CESA_SA_SR			0xDE0C
#define CESA_SA_SR_ACTIVE		(1 << 0)

#endif
OpenPOWER on IntegriCloud