Statistics
| Branch: | Revision:

root / xseg / drivers / kernel / xseg_segdev.c @ 7b4f31ea

History | View | Annotate | Download (9.5 kB)

1
/*
2
 * Copyright 2012 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
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.
15
 *
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.
28
 *
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.
33
 */
34

    
35
/* xseg_segdev.c
36
 *
37
 */
38

    
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>
45
#include <linux/fs.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>
55

    
56
#include <xseg/xseg.h>
57
#include <sys/kernel/segdev.h>
58
#include <sys/util.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");
64

    
65
/* FIXME */
66
static struct xseg *xsegments[65536];
67
static unsigned int nr_xsegments = 1;
68

    
69
struct segpriv {
70
        unsigned int segno;
71
};
72

    
73
static void *segdev_malloc(uint64_t size)
74
{
75
        return kmalloc((size_t)size, GFP_KERNEL);
76
}
77

    
78
static void *segdev_realloc(void *mem, uint64_t size)
79
{
80
        return krealloc(mem, (size_t)size, GFP_KERNEL);
81
}
82

    
83
static void segdev_mfree(void *ptr)
84
{
85
        return kfree(ptr);
86
}
87

    
88
static long segdev_allocate(const char *name, uint64_t size)
89
{
90
        int r;
91
        struct segdev *segdev = segdev_get(0);
92

    
93
        r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
94
        if (r) {
95
                XSEGLOG("cannot acquire segdev");
96
                goto out;
97
        }
98

    
99
        /*
100
        if (segdev->segment) {
101
                XSEGLOG("destroying existing segdev segment");
102
                r = segdev_destroy_segment(segdev);
103
                if (r)
104
                        goto out;
105
        }
106
        */
107

    
108
        XSEGLOG("creating segdev segment size %llu", size);
109
        r = segdev_create_segment(segdev, size, 1);
110
        if (r)
111
                goto out;
112

    
113
        segdev_put(segdev);
114
        r = 0;
115
out:
116
        return r;
117
}
118

    
119
static long segdev_deallocate(const char *name)
120
{
121
        struct segdev *segdev = segdev_get(0);
122
        int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
123
        if (r)
124
                return r;
125

    
126
        clear_bit(SEGDEV_RESERVED, &segdev->flags);
127
        XSEGLOG("destroying segment");
128
        r = segdev_destroy_segment(segdev);
129
        if (r)
130
                XSEGLOG("   ...failed");
131
        segdev_put(segdev);
132
        return r;
133
}
134

    
135
static void *segdev_map(const char *name, uint64_t size, struct xseg *seg)
136
{
137
        struct xseg *xseg = NULL;
138
        /* map() holds a reference to the segment */
139
        struct segdev *dev = segdev_get(0);
140
        struct segpriv *priv;
141
        int r;
142
        r = IS_ERR(dev) ? PTR_ERR(dev) : 0;
143
        if (r)
144
                goto out;
145

    
146
        if (!dev->segment)
147
                goto out;
148

    
149
        if (size > dev->segsize)
150
                goto out;
151

    
152
        priv = dev->priv;
153
        if (priv->segno >= nr_xsegments)
154
                goto out;
155

    
156
//        if (seg)
157
//                xsegments[priv->segno] = seg;
158

    
159
        xseg = (void *)dev->segment;
160
out:
161
        return xseg;
162
}
163

    
164
static void segdev_unmap(void *ptr, uint64_t size)
165
{
166
        struct segdev *segdev = segdev_get(0);
167
        struct segpriv *priv;
168
        int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
169
        if (r)
170
                return;
171

    
172
        priv = segdev->priv;
173
        if (priv->segno >= nr_xsegments)
174
                goto out;
175

    
176
//        xsegments[priv->segno] = NULL;
177

    
178
out:
179
        /* unmap() releases the reference taken by map() */
180
        segdev_put(segdev);
181

    
182
        segdev_put(segdev);
183
}
184

    
185
static void segdev_callback(struct segdev *dev, xport portno)
186
{
187
        struct xseg *xseg;
188
        struct segpriv *priv = dev->priv;
189
        struct xseg_private *xpriv;
190
        struct xseg_port *port;
191
        struct segdev_signal_desc *ssd;
192

    
193
        xseg = xsegments[portno];
194
        if (!xseg)
195
                return;
196
        if (priv->segno >= nr_xsegments)
197
                return;
198

    
199
        xpriv = xseg->priv;
200
        port = xseg_get_port(xseg, portno);
201
        if (!port)
202
                return;
203
        ssd = xseg_get_signal_desc(xseg, port);
204
        if (!ssd || !ssd->waitcue){
205
                return;
206
        }
207

    
208
        if (xpriv->wakeup) {
209
                xpriv->wakeup(portno);
210
        }
211
        return;
212
}
213

    
214
static struct xseg_type xseg_segdev = {
215
        /* xseg operations */
216
        {
217
                .allocate = segdev_allocate,
218
                .deallocate = segdev_deallocate,
219
                .map = segdev_map,
220
                .unmap = segdev_unmap
221
        },
222
        /* name */
223
        "segdev"
224
};
225

    
226
static int segdev_remote_signal_init(void)
227
{
228
        return 0;
229
}
230

    
231
static void segdev_remote_signal_quit(void)
232
{
233
        return;
234
}
235

    
236
static int segdev_local_signal_init(struct xseg *xseg, xport portno)
237
{
238
        //assert xsegments[portno] == NULL;
239
        xsegments[portno] = xseg;
240
        return 0;
241
}
242

    
243
static void segdev_local_signal_quit(struct xseg *xseg, xport portno)
244
{
245
        //assert xsegments[portno] == xseg;
246
        xsegments[portno] = NULL;
247
        return;
248
}
249

    
250
static int segdev_prepare_wait(struct xseg *xseg, uint32_t portno)
251
{
252
        struct segdev_signal_desc *ssd; 
253
        struct xseg_port *port = xseg_get_port(xseg, portno);
254
        if (!port)
255
                return -1;
256
        ssd = xseg_get_signal_desc(xseg, port);
257
        if (!ssd)
258
                return -1;
259
        /* true/false value */
260
        ssd->waitcue = 1;
261
        return 0;
262
}
263

    
264
static int segdev_cancel_wait(struct xseg *xseg, uint32_t portno)
265
{
266
        struct segdev_signal_desc *ssd; 
267
        struct xseg_port *port = xseg_get_port(xseg, portno);
268
        if (!port)
269
                return -1;
270
        ssd = xseg_get_signal_desc(xseg, port);
271
        if (!ssd)
272
                return -1;
273
        /* true/false value */
274
        ssd->waitcue = 0;
275
        return -0;
276
}
277

    
278
static int segdev_wait_signal(struct xseg *xseg, uint32_t timeout)
279
{
280
        return -1;
281
}
282

    
283
static int segdev_signal(struct xseg *xseg, uint32_t portno)
284
{
285
        return -1;
286
}
287

    
288
static int segdev_init_signal_desc(struct xseg *xseg, void *sd)
289
{
290
        struct segdev_signal_desc *ssd = sd;
291
        if (!ssd)
292
                return -1;
293
        ssd->waitcue = 0;
294
        return 0;
295
}
296

    
297
static void segdev_quit_signal_desc(struct xseg *xseg, void *sd)
298
{
299
        return;
300
}
301

    
302
static void *segdev_alloc_data(struct xseg *xseg)
303
{
304
        struct xobject_h *sd_h = xseg_get_objh(xseg, MAGIC_SEGDEV_SD,
305
                                sizeof(struct segdev_signal_desc));
306
        return sd_h;
307
}
308

    
309
static void segdev_free_data(struct xseg *xseg, void *data)
310
{
311
        if (data)
312
                xseg_put_objh(xseg, (struct xobject_h *)data);
313
}
314

    
315
static void *segdev_alloc_signal_desc(struct xseg *xseg, void *data)
316
{
317
        struct segdev_signal_desc *ssd;
318
        struct xobject_h *sd_h = (struct xobject_h *) data;
319
        if (!sd_h)
320
                return NULL;
321
        ssd = xobj_get_obj(sd_h, X_ALLOC);
322
        if (!ssd)
323
                return NULL;
324
        ssd->waitcue = 0;
325
        return ssd;
326
}
327

    
328
static void segdev_free_signal_desc(struct xseg *xseg, void *data, void *sd)
329
{
330
        struct xobject_h *sd_h = (struct xobject_h *) data;
331
        if (!sd_h)
332
                return;
333
        if (sd)
334
                xobj_put_obj(sd_h, sd);
335
        return;
336
}
337

    
338
static struct xseg_peer xseg_peer_segdev = {
339
        /* xseg signal operations */
340
        {
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
358
        },
359
        /* name */
360
        "segdev"
361
};
362

    
363

    
364
/* ************************* */
365
/* ** XSEG Initialization ** */
366
/* ************************* */
367

    
368
static int segdev_init(void)
369
{
370
        struct segdev *segdev;
371
        struct segpriv *segpriv;
372
        int r;
373

    
374
        XSEGLOG("registering xseg types");
375
        r = xseg_register_type(&xseg_segdev);
376
        if (r)
377
                goto err0;
378

    
379
        r = xseg_register_peer(&xseg_peer_segdev);
380
        if (r)
381
                goto err1;
382
        
383
        segdev = segdev_get(0);
384
        r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
385
        if (r)
386
                goto err2;
387

    
388
        r = -ENOMEM;
389
        segpriv = kmalloc(sizeof(struct segpriv), GFP_KERNEL);
390
        if (!segpriv)
391
                goto err3;
392

    
393
        segpriv->segno = 0;
394
        segdev->callback = segdev_callback;
395
        segdev->priv = segpriv;
396

    
397
        return 0;
398

    
399
err3:
400
        segdev_put(segdev);
401
err2:
402
        xseg_unregister_peer(xseg_peer_segdev.name);
403
err1:
404
        xseg_unregister_type(xseg_segdev.name);
405
err0:
406
        return r;
407
}
408

    
409
static int segdev_quit(void)
410
{
411
        struct segdev *segdev = segdev_get(0);
412
        int r = IS_ERR(segdev) ? PTR_ERR(segdev) : 0;
413
        if (!r){
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?
418
                segdev_put(segdev);
419
        }
420
        xseg_unregister_peer(xseg_peer_segdev.name);
421
        xseg_unregister_type(xseg_segdev.name);
422

    
423
        return 0;
424
}
425

    
426
/* *************************** */
427
/* ** Module Initialization ** */
428
/* *************************** */
429

    
430
static int __init xseg_segdev_init(void)
431
{
432
        int ret = -ENOSYS;
433

    
434
        ret = segdev_init();
435
        if (ret)
436
                goto out;
437

    
438
        XSEGLOG("initialization complete");
439
out:
440
        return ret;
441
}
442

    
443
static void __exit xseg_segdev_exit(void)
444
{
445
        segdev_quit();
446
}
447

    
448
module_init(xseg_segdev_init);
449
module_exit(xseg_segdev_exit);
450