X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Fide-disk.c;h=9217f0ced156afe2fa025693971b47b24625292a;hb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;hp=ac94367eeade834910e1b2caf81a6b07c4b76e0e;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index ac94367ee..9217f0ced 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -45,6 +45,8 @@ #undef REALLY_SLOW_IO /* most systems can safely undef this */ +//#define DEBUG + #include #include #include @@ -118,20 +120,6 @@ static int lba_capacity_is_ok (struct hd_driveid *id) return 0; /* lba_capacity value may be bad */ } -static int idedisk_start_tag(ide_drive_t *drive, struct request *rq) -{ - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&ide_lock, flags); - - if (ata_pending_commands(drive) < drive->queue_depth) - ret = blk_queue_start_tag(drive->queue, rq); - - spin_unlock_irqrestore(&ide_lock, flags); - return ret; -} - #ifndef CONFIG_IDE_TASKFILE_IO /* @@ -358,13 +346,6 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector nsectors.all = (u16) rq->nr_sectors; - if (drive->using_tcq && idedisk_start_tag(drive, rq)) { - if (!ata_pending_commands(drive)) - BUG(); - - return ide_started; - } - if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl, IDE_CONTROL_REG); @@ -372,18 +353,12 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector if (drive->addressing == 1) { task_ioreg_t tasklets[10]; - if (blk_rq_tagged(rq)) { - tasklets[0] = nsectors.b.low; - tasklets[1] = nsectors.b.high; - tasklets[2] = rq->tag << 3; - tasklets[3] = 0; - } else { - tasklets[0] = 0; - tasklets[1] = 0; - tasklets[2] = nsectors.b.low; - tasklets[3] = nsectors.b.high; - } + pr_debug("%s: LBA=0x%012llx\n", drive->name, block); + tasklets[0] = 0; + tasklets[1] = 0; + tasklets[2] = nsectors.b.low; + tasklets[3] = nsectors.b.high; tasklets[4] = (task_ioreg_t) block; tasklets[5] = (task_ioreg_t) (block>>8); tasklets[6] = (task_ioreg_t) (block>>16); @@ -396,14 +371,6 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector tasklets[9] = (task_ioreg_t)((u64)block >> 40); } #ifdef DEBUG - printk("%s: %sing: LBAsect=%lu, sectors=%ld, " - "buffer=0x%08lx, LBAsect=0x%012lx\n", - drive->name, - rq_data_dir(rq)==READ?"read":"writ", - block, - rq->nr_sectors, - (unsigned long) rq->buffer, - block); printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n", drive->name, tasklets[3], tasklets[2], tasklets[9], tasklets[8], tasklets[7], @@ -422,22 +389,8 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector hwif->OUTB(tasklets[6], IDE_HCYL_REG); hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG); } else { -#ifdef DEBUG - printk("%s: %sing: LBAsect=%llu, sectors=%ld, " - "buffer=0x%08lx\n", - drive->name, - rq_data_dir(rq)==READ?"read":"writ", - (unsigned long long)block, rq->nr_sectors, - (unsigned long) rq->buffer); -#endif - if (blk_rq_tagged(rq)) { - hwif->OUTB(nsectors.b.low, IDE_FEATURE_REG); - hwif->OUTB(rq->tag << 3, IDE_NSECTOR_REG); - } else { - hwif->OUTB(0x00, IDE_FEATURE_REG); - hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); - } - + hwif->OUTB(0x00, IDE_FEATURE_REG); + hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); hwif->OUTB(block, IDE_SECTOR_REG); hwif->OUTB(block>>=8, IDE_LCYL_REG); hwif->OUTB(block>>=8, IDE_HCYL_REG); @@ -451,29 +404,16 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector head = track % drive->head; cyl = track / drive->head; - if (blk_rq_tagged(rq)) { - hwif->OUTB(nsectors.b.low, IDE_FEATURE_REG); - hwif->OUTB(rq->tag << 3, IDE_NSECTOR_REG); - } else { - hwif->OUTB(0x00, IDE_FEATURE_REG); - hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); - } + pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); + hwif->OUTB(0x00, IDE_FEATURE_REG); + hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG); hwif->OUTB(cyl, IDE_LCYL_REG); hwif->OUTB(cyl>>8, IDE_HCYL_REG); hwif->OUTB(head|drive->select.all,IDE_SELECT_REG); -#ifdef DEBUG - printk("%s: %sing: CHS=%d/%d/%d, sectors=%ld, buffer=0x%08lx\n", - drive->name, rq_data_dir(rq)==READ?"read":"writ", cyl, - head, sect, rq->nr_sectors, (unsigned long) rq->buffer); -#endif } if (rq_data_dir(rq) == READ) { -#ifdef CONFIG_BLK_DEV_IDE_TCQ - if (blk_rq_tagged(rq)) - return __ide_dma_queued_read(drive); -#endif if (drive->using_dma && !hwif->ide_dma_read(drive)) return ide_started; @@ -482,12 +422,9 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector ((lba48) ? WIN_READ_EXT : WIN_READ)); ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); return ide_started; - } else if (rq_data_dir(rq) == WRITE) { + } else { ide_startstop_t startstop; -#ifdef CONFIG_BLK_DEV_IDE_TCQ - if (blk_rq_tagged(rq)) - return __ide_dma_queued_write(drive); -#endif + if (drive->using_dma && !(HWIF(drive)->ide_dma_write(drive))) return ide_started; @@ -520,9 +457,6 @@ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector } return ide_started; } - blk_dump_rq_flags(rq, "__ide_do_rw_disk - bad command"); - ide_end_request(drive, 0, 0); - return ide_stopped; } EXPORT_SYMBOL_GPL(__ide_do_rw_disk); @@ -539,26 +473,11 @@ static ide_startstop_t lba_48_rw_disk(ide_drive_t *, struct request *, unsigned */ ide_startstop_t __ide_do_rw_disk (ide_drive_t *drive, struct request *rq, sector_t block) { - BUG_ON(drive->blocked); - if (!blk_fs_request(rq)) { - blk_dump_rq_flags(rq, "__ide_do_rw_disk - bad command"); - ide_end_request(drive, 0, 0); - return ide_stopped; - } - /* * 268435455 == 137439 MB or 28bit limit * * need to add split taskfile operations based on 28bit threshold. */ - - if (drive->using_tcq && idedisk_start_tag(drive, rq)) { - if (!ata_pending_commands(drive)) - BUG(); - - return ide_started; - } - if (drive->addressing == 1) /* 48-bit LBA */ return lba_48_rw_disk(drive, rq, (unsigned long long) block); if (drive->select.b.lba) /* 28-bit LBA */ @@ -575,8 +494,6 @@ static u8 get_command(ide_drive_t *drive, int cmd, ide_task_t *task) if (cmd == READ) { task->command_type = IDE_DRIVE_TASK_IN; - if (drive->using_tcq) - return lba48 ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED; if (drive->using_dma) return lba48 ? WIN_READDMA_EXT : WIN_READDMA; if (drive->mult_count) { @@ -587,8 +504,6 @@ static u8 get_command(ide_drive_t *drive, int cmd, ide_task_t *task) return lba48 ? WIN_READ_EXT : WIN_READ; } else { task->command_type = IDE_DRIVE_TASK_RAW_WRITE; - if (drive->using_tcq) - return lba48 ? WIN_WRITEDMA_QUEUED_EXT : WIN_WRITEDMA_QUEUED; if (drive->using_dma) return lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; if (drive->mult_count) { @@ -614,23 +529,13 @@ static ide_startstop_t chs_rw_disk (ide_drive_t *drive, struct request *rq, unsi nsectors.all = (u16) rq->nr_sectors; -#ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); - printk("CHS=%d/%d/%d, ", cyl, head, sect); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); -#endif + pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect); memset(&args, 0, sizeof(ide_task_t)); sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; - if (blk_rq_tagged(rq)) { - args.tfRegister[IDE_FEATURE_OFFSET] = sectors; - args.tfRegister[IDE_NSECTOR_OFFSET] = rq->tag << 3; - } else - args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; - + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; args.tfRegister[IDE_SECTOR_OFFSET] = sect; args.tfRegister[IDE_LCYL_OFFSET] = cyl; args.tfRegister[IDE_HCYL_OFFSET] = (cyl>>8); @@ -650,23 +555,11 @@ static ide_startstop_t lba_28_rw_disk (ide_drive_t *drive, struct request *rq, u nsectors.all = (u16) rq->nr_sectors; -#ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); - printk("LBAsect=%lld, ", block); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); -#endif - memset(&args, 0, sizeof(ide_task_t)); sectors = (rq->nr_sectors == 256) ? 0x00 : rq->nr_sectors; - if (blk_rq_tagged(rq)) { - args.tfRegister[IDE_FEATURE_OFFSET] = sectors; - args.tfRegister[IDE_NSECTOR_OFFSET] = rq->tag << 3; - } else - args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; - + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; args.tfRegister[IDE_SECTOR_OFFSET] = block; args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); @@ -692,27 +585,12 @@ static ide_startstop_t lba_48_rw_disk (ide_drive_t *drive, struct request *rq, u nsectors.all = (u16) rq->nr_sectors; -#ifdef DEBUG - printk("%s: %sing: ", drive->name, (rq_data_dir(rq)==READ) ? "read" : "writ"); - printk("LBAsect=%lld, ", block); - printk("sectors=%ld, ", rq->nr_sectors); - printk("buffer=0x%08lx\n", (unsigned long) rq->buffer); -#endif - memset(&args, 0, sizeof(ide_task_t)); sectors = (rq->nr_sectors == 65536) ? 0 : rq->nr_sectors; - if (blk_rq_tagged(rq)) { - args.tfRegister[IDE_FEATURE_OFFSET] = sectors; - args.tfRegister[IDE_NSECTOR_OFFSET] = rq->tag << 3; - args.hobRegister[IDE_FEATURE_OFFSET] = sectors >> 8; - args.hobRegister[IDE_NSECTOR_OFFSET] = 0; - } else { - args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; - args.hobRegister[IDE_NSECTOR_OFFSET] = sectors >> 8; - } - + args.tfRegister[IDE_NSECTOR_OFFSET] = sectors; + args.hobRegister[IDE_NSECTOR_OFFSET] = sectors >> 8; args.tfRegister[IDE_SECTOR_OFFSET] = block; /* low lba */ args.tfRegister[IDE_LCYL_OFFSET] = (block>>=8); /* mid lba */ args.tfRegister[IDE_HCYL_OFFSET] = (block>>=8); /* hi lba */ @@ -734,14 +612,24 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s { ide_hwif_t *hwif = HWIF(drive); + BUG_ON(drive->blocked); + + if (!blk_fs_request(rq)) { + blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); + ide_end_request(drive, 0, 0); + return ide_stopped; + } + + pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", + drive->name, rq_data_dir(rq) == READ ? "read" : "writ", + block, rq->nr_sectors, (unsigned long)rq->buffer); + if (hwif->rw_disk) return hwif->rw_disk(drive, rq, block); else return __ide_do_rw_disk(drive, rq, block); } -static int do_idedisk_flushcache(ide_drive_t *drive); - static u8 idedisk_dump_status (ide_drive_t *drive, const char *msg, u8 stat) { ide_hwif_t *hwif = HWIF(drive); @@ -823,7 +711,6 @@ ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) ide_hwif_t *hwif; struct request *rq; u8 err; - int i = (drive->mult_count ? drive->mult_count : 1) * SECTOR_WORDS; err = idedisk_dump_status(drive, msg, stat); @@ -863,22 +750,8 @@ ide_startstop_t idedisk_error (ide_drive_t *drive, const char *msg, u8 stat) rq->errors |= ERROR_RECAL; } } - if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) { - /* - * try_to_flush_leftover_data() is invoked in response to - * a drive unexpectedly having its DRQ_STAT bit set. As - * an alternative to resetting the drive, this routine - * tries to clear the condition by read a sector's worth - * of data from the drive. Of course, this may not help - * if the drive is *waiting* for data from *us*. - */ - while (i > 0) { - u32 buffer[16]; - unsigned int wcount = (i > 16) ? 16 : i; - i -= wcount; - taskfile_input_data(drive, buffer, wcount); - } - } + if ((stat & DRQ_STAT) && rq_data_dir(rq) == READ) + try_to_flush_leftover_data(drive); if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT)) { /* force an abort */ hwif->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); @@ -975,7 +848,6 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive return addr; } -#ifdef CONFIG_IDEDISK_STROKE /* * Sets maximum virtual LBA address of the drive. * Returns new maximum virtual LBA address (> 0) or 0 on failure. @@ -1044,8 +916,6 @@ static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsign return addr_set; } -#endif /* CONFIG_IDEDISK_STROKE */ - static unsigned long long sectors_to_MB(unsigned long long n) { n <<= 9; /* make it bytes */ @@ -1092,7 +962,10 @@ static inline void idedisk_check_hpa(ide_drive_t *drive) drive->name, capacity, sectors_to_MB(capacity), set_max, sectors_to_MB(set_max)); -#ifdef CONFIG_IDEDISK_STROKE + + if (!drive->stroke) + return; + if (lba48) set_max = idedisk_set_max_address_ext(drive, set_max); else @@ -1102,7 +975,6 @@ static inline void idedisk_check_hpa(ide_drive_t *drive) printk(KERN_INFO "%s: Host Protected Area disabled.\n", drive->name); } -#endif } /* @@ -1359,11 +1231,18 @@ static int set_nowerr(ide_drive_t *drive, int arg) return 0; } +/* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ +#define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000) + +/* some Maxtor disks have bit 13 defined incorrectly so check bit 10 too */ +#define ide_id_has_flush_cache_ext(id) \ + (((id)->cfs_enable_2 & 0x2400) == 0x2400) + static int write_cache (ide_drive_t *drive, int arg) { ide_task_t args; - if (!(drive->id->cfs_enable_2 & 0x3000)) + if (!ide_id_has_flush_cache(drive->id)) return 1; memset(&args, 0, sizeof(ide_task_t)); @@ -1383,7 +1262,7 @@ static int do_idedisk_flushcache (ide_drive_t *drive) ide_task_t args; memset(&args, 0, sizeof(ide_task_t)); - if (drive->id->cfs_enable_2 & 0x2400) + if (ide_id_has_flush_cache_ext(drive->id)) args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; else args.tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; @@ -1408,34 +1287,6 @@ static int set_acoustic (ide_drive_t *drive, int arg) return 0; } -#ifdef CONFIG_BLK_DEV_IDE_TCQ -static int set_using_tcq(ide_drive_t *drive, int arg) -{ - int ret; - - if (!drive->driver) - return -EPERM; - if (arg == drive->queue_depth && drive->using_tcq) - return 0; - - /* - * set depth, but check also id for max supported depth - */ - drive->queue_depth = arg ? arg : 1; - if (drive->id) { - if (drive->queue_depth > drive->id->queue_depth + 1) - drive->queue_depth = drive->id->queue_depth + 1; - } - - if (arg) - ret = __ide_dma_queued_on(drive); - else - ret = __ide_dma_queued_off(drive); - - return ret ? -EIO : 0; -} -#endif - /* * drive->addressing: * 0: 28-bit @@ -1471,9 +1322,6 @@ static void idedisk_add_settings(ide_drive_t *drive) ide_add_setting(drive, "acoustic", SETTING_RW, HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, TYPE_BYTE, 0, 254, 1, 1, &drive->acoustic, set_acoustic); ide_add_setting(drive, "failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->failures, NULL); ide_add_setting(drive, "max_failures", SETTING_RW, -1, -1, TYPE_INT, 0, 65535, 1, 1, &drive->max_failures, NULL); -#ifdef CONFIG_BLK_DEV_IDE_TCQ - ide_add_setting(drive, "using_tcq", SETTING_RW, HDIO_GET_QDMA, HDIO_SET_QDMA, TYPE_BYTE, 0, IDE_MAX_TAG, 1, 1, &drive->using_tcq, set_using_tcq); -#endif } /* @@ -1513,11 +1361,11 @@ static ide_startstop_t idedisk_start_power_step (ide_drive_t *drive, struct requ switch (rq->pm->pm_step) { case idedisk_pm_flush_cache: /* Suspend step 1 (flush cache) */ /* Not supported? Switch to next step now. */ - if (!drive->wcache) { + if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) { idedisk_complete_power_step(drive, rq, 0, 0); return ide_stopped; } - if (drive->id->cfs_enable_2 & 0x2400) + if (ide_id_has_flush_cache_ext(drive->id)) args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT; else args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE; @@ -1678,18 +1526,25 @@ static void idedisk_setup (ide_drive_t *drive) #endif /* CONFIG_IDEDISK_MULTI_MODE */ } drive->no_io_32bit = id->dword_io ? 1 : 0; - if (drive->id->cfs_enable_2 & 0x3000) - write_cache(drive, (id->cfs_enable_2 & 0x3000)); -#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - if (drive->using_dma) - __ide_dma_queued_on(drive); -#endif + /* write cache enabled? */ + if ((id->csfo & 1) || (id->cfs_enable_1 & (1 << 5))) + drive->wcache = 1; + + write_cache(drive, 1); +} + +static void ide_cacheflush_p(ide_drive_t *drive) +{ + if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) + return; + + if (do_idedisk_flushcache(drive)) + printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); } static int idedisk_cleanup (ide_drive_t *drive) { - static int ide_cacheflush_p(ide_drive_t *drive); struct gendisk *g = drive->disk; ide_cacheflush_p(drive); if (ide_unregister_subdriver(drive)) @@ -1706,6 +1561,26 @@ static void ide_device_shutdown(struct device *dev) { ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); +#ifdef CONFIG_ALPHA + /* On Alpha, halt(8) doesn't actually turn the machine off, + it puts you into the sort of firmware monitor. Typically, + it's used to boot another kernel image, so it's not much + different from reboot(8). Therefore, we don't need to + spin down the disk in this case, especially since Alpha + firmware doesn't handle disks in standby mode properly. + On the other hand, it's reasonably safe to turn the power + off when the shutdown process reaches the firmware prompt, + as the firmware initialization takes rather long time - + at least 10 seconds, which should be sufficient for + the disk to expire its write cache. */ + if (system_state != SYSTEM_POWER_OFF) { +#else + if (system_state == SYSTEM_RESTART) { +#endif + ide_cacheflush_p(drive); + return; + } + printk("Shutdown: %s\n", drive->name); dev->bus->suspend(dev, PM_SUSPEND_STANDBY); } @@ -1740,7 +1615,6 @@ static ide_driver_t idedisk_driver = { static int idedisk_open(struct inode *inode, struct file *filp) { - u8 cf; ide_drive_t *drive = inode->i_bdev->bd_disk->private_data; drive->usage++; if (drive->removable && drive->usage == 1) { @@ -1758,35 +1632,6 @@ static int idedisk_open(struct inode *inode, struct file *filp) if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } - drive->wcache = 0; - /* Cache enabled? */ - if (drive->id->csfo & 1) - drive->wcache = 1; - /* Cache command set available? */ - if (drive->id->cfs_enable_1 & (1 << 5)) - drive->wcache = 1; - /* ATA6 cache extended commands */ - cf = drive->id->command_set_2 >> 24; - if ((cf & 0xC0) == 0x40 && (cf & 0x30) != 0) - drive->wcache = 1; - return 0; -} - -static int ide_cacheflush_p(ide_drive_t *drive) -{ - if (!(drive->id->cfs_enable_2 & 0x3000)) - return 0; - - if(drive->wcache) - { - if (do_idedisk_flushcache(drive)) - { - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); - return -EIO; - } - return 1; - } return 0; } @@ -1867,10 +1712,7 @@ static int idedisk_attach(ide_drive_t *drive) if ((!drive->head || drive->head > 16) && !drive->select.b.lba) { printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n", drive->name, drive->head); - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); ide_unregister_subdriver(drive); DRIVER(drive)->busy--; goto failed;