1eda14cbcSMatt Macy /*
2eda14cbcSMatt Macy  * CDDL HEADER START
3eda14cbcSMatt Macy  *
4eda14cbcSMatt Macy  * The contents of this file are subject to the terms of the
5eda14cbcSMatt Macy  * Common Development and Distribution License (the "License").
6eda14cbcSMatt Macy  * You may not use this file except in compliance with the License.
7eda14cbcSMatt Macy  *
8eda14cbcSMatt Macy  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9271171e0SMartin Matuska  * or https://opensource.org/licenses/CDDL-1.0.
10eda14cbcSMatt Macy  * See the License for the specific language governing permissions
11eda14cbcSMatt Macy  * and limitations under the License.
12eda14cbcSMatt Macy  *
13eda14cbcSMatt Macy  * When distributing Covered Code, include this CDDL HEADER in each
14eda14cbcSMatt Macy  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15eda14cbcSMatt Macy  * If applicable, add the following below this CDDL HEADER, with the
16eda14cbcSMatt Macy  * fields enclosed by brackets "[]" replaced with your own identifying
17eda14cbcSMatt Macy  * information: Portions Copyright [yyyy] [name of copyright owner]
18eda14cbcSMatt Macy  *
19eda14cbcSMatt Macy  * CDDL HEADER END
20eda14cbcSMatt Macy  */
21eda14cbcSMatt Macy /*
22eda14cbcSMatt Macy  * Copyright (C) 2016 Gvozden Nešković. All rights reserved.
23eda14cbcSMatt Macy  */
24eda14cbcSMatt Macy 
25eda14cbcSMatt Macy #ifndef _VDEV_RAIDZ_H
26eda14cbcSMatt Macy #define	_VDEV_RAIDZ_H
27eda14cbcSMatt Macy 
28eda14cbcSMatt Macy #include <sys/types.h>
29eda14cbcSMatt Macy #include <sys/debug.h>
30eda14cbcSMatt Macy #include <sys/kstat.h>
31eda14cbcSMatt Macy #include <sys/abd.h>
327877fdebSMatt Macy #include <sys/vdev_impl.h>
33eda14cbcSMatt Macy 
34eda14cbcSMatt Macy #ifdef  __cplusplus
35eda14cbcSMatt Macy extern "C" {
36eda14cbcSMatt Macy #endif
37eda14cbcSMatt Macy 
38eda14cbcSMatt Macy #define	CODE_P		(0U)
39eda14cbcSMatt Macy #define	CODE_Q		(1U)
40eda14cbcSMatt Macy #define	CODE_R		(2U)
41eda14cbcSMatt Macy 
42eda14cbcSMatt Macy #define	PARITY_P	(1U)
43eda14cbcSMatt Macy #define	PARITY_PQ	(2U)
44eda14cbcSMatt Macy #define	PARITY_PQR	(3U)
45eda14cbcSMatt Macy 
46eda14cbcSMatt Macy #define	TARGET_X	(0U)
47eda14cbcSMatt Macy #define	TARGET_Y	(1U)
48eda14cbcSMatt Macy #define	TARGET_Z	(2U)
49eda14cbcSMatt Macy 
50eda14cbcSMatt Macy /*
51eda14cbcSMatt Macy  * Parity generation methods indexes
52eda14cbcSMatt Macy  */
53eda14cbcSMatt Macy enum raidz_math_gen_op {
54eda14cbcSMatt Macy 	RAIDZ_GEN_P = 0,
55eda14cbcSMatt Macy 	RAIDZ_GEN_PQ,
56eda14cbcSMatt Macy 	RAIDZ_GEN_PQR,
57eda14cbcSMatt Macy 	RAIDZ_GEN_NUM = 3
58eda14cbcSMatt Macy };
59eda14cbcSMatt Macy /*
60eda14cbcSMatt Macy  * Data reconstruction methods indexes
61eda14cbcSMatt Macy  */
62eda14cbcSMatt Macy enum raidz_rec_op {
63eda14cbcSMatt Macy 	RAIDZ_REC_P = 0,
64eda14cbcSMatt Macy 	RAIDZ_REC_Q,
65eda14cbcSMatt Macy 	RAIDZ_REC_R,
66eda14cbcSMatt Macy 	RAIDZ_REC_PQ,
67eda14cbcSMatt Macy 	RAIDZ_REC_PR,
68eda14cbcSMatt Macy 	RAIDZ_REC_QR,
69eda14cbcSMatt Macy 	RAIDZ_REC_PQR,
70eda14cbcSMatt Macy 	RAIDZ_REC_NUM = 7
71eda14cbcSMatt Macy };
72eda14cbcSMatt Macy 
73e92ffd9bSMartin Matuska extern const char *const raidz_gen_name[RAIDZ_GEN_NUM];
74e92ffd9bSMartin Matuska extern const char *const raidz_rec_name[RAIDZ_REC_NUM];
75eda14cbcSMatt Macy 
76eda14cbcSMatt Macy /*
77eda14cbcSMatt Macy  * Methods used to define raidz implementation
78eda14cbcSMatt Macy  *
79eda14cbcSMatt Macy  * @raidz_gen_f	Parity generation function
80eda14cbcSMatt Macy  *     @par1	pointer to raidz_map
81eda14cbcSMatt Macy  * @raidz_rec_f	Data reconstruction function
82eda14cbcSMatt Macy  *     @par1	pointer to raidz_map
83eda14cbcSMatt Macy  *     @par2	array of reconstruction targets
84eda14cbcSMatt Macy  * @will_work_f Function returns TRUE if impl. is supported on the system
85eda14cbcSMatt Macy  * @init_impl_f Function is called once on init
86eda14cbcSMatt Macy  * @fini_impl_f Function is called once on fini
87eda14cbcSMatt Macy  */
88eda14cbcSMatt Macy typedef void		(*raidz_gen_f)(void *);
89eda14cbcSMatt Macy typedef int		(*raidz_rec_f)(void *, const int *);
90eda14cbcSMatt Macy typedef boolean_t	(*will_work_f)(void);
91eda14cbcSMatt Macy typedef void		(*init_impl_f)(void);
92eda14cbcSMatt Macy typedef void		(*fini_impl_f)(void);
93eda14cbcSMatt Macy 
94eda14cbcSMatt Macy #define	RAIDZ_IMPL_NAME_MAX	(20)
95eda14cbcSMatt Macy 
96eda14cbcSMatt Macy typedef struct raidz_impl_ops {
97eda14cbcSMatt Macy 	init_impl_f init;
98eda14cbcSMatt Macy 	fini_impl_f fini;
99eda14cbcSMatt Macy 	raidz_gen_f gen[RAIDZ_GEN_NUM];	/* Parity generate functions */
100eda14cbcSMatt Macy 	raidz_rec_f rec[RAIDZ_REC_NUM];	/* Data reconstruction functions */
101eda14cbcSMatt Macy 	will_work_f is_supported;	/* Support check function */
102eda14cbcSMatt Macy 	char name[RAIDZ_IMPL_NAME_MAX];	/* Name of the implementation */
103eda14cbcSMatt Macy } raidz_impl_ops_t;
104eda14cbcSMatt Macy 
105eda14cbcSMatt Macy typedef struct raidz_col {
106eda14cbcSMatt Macy 	uint64_t rc_devidx;		/* child device index for I/O */
107eda14cbcSMatt Macy 	uint64_t rc_offset;		/* device offset */
108eda14cbcSMatt Macy 	uint64_t rc_size;		/* I/O size */
109184c1b94SMartin Matuska 	abd_t rc_abdstruct;		/* rc_abd probably points here */
110eda14cbcSMatt Macy 	abd_t *rc_abd;			/* I/O data */
111f9693befSMartin Matuska 	abd_t *rc_orig_data;		/* pre-reconstruction */
112eda14cbcSMatt Macy 	int rc_error;			/* I/O error for this device */
113eda14cbcSMatt Macy 	uint8_t rc_tried;		/* Did we attempt this I/O column? */
114eda14cbcSMatt Macy 	uint8_t rc_skipped;		/* Did we skip this I/O column? */
1157877fdebSMatt Macy 	uint8_t rc_need_orig_restore;	/* need to restore from orig_data? */
11616038816SMartin Matuska 	uint8_t rc_force_repair;	/* Write good data to this column */
11716038816SMartin Matuska 	uint8_t rc_allow_repair;	/* Allow repair I/O to this column */
118eda14cbcSMatt Macy } raidz_col_t;
119eda14cbcSMatt Macy 
1207877fdebSMatt Macy typedef struct raidz_row {
1217877fdebSMatt Macy 	uint64_t rr_cols;		/* Regular column count */
1227877fdebSMatt Macy 	uint64_t rr_scols;		/* Count including skipped columns */
1237877fdebSMatt Macy 	uint64_t rr_bigcols;		/* Remainder data column count */
1247877fdebSMatt Macy 	uint64_t rr_missingdata;	/* Count of missing data devices */
1257877fdebSMatt Macy 	uint64_t rr_missingparity;	/* Count of missing parity devices */
1267877fdebSMatt Macy 	uint64_t rr_firstdatacol;	/* First data column/parity count */
1277877fdebSMatt Macy 	abd_t *rr_abd_empty;		/* dRAID empty sector buffer */
1287877fdebSMatt Macy 	int rr_nempty;			/* empty sectors included in parity */
1297877fdebSMatt Macy #ifdef ZFS_DEBUG
1307877fdebSMatt Macy 	uint64_t rr_offset;		/* Logical offset for *_io_verify() */
1317877fdebSMatt Macy 	uint64_t rr_size;		/* Physical size for *_io_verify() */
1327877fdebSMatt Macy #endif
1337877fdebSMatt Macy 	raidz_col_t rr_col[0];		/* Flexible array of I/O columns */
1347877fdebSMatt Macy } raidz_row_t;
1357877fdebSMatt Macy 
136eda14cbcSMatt Macy typedef struct raidz_map {
1377877fdebSMatt Macy 	boolean_t rm_ecksuminjected;	/* checksum error was injected */
1387877fdebSMatt Macy 	int rm_nrows;			/* Regular row count */
1397877fdebSMatt Macy 	int rm_nskip;			/* RAIDZ sectors skipped for padding */
1407877fdebSMatt Macy 	int rm_skipstart;		/* Column index of padding start */
141eda14cbcSMatt Macy 	const raidz_impl_ops_t *rm_ops;	/* RAIDZ math operations */
1427877fdebSMatt Macy 	raidz_row_t *rm_row[0];		/* flexible array of rows */
143eda14cbcSMatt Macy } raidz_map_t;
144eda14cbcSMatt Macy 
1457877fdebSMatt Macy 
146eda14cbcSMatt Macy #define	RAIDZ_ORIGINAL_IMPL	(INT_MAX)
147eda14cbcSMatt Macy 
148eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_scalar_impl;
149eda14cbcSMatt Macy extern boolean_t raidz_will_scalar_work(void);
150eda14cbcSMatt Macy 
151eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_SSE2)	/* only x86_64 for now */
152eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_sse2_impl;
153eda14cbcSMatt Macy #endif
154eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_SSSE3)	/* only x86_64 for now */
155eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_ssse3_impl;
156eda14cbcSMatt Macy #endif
157eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_AVX2)	/* only x86_64 for now */
158eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_avx2_impl;
159eda14cbcSMatt Macy #endif
160eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_AVX512F)	/* only x86_64 for now */
161eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_avx512f_impl;
162eda14cbcSMatt Macy #endif
163eda14cbcSMatt Macy #if defined(__x86_64) && defined(HAVE_AVX512BW)	/* only x86_64 for now */
164eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_avx512bw_impl;
165eda14cbcSMatt Macy #endif
166eda14cbcSMatt Macy #if defined(__aarch64__)
167eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_aarch64_neon_impl;
168eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_aarch64_neonx2_impl;
169eda14cbcSMatt Macy #endif
170eda14cbcSMatt Macy #if defined(__powerpc__)
171eda14cbcSMatt Macy extern const raidz_impl_ops_t vdev_raidz_powerpc_altivec_impl;
172eda14cbcSMatt Macy #endif
173eda14cbcSMatt Macy 
174eda14cbcSMatt Macy /*
175eda14cbcSMatt Macy  * Commonly used raidz_map helpers
176eda14cbcSMatt Macy  *
177eda14cbcSMatt Macy  * raidz_parity		Returns parity of the RAIDZ block
178eda14cbcSMatt Macy  * raidz_ncols		Returns number of columns the block spans
1797877fdebSMatt Macy  *			Note, all rows have the same number of columns.
180eda14cbcSMatt Macy  * raidz_nbigcols	Returns number of big columns
181eda14cbcSMatt Macy  * raidz_col_p		Returns pointer to a column
182eda14cbcSMatt Macy  * raidz_col_size	Returns size of a column
183eda14cbcSMatt Macy  * raidz_big_size	Returns size of big columns
184eda14cbcSMatt Macy  * raidz_short_size	Returns size of short columns
185eda14cbcSMatt Macy  */
1867877fdebSMatt Macy #define	raidz_parity(rm)	((rm)->rm_row[0]->rr_firstdatacol)
1877877fdebSMatt Macy #define	raidz_ncols(rm)		((rm)->rm_row[0]->rr_cols)
188eda14cbcSMatt Macy #define	raidz_nbigcols(rm)	((rm)->rm_bigcols)
189eda14cbcSMatt Macy #define	raidz_col_p(rm, c)	((rm)->rm_col + (c))
190eda14cbcSMatt Macy #define	raidz_col_size(rm, c)	((rm)->rm_col[c].rc_size)
191eda14cbcSMatt Macy #define	raidz_big_size(rm)	(raidz_col_size(rm, CODE_P))
192eda14cbcSMatt Macy #define	raidz_short_size(rm)	(raidz_col_size(rm, raidz_ncols(rm)-1))
193eda14cbcSMatt Macy 
194eda14cbcSMatt Macy /*
195eda14cbcSMatt Macy  * Macro defines an RAIDZ parity generation method
196eda14cbcSMatt Macy  *
197eda14cbcSMatt Macy  * @code	parity the function produce
198eda14cbcSMatt Macy  * @impl	name of the implementation
199eda14cbcSMatt Macy  */
200eda14cbcSMatt Macy #define	_RAIDZ_GEN_WRAP(code, impl)					\
201eda14cbcSMatt Macy static void								\
2027877fdebSMatt Macy impl ## _gen_ ## code(void *rrp)					\
203eda14cbcSMatt Macy {									\
2047877fdebSMatt Macy 	raidz_row_t *rr = (raidz_row_t *)rrp;				\
2057877fdebSMatt Macy 	raidz_generate_## code ## _impl(rr);				\
206eda14cbcSMatt Macy }
207eda14cbcSMatt Macy 
208eda14cbcSMatt Macy /*
209eda14cbcSMatt Macy  * Macro defines an RAIDZ data reconstruction method
210eda14cbcSMatt Macy  *
211eda14cbcSMatt Macy  * @code	parity the function produce
212eda14cbcSMatt Macy  * @impl	name of the implementation
213eda14cbcSMatt Macy  */
214eda14cbcSMatt Macy #define	_RAIDZ_REC_WRAP(code, impl)					\
215eda14cbcSMatt Macy static int								\
2167877fdebSMatt Macy impl ## _rec_ ## code(void *rrp, const int *tgtidx)			\
217eda14cbcSMatt Macy {									\
2187877fdebSMatt Macy 	raidz_row_t *rr = (raidz_row_t *)rrp;				\
2197877fdebSMatt Macy 	return (raidz_reconstruct_## code ## _impl(rr, tgtidx));	\
220eda14cbcSMatt Macy }
221eda14cbcSMatt Macy 
222eda14cbcSMatt Macy /*
223eda14cbcSMatt Macy  * Define all gen methods for an implementation
224eda14cbcSMatt Macy  *
225eda14cbcSMatt Macy  * @impl	name of the implementation
226eda14cbcSMatt Macy  */
227eda14cbcSMatt Macy #define	DEFINE_GEN_METHODS(impl)					\
228eda14cbcSMatt Macy 	_RAIDZ_GEN_WRAP(p, impl);					\
229eda14cbcSMatt Macy 	_RAIDZ_GEN_WRAP(pq, impl);					\
230eda14cbcSMatt Macy 	_RAIDZ_GEN_WRAP(pqr, impl)
231eda14cbcSMatt Macy 
232eda14cbcSMatt Macy /*
233eda14cbcSMatt Macy  * Define all rec functions for an implementation
234eda14cbcSMatt Macy  *
235eda14cbcSMatt Macy  * @impl	name of the implementation
236eda14cbcSMatt Macy  */
237eda14cbcSMatt Macy #define	DEFINE_REC_METHODS(impl)					\
238eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(p, impl);					\
239eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(q, impl);					\
240eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(r, impl);					\
241eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(pq, impl);					\
242eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(pr, impl);					\
243eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(qr, impl);					\
244eda14cbcSMatt Macy 	_RAIDZ_REC_WRAP(pqr, impl)
245eda14cbcSMatt Macy 
246eda14cbcSMatt Macy #define	RAIDZ_GEN_METHODS(impl)						\
247eda14cbcSMatt Macy {									\
248eda14cbcSMatt Macy 	[RAIDZ_GEN_P] = & impl ## _gen_p,				\
249eda14cbcSMatt Macy 	[RAIDZ_GEN_PQ] = & impl ## _gen_pq,				\
250eda14cbcSMatt Macy 	[RAIDZ_GEN_PQR] = & impl ## _gen_pqr				\
251eda14cbcSMatt Macy }
252eda14cbcSMatt Macy 
253eda14cbcSMatt Macy #define	RAIDZ_REC_METHODS(impl)						\
254eda14cbcSMatt Macy {									\
255eda14cbcSMatt Macy 	[RAIDZ_REC_P] = & impl ## _rec_p,				\
256eda14cbcSMatt Macy 	[RAIDZ_REC_Q] = & impl ## _rec_q,				\
257eda14cbcSMatt Macy 	[RAIDZ_REC_R] = & impl ## _rec_r,				\
258eda14cbcSMatt Macy 	[RAIDZ_REC_PQ] = & impl ## _rec_pq,				\
259eda14cbcSMatt Macy 	[RAIDZ_REC_PR] = & impl ## _rec_pr,				\
260eda14cbcSMatt Macy 	[RAIDZ_REC_QR] = & impl ## _rec_qr,				\
261eda14cbcSMatt Macy 	[RAIDZ_REC_PQR] = & impl ## _rec_pqr				\
262eda14cbcSMatt Macy }
263eda14cbcSMatt Macy 
264eda14cbcSMatt Macy 
265eda14cbcSMatt Macy typedef struct raidz_impl_kstat {
266eda14cbcSMatt Macy 	uint64_t gen[RAIDZ_GEN_NUM];	/* gen method speed B/s */
267eda14cbcSMatt Macy 	uint64_t rec[RAIDZ_REC_NUM];	/* rec method speed B/s */
268eda14cbcSMatt Macy } raidz_impl_kstat_t;
269eda14cbcSMatt Macy 
270eda14cbcSMatt Macy /*
271eda14cbcSMatt Macy  * Enumerate various multiplication constants
272eda14cbcSMatt Macy  * used in reconstruction methods
273eda14cbcSMatt Macy  */
274eda14cbcSMatt Macy typedef enum raidz_mul_info {
275eda14cbcSMatt Macy 	/* Reconstruct Q */
276eda14cbcSMatt Macy 	MUL_Q_X		= 0,
277eda14cbcSMatt Macy 	/* Reconstruct R */
278eda14cbcSMatt Macy 	MUL_R_X		= 0,
279eda14cbcSMatt Macy 	/* Reconstruct PQ */
280eda14cbcSMatt Macy 	MUL_PQ_X	= 0,
281eda14cbcSMatt Macy 	MUL_PQ_Y	= 1,
282eda14cbcSMatt Macy 	/* Reconstruct PR */
283eda14cbcSMatt Macy 	MUL_PR_X	= 0,
284eda14cbcSMatt Macy 	MUL_PR_Y	= 1,
285eda14cbcSMatt Macy 	/* Reconstruct QR */
286eda14cbcSMatt Macy 	MUL_QR_XQ	= 0,
287eda14cbcSMatt Macy 	MUL_QR_X	= 1,
288eda14cbcSMatt Macy 	MUL_QR_YQ	= 2,
289eda14cbcSMatt Macy 	MUL_QR_Y	= 3,
290eda14cbcSMatt Macy 	/* Reconstruct PQR */
291eda14cbcSMatt Macy 	MUL_PQR_XP	= 0,
292eda14cbcSMatt Macy 	MUL_PQR_XQ	= 1,
293eda14cbcSMatt Macy 	MUL_PQR_XR	= 2,
294eda14cbcSMatt Macy 	MUL_PQR_YU	= 3,
295eda14cbcSMatt Macy 	MUL_PQR_YP	= 4,
296eda14cbcSMatt Macy 	MUL_PQR_YQ	= 5,
297eda14cbcSMatt Macy 
298eda14cbcSMatt Macy 	MUL_CNT		= 6
299eda14cbcSMatt Macy } raidz_mul_info_t;
300eda14cbcSMatt Macy 
301eda14cbcSMatt Macy /*
302eda14cbcSMatt Macy  * Powers of 2 in the Galois field.
303eda14cbcSMatt Macy  */
304eda14cbcSMatt Macy extern const uint8_t vdev_raidz_pow2[256] __attribute__((aligned(256)));
305eda14cbcSMatt Macy /* Logs of 2 in the Galois field defined above. */
306eda14cbcSMatt Macy extern const uint8_t vdev_raidz_log2[256] __attribute__((aligned(256)));
307eda14cbcSMatt Macy 
308eda14cbcSMatt Macy /*
309eda14cbcSMatt Macy  * Multiply a given number by 2 raised to the given power.
310eda14cbcSMatt Macy  */
311eda14cbcSMatt Macy static inline uint8_t
312eda14cbcSMatt Macy vdev_raidz_exp2(const uint8_t a, const unsigned exp)
313eda14cbcSMatt Macy {
314eda14cbcSMatt Macy 	if (a == 0)
315eda14cbcSMatt Macy 		return (0);
316eda14cbcSMatt Macy 
317eda14cbcSMatt Macy 	return (vdev_raidz_pow2[(exp + (unsigned)vdev_raidz_log2[a]) % 255]);
318eda14cbcSMatt Macy }
319eda14cbcSMatt Macy 
320eda14cbcSMatt Macy /*
321eda14cbcSMatt Macy  * Galois Field operations.
322eda14cbcSMatt Macy  *
323eda14cbcSMatt Macy  * gf_exp2	- computes 2 raised to the given power
324eda14cbcSMatt Macy  * gf_exp2	- computes 4 raised to the given power
325eda14cbcSMatt Macy  * gf_mul	- multiplication
326eda14cbcSMatt Macy  * gf_div	- division
327eda14cbcSMatt Macy  * gf_inv	- multiplicative inverse
328eda14cbcSMatt Macy  */
329eda14cbcSMatt Macy typedef unsigned gf_t;
330eda14cbcSMatt Macy typedef unsigned gf_log_t;
331eda14cbcSMatt Macy 
332eda14cbcSMatt Macy static inline gf_t
333eda14cbcSMatt Macy gf_mul(const gf_t a, const gf_t b)
334eda14cbcSMatt Macy {
335eda14cbcSMatt Macy 	gf_log_t logsum;
336eda14cbcSMatt Macy 
337eda14cbcSMatt Macy 	if (a == 0 || b == 0)
338eda14cbcSMatt Macy 		return (0);
339eda14cbcSMatt Macy 
340eda14cbcSMatt Macy 	logsum = (gf_log_t)vdev_raidz_log2[a] + (gf_log_t)vdev_raidz_log2[b];
341eda14cbcSMatt Macy 
342eda14cbcSMatt Macy 	return ((gf_t)vdev_raidz_pow2[logsum % 255]);
343eda14cbcSMatt Macy }
344eda14cbcSMatt Macy 
345eda14cbcSMatt Macy static inline gf_t
346eda14cbcSMatt Macy gf_div(const gf_t  a, const gf_t b)
347eda14cbcSMatt Macy {
348eda14cbcSMatt Macy 	gf_log_t logsum;
349eda14cbcSMatt Macy 
350eda14cbcSMatt Macy 	ASSERT3U(b, >, 0);
351eda14cbcSMatt Macy 	if (a == 0)
352eda14cbcSMatt Macy 		return (0);
353eda14cbcSMatt Macy 
354eda14cbcSMatt Macy 	logsum = (gf_log_t)255 + (gf_log_t)vdev_raidz_log2[a] -
355eda14cbcSMatt Macy 	    (gf_log_t)vdev_raidz_log2[b];
356eda14cbcSMatt Macy 
357eda14cbcSMatt Macy 	return ((gf_t)vdev_raidz_pow2[logsum % 255]);
358eda14cbcSMatt Macy }
359eda14cbcSMatt Macy 
360eda14cbcSMatt Macy static inline gf_t
361eda14cbcSMatt Macy gf_inv(const gf_t a)
362eda14cbcSMatt Macy {
363eda14cbcSMatt Macy 	gf_log_t logsum;
364eda14cbcSMatt Macy 
365eda14cbcSMatt Macy 	ASSERT3U(a, >, 0);
366eda14cbcSMatt Macy 
367eda14cbcSMatt Macy 	logsum = (gf_log_t)255 - (gf_log_t)vdev_raidz_log2[a];
368eda14cbcSMatt Macy 
369eda14cbcSMatt Macy 	return ((gf_t)vdev_raidz_pow2[logsum]);
370eda14cbcSMatt Macy }
371eda14cbcSMatt Macy 
372eda14cbcSMatt Macy static inline gf_t
373eda14cbcSMatt Macy gf_exp2(gf_log_t exp)
374eda14cbcSMatt Macy {
375eda14cbcSMatt Macy 	return (vdev_raidz_pow2[exp % 255]);
376eda14cbcSMatt Macy }
377eda14cbcSMatt Macy 
378eda14cbcSMatt Macy static inline gf_t
379eda14cbcSMatt Macy gf_exp4(gf_log_t exp)
380eda14cbcSMatt Macy {
381eda14cbcSMatt Macy 	ASSERT3U(exp, <=, 255);
382eda14cbcSMatt Macy 	return ((gf_t)vdev_raidz_pow2[(2 * exp) % 255]);
383eda14cbcSMatt Macy }
384eda14cbcSMatt Macy 
385eda14cbcSMatt Macy #ifdef  __cplusplus
386eda14cbcSMatt Macy }
387eda14cbcSMatt Macy #endif
388eda14cbcSMatt Macy 
389eda14cbcSMatt Macy #endif /* _VDEV_RAIDZ_H */
390