2 * Copyright 2012 GRNET S.A. All rights reserved.
4 * Redistribution and use in source and binary forms, with or
5 * without modification, are permitted provided that the following
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and
30 * documentation are those of the authors and should not be
31 * interpreted as representing official policies, either expressed
32 * or implied, of GRNET S.A.
39 #include <linux/module.h>
40 #include <linux/moduleparam.h>
41 #include <linux/init.h>
42 #include <linux/sched.h>
43 #include <linux/kernel.h>
44 #include <linux/slab.h>
46 #include <linux/errno.h>
47 #include <linux/timer.h>
48 #include <linux/types.h>
49 #include <linux/vmalloc.h>
50 #include <linux/genhd.h>
51 #include <linux/blkdev.h>
52 #include <linux/bio.h>
53 #include <linux/device.h>
54 #include <linux/completion.h>
56 #include <xseg/xseg.h>
57 #include <sys/kernel/segdev.h>
59 #include <drivers/xseg_segdev.h>
60 #include <peers/kernel/xsegbd.h>
61 MODULE_DESCRIPTION("xseg_segdev");
62 MODULE_AUTHOR("XSEG");
63 MODULE_LICENSE("BSD");
66 static struct xseg *xsegments[65536];
67 static unsigned int nr_xsegments = 1;
73 static void *segdev_malloc(uint64_t size)
75 return kmalloc((size_t)size, GFP_KERNEL);
78 static void *segdev_realloc(void *mem, uint64_t size)
80 return krealloc(mem, (size_t)size, GFP_KERNEL);
83 static void segdev_mfree(void *ptr)
88 static long segdev_allocate(const char *name, uint64_t size)
91 struct segdev *segdev = segdev_get(0);
93 r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
95 XSEGLOG("cannot acquire segdev");
100 if (segdev->segment) {
101 XSEGLOG("destroying existing segdev segment");
102 r = segdev_destroy_segment(segdev);
108 XSEGLOG("creating segdev segment size %llu", size);
109 r = segdev_create_segment(segdev, size, 1);
119 static long segdev_deallocate(const char *name)
121 struct segdev *segdev = segdev_get(0);
122 int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
126 clear_bit(SEGDEV_RESERVED, &segdev->flags);
127 XSEGLOG("destroying segment");
128 r = segdev_destroy_segment(segdev);
130 XSEGLOG(" ...failed");
135 static void *segdev_map(const char *name, uint64_t size, struct xseg *seg)
137 struct xseg *xseg = NULL;
138 /* map() holds a reference to the segment */
139 struct segdev *dev = segdev_get(0);
140 struct segpriv *priv;
142 r = IS_ERR(dev) ? PTR_ERR(dev) : 0;
149 if (size > dev->segsize)
153 if (priv->segno >= nr_xsegments)
157 // xsegments[priv->segno] = seg;
159 xseg = (void *)dev->segment;
164 static void segdev_unmap(void *ptr, uint64_t size)
166 struct segdev *segdev = segdev_get(0);
167 struct segpriv *priv;
168 int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
173 if (priv->segno >= nr_xsegments)
176 // xsegments[priv->segno] = NULL;
179 /* unmap() releases the reference taken by map() */
185 static void segdev_callback(struct segdev *dev, xport portno)
188 struct segpriv *priv = dev->priv;
189 struct xseg_private *xpriv;
190 struct xseg_port *port;
191 struct segdev_signal_desc *ssd;
193 xseg = xsegments[portno];
196 if (priv->segno >= nr_xsegments)
200 port = xseg_get_port(xseg, portno);
203 ssd = xseg_get_signal_desc(xseg, port);
204 if (!ssd || !ssd->waitcue){
209 xpriv->wakeup(portno);
214 static struct xseg_type xseg_segdev = {
215 /* xseg operations */
217 .allocate = segdev_allocate,
218 .deallocate = segdev_deallocate,
220 .unmap = segdev_unmap
226 static int segdev_remote_signal_init(void)
231 static void segdev_remote_signal_quit(void)
236 static int segdev_local_signal_init(struct xseg *xseg, xport portno)
238 //assert xsegments[portno] == NULL;
239 xsegments[portno] = xseg;
243 static void segdev_local_signal_quit(struct xseg *xseg, xport portno)
245 //assert xsegments[portno] == xseg;
246 xsegments[portno] = NULL;
250 static int segdev_prepare_wait(struct xseg *xseg, uint32_t portno)
252 struct segdev_signal_desc *ssd;
253 struct xseg_port *port = xseg_get_port(xseg, portno);
256 ssd = xseg_get_signal_desc(xseg, port);
259 /* true/false value */
264 static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
266 struct segdev_signal_desc *ssd;
267 struct xseg_port *port = xseg_get_port(xseg, portno);
270 ssd = xseg_get_signal_desc(xseg, port);
273 /* true/false value */
278 static int segdev_wait_signal(struct xseg *xseg, uint32_t timeout)
283 static int segdev_signal(struct xseg *xseg, uint32_t portno)
288 static int segdev_init_signal_desc(struct xseg *xseg, void *sd)
290 struct segdev_signal_desc *ssd = sd;
297 static void segdev_quit_signal_desc(struct xseg *xseg, void *sd)
302 static void *segdev_alloc_data(struct xseg *xseg)
304 struct xobject_h *sd_h = xseg_get_objh(xseg, MAGIC_SEGDEV_SD,
305 sizeof(struct segdev_signal_desc));
309 static void segdev_free_data(struct xseg *xseg, void *data)
312 xseg_put_objh(xseg, (struct xobject_h *)data);
315 static void *segdev_alloc_signal_desc(struct xseg *xseg, void *data)
317 struct segdev_signal_desc *ssd;
318 struct xobject_h *sd_h = (struct xobject_h *) data;
321 ssd = xobj_get_obj(sd_h, X_ALLOC);
328 static void segdev_free_signal_desc(struct xseg *xseg, void *data, void *sd)
330 struct xobject_h *sd_h = (struct xobject_h *) data;
334 xobj_put_obj(sd_h, sd);
338 static struct xseg_peer xseg_peer_segdev = {
339 /* xseg signal operations */
341 .init_signal_desc = segdev_init_signal_desc,
342 .quit_signal_desc = segdev_quit_signal_desc,
343 .alloc_data = segdev_alloc_data,
344 .free_data = segdev_free_data,
345 .alloc_signal_desc = segdev_alloc_signal_desc,
346 .free_signal_desc = segdev_free_signal_desc,
347 .local_signal_init = segdev_local_signal_init,
348 .local_signal_quit = segdev_local_signal_quit,
349 .remote_signal_init = segdev_remote_signal_init,
350 .remote_signal_quit = segdev_remote_signal_quit,
351 .cancel_wait = segdev_cancel_wait,
352 .prepare_wait = segdev_prepare_wait,
353 .wait_signal = segdev_wait_signal,
354 .signal = segdev_signal,
355 .malloc = segdev_malloc,
356 .realloc = segdev_realloc,
357 .mfree = segdev_mfree
364 /* ************************* */
365 /* ** XSEG Initialization ** */
366 /* ************************* */
368 static int segdev_init(void)
370 struct segdev *segdev;
371 struct segpriv *segpriv;
374 XSEGLOG("registering xseg types");
375 r = xseg_register_type(&xseg_segdev);
379 r = xseg_register_peer(&xseg_peer_segdev);
383 segdev = segdev_get(0);
384 r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
389 segpriv = kmalloc(sizeof(struct segpriv), GFP_KERNEL);
394 segdev->callback = segdev_callback;
395 segdev->priv = segpriv;
402 xseg_unregister_peer(xseg_peer_segdev.name);
404 xseg_unregister_type(xseg_segdev.name);
409 static int segdev_quit(void)
411 struct segdev *segdev = segdev_get(0);
412 int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
414 /* make sure to unmap the segment first */
415 clear_bit(SEGDEV_RESERVED, &segdev->flags);
416 segdev->callback = NULL;
417 //FIXME what aboud segdev->priv?
420 xseg_unregister_peer(xseg_peer_segdev.name);
421 xseg_unregister_type(xseg_segdev.name);
426 /* *************************** */
427 /* ** Module Initialization ** */
428 /* *************************** */
430 static int __init xseg_segdev_init(void)
438 XSEGLOG("initialization complete");
443 static void __exit xseg_segdev_exit(void)
448 module_init(xseg_segdev_init);
449 module_exit(xseg_segdev_exit);