1e86372a0SGvozden Neskovic /*
2e86372a0SGvozden Neskovic  * CDDL HEADER START
3e86372a0SGvozden Neskovic  *
4e86372a0SGvozden Neskovic  * The contents of this file are subject to the terms of the
5e86372a0SGvozden Neskovic  * Common Development and Distribution License (the "License").
6e86372a0SGvozden Neskovic  * You may not use this file except in compliance with the License.
7e86372a0SGvozden Neskovic  *
8e86372a0SGvozden Neskovic  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e86372a0SGvozden Neskovic  * or http://www.opensolaris.org/os/licensing.
10e86372a0SGvozden Neskovic  * See the License for the specific language governing permissions
11e86372a0SGvozden Neskovic  * and limitations under the License.
12e86372a0SGvozden Neskovic  *
13e86372a0SGvozden Neskovic  * When distributing Covered Code, include this CDDL HEADER in each
14e86372a0SGvozden Neskovic  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e86372a0SGvozden Neskovic  * If applicable, add the following below this CDDL HEADER, with the
16e86372a0SGvozden Neskovic  * fields enclosed by brackets "[]" replaced with your own identifying
17e86372a0SGvozden Neskovic  * information: Portions Copyright [yyyy] [name of copyright owner]
18e86372a0SGvozden Neskovic  *
19e86372a0SGvozden Neskovic  * CDDL HEADER END
20e86372a0SGvozden Neskovic  */
21e86372a0SGvozden Neskovic /*
22e86372a0SGvozden Neskovic  * Copyright (C) 2016 Gvozden Nešković. All rights reserved.
23e86372a0SGvozden Neskovic  */
24e86372a0SGvozden Neskovic 
25e86372a0SGvozden Neskovic #ifndef _VDEV_RAIDZ_H
26e86372a0SGvozden Neskovic #define	_VDEV_RAIDZ_H
27e86372a0SGvozden Neskovic 
28e86372a0SGvozden Neskovic #include <sys/types.h>
29e86372a0SGvozden Neskovic #include <sys/debug.h>
30e86372a0SGvozden Neskovic #include <sys/kstat.h>
31e86372a0SGvozden Neskovic #include <sys/abd.h>
32e86372a0SGvozden Neskovic 
33e86372a0SGvozden Neskovic #ifdef  __cplusplus
34e86372a0SGvozden Neskovic extern "C" {
35e86372a0SGvozden Neskovic #endif
36e86372a0SGvozden Neskovic 
37e86372a0SGvozden Neskovic #define	CODE_P		(0U)
38e86372a0SGvozden Neskovic #define	CODE_Q		(1U)
39e86372a0SGvozden Neskovic #define	CODE_R		(2U)
40e86372a0SGvozden Neskovic 
41e86372a0SGvozden Neskovic #define	PARITY_P	(1U)
42e86372a0SGvozden Neskovic #define	PARITY_PQ	(2U)
43e86372a0SGvozden Neskovic #define	PARITY_PQR	(3U)
44e86372a0SGvozden Neskovic 
45e86372a0SGvozden Neskovic #define	TARGET_X	(0U)
46e86372a0SGvozden Neskovic #define	TARGET_Y	(1U)
47e86372a0SGvozden Neskovic #define	TARGET_Z	(2U)
48e86372a0SGvozden Neskovic 
49e86372a0SGvozden Neskovic /*
50e86372a0SGvozden Neskovic  * Parity generation methods indexes
51e86372a0SGvozden Neskovic  */
52e86372a0SGvozden Neskovic enum raidz_math_gen_op {
53e86372a0SGvozden Neskovic 	RAIDZ_GEN_P = 0,
54e86372a0SGvozden Neskovic 	RAIDZ_GEN_PQ,
55e86372a0SGvozden Neskovic 	RAIDZ_GEN_PQR,
56e86372a0SGvozden Neskovic 	RAIDZ_GEN_NUM = 3
57e86372a0SGvozden Neskovic };
58e86372a0SGvozden Neskovic /*
59e86372a0SGvozden Neskovic  * Data reconstruction methods indexes
60e86372a0SGvozden Neskovic  */
61e86372a0SGvozden Neskovic enum raidz_rec_op {
62e86372a0SGvozden Neskovic 	RAIDZ_REC_P = 0,
63e86372a0SGvozden Neskovic 	RAIDZ_REC_Q,
64e86372a0SGvozden Neskovic 	RAIDZ_REC_R,
65e86372a0SGvozden Neskovic 	RAIDZ_REC_PQ,
66e86372a0SGvozden Neskovic 	RAIDZ_REC_PR,
67e86372a0SGvozden Neskovic 	RAIDZ_REC_QR,
68e86372a0SGvozden Neskovic 	RAIDZ_REC_PQR,
69e86372a0SGvozden Neskovic 	RAIDZ_REC_NUM = 7
70e86372a0SGvozden Neskovic };
71e86372a0SGvozden Neskovic 
72e86372a0SGvozden Neskovic extern const char *raidz_gen_name[RAIDZ_GEN_NUM];
73e86372a0SGvozden Neskovic extern const char *raidz_rec_name[RAIDZ_REC_NUM];
74e86372a0SGvozden Neskovic 
75e86372a0SGvozden Neskovic /*
76e86372a0SGvozden Neskovic  * Methods used to define raidz implementation
77e86372a0SGvozden Neskovic  *
78e86372a0SGvozden Neskovic  * @raidz_gen_f	Parity generation function
79e86372a0SGvozden Neskovic  *     @par1	pointer to raidz_map
80e86372a0SGvozden Neskovic  * @raidz_rec_f	Data reconstruction function
81e86372a0SGvozden Neskovic  *     @par1	pointer to raidz_map
82e86372a0SGvozden Neskovic  *     @par2	array of reconstruction targets
83e86372a0SGvozden Neskovic  * @will_work_f Function returns TRUE if impl. is supported on the system
84e86372a0SGvozden Neskovic  * @init_impl_f Function is called once on init
85e86372a0SGvozden Neskovic  * @fini_impl_f Function is called once on fini
86e86372a0SGvozden Neskovic  */
87e86372a0SGvozden Neskovic typedef void		(*raidz_gen_f)(void *);
88e86372a0SGvozden Neskovic typedef int		(*raidz_rec_f)(void *, const int *);
89e86372a0SGvozden Neskovic typedef boolean_t	(*will_work_f)(void);
90e86372a0SGvozden Neskovic typedef void		(*init_impl_f)(void);
91e86372a0SGvozden Neskovic typedef void		(*fini_impl_f)(void);
92e86372a0SGvozden Neskovic 
93e86372a0SGvozden Neskovic #define	RAIDZ_IMPL_NAME_MAX	(20)
94e86372a0SGvozden Neskovic 
95e86372a0SGvozden Neskovic typedef struct raidz_impl_ops {
96e86372a0SGvozden Neskovic 	init_impl_f init;
97e86372a0SGvozden Neskovic 	fini_impl_f fini;
98e86372a0SGvozden Neskovic 	raidz_gen_f gen[RAIDZ_GEN_NUM];	/* Parity generate functions */
99e86372a0SGvozden Neskovic 	raidz_rec_f rec[RAIDZ_REC_NUM];	/* Data reconstruction functions */
100e86372a0SGvozden Neskovic 	will_work_f is_supported;	/* Support check function */
101e86372a0SGvozden Neskovic 	char name[RAIDZ_IMPL_NAME_MAX];	/* Name of the implementation */
102e86372a0SGvozden Neskovic } raidz_impl_ops_t;
103e86372a0SGvozden Neskovic 
104e86372a0SGvozden Neskovic typedef struct raidz_col {
105e86372a0SGvozden Neskovic 	size_t rc_devidx;		/* child device index for I/O */
106e86372a0SGvozden Neskovic 	size_t rc_offset;		/* device offset */
107e86372a0SGvozden Neskovic 	size_t rc_size;			/* I/O size */
108e86372a0SGvozden Neskovic 	abd_t *rc_abd;			/* I/O data */
109e86372a0SGvozden Neskovic 	void *rc_gdata;			/* used to store the "good" version */
110e86372a0SGvozden Neskovic 	int rc_error;			/* I/O error for this device */
111e86372a0SGvozden Neskovic 	unsigned int rc_tried;		/* Did we attempt this I/O column? */
112e86372a0SGvozden Neskovic 	unsigned int rc_skipped;	/* Did we skip this I/O column? */
113e86372a0SGvozden Neskovic } raidz_col_t;
114e86372a0SGvozden Neskovic 
115e86372a0SGvozden Neskovic typedef struct raidz_map {
116e86372a0SGvozden Neskovic 	size_t rm_cols;			/* Regular column count */
117e86372a0SGvozden Neskovic 	size_t rm_scols;		/* Count including skipped columns */
118e86372a0SGvozden Neskovic 	size_t rm_bigcols;		/* Number of oversized columns */
119e86372a0SGvozden Neskovic 	size_t rm_asize;		/* Actual total I/O size */
120e86372a0SGvozden Neskovic 	size_t rm_missingdata;		/* Count of missing data devices */
121e86372a0SGvozden Neskovic 	size_t rm_missingparity;	/* Count of missing parity devices */
122e86372a0SGvozden Neskovic 	size_t rm_firstdatacol;		/* First data column/parity count */
123e86372a0SGvozden Neskovic 	size_t rm_nskip;		/* Skipped sectors for padding */
124e86372a0SGvozden Neskovic 	size_t rm_skipstart;		/* Column index of padding start */
125e86372a0SGvozden Neskovic 	void *rm_abd_copy;		/* rm_asize-buffer of copied data */
126e86372a0SGvozden Neskovic 	size_t rm_reports;		/* # of referencing checksum reports */
127e86372a0SGvozden Neskovic 	unsigned int rm_freed;		/* map no longer has referencing ZIO */
128e86372a0SGvozden Neskovic 	unsigned int rm_ecksuminjected;	/* checksum error was injected */
129e86372a0SGvozden Neskovic 	const raidz_impl_ops_t *rm_ops;	/* RAIDZ math operations */
130e86372a0SGvozden Neskovic 	raidz_col_t rm_col[1];		/* Flexible array of I/O columns */
131e86372a0SGvozden Neskovic } raidz_map_t;
132e86372a0SGvozden Neskovic 
133e86372a0SGvozden Neskovic #define	RAIDZ_ORIGINAL_IMPL	(INT_MAX)
134e86372a0SGvozden Neskovic 
135e86372a0SGvozden Neskovic extern const raidz_impl_ops_t vdev_raidz_scalar_impl;
136*f91a4547SGvozden Neskovic #if defined(__x86)
137*f91a4547SGvozden Neskovic extern const raidz_impl_ops_t vdev_raidz_sse2_impl;
138*f91a4547SGvozden Neskovic #endif
139*f91a4547SGvozden Neskovic #if defined(__x86)
140*f91a4547SGvozden Neskovic extern const raidz_impl_ops_t vdev_raidz_ssse3_impl;
141*f91a4547SGvozden Neskovic #endif
142*f91a4547SGvozden Neskovic #if defined(__x86)
143*f91a4547SGvozden Neskovic extern const raidz_impl_ops_t vdev_raidz_avx2_impl;
144*f91a4547SGvozden Neskovic #endif
145e86372a0SGvozden Neskovic 
146e86372a0SGvozden Neskovic /*
147e86372a0SGvozden Neskovic  * Commonly used raidz_map helpers
148e86372a0SGvozden Neskovic  *
149e86372a0SGvozden Neskovic  * raidz_parity		Returns parity of the RAIDZ block
150e86372a0SGvozden Neskovic  * raidz_ncols		Returns number of columns the block spans
151*f91a4547SGvozden Neskovic  * raidz_nbigcols	Returns number of big columns
152e86372a0SGvozden Neskovic  * raidz_col_p		Returns pointer to a column
153e86372a0SGvozden Neskovic  * raidz_col_size	Returns size of a column
154e86372a0SGvozden Neskovic  * raidz_big_size	Returns size of big columns
155e86372a0SGvozden Neskovic  * raidz_short_size	Returns size of short columns
156e86372a0SGvozden Neskovic  */
157e86372a0SGvozden Neskovic #define	raidz_parity(rm)	((rm)->rm_firstdatacol)
158e86372a0SGvozden Neskovic #define	raidz_ncols(rm)		((rm)->rm_cols)
159e86372a0SGvozden Neskovic #define	raidz_nbigcols(rm)	((rm)->rm_bigcols)
160e86372a0SGvozden Neskovic #define	raidz_col_p(rm, c)	((rm)->rm_col + (c))
161e86372a0SGvozden Neskovic #define	raidz_col_size(rm, c)	((rm)->rm_col[c].rc_size)
162e86372a0SGvozden Neskovic #define	raidz_big_size(rm)	(raidz_col_size(rm, CODE_P))
163e86372a0SGvozden Neskovic #define	raidz_short_size(rm)	(raidz_col_size(rm, raidz_ncols(rm)-1))
164e86372a0SGvozden Neskovic 
165e86372a0SGvozden Neskovic /*
166e86372a0SGvozden Neskovic  * Macro defines an RAIDZ parity generation method
167e86372a0SGvozden Neskovic  *
168e86372a0SGvozden Neskovic  * @code	parity the function produce
169e86372a0SGvozden Neskovic  * @impl	name of the implementation
170e86372a0SGvozden Neskovic  */
171e86372a0SGvozden Neskovic #define	_RAIDZ_GEN_WRAP(code, impl) 					\
172e86372a0SGvozden Neskovic static void								\
173e86372a0SGvozden Neskovic impl ## _gen_ ## code(void *rmp)					\
174e86372a0SGvozden Neskovic {									\
175e86372a0SGvozden Neskovic 	raidz_map_t *rm = (raidz_map_t *) rmp;				\
176e86372a0SGvozden Neskovic 	raidz_generate_## code ## _impl(rm); 				\
177e86372a0SGvozden Neskovic }
178e86372a0SGvozden Neskovic 
179e86372a0SGvozden Neskovic /*
180e86372a0SGvozden Neskovic  * Macro defines an RAIDZ data reconstruction method
181e86372a0SGvozden Neskovic  *
182e86372a0SGvozden Neskovic  * @code	parity the function produce
183e86372a0SGvozden Neskovic  * @impl	name of the implementation
184e86372a0SGvozden Neskovic  */
185e86372a0SGvozden Neskovic #define	_RAIDZ_REC_WRAP(code, impl) 					\
186e86372a0SGvozden Neskovic static int 								\
187e86372a0SGvozden Neskovic impl ## _rec_ ## code(void *rmp, const int *tgtidx)			\
188e86372a0SGvozden Neskovic {									\
189e86372a0SGvozden Neskovic 	raidz_map_t *rm = (raidz_map_t *) rmp;				\
190e86372a0SGvozden Neskovic 	return (raidz_reconstruct_## code ## _impl(rm, tgtidx));	\
191e86372a0SGvozden Neskovic }
192e86372a0SGvozden Neskovic 
193e86372a0SGvozden Neskovic /*
194e86372a0SGvozden Neskovic  * Define all gen methods for an implementation
195e86372a0SGvozden Neskovic  *
196e86372a0SGvozden Neskovic  * @impl	name of the implementation
197e86372a0SGvozden Neskovic  */
198e86372a0SGvozden Neskovic #define	DEFINE_GEN_METHODS(impl)					\
199e86372a0SGvozden Neskovic 	_RAIDZ_GEN_WRAP(p, impl);					\
200e86372a0SGvozden Neskovic 	_RAIDZ_GEN_WRAP(pq, impl);					\
201e86372a0SGvozden Neskovic 	_RAIDZ_GEN_WRAP(pqr, impl)
202e86372a0SGvozden Neskovic 
203e86372a0SGvozden Neskovic /*
204e86372a0SGvozden Neskovic  * Define all rec functions for an implementation
205e86372a0SGvozden Neskovic  *
206e86372a0SGvozden Neskovic  * @impl	name of the implementation
207e86372a0SGvozden Neskovic  */
208e86372a0SGvozden Neskovic #define	DEFINE_REC_METHODS(impl)					\
209e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(p, impl);					\
210e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(q, impl);					\
211e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(r, impl);					\
212e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(pq, impl);					\
213e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(pr, impl);					\
214e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(qr, impl);					\
215e86372a0SGvozden Neskovic 	_RAIDZ_REC_WRAP(pqr, impl)
216e86372a0SGvozden Neskovic 
217e86372a0SGvozden Neskovic #define	RAIDZ_GEN_METHODS(impl)						\
218e86372a0SGvozden Neskovic {									\
219e86372a0SGvozden Neskovic 	[RAIDZ_GEN_P] = & impl ## _gen_p,				\
220e86372a0SGvozden Neskovic 	[RAIDZ_GEN_PQ] = & impl ## _gen_pq,				\
221e86372a0SGvozden Neskovic 	[RAIDZ_GEN_PQR] = & impl ## _gen_pqr				\
222e86372a0SGvozden Neskovic }
223e86372a0SGvozden Neskovic 
224e86372a0SGvozden Neskovic #define	RAIDZ_REC_METHODS(impl)						\
225e86372a0SGvozden Neskovic {									\
226e86372a0SGvozden Neskovic 	[RAIDZ_REC_P] = & impl ## _rec_p,				\
227e86372a0SGvozden Neskovic 	[RAIDZ_REC_Q] = & impl ## _rec_q,				\
228e86372a0SGvozden Neskovic 	[RAIDZ_REC_R] = & impl ## _rec_r,				\
229e86372a0SGvozden Neskovic 	[RAIDZ_REC_PQ] = & impl ## _rec_pq,				\
230e86372a0SGvozden Neskovic 	[RAIDZ_REC_PR] = & impl ## _rec_pr,				\
231e86372a0SGvozden Neskovic 	[RAIDZ_REC_QR] = & impl ## _rec_qr,				\
232e86372a0SGvozden Neskovic 	[RAIDZ_REC_PQR] = & impl ## _rec_pqr				\
233e86372a0SGvozden Neskovic }
234e86372a0SGvozden Neskovic 
235e86372a0SGvozden Neskovic 
236e86372a0SGvozden Neskovic typedef struct raidz_impl_kstat {
237*f91a4547SGvozden Neskovic 	uint64_t gen[RAIDZ_GEN_NUM];	/* gen method speed B/s */
238*f91a4547SGvozden Neskovic 	uint64_t rec[RAIDZ_REC_NUM];	/* rec method speed B/s */
239e86372a0SGvozden Neskovic } raidz_impl_kstat_t;
240e86372a0SGvozden Neskovic 
241e86372a0SGvozden Neskovic /*
242e86372a0SGvozden Neskovic  * Enumerate various multiplication constants
243e86372a0SGvozden Neskovic  * used in reconstruction methods
244e86372a0SGvozden Neskovic  */
245e86372a0SGvozden Neskovic typedef enum raidz_mul_info {
246e86372a0SGvozden Neskovic 	/* Reconstruct Q */
247e86372a0SGvozden Neskovic 	MUL_Q_X		= 0,
248e86372a0SGvozden Neskovic 	/* Reconstruct R */
249e86372a0SGvozden Neskovic 	MUL_R_X		= 0,
250e86372a0SGvozden Neskovic 	/* Reconstruct PQ */
251e86372a0SGvozden Neskovic 	MUL_PQ_X	= 0,
252e86372a0SGvozden Neskovic 	MUL_PQ_Y	= 1,
253e86372a0SGvozden Neskovic 	/* Reconstruct PR */
254e86372a0SGvozden Neskovic 	MUL_PR_X	= 0,
255e86372a0SGvozden Neskovic 	MUL_PR_Y	= 1,
256e86372a0SGvozden Neskovic 	/* Reconstruct QR */
257e86372a0SGvozden Neskovic 	MUL_QR_XQ	= 0,
258e86372a0SGvozden Neskovic 	MUL_QR_X	= 1,
259e86372a0SGvozden Neskovic 	MUL_QR_YQ	= 2,
260e86372a0SGvozden Neskovic 	MUL_QR_Y	= 3,
261e86372a0SGvozden Neskovic 	/* Reconstruct PQR */
262e86372a0SGvozden Neskovic 	MUL_PQR_XP	= 0,
263e86372a0SGvozden Neskovic 	MUL_PQR_XQ	= 1,
264e86372a0SGvozden Neskovic 	MUL_PQR_XR	= 2,
265e86372a0SGvozden Neskovic 	MUL_PQR_YU	= 3,
266e86372a0SGvozden Neskovic 	MUL_PQR_YP	= 4,
267e86372a0SGvozden Neskovic 	MUL_PQR_YQ	= 5,
268e86372a0SGvozden Neskovic 
269e86372a0SGvozden Neskovic 	MUL_CNT		= 6
270e86372a0SGvozden Neskovic } raidz_mul_info_t;
271e86372a0SGvozden Neskovic 
272e86372a0SGvozden Neskovic /*
273e86372a0SGvozden Neskovic  * Powers of 2 in the Galois field.
274e86372a0SGvozden Neskovic  */
275e86372a0SGvozden Neskovic extern const uint8_t vdev_raidz_pow2[256] __attribute__((aligned(256)));
276e86372a0SGvozden Neskovic /* Logs of 2 in the Galois field defined above. */
277e86372a0SGvozden Neskovic extern const uint8_t vdev_raidz_log2[256] __attribute__((aligned(256)));
278e86372a0SGvozden Neskovic 
279e86372a0SGvozden Neskovic /*
280e86372a0SGvozden Neskovic  * Multiply a given number by 2 raised to the given power.
281e86372a0SGvozden Neskovic  */
282e86372a0SGvozden Neskovic static inline uint8_t
vdev_raidz_exp2(const uint8_t a,const unsigned exp)283e86372a0SGvozden Neskovic vdev_raidz_exp2(const uint8_t a, const unsigned exp)
284e86372a0SGvozden Neskovic {
285e86372a0SGvozden Neskovic 	if (a == 0)
286e86372a0SGvozden Neskovic 		return (0);
287e86372a0SGvozden Neskovic 
288e86372a0SGvozden Neskovic 	return (vdev_raidz_pow2[(exp + (unsigned) vdev_raidz_log2[a]) % 255]);
289e86372a0SGvozden Neskovic }
290e86372a0SGvozden Neskovic 
291e86372a0SGvozden Neskovic /*
292e86372a0SGvozden Neskovic  * Galois Field operations.
293e86372a0SGvozden Neskovic  *
294e86372a0SGvozden Neskovic  * gf_exp2	- computes 2 raised to the given power
295e86372a0SGvozden Neskovic  * gf_exp2	- computes 4 raised to the given power
296e86372a0SGvozden Neskovic  * gf_mul	- multiplication
297e86372a0SGvozden Neskovic  * gf_div	- division
298e86372a0SGvozden Neskovic  * gf_inv	- multiplicative inverse
299e86372a0SGvozden Neskovic  */
300e86372a0SGvozden Neskovic typedef unsigned gf_t;
301e86372a0SGvozden Neskovic typedef unsigned gf_log_t;
302e86372a0SGvozden Neskovic 
303e86372a0SGvozden Neskovic static inline gf_t
gf_mul(const gf_t a,const gf_t b)304e86372a0SGvozden Neskovic gf_mul(const gf_t a, const gf_t b)
305e86372a0SGvozden Neskovic {
306e86372a0SGvozden Neskovic 	gf_log_t logsum;
307e86372a0SGvozden Neskovic 
308e86372a0SGvozden Neskovic 	if (a == 0 || b == 0)
309e86372a0SGvozden Neskovic 		return (0);
310e86372a0SGvozden Neskovic 
311e86372a0SGvozden Neskovic 	logsum = (gf_log_t) vdev_raidz_log2[a] + (gf_log_t) vdev_raidz_log2[b];
312e86372a0SGvozden Neskovic 
313e86372a0SGvozden Neskovic 	return ((gf_t) vdev_raidz_pow2[logsum % 255]);
314e86372a0SGvozden Neskovic }
315e86372a0SGvozden Neskovic 
316e86372a0SGvozden Neskovic static inline gf_t
gf_div(const gf_t a,const gf_t b)317e86372a0SGvozden Neskovic gf_div(const gf_t  a, const gf_t b)
318e86372a0SGvozden Neskovic {
319e86372a0SGvozden Neskovic 	gf_log_t logsum;
320e86372a0SGvozden Neskovic 
321e86372a0SGvozden Neskovic 	ASSERT3U(b, >, 0);
322e86372a0SGvozden Neskovic 	if (a == 0)
323e86372a0SGvozden Neskovic 		return (0);
324e86372a0SGvozden Neskovic 
325e86372a0SGvozden Neskovic 	logsum = (gf_log_t) 255 + (gf_log_t) vdev_raidz_log2[a] -
326e86372a0SGvozden Neskovic 	    (gf_log_t) vdev_raidz_log2[b];
327e86372a0SGvozden Neskovic 
328e86372a0SGvozden Neskovic 	return ((gf_t) vdev_raidz_pow2[logsum % 255]);
329e86372a0SGvozden Neskovic }
330e86372a0SGvozden Neskovic 
331e86372a0SGvozden Neskovic static inline gf_t
gf_inv(const gf_t a)332e86372a0SGvozden Neskovic gf_inv(const gf_t a)
333e86372a0SGvozden Neskovic {
334e86372a0SGvozden Neskovic 	gf_log_t logsum;
335e86372a0SGvozden Neskovic 
336e86372a0SGvozden Neskovic 	ASSERT3U(a, >, 0);
337e86372a0SGvozden Neskovic 
338e86372a0SGvozden Neskovic 	logsum = (gf_log_t) 255 - (gf_log_t) vdev_raidz_log2[a];
339e86372a0SGvozden Neskovic 
340e86372a0SGvozden Neskovic 	return ((gf_t) vdev_raidz_pow2[logsum]);
341e86372a0SGvozden Neskovic }
342e86372a0SGvozden Neskovic 
343e86372a0SGvozden Neskovic static inline gf_t
gf_exp2(gf_log_t exp)344e86372a0SGvozden Neskovic gf_exp2(gf_log_t exp)
345e86372a0SGvozden Neskovic {
346e86372a0SGvozden Neskovic 	return (vdev_raidz_pow2[exp % 255]);
347e86372a0SGvozden Neskovic }
348e86372a0SGvozden Neskovic 
349e86372a0SGvozden Neskovic static inline gf_t
gf_exp4(gf_log_t exp)350e86372a0SGvozden Neskovic gf_exp4(gf_log_t exp)
351e86372a0SGvozden Neskovic {
352e86372a0SGvozden Neskovic 	ASSERT3U(exp, <=, 255);
353e86372a0SGvozden Neskovic 	return ((gf_t) vdev_raidz_pow2[(2 * exp) % 255]);
354e86372a0SGvozden Neskovic }
355e86372a0SGvozden Neskovic 
356e86372a0SGvozden Neskovic #ifdef  __cplusplus
357e86372a0SGvozden Neskovic }
358e86372a0SGvozden Neskovic #endif
359e86372a0SGvozden Neskovic 
360e86372a0SGvozden Neskovic #endif /* _VDEV_RAIDZ_H */
361