OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [ide/] [raid/] [medley.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * MEDLEY SOFTWARE RAID DRIVER (Silicon Image 3112 and others)
3
 *
4
 * Copyright (C) 2003 Thomas Horsten <thomas@horsten.com>
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 as published by
8
 * the Free Software Foundation; either version 2 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 * Copyright (C) 2003 Thomas Horsten <thomas@horsten.com>
20
 * All Rights Reserved.
21
 *
22
 * This driver uses the ATA RAID driver framework and is based on
23
 * code from Arjan van de Ven's silraid.c and hptraid.c.
24
 *
25
 * It is a driver for the Medley software RAID, which is used by
26
 * some IDE controllers, including the Silicon Image 3112 SATA
27
 * controller found onboard many modern motherboards, and the
28
 * CMD680 stand-alone PCI RAID controller.
29
 *
30
 * The author has only tested this on the Silicon Image SiI3112.
31
 * If you have any luck using more than 2 drives, and/or more
32
 * than one RAID set, and/or any other chip than the SiI3112,
33
 * please let me know by sending me mail at the above address.
34
 *
35
 * Currently, only striped mode is supported for these RAIDs.
36
 *
37
 * You are welcome to contact me if you have any questions or
38
 * suggestions for improvement.
39
 *
40
 * Change history:
41
 *
42
 * 20040310 - thomas@horsten.com
43
 *   Removed C99 style variable declarations that confused gcc-2.x
44
 *   Fixed a bug where more than one RAID set would not be detected correctly
45
 *   General cleanup for submission to kernel
46
 *
47
 * 20031012 - thomas@horsten.com
48
 *   Added support for BLKRRPART ioctl to re-read partition table
49
 *
50
 * 20030801 - thomas@horsten.com
51
 *   First test release
52
 *
53
 */
54
 
55
#include <linux/version.h>
56
#include <linux/module.h>
57
#include <linux/init.h>
58
#include <linux/kernel.h>
59
#include <linux/sched.h>
60
#include <linux/smp_lock.h>
61
#include <linux/blkdev.h>
62
#include <linux/blkpg.h>
63
#include <linux/genhd.h>
64
#include <linux/ioctl.h>
65
 
66
#include <linux/ide.h>
67
#include <asm/uaccess.h>
68
 
69
#include "ataraid.h"
70
 
71
/*
72
 * These options can be tuned if the need should occur.
73
 *
74
 * Even better, this driver could be changed to allocate the structures
75
 * dynamically.
76
 */
77
#define MAX_DRIVES_PER_SET 8
78
#define MAX_MEDLEY_ARRAYS 4
79
 
80
/*
81
 * Set to 1 only if you are debugging the driver, or if it doesn't work
82
 * the way you expect and you want to to report it.
83
 *
84
 * This will produce lots of kernel messages, some of which might
85
 * help me figure out what is going wrong).
86
 */
87
#define DEBUGGING_MEDLEY 0
88
 
89
#if DEBUGGING_MEDLEY
90
#define dprintk(fmt, args...) printk(fmt, ##args)
91
#else
92
#define dprintk(fmt, args...)
93
#endif
94
 
95
/*
96
 * Medley RAID metadata structure.
97
 *
98
 * The metadata structure is based on the ATA drive ID from the drive itself,
99
 * with the RAID information in the vendor specific regions.
100
 *
101
 * We do not use all the fields, since we only support Striped Sets.
102
 */
103
struct medley_metadata {
104
        u8  driveid0[46];
105
        u8  ascii_version[8];
106
        u8  driveid1[52];
107
        u32 total_sectors_low;
108
        u32 total_sectors_high;
109
        u16 reserved0;
110
        u8  driveid2[142];
111
        u16 product_id;
112
        u16 vendor_id;
113
        u16 minor_ver;
114
        u16 major_ver;
115
        u16 creation_timestamp[3];
116
        u16 chunk_size;
117
        u16 reserved1;
118
        u8  drive_number;
119
        u8  raid_type;
120
        u8  drives_per_striped_set;
121
        u8  striped_set_number;
122
        u8  drives_per_mirrored_set;
123
        u8  mirrored_set_number;
124
        u32 rebuild_ptr_low;
125
        u32 rebuild_ptr_high;
126
        u32 incarnation_no;
127
        u8  member_status;
128
        u8  mirrored_set_state;
129
        u8  reported_device_location;
130
        u8  member_location;
131
        u8  auto_rebuild;
132
        u8  reserved3[17];
133
        u16 checksum;
134
};
135
 
136
/*
137
 * This struct holds the information about a Medley array
138
 */
139
struct medley_array {
140
        u8       drives;
141
        u16      chunk_size;
142
        u32      sectors_per_row;
143
        u8       chunk_size_log;
144
        u16      present;
145
        u16      timestamp[3];
146
        u32      sectors;
147
        int      registered;
148
        atomic_t valid;
149
        int      access;
150
 
151
        kdev_t   members[MAX_DRIVES_PER_SET];
152
        struct   block_device *bdev[MAX_DRIVES_PER_SET];
153
};
154
 
155
static struct medley_array raid[MAX_MEDLEY_ARRAYS];
156
 
157
/*
158
 * Here we keep the offset of the ATARAID device ID's compared to our
159
 * own (this will normally be 0, unless another ATARAID driver has
160
 * registered some arrays before us).
161
 */
162
static int medley_devid_offset = 0;
163
 
164
/*
165
 * This holds the number of detected arrays.
166
 */
167
static int medley_arrays = 0;
168
 
169
/*
170
 * Wait queue for opening device (used when re-reading partition table)
171
 */
172
static DECLARE_WAIT_QUEUE_HEAD(medley_wait_open);
173
 
174
/*
175
 * The interface functions used by the ataraid framework.
176
 */
177
static int medley_open(struct inode *inode, struct file *filp);
178
static int medley_release(struct inode *inode, struct file *filp);
179
static int medley_ioctl(struct inode *inode, struct file *file,
180
                        unsigned int cmd, unsigned long arg);
181
static int medley_make_request(request_queue_t * q, int rw,
182
                               struct buffer_head *bh);
183
 
184
static struct raid_device_operations medley_ops = {
185
        open:         medley_open,
186
        release:      medley_release,
187
        ioctl:        medley_ioctl,
188
        make_request: medley_make_request
189
};
190
 
191
/*
192
 * This is the list of devices to probe.
193
 */
194
static const kdev_t probelist[] = {
195
        MKDEV(IDE0_MAJOR, 0),
196
        MKDEV(IDE0_MAJOR, 64),
197
        MKDEV(IDE1_MAJOR, 0),
198
        MKDEV(IDE1_MAJOR, 64),
199
        MKDEV(IDE2_MAJOR, 0),
200
        MKDEV(IDE2_MAJOR, 64),
201
        MKDEV(IDE3_MAJOR, 0),
202
        MKDEV(IDE3_MAJOR, 64),
203
        MKDEV(IDE4_MAJOR, 0),
204
        MKDEV(IDE4_MAJOR, 64),
205
        MKDEV(IDE5_MAJOR, 0),
206
        MKDEV(IDE5_MAJOR, 64),
207
        MKDEV(IDE6_MAJOR, 0),
208
        MKDEV(IDE6_MAJOR, 64),
209
        MKDEV(0, 0)
210
};
211
 
212
/*
213
 * Handler for ioctl calls to the virtual device
214
 */
215
static int medley_ioctl(struct inode *inode, struct file *file,
216
                        unsigned int cmd, unsigned long arg)
217
{
218
        unsigned int minor;
219
        unsigned long sectors;
220
        int devminor = (inode->i_rdev >> SHIFT) & MAJOR_MASK;
221
        int device = devminor - medley_devid_offset;
222
        int partition;
223
 
224
        dprintk("medley_ioctl\n");
225
 
226
        minor = MINOR(inode->i_rdev) >> SHIFT;
227
 
228
        switch (cmd) {
229
 
230
        case BLKGETSIZE:        /* Return device size */
231
                if (!arg)
232
                        return -EINVAL;
233
                sectors =
234
                    ataraid_gendisk.part[MINOR(inode->i_rdev)].nr_sects;
235
                dprintk("medley_ioctl: BLKGETSIZE\n");
236
                if (MINOR(inode->i_rdev) & 15)
237
                        return put_user(sectors, (unsigned long *) arg);
238
                return put_user(raid[minor - medley_devid_offset].sectors,
239
                                (unsigned long *) arg);
240
                break;
241
 
242
        case HDIO_GETGEO: {
243
                        struct hd_geometry *loc =
244
                            (struct hd_geometry *) arg;
245
                        unsigned short bios_cyl = (unsigned short)
246
                            (raid[minor].sectors / 255 / 63);   /* truncate */
247
 
248
                        dprintk("medley_ioctl: HDIO_GETGEO\n");
249
                        if (!loc)
250
                                return -EINVAL;
251
                        if (put_user(255, (byte *) & loc->heads))
252
                                return -EFAULT;
253
                        if (put_user(63, (byte *) & loc->sectors))
254
                                return -EFAULT;
255
                        if (put_user
256
                            (bios_cyl, (unsigned short *) &loc->cylinders))
257
                                return -EFAULT;
258
                        if (put_user
259
                            ((unsigned) ataraid_gendisk.
260
                             part[MINOR(inode->i_rdev)].start_sect,
261
                             (unsigned long *) &loc->start))
262
                                return -EFAULT;
263
                        return 0;
264
                }
265
 
266
        case HDIO_GETGEO_BIG: {
267
                        struct hd_big_geometry *loc =
268
                            (struct hd_big_geometry *) arg;
269
 
270
                        dprintk("medley_ioctl: HDIO_GETGEO_BIG\n");
271
                        if (!loc)
272
                                return -EINVAL;
273
                        if (put_user(255, (byte *) & loc->heads))
274
                                return -EFAULT;
275
                        if (put_user(63, (byte *) & loc->sectors))
276
                                return -EFAULT;
277
                        if (put_user
278
                            (raid[minor - medley_devid_offset].sectors /
279
                             255 / 63, (unsigned int *) &loc->cylinders))
280
                                return -EFAULT;
281
                        if (put_user
282
                            ((unsigned) ataraid_gendisk.
283
                             part[MINOR(inode->i_rdev)].start_sect,
284
                             (unsigned long *) &loc->start))
285
                                return -EFAULT;
286
                        return 0;
287
                }
288
 
289
        case BLKROSET:
290
        case BLKROGET:
291
        case BLKSSZGET:
292
                dprintk("medley_ioctl: BLK*\n");
293
                return blk_ioctl(inode->i_rdev, cmd, arg);
294
 
295
        case BLKRRPART: /* Re-read partition tables */
296
                if (!capable(CAP_SYS_ADMIN))
297
                        return -EACCES;
298
                if (minor != 0)
299
                        return -EINVAL;
300
                if (atomic_read(&(raid[device].valid)) == 0)
301
                        return -EINVAL;
302
 
303
                atomic_set(&(raid[device].valid), 0);
304
                if (raid[device].access != 1) {
305
                        atomic_set(&(raid[device].valid), 1);
306
                        return -EBUSY;
307
                }
308
 
309
                for (partition = 15; partition >= 0; partition--) {
310
                        invalidate_device(MKDEV(ATARAID_MAJOR,
311
                                                partition + devminor), 1);
312
                        ataraid_gendisk.part[partition +
313
                                             devminor].start_sect = 0;
314
                        ataraid_gendisk.part[partition +
315
                                             devminor].nr_sects = 0;
316
                }
317
                ataraid_register_disk(device, raid[device].sectors);
318
                atomic_set(&(raid[device].valid), 1);
319
                wake_up(&medley_wait_open);
320
                return 0;
321
 
322
        default:
323
                return -EINVAL;
324
        }
325
 
326
        return 0;
327
}
328
 
329
/*
330
 * Handler to map a request to the real device.
331
 * If the request cannot be made because it spans multiple disks,
332
 * we return -1, otherwise we modify the request and return 1.
333
 */
334
static int medley_make_request(request_queue_t * q, int rw,
335
                               struct buffer_head *bh)
336
{
337
        u8 disk;
338
        u32 rsect = bh->b_rsector;
339
        int device =
340
            ((bh->b_rdev >> SHIFT) & MAJOR_MASK) - medley_devid_offset;
341
        struct medley_array *r = raid + device;
342
 
343
        /* Add the partition offset */
344
        rsect = rsect + ataraid_gendisk.part[MINOR(bh->b_rdev)].start_sect;
345
 
346
        dprintk("medley_make_request, rsect=%ul\n", rsect);
347
 
348
        /* Detect if the request crosses a chunk barrier */
349
        if (r->chunk_size_log) {
350
                if (((rsect & (r->chunk_size - 1)) +
351
                     (bh->b_size / 512)) > (1 << r->chunk_size_log)) {
352
                        return -1;
353
                }
354
        } else {
355
                if ((rsect / r->chunk_size) !=
356
                    ((rsect + (bh->b_size / 512) - 1) / r->chunk_size)) {
357
                        return -1;
358
                }
359
        }
360
 
361
        /*
362
         * Medley arrays are simple enough, since the smallest disk decides the
363
         * number of sectors used per disk. So there is no need for the cutoff
364
         * magic found in other drivers like hptraid.
365
         */
366
        if (r->chunk_size_log) {
367
                /* We save some expensive operations (1 div, 1 mul, 1 mod),
368
                 * if the chunk size is a power of 2, which is true in most
369
                 * cases (at least with my version of the RAID BIOS).
370
                 */
371
                disk = (rsect >> r->chunk_size_log) % r->drives;
372
                rsect = ((rsect / r->sectors_per_row) <<
373
                         r->chunk_size_log) + (rsect & (r->chunk_size -
374
                                                        1));
375
        } else {
376
                disk = (rsect / r->chunk_size) % r->drives;
377
                rsect = rsect / r->sectors_per_row * r->chunk_size +
378
                    rsect % r->chunk_size;
379
        }
380
 
381
        dprintk("medley_make_request :-), disk=%d, rsect=%ul\n", disk,
382
                rsect);
383
        bh->b_rdev = r->members[disk];
384
        bh->b_rsector = rsect;
385
        return 1;
386
}
387
 
388
/*
389
 * Find out which array a drive belongs to, and add it to that array.
390
 * If it is not a member of a detected array, add a new array for it.
391
 */
392
void medley_add_raiddrive(kdev_t dev, struct medley_metadata *md)
393
{
394
        int c;
395
 
396
        dprintk("Candidate drive %02x:%02x - drive %d of %d, stride %d, "
397
                "sectors %ul (%d MB)\n",
398
                MAJOR(dev), MINOR(dev), md->drive_number,
399
                md->drives_per_striped_set, md->chunk_size,
400
                md->total_sectors_low,
401
                md->total_sectors_low / 1024 / 1024 / 2);
402
 
403
        for (c = 0; c < medley_arrays; c++) {
404
                if ((raid[c].timestamp[0] == md->creation_timestamp[0]) &&
405
                    (raid[c].timestamp[1] == md->creation_timestamp[1]) &&
406
                    (raid[c].timestamp[2] == md->creation_timestamp[2]) &&
407
                    (raid[c].drives == md->drives_per_striped_set) &&
408
                    (raid[c].chunk_size == md->chunk_size) &&
409
                    ((raid[c].present & (1 << md->drive_number)) == 0)) {
410
                        dprintk("Existing array %d\n", c);
411
                        raid[c].present |= (1 << md->drive_number);
412
                        raid[c].members[md->drive_number] = dev;
413
                        break;
414
                }
415
        }
416
        if (c == medley_arrays) {
417
                dprintk("New array %d\n", medley_arrays);
418
                if (medley_arrays == MAX_MEDLEY_ARRAYS) {
419
                        printk(KERN_ERR "Medley RAID: "
420
                               "Too many RAID sets detected - you can change "
421
                               "the max in the driver.\n");
422
                } else {
423
                        raid[c].timestamp[0] = md->creation_timestamp[0];
424
                        raid[c].timestamp[1] = md->creation_timestamp[1];
425
                        raid[c].timestamp[2] = md->creation_timestamp[2];
426
                        raid[c].drives = md->drives_per_striped_set;
427
                        raid[c].chunk_size = md->chunk_size;
428
                        raid[c].sectors_per_row = md->chunk_size *
429
                            md->drives_per_striped_set;
430
 
431
                        /* Speedup if chunk size is a power of 2 */
432
                        if (((raid[c].chunk_size - 1) &
433
                             (raid[c].chunk_size)) == 0) {
434
                                raid[c].chunk_size_log =
435
                                    ffs(raid[c].chunk_size) - 1;
436
                        } else {
437
                                raid[c].chunk_size_log = 0;
438
                        }
439
                        raid[c].present = (1 << md->drive_number);
440
                        raid[c].members[md->drive_number] = dev;
441
                        if (md->major_ver == 1) {
442
                                raid[c].sectors = ((u32 *) (md))[27];
443
                        } else {
444
                                raid[c].sectors = md->total_sectors_low;
445
                        }
446
                        medley_arrays++;
447
                }
448
        }
449
}
450
 
451
/*
452
 * Read the Medley metadata from a drive.
453
 * Returns the bh if it was found, otherwise NULL.
454
 */
455
struct buffer_head *medley_get_metadata(kdev_t dev)
456
{
457
        struct buffer_head *bh = NULL;
458
        struct pci_dev *pcidev;
459
        u32 lba;
460
        int pos;
461
        struct medley_metadata *md;
462
 
463
        ide_drive_t *drvinfo = ide_info_ptr(dev, 0);
464
        if ((drvinfo == NULL) || drvinfo->capacity < 1) {
465
                return NULL;
466
        }
467
 
468
        dprintk("Probing %02x:%02x\n", MAJOR(dev), MINOR(dev));
469
 
470
        /* If this drive is not on a PCI controller, it is not Medley RAID.
471
         * Medley matches the PCI device ID with the metadata to check if
472
         * it is valid. Unfortunately it is the only reliable way to identify
473
         * the superblock */
474
        pcidev = drvinfo->hwif ? drvinfo->hwif->pci_dev : NULL;
475
        if (!pcidev) {
476
                return NULL;
477
        }
478
 
479
        /*
480
         * 4 copies of the metadata exist, in the following 4 sectors:
481
         * last, last-0x200, last-0x400, last-0x600.
482
         *
483
         * We must try each of these in order, until we find the metadata.
484
         * FIXME: This does not take into account drives with 48/64-bit LBA
485
         * addressing, even though the Medley RAID version 2 supports these.
486
         */
487
        lba = drvinfo->capacity - 1;
488
        for (pos = 0; pos < 4; pos++, lba -= 0x200) {
489
                bh = bread(dev, lba, 512);
490
                if (!bh) {
491
                        printk(KERN_ERR "Medley RAID (%02x:%02x): "
492
                               "Error reading metadata (lba=%d)\n",
493
                               MAJOR(dev), MINOR(dev), lba);
494
                        break;
495
                }
496
 
497
                /* A valid Medley RAID has the PCI vendor/device ID of its
498
                 * IDE controller, and the correct checksum. */
499
                md = (void *) (bh->b_data);
500
 
501
                if (pcidev->vendor == md->vendor_id &&
502
                    pcidev->device == md->product_id) {
503
                        u16 checksum = 0;
504
                        u16 *p = (void *) (bh->b_data);
505
                        int c;
506
                        for (c = 0; c < 160; c++) {
507
                                checksum += *p++;
508
                        }
509
                        dprintk
510
                            ("Probing %02x:%02x csum=%d, major_ver=%d\n",
511
                             MAJOR(dev), MINOR(dev), checksum,
512
                             md->major_ver);
513
                        if (((checksum == 0xffff) && (md->major_ver == 1))
514
                            || (checksum == 0)) {
515
                                dprintk("Probing %02x:%02x VALID\n",
516
                                        MAJOR(dev), MINOR(dev));
517
                                break;
518
                        }
519
                }
520
                /* Was not a valid superblock */
521
                if (bh) {
522
                        brelse(bh);
523
                        bh = NULL;
524
                }
525
        }
526
        return bh;
527
}
528
 
529
/*
530
 * Determine if this drive belongs to a Medley array.
531
 */
532
static void medley_probe_drive(int major, int minor)
533
{
534
        struct buffer_head *bh;
535
        kdev_t dev = MKDEV(major, minor);
536
        struct medley_metadata *md;
537
 
538
        bh = medley_get_metadata(dev);
539
        if (!bh)
540
                return;
541
 
542
        md = (void *) (bh->b_data);
543
 
544
        if (md->raid_type != 0x0) {
545
                printk(KERN_INFO "Medley RAID (%02x:%02x): "
546
                       "Sorry, this driver currently only supports "
547
                       "striped sets (RAID level 0).\n", major, minor);
548
        } else if (md->major_ver == 2 && md->total_sectors_high != 0) {
549
                printk(KERN_ERR "Medley RAID (%02x:%02x):"
550
                       "Sorry, the driver only supports 32 bit LBA disks "
551
                       "(disk too big).\n", major, minor);
552
        } else if (md->major_ver > 0 && md->major_ver > 2) {
553
                printk(KERN_INFO "Medley RAID (%02x:%02x): "
554
                       "Unsupported version (%d.%d) - this driver supports "
555
                       "Medley version 1.x and 2.x\n",
556
                       major, minor, md->major_ver, md->minor_ver);
557
        } else if (md->drives_per_striped_set > MAX_DRIVES_PER_SET) {
558
                printk(KERN_ERR "Medley RAID (%02x:%02x): "
559
                       "Striped set too large (%d drives) - please report "
560
                       "this (and change max in driver).\n",
561
                       major, minor, md->drives_per_striped_set);
562
        } else if ((md->drive_number > md->drives_per_striped_set) ||
563
                   (md->drives_per_striped_set < 1) ||
564
                   (md->chunk_size < 1)) {
565
                printk(KERN_ERR "Medley RAID (%02x:%02x): "
566
                       "Metadata appears to be corrupt.\n", major, minor);
567
        } else {
568
                /* We have a good candidate, put it in the correct array */
569
                medley_add_raiddrive(dev, md);
570
        }
571
 
572
        if (bh) {
573
                brelse(bh);
574
        }
575
}
576
 
577
 
578
/*
579
 * Taken from hptraid.c, this is called to prevent the device
580
 * from disappearing from under us and also nullifies the (incorrect)
581
 * partitions of the underlying disk.
582
 */
583
struct block_device *get_device_lock(kdev_t member)
584
{
585
        struct block_device *bdev = bdget(member);
586
        struct gendisk *gd;
587
        int minor = MINOR(member);
588
        int j;
589
 
590
        if (bdev
591
            && blkdev_get(bdev, FMODE_READ | FMODE_WRITE, 0,
592
                          BDEV_RAW) == 0) {
593
                /*
594
                 * This is supposed to prevent others from
595
                 * stealing our underlying disks. Now blank
596
                 * the /proc/partitions table for the wrong
597
                 * partition table, so that scripts don't
598
                 * accidentally mount it and crash the kernel
599
                 */
600
                /* XXX: the 0 is an utter hack  --hch */
601
                gd = get_gendisk(MKDEV(MAJOR(member), 0));
602
                if (gd != NULL) {
603
                        if (gd->major == MAJOR(member)) {
604
                                for (j = 1 + (minor << gd->minor_shift);
605
                                     j < ((minor + 1) << gd->minor_shift);
606
                                     j++)
607
                                        gd->part[j].nr_sects = 0;
608
                        }
609
                }
610
        }
611
        return bdev;
612
}
613
 
614
/*
615
 * Initialise the driver.
616
 */
617
static __init int medley_init(void)
618
{
619
        int c, d;
620
 
621
        memset(raid, 0, MAX_MEDLEY_ARRAYS * sizeof(struct medley_array));
622
 
623
        /* Probe each of the drives on our list */
624
        for (c = 0; probelist[c] != MKDEV(0, 0); c++) {
625
                medley_probe_drive(MAJOR(probelist[c]),
626
                                   MINOR(probelist[c]));
627
        }
628
 
629
        /* Check if the detected sets are complete */
630
        for (c = 0; c < medley_arrays; c++) {
631
                if (raid[c].present != (1 << raid[c].drives) - 1) {
632
                        printk(KERN_ERR "Medley RAID: "
633
                               "Incomplete RAID set deleted - disks:");
634
                        for (d = 0; c < raid[c].drives; c++) {
635
                                if (raid[c].present & (1 << d)) {
636
                                        printk(" %02x:%02x",
637
                                               MAJOR(raid[c].members[d]),
638
                                               MINOR(raid[c].members[d]));
639
                                }
640
                        }
641
                        printk("\n");
642
                        if (c + 1 < medley_arrays) {
643
                                memmove(raid + c + 1, raid + c,
644
                                        (medley_arrays - c -
645
                                         1) * sizeof(struct medley_array));
646
                        }
647
                        medley_arrays--;
648
                }
649
        }
650
 
651
        /* Register any remaining array(s) */
652
        for (c = 0; c < medley_arrays; c++) {
653
                int device = ataraid_get_device(&medley_ops);
654
                if (device < 0) {
655
                        printk(KERN_ERR "Medley RAID: "
656
                               "Could not get ATARAID device.\n");
657
                        break;
658
                }
659
                if (c == 0) {
660
                        /* First array, compute offset to our device ID's */
661
                        medley_devid_offset = device;
662
                        dprintk("Medley_devid_offset: %d\n",
663
                                medley_devid_offset);
664
                } else if (device - medley_devid_offset != c) {
665
                        printk(KERN_ERR "Medley RAID: "
666
                               "ATARAID gave us an illegal device ID.\n");
667
                        ataraid_release_device(device);
668
                        break;
669
                }
670
 
671
                printk(KERN_INFO "Medley RAID: "
672
                       "Striped set %d consists of %d disks, total %dMiB "
673
                       "- disks:",
674
                       c, raid[c].drives,
675
                       raid[c].sectors / 1024 / 1024 / 2);
676
                for (d = 0; d < raid[c].drives; d++) {
677
                        printk(" %02x:%02x", MAJOR(raid[c].members[d]),
678
                               MINOR(raid[c].members[d]));
679
                        raid[c].bdev[d] = get_device_lock(raid[c].members[d]);
680
                }
681
                printk("\n");
682
                raid[c].registered = 1;
683
                atomic_set(&(raid[c].valid), 1);
684
                ataraid_register_disk(c, raid[c].sectors);
685
        }
686
 
687
        if (medley_arrays > 0) {
688
                printk(KERN_INFO "Medley RAID: %d active RAID set%s\n",
689
                       medley_arrays, medley_arrays == 1 ? "" : "s");
690
                return 0;
691
        }
692
 
693
        printk(KERN_INFO "Medley RAID: No usable RAID sets found\n");
694
        return -ENODEV;
695
}
696
 
697
/*
698
 * Remove the arrays and clean up.
699
 */
700
static void __exit medley_exit(void)
701
{
702
        int device, d;
703
        for (device = 0; device < medley_arrays; device++) {
704
                for (d = 0; d < raid[device].drives; d++) {
705
                        if (raid[device].bdev[d]) {
706
                                blkdev_put(raid[device].bdev[d], BDEV_RAW);
707
                                raid[device].bdev[d] = NULL;
708
                        }
709
                }
710
                if (raid[device].registered) {
711
                        ataraid_release_device(device +
712
                                               medley_devid_offset);
713
                        raid[device].registered = 0;
714
                }
715
        }
716
}
717
 
718
/*
719
 * Called to open the virtual device
720
 */
721
static int medley_open(struct inode *inode, struct file *filp)
722
{
723
        int device = ((inode->i_rdev >> SHIFT) & MAJOR_MASK) -
724
            medley_devid_offset;
725
        dprintk("medley_open\n");
726
 
727
        if (device < medley_arrays) {
728
                while (!atomic_read(&(raid[device].valid)))
729
                        sleep_on(&medley_wait_open);
730
                raid[device].access++;
731
                MOD_INC_USE_COUNT;
732
                return (0);
733
        }
734
        return -ENODEV;
735
}
736
 
737
/*
738
 * Called to release the handle on the virtual device
739
 */
740
static int medley_release(struct inode *inode, struct file *filp)
741
{
742
        int device = ((inode->i_rdev >> SHIFT) & MAJOR_MASK) -
743
            medley_devid_offset;
744
        dprintk("medley_release\n");
745
        raid[device].access--;
746
        MOD_DEC_USE_COUNT;
747
        return 0;
748
}
749
 
750
module_init(medley_init);
751
module_exit(medley_exit);
752
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.