Commit 81ad17d7 authored by Linus Torvalds's avatar Linus Torvalds

Merge penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/viro

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents f7ce058b aebd88df
...@@ -415,8 +415,7 @@ static struct floppy_drive_params drive_params[N_DRIVE]; ...@@ -415,8 +415,7 @@ static struct floppy_drive_params drive_params[N_DRIVE];
static struct floppy_drive_struct drive_state[N_DRIVE]; static struct floppy_drive_struct drive_state[N_DRIVE];
static struct floppy_write_errors write_errors[N_DRIVE]; static struct floppy_write_errors write_errors[N_DRIVE];
static struct timer_list motor_off_timer[N_DRIVE]; static struct timer_list motor_off_timer[N_DRIVE];
static struct gendisk disks[N_DRIVE]; static struct gendisk *disks[N_DRIVE];
static char names[N_DRIVE][4];
static struct floppy_raw_cmd *raw_cmd, default_raw_cmd; static struct floppy_raw_cmd *raw_cmd, default_raw_cmd;
/* /*
...@@ -3772,7 +3771,7 @@ static int floppy_open(struct inode * inode, struct file * filp) ...@@ -3772,7 +3771,7 @@ static int floppy_open(struct inode * inode, struct file * filp)
} }
UDRS->fd_device = minor(inode->i_rdev); UDRS->fd_device = minor(inode->i_rdev);
set_capacity(&disks[drive], floppy_sizes[minor(inode->i_rdev)]); set_capacity(disks[drive], floppy_sizes[minor(inode->i_rdev)]);
if (old_dev != -1 && old_dev != minor(inode->i_rdev)) { if (old_dev != -1 && old_dev != minor(inode->i_rdev)) {
if (buffer_drive == drive) if (buffer_drive == drive)
buffer_track = -1; buffer_track = -1;
...@@ -3952,7 +3951,7 @@ static int floppy_revalidate(kdev_t dev) ...@@ -3952,7 +3951,7 @@ static int floppy_revalidate(kdev_t dev)
process_fd_request(); process_fd_request();
} }
} }
set_capacity(&disks[drive], floppy_sizes[minor(dev)]); set_capacity(disks[drive], floppy_sizes[minor(dev)]);
return res; return res;
} }
...@@ -4230,26 +4229,34 @@ static struct gendisk *floppy_find(int minor) ...@@ -4230,26 +4229,34 @@ static struct gendisk *floppy_find(int minor)
!(allowed_drive_mask & (1 << drive)) || !(allowed_drive_mask & (1 << drive)) ||
fdc_state[FDC(drive)].version == FDC_NONE) fdc_state[FDC(drive)].version == FDC_NONE)
return NULL; return NULL;
return &disks[drive]; return disks[drive];
} }
int __init floppy_init(void) int __init floppy_init(void)
{ {
int i,unit,drive; int i,unit,drive;
int err;
raw_cmd = NULL; raw_cmd = NULL;
for (i=0; i<N_DRIVE; i++) {
disks[i] = alloc_disk();
if (!disks[i])
goto Enomem;
}
devfs_handle = devfs_mk_dir (NULL, "floppy", NULL); devfs_handle = devfs_mk_dir (NULL, "floppy", NULL);
if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) { if (register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
printk("Unable to get major %d for floppy\n",MAJOR_NR); printk("Unable to get major %d for floppy\n",MAJOR_NR);
return -EBUSY; err = -EBUSY;
goto out;
} }
for (i=0; i<N_DRIVE; i++) { for (i=0; i<N_DRIVE; i++) {
disks[i].major = MAJOR_NR; disks[i]->major = MAJOR_NR;
disks[i].first_minor = TOMINOR(i); disks[i]->first_minor = TOMINOR(i);
disks[i].fops = &floppy_fops; disks[i]->fops = &floppy_fops;
sprintf(disks[i].disk_name, "fd%d", i); sprintf(disks[i]->disk_name, "fd%d", i);
} }
blk_set_probe(MAJOR_NR, floppy_find); blk_set_probe(MAJOR_NR, floppy_find);
...@@ -4281,11 +4288,8 @@ int __init floppy_init(void) ...@@ -4281,11 +4288,8 @@ int __init floppy_init(void)
use_virtual_dma = can_use_virtual_dma & 1; use_virtual_dma = can_use_virtual_dma & 1;
fdc_state[0].address = FDC1; fdc_state[0].address = FDC1;
if (fdc_state[0].address == -1) { if (fdc_state[0].address == -1) {
unregister_blkdev(MAJOR_NR,"fd"); err = -ENODEV;
del_timer(&fd_timeout); goto out1;
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blk_set_probe(MAJOR_NR, NULL);
return -ENODEV;
} }
#if N_FDC > 1 #if N_FDC > 1
fdc_state[1].address = FDC2; fdc_state[1].address = FDC2;
...@@ -4293,11 +4297,8 @@ int __init floppy_init(void) ...@@ -4293,11 +4297,8 @@ int __init floppy_init(void)
fdc = 0; /* reset fdc in case of unexpected interrupt */ fdc = 0; /* reset fdc in case of unexpected interrupt */
if (floppy_grab_irq_and_dma()){ if (floppy_grab_irq_and_dma()){
del_timer(&fd_timeout); err = -EBUSY;
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); goto out1;
unregister_blkdev(MAJOR_NR,"fd");
blk_set_probe(MAJOR_NR, NULL);
return -EBUSY;
} }
/* initialise drive state */ /* initialise drive state */
...@@ -4352,15 +4353,13 @@ int __init floppy_init(void) ...@@ -4352,15 +4353,13 @@ int __init floppy_init(void)
current_drive = 0; current_drive = 0;
floppy_release_irq_and_dma(); floppy_release_irq_and_dma();
initialising=0; initialising=0;
if (have_no_fdc) if (have_no_fdc) {
{
DPRINT("no floppy controllers found\n"); DPRINT("no floppy controllers found\n");
flush_scheduled_work(); flush_scheduled_work();
if (usage_count) if (usage_count)
floppy_release_irq_and_dma(); floppy_release_irq_and_dma();
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); err = have_no_fdc;
unregister_blkdev(MAJOR_NR,"fd"); goto out2;
blk_set_probe(MAJOR_NR, NULL);
} }
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
...@@ -4370,12 +4369,27 @@ int __init floppy_init(void) ...@@ -4370,12 +4369,27 @@ int __init floppy_init(void)
continue; continue;
if (fdc_state[FDC(drive)].version == FDC_NONE) if (fdc_state[FDC(drive)].version == FDC_NONE)
continue; continue;
add_disk(disks + drive); add_disk(disks[drive]);
} }
platform_device_register(&floppy_device); platform_device_register(&floppy_device);
return 0;
return have_no_fdc; out1:
del_timer(&fd_timeout);
out2:
unregister_blkdev(MAJOR_NR,"fd");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
blk_set_probe(MAJOR_NR, NULL);
out:
for (i=0; i<N_DRIVE; i++)
put_disk(disks[i]);
return err;
Enomem:
while (i--)
put_disk(disks[i]);
return -ENOMEM;
} }
static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED; static spinlock_t floppy_usage_lock = SPIN_LOCK_UNLOCKED;
...@@ -4564,7 +4578,8 @@ void cleanup_module(void) ...@@ -4564,7 +4578,8 @@ void cleanup_module(void)
for (drive = 0; drive < N_DRIVE; drive++) { for (drive = 0; drive < N_DRIVE; drive++) {
if ((allowed_drive_mask & (1 << drive)) && if ((allowed_drive_mask & (1 << drive)) &&
fdc_state[FDC(drive)].version != FDC_NONE) fdc_state[FDC(drive)].version != FDC_NONE)
del_gendisk(disks + drive); del_gendisk(disks[drive]);
put_disk(disks[drive]);
} }
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
......
...@@ -83,7 +83,7 @@ ...@@ -83,7 +83,7 @@
static int max_loop = 8; static int max_loop = 8;
static struct loop_device *loop_dev; static struct loop_device *loop_dev;
static struct gendisk *disks; static struct gendisk **disks;
static devfs_handle_t devfs_handle; /* For the directory */ static devfs_handle_t devfs_handle; /* For the directory */
/* /*
...@@ -159,9 +159,7 @@ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { ...@@ -159,9 +159,7 @@ struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
static void figure_loop_size(struct loop_device *lo) static void figure_loop_size(struct loop_device *lo)
{ {
loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_size; loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_size;
set_capacity(disks[lo->lo_number], (size - lo->lo_offset) >> 9);
set_capacity(disks + lo->lo_number,
(size - lo->lo_offset) >> 9);
} }
static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf,
...@@ -809,7 +807,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) ...@@ -809,7 +807,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_name, 0, LO_NAME_SIZE); memset(lo->lo_name, 0, LO_NAME_SIZE);
invalidate_bdev(bdev, 0); invalidate_bdev(bdev, 0);
set_capacity(disks + lo->lo_number, 0); set_capacity(disks[lo->lo_number], 0);
filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp;
lo->lo_state = Lo_unbound; lo->lo_state = Lo_unbound;
fput(filp); fput(filp);
...@@ -1048,20 +1046,25 @@ int __init loop_init(void) ...@@ -1048,20 +1046,25 @@ int __init loop_init(void)
if (!loop_dev) if (!loop_dev)
return -ENOMEM; return -ENOMEM;
disks = kmalloc(max_loop * sizeof(struct gendisk), GFP_KERNEL); disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL);
if (!disks) if (!disks)
goto out_mem; goto out_mem;
for (i = 0; i < max_loop; i++) {
disks[i] = alloc_disk();
if (!disks[i])
goto out_mem2;
}
for (i = 0; i < max_loop; i++) { for (i = 0; i < max_loop; i++) {
struct loop_device *lo = &loop_dev[i]; struct loop_device *lo = &loop_dev[i];
struct gendisk *disk = disks + i; struct gendisk *disk = disks[i];
memset(lo, 0, sizeof(struct loop_device)); memset(lo, 0, sizeof(struct loop_device));
init_MUTEX(&lo->lo_ctl_mutex); init_MUTEX(&lo->lo_ctl_mutex);
init_MUTEX_LOCKED(&lo->lo_sem); init_MUTEX_LOCKED(&lo->lo_sem);
init_MUTEX_LOCKED(&lo->lo_bh_mutex); init_MUTEX_LOCKED(&lo->lo_bh_mutex);
lo->lo_number = i; lo->lo_number = i;
spin_lock_init(&lo->lo_lock); spin_lock_init(&lo->lo_lock);
memset(disk, 0, sizeof(struct gendisk));
disk->major = LOOP_MAJOR; disk->major = LOOP_MAJOR;
disk->first_minor = i; disk->first_minor = i;
disk->fops = &lo_fops; disk->fops = &lo_fops;
...@@ -1074,6 +1077,9 @@ int __init loop_init(void) ...@@ -1074,6 +1077,9 @@ int __init loop_init(void)
printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
return 0; return 0;
out_mem2:
while (i--)
put_disk(disks[i]);
out_mem: out_mem:
kfree(disks); kfree(disks);
kfree(loop_dev); kfree(loop_dev);
...@@ -1084,8 +1090,10 @@ int __init loop_init(void) ...@@ -1084,8 +1090,10 @@ int __init loop_init(void)
void loop_exit(void) void loop_exit(void)
{ {
int i; int i;
for (i = 0; i < max_loop; i++) for (i = 0; i < max_loop; i++) {
del_gendisk(disks + i); del_gendisk(disks[i]);
put_disk(disks[i]);
}
devfs_unregister(devfs_handle); devfs_unregister(devfs_handle);
if (unregister_blkdev(MAJOR_NR, "loop")) if (unregister_blkdev(MAJOR_NR, "loop"))
printk(KERN_WARNING "loop: cannot unregister blkdev\n"); printk(KERN_WARNING "loop: cannot unregister blkdev\n");
......
...@@ -276,7 +276,7 @@ struct pd_unit { ...@@ -276,7 +276,7 @@ struct pd_unit {
int alt_geom; int alt_geom;
int present; int present;
char name[PD_NAMELEN]; /* pda, pdb, etc ... */ char name[PD_NAMELEN]; /* pda, pdb, etc ... */
struct gendisk gd; struct gendisk *gd;
}; };
struct pd_unit pd[PD_UNITS]; struct pd_unit pd[PD_UNITS];
...@@ -287,8 +287,6 @@ static void pd_doorlock(struct pd_unit *disk, int func); ...@@ -287,8 +287,6 @@ static void pd_doorlock(struct pd_unit *disk, int func);
static int pd_check_media(kdev_t dev); static int pd_check_media(kdev_t dev);
static void pd_eject(struct pd_unit *disk); static void pd_eject(struct pd_unit *disk);
/* 'unit' must be defined in all functions - either as a local or a param */
static char pd_scratch[512]; /* scratch block buffer */ static char pd_scratch[512]; /* scratch block buffer */
/* the variables below are used mainly in the I/O request engine, which /* the variables below are used mainly in the I/O request engine, which
...@@ -368,11 +366,8 @@ static int pd_ioctl(struct inode *inode, struct file *file, ...@@ -368,11 +366,8 @@ static int pd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
struct hd_geometry *geo = (struct hd_geometry *) arg; struct hd_geometry *geo = (struct hd_geometry *) arg;
int err, unit = DEVICE_NR(inode->i_rdev); struct hd_geometry g;
struct pd_unit *disk = pd + unit; struct pd_unit *disk = pd + DEVICE_NR(inode->i_rdev);
if (!disk->present)
return -ENODEV;
switch (cmd) { switch (cmd) {
case CDROMEJECT: case CDROMEJECT:
...@@ -380,23 +375,18 @@ static int pd_ioctl(struct inode *inode, struct file *file, ...@@ -380,23 +375,18 @@ static int pd_ioctl(struct inode *inode, struct file *file,
pd_eject(disk); pd_eject(disk);
return 0; return 0;
case HDIO_GETGEO: case HDIO_GETGEO:
if (!geo)
return -EINVAL;
err = verify_area(VERIFY_WRITE, geo, sizeof (*geo));
if (err)
return err;
if (disk->alt_geom) { if (disk->alt_geom) {
put_user(disk->capacity / (PD_LOG_HEADS * PD_LOG_SECTS), g.heads = PD_LOG_HEADS;
(short *) &geo->cylinders); g.sectors = PD_LOG_SECTS;
put_user(PD_LOG_HEADS, (char *) &geo->heads); g.cylinders = disk->capacity / (g.heads * g.sectors);
put_user(PD_LOG_SECTS, (char *) &geo->sectors);
} else { } else {
put_user(disk->cylinders, (short *) &geo->cylinders); g.heads = disk->heads;
put_user(disk->heads, (char *) &geo->heads); g.sectors = disk->sectors;
put_user(disk->sectors, (char *) &geo->sectors); g.cylinders = disk->cylinders;
} }
put_user(get_start_sect(inode->i_bdev), (long *) &geo->start); g.start = get_start_sect(inode->i_bdev);
if (copy_to_user(geo, &g, sizeof(struct hd_geometry)))
return -EFAULT;
return 0; return 0;
default: default:
return -EINVAL; return -EINVAL;
...@@ -418,8 +408,6 @@ static int pd_check_media(kdev_t dev) ...@@ -418,8 +408,6 @@ static int pd_check_media(kdev_t dev)
{ {
int r, unit = DEVICE_NR(dev); int r, unit = DEVICE_NR(dev);
struct pd_unit *disk = pd + unit; struct pd_unit *disk = pd + unit;
if (unit >= PD_UNITS || (!disk->present))
return -ENODEV;
if (!disk->removable) if (!disk->removable)
return 0; return 0;
pd_media_check(disk); pd_media_check(disk);
...@@ -432,12 +420,10 @@ static int pd_revalidate(kdev_t dev) ...@@ -432,12 +420,10 @@ static int pd_revalidate(kdev_t dev)
{ {
int unit = DEVICE_NR(dev); int unit = DEVICE_NR(dev);
struct pd_unit *disk = pd + unit; struct pd_unit *disk = pd + unit;
if (unit >= PD_UNITS || !disk->present)
return -ENODEV;
if (pd_identify(disk)) if (pd_identify(disk))
set_capacity(&disk->gd, disk->capacity); set_capacity(disk->gd, disk->capacity);
else else
set_capacity(&disk->gd, 0); set_capacity(disk->gd, 0);
return 0; return 0;
} }
...@@ -717,13 +703,20 @@ static int pd_detect(void) ...@@ -717,13 +703,20 @@ static int pd_detect(void)
} }
for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) { for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) {
if (disk->present) { if (disk->present) {
strcpy(disk->gd.disk_name, disk->name); struct gendisk *p = alloc_disk();
disk->gd.minor_shift = PD_BITS; if (!p) {
disk->gd.fops = &pd_fops; disk->present = 0;
disk->gd.major = major; k--;
disk->gd.first_minor = unit << PD_BITS; continue;
set_capacity(&disk->gd, disk->capacity); }
add_disk(&disk->gd); strcpy(p->disk_name, disk->name);
p->minor_shift = PD_BITS;
p->fops = &pd_fops;
p->major = major;
p->first_minor = unit << PD_BITS;
set_capacity(p, disk->capacity);
disk->gd = p;
add_disk(p);
} }
} }
if (k) if (k)
...@@ -760,7 +753,7 @@ static void do_pd_request(request_queue_t * q) ...@@ -760,7 +753,7 @@ static void do_pd_request(request_queue_t * q)
pd_run = pd_req->nr_sectors; pd_run = pd_req->nr_sectors;
pd_count = pd_req->current_nr_sectors; pd_count = pd_req->current_nr_sectors;
pd_current = pd + unit; pd_current = pd + unit;
if (pd_block + pd_count > get_capacity(&pd_current->gd)) { if (pd_block + pd_count > get_capacity(pd_current->gd)) {
end_request(pd_req, 0); end_request(pd_req, 0);
goto repeat; goto repeat;
} }
...@@ -942,7 +935,10 @@ static void __exit pd_exit(void) ...@@ -942,7 +935,10 @@ static void __exit pd_exit(void)
unregister_blkdev(MAJOR_NR, name); unregister_blkdev(MAJOR_NR, name);
for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) { for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) {
if (disk->present) { if (disk->present) {
del_gendisk(&disk->gd); struct gendisk *p = disk->gd;
disk->gd = NULL;
del_gendisk(p);
put_disk(p);
pi_release(disk->pi); pi_release(disk->pi);
} }
} }
......
...@@ -77,7 +77,7 @@ int initrd_below_start_ok; ...@@ -77,7 +77,7 @@ int initrd_below_start_ok;
*/ */
static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */ static unsigned long rd_length[NUM_RAMDISKS]; /* Size of RAM disks in bytes */
static struct gendisk rd_disks[NUM_RAMDISKS]; static struct gendisk *rd_disks[NUM_RAMDISKS];
static devfs_handle_t devfs_handle; static devfs_handle_t devfs_handle;
static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */ static struct block_device *rd_bdev[NUM_RAMDISKS];/* Protected device data */
...@@ -310,13 +310,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un ...@@ -310,13 +310,7 @@ static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
static struct block_device_operations rd_bd_op; static struct block_device_operations rd_bd_op;
static struct gendisk initrd_disk = { static struct gendisk *initrd_disk;
.major = MAJOR_NR,
.first_minor = INITRD_MINOR,
.minor_shift = 0,
.fops = &rd_bd_op,
.disk_name = "initrd"
};
static ssize_t initrd_read(struct file *file, char *buf, static ssize_t initrd_read(struct file *file, char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -340,7 +334,7 @@ static int initrd_release(struct inode *inode,struct file *file) ...@@ -340,7 +334,7 @@ static int initrd_release(struct inode *inode,struct file *file)
spin_lock(&initrd_users_lock); spin_lock(&initrd_users_lock);
if (!--initrd_users) { if (!--initrd_users) {
spin_unlock(&initrd_users_lock); spin_unlock(&initrd_users_lock);
del_gendisk(&initrd_disk); del_gendisk(initrd_disk);
free_initrd_mem(initrd_start, initrd_end); free_initrd_mem(initrd_start, initrd_end);
initrd_start = 0; initrd_start = 0;
} else { } else {
...@@ -412,8 +406,12 @@ static void __exit rd_cleanup (void) ...@@ -412,8 +406,12 @@ static void __exit rd_cleanup (void)
invalidate_bdev(bdev, 1); invalidate_bdev(bdev, 1);
blkdev_put(bdev, BDEV_FILE); blkdev_put(bdev, BDEV_FILE);
} }
del_gendisk(rd_disks + i); del_gendisk(rd_disks[i]);
put_disk(rd_disks[i]);
} }
#ifdef CONFIG_BLK_DEV_INITRD
put_disk(initrd_disk);
#endif
devfs_unregister (devfs_handle); devfs_unregister (devfs_handle);
unregister_blkdev( MAJOR_NR, "ramdisk" ); unregister_blkdev( MAJOR_NR, "ramdisk" );
...@@ -423,6 +421,7 @@ static void __exit rd_cleanup (void) ...@@ -423,6 +421,7 @@ static void __exit rd_cleanup (void)
static int __init rd_init (void) static int __init rd_init (void)
{ {
int i; int i;
int err = -ENOMEM;
if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 ||
(rd_blocksize & (rd_blocksize-1))) { (rd_blocksize & (rd_blocksize-1))) {
...@@ -431,15 +430,32 @@ static int __init rd_init (void) ...@@ -431,15 +430,32 @@ static int __init rd_init (void)
rd_blocksize = BLOCK_SIZE; rd_blocksize = BLOCK_SIZE;
} }
#ifdef CONFIG_BLK_DEV_INITRD
initrd_disk = alloc_disk();
if (!initrd_disk)
return -ENOMEM;
initrd_disk->major = MAJOR_NR;
initrd_disk->first_minor = INITRD_MINOR;
initrd_disk->minor_shift = 0;
initrd_disk->fops = &rd_bd_op;
sprintf(initrd_disk->disk_name, "initrd");
#endif
for (i = 0; i < NUM_RAMDISKS; i++) {
rd_disks[i] = alloc_disk();
if (!rd_disks[i])
goto out;
}
if (register_blkdev(MAJOR_NR, "ramdisk", &rd_bd_op)) { if (register_blkdev(MAJOR_NR, "ramdisk", &rd_bd_op)) {
printk("RAMDISK: Could not get major %d", MAJOR_NR); printk("RAMDISK: Could not get major %d", MAJOR_NR);
return -EIO; err = -EIO;
goto out;
} }
blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request); blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request);
for (i = 0; i < NUM_RAMDISKS; i++) { for (i = 0; i < NUM_RAMDISKS; i++) {
struct gendisk *disk = rd_disks + i; struct gendisk *disk = rd_disks[i];
/* rd_size is given in kB */ /* rd_size is given in kB */
rd_length[i] = rd_size << 10; rd_length[i] = rd_size << 10;
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
...@@ -456,11 +472,11 @@ static int __init rd_init (void) ...@@ -456,11 +472,11 @@ static int __init rd_init (void)
&rd_bd_op, NULL); &rd_bd_op, NULL);
for (i = 0; i < NUM_RAMDISKS; i++) for (i = 0; i < NUM_RAMDISKS; i++)
add_disk(rd_disks + i); add_disk(rd_disks[i]);
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
/* We ought to separate initrd operations here */ /* We ought to separate initrd operations here */
add_disk(&initrd_disk); add_disk(initrd_disk);
devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR, devfs_register(devfs_handle, "initrd", DEVFS_FL_DEFAULT, MAJOR_NR,
INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL); INITRD_MINOR, S_IFBLK | S_IRUSR, &rd_bd_op, NULL);
#endif #endif
...@@ -471,6 +487,13 @@ static int __init rd_init (void) ...@@ -471,6 +487,13 @@ static int __init rd_init (void)
NUM_RAMDISKS, rd_size, rd_blocksize); NUM_RAMDISKS, rd_size, rd_blocksize);
return 0; return 0;
out:
while (i--)
put_disk(rd_disks[i]);
#ifdef CONFIG_BLK_DEV_INITRD
put_disk(initrd_disk);
#endif
return err;
} }
module_init(rd_init); module_init(rd_init);
......
...@@ -1690,13 +1690,7 @@ static int aztcd_release(struct inode *inode, struct file *file) ...@@ -1690,13 +1690,7 @@ static int aztcd_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static struct gendisk azt_disk = { static struct gendisk *azt_disk;
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.fops = &azt_fops,
.disk_name = "aztcd"
};
/* /*
* Test for presence of drive and initialize it. Called at boot time. * Test for presence of drive and initialize it. Called at boot time.
...@@ -1844,6 +1838,7 @@ static int __init aztcd_init(void) ...@@ -1844,6 +1838,7 @@ static int __init aztcd_init(void)
for (count = 0; count < AZT_TIMEOUT; for (count = 0; count < AZT_TIMEOUT;
count++) count++)
barrier(); /* Stop gcc 2.96 being smart */ barrier(); /* Stop gcc 2.96 being smart */
/* use udelay(), damnit -- AV */
if ((st = getAztStatus()) == -1) { if ((st = getAztStatus()) == -1) {
printk(KERN_WARNING "aztcd: Drive Status" printk(KERN_WARNING "aztcd: Drive Status"
...@@ -1913,21 +1908,33 @@ static int __init aztcd_init(void) ...@@ -1913,21 +1908,33 @@ static int __init aztcd_init(void)
} }
devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, devfs_register(NULL, "aztcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL); S_IFBLK | S_IRUGO | S_IWUGO, &azt_fops, NULL);
azt_disk = alloc_disk();
if (!azt_disk)
goto err_out2;
if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) {
printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech" printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech"
" CD-ROM\n", MAJOR_NR); " CD-ROM\n", MAJOR_NR);
ret = -EIO; ret = -EIO;
goto err_out; goto err_out3;
} }
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_aztcd_request, &aztSpin);
blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
add_disk(&azt_disk); azt_disk->major = MAJOR_NR;
azt_disk->first_minor = 0;
azt_disk->minor_shift = 0;
azt_disk->fops = &azt_fops;
sprintf(azt_disk->disk_name, "aztcd");
add_disk(azt_disk);
azt_invalidate_buffers(); azt_invalidate_buffers();
aztPresent = 1; aztPresent = 1;
aztCloseDoor(); aztCloseDoor();
return (0); return (0);
err_out: err_out3:
put_disk(azt_disk);
err_out2:
devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
err_out:
if ((azt_port == 0x1f0) || (azt_port == 0x170)) { if ((azt_port == 0x1f0) || (azt_port == 0x170)) {
SWITCH_IDE_MASTER; SWITCH_IDE_MASTER;
release_region(azt_port, 8); /*IDE-interface */ release_region(azt_port, 8); /*IDE-interface */
...@@ -1940,7 +1947,8 @@ static int __init aztcd_init(void) ...@@ -1940,7 +1947,8 @@ static int __init aztcd_init(void)
static void __exit aztcd_exit(void) static void __exit aztcd_exit(void)
{ {
devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0); devfs_find_and_unregister(NULL, "aztcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
del_gendisk(&azt_disk); del_gendisk(azt_disk);
put_disk(azt_disk);
if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) { if ((unregister_blkdev(MAJOR_NR, "aztcd") == -EINVAL)) {
printk("What's that: can't unregister aztcd\n"); printk("What's that: can't unregister aztcd\n");
return; return;
......
...@@ -3188,14 +3188,7 @@ static struct cdrom_device_info scd_info = { ...@@ -3188,14 +3188,7 @@ static struct cdrom_device_info scd_info = {
.name = "cdu31a" .name = "cdu31a"
}; };
static struct gendisk scd_gendisk = { static struct gendisk *scd_gendisk;
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.disk_name = "cdu31a",
.fops = &scd_bdops,
.flags = GENHD_FL_CD,
};
/* The different types of disc loading mechanisms supported */ /* The different types of disc loading mechanisms supported */
static char *load_mech[] __initdata = static char *load_mech[] __initdata =
...@@ -3299,7 +3292,8 @@ __setup("cdu31a=", cdu31a_setup); ...@@ -3299,7 +3292,8 @@ __setup("cdu31a=", cdu31a_setup);
int __init cdu31a_init(void) int __init cdu31a_init(void)
{ {
struct s_sony_drive_config drive_config; struct s_sony_drive_config drive_config;
struct gendisk *disk = &scd_gendisk; struct gendisk *disk;
int deficiency = 0;
unsigned int res_size; unsigned int res_size;
char msg[255]; char msg[255];
char buf[40]; char buf[40];
...@@ -3360,115 +3354,119 @@ int __init cdu31a_init(void) ...@@ -3360,115 +3354,119 @@ int __init cdu31a_init(void)
} }
} }
if (drive_found) { if (!drive_found)
int deficiency = 0; goto errout3;
if (!request_region(cdu31a_port, 4, "cdu31a")) if (!request_region(cdu31a_port, 4, "cdu31a"))
goto errout3; goto errout3;
if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) {
printk("Unable to get major %d for CDU-31a\n", printk("Unable to get major %d for CDU-31a\n",
MAJOR_NR); MAJOR_NR);
goto errout2; goto errout2;
} }
if (SONY_HWC_DOUBLE_SPEED(drive_config)) { disk = alloc_disk();
is_double_speed = 1; if (!disk)
} goto errout1;
disk->major = MAJOR_NR;
disk->first_minor = 0;
disk->minor_shift = 0;
sprintf(disk->disk_name, "cdu31a");
disk->fops = &scd_bdops;
disk->flags = GENHD_FL_CD;
tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */ if (SONY_HWC_DOUBLE_SPEED(drive_config))
cdu31a_irq = 0; is_double_speed = 1;
set_drive_params(sony_speed); tmp_irq = cdu31a_irq; /* Need IRQ 0 because we can't sleep here. */
cdu31a_irq = 0;
cdu31a_irq = tmp_irq; set_drive_params(sony_speed);
if (cdu31a_irq > 0) { cdu31a_irq = tmp_irq;
if (request_irq
(cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT,
"cdu31a", NULL)) {
printk
("Unable to grab IRQ%d for the CDU31A driver\n",
cdu31a_irq);
cdu31a_irq = 0;
}
}
sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n", if (cdu31a_irq > 0) {
drive_config.vendor_id, if (request_irq
drive_config.product_id, (cdu31a_irq, cdu31a_interrupt, SA_INTERRUPT,
drive_config.product_rev_level); "cdu31a", NULL)) {
sprintf(buf, " Capabilities: %s", printk
load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]); ("Unable to grab IRQ%d for the CDU31A driver\n",
strcat(msg, buf); cdu31a_irq);
if (SONY_HWC_AUDIO_PLAYBACK(drive_config)) { cdu31a_irq = 0;
strcat(msg, ", audio");
} else
deficiency |= CDC_PLAY_AUDIO;
if (SONY_HWC_EJECT(drive_config)) {
strcat(msg, ", eject");
} else
deficiency |= CDC_OPEN_TRAY;
if (SONY_HWC_LED_SUPPORT(drive_config)) {
strcat(msg, ", LED");
}
if (SONY_HWC_ELECTRIC_VOLUME(drive_config)) {
strcat(msg, ", elec. Vol");
}
if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config)) {
strcat(msg, ", sep. Vol");
}
if (is_double_speed) {
strcat(msg, ", double speed");
} else
deficiency |= CDC_SELECT_SPEED;
if (cdu31a_irq > 0) {
sprintf(buf, ", irq %d", cdu31a_irq);
strcat(msg, buf);
} }
strcat(msg, "\n"); }
is_a_cdu31a = sprintf(msg, "Sony I/F CDROM : %8.8s %16.16s %8.8s\n",
strcmp("CD-ROM CDU31A", drive_config.product_id) == 0; drive_config.vendor_id,
drive_config.product_id,
drive_config.product_rev_level);
sprintf(buf, " Capabilities: %s",
load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);
strcat(msg, buf);
if (SONY_HWC_AUDIO_PLAYBACK(drive_config))
strcat(msg, ", audio");
else
deficiency |= CDC_PLAY_AUDIO;
if (SONY_HWC_EJECT(drive_config))
strcat(msg, ", eject");
else
deficiency |= CDC_OPEN_TRAY;
if (SONY_HWC_LED_SUPPORT(drive_config))
strcat(msg, ", LED");
if (SONY_HWC_ELECTRIC_VOLUME(drive_config))
strcat(msg, ", elec. Vol");
if (SONY_HWC_ELECTRIC_VOLUME_CTL(drive_config))
strcat(msg, ", sep. Vol");
if (is_double_speed)
strcat(msg, ", double speed");
else
deficiency |= CDC_SELECT_SPEED;
if (cdu31a_irq > 0) {
sprintf(buf, ", irq %d", cdu31a_irq);
strcat(msg, buf);
}
strcat(msg, "\n");
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), is_a_cdu31a =
do_cdu31a_request, strcmp("CD-ROM CDU31A", drive_config.product_id) == 0;
&cdu31a_lock);
init_timer(&cdu31a_abort_timer); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR),
cdu31a_abort_timer.function = handle_abort_timeout; do_cdu31a_request,
&cdu31a_lock);
scd_info.dev = mk_kdev(MAJOR_NR, 0); init_timer(&cdu31a_abort_timer);
scd_info.mask = deficiency; cdu31a_abort_timer.function = handle_abort_timeout;
if (register_cdrom(&scd_info))
goto errout0;
add_disk(disk);
}
scd_info.dev = mk_kdev(MAJOR_NR, 0);
scd_info.mask = deficiency;
scd_gendisk = disk;
if (register_cdrom(&scd_info))
goto errout0;
add_disk(disk);
disk_changed = 1; disk_changed = 1;
return (0);
if (drive_found) { errout0:
return (0);
} else {
goto errout3;
}
errout0:
printk("Unable to register CDU-31a with Uniform cdrom driver\n"); printk("Unable to register CDU-31a with Uniform cdrom driver\n");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
put_disk(disk);
errout1:
if (unregister_blkdev(MAJOR_NR, "cdu31a")) { if (unregister_blkdev(MAJOR_NR, "cdu31a")) {
printk("Can't unregister block device for cdu31a\n"); printk("Can't unregister block device for cdu31a\n");
} }
errout2: errout2:
release_region(cdu31a_port, 4); release_region(cdu31a_port, 4);
errout3: errout3:
return -EIO; return -EIO;
} }
void __exit cdu31a_exit(void) void __exit cdu31a_exit(void)
{ {
del_gendisk(&scd_gendisk); del_gendisk(scd_gendisk);
put_disk(scd_gendisk);
if (unregister_cdrom(&scd_info)) { if (unregister_cdrom(&scd_info)) {
printk printk
("Can't unregister cdu31a from Uniform cdrom driver\n"); ("Can't unregister cdu31a from Uniform cdrom driver\n");
......
...@@ -1357,14 +1357,7 @@ static struct cdrom_device_info cm206_info = { ...@@ -1357,14 +1357,7 @@ static struct cdrom_device_info cm206_info = {
.name = "cm206", .name = "cm206",
}; };
static struct gendisk cm206_gendisk = { static struct gendisk *cm206_gendisk;
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.disk_name = "cm206",
.fops = &cm206_bdops,
.flags = GENHD_FL_CD,
};
/* This function probes for the adapter card. It returns the base /* This function probes for the adapter card. It returns the base
address if it has found the adapter card. One can specify a base address if it has found the adapter card. One can specify a base
...@@ -1419,7 +1412,7 @@ int __init cm206_init(void) ...@@ -1419,7 +1412,7 @@ int __init cm206_init(void)
{ {
uch e = 0; uch e = 0;
long int size = sizeof(struct cm206_struct); long int size = sizeof(struct cm206_struct);
struct gendisk *disk = &cm206_gendisk; struct gendisk *disk;
printk(KERN_INFO "cm206 cdrom driver " REVISION); printk(KERN_INFO "cm206 cdrom driver " REVISION);
cm206_base = probe_base_port(auto_probe ? 0 : cm206_base); cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
...@@ -1477,6 +1470,16 @@ int __init cm206_init(void) ...@@ -1477,6 +1470,16 @@ int __init cm206_init(void)
printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR);
goto out_blkdev; goto out_blkdev;
} }
disk = alloc_disk();
if (!disk)
goto out_disk;
disk->major = MAJOR_NR;
disk->first_minor = 0;
disk->minor_shift = 0;
sprintf(disk->disk_name, "cm206");
disk->fops = &cm206_bdops;
disk->flags = GENHD_FL_CD;
cm206_gendisk = disk;
cm206_info.dev = mk_kdev(MAJOR_NR, 0); cm206_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&cm206_info) != 0) { if (register_cdrom(&cm206_info) != 0) {
printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR); printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
...@@ -1498,6 +1501,8 @@ int __init cm206_init(void) ...@@ -1498,6 +1501,8 @@ int __init cm206_init(void)
return 0; return 0;
out_cdrom: out_cdrom:
put_disk(disk);
out_disk:
unregister_blkdev(MAJOR_NR, "cm206"); unregister_blkdev(MAJOR_NR, "cm206");
out_blkdev: out_blkdev:
free_irq(cm206_irq, NULL); free_irq(cm206_irq, NULL);
...@@ -1536,7 +1541,8 @@ int __cm206_init(void) ...@@ -1536,7 +1541,8 @@ int __cm206_init(void)
void __exit cm206_exit(void) void __exit cm206_exit(void)
{ {
del_gendisk(&cm206_gendisk); del_gendisk(cm206_gendisk);
put_disk(cm206_gendisk);
if (unregister_cdrom(&cm206_info)) { if (unregister_cdrom(&cm206_info)) {
printk("Can't unregister cdrom cm206\n"); printk("Can't unregister cdrom cm206\n");
return; return;
......
...@@ -898,20 +898,15 @@ static void update_state(void) ...@@ -898,20 +898,15 @@ static void update_state(void)
} }
#endif #endif
static struct gendisk gscd_disk = { static struct gendisk *gscd_disk;
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.fops = &gscd_fops,
.disk_name = "gscd"
};
static void __exit gscd_exit(void) static void __exit gscd_exit(void)
{ {
CLEAR_TIMER; CLEAR_TIMER;
devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0); devfs_find_and_unregister(NULL, "gscd", 0, 0, DEVFS_SPECIAL_BLK, 0);
del_gendisk(&gscd_disk); del_gendisk(gscd_disk);
put_disk(gscd_disk);
if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) { if ((unregister_blkdev(MAJOR_NR, "gscd") == -EINVAL)) {
printk("What's that: can't unregister GoldStar-module\n"); printk("What's that: can't unregister GoldStar-module\n");
return; return;
...@@ -977,11 +972,20 @@ static int __init gscd_init(void) ...@@ -977,11 +972,20 @@ static int __init gscd_init(void)
i++; i++;
} }
gscd_disk = alloc_disk();
if (!gscd_disk)
goto err_out1;
gscd_disk->major = MAJOR_NR;
gscd_disk->first_minor = 0;
gscd_disk->minor_shift = 0;
gscd_disk->fops = &gscd_fops;
sprintf(gscd_disk->disk_name, "gscd");
if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) {
printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar " printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar "
"CD-ROM\n", MAJOR_NR); "CD-ROM\n", MAJOR_NR);
ret = -EIO; ret = -EIO;
goto err_out1; goto err_out2;
} }
devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL);
...@@ -991,10 +995,13 @@ static int __init gscd_init(void) ...@@ -991,10 +995,13 @@ static int __init gscd_init(void)
disk_state = 0; disk_state = 0;
gscdPresent = 1; gscdPresent = 1;
add_disk(&gscd_disk); add_disk(gscd_disk);
printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n"); printk(KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n");
return 0; return 0;
err_out2:
put_disk(gscd_disk);
err_out1: err_out1:
release_region(gscd_port, GSCD_IO_EXTENT); release_region(gscd_port, GSCD_IO_EXTENT);
return ret; return ret;
......
...@@ -221,14 +221,7 @@ static struct cdrom_device_info mcd_info = { ...@@ -221,14 +221,7 @@ static struct cdrom_device_info mcd_info = {
.name = "mcd", .name = "mcd",
}; };
static struct gendisk mcd_gendisk = { static struct gendisk *mcd_gendisk;
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.disk_name = "mcd",
.fops = &mcd_bdops,
.flags = GENHD_FL_CD,
};
#ifndef MODULE #ifndef MODULE
static int __init mcd_setup(char *str) static int __init mcd_setup(char *str)
...@@ -1038,18 +1031,23 @@ static void mcd_release(struct cdrom_device_info *cdi) ...@@ -1038,18 +1031,23 @@ static void mcd_release(struct cdrom_device_info *cdi)
int __init mcd_init(void) int __init mcd_init(void)
{ {
struct gendisk *disk = &mcd_gendisk; struct gendisk *disk = alloc_disk();
int count; int count;
unsigned char result[3]; unsigned char result[3];
char msg[80]; char msg[80];
if (!disk) {
printk(KERN_INFO "mcd: can't allocated disk.\n");
return -ENOMEM;
}
if (mcd_port <= 0 || mcd_irq <= 0) { if (mcd_port <= 0 || mcd_irq <= 0) {
printk(KERN_INFO "mcd: not probing.\n"); printk(KERN_INFO "mcd: not probing.\n");
put_disk(disk);
return -EIO; return -EIO;
} }
if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) { if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
put_disk(disk);
return -EIO; return -EIO;
} }
if (!request_region(mcd_port, 4, "mcd")) { if (!request_region(mcd_port, 4, "mcd")) {
...@@ -1124,6 +1122,13 @@ int __init mcd_init(void) ...@@ -1124,6 +1122,13 @@ int __init mcd_init(void)
mcd_invalidate_buffers(); mcd_invalidate_buffers();
mcdPresent = 1; mcdPresent = 1;
disk->major = MAJOR_NR;
disk->first_minor = 0;
disk->minor_shift = 0;
sprintf(disk->disk_name, "mcd");
disk->fops = &mcd_bdops;
disk->flags = GENHD_FL_CD;
mcd_gendisk = disk;
mcd_info.dev = mk_kdev(MAJOR_NR, 0); mcd_info.dev = mk_kdev(MAJOR_NR, 0);
if (register_cdrom(&mcd_info) != 0) { if (register_cdrom(&mcd_info) != 0) {
...@@ -1141,6 +1146,7 @@ int __init mcd_init(void) ...@@ -1141,6 +1146,7 @@ int __init mcd_init(void)
out_region: out_region:
unregister_blkdev(MAJOR_NR, "mcd"); unregister_blkdev(MAJOR_NR, "mcd");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
put_disk(disk);
return -EIO; return -EIO;
} }
...@@ -1506,7 +1512,8 @@ static int GetToc(void) ...@@ -1506,7 +1512,8 @@ static int GetToc(void)
void __exit mcd_exit(void) void __exit mcd_exit(void)
{ {
del_gendisk(&mcd_gendisk); del_gendisk(mcd_gendisk);
put_disk(mcd_gendisk);
if (unregister_cdrom(&mcd_info)) { if (unregister_cdrom(&mcd_info)) {
printk(KERN_WARNING "Can't unregister cdrom mcd\n"); printk(KERN_WARNING "Can't unregister cdrom mcd\n");
return; return;
......
...@@ -206,7 +206,7 @@ struct s_drive_stuff { ...@@ -206,7 +206,7 @@ struct s_drive_stuff {
int status; /* last operation's error / status */ int status; /* last operation's error / status */
int readerrs; /* # of blocks read w/o error */ int readerrs; /* # of blocks read w/o error */
struct cdrom_device_info info; struct cdrom_device_info info;
struct gendisk disk; struct gendisk *disk;
}; };
...@@ -1021,11 +1021,12 @@ void __exit mcdx_exit(void) ...@@ -1021,11 +1021,12 @@ void __exit mcdx_exit(void)
struct s_drive_stuff *stuffp = mcdx_stuffp[i]; struct s_drive_stuff *stuffp = mcdx_stuffp[i];
if (!stuffp) if (!stuffp)
continue; continue;
del_gendisk(&stuffp->disk); del_gendisk(stuffp->disk);
if (unregister_cdrom(&stuffp->info)) { if (unregister_cdrom(&stuffp->info)) {
printk(KERN_WARNING "Can't unregister cdrom mcdx\n"); printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
return; continue;
} }
put_disk(stuffp->disk);
release_region((unsigned long) stuffp->wreg_data, release_region((unsigned long) stuffp->wreg_data,
MCDX_IO_SIZE); MCDX_IO_SIZE);
free_irq(stuffp->irq, NULL); free_irq(stuffp->irq, NULL);
...@@ -1075,6 +1076,13 @@ int __init mcdx_init_drive(int drive) ...@@ -1075,6 +1076,13 @@ int __init mcdx_init_drive(int drive)
return 1; return 1;
} }
disk = alloc_disk();
if (!disk) {
xwarn("init() malloc failed\n");
kfree(stuffp);
return 1;
}
xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n", xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
sizeof(*stuffp), stuffp); sizeof(*stuffp), stuffp);
...@@ -1106,6 +1114,7 @@ int __init mcdx_init_drive(int drive) ...@@ -1106,6 +1114,7 @@ int __init mcdx_init_drive(int drive)
stuffp->wreg_data + MCDX_IO_SIZE - 1); stuffp->wreg_data + MCDX_IO_SIZE - 1);
xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
kfree(stuffp); kfree(stuffp);
put_disk(disk);
xtrace(INIT, "init() continue at next drive\n"); xtrace(INIT, "init() continue at next drive\n");
return 0; /* next drive */ return 0; /* next drive */
} }
...@@ -1124,6 +1133,7 @@ int __init mcdx_init_drive(int drive) ...@@ -1124,6 +1133,7 @@ int __init mcdx_init_drive(int drive)
MCDX, stuffp->wreg_data, stuffp->irq); MCDX, stuffp->wreg_data, stuffp->irq);
xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp); xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
kfree(stuffp); kfree(stuffp);
put_disk(disk);
xtrace(INIT, "init() continue at next drive\n"); xtrace(INIT, "init() continue at next drive\n");
return 0; return 0;
} }
...@@ -1154,6 +1164,7 @@ int __init mcdx_init_drive(int drive) ...@@ -1154,6 +1164,7 @@ int __init mcdx_init_drive(int drive)
xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n", xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",
MCDX, stuffp->wreg_data, stuffp->irq); MCDX, stuffp->wreg_data, stuffp->irq);
kfree(stuffp); kfree(stuffp);
put_disk(disk);
return 0; /* next drive */ return 0; /* next drive */
} }
...@@ -1164,6 +1175,7 @@ int __init mcdx_init_drive(int drive) ...@@ -1164,6 +1175,7 @@ int __init mcdx_init_drive(int drive)
xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n", xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR); MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);
kfree(stuffp); kfree(stuffp);
put_disk(disk);
return 1; return 1;
} }
...@@ -1180,6 +1192,7 @@ int __init mcdx_init_drive(int drive) ...@@ -1180,6 +1192,7 @@ int __init mcdx_init_drive(int drive)
stuffp->irq = 0; stuffp->irq = 0;
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
kfree(stuffp); kfree(stuffp);
put_disk(disk);
return 0; return 0;
} }
...@@ -1206,13 +1219,13 @@ int __init mcdx_init_drive(int drive) ...@@ -1206,13 +1219,13 @@ int __init mcdx_init_drive(int drive)
stuffp->info.handle = stuffp; stuffp->info.handle = stuffp;
sprintf(stuffp->info.name, "mcdx%d", drive); sprintf(stuffp->info.name, "mcdx%d", drive);
stuffp->info.dev = mk_kdev(MAJOR_NR, drive); stuffp->info.dev = mk_kdev(MAJOR_NR, drive);
disk = &stuffp->disk;
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
disk->first_minor = drive; disk->first_minor = drive;
disk->minor_shift = 0; disk->minor_shift = 0;
strcpy(disk->disk_name, stuffp->info.name); strcpy(disk->disk_name, stuffp->info.name);
disk->fops = &mcdx_bdops; disk->fops = &mcdx_bdops;
disk->flags = GENHD_FL_CD; disk->flags = GENHD_FL_CD;
stuffp->disk = disk;
sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d." sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
" (Firmware version %c %x)\n", " (Firmware version %c %x)\n",
...@@ -1225,6 +1238,7 @@ int __init mcdx_init_drive(int drive) ...@@ -1225,6 +1238,7 @@ int __init mcdx_init_drive(int drive)
MCDX_IO_SIZE); MCDX_IO_SIZE);
free_irq(stuffp->irq, NULL); free_irq(stuffp->irq, NULL);
kfree(stuffp); kfree(stuffp);
put_disk(disk);
if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
xwarn("cleanup() unregister_blkdev() failed\n"); xwarn("cleanup() unregister_blkdev() failed\n");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
......
...@@ -1997,13 +1997,7 @@ __setup("optcd=", optcd_setup); ...@@ -1997,13 +1997,7 @@ __setup("optcd=", optcd_setup);
#endif /* MODULE */ #endif /* MODULE */
static struct gendisk optcd_disk = { static struct gendisk *optcd_disk;
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.fops = &opt_fops,
.disk_name = "optcd"
};
/* Test for presence of drive and initialize it. Called at boot time /* Test for presence of drive and initialize it. Called at boot time
or during module initialisation. */ or during module initialisation. */
...@@ -2016,20 +2010,33 @@ static int __init optcd_init(void) ...@@ -2016,20 +2010,33 @@ static int __init optcd_init(void)
"optcd: no Optics Storage CDROM Initialization\n"); "optcd: no Optics Storage CDROM Initialization\n");
return -EIO; return -EIO;
} }
optcd_disk = alloc_disk();
if (!optcd_disk) {
printk(KERN_ERR "optcd: can't allocate disk\n");
return -ENOMEM;
}
optcd_disk->major = MAJOR_NR;
optcd_disk->first_minor = 0;
optcd_disk->minor_shift = 0;
optcd_disk->fops = &opt_fops;
sprintf(optcd_disk->disk_name, "optcd");
if (!request_region(optcd_port, 4, "optcd")) { if (!request_region(optcd_port, 4, "optcd")) {
printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n", printk(KERN_ERR "optcd: conflict, I/O port 0x%x already used\n",
optcd_port); optcd_port);
put_disk(optcd_disk);
return -EIO; return -EIO;
} }
if (!reset_drive()) { if (!reset_drive()) {
printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port); printk(KERN_ERR "optcd: drive at 0x%x not ready\n", optcd_port);
release_region(optcd_port, 4); release_region(optcd_port, 4);
put_disk(optcd_disk);
return -EIO; return -EIO;
} }
if (!version_ok()) { if (!version_ok()) {
printk(KERN_ERR "optcd: unknown drive detected; aborting\n"); printk(KERN_ERR "optcd: unknown drive detected; aborting\n");
release_region(optcd_port, 4); release_region(optcd_port, 4);
put_disk(optcd_disk);
return -EIO; return -EIO;
} }
status = exec_cmd(COMINITDOUBLE); status = exec_cmd(COMINITDOUBLE);
...@@ -2037,11 +2044,13 @@ static int __init optcd_init(void) ...@@ -2037,11 +2044,13 @@ static int __init optcd_init(void)
printk(KERN_ERR "optcd: cannot init double speed mode\n"); printk(KERN_ERR "optcd: cannot init double speed mode\n");
release_region(optcd_port, 4); release_region(optcd_port, 4);
DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status)); DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
put_disk(optcd_disk);
return -EIO; return -EIO;
} }
if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) { if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) {
printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR); printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR);
release_region(optcd_port, 4); release_region(optcd_port, 4);
put_disk(optcd_disk);
return -EIO; return -EIO;
} }
devfs_register (NULL, "optcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, devfs_register (NULL, "optcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
...@@ -2049,7 +2058,7 @@ static int __init optcd_init(void) ...@@ -2049,7 +2058,7 @@ static int __init optcd_init(void)
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request, blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_optcd_request,
&optcd_lock); &optcd_lock);
blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
add_disk(&optcd_disk); add_disk(optcd_disk);
printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port); printk(KERN_INFO "optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
return 0; return 0;
...@@ -2059,7 +2068,8 @@ static int __init optcd_init(void) ...@@ -2059,7 +2068,8 @@ static int __init optcd_init(void)
static void __exit optcd_exit(void) static void __exit optcd_exit(void)
{ {
devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0); devfs_find_and_unregister(NULL, "optcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
del_gendisk(&optcd_disk); del_gendisk(optcd_disk);
put_disk(optcd_disk);
if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) { if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
printk(KERN_ERR "optcd: what's that: can't unregister\n"); printk(KERN_ERR "optcd: what's that: can't unregister\n");
return; return;
......
...@@ -722,7 +722,7 @@ static struct sbpcd_drive { ...@@ -722,7 +722,7 @@ static struct sbpcd_drive {
u_char mode_xb_8; u_char mode_xb_8;
u_char delay; u_char delay;
struct cdrom_device_info *sbpcd_infop; struct cdrom_device_info *sbpcd_infop;
struct gendisk disk; struct gendisk *disk;
} D_S[NR_SBPCD]; } D_S[NR_SBPCD];
static struct sbpcd_drive *current_drive = D_S; static struct sbpcd_drive *current_drive = D_S;
...@@ -5609,6 +5609,7 @@ static int __init config_spea(void) ...@@ -5609,6 +5609,7 @@ static int __init config_spea(void)
static devfs_handle_t devfs_handle; static devfs_handle_t devfs_handle;
/* FIXME: cleanups after failed allocations are too ugly for words */
#ifdef MODULE #ifdef MODULE
int __init __sbpcd_init(void) int __init __sbpcd_init(void)
#else #else
...@@ -5830,7 +5831,7 @@ int __init sbpcd_init(void) ...@@ -5830,7 +5831,7 @@ int __init sbpcd_init(void)
sbpcd_infop->dev = mk_kdev(MAJOR_NR, j); sbpcd_infop->dev = mk_kdev(MAJOR_NR, j);
sbpcd_infop->handle = p; sbpcd_infop->handle = p;
p->sbpcd_infop = sbpcd_infop; p->sbpcd_infop = sbpcd_infop;
disk = &p->disk; disk = alloc_disk();
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
disk->first_minor = j; disk->first_minor = j;
disk->minor_shift = 0; disk->minor_shift = 0;
...@@ -5839,6 +5840,7 @@ int __init sbpcd_init(void) ...@@ -5839,6 +5840,7 @@ int __init sbpcd_init(void)
disk->flags = GENHD_FL_CD; disk->flags = GENHD_FL_CD;
sprintf(nbuff, "c0t%d", p->drv_id); sprintf(nbuff, "c0t%d", p->drv_id);
disk->de = devfs_mk_dir(devfs_handle, nbuff, NULL); disk->de = devfs_mk_dir(devfs_handle, nbuff, NULL);
p->disk = disk;
if (register_cdrom(sbpcd_infop)) if (register_cdrom(sbpcd_infop))
{ {
printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n");
...@@ -5869,7 +5871,8 @@ void sbpcd_exit(void) ...@@ -5869,7 +5871,8 @@ void sbpcd_exit(void)
for (j=0;j<NR_SBPCD;j++) for (j=0;j<NR_SBPCD;j++)
{ {
if (D_S[j].drv_id==-1) continue; if (D_S[j].drv_id==-1) continue;
del_gendisk(&D_S[j].disk); del_gendisk(D_S[j].disk);
put_disk(D_S[j].disk);
vfree(D_S[j].sbp_buf); vfree(D_S[j].sbp_buf);
if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf); if (D_S[j].sbp_audsiz>0) vfree(D_S[j].aud_buf);
devfs_unregister(D_S[j].disk.de); devfs_unregister(D_S[j].disk.de);
......
...@@ -159,8 +159,6 @@ static struct timer_list sjcd_delay_timer; ...@@ -159,8 +159,6 @@ static struct timer_list sjcd_delay_timer;
#define CLEAR_TIMER del_timer( &sjcd_delay_timer ) #define CLEAR_TIMER del_timer( &sjcd_delay_timer )
static int sjcd_cleanup(void);
/* /*
* Set up device, i.e., use command line data to set * Set up device, i.e., use command line data to set
* base address. * base address.
...@@ -1664,14 +1662,7 @@ static struct { ...@@ -1664,14 +1662,7 @@ static struct {
unsigned char major, minor; unsigned char major, minor;
} sjcd_version; } sjcd_version;
static struct gendisk sjcd_disk = static struct gendisk *sjcd_disk;
{
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.fops = &sjcd_fops,
.disk_name = "sjcd"
};
/* /*
* Test for presence of drive and initialize it. Called at boot time. * Test for presence of drive and initialize it. Called at boot time.
...@@ -1698,12 +1689,22 @@ static int __init sjcd_init(void) ...@@ -1698,12 +1689,22 @@ static int __init sjcd_init(void)
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sjcd_request, &sjcd_lock);
blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048); blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), 2048);
sjcd_disk = alloc_disk();
if (!sjcd_disk) {
printk(KERN_ERR "SJCD: can't allocate disk");
goto out1;
}
sjcd_disk->major = MAJOR_NR,
sjcd_disk->first_minor = 0,
sjcd_disk->minor_shift = 0,
sjcd_disk->fops = &sjcd_fops,
sprintf(sjcd_disk->disk_name, "sjcd");
if (check_region(sjcd_base, 4)) { if (check_region(sjcd_base, 4)) {
printk printk
("SJCD: Init failed, I/O port (%X) is already in use\n", ("SJCD: Init failed, I/O port (%X) is already in use\n",
sjcd_base); sjcd_base);
sjcd_cleanup(); goto out2;
return (-EIO);
} }
/* /*
...@@ -1725,8 +1726,7 @@ static int __init sjcd_init(void) ...@@ -1725,8 +1726,7 @@ static int __init sjcd_init(void)
} }
if (i == 0 || sjcd_command_failed) { if (i == 0 || sjcd_command_failed) {
printk(" reset failed, no drive found.\n"); printk(" reset failed, no drive found.\n");
sjcd_cleanup(); goto out3;
return (-EIO);
} else } else
printk("\n"); printk("\n");
...@@ -1748,8 +1748,7 @@ static int __init sjcd_init(void) ...@@ -1748,8 +1748,7 @@ static int __init sjcd_init(void)
} }
if (i == 0 || sjcd_command_failed) { if (i == 0 || sjcd_command_failed) {
printk(" get version failed, no drive found.\n"); printk(" get version failed, no drive found.\n");
sjcd_cleanup(); goto out3;
return (-EIO);
} }
if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) { if (sjcd_load_response(&sjcd_version, sizeof(sjcd_version)) == 0) {
...@@ -1757,8 +1756,7 @@ static int __init sjcd_init(void) ...@@ -1757,8 +1756,7 @@ static int __init sjcd_init(void)
(int) sjcd_version.minor); (int) sjcd_version.minor);
} else { } else {
printk(" read version failed, no drive found.\n"); printk(" read version failed, no drive found.\n");
sjcd_cleanup(); goto out3;
return (-EIO);
} }
/* /*
...@@ -1781,8 +1779,7 @@ static int __init sjcd_init(void) ...@@ -1781,8 +1779,7 @@ static int __init sjcd_init(void)
} }
if (i == 0 || sjcd_command_failed) { if (i == 0 || sjcd_command_failed) {
printk(" get status failed, no drive found.\n"); printk(" get status failed, no drive found.\n");
sjcd_cleanup(); goto out3;
return (-EIO);
} else } else
printk("\n"); printk("\n");
} }
...@@ -1790,33 +1787,32 @@ static int __init sjcd_init(void) ...@@ -1790,33 +1787,32 @@ static int __init sjcd_init(void)
printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base); printk(KERN_INFO "SJCD: Status: port=0x%x.\n", sjcd_base);
devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, devfs_register(NULL, "sjcd", DEVFS_FL_DEFAULT, MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL); S_IFBLK | S_IRUGO | S_IWUGO, &sjcd_fops, NULL);
add_disk(&sjcd_disk); add_disk(sjcd_disk);
sjcd_present++; sjcd_present++;
return (0); return (0);
} out3:
release_region(sjcd_base, 4);
static int sjcd_cleanup(void) blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
{ out2:
put_disk(sjcd_disk);
out1:
if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL)) if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
printk("SJCD: cannot unregister device.\n"); printk("SJCD: cannot unregister device.\n");
else { return (-EIO);
release_region(sjcd_base, 4);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
}
return (0);
} }
static void __exit sjcd_exit(void) static void __exit sjcd_exit(void)
{ {
devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0); devfs_find_and_unregister(NULL, "sjcd", 0, 0, DEVFS_SPECIAL_BLK, 0);
del_gendisk(&sjcd_disk); del_gendisk(sjcd_disk);
if (sjcd_cleanup()) put_disk(sjcd_disk);
printk("SJCD: module: cannot be removed.\n"); release_region(sjcd_base, 4);
else blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
printk(KERN_INFO "SJCD: module: removed.\n"); if ((unregister_blkdev(MAJOR_NR, "sjcd") == -EINVAL))
printk("SJCD: cannot unregister device.\n");
printk(KERN_INFO "SJCD: module: removed.\n");
return (0);
} }
module_init(sjcd_init); module_init(sjcd_init);
......
...@@ -1454,14 +1454,7 @@ static struct block_device_operations cdu_fops = ...@@ -1454,14 +1454,7 @@ static struct block_device_operations cdu_fops =
.check_media_change = cdu535_check_media_change, .check_media_change = cdu535_check_media_change,
}; };
static struct gendisk cdu_disk = static struct gendisk *cdu_disk;
{
.major = MAJOR_NR,
.first_minor = 0,
.minor_shift = 0,
.fops = &cdu_fops,
.disk_name = "cdu",
};
/* /*
* Initialize the driver. * Initialize the driver.
...@@ -1477,6 +1470,7 @@ static int __init sony535_init(void) ...@@ -1477,6 +1470,7 @@ static int __init sony535_init(void)
int tmp_irq; int tmp_irq;
int i; int i;
devfs_handle_t sony_devfs_handle; devfs_handle_t sony_devfs_handle;
int err;
/* Setting the base I/O address to 0 will disable it. */ /* Setting the base I/O address to 0 will disable it. */
if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0)) if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
...@@ -1518,145 +1512,142 @@ static int __init sony535_init(void) ...@@ -1518,145 +1512,142 @@ static int __init sony535_init(void)
sony_sleep(); sony_sleep();
} }
if (got_result && (check_drive_status() != TIME_OUT)) { if (!got_result || check_drive_status() == TIME_OUT)
/* CD-ROM drive responded -- get the drive configuration */ goto Enodev;
cmd_buff[0] = SONY535_INQUIRY;
if (do_sony_cmd(cmd_buff, 1, status, /* CD-ROM drive responded -- get the drive configuration */
(Byte *)&drive_config, 28, 1) == 0) { cmd_buff[0] = SONY535_INQUIRY;
/* was able to get the configuration, if (do_sony_cmd(cmd_buff, 1, status, (Byte *)&drive_config, 28, 1) != 0)
* set drive mode as rest of init goto Enodev;
*/
/* was able to get the configuration,
* set drive mode as rest of init
*/
#if DEBUG > 0 #if DEBUG > 0
/* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */ /* 0x50 == CADDY_NOT_INSERTED | NOT_SPINNING */
if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 ) if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
printk(CDU535_MESSAGE_NAME printk(CDU535_MESSAGE_NAME
"Inquiry command returned status = 0x%x\n", status[0]); "Inquiry command returned status = 0x%x\n", status[0]);
#endif #endif
/* now ready to use interrupts, if available */ /* now ready to use interrupts, if available */
sony535_irq_used = tmp_irq; sony535_irq_used = tmp_irq;
/* A negative sony535_irq_used will attempt an autoirq. */ /* A negative sony535_irq_used will attempt an autoirq. */
if (sony535_irq_used < 0) { if (sony535_irq_used < 0) {
unsigned long irq_mask, delay; unsigned long irq_mask, delay;
irq_mask = probe_irq_on(); irq_mask = probe_irq_on();
enable_interrupts(); enable_interrupts();
outb(0, read_status_reg); /* does a reset? */ outb(0, read_status_reg); /* does a reset? */
delay = jiffies + HZ/10; delay = jiffies + HZ/10;
while (time_before(jiffies, delay)) ; while (time_before(jiffies, delay)) ;
sony535_irq_used = probe_irq_off(irq_mask); sony535_irq_used = probe_irq_off(irq_mask);
disable_interrupts(); disable_interrupts();
} }
if (sony535_irq_used > 0) { if (sony535_irq_used > 0) {
if (request_irq(sony535_irq_used, cdu535_interrupt, if (request_irq(sony535_irq_used, cdu535_interrupt,
SA_INTERRUPT, CDU535_HANDLE, NULL)) { SA_INTERRUPT, CDU535_HANDLE, NULL)) {
printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
" driver; polling instead.\n", sony535_irq_used); " driver; polling instead.\n", sony535_irq_used);
sony535_irq_used = 0; sony535_irq_used = 0;
}
}
cmd_buff[0] = SONY535_SET_DRIVE_MODE;
cmd_buff[1] = 0x0; /* default audio */
if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
/* set the drive mode successful, we are set! */
sony_buffer_size = SONY535_BUFFER_SIZE;
sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
drive_config.vendor_id,
drive_config.product_id,
drive_config.product_rev_level);
printk(" base address %03X, ", sony535_cd_base_io);
if (tmp_irq > 0)
printk("IRQ%d, ", tmp_irq);
printk("using %d byte buffer\n", sony_buffer_size);
sony_devfs_handle = devfs_register (NULL, CDU535_HANDLE,
DEVFS_FL_DEFAULT,
MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO,
&cdu_fops, NULL);
if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
printk("Unable to get major %d for %s\n",
MAJOR_NR, CDU535_MESSAGE_NAME);
return -EIO;
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR),
do_cdu535_request,
&sonycd535_lock);
blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE);
sony_toc = (struct s535_sony_toc *)
kmalloc(sizeof *sony_toc, GFP_KERNEL);
if (sony_toc == NULL) {
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
devfs_unregister(sony_devfs_handle);
return -ENOMEM;
}
last_sony_subcode = (struct s535_sony_subcode *)
kmalloc(sizeof *last_sony_subcode, GFP_KERNEL);
if (last_sony_subcode == NULL) {
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
kfree(sony_toc);
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
devfs_unregister(sony_devfs_handle);
return -ENOMEM;
}
sony_buffer = (Byte **)
kmalloc(4 * sony_buffer_sectors, GFP_KERNEL);
if (sony_buffer == NULL) {
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
kfree(sony_toc);
kfree(last_sony_subcode);
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
devfs_unregister(sony_devfs_handle);
return -ENOMEM;
}
for (i = 0; i < sony_buffer_sectors; i++) {
sony_buffer[i] =
(Byte *)kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
if (sony_buffer[i] == NULL) {
while (--i>=0)
kfree(sony_buffer[i]);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
kfree(sony_buffer);
kfree(sony_toc);
kfree(last_sony_subcode);
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
devfs_unregister(sony_devfs_handle);
return -ENOMEM;
}
}
initialized = 1;
}
} }
} }
cmd_buff[0] = SONY535_SET_DRIVE_MODE;
if (!initialized) { cmd_buff[1] = 0x0; /* default audio */
printk("Did not find a " CDU535_MESSAGE_NAME " drive\n"); if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) != 0)
return -EIO; goto Enodev_irq;
/* set the drive mode successful, we are set! */
sony_buffer_size = SONY535_BUFFER_SIZE;
sony_buffer_sectors = sony_buffer_size / CDU535_BLOCK_SIZE;
printk(KERN_INFO CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
drive_config.vendor_id,
drive_config.product_id,
drive_config.product_rev_level);
printk(" base address %03X, ", sony535_cd_base_io);
if (tmp_irq > 0)
printk("IRQ%d, ", tmp_irq);
printk("using %d byte buffer\n", sony_buffer_size);
sony_devfs_handle = devfs_register (NULL, CDU535_HANDLE,
DEVFS_FL_DEFAULT,
MAJOR_NR, 0,
S_IFBLK | S_IRUGO | S_IWUGO,
&cdu_fops, NULL);
if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
printk("Unable to get major %d for %s\n",
MAJOR_NR, CDU535_MESSAGE_NAME);
err = -EIO;
goto out1;
} }
if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_cdu535_request,
{ &sonycd535_lock);
printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n", blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CDU535_BLOCK_SIZE);
sony535_cd_base_io); sony_toc = kamlloc(sizeof(struct s535_sony_toc), GFP_KERNEL);
for (i = 0; i < sony_buffer_sectors; i++) err = -ENOMEM;
if (sony_buffer[i]) if (!sony_toc)
goto out2;
last_sony_subcode = kmalloc(sizeof(struct s535_sony_subcode), GFP_KERNEL);
if (!last_sony_subcode)
goto out3;
sony_buffer = kmalloc(sizeof(Byte *) * sony_buffer_sectors, GFP_KERNEL);
if (!sony_buffer)
goto out4;
for (i = 0; i < sony_buffer_sectors; i++) {
sony_buffer[i] = kmalloc(CDU535_BLOCK_SIZE, GFP_KERNEL);
if (!sony_buffer[i]) {
while (--i>=0)
kfree(sony_buffer[i]); kfree(sony_buffer[i]);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); goto out5;
kfree(sony_buffer);
kfree(sony_toc);
kfree(last_sony_subcode);
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
devfs_unregister(sony_devfs_handle);
if (sony535_irq_used)
free_irq(sony535_irq_used, NULL);
return -EIO;
} }
add_disk(&cdu_disk); }
initialized = 1;
cdu_disk = alloc_disk();
if (!cdu_disk)
goto out6;
cdu_disk->major = MAJOR_NR;
cdu_disk->first_minor = 0;
cdu_disk->minor_shift = 0;
cdu_disk->fops = &cdu_fops;
sprintf(cdu_disk->disk_name, "cdu");
if (!request_region(sony535_cd_base_io, 4, CDU535_HANDLE)) {
printk(KERN_WARNING"sonycd535: Unable to request region 0x%x\n",
sony535_cd_base_io);
goto out7;
}
add_disk(cdu_disk);
return 0; return 0;
out7:
put_disk(cdu_disk);
out6:
for (i = 0; i < sony_buffer_sectors; i++)
if (sony_buffer[i])
kfree(sony_buffer[i]);
out5:
kfree(sony_buffer);
out4:
kfree(last_sony_subcode);
out3:
kfree(sony_toc);
out2:
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
unregister_blkdev(MAJOR_NR, CDU535_HANDLE);
out1:
devfs_unregister(sony_devfs_handle);
if (sony535_irq_used)
free_irq(sony535_irq_used, NULL);
return err;
Enodev_irq:
if (sony535_irq_used)
free_irq(sony535_irq_used, NULL);
Enodev:
printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
return -EIO;
} }
#ifndef MODULE #ifndef MODULE
...@@ -1707,7 +1698,8 @@ static sony535_exit(void) ...@@ -1707,7 +1698,8 @@ static sony535_exit(void)
kfree(sony_toc); kfree(sony_toc);
devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0, devfs_find_and_unregister(NULL, CDU535_HANDLE, 0, 0,
DEVFS_SPECIAL_BLK, 0); DEVFS_SPECIAL_BLK, 0);
del_gendisk(&cdu_disk); del_gendisk(cdu_disk);
put_disk(cdu_disk);
if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL) if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n"); printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
else else
......
...@@ -138,6 +138,8 @@ static struct hd_i_struct hd_info[MAX_HD]; ...@@ -138,6 +138,8 @@ static struct hd_i_struct hd_info[MAX_HD];
static int NR_HD; static int NR_HD;
#endif #endif
static struct gendisk *hd_gendisk[MAX_HD];
static struct timer_list device_timer; static struct timer_list device_timer;
#define TIMEOUT_VALUE (6*HZ) #define TIMEOUT_VALUE (6*HZ)
...@@ -590,14 +592,15 @@ static void hd_request(void) ...@@ -590,14 +592,15 @@ static void hd_request(void)
dev = DEVICE_NR(CURRENT->rq_dev); dev = DEVICE_NR(CURRENT->rq_dev);
block = CURRENT->sector; block = CURRENT->sector;
nsect = CURRENT->nr_sectors; nsect = CURRENT->nr_sectors;
if (dev >= NR_HD || block >= get_capacity(hd_gendisk+dev) || if (dev >= NR_HD) {
((block+nsect) > get_capacity(hd_gendisk+unit))) { printk("hd: bad disk number: %d\n", dev);
if (dev >= NR_HD) end_request(CURRENT, 0);
printk("hd: bad minor number: device=%s\n", goto repeat;
kdevname(CURRENT->rq_dev)); }
else if (block >= get_capacity(hd_gendisk[dev]) ||
printk("hd%c: bad access: block=%d, count=%d\n", ((block+nsect) > get_capacity(hd_gendisk[dev]))) {
dev+'a', block, nsect); printk("%s: bad access: block=%d, count=%d\n",
hd_gendisk[dev]->disk_name, block, nsect);
end_request(CURRENT, 0); end_request(CURRENT, 0);
goto repeat; goto repeat;
} }
...@@ -691,22 +694,6 @@ static int hd_open(struct inode * inode, struct file * filp) ...@@ -691,22 +694,6 @@ static int hd_open(struct inode * inode, struct file * filp)
extern struct block_device_operations hd_fops; extern struct block_device_operations hd_fops;
static struct gendisk hd_gendisk[2] = {
{
.major = MAJOR_NR,
.first_minor = 0,
.disk_name = "hda",
.minor_shift = 6,
.fops = &hd_fops,
},{
.major = MAJOR_NR,
.first_minor = 64,
.disk_name = "hdb",
.minor_shift = 6,
.fops = &hd_fops,
}
};
static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
void (*handler)(void) = do_hd; void (*handler)(void) = do_hd;
...@@ -733,10 +720,18 @@ static struct block_device_operations hd_fops = { ...@@ -733,10 +720,18 @@ static struct block_device_operations hd_fops = {
* We enable interrupts in some of the routines after making sure it's * We enable interrupts in some of the routines after making sure it's
* safe. * safe.
*/ */
static void __init hd_geninit(void)
static int __init hd_init(void)
{ {
int drive; int drive;
if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
return -1;
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
init_timer(&device_timer);
device_timer.function = hd_times_out;
blk_queue_hardsect_size(QUEUE, 512); blk_queue_hardsect_size(QUEUE, 512);
#ifdef __i386__ #ifdef __i386__
...@@ -805,57 +800,68 @@ static void __init hd_geninit(void) ...@@ -805,57 +800,68 @@ static void __init hd_geninit(void)
" on kernel command line\n"); " on kernel command line\n");
} }
#endif #endif
if (!NR_HD)
goto out;
for (drive=0 ; drive < NR_HD ; drive++) {
struct gendisk *disk = alloc_disk();
if (!disk)
goto Enomem;
disk->major = MAJOR_NR;
disk->first_minor = drive << 6;
disk->minor_shift = 6;
disk->fops = &hd_fops;
sprintf(disk->disk_name, "hd%c", 'a'+drive);
hd_gendisk[drive] = disk;
}
for (drive=0 ; drive < NR_HD ; drive++) { for (drive=0 ; drive < NR_HD ; drive++) {
sector_t size = hd_info[drive].head * sector_t size = hd_info[drive].head *
hd_info[drive].sect * hd_info[drive].cyl; hd_info[drive].sect * hd_info[drive].cyl;
set_capacity(hd_gendisk + drive, size); set_capacity(hd_gendisk[drive], size);
printk ("%s: %ldMB, CHS=%d/%d/%d\n", hd_gendisk[drive].disk_name, printk ("%s: %ldMB, CHS=%d/%d/%d\n",
hd_gendisk[drive]->disk_name,
size / 2048, hd_info[drive].cyl, size / 2048, hd_info[drive].cyl,
hd_info[drive].head, hd_info[drive].sect); hd_info[drive].head, hd_info[drive].sect);
} }
if (!NR_HD)
return;
if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) { if (request_irq(HD_IRQ, hd_interrupt, SA_INTERRUPT, "hd", NULL)) {
printk("hd: unable to get IRQ%d for the hard disk driver\n", printk("hd: unable to get IRQ%d for the hard disk driver\n",
HD_IRQ); HD_IRQ);
NR_HD = 0; goto out1;
return;
} }
if (!request_region(HD_DATA, 8, "hd")) { if (!request_region(HD_DATA, 8, "hd")) {
printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA); printk(KERN_WARNING "hd: port 0x%x busy\n", HD_DATA);
NR_HD = 0; goto out2;
free_irq(HD_IRQ, NULL);
return;
} }
if (!request_region(HD_CMD, 1, "hd(cmd)")) { if (!request_region(HD_CMD, 1, "hd(cmd)")) {
printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD); printk(KERN_WARNING "hd: port 0x%x busy\n", HD_CMD);
NR_HD = 0; goto out3;
free_irq(HD_IRQ, NULL);
release_region(HD_DATA, 8);
return;
} }
for(drive=0; drive < NR_HD; drive++) { for(drive=0; drive < NR_HD; drive++) {
struct hd_i_struct *p = hd_info + drive; struct hd_i_struct *p = hd_info + drive;
set_capacity(hd_gendisk + drive, p->head * p->sect * p->cyl); set_capacity(hd_gendisk[drive], p->head * p->sect * p->cyl);
add_disk(hd_gendisk + drive); add_disk(hd_gendisk[drive]);
} }
}
static int __init hd_init(void)
{
if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) {
printk("hd: unable to get major %d for hard disk\n",MAJOR_NR);
return -1;
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
init_timer(&device_timer);
device_timer.function = hd_times_out;
hd_geninit();
return 0; return 0;
out3:
release_region(HD_DATA, 8);
out2:
free_irq(HD_IRQ, NULL);
out1:
for (drive = 0; drive < NR_HD; drive++)
put_disk(hd_gendisk[drive]);
NR_HD = 0;
out:
del_timer(&device_timer);
unregister_blkdev(MAJOR_NR,"hd");
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
return -1;
Enomem:
while (drive--)
put_disk(hd_gendisk[drive]);
goto out;
} }
static int parse_hd_setup (char *line) { static int parse_hd_setup (char *line) {
......
...@@ -1389,10 +1389,9 @@ static int do_md_run(mddev_t * mddev) ...@@ -1389,10 +1389,9 @@ static int do_md_run(mddev_t * mddev)
#endif #endif
} }
disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); disk = alloc_disk();
if (!disk) if (!disk)
return -ENOMEM; return -ENOMEM;
memset(disk, 0, sizeof(struct gendisk));
disk->major = MD_MAJOR; disk->major = MD_MAJOR;
disk->first_minor = mdidx(mddev); disk->first_minor = mdidx(mddev);
disk->minor_shift = 0; disk->minor_shift = 0;
...@@ -1408,7 +1407,7 @@ static int do_md_run(mddev_t * mddev) ...@@ -1408,7 +1407,7 @@ static int do_md_run(mddev_t * mddev)
if (err) { if (err) {
printk(KERN_ERR "md: pers->run() failed ...\n"); printk(KERN_ERR "md: pers->run() failed ...\n");
mddev->pers = NULL; mddev->pers = NULL;
kfree(disk); put_disk(disk);
return -EINVAL; return -EINVAL;
} }
...@@ -1538,7 +1537,7 @@ static int do_md_stop(mddev_t * mddev, int ro) ...@@ -1538,7 +1537,7 @@ static int do_md_stop(mddev_t * mddev, int ro)
if (disk) { if (disk) {
del_gendisk(disk); del_gendisk(disk);
kfree(disk); put_disk(disk);
} }
} else } else
......
...@@ -1223,18 +1223,17 @@ static void ftl_notify_add(struct mtd_info *mtd) ...@@ -1223,18 +1223,17 @@ static void ftl_notify_add(struct mtd_info *mtd)
} }
partition = kmalloc(sizeof(partition_t), GFP_KERNEL); partition = kmalloc(sizeof(partition_t), GFP_KERNEL);
disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); disk = alloc_disk();
if (!partition||!disk) { if (!partition||!disk) {
printk(KERN_WARNING "No memory to scan for FTL on %s\n", printk(KERN_WARNING "No memory to scan for FTL on %s\n",
mtd->name); mtd->name);
kfree(partition); kfree(partition);
kfree(disk); put_disk(disk);
return; return;
} }
memset(partition, 0, sizeof(partition_t)); memset(partition, 0, sizeof(partition_t));
memset(disk, 0, sizeof(struct gendisk));
sprintf(disk->disk_name, "ftl%c", 'a' + device); sprintf(disk->disk_name, "ftl%c", 'a' + device);
disk->major = FTL_MAJOR; disk->major = FTL_MAJOR;
disk->first_minor = device << 4; disk->first_minor = device << 4;
...@@ -1255,7 +1254,7 @@ static void ftl_notify_add(struct mtd_info *mtd) ...@@ -1255,7 +1254,7 @@ static void ftl_notify_add(struct mtd_info *mtd)
#endif #endif
} else { } else {
kfree(partition); kfree(partition);
kfree(disk); put_disk(disk);
} }
} }
...@@ -1281,7 +1280,7 @@ static void ftl_notify_remove(struct mtd_info *mtd) ...@@ -1281,7 +1280,7 @@ static void ftl_notify_remove(struct mtd_info *mtd)
myparts[i]->state = 0; myparts[i]->state = 0;
del_gendisk(myparts[i]->disk); del_gendisk(myparts[i]->disk);
kfree(myparts[i]->disk); put_disk(myparts[i]->disk);
kfree(myparts[i]); kfree(myparts[i]);
myparts[i] = NULL; myparts[i] = NULL;
} }
......
...@@ -42,7 +42,7 @@ static struct mtdblk_dev { ...@@ -42,7 +42,7 @@ static struct mtdblk_dev {
unsigned long cache_offset; unsigned long cache_offset;
unsigned int cache_size; unsigned int cache_size;
enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
struct gendisk disk; struct gendisk *disk;
} *mtdblks[MAX_MTD_DEVICES]; } *mtdblks[MAX_MTD_DEVICES];
static spinlock_t mtdblks_lock; static spinlock_t mtdblks_lock;
...@@ -263,6 +263,7 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -263,6 +263,7 @@ static int mtdblock_open(struct inode *inode, struct file *file)
struct mtdblk_dev *mtdblk; struct mtdblk_dev *mtdblk;
struct mtd_info *mtd; struct mtd_info *mtd;
int dev = minor(inode->i_rdev); int dev = minor(inode->i_rdev);
struct gendisk *disk;
DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
...@@ -294,10 +295,9 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -294,10 +295,9 @@ static int mtdblock_open(struct inode *inode, struct file *file)
spin_unlock(&mtdblks_lock); spin_unlock(&mtdblks_lock);
mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL);
if (!mtdblk) { disk = alloc_disk();
put_mtd_device(mtd); if (!mtdblk || !disk)
return -ENOMEM; goto Enomem;
}
memset(mtdblk, 0, sizeof(*mtdblk)); memset(mtdblk, 0, sizeof(*mtdblk));
mtdblk->count = 1; mtdblk->count = 1;
mtdblk->mtd = mtd; mtdblk->mtd = mtd;
...@@ -308,17 +308,15 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -308,17 +308,15 @@ static int mtdblock_open(struct inode *inode, struct file *file)
mtdblk->mtd->erasesize) { mtdblk->mtd->erasesize) {
mtdblk->cache_size = mtdblk->mtd->erasesize; mtdblk->cache_size = mtdblk->mtd->erasesize;
mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize);
if (!mtdblk->cache_data) { if (!mtdblk->cache_data)
put_mtd_device(mtdblk->mtd); goto Enomem;
kfree(mtdblk);
return -ENOMEM;
}
} }
mtdblk->disk.major = MAJOR_NR; disk->major = MAJOR_NR;
mtdblk->disk.first_minor = dev; disk->first_minor = dev;
mtdblk->disk.minor_shift = 0; disk->minor_shift = 0;
mtdblk->disk.fops = &mtd_fops; disk->fops = &mtd_fops;
sprintf(mtdblk->disk.disk_name, "mtd%d", dev); sprintf(disk->disk_name, "mtd%d", dev);
mtdblk->disk = disk;
/* OK, we've created a new one. Add it to the list. */ /* OK, we've created a new one. Add it to the list. */
...@@ -331,19 +329,25 @@ static int mtdblock_open(struct inode *inode, struct file *file) ...@@ -331,19 +329,25 @@ static int mtdblock_open(struct inode *inode, struct file *file)
put_mtd_device(mtdblk->mtd); put_mtd_device(mtdblk->mtd);
vfree(mtdblk->cache_data); vfree(mtdblk->cache_data);
kfree(mtdblk); kfree(mtdblk);
put_disk(disk);
return 0; return 0;
} }
mtdblks[dev] = mtdblk; mtdblks[dev] = mtdblk;
set_capacity(&mtdblk->disk, mtdblk->mtd->size/512); set_capacity(disk, mtdblk->mtd->size/512);
add_disk(&mtdblk->disk); add_disk(disk);
set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE));
spin_unlock(&mtdblks_lock); spin_unlock(&mtdblks_lock);
DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
return 0; return 0;
Enomem:
put_mtd_device(mtd);
put_disk(disk);
kfree(mtdblk);
return -ENOMEM;
} }
static release_t mtdblock_release(struct inode *inode, struct file *file) static release_t mtdblock_release(struct inode *inode, struct file *file)
...@@ -367,7 +371,8 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) ...@@ -367,7 +371,8 @@ static release_t mtdblock_release(struct inode *inode, struct file *file)
/* It was the last usage. Free the device */ /* It was the last usage. Free the device */
mtdblks[dev] = NULL; mtdblks[dev] = NULL;
spin_unlock(&mtdblks_lock); spin_unlock(&mtdblks_lock);
del_gendisk(&mtdblk->disk); del_gendisk(mtdblk->disk);
put_disk(mtdblk->disk);
if (mtdblk->mtd->sync) if (mtdblk->mtd->sync)
mtdblk->mtd->sync(mtdblk->mtd); mtdblk->mtd->sync(mtdblk->mtd);
put_mtd_device(mtdblk->mtd); put_mtd_device(mtdblk->mtd);
......
...@@ -29,13 +29,13 @@ static int debug = MTDBLOCK_DEBUG; ...@@ -29,13 +29,13 @@ static int debug = MTDBLOCK_DEBUG;
MODULE_PARM(debug, "i"); MODULE_PARM(debug, "i");
#endif #endif
static struct gendisk mtd_disks[MAX_MTD_DEVICES]; static struct gendisk *mtd_disks[MAX_MTD_DEVICES];
static int mtdblock_open(struct inode *inode, struct file *file) static int mtdblock_open(struct inode *inode, struct file *file)
{ {
struct mtd_info *mtd = NULL; struct mtd_info *mtd = NULL;
int dev = minor(inode->i_rdev); int dev = minor(inode->i_rdev);
struct gendisk *disk = mtd_disks + dev; struct gendisk *disk = mtd_disks[dev];
DEBUG(1,"mtdblock_open\n"); DEBUG(1,"mtdblock_open\n");
...@@ -73,7 +73,7 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) ...@@ -73,7 +73,7 @@ static release_t mtdblock_release(struct inode *inode, struct file *file)
release_return(-ENODEV); release_return(-ENODEV);
} }
del_gendisk(mtd_disks + dev); del_gendisk(mtd_disks[dev]);
if (mtd->sync) if (mtd->sync)
mtd->sync(mtd); mtd->sync(mtd);
...@@ -218,30 +218,42 @@ static struct block_device_operations mtd_fops = ...@@ -218,30 +218,42 @@ static struct block_device_operations mtd_fops =
int __init init_mtdblock(void) int __init init_mtdblock(void)
{ {
int err = -ENOMEM;
int i; int i;
if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
MTD_BLOCK_MAJOR);
return -EAGAIN;
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request);
for (i = 0; i < MAX_MTD_DEVICES; i++) { for (i = 0; i < MAX_MTD_DEVICES; i++) {
struct gendisk *disk = mtd_disks + i; struct gendisk *disk = alloc_disk();
if (!disk)
goto out;
disk->major = MAJOR_NR; disk->major = MAJOR_NR;
disk->first_minor = i; disk->first_minor = i;
sprintf(disk->disk_name, "mtdblock%d", i); sprintf(disk->disk_name, "mtdblock%d", i);
disk->fops = &mtd_fops; disk->fops = &mtd_fops;
mtd_disks[i] = disk;
} }
if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) {
printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
MTD_BLOCK_MAJOR);
err = -EAGAIN;
goto out;
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request);
return 0; return 0;
out:
while (i--)
put_disk(mtd_disks[i]);
return err;
} }
static void __exit cleanup_mtdblock(void) static void __exit cleanup_mtdblock(void)
{ {
int i;
unregister_blkdev(MAJOR_NR,DEVICE_NAME); unregister_blkdev(MAJOR_NR,DEVICE_NAME);
blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
for (i = 0; i < MAX_MTD_DEVICES; i++)
put_disk(mtd_disks[i]);
} }
module_init(init_mtdblock); module_init(init_mtdblock);
......
...@@ -74,10 +74,10 @@ static void NFTL_setup(struct mtd_info *mtd) ...@@ -74,10 +74,10 @@ static void NFTL_setup(struct mtd_info *mtd)
} }
nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL); gd = alloc_disk();
if (!nftl || !gd) { if (!nftl || !gd) {
kfree(nftl); kfree(nftl);
kfree(gd); put_disk(gd);
printk(KERN_WARNING "Out of memory for NFTL data structures\n"); printk(KERN_WARNING "Out of memory for NFTL data structures\n");
return; return;
} }
...@@ -92,7 +92,7 @@ static void NFTL_setup(struct mtd_info *mtd) ...@@ -92,7 +92,7 @@ static void NFTL_setup(struct mtd_info *mtd)
if (NFTL_mount(nftl) < 0) { if (NFTL_mount(nftl) < 0) {
printk(KERN_WARNING "Could not mount NFTL device\n"); printk(KERN_WARNING "Could not mount NFTL device\n");
kfree(nftl); kfree(nftl);
kfree(gd); put_disk(gd);
return; return;
} }
...@@ -129,7 +129,6 @@ static void NFTL_setup(struct mtd_info *mtd) ...@@ -129,7 +129,6 @@ static void NFTL_setup(struct mtd_info *mtd)
/* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */
} }
NFTLs[firstfree] = nftl; NFTLs[firstfree] = nftl;
memset(gd, 0, sizeof(struct gendisk));
sprintf(gd->disk_name, "nftl%c", 'a' + firstfree); sprintf(gd->disk_name, "nftl%c", 'a' + firstfree);
gd->major = MAJOR_NR; gd->major = MAJOR_NR;
gd->first_minor = firstfree << NFTL_PARTN_BITS; gd->first_minor = firstfree << NFTL_PARTN_BITS;
...@@ -152,7 +151,7 @@ static void NFTL_unsetup(int i) ...@@ -152,7 +151,7 @@ static void NFTL_unsetup(int i)
if (nftl->EUNtable) if (nftl->EUNtable)
kfree(nftl->EUNtable); kfree(nftl->EUNtable);
del_gendisk(nftl->disk); del_gendisk(nftl->disk);
kfree(nftl->disk); put_disk(nftl->disk);
kfree(nftl); kfree(nftl);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment