diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-07-05 23:09:37 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-07-05 23:09:37 +0000 |
commit | aba344fdfed81b2c03d6114c54cfd73a486aa10b (patch) | |
tree | d032d8430bf1234c3ecc6f6330d6de6e887e5963 /drivers/block | |
parent | 40c138bfc6d37dbff5339f84575db1e3cec6e34e (diff) |
Merge with Linux 2.3.9.
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Config.in | 7 | ||||
-rw-r--r-- | drivers/block/genhd.c | 31 | ||||
-rw-r--r-- | drivers/block/icside.c | 1 | ||||
-rw-r--r-- | drivers/block/ide-disk.c | 7 | ||||
-rw-r--r-- | drivers/block/ide-floppy.c | 7 | ||||
-rw-r--r-- | drivers/block/ide-pci.c | 4 | ||||
-rw-r--r-- | drivers/block/ide-pmac.c | 4 | ||||
-rw-r--r-- | drivers/block/ide-probe.c | 4 | ||||
-rw-r--r-- | drivers/block/ide-proc.c | 98 | ||||
-rw-r--r-- | drivers/block/ide-tape.c | 56 | ||||
-rw-r--r-- | drivers/block/ide.c | 37 | ||||
-rw-r--r-- | drivers/block/ll_rw_blk.c | 29 | ||||
-rw-r--r-- | drivers/block/pdc4030.c | 87 | ||||
-rw-r--r-- | drivers/block/raid1.c | 2 | ||||
-rw-r--r-- | drivers/block/raid5.c | 35 | ||||
-rw-r--r-- | drivers/block/rd.c | 2 |
16 files changed, 273 insertions, 138 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in index a9b9a000f..0e73f0c65 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -75,7 +75,7 @@ else if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then - bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO + bool ' Use DMA by default' CONFIG_IDEDMA_PMAC_AUTO fi fi fi @@ -93,6 +93,11 @@ else "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \ "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then define_bool CONFIG_BLK_DEV_IDEDMA y + if [ "$CONFIG_IDEDMA_PCI_AUTO" = "y" -o \ + "$CONFIG_IDEDMA_PMAC_AUTO" = "y" -o \ + "$CONFIG_IDEDMA_ICS_AUTO" = "y" ]; then + define_bool CONFIG_IDEDMA_AUTO y + fi fi bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index f52489d76..4197ad92a 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -221,11 +221,6 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) return; if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) return; - /* - * This block is from a device that we're about to stomp on. - * So make sure nobody thinks this block is usable. - */ - bh->b_state = 0; if ((*(unsigned short *) (bh->b_data+510)) != cpu_to_le16(MSDOS_LABEL_MAGIC)) goto done; @@ -285,10 +280,12 @@ static void extended_partition(struct gendisk *hd, kdev_t dev) hd->part[current_minor].start_sect = first_sector + START_SECT(p) * sector_size; this_sector = first_sector + START_SECT(p) * sector_size; dev = MKDEV(hd->major, current_minor); - brelse(bh); + + /* Use bforget(), as we have changed the disk geometry */ + bforget(bh); } done: - brelse(bh); + bforget(bh); } #ifdef CONFIG_SOLARIS_X86_PARTITION @@ -386,7 +383,6 @@ static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev, if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) return; - bh->b_state = 0; l = (struct bsd_disklabel *) (bh->b_data+512); if (l->d_magic != BSD_DISKMAGIC) { brelse(bh); @@ -402,7 +398,9 @@ static void bsd_disklabel_partition(struct gendisk *hd, kdev_t dev, if (p->p_fstype != BSD_FS_UNUSED) check_and_add_bsd_partition(hd, p, dev); } - brelse(bh); + + /* Use bforget(), as we have changed the disk setup */ + bforget(bh); } #endif @@ -421,7 +419,6 @@ static void unixware_partition(struct gendisk *hd, kdev_t dev) if (!(bh = bread(dev, 14, get_ptable_blocksize(dev)))) return; - bh->b_state = 0; l = (struct unixware_disklabel *) (bh->b_data+512); if (le32_to_cpu(l->d_magic) != UNIXWARE_DISKMAGIC || le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_DISKMAGIC2) { @@ -441,7 +438,8 @@ static void unixware_partition(struct gendisk *hd, kdev_t dev) } p++; } - brelse(bh); + /* Use bforget, as we have changed the disk setup */ + bforget(bh); printk(" >"); } #endif @@ -469,15 +467,12 @@ read_mbr: return -1; } data = bh->b_data; - /* In some cases we modify the geometry */ - /* of the drive (below), so ensure that */ - /* nobody else tries to re-use this data. */ - bh->b_state = 0; #ifdef CONFIG_BLK_DEV_IDE check_table: #endif + /* Use bforget(), because we have potentially changed the disk geometry */ if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) { - brelse(bh); + bforget(bh); return 0; } p = (struct partition *) (0x1be + data); @@ -515,7 +510,7 @@ check_table: * adjustments to fool fdisk/LILO and partition check. */ if (ide_xlate_1024(dev, 1, " [DM6:DDO]")) { - brelse(bh); + bforget(bh); goto read_mbr; /* start over with new MBR */ } } else if (sig <= 0x1ae && @@ -627,7 +622,7 @@ check_table: } } printk("\n"); - brelse(bh); + bforget(bh); return 1; } diff --git a/drivers/block/icside.c b/drivers/block/icside.c index 299bce7a6..0d29761ee 100644 --- a/drivers/block/icside.c +++ b/drivers/block/icside.c @@ -10,6 +10,7 @@ * 22-May-1999 RMK Added support for V6 DMA */ +#include <linux/config.h> #include <linux/string.h> #include <linux/module.h> #include <linux/ioport.h> diff --git a/drivers/block/ide-disk.c b/drivers/block/ide-disk.c index 5d8548d96..fee5297f1 100644 --- a/drivers/block/ide-disk.c +++ b/drivers/block/ide-disk.c @@ -856,11 +856,16 @@ void cleanup_module (void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) + while ((drive = ide_scan_devices (ide_disk, idedisk_driver.name, &idedisk_driver, failed)) != NULL) { if (idedisk_cleanup (drive)) { printk (KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); failed++; } + /* We must remove proc entries defined in this module. + Otherwise we oops while accessing these entries */ + if (drive->proc) + ide_remove_proc_entries(drive->proc, idedisk_proc); + } ide_unregister_module(&idedisk_module); } #endif /* MODULE */ diff --git a/drivers/block/ide-floppy.c b/drivers/block/ide-floppy.c index 78aa7fe29..49ccb66ce 100644 --- a/drivers/block/ide-floppy.c +++ b/drivers/block/ide-floppy.c @@ -1630,11 +1630,16 @@ void cleanup_module (void) ide_drive_t *drive; int failed = 0; - while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) + while ((drive = ide_scan_devices (ide_floppy, idefloppy_driver.name, &idefloppy_driver, failed)) != NULL) { if (idefloppy_cleanup (drive)) { printk ("%s: cleanup_module() called while still busy\n", drive->name); failed++; } + /* We must remove proc entries defined in this module. + Otherwise we oops while accessing these entries */ + if (drive->proc) + ide_remove_proc_entries(drive->proc, idefloppy_proc); + } ide_unregister_module(&idefloppy_module); } #endif /* MODULE */ diff --git a/drivers/block/ide-pci.c b/drivers/block/ide-pci.c index d1d906ecb..8b4c5fe2c 100644 --- a/drivers/block/ide-pci.c +++ b/drivers/block/ide-pci.c @@ -29,6 +29,7 @@ #define DEVID_PIIXb ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_1}) #define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1}) #define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB}) +#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561}) #define DEVID_VP_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1}) #define DEVID_PDC20246 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20246}) #define DEVID_PDC20262 ((ide_pci_devid_t){PCI_VENDOR_ID_PROMISE, PCI_DEVICE_ID_PROMISE_20262}) @@ -190,6 +191,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = { {DEVID_PIIXb, "PIIX", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX3, "PIIX3", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, {DEVID_PIIX4, "PIIX4", NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 }, + {DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 }, {DEVID_VP_IDE, "VP_IDE", NULL, INIT_VIA82C586, DMA_VIA82C586, {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, ON_BOARD, 0 }, {DEVID_PDC20246,"PDC20246", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 16 }, {DEVID_PDC20262,"PDC20262", PCI_PDC202XX, INIT_PDC202XX, NULL, {{0x50,0x02,0x02}, {0x50,0x04,0x04}}, OFF_BOARD, 48 }, @@ -548,6 +550,8 @@ __initfunc(void ide_scan_pcibus (void)) continue; /* OPTI Viper-M uses same devid for functions 0 and 1 */ else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_CY82C693) && (!(PCI_FUNC(dev->devfn) & 1) || !((dev->class >> 8) == PCI_CLASS_STORAGE_IDE))) continue; /* CY82C693 is more than only a IDE controller */ + else if (IDE_PCI_DEVID_EQ(d->devid, DEVID_UM8886A) && !(PCI_FUNC(dev->devfn) & 1)) + continue; /* UM8886A/BF pair */ else if (!IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL) || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) { if (IDE_PCI_DEVID_EQ(d->devid, IDE_PCI_DEVID_NULL)) printk("%s: unknown IDE controller on PCI bus %02x device %02x, VID=%04x, DID=%04x\n", diff --git a/drivers/block/ide-pmac.c b/drivers/block/ide-pmac.c index 4e38b4f64..52c658311 100644 --- a/drivers/block/ide-pmac.c +++ b/drivers/block/ide-pmac.c @@ -218,9 +218,9 @@ pmac_ide_setup_dma(struct device_node *np, ide_hwif_t *hwif)) } hwif->dmaproc = &pmac_ide_dmaproc; -#ifdef CONFIG_PMAC_IDEDMA_AUTO +#ifdef CONFIG_IDEDMA_PMAC_AUTO hwif->autodma = 1; -#endif +#endif /* CONFIG_IDEDMA_PMAC_AUTO */ } /* diff --git a/drivers/block/ide-probe.c b/drivers/block/ide-probe.c index 9fc293b18..3b5d24744 100644 --- a/drivers/block/ide-probe.c +++ b/drivers/block/ide-probe.c @@ -845,7 +845,9 @@ int init_module (void) for (index = 0; index < MAX_HWIFS; ++index) ide_unregister(index); - return ideprobe_init(); + ideprobe_init(); + create_proc_ide_interfaces(); + return 0; } void cleanup_module (void) diff --git a/drivers/block/ide-proc.c b/drivers/block/ide-proc.c index f985980b1..623ac9268 100644 --- a/drivers/block/ide-proc.c +++ b/drivers/block/ide-proc.c @@ -112,6 +112,8 @@ static int xx_xx_parse_error (const char *data, unsigned long len, const char *m return -EINVAL; } +static struct proc_dir_entry * proc_ide_root = NULL; + static int proc_ide_write_config (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -384,7 +386,7 @@ static int proc_ide_read_identify ide_drive_t *drive = (ide_drive_t *)data; int len = 0, i = 0; - if (!proc_ide_get_identify(drive, page)) { + if (drive && !proc_ide_get_identify(drive, page)) { unsigned short *val = ((unsigned short *)page) + 2; char *out = ((char *)val) + (SECTOR_WORDS * 4); page = out; @@ -394,6 +396,8 @@ static int proc_ide_read_identify } while (i < (SECTOR_WORDS * 2)); len = out - page; } + else + len = sprintf(page, "\n"); PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -525,8 +529,8 @@ int proc_ide_read_geometry char *out = page; int len; - out += sprintf(out,"physical %hi/%hi/%hi\n", drive->cyl, drive->head, drive->sect); - out += sprintf(out,"logical %hi/%hi/%hi\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); + out += sprintf(out,"physical %d/%d/%d\n", drive->cyl, drive->head, drive->sect); + out += sprintf(out,"logical %d/%d/%d\n", drive->bios_cyl, drive->bios_head, drive->bios_sect); len = out - page; PROC_IDE_READ_RETURN(page,start,off,count,eof,len); } @@ -634,21 +638,30 @@ static int proc_ide_readlink(struct proc_dir_entry *de, char *page) return sprintf(page, "ide%d/%s", n, de->name); } -static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *parent, struct proc_dir_entry *root) +static void create_proc_ide_drives(ide_hwif_t *hwif) { int d; struct proc_dir_entry *ent; + struct proc_dir_entry *parent = hwif->proc; for (d = 0; d < MAX_DRIVES; d++) { ide_drive_t *drive = &hwif->drives[d]; + ide_driver_t *driver = drive->driver; if (!drive->present) continue; - drive->proc = create_proc_entry(drive->name, S_IFDIR, parent); if (drive->proc) - ide_add_proc_entries(drive->proc, generic_drive_entries, drive); + continue; - ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, root); + drive->proc = create_proc_entry(drive->name, S_IFDIR, parent); + if (drive->proc) { + ide_add_proc_entries(drive->proc, generic_drive_entries, drive); + if (driver) { + ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive); + ide_add_proc_entries(drive->proc, driver->proc, drive); + } + } + ent = create_proc_entry(drive->name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, proc_ide_root); if (!ent) return; ent->data = drive; ent->readlink_proc = proc_ide_readlink; @@ -656,6 +669,25 @@ static void create_proc_ide_drives (ide_hwif_t *hwif, struct proc_dir_entry *par } } +void destroy_proc_ide_drives(ide_hwif_t *hwif) +{ + int d; + + for (d = 0; d < MAX_DRIVES; d++) { + ide_drive_t *drive = &hwif->drives[d]; + ide_driver_t *driver = drive->driver; + + if (!drive->proc) + continue; + if (driver) + ide_remove_proc_entries(drive->proc, driver->proc); + ide_remove_proc_entries(drive->proc, generic_drive_entries); + remove_proc_entry(drive->name, proc_ide_root); + remove_proc_entry(drive->name, hwif->proc); + drive->proc = NULL; + } +} + static ide_proc_entry_t hwif_entries[] = { { "channel", S_IFREG|S_IRUGO, proc_ide_read_channel, NULL }, { "config", S_IFREG|S_IRUGO|S_IWUSR,proc_ide_read_config, proc_ide_write_config }, @@ -664,42 +696,67 @@ static ide_proc_entry_t hwif_entries[] = { { NULL, 0, NULL, NULL } }; -static void create_proc_ide_interfaces (struct proc_dir_entry *parent) +void create_proc_ide_interfaces(void) { int h; - struct proc_dir_entry *hwif_ent; for (h = 0; h < MAX_HWIFS; h++) { ide_hwif_t *hwif = &ide_hwifs[h]; + int exist = (hwif->proc != NULL); if (!hwif->present) continue; - hwif_ent = create_proc_entry(hwif->name, S_IFDIR, parent); - if (!hwif_ent) return; - ide_add_proc_entries(hwif_ent, hwif_entries, hwif); - create_proc_ide_drives(hwif, hwif_ent, parent); + if (!exist) + hwif->proc = create_proc_entry(hwif->name, S_IFDIR, proc_ide_root); + if (!hwif->proc) + return; + if (!exist) + ide_add_proc_entries(hwif->proc, hwif_entries, hwif); + create_proc_ide_drives(hwif); + } +} + +static void destroy_proc_ide_interfaces(void) +{ + int h; + + for (h = 0; h < MAX_HWIFS; h++) { + ide_hwif_t *hwif = &ide_hwifs[h]; + int exist = (hwif->proc != NULL); + +#if 0 + if (!hwif->present) + continue; +#endif + if (exist) { + destroy_proc_ide_drives(hwif); + ide_remove_proc_entries(hwif->proc, hwif_entries); + remove_proc_entry(hwif->name, proc_ide_root); + hwif->proc = NULL; + } else + continue; } } void proc_ide_create(void) { - struct proc_dir_entry *root, *ent; - root = create_proc_entry("ide", S_IFDIR, 0); - if (!root) return; - create_proc_ide_interfaces(root); + struct proc_dir_entry *ent; + proc_ide_root = create_proc_entry("ide", S_IFDIR, 0); + if (!proc_ide_root) return; + create_proc_ide_interfaces(); - ent = create_proc_entry("drivers", 0, root); + ent = create_proc_entry("drivers", 0, proc_ide_root); if (!ent) return; ent->read_proc = proc_ide_read_drivers; #ifdef CONFIG_BLK_DEV_VIA82C586 if (via_display_info) { - ent = create_proc_entry("via", 0, root); + ent = create_proc_entry("via", 0, proc_ide_root); ent->get_info = via_display_info; } #endif /* CONFIG_BLK_DEV_VIA82C586 */ #ifdef CONFIG_BLK_DEV_ALI15X3 if (ali_display_info) { - ent = create_proc_entry("ali", 0, root); + ent = create_proc_entry("ali", 0, proc_ide_root); ent->get_info = ali_display_info; } #endif /* CONFIG_BLK_DEV_ALI15X3 */ @@ -720,5 +777,6 @@ void proc_ide_destroy(void) remove_proc_entry("ide/ali",0); #endif /* CONFIG_BLK_DEV_ALI15X3 */ remove_proc_entry("ide/drivers", 0); + destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); } diff --git a/drivers/block/ide-tape.c b/drivers/block/ide-tape.c index 1382eb3ab..74c89cff0 100644 --- a/drivers/block/ide-tape.c +++ b/drivers/block/ide-tape.c @@ -1073,13 +1073,13 @@ static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigne return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - bh->b_count, bcount); - atapi_input_bytes (drive, bh->b_data + bh->b_count, count); - bcount -= count; bh->b_count += count; - if (bh->b_count == bh->b_size) { + count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), bcount); + atapi_input_bytes (drive, bh->b_data + atomic_read(&bh->b_count), count); + bcount -= count; atomic_add(count, &bh->b_count); + if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) - bh->b_count = 0; + atomic_set(&bh->b_count, 0); } } pc->bh = bh; @@ -1104,7 +1104,7 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign pc->bh = bh = bh->b_reqnext; if (bh) { pc->b_data = bh->b_data; - pc->b_count = bh->b_count; + pc->b_count = atomic_read(&bh->b_count); } } } @@ -1126,8 +1126,8 @@ static void idetape_update_buffers (idetape_pc_t *pc) } #endif /* IDETAPE_DEBUG_BUGS */ count = IDE_MIN (bh->b_size, bcount); - bh->b_count = count; - if (bh->b_count == bh->b_size) + atomic_set(&bh->b_count, count); + if (atomic_read(&bh->b_count) == bh->b_size) bh = bh->b_reqnext; bcount -= count; } @@ -1351,13 +1351,13 @@ static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t return; } #endif /* IDETAPE_DEBUG_BUGS */ - count = IDE_MIN (bh->b_size - bh->b_count, n); - copy_from_user (bh->b_data + bh->b_count, buf, count); - n -= count; bh->b_count += count; buf += count; - if (bh->b_count == bh->b_size) { + count = IDE_MIN (bh->b_size - atomic_read(&bh->b_count), n); + copy_from_user (bh->b_data + atomic_read(&bh->b_count), buf, count); + n -= count; atomic_add(count, &bh->b_count); buf += count; + if (atomic_read(&bh->b_count) == bh->b_size) { bh = bh->b_reqnext; if (bh) - bh->b_count = 0; + atomic_set(&bh->b_count, 0); } } tape->bh = bh; @@ -1382,7 +1382,7 @@ static void idetape_copy_stage_to_user (idetape_tape_t *tape, char *buf, idetape tape->bh = bh = bh->b_reqnext; if (bh) { tape->b_data = bh->b_data; - tape->b_count = bh->b_count; + tape->b_count = atomic_read(&bh->b_count); } } } @@ -1394,10 +1394,10 @@ static void idetape_init_merge_stage (idetape_tape_t *tape) tape->bh = bh; if (tape->chrdev_direction == idetape_direction_write) - bh->b_count = 0; + atomic_set(&bh->b_count, 0); else { tape->b_data = bh->b_data; - tape->b_count = bh->b_count; + tape->b_count = atomic_read(&bh->b_count); } } @@ -2131,7 +2131,7 @@ static void idetape_create_read_cmd (idetape_tape_t *tape, idetape_pc_t *pc, uns pc->c[1] = 1; pc->callback = &idetape_rw_callback; pc->bh = bh; - bh->b_count = 0; + atomic_set(&bh->b_count, 0); pc->buffer = NULL; pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; if (pc->request_transfer == tape->stage_size) @@ -2158,7 +2158,7 @@ static void idetape_create_write_cmd (idetape_tape_t *tape, idetape_pc_t *pc, un set_bit (PC_WRITING, &pc->flags); pc->bh = bh; pc->b_data = bh->b_data; - pc->b_count = bh->b_count; + pc->b_count = atomic_read(&bh->b_count); pc->buffer = NULL; pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; if (pc->request_transfer == tape->stage_size) @@ -2587,9 +2587,9 @@ static void idetape_pad_zeros (ide_drive_t *drive, int bcount) bcount -= count; blocks = count / tape->tape_block_size; while (count) { - bh->b_count = IDE_MIN (count, bh->b_size); - memset (bh->b_data, 0, bh->b_count); - count -= bh->b_count; + atomic_set(&bh->b_count, IDE_MIN (count, bh->b_size)); + memset (bh->b_data, 0, atomic_read(&bh->b_count)); + count -= atomic_read(&bh->b_count); bh = bh->b_reqnext; } idetape_queue_rw_tail (drive, IDETAPE_WRITE_RQ, blocks, tape->merge_stage->bh); @@ -2616,8 +2616,8 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive) if (tape->merge_stage_size % tape->tape_block_size) { blocks++; i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size; - memset (tape->bh->b_data + tape->bh->b_count, 0, i); - tape->bh->b_count += i; + memset (tape->bh->b_data + atomic_read(&tape->bh->b_count), 0, i); + atomic_add(i, &tape->bh->b_count); } (void) idetape_add_chrdev_write_request (drive, blocks); tape->merge_stage_size = 0; @@ -3814,8 +3814,14 @@ void cleanup_module (void) for (minor = 0; minor < MAX_HWIFS * MAX_DRIVES; minor++) { drive = idetape_chrdevs[minor].drive; - if (drive != NULL && idetape_cleanup (drive)) - printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); + if (drive) { + if (idetape_cleanup (drive)) + printk (KERN_ERR "ide-tape: %s: cleanup_module() called while still busy\n", drive->name); + /* We must remove proc entries defined in this module. + Otherwise we oops while accessing these entries */ + if (drive->proc) + ide_remove_proc_entries(drive->proc, idetape_proc); + } } ide_unregister_module(&idetape_module); } diff --git a/drivers/block/ide.c b/drivers/block/ide.c index 2d6eebd24..17b10593d 100644 --- a/drivers/block/ide.c +++ b/drivers/block/ide.c @@ -1748,6 +1748,13 @@ abort: return 1; } +#ifdef CONFIG_PROC_FS +ide_proc_entry_t generic_subdriver_entries[] = { + { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, + { NULL, 0, NULL, NULL } +}; +#endif + void ide_unregister (unsigned int index) { struct gendisk *gd, **gdp; @@ -1757,6 +1764,7 @@ void ide_unregister (unsigned int index) int irq_count = 0, unit, i; unsigned long flags; unsigned int p, minor; + ide_hwif_t old_hwif; if (index >= MAX_HWIFS) return; @@ -1793,6 +1801,9 @@ void ide_unregister (unsigned int index) invalidate_buffers (devp); } } +#ifdef CONFIG_PROC_FS + destroy_proc_ide_drives(hwif); +#endif } cli(); hwgroup = hwif->hwgroup; @@ -1875,7 +1886,21 @@ void ide_unregister (unsigned int index) kfree(gd->part); kfree(gd); } + old_hwif = *hwif; init_hwif_data (index); /* restore hwif data to pristine status */ + hwif->hwgroup = old_hwif.hwgroup; + hwif->tuneproc = old_hwif.tuneproc; + hwif->dmaproc = old_hwif.dmaproc; + hwif->dma_base = old_hwif.dma_base; + hwif->dma_extra = old_hwif.dma_extra; + hwif->config_data = old_hwif.config_data; + hwif->select_data = old_hwif.select_data; + hwif->irq = old_hwif.irq; + hwif->major = old_hwif.major; + hwif->proc = old_hwif.proc; + hwif->chipset = old_hwif.chipset; + hwif->pci_dev = old_hwif.pci_dev; + hwif->pci_devid = old_hwif.pci_devid; abort: restore_flags(flags); /* all CPUs */ } @@ -1950,6 +1975,9 @@ found: if (!initializing) { ide_init_module(IDE_PROBE_MODULE); +#ifdef CONFIG_PROC_FS + create_proc_ide_interfaces(); +#endif ide_init_module(IDE_DRIVER_MODULE); } @@ -1966,7 +1994,6 @@ found: int ide_register (int arg1, int arg2, int irq) { hw_regs_t hw; - ide_init_hwif_ports(&hw, (ide_ioreg_t) arg1, (ide_ioreg_t) arg2, NULL); hw.irq = irq; return ide_register_hw(&hw, NULL); @@ -3239,13 +3266,6 @@ search: return NULL; } -#ifdef CONFIG_PROC_FS -static ide_proc_entry_t generic_subdriver_entries[] = { - { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, - { NULL, 0, NULL, NULL } -}; -#endif - int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) { unsigned long flags; @@ -3401,6 +3421,7 @@ EXPORT_SYMBOL(ide_stall_queue); EXPORT_SYMBOL(ide_add_proc_entries); EXPORT_SYMBOL(ide_remove_proc_entries); EXPORT_SYMBOL(proc_ide_read_geometry); +EXPORT_SYMBOL(create_proc_ide_interfaces); #endif EXPORT_SYMBOL(ide_add_setting); EXPORT_SYMBOL(ide_remove_setting); diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 185591b3a..02df81f77 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -17,6 +17,7 @@ #include <linux/locks.h> #include <linux/mm.h> #include <linux/init.h> +#include <linux/smp_lock.h> #include <asm/system.h> #include <asm/io.h> @@ -322,8 +323,6 @@ void add_request(struct blk_dev_struct * dev, struct request * req) spin_lock_irqsave(&io_request_lock,flags); current_request = get_queue(req->rq_dev); - if (req->bh) - mark_buffer_clean(req->bh); if (!(tmp = *current_request)) { *current_request = req; if (dev->current_request != &dev->plug) @@ -385,12 +384,17 @@ void make_request(int major,int rw, struct buffer_head * bh) count = bh->b_size >> 9; sector = bh->b_rsector; - /* Uhhuh.. Nasty dead-lock possible here.. */ - if (buffer_locked(bh)) - return; - /* Maybe the above fixes it, and maybe it doesn't boot. Life is interesting */ + /* We'd better have a real physical mapping! */ + if (!buffer_mapped(bh)) + BUG(); + + /* It had better not be a new buffer by the time we see it */ + if (buffer_new(bh)) + BUG(); - lock_buffer(bh); + /* Only one thread can actually submit the I/O. */ + if (test_and_set_bit(BH_Lock, &bh->b_state)) + return; if (blk_size[major]) { unsigned long maxsector = (blk_size[major][MINOR(bh->b_rdev)] << 1) + 1; @@ -425,9 +429,11 @@ void make_request(int major,int rw, struct buffer_head * bh) rw_ahead = 1; rw = WRITE; /* drop into WRITE */ case WRITE: - if (!buffer_dirty(bh)) /* Hmmph! Nothing to write */ - goto end_io; - /* We don't allow the write-requests to fill up the + if (!test_and_clear_bit(BH_Dirty, &bh->b_state)) + goto end_io; /* Hmmph! Nothing to write */ + refile_buffer(bh); + /* + * We don't allow the write-requests to fill up the * queue completely: we want some room for reads, * as they take precedence. The last third of the * requests are only for reads. @@ -528,7 +534,6 @@ void make_request(int major,int rw, struct buffer_head * bh) } else continue; - mark_buffer_clean(bh); spin_unlock_irqrestore(&io_request_lock,flags); return; @@ -605,7 +610,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[]) for (i = 0; i < nr; i++) { if (bh[i]->b_size != correct_size) { printk(KERN_NOTICE "ll_rw_block: device %s: " - "only %d-char blocks implemented (%lu)\n", + "only %d-char blocks implemented (%u)\n", kdevname(bh[0]->b_dev), correct_size, bh[i]->b_size); goto sorry; diff --git a/drivers/block/pdc4030.c b/drivers/block/pdc4030.c index 92c7082c6..84fbb4856 100644 --- a/drivers/block/pdc4030.c +++ b/drivers/block/pdc4030.c @@ -1,5 +1,5 @@ /* -*- linux-c -*- - * linux/drivers/block/pdc4030.c Version 0.11 May 17, 1999 + * linux/drivers/block/pdc4030.c Version 0.90 May 27, 1999 * * Copyright (C) 1995-1999 Linus Torvalds & authors (see below) */ @@ -35,6 +35,8 @@ * Version 0.10 Updated for 2.1 series of kernels * Version 0.11 Updated for 2.3 series of kernels * Autodetection code added. + * + * Version 0.90 Transition to BETA code. No lost/unexpected interrupts */ /* @@ -68,8 +70,8 @@ * because I still don't understand what the card is doing with interrupts. */ -#undef DEBUG_READ -#undef DEBUG_WRITE +#define DEBUG_READ +#define DEBUG_WRITE #include <linux/types.h> #include <linux/kernel.h> @@ -100,7 +102,8 @@ static void promise_selectproc (ide_drive_t *drive) /* * pdc4030_cmd handles the set of vendor specific commands that are initiated - * by command F0. They all have the same success/failure notification. + * by command F0. They all have the same success/failure notification - + * 'P' (=0x50) on success, 'p' (=0x70) on failure. */ int pdc4030_cmd(ide_drive_t *drive, byte cmd) { @@ -358,11 +361,11 @@ read_next: if (stat & DRQ_STAT) goto read_again; if (stat & BUSY_STAT) { + ide_set_handler (drive, &promise_read_intr, WAIT_CMD); #ifdef DEBUG_READ printk(KERN_DEBUG "%s: promise_read: waiting for" "interrupt\n", drive->name); #endif - ide_set_handler (drive, &promise_read_intr, WAIT_CMD); return; } printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left " @@ -372,37 +375,39 @@ read_next: } /* - * promise_finish_write() - * called at the end of all writes + * promise_complete_pollfunc() + * This is the polling function for waiting (nicely!) until drive stops + * being busy. It is invoked at the end of a write, after the previous poll + * has finished. + * + * Once not busy, the end request is called. */ -static void promise_finish_write(ide_drive_t *drive) +static void promise_complete_pollfunc(ide_drive_t *drive) { - struct request *rq = HWGROUP(drive)->rq; + ide_hwgroup_t *hwgroup = HWGROUP(drive); + struct request *rq = hwgroup->rq; int i; - for (i = rq->nr_sectors; i > 0; ) { - i -= rq->current_nr_sectors; - ide_end_request(1, HWGROUP(drive)); - } -} - -/* - * promise_write_intr() - * This interrupt is called after the particularly odd polling for completion - * of the write request, once all the data has been sent. - */ -static void promise_write_intr(ide_drive_t *drive) -{ - byte stat; - - if (!OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) { - ide_error(drive, "promise_write_intr", stat); + if (GET_STAT() & BUSY_STAT) { + if (time_before(jiffies, hwgroup->poll_timeout)) { + ide_set_handler(drive, &promise_complete_pollfunc, 1); + return; /* continue polling... */ + } + hwgroup->poll_timeout = 0; + printk(KERN_ERR "%s: completion timeout - still busy!\n", + drive->name); + ide_error(drive, "busy timeout", GET_STAT()); + return; } + hwgroup->poll_timeout = 0; #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); #endif - promise_finish_write(drive); + for (i = rq->nr_sectors; i > 0; ) { + i -= rq->current_nr_sectors; + ide_end_request(1, hwgroup); + } } /* @@ -410,22 +415,29 @@ static void promise_write_intr(ide_drive_t *drive) */ static void promise_write_pollfunc (ide_drive_t *drive) { + ide_hwgroup_t *hwgroup = HWGROUP(drive); + if (IN_BYTE(IDE_NSECTOR_REG) != 0) { - if (time_before(jiffies, HWGROUP(drive)->poll_timeout)) { + if (time_before(jiffies, hwgroup->poll_timeout)) { ide_set_handler (drive, &promise_write_pollfunc, 1); return; /* continue polling... */ } + hwgroup->poll_timeout = 0; printk(KERN_ERR "%s: write timed-out!\n",drive->name); ide_error (drive, "write timeout", GET_STAT()); return; } + /* + * Now write out last 4 sectors and poll for not BUSY + */ ide_multwrite(drive, 4); + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + ide_set_handler(drive, &promise_complete_pollfunc, 1); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n", drive->name, GET_STAT()); #endif - ide_set_handler(drive, &promise_write_intr, WAIT_CMD); return; } @@ -433,8 +445,8 @@ static void promise_write_pollfunc (ide_drive_t *drive) * promise_write() transfers a block of one or more sectors of data to a * drive as part of a disk write operation. All but 4 sectors are transfered * in the first attempt, then the interface is polled (nicely!) for completion - * before the final 4 sectors are transfered. The interrupt generated on - * writes occurs after this process, which is why I got it wrong for so long! + * before the final 4 sectors are transfered. There is no interrupt generated + * on writes (at least on the DC4030VL-2), we just have to poll for NOT BUSY. */ static void promise_write (ide_drive_t *drive) { @@ -446,18 +458,27 @@ static void promise_write (ide_drive_t *drive) "buffer=0x%08x\n", drive->name, rq->sector, rq->sector + rq->nr_sectors - 1, (unsigned int)rq->buffer); #endif + + /* + * If there are more than 4 sectors to transfer, do n-4 then go into + * the polling strategy as defined above. + */ if (rq->nr_sectors > 4) { ide_multwrite(drive, rq->nr_sectors - 4); hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; ide_set_handler (drive, &promise_write_pollfunc, 1); - return; } else { + /* + * There are 4 or fewer sectors to transfer, do them all in one go + * and wait for NOT BUSY. + */ ide_multwrite(drive, rq->nr_sectors); + hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; + ide_set_handler(drive, &promise_complete_pollfunc, 1); #ifdef DEBUG_WRITE printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, " "status = %02x\n", drive->name, GET_STAT()); #endif - promise_finish_write(drive); } } diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c index 890584dcd..7efb78400 100644 --- a/drivers/block/raid1.c +++ b/drivers/block/raid1.c @@ -310,7 +310,7 @@ raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) mirror_bh [i]->b_rdev = raid_conf->mirrors [i].dev; mirror_bh [i]->b_rsector = bh->b_rsector; mirror_bh [i]->b_state = (1<<BH_Req) | (1<<BH_Dirty); - mirror_bh [i]->b_count = 1; + atomic_set(&mirror_bh [i]->b_count, 1); mirror_bh [i]->b_size = bh->b_size; mirror_bh [i]->b_data = bh->b_data; mirror_bh [i]->b_list = BUF_LOCKED; diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c index 3c5701b3e..3e60f92ce 100644 --- a/drivers/block/raid5.c +++ b/drivers/block/raid5.c @@ -586,13 +586,15 @@ static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, i b_data = ((volatile struct buffer_head *) bh)->b_data; memset (bh, 0, sizeof (struct buffer_head)); - init_buffer(bh, dev, block, raid5_end_request, sh); + init_buffer(bh, raid5_end_request, sh); + bh->b_dev = dev; + bh->b_blocknr = block; ((volatile struct buffer_head *) bh)->b_data = b_data; bh->b_rdev = raid_conf->disks[i].dev; bh->b_rsector = sh->sector; - bh->b_state = (1 << BH_Req); + bh->b_state = (1 << BH_Req) | (1 << BH_Mapped); bh->b_size = sh->size; bh->b_list = BUF_LOCKED; } @@ -1030,19 +1032,24 @@ static void handle_stripe(struct stripe_head *sh) if (sh->bh_new[i]) continue; block = (int) compute_blocknr(sh, i); - bh = find_buffer(MKDEV(MD_MAJOR, minor), block, sh->size); - if (bh && bh->b_count == 0 && buffer_dirty(bh) && !buffer_locked(bh)) { - PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); - add_stripe_bh(sh, bh, i, WRITE); - sh->new[i] = 0; - nr++; nr_write++; - if (sh->bh_old[i]) { - nr_cache_overwrite++; - nr_cache_other--; - } else if (!operational[i]) { - nr_failed_overwrite++; - nr_failed_other--; + bh = get_hash_table(MKDEV(MD_MAJOR, minor), block, sh->size); + if (bh) { + if (atomic_read(&bh->b_count) == 1 && + buffer_dirty(bh) && + !buffer_locked(bh)) { + PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); + add_stripe_bh(sh, bh, i, WRITE); + sh->new[i] = 0; + nr++; nr_write++; + if (sh->bh_old[i]) { + nr_cache_overwrite++; + nr_cache_other--; + } else if (!operational[i]) { + nr_failed_overwrite++; + nr_failed_other--; + } } + atomic_dec(&bh->b_count); } } } diff --git a/drivers/block/rd.c b/drivers/block/rd.c index 81ce11c49..6c2768b27 100644 --- a/drivers/block/rd.c +++ b/drivers/block/rd.c @@ -173,7 +173,7 @@ repeat: if (CURRENT->cmd == READ) memset(CURRENT->buffer, 0, len); - else + else set_bit(BH_Protected, &CURRENT->bh->b_state); end_request(1); |