Commit | Line | Data |
---|---|---|
d7e09d03 PT |
1 | /* |
2 | * GPL HEADER START | |
3 | * | |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 only, | |
8 | * as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * General Public License version 2 for more details (a copy is included | |
14 | * in the LICENSE file that accompanied this code). | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * version 2 along with this program; If not, see | |
18 | * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf | |
19 | * | |
20 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
21 | * CA 95054 USA or visit www.sun.com if you need additional information or | |
22 | * have any questions. | |
23 | * | |
24 | * GPL HEADER END | |
25 | */ | |
26 | /* | |
27 | * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. | |
28 | * Use is subject to license terms. | |
29 | * | |
30 | * Copyright (c) 2011, 2012, Intel Corporation. | |
31 | */ | |
32 | /* | |
33 | * This file is part of Lustre, http://www.lustre.org/ | |
34 | * Lustre is a trademark of Sun Microsystems, Inc. | |
35 | * | |
36 | * lnet/selftest/brw_test.c | |
37 | * | |
38 | * Author: Isaac Huang <isaac@clusterfs.com> | |
39 | */ | |
40 | ||
41 | #include "selftest.h" | |
42 | ||
43 | static int brw_srv_workitems = SFW_TEST_WI_MAX; | |
8cc7b4b9 PT |
44 | module_param(brw_srv_workitems, int, 0644); |
45 | MODULE_PARM_DESC(brw_srv_workitems, "# BRW server workitems"); | |
d7e09d03 PT |
46 | |
47 | static int brw_inject_errors; | |
8cc7b4b9 PT |
48 | module_param(brw_inject_errors, int, 0644); |
49 | MODULE_PARM_DESC(brw_inject_errors, "# data errors to inject randomly, zero by default"); | |
d7e09d03 PT |
50 | |
51 | static void | |
5f849bb0 | 52 | brw_client_fini(sfw_test_instance_t *tsi) |
d7e09d03 PT |
53 | { |
54 | srpc_bulk_t *bulk; | |
55 | sfw_test_unit_t *tsu; | |
56 | ||
5f849bb0 | 57 | LASSERT(tsi->tsi_is_client); |
d7e09d03 | 58 | |
5f849bb0 | 59 | list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { |
d7e09d03 | 60 | bulk = tsu->tsu_private; |
5252bbfd LN |
61 | if (bulk == NULL) |
62 | continue; | |
d7e09d03 PT |
63 | |
64 | srpc_free_bulk(bulk); | |
65 | tsu->tsu_private = NULL; | |
66 | } | |
67 | } | |
68 | ||
d5bd0504 | 69 | static int |
5f849bb0 | 70 | brw_client_init(sfw_test_instance_t *tsi) |
d7e09d03 PT |
71 | { |
72 | sfw_session_t *sn = tsi->tsi_batch->bat_session; | |
73 | int flags; | |
74 | int npg; | |
75 | int len; | |
76 | int opc; | |
77 | srpc_bulk_t *bulk; | |
78 | sfw_test_unit_t *tsu; | |
79 | ||
80 | LASSERT(sn != NULL); | |
81 | LASSERT(tsi->tsi_is_client); | |
82 | ||
83 | if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { | |
84 | test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; | |
85 | ||
86 | opc = breq->blk_opc; | |
87 | flags = breq->blk_flags; | |
88 | npg = breq->blk_npg; | |
89 | /* NB: this is not going to work for variable page size, | |
90 | * but we have to keep it for compatibility */ | |
91 | len = npg * PAGE_CACHE_SIZE; | |
92 | ||
93 | } else { | |
74d68011 | 94 | test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; |
d7e09d03 PT |
95 | |
96 | /* I should never get this step if it's unknown feature | |
97 | * because make_session will reject unknown feature */ | |
98 | LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); | |
99 | ||
100 | opc = breq->blk_opc; | |
101 | flags = breq->blk_flags; | |
102 | len = breq->blk_len; | |
103 | npg = (len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
104 | } | |
105 | ||
106 | if (npg > LNET_MAX_IOV || npg <= 0) | |
107 | return -EINVAL; | |
108 | ||
109 | if (opc != LST_BRW_READ && opc != LST_BRW_WRITE) | |
110 | return -EINVAL; | |
111 | ||
112 | if (flags != LST_BRW_CHECK_NONE && | |
113 | flags != LST_BRW_CHECK_FULL && flags != LST_BRW_CHECK_SIMPLE) | |
114 | return -EINVAL; | |
115 | ||
116 | list_for_each_entry(tsu, &tsi->tsi_units, tsu_list) { | |
117 | bulk = srpc_alloc_bulk(lnet_cpt_of_nid(tsu->tsu_dest.nid), | |
118 | npg, len, opc == LST_BRW_READ); | |
119 | if (bulk == NULL) { | |
120 | brw_client_fini(tsi); | |
121 | return -ENOMEM; | |
122 | } | |
123 | ||
124 | tsu->tsu_private = bulk; | |
125 | } | |
126 | ||
127 | return 0; | |
128 | } | |
129 | ||
130 | #define BRW_POISON 0xbeefbeefbeefbeefULL | |
131 | #define BRW_MAGIC 0xeeb0eeb1eeb2eeb3ULL | |
132 | #define BRW_MSIZE sizeof(__u64) | |
133 | ||
d4b2d88a | 134 | static int |
5f849bb0 | 135 | brw_inject_one_error(void) |
d7e09d03 | 136 | { |
d9f79e6b | 137 | struct timespec64 ts; |
d7e09d03 | 138 | |
5252bbfd LN |
139 | if (brw_inject_errors <= 0) |
140 | return 0; | |
d7e09d03 | 141 | |
d9f79e6b | 142 | ktime_get_ts64(&ts); |
d7e09d03 | 143 | |
d9f79e6b | 144 | if (((ts.tv_nsec / NSEC_PER_USEC) & 1) == 0) |
5252bbfd | 145 | return 0; |
d7e09d03 PT |
146 | |
147 | return brw_inject_errors--; | |
148 | } | |
149 | ||
2e3e133d | 150 | static void |
5f849bb0 | 151 | brw_fill_page(struct page *pg, int pattern, __u64 magic) |
d7e09d03 PT |
152 | { |
153 | char *addr = page_address(pg); | |
154 | int i; | |
155 | ||
5f849bb0 | 156 | LASSERT(addr != NULL); |
d7e09d03 | 157 | |
5252bbfd LN |
158 | if (pattern == LST_BRW_CHECK_NONE) |
159 | return; | |
d7e09d03 PT |
160 | |
161 | if (magic == BRW_MAGIC) | |
162 | magic += brw_inject_one_error(); | |
163 | ||
164 | if (pattern == LST_BRW_CHECK_SIMPLE) { | |
165 | memcpy(addr, &magic, BRW_MSIZE); | |
166 | addr += PAGE_CACHE_SIZE - BRW_MSIZE; | |
167 | memcpy(addr, &magic, BRW_MSIZE); | |
168 | return; | |
169 | } | |
170 | ||
171 | if (pattern == LST_BRW_CHECK_FULL) { | |
172 | for (i = 0; i < PAGE_CACHE_SIZE / BRW_MSIZE; i++) | |
173 | memcpy(addr + i * BRW_MSIZE, &magic, BRW_MSIZE); | |
174 | return; | |
175 | } | |
176 | ||
5f849bb0 | 177 | LBUG(); |
d7e09d03 PT |
178 | } |
179 | ||
43311238 | 180 | static int |
5f849bb0 | 181 | brw_check_page(struct page *pg, int pattern, __u64 magic) |
d7e09d03 PT |
182 | { |
183 | char *addr = page_address(pg); | |
184 | __u64 data = 0; /* make compiler happy */ | |
185 | int i; | |
186 | ||
5f849bb0 | 187 | LASSERT(addr != NULL); |
d7e09d03 PT |
188 | |
189 | if (pattern == LST_BRW_CHECK_NONE) | |
190 | return 0; | |
191 | ||
192 | if (pattern == LST_BRW_CHECK_SIMPLE) { | |
193 | data = *((__u64 *) addr); | |
5252bbfd LN |
194 | if (data != magic) |
195 | goto bad_data; | |
d7e09d03 PT |
196 | |
197 | addr += PAGE_CACHE_SIZE - BRW_MSIZE; | |
198 | data = *((__u64 *) addr); | |
5252bbfd LN |
199 | if (data != magic) |
200 | goto bad_data; | |
d7e09d03 PT |
201 | |
202 | return 0; | |
203 | } | |
204 | ||
205 | if (pattern == LST_BRW_CHECK_FULL) { | |
206 | for (i = 0; i < PAGE_CACHE_SIZE / BRW_MSIZE; i++) { | |
207 | data = *(((__u64 *) addr) + i); | |
5252bbfd LN |
208 | if (data != magic) |
209 | goto bad_data; | |
d7e09d03 PT |
210 | } |
211 | ||
212 | return 0; | |
213 | } | |
214 | ||
5f849bb0 | 215 | LBUG(); |
d7e09d03 PT |
216 | |
217 | bad_data: | |
55f5a824 | 218 | CERROR("Bad data in page %p: %#llx, %#llx expected\n", |
d7e09d03 PT |
219 | pg, data, magic); |
220 | return 1; | |
221 | } | |
222 | ||
56e1ccac | 223 | static void |
5f849bb0 | 224 | brw_fill_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) |
d7e09d03 | 225 | { |
74d68011 | 226 | int i; |
d7e09d03 PT |
227 | struct page *pg; |
228 | ||
229 | for (i = 0; i < bk->bk_niov; i++) { | |
230 | pg = bk->bk_iovs[i].kiov_page; | |
231 | brw_fill_page(pg, pattern, magic); | |
232 | } | |
233 | } | |
234 | ||
ec17e811 | 235 | static int |
5f849bb0 | 236 | brw_check_bulk(srpc_bulk_t *bk, int pattern, __u64 magic) |
d7e09d03 | 237 | { |
74d68011 | 238 | int i; |
d7e09d03 PT |
239 | struct page *pg; |
240 | ||
241 | for (i = 0; i < bk->bk_niov; i++) { | |
242 | pg = bk->bk_iovs[i].kiov_page; | |
243 | if (brw_check_page(pg, pattern, magic) != 0) { | |
5f849bb0 | 244 | CERROR("Bulk page %p (%d/%d) is corrupted!\n", |
d7e09d03 PT |
245 | pg, i, bk->bk_niov); |
246 | return 1; | |
247 | } | |
248 | } | |
249 | ||
250 | return 0; | |
251 | } | |
252 | ||
253 | static int | |
5f849bb0 | 254 | brw_client_prep_rpc(sfw_test_unit_t *tsu, |
d7e09d03 PT |
255 | lnet_process_id_t dest, srpc_client_rpc_t **rpcpp) |
256 | { | |
74d68011 | 257 | srpc_bulk_t *bulk = tsu->tsu_private; |
d7e09d03 | 258 | sfw_test_instance_t *tsi = tsu->tsu_instance; |
74d68011 MS |
259 | sfw_session_t *sn = tsi->tsi_batch->bat_session; |
260 | srpc_client_rpc_t *rpc; | |
261 | srpc_brw_reqst_t *req; | |
262 | int flags; | |
263 | int npg; | |
264 | int len; | |
265 | int opc; | |
266 | int rc; | |
d7e09d03 PT |
267 | |
268 | LASSERT(sn != NULL); | |
269 | LASSERT(bulk != NULL); | |
270 | ||
271 | if ((sn->sn_features & LST_FEAT_BULK_LEN) == 0) { | |
272 | test_bulk_req_t *breq = &tsi->tsi_u.bulk_v0; | |
273 | ||
274 | opc = breq->blk_opc; | |
275 | flags = breq->blk_flags; | |
276 | npg = breq->blk_npg; | |
277 | len = npg * PAGE_CACHE_SIZE; | |
278 | ||
279 | } else { | |
74d68011 | 280 | test_bulk_req_v1_t *breq = &tsi->tsi_u.bulk_v1; |
d7e09d03 PT |
281 | |
282 | /* I should never get this step if it's unknown feature | |
283 | * because make_session will reject unknown feature */ | |
284 | LASSERT((sn->sn_features & ~LST_FEATS_MASK) == 0); | |
285 | ||
286 | opc = breq->blk_opc; | |
287 | flags = breq->blk_flags; | |
288 | len = breq->blk_len; | |
289 | npg = (len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
290 | } | |
291 | ||
292 | rc = sfw_create_test_rpc(tsu, dest, sn->sn_features, npg, len, &rpc); | |
293 | if (rc != 0) | |
294 | return rc; | |
295 | ||
296 | memcpy(&rpc->crpc_bulk, bulk, offsetof(srpc_bulk_t, bk_iovs[npg])); | |
297 | if (opc == LST_BRW_WRITE) | |
298 | brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_MAGIC); | |
299 | else | |
300 | brw_fill_bulk(&rpc->crpc_bulk, flags, BRW_POISON); | |
301 | ||
302 | req = &rpc->crpc_reqstmsg.msg_body.brw_reqst; | |
303 | req->brw_flags = flags; | |
304 | req->brw_rw = opc; | |
305 | req->brw_len = len; | |
306 | ||
307 | *rpcpp = rpc; | |
308 | return 0; | |
309 | } | |
310 | ||
311 | static void | |
5f849bb0 | 312 | brw_client_done_rpc(sfw_test_unit_t *tsu, srpc_client_rpc_t *rpc) |
d7e09d03 | 313 | { |
74d68011 | 314 | __u64 magic = BRW_MAGIC; |
d7e09d03 | 315 | sfw_test_instance_t *tsi = tsu->tsu_instance; |
74d68011 MS |
316 | sfw_session_t *sn = tsi->tsi_batch->bat_session; |
317 | srpc_msg_t *msg = &rpc->crpc_replymsg; | |
318 | srpc_brw_reply_t *reply = &msg->msg_body.brw_reply; | |
319 | srpc_brw_reqst_t *reqst = &rpc->crpc_reqstmsg.msg_body.brw_reqst; | |
d7e09d03 | 320 | |
5f849bb0 | 321 | LASSERT(sn != NULL); |
d7e09d03 PT |
322 | |
323 | if (rpc->crpc_status != 0) { | |
5f849bb0 | 324 | CERROR("BRW RPC to %s failed with %d\n", |
d7e09d03 PT |
325 | libcfs_id2str(rpc->crpc_dest), rpc->crpc_status); |
326 | if (!tsi->tsi_stopping) /* rpc could have been aborted */ | |
327 | atomic_inc(&sn->sn_brw_errors); | |
328 | goto out; | |
329 | } | |
330 | ||
331 | if (msg->msg_magic != SRPC_MSG_MAGIC) { | |
332 | __swab64s(&magic); | |
333 | __swab32s(&reply->brw_status); | |
334 | } | |
335 | ||
5f849bb0 | 336 | CDEBUG(reply->brw_status ? D_WARNING : D_NET, |
d7e09d03 PT |
337 | "BRW RPC to %s finished with brw_status: %d\n", |
338 | libcfs_id2str(rpc->crpc_dest), reply->brw_status); | |
339 | ||
340 | if (reply->brw_status != 0) { | |
341 | atomic_inc(&sn->sn_brw_errors); | |
342 | rpc->crpc_status = -(int)reply->brw_status; | |
343 | goto out; | |
344 | } | |
345 | ||
5252bbfd LN |
346 | if (reqst->brw_rw == LST_BRW_WRITE) |
347 | goto out; | |
d7e09d03 PT |
348 | |
349 | if (brw_check_bulk(&rpc->crpc_bulk, reqst->brw_flags, magic) != 0) { | |
5f849bb0 | 350 | CERROR("Bulk data from %s is corrupted!\n", |
d7e09d03 PT |
351 | libcfs_id2str(rpc->crpc_dest)); |
352 | atomic_inc(&sn->sn_brw_errors); | |
353 | rpc->crpc_status = -EBADMSG; | |
354 | } | |
355 | ||
356 | out: | |
357 | return; | |
358 | } | |
359 | ||
6888871c | 360 | static void |
5f849bb0 | 361 | brw_server_rpc_done(srpc_server_rpc_t *rpc) |
d7e09d03 PT |
362 | { |
363 | srpc_bulk_t *blk = rpc->srpc_bulk; | |
364 | ||
5252bbfd LN |
365 | if (blk == NULL) |
366 | return; | |
d7e09d03 PT |
367 | |
368 | if (rpc->srpc_status != 0) | |
5f849bb0 | 369 | CERROR("Bulk transfer %s %s has failed: %d\n", |
d7e09d03 PT |
370 | blk->bk_sink ? "from" : "to", |
371 | libcfs_id2str(rpc->srpc_peer), rpc->srpc_status); | |
372 | else | |
5f849bb0 | 373 | CDEBUG(D_NET, "Transferred %d pages bulk data %s %s\n", |
d7e09d03 PT |
374 | blk->bk_niov, blk->bk_sink ? "from" : "to", |
375 | libcfs_id2str(rpc->srpc_peer)); | |
376 | ||
377 | sfw_free_pages(rpc); | |
378 | } | |
379 | ||
0c05ef92 | 380 | static int |
5f849bb0 | 381 | brw_bulk_ready(srpc_server_rpc_t *rpc, int status) |
d7e09d03 | 382 | { |
74d68011 | 383 | __u64 magic = BRW_MAGIC; |
d7e09d03 PT |
384 | srpc_brw_reply_t *reply = &rpc->srpc_replymsg.msg_body.brw_reply; |
385 | srpc_brw_reqst_t *reqst; | |
74d68011 | 386 | srpc_msg_t *reqstmsg; |
d7e09d03 | 387 | |
5f849bb0 LN |
388 | LASSERT(rpc->srpc_bulk != NULL); |
389 | LASSERT(rpc->srpc_reqstbuf != NULL); | |
d7e09d03 PT |
390 | |
391 | reqstmsg = &rpc->srpc_reqstbuf->buf_msg; | |
392 | reqst = &reqstmsg->msg_body.brw_reqst; | |
393 | ||
394 | if (status != 0) { | |
5f849bb0 | 395 | CERROR("BRW bulk %s failed for RPC from %s: %d\n", |
d7e09d03 PT |
396 | reqst->brw_rw == LST_BRW_READ ? "READ" : "WRITE", |
397 | libcfs_id2str(rpc->srpc_peer), status); | |
398 | return -EIO; | |
399 | } | |
400 | ||
401 | if (reqst->brw_rw == LST_BRW_READ) | |
402 | return 0; | |
403 | ||
404 | if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) | |
405 | __swab64s(&magic); | |
406 | ||
407 | if (brw_check_bulk(rpc->srpc_bulk, reqst->brw_flags, magic) != 0) { | |
5f849bb0 | 408 | CERROR("Bulk data from %s is corrupted!\n", |
d7e09d03 PT |
409 | libcfs_id2str(rpc->srpc_peer)); |
410 | reply->brw_status = EBADMSG; | |
411 | } | |
412 | ||
413 | return 0; | |
414 | } | |
415 | ||
4a1b86dc | 416 | static int |
d7e09d03 PT |
417 | brw_server_handle(struct srpc_server_rpc *rpc) |
418 | { | |
74d68011 MS |
419 | struct srpc_service *sv = rpc->srpc_scd->scd_svc; |
420 | srpc_msg_t *replymsg = &rpc->srpc_replymsg; | |
421 | srpc_msg_t *reqstmsg = &rpc->srpc_reqstbuf->buf_msg; | |
d7e09d03 PT |
422 | srpc_brw_reply_t *reply = &replymsg->msg_body.brw_reply; |
423 | srpc_brw_reqst_t *reqst = &reqstmsg->msg_body.brw_reqst; | |
74d68011 MS |
424 | int npg; |
425 | int rc; | |
d7e09d03 | 426 | |
5f849bb0 | 427 | LASSERT(sv->sv_id == SRPC_SERVICE_BRW); |
d7e09d03 PT |
428 | |
429 | if (reqstmsg->msg_magic != SRPC_MSG_MAGIC) { | |
5f849bb0 | 430 | LASSERT(reqstmsg->msg_magic == __swab32(SRPC_MSG_MAGIC)); |
d7e09d03 PT |
431 | |
432 | __swab32s(&reqst->brw_rw); | |
433 | __swab32s(&reqst->brw_len); | |
434 | __swab32s(&reqst->brw_flags); | |
435 | __swab64s(&reqst->brw_rpyid); | |
436 | __swab64s(&reqst->brw_bulkid); | |
437 | } | |
5f849bb0 | 438 | LASSERT(reqstmsg->msg_type == (__u32)srpc_service2request(sv->sv_id)); |
d7e09d03 PT |
439 | |
440 | reply->brw_status = 0; | |
441 | rpc->srpc_done = brw_server_rpc_done; | |
442 | ||
443 | if ((reqst->brw_rw != LST_BRW_READ && reqst->brw_rw != LST_BRW_WRITE) || | |
444 | (reqst->brw_flags != LST_BRW_CHECK_NONE && | |
445 | reqst->brw_flags != LST_BRW_CHECK_FULL && | |
446 | reqst->brw_flags != LST_BRW_CHECK_SIMPLE)) { | |
447 | reply->brw_status = EINVAL; | |
448 | return 0; | |
449 | } | |
450 | ||
451 | if ((reqstmsg->msg_ses_feats & ~LST_FEATS_MASK) != 0) { | |
452 | replymsg->msg_ses_feats = LST_FEATS_MASK; | |
453 | reply->brw_status = EPROTO; | |
454 | return 0; | |
455 | } | |
456 | ||
457 | if ((reqstmsg->msg_ses_feats & LST_FEAT_BULK_LEN) == 0) { | |
458 | /* compat with old version */ | |
459 | if ((reqst->brw_len & ~CFS_PAGE_MASK) != 0) { | |
460 | reply->brw_status = EINVAL; | |
461 | return 0; | |
462 | } | |
463 | npg = reqst->brw_len >> PAGE_CACHE_SHIFT; | |
464 | ||
465 | } else { | |
466 | npg = (reqst->brw_len + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | |
467 | } | |
468 | ||
469 | replymsg->msg_ses_feats = reqstmsg->msg_ses_feats; | |
470 | ||
471 | if (reqst->brw_len == 0 || npg > LNET_MAX_IOV) { | |
472 | reply->brw_status = EINVAL; | |
473 | return 0; | |
474 | } | |
475 | ||
476 | rc = sfw_alloc_pages(rpc, rpc->srpc_scd->scd_cpt, npg, | |
477 | reqst->brw_len, | |
478 | reqst->brw_rw == LST_BRW_WRITE); | |
479 | if (rc != 0) | |
480 | return rc; | |
481 | ||
482 | if (reqst->brw_rw == LST_BRW_READ) | |
483 | brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_MAGIC); | |
484 | else | |
485 | brw_fill_bulk(rpc->srpc_bulk, reqst->brw_flags, BRW_POISON); | |
486 | ||
487 | return 0; | |
488 | } | |
489 | ||
490 | sfw_test_client_ops_t brw_test_client; | |
491 | void brw_init_test_client(void) | |
492 | { | |
74d68011 MS |
493 | brw_test_client.tso_init = brw_client_init; |
494 | brw_test_client.tso_fini = brw_client_fini; | |
495 | brw_test_client.tso_prep_rpc = brw_client_prep_rpc; | |
496 | brw_test_client.tso_done_rpc = brw_client_done_rpc; | |
d7e09d03 PT |
497 | }; |
498 | ||
499 | srpc_service_t brw_test_service; | |
500 | void brw_init_test_service(void) | |
501 | { | |
502 | ||
74d68011 | 503 | brw_test_service.sv_id = SRPC_SERVICE_BRW; |
d7e09d03 PT |
504 | brw_test_service.sv_name = "brw_test"; |
505 | brw_test_service.sv_handler = brw_server_handle; | |
506 | brw_test_service.sv_bulk_ready = brw_bulk_ready; | |
507 | brw_test_service.sv_wi_total = brw_srv_workitems; | |
508 | } |