summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-07-05 23:09:37 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-07-05 23:09:37 +0000
commitaba344fdfed81b2c03d6114c54cfd73a486aa10b (patch)
treed032d8430bf1234c3ecc6f6330d6de6e887e5963 /drivers/block
parent40c138bfc6d37dbff5339f84575db1e3cec6e34e (diff)
Merge with Linux 2.3.9.
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/Config.in7
-rw-r--r--drivers/block/genhd.c31
-rw-r--r--drivers/block/icside.c1
-rw-r--r--drivers/block/ide-disk.c7
-rw-r--r--drivers/block/ide-floppy.c7
-rw-r--r--drivers/block/ide-pci.c4
-rw-r--r--drivers/block/ide-pmac.c4
-rw-r--r--drivers/block/ide-probe.c4
-rw-r--r--drivers/block/ide-proc.c98
-rw-r--r--drivers/block/ide-tape.c56
-rw-r--r--drivers/block/ide.c37
-rw-r--r--drivers/block/ll_rw_blk.c29
-rw-r--r--drivers/block/pdc4030.c87
-rw-r--r--drivers/block/raid1.c2
-rw-r--r--drivers/block/raid5.c35
-rw-r--r--drivers/block/rd.c2
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);