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");
99 if (segdev->segment) {
100 XSEGLOG("destroying existing segdev segment");
101 r = segdev_destroy_segment(segdev);
106 XSEGLOG("creating segdev segment size %llu", size);
107 r = segdev_create_segment(segdev, size, 1);
117 static long segdev_deallocate(const char *name)
119 struct segdev *segdev = segdev_get(0);
120 int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
124 clear_bit(SEGDEV_RESERVED, &segdev->flags);
125 XSEGLOG("destroying segment");
126 r = segdev_destroy_segment(segdev);
128 XSEGLOG(" ...failed");
133 static void *segdev_map(const char *name, uint64_t size, struct xseg *seg)
135 struct xseg *xseg = NULL;
136 /* map() holds a reference to the segment */
137 struct segdev *dev = segdev_get(0);
138 struct segpriv *priv;
140 r = IS_ERR(dev) ? PTR_ERR(dev) : 0;
147 if (size > dev->segsize)
151 if (priv->segno >= nr_xsegments)
155 // xsegments[priv->segno] = seg;
157 xseg = (void *)dev->segment;
162 static void segdev_unmap(void *ptr, uint64_t size)
164 struct segdev *segdev = segdev_get(0);
165 struct segpriv *priv;
166 int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
171 if (priv->segno >= nr_xsegments)
174 // xsegments[priv->segno] = NULL;
177 /* unmap() releases the reference taken by map() */
183 static void segdev_callback(struct segdev *dev, xport portno)
186 struct segpriv *priv = dev->priv;
187 struct xseg_private *xpriv;
188 struct xseg_port *port;
189 struct segdev_signal_desc *ssd;
191 xseg = xsegments[portno];
194 if (priv->segno >= nr_xsegments)
198 port = xseg_get_port(xseg, portno);
201 ssd = xseg_get_signal_desc(xseg, port);
202 if (!ssd || !ssd->waitcue){
207 xpriv->wakeup(portno);
212 static struct xseg_type xseg_segdev = {
213 /* xseg operations */
215 .allocate = segdev_allocate,
216 .deallocate = segdev_deallocate,
218 .unmap = segdev_unmap
224 static int segdev_remote_signal_init(void)
229 static void segdev_remote_signal_quit(void)
234 static int segdev_local_signal_init(struct xseg *xseg, xport portno)
236 //assert xsegments[portno] == NULL;
237 xsegments[portno] = xseg;
240 static void segdev_local_signal_quit(struct xseg *xseg, xport portno)
242 //assert xsegments[portno] == xseg;
243 xsegments[portno] = NULL;
247 static int segdev_prepare_wait(struct xseg *xseg, uint32_t portno)
249 struct segdev_signal_desc *ssd;
250 struct xseg_port *port = xseg_get_port(xseg, portno);
253 ssd = xseg_get_signal_desc(xseg, port);
256 /* true/false value */
261 static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
263 struct segdev_signal_desc *ssd;
264 struct xseg_port *port = xseg_get_port(xseg, portno);
267 ssd = xseg_get_signal_desc(xseg, port);
270 /* true/false value */
275 static int segdev_wait_signal(struct xseg *xseg, uint32_t timeout)
280 static int segdev_signal(struct xseg *xseg, uint32_t portno)
285 static int segdev_init_signal_desc(struct xseg *xseg, void *sd)
287 struct segdev_signal_desc *ssd = sd;
294 static void segdev_quit_signal_desc(struct xseg *xseg, void *sd)
299 static void *segdev_alloc_data(struct xseg *xseg)
301 struct xobject_h *sd_h = xseg_get_objh(xseg, MAGIC_SEGDEV_SD,
302 sizeof(struct segdev_signal_desc));
306 static void segdev_free_data(struct xseg *xseg, void *data)
309 xseg_put_objh(xseg, (struct xobject_h *)data);
312 static void *segdev_alloc_signal_desc(struct xseg *xseg, void *data)
314 struct xobject_h *sd_h = (struct xobject_h *) data;
317 struct segdev_signal_desc *ssd = xobj_get_obj(sd_h, X_ALLOC);
324 static void segdev_free_signal_desc(struct xseg *xseg, void *data, void *sd)
326 struct xobject_h *sd_h = (struct xobject_h *) data;
330 xobj_put_obj(sd_h, sd);
334 static struct xseg_peer xseg_peer_segdev = {
335 /* xseg signal operations */
337 .init_signal_desc = segdev_init_signal_desc,
338 .quit_signal_desc = segdev_quit_signal_desc,
339 .alloc_data = segdev_alloc_data,
340 .free_data = segdev_free_data,
341 .alloc_signal_desc = segdev_alloc_signal_desc,
342 .free_signal_desc = segdev_free_signal_desc,
343 .local_signal_init = segdev_local_signal_init,
344 .local_signal_quit = segdev_local_signal_quit,
345 .remote_signal_init = segdev_remote_signal_init,
346 .remote_signal_quit = segdev_remote_signal_quit,
347 .cancel_wait = segdev_cancel_wait,
348 .prepare_wait = segdev_prepare_wait,
349 .wait_signal = segdev_wait_signal,
350 .signal = segdev_signal,
351 .malloc = segdev_malloc,
352 .realloc = segdev_realloc,
353 .mfree = segdev_mfree
360 /* ************************* */
361 /* ** XSEG Initialization ** */
362 /* ************************* */
364 static int segdev_init(void)
366 struct segdev *segdev;
367 struct segpriv *segpriv;
370 XSEGLOG("registering xseg types");
371 r = xseg_register_type(&xseg_segdev);
375 r = xseg_register_peer(&xseg_peer_segdev);
379 segdev = segdev_get(0);
380 r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
385 segpriv = kmalloc(sizeof(struct segpriv), GFP_KERNEL);
390 segdev->callback = segdev_callback;
391 segdev->priv = segpriv;
398 xseg_unregister_peer(xseg_peer_segdev.name);
400 xseg_unregister_type(xseg_segdev.name);
405 static int segdev_quit(void)
407 struct segdev *segdev = segdev_get(0);
408 int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
410 /* make sure to unmap the segment first */
411 clear_bit(SEGDEV_RESERVED, &segdev->flags);
412 segdev->callback = NULL;
413 //FIXME what aboud segdev->priv?
416 xseg_unregister_peer(xseg_peer_segdev.name);
417 xseg_unregister_type(xseg_segdev.name);
422 /* *************************** */
423 /* ** Module Initialization ** */
424 /* *************************** */
426 static int __init xseg_segdev_init(void)
434 XSEGLOG("initialization complete");
439 static void __exit xseg_segdev_exit(void)
444 module_init(xseg_segdev_init);
445 module_exit(xseg_segdev_exit);