Commit 3f41fa2f authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] split "gendisk" to be per-disk, part 2

we are starting to split gendisks - now we can do that.  Done for
ide, sd, pd, hd and mfm

It's in transit - what we are aiming at is getting ->nr_real to 1 for
all gendisks.  Once that will be done we will be able to simplify a lot
stuff and remove ad-hackery.  First thing that will happen after that
is death of ->nr_real, obviouslye.  Then we
	(a) will merge ->major and ->first_minor into ->dev
	(b) strip one level of indirection from  ->driverfs_dev_arr, ->de_arr
and ->flags - they turn into single-element arrays and we will simply pull
the (only) element into struct gendisk.  Kills a lot of ad-hackery in splitup
code (fewer things to allocate).
	(c) replace ->major_name with ->disk_name; kills most of the crap in
disk_name(9) - it only has to care about adding partition number to the name.
parent d7536161
...@@ -1253,11 +1253,20 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack, ...@@ -1253,11 +1253,20 @@ void xd_set_geometry(struct block_device *bdev, unsigned char secsptrack,
} }
} }
static struct gendisk mfm_gendisk = { static struct gendisk mfm_gendisk[2] = {
{
major: MAJOR_NR, major: MAJOR_NR,
first_minor: 0,
major_name: "mfm", major_name: "mfm",
minor_shift: 6, minor_shift: 6,
part: mfm, part: mfm,
},
{
major: MAJOR_NR,
first_minor: 64,
major_name: "mfm",
minor_shift: 6,
part: mfm + 64,
}; };
static struct block_device_operations mfm_fops = static struct block_device_operations mfm_fops =
...@@ -1275,8 +1284,6 @@ static void mfm_geninit (void) ...@@ -1275,8 +1284,6 @@ static void mfm_geninit (void)
printk("mfm: detected %d hard drive%s\n", mfm_drives, printk("mfm: detected %d hard drive%s\n", mfm_drives,
mfm_drives == 1 ? "" : "s"); mfm_drives == 1 ? "" : "s");
mfm_gendisk.nr_real = mfm_drives;
if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL)) if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
printk("mfm: unable to get IRQ%d\n", mfm_irq); printk("mfm: unable to get IRQ%d\n", mfm_irq);
...@@ -1284,8 +1291,10 @@ static void mfm_geninit (void) ...@@ -1284,8 +1291,10 @@ static void mfm_geninit (void)
outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */ outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */
for (i = 0; i < mfm_drives; i++) { for (i = 0; i < mfm_drives; i++) {
mfm_gendisk[i].nr_real = 1;
add_gendisk(mfm_gendisk + i);
mfm_geometry (i); mfm_geometry (i);
register_disk(&mfm_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6, register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6,
&mfm_fops, &mfm_fops,
mfm_info[i].cylinders * mfm_info[i].heads * mfm_info[i].cylinders * mfm_info[i].heads *
mfm_info[i].sectors / 2); mfm_info[i].sectors / 2);
...@@ -1380,8 +1389,6 @@ int mfm_init (void) ...@@ -1380,8 +1389,6 @@ int mfm_init (void)
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request);
add_gendisk(&mfm_gendisk);
Busy = 0; Busy = 0;
lastspecifieddrive = -1; lastspecifieddrive = -1;
...@@ -1419,11 +1426,13 @@ int init_module(void) ...@@ -1419,11 +1426,13 @@ int init_module(void)
void cleanup_module(void) void cleanup_module(void)
{ {
int i;
if (ecs && mfm_irqenable) if (ecs && mfm_irqenable)
outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */ outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */
free_irq(mfm_irq, NULL); free_irq(mfm_irq, NULL);
unregister_blkdev(MAJOR_NR, "mfm"); unregister_blkdev(MAJOR_NR, "mfm");
del_gendisk(&mfm_gendisk); for (i = 0; i < mfm_drives; i++)
del_gendisk(mfm_gendisk + i);
if (ecs) if (ecs)
ecard_release(ecs); ecard_release(ecs);
if (mfm_addr) if (mfm_addr)
......
...@@ -55,8 +55,8 @@ add_gendisk(struct gendisk *gp) ...@@ -55,8 +55,8 @@ add_gendisk(struct gendisk *gp)
{ {
if (sgp == gp) if (sgp == gp)
{ {
// printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n", printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
// sgp->major) sgp->major)
goto out; goto out;
} }
} }
......
...@@ -291,6 +291,7 @@ struct pd_unit { ...@@ -291,6 +291,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 pd_unit pd[PD_UNITS]; struct pd_unit pd[PD_UNITS];
...@@ -330,8 +331,8 @@ static struct gendisk pd_gendisk = { ...@@ -330,8 +331,8 @@ static struct gendisk pd_gendisk = {
major: PD_MAJOR, major: PD_MAJOR,
major_name: PD_NAME, major_name: PD_NAME,
minor_shift: PD_BITS, minor_shift: PD_BITS,
part: pd_hd,
fops: &pd_fops, fops: &pd_fops,
nr_real: 1,
}; };
static struct block_device_operations pd_fops = { static struct block_device_operations pd_fops = {
...@@ -680,8 +681,8 @@ static int pd_probe_drive( int unit ) ...@@ -680,8 +681,8 @@ static int pd_probe_drive( int unit )
} }
static int pd_detect( void ) static int pd_detect( void )
{
{ int k, unit; int k, unit;
k = 0; k = 0;
if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
...@@ -703,18 +704,19 @@ static int pd_detect( void ) ...@@ -703,18 +704,19 @@ static int pd_detect( void )
k = unit+1; k = unit+1;
} else pi_release(PI); } else pi_release(PI);
} }
for (unit=0;unit<PD_UNITS;unit++) for (unit=0;unit<PD_UNITS;unit++) {
register_disk(&pd_gendisk,mk_kdev(MAJOR_NR,unit<<PD_BITS), if (PD.present) {
PD_PARTNS,&pd_fops, PD.gd = pd_gendisk;
PD.present?PD.capacity:0); PD.gd.first_minor = unit << PD_BITS;
PD.gd.part = pd_hd + (unit << PD_BITS);
/* We lie about the number of drives found, as the generic partition add_gendisk(&PD.gd);
scanner assumes that the drives are numbered sequentially from 0. register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS),
This can result in some bogus error messages if non-sequential PD_PARTNS,&pd_fops,
drive numbers are used. PD.capacity);
*/ }
}
if (k) if (k)
return k; return 1;
printk("%s: no valid drive found\n",name); printk("%s: no valid drive found\n",name);
return 0; return 0;
} }
...@@ -935,8 +937,6 @@ static void do_pd_write_done( void ) ...@@ -935,8 +937,6 @@ static void do_pd_write_done( void )
static int __init pd_init(void) static int __init pd_init(void)
{ {
request_queue_t * q; request_queue_t * q;
int unit;
if (disable) return -1; if (disable) return -1;
if (register_blkdev(MAJOR_NR,name,&pd_fops)) { if (register_blkdev(MAJOR_NR,name,&pd_fops)) {
printk("%s: unable to get major number %d\n", printk("%s: unable to get major number %d\n",
...@@ -949,18 +949,11 @@ static int __init pd_init(void) ...@@ -949,18 +949,11 @@ static int __init pd_init(void)
pd_gendisk.major = major; pd_gendisk.major = major;
pd_gendisk.major_name = name; pd_gendisk.major_name = name;
add_gendisk(&pd_gendisk);
printk("%s: %s version %s, major %d, cluster %d, nice %d\n", printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
name,name,PD_VERSION,major,cluster,nice); name,name,PD_VERSION,major,cluster,nice);
pd_init_units(); pd_init_units();
pd_gendisk.nr_real = pd_detect(); if (!pd_detect()) {
if (!pd_gendisk.nr_real) {
unregister_blkdev(MAJOR_NR, name); unregister_blkdev(MAJOR_NR, name);
del_gendisk(&pd_gendisk);
for (unit=0; unit<PD_UNITS; unit++)
if (PD.present)
pi_release(PI);
return -1; return -1;
} }
return 0; return 0;
...@@ -970,10 +963,11 @@ static void __exit pd_exit(void) ...@@ -970,10 +963,11 @@ static void __exit pd_exit(void)
{ {
int unit; int unit;
unregister_blkdev(MAJOR_NR, name); unregister_blkdev(MAJOR_NR, name);
del_gendisk(&pd_gendisk);
for (unit=0; unit<PD_UNITS; unit++) for (unit=0; unit<PD_UNITS; unit++)
if (PD.present) if (PD.present) {
del_gendisk(&PD.gd);
pi_release(PI); pi_release(PI);
}
} }
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -708,12 +708,22 @@ static int hd_open(struct inode * inode, struct file * filp) ...@@ -708,12 +708,22 @@ 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 = { static struct gendisk hd_gendisk[2] = {
{
.major = MAJOR_NR, .major = MAJOR_NR,
.first_minor = 0,
.major_name = "hd", .major_name = "hd",
.minor_shift = 6, .minor_shift = 6,
.part = hd, .part = hd,
.fops = &hd_fops, .fops = &hd_fops,
},{
.major = MAJOR_NR,
.first_minor = 64,
.major_name = "hd",
.minor_shift = 6,
.part = hd + 64,
.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)
...@@ -845,12 +855,14 @@ static void __init hd_geninit(void) ...@@ -845,12 +855,14 @@ static void __init hd_geninit(void)
return; return;
} }
hd_gendisk.nr_real = NR_HD; for(drive=0; drive < NR_HD; drive++) {
hd_gendisk[i].nr_real = 1;
for(drive=0; drive < NR_HD; drive++) add_gendisk(hd_gendisk + drive);
register_disk(&hd_gendisk, mk_kdev(MAJOR_NR,drive<<6), 1<<6, register_disk(hd_gendisk + drive,
mk_kdev(MAJOR_NR,drive<<6), 1<<6,
&hd_fops, hd_info[drive].head * hd_info[drive].sect * &hd_fops, hd_info[drive].head * hd_info[drive].sect *
hd_info[drive].cyl); hd_info[drive].cyl);
}
} }
int __init hd_init(void) int __init hd_init(void)
...@@ -861,7 +873,6 @@ int __init hd_init(void) ...@@ -861,7 +873,6 @@ int __init hd_init(void)
} }
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock); blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255); blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
add_gendisk(&hd_gendisk);
init_timer(&device_timer); init_timer(&device_timer);
device_timer.function = hd_times_out; device_timer.function = hd_times_out;
hd_geninit(); hd_geninit();
......
...@@ -1064,9 +1064,9 @@ static void idedisk_setup(struct ata_device *drive) ...@@ -1064,9 +1064,9 @@ static void idedisk_setup(struct ata_device *drive)
if (drive != &ch->drives[i]) if (drive != &ch->drives[i])
continue; continue;
drvid = i; drvid = i;
ch->gd->de_arr[i] = drive->de; ch->gd[i]->de_arr[0] = drive->de;
if (drive->removable) if (drive->removable)
ch->gd->flags[i] |= GENHD_FL_REMOVABLE; ch->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
break; break;
} }
......
...@@ -1712,9 +1712,9 @@ static void idefloppy_setup(struct ata_device *drive, idefloppy_floppy_t *floppy ...@@ -1712,9 +1712,9 @@ static void idefloppy_setup(struct ata_device *drive, idefloppy_floppy_t *floppy
struct ata_channel *hwif = drive->channel; struct ata_channel *hwif = drive->channel;
if (drive != &hwif->drives[i]) continue; if (drive != &hwif->drives[i]) continue;
hwif->gd->de_arr[i] = drive->de; hwif->gd[i]->de_arr[0] = drive->de;
if (drive->removable) if (drive->removable)
hwif->gd->flags[i] |= GENHD_FL_REMOVABLE; hwif->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
break; break;
} }
} }
......
...@@ -488,16 +488,19 @@ void ide_unregister(struct ata_channel *ch) ...@@ -488,16 +488,19 @@ void ide_unregister(struct ata_channel *ch)
blk_dev[ch->major].data = NULL; blk_dev[ch->major].data = NULL;
blk_dev[ch->major].queue = NULL; blk_dev[ch->major].queue = NULL;
blk_clear(ch->major); blk_clear(ch->major);
gd = ch->gd; gd = ch->gd[0];
if (gd) { if (gd) {
del_gendisk(gd); int i;
for (i = 0; i < MAX_DRIVES; i++)
del_gendisk(gd + i);
kfree(gd->part); kfree(gd->part);
if (gd->de_arr) if (gd->de_arr)
kfree (gd->de_arr); kfree (gd->de_arr);
if (gd->flags) if (gd->flags)
kfree (gd->flags); kfree (gd->flags);
kfree(gd); kfree(gd);
ch->gd = NULL; for (i = 0; i < MAX_DRIVES; i++)
ch->gd[i] = NULL;
} }
/* /*
......
...@@ -1043,6 +1043,9 @@ static request_queue_t *ata_get_queue(kdev_t dev) ...@@ -1043,6 +1043,9 @@ static request_queue_t *ata_get_queue(kdev_t dev)
static void channel_init(struct ata_channel *ch) static void channel_init(struct ata_channel *ch)
{ {
struct gendisk *gd; struct gendisk *gd;
struct hd_struct *part;
devfs_handle_t *de_arr;
char *flags;
unsigned int unit; unsigned int unit;
extern devfs_handle_t ide_devfs_handle; extern devfs_handle_t ide_devfs_handle;
...@@ -1103,39 +1106,42 @@ static void channel_init(struct ata_channel *ch) ...@@ -1103,39 +1106,42 @@ static void channel_init(struct ata_channel *ch)
/* Initialize partition and global device data. /* Initialize partition and global device data.
*/ */
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL); gd = kmalloc (MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL);
if (!gd) if (!gd)
goto err_kmalloc_gd; goto err_kmalloc_gd;
memset(gd, 0, sizeof(struct gendisk)); memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk));
gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL); part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
if (!gd->part) if (!part)
goto err_kmalloc_gd_part; goto err_kmalloc_gd_part;
memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct)); memset(part, 0, ATA_MINORS * sizeof(struct hd_struct));
gd->de_arr = kmalloc (sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL); de_arr = kmalloc (sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL);
if (!gd->de_arr) if (!de_arr)
goto err_kmalloc_gd_de_arr; goto err_kmalloc_gd_de_arr;
memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES); memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES);
gd->flags = kmalloc (sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL); flags = kmalloc (sizeof(char) * MAX_DRIVES, GFP_KERNEL);
if (!gd->flags) if (!flags)
goto err_kmalloc_gd_flags; goto err_kmalloc_gd_flags;
memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES); memset(flags, 0, sizeof(char) * MAX_DRIVES);
for (unit = 0; unit < MAX_DRIVES; ++unit) for (unit = 0; unit < MAX_DRIVES; ++unit) {
ch->drives[unit].part = &gd->part[unit << PARTN_BITS]; gd[unit].part = part + (unit << PARTN_BITS);
gd[unit].de_arr = de_arr + unit;
gd->major = ch->major; /* our major device number */ gd[unit].flags = flags + unit;
gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */ ch->drives[unit].part = gd[unit].part;
gd->minor_shift = PARTN_BITS; /* num bits for partitions */ gd[unit].major = ch->major;
gd->nr_real = MAX_DRIVES; /* current num real drives */ gd[unit].first_minor = unit << PARTN_BITS;
gd->next = NULL; /* linked list of major devs */ /* treated special in genhd.c */
gd->fops = ide_fops; /* file operations */ gd[unit].major_name = IDE_MAJOR_NAME;
gd[unit].minor_shift = PARTN_BITS;
ch->gd = gd; gd[unit].nr_real = 1;
add_gendisk(gd); gd[unit].fops = ide_fops;
ch->gd[unit] = gd + unit;
add_gendisk(gd + unit);
}
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
char name[80]; char name[80];
...@@ -1156,9 +1162,9 @@ static void channel_init(struct ata_channel *ch) ...@@ -1156,9 +1162,9 @@ static void channel_init(struct ata_channel *ch)
return; return;
err_kmalloc_gd_flags: err_kmalloc_gd_flags:
kfree(gd->de_arr); kfree(de_arr);
err_kmalloc_gd_de_arr: err_kmalloc_gd_de_arr:
kfree(gd->part); kfree(part);
err_kmalloc_gd_part: err_kmalloc_gd_part:
kfree(gd); kfree(gd);
err_kmalloc_gd: err_kmalloc_gd:
......
...@@ -90,8 +90,6 @@ struct hd_struct *sd; ...@@ -90,8 +90,6 @@ struct hd_struct *sd;
static Scsi_Disk ** sd_dsk_arr; static Scsi_Disk ** sd_dsk_arr;
static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED; static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
static int *sd_max_sectors;
static int check_scsidisk_media_change(kdev_t); static int check_scsidisk_media_change(kdev_t);
static int fop_revalidate_scsidisk(kdev_t); static int fop_revalidate_scsidisk(kdev_t);
...@@ -605,22 +603,7 @@ static struct block_device_operations sd_fops = ...@@ -605,22 +603,7 @@ static struct block_device_operations sd_fops =
revalidate: fop_revalidate_scsidisk revalidate: fop_revalidate_scsidisk
}; };
/* static struct gendisk **sd_disks;
* If we need more than one SCSI disk major (i.e. more than
* 16 SCSI disks), we'll have to vmalloc() more gendisks later.
*/
static struct gendisk sd_gendisk =
{
major: SCSI_DISK0_MAJOR,
major_name: "sd",
minor_shift: 4,
fops: &sd_fops,
};
static struct gendisk *sd_gendisks = &sd_gendisk;
#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
/** /**
* sd_rw_intr - bottom half handler: called when the lower level * sd_rw_intr - bottom half handler: called when the lower level
...@@ -1224,62 +1207,23 @@ static int sd_init() ...@@ -1224,62 +1207,23 @@ static int sd_init()
sd_dsk_arr[k] = sdkp; sd_dsk_arr[k] = sdkp;
} }
} }
init_mem_lth(sd_disks, sd_template.dev_max);
if (sd_disks)
zero_mem_lth(sd_disks, sd_template.dev_max);
init_mem_lth(sd, maxparts); init_mem_lth(sd, maxparts);
init_mem_lth(sd_gendisks, N_USED_SD_MAJORS);
init_mem_lth(sd_max_sectors, sd_template.dev_max << 4);
if (!sd_dsk_arr || !sd || !sd_gendisks) if (!sd_dsk_arr || !sd || !sd_disks)
goto cleanup_mem; goto cleanup_mem;
zero_mem_lth(sd, maxparts); zero_mem_lth(sd, maxparts);
for (k = 0; k < maxparts; k++) {
/*
* Allow lowlevel device drivers to generate 512k large scsi
* commands if they know what they're doing and they ask for it
* explicitly via the SHpnt->max_sectors API.
*/
sd_max_sectors[k] = MAX_PHYS_SEGMENTS*8;
}
for (k = 0; k < N_USED_SD_MAJORS; k++) {
int N = SCSI_DISKS_PER_MAJOR;
sd_gendisks[k] = sd_gendisk;
init_mem_lth(sd_gendisks[k].de_arr, N);
init_mem_lth(sd_gendisks[k].flags, N);
init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags ||
!sd_gendisks[k].driverfs_dev_arr)
goto cleanup_gendisks;
zero_mem_lth(sd_gendisks[k].de_arr, N);
zero_mem_lth(sd_gendisks[k].flags, N);
zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
sd_gendisks[k].major = SD_MAJOR(k);
sd_gendisks[k].major_name = "sd";
sd_gendisks[k].minor_shift = 4;
sd_gendisks[k].part = sd + k * (N << 4);
sd_gendisks[k].nr_real = 0;
}
return 0; return 0;
#undef init_mem_lth #undef init_mem_lth
#undef zero_mem_lth #undef zero_mem_lth
cleanup_gendisks:
/* vfree can handle NULL, so no test is required here */
for (k = 0; k < N_USED_SD_MAJORS; k++) {
vfree(sd_gendisks[k].de_arr);
vfree(sd_gendisks[k].flags);
vfree(sd_gendisks[k].driverfs_dev_arr);
}
cleanup_mem: cleanup_mem:
vfree(sd_gendisks); vfree(sd_disks);
sd_gendisks = NULL; sd_disks = NULL;
vfree(sd); vfree(sd);
sd = NULL; sd = NULL;
if (sd_dsk_arr) { if (sd_dsk_arr) {
...@@ -1310,17 +1254,16 @@ static void sd_finish() ...@@ -1310,17 +1254,16 @@ static void sd_finish()
Scsi_Disk * sdkp; Scsi_Disk * sdkp;
SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n")); SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n"));
for (k = 0; k < N_USED_SD_MAJORS; k++) { for (k = 0; k < N_USED_SD_MAJORS; k++)
blk_dev[SD_MAJOR(k)].queue = sd_find_queue; blk_dev[SD_MAJOR(k)].queue = sd_find_queue;
add_gendisk(&(sd_gendisks[k]));
}
for (k = 0; k < sd_template.dev_max; ++k) { for (k = 0; k < sd_template.dev_max; ++k) {
sdkp = sd_get_sdisk(k); sdkp = sd_get_sdisk(k);
if (sdkp && (0 == sdkp->capacity) && sdkp->device) { if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
sd_init_onedisk(sdkp, k); sd_init_onedisk(sdkp, k);
if (!sdkp->has_been_registered) { if (!sdkp->has_been_registered) {
register_disk(&SD_GENDISK(k), MKDEV_SD(k), add_gendisk(sd_disks[k]);
register_disk(sd_disks[k], MKDEV_SD(k),
1<<4, &sd_fops, 1<<4, &sd_fops,
sdkp->capacity); sdkp->capacity);
sdkp->has_been_registered = 1; sdkp->has_been_registered = 1;
...@@ -1366,21 +1309,36 @@ static int sd_detect(Scsi_Device * sdp) ...@@ -1366,21 +1309,36 @@ static int sd_detect(Scsi_Device * sdp)
**/ **/
static int sd_attach(Scsi_Device * sdp) static int sd_attach(Scsi_Device * sdp)
{ {
unsigned int devnum;
Scsi_Disk *sdkp; Scsi_Disk *sdkp;
int dsk_nr; int dsk_nr;
char diskname[6]; char diskname[6];
unsigned long iflags; unsigned long iflags;
struct {
struct gendisk disk;
devfs_handle_t de;
struct device *dev;
char flags;
} *p;
struct gendisk *gd;
if ((NULL == sdp) || if ((NULL == sdp) ||
((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))) ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)))
return 0; return 0;
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return 1;
gd = &p->disk;
gd->de_arr = &p->de;
gd->flags = &p->flags;
gd->driverfs_dev_arr = &p->dev;
SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n",
sdp->host->host_no, sdp->channel, sdp->id, sdp->lun)); sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
if (sd_template.nr_dev >= sd_template.dev_max) { if (sd_template.nr_dev >= sd_template.dev_max) {
sdp->attached--; sdp->attached--;
printk(KERN_ERR "sd_init: no more room for device\n"); printk(KERN_ERR "sd_init: no more room for device\n");
kfree(p);
return 1; return 1;
} }
...@@ -1400,17 +1358,23 @@ static int sd_attach(Scsi_Device * sdp) ...@@ -1400,17 +1358,23 @@ static int sd_attach(Scsi_Device * sdp)
if (dsk_nr >= sd_template.dev_max) { if (dsk_nr >= sd_template.dev_max) {
/* panic("scsi_devices corrupt (sd)"); overkill */ /* panic("scsi_devices corrupt (sd)"); overkill */
printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n"); printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n");
kfree(p);
return 1; return 1;
} }
sd_template.nr_dev++; sd_template.nr_dev++;
SD_GENDISK(dsk_nr).nr_real++; gd->nr_real = 1;
devnum = dsk_nr % SCSI_DISKS_PER_MAJOR; gd->de_arr[0] = sdp->de;
SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de; gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev;
SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] = gd->major = SD_MAJOR(dsk_nr>>4);
&sdp->sdev_driverfs_dev; gd->first_minor = (dsk_nr & 15)<<4;
gd->major_name = "sd";
gd->minor_shift = 4;
gd->part = sd + (dsk_nr << 4);
gd->fops = &sd_fops;
if (sdp->removable) if (sdp->removable)
SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE; gd->flags[0] |= GENHD_FL_REMOVABLE;
sd_disks[dsk_nr] = gd;
sd_dskname(dsk_nr, diskname); sd_dskname(dsk_nr, diskname);
printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, " printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
"id %d, lun %d\n", sdp->removable ? "removable " : "", "id %d, lun %d\n", sdp->removable ? "removable " : "",
...@@ -1480,8 +1444,6 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1480,8 +1444,6 @@ static void sd_detach(Scsi_Device * sdp)
Scsi_Disk *sdkp = NULL; Scsi_Disk *sdkp = NULL;
kdev_t dev; kdev_t dev;
int dsk_nr; int dsk_nr;
int max_p;
int start;
unsigned long iflags; unsigned long iflags;
SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n", SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n",
...@@ -1491,7 +1453,6 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1491,7 +1453,6 @@ static void sd_detach(Scsi_Device * sdp)
for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) { for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
sdkp = sd_dsk_arr[dsk_nr]; sdkp = sd_dsk_arr[dsk_nr];
if (sdkp->device == sdp) { if (sdkp->device == sdp) {
sdkp->has_been_registered = 0;
sdkp->device = NULL; sdkp->device = NULL;
sdkp->capacity = 0; sdkp->capacity = 0;
/* sdkp->detaching = 1; */ /* sdkp->detaching = 1; */
...@@ -1502,19 +1463,20 @@ static void sd_detach(Scsi_Device * sdp) ...@@ -1502,19 +1463,20 @@ static void sd_detach(Scsi_Device * sdp)
if (dsk_nr >= sd_template.dev_max) if (dsk_nr >= sd_template.dev_max)
return; return;
max_p = 1 << sd_gendisk.minor_shift; if (sdkp->has_been_registered) {
start = dsk_nr << sd_gendisk.minor_shift; sdkp->has_been_registered = 0;
dev = MKDEV_SD_PARTITION(start); dev = MKDEV_SD(dsk_nr);
driverfs_remove_partitions(&SD_GENDISK (dsk_nr), driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev));
SD_MINOR_NUMBER (start)); wipe_partitions(dev);
wipe_partitions(dev); devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1);
devfs_register_partitions (&SD_GENDISK (dsk_nr), /* unregister_disk() */
SD_MINOR_NUMBER (start), 1); del_gendisk(sd_disks[dsk_nr]);
/* unregister_disk() */ }
sdp->attached--; sdp->attached--;
sd_template.dev_noticed--; sd_template.dev_noticed--;
sd_template.nr_dev--; sd_template.nr_dev--;
SD_GENDISK(dsk_nr).nr_real--; kfree(sd_disks[dsk_nr]);
sd_disks[dsk_nr] = NULL;
} }
/** /**
...@@ -1560,12 +1522,9 @@ static void __exit exit_sd(void) ...@@ -1560,12 +1522,9 @@ static void __exit exit_sd(void)
vfree((char *) sd); vfree((char *) sd);
for (k = 0; k < N_USED_SD_MAJORS; k++) { for (k = 0; k < N_USED_SD_MAJORS; k++) {
blk_dev[SD_MAJOR(k)].queue = NULL; blk_dev[SD_MAJOR(k)].queue = NULL;
del_gendisk(&(sd_gendisks[k]));
blk_clear(SD_MAJOR(k)); blk_clear(SD_MAJOR(k));
} }
sd_template.dev_max = 0; sd_template.dev_max = 0;
if (sd_gendisks != &sd_gendisk)
vfree(sd_gendisks);
remove_driver(&sd_template.scsi_driverfs_driver); remove_driver(&sd_template.scsi_driverfs_driver);
} }
......
...@@ -894,7 +894,7 @@ struct ata_channel { ...@@ -894,7 +894,7 @@ struct ata_channel {
struct pci_dev *pci_dev; /* for pci chipsets */ struct pci_dev *pci_dev; /* for pci chipsets */
#endif #endif
struct ata_device drives[MAX_DRIVES]; /* drive info */ struct ata_device drives[MAX_DRIVES]; /* drive info */
struct gendisk *gd; /* gendisk structure */ struct gendisk *gd[MAX_DRIVES]; /* gendisk structure */
/* /*
* Routines to tune PIO and DMA mode for drives. * Routines to tune PIO and DMA mode for drives.
......
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